diff --git a/src/GBC/CPU.hs b/src/GBC/CPU.hs index 5c87366..ba144b3 100644 --- a/src/GBC/CPU.hs +++ b/src/GBC/CPU.hs @@ -11,6 +11,12 @@ import Data.Bits import Data.Int import qualified Data.Vector.Sized as V +splitWord :: Word16 -> (Word8, Word8) +splitWord w = (fromIntegral $ w .>>. 8, fromIntegral $ w .&. 255) + +combineWords :: Word8 -> Word8 -> Word16 +combineWords msb lsb = (fromIntegral msb .<<. 8) + (fromIntegral lsb) + class Convert a b where convert :: a -> b @@ -64,15 +70,15 @@ makeLenses ''Registers rbc :: Lens' Registers Word16 rbc = lens (\r -> (( .<<. 8) . fromIntegral $ r ^. rb) + (fromIntegral $ r ^. rc)) - (\r w -> r & rb %~ (const $ fromIntegral $ w .>>. 8) & rc %~ (const $ fromIntegral $ w .&. 255)) + (\r w -> let (msb, lsb) = splitWord w in r & rb .~ msb & rc .~ lsb) rde :: Lens' Registers Word16 rde = lens (\r -> (( .<<. 8) . fromIntegral $ r ^. rd) + (fromIntegral $ r ^. re)) - (\r w -> r & rd %~ (const $ fromIntegral $ w .>>. 8) & re %~ (const $ fromIntegral $ w .&. 255)) + (\r w -> let (msb, lsb) = splitWord w in r & rd .~ msb & re .~ lsb) rhl :: Lens' Registers Word16 rhl = lens (\r -> ((.<<. 8) . fromIntegral $ r ^. rh) + (fromIntegral $ r ^. rl)) - (\r w -> r & rh %~ (const $ fromIntegral $ w .>>. 8) & rl %~ (const $ fromIntegral $ w .&. 255)) + (\r w -> let (msb, lsb) = splitWord w in r & rh .~ msb & rl .~ lsb) data CPU = CPU { _registers :: Registers , _ir :: Word8 @@ -107,6 +113,7 @@ negative = lens (^. flags . fNegative) (\cpu _f -> cpu & flags . fNegative .~ halfCarry = lens (^. flags . fHalfCarry) (\cpu _f -> cpu & flags . fHalfCarry .~ _f) carry = lens (^. flags . fCarry) (\cpu _f -> cpu & flags . fCarry .~ _f) + type ByteTarget = Lens' CPU Word8 type WordTarget = Lens' CPU Word16 type FlagTarget = Lens' CPU Bool @@ -419,14 +426,13 @@ execute cpu = \case LDNNSP v -> write cpu v . fetch cpu $ cpu ^. sp LDSPHL -> cpu & sp .~ cpu ^. hl PUSHRR t -> let cpu' = cpu & sp %~ subtract 1 - msb = fromIntegral $ (cpu ^. t) .>>. 4 - lsb = fromIntegral $ (cpu ^. t) .&. 255 + (msb, lsb) = splitWord $ cpu ^. t cpu'' = write cpu' (cpu' ^. sp) msb & sp %~ subtract 1 in write cpu'' (cpu'' ^. sp) lsb POPRR t -> let lsb = fetch cpu (cpu ^. sp) cpu' = cpu & sp %~ (+1) msb = fetch cpu' (cpu' ^. sp) - value = (fromIntegral msb .<<. 8) + (fromIntegral lsb) + value = combineWords msb lsb in cpu & t .~ value & sp %~ (+1) @@ -450,14 +456,27 @@ execute cpu = \case cpu CALLNN v -> undefined CALLCCNN v _f op -> undefined - RET -> undefined + RET -> let lsb = fetch cpu (cpu ^. sp) + cpu' = cpu & sp %~ (+1) + msb = fetch cpu' (cpu' ^. sp) + value = combineWords msb lsb in + cpu & pc .~ value + & ie .~ 1 RETCC _f op -> undefined - RETI -> undefined - RSTN v -> undefined + RETI -> let lsb = fetch cpu (cpu ^. sp) + cpu' = cpu & sp %~ (+1) + msb = fetch cpu' (cpu' ^. sp) + value = combineWords msb lsb in + cpu & pc .~ value + & ie .~ 1 + RSTN v -> let cpu' = cpu & sp %~ subtract 1 + (msb,lsb) = splitWord $ cpu ^. pc + cpu'' = write cpu' (cpu' ^. sp) msb & sp %~ subtract 1 in + write cpu'' (cpu'' ^. sp) lsb & pc .~ v HALT -> undefined STOP -> undefined - DI -> undefined - EI -> undefined + DI -> cpu & ie .~ 0 + EI -> cpu & ie .~ 1 NOP -> cpu where add :: Word8 -> Word8 -> Bool -> (Word8, FlagRegister) @@ -484,7 +503,7 @@ execute cpu = \case (new, FlagRegister {..}) fetch :: CPU -> Word16 -> Word8 - fetch _cpu addr = (`V.index` (fromIntegral addr)) $ _cpu ^. bus + fetch _cpu addr = _cpu ^. bus . V.ix (fromIntegral addr) write :: CPU -> Word16 -> Word8 -> CPU - write _cpu target value = _cpu & bus %~ (`V.update` V.singleton (fromIntegral target, value)) + write _cpu target value = _cpu & bus . V.ix (fromIntegral target) .~ value