Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
## [Unreleased]
## [1.5.0] - 2025-02-09

- Add EmulatorHeadless and use it for bench
- Bump ruby.wasm version to 2.7.1

## [1.4.2] - 2025-01-11

Expand Down
4 changes: 2 additions & 2 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,6 @@ group :development, :test do
end

group :wasm do
gem 'js', '2.7.0'
gem 'ruby_wasm', '2.7.0'
gem 'js', '2.7.1'
gem 'ruby_wasm', '2.7.1'
end
12 changes: 6 additions & 6 deletions Gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
PATH
remote: .
specs:
rubyboy (1.4.2)
rubyboy (1.5.0)
ffi (~> 1.16, >= 1.16.3)

GEM
Expand All @@ -12,7 +12,7 @@ GEM
diff-lcs (1.5.0)
ffi (1.16.3)
heap-profiler (0.7.0)
js (2.7.0)
js (2.7.1)
json (2.6.3)
language_server-protocol (3.17.0.3)
parallel (1.23.0)
Expand Down Expand Up @@ -52,8 +52,8 @@ GEM
rubocop-ast (1.29.0)
parser (>= 3.2.1.0)
ruby-progressbar (1.13.0)
ruby_wasm (2.7.0-x86_64-darwin)
ruby_wasm (2.7.0-x86_64-linux)
ruby_wasm (2.7.1-x86_64-darwin)
ruby_wasm (2.7.1-x86_64-linux)
stackprof (0.2.25)
unicode-display_width (2.5.0)

Expand All @@ -63,11 +63,11 @@ PLATFORMS

DEPENDENCIES
heap-profiler (~> 0.7.0)
js (= 2.7.0)
js (= 2.7.1)
rake (~> 13.0)
rspec (~> 3.12)
rubocop (~> 1.57)
ruby_wasm (= 2.7.0)
ruby_wasm (= 2.7.1)
rubyboy!
stackprof (~> 0.2.25)

Expand Down
2 changes: 1 addition & 1 deletion docs/worker.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { DefaultRubyVM } from 'https://cdn.jsdelivr.net/npm/@ruby/wasm-wasi@2.7.0/dist/browser/+esm';
import { DefaultRubyVM } from 'https://cdn.jsdelivr.net/npm/@ruby/wasm-wasi@2.7.1/dist/browser/+esm';
import { File } from 'https://cdn.jsdelivr.net/npm/@bjorn3/browser_wasi_shim@0.3.0/+esm';

const DIRECTION_KEY_MASKS = {
Expand Down
2 changes: 1 addition & 1 deletion exe/rubyboy-bench
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,4 @@ else
puts 'YJIT is not available in this environment.'
end

Rubyboy::Bench.new.bench(**options)
Rubyboy::Bench.new.run(**options)
2 changes: 1 addition & 1 deletion exe/rubyboy-wasm
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

case ARGV[0]
when 'build'
command = %w[build --ruby-version 3.3 -o ./docs/ruby-js.wasm]
command = %w[build --ruby-version 3.4 -o ./docs/ruby-js.wasm]
when 'pack'
command = %w[pack ./docs/ruby-js.wasm --dir ./lib::/lib -o ./docs/rubyboy.wasm]
else
Expand Down
24 changes: 13 additions & 11 deletions lib/bench.rb
Original file line number Diff line number Diff line change
@@ -1,22 +1,24 @@
# frozen_string_literal: true

require 'stackprof'
require_relative 'rubyboy'
require_relative 'rubyboy/emulator_headless'

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

def bench(count: 3, frames: 1500, rom_path: 'lib/roms/tobu.gb')
def run(count: 3, frames: 1500, rom_path: 'lib/roms/tobu.gb')
time_sum = 0

count.times do |i|
time = Rubyboy::Emulator.new(rom_path).bench(frames)
time_sum += time
emulator = Rubyboy::EmulatorHeadless.new(rom_path)
frame_count = 0
start_time = Process.clock_gettime(Process::CLOCK_MONOTONIC, :nanosecond)
while frame_count < frames
emulator.step
frame_count += 1
end
time = Process.clock_gettime(Process::CLOCK_MONOTONIC, :nanosecond) - start_time
puts "#{i + 1}: #{time / 1_000_000_000.0} sec"

time_sum += time
end

puts "FPS: #{frames * count * 1_000_000_000.0 / time_sum}"
Expand Down
39 changes: 39 additions & 0 deletions lib/rubyboy/emulator_headless.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# frozen_string_literal: true

require_relative 'apu'
require_relative 'bus'
require_relative 'cpu'
require_relative 'ppu'
require_relative 'rom'
require_relative 'ram'
require_relative 'timer'
require_relative 'joypad'
require_relative 'interrupt'
require_relative 'cartridge/factory'

module Rubyboy
class EmulatorHeadless
def initialize(rom_path)
rom_data = File.open(rom_path, 'r') { _1.read.bytes }
rom = Rom.new(rom_data)
ram = Ram.new
mbc = Cartridge::Factory.create(rom, ram)
interrupt = Interrupt.new
@ppu = Ppu.new(interrupt)
@timer = Timer.new(interrupt)
joypad = Joypad.new(interrupt)
@apu = Apu.new
bus = Bus.new(@ppu, rom, ram, mbc, @timer, interrupt, joypad, @apu)
@cpu = Cpu.new(bus, interrupt)
end

def step
loop do
cycles = @cpu.exec
@timer.step(cycles)
@apu.step(cycles)
break if @ppu.step(cycles)
end
end
end
end
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.4.2'
VERSION = '1.5.0'
end
14 changes: 14 additions & 0 deletions lib/stackprof.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# frozen_string_literal: true

require 'stackprof'
require_relative 'rubyboy/emulator'

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