feat(cartridge): add explicit GPIO and RTC control support
This commit is contained in:
parent
c5e19baed4
commit
692be36349
18 changed files with 889 additions and 26 deletions
|
|
@ -13,13 +13,14 @@ use std::{
|
|||
|
||||
use gba_core::{
|
||||
bios,
|
||||
cartridge::CartridgeHardware,
|
||||
machine::{Machine, MachineError, StepKind},
|
||||
memory::ROM_CAPACITY,
|
||||
};
|
||||
|
||||
const MAX_STEPS: u64 = 100_000_000;
|
||||
const MAX_FRAMES: u64 = 100_000;
|
||||
const USAGE: &str = "usage: gameboy-rust --rom PATH (--steps COUNT | --window [--frames COUNT]); steps: 1..=100000000, frames: 1..=100000; do not combine with demo or help options";
|
||||
const USAGE: &str = "usage: gameboy-rust --rom PATH [--rtc] (--steps COUNT | --window [--frames COUNT]); steps: 1..=100000000, frames: 1..=100000; do not combine with demo or help options";
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
enum Mode {
|
||||
|
|
@ -31,6 +32,7 @@ enum Mode {
|
|||
pub struct Options {
|
||||
path: PathBuf,
|
||||
mode: Mode,
|
||||
hardware: CartridgeHardware,
|
||||
}
|
||||
|
||||
pub fn parse_args(args: &[OsString]) -> io::Result<Options> {
|
||||
|
|
@ -39,6 +41,7 @@ pub fn parse_args(args: &[OsString]) -> io::Result<Options> {
|
|||
let mut steps = None;
|
||||
let mut frames = None;
|
||||
let mut window = false;
|
||||
let mut hardware = CartridgeHardware::None;
|
||||
let mut args = args.iter();
|
||||
while let Some(arg) = args.next() {
|
||||
if arg == "--rom" && path.is_none() {
|
||||
|
|
@ -47,6 +50,8 @@ pub fn parse_args(args: &[OsString]) -> io::Result<Options> {
|
|||
.filter(|value| !value.is_empty())
|
||||
.ok_or_else(invalid)?;
|
||||
path = Some(PathBuf::from(value));
|
||||
} else if arg == "--rtc" && hardware == CartridgeHardware::None {
|
||||
hardware = CartridgeHardware::Rtc;
|
||||
} else if arg == "--window" && !window {
|
||||
window = true;
|
||||
} else if (arg == "--steps" && steps.is_none()) || (arg == "--frames" && frames.is_none()) {
|
||||
|
|
@ -83,6 +88,7 @@ pub fn parse_args(args: &[OsString]) -> io::Result<Options> {
|
|||
Ok(Options {
|
||||
path: path.ok_or_else(invalid)?,
|
||||
mode,
|
||||
hardware,
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -237,12 +243,20 @@ pub fn execute(options: Options, writer: &mut impl Write) -> Result<(), Box<dyn
|
|||
writer,
|
||||
"Original BIOS replacement; no commercial-game compatibility claim."
|
||||
)?;
|
||||
if options.hardware == CartridgeHardware::Rtc {
|
||||
writeln!(writer, "RTC selected: GPIO and command/control only; calendar and IRQ commands remain diagnostic.")?;
|
||||
}
|
||||
let steps = match options.mode {
|
||||
Mode::Terminal { steps } => steps,
|
||||
Mode::Window { frames } => return crate::desktop::run_rom(bytes, frames, writer),
|
||||
Mode::Window { frames } => {
|
||||
return crate::desktop::run_rom(bytes, frames, options.hardware, writer)
|
||||
}
|
||||
};
|
||||
writeln!(writer, "Machine-step limit: {steps} (includes boot)")?;
|
||||
let mut machine = bios::boot(bytes)?;
|
||||
machine
|
||||
.memory_mut()
|
||||
.set_cartridge_hardware(options.hardware);
|
||||
let report = run_bounded(&mut machine, steps);
|
||||
write_report(writer, &machine, &report)?;
|
||||
writer.flush()?;
|
||||
|
|
|
|||
|
|
@ -26,7 +26,8 @@ fn options_require_both_flags_in_either_order() {
|
|||
parse_args(&arguments).unwrap(),
|
||||
Options {
|
||||
path: "original program.gba".into(),
|
||||
mode: Mode::Terminal { steps: count }
|
||||
mode: Mode::Terminal { steps: count },
|
||||
hardware: CartridgeHardware::None
|
||||
}
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,6 +46,10 @@ impl Session {
|
|||
})
|
||||
}
|
||||
|
||||
pub fn set_cartridge_hardware(&mut self, hardware: gba_core::cartridge::CartridgeHardware) {
|
||||
self.machine.memory_mut().set_cartridge_hardware(hardware);
|
||||
}
|
||||
|
||||
pub fn frame(&self) -> &Framebuffer {
|
||||
&self.frame
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,9 +8,11 @@ use crate::cartridge::window::{Session, Update};
|
|||
pub fn run(
|
||||
bytes: Vec<u8>,
|
||||
frame_limit: Option<u64>,
|
||||
hardware: gba_core::cartridge::CartridgeHardware,
|
||||
writer: &mut impl Write,
|
||||
) -> Result<(), Box<dyn Error>> {
|
||||
let mut session = Session::new(bytes)?;
|
||||
session.set_cartridge_hardware(hardware);
|
||||
writeln!(
|
||||
writer,
|
||||
"ROM window: Arrows=D-pad; Z/X=A/B; Q/W=L/R; Enter=Start; Backspace=Select; Escape exits."
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ fn parse_args(args: &[OsString]) -> Result<RunMode, io::Error> {
|
|||
return cartridge::suite::parse_args(args).map(RunMode::TestSuite);
|
||||
}
|
||||
if args.iter().any(|arg| {
|
||||
["--rom", "--steps", "--window", "--frames"]
|
||||
["--rom", "--steps", "--window", "--frames", "--rtc"]
|
||||
.iter()
|
||||
.any(|flag| arg == flag)
|
||||
}) {
|
||||
|
|
@ -79,7 +79,7 @@ fn parse_args(args: &[OsString]) -> Result<RunMode, io::Error> {
|
|||
[arg] if arg == "--help" || arg == "-h" => Ok(RunMode::Help),
|
||||
_ => Err(io::Error::new(
|
||||
io::ErrorKind::InvalidInput,
|
||||
"usage: gameboy-rust [--cpu-demo | --timer-demo | --graphics-demo | --smoke-test | --graphics-smoke-test | --raster-demo | --raster-smoke-test | --mosaic-demo | --mosaic-smoke-test | --effects-demo | --effects-smoke-test | --tile-demo | --tile-smoke-test | --affine-demo | --affine-smoke-test | --affine-raster-demo | --affine-raster-smoke-test | --bitmap4-demo | --bitmap5-demo | --bitmap4-smoke-test | --bitmap5-smoke-test | --help]; or gameboy-rust --rom PATH (--steps COUNT | --window [--frames COUNT]); or gameboy-rust --test-suite PATH.json",
|
||||
"usage: gameboy-rust [--cpu-demo | --timer-demo | --graphics-demo | --smoke-test | --graphics-smoke-test | --raster-demo | --raster-smoke-test | --mosaic-demo | --mosaic-smoke-test | --effects-demo | --effects-smoke-test | --tile-demo | --tile-smoke-test | --affine-demo | --affine-smoke-test | --affine-raster-demo | --affine-raster-smoke-test | --bitmap4-demo | --bitmap5-demo | --bitmap4-smoke-test | --bitmap5-smoke-test | --help]; or gameboy-rust --rom PATH [--rtc] (--steps COUNT | --window [--frames COUNT]); or gameboy-rust --test-suite PATH.json",
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
|
@ -125,6 +125,7 @@ fn run() -> Result<(), Box<dyn Error>> {
|
|||
--rom PATH --steps COUNT Run a raw ROM in the terminal (1..=100000000 steps)\n\
|
||||
--rom PATH --window Open a raw ROM with keyboard input\n\
|
||||
--frames COUNT Exit ROM window after 1..=100000 captured frames\n\
|
||||
--rtc Select RTC GPIO/control subset for --rom (no calendar yet)\n\
|
||||
--test-suite PATH.json Run bounded ROM assertions; write a JSON report\n\
|
||||
--cpu-demo Run the terminal-only ARM/Thumb instruction demo\n\
|
||||
--timer-demo Run the timer IRQ demo with nominal cycle costs\n\
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue