Skip to content

Commit

Permalink
add some work-in-progress conditional logic plus a boolean and
Browse files Browse the repository at this point in the history
  • Loading branch information
ix committed May 29, 2019
1 parent 730ffce commit ce486bf
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 24 deletions.
23 changes: 5 additions & 18 deletions example/Main.hs
Original file line number Diff line number Diff line change
Expand Up @@ -10,21 +10,8 @@ import Lazyboy.Target.ASM
main :: IO ()
main = rom >>= T.putStrLn
where rom = compileROM $ do
smiley <- embedBytes image
-- set scroll values
write (Address scx) 0
write (Address scy) 0
-- set background palette
setBackgroundPalette defaultPalette
-- perform graphics operations
onVblank $ do
disableLCD
memcpy (Name smiley) (Address $ 0x9010) $ fromIntegral $ length image
memset (Address 0x9904) (0x992F - 0x9904) 0 -- clear the background tilemap
write (Address background1) 1 -- write the background tile data
setLCDControl $ defaultLCDControl { lcdDisplayEnable = True, lcdBackgroundEnable = True }
-- halt indefinitely
freeze

image :: [Word8]
image = [0x00,0x00,0x00,0x00,0x24,0x24,0x00,0x00,0x81,0x81,0x7e,0x7e,0x00,0x00,0x00,0x00]
byte A 0xDE
byte B 0xDE
if' ((A `equalTo` (0xDE :: Word8)) `Lazyboy.and` (A `equalTo` B)) $ do
write (Address wram0) 0xDE
freeze
92 changes: 86 additions & 6 deletions src/Lazyboy/Control.hs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
This module defines methods of controlling the flow of execution for Lazyboy.
-}

{-# LANGUAGE MultiParamTypeClasses #-}

module Lazyboy.Control where

import Control.Monad.Trans.RWS
Expand All @@ -19,7 +21,7 @@ import Lazyboy.Types
-- | Get a label, and in the process increment the counter used to track labels.
-- this provides a safe interface to label retrieval and utilization.
getLabel :: Lazyboy Integer
getLabel = do
getLabel = do
label <- get
modify (+ 1)
return label
Expand All @@ -42,15 +44,15 @@ withLabel block = do
-- | Execute an action within a local label and pass the action the label.
withLocalLabel :: (Label -> Lazyboy ()) -> Lazyboy ()
withLocalLabel block = do
label <- getLocalLabel
label <- getLocalLabel
tell [LABEL label]
block label

-- | Embed a file and return a global label for it.
-- A jump over the block of data is added to prevent the image data being executed.
embedFile :: FilePath -> Lazyboy Label
embedFile file = do
label <- getGlobalLabel
label <- getGlobalLabel
skipLabel <- getGlobalLabel
tell [JP $ Name skipLabel]
tell [LABEL label, INCLUDE file]
Expand Down Expand Up @@ -79,9 +81,87 @@ freeze = withLabel $ \label -> do
tell [JP $ Name label]

-- | Executes the given action provided condition flag is set.
cond :: Condition -> Lazyboy () -> Lazyboy ()
cond :: Condition -> Lazyboy a -> Lazyboy a
cond condition block = do
label <- getLocalLabel
label <- getLocalLabel
tell [JPif condition (Name label)]
block
a <- block
tell [LABEL label]
return a

-- | A typeclass for comparisons between registers and values.
class Comparable a b where
equalTo :: a -> b -> Lazyboy Condition -- ^ Check the equality of two items.
notEqualTo :: a -> b -> Lazyboy Condition -- ^ Check the inequality of two items.
greaterThan :: a -> b -> Lazyboy Condition -- ^ Check whether `a` is greater than `b`.
lessThan :: a -> b -> Lazyboy Condition -- ^ Check whether `a` is less than `b`.

-- | An instance for comparing two 8-bit registers.
instance Comparable Register8 Register8 where
equalTo A r = tell [CPr r] >> return NonZero
equalTo r r' = tell [LDrr A r, CPr r'] >> return NonZero
notEqualTo A r = equalTo A r >> return Zero
notEqualTo r r' = equalTo r r' >> return Zero
greaterThan A r = equalTo A r >> return NoCarry
greaterThan r r' = equalTo r r' >> return NoCarry
lessThan A r = equalTo A r >> return Carry
lessThan r r' = equalTo r r' >> return Carry

-- | An instance for comparing an 8-bit register and a Word8.
instance Comparable Register8 Word8 where
equalTo A n = tell [CPn n] >> return NonZero
equalTo r n = tell [LDrr A r, CPn n] >> return NonZero
notEqualTo A n = equalTo A n >> return Zero
notEqualTo r n = equalTo r n >> return Zero
greaterThan A n = equalTo A n >> return NoCarry
greaterThan r n = equalTo r n >> return NoCarry
lessThan A n = equalTo A n >> return Carry
lessThan r n = equalTo r n >> return Carry

-- | An instance for comparing a Word8 and an 8-bit register (this is an alias).
instance Comparable Word8 Register8 where
equalTo = flip equalTo
notEqualTo = flip notEqualTo
greaterThan = flip greaterThan
lessThan = flip lessThan

-- | Executes an action which returns a condition flag, then conditionally executes
-- another action baed on the state of that condition flag.
if' :: Lazyboy Condition -> Lazyboy a -> Lazyboy a
if' condition block = do
flag <- condition
cond flag block


not :: Lazyboy Condition -> Lazyboy Condition
not action = do
flag <- action
return $ case flag of
Zero -> NonZero
NonZero -> Zero
Carry -> NoCarry
NoCarry -> Carry

-- | Assign boolean values to two registers based on the result flags of
-- some conditions and then AND them and return the result.

-- [TODO] Establish whether we still need this at all - it was the ideal but it's seemingly not possible.
{- and :: Lazyboy Condition -> Lazyboy Condition -> Lazyboy Condition
and a b = do
a' <- a
tell [LDrr L F]
b' <- b
tell [LDrr A F]
tell [ANDr L]
return Zero -}

and :: Lazyboy Condition -> Lazyboy Condition -> Lazyboy Condition
and a b = do
a' <- a
cond a' $ do
tell [LDrn L 1]
b' <- b
cond b' $ do
tell [LDrn A 1]
tell [ANDr L]
return Zero

0 comments on commit ce486bf

Please sign in to comment.