Skip to content

Commit

Permalink
Merge pull request #12 from sacckey/refactoring-v1.1.0
Browse files Browse the repository at this point in the history
Refactoring v1.1.0
  • Loading branch information
sacckey authored Dec 28, 2023
2 parents 37f086f + c9756f7 commit 449044b
Show file tree
Hide file tree
Showing 13 changed files with 616 additions and 554 deletions.
3 changes: 3 additions & 0 deletions .rubocop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,6 @@ Style/FormatString:

Style/NumericLiterals:
Enabled: false

Style/NumericPredicate:
EnforcedStyle: comparison
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
## [Unreleased]

## [1.1.0] - 2023-12-28

- Add bench option
- Improve speed by refactoring

## [1.0.0] - 2023-12-04

- Fix halt and timer
Expand Down
2 changes: 2 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,6 @@ gem 'rake', '~> 13.0'
group :development, :test do
gem 'rspec', '~> 3.12'
gem 'rubocop', '~> 1.57'

gem 'stackprof', '~> 0.2.25'
end
4 changes: 3 additions & 1 deletion Gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
PATH
remote: .
specs:
rubyboy (1.0.0)
rubyboy (1.1.0)
raylib-bindings (~> 0.5.7)

GEM
Expand Down Expand Up @@ -54,6 +54,7 @@ GEM
rubocop-ast (1.29.0)
parser (>= 3.2.1.0)
ruby-progressbar (1.13.0)
stackprof (0.2.25)
unicode-display_width (2.5.0)

PLATFORMS
Expand All @@ -65,6 +66,7 @@ DEPENDENCIES
rspec (~> 3.12)
rubocop (~> 1.57)
rubyboy!
stackprof (~> 0.2.25)

BUNDLED WITH
2.4.20
14 changes: 12 additions & 2 deletions exe/rubyboy
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,16 @@
# frozen_string_literal: true

require 'rubyboy'
require 'bench'

rom_path = ARGV[0]
Rubyboy::Console.new(rom_path).start
arg = ARGV[0]

puts "yjit: #{RubyVM::YJIT.enabled?}"

if arg == 'bench'
Rubyboy::Bench.new.bench
elsif arg == 'stackprof'
Rubyboy::Bench.new.stackprof
else
Rubyboy::Console.new(arg).start
end
26 changes: 26 additions & 0 deletions lib/bench.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# frozen_string_literal: true

require 'stackprof'
require_relative 'rubyboy'

module Rubyboy
class Bench
def stackprof
StackProf.run(mode: :cpu, out: 'stackprof-cpu-myapp.dump', raw: true) do
Rubyboy::Console.new('lib/roms/tobu.gb').bench
end
end

def bench
bench_cnt = 3
time_sum = 0
bench_cnt.times do |i|
time = Rubyboy::Console.new('lib/roms/tobu.gb').bench
time_sum += time
puts "#{i + 1}: #{time} sec"
end

puts "FPS: #{1500 * bench_cnt / time_sum}"
end
end
end
15 changes: 15 additions & 0 deletions lib/rubyboy.rb
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,21 @@ def start
raise e
end

def bench
cnt = 0
start_time = Time.now
while cnt < 1500
cycles = @cpu.exec
@timer.step(cycles)
if @ppu.step(cycles)
key_input_check
cnt += 1
end
end

Time.now - start_time
end

private

def draw
Expand Down
2 changes: 1 addition & 1 deletion lib/rubyboy/cartridge/mbc1.rb
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ def write_byte(addr, value)
@ram_enable = value & 0x0f == 0x0a
when 0x2000..0x3fff
@rom_bank = value & 0x1f
@rom_bank = 1 if @rom_bank.zero?
@rom_bank = 1 if @rom_bank == 0
when 0x4000..0x5fff
@ram_bank = value & 0x03
when 0x6000..0x7fff
Expand Down
1,034 changes: 517 additions & 517 deletions lib/rubyboy/cpu.rb

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions lib/rubyboy/joypad.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ def read_byte(addr)
raise "not implemented: write_byte #{addr}" unless addr == 0xff00

res = @mode | 0xcf
res &= @direction if @mode[4].zero?
res &= @action if @mode[5].zero?
res &= @direction if @mode[4] == 0
res &= @action if @mode[5] == 0

res
end
Expand Down
57 changes: 28 additions & 29 deletions lib/rubyboy/ppu.rb
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ def write_byte(addr, value)
end

def step(cycles)
return false if @lcdc[LCDC[:lcd_ppu_enable]].zero?
return false if @lcdc[LCDC[:lcd_ppu_enable]] == 0

res = false
@cycles += cycles
Expand Down Expand Up @@ -187,60 +187,61 @@ def step(cycles)
end

def render_bg
return if @lcdc[LCDC[:bg_window_enable]].zero?
return if @lcdc[LCDC[:bg_window_enable]] == 0

y = (@ly + @scy) % 256
tile_map_addr = @lcdc[LCDC[:bg_tile_map_area]] == 0 ? 0x1800 : 0x1c00
tile_map_addr += (y / 8) * 32
LCD_WIDTH.times do |i|
x = (i + @scx) % 256
tile_index = get_tile_index(@lcdc[LCDC[:bg_tile_map_area]], x, y)
pixel = get_pixel(tile_index, x, y)
tile_index = get_tile_index(tile_map_addr + (x / 8))
pixel = get_pixel(tile_index << 4, 7 - (x % 8), (y % 8) * 2)
@buffer[@ly * LCD_WIDTH + i] = get_color(@bgp, pixel)
@bg_pixels[i] = pixel
end
end

def render_window
return if @lcdc[LCDC[:bg_window_enable]].zero? || @lcdc[LCDC[:window_enable]].zero? || @ly < @wy
return if @lcdc[LCDC[:bg_window_enable]] == 0 || @lcdc[LCDC[:window_enable]] == 0 || @ly < @wy

rendered = false
y = @wly
tile_map_addr = @lcdc[LCDC[:window_tile_map_area]] == 0 ? 0x1800 : 0x1c00
tile_map_addr += (y / 8) * 32
LCD_WIDTH.times do |i|
next if i < @wx - 7

rendered = true
x = i - (@wx - 7)
tile_index = get_tile_index(@lcdc[LCDC[:window_tile_map_area]], x, y)
pixel = get_pixel(tile_index, x, y)
tile_index = get_tile_index(tile_map_addr + (x / 8))
pixel = get_pixel(tile_index << 4, 7 - (x % 8), (y % 8) * 2)
@buffer[@ly * LCD_WIDTH + i] = get_color(@bgp, pixel)
@bg_pixels[i] = pixel
end
@wly += 1 if rendered
end

def render_sprites
return if @lcdc[LCDC[:sprite_enable]].zero?
return if @lcdc[LCDC[:sprite_enable]] == 0

sprite_height = @lcdc[LCDC[:sprite_size]].zero? ? 8 : 16
sprite_height = @lcdc[LCDC[:sprite_size]] == 0 ? 8 : 16
sprites = []
cnt = 0
@oam.each_slice(4).each do |sprite_attr|
sprite = {
y: (sprite_attr[0] - 16) % 256,
x: (sprite_attr[1] - 8) % 256,
tile_index: sprite_attr[2],
flags: sprite_attr[3]
}
next if sprite[:y] > @ly || sprite[:y] + sprite_height <= @ly

sprites << sprite

@oam.each_slice(4) do |y, x, tile_index, flags|
y = (y - 16) % 256
x = (x - 8) % 256
next if y > @ly || y + sprite_height <= @ly

sprites << { y:, x:, tile_index:, flags: }
cnt += 1
break if cnt == 10
end
sprites = sprites.sort_by.with_index { |sprite, i| [-sprite[:x], -i] }

sprites.each do |sprite|
flags = sprite[:flags]
pallet = flags[SPRITE_FLAGS[:dmg_palette]].zero? ? @obp0 : @obp1
pallet = flags[SPRITE_FLAGS[:dmg_palette]] == 0 ? @obp0 : @obp1
tile_index = sprite[:tile_index]
tile_index &= 0xfe if sprite_height == 16
y = (@ly - sprite[:y]) % 256
Expand All @@ -251,10 +252,10 @@ def render_sprites
8.times do |x|
x_flipped = flags[SPRITE_FLAGS[:x_flip]] == 1 ? 7 - x : x

pixel = get_pixel(tile_index, x_flipped, y)
pixel = get_pixel(tile_index << 4, 7 - x_flipped, (y % 8) * 2)
i = (sprite[:x] + x) % 256

next if pixel.zero? || i >= LCD_WIDTH
next if pixel == 0 || i >= LCD_WIDTH
next if flags[SPRITE_FLAGS[:priority]] == 1 && @bg_pixels[i] != 0

@buffer[@ly * LCD_WIDTH + i] = get_color(pallet, pixel)
Expand All @@ -264,15 +265,13 @@ def render_sprites

private

def get_tile_index(tile_map_area, x, y)
tile_map_addr = tile_map_area.zero? ? 0x1800 : 0x1c00
tile_map_index = (y / 8) * 32 + (x / 8)
tile_index = @vram[tile_map_addr + tile_map_index]
@lcdc[LCDC[:bg_window_tile_data_area]].zero? ? to_signed_byte(tile_index) + 256 : tile_index
def get_tile_index(tile_map_addr)
tile_index = @vram[tile_map_addr]
@lcdc[LCDC[:bg_window_tile_data_area]] == 0 ? to_signed_byte(tile_index) + 256 : tile_index
end

def get_pixel(tile_index, x, y)
@vram[tile_index * 16 + (y % 8) * 2][7 - (x % 8)] + (@vram[tile_index * 16 + (y % 8) * 2 + 1][7 - (x % 8)] << 1)
def get_pixel(tile_index, c, r)
@vram[tile_index + r][c] + (@vram[tile_index + r + 1][c] << 1)
end

def get_color(pallet, pixel)
Expand Down
2 changes: 1 addition & 1 deletion lib/rubyboy/timer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ def step(cycles)
@div += after_cycles / 256 - before_cycles / 256
@div &= 0xffff

return if @tac[2].zero?
return if @tac[2] == 0

divider = case @tac & 0b11
when 0b00 then 1024
Expand Down
2 changes: 1 addition & 1 deletion lib/rubyboy/version.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# frozen_string_literal: true

module Rubyboy
VERSION = '1.0.0'
VERSION = '1.1.0'
end

0 comments on commit 449044b

Please sign in to comment.