3.3 KiB
Raster Interrupts
Source: https://www.c64-wiki.com/wiki/Raster_interrupt
A raster interrupt is an interrupt trigger signal that the VIC-II can supply, if desired, to the CPU whenever the raster in the VIC's video signal reaches a specific line. With machine code programming, this mechanism can be exploited to perform many kinds of VIC "trickery" — having both text and high-res graphics on screen simultaneously, displaying more than eight hardware-supported sprites at once. This is heavily used on the C64/C128 for computer games and demos.
The Atari 800, MSX, and Amstrad CPC also support raster interrupts. The 80-column mode on the C128/VDC cannot.
Setting up a raster interrupt
By default, the system is set up to receive timer-based signals from CIA-1's Timer A. To use the VIC raster interrupt:
Init SEI ; disable IRQ
LDA #%01111111
STA $DC0D ; switch off interrupt signals from CIA-1
AND $D011 ; clear MSB of VIC raster
STA $D011
STA $DC0D ; acknowledge pending CIA-1 IRQs
STA $DD0D ; acknowledge pending CIA-2 NMIs
LDA #210 ; set raster line where interrupt shall occur
STA $D012
LDA #<Irq
STA $0314 ; set IRQ vector
LDA #>Irq
STA $0315
LDA #%00000001
STA $D01A ; enable raster interrupt
CLI ; re-enable IRQ
RTS
Note: enabling raster interrupts from the VIC takes place after setting up everything else. The routine starts with SEI because if the interrupt is enabled before e.g. the vector is re-directed, an interrupt may occur while the vector is being altered, sending the CPU to a "random" address and crashing the system.
Single ISR example (wiggle border)
Irq LDA #$07
STA $D020 ; border = yellow
LDX #$90 ; delay ~half a millisecond
Pause: DEX
BNE Pause
LDA #$00
STA $D020 ; border = black
ASL $D019 ; acknowledge raster IRQ
JMP $EA31 ; into KERNAL standard ISR (handles cursor blink, etc.)
The yellow stripe across the border is exactly 8 raster lines wide, set by the pause loop length.
Multiple raster ISRs (split-screen: hires top, text bottom)
The "concatenated" pattern — two routines handling two different raster lines, each setting up the next:
Irq LDA $D011
AND #%11011111
STA $D011 ; switch to text mode
LDA #<Irq2
STA $0314
LDA #>Irq2
STA $0315
LDA #$0
STA $D012 ; next IRQ at line 0
ASL $D019 ; acknowledge
JMP $EA31 ; into KERNAL ISR
Irq2 LDA $D011
ORA #%00100000
STA $D011 ; switch to bitmap mode
LDA #<Irq
STA $0314
LDA #>Irq
STA $0315
LDA #210
STA $D012 ; next IRQ at line 210
ASL $D019
JMP $EA81 ; shorter ROM routine — just restore regs and RTI
Only one of the chained routines needs to jump to the full KERNAL ISR; the others can exit through $EA81 (the register-restore stub) for speed.