{-# LANGUAGE BinaryLiterals #-}
{-# LANGUAGE RecordWildCards #-}
module Lazyboy.IO where
import Control.Monad.Trans.RWS.Lazy
import Data.Bits
import Data.Word
import Lazyboy.Constants
import Lazyboy.Control
import Lazyboy.Types
class Bitfield a where
pack :: a -> Word8
data Color = White | Light | Dark | Black
deriving (Eq, Ord)
instance Bitfield Color where
pack White = 0b00
pack Light = 0b01
pack Dark = 0b10
pack Black = 0b11
data LCDControl = LCDControl { lcdDisplayEnable :: Bool
, lcdWindowTileMap :: Bool
, lcdEnableWindowDisplay :: Bool
, lcdWindowSelect :: Bool
, lcdTileMapSelect :: Bool
, lcdObjSize :: Bool
, lcdEnableObjects :: Bool
, lcdBackgroundEnable :: Bool
}
defaultLCDControl :: LCDControl
defaultLCDControl = LCDControl False False False False False False False False
instance Bitfield LCDControl where
pack lcds = zeroBits .|. lcdDE .|. lcdWTM .|. lcdEWD .|. lcdWS .|. lcdTMS .|. lcdOS .|. lcdEO .|. lcdBE
where lcdDE = if lcdDisplayEnable lcds then 0b10000000 else 0
lcdWTM = if lcdWindowTileMap lcds then 0b01000000 else 0
lcdEWD = if lcdEnableWindowDisplay lcds then 0b00100000 else 0
lcdWS = if lcdWindowSelect lcds then 0b00010000 else 0
lcdTMS = if lcdTileMapSelect lcds then 0b00001000 else 0
lcdOS = if lcdObjSize lcds then 0b00000100 else 0
lcdEO = if lcdEnableObjects lcds then 0b00000010 else 0
lcdBE = if lcdBackgroundEnable lcds then 0b00000001 else 0
disableLCD :: Lazyboy ()
disableLCD = setLCDControl defaultLCDControl
setLCDControl :: LCDControl -> Lazyboy ()
setLCDControl lcd = write (Address lcdc) $ pack lcd
data BackgroundPalette = BackgroundPalette { bgpColor3 :: Color
, bgpColor2 :: Color
, bgpColor1 :: Color
, bgpColor0 :: Color
}
defaultPalette :: BackgroundPalette
defaultPalette = BackgroundPalette Black Dark Light White
instance Bitfield BackgroundPalette where
pack BackgroundPalette {..} = zeroBits .|. zero .|. one .|. two .|. three
where zero = pack bgpColor0
one = pack bgpColor1 `shiftL` 2
two = pack bgpColor2 `shiftL` 4
three = pack bgpColor3 `shiftL` 6
setBackgroundPalette :: BackgroundPalette -> Lazyboy ()
setBackgroundPalette pal = write (Address bgp) $ pack pal
byte :: Register8 -> Word8 -> Lazyboy ()
byte reg val = tell [LDrn reg val]
write :: Location -> Word8 -> Lazyboy ()
write addr val = tell [LDrrnn HL addr, LDHLn val]
memcpy :: Location -> Location -> Word8 -> Lazyboy ()
memcpy src dest len = do
tell [LDrrnn HL src, LDrrnn DE dest, LDrn B len]
withLocalLabel $ \label -> do
tell [LDAHLI]
tell [LDrrA DE, INCrr DE, DECr B, JPif NonZero (Name label)]
memset :: Location -> Word8 -> Word8 -> Lazyboy ()
memset dest len value = do
tell [LDrrnn HL dest, LDrn B len, LDrn A value]
withLocalLabel $ \label -> do
tell [LDHLAI]
tell [DECr B, JPif NonZero (Name label)]
onVblank :: Lazyboy () -> Lazyboy ()
onVblank block = do
withLocalLabel $ \label -> do
tell [LDAnn $ Address ly, CPn 145]
tell [JPif NonZero $ Name label]
block