GBRb 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|