pub enum Cpu2A03Revision {
Rp2A03G,
Rp2A03H,
}Expand description
Ricoh 2A03 CPU/APU die revision, selecting the hardware-revision difference in the DMA unit’s “unexpected DMA” extra halt-read (v2.1.7 “Hardware Revisions & DMA Frontier”).
§The frontier — read this before trusting the non-default arm
The 2A03 shipped in several mask revisions. nesdev
(DMA) documents that when a DMC DMA halt
is requested on a CPU cycle where an OAM ($4014) DMA is also halting —
the “double-halt” overlap — some silicon performs an extra re-read of
the parked 6502 address bus before the transfer resumes (the “unexpected
DMA” read), and this differs by die revision.
No public reference emulator models this die-revision difference, and no
public test ROM verifies it. A survey of Mesen2, ares, BizHawk,
TriCNES, fceux, nestopia, GeraNES, and higan (v2.1.7, see ADR 0033)
found that none
branch DMA cycle behavior on 2A03 die stepping — the only revision-like
switch any of them models is the orthogonal console-type distinction
(Mesen2 isNesBehavior: NES-001/AV-Famicom clock a controller only on the
first DMA idle read, original Famicom on every one), which is a
different axis and is already reflected in this core’s default
register-readout model. The die-revision extra-read is therefore a genuine
open frontier: this enum provides the config surface for it and a
conservative, deterministic model, but the Rp2A03H arm’s
direction is an unverified hypothesis, not an oracle-proven behavior.
§Contract
- Default =
Rp2A03Gis byte-identical to the core as it shipped before v2.1.7 (AccuracyCoin141/141, nestest 0-diff, and every committed DMA oracle ROM — the fivedmc_dma_during_read4ROMs and bothsprdma_and_dmc_dmaROMs — stillPassed). Rp2A03His a purely additive, opt-in knob that omits the double-halt extra read in the model. It is deterministic and reachable only when explicitly selected; the shipped/default build never touches it. On this engine the extra-read gate is a documented no-op on every committed oracle, so todayRp2A03Hproduces a byte-identical result toRp2A03Gacross the entire committed DMA corpus (proven by thecpu_2a03_revisiontests): the halted-DMC overlap-read fires but its parked address is always the post-$4014instruction fetch, never a side-effect register (see below). The revision difference is therefore a mechanism-level model, not an observable divergence — ADR 0033.
The revision is a config knob re-applied on load, not part of the
save-state (like the optional OAM-decay model): the only state it
influences is fully re-derived from the deterministic timeline, so a
save/restore round-trip stays byte-identical for a fixed revision. See
docs/adr/0033-cpu-2a03-revision-dma-frontier.md.
Variants§
Rp2A03G
RP2A03G — the common early/mid die the accuracy oracles were captured against. Performs the double-halt “unexpected DMA” extra read. This is the default and the byte-identical baseline.
Rp2A03H
RP2A03H — a later die modeled as omitting the double-halt extra read. Opt-in, additive, deterministic — but an unverified direction (no reference / no ROM proves it; see the type-level docs and ADR 0033).
Implementations§
Source§impl Cpu2A03Revision
impl Cpu2A03Revision
Sourcepub const fn has_unexpected_dma_extra_read(self) -> bool
pub const fn has_unexpected_dma_extra_read(self) -> bool
Trait Implementations§
Source§impl Clone for Cpu2A03Revision
impl Clone for Cpu2A03Revision
Source§fn clone(&self) -> Cpu2A03Revision
fn clone(&self) -> Cpu2A03Revision
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read more