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
|
|
@ -48,6 +48,9 @@ The repository is a Cargo workspace with three crates:
|
|||
| `crates/gba-core/src/cpu/transfer_tests.rs` | Stack, addressing, overlap, empty-list, and swap tests |
|
||||
| `crates/gba-core/src/cpu/tests.rs` | Condition truth tables and immediate arithmetic tests |
|
||||
| `crates/gba-core/src/cpu/instruction_tests.rs` | Register operations, transfers, branches, and edge cases |
|
||||
| `crates/gba-core/src/cartridge.rs` | Explicit GPIO/RTC selection, ROM read overlay, pin directions, serial command/control, and bounded diagnostics |
|
||||
| `crates/gba-core/tests/cartridge_gpio.rs` | GPIO lanes, ROM preservation, RTC framing/control/aborts, unsupported commands, and DMA3 access |
|
||||
| `crates/gba-core/src/memory/cartridge_step_tests.rs` | ARM/Thumb GPIO timing, rejected command-edge rollback, block preflight, and staged fetch/read overlays |
|
||||
| `crates/gba-core/src/memory.rs` | Memory mapping, I/O routing, write validation, and device clock |
|
||||
| `crates/gba-core/src/memory/fetch.rs` | Strict instruction samples with captured region-dependent bus observations |
|
||||
| `crates/gba-core/src/memory/fetch_tests.rs` | Fetch widths, bus lanes, captured refill/BIOS values, strict errors, and side-effect isolation |
|
||||
|
|
|
|||
104
docs/hardware/cartridge-gpio.md
Normal file
104
docs/hardware/cartridge-gpio.md
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
# Game Pak GPIO and RTC control subset
|
||||
|
||||
The core supports an explicitly selected cartridge GPIO interface and RTC command/control transactions.
|
||||
GPIO means general-purpose input/output. RTC means real-time clock.
|
||||
Calendar access, clock advancement, battery persistence, RTC interrupts, and other cartridge sensors remain unimplemented.
|
||||
Unsupported operations return diagnostics. No fabricated date or successful calendar transfer is reported.
|
||||
|
||||
## Selection
|
||||
|
||||
`Memory::set_cartridge_hardware(CartridgeHardware::Rtc)` attaches the bounded interface with initial state.
|
||||
`CartridgeHardware::None` is the default. Selecting either option replaces peripheral state, without changing ROM bytes.
|
||||
Call this API between machine steps. The core does not inspect filenames, game headers, or library signatures to select hardware.
|
||||
|
||||
The desktop enables this interface with `--rtc`, in either ROM execution mode:
|
||||
|
||||
```sh
|
||||
direnv exec . cargo run --locked --release -- --rom roms/pokemon-emerald.gba --rtc --steps 2000000
|
||||
direnv exec . cargo run --locked --release -- --rom roms/pokemon-emerald.gba --rtc --window --frames 60
|
||||
```
|
||||
|
||||
The report states that only GPIO and command/control are supported.
|
||||
The JSON suite schema does not yet select cartridge peripherals. Its default remains no attached peripheral.
|
||||
There is no host-clock dependency, ROM patch, save file, or automatic device detection.
|
||||
|
||||
## GPIO registers
|
||||
|
||||
| Address | Register | Retained bits |
|
||||
| --- | --- | --- |
|
||||
| `0x080000c4` | Data output latch and pin samples | 0–3 |
|
||||
| `0x080000c6` | Direction: 0=input, 1=output | 0–3 |
|
||||
| `0x080000c8` | Read enable: 0=ROM reads, 1=register reads | 0 |
|
||||
|
||||
All other register bits read zero when read enable is set. Initial direction, data latch, and read enable are zero.
|
||||
With read enable clear, reads return the original supplied ROM bytes, including nonzero bytes.
|
||||
Disabling reads does not disable writes or reset an RTC transaction.
|
||||
ROM bytes are never overwritten with register values.
|
||||
|
||||
Data writes retain an output latch independently of direction.
|
||||
Output pins read their driven latch bits. Changing direction can expose a retained output and create an RTC signal edge.
|
||||
The RTC mapping uses bit 0 for clock, bit 1 for bidirectional data, and bit 2 for chip select.
|
||||
The bounded input model holds clock, select, and the unused pin low; RTC data is high outside a read transaction.
|
||||
This input policy follows the pinned reference implementation, not independent physical measurements.
|
||||
No solar sensor, rumble, gyro, or cartridge interrupt source is attached.
|
||||
|
||||
Aligned halfword writes are supported. A word at `0x080000c4` applies data, then direction, as two ordered halfwords.
|
||||
A rejected second halfword leaves both registers unchanged under the core's diagnostic policy.
|
||||
A word at `0x080000c8` reaches ordinary ROM at `0x080000ca` and fails without changing control.
|
||||
Byte writes are diagnostic because the consulted bus-width description is uncertain about GBA versus DS behavior.
|
||||
Byte, halfword, and word reads use ordinary little-endian lanes, including register/ROM boundaries.
|
||||
|
||||
Only the documented first-window addresses are implemented.
|
||||
Other ROM windows still expose supplied ROM bytes; their writes remain read-only diagnostics.
|
||||
GPIO mirroring and writes at alias addresses have not been independently validated.
|
||||
Without explicit hardware selection, all these addresses remain ordinary read-only cartridge memory.
|
||||
|
||||
## RTC command and control transfers
|
||||
|
||||
Chip select rising with clock high begins a command. Chip select falling aborts the current transaction.
|
||||
Command bits enter on rising clock edges after software establishes data while clock is low.
|
||||
The first four command bits on the wire must be `0,1,1,0`.
|
||||
GBATEK's forward and reverse command-byte representations describe this same wire sequence, not interchangeable wire prefixes.
|
||||
Control parameters transfer least-significant bit first.
|
||||
During reads, the RTC supplies each bit on the falling edge. GPIO reads do not advance the serial state.
|
||||
|
||||
Using GBATEK's MSB-first command representation:
|
||||
|
||||
- `0x62` writes one control byte; `0x63` reads one control byte.
|
||||
- `0x60` and `0x61` reset supported control state to zero. Calendar reset side effects are not implemented.
|
||||
- `0x64` through `0x67` return an explicit calendar-access diagnostic.
|
||||
- `0x6c` and `0x6d` return an explicit force-interrupt diagnostic.
|
||||
- Unused commands and invalid command prefixes remain diagnostic.
|
||||
|
||||
Initial control is `0x40`, a deterministic powered 24-hour-mode setting.
|
||||
Bit 6 is writable. Unused bits and read-only bit 7 do not retain writes.
|
||||
Writes enabling bits 1, 3, or 5 fail because their interrupt or uncertain control behavior is not implemented.
|
||||
No power-failure condition is synthesized. There is no calendar value behind this control setting yet.
|
||||
|
||||
A partial control write does not commit. A complete byte commits at its final rising edge.
|
||||
Extra clocks beyond the documented parameter length remain diagnostic rather than guessing repeated transfers.
|
||||
Selecting with clock low, driving data during read clocks, and changing data at a sampling edge also remain diagnostic.
|
||||
Minimum physical setup/hold durations, signal races, and exact analog behavior are not modeled.
|
||||
|
||||
## Bus integration and tests
|
||||
|
||||
CPU and DMA accesses retain Game Pak wait-state costs.
|
||||
Machine steps stage cartridge state separately from ROM bytes. Failed steps discard pin edges and control changes.
|
||||
Block-store preflight applies earlier pin/direction changes before validating later accesses.
|
||||
A later diagnostic leaves earlier RAM, GPIO, and CPU state unchanged.
|
||||
Data reads and instruction fetches share the selected register overlay. Fetches have no serial side effects.
|
||||
|
||||
Original tests cover selection, masks, directions, retained latches, read enable, widths, ROM preservation, and command framing.
|
||||
They check control reads/writes/reset, aborts, both command-byte representations, edge stability, and unsupported commands.
|
||||
ARM/Thumb, DMA3, block preflight, staged fetches, retryable errors, and nominal bus costs have separate regressions.
|
||||
File-backed desktop tests check explicit `--rtc` selection, unchanged files, option rejection, and native-window propagation.
|
||||
These tests validate the bounded implementation, not physical RTC timing or game playability.
|
||||
|
||||
## References
|
||||
|
||||
- [GBATEK cartridge GPIO](https://problemkaputt.de/gbatek-gba-cart-i-o-port-gpio.htm): register addresses, masks, directions, read control, and uncertain byte-store behavior.
|
||||
- [GBATEK GBA RTC](https://problemkaputt.de/gbatek-gba-cart-real-time-clock-rtc.htm): control fields, reset, calendar formats, and command mapping relative to the DS chip.
|
||||
- [GBATEK DS RTC](https://problemkaputt.de/gbatek-ds-real-time-clock-rtc.htm): the linked serial flow, chip-select sequencing, bit edges, and forward/reverse command representations. GBA register differences remain separate.
|
||||
- [mGBA GPIO at 3a5e34be](https://github.com/mgba-emu/mgba/blob/3a5e34be33dc7f8f707e5bc9db69e8a430046f21/src/gba/cart/gpio.c): comparison for retained outputs, direction changes, idle inputs, serial edges, and initial control. Its host-clock lookup, ROM-buffer mutation, and repeated transfers are not copied.
|
||||
- [mGBA memory at 3a5e34be](https://github.com/mgba-emu/mgba/blob/3a5e34be33dc7f8f707e5bc9db69e8a430046f21/src/gba/memory.c): first-window halfword GPIO write routing. This is not physical proof of all address aliases.
|
||||
- [Explaining GBA RTC](https://bmchtech.github.io/post/rtc/): introductory background surfaced during research; the author explicitly warns that details may be inaccurate. Register and protocol decisions use the references above.
|
||||
|
|
@ -33,9 +33,13 @@ It does not decode archives or ELF executables. Supply a raw binary with an ARM
|
|||
Headerless original programs are accepted.
|
||||
Reads past supplied cartridge bytes remain explicit memory errors, not open-bus values.
|
||||
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.
|
||||
Ordinary cartridge bytes remain read-only. Save devices remain unsupported.
|
||||
Optional `--rtc` selection enables the bounded [Game Pak GPIO and RTC control interface](cartridge-gpio.md).
|
||||
It supports configuration and control transactions, not calendar access, clock advancement, or RTC interrupts.
|
||||
|
||||
Both modes call `bios::boot` with the loaded bytes.
|
||||
With `--rtc`, the host then selects the cartridge peripheral before the first machine step.
|
||||
Without that option, no cartridge peripheral is attached. Duplicate `--rtc` options are rejected.
|
||||
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. RegisterRamReset now accepts sound/serial reset flags, including `r0=0xff`, within the initialization subset.
|
||||
|
|
|
|||
|
|
@ -25,8 +25,8 @@ Byte, halfword, word, block-store, and DMA validation retain explicit errors wit
|
|||
Use a local ROM that you may lawfully use:
|
||||
|
||||
```sh
|
||||
direnv exec . cargo run --locked --release -- --rom roms/pokemon-emerald.gba --steps 1000000
|
||||
direnv exec . cargo run --locked --release -- --rom roms/pokemon-emerald.gba --window --frames 120
|
||||
direnv exec . cargo run --locked --release -- --rom roms/pokemon-emerald.gba --rtc --steps 2000000
|
||||
direnv exec . cargo run --locked --release -- --rom roms/pokemon-emerald.gba --rtc --window --frames 60
|
||||
```
|
||||
|
||||
The earlier reset-only implementation stopped at master sound enable (`0x04000084`, PC `0x082e0518`).
|
||||
|
|
@ -64,13 +64,18 @@ A child cannot start itself without a parent clock. No linked transfer, assigned
|
|||
The send register supports 16-bit data; receive latches do not become invented peer data.
|
||||
See [the register model and evidence limits](../hardware/serial.md#disconnected-multiplayer-configuration).
|
||||
|
||||
Both terminal and native runs now reach a Game Pak GPIO control write:
|
||||
Multiplayer configuration then reached a Game Pak GPIO control write (`0x080000c8`, PC `0x082e29f8`).
|
||||
The optional [cartridge GPIO/RTC interface](../hardware/cartridge-gpio.md) now supports read enable, directions, pin latches, and RTC control transactions.
|
||||
Select it explicitly with `--rtc`; ordinary ROM bytes and other ROMs' default hardware remain unchanged.
|
||||
No host date, RTC calendar, or successful calendar read is invented.
|
||||
|
||||
Both terminal and native runs with `--rtc` now reach a calendar-read command:
|
||||
|
||||
```text
|
||||
Steps: 956055; instructions: 953375; IRQ entries: 80; DMA units: 2600; HALT idle: 0
|
||||
Nominal cycles: 3514932
|
||||
PC=0x082e29f8
|
||||
read-only memory at 0x080000c8
|
||||
Steps: 957729; instructions: 955049; IRQ entries: 80; DMA units: 2600; HALT idle: 0
|
||||
Nominal cycles: 3520685
|
||||
PC=0x082e28a6
|
||||
unsupported RTC calendar access: write 0x07 at 0x080000c4
|
||||
```
|
||||
|
||||
The native run captures twelve startup frames. These do not establish a working title screen or gameplay.
|
||||
|
|
@ -85,10 +90,11 @@ 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 requirement is cartridge GPIO, starting with the control register at `0x080000c8`.
|
||||
Research the Game Pak data/direction/control registers and real-time clock protocol before implementing them.
|
||||
Keep ordinary ROM writes read-only. Do not hide the failure by ignoring every cartridge write.
|
||||
This serial result does not establish linked gameplay or serial GPIO interrupt support.
|
||||
The next requirement is RTC calendar transfers with an explicit clock-source model.
|
||||
Implement validated date/time formats, read snapshots, writes/reset, and clock ownership without putting host time in the core.
|
||||
Keep battery persistence and cartridge IRQ behavior explicit; do not equate GBA STOP with stopping a battery-powered RTC.
|
||||
Ordinary ROM writes remain read-only. Without `--rtc`, the earlier GPIO diagnostic is still expected.
|
||||
This result does not establish gameplay, linked transfers, or cartridge/serial GPIO interrupt support.
|
||||
|
||||
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.
|
||||
|
|
|
|||
|
|
@ -76,6 +76,8 @@ 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.
|
||||
- Explicit cartridge RTC selection with first-window GPIO read enable, direction/latch behavior, and serial command/control transactions.
|
||||
- Cartridge GPIO changes participate in CPU/DMA rollback and block-store preflight without modifying ROM bytes.
|
||||
- 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.
|
||||
- RegisterRamReset supports disabled sound and disconnected serial initialization, including the common `r0=0xff` request.
|
||||
|
|
@ -139,6 +141,8 @@ Horizontal window comparators retain four-cycle event history.
|
|||
Sprite rows prepare one line ahead with a whole-row cycle40 sample and nominal per-row work limits.
|
||||
Individual fetch timing, hardware-accurate work cutoffs, video-bus contention, and per-pixel color composition remain unimplemented.
|
||||
There is no host audio output or cartridge save support.
|
||||
The optional [cartridge GPIO/RTC subset](hardware/cartridge-gpio.md) supports command/control only, selected with `--rtc` in ROM modes.
|
||||
RTC calendar access, clock advancement, persistence, interrupts, GPIO aliases, and byte writes remain unsupported or unverified.
|
||||
The [audio subset](hardware/audio.md) supports Direct Sound, both PSG pulse channels, noise channel 4, idle wave channel 3 state, and instantaneous digital mixing.
|
||||
It does not yet provide a continuous sample stream. Wave channel 3 playback and unverified sound-DMA pairings remain diagnostic.
|
||||
PSG timing and signed mixing are nominal; hardware startup edges and analog behavior remain unverified.
|
||||
|
|
@ -161,7 +165,9 @@ It also passes the pulse/noise triggers and normal-mode RCNT configuration.
|
|||
It also completes a CpuSet call to address zero through the corrected ignored BIOS-write behavior.
|
||||
It also accepts an external-clock serial request without inventing clock edges or completion.
|
||||
It now also completes internally clocked normal transfers and selects idle multiplayer mode.
|
||||
It next stops at a Game Pak GPIO control write (`0x080000c8`, PC `0x082e29f8`). Cartridge GPIO remains unimplemented.
|
||||
With explicit `--rtc` selection, it also passes Game Pak GPIO configuration and reaches an RTC calendar-read command.
|
||||
That command remains diagnostic (`0x080000c4`, PC `0x082e28a6`); no date is fabricated.
|
||||
Without `--rtc`, cartridge GPIO writes still return read-only diagnostics.
|
||||
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.
|
||||
|
|
@ -192,7 +198,7 @@ Host inspection and instruction fetches remain strict. Other unmapped reads retu
|
|||
Reads beyond the supplied cartridge bytes also return errors.
|
||||
Direct memory-bus halfword and word accesses require alignment.
|
||||
CPU load/store instructions apply ARM7TDMI alignment and rotation rules before accessing the bus.
|
||||
Writes to cartridge addresses return errors instead of modeling cartridge hardware.
|
||||
Ordinary ROM writes remain read-only. Only the explicitly selected cartridge GPIO register subset accepts writes.
|
||||
|
||||
## Next steps
|
||||
|
||||
|
|
|
|||
|
|
@ -65,6 +65,11 @@ They verify suite selection, pinned URLs, hashes, sizes, checkpoint validation,
|
|||
The [Pong adapter](public-pong.md) has additional offline tests for its pinned downloads, retained license, and bounded gameplay scenarios.
|
||||
Run the external Pong suite separately; ordinary Cargo and Python tests require no public ROM or network access.
|
||||
Device initialization regressions use original instructions to check disabled sound, wave RAM, disconnected serial pins, and reset flags.
|
||||
Cartridge GPIO tests use an explicitly attached RTC control subset and original pin sequences, never game code or host time.
|
||||
They cover read overlays, unchanged ROM bytes, masks, directions, widths, serial framing, control/reset, aborts, and explicit calendar/IRQ diagnostics.
|
||||
ARM/Thumb and DMA3 checks retain Game Pak costs; staged fetches, rejected edges, and block-store preflight retain diagnostic atomicity.
|
||||
Desktop tests check explicit `--rtc` selection, duplicate rejection, unchanged files, and native-window configuration.
|
||||
Physical pin timing, GPIO aliases, RTC calendar values, and battery behavior remain unverified or unimplemented.
|
||||
They verify explicit activation errors and atomic byte/word/block-store/DMA failure behavior.
|
||||
The optional [local Emerald startup check](research/emerald-reset.md) now reaches sound activation but still fails deliberately there.
|
||||
[Jev evidence review](jev-debugging.md) is optional and never changes deterministic test verdicts.
|
||||
|
|
|
|||
|
|
@ -40,10 +40,11 @@ The native Darwin window also starts and presents frames without a diagnostic.
|
|||
This exposed and corrected missing firmware affine-scale initialization, without a game-specific patch.
|
||||
Frame-based scenarios and the preparation adapter now make the result repeatable.
|
||||
A local Emerald run now passes its initial all-device reset, master sound enable, and pulse/noise triggers.
|
||||
It also passes normal serial transfers and idle multiplayer configuration, then stops at Game Pak GPIO control.
|
||||
It also passes normal serial transfers and idle multiplayer configuration.
|
||||
With `--rtc`, it passes Game Pak GPIO setup and stops at the first unsupported RTC calendar-read command.
|
||||
The core has tested Direct Sound, both pulse channels, and noise channel 4.
|
||||
Wave channel 3, a continuous sample stream, and desktop audio output remain missing.
|
||||
See [the runtime result](research/emerald-reset.md). Cartridge GPIO and its real-time clock protocol are the next demonstrated startup investigation.
|
||||
See [the runtime result](research/emerald-reset.md). RTC calendar transfers and an explicit clock-source model are the next startup requirement.
|
||||
The separate save requirement remains cartridge SRAM, followed by safe host save persistence.
|
||||
SRAM is byte-addressable battery-backed save memory. Flash and EEPROM remain separate protocols.
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue