rubyboy 0.4.0 → 1.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 +4 -4
- data/.rubocop.yml +3 -0
- data/CHANGELOG.md +12 -0
- data/README.md +7 -15
- data/exe/rubyboy +17 -0
- data/lib/bench.rb +26 -0
- data/lib/rubyboy/bus.rb +1 -8
- data/lib/rubyboy/cartridge/mbc1.rb +1 -1
- data/lib/rubyboy/cpu.rb +1016 -1501
- data/lib/rubyboy/interrupt.rb +12 -4
- data/lib/rubyboy/joypad.rb +4 -4
- data/lib/rubyboy/operand/direct16.rb +13 -0
- data/lib/rubyboy/operand/direct8.rb +13 -0
- data/lib/rubyboy/operand/hl_dec.rb +11 -0
- data/lib/rubyboy/operand/hl_inc.rb +11 -0
- data/lib/rubyboy/operand/immediate16.rb +13 -0
- data/lib/rubyboy/operand/immediate8.rb +13 -0
- data/lib/rubyboy/operand/indirect.rb +13 -0
- data/lib/rubyboy/operand/register16.rb +13 -0
- data/lib/rubyboy/operand/register8.rb +13 -0
- data/lib/rubyboy/operand.rb +12 -0
- data/lib/rubyboy/ppu.rb +68 -40
- data/lib/rubyboy/register.rb +0 -2
- data/lib/rubyboy/registers.rb +80 -0
- data/lib/rubyboy/rom.rb +1 -30
- data/lib/rubyboy/timer.rb +4 -5
- data/lib/rubyboy/version.rb +1 -1
- data/lib/rubyboy.rb +23 -9
- metadata +18 -4
data/lib/rubyboy/interrupt.rb
CHANGED
@@ -1,10 +1,14 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'json'
|
4
|
-
|
5
3
|
module Rubyboy
|
6
4
|
class Interrupt
|
7
|
-
|
5
|
+
INTERRUPTS = {
|
6
|
+
vblank: 0,
|
7
|
+
lcd: 1,
|
8
|
+
timer: 2,
|
9
|
+
serial: 3,
|
10
|
+
joypad: 4
|
11
|
+
}.freeze
|
8
12
|
|
9
13
|
def initialize
|
10
14
|
@ie = 0
|
@@ -34,7 +38,11 @@ module Rubyboy
|
|
34
38
|
end
|
35
39
|
|
36
40
|
def request(interrupt)
|
37
|
-
@if |= interrupt
|
41
|
+
@if |= (1 << INTERRUPTS[interrupt])
|
42
|
+
end
|
43
|
+
|
44
|
+
def reset_flag(i)
|
45
|
+
@if &= (~(1 << i)) & 0xff
|
38
46
|
end
|
39
47
|
end
|
40
48
|
end
|
data/lib/rubyboy/joypad.rb
CHANGED
@@ -13,8 +13,8 @@ module Rubyboy
|
|
13
13
|
raise "not implemented: write_byte #{addr}" unless addr == 0xff00
|
14
14
|
|
15
15
|
res = @mode | 0xcf
|
16
|
-
res &= @direction if @mode[4]
|
17
|
-
res &= @action if @mode[5]
|
16
|
+
res &= @direction if @mode[4] == 0
|
17
|
+
res &= @action if @mode[5] == 0
|
18
18
|
|
19
19
|
res
|
20
20
|
end
|
@@ -29,13 +29,13 @@ module Rubyboy
|
|
29
29
|
def direction_button(button)
|
30
30
|
@direction = button | 0xf0
|
31
31
|
|
32
|
-
@interupt.request(
|
32
|
+
@interupt.request(:joypad) if button < 0b1111
|
33
33
|
end
|
34
34
|
|
35
35
|
def action_button(button)
|
36
36
|
@action = button | 0xf0
|
37
37
|
|
38
|
-
@interupt.request(
|
38
|
+
@interupt.request(:joypad) if button < 0b1111
|
39
39
|
end
|
40
40
|
end
|
41
41
|
end
|
data/lib/rubyboy/ppu.rb
CHANGED
@@ -11,6 +11,33 @@ module Rubyboy
|
|
11
11
|
drawing: 3
|
12
12
|
}.freeze
|
13
13
|
|
14
|
+
LCDC = {
|
15
|
+
bg_window_enable: 0,
|
16
|
+
sprite_enable: 1,
|
17
|
+
sprite_size: 2,
|
18
|
+
bg_tile_map_area: 3,
|
19
|
+
bg_window_tile_data_area: 4,
|
20
|
+
window_enable: 5,
|
21
|
+
window_tile_map_area: 6,
|
22
|
+
lcd_ppu_enable: 7
|
23
|
+
}.freeze
|
24
|
+
|
25
|
+
STAT = {
|
26
|
+
ly_eq_lyc: 2,
|
27
|
+
hblank: 3,
|
28
|
+
vblank: 4,
|
29
|
+
oam_scan: 5,
|
30
|
+
lyc: 6
|
31
|
+
}.freeze
|
32
|
+
|
33
|
+
SPRITE_FLAGS = {
|
34
|
+
bank: 3,
|
35
|
+
dmg_palette: 4,
|
36
|
+
x_flip: 5,
|
37
|
+
y_flip: 6,
|
38
|
+
priority: 7
|
39
|
+
}.freeze
|
40
|
+
|
14
41
|
LCD_WIDTH = 160
|
15
42
|
LCD_HEIGHT = 144
|
16
43
|
|
@@ -90,8 +117,6 @@ module Rubyboy
|
|
90
117
|
# ly is read only
|
91
118
|
when 0xff45
|
92
119
|
@lyc = value
|
93
|
-
when 0xff46
|
94
|
-
# dma
|
95
120
|
when 0xff47
|
96
121
|
@bgp = value
|
97
122
|
when 0xff48
|
@@ -106,7 +131,7 @@ module Rubyboy
|
|
106
131
|
end
|
107
132
|
|
108
133
|
def step(cycles)
|
109
|
-
return false if @lcdc[
|
134
|
+
return false if @lcdc[LCDC[:lcd_ppu_enable]] == 0
|
110
135
|
|
111
136
|
res = false
|
112
137
|
@cycles += cycles
|
@@ -124,7 +149,7 @@ module Rubyboy
|
|
124
149
|
render_sprites
|
125
150
|
@cycles -= DRAWING_CYCLES
|
126
151
|
@mode = MODE[:hblank]
|
127
|
-
@interrupt.request(
|
152
|
+
@interrupt.request(:lcd) if @stat[STAT[:hblank]] == 1
|
128
153
|
end
|
129
154
|
when MODE[:hblank]
|
130
155
|
if @cycles >= HBLANK_CYCLES
|
@@ -134,11 +159,11 @@ module Rubyboy
|
|
134
159
|
|
135
160
|
if @ly == LCD_HEIGHT
|
136
161
|
@mode = MODE[:vblank]
|
137
|
-
@interrupt.request(
|
138
|
-
@interrupt.request(
|
162
|
+
@interrupt.request(:vblank)
|
163
|
+
@interrupt.request(:lcd) if @stat[STAT[:vblank]] == 1
|
139
164
|
else
|
140
165
|
@mode = MODE[:oam_scan]
|
141
|
-
@interrupt.request(
|
166
|
+
@interrupt.request(:lcd) if @stat[STAT[:oam_scan]] == 1
|
142
167
|
end
|
143
168
|
end
|
144
169
|
when MODE[:vblank]
|
@@ -152,7 +177,7 @@ module Rubyboy
|
|
152
177
|
@wly = 0
|
153
178
|
handle_ly_eq_lyc
|
154
179
|
@mode = MODE[:oam_scan]
|
155
|
-
@interrupt.request(
|
180
|
+
@interrupt.request(:lcd) if @stat[STAT[:oam_scan]] == 1
|
156
181
|
res = true
|
157
182
|
end
|
158
183
|
end
|
@@ -162,30 +187,34 @@ module Rubyboy
|
|
162
187
|
end
|
163
188
|
|
164
189
|
def render_bg
|
165
|
-
return if @lcdc[0
|
190
|
+
return if @lcdc[LCDC[:bg_window_enable]] == 0
|
166
191
|
|
167
192
|
y = (@ly + @scy) % 256
|
193
|
+
tile_map_addr = @lcdc[LCDC[:bg_tile_map_area]] == 0 ? 0x1800 : 0x1c00
|
194
|
+
tile_map_addr += (y / 8) * 32
|
168
195
|
LCD_WIDTH.times do |i|
|
169
196
|
x = (i + @scx) % 256
|
170
|
-
tile_index = get_tile_index(
|
171
|
-
pixel = get_pixel(tile_index, x, y)
|
197
|
+
tile_index = get_tile_index(tile_map_addr + (x / 8))
|
198
|
+
pixel = get_pixel(tile_index << 4, 7 - (x % 8), (y % 8) * 2)
|
172
199
|
@buffer[@ly * LCD_WIDTH + i] = get_color(@bgp, pixel)
|
173
200
|
@bg_pixels[i] = pixel
|
174
201
|
end
|
175
202
|
end
|
176
203
|
|
177
204
|
def render_window
|
178
|
-
return if @lcdc[
|
205
|
+
return if @lcdc[LCDC[:bg_window_enable]] == 0 || @lcdc[LCDC[:window_enable]] == 0 || @ly < @wy
|
179
206
|
|
180
207
|
rendered = false
|
181
208
|
y = @wly
|
209
|
+
tile_map_addr = @lcdc[LCDC[:window_tile_map_area]] == 0 ? 0x1800 : 0x1c00
|
210
|
+
tile_map_addr += (y / 8) * 32
|
182
211
|
LCD_WIDTH.times do |i|
|
183
212
|
next if i < @wx - 7
|
184
213
|
|
185
214
|
rendered = true
|
186
215
|
x = i - (@wx - 7)
|
187
|
-
tile_index = get_tile_index(
|
188
|
-
pixel = get_pixel(tile_index, x, y)
|
216
|
+
tile_index = get_tile_index(tile_map_addr + (x / 8))
|
217
|
+
pixel = get_pixel(tile_index << 4, 7 - (x % 8), (y % 8) * 2)
|
189
218
|
@buffer[@ly * LCD_WIDTH + i] = get_color(@bgp, pixel)
|
190
219
|
@bg_pixels[i] = pixel
|
191
220
|
end
|
@@ -193,40 +222,41 @@ module Rubyboy
|
|
193
222
|
end
|
194
223
|
|
195
224
|
def render_sprites
|
196
|
-
return if @lcdc[
|
225
|
+
return if @lcdc[LCDC[:sprite_enable]] == 0
|
197
226
|
|
198
|
-
sprite_height = @lcdc[
|
227
|
+
sprite_height = @lcdc[LCDC[:sprite_size]] == 0 ? 8 : 16
|
228
|
+
sprites = []
|
229
|
+
cnt = 0
|
199
230
|
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
tile_index: sprite_attr[2],
|
205
|
-
flags: sprite_attr[3]
|
206
|
-
}
|
207
|
-
next if sprite[:y] > @ly || sprite[:y] + sprite_height <= @ly
|
231
|
+
@oam.each_slice(4) do |y, x, tile_index, flags|
|
232
|
+
y = (y - 16) % 256
|
233
|
+
x = (x - 8) % 256
|
234
|
+
next if y > @ly || y + sprite_height <= @ly
|
208
235
|
|
209
|
-
|
236
|
+
sprites << { y:, x:, tile_index:, flags: }
|
237
|
+
cnt += 1
|
238
|
+
break if cnt == 10
|
210
239
|
end
|
211
|
-
sprites = sprites.
|
240
|
+
sprites = sprites.sort_by.with_index { |sprite, i| [-sprite[:x], -i] }
|
212
241
|
|
213
242
|
sprites.each do |sprite|
|
214
|
-
|
243
|
+
flags = sprite[:flags]
|
244
|
+
pallet = flags[SPRITE_FLAGS[:dmg_palette]] == 0 ? @obp0 : @obp1
|
215
245
|
tile_index = sprite[:tile_index]
|
216
246
|
tile_index &= 0xfe if sprite_height == 16
|
217
247
|
y = (@ly - sprite[:y]) % 256
|
218
|
-
y = sprite_height - y - 1 if
|
248
|
+
y = sprite_height - y - 1 if flags[SPRITE_FLAGS[:y_flip]] == 1
|
219
249
|
tile_index = (tile_index + 1) % 256 if y >= 8
|
220
250
|
y %= 8
|
221
251
|
|
222
252
|
8.times do |x|
|
223
|
-
x_flipped =
|
253
|
+
x_flipped = flags[SPRITE_FLAGS[:x_flip]] == 1 ? 7 - x : x
|
224
254
|
|
225
|
-
pixel = get_pixel(tile_index, x_flipped, y)
|
255
|
+
pixel = get_pixel(tile_index << 4, 7 - x_flipped, (y % 8) * 2)
|
226
256
|
i = (sprite[:x] + x) % 256
|
227
257
|
|
228
|
-
next if pixel
|
229
|
-
next if
|
258
|
+
next if pixel == 0 || i >= LCD_WIDTH
|
259
|
+
next if flags[SPRITE_FLAGS[:priority]] == 1 && @bg_pixels[i] != 0
|
230
260
|
|
231
261
|
@buffer[@ly * LCD_WIDTH + i] = get_color(pallet, pixel)
|
232
262
|
end
|
@@ -235,15 +265,13 @@ module Rubyboy
|
|
235
265
|
|
236
266
|
private
|
237
267
|
|
238
|
-
def get_tile_index(
|
239
|
-
|
240
|
-
|
241
|
-
tile_index = @vram[tile_map_addr + tile_map_index]
|
242
|
-
@lcdc[4].zero? ? to_signed_byte(tile_index) + 256 : tile_index
|
268
|
+
def get_tile_index(tile_map_addr)
|
269
|
+
tile_index = @vram[tile_map_addr]
|
270
|
+
@lcdc[LCDC[:bg_window_tile_data_area]] == 0 ? to_signed_byte(tile_index) + 256 : tile_index
|
243
271
|
end
|
244
272
|
|
245
|
-
def get_pixel(tile_index,
|
246
|
-
@vram[tile_index
|
273
|
+
def get_pixel(tile_index, c, r)
|
274
|
+
@vram[tile_index + r][c] + (@vram[tile_index + r + 1][c] << 1)
|
247
275
|
end
|
248
276
|
|
249
277
|
def get_color(pallet, pixel)
|
@@ -263,7 +291,7 @@ module Rubyboy
|
|
263
291
|
def handle_ly_eq_lyc
|
264
292
|
if @ly == @lyc
|
265
293
|
@stat |= 0x04
|
266
|
-
@interrupt.request(
|
294
|
+
@interrupt.request(:lcd) if @stat[STAT[:lyc]] == 1
|
267
295
|
else
|
268
296
|
@stat &= 0xfb
|
269
297
|
end
|
data/lib/rubyboy/register.rb
CHANGED
@@ -0,0 +1,80 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Rubyboy
|
4
|
+
class Registers
|
5
|
+
attr_reader :value
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
@a = 0x01
|
9
|
+
@b = 0x00
|
10
|
+
@c = 0x13
|
11
|
+
@d = 0x00
|
12
|
+
@e = 0xd8
|
13
|
+
@h = 0x01
|
14
|
+
@l = 0x4d
|
15
|
+
@f = 0xb0
|
16
|
+
end
|
17
|
+
|
18
|
+
def read8(register)
|
19
|
+
case register
|
20
|
+
when :a then @a
|
21
|
+
when :b then @b
|
22
|
+
when :c then @c
|
23
|
+
when :d then @d
|
24
|
+
when :e then @e
|
25
|
+
when :h then @h
|
26
|
+
when :l then @l
|
27
|
+
when :f then @f
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def write8(register, value)
|
32
|
+
value &= 0xff
|
33
|
+
case register
|
34
|
+
when :a then @a = value
|
35
|
+
when :b then @b = value
|
36
|
+
when :c then @c = value
|
37
|
+
when :d then @d = value
|
38
|
+
when :e then @e = value
|
39
|
+
when :h then @h = value
|
40
|
+
when :l then @l = value
|
41
|
+
when :f then @f = value & 0xf0
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def read16(register)
|
46
|
+
case register
|
47
|
+
when :af then (@a << 8) | @f
|
48
|
+
when :bc then (@b << 8) | @c
|
49
|
+
when :de then (@d << 8) | @e
|
50
|
+
when :hl then (@h << 8) | @l
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def write16(register, value)
|
55
|
+
value &= 0xffff
|
56
|
+
case register
|
57
|
+
when :af
|
58
|
+
@a = (value >> 8) & 0xff
|
59
|
+
@f = value & 0xf0
|
60
|
+
when :bc
|
61
|
+
@b = (value >> 8) & 0xff
|
62
|
+
@c = value & 0xff
|
63
|
+
when :de
|
64
|
+
@d = (value >> 8) & 0xff
|
65
|
+
@e = value & 0xff
|
66
|
+
when :hl
|
67
|
+
@h = (value >> 8) & 0xff
|
68
|
+
@l = value & 0xff
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def increment16(register)
|
73
|
+
write16(register, read16(register) + 1)
|
74
|
+
end
|
75
|
+
|
76
|
+
def decrement16(register)
|
77
|
+
write16(register, read16(register) - 1)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
data/lib/rubyboy/rom.rb
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
module Rubyboy
|
4
4
|
class Rom
|
5
|
-
|
5
|
+
attr_reader :data, :entroy_point, :logo, :title, :new_licensee_code, :sgb_flag, :cartridge_type, :rom_size, :ram_size, :destination_code, :old_licensee_code, :mask_rom_version_number, :header_checksum, :global_checksum
|
6
6
|
|
7
7
|
LOGO_DUMP = %w[
|
8
8
|
CE ED 66 66 CC 0D 00 0B 03 73 00 83 00 0C 00 0D
|
@@ -18,49 +18,20 @@ module Rubyboy
|
|
18
18
|
private
|
19
19
|
|
20
20
|
def load_data
|
21
|
-
# The Cartridge Header
|
22
|
-
# see: https://gbdev.io/pandocs/The_Cartridge_Header.html
|
23
|
-
|
24
|
-
# 0x100 - 0x103: Entry Point
|
25
21
|
@entroy_point = @data[0x100..0x103]
|
26
|
-
# p data[0x102..0x103].pack('C*').unpack('v').first
|
27
|
-
|
28
|
-
# 0x104 - 0x133: Nintendo Logo
|
29
22
|
@logo = @data[0x104..0x133]
|
30
23
|
raise 'logo is not match' unless @logo == LOGO_DUMP
|
31
24
|
|
32
|
-
# 0x134 - 0x143: Title
|
33
25
|
@title = @data[0x134..0x143]
|
34
|
-
# p data[0x134..0x143].pack('C*').strip
|
35
|
-
|
36
|
-
# 0x144 - 0x145: New Licensee Code
|
37
26
|
@new_licensee_code = @data[0x144..0x145]
|
38
|
-
|
39
|
-
# 0x146: SGB Flag
|
40
27
|
@sgb_flag = @data[0x146]
|
41
|
-
|
42
|
-
# 0x147: Cartridge Type
|
43
28
|
@cartridge_type = @data[0x147]
|
44
|
-
|
45
|
-
# 0x148: ROM Size
|
46
29
|
@rom_size = @data[0x148]
|
47
|
-
|
48
|
-
# 0x149: RAM Size
|
49
30
|
@ram_size = @data[0x149]
|
50
|
-
|
51
|
-
# 0x14A: Destination Code
|
52
31
|
@destination_code = @data[0x14A]
|
53
|
-
|
54
|
-
# 0x14B: Old Licensee Code
|
55
32
|
@old_licensee_code = @data[0x14B]
|
56
|
-
|
57
|
-
# 0x14C: Mask ROM Version number
|
58
33
|
@mask_rom_version_number = @data[0x14C]
|
59
|
-
|
60
|
-
# 0x14D: Header Checksum
|
61
34
|
@header_checksum = @data[0x14D]
|
62
|
-
|
63
|
-
# 0x14E - 0x14F: Global Checksum
|
64
35
|
@global_checksum = @data[0x14E..0x14F]
|
65
36
|
end
|
66
37
|
end
|
data/lib/rubyboy/timer.rb
CHANGED
@@ -1,7 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'json'
|
4
|
-
|
5
3
|
module Rubyboy
|
6
4
|
class Timer
|
7
5
|
def initialize(interrupt)
|
@@ -21,7 +19,7 @@ module Rubyboy
|
|
21
19
|
@div += after_cycles / 256 - before_cycles / 256
|
22
20
|
@div &= 0xffff
|
23
21
|
|
24
|
-
return if @tac[2]
|
22
|
+
return if @tac[2] == 0
|
25
23
|
|
26
24
|
divider = case @tac & 0b11
|
27
25
|
when 0b00 then 1024
|
@@ -35,8 +33,8 @@ module Rubyboy
|
|
35
33
|
|
36
34
|
return if @tima < 256
|
37
35
|
|
38
|
-
@tima
|
39
|
-
@interrupt.request(
|
36
|
+
@tima = @tma
|
37
|
+
@interrupt.request(:timer)
|
40
38
|
end
|
41
39
|
|
42
40
|
def read_byte(byte)
|
@@ -56,6 +54,7 @@ module Rubyboy
|
|
56
54
|
case byte
|
57
55
|
when 0xff04
|
58
56
|
@div = 0
|
57
|
+
@cycles = 0
|
59
58
|
when 0xff05
|
60
59
|
@tima = value
|
61
60
|
when 0xff06
|
data/lib/rubyboy/version.rb
CHANGED
data/lib/rubyboy.rb
CHANGED
@@ -1,8 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'raylib'
|
4
|
-
require 'benchmark'
|
5
|
-
require_relative 'rubyboy/version'
|
6
4
|
require_relative 'rubyboy/bus'
|
7
5
|
require_relative 'rubyboy/cpu'
|
8
6
|
require_relative 'rubyboy/ppu'
|
@@ -10,29 +8,33 @@ require_relative 'rubyboy/rom'
|
|
10
8
|
require_relative 'rubyboy/timer'
|
11
9
|
require_relative 'rubyboy/lcd'
|
12
10
|
require_relative 'rubyboy/joypad'
|
11
|
+
require_relative 'rubyboy/interrupt'
|
13
12
|
|
14
13
|
module Rubyboy
|
15
14
|
class Console
|
16
15
|
include Raylib
|
17
16
|
|
18
|
-
def initialize(
|
17
|
+
def initialize(rom_path)
|
19
18
|
load_raylib
|
19
|
+
rom_data = File.open(rom_path, 'r') { _1.read.bytes }
|
20
20
|
rom = Rom.new(rom_data)
|
21
21
|
interrupt = Interrupt.new
|
22
22
|
@ppu = Ppu.new(interrupt)
|
23
23
|
@timer = Timer.new(interrupt)
|
24
24
|
@joypad = Joypad.new(interrupt)
|
25
25
|
@bus = Bus.new(@ppu, rom, @timer, interrupt, @joypad)
|
26
|
-
@cpu = Cpu.new(@bus)
|
26
|
+
@cpu = Cpu.new(@bus, interrupt)
|
27
27
|
@lcd = Lcd.new
|
28
28
|
end
|
29
29
|
|
30
30
|
def start
|
31
31
|
until @lcd.window_should_close?
|
32
|
-
key_input_check
|
33
32
|
cycles = @cpu.exec
|
34
33
|
@timer.step(cycles)
|
35
|
-
|
34
|
+
if @ppu.step(cycles)
|
35
|
+
draw
|
36
|
+
key_input_check
|
37
|
+
end
|
36
38
|
end
|
37
39
|
@lcd.close_window
|
38
40
|
rescue StandardError => e
|
@@ -40,6 +42,21 @@ module Rubyboy
|
|
40
42
|
raise e
|
41
43
|
end
|
42
44
|
|
45
|
+
def bench
|
46
|
+
cnt = 0
|
47
|
+
start_time = Time.now
|
48
|
+
while cnt < 1500
|
49
|
+
cycles = @cpu.exec
|
50
|
+
@timer.step(cycles)
|
51
|
+
if @ppu.step(cycles)
|
52
|
+
key_input_check
|
53
|
+
cnt += 1
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
Time.now - start_time
|
58
|
+
end
|
59
|
+
|
43
60
|
private
|
44
61
|
|
45
62
|
def draw
|
@@ -78,6 +95,3 @@ module Rubyboy
|
|
78
95
|
end
|
79
96
|
end
|
80
97
|
end
|
81
|
-
|
82
|
-
rom_data = File.open(File.expand_path('roms/bgbtest.gb', __dir__), 'r') { _1.read.bytes }
|
83
|
-
Rubyboy::Console.new(rom_data).start
|