Skip to content

Commit

Permalink
Trying to clean up opcode 0xDXYN
Browse files Browse the repository at this point in the history
  • Loading branch information
smparsons committed Sep 13, 2018
1 parent 163dc2d commit 8e191c6
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 24 deletions.
4 changes: 4 additions & 0 deletions src/Constants.hs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ module Constants
( programCounterIncrement,
chip8NumberOfColumns,
chip8NumberOfRows,
chip8SpriteWidth,
chip8InitialState,
chip8Fontset
) where
Expand All @@ -21,6 +22,9 @@ chip8NumberOfColumns = 64
chip8NumberOfRows :: Int
chip8NumberOfRows = 32

chip8SpriteWidth :: Int
chip8SpriteWidth = 8

chip8InitialState :: Chip8State
chip8InitialState = Chip8State {
_currentOpcode = 0x0000,
Expand Down
64 changes: 40 additions & 24 deletions src/Opcodes/Display.hs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ module Opcodes.Display

import qualified Data.Vector as V
import Data.Bits
import Data.Word
import Control.Monad.State
import Control.Lens

Expand All @@ -30,33 +31,48 @@ clearScreen = do
screen pixels are flipped from set to unset when the sprite is drawn, and to 0 if that
doesn’t happen
-}
type PixelUpdate = (Int, Word8)
type PixelCoordinates = (Int, Int)
type Offsets = (Int, Int)

data PixelUpdates = PixelUpdates {
updates :: [PixelUpdate],
collisionResult :: Word8
}

drawGraphics :: Chip8 ()
drawGraphics = do
chip8State <- get
result <- getPixelsToUpdate
let updateGraphics = flip V.update $ V.fromList $ updates result
storeCollision = flip V.update $ V.fromList [(0xF, collisionResult result)]
modify (\givenState -> givenState & graphics %~ updateGraphics)
modify (\givenState -> givenState & vRegisters %~ storeCollision)
modify (\givenState -> givenState & drawFlag .~ True)
incrementProgramCounter

getPixelsToUpdate :: Chip8 PixelUpdates
getPixelsToUpdate = do
coordinateX <- fmap fromIntegral getRegisterXValue
coordinateY <- fmap fromIntegral getRegisterYValue
spriteHeight <- fmap fromIntegral parseOneDigitConstant
let offsets = [(colOffset,rowOffset) | colOffset <- [0..chip8SpriteWidth-1], rowOffset <- [0..spriteHeight-1]]
pixelUpdateResults <- mapM (getPixelUpdate (coordinateX, coordinateY)) offsets
return PixelUpdates {
updates = map (\(pixelUpdate, _) -> pixelUpdate) pixelUpdateResults,
collisionResult = if (any (\(_, collision) -> collision) pixelUpdateResults) then 0x1 else 0x0
}

getPixelUpdate :: PixelCoordinates -> Offsets -> Chip8 (PixelUpdate, Bool)
getPixelUpdate (coordinateX, coordinateY) (colOffset, rowOffset) = do
chip8State <- get
let spriteWidth = 8
pixelChangesAndCollisions =
map
(\(colOffset,rowOffset) ->
let convertedIndexRegisterValue = (fromIntegral $ chip8State^.indexRegister) :: Int
xIndex = (coordinateX + colOffset) `mod` chip8NumberOfColumns
yIndex = (coordinateY + rowOffset) `mod` chip8NumberOfRows
currentIndex = xIndex + (yIndex * chip8NumberOfColumns)
graphicsPixel = (chip8State^.graphics) V.! currentIndex
memoryValue = (chip8State^.memory) V.! (convertedIndexRegisterValue + rowOffset)
memoryPixel =
(memoryValue .&. (0x80 `shiftR` colOffset)) `shiftR` ((spriteWidth - 1) - colOffset)
result = graphicsPixel `xor` memoryPixel
collision = graphicsPixel == 1 && memoryPixel == 1
in ((currentIndex, result), collision))
[(colOffset,rowOffset) | colOffset <- [0..spriteWidth-1], rowOffset <- [0..spriteHeight-1]]
pixelChanges = map (\((currentIndex, result), _) -> (currentIndex, result)) pixelChangesAndCollisions
collisionResult = if (any (\((_, _), collision) -> collision) pixelChangesAndCollisions) then 0x1 else 0x0
updateGraphics = flip V.update $ V.fromList pixelChanges
storeCollision = flip V.update $ V.fromList [(0xF, collisionResult)]
modify (\givenState -> givenState & graphics %~ updateGraphics)
modify (\givenState -> givenState & vRegisters %~ storeCollision)
modify (\givenState -> givenState & drawFlag .~ True)
incrementProgramCounter
convertedIndexRegisterValue = (fromIntegral $ chip8State^.indexRegister) :: Int
xIndex = (coordinateX + colOffset) `mod` chip8NumberOfColumns
yIndex = (coordinateY + rowOffset) `mod` chip8NumberOfRows
currentIndex = xIndex + (yIndex * chip8NumberOfColumns)
graphicsPixel = (chip8State^.graphics) V.! currentIndex
memoryValue = (chip8State^.memory) V.! (convertedIndexRegisterValue + rowOffset)
memoryPixel = (memoryValue .&. (0x80 `shiftR` colOffset)) `shiftR` ((spriteWidth - 1) - colOffset)
result = graphicsPixel `xor` memoryPixel
collision = graphicsPixel == 1 && memoryPixel == 1
return ((currentIndex, result), collision)

0 comments on commit 8e191c6

Please sign in to comment.