fix(memory): ignore emulated writes to mapped BIOS
This commit is contained in:
parent
86f8663904
commit
a0516de748
16 changed files with 462 additions and 34 deletions
|
|
@ -33,6 +33,7 @@ The repository is a Cargo workspace with three crates:
|
|||
| `crates/gba-core/src/cpu/exception.rs` | Reset state, exception entry, and interrupt sampling |
|
||||
| `crates/gba-core/src/cpu/load_alias_tests.rs` | Original single-load alias regressions for indexing, banks, widths, alignment, I/O, timing, and diagnostics |
|
||||
| `crates/gba-core/src/cpu/bios_access_tests.rs` | Original CPU BIOS protection regressions for retained history, modes, widths, exception returns, and diagnostics |
|
||||
| `crates/gba-core/src/cpu/bios_write_tests.rs` | Ignored CPU/DMA BIOS writes, immutable images, swaps, timing, completion, and strict unsupported boundaries |
|
||||
| `crates/gba-core/src/cpu/thumb_bios_access_tests.rs` | Thumb BIOS aligned-word snapshots, transitions, load lanes, boundaries, diagnostics, and nominal timing |
|
||||
| `crates/gba-core/src/cpu/thumb_open_bus_tests.rs` | Region-dependent Thumb open bus, mirrors, widths, transfers, source boundaries, isolation, and nominal timing |
|
||||
| `crates/gba-core/src/cpu/iwram_open_bus_tests.rs` | Persistent IWRAM lanes, cold fills, access widths, isolation, errors, refills, IRQ preservation, and nominal timing |
|
||||
|
|
@ -96,6 +97,7 @@ The repository is a Cargo workspace with three crates:
|
|||
| `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/tests/bios/copy_bus.rs` | Original copy/fill services with ignored BIOS destinations and retained source diagnostics |
|
||||
| `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 |
|
||||
|
|
|
|||
|
|
@ -134,7 +134,8 @@ See the [root-cause research](../research/bios-readback.md) for evidence and the
|
|||
|
||||
Host/debug reads and ROM-suite memory assertions still inspect raw mapped bytes and do not initialize or change the history.
|
||||
Instruction fetches remain strict mapped reads outside the CPU data-access context.
|
||||
BIOS writes remain read-only diagnostics. DMA BIOS sources never read image bytes.
|
||||
CPU and DMA writes to the mapped BIOS are ignored, as described below. Host writes remain read-only diagnostics.
|
||||
DMA BIOS sources never read image bytes.
|
||||
They reuse known [channel data](dma.md#retained-channel-data), or report an unsupported-source diagnostic when channel data is unknown.
|
||||
Missing BIOS images remain unmapped. The unused-memory ARM open-bus snapshot is separate from this retained BIOS value.
|
||||
|
||||
|
|
@ -148,6 +149,38 @@ Original regressions cover synthetic images, boot, exception returns, access wid
|
|||
The [public BIOS ROM](../public-bios-tests.md) passes its unchanged protected-read assertions in debug and release builds.
|
||||
This result covers these firmware boundaries, not full BIOS service compatibility.
|
||||
|
||||
## Writes to the mapped BIOS
|
||||
|
||||
CPU stores to `0x00000000..0x00003fff` complete without changing the supplied BIOS image.
|
||||
This applies to ARM and Thumb stores, all processor modes, block stores, and the write phase of swaps.
|
||||
The rule depends on the destination, not the executing address or a particular BIOS service.
|
||||
A swap must still complete its protected read; unknown read history remains diagnostic.
|
||||
|
||||
Ignored writes retain nominal data-access costs, instruction writeback, and normal machine clock advancement.
|
||||
The write value does not replace BIOS read history. Instructions executed inside BIOS still update history through their ordinary fetches.
|
||||
DMA writes follow the same discard rule, with source reads, channel data, address progression, completion IRQs, and nominal timing intact.
|
||||
Host/debug `Memory::write*` calls remain strict and report `ReadOnly` for the mapped BIOS.
|
||||
|
||||
The bounded rule requires a supplied BIOS image and stops at `0x00003fff`.
|
||||
Missing BIOS images, unmapped destinations beyond that boundary, and cartridge writes retain their existing diagnostics.
|
||||
Whole-instruction validation still rejects a block store with a later unsupported destination before committing CPU state.
|
||||
DMA retains earlier completed units when a later unit fails.
|
||||
This is not a general model of ignored writes across unused address ranges.
|
||||
|
||||
`CpuSet` and `CpuFastSet` need no service-specific change: their original ARM stores obey these bus rules.
|
||||
Tests use original programs and images to check immutable firmware, widths, lanes, modes, swaps, clocks, DMA, and failed-step retry.
|
||||
The local Emerald caller supplies destination zero itself; the copy routine does not corrupt that argument.
|
||||
See [the startup investigation](../research/emerald-reset.md).
|
||||
|
||||
### Write-behavior references
|
||||
|
||||
- [GBATEK memory map](https://mgba-emu.github.io/gbatek/): the 16 KiB BIOS system-ROM region and bus widths.
|
||||
- [GBATEK memory-copy services](https://problemkaputt.de/gbatek-bios-memory-copy.htm): CpuSet/CpuFastSet arguments and executed copy operations.
|
||||
- [mGBA memory implementation at 3a5e34be](https://github.com/mgba-emu/mgba/blob/3a5e34be33dc7f8f707e5bc9db69e8a430046f21/src/gba/memory.c): unsupported BIOS store cases log and continue without writing the image.
|
||||
- [ares BIOS implementation at 728105b2](https://github.com/ares-emulator/ares/blob/728105b28ed6f1429841d5b2f5a38794d01d5c39/ares/gba/system/bios.cpp): the BIOS write handler discards writes separately from protected reads.
|
||||
|
||||
These are documentation and emulator comparisons, not new physical-hardware measurements. No reference implementation was copied.
|
||||
|
||||
## Stop
|
||||
|
||||
`Stop` (`SWI 0x03`) executes an original ARM byte store of `0x80` to HALTCNT.
|
||||
|
|
|
|||
|
|
@ -146,7 +146,8 @@ Limits remain explicit:
|
|||
- Unused/write-only I/O reads, general DMA-to-CPU bus handoff, and disabled-RAM reads are not modeled here.
|
||||
[DMA channel data](dma.md#retained-channel-data) is separate and never overrides a CPU snapshot.
|
||||
- Missing BIOS, truncated ROM, unsupported I/O, and save-memory accesses retain their existing diagnostics.
|
||||
- Unused-memory writes remain diagnostics rather than ignored hardware writes. Swaps cannot silently discard their write.
|
||||
- Unused-memory writes remain diagnostics rather than ignored hardware writes. Swaps to those ranges still fail.
|
||||
- Writes to the mapped BIOS are a separate [ignored-write subset](bios.md#writes-to-the-mapped-bios), including swap write phases.
|
||||
- ARM/Thumb instruction buffering is persistent, but these data snapshots remain a separate bounded model.
|
||||
Thumb IWRAM bus-history samples do not share storage with retained instructions.
|
||||
DMA updates IWRAM lanes at instruction boundaries, not during CPU accesses.
|
||||
|
|
|
|||
|
|
@ -64,6 +64,9 @@ Timer-driven requests, repeat, and completion IRQs are described in [Direct Soun
|
|||
Other special-mode pairings, video capture, Game Pak DRQ, and prohibited source mode 3 return `DmaError::UnsupportedControl`.
|
||||
DMA reads below work RAM reuse known channel data as described below. They never expose BIOS bytes.
|
||||
DMA writes to DMA registers return `DmaError::RegisterDestination`; self-modifying transfers are not supported.
|
||||
Writes into the mapped 16 KiB BIOS [complete without changing its image](bios.md#writes-to-the-mapped-bios).
|
||||
Source reads, channel data, address progression, timing, and completion IRQs still apply to these ignored writes.
|
||||
DMA0–2 mask destination bit 27, so a programmed cartridge address can instead select the BIOS region.
|
||||
Other accesses use the existing memory map, alignment checks, mirrors, and I/O write rules.
|
||||
Other unmapped reads and cartridge writes remain diagnostics, not general DMA open-bus behavior.
|
||||
A failed unit changes no memory, device state, or clock. Earlier units remain committed; the failed unit remains pending.
|
||||
|
|
|
|||
|
|
@ -38,13 +38,23 @@ RCNT bit 15 was clear, so bit 8 did not enable general-purpose input/output (GPI
|
|||
GBATEK documents bits 8 and 14 as writable but unused in normal mode.
|
||||
The serial model now retains these inactive bits. Effective GPIO interrupt enable and Joybus selection still return explicit errors.
|
||||
|
||||
Both runs pass that write and now stop in the original BIOS replacement:
|
||||
That correction reached `read-only memory at 0x00000000` inside the original BIOS replacement, PC `0x00000378`.
|
||||
A bounded local trace found a Thumb `CpuSet` call with source `0x02022a74`, destination zero, and count `0x1c` halfwords.
|
||||
The caller supplied zero before entering the service. The failing original BIOS instruction was a halfword store.
|
||||
The copy routine did not corrupt the destination. Its stores encountered an overly strict memory-bus diagnostic.
|
||||
|
||||
The [mapped-BIOS write correction](../hardware/bios.md#writes-to-the-mapped-bios) now discards CPU/DMA writes without modifying firmware.
|
||||
The original copy service still executes all its reads and writes. No ROM patch or service-specific bypass was added.
|
||||
Host writes remain strict. Reference-emulator comparisons and original tests support this bounded bus behavior.
|
||||
The trace stayed local; no game code or assets were added to the repository.
|
||||
|
||||
Both runs pass the copy and now stop at an unsupported serial-transfer start:
|
||||
|
||||
```text
|
||||
Steps: 398019; instructions: 396289; IRQ entries: 2; DMA units: 1728; HALT idle: 0
|
||||
Nominal cycles: 1334271
|
||||
PC=0x00000378
|
||||
read-only memory at 0x00000000
|
||||
Steps: 426406; instructions: 424636; IRQ entries: 2; DMA units: 1768; HALT idle: 0
|
||||
Nominal cycles: 1416670
|
||||
PC=0x082e6e5c
|
||||
unsupported serial transfer start: write 0x84 at 0x04000128
|
||||
```
|
||||
|
||||
The native run captures five startup frames. These do not establish a working title screen or gameplay.
|
||||
|
|
@ -59,10 +69,10 @@ Workspace debug/release tests, strict Clippy, public ARM/Thumb/memory/BIOS check
|
|||
Native ROM-window tests and graphics smoke modes pass on Darwin arm64.
|
||||
The pinned Pong debug/release reports match.
|
||||
|
||||
The next investigation is the BIOS replacement's attempted write to address zero at PC `0x00000378`.
|
||||
Trace the service arguments and original firmware routine before deciding whether the caller or service behavior is wrong.
|
||||
The diagnostic alone does not establish the root cause. Do not make BIOS memory writable to bypass it.
|
||||
The corrected RCNT write does not establish a need for active link transfers or GPIO interrupts.
|
||||
The next investigation is the serial-transfer start at SIOCNT (`0x04000128`).
|
||||
Check RCNT mode, clock selection, disconnected-input behavior, and completion/IRQ timing before implementing a transfer model.
|
||||
Do not invent a connected partner or immediate completion to suppress the diagnostic.
|
||||
The corrected inactive RCNT write does not establish a need for GPIO interrupts.
|
||||
|
||||
Noise now has deterministic counter clocks and shares tested length/envelope logic with the independent pulse channels.
|
||||
Sweep applies only to channel 1. Direct Sound has FIFO clocks and nominal DMA requests.
|
||||
|
|
|
|||
|
|
@ -56,6 +56,7 @@ Update this file when a feature lands or a limit is removed.
|
|||
- The unchanged original ARM cancellation probe matches both published read interval totals and its unadjusted timer samples.
|
||||
- Sequential/non-sequential data accesses, branch refill costs, and variable multiply timing.
|
||||
- Optional caller-supplied 16 KiB BIOS mapping, with CPU read protection based on retained ARM PC+8 or aligned Thumb PC+4 words.
|
||||
- CPU/DMA writes to the mapped BIOS complete without changing its image; host writes retain read-only diagnostics.
|
||||
- Optional original BIOS replacement: minimal boot, SoftReset, selective RegisterRamReset, IRQ dispatch, interrupt waits, memory copy/fill, integer/fixed-point arithmetic, affine matrices, bit unpacking, LZ77/run-length/Huffman decompression, and differential filters.
|
||||
- All 16 ARM data-processing operations, with immediate and shifted-register operands.
|
||||
- Logical operations: `AND`, `EOR`, `TST`, `TEQ`, `ORR`, `MOV`, `BIC`, and `MVN`.
|
||||
|
|
@ -153,8 +154,9 @@ ROM windows have no demo-specific startup checks. Input is sampled between bound
|
|||
Audio, saves, and external BIOS loading remain unavailable. ROM loading does not establish commercial-game compatibility.
|
||||
A local Emerald run now completes its all-device reset and master sound enable.
|
||||
It also passes the pulse/noise triggers and normal-mode RCNT configuration.
|
||||
It next stops on an attempted write to address zero in the BIOS replacement at PC `0x00000378`.
|
||||
The cause remains under investigation. No title-screen, gameplay, or audible-game compatibility is established.
|
||||
It also completes a CpuSet call to address zero through the corrected ignored BIOS-write behavior.
|
||||
It next stops at an unsupported serial-transfer start (`0x04000128`, PC `0x082e6e5c`).
|
||||
No title-screen, gameplay, or audible-game compatibility is established.
|
||||
See [the startup result](research/emerald-reset.md) for the bounded run and next investigation.
|
||||
See [cartridge loading](hardware/cartridge.md) for file limits, step budgets, and exit status.
|
||||
The [ROM suite runner](rom-tests.md) has original regressions and a [pinned public ARM baseline](public-arm-tests.md).
|
||||
|
|
|
|||
|
|
@ -309,6 +309,10 @@ Status tests cover all modes, flag combinations, interrupt masks, field selectio
|
|||
Exception tests cover vectors, ARM/Thumb return addresses, nested interrupts, mask priority, and return-state restoration.
|
||||
User-bank transfers and failed returns are checked for unintended changes to active and hidden registers.
|
||||
Integration tests execute original vector handlers and check optional BIOS mapping boundaries and write protection.
|
||||
Mapped-BIOS write tests distinguish ignored CPU/DMA transfers from strict host writes without changing the supplied image.
|
||||
They cover ARM/Thumb widths, lanes, modes, block stores, swaps, timing, DMA completion, and failed boundary transfers.
|
||||
Original CpuSet/CpuFastSet callers verify ignored BIOS destinations without bypassing source reads or the service instructions.
|
||||
Desktop DMA-error fixtures use an unmapped destination because DMA0 masks cartridge destination addresses into the BIOS region.
|
||||
Original BIOS-access regressions check retained ARM PC+8 and aligned Thumb PC+4 words for ARM/Thumb callers.
|
||||
They cover all processor modes, load widths, lanes, rotation, both Thumb code alignments, and distinct halfwords.
|
||||
They verify direct reads while executing inside BIOS, re-entry, SWI/IRQ returns, host-inspection isolation, and original-boot provenance.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue