Skip to content
DoubleGate edited this page Jul 8, 2026 · 1 revision

MOS 6532 RIOT

The RIOT (RAM-I/O-Timer; called "PIA" in the Stella Programmer's Guide) has no direct analog in most other consoles Rusty2600's sibling emulators cover — it's a standard MOS 6532, entirely independent of the TIA. It supplies the three things the VCS needs outside the TIA: the console's only RAM, its two I/O ports, and an interval timer.

Audio is NOT here. The Atari 2600's two sound channels live entirely in the TIA (see TIA); the 6532 has no sound hardware of any kind. This is worth stating plainly since a reader coming from another console's architecture might otherwise assume a chip named "I/O and Timer" also carries sound — it doesn't, on this console.

RAM — the console's only general RAM

128 bytes, at $80..=$FF. There is no separate work RAM on the 2600 — this is it, and the CPU stack overlaps this same region (the 6502 $0100 stack page maps into the RIOT RAM mirror). Rusty2600's Bus therefore has no wram field at all; the RIOT's own RAM array is the entire story. Power-on RAM contents are randomized from the same seeded PRNG that seeds CPU register state (see Architecture-Decision-Records ADR 0004/0006), never the OS RNG.

I/O ports

Port Address DDR Contents
SWCHA $280 SWACNT ($281) Port A: the two joystick directionals (and paddle/keypad multiplexing)
SWCHB $282 SWBCNT ($283) Port B: console switches — Reset, Select, Color/B&W, the two difficulty switches

Idle inputs read high (pulled up): ports power on to 0xFF.

Interval timer

Writing the count to one of four prescaler-selecting addresses starts the timer decrementing at that rate:

Write addr Name Prescale Tick period (NTSC)
$294 TIM1T 1 CPU cycle 838 ns
$295 TIM8T 8 cycles 6.7 µs
$296 TIM64T 64 cycles 53.6 µs
$297 T1024T 1024 cycles 858.2 µs (power-on default)

Read the current value at INTIM ($284) and the underflow status at INSTAT ($285, undocumented). After hitting zero, the timer holds 0 for one prescale interval, then wraps to $FF and decrements once per CPU cycle — the classic "fast rollover" real hardware exhibits. Because the 6507 has no interrupt lines, the timer cannot fire an IRQ; software must poll INTIM, and this is the 2600's only substitute for a frame interrupt.

A real hardware bug the emulator faithfully reproduces

Once the timer underflows, real 6532 silicon decrements at the forced 1-CPU-cycle rate until the next time a program reads INTIM — at which point the divider reverts to the originally-selected prescale. Rusty2600 originally modeled this as two separate flags (one for the INSTAT-visible interrupt latch, one for the actual decrement-rate gate) rather than the single flag real silicon uses for both, which meant a program's timer, once underflowed even once, stayed in fast mode forever. This was found via a real differential-testing session against Gopher2600 and Stella on Pitfall II's boot-time RIOT-timer wait loop, and fixed to match the confirmed real-hardware behavior exactly. See Testing-Strategy for more on how this kind of bug gets found.

Timing

The RIOT advances on the CPU cycle (every third TIA color clock); the interval timer is further prescaled by 1/8/64/1024. See Lockstep-Scheduler for the full divisor table.

See also

Architecture-Overview · Lockstep-Scheduler · CPU-6507 · TIA

Clone this wiki locally