summaryrefslogtreecommitdiff
path: root/fig-emulator-gb/src/Fig/Emulator/GB/Utils.hs
blob: 4ad6f2440035adb60d7752db9b9906cecb1f90cd (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
90
module Fig.Emulator.GB.Utils where

import Fig.Prelude

import Prelude (fromIntegral)

import qualified Text.Printf as Pr

import Data.Word (Word8, Word16)
import Data.Int (Int8)
import Data.Bits

show8 :: Word8 -> Text
show8 = pack . Pr.printf "%02X"

show16 :: Word8 -> Text
show16 = pack . Pr.printf "%04X"

w8w8 :: Word8 -> Word8 -> Word16
w8w8 high low = shiftL (fromIntegral high) 8 .|. fromIntegral low

w16hi :: Word16 -> Word8
w16hi v = fromIntegral $ shiftR v 8

w16lo :: Word16 -> Word8
w16lo v = fromIntegral $ v .&. 0xff

w8bit :: Int -> Word8 -> Bool
w8bit i v = shiftR v i .&. 0b1 == 1

w8bits2 :: Int -> Word8 -> Word8
w8bits2 i v = shiftR v (i - 1) .&. 0b11

w8bits3 :: Int -> Word8 -> Word8
w8bits3 i v = shiftR v (i - 2) .&. 0b111

w8bits4 :: Int -> Word8 -> Word8
w8bits4 i v = shiftR v (i - 3) .&. 0b1111

flagsw8 :: Bool -> Bool -> Bool -> Bool -> Word8
flagsw8 z n h c =
  shiftL (if z then 1 else 0) 7
  .|. shiftL (if n then 1 else 0) 6
  .|. shiftL (if h then 1 else 0) 5
  .|. shiftL (if c then 1 else 0) 4

w8flags :: Word8 -> (Bool, Bool, Bool, Bool)
w8flags x = (z, n, h, c)
  where
    z = w8bit 7 x
    n = w8bit 6 x
    h = w8bit 5 x
    c = w8bit 4 x

zext :: Word8 -> Word16
zext = fromIntegral

sext :: Word8 -> Word16
sext x = fromIntegral y
  where
    y :: Int8
    y = fromIntegral x

trunc :: Word16 -> Word8
trunc = fromIntegral

addC :: Bool -> Word8 -> Word8 -> (Word8, Bool)
addC c x y = (trunc res, shiftR res 8 .&. 1 == 1)
  where
    res :: Word16
    res = zext x + zext y + if c then 1 else 0

addH :: Bool -> Word8 -> Word8 -> Bool
addH c x y = shiftR res 4 .&. 1 == 1
  where
    xlo = x .&. 0xf
    ylo = y .&. 0xf
    res :: Word8
    res = xlo + ylo + if c then 1 else 0

subC :: Bool -> Word8 -> Word8 -> (Word8, Bool)
subC c x y = (trunc $ xs - ys, yz > xz)
  where
    xs = sext x
    ys = sext y + if c then 1 else 0
    xz = zext x
    yz = zext y + if c then 1 else 0

subH :: Bool -> Word8 -> Word8 -> Bool
subH c x y = zext (w8bits4 3 x) < (zext (w8bits4 3 y) + if c then 1 else 0)