From 45339997c863a7798839de76265b4c1182345711 Mon Sep 17 00:00:00 2001 From: pingu Date: Mon, 30 Mar 2026 13:59:53 +0200 Subject: [PATCH] All the 8bit arithmetic things done --- src/GB/CPU.hs | 44 ++++++++++++++++++++++++++++++++++++-------- 1 file changed, 36 insertions(+), 8 deletions(-) diff --git a/src/GB/CPU.hs b/src/GB/CPU.hs index bb563ba..1205a8c 100644 --- a/src/GB/CPU.hs +++ b/src/GB/CPU.hs @@ -9,13 +9,12 @@ import Lens.Micro.Platform import Data.Word import Data.Bits import qualified Data.Vector.Sized as V -import Prelude hiding (subtract) class Convert a b where convert :: a -> b data FlagRegister = FlagRegister { _zero :: Bool - , _subtract :: Bool + , _negative :: Bool , _halfCarry :: Bool , _carry :: Bool } @@ -25,8 +24,8 @@ makeLenses ''FlagRegister zeroFlagPosition :: Int zeroFlagPosition = 7 -subtractFlagPosition :: Int -subtractFlagPosition = 6 +negativeFlagPosition :: Int +negativeFlagPosition = 6 halfCarryFlagPosition :: Int halfCarryFlagPosition = 5 carryFlagPosition :: Int @@ -35,14 +34,14 @@ carryFlagPosition = 4 instance Convert FlagRegister Word8 where convert r = ((`shiftL` zeroFlagPosition) $ if r ^. zero then 1 else 0) + - ((`shiftL` subtractFlagPosition) $ if r ^. subtract then 1 else 0) + + ((`shiftL` negativeFlagPosition) $ if r ^. negative then 1 else 0) + ((`shiftL` halfCarryFlagPosition) $ if r ^. halfCarry then 1 else 0) + ((`shiftL` carryFlagPosition) $ if r ^. carry then 1 else 0) instance Convert Word8 FlagRegister where convert w = let _zero = (shiftR w zeroFlagPosition .&. 1 /= 0) - _subtract = (shiftR w subtractFlagPosition .&. 1 /= 0) + _negative = (shiftR w negativeFlagPosition .&. 1 /= 0) _halfCarry = (shiftR w halfCarryFlagPosition .&. 1 /= 0) _carry = (shiftR w carryFlagPosition .&. 1 /= 0) in FlagRegister {..} @@ -96,6 +95,13 @@ data Instruction where IncHL :: Instruction DecR :: ArithmeticTarget -> Instruction DecHL :: Instruction + BOR :: ArithmeticTarget -> (Word8 -> Word8 -> Word8) -> FlagRegister -> Instruction + BOHL :: (Word8 -> Word8 -> Word8) -> FlagRegister -> Instruction + BON :: Word8 -> (Word8 -> Word8 -> Word8) -> FlagRegister -> Instruction + CCF :: Instruction + SCF :: Instruction + DAA :: Instruction -- TODO: What does this do? + CPL :: Instruction execute :: CPU -> Instruction -> CPU execute cpu = \case @@ -135,11 +141,33 @@ execute cpu = \case value = fetch cpu target (newValue, newFlags) = sub value 1 False in write cpu target newValue & registers . flags .~ newFlags + BOR t op _f -> let newValue = (cpu ^. registers . a) `op` (cpu ^. registers . t) + newFlags = _f {_zero = newValue == 0} in + cpu & registers . a .~ newValue & registers . flags .~ newFlags + BOHL op _f -> let target = getHL $ cpu ^. registers + value = fetch cpu target + newValue = (cpu ^. registers . a) `op` value + newFlags = _f {_zero = value == 0} in + cpu & registers . a .~ newValue & registers . flags .~ newFlags + + BON value op _f -> let newValue = (cpu ^. registers . a) `op` value + newFlags = _f {_zero = newValue == 0} in + cpu & registers . a .~ newValue & registers . flags .~ newFlags + CCF -> cpu & registers . flags . negative .~ False + & registers . flags . halfCarry .~ False + & registers . flags . carry %~ not + SCF -> cpu & registers . flags . negative .~ False + & registers . flags . halfCarry .~ False + & registers . flags . carry .~ True + DAA -> undefined -- TODO: undefined in manual + CPL -> cpu & registers . a %~ complement + & registers . flags . negative .~ True + & registers . flags . halfCarry .~ True where add :: Word8 -> Word8 -> Bool -> (Word8, FlagRegister) add o n _c = let new = o + n + if _c then 1 else 0 _zero = new == 0 - _subtract = False + _negative = False _carry = o > new _halfCarry = o .&. 16 + n .&. 16 > 16 in (new, FlagRegister {..}) @@ -147,7 +175,7 @@ execute cpu = \case sub :: Word8 -> Word8 -> Bool -> (Word8, FlagRegister) sub o n _c = let new = o - n - if _c then 1 else 0 _zero = new == 0 - _subtract = True + _negative = True _carry = o > new _halfCarry = o .&. 16 + n .&. 16 > 16 in (new, FlagRegister {..})