Raster interrupt

From C64-Wiki
Jump to: navigation, search
AFL 1970 intro (19.01.1989): In the middle of the screen a white and blue raster bar is shown.

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 a bit of (machine code) programming, this mechanism can be exploited to perform many kinds of VIC "trickery", like having both text and high-res graphics on screen simultaneously, and displaying more than the eight hardware-supported sprites at once. This method is often used on the C64/C128 for computer games and demos.

Also on other 8 bit computer systeme like Atari 800, MSX home computers and Amstrad/Schneider CPC can used raster (line) interrupts. On the C128/VDC in 80 char mode can't used this method. That is the reason, that only the demo Risen from Oblivion (2001) exists.


Setting up a raster interrupt[edit]

By default, the system is set up to receive timer-based signals from CIA-1's Timer A, but instead the VIC needs to be configured to deliver raster interrupt signals. This is handled by a small initialization routine:

Init LDA #%01111111
STA $DC0D
"Switch off" interrupts signals from CIA-1
AND $D011
STA $D011
Clear most significant bit in VIC's raster register
LDA #210
STA $D012
Set the raster line number where interrupt should occur
LDA #<Irq
STA $0314
LDA #>Irq
STA $0315
Set the interrupt vector to point to interrupt service routine below
LDA #%00000001
STA $D01A
Enable raster interrupt signals from VIC
RTS Initialization done; return to BASIC

Notice that enabling the raster interrupts from the VIC takes place after setting up everything else. If the interrupts are enabled before e.g. the interrupt vector is re-directed to the new routine, an interrupt may occur just as this vector is being altered, sending the CPU to a "random" address and probably crashing the system.

Using a single interrupt service routine[edit]

Here is a very simple interrupt service routine that that "wiggles" the screen frame color (53280) to indicate where on the screen the interrupt occurs:

Irq LDA #7
STA $D020
Turn screen frame yellow

Pause
LDX #90
DEX
BNE Pause
Empty loop that "does nothing" for a little under a half millisecond
LDA #0
STA $D020
Switch frame color back to black
ASL $D019 "Acknowledge" the interrupt by clearing the VIC's interrupt flag.
JMP $EA31 Jump into KERNAL's standard interrupt service routine to handle keyboard scan, cursor display etc.

When this is run, the frame, or "border", around the screen is mostly black, except for a yellow stripe at the left and right edges: This stripe appears at raster line #210 as set in the initialization routine, because just as the raster starts out on this pixel line across the screen, the interrupt service routine sets the frame color to yellow. During the pause loop, the raster swipes swipe through 8 whole pixel lines, leaving a 8-pixel-wide stripe before the color is set back to black.

Using multiple interrupt service routines[edit]

Raster interrupts are often used with a system of two or more interrupt service routines, handling interrupts triggered at different raster lines: Each routine perfoms it's "own" tasks, then sets up an interrupt to occur at the "next" desired raster line and re-directs the vector at 788–789/$0314–$0315 to point to the next routine associated with that line.

The following example shows two such "concatenated" raster interrupt service routines, splitting the screen in a high-resolution part and a text part: They can be initialized using the routine outlined at the beginning of this article.

The first routine is triggered at raster line 210, and handles the switch from high-res to text mode. It also sets up the interrupt pointer to the second interrupt service routine, and configures the corresponding raster line:

Irq LDA $D011
AND #%11011111
STA $D011
Select text screen mode
LDA #<Irq2
STA $0314
LDA #>Irq2
STA $0315
Re-direct next interrupt to Irq2 service routine
LDA #0
STA $D012
Next interrupt to occur at raster line no. 0
ASL $D019 "Acknowledge" the interrupt by clearing the VIC's interrupt flag.
JMP $EA31 Jump to the beginning KERNAL's standard interrupt service routine.

The second routine handles the switch from text to high-res at raster line 250. It also re-adjusts the interrupt pointer back to the first interrupt service routine, and sets up the raster to trigger it next time the raster passes by line 210:

Irq2 LDA $D011
AND #%11011111
STA $D011
Select text screen mode
LDA #<Irq
STA $0314
LDA #>Irq
STA $0315
Re-direct next interrupt back to Irq
LDA #210
STA $D012
Next interrupt to occur at raster line no. 210
ASL $D019 "Acknowledge" the interrupt by clearing the VIC's interrupt flag.
JMP $EA81 Jump to the final part of KERNAL's standard interrupt service routine.

In this example the "default" interrupt service routine at 59953/$EA31 is "included" through the JMP command at the end of the first of the two raster routines, enabling you to move the cursor, type commands etc. after the interrupt system has started. Notice that only one in such a set of raster-driven interrupt service routine need to end in a jump into the entire KERNAL service routine: The latter routine takes a jump to 60033/$EA81, where the ROM routine pulls back registers etc. from the stack before handing the CPU back to what it was doing when the interrupt occurred.

Links[edit]

WP-W11.png Wikipedia: Raster_interrupt