Expand description
Minimal interrupt support used by engine-level clocks.
The first consumer is a monotonic VBlank counter. We install a
tiny exception-vector trampoline that handles VBlank IRQs itself,
increments a volatile counter, acknowledges the IRQ, then returns
with rfe. The handler deliberately uses only the MIPS kernel
registers $k0/$k1, so it does not need a stack frame.
Constants§
- PRESENT_
QUEUE - True when psx-rt was built with the
present-queuefeature: the VBlank handler kicks frames published throughcrate::present. - STRICT_
FAULTS - True when psx-rt was built with the
strict-faultsfeature: the exception handler halts on every fault instead of stepping over the faulting instruction (seefault_resume_pc).
Functions§
- are_
interrupts_ enabled - True when COP0 SR has interrupts enabled (IEc).
- declare_
stack_ ⚠safe_ handler - Declare that the game’s own exception handler at
handleris safe to take an interrupt on any stack, including aScratchpadStack. - fault_
bad_ address - COP0 BadVAddr captured for the latest unexpected exception.
- fault_
cause - Raw COP0 Cause captured for the latest unexpected exception.
- fault_
count - Unexpected exceptions survived so far. Non-zero means some access faulted and was stepped over; the value it read or wrote is garbage.
- fault_
pc - COP0 EPC captured for the latest unexpected exception.
- fault_
resume_ pc - Where psx-rt’s exception handler resumes after a fault (any exception
but an interrupt), or
Nonewhere it halts.badvaddris COP0 BadVAddr. - gp1_
queue_ pending Deprecated - Renamed to
is_display_control_queued. - gte_
skip_ count - Interrupts that landed on a GTE command, whose return the handler moved to EPC + 4 so the command did not run twice.
- install_
vblank_ counter - Install and enable the VBlank counter interrupt path.
- interrupt_
resume_ pc - Where psx-rt’s exception handler resumes after an interrupt:
epc, orepc + 4whenword_at_epcis a GTE command. - is_
display_ control_ queued - True while a word queued by
queue_display_control_at_vblankhas not yet been applied by the VBlank handler. - is_
gte_ command - True when
wordis a GTE command (a COP2cofun: opcode 0x12 with bit 25 set, so the top seven bits are0100101). psx-spx’s test is(word & 0xFE00_0000) == 0x4A00_0000. GTE register moves (mfc2,mtc2,cfc2,ctc2),lwc2/swc2and thebc2branches are not commands: an interrupt on them is taken before they run. - is_
handler_ installed - True when the general exception vector jumps to psx-rt’s handler, the
one that never touches
$sp(so interrupts are safe on any stack). - is_
stack_ safe_ handler_ installed - True when the general exception vector jumps to psx-rt’s handler or to
the one declared with
declare_stack_safe_handler. - last_
stray_ interrupt_ sources - The
I_STAT & I_MASKbits of the latest stray interrupt (stray_interrupt_count); zero before the first. - queue_
display_ control_ at_ vblank - Queue one GP1 word for the VBlank handler to apply at a blank edge (deferred tear-free display flip). Overwrites any unapplied word.
- queue_
gp1_ at_ vblank Deprecated - Renamed to
queue_display_control_at_vblank. - stray_
interrupt_ count - Stray interrupts acknowledged so far. psx-rt’s handler owns VBlank only;
any other source enabled in
I_MASKthat fires while no VBlank is pending, and that no handler in front of this one claimed, is acknowledged and counted here instead of re-entering forever. Non-zero means something enabled a source nothing services. - stray_
interrupt_ sources - The sources psx-rt’s handler acknowledges as strays for one entry, given
I_STAT,I_MASKand COP0 Cause; zero when it leaves them alone. - take_
pending_ gp1 Deprecated - Renamed to
take_queued_display_control. - take_
queued_ display_ control - Empty the queue and hand back the word the handler has not applied, so the caller can write it to GP1 itself. Returns 0 when nothing was queued.
- try_
wait_ vblank wait_vblankwith its own bound:trueonce the count has advanced,falseafterspinsreads of it without a change. Afalsemeans no VBlank interrupt reached psx-rt’s handler: interrupts are masked (inside acritical_section), the counter was never installed, or a game’s handler does not chain to psx-rt’s. Does not install the counter;wait_vblankdoes that first.- vblank_
count - Current monotonic VBlank count.
- wait_
vblank - Block until the next VBlank IRQ.