Skip to main content

Module scheduler

Module scheduler 

Source
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.