rubyboy 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.
data/lib/rubyboy/cpu.rb CHANGED
@@ -1,181 +1,1534 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'json'
4
+ require_relative 'register'
5
+
3
6
  module Rubyboy
4
7
  class Cpu
5
- attr_accessor :a, :b, :c, :d, :e, :h, :l, :f, :pc, :sp, :ime, :bus
6
-
7
8
  def initialize(bus)
8
- @a = 0x01
9
- @b = 0x00
10
- @c = 0x13
11
- @d = 0x00
12
- @e = 0xd8
13
- @h = 0x01
14
- @l = 0x4d
15
- @f = 0xb0
9
+ @a = Register.new(name: 'a', value: 0x01)
10
+ @b = Register.new(name: 'b', value: 0x00)
11
+ @c = Register.new(name: 'c', value: 0x13)
12
+ @d = Register.new(name: 'd', value: 0x00)
13
+ @e = Register.new(name: 'e', value: 0xd8)
14
+ @h = Register.new(name: 'h', value: 0x01)
15
+ @l = Register.new(name: 'l', value: 0x4d)
16
+ @f = Register.new(name: 'f', value: 0xb0)
17
+
16
18
  @pc = 0x0100
17
19
  @sp = 0xfffe
18
20
  @ime = false
21
+ @ime_delay = false
19
22
  @bus = bus
23
+ @opcodes = File.open('lib/opcodes.json', 'r') { |file| JSON.parse(file.read) }
24
+ @halted = false
25
+
26
+ @cnt = 0
20
27
  end
21
28
 
22
- def get_bc
23
- (@b << 8) + @c
29
+ def af
30
+ (@a.value << 8) + @f.value
24
31
  end
25
32
 
26
- def set_bc(value)
27
- @b = value >> 8
28
- @c = value & 0xff
33
+ def af=(value)
34
+ value &= 0xffff
35
+ @a.value = value >> 8
36
+ @f.value = value & 0xf0
29
37
  end
30
38
 
31
- def get_de
32
- (@d << 8) + @e
39
+ def bc
40
+ (@b.value << 8) + @c.value
33
41
  end
34
42
 
35
- def set_de(value)
36
- @d = value >> 8
37
- @e = value & 0xff
43
+ def bc=(value)
44
+ value &= 0xffff
45
+ @b.value = value >> 8
46
+ @c.value = value & 0xff
38
47
  end
39
48
 
40
- def get_hl
41
- (@h << 8) + @l
49
+ def de
50
+ (@d.value << 8) + @e.value
42
51
  end
43
52
 
44
- def set_hl(value)
45
- @h = value >> 8
46
- @l = value & 0xff
53
+ def de=(value)
54
+ value &= 0xffff
55
+ @d.value = value >> 8
56
+ @e.value = value & 0xff
57
+ end
58
+
59
+ def hl
60
+ (@h.value << 8) + @l.value
61
+ end
62
+
63
+ def hl=(value)
64
+ value &= 0xffff
65
+ @h.value = value >> 8
66
+ @l.value = value & 0xff
47
67
  end
48
68
 
49
69
  def exec
50
- opcode = @bus.read_byte(@pc)
51
- increment_pc
52
- # TODO: Set valid clock
53
- clock = 4
70
+ opcode = read_byte(@pc)
71
+ # print_log(opcode)
72
+
73
+ in_interrupt = false
74
+
75
+ if @ime && @bus.interrupt.interrupts.positive?
76
+ in_interrupt = true
77
+ else
78
+ increment_pc
79
+ end
80
+
81
+ if in_interrupt
82
+ pcs = [0x0040, 0x0048, 0x0050, 0x0058, 0x0060]
83
+ 5.times do |i|
84
+ next if @bus.interrupt.interrupts[i].zero?
85
+
86
+ @bus.interrupt.if &= (~(1 << i)) & 0xff
87
+ @ime = false
88
+ @bus.write_word(@sp - 2, @pc)
89
+ @sp -= 2
90
+ @pc = pcs[i]
91
+ opcode = read_byte(@pc)
92
+ break
93
+ end
94
+ end
95
+
96
+ if @ime_delay
97
+ @ime_delay = false
98
+ @ime = true
99
+ end
100
+
101
+ cbprefixed = false
102
+ branched = false
54
103
 
55
104
  case opcode
56
105
  when 0x00 # NOP
57
106
  when 0x01 # LD BC, nn
58
- @c = @bus.read_byte(@pc)
59
- increment_pc
60
- @b = @bus.read_byte(@pc)
61
- increment_pc
107
+ self.bc = read_word_and_advance_pc
108
+ when 0x02 # LD (BC), A
109
+ write_byte(bc, @a.value)
110
+ when 0x03 # INC BC
111
+ self.bc = bc + 1
112
+ when 0x04 # INC B
113
+ @b.increment
114
+ update_flags(
115
+ z: @b.value.zero?,
116
+ n: false,
117
+ h: (@b.value & 0x0f).zero?
118
+ )
119
+ when 0x05 # DEC B
120
+ @b.decrement
121
+ update_flags(
122
+ z: @b.value.zero?,
123
+ n: true,
124
+ h: (@b.value & 0x0f) == 0x0f
125
+ )
126
+ when 0x06 # LD B, d8
127
+ @b.value = read_byte_and_advance_pc
128
+ when 0x07 # RLCA
129
+ @a.value = (@a.value << 1) | (@a.value >> 7)
130
+ update_flags(
131
+ z: false,
132
+ n: false,
133
+ h: false,
134
+ c: @a.value[0] == 1
135
+ )
136
+ when 0x08 # LD (nn), SP
137
+ word = read_word_and_advance_pc
138
+ write_word(word, @sp)
139
+ when 0x09 # ADD HL, BC
140
+ hflag = (hl & 0x0fff) + (bc & 0x0fff) > 0x0fff
141
+ cflag = hl + bc > 0xffff
142
+ self.hl = hl + bc
143
+ update_flags(
144
+ n: false,
145
+ h: hflag,
146
+ c: cflag
147
+ )
148
+ when 0x0a # LD A, (BC)
149
+ @a.value = read_byte(bc)
62
150
  when 0x0b # DEC BC
63
- set_bc(get_bc - 1)
151
+ self.bc = bc - 1
152
+ when 0x0c # INC C
153
+ @c.increment
154
+ update_flags(
155
+ z: @c.value.zero?,
156
+ n: false,
157
+ h: (@c.value & 0x0f).zero?
158
+ )
159
+ when 0x0d # DEC C
160
+ @c.decrement
161
+ update_flags(
162
+ z: @c.value.zero?,
163
+ n: true,
164
+ h: (@c.value & 0x0f) == 0x0f
165
+ )
166
+ when 0x0e # LD C, d8
167
+ @c.value = read_byte_and_advance_pc
168
+ when 0x0f # RRCA
169
+ @a.value = (@a.value >> 1) | (@a.value << 7)
170
+ update_flags(
171
+ z: false,
172
+ n: false,
173
+ h: false,
174
+ c: @a.value[7] == 1
175
+ )
176
+ when 0x10 # STOP
64
177
  when 0x11 # LD DE, nn
65
- @e = @bus.read_byte(@pc)
66
- increment_pc
67
- @d = @bus.read_byte(@pc)
68
- increment_pc
178
+ self.de = read_word_and_advance_pc
179
+ when 0x12 # LD (DE), A
180
+ write_byte(de, @a.value)
69
181
  when 0x13 # INC DE
70
- set_de(get_de + 1)
71
- when 0x1a # LD A, (DE)
72
- @a = @bus.read_byte(get_de)
182
+ self.de = de + 1
183
+ when 0x14 # INC D
184
+ @d.increment
185
+ update_flags(
186
+ z: @d.value.zero?,
187
+ n: false,
188
+ h: (@d.value & 0x0f).zero?
189
+ )
190
+ when 0x15 # DEC D
191
+ @d.decrement
192
+ update_flags(
193
+ z: @d.value.zero?,
194
+ n: true,
195
+ h: (@d.value & 0x0f) == 0x0f
196
+ )
197
+ when 0x16 # LD D, d8
198
+ @d.value = read_byte_and_advance_pc
199
+ when 0x17 # RLA
200
+ cflag = @a.value[7] == 1
201
+ @a.value = (@a.value << 1) | bool_to_integer(flags[:c])
202
+ update_flags(
203
+ z: false,
204
+ n: false,
205
+ h: false,
206
+ c: cflag
207
+ )
73
208
  when 0x18 # JR r8
74
- byte = to_signed_byte(@bus.read_byte(@pc))
75
- increment_pc
209
+ byte = convert_to_twos_complement(read_byte_and_advance_pc)
76
210
  @pc += byte
211
+ when 0x19 # ADD HL, DE
212
+ hflag = (hl & 0x0fff) + (de & 0x0fff) > 0x0fff
213
+ cflag = hl + de > 0xffff
214
+ self.hl = hl + de
215
+ update_flags(
216
+ n: false,
217
+ h: hflag,
218
+ c: cflag
219
+ )
220
+ when 0x1a # LD A, (DE)
221
+ @a.value = read_byte(de)
222
+ when 0x1b # DEC DE
223
+ self.de = de - 1
224
+ when 0x1c # INC E
225
+ @e.increment
226
+ update_flags(
227
+ z: @e.value.zero?,
228
+ n: false,
229
+ h: (@e.value & 0x0f).zero?
230
+ )
231
+ when 0x1d # DEC E
232
+ @e.decrement
233
+ update_flags(
234
+ z: @e.value.zero?,
235
+ n: true,
236
+ h: (@e.value & 0x0f) == 0x0f
237
+ )
238
+ when 0x1e # LD E, d8
239
+ @e.value = read_byte_and_advance_pc
240
+ when 0x1f # RRA
241
+ cflag = @a.value[0] == 1
242
+ @a.value = (@a.value >> 1) | (bool_to_integer(flags[:c]) << 7)
243
+ update_flags(
244
+ z: false,
245
+ n: false,
246
+ h: false,
247
+ c: cflag
248
+ )
77
249
  when 0x20 # JR NZ, r8
78
- byte = to_signed_byte(@bus.read_byte(@pc))
79
- increment_pc
80
- @pc += byte if !get_flags[:z]
250
+ byte = convert_to_twos_complement(read_byte_and_advance_pc)
251
+ unless flags[:z]
252
+ @pc += byte
253
+ branched = true
254
+ end
81
255
  when 0x21 # LD HL, nn
82
- @l = @bus.read_byte(@pc)
83
- increment_pc
84
- @h = @bus.read_byte(@pc)
85
- increment_pc
256
+ self.hl = read_word_and_advance_pc
86
257
  when 0x22 # LD (HL+), A
87
- @bus.write_byte(get_hl, @a)
88
- set_hl(get_hl + 1)
89
- when 0x38 # JR C, r8
90
- byte = to_signed_byte(@bus.read_byte(@pc))
91
- increment_pc
92
- @pc += byte if get_flags[:c]
93
- when 0x3e # LD A, d8
94
- @a = @bus.read_byte(@pc)
95
- increment_pc
96
- when 0x40 # LD B, B
97
- @b = @b
98
- when 0x42 # LD B, D
99
- @b = @d
100
- when 0x43 # LD B, E
101
- @b = @e
102
- when 0x78 # LD A, B
103
- @a = @b
104
- when 0xa7 # AND A
105
- @a &= @a
258
+ write_byte(hl, @a.value)
259
+ self.hl = hl + 1
260
+ when 0x23 # INC HL
261
+ self.hl = hl + 1
262
+ when 0x24 # INC H
263
+ @h.increment
106
264
  update_flags(
107
- z: @a == 0,
265
+ z: @h.value.zero?,
108
266
  n: false,
109
- h: true,
110
- c: false
267
+ h: (@h.value & 0x0f).zero?
111
268
  )
112
- when 0xaf # XOR A
113
- @a ^= @a
269
+ when 0x25 # DEC H
270
+ @h.decrement
271
+ update_flags(
272
+ z: @h.value.zero?,
273
+ n: true,
274
+ h: (@h.value & 0x0f) == 0x0f
275
+ )
276
+ when 0x26 # LD H, d8
277
+ @h.value = read_byte_and_advance_pc
278
+ when 0x27 # DAA
279
+ if flags[:n]
280
+ @a.value -= 0x06 if flags[:h]
281
+ @a.value -= 0x60 if flags[:c]
282
+ else
283
+ if flags[:c] || @a.value > 0x99
284
+ @a.value += 0x60
285
+ update_flags(c: true)
286
+ end
287
+ @a.value += 0x06 if flags[:h] || (@a.value & 0x0f) > 0x09
288
+ end
289
+ update_flags(
290
+ z: @a.value.zero?,
291
+ h: false
292
+ )
293
+ when 0x28 # JR Z, r8
294
+ byte = convert_to_twos_complement(read_byte_and_advance_pc)
295
+ if flags[:z]
296
+ @pc += byte
297
+ branched = true
298
+ end
299
+ when 0x29 # ADD HL, HL
300
+ hflag = (hl & 0x0fff) + (hl & 0x0fff) > 0x0fff
301
+ cflag = hl + hl > 0xffff
302
+ self.hl = hl + hl
303
+ update_flags(
304
+ n: false,
305
+ h: hflag,
306
+ c: cflag
307
+ )
308
+ when 0x2a # LD A, (HL+)
309
+ @a.value = read_byte(hl)
310
+ self.hl = hl + 1
311
+ when 0x2b # DEC HL
312
+ self.hl = hl - 1
313
+ when 0x2c # INC L
314
+ @l.increment
315
+ update_flags(
316
+ z: @l.value.zero?,
317
+ n: false,
318
+ h: (@l.value & 0x0f).zero?
319
+ )
320
+ when 0x2d # DEC L
321
+ @l.decrement
322
+ update_flags(
323
+ z: @l.value.zero?,
324
+ n: true,
325
+ h: (@l.value & 0x0f) == 0x0f
326
+ )
327
+ when 0x2e # LD L, d8
328
+ @l.value = read_byte_and_advance_pc
329
+ when 0x2f # CPL
330
+ @a.value = ~@a.value
331
+ update_flags(
332
+ n: true,
333
+ h: true
334
+ )
335
+ when 0x30 # JR NC, r8
336
+ byte = convert_to_twos_complement(read_byte_and_advance_pc)
337
+ unless flags[:c]
338
+ @pc += byte
339
+ branched = true
340
+ end
341
+ when 0x31 # LD SP, nn
342
+ @sp = read_word_and_advance_pc
343
+ when 0x32 # LD (HL-), A
344
+ write_byte(hl, @a.value)
345
+ self.hl = hl - 1
346
+ when 0x33 # INC SP
347
+ @sp = (@sp + 1) & 0xffff
348
+ when 0x34 # INC (HL)
349
+ byte = read_byte(hl)
350
+ byte = (byte + 1) & 0xff
351
+ write_byte(hl, byte)
352
+ update_flags(
353
+ z: byte.zero?,
354
+ n: false,
355
+ h: (byte & 0x0f).zero?
356
+ )
357
+ when 0x35 # DEC (HL)
358
+ byte = read_byte(hl)
359
+ byte = (byte - 1) & 0xff
360
+ write_byte(hl, byte)
361
+ update_flags(
362
+ z: byte.zero?,
363
+ n: true,
364
+ h: (byte & 0x0f) == 0x0f
365
+ )
366
+ when 0x36 # LD (HL), d8
367
+ byte = read_byte_and_advance_pc
368
+ write_byte(hl, byte)
369
+ when 0x37 # SCF
114
370
  update_flags(
115
- z: @a == 0,
116
371
  n: false,
117
372
  h: false,
118
- c: false
373
+ c: true
119
374
  )
120
- when 0xb1 # OR C
121
- @a |= @c
375
+ when 0x38 # JR C, r8
376
+ byte = convert_to_twos_complement(read_byte_and_advance_pc)
377
+ if flags[:c]
378
+ @pc += byte
379
+ branched = true
380
+ end
381
+ when 0x39 # ADD HL, SP
382
+ hflag = (hl & 0x0fff) + (@sp & 0x0fff) > 0x0fff
383
+ cflag = hl + @sp > 0xffff
384
+ self.hl = hl + @sp
385
+ update_flags(
386
+ n: false,
387
+ h: hflag,
388
+ c: cflag
389
+ )
390
+ when 0x3a # LD A, (HL-)
391
+ @a.value = read_byte(hl)
392
+ self.hl = hl - 1
393
+ when 0x3b # DEC SP
394
+ @sp = (@sp - 1) & 0xffff
395
+ when 0x3c # INC A
396
+ @a.increment
397
+ update_flags(
398
+ z: @a.value.zero?,
399
+ n: false,
400
+ h: (@a.value & 0x0f).zero?
401
+ )
402
+ when 0x3d # DEC A
403
+ @a.decrement
404
+ update_flags(
405
+ z: @a.value.zero?,
406
+ n: true,
407
+ h: (@a.value & 0x0f) == 0x0f
408
+ )
409
+ when 0x3e # LD A, d8
410
+ @a.value = read_byte_and_advance_pc
411
+ when 0x3f # CCF
122
412
  update_flags(
123
- z: @a == 0,
124
413
  n: false,
125
414
  h: false,
126
- c: false
415
+ c: !flags[:c]
127
416
  )
417
+ when 0x40 # LD B, B
418
+ @b.value = @b.value
419
+ when 0x41 # LD B, C
420
+ @b.value = @c.value
421
+ when 0x42 # LD B, D
422
+ @b.value = @d.value
423
+ when 0x43 # LD B, E
424
+ @b.value = @e.value
425
+ when 0x44 # LD B, H
426
+ @b.value = @h.value
427
+ when 0x45 # LD B, L
428
+ @b.value = @l.value
429
+ when 0x46 # LD B, (HL)
430
+ @b.value = read_byte(hl)
431
+ when 0x47 # LD B, A
432
+ @b.value = @a.value
433
+ when 0x48 # LD C, B
434
+ @c.value = @b.value
435
+ when 0x49 # LD C, C
436
+ @c.value = @c.value
437
+ when 0x4a # LD C, D
438
+ @c.value = @d.value
439
+ when 0x4b # LD C, E
440
+ @c.value = @e.value
441
+ when 0x4c # LD C, H
442
+ @c.value = @h.value
443
+ when 0x4d # LD C, L
444
+ @c.value = @l.value
445
+ when 0x4e # LD C, (HL)
446
+ @c.value = read_byte(hl)
447
+ when 0x4f # LD C, A
448
+ @c.value = @a.value
449
+ when 0x50 # LD D, B
450
+ @d.value = @b.value
451
+ when 0x51 # LD D, C
452
+ @d.value = @c.value
453
+ when 0x52 # LD D, D
454
+ @d.value = @d.value
455
+ when 0x53 # LD D, E
456
+ @d.value = @e.value
457
+ when 0x54 # LD D, H
458
+ @d.value = @h.value
459
+ when 0x55 # LD D, L
460
+ @d.value = @l.value
461
+ when 0x56 # LD D, (HL)
462
+ @d.value = read_byte(hl)
463
+ when 0x57 # LD D, A
464
+ @d.value = @a.value
465
+ when 0x58 # LD E, B
466
+ @e.value = @b.value
467
+ when 0x59 # LD E, C
468
+ @e.value = @c.value
469
+ when 0x5a # LD E, D
470
+ @e.value = @d.value
471
+ when 0x5b # LD E, E
472
+ @e.value = @e.value
473
+ when 0x5c # LD E, H
474
+ @e.value = @h.value
475
+ when 0x5d # LD E, L
476
+ @e.value = @l.value
477
+ when 0x5e # LD E, (HL)
478
+ @e.value = read_byte(hl)
479
+ when 0x5f # LD E, A
480
+ @e.value = @a.value
481
+ when 0x60 # LD H, B
482
+ @h.value = @b.value
483
+ when 0x61 # LD H, C
484
+ @h.value = @c.value
485
+ when 0x62 # LD H, D
486
+ @h.value = @d.value
487
+ when 0x63 # LD H, E
488
+ @h.value = @e.value
489
+ when 0x64 # LD H, H
490
+ @h.value = @h.value
491
+ when 0x65 # LD H, L
492
+ @h.value = @l.value
493
+ when 0x66 # LD H, (HL)
494
+ @h.value = read_byte(hl)
495
+ when 0x67 # LD H, A
496
+ @h.value = @a.value
497
+ when 0x68 # LD L, B
498
+ @l.value = @b.value
499
+ when 0x69 # LD L, C
500
+ @l.value = @c.value
501
+ when 0x6a # LD L, D
502
+ @l.value = @d.value
503
+ when 0x6b # LD L, E
504
+ @l.value = @e.value
505
+ when 0x6c # LD L, H
506
+ @l.value = @h.value
507
+ when 0x6d # LD L, L
508
+ @l.value = @l.value
509
+ when 0x6e # LD L, (HL)
510
+ @l.value = read_byte(hl)
511
+ when 0x6f # LD L, A
512
+ @l.value = @a.value
513
+ when 0x70 # LD (HL), B
514
+ write_byte(hl, @b.value)
515
+ when 0x71 # LD (HL), C
516
+ write_byte(hl, @c.value)
517
+ when 0x72 # LD (HL), D
518
+ write_byte(hl, @d.value)
519
+ when 0x73 # LD (HL), E
520
+ write_byte(hl, @e.value)
521
+ when 0x74 # LD (HL), H
522
+ write_byte(hl, @h.value)
523
+ when 0x75 # LD (HL), L
524
+ write_byte(hl, @l.value)
525
+ when 0x76 # HALT
526
+ @pc -= 1 unless @bus.interrupt.interrupts.positive?
527
+ when 0x77 # LD (HL), A
528
+ write_byte(hl, @a.value)
529
+ when 0x78 # LD A, B
530
+ @a.value = @b.value
531
+ when 0x79 # LD A, C
532
+ @a.value = @c.value
533
+ when 0x7a # LD A, D
534
+ @a.value = @d.value
535
+ when 0x7b # LD A, E
536
+ @a.value = @e.value
537
+ when 0x7c # LD A, H
538
+ @a.value = @h.value
539
+ when 0x7d # LD A, L
540
+ @a.value = @l.value
541
+ when 0x7e # LD A, (HL)
542
+ @a.value = read_byte(hl)
543
+ when 0x7f # LD A, A
544
+ @a.value = @a.value
545
+ when 0x80 # ADD A, B
546
+ add8(@a, @b)
547
+ when 0x81 # ADD A, C
548
+ add8(@a, @c)
549
+ when 0x82 # ADD A, D
550
+ add8(@a, @d)
551
+ when 0x83 # ADD A, E
552
+ add8(@a, @e)
553
+ when 0x84 # ADD A, H
554
+ add8(@a, @h)
555
+ when 0x85 # ADD A, L
556
+ add8(@a, @l)
557
+ when 0x86 # ADD A, (HL)
558
+ add8(@a, Register.new(name: 'HL', value: read_byte(hl)))
559
+ when 0x87 # ADD A, A
560
+ add8(@a, @a)
561
+ when 0x88 # ADC A, B
562
+ adc8(@a, @b)
563
+ when 0x89 # ADC A, C
564
+ adc8(@a, @c)
565
+ when 0x8a # ADC A, D
566
+ adc8(@a, @d)
567
+ when 0x8b # ADC A, E
568
+ adc8(@a, @e)
569
+ when 0x8c # ADC A, H
570
+ adc8(@a, @h)
571
+ when 0x8d # ADC A, L
572
+ adc8(@a, @l)
573
+ when 0x8e # ADC A, (HL)
574
+ adc8(@a, Register.new(name: 'HL', value: read_byte(hl)))
575
+ when 0x8f # ADC A, A
576
+ adc8(@a, @a)
577
+ when 0x90 # SUB B
578
+ sub8(@b)
579
+ when 0x91 # SUB C
580
+ sub8(@c)
581
+ when 0x92 # SUB D
582
+ sub8(@d)
583
+ when 0x93 # SUB E
584
+ sub8(@e)
585
+ when 0x94 # SUB H
586
+ sub8(@h)
587
+ when 0x95 # SUB L
588
+ sub8(@l)
589
+ when 0x96 # SUB (HL)
590
+ sub8(Register.new(name: 'HL', value: read_byte(hl)))
591
+ when 0x97 # SUB A
592
+ sub8(@a)
593
+ when 0x98 # SBC A, B
594
+ sbc8(@b)
595
+ when 0x99 # SBC A, C
596
+ sbc8(@c)
597
+ when 0x9a # SBC A, D
598
+ sbc8(@d)
599
+ when 0x9b # SBC A, E
600
+ sbc8(@e)
601
+ when 0x9c # SBC A, H
602
+ sbc8(@h)
603
+ when 0x9d # SBC A, L
604
+ sbc8(@l)
605
+ when 0x9e # SBC A, (HL)
606
+ sbc8(Register.new(name: 'HL', value: read_byte(hl)))
607
+ when 0x9f # SBC A, A
608
+ sbc8(@a)
609
+ when 0xa0 # AND B
610
+ and8(@b)
611
+ when 0xa1 # AND C
612
+ and8(@c)
613
+ when 0xa2 # AND D
614
+ and8(@d)
615
+ when 0xa3 # AND E
616
+ and8(@e)
617
+ when 0xa4 # AND H
618
+ and8(@h)
619
+ when 0xa5 # AND L
620
+ and8(@l)
621
+ when 0xa6 # AND (HL)
622
+ and8(Register.new(name: 'HL', value: read_byte(hl)))
623
+ when 0xa7 # AND A
624
+ and8(@a)
625
+ when 0xa8 # XOR B
626
+ xor8(@b)
627
+ when 0xa9 # XOR C
628
+ xor8(@c)
629
+ when 0xaa # XOR D
630
+ xor8(@d)
631
+ when 0xab # XOR E
632
+ xor8(@e)
633
+ when 0xac # XOR H
634
+ xor8(@h)
635
+ when 0xad # XOR L
636
+ xor8(@l)
637
+ when 0xae # XOR (HL)
638
+ xor8(Register.new(name: 'HL', value: read_byte(hl)))
639
+ when 0xaf # XOR A
640
+ xor8(@a)
641
+ when 0xb0 # OR B
642
+ or8(@b)
643
+ when 0xb1 # OR C
644
+ or8(@c)
645
+ when 0xb2 # OR D
646
+ or8(@d)
647
+ when 0xb3 # OR E
648
+ or8(@e)
649
+ when 0xb4 # OR H
650
+ or8(@h)
651
+ when 0xb5 # OR L
652
+ or8(@l)
653
+ when 0xb6 # OR (HL)
654
+ or8(Register.new(name: 'HL', value: read_byte(hl)))
655
+ when 0xb7 # OR A
656
+ or8(@a)
657
+ when 0xb8 # CP B
658
+ cp8(@b)
659
+ when 0xb9 # CP C
660
+ cp8(@c)
661
+ when 0xba # CP D
662
+ cp8(@d)
663
+ when 0xbb # CP E
664
+ cp8(@e)
665
+ when 0xbc # CP H
666
+ cp8(@h)
667
+ when 0xbd # CP L
668
+ cp8(@l)
669
+ when 0xbe # CP (HL)
670
+ cp8(Register.new(name: 'HL', value: read_byte(hl)))
671
+ when 0xbf # CP A
672
+ cp8(@a)
673
+ when 0xc0 # RET NZ
674
+ unless flags[:z]
675
+ @pc = read_word(@sp)
676
+ @sp += 2
677
+ branched = true
678
+ end
679
+ when 0xc1 # POP BC
680
+ self.bc = read_word(@sp)
681
+ @sp += 2
682
+ when 0xc2 # JP NZ, nn
683
+ word = read_word_and_advance_pc
684
+ unless flags[:z]
685
+ @pc = word
686
+ branched = true
687
+ end
128
688
  when 0xc3 # JP nn
129
- @pc = @bus.read_word(@pc)
689
+ @pc = read_word_and_advance_pc
690
+ when 0xc4 # CALL NZ, nn
691
+ word = read_word_and_advance_pc
692
+ unless flags[:z]
693
+ @sp -= 2
694
+ write_word(@sp, @pc)
695
+ @pc = word
696
+ branched = true
697
+ end
698
+ when 0xc5 # PUSH BC
699
+ @sp -= 2
700
+ write_word(@sp, bc)
701
+ when 0xc6 # ADD A, d8
702
+ byte = read_byte_and_advance_pc
703
+ add8(@a, Register.new(name: 'd8', value: byte))
704
+ when 0xc7 # RST 00H
705
+ @sp -= 2
706
+ write_word(@sp, @pc)
707
+ @pc = 0x00
708
+ when 0xc8 # RET Z
709
+ if flags[:z]
710
+ @pc = read_word(@sp)
711
+ @sp += 2
712
+ branched = true
713
+ end
714
+ when 0xc9 # RET
715
+ @pc = read_word(@sp)
716
+ @sp += 2
717
+ when 0xca # JP Z, nn
718
+ word = read_word_and_advance_pc
719
+ if flags[:z]
720
+ @pc = word
721
+ branched = true
722
+ end
723
+ when 0xcc # CALL Z, nn
724
+ word = read_word_and_advance_pc
725
+ if flags[:z]
726
+ @sp -= 2
727
+ write_word(@sp, @pc)
728
+ @pc = word
729
+ branched = true
730
+ end
731
+ when 0xcd # CALL nn
732
+ word = read_word_and_advance_pc
733
+ @sp -= 2
734
+ write_word(@sp, @pc)
735
+ @pc = word
736
+ when 0xce # ADC A, d8
737
+ byte = read_byte_and_advance_pc
738
+ adc8(@a, Register.new(name: 'd8', value: byte))
739
+ when 0xcf # RST 08H
740
+ @sp -= 2
741
+ write_word(@sp, @pc)
742
+ @pc = 0x08
743
+ when 0xd0 # RET NC
744
+ unless flags[:c]
745
+ @pc = read_word(@sp)
746
+ @sp += 2
747
+ branched = true
748
+ end
749
+ when 0xd1 # POP DE
750
+ self.de = read_word(@sp)
751
+ @sp += 2
752
+ when 0xd2 # JP NC, nn
753
+ word = read_word_and_advance_pc
754
+ unless flags[:c]
755
+ @pc = word
756
+ branched = true
757
+ end
758
+ when 0xd4 # CALL NC, nn
759
+ word = read_word_and_advance_pc
760
+ unless flags[:c]
761
+ @sp -= 2
762
+ write_word(@sp, @pc)
763
+ @pc = word
764
+ branched = true
765
+ end
766
+ when 0xd5 # PUSH DE
767
+ @sp -= 2
768
+ write_word(@sp, de)
769
+ when 0xd6 # SUB d8
770
+ byte = read_byte_and_advance_pc
771
+ sub8(Register.new(name: 'd8', value: byte))
772
+ when 0xd7 # RST 10H
773
+ @sp -= 2
774
+ write_word(@sp, @pc)
775
+ @pc = 0x10
776
+ when 0xd8 # RET C
777
+ if flags[:c]
778
+ @pc = read_word(@sp)
779
+ @sp += 2
780
+ branched = true
781
+ end
782
+ when 0xd9 # RETI
783
+ @pc = read_word(@sp)
784
+ @sp += 2
785
+ @ime = true
786
+ when 0xda # JP C, nn
787
+ word = read_word_and_advance_pc
788
+ if flags[:c]
789
+ @pc = word
790
+ branched = true
791
+ end
792
+ when 0xdc # CALL C, nn
793
+ word = read_word_and_advance_pc
794
+ if flags[:c]
795
+ @sp -= 2
796
+ write_word(@sp, @pc)
797
+ @pc = word
798
+ branched = true
799
+ end
800
+ when 0xde # SBC A, d8
801
+ byte = read_byte_and_advance_pc
802
+ sbc8(Register.new(name: 'd8', value: byte))
803
+ when 0xdf # RST 18H
804
+ @sp -= 2
805
+ write_word(@sp, @pc)
806
+ @pc = 0x18
130
807
  when 0xe0 # LDH (a8), A
131
- byte = @bus.read_byte(@pc)
132
- @bus.write_byte(0xff00 + byte, @a)
133
- increment_pc
808
+ byte = read_byte_and_advance_pc
809
+ write_byte(0xff00 + byte, @a.value)
810
+ when 0xe1 # POP HL
811
+ self.hl = read_word(@sp)
812
+ @sp += 2
813
+ when 0xe2 # LD (C), A
814
+ write_byte(0xff00 + @c.value, @a.value)
815
+ when 0xe5 # PUSH HL
816
+ @sp -= 2
817
+ write_word(@sp, hl)
818
+ when 0xe6 # AND d8
819
+ byte = read_byte_and_advance_pc
820
+ and8(Register.new(name: 'd8', value: byte))
821
+ when 0xe7 # RST 20H
822
+ @sp -= 2
823
+ write_word(@sp, @pc)
824
+ @pc = 0x20
825
+ when 0xe8 # ADD SP, r8
826
+ byte = convert_to_twos_complement(read_byte_and_advance_pc)
827
+
828
+ hflag = (@sp & 0x0f) + (byte & 0x0f) > 0x0f
829
+ cflag = (@sp & 0xff) + (byte & 0xff) > 0xff
830
+
831
+ @sp += byte
832
+ @sp &= 0xffff
833
+ update_flags(
834
+ z: false,
835
+ n: false,
836
+ h: hflag,
837
+ c: cflag
838
+ )
839
+ when 0xe9 # JP (HL)
840
+ @pc = hl
841
+ when 0xea # LD (nn), A
842
+ word = read_word_and_advance_pc
843
+ write_byte(word, @a.value)
844
+ when 0xee # XOR d8
845
+ byte = read_byte_and_advance_pc
846
+ xor8(Register.new(name: 'd8', value: byte))
847
+ when 0xef # RST 28H
848
+ @sp -= 2
849
+ write_word(@sp, @pc)
850
+ @pc = 0x28
134
851
  when 0xf0 # LDH A, (a8)
135
- byte = @bus.read_byte(@pc)
136
- @a = @bus.read_byte(0xff00 + byte)
137
- increment_pc
852
+ byte = read_byte_and_advance_pc
853
+ @a.value = read_byte(0xff00 + byte)
854
+ when 0xf1 # POP AF
855
+ self.af = read_word(@sp)
856
+ @sp += 2
857
+ when 0xf2 # LD A, (C)
858
+ @a.value = read_byte(0xff00 + @c.value)
138
859
  when 0xf3 # DI
860
+ @ime_delay = false
139
861
  @ime = false
862
+ when 0xf5 # PUSH AF
863
+ @sp -= 2
864
+ write_word(@sp, af)
865
+ when 0xf6 # OR d8
866
+ byte = read_byte_and_advance_pc
867
+ or8(Register.new(name: 'd8', value: byte))
868
+ when 0xf7 # RST 30H
869
+ @sp -= 2
870
+ write_word(@sp, @pc)
871
+ @pc = 0x30
872
+ when 0xf8 # LD HL, SP+r8
873
+ byte = convert_to_twos_complement(read_byte_and_advance_pc)
874
+
875
+ hflag = (@sp & 0x0f) + (byte & 0x0f) > 0x0f
876
+ cflag = (@sp & 0xff) + (byte & 0xff) > 0xff
877
+ self.hl = @sp + byte
878
+ update_flags(
879
+ z: false,
880
+ n: false,
881
+ h: hflag,
882
+ c: cflag
883
+ )
884
+ when 0xf9 # LD SP, HL
885
+ @sp = hl
886
+ when 0xfa # LD A, (nn)
887
+ word = read_word_and_advance_pc
888
+ @a.value = read_byte(word)
889
+ when 0xfb # EI
890
+ @ime_delay = true
140
891
  when 0xfe # CP d8
141
- byte = @bus.read_byte(@pc)
892
+ byte = read_byte_and_advance_pc
142
893
  update_flags(
143
- z: @a == byte,
894
+ z: @a.value == byte,
144
895
  n: true,
145
- h: (@a & 0x0f) < (byte & 0x0f),
146
- c: @a < byte
896
+ h: (@a.value & 0x0f) < (byte & 0x0f),
897
+ c: @a.value < byte
147
898
  )
148
- increment_pc
899
+ when 0xff # RST 38H
900
+ @sp -= 2
901
+ write_word(@sp, @pc)
902
+ @pc = 0x38
903
+ when 0xcb # CB prefix
904
+ opcode = read_byte_and_advance_pc
905
+ cbprefixed = true
906
+
907
+ # p "CB #{opcode.to_s(16)}"
908
+
909
+ case opcode
910
+ when 0x00 # RLC B
911
+ rlc8(@b)
912
+ when 0x01 # RLC C
913
+ rlc8(@c)
914
+ when 0x02 # RLC D
915
+ rlc8(@d)
916
+ when 0x03 # RLC E
917
+ rlc8(@e)
918
+ when 0x04 # RLC H
919
+ rlc8(@h)
920
+ when 0x05 # RLC L
921
+ rlc8(@l)
922
+ when 0x06 # RLC (HL)
923
+ reg = Register.new(name: 'HL', value: read_byte(hl))
924
+ rlc8(reg)
925
+ write_byte(hl, reg.value)
926
+ when 0x07 # RLC A
927
+ rlc8(@a)
928
+ when 0x08 # RRC B
929
+ rrc8(@b)
930
+ when 0x09 # RRC C
931
+ rrc8(@c)
932
+ when 0x0a # RRC D
933
+ rrc8(@d)
934
+ when 0x0b # RRC E
935
+ rrc8(@e)
936
+ when 0x0c # RRC H
937
+ rrc8(@h)
938
+ when 0x0d # RRC L
939
+ rrc8(@l)
940
+ when 0x0e # RRC (HL)
941
+ reg = Register.new(name: 'HL', value: read_byte(hl))
942
+ rrc8(reg)
943
+ write_byte(hl, reg.value)
944
+ when 0x0f # RRC A
945
+ rrc8(@a)
946
+ when 0x10 # RL B
947
+ rl8(@b)
948
+ when 0x11 # RL C
949
+ rl8(@c)
950
+ when 0x12 # RL D
951
+ rl8(@d)
952
+ when 0x13 # RL E
953
+ rl8(@e)
954
+ when 0x14 # RL H
955
+ rl8(@h)
956
+ when 0x15 # RL L
957
+ rl8(@l)
958
+ when 0x16 # RL (HL)
959
+ reg = Register.new(name: 'HL', value: read_byte(hl))
960
+ rl8(reg)
961
+ write_byte(hl, reg.value)
962
+ when 0x17 # RL A
963
+ rl8(@a)
964
+ when 0x18 # RR B
965
+ rr8(@b)
966
+ when 0x19 # RR C
967
+ rr8(@c)
968
+ when 0x1a # RR D
969
+ rr8(@d)
970
+ when 0x1b # RR E
971
+ rr8(@e)
972
+ when 0x1c # RR H
973
+ rr8(@h)
974
+ when 0x1d # RR L
975
+ rr8(@l)
976
+ when 0x1e # RR (HL)
977
+ reg = Register.new(name: 'HL', value: read_byte(hl))
978
+ rr8(reg)
979
+ write_byte(hl, reg.value)
980
+ when 0x1f # RR A
981
+ rr8(@a)
982
+ when 0x20 # SLA B
983
+ sla8(@b)
984
+ when 0x21 # SLA C
985
+ sla8(@c)
986
+ when 0x22 # SLA D
987
+ sla8(@d)
988
+ when 0x23 # SLA E
989
+ sla8(@e)
990
+ when 0x24 # SLA H
991
+ sla8(@h)
992
+ when 0x25 # SLA L
993
+ sla8(@l)
994
+ when 0x26 # SLA (HL)
995
+ reg = Register.new(name: 'HL', value: read_byte(hl))
996
+ sla8(reg)
997
+ write_byte(hl, reg.value)
998
+ when 0x27 # SLA A
999
+ sla8(@a)
1000
+ when 0x28 # SRA B
1001
+ sra8(@b)
1002
+ when 0x29 # SRA C
1003
+ sra8(@c)
1004
+ when 0x2a # SRA D
1005
+ sra8(@d)
1006
+ when 0x2b # SRA E
1007
+ sra8(@e)
1008
+ when 0x2c # SRA H
1009
+ sra8(@h)
1010
+ when 0x2d # SRA L
1011
+ sra8(@l)
1012
+ when 0x2e # SRA (HL)
1013
+ reg = Register.new(name: 'HL', value: read_byte(hl))
1014
+ sra8(reg)
1015
+ write_byte(hl, reg.value)
1016
+ when 0x2f # SRA A
1017
+ sra8(@a)
1018
+ when 0x30 # SWAP B
1019
+ swap8(@b)
1020
+ when 0x31 # SWAP C
1021
+ swap8(@c)
1022
+ when 0x32 # SWAP D
1023
+ swap8(@d)
1024
+ when 0x33 # SWAP E
1025
+ swap8(@e)
1026
+ when 0x34 # SWAP H
1027
+ swap8(@h)
1028
+ when 0x35 # SWAP L
1029
+ swap8(@l)
1030
+ when 0x36 # SWAP (HL)
1031
+ reg = Register.new(name: 'HL', value: read_byte(hl))
1032
+ swap8(reg)
1033
+ write_byte(hl, reg.value)
1034
+ when 0x37 # SWAP A
1035
+ swap8(@a)
1036
+ when 0x38 # SRL B
1037
+ srl8(@b)
1038
+ when 0x39 # SRL C
1039
+ srl8(@c)
1040
+ when 0x3a # SRL D
1041
+ srl8(@d)
1042
+ when 0x3b # SRL E
1043
+ srl8(@e)
1044
+ when 0x3c # SRL H
1045
+ srl8(@h)
1046
+ when 0x3d # SRL L
1047
+ srl8(@l)
1048
+ when 0x3e # SRL (HL)
1049
+ reg = Register.new(name: 'HL', value: read_byte(hl))
1050
+ srl8(reg)
1051
+ write_byte(hl, reg.value)
1052
+ when 0x3f # SRL A
1053
+ srl8(@a)
1054
+ when 0x40 # BIT 0, B
1055
+ bit8(0, @b)
1056
+ when 0x41 # BIT 0, C
1057
+ bit8(0, @c)
1058
+ when 0x42 # BIT 0, D
1059
+ bit8(0, @d)
1060
+ when 0x43 # BIT 0, E
1061
+ bit8(0, @e)
1062
+ when 0x44 # BIT 0, H
1063
+ bit8(0, @h)
1064
+ when 0x45 # BIT 0, L
1065
+ bit8(0, @l)
1066
+ when 0x46 # BIT 0, (HL)
1067
+ bit8(0, Register.new(name: 'HL', value: read_byte(hl)))
1068
+ when 0x47 # BIT 0, A
1069
+ bit8(0, @a)
1070
+ when 0x48 # BIT 1, B
1071
+ bit8(1, @b)
1072
+ when 0x49 # BIT 1, C
1073
+ bit8(1, @c)
1074
+ when 0x4a # BIT 1, D
1075
+ bit8(1, @d)
1076
+ when 0x4b # BIT 1, E
1077
+ bit8(1, @e)
1078
+ when 0x4c # BIT 1, H
1079
+ bit8(1, @h)
1080
+ when 0x4d # BIT 1, L
1081
+ bit8(1, @l)
1082
+ when 0x4e # BIT 1, (HL)
1083
+ bit8(1, Register.new(name: 'HL', value: read_byte(hl)))
1084
+ when 0x4f # BIT 1, A
1085
+ bit8(1, @a)
1086
+ when 0x50 # BIT 2, B
1087
+ bit8(2, @b)
1088
+ when 0x51 # BIT 2, C
1089
+ bit8(2, @c)
1090
+ when 0x52 # BIT 2, D
1091
+ bit8(2, @d)
1092
+ when 0x53 # BIT 2, E
1093
+ bit8(2, @e)
1094
+ when 0x54 # BIT 2, H
1095
+ bit8(2, @h)
1096
+ when 0x55 # BIT 2, L
1097
+ bit8(2, @l)
1098
+ when 0x56 # BIT 2, (HL)
1099
+ bit8(2, Register.new(name: 'HL', value: read_byte(hl)))
1100
+ when 0x57 # BIT 2, A
1101
+ bit8(2, @a)
1102
+ when 0x58 # BIT 3, B
1103
+ bit8(3, @b)
1104
+ when 0x59 # BIT 3, C
1105
+ bit8(3, @c)
1106
+ when 0x5a # BIT 3, D
1107
+ bit8(3, @d)
1108
+ when 0x5b # BIT 3, E
1109
+ bit8(3, @e)
1110
+ when 0x5c # BIT 3, H
1111
+ bit8(3, @h)
1112
+ when 0x5d # BIT 3, L
1113
+ bit8(3, @l)
1114
+ when 0x5e # BIT 3, (HL)
1115
+ bit8(3, Register.new(name: 'HL', value: read_byte(hl)))
1116
+ when 0x5f # BIT 3, A
1117
+ bit8(3, @a)
1118
+ when 0x60 # BIT 4, B
1119
+ bit8(4, @b)
1120
+ when 0x61 # BIT 4, C
1121
+ bit8(4, @c)
1122
+ when 0x62 # BIT 4, D
1123
+ bit8(4, @d)
1124
+ when 0x63 # BIT 4, E
1125
+ bit8(4, @e)
1126
+ when 0x64 # BIT 4, H
1127
+ bit8(4, @h)
1128
+ when 0x65 # BIT 4, L
1129
+ bit8(4, @l)
1130
+ when 0x66 # BIT 4, (HL)
1131
+ bit8(4, Register.new(name: 'HL', value: read_byte(hl)))
1132
+ when 0x67 # BIT 4, A
1133
+ bit8(4, @a)
1134
+ when 0x68 # BIT 5, B
1135
+ bit8(5, @b)
1136
+ when 0x69 # BIT 5, C
1137
+ bit8(5, @c)
1138
+ when 0x6a # BIT 5, D
1139
+ bit8(5, @d)
1140
+ when 0x6b # BIT 5, E
1141
+ bit8(5, @e)
1142
+ when 0x6c # BIT 5, H
1143
+ bit8(5, @h)
1144
+ when 0x6d # BIT 5, L
1145
+ bit8(5, @l)
1146
+ when 0x6e # BIT 5, (HL)
1147
+ bit8(5, Register.new(name: 'HL', value: read_byte(hl)))
1148
+ when 0x6f # BIT 5, A
1149
+ bit8(5, @a)
1150
+ when 0x70 # BIT 6, B
1151
+ bit8(6, @b)
1152
+ when 0x71 # BIT 6, C
1153
+ bit8(6, @c)
1154
+ when 0x72 # BIT 6, D
1155
+ bit8(6, @d)
1156
+ when 0x73 # BIT 6, E
1157
+ bit8(6, @e)
1158
+ when 0x74 # BIT 6, H
1159
+ bit8(6, @h)
1160
+ when 0x75 # BIT 6, L
1161
+ bit8(6, @l)
1162
+ when 0x76 # BIT 6, (HL)
1163
+ bit8(6, Register.new(name: 'HL', value: read_byte(hl)))
1164
+ when 0x77 # BIT 6, A
1165
+ bit8(6, @a)
1166
+ when 0x78 # BIT 7, B
1167
+ bit8(7, @b)
1168
+ when 0x79 # BIT 7, C
1169
+ bit8(7, @c)
1170
+ when 0x7a # BIT 7, D
1171
+ bit8(7, @d)
1172
+ when 0x7b # BIT 7, E
1173
+ bit8(7, @e)
1174
+ when 0x7c # BIT 7, H
1175
+ bit8(7, @h)
1176
+ when 0x7d # BIT 7, L
1177
+ bit8(7, @l)
1178
+ when 0x7e # BIT 7, (HL)
1179
+ bit8(7, Register.new(name: 'HL', value: read_byte(hl)))
1180
+ when 0x7f # BIT 7, A
1181
+ bit8(7, @a)
1182
+ when 0x80 # RES 0, B
1183
+ res8(0, @b)
1184
+ when 0x81 # RES 0, C
1185
+ res8(0, @c)
1186
+ when 0x82 # RES 0, D
1187
+ res8(0, @d)
1188
+ when 0x83 # RES 0, E
1189
+ res8(0, @e)
1190
+ when 0x84 # RES 0, H
1191
+ res8(0, @h)
1192
+ when 0x85 # RES 0, L
1193
+ res8(0, @l)
1194
+ when 0x86 # RES 0, (HL)
1195
+ reg = Register.new(name: 'HL', value: read_byte(hl))
1196
+ res8(0, reg)
1197
+ write_byte(hl, reg.value)
1198
+ when 0x87 # RES 0, A
1199
+ res8(0, @a)
1200
+ when 0x88 # RES 1, B
1201
+ res8(1, @b)
1202
+ when 0x89 # RES 1, C
1203
+ res8(1, @c)
1204
+ when 0x8a # RES 1, D
1205
+ res8(1, @d)
1206
+ when 0x8b # RES 1, E
1207
+ res8(1, @e)
1208
+ when 0x8c # RES 1, H
1209
+ res8(1, @h)
1210
+ when 0x8d # RES 1, L
1211
+ res8(1, @l)
1212
+ when 0x8e # RES 1, (HL)
1213
+ reg = Register.new(name: 'HL', value: read_byte(hl))
1214
+ res8(1, reg)
1215
+ write_byte(hl, reg.value)
1216
+ when 0x8f # RES 1, A
1217
+ res8(1, @a)
1218
+ when 0x90 # RES 2, B
1219
+ res8(2, @b)
1220
+ when 0x91 # RES 2, C
1221
+ res8(2, @c)
1222
+ when 0x92 # RES 2, D
1223
+ res8(2, @d)
1224
+ when 0x93 # RES 2, E
1225
+ res8(2, @e)
1226
+ when 0x94 # RES 2, H
1227
+ res8(2, @h)
1228
+ when 0x95 # RES 2, L
1229
+ res8(2, @l)
1230
+ when 0x96 # RES 2, (HL)
1231
+ reg = Register.new(name: 'HL', value: read_byte(hl))
1232
+ res8(2, reg)
1233
+ write_byte(hl, reg.value)
1234
+ when 0x97 # RES 2, A
1235
+ res8(2, @a)
1236
+ when 0x98 # RES 3, B
1237
+ res8(3, @b)
1238
+ when 0x99 # RES 3, C
1239
+ res8(3, @c)
1240
+ when 0x9a # RES 3, D
1241
+ res8(3, @d)
1242
+ when 0x9b # RES 3, E
1243
+ res8(3, @e)
1244
+ when 0x9c # RES 3, H
1245
+ res8(3, @h)
1246
+ when 0x9d # RES 3, L
1247
+ res8(3, @l)
1248
+ when 0x9e # RES 3, (HL)
1249
+ reg = Register.new(name: 'HL', value: read_byte(hl))
1250
+ res8(3, reg)
1251
+ write_byte(hl, reg.value)
1252
+ when 0x9f # RES 3, A
1253
+ res8(3, @a)
1254
+ when 0xa0 # RES 4, B
1255
+ res8(4, @b)
1256
+ when 0xa1 # RES 4, C
1257
+ res8(4, @c)
1258
+ when 0xa2 # RES 4, D
1259
+ res8(4, @d)
1260
+ when 0xa3 # RES 4, E
1261
+ res8(4, @e)
1262
+ when 0xa4 # RES 4, H
1263
+ res8(4, @h)
1264
+ when 0xa5 # RES 4, L
1265
+ res8(4, @l)
1266
+ when 0xa6 # RES 4, (HL)
1267
+ reg = Register.new(name: 'HL', value: read_byte(hl))
1268
+ res8(4, reg)
1269
+ write_byte(hl, reg.value)
1270
+ when 0xa7 # RES 4, A
1271
+ res8(4, @a)
1272
+ when 0xa8 # RES 5, B
1273
+ res8(5, @b)
1274
+ when 0xa9 # RES 5, C
1275
+ res8(5, @c)
1276
+ when 0xaa # RES 5, D
1277
+ res8(5, @d)
1278
+ when 0xab # RES 5, E
1279
+ res8(5, @e)
1280
+ when 0xac # RES 5, H
1281
+ res8(5, @h)
1282
+ when 0xad # RES 5, L
1283
+ res8(5, @l)
1284
+ when 0xae # RES 5, (HL)
1285
+ reg = Register.new(name: 'HL', value: read_byte(hl))
1286
+ res8(5, reg)
1287
+ write_byte(hl, reg.value)
1288
+ when 0xaf # RES 5, A
1289
+ res8(5, @a)
1290
+ when 0xb0 # RES 6, B
1291
+ res8(6, @b)
1292
+ when 0xb1 # RES 6, C
1293
+ res8(6, @c)
1294
+ when 0xb2 # RES 6, D
1295
+ res8(6, @d)
1296
+ when 0xb3 # RES 6, E
1297
+ res8(6, @e)
1298
+ when 0xb4 # RES 6, H
1299
+ res8(6, @h)
1300
+ when 0xb5 # RES 6, L
1301
+ res8(6, @l)
1302
+ when 0xb6 # RES 6, (HL)
1303
+ reg = Register.new(name: 'HL', value: read_byte(hl))
1304
+ res8(6, reg)
1305
+ write_byte(hl, reg.value)
1306
+ when 0xb7 # RES 6, A
1307
+ res8(6, @a)
1308
+ when 0xb8 # RES 7, B
1309
+ res8(7, @b)
1310
+ when 0xb9 # RES 7, C
1311
+ res8(7, @c)
1312
+ when 0xba # RES 7, D
1313
+ res8(7, @d)
1314
+ when 0xbb # RES 7, E
1315
+ res8(7, @e)
1316
+ when 0xbc # RES 7, H
1317
+ res8(7, @h)
1318
+ when 0xbd # RES 7, L
1319
+ res8(7, @l)
1320
+ when 0xbe # RES 7, (HL)
1321
+ reg = Register.new(name: 'HL', value: read_byte(hl))
1322
+ res8(7, reg)
1323
+ write_byte(hl, reg.value)
1324
+ when 0xbf # RES 7, A
1325
+ res8(7, @a)
1326
+ when 0xc0 # SET 0, B
1327
+ set8(0, @b)
1328
+ when 0xc1 # SET 0, C
1329
+ set8(0, @c)
1330
+ when 0xc2 # SET 0, D
1331
+ set8(0, @d)
1332
+ when 0xc3 # SET 0, E
1333
+ set8(0, @e)
1334
+ when 0xc4 # SET 0, H
1335
+ set8(0, @h)
1336
+ when 0xc5 # SET 0, L
1337
+ set8(0, @l)
1338
+ when 0xc6 # SET 0, (HL)
1339
+ reg = Register.new(name: 'HL', value: read_byte(hl))
1340
+ set8(0, reg)
1341
+ write_byte(hl, reg.value)
1342
+ when 0xc7 # SET 0, A
1343
+ set8(0, @a)
1344
+ when 0xc8 # SET 1, B
1345
+ set8(1, @b)
1346
+ when 0xc9 # SET 1, C
1347
+ set8(1, @c)
1348
+ when 0xca # SET 1, D
1349
+ set8(1, @d)
1350
+ when 0xcb # SET 1, E
1351
+ set8(1, @e)
1352
+ when 0xcc # SET 1, H
1353
+ set8(1, @h)
1354
+ when 0xcd # SET 1, L
1355
+ set8(1, @l)
1356
+ when 0xce # SET 1, (HL)
1357
+ reg = Register.new(name: 'HL', value: read_byte(hl))
1358
+ set8(1, reg)
1359
+ write_byte(hl, reg.value)
1360
+ when 0xcf # SET 1, A
1361
+ set8(1, @a)
1362
+ when 0xd0 # SET 2, B
1363
+ set8(2, @b)
1364
+ when 0xd1 # SET 2, C
1365
+ set8(2, @c)
1366
+ when 0xd2 # SET 2, D
1367
+ set8(2, @d)
1368
+ when 0xd3 # SET 2, E
1369
+ set8(2, @e)
1370
+ when 0xd4 # SET 2, H
1371
+ set8(2, @h)
1372
+ when 0xd5 # SET 2, L
1373
+ set8(2, @l)
1374
+ when 0xd6 # SET 2, (HL)
1375
+ reg = Register.new(name: 'HL', value: read_byte(hl))
1376
+ set8(2, reg)
1377
+ write_byte(hl, reg.value)
1378
+ when 0xd7 # SET 2, A
1379
+ set8(2, @a)
1380
+ when 0xd8 # SET 3, B
1381
+ set8(3, @b)
1382
+ when 0xd9 # SET 3, C
1383
+ set8(3, @c)
1384
+ when 0xda # SET 3, D
1385
+ set8(3, @d)
1386
+ when 0xdb # SET 3, E
1387
+ set8(3, @e)
1388
+ when 0xdc # SET 3, H
1389
+ set8(3, @h)
1390
+ when 0xdd # SET 3, L
1391
+ set8(3, @l)
1392
+ when 0xde # SET 3, (HL)
1393
+ reg = Register.new(name: 'HL', value: read_byte(hl))
1394
+ set8(3, reg)
1395
+ write_byte(hl, reg.value)
1396
+ when 0xdf # SET 3, A
1397
+ set8(3, @a)
1398
+ when 0xe0 # SET 4, B
1399
+ set8(4, @b)
1400
+ when 0xe1 # SET 4, C
1401
+ set8(4, @c)
1402
+ when 0xe2 # SET 4, D
1403
+ set8(4, @d)
1404
+ when 0xe3 # SET 4, E
1405
+ set8(4, @e)
1406
+ when 0xe4 # SET 4, H
1407
+ set8(4, @h)
1408
+ when 0xe5 # SET 4, L
1409
+ set8(4, @l)
1410
+ when 0xe6 # SET 4, (HL)
1411
+ reg = Register.new(name: 'HL', value: read_byte(hl))
1412
+ set8(4, reg)
1413
+ write_byte(hl, reg.value)
1414
+ when 0xe7 # SET 4, A
1415
+ set8(4, @a)
1416
+ when 0xe8 # SET 5, B
1417
+ set8(5, @b)
1418
+ when 0xe9 # SET 5, C
1419
+ set8(5, @c)
1420
+ when 0xea # SET 5, D
1421
+ set8(5, @d)
1422
+ when 0xeb # SET 5, E
1423
+ set8(5, @e)
1424
+ when 0xec # SET 5, H
1425
+ set8(5, @h)
1426
+ when 0xed # SET 5, L
1427
+ set8(5, @l)
1428
+ when 0xee # SET 5, (HL)
1429
+ reg = Register.new(name: 'HL', value: read_byte(hl))
1430
+ set8(5, reg)
1431
+ write_byte(hl, reg.value)
1432
+ when 0xef # SET 5, A
1433
+ set8(5, @a)
1434
+ when 0xf0 # SET 6, B
1435
+ set8(6, @b)
1436
+ when 0xf1 # SET 6, C
1437
+ set8(6, @c)
1438
+ when 0xf2 # SET 6, D
1439
+ set8(6, @d)
1440
+ when 0xf3 # SET 6, E
1441
+ set8(6, @e)
1442
+ when 0xf4 # SET 6, H
1443
+ set8(6, @h)
1444
+ when 0xf5 # SET 6, L
1445
+ set8(6, @l)
1446
+ when 0xf6 # SET 6, (HL)
1447
+ reg = Register.new(name: 'HL', value: read_byte(hl))
1448
+ set8(6, reg)
1449
+ write_byte(hl, reg.value)
1450
+ when 0xf7 # SET 6, A
1451
+ set8(6, @a)
1452
+ when 0xf8 # SET 7, B
1453
+ set8(7, @b)
1454
+ when 0xf9 # SET 7, C
1455
+ set8(7, @c)
1456
+ when 0xfa # SET 7, D
1457
+ set8(7, @d)
1458
+ when 0xfb # SET 7, E
1459
+ set8(7, @e)
1460
+ when 0xfc then set8(7, @h)
1461
+ when 0xfd then set8(7, @l)
1462
+ when 0xfe # SET 7, (HL)
1463
+ reg = Register.new(name: 'HL', value: read_byte(hl))
1464
+ set8(7, reg)
1465
+ write_byte(hl, reg.value)
1466
+ when 0xff then set8(7, @a) # SET 7, A
1467
+ else
1468
+ raise "unknown opcode: 0xcb 0x#{'%02x' % opcode}"
1469
+ end
149
1470
  else
150
1471
  raise "unknown opcode: 0x#{'%02x' % opcode}"
151
1472
  end
152
1473
 
153
- print_log(opcode)
1474
+ @sp &= 0xffff
1475
+
1476
+ opcode_kind = cbprefixed ? 'cbprefixed' : 'unprefixed'
1477
+ opcode_str = "0x#{'%02X' % opcode}"
1478
+ cycles = @opcodes[opcode_kind][opcode_str]['cycles']
154
1479
 
155
- clock
1480
+ branched ? cycles.max : cycles.min
156
1481
  end
157
1482
 
158
1483
  private
159
1484
 
1485
+ def read_byte(addr)
1486
+ @bus.read_byte(addr)
1487
+ end
1488
+
1489
+ def read_word(addr)
1490
+ @bus.read_word(addr)
1491
+ end
1492
+
1493
+ def write_byte(addr, value)
1494
+ @bus.write_byte(addr, value)
1495
+ end
1496
+
1497
+ def write_word(addr, value)
1498
+ @bus.write_word(addr, value)
1499
+ end
1500
+
1501
+ def read_byte_and_advance_pc
1502
+ byte = read_byte(@pc)
1503
+ increment_pc
1504
+ byte
1505
+ end
1506
+
1507
+ def read_word_and_advance_pc
1508
+ word = read_word(@pc)
1509
+ increment_pc_by_byte(2)
1510
+ word
1511
+ end
1512
+
160
1513
  def print_log(opcode)
161
- puts "OP: 0x#{'%02x' % opcode}, PC: 0x#{'%04x' % @pc}, SP: 0x#{'%04x' % @sp}, A: 0x#{'%02x' % @a}, B: 0x#{'%02x' % @b}, C: 0x#{'%02x' % @c}, D: 0x#{'%02x' % @d}, E: 0x#{'%02x' % @e}, H: 0x#{'%02x' % @h}, L: 0x#{'%02x' % @l}, F: 0x#{'%02x' % @f}"
1514
+ puts "OP: 0x#{'%02x' % opcode}, PC: 0x#{'%04x' % @pc}, SP: 0x#{'%04x' % @sp}, A: 0x#{'%02x' % @a.value}, B: 0x#{'%02x' % @b.value}, C: 0x#{'%02x' % @c.value}, D: 0x#{'%02x' % @d.value}, E: 0x#{'%02x' % @e.value}, H: 0x#{'%02x' % @h.value}, L: 0x#{'%02x' % @l.value}, F: 0x#{'%02x' % @f.value}"
162
1515
  end
163
1516
 
164
- def get_flags
1517
+ def flags
165
1518
  {
166
- z: @f[7] == 1,
167
- n: @f[6] == 1,
168
- h: @f[5] == 1,
169
- c: @f[4] == 1
1519
+ z: @f.value[7] == 1,
1520
+ n: @f.value[6] == 1,
1521
+ h: @f.value[5] == 1,
1522
+ c: @f.value[4] == 1
170
1523
  }
171
1524
  end
172
1525
 
173
- def update_flags(z:, n:, h:, c:)
174
- @f = 0x00
175
- @f |= 0x80 if z
176
- @f |= 0x40 if n
177
- @f |= 0x20 if h
178
- @f |= 0x10 if c
1526
+ def update_flags(z: flags[:z], n: flags[:n], h: flags[:h], c: flags[:c])
1527
+ @f.value = 0x00
1528
+ @f.value |= 0x80 if z
1529
+ @f.value |= 0x40 if n
1530
+ @f.value |= 0x20 if h
1531
+ @f.value |= 0x10 if c
179
1532
  end
180
1533
 
181
1534
  def bool_to_integer(bool)
@@ -183,12 +1536,212 @@ module Rubyboy
183
1536
  end
184
1537
 
185
1538
  def increment_pc
186
- @pc += 1
1539
+ increment_pc_by_byte(1)
187
1540
  end
188
1541
 
189
- def to_signed_byte(byte)
190
- byte = -((byte ^ 0xff) + 1) if byte[7] == 1
191
- byte
1542
+ def increment_pc_by_byte(byte)
1543
+ @pc += byte
1544
+ end
1545
+
1546
+ def convert_to_twos_complement(byte)
1547
+ byte &= 0xff
1548
+ byte > 127 ? byte - 256 : byte
1549
+ end
1550
+
1551
+ def ld8(x, y)
1552
+ x.value = y.value
1553
+ end
1554
+
1555
+ def add8(x, y)
1556
+ hflag = (x.value & 0x0f) + (y.value & 0x0f) > 0x0f
1557
+ cflag = x.value + y.value > 0xff
1558
+ x.value += y.value
1559
+ update_flags(
1560
+ z: x.value.zero?,
1561
+ n: false,
1562
+ h: hflag,
1563
+ c: cflag
1564
+ )
1565
+ end
1566
+
1567
+ def adc8(x, y)
1568
+ c_value = bool_to_integer(flags[:c])
1569
+ hflag = (x.value & 0x0f) + (y.value & 0x0f) + c_value > 0x0f
1570
+ cflag = x.value + y.value + c_value > 0xff
1571
+ x.value += y.value + c_value
1572
+ update_flags(
1573
+ z: x.value.zero?,
1574
+ n: false,
1575
+ h: hflag,
1576
+ c: cflag
1577
+ )
1578
+ end
1579
+
1580
+ def sub8(x)
1581
+ hflag = (x.value & 0x0f) > (@a.value & 0x0f)
1582
+ cflag = x.value > @a.value
1583
+ @a.value -= x.value
1584
+ update_flags(
1585
+ z: @a.value.zero?,
1586
+ n: true,
1587
+ h: hflag,
1588
+ c: cflag
1589
+ )
1590
+ end
1591
+
1592
+ def sbc8(x)
1593
+ c_value = bool_to_integer(flags[:c])
1594
+ hflag = (x.value & 0x0f) + c_value > (@a.value & 0x0f)
1595
+ cflag = x.value + c_value > @a.value
1596
+ @a.value -= x.value + c_value
1597
+ update_flags(
1598
+ z: @a.value.zero?,
1599
+ n: true,
1600
+ h: hflag,
1601
+ c: cflag
1602
+ )
1603
+ end
1604
+
1605
+ def and8(x)
1606
+ @a.value &= x.value
1607
+ update_flags(
1608
+ z: @a.value.zero?,
1609
+ n: false,
1610
+ h: true,
1611
+ c: false
1612
+ )
1613
+ end
1614
+
1615
+ def or8(x)
1616
+ @a.value |= x.value
1617
+ update_flags(
1618
+ z: @a.value.zero?,
1619
+ n: false,
1620
+ h: false,
1621
+ c: false
1622
+ )
1623
+ end
1624
+
1625
+ def xor8(x)
1626
+ @a.value ^= x.value
1627
+ update_flags(
1628
+ z: @a.value.zero?,
1629
+ n: false,
1630
+ h: false,
1631
+ c: false
1632
+ )
1633
+ end
1634
+
1635
+ def cp8(x)
1636
+ hflag = (x.value & 0x0f) > (@a.value & 0x0f)
1637
+ cflag = x.value > @a.value
1638
+ update_flags(
1639
+ z: @a.value == x.value,
1640
+ n: true,
1641
+ h: hflag,
1642
+ c: cflag
1643
+ )
1644
+ end
1645
+
1646
+ def rlc8(x)
1647
+ x.value = (x.value << 1) | (x.value >> 7)
1648
+ update_flags(
1649
+ z: x.value.zero?,
1650
+ n: false,
1651
+ h: false,
1652
+ c: x.value[0] == 1
1653
+ )
1654
+ end
1655
+
1656
+ def rrc8(x)
1657
+ x.value = (x.value >> 1) | (x.value << 7)
1658
+ update_flags(
1659
+ z: x.value.zero?,
1660
+ n: false,
1661
+ h: false,
1662
+ c: x.value[7] == 1
1663
+ )
1664
+ end
1665
+
1666
+ def rl8(x)
1667
+ cflag = x.value[7] == 1
1668
+ x.value = (x.value << 1) | bool_to_integer(flags[:c])
1669
+ update_flags(
1670
+ z: x.value.zero?,
1671
+ n: false,
1672
+ h: false,
1673
+ c: cflag
1674
+ )
1675
+ end
1676
+
1677
+ def rr8(x)
1678
+ cflag = x.value[0] == 1
1679
+ x.value = (x.value >> 1) | (bool_to_integer(flags[:c]) << 7)
1680
+ update_flags(
1681
+ z: x.value.zero?,
1682
+ n: false,
1683
+ h: false,
1684
+ c: cflag
1685
+ )
1686
+ end
1687
+
1688
+ def sla8(x)
1689
+ cflag = x.value[7] == 1
1690
+ x.value <<= 1
1691
+ update_flags(
1692
+ z: x.value.zero?,
1693
+ n: false,
1694
+ h: false,
1695
+ c: cflag
1696
+ )
1697
+ end
1698
+
1699
+ def sra8(x)
1700
+ cflag = x.value[0] == 1
1701
+ x.value = (x.value >> 1) | (x.value[7] << 7)
1702
+ update_flags(
1703
+ z: x.value.zero?,
1704
+ n: false,
1705
+ h: false,
1706
+ c: cflag
1707
+ )
1708
+ end
1709
+
1710
+ def swap8(x)
1711
+ x.value = ((x.value & 0x0f) << 4) | ((x.value & 0xf0) >> 4)
1712
+ update_flags(
1713
+ z: x.value.zero?,
1714
+ n: false,
1715
+ h: false,
1716
+ c: false
1717
+ )
1718
+ end
1719
+
1720
+ def srl8(x)
1721
+ cflag = x.value[0] == 1
1722
+ x.value >>= 1
1723
+ update_flags(
1724
+ z: x.value.zero?,
1725
+ n: false,
1726
+ h: false,
1727
+ c: cflag
1728
+ )
1729
+ end
1730
+
1731
+ def bit8(n, x)
1732
+ update_flags(
1733
+ z: x.value[n].zero?,
1734
+ n: false,
1735
+ h: true
1736
+ )
1737
+ end
1738
+
1739
+ def set8(n, x)
1740
+ x.value |= (1 << n)
1741
+ end
1742
+
1743
+ def res8(n, x)
1744
+ x.value &= ((~(1 << n)) & 0xff)
192
1745
  end
193
1746
  end
194
1747
  end