fix(bios): initialize affine scales before cartridge boot

This commit is contained in:
0xrsydn 2026-10-06 22:35:26 +07:00
commit 1b39a7f33f
8 changed files with 157 additions and 3 deletions

View file

@ -76,6 +76,7 @@ The repository is a Cargo workspace with three crates:
| `crates/gba-core/src/lib.rs` | Core modules |
| `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/tests/bios/boot_video.rs` | Firmware identity scales, bitmap/affine startup rendering, capture, and raw-memory isolation |
| `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 |
| `crates/gba-core/src/bios/affine.rs` | Emitted ARM background/sprite matrix services, range checks, and generated sine table |

View file

@ -23,6 +23,12 @@ Minimal boot initializes:
- Supervisor stack: `0x03007fe0`.
- BIOS IRQ flags at `0x03007ff8` and the callback pointer at `0x03007ffc`: zero.
- IME: zero; POSTFLG: one.
- BG2/BG3 affine PA and PD: 256 (identity scale), through executed ARM halfword stores.
Fresh device state supplies zero PB, PC, and origins. Raw `Memory::new` defaults remain unchanged.
This prevents bitmap and affine ROMs from sampling one pixel across the screen when they rely on firmware initialization.
Original regressions verify bitmap coordinates, both affine backgrounds, and scanline capture without ROM-side matrix writes.
See the [boot graphics investigation](../research/boot-video.md) for the independent homebrew failure and evidence.
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.

View file

@ -231,6 +231,13 @@ Shared timer prescaler phase:
See [shared divider scope and tests](research/timer-prescaler.md). The correction does not implement delayed register writes or startup edges.
General gameplay and boot graphics:
- [ZeroDayArcade Pong at c784b603](https://github.com/ZeroDayArcade/Pong-Homebrew-GBA/tree/c784b6036a4f188c50932b411e98126bfcbd07d6), for a licensed independent homebrew, source-defined menu/input behavior, and bitmap startup requirements.
- [mGBA I/O initialization at 3a5e34be](https://github.com/mgba-emu/mgba/blob/3a5e34be33dc7f8f707e5bc9db69e8a430046f21/src/gba/io.c), cross-checked with its BIOS reset implementation for identity affine scales.
- [gbadoc register summary](https://gbadev.net/gbadoc/registers.html), for affine coefficient meanings. See [boot graphics evidence](research/boot-video.md).
- [tolik518/GBA_Pong](https://github.com/tolik518/GBA_Pong/tree/422e22a5d1f7d11710e03ffc19d5bff6ac95240f): a future homebrew candidate found during research. It has not been built or tested here.
Use [GBATEK](https://problemkaputt.de/gbatek.htm) and ARM7TDMI documentation for further hardware work.
Only use game ROMs that you may lawfully use. Do not commit game ROMs, BIOS files, or game assets.
The ignore file excludes `roms/`, common game ROM extensions, and save files.

View file

@ -0,0 +1,44 @@
# BIOS boot graphics initialization
## Observed failure
The MIT-licensed ZeroDayArcade Pong homebrew booted and serviced VBlank interrupts without a CPU diagnostic.
Version 2 ROM scenarios then found a black captured screen despite running menu and gameplay logic.
The same checks passed after firmware initialized the affine scales. The ROM bytes and assertions did not change.
The source selects Mode 3 and BG2 but does not write an affine matrix.
Our raw I/O state starts with zero coefficients. The original boot sequence previously left those values unchanged.
Zero PA and PD make the renderer sample the same source pixel across the screen.
This is a firmware initialization gap, not a reason to bypass affine rendering for bitmap modes.
## Correction and independent regressions
The original BIOS now executes ARM stores of 256 to BG2PA, BG2PD, BG3PA, and BG3PD before entering the cartridge.
Fresh device state already supplies zero PB, PC, and origins.
The change does not alter `Memory::new`, external firmware, or SoftReset behavior.
It does not claim complete hardware initialization or exact startup timing.
Original test programs select a video mode without writing matrices.
Separate horizontal and vertical pixels establish the expected identity transform for bitmap graphics and both affine backgrounds.
A captured frame checks the timed rendering path. A raw-memory control retains the zero-matrix behavior.
The bitmap and affine startup tests failed before the correction and pass afterward.
## Compatibility evidence
Pong revision `c784b6036a4f188c50932b411e98126bfcbd07d6` passes bounded menu, settings, return, match-start, ball-motion, and paddle press/release checks.
Debug and release scenario reports match on Darwin arm64.
A bounded native Pong window run and the original native-window smoke test complete successfully.
The automated input checks use the core input interface; they do not establish manual keyboard playthrough or full-game correctness.
The pinned public ARM, Thumb, memory, and BIOS checkpoints still pass in both profiles.
Additional boot instructions intentionally change startup step/cycle counters and internal firmware addresses.
No public ROM, game asset, or third-party implementation source is included in this repository.
## References
- [Pinned Pong source and license](https://github.com/ZeroDayArcade/Pong-Homebrew-GBA/tree/c784b6036a4f188c50932b411e98126bfcbd07d6): `main.c` selects Mode 3; `graphics.h` defines rectangles and text positions.
- [Pinned mGBA I/O initialization](https://github.com/mgba-emu/mgba/blob/3a5e34be33dc7f8f707e5bc9db69e8a430046f21/src/gba/io.c): `GBAIOInit` supplies identity PA/PD values.
- [Pinned mGBA RegisterRamReset](https://github.com/mgba-emu/mgba/blob/3a5e34be33dc7f8f707e5bc9db69e8a430046f21/src/gba/bios.c): independent cross-check of affine reset values, not copied implementation.
- [gbadoc register summary](https://gbadev.net/gbadoc/registers.html) and [GBATEK](https://mgba-emu.github.io/gbatek/): affine coefficient roles and register addresses.
These sources support functional initialization. They are not a hardware trace of Nintendo firmware startup.

View file

@ -76,6 +76,7 @@ Update this file when a feature lands or a limit is removed.
- 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 with original BIOS boot, terminal diagnostics, and final CPU/step reports.
- Firmware boot initializes BG2/BG3 identity scales for bitmap and affine programs that do not program their own matrices.
- 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.
- Headless JSON ROM suites with PC or VBlank completion, register/CPSR/memory/pixel assertions, scheduled buttons, bounded budgets, and structured failure reports.