GBRb 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +0 -1
- data/README.md +9 -1
- data/bin/gbrb +3 -3
- data/doc/images/blargg_cpu.png +0 -0
- data/doc/images/cpu_01.png +0 -0
- data/doc/images/cpu_03.png +0 -0
- data/doc/images/cpu_04.png +0 -0
- data/doc/images/cpu_05.png +0 -0
- data/doc/images/cpu_06.png +0 -0
- data/doc/images/cpu_07.png +0 -0
- data/doc/images/cpu_08.png +0 -0
- data/doc/images/cpu_09.png +0 -0
- data/doc/images/cpu_10.png +0 -0
- data/doc/images/cpu_11.png +0 -0
- data/doc/images/nintendo_logo.png +0 -0
- data/doc/images/opus5.png +0 -0
- data/doc/images/test.gb.png +0 -0
- data/doc/images/ttt.png +0 -0
- data/lib/gbrb.rb +7 -0
- data/lib/gbrb/cartridge.rb +21 -8
- data/lib/gbrb/cartridge/cartridge.rb +187 -0
- data/lib/gbrb/cpu/concatenated_register.rb +1 -1
- data/lib/gbrb/cpu/z80.rb +575 -498
- data/lib/gbrb/gb.rb +102 -32
- data/lib/gbrb/graphics.rb +1 -1
- data/lib/gbrb/graphics/gpu.rb +38 -30
- data/lib/gbrb/graphics/mode_clock.rb +31 -30
- data/lib/gbrb/graphics/screen_client.rb +3 -2
- data/lib/gbrb/instruction_set.rb +16 -0
- data/lib/gbrb/instruction_set/arithmetic.rb +238 -0
- data/lib/gbrb/instruction_set/bitwise.rb +64 -0
- data/lib/gbrb/instruction_set/boolean.rb +61 -0
- data/lib/gbrb/instruction_set/call.rb +40 -0
- data/lib/gbrb/instruction_set/carry.rb +23 -0
- data/lib/gbrb/instruction_set/cpl.rb +12 -0
- data/lib/gbrb/instruction_set/daa.rb +33 -0
- data/lib/gbrb/instruction_set/instruction.rb +23 -0
- data/lib/gbrb/instruction_set/jump.rb +47 -0
- data/lib/gbrb/instruction_set/ld.rb +241 -0
- data/lib/gbrb/instruction_set/return.rb +43 -0
- data/lib/gbrb/instruction_set/rotate.rb +178 -0
- data/lib/gbrb/instruction_set/rst.rb +16 -0
- data/lib/gbrb/instruction_set/special.rb +37 -0
- data/lib/gbrb/instruction_set/stack.rb +34 -0
- data/lib/gbrb/instruction_set/swap.rb +32 -0
- data/lib/gbrb/mmu.rb +60 -35
- data/lib/gbrb/options.rb +54 -0
- data/lib/gbrb/timer.rb +114 -0
- data/lib/gbrb/version.rb +1 -1
- data/misc/dump_diff +133 -0
- data/perf/cpu_perf_spec.rb +2 -2
- data/spec/gbrb/cartridge/cartridge_spec.rb +19 -0
- data/spec/gbrb/cartridge/mbc1_spec.rb +83 -0
- data/spec/gbrb/cpu/z80_spec.rb +92 -2
- data/spec/gbrb/{cpu/instruction_spec.rb → instruction_set/arithmetic_spec.rb} +21 -100
- data/spec/gbrb/instruction_set/boolean_spec.rb +50 -0
- data/spec/gbrb/instruction_set/instruction_spec.rb +22 -0
- data/spec/gbrb/instruction_set/ld_spec.rb +21 -0
- data/spec/gbrb/instruction_set/special_spec.rb +22 -0
- data/spec/gbrb/mmu_spec.rb +1 -1
- data/spec/gbrb/timer_spec.rb +26 -0
- metadata +53 -9
- data/lib/gbrb/cpu/instruction.rb +0 -648
- data/spec/gbrb/cartridge_spec.rb +0 -19
- data/spec/gbrb/graphics/mode_clock_spec.rb +0 -82
@@ -0,0 +1,33 @@
|
|
1
|
+
require_relative '../cpu'
|
2
|
+
require_relative 'instruction'
|
3
|
+
|
4
|
+
module GBRb::InstructionSet
|
5
|
+
class Daa < Instruction
|
6
|
+
def initialize m=1, t=4
|
7
|
+
super
|
8
|
+
end
|
9
|
+
|
10
|
+
def call r, *misc
|
11
|
+
a = r.a.read
|
12
|
+
|
13
|
+
if r.add_sub_flag?
|
14
|
+
a = (a - 0x06) & 0xff if r.half_carry_flag?
|
15
|
+
a -= 0x60 if r.carry_flag?
|
16
|
+
else
|
17
|
+
if r.half_carry_flag? || a&0x0f > 9
|
18
|
+
a += 0x06
|
19
|
+
end
|
20
|
+
if r.carry_flag? || a > 0x9f
|
21
|
+
a += 0x60
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
r.clear_half_carry_flag
|
26
|
+
|
27
|
+
r.set_carry_flag if a & 0x100 == 0x100
|
28
|
+
|
29
|
+
r.a.store a
|
30
|
+
r.a.zero? ? r.set_zero_flag : r.clear_zero_flag
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module GBRb::InstructionSet
|
2
|
+
class Instruction
|
3
|
+
attr_accessor :i, :m, :t
|
4
|
+
|
5
|
+
def initialize m=1, t=4, immediates=0, *extra
|
6
|
+
@m = m
|
7
|
+
@t = t
|
8
|
+
@immediates = immediates
|
9
|
+
end
|
10
|
+
|
11
|
+
def immediate_count
|
12
|
+
@immediates
|
13
|
+
end
|
14
|
+
|
15
|
+
def call r, mem
|
16
|
+
nil
|
17
|
+
end
|
18
|
+
|
19
|
+
def carry? left, right, mask
|
20
|
+
(mask-1 & left).public_send(@op, mask-1 & right) & mask == mask
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require_relative 'instruction'
|
2
|
+
|
3
|
+
module GBRb::InstructionSet
|
4
|
+
class Jump < Instruction
|
5
|
+
def initialize condition, m=2, t_high=12, t_low=8, immediates=1
|
6
|
+
super m, t_low, immediates
|
7
|
+
@m_low = m
|
8
|
+
@t_high = t_high
|
9
|
+
@t_low = t_low
|
10
|
+
@condition = condition.downcase.to_sym
|
11
|
+
end
|
12
|
+
|
13
|
+
def call r, mem, offset=0x00
|
14
|
+
do_it = case @condition
|
15
|
+
when :c
|
16
|
+
r.carry_flag?
|
17
|
+
when :none
|
18
|
+
true
|
19
|
+
when :nc
|
20
|
+
not r.carry_flag?
|
21
|
+
when :nz
|
22
|
+
not r.zero_flag?
|
23
|
+
when :z
|
24
|
+
r.zero_flag?
|
25
|
+
else
|
26
|
+
false
|
27
|
+
end
|
28
|
+
|
29
|
+
if do_it
|
30
|
+
@t = @t_high
|
31
|
+
@m = @t_high / 4
|
32
|
+
if @immediates == 0
|
33
|
+
r.pc.store r.hl.read
|
34
|
+
elsif @immediates == 1
|
35
|
+
sign = (offset >> 7 == 1) ? :- : :+
|
36
|
+
offset = ((offset ^ 0xff) + 1) & 0xff if sign == :-
|
37
|
+
r.pc.store r.pc.read.public_send(sign, offset)
|
38
|
+
else
|
39
|
+
r.pc.store offset
|
40
|
+
end
|
41
|
+
else
|
42
|
+
@t = @t_low
|
43
|
+
@m = @m_low
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,241 @@
|
|
1
|
+
require_relative '../cpu'
|
2
|
+
require_relative 'instruction'
|
3
|
+
|
4
|
+
|
5
|
+
module GBRb::InstructionSet
|
6
|
+
class Ld < Instruction
|
7
|
+
def initialize destination, target, m=1, t=4
|
8
|
+
super m, t
|
9
|
+
@destination = destination.to_sym
|
10
|
+
@target = target.to_sym
|
11
|
+
end
|
12
|
+
|
13
|
+
def call r, mem
|
14
|
+
v = r.public_send(@target).read
|
15
|
+
r.public_send(@destination).store v
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
class Ldnhl < Instruction
|
20
|
+
def initialize destination, m=2, t=8
|
21
|
+
super m, t
|
22
|
+
@destination = destination.to_sym
|
23
|
+
end
|
24
|
+
|
25
|
+
def call r, mem
|
26
|
+
r.public_send(@destination).store mem.read_byte(r.hl.read)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
class Ldhln < Instruction
|
31
|
+
def initialize target, m=2, t=8
|
32
|
+
super m, t
|
33
|
+
@target = target.to_sym
|
34
|
+
end
|
35
|
+
|
36
|
+
def call r, mem
|
37
|
+
mem.write_byte r.hl.read, r.public_send(@target).read
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
class LdD8 < Instruction
|
42
|
+
def initialize destination, m=2, t=8
|
43
|
+
super m, t, 1
|
44
|
+
@destination = destination
|
45
|
+
end
|
46
|
+
|
47
|
+
def call r, mem, v
|
48
|
+
r.public_send(@destination).store v
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
class LdhlD8 < Instruction
|
53
|
+
def initialize m=3, t=12
|
54
|
+
super m, t, 1
|
55
|
+
end
|
56
|
+
|
57
|
+
def call r, mem, v
|
58
|
+
mem.write_byte r.hl.read, v
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
class LdD16 < Instruction
|
63
|
+
def initialize destination, m=3, t=12
|
64
|
+
super m, t, 2
|
65
|
+
@destination = destination
|
66
|
+
end
|
67
|
+
|
68
|
+
def call r, mem, v
|
69
|
+
r.public_send(@destination).store v
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
class Ldahli < Instruction
|
74
|
+
def initialize m=2, t=8
|
75
|
+
super
|
76
|
+
end
|
77
|
+
|
78
|
+
def call r, mem
|
79
|
+
r.a.store mem.read_byte r.hl.read
|
80
|
+
r.hl.store r.hl.read + 1
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
class Ldhlia < Instruction
|
85
|
+
def initialize m=2, t=8
|
86
|
+
super
|
87
|
+
end
|
88
|
+
|
89
|
+
def call r, mem
|
90
|
+
mem.write_byte r.hl.read, r.a.read
|
91
|
+
r.hl.store r.hl.read + 1
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
class Ldahld < Instruction
|
96
|
+
def initialize m=2, t=8
|
97
|
+
super
|
98
|
+
end
|
99
|
+
|
100
|
+
def call r, mem
|
101
|
+
r.a.store mem.read_byte r.hl.read
|
102
|
+
r.hl.store r.hl.read - 1
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
class Ldhlda < Instruction
|
107
|
+
def initialize m=2, t=8
|
108
|
+
super
|
109
|
+
end
|
110
|
+
|
111
|
+
def call r, mem
|
112
|
+
mem.write_byte r.hl.read, r.a.read
|
113
|
+
r.hl.store r.hl.read - 1
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
|
118
|
+
class Ldann < Instruction
|
119
|
+
def initialize target, m=2, t=8
|
120
|
+
super m, t
|
121
|
+
@target = target
|
122
|
+
end
|
123
|
+
|
124
|
+
def call r, mem
|
125
|
+
r.a.store mem.read_byte r.public_send(@target).read
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
class Ldnna < Instruction
|
130
|
+
def initialize destination, m=2, t=8
|
131
|
+
super m, t
|
132
|
+
@destination = destination
|
133
|
+
end
|
134
|
+
|
135
|
+
def call r, mem
|
136
|
+
mem.write_byte r.public_send(@destination).read, r.a.read
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
class Ldca < Instruction
|
141
|
+
def initialize m=2, t=8
|
142
|
+
super m, t
|
143
|
+
end
|
144
|
+
|
145
|
+
def call r, mem
|
146
|
+
mem.write_byte r.c.read + 0xff00, r.a.read
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
|
151
|
+
class Ldac < Instruction
|
152
|
+
def initialize m=2, t=8
|
153
|
+
super m,t
|
154
|
+
end
|
155
|
+
|
156
|
+
def call r, mem
|
157
|
+
r.a.store mem.read_byte(r.c.read + 0xff00)
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
class Lda16a < Instruction
|
162
|
+
def initialize m=4, t=16, immediates=2
|
163
|
+
super
|
164
|
+
end
|
165
|
+
|
166
|
+
def call r, mem, v
|
167
|
+
mem.write_byte v, r.a.read
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
class Ldaa16 < Instruction
|
172
|
+
def initialize m=4, t=16, immediates=2
|
173
|
+
super
|
174
|
+
end
|
175
|
+
|
176
|
+
def call r, mem, v
|
177
|
+
r.a.store mem.read_byte v
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
class Lda16sp < Instruction
|
182
|
+
def initialize m=5, t=20, immediates=2
|
183
|
+
super
|
184
|
+
end
|
185
|
+
|
186
|
+
def call r, mem, v
|
187
|
+
mem.write_word v, r.sp.read
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
class Ldsphl < Instruction
|
192
|
+
def initialize m=2, t=8
|
193
|
+
super m, t
|
194
|
+
end
|
195
|
+
|
196
|
+
def call r, mem
|
197
|
+
r.sp.store r.hl.read
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
class Ldh < Instruction
|
202
|
+
def initialize destination, target, indirect_dest, indirect_target, m=3, t=12, immediates=1
|
203
|
+
super m, t, immediates
|
204
|
+
|
205
|
+
@destination = destination
|
206
|
+
@target = target
|
207
|
+
@indirect_dest = indirect_dest
|
208
|
+
@indirect_target = indirect_target
|
209
|
+
@offset = 0xff00
|
210
|
+
end
|
211
|
+
|
212
|
+
def call r, mem, address
|
213
|
+
if @indirect_dest
|
214
|
+
value = r.public_send(@target.to_sym).read
|
215
|
+
mem.write_byte address + @offset, value
|
216
|
+
elsif @indirect_target
|
217
|
+
value = mem.read_byte address + @offset
|
218
|
+
r.public_send(@destination.to_sym).store value
|
219
|
+
end
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
class Ldhlsp < Instruction
|
224
|
+
def initialize m=3, t=12, immediates=1
|
225
|
+
super
|
226
|
+
@op = :+
|
227
|
+
end
|
228
|
+
|
229
|
+
def call r, mem, offset
|
230
|
+
check = (r.sp.read ^ offset ^ ((r.sp.read + offset) & 0xffff))
|
231
|
+
sign = (offset >> 7 == 1) ? :- : :+
|
232
|
+
offset = ((offset ^ 0xff) + 1) & 0xff if sign == :-
|
233
|
+
value = r.sp.read.public_send(sign, offset)
|
234
|
+
r.hl.store value
|
235
|
+
r.clear_zero_flag
|
236
|
+
r.clear_add_sub_flag
|
237
|
+
check & 0x100 == 0x100 ? r.set_carry_flag : r.clear_carry_flag
|
238
|
+
check & 0x10 == 0x10 ? r.set_half_carry_flag : r.clear_half_carry_flag
|
239
|
+
end
|
240
|
+
end
|
241
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require_relative 'instruction'
|
2
|
+
|
3
|
+
module GBRb::InstructionSet
|
4
|
+
class Ret < Instruction
|
5
|
+
def initialize condition, m=2, t_high=20, t=8
|
6
|
+
@condition = condition
|
7
|
+
@t_high = t_high
|
8
|
+
@t_low = t
|
9
|
+
@m_low = m
|
10
|
+
super m, t, 0
|
11
|
+
end
|
12
|
+
|
13
|
+
def call r, mem
|
14
|
+
condition_met = case @condition
|
15
|
+
when :c
|
16
|
+
r.carry_flag?
|
17
|
+
when :nc
|
18
|
+
not r.carry_flag?
|
19
|
+
when :nz
|
20
|
+
not r.zero_flag?
|
21
|
+
when :z
|
22
|
+
r.zero_flag?
|
23
|
+
when :none
|
24
|
+
true
|
25
|
+
else
|
26
|
+
false
|
27
|
+
end
|
28
|
+
if condition_met
|
29
|
+
@t = @t_high
|
30
|
+
@m = @t_high / 4
|
31
|
+
low = mem.read_byte(r.sp.read)
|
32
|
+
r.sp.store r.sp.read + 1
|
33
|
+
high = mem.read_byte(r.sp.read)
|
34
|
+
r.sp.store r.sp.read + 1
|
35
|
+
|
36
|
+
r.pc.store (high << 8) + low
|
37
|
+
else
|
38
|
+
@t = @t_low
|
39
|
+
@m = @m_low
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,178 @@
|
|
1
|
+
require_relative '../cpu'
|
2
|
+
require_relative 'instruction'
|
3
|
+
|
4
|
+
module GBRb::InstructionSet
|
5
|
+
class Rl < Instruction
|
6
|
+
def initialize target, carry=false, indirect=false, m=1, t=4, zero=true
|
7
|
+
super m, t
|
8
|
+
@target = target.to_sym
|
9
|
+
@carry = carry
|
10
|
+
@indirect = indirect
|
11
|
+
@zero_check = zero
|
12
|
+
end
|
13
|
+
|
14
|
+
def call r, mem
|
15
|
+
if @indirect
|
16
|
+
address = r.public_send(@target).read
|
17
|
+
v = mem.read_byte(address) << 1
|
18
|
+
else
|
19
|
+
v = r.public_send(@target).read << 1
|
20
|
+
end
|
21
|
+
|
22
|
+
carry_in = if @carry
|
23
|
+
v & 0x100 == 0x100 ? 1 : 0
|
24
|
+
else
|
25
|
+
r.carry_flag? ? 1 : 0
|
26
|
+
end
|
27
|
+
|
28
|
+
v += carry_in
|
29
|
+
|
30
|
+
if @indirect
|
31
|
+
mem.write_byte(address, v)
|
32
|
+
else
|
33
|
+
r.public_send(@target).store v
|
34
|
+
end
|
35
|
+
|
36
|
+
r.clear_add_sub_flag
|
37
|
+
r.clear_half_carry_flag
|
38
|
+
if @zero_check
|
39
|
+
v & 0xff == 0 ? r.set_zero_flag : r.clear_zero_flag
|
40
|
+
else
|
41
|
+
r.clear_zero_flag
|
42
|
+
end
|
43
|
+
carry_out = v >> 8
|
44
|
+
carry_out == 1 ? r.set_carry_flag : r.clear_carry_flag
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
class Rr < Instruction
|
49
|
+
def initialize target, carry=false, indirect=false, m=1, t=4, check_for_zero=true
|
50
|
+
super m, t
|
51
|
+
@target = target.to_sym
|
52
|
+
@carry = carry
|
53
|
+
@indirect = indirect
|
54
|
+
@check_for_zero = check_for_zero
|
55
|
+
end
|
56
|
+
|
57
|
+
def call r, mem
|
58
|
+
if @indirect
|
59
|
+
address = r.public_send(@target).read
|
60
|
+
v = mem.read_byte(address)
|
61
|
+
else
|
62
|
+
v = r.public_send(@target).read
|
63
|
+
end
|
64
|
+
|
65
|
+
carry_out = v & 0x01
|
66
|
+
|
67
|
+
carry_in = if @carry
|
68
|
+
carry_out
|
69
|
+
else
|
70
|
+
r.carry_flag? ? 1 : 0
|
71
|
+
end
|
72
|
+
|
73
|
+
v >>= 1
|
74
|
+
|
75
|
+
v += carry_in << 7
|
76
|
+
|
77
|
+
if @indirect
|
78
|
+
original = mem.read_byte address
|
79
|
+
mem.write_byte(address, v)
|
80
|
+
else
|
81
|
+
r.public_send(@target).store v
|
82
|
+
end
|
83
|
+
|
84
|
+
r.clear_add_sub_flag
|
85
|
+
r.clear_half_carry_flag
|
86
|
+
if @check_for_zero
|
87
|
+
v & 0xff == 0 ? r.set_zero_flag : r.clear_zero_flag
|
88
|
+
else
|
89
|
+
r.clear_zero_flag
|
90
|
+
end
|
91
|
+
carry_out == 1 ? r.set_carry_flag : r.clear_carry_flag
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
class Srl < Instruction
|
96
|
+
def initialize target, indirect=false, m=1, t=4
|
97
|
+
super m, t
|
98
|
+
@target = target
|
99
|
+
@indirect = indirect
|
100
|
+
end
|
101
|
+
|
102
|
+
def call r, mem
|
103
|
+
if @indirect
|
104
|
+
v = mem.read_byte r.public_send(@target).read
|
105
|
+
else
|
106
|
+
v = r.public_send(@target).read
|
107
|
+
end
|
108
|
+
|
109
|
+
v & 0b1 == 0 ? r.clear_carry_flag : r.set_carry_flag
|
110
|
+
v >>= 1
|
111
|
+
v == 0 ? r.set_zero_flag : r.clear_zero_flag
|
112
|
+
r.clear_add_sub_flag
|
113
|
+
r.clear_half_carry_flag
|
114
|
+
|
115
|
+
if @indirect
|
116
|
+
mem.write_byte(r.public_send(@target).read, v)
|
117
|
+
else
|
118
|
+
r.public_send(@target).store v
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
class Sla < Instruction
|
124
|
+
def initialize target, indirect=false, m=1, t=4
|
125
|
+
super m, t
|
126
|
+
@target = target
|
127
|
+
@indirect = indirect
|
128
|
+
end
|
129
|
+
|
130
|
+
def call r, mem
|
131
|
+
if @indirect
|
132
|
+
v = mem.read_byte r.public_send(@target).read
|
133
|
+
else
|
134
|
+
v = r.public_send(@target).read
|
135
|
+
end
|
136
|
+
|
137
|
+
v & 0b10000000 == 0b10000000 ? r.set_carry_flag : r.clear_carry_flag
|
138
|
+
v = (v << 1) & 0xff
|
139
|
+
v == 0 ? r.set_zero_flag : r.clear_zero_flag
|
140
|
+
r.clear_add_sub_flag
|
141
|
+
r.clear_half_carry_flag
|
142
|
+
|
143
|
+
if @indirect
|
144
|
+
mem.write_byte(r.public_send(@target).read, v)
|
145
|
+
else
|
146
|
+
r.public_send(@target).store v
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
class Sra < Instruction
|
152
|
+
def initialize target, indirect=false, m=1, t=4
|
153
|
+
super m, t
|
154
|
+
@target = target
|
155
|
+
@indirect = indirect
|
156
|
+
end
|
157
|
+
|
158
|
+
def call r, mem
|
159
|
+
if @indirect
|
160
|
+
v = mem.read_byte r.public_send(@target).read
|
161
|
+
else
|
162
|
+
v = r.public_send(@target).read
|
163
|
+
end
|
164
|
+
|
165
|
+
v & 0b01 == 0b01 ? r.set_carry_flag : r.clear_carry_flag
|
166
|
+
v = ((v >> 1) | (v & 0x80)) & 0xff
|
167
|
+
v == 0 ? r.set_zero_flag : r.clear_zero_flag
|
168
|
+
r.clear_add_sub_flag
|
169
|
+
r.clear_half_carry_flag
|
170
|
+
|
171
|
+
if @indirect
|
172
|
+
mem.write_byte(r.public_send(@target).read, v)
|
173
|
+
else
|
174
|
+
r.public_send(@target).store v
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|