feat(desktop): run ROM files in a window with keypad input
Add --rom PATH --window with optional bounded --frames execution. Capture from BIOS boot, pump native events between bounded machine slices, retain frames during STOP, and sample keypad input for wake-up. Share final machine reports with terminal mode. Add an original file-exportable input ROM, controller and CLI regressions, and opt-in native window tests. Document controls, frame limits, STOP behavior, and compatibility limits. Verified on Darwin arm64: debug/release workspace and core tests, Clippy, rustdoc, native ROM diagnostics, all ten demo smoke tests, and a 60-frame release ROM run.
This commit is contained in:
parent
c256bf8ccd
commit
109c1ffe81
19 changed files with 919 additions and 57 deletions
|
|
@ -39,7 +39,7 @@ The repository is a Cargo workspace with three crates:
|
|||
| `crates/gba-demos/src/timer_demo.rs` | Original timer-configuration program and IRQ handler |
|
||||
| `Cargo.toml` | Workspace members and shared package settings |
|
||||
| `crates/gba-core/src/lib.rs` | Core modules |
|
||||
| `crates/gba-demos/src/lib.rs` | Demo modules and original instruction/exception demo bytes |
|
||||
| `crates/gba-demos/src/lib.rs` | Demo modules, original instruction/exception bytes, and raw input-test ROM |
|
||||
| `crates/gba-core/src/bios.rs` | Original ARM BIOS image builder, minimal boot, IRQ dispatch, waits, and memory services |
|
||||
| `crates/gba-core/src/bios/reset.rs` | Emitted ARM SoftReset and selective RegisterRamReset; CPU banks, RAM clearing, and supported device-register resets |
|
||||
| `crates/gba-core/src/bios/arithmetic.rs` | Emitted ARM division and integer-square-root routines |
|
||||
|
|
@ -79,9 +79,13 @@ The repository is a Cargo workspace with three crates:
|
|||
| `crates/desktop/src/desktop/mosaic.rs` | Mosaic window and 128-frame independent pixel checks |
|
||||
| `crates/desktop/src/desktop/raster.rs` | Raster window and scanline color-band smoke test |
|
||||
| `crates/desktop/src/main.rs` | Command-line modes, error exit status, and fixed-length CPU demo |
|
||||
| `crates/desktop/src/cartridge.rs` | Read-only ROM files, argument checks, bounded machine execution, and terminal reports |
|
||||
| `crates/desktop/src/cartridge.rs` | Read-only ROM files, mode/limit checks, bounded terminal execution, and shared state reports |
|
||||
| `crates/desktop/src/cartridge/window.rs` | ROM-window session, bounded slices, capture, STOP/input handling, and progress limits |
|
||||
| `crates/desktop/src/cartridge/window/tests.rs` | Original ROM pixels, keyboard mapping, STOP wake, HALT, frame budgets, and diagnostics |
|
||||
| `crates/desktop/src/desktop/rom.rs` | Main-thread ROM window, input polling, presentation pacing, and frame-limited exit |
|
||||
| `crates/desktop/examples/write_rom_demo.rs` | Non-overwriting export of the original input-test ROM |
|
||||
| `crates/desktop/src/cartridge/tests.rs` | ROM options, bounded readers, instruction/DMA/IRQ budgets, HALT/STOP, and diagnostic reports |
|
||||
| `crates/desktop/tests/rom_cli.rs` | Process-level loading and exit-status checks using temporary original programs |
|
||||
| `crates/desktop/tests/rom_cli.rs` | File loading and exit-status checks; opt-in native ROM-window integration test |
|
||||
| `crates/gba-core/tests/core.rs` | CPU integration tests and the complete demo |
|
||||
| `crates/gba-core/tests/memory.rs` | Memory widths, alignment, errors, and mirrors |
|
||||
| `crates/gba-core/tests/exceptions.rs` | Exception demo, BIOS mapping, and reset-vector execution |
|
||||
|
|
|
|||
|
|
@ -17,12 +17,13 @@ Verified locally on macOS 15.7.3:
|
|||
- All ten native window smoke tests pass. The mosaic test submits 128 frames; the other nine submit 60 frames each.
|
||||
- The eight CPU-driven smoke tests check CPU state, every output pixel, and presentation at VBlank entry.
|
||||
- The terminal-only CPU and timer IRQ demos run successfully.
|
||||
- The bounded ROM runner loads original raw programs and reports state without opening a window.
|
||||
- The bounded terminal ROM runner loads original raw programs and reports state without opening a window.
|
||||
- The native ROM-window test presents a file-backed original program and reports STOP, CPU, and video failures.
|
||||
|
||||
These results cover the CPU core, memory, Mode 0–5 snapshots and row capture, input mapping, and desktop windows.
|
||||
They do not verify a complete GBA display controller or audio.
|
||||
Arrow-key movement in the original host display test was confirmed manually on this Mac.
|
||||
The new CPU graphics demo has automated input-mapping tests; its physical keyboard behavior still needs manual confirmation.
|
||||
CPU demos and ROM windows have automated input-mapping tests; their physical keyboard behavior still needs manual confirmation.
|
||||
|
||||
Enable the direnv hook in your shell if it is not already configured.
|
||||
For zsh, add this line to `~/.zshrc`:
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ Minimal boot initializes:
|
|||
|
||||
It then enters `0x08000000` in ARM System mode with IRQ/FIQ masks clear.
|
||||
It does not reproduce Nintendo's logo, cartridge-header checks, RAM clearing, boot delays, or full hardware initialization.
|
||||
The executable can load raw ROM files for [bounded terminal diagnostics](cartridge.md) using this boot sequence.
|
||||
The executable can load raw ROM files for [terminal or window execution](cartridge.md) using this boot sequence.
|
||||
This does not establish game compatibility or complete BIOS behavior.
|
||||
|
||||
Supported software interrupt services:
|
||||
|
|
|
|||
|
|
@ -1,14 +1,17 @@
|
|||
# Cartridge files and terminal execution
|
||||
# Cartridge files and execution
|
||||
|
||||
The desktop executable can load raw ROM bytes and run a bounded diagnostic session.
|
||||
The desktop executable can load raw ROM bytes for terminal diagnostics or window execution.
|
||||
This supports original test programs. It does not establish commercial-game compatibility.
|
||||
|
||||
```sh
|
||||
direnv exec . cargo run --locked --release -- --rom path/to/original.gba --steps 100000
|
||||
direnv exec . cargo run --locked --release -- --rom path/to/original.gba --window
|
||||
```
|
||||
|
||||
Both options are required. Their order does not matter.
|
||||
`COUNT` must contain decimal digits and be between 1 and 100,000,000 inclusive.
|
||||
Supply `--rom PATH` and exactly one execution mode: `--steps COUNT` or `--window`.
|
||||
Option order does not matter. Terminal step counts accept decimal digits from 1 through 100,000,000.
|
||||
Window mode optionally accepts `--frames COUNT`, from 1 through 100,000, for bounded presentation tests.
|
||||
Reject zero, signed numbers, duplicate options, and combinations of terminal and window limits.
|
||||
Do not combine ROM mode with demo or help options. Bare file paths are not accepted.
|
||||
Quote paths that contain spaces. File extensions do not affect loading.
|
||||
|
||||
|
|
@ -31,12 +34,12 @@ Reads past supplied cartridge bytes remain explicit memory errors, not open-bus
|
|||
All three Game Pak ROM windows use the same supplied bytes and existing wait-state rules.
|
||||
Cartridge writes, save devices, and cartridge peripherals remain unsupported.
|
||||
|
||||
The runner calls `bios::boot` with the loaded bytes.
|
||||
Both modes call `bios::boot` with the loaded bytes.
|
||||
The [original BIOS replacement](bios.md) executes its minimal boot before entering `0x08000000` in ARM System mode.
|
||||
There is no command-line option for external BIOS files.
|
||||
Unsupported services remain diagnostics. In particular, RegisterRamReset sound/serial flags, including `r0=0xff`, still fail.
|
||||
|
||||
## Execution limits and results
|
||||
## Terminal execution limits and results
|
||||
|
||||
The budget counts successful machine steps, including BIOS boot instructions.
|
||||
Each CPU instruction, IRQ entry, DMA unit, or HALT idle batch consumes one step.
|
||||
|
|
@ -58,7 +61,67 @@ It does not mean the program completed or passed a hardware test.
|
|||
Invalid arguments, loading failures, output failures, and emulation diagnostics produce a nonzero exit status.
|
||||
For emulation diagnostics, stdout contains the final machine state and stderr contains the core error.
|
||||
|
||||
ROM mode has no window, keyboard input, audio, saves, per-step trace, or real-time pacing.
|
||||
Terminal mode has no window, keyboard input, or real-time pacing.
|
||||
It does not enable frame capture or validate rendered output.
|
||||
Use the existing demos for window and input tests.
|
||||
|
||||
## Window execution
|
||||
|
||||
`--window` opens a native 240×160 window at 4× scale on the main thread.
|
||||
The window presents [scanline-captured frames](display-timing.md#scanline-frame-capture) at VBlank entry.
|
||||
Capture starts before BIOS boot. It has no demo-specific readiness checks and does not suppress startup images.
|
||||
A black buffer appears before the first captured frame.
|
||||
The host does not set display registers, initialize game RAM, or draw replacement game graphics.
|
||||
|
||||
Controls use the same focus correction and key mapping as the existing demos:
|
||||
|
||||
| Host key | GBA button |
|
||||
| --- | --- |
|
||||
| Arrows | D-pad |
|
||||
| Z / X | A / B |
|
||||
| Q / W | L / R |
|
||||
| Enter | Start |
|
||||
| Backspace | Select |
|
||||
|
||||
Escape or the window close control ends execution. Enter does not reset the emulator.
|
||||
Focus loss releases all buttons but does not pause execution.
|
||||
The host samples buttons before each execution slice, including while stopped.
|
||||
|
||||
Each slice executes at most 4,096 machine steps or stops at the next VBlank event.
|
||||
The host processes window events between slices, not only when a frame completes.
|
||||
A separate 400,000-step limit guards progress between VBlank events and persists across slices and STOP waits.
|
||||
This limit permits a full frame of one-cycle instructions. It is not a wall-clock deadline.
|
||||
HALT continues device clocks and frame publication.
|
||||
Normal presentation targets approximately 59.73 frames per second, without frame skipping or accumulated catch-up work.
|
||||
Slow hosts can run slower than real time. Host sleeping never advances emulated clocks.
|
||||
|
||||
In interactive mode, STOP retains the last image and changes the window title.
|
||||
The host continues polling input and window-close events while GBA clocks remain frozen.
|
||||
Only keypad conditions configured by the ROM through KEYCNT and IE can wake STOP.
|
||||
A key press cannot wake a program that has not enabled a matching wake source.
|
||||
|
||||
`--frames COUNT` exits successfully after that many captured frames are submitted to the window.
|
||||
It is a presentation limit, not proof that the ROM completed or passed a test.
|
||||
STOP before that limit is an error instead of an indefinite wait for physical input.
|
||||
Early window closure is also an error in this bounded mode; closure is normal in interactive mode.
|
||||
|
||||
CPU, DMA, video, and window errors end the session with a nonzero exit status.
|
||||
The terminal report includes captured-frame count and the final machine state; stderr contains the error.
|
||||
Rendering errors do not overwrite the last complete framebuffer.
|
||||
Reports count captured frames, not idle redraws or window-event updates.
|
||||
|
||||
## Try an original ROM
|
||||
|
||||
Generate an original headerless input-test file, then open that file through the ROM loader:
|
||||
|
||||
```sh
|
||||
direnv exec . cargo run --locked --example write_rom_demo -- /tmp/gba-input-demo.gba
|
||||
direnv exec . cargo run --locked --release -- --rom /tmp/gba-input-demo.gba --window
|
||||
```
|
||||
|
||||
The generator refuses to overwrite an existing file. Choose a new path if needed.
|
||||
The CPU writes the palette: blue at rest, red while Z is held, and green while Right is held.
|
||||
Right takes priority over Z. Other buttons have no visible effect in this small program.
|
||||
No game or firmware content is included.
|
||||
|
||||
Both ROM modes lack audio, saves, and per-step tracing. Commercial-game compatibility remains unverified and unsupported.
|
||||
Only load files that you may lawfully use. Do not commit game ROMs or firmware.
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ When row capture is enabled, the clock advances within those steps also render v
|
|||
|
||||
`Memory::set_scanline_rendering(true)` enables row capture without changing clocks or hardware registers.
|
||||
Capture is disabled by default for CPU-only use. All CPU-driven demo frame runners enable it automatically.
|
||||
The ROM window runner enables capture before BIOS boot and presents the first complete frame without demo-specific startup checks.
|
||||
Repeatedly enabling capture preserves progress. Disabling it drops captured buffers and availability state.
|
||||
|
||||
For each visible line, the renderer composes the row at HBlank entry, cycle 1,006.
|
||||
|
|
|
|||
|
|
@ -62,7 +62,9 @@ Update this file when a feature lands or a limit is removed.
|
|||
- `SWP`/`SWPB`, including unaligned word rotation and register aliases.
|
||||
- 256 KiB external work RAM and 32 KiB internal work RAM, including mirrors.
|
||||
- Read-only cartridge bytes in the three GBA cartridge windows.
|
||||
- Raw ROM-file loading for bounded terminal diagnostics, with original BIOS boot and final CPU/step reports.
|
||||
- Raw ROM-file loading with original BIOS boot, terminal diagnostics, and final CPU/step reports.
|
||||
- ROM windows with scanline capture, keyboard input, focus-loss release, bounded execution slices, and interactive keypad wake from STOP.
|
||||
- Optional ROM-window frame limits and an original input-test ROM generator.
|
||||
- Little-endian byte, halfword, and word reads/writes.
|
||||
- ARM7TDMI word-load rotation, aligned stores, and odd-address halfword-load behavior.
|
||||
- Explicit errors for unsupported instructions when their condition passes, and for unsupported memory accesses.
|
||||
|
|
@ -103,8 +105,9 @@ Keypad IRQs use a documented polling model; hardware retrigger edges and asynchr
|
|||
STOP implements keypad wake only. Serial/Game Pak wake sources, oscillator restart delays, and exact wake timing remain unimplemented or unverified.
|
||||
The presentation framebuffer is separate from emulated video RAM.
|
||||
All named graphics demos connect desktop input and rendering to the emulated CPU. The default display test remains host-generated.
|
||||
ROM files can run in bounded terminal mode with the original BIOS replacement.
|
||||
This mode has no window, input, audio, saves, or external BIOS option. It does not establish commercial-game compatibility.
|
||||
ROM files can run in bounded terminal mode or a window with the original BIOS replacement.
|
||||
ROM windows have no demo-specific startup checks. Input is sampled between bounded execution slices.
|
||||
Audio, saves, and external BIOS loading remain unavailable. ROM loading does not establish commercial-game compatibility.
|
||||
See [cartridge loading](hardware/cartridge.md) for file limits, step budgets, and exit status.
|
||||
|
||||
Unmapped reads return errors instead of hardware open-bus values.
|
||||
|
|
@ -120,7 +123,7 @@ Writes to cartridge addresses return errors instead of modeling cartridge hardwa
|
|||
3. Validate keypad retrigger behavior with hardware tests and add remaining device registers; extend BIOS reset coverage as sound/serial support becomes available.
|
||||
Validate STOP entry/wake edges and add external wake sources and remaining DMA device modes.
|
||||
4. Replace nominal sprite work limits with verified individual fetch timing; add background fetch timing and per-pixel composition.
|
||||
5. Connect ROM execution to the window and input; expand audio, cartridge hardware, and saves before testing Emerald compatibility.
|
||||
5. Validate more original/public test ROMs through the window; add audio, cartridge hardware, and saves before testing Emerald compatibility.
|
||||
|
||||
Keep the emulator core independent of window and audio libraries.
|
||||
Treat Nintendo DS support as a separate project phase.
|
||||
|
|
|
|||
|
|
@ -23,7 +23,16 @@ file target/release/gameboy-rust
|
|||
./target/release/gameboy-rust --timer-demo
|
||||
```
|
||||
|
||||
All ten window smoke tests need an active desktop session. Ordinary tests do not open windows.
|
||||
All ten demo window smoke tests need an active desktop session. Ordinary tests do not open windows.
|
||||
Run the additional file-backed ROM-window test explicitly in that desktop session:
|
||||
|
||||
```sh
|
||||
direnv exec . cargo test --locked -p gameboy-rust-desktop --test rom_cli native_rom_window -- --ignored --test-threads=1
|
||||
direnv exec . cargo test --locked --release -p gameboy-rust-desktop --test rom_cli native_rom_window -- --ignored --test-threads=1
|
||||
```
|
||||
|
||||
This opt-in test opens native windows in child processes and checks bounded presentation and STOP/CPU/video diagnostics.
|
||||
Each process has a host-side timeout. It does not require or validate physical keyboard presses.
|
||||
CPU-driven smoke tests supply scripted buttons; they do not validate physical keyboard events.
|
||||
To test the core and demo programs without building the window dependency:
|
||||
|
||||
|
|
@ -42,7 +51,10 @@ They check file-size boundaries, bounded reads, short reads, I/O errors, paths,
|
|||
CLI tests cover option order, missing/conflicting options, invalid step limits, process exit status, and reports.
|
||||
Execution tests cover original ARM/Thumb code, BIOS boot, DMA/IRQ step accounting, HALT budgets, and prompt STOP results.
|
||||
Unsupported instructions, truncated code, and DMA errors retain the failure state for inspection.
|
||||
See [cartridge execution](hardware/cartridge.md) for usage and limitations.
|
||||
ROM-window session tests compare every pixel from an original CPU-written palette with expected colors.
|
||||
They check keyboard-to-ROM input, focus loss, repeated STOP polling, keypad wake, HALT progress, and bounded slices.
|
||||
Further checks cover frame-budget retention/reset, DMA/IRQ step accounting, video errors, and final reports.
|
||||
See [cartridge execution](hardware/cartridge.md) for usage, limitations, and a generated original ROM for manual input testing.
|
||||
|
||||
Angle-service tests compare results with wide-integer polynomial and signed-sector references, plus floating-point accuracy checks in supported ranges.
|
||||
They cover a dense ArcTan unit-interval grid, sampled full-domain and seeded inputs, axes, quadrant boundaries, signed extremes, and scale invariance.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue