-
Notifications
You must be signed in to change notification settings - Fork 0
/
util.lua
140 lines (110 loc) · 3.23 KB
/
util.lua
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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
--@name Util
--@client
local bit_band, bit_bor, bit_bxor, bit_lshift, bit_rshift = bit.band, bit.bor, bit.bxor, bit.lshift, bit.rshift
local assert = assert
require("gameboy/memory/mmu.txt")
local mmu_set, mmu_get, init_memory = mmu_set, mmu_get, init_memory
function load_bytes(path)
-- Loads SIZE bytes into an array. If the files contains less than SIZE bytes, it will pad with zeros.
local f = file.open(path, "rb")
assert(f ~= nil, "could not open file")
local size = f:size()
local content = f:read(size)
f:close()
local arr = {}
for i = 1, size do
arr[i] = string.byte(content:sub(i, i))
end
return arr
end
function inv16(x)
return bit_band(bit_bxor(x, 0xFFFF) + 1, 0xFFFF)
end
function inv8(x)
return bit_band(bit_bxor(x, 0xFF) + 1, 0xFF)
end
function add8to8(x, y, reg, half_carry, carry)
local result = x + y
local c = (result > 0xFF)
local h = (bit_band(bit_band(x, 0x0F) + bit_band(y, 0x0F), 0xF0) ~= 0)
if half_carry then
if h then
register_set_flag_h(reg)
else
register_unset_flag_h(reg)
end
end
if carry then
if c then
register_set_flag_cy(reg)
else
register_unset_flag_cy(reg)
end
end
return bit_band(result, 0xFF)
end
function add16to16(x, y, reg, half_carry, carry)
local result = x + y
local c = (result > 0xFFFF)
local h = (bit_band(bit_band(x, 0x0FFF) + bit_band(y, 0x0FFF), 0xF000) ~= 0)
if half_carry then
if h then
register_set_flag_h(reg)
else
register_unset_flag_h(reg)
end
end
if carry then
if c then
register_set_flag_cy(reg)
else
register_unset_flag_cy(reg)
end
end
return bit_band(result, 0xFFFF)
end
function add8to16(x, y, reg, half_carry, carry)
-- x: 8 bits
-- y: 16 bits
assert(x >= 0 and x <= 0xFF)
assert(y >= 0 and y <= 0xFFFF)
local x16 = x
local x16 = (bit_band(x, 0x80) > 0) and inv16(inv8(x16)) or x16
local result = add16to16(x16, y, reg, false, false)
-- Set the flag, apparently adding 8 bits to 16 bits behaves like a 8 bits + 8 bits...
add8to8(x, bit_band(y,0xFF), reg, half_carry, carry)
return result
end
function sub8to8(x, y, reg, half_carry, carry)
local r1 = bit_band(x, 0x0F) - bit_band(y, 0x0F)
local r1 = (r1 < 0) and inv16(-r1) or r1
local r2 = x - y
local r2 = (r2 < 0) and inv16(-r2) or r2
local c = (r2 > 0xFF)
local h = (r1 > 0xF)
if half_carry then
if h then
register_set_flag_h(reg)
else
register_unset_flag_h(reg)
end
end
if carry then
if c then
register_set_flag_cy(reg)
else
register_unset_flag_cy(reg)
end
end
return bit_band(r2, 0xFF)
end
function sub16to16(x, y, reg, half_carry, carry)
assert(half_carry == false, "not implemented for half_carry=true")
assert(carry == false, "not implemented for carry=true")
return add16to16(x, inv16(y), reg, half_carry, carry)
end
function next16(memory, pos)
local low = mmu_get(memory, pos)
local high = mmu_get(memory, pos+1)
return bit_bor(low, bit_lshift(high, 8))
end