summaryrefslogtreecommitdiff
path: root/fig-emulator-gb/src/Fig/Emulator/GB.hs
blob: cc68afe5a4caff2a8c018a96309fc5d81320f0e8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
module Fig.Emulator.GB where

import Prelude (error)
import Fig.Prelude

import System.IO (withFile, IOMode (WriteMode))

import Control.Lens ((.=), use)
import Control.Monad (when)
import Control.Monad.State.Strict (StateT(..))

import qualified Data.Vector as V
import qualified Data.ByteString as BS

import qualified SDL

import Fig.Emulator.GB.CPU
import Fig.Emulator.GB.CPU.Instruction
import Fig.Emulator.GB.Bus (Bus(..), Addr(..))
import Fig.Emulator.GB.Component.RAM
import Fig.Emulator.GB.Component.ROM
import Fig.Emulator.GB.Component.Video
import Fig.Emulator.GB.Component.Joystick
import Fig.Emulator.GB.Component.Serial
import Fig.Emulator.GB.Component.Interrupt (compInterrupt)

cpuDMG :: Maybe Handle -> ByteString -> Framebuffer -> CPU
cpuDMG serial rom fb = CPU
  { _lastPC = 0x0
  , _lastIns = Nop
  , _running = True
  , _regs = initialRegs
  , _bus = Bus
    [ compROM rom
    , compWRAM 0xc000 $ 8 * 1024
    , compVideo fb
    , compJoystick
    , compSerial serial
    , compInterrupt
    , compWRAM 0xff80 0x7e -- HRAM
    ]
  }

testRun :: Maybe FilePath -> ByteString -> IO ()
testRun serialOut rom = do
  SDL.initializeAll
  window <- SDL.createWindow "taking" SDL.defaultWindow
  fb <- initializeFramebuffer
  let withSerial f = case serialOut of
        Nothing -> f Nothing
        Just p -> withFile p WriteMode $ f . Just
  liftIO $ withSerial \hserial -> do
    let cpu = cpuDMG hserial rom fb
    let
      loop :: Int -> Emulating ()
      loop cycle = do
        -- events <- SDL.pollEvents
        -- forM_ events \ev ->
        --   case SDL.eventPayload ev of
        --     SDL.QuitEvent -> running .= False
        --     _else -> pure ()
        pc <- use $ regs . regPC
        ins <- decode
        when (pc == 0x2817) do
          log $ mconcat
            [ pretty $ Addr pc
            , ": ", tshow ins
            ]
        step ins
        when (rem cycle 1000000 == 0) do
          log "1 million"
        -- when (rem cycle 70224 == 0) do
        --   ws <- SDL.getWindowSurface window
        --   SDL.surfaceFillRect ws Nothing $ SDL.V4 0x00 0x00 0x00 0xff
        --   void $
        --     SDL.surfaceBlitScaled
        --     (fbSurface fb)
        --     Nothing
        --     ws
        --     (Just $ SDL.Rectangle
        --      (SDL.P $ SDL.V2 0 0)
        --      (SDL.V2
        --       (fromIntegral screenWidth * 8)
        --       (fromIntegral screenHeight * 8)))
        --   SDL.updateWindowSurface window
        r <- use running
        when r . loop $ cycle + 1
    void $ flip (runStateT . runEmulating) cpu do
      loop 0