mirror of
https://github.com/mattrberry/crab.git
synced 2025-01-29 20:35:13 +01:00
Refactor Config to allow temporary command-line overrides
This commit is contained in:
parent
5405b3978b
commit
4001dae0b8
11 changed files with 64 additions and 24 deletions
21
src/crab.cr
21
src/crab.cr
|
@ -16,32 +16,41 @@ module Crab
|
|||
|
||||
extend self
|
||||
|
||||
def run
|
||||
def run : NoReturn
|
||||
config = Config.new
|
||||
|
||||
rom = nil
|
||||
bios = nil
|
||||
fifo = false
|
||||
headless = false
|
||||
|
||||
OptionParser.parse do |parser|
|
||||
parser.banner = "#{"crab".colorize.bold} - An accurate and readable Game Boy (Color) (Advance) emulator"
|
||||
parser.separator
|
||||
parser.separator("Usage: bin/crab [BIOS] ROM")
|
||||
parser.separator("Usage: bin/crab [BIOS] [ROM]")
|
||||
parser.separator
|
||||
parser.separator("All command-line arguments serve as optional overrides to the config.")
|
||||
parser.on("-h", "--help", "Show the help message") do
|
||||
puts parser
|
||||
exit
|
||||
end
|
||||
parser.on("--fifo", "Enable FIFO rendering") { fifo = true }
|
||||
parser.on("--headless", "Don't open window or play audio") { headless = true }
|
||||
parser.on("--run-bios", "Run the bios on startup") { config.args.run_bios = true }
|
||||
parser.on("--skip-bios", "Skip the bios on startup") { config.args.run_bios = false }
|
||||
parser.on("--fifo", "Enable per-pixel rendering for GBC") { config.args.fifo = true }
|
||||
parser.on("--scanline", "Enable scanline rendering for GBC") { config.args.fifo = false }
|
||||
parser.on("--headless", "Don't open window or play audio") { config.args.headless = true }
|
||||
parser.unknown_args do |args|
|
||||
case args.size
|
||||
when 0 # launch the emulator without a rom selected
|
||||
when 1 then rom = args[0]
|
||||
when 2 then bios, rom = args[0], args[1]
|
||||
else abort "Unknown args #{args[2..]}. Use '--help' for help"
|
||||
end
|
||||
end
|
||||
parser.invalid_option { |flag| abort "Unknown flag '#{flag}'. Use '--help' for help" }
|
||||
parser.missing_option { |flag| abort "Option '#{flag}' is missing a value. Use '--help' for help" }
|
||||
end
|
||||
|
||||
frontend = Frontend.new(bios, rom, headless)
|
||||
frontend = Frontend.new(config, bios, rom)
|
||||
frontend.run
|
||||
end
|
||||
end
|
||||
|
|
|
@ -23,9 +23,19 @@ class Config
|
|||
LibSDL::Keycode::R => Input::R,
|
||||
}
|
||||
property recents : Array(String) = [] of String
|
||||
property run_bios : Bool = false
|
||||
property gba : GBA = GBA.new
|
||||
property gbc : GBC = GBC.new
|
||||
|
||||
private class Args
|
||||
property headless : Bool = false
|
||||
property run_bios : Bool?
|
||||
property fifo : Bool?
|
||||
end
|
||||
|
||||
@[YAML::Field(ignore: true)]
|
||||
getter args = Args.new
|
||||
|
||||
def self.new : Config
|
||||
Config.from_yaml(File.read(CONFIG_FILE))
|
||||
end
|
||||
|
@ -34,6 +44,14 @@ class Config
|
|||
File.write(CONFIG_FILE, to_yaml)
|
||||
end
|
||||
|
||||
def run_bios : Bool
|
||||
unless (run_bios = args.run_bios).nil?
|
||||
run_bios
|
||||
else
|
||||
@run_bios
|
||||
end
|
||||
end
|
||||
|
||||
class GBA
|
||||
include YAML::Serializable
|
||||
property bios : String = "bios.bin"
|
||||
|
@ -45,6 +63,7 @@ class Config
|
|||
class GBC
|
||||
include YAML::Serializable
|
||||
property bios : String?
|
||||
property fifo : Bool = false
|
||||
|
||||
def initialize
|
||||
end
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
abstract class Frontend
|
||||
def self.new(bios : String?, rom : String?, headless = false)
|
||||
config = Config.new
|
||||
if headless
|
||||
def self.new(config : Config, bios : String?, rom : String?)
|
||||
if config.args.headless
|
||||
HeadlessFrontend.new(config, bios, rom)
|
||||
else
|
||||
SDLOpenGLImGuiFrontend.new(config, bios, rom)
|
||||
|
@ -10,7 +9,7 @@ abstract class Frontend
|
|||
|
||||
abstract def run : NoReturn
|
||||
|
||||
private def init_controller(bios : String?, rom : String?) : Controller
|
||||
private def init_controller(bios : String?, rom : String?, skip_bios : Bool) : Controller
|
||||
return StubbedController.new unless rom
|
||||
extension = rom.rpartition('.')[2]
|
||||
if GBController.extensions.includes? extension
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
class GBController < Controller
|
||||
@config : Config
|
||||
getter emu : GB::GB
|
||||
class_getter extensions : Array(String) = ["gb", "gbc"]
|
||||
class_getter vertex_shader : String = "identity.vert"
|
||||
|
@ -8,8 +7,13 @@ class GBController < Controller
|
|||
getter width : Int32 = 160
|
||||
getter height : Int32 = 144
|
||||
|
||||
def initialize(@config : Config, bios : String?, rom : String)
|
||||
@emu = GB::GB.new(bios || @config.gbc.bios, rom, true, false)
|
||||
def initialize(config : Config, bios : String?, rom : String)
|
||||
fifo = if config.args.fifo.nil?
|
||||
config.gbc.fifo
|
||||
else
|
||||
config.args.fifo.not_nil!
|
||||
end
|
||||
@emu = GB::GB.new(bios || config.gbc.bios, rom, fifo, config.args.headless, config.run_bios)
|
||||
@emu.post_init
|
||||
end
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
class GBAController < Controller
|
||||
@config : Config
|
||||
getter emu : GBA::GBA
|
||||
class_getter extensions : Array(String) = ["gba"]
|
||||
class_getter vertex_shader : String = "identity.vert"
|
||||
|
@ -11,8 +10,8 @@ class GBAController < Controller
|
|||
@debug_window = false
|
||||
@scheduler_window = false
|
||||
|
||||
def initialize(@config : Config, bios : String?, rom : String)
|
||||
@emu = GBA::GBA.new(bios || @config.gba.bios, rom)
|
||||
def initialize(config : Config, bios : String?, rom : String)
|
||||
@emu = GBA::GBA.new(bios || config.gba.bios, rom, config.run_bios)
|
||||
@emu.post_init
|
||||
end
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ class HeadlessFrontend < Frontend
|
|||
@controller : Controller
|
||||
|
||||
def initialize(@config : Config, bios : String?, rom : String?)
|
||||
@controller = init_controller(bios, rom.not_nil!)
|
||||
@controller = init_controller(bios, rom.not_nil!, @config.run_bios)
|
||||
end
|
||||
|
||||
def run : NoReturn
|
||||
|
|
|
@ -44,7 +44,7 @@ class SDLOpenGLImGuiFrontend < Frontend
|
|||
LibSDL.joystick_open 0
|
||||
at_exit { SDL.quit }
|
||||
|
||||
@controller = init_controller(bios, rom)
|
||||
@controller = init_controller(bios, rom, @config.run_bios)
|
||||
@window = SDL::Window.new(
|
||||
window_title(59.7),
|
||||
@controller.window_width * @scale,
|
||||
|
@ -118,7 +118,7 @@ class SDLOpenGLImGuiFrontend < Frontend
|
|||
|
||||
private def load_new_rom(rom : String?) : Nil
|
||||
LibSDL.close_audio(1)
|
||||
@controller = init_controller(nil, rom)
|
||||
@controller = init_controller(nil, rom, @config.run_bios)
|
||||
@file_explorer.clear_selection
|
||||
|
||||
@config.recents.delete(rom)
|
||||
|
|
|
@ -15,7 +15,8 @@ require "./timer"
|
|||
module GB
|
||||
class GB < Emu
|
||||
getter bootrom : String?
|
||||
getter cgb_ptr : Pointer(Bool) { pointerof(@cgb_enabled) }
|
||||
@cgb_enabled : Bool
|
||||
getter cgb_ptr : Pointer(Bool)
|
||||
getter cartridge : Cartridge
|
||||
|
||||
getter! apu : APU
|
||||
|
@ -27,9 +28,10 @@ module GB
|
|||
getter! scheduler : Scheduler
|
||||
getter! timer : Timer
|
||||
|
||||
def initialize(@bootrom : String?, rom_path : String, @fifo : Bool, @headless : Bool)
|
||||
def initialize(@bootrom : String?, rom_path : String, @fifo : Bool, @headless : Bool, @run_bios : Bool)
|
||||
@cartridge = Cartridge.new rom_path
|
||||
@cgb_enabled = !(bootrom.nil? && @cartridge.cgb == Cartridge::CGB::NONE)
|
||||
@cgb_enabled = (!bootrom.nil? && @run_bios) || @cartridge.cgb != Cartridge::CGB::NONE
|
||||
@cgb_ptr = pointerof(@cgb_enabled)
|
||||
end
|
||||
|
||||
def post_init : Nil
|
||||
|
@ -41,7 +43,8 @@ module GB
|
|||
@timer = Timer.new self
|
||||
@memory = Memory.new self
|
||||
@cpu = CPU.new self
|
||||
skip_boot if @bootrom.nil?
|
||||
|
||||
skip_boot if @bootrom.nil? || !@run_bios
|
||||
end
|
||||
|
||||
private def skip_boot : Nil
|
||||
|
|
|
@ -107,6 +107,7 @@ module GB
|
|||
end
|
||||
|
||||
def skip_boot : Nil
|
||||
@bootrom = Bytes.new 0
|
||||
write_byte 0xFF10, 0x80_u8 # NR10
|
||||
write_byte 0xFF11, 0xBF_u8 # NR11
|
||||
write_byte 0xFF12, 0xF3_u8 # NR12
|
||||
|
|
|
@ -53,6 +53,10 @@ module GBA
|
|||
property halted = false
|
||||
|
||||
def initialize(@gba : GBA)
|
||||
clear_pipeline
|
||||
end
|
||||
|
||||
def skip_bios : Nil
|
||||
@reg_banks[Mode::USR.bank][5] = @r[13] = 0x03007F00
|
||||
@reg_banks[Mode::IRQ.bank][5] = 0x03007FA0
|
||||
@reg_banks[Mode::SVC.bank][5] = 0x03007FE0
|
||||
|
|
|
@ -30,7 +30,7 @@ module GBA
|
|||
getter! dma : DMA
|
||||
getter! debugger : Debugger
|
||||
|
||||
def initialize(@bios_path : String, @rom_path : String)
|
||||
def initialize(@bios_path : String, @rom_path : String, @run_bios : Bool)
|
||||
@scheduler = Scheduler.new
|
||||
@cartridge = Cartridge.new @rom_path
|
||||
scheduler.schedule 280896, ->handle_saves
|
||||
|
@ -48,6 +48,8 @@ module GBA
|
|||
@apu = APU.new self
|
||||
@dma = DMA.new self
|
||||
@debugger = Debugger.new self
|
||||
|
||||
cpu.skip_bios unless @run_bios
|
||||
end
|
||||
|
||||
def run_until_frame : Nil
|
||||
|
|
Loading…
Add table
Reference in a new issue