Expand description
The master-clock lockstep scheduler — the heart of the emulator.
Timing master: the TIA color clock @ 3.579545 MHz (NTSC). The 6507 CPU advances on every third color clock (the VCS divides the color clock by 3 to make the CPU’s φ0) — LOCKSTEP, not catch-up: a mid-instruction TIA register write takes effect at the exact color clock it’s written on, not after the whole instruction “finishes.”
The CPU drives this directly: System::step_instruction runs one full
6507 instruction via [rusty2600_cpu::Cpu::step], and every cycle THAT
instruction consumes calls back into [CpuView::tick_cycle] (via
[rusty2600_cpu::CpuBus::tick_cycle]) to advance the TIA by exactly 3
color clocks, the RIOT by one tick, and the cart coprocessor by one tick —
cycle by cycle as the instruction executes, not all at once when it
returns. (An earlier version of this scheduler called cpu.tick() once per
color clock expecting it to consume exactly one CPU cycle, but the CPU
actually ran the whole instruction synchronously per call — racing far
ahead of the color clock it was supposed to be locked to. That mismatch is
why object-positioning routines, which time themselves against the color
clock via WSYNC + a cycle-counted delay, never reached realistic
positions. See the regression test below.)
The WSYNC / RDY beam-stall. When the program strobes WSYNC, the TIA
pulls RDY low, and the 6507 freezes BEFORE its next cycle (typically the
next instruction’s opcode fetch) until the TIA releases RDY at the end of
HBLANK. The TIA owns the signal (Tia::rdy_stall); [CpuView::rdy_stall]
exposes it to the CPU crate, which spins on [CpuView::tick_cycle] while
it’s asserted — the color clock (and RIOT/cart) keep advancing, only the
CPU is frozen.
Determinism contract: same seed + ROM + input ⇒ bit-identical AV. The
per-power-on CPU/color-clock phase alignment comes from a SEEDED PRNG
(never the OS RNG) applied as a one-time 0..3 extra-color-clock offset
before the CPU’s first cycle. See docs/scheduler.md.
Structs§
- System
- Owns the run loop and the lockstep timebase.