, then the stage 2 VBLANK processor is executed.
The OS then jumps through the “deferred” vertical-blank global RAM vector VBLKD [0224], that normally points to the VBLANK exit routine.
The following actions occur assuming that you have not changed VVBLKD.
The 6502 A, X and Y registers are restored.
An RTI instruction is executed.
NOTE: You can alter the deferred and immediate VBLANK RAM vectors, but still enable normal system processes; or restore original vectors without having to save them. The instruction at E45F is a JMP to the stage 1 VBLANK processor, the address at [E460,2] is the value normally found in VVBLKI. The instruction at E462 is a JMP to the VBLANK exit routine, the address at [E463,2] is the value normally found in VVBLKD. These ROM vectors to stage 1 VBLANK processor and to the VBLANK exit routine will accomplish your goal.
NOTE: Every VBLANK interrupt jumps through vector VVBLKI. Only VBLANK interrupts from noncritical code sections jump through vector VVBLKD.
The stage 1 VBLANK process increments the 3-byte frame counter RTCLOK [0012-0014], RTCLOK+0 is the MSB and RTCLOK+2 is the LSB. This counter wraps to zero when it overflows (every 77 hours or so), and continues counting.
The Attract mode variables are processed (see Appendix L, B10-12).
The stage 1 VBLANK process decrements the System Timer 1 CDTMV1 [0218,2] if it is nonzero; if the timer goes from nonzero to zero then an indirect JSR is performed via CDTMA1 [0226,2].
The stage 2 VBLANK process clears the 6502 processor I bit. This enables the IRQ interrupts.
COLOR0 [02C4]   COLPF0 [D016]   Attract mode.
Constant = 8   CONSOL [D01F]    Console speaker off.
The stage 2 VBLANK process decrements the System Timer 2 CDTMV2 [021A,2] if it is nonzero; if the timer goes from nonzero to zero, then an indirect JSR is performed through CDTMA2 [0228,2].
The stage 2 VBLANK process decrements System Timers 3, 4 and 5 if they are nonzero; the corresponding flags are set to zero for each timer that changes from nonzero to zero.
A character is read from the POKEY keyboard register and stored in CH [02FC], if auto repeat is active.
The stage 2 VBLANK process decrements the keyboard debounce counter if it is not equal to zero, and if no key is pressed.
The stage 2 VBLANK process processes the keyboard auto repeat (see Appendix L, E8).
The IRQ Handler determines a cause for the interrupt by examining the IRQST [D20E] register and the PIA status registers PACTL [D302] and PBCTL [D303]. The interrupt status bit is cleared when it is found. One interrupt event is cleaved and processed for each interrupt-service entry. If multiple IRQs are pending, then a separate interrupt will be generated for each pending IRQ, until all are serviced.
The 6502 A register is pushed to the stack.
If the interrupt is due to serial I/O bus output ready, then clear the interrupt and jump through global RAM vector VSEROR [020C].
If the interrupt is due to serial I/O bus input ready, then clear the interrupt and jump through global RAM vector VSERIN [020A].
If the interrupt is due to serial I/O bus output complete, then clear the interrupt and jump through global RAM vector VSEROC [020E].
If the interrupt is due to POKEY timer #1, then clear the interrupt and jump through global RAM vector VTIMR1 [0210].
If the interrupt is due to POKEY timer #4, then clear the interrupt. The service routine contains a bug, and falls into the following test.
If pressing a keyboard key caused the interrupt (other than [BREAK], [START], [OPTION], or [SELECT]); then clear the interrupt and jump through global RAM vector VKEYBD [0208].
Return from the interrupt after restoring the 6502 A register from the stack.
If the interrupt is due to the serial I/O bus proceed line, then clear the interrupt, and jump through global RAM vector VPRCED [0202].
If the interrupt is due to the serial I/O bus interrupt line, then clear the interrupt and jump through global RAM vector VINTER [0204].
If the interrupt is due to a 6502 BRK instruction, then jump through global RAM vector VBREAK [0206].
If none of the above, restore the 6502 A register and return from the interrupt (RTI).
VDSLST [0200]   NMI     RTI -- ignore interrupt.
VVBLKI [0222]    "      System stage 1 VBLANK.
CDTMA1 [0226]    "      SIO timeout timer.
CDTMA2 [0228]    "      No system function.
VVBLKD [0224]    "      System return from interrupt.
VIMIRQ [0216]   IRQ     System IRQ processor.
VSEROR [020C]    "      SIO.
VSERIN [020A]    "      SIO.
VSEROC [020E]    "      SIO.
VTIMR1 [0210]    "      PLA,RTI -- ignore interrupt.
VPRCED [0202]    "      PLA,RTI -- ignore interrupt.
VINTER [0204]    "      PLA,RTI -- ignore interrupt.
VBREAK [0206]   BRK     PLA,RTI -- ignore interrupt.
NMI     VBLANK enabled, display list disabled.
The OS contains five general purpose software timers, plus an OS-supported frame counter. The timers are 2 bytes in length (lo, hi) and the frame counter RTCLOK [0012] is three bytes in length (hi/mid/lo). The timers count downward from any nonzero value to zero. Upon reaching zero, they either clear an associated flag, or JSR through a RAM vector. The frame counter counts upward, wrapping to zero when it overflows.
* RTCLOK [0012]                3-byte frame counter.
* These two timers are maintained as part of every VBLANK interrupt (stage 1 process). The other timers are subject to the critical section test (stage-2 process), that can defer their updating to a later VBLANK interrupt.
This subsection describes the techniques you need to know in order to utilize interrupts in conjunction with the operating system.
ANTIC (display-list and vertical-blank) and PIA (interrupt and proceed lines) interrupts can be masked directly (see the Hardware Manual). However, eight bits of a single byte IRQEN [D20E] mask the POKEY interrupts ([BREAK] key, data key, serial input ready, serial output ready, serial output done and timers 1/2 and 4).
SEI             ; TO AVOID CONFLICT WITH IRQ...
LDA     POKMSK  ;... PROCESSOR WHICH ALTERS VAR.
ORA     #$xx    ; ENABLE BIT(S).
STA     IRQEN   ; TO HARDWARE REG TOO.
AND     #$FF-xx ; DISABLE BIT(S).
STA     IRQEN   ; TO HARDWARE REGISTER TOO.
Note that the OS IRQ service routine uses and alters POKMSK, so alterations to the variable must be done with interrupts inhibited. If done at the interrupt level there is no problem, as the I bit is already set; if done at a background level then the SEI and CLI instructions should be used as shown in the examples.
1-5 for timers 1-5.
6 for immediate VBLANK vector WBLKI.
7 for deferred VBLANK vector VVBLKD.
X = MSB of value to store.
Y = LSB of value to store.
The A, X and Y registers can be altered.
return, even if enabled upon entry.
It is possible to fully process a vertical-blank interrupt during a call to this routine.
When working with the System Timers, the vectors for timers 1 and 2 and the flags for timers 3, 4 and 5 should be set while the associated timer is equal to zero, then the timer should be set to its (nonzero) value.
* The OS initializes these entries at power-up. Improperly changing these vectors will alter system performance.
Display list, immediate vertical-blank and System Timer #1 routines should not clear the 6502 I bit. If the NMI leading to one of these routines occurred while an IRQ was being processed, then clearing the I bit will cause the IRQ to re-interrupt with an unknown result.
The OS VBLANK processor carefully checks this condition after the stage 1 process and before the stage 2 process.
You should not write an interrupt routine that exceeds 400 msec when added to the stage 1 VBLANK, if the serial I/O is being used. The SIO sets the CRITIC flag while serial bus I/O is in progress.