Class: Rubyboy::Emulator

Inherits:
Object
  • Object
show all
Defined in:
lib/rubyboy/emulator.rb

Constant Summary collapse

CPU_CLOCK_HZ =
4_194_304
CYCLE_NANOSEC =
1_000_000_000 / CPU_CLOCK_HZ

Instance Method Summary collapse

Constructor Details

#initialize(rom_path) ⇒ Emulator

Returns a new instance of Emulator.



8
9
10
11
12
13
14
15
16
17
18
19
20
21
# File 'lib/rubyboy/emulator.rb', line 8

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)
  @lcd = Lcd.new
end

Instance Method Details

#bench(frames) ⇒ Object



51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/rubyboy/emulator.rb', line 51

def bench(frames)
  @lcd.close_window
  frame_count = 0
  start_time = Process.clock_gettime(Process::CLOCK_MONOTONIC, :nanosecond)
  while frame_count < frames
    cycles = @cpu.exec
    @timer.step(cycles)
    if @ppu.step(cycles)
      key_input_check
      frame_count += 1
    end
  end

  Process.clock_gettime(Process::CLOCK_MONOTONIC, :nanosecond) - start_time
end

#startObject



23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/rubyboy/emulator.rb', line 23

def start
  SDL.InitSubSystem(SDL::INIT_KEYBOARD)

  start_time = Process.clock_gettime(Process::CLOCK_MONOTONIC, :nanosecond)
  elapsed_machine_time = 0
  catch(:exit_loop) do
    loop do
      elapsed_real_time = Process.clock_gettime(Process::CLOCK_MONOTONIC, :nanosecond) - start_time
      while elapsed_real_time > elapsed_machine_time
        cycles = @cpu.exec
        @timer.step(cycles)
        @apu.step(cycles)
        if @ppu.step(cycles)
          @lcd.draw(@ppu.buffer)
          key_input_check
          throw :exit_loop if @lcd.window_should_close?
        end

        elapsed_machine_time += cycles * CYCLE_NANOSEC
      end
    end
  end
  @lcd.close_window
rescue StandardError => e
  puts e.to_s[0, 100]
  raise e
end