GBRb 0.1.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.
@@ -0,0 +1,44 @@
1
+ require_relative '../cpu'
2
+
3
+ module GBRb::CPU
4
+ class Register
5
+ def initialize value=0x00, bits=8
6
+ if bits == 8 or bits == 16
7
+ @bits = bits
8
+ else
9
+ raise ArgumentError
10
+ end
11
+ store value
12
+ end
13
+
14
+ def read
15
+ @value
16
+ end
17
+
18
+ def store value
19
+ @value = value & (mask - 1)
20
+ end
21
+
22
+ def clear
23
+ store 0x00
24
+ end
25
+
26
+ def zero?
27
+ @value.zero?
28
+ end
29
+
30
+ def == other
31
+ other.read == @value and other.bits == bits
32
+ end
33
+
34
+ def mask
35
+ @mask ||= 0x10 ** (@bits/4 )
36
+ end
37
+
38
+ def half_mask
39
+ @half_mask ||= 0x10 ** (@bits/8)
40
+ end
41
+
42
+ attr_reader :bits
43
+ end
44
+ end
@@ -0,0 +1,59 @@
1
+ require_relative '../cpu'
2
+ require_relative 'register'
3
+ require_relative 'flags_register'
4
+ require_relative 'concatenated_register'
5
+
6
+ module GBRb::CPU
7
+ class RegisterEnsemble
8
+ attr_accessor :a, :b, :c, :d, :e, :f, :h, :l, :m, :t, :pc, :sp, :bc, :de, :hl, :af
9
+
10
+ def initialize
11
+ @a = Register.new
12
+ @b = Register.new
13
+ @c = Register.new
14
+ @d = Register.new
15
+ @e = Register.new
16
+ @h = Register.new
17
+ @l = Register.new
18
+
19
+ @f = FlagsRegister.new
20
+
21
+ @pc = Register.new(0x0000, 16)
22
+ @sp = Register.new(0x0000, 16)
23
+
24
+ @m = Register.new
25
+ @t = Register.new
26
+
27
+ @bc = ConcatenatedRegister.new @b, @c
28
+ @de = ConcatenatedRegister.new @d, @e
29
+ @hl = ConcatenatedRegister.new @h, @l
30
+ @af = ConcatenatedRegister.new @a, @f
31
+ end
32
+
33
+ def each &block
34
+ [@pc, @sp, @a, @b, @c, @d, @e, @h, @l, @f].each &block
35
+ end
36
+
37
+ def == other
38
+ register_list.inject(true){|result, el| result && public_send(el) == other.public_send(el)}
39
+ end
40
+
41
+ def method_missing m, *a, &b
42
+ case m
43
+ when /\Aset_.*_flag\z/
44
+ f.public_send m
45
+ when /\Aclear_.*_flag\z/
46
+ f.public_send m
47
+ when /\A.*_flag\?\z/
48
+ f.public_send m
49
+ else
50
+ super m, a, b
51
+ end
52
+ end
53
+
54
+ private
55
+ def register_list
56
+ instance_variables.map {|iv| iv.to_s.chars.drop(1).join.to_sym}
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,584 @@
1
+ require_relative '../cpu'
2
+ require_relative '../mmu'
3
+ require_relative 'register_ensemble'
4
+ require_relative 'instruction'
5
+
6
+ module GBRb
7
+ module CPU
8
+ class Z80
9
+ attr_reader :registers
10
+ alias_method :r, :registers
11
+
12
+ attr_reader :mmu
13
+
14
+ def initialize mmu=MMU.new
15
+ @mmu = mmu
16
+ reset
17
+ end
18
+
19
+ def reset
20
+ @registers = RegisterEnsemble.new
21
+ @mmu.reset
22
+ clock
23
+ @registers.sp.store 0xfffe
24
+ @registers.pc.store 0x0000
25
+ @last_m = 0
26
+ @last_t = 0
27
+ end
28
+
29
+ def instructions
30
+ return @instructions if @instructions
31
+
32
+ i = Array.new 256, :not_implemented
33
+ i[0x00] = Instruction.new
34
+ i[0x01] = Ld.new(:bc, nil, 3, 12, false, false, 2)
35
+ i[0x02] = Ld.new(:bc, :a, 1, 8, true, false)
36
+ i[0x03] = Inc.new(:bc, 1, 8, false)
37
+ i[0x04] = Inc.new(:b)
38
+ i[0x05] = Dec.new(:b)
39
+ i[0x06] = Ld.new(:b, nil, 2, 8, false, false, 1)
40
+ i[0x07] = Rl.new :a, true, false, 1, 4
41
+ i[0x08] = Ld.new(nil, :sp, 3, 20, :immediate, false, 2)
42
+ i[0x09] = AddHl.new(:bc)
43
+ i[0x0a] = Ld.new(:a, :bc, 1, 8, false, true)
44
+ i[0x0b] = Dec.new(:bc, 1, 8, false)
45
+ i[0x0c] = Inc.new(:c)
46
+ i[0x0d] = Dec.new(:c)
47
+ i[0x0e] = Ld.new(:c, nil, 2, 8, false, false, 1)
48
+ i[0x0f] = Rr.new :a, true, false, 1, 4
49
+
50
+ i[0x10] = Stop.new
51
+ i[0x11] = Ld.new(:de, nil, 3, 12, false, false, 2)
52
+ i[0x12] = Ld.new(:de, :a, 1, 8, true, false)
53
+ i[0x13] = Inc.new(:de, 1, 8, false)
54
+ i[0x14] = Inc.new(:d)
55
+ i[0x15] = Dec.new(:d)
56
+ i[0x16] = Ld.new(:d, nil, 2, 8, false, false, 1)
57
+ i[0x17] = Rl.new :a, false, false, 1, 4
58
+ i[0x18] = Jump.new :none
59
+ i[0x19] = AddHl.new(:de)
60
+ i[0x1a] = Ld.new(:a, :de, 1, 8, false, true)
61
+ i[0x1b] = Dec.new(:de, 1, 8, false)
62
+ i[0x1c] = Inc.new(:e)
63
+ i[0x1d] = Dec.new(:e)
64
+ i[0x1e] = Ld.new(:e, nil, 2, 8, false, false, 1)
65
+ i[0x1f] = Rr.new :a, true, false, 1, 4
66
+
67
+ i[0x20] = Jump.new(:nz)
68
+ i[0x21] = Ld.new(:hl, nil, 3, 12, false, false, 2)
69
+ i[0x22] = Ld.new(:hl, :a, 1, 8, :increment, false)
70
+ i[0x23] = Inc.new(:hl, 1, 8, false)
71
+ i[0x24] = Inc.new(:h)
72
+ i[0x25] = Dec.new(:h)
73
+ i[0x26] = Ld.new(:h, nil, 2, 8, false, false, 1)
74
+ i[0x28] = Jump.new :z
75
+ i[0x29] = AddHl.new(:hl)
76
+ i[0x2a] = Ld.new(:a, :hl, 1, 8, false, :increment)
77
+ i[0x2b] = Dec.new(:hl, 1, 8, false)
78
+ i[0x2c] = Inc.new(:l)
79
+ i[0x2d] = Dec.new(:l)
80
+ i[0x2e] = Ld.new(:l, nil, 2, 8, false, false, 1)
81
+ i[0x2f] = Cpl.new(1, 4)
82
+
83
+ i[0x30] = Jump.new :nc
84
+ i[0x31] = Ld.new(:sp, nil, 3, 12, false, false, 2)
85
+ i[0x32] = Ld.new(:hl, :a, 1, 8, :decrement, false)
86
+ i[0x33] = Inc.new(:sp, 1, 8, false)
87
+ i[0x34] = Inc.new(:hl, 1, 12, true, true)
88
+ i[0x35] = Dec.new(:hl, 1, 12, true, true)
89
+ i[0x36] = Ld.new(:hl, nil, 2, 12, true, false, 1)
90
+ i[0x37] = Scf.new
91
+ i[0x38] = Jump.new :c
92
+ i[0x39] = AddHl.new(:sp)
93
+ i[0x3a] = Ld.new(:a, :hl, 1, 8, false, :decrement)
94
+ i[0x3b] = Dec.new(:sp, 1, 8, false)
95
+ i[0x3c] = Inc.new(:a)
96
+ i[0x3d] = Dec.new(:a)
97
+ i[0x3e] = Ld.new(:a, nil, 2, 8, false, false, 1)
98
+ i[0x3f] = Ccf.new
99
+
100
+ i[0x40] = Ld.new(:b, :b)
101
+ i[0x41] = Ld.new(:b, :c)
102
+ i[0x42] = Ld.new(:b, :d)
103
+ i[0x43] = Ld.new(:b, :e)
104
+ i[0x44] = Ld.new(:b, :h)
105
+ i[0x45] = Ld.new(:b, :l)
106
+ i[0x46] = Ld.new(:b, :hl, 1, 8, false, true)
107
+ i[0x47] = Ld.new(:b, :a)
108
+ i[0x48] = Ld.new(:c, :b)
109
+ i[0x49] = Ld.new(:c, :c)
110
+ i[0x4a] = Ld.new(:c, :d)
111
+ i[0x4b] = Ld.new(:c, :e)
112
+ i[0x4c] = Ld.new(:c, :h)
113
+ i[0x4d] = Ld.new(:c, :l)
114
+ i[0x4e] = Ld.new(:c, :hl, 1, 8, false, true)
115
+ i[0x4f] = Ld.new(:c, :a)
116
+
117
+ i[0x50] = Ld.new(:d, :b)
118
+ i[0x51] = Ld.new(:d, :c)
119
+ i[0x52] = Ld.new(:d, :d)
120
+ i[0x53] = Ld.new(:d, :e)
121
+ i[0x54] = Ld.new(:d, :h)
122
+ i[0x55] = Ld.new(:d, :l)
123
+ i[0x56] = Ld.new(:d, :hl, 1, 8, false, true)
124
+ i[0x57] = Ld.new(:d, :a)
125
+ i[0x58] = Ld.new(:e, :b)
126
+ i[0x59] = Ld.new(:e, :c)
127
+ i[0x5a] = Ld.new(:e, :d)
128
+ i[0x5b] = Ld.new(:e, :e)
129
+ i[0x5c] = Ld.new(:e, :h)
130
+ i[0x5d] = Ld.new(:e, :l)
131
+ i[0x5e] = Ld.new(:e, :hl, 1, 8, false, true)
132
+ i[0x5f] = Ld.new(:e, :a)
133
+
134
+ i[0x60] = Ld.new(:h, :b)
135
+ i[0x61] = Ld.new(:h, :c)
136
+ i[0x62] = Ld.new(:h, :d)
137
+ i[0x63] = Ld.new(:h, :e)
138
+ i[0x64] = Ld.new(:h, :h)
139
+ i[0x65] = Ld.new(:h, :l)
140
+ i[0x66] = Ld.new(:h, :hl, 1, 8, false, true)
141
+ i[0x67] = Ld.new(:h, :a)
142
+ i[0x68] = Ld.new(:l, :b)
143
+ i[0x69] = Ld.new(:l, :c)
144
+ i[0x6a] = Ld.new(:l, :d)
145
+ i[0x6b] = Ld.new(:l, :e)
146
+ i[0x6c] = Ld.new(:l, :h)
147
+ i[0x6d] = Ld.new(:l, :l)
148
+ i[0x6e] = Ld.new(:l, :hl, 1, 8, false, true)
149
+ i[0x6f] = Ld.new(:l, :a)
150
+
151
+ i[0x70] = Ld.new(:hl, :b, 1, 8, true)
152
+ i[0x71] = Ld.new(:hl, :c, 1, 8, true)
153
+ i[0x72] = Ld.new(:hl, :d, 1, 8, true)
154
+ i[0x73] = Ld.new(:hl, :e, 1, 8, true)
155
+ i[0x74] = Ld.new(:hl, :h, 1, 8, true)
156
+ i[0x75] = Ld.new(:hl, :l, 1, 8, true)
157
+ i[0x77] = Ld.new(:hl, :a, 1, 8, true)
158
+ i[0x78] = Ld.new(:a, :b)
159
+ i[0x79] = Ld.new(:a, :c)
160
+ i[0x7a] = Ld.new(:a, :d)
161
+ i[0x7b] = Ld.new(:a, :e)
162
+ i[0x7c] = Ld.new(:a, :h)
163
+ i[0x7d] = Ld.new(:a, :l)
164
+ i[0x7e] = Ld.new(:a, :hl, 1, 8, false, true)
165
+ i[0x7f] = Ld.new(:a, :a)
166
+
167
+ i[0x80] = Add.new(:b)
168
+ i[0x81] = Add.new(:c)
169
+ i[0x82] = Add.new(:d)
170
+ i[0x83] = Add.new(:e)
171
+ i[0x84] = Add.new(:h)
172
+ i[0x85] = Add.new(:l)
173
+ i[0x86] = Add.new(:hl, 1, 8, true)
174
+ i[0x87] = Add.new(:a)
175
+ i[0x88] = Adc.new(:b)
176
+ i[0x89] = Adc.new(:c)
177
+ i[0x8a] = Adc.new(:d)
178
+ i[0x8b] = Adc.new(:e)
179
+ i[0x8c] = Adc.new(:h)
180
+ i[0x8d] = Adc.new(:l)
181
+ i[0x8e] = Adc.new(:hl, 1, 8, true)
182
+ i[0x8f] = Adc.new(:a)
183
+
184
+ i[0x90] = Sub.new(:b)
185
+ i[0x91] = Sub.new(:c)
186
+ i[0x92] = Sub.new(:d)
187
+ i[0x93] = Sub.new(:e)
188
+ i[0x94] = Sub.new(:h)
189
+ i[0x95] = Sub.new(:l)
190
+ i[0x96] = Sub.new(:hl, 1, 8, true)
191
+ i[0x97] = Sub.new(:a)
192
+ i[0x98] = Sbc.new(:b)
193
+ i[0x99] = Sbc.new(:c)
194
+ i[0x9a] = Sbc.new(:d)
195
+ i[0x9b] = Sbc.new(:e)
196
+ i[0x9c] = Sbc.new(:h)
197
+ i[0x9d] = Sbc.new(:l)
198
+ i[0x9e] = Sbc.new(:hl, 1, 8, true)
199
+ i[0x9f] = Sbc.new(:a)
200
+
201
+ i[0xa0] = And.new(:b)
202
+ i[0xa1] = And.new(:c)
203
+ i[0xa2] = And.new(:d)
204
+ i[0xa3] = And.new(:e)
205
+ i[0xa4] = And.new(:h)
206
+ i[0xa5] = And.new(:l)
207
+ i[0xa6] = And.new(:hl, 1, 8, true)
208
+ i[0xa7] = And.new(:a)
209
+ i[0xa8] = Xor.new(:b)
210
+ i[0xa9] = Xor.new(:c)
211
+ i[0xaa] = Xor.new(:d)
212
+ i[0xab] = Xor.new(:e)
213
+ i[0xac] = Xor.new(:h)
214
+ i[0xad] = Xor.new(:l)
215
+ i[0xae] = Xor.new(:hl, 1, 8, true)
216
+ i[0xaf] = Xor.new(:a)
217
+
218
+ i[0xb0] = Or.new(:b)
219
+ i[0xb1] = Or.new(:c)
220
+ i[0xb2] = Or.new(:d)
221
+ i[0xb3] = Or.new(:e)
222
+ i[0xb4] = Or.new(:h)
223
+ i[0xb5] = Or.new(:l)
224
+ i[0xb6] = Or.new(:hl, 1, 8, true)
225
+ i[0xb7] = Or.new(:a)
226
+ i[0xb8] = Cp.new(:b)
227
+ i[0xb9] = Cp.new(:c)
228
+ i[0xba] = Cp.new(:d)
229
+ i[0xbb] = Cp.new(:e)
230
+ i[0xbc] = Cp.new(:h)
231
+ i[0xbd] = Cp.new(:l)
232
+ i[0xbe] = Cp.new(:hl, 1, 8, true)
233
+ i[0xbf] = Cp.new(:a)
234
+
235
+ i[0xc0] = Ret.new(1, 8, 20, :NZ)
236
+ i[0xc1] = Pop.new(:bc)
237
+ i[0xc2] = Jump.new(:nz, 3, 16, 12, 2)
238
+ i[0xc5] = Push.new(:bc)
239
+ i[0xc6] = Add.new :a, 2, 8, false, 1
240
+ i[0xc7] = Rst.new(0x00)
241
+ i[0xc9] = Ret.new
242
+ i[0xcb] = Instruction.new
243
+ i[0xcc] = Call.new(3, 24, 2, :Z)
244
+ i[0xcd] = Call.new
245
+ i[0xce] = Adc.new(:a, 2, 8, false, 1)
246
+ i[0xcf] = Rst.new(0x08)
247
+
248
+ i[0xd1] = Pop.new(:de)
249
+ i[0xd5] = Push.new(:de)
250
+ i[0xd7] = Rst.new(0x10)
251
+ i[0xd9] = Ret.new
252
+ i[0xdd] = Instruction.new 0, 0
253
+ i[0xde] = Sbc.new(:a, 2, 8, false, 1)
254
+ i[0xdf] = Rst.new(0x18)
255
+
256
+ i[0xe0] = Ldh.new(nil, :a, 2, 12, true, false, 1, 0xff00)
257
+ i[0xe1] = Pop.new(:hl)
258
+ i[0xe2] = Ld.new(:c, :a, 2, 8, true, false, 0, 0xff00)
259
+ i[0xe5] = Push.new(:hl)
260
+ i[0xe6] = And.new(nil, 2, 8, false, 1)
261
+ i[0xe7] = Rst.new(0x20)
262
+ i[0xea] = Ld.new(nil, :a, 3, 16, :immediate, false, 2)
263
+ i[0xee] = Xor.new(:a, 2, 8, false, 1)
264
+ i[0xef] = Rst.new(0x28)
265
+
266
+ i[0xf0] = Ldh.new(:a, nil, 2, 12, false, true, 1, 0xff00)
267
+ i[0xf1] = Pop.new(:af)
268
+ i[0xf2] = Ld.new(:a, :c, 2, 8, false, true, 0, 0xff00)
269
+ i[0xf3] = DisableInterrupts.new
270
+ i[0xf5] = Push.new(:af)
271
+ i[0xf7] = Rst.new(0x30)
272
+ i[0xf8] = Ldhlsp.new
273
+ i[0xf9] = Ld.new(:sp, :hl, 1, 8)
274
+ i[0xfa] = Ld.new(:a, nil, 3, 16, false, true, 2)
275
+ i[0xfb] = EnableInterrupts.new
276
+ i[0xfe] = Cp.new nil, 2, 8, false, 1
277
+ i[0xff] = Rst.new(0x38)
278
+
279
+ @instructions = i
280
+ end
281
+
282
+ def cb_instructions
283
+ return @cb_instructions if @cb_instructions
284
+
285
+ i = Array.new 256, :not_implemented
286
+
287
+ i[0x00] = Rl.new :b, true
288
+ i[0x01] = Rl.new :c, true
289
+ i[0x02] = Rl.new :d, true
290
+ i[0x03] = Rl.new :e, true
291
+ i[0x04] = Rl.new :h, true
292
+ i[0x05] = Rl.new :l, true
293
+ i[0x06] = Rl.new :hl, true, true
294
+ i[0x07] = Rl.new :a, true
295
+ i[0x08] = Rr.new :b, true
296
+ i[0x09] = Rr.new :c, true
297
+ i[0x0a] = Rr.new :d, true
298
+ i[0x0b] = Rr.new :e, true
299
+ i[0x0c] = Rr.new :h, true
300
+ i[0x0d] = Rr.new :l, true
301
+ i[0x0e] = Rr.new :hl, true, true
302
+ i[0x0f] = Rr.new :a, true
303
+
304
+ i[0x10] = Rl.new :b
305
+ i[0x11] = Rl.new :c
306
+ i[0x12] = Rl.new :d
307
+ i[0x13] = Rl.new :e
308
+ i[0x14] = Rl.new :h
309
+ i[0x15] = Rl.new :l
310
+ i[0x16] = Rl.new :hl, false, true
311
+ i[0x17] = Rl.new :a
312
+ i[0x18] = Rr.new :b
313
+ i[0x19] = Rr.new :c
314
+ i[0x1a] = Rr.new :d
315
+ i[0x1b] = Rr.new :e
316
+ i[0x1c] = Rr.new :h
317
+ i[0x1d] = Rr.new :l
318
+ i[0x1e] = Rr.new :hl, false, true
319
+ i[0x1f] = Rr.new :a
320
+
321
+ i[0x30] = Swap.new :b
322
+ i[0x31] = Swap.new :c
323
+ i[0x32] = Swap.new :d
324
+ i[0x33] = Swap.new :e
325
+ i[0x34] = Swap.new :h
326
+ i[0x35] = Swap.new :l
327
+ i[0x36] = Swap.new :hl, 2, 16, true
328
+ i[0x37] = Swap.new :a
329
+
330
+ i[0x40] = Bit.new 0, :b
331
+ i[0x41] = Bit.new 0, :c
332
+ i[0x42] = Bit.new 0, :d
333
+ i[0x43] = Bit.new 0, :e
334
+ i[0x44] = Bit.new 0, :h
335
+ i[0x45] = Bit.new 0, :l
336
+ i[0x46] = Bit.new 0, :hl, true
337
+ i[0x47] = Bit.new 0, :a
338
+ i[0x48] = Bit.new 1, :b
339
+ i[0x49] = Bit.new 1, :c
340
+ i[0x4a] = Bit.new 1, :d
341
+ i[0x4b] = Bit.new 1, :e
342
+ i[0x4c] = Bit.new 1, :h
343
+ i[0x4d] = Bit.new 1, :l
344
+ i[0x4e] = Bit.new 1, :hl, true
345
+ i[0x4f] = Bit.new 1, :a
346
+
347
+ i[0x50] = Bit.new 2, :b
348
+ i[0x51] = Bit.new 2, :c
349
+ i[0x52] = Bit.new 2, :d
350
+ i[0x53] = Bit.new 2, :e
351
+ i[0x54] = Bit.new 2, :h
352
+ i[0x55] = Bit.new 2, :l
353
+ i[0x56] = Bit.new 2, :hl, true
354
+ i[0x57] = Bit.new 2, :a
355
+ i[0x58] = Bit.new 3, :b
356
+ i[0x59] = Bit.new 3, :c
357
+ i[0x5a] = Bit.new 3, :d
358
+ i[0x5b] = Bit.new 3, :e
359
+ i[0x5c] = Bit.new 3, :h
360
+ i[0x5d] = Bit.new 3, :l
361
+ i[0x5e] = Bit.new 3, :hl, true
362
+ i[0x5f] = Bit.new 3, :a
363
+
364
+ i[0x60] = Bit.new 4, :b
365
+ i[0x61] = Bit.new 4, :c
366
+ i[0x62] = Bit.new 4, :d
367
+ i[0x63] = Bit.new 4, :e
368
+ i[0x64] = Bit.new 4, :h
369
+ i[0x65] = Bit.new 4, :l
370
+ i[0x66] = Bit.new 4, :hl, true
371
+ i[0x67] = Bit.new 4, :a
372
+ i[0x68] = Bit.new 5, :b
373
+ i[0x69] = Bit.new 5, :c
374
+ i[0x6a] = Bit.new 5, :d
375
+ i[0x6b] = Bit.new 5, :e
376
+ i[0x6c] = Bit.new 5, :h
377
+ i[0x6d] = Bit.new 5, :l
378
+ i[0x6e] = Bit.new 5, :hl, true
379
+ i[0x6f] = Bit.new 5, :a
380
+
381
+ i[0x70] = Bit.new 6, :b
382
+ i[0x71] = Bit.new 6, :c
383
+ i[0x72] = Bit.new 6, :d
384
+ i[0x73] = Bit.new 6, :e
385
+ i[0x74] = Bit.new 6, :h
386
+ i[0x75] = Bit.new 6, :l
387
+ i[0x76] = Bit.new 6, :hl, true
388
+ i[0x77] = Bit.new 6, :a
389
+ i[0x78] = Bit.new 7, :b
390
+ i[0x79] = Bit.new 7, :c
391
+ i[0x7a] = Bit.new 7, :d
392
+ i[0x7b] = Bit.new 7, :e
393
+ i[0x7c] = Bit.new 7, :h
394
+ i[0x7d] = Bit.new 7, :l
395
+ i[0x7e] = Bit.new 7, :hl, true
396
+ i[0x7f] = Bit.new 7, :a
397
+
398
+ i[0x80] = Res.new 0, :b
399
+ i[0x81] = Res.new 0, :c
400
+ i[0x82] = Res.new 0, :d
401
+ i[0x83] = Res.new 0, :e
402
+ i[0x84] = Res.new 0, :h
403
+ i[0x85] = Res.new 0, :l
404
+ i[0x86] = Res.new 0, :hl, true
405
+ i[0x87] = Res.new 0, :a
406
+ i[0x88] = Res.new 1, :b
407
+ i[0x89] = Res.new 1, :c
408
+ i[0x8a] = Res.new 1, :d
409
+ i[0x8b] = Res.new 1, :e
410
+ i[0x8c] = Res.new 1, :h
411
+ i[0x8d] = Res.new 1, :l
412
+ i[0x8e] = Res.new 1, :hl, true
413
+ i[0x8f] = Res.new 1, :a
414
+
415
+ i[0x90] = Res.new 2, :b
416
+ i[0x91] = Res.new 2, :c
417
+ i[0x92] = Res.new 2, :d
418
+ i[0x93] = Res.new 2, :e
419
+ i[0x94] = Res.new 2, :h
420
+ i[0x95] = Res.new 2, :l
421
+ i[0x96] = Res.new 2, :hl, true
422
+ i[0x97] = Res.new 2, :a
423
+ i[0x98] = Res.new 3, :b
424
+ i[0x99] = Res.new 3, :c
425
+ i[0x9a] = Res.new 3, :d
426
+ i[0x9b] = Res.new 3, :e
427
+ i[0x9c] = Res.new 3, :h
428
+ i[0x9d] = Res.new 3, :l
429
+ i[0x9e] = Res.new 3, :hl, true
430
+ i[0x9f] = Res.new 3, :a
431
+
432
+ i[0xa0] = Res.new 4, :b
433
+ i[0xa1] = Res.new 4, :c
434
+ i[0xa2] = Res.new 4, :d
435
+ i[0xa3] = Res.new 4, :e
436
+ i[0xa4] = Res.new 4, :h
437
+ i[0xa5] = Res.new 4, :l
438
+ i[0xa6] = Res.new 4, :hl, true
439
+ i[0xa7] = Res.new 4, :a
440
+ i[0xa8] = Res.new 5, :b
441
+ i[0xa9] = Res.new 5, :c
442
+ i[0xaa] = Res.new 5, :d
443
+ i[0xab] = Res.new 5, :e
444
+ i[0xac] = Res.new 5, :h
445
+ i[0xad] = Res.new 5, :l
446
+ i[0xae] = Res.new 5, :hl, true
447
+ i[0xaf] = Res.new 5, :a
448
+
449
+ i[0xb0] = Res.new 6, :b
450
+ i[0xb1] = Res.new 6, :c
451
+ i[0xb2] = Res.new 6, :d
452
+ i[0xb3] = Res.new 6, :e
453
+ i[0xb4] = Res.new 6, :h
454
+ i[0xb5] = Res.new 6, :l
455
+ i[0xb6] = Res.new 6, :hl, true
456
+ i[0xb7] = Res.new 6, :a
457
+ i[0xb8] = Res.new 7, :b
458
+ i[0xb9] = Res.new 7, :c
459
+ i[0xba] = Res.new 7, :d
460
+ i[0xbb] = Res.new 7, :e
461
+ i[0xbc] = Res.new 7, :h
462
+ i[0xbd] = Res.new 7, :l
463
+ i[0xbe] = Res.new 7, :hl, true
464
+ i[0xbf] = Res.new 7, :a
465
+
466
+ i[0xc0] = Set.new 0, :b
467
+ i[0xc1] = Set.new 0, :c
468
+ i[0xc2] = Set.new 0, :d
469
+ i[0xc3] = Set.new 0, :e
470
+ i[0xc4] = Set.new 0, :h
471
+ i[0xc5] = Set.new 0, :l
472
+ i[0xc6] = Set.new 0, :hl, true
473
+ i[0xc7] = Set.new 0, :a
474
+ i[0xc8] = Set.new 1, :b
475
+ i[0xc9] = Set.new 1, :c
476
+ i[0xca] = Set.new 1, :d
477
+ i[0xcb] = Set.new 1, :e
478
+ i[0xcc] = Set.new 1, :h
479
+ i[0xcd] = Set.new 1, :l
480
+ i[0xce] = Set.new 1, :hl, true
481
+ i[0xcf] = Set.new 1, :a
482
+
483
+ i[0xd0] = Set.new 2, :b
484
+ i[0xd1] = Set.new 2, :c
485
+ i[0xd2] = Set.new 2, :d
486
+ i[0xd3] = Set.new 2, :e
487
+ i[0xd4] = Set.new 2, :h
488
+ i[0xd5] = Set.new 2, :l
489
+ i[0xd6] = Set.new 2, :hl, true
490
+ i[0xd7] = Set.new 2, :a
491
+ i[0xd8] = Set.new 3, :b
492
+ i[0xd9] = Set.new 3, :c
493
+ i[0xda] = Set.new 3, :d
494
+ i[0xdb] = Set.new 3, :e
495
+ i[0xdc] = Set.new 3, :h
496
+ i[0xdd] = Set.new 3, :l
497
+ i[0xde] = Set.new 3, :hl, true
498
+ i[0xdf] = Set.new 3, :a
499
+
500
+ i[0xe0] = Set.new 4, :b
501
+ i[0xe1] = Set.new 4, :c
502
+ i[0xe2] = Set.new 4, :d
503
+ i[0xe3] = Set.new 4, :e
504
+ i[0xe4] = Set.new 4, :h
505
+ i[0xe5] = Set.new 4, :l
506
+ i[0xe6] = Set.new 4, :hl, true
507
+ i[0xe7] = Set.new 4, :a
508
+ i[0xe8] = Set.new 5, :b
509
+ i[0xe9] = Set.new 5, :c
510
+ i[0xea] = Set.new 5, :d
511
+ i[0xeb] = Set.new 5, :e
512
+ i[0xec] = Set.new 5, :h
513
+ i[0xed] = Set.new 5, :l
514
+ i[0xee] = Set.new 5, :hl, true
515
+ i[0xef] = Set.new 5, :a
516
+
517
+ i[0xf0] = Set.new 6, :b
518
+ i[0xf1] = Set.new 6, :c
519
+ i[0xf2] = Set.new 6, :d
520
+ i[0xf3] = Set.new 6, :e
521
+ i[0xf4] = Set.new 6, :h
522
+ i[0xf5] = Set.new 6, :l
523
+ i[0xf6] = Set.new 6, :hl, true
524
+ i[0xf7] = Set.new 6, :a
525
+ i[0xf8] = Set.new 7, :b
526
+ i[0xf9] = Set.new 7, :c
527
+ i[0xfa] = Set.new 7, :d
528
+ i[0xfb] = Set.new 7, :e
529
+ i[0xfc] = Set.new 7, :h
530
+ i[0xfd] = Set.new 7, :l
531
+ i[0xfe] = Set.new 7, :hl, true
532
+ i[0xff] = Set.new 7, :a
533
+
534
+ @cb_instructions = i
535
+ end
536
+
537
+ def clock
538
+ @clock ||= { m: 0, t: 0 }
539
+ end
540
+
541
+ def step
542
+ dispatch decode fetch
543
+ end
544
+
545
+ def fetch
546
+ opcode = mmu.read_byte(r.pc.read)
547
+ r.pc.store r.pc.read + 1
548
+ opcode
549
+ end
550
+
551
+ def decode opcode
552
+ if @cb_prefix
553
+ @cb_prefix = false
554
+ cb_instructions[opcode.to_i]
555
+ else
556
+ @cb_prefix = true if opcode == 0xcb
557
+ instructions[opcode.to_i]
558
+ end
559
+ end
560
+
561
+ def dispatch instruction
562
+ raise GBRb::CPU::InstructionNotImplemented if instruction == :not_implemented
563
+
564
+ if instruction.immediate_count > 0
565
+ immediates = []
566
+ instruction.immediate_count.times { immediates << fetch }
567
+ if immediates.length == 1
568
+ immediates = immediates.first
569
+ else
570
+ immediates = (immediates.last << 8) + immediates.first
571
+ end
572
+ instruction.call @registers, @mmu, immediates
573
+ else
574
+ instruction.call @registers, @mmu
575
+ end
576
+
577
+ @clock[:m] += instruction.m
578
+ @clock[:t] += instruction.t
579
+ @last_m = instruction.m
580
+ @last_t = instruction.t
581
+ end
582
+ end
583
+ end
584
+ end