Skip to main content

Cpu2A03Revision

Enum Cpu2A03Revision 

Source
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 = Rp2A03G is byte-identical to the core as it shipped before v2.1.7 (AccuracyCoin 141/141, nestest 0-diff, and every committed DMA oracle ROM — the five dmc_dma_during_read4 ROMs and both sprdma_and_dmc_dma ROMs — still Passed).
  • Rp2A03H is 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 today Rp2A03H produces a byte-identical result to Rp2A03G across the entire committed DMA corpus (proven by the cpu_2a03_revision tests): the halted-DMC overlap-read fires but its parked address is always the post-$4014 instruction 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

Source

pub const fn has_unexpected_dma_extra_read(self) -> bool

Whether this revision performs the “unexpected DMA” extra re-read of the parked address bus on the DMC-halt-coincides-with-OAM-halt overlap cycle. true for Rp2A03G (the default / byte-identical baseline), false for Rp2A03H.

Trait Implementations§

Source§

impl Clone for Cpu2A03Revision

Source§

fn clone(&self) -> Cpu2A03Revision

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for Cpu2A03Revision

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for Cpu2A03Revision

Source§

fn default() -> Cpu2A03Revision

Returns the “default value” for a type. Read more
Source§

impl Hash for Cpu2A03Revision

Source§

fn hash<__H: Hasher>(&self, state: &mut __H)

Feeds this value into the given Hasher. Read more
1.3.0 · Source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where H: Hasher, Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
Source§

impl PartialEq for Cpu2A03Revision

Source§

fn eq(&self, other: &Cpu2A03Revision) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl Copy for Cpu2A03Revision

Source§

impl Eq for Cpu2A03Revision

Source§

impl StructuralPartialEq for Cpu2A03Revision

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.