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.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/.travis.yml +5 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +39 -0
- data/Rakefile +6 -0
- data/bin/display +9 -0
- data/bin/gbrb +12 -0
- data/gbrb.gemspec +26 -0
- data/lib/gbrb.rb +9 -0
- data/lib/gbrb/bios +256 -0
- data/lib/gbrb/cartridge.rb +15 -0
- data/lib/gbrb/cpu.rb +7 -0
- data/lib/gbrb/cpu/concatenated_register.rb +44 -0
- data/lib/gbrb/cpu/flags_register.rb +42 -0
- data/lib/gbrb/cpu/instruction.rb +648 -0
- data/lib/gbrb/cpu/register.rb +44 -0
- data/lib/gbrb/cpu/register_ensemble.rb +59 -0
- data/lib/gbrb/cpu/z80.rb +584 -0
- data/lib/gbrb/gb.rb +125 -0
- data/lib/gbrb/graphics.rb +14 -0
- data/lib/gbrb/graphics/gpu.rb +196 -0
- data/lib/gbrb/graphics/mode_clock.rb +51 -0
- data/lib/gbrb/graphics/screen_client.rb +31 -0
- data/lib/gbrb/graphics/screen_server.rb +90 -0
- data/lib/gbrb/mmu.rb +96 -0
- data/lib/gbrb/version.rb +3 -0
- data/misc/parse_tiles +27 -0
- data/perf/cpu_perf_spec.rb +23 -0
- data/spec/gbrb/cartridge_spec.rb +19 -0
- data/spec/gbrb/cpu/concatenated_register_spec.rb +36 -0
- data/spec/gbrb/cpu/flags_register_spec.rb +91 -0
- data/spec/gbrb/cpu/instruction_spec.rb +283 -0
- data/spec/gbrb/cpu/register_ensemble_spec.rb +84 -0
- data/spec/gbrb/cpu/register_spec.rb +86 -0
- data/spec/gbrb/cpu/z80_spec.rb +2534 -0
- data/spec/gbrb/graphics/mode_clock_spec.rb +82 -0
- data/spec/gbrb/mmu_spec.rb +61 -0
- data/spec/gbrb/version_spec.rb +10 -0
- data/spec/spec_helper.rb +4 -0
- metadata +154 -0
@@ -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
|
data/lib/gbrb/cpu/z80.rb
ADDED
@@ -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
|