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
|