psx.wiki

Root Counters

Three 16-bit hardware timers and the vertical sync counter of the PlayStation.

This is an old revision of this page, as edited by RemmyLee at 02:44, 23 October 2026. Edit this revision | Latest revision

Summary

The root counters are timers that count automatically. Sony provides them for time limits and timing adjustments, which game programs need. A counter counts up from zero, and when it reaches its target value it generates an interrupt, clears to zero and starts again. Each interrupt can be masked.1

Sony's libraries name four root counters. RCntCNT0 to RCntCNT2 are 16-bit hardware timers with registers at 1F801100h, 1F801110h and 1F801120h. The table below shows all four. RCntCNT3 counts vertical synchronization, and its target value is fixed at 1, so it generates an interrupt at each vertical blank.12

Table 1: Root counters
Macro Registers Clock sources Notes
RCntCNT0 1F801100h System clock or dot clock
RCntCNT1 1F801110h System clock or H-blank Target value more than 2
RCntCNT2 1F801120h System clock or system clock / 8 Target value more than 2
RCntCNT3 None Vertical synchronization Target value is fixed at 1; halting the count is invalid

The Notes column is Sony's. psx-spx documents no timer registers for the vertical sync counter. The vertical blank reaches the CPU as IRQ0 in I_STAT, while the three hardware timers raise IRQ4, IRQ5 and IRQ6.134

Registers

Each hardware timer has three registers at its base address. Official names for the registers and bits are in timerman.h of Sony's PlayStation 2 IOP SDK, which psx-spx follows. The PlayStation libraries call the third register TARGET.2

Table 2: Timer registers
Address Name Content
1F801100h + 10h x N COUNT Current counter value (R/W)
1F801104h + 10h x N MODE Counter mode (R/W)
1F801108h + 10h x N COMP (TARGET) Counter target value (R/W)

COUNT - Current Value

Bits 0 to 15 hold the current counter value and bits 16 to 31 are garbage. The counter increments by itself and may be written with any value. It is reset to 0000h on every write to MODE and when it reaches its reset condition, which is either FFFFh or the target value.5

A current value written above the target value does not match the target on the way up. The counter therefore runs to FFFFh, wraps to 0000h once and only then uses the target value.5

MODE - Counter Mode

MODE selects the synchronization, reset point, interrupt conditions and clock source of a counter:6

Table 3: MODE bits
Bits Name Content
0 GATF Synchronization enable (0 = free run, 1 = synchronize by GATM)
1 to 2 GATM Synchronization mode (0 to 3, see below)
3 ZRET Reset counter to 0000h (0 = after FFFFh, 1 = after COMP)
4 CMP IRQ when counter = COMP (0 = off, 1 = on)
5 OVFL IRQ when counter = FFFFh (0 = off, 1 = on)
6 REPT IRQ once or repeatedly (0 = one-shot, 1 = repeat)
7 LEVL IRQ pulse or toggle (0 = short pulse of INTF = 0, 1 = toggle INTF)
8 EXTC Clock source of timers 0 and 1 (0 = system clock, 1 = dot clock or H-blank)
9 PSCL Prescaler of timer 2 (0 = divide by 1, 1 = divide by 8)
10 INTF Interrupt request (0 = yes, 1 = no), set by a write (R)
11 EQUF Reached COMP (0 = no, 1 = yes), reset after reading (R)
12 OVFF Reached FFFFh (0 = no, 1 = yes), reset after reading (R)
13 to 15 Unused (zero)
16 to 31 Garbage

The meaning of GATM depends on the counter. Timer 0 synchronizes to H-blank and timer 1 to V-blank with the same four modes, while timer 2 has only two behaviors:6

Table 4: Synchronization modes
GATM Timer 0 (H-blank) and timer 1 (V-blank) Timer 2
0 Pause the counter during the blank Stop the counter at its current value
1 Reset the counter to 0000h at the blank Free run
2 Reset at the blank and pause outside it Free run
3 Pause until the first blank, then free run Stop the counter at its current value

In one-shot mode the interrupt is pulsed or toggled only once. The counter keeps counting, but further interrupts are suppressed until MODE is written again. If both CMP and OVFL are set, one-shot mode triggers only the condition that occurs first.6

Pulse mode is the normal setting. INTF then stays 1 except for a few clock cycles at each interrupt. In toggle mode INTF is set by the write to MODE and inverts at each interrupt, so in repeat mode IRQ4 to IRQ6 occur only on every second match, when INTF changes from 1 to 0.6

COMP - Target Value

Bits 0 to 15 hold the target value and bits 16 to 31 are garbage. With ZRET set the counter counts up to and including the target value and then restarts at 0000h.7

Reset and Wrap Timing

A counter reset by a write to MODE stays at 0000h for 2 clock cycles before it counts. A written current value likewise stays for 2 cycles before the counter counts or checks the target. A wrap at FFFFh holds 0000h for only 1 cycle, but a reset at the target value holds 0000h for 2 cycles.8

With a target of 0001h and ZRET set the counter therefore repeats the sequence 0000h 0000h 0001h.8

Clock Sources and Counter Timing

One system clock tick is about 0.03 microseconds. The display counters run at the timings below:9

Table 5: Counter timing
Counter event NTSC PAL Unit
Vertical sync 1/60 1/50 Second
Horizontal sync 63.56 64.00 Microsecond
Pixel display N x 0.0186243 N x 0.01879578 Microsecond

The pixel display period depends on the display width through N:9

Table 6: Pixel display timing and display width
Display width N
256 pixels 10
320 8
384 7
512 5
640 4

The GPU dot clock and H-blank are not synchronized with the CPU clock, so the counter may change during the CPU read cycle. A program should therefore read the counter repeatedly until two reads give the same value or the second is slightly larger.10

Library Modes

The kernel library sets the counters with mode macros combined by logical OR. RCntMdINTR permits the interrupt and RCntMdNOINTR prohibits it, which leaves polling as the only method.9

Table 7: Root counter mode (2)
Macro Root counter Type of counter
RCnDtMdSP (default) RCntCNT0, 1 (Use prohibited)
RCnDtMdSP (default) RCntCNT2 System clock 8 second cycle
RCnDtMdSP (default) RCntCNT3 Vertical blanking
RCntMdSC RCntCNT0, 1 System clock
RCntMdSC RCntCNT2, 3 Not valid

RCntMdFR, the default, counts normally. RCntMdGATE makes the counter count only while its gate condition holds:911

Table 8: Root counter gate condition
Root counter Gate condition
RCntCNT0 Not during horizontal blanking
RCntCNT1 Not during vertical blanking
RCntCNT2, 3 None (usual time count)

The counters count in hardware, so StopRCnt() does not stop a count. StopRCnt() only stops the counter from generating interrupts, and StartRCnt() only permits them.9

Use by the Kernel

All counters are stopped or free running immediately after the kernel starts, and a program must therefore initialize a counter before it uses one. The kernel itself uses root counter 3 (vertical blanking) to read the controller buttons. The button state cannot be read while root counter 3 is stopped or uninitialized.11

The beginning of the vertical blanking period can be detected with root counter 3 and the event management service. The PS-X OS manual gives this sequence:12

EnterCriticalSection();
EV = OpenEvent(RCntCNT3, EvSpINT, EvMdNOINTR, NULL);
EnableEvent(EV);
SetRCnt(RCntCNT3, 1, RCntMdINTR);
StartRCnt(RCntCNT3);
while (1) {
    WaitEvent(EV);
}

References


  1. ^ a b c Sony Computer Entertainment Inc. Run-Time Library Overview. January 1999. Page 2-7, Table 2-5.

  2. ^ a b psx-spx. Timers. https://psx-spx.consoledev.net/timers/

  3. ^ psx-spx. I/O Map, Timers (aka Root counters). https://psx-spx.consoledev.net/iomap/

  4. ^ psx-spx. Interrupts, 1F801070h I_STAT and 1F801074h I_MASK. https://psx-spx.consoledev.net/interrupts/

  5. ^ a b psx-spx. Timers, 0x1f801100 + 0x10*N: COUNT. https://psx-spx.consoledev.net/timers/

  6. ^ a b c d psx-spx. Timers, 0x1f801104 + 0x10*N: MODE. https://psx-spx.consoledev.net/timers/

  7. ^ psx-spx. Timers, 0x1f801108 + 0x10*N: COMP / TARGET. https://psx-spx.consoledev.net/timers/

  8. ^ a b psx-spx. Timers, Reset and Wrap. https://psx-spx.consoledev.net/timers/

  9. ^ a b c d e Sony Computer Entertainment Inc. Run-Time Library Overview. January 1999. Page 2-8, Tables 2-6 to 2-10.

  10. ^ psx-spx. Timers, Dotclock/Hblank. https://psx-spx.consoledev.net/timers/

  11. ^ a b Sony Computer Entertainment Inc. Run-Time Library Overview. January 1999. Page 2-9, Table 2-11.

  12. ^ Sony Computer Entertainment Inc. PlayStation Operating System. August 1998. Page 4-4.

Categories: Hardware