pub const APU_SNAPSHOT_VERSION: u8 = 4;Expand description
Schema version for the APU snapshot blob.
-
v1 (v0.9.0 .. v1.0.0-rc2): original schema with
FrameCountercarrying apending_irq_clear: boolconsumed at the next tick. -
v2 (Session-25, 2026-05-23):
FrameCounterreplaces the bool with airq_flag_clear_cycle: u64lazy-clear schedule mirroring Mesen2’s_irqFlagClearClock. Old v1 blobs restore by migrating the bool to a synthesized schedule (a pending clear becomes “schedule forcpu_cycle + 1”, a fresh clear). -
v3 (Session-26 Sprint 2 iter 5, 2026-05-23 onwards):
FrameCounteraddsirq_line_active: boolas a SEPARATE field fromirq_flag. v2 blobs migrate by setting both fields to the v2irq_flagvalue (the IRQ-line state coincided with $4015 bit 6 visibility under the v2 conflated model). Per ADR-0003, the v2 -> v3 migration may show a 1-cycle transient where a reloaded inhibited state has the CPU IRQ line deasserted as the FC step re-establishes it — acceptable. -
v4 (2026-07-22): appends the scheduled warm-reset
$4017re-write (reset_4017_delay+reset_4017_value, 2 bytes).Apu::resetarms the countdown at 2 andtick_with_externaldecrements it once per CPU cycle, issuingFrameCounter::writewhen it hits zero (the v2.0.0 beta.3 A4 cycle-accurate reset, calibrated against blargg4017_timing). Both fields were previously unserialized, so a snapshot taken inside that 2-cycle window restoreddelay = 0and dropped the re-write entirely — the restored frame counter then kept the sequencer phase the re-write was supposed to reset. This is the same class as the PPU’s v5 / v6 / v8 tails (ADR 0030 / ADR 0034): live mid-frame state absent from the schema, invisible to any straight-run_frametest and reachable only through a snapshot/restore round trip. Surfaced by the standing schema audit (crates/rustynes-test-harness/tests/snapshot_schema_audit.rs) rather than by a user-visible symptom.v1..=3 blobs upconvert with both at
0— “no re-write pending”, which is the resting value and therefore correct for any pre-v4 state not captured inside the 2-cycle arming window (and for one that was, the bytes simply do not exist to recover).Unlike this module’s earlier trailing-optional tails (the v1.x DMC-DMA scheduling bytes and the W3-Stage-4 block, both detected by
has_remaining), this one is version-gated. Trailing-optional makes two different blob lengths both valid at one version, which is workable but leaves the format ambiguous; a version gate does not. The bump costs no additional compatibility here because the same change already bumpsPPU_SNAPSHOT_VERSIONto 8 (ADR 0034), andrustynes_core’s.rnscontainer is version-exact per section — pre-existing save states are already rejected at the PPU section.