The idea of raster interrupt is to simple enough, but it's not easily understood. Think of this: Your monitor draws the picture one scanline at time. Your video chip (in my example, the VIC-II of Commodore 64) processes the "outgoing" data one scanline at time. (Okay, this is a simplistic example. In reality, it may pre-shade tesselated concave quadrilaterals 80 frames in advance, but this is just for the sake of example, okay?)
The important thing to understand is this: If you know what is and isn't being drawn, you can change stuff behind the scenes at precisely the right time. And VIC-II conviniently allows you to read which scanline it's drawing.
Which would, of course, mean that you could just hang out there, wait until specific scanline hits the screen, and do some Voodoo Magic (update sprite pointers to get more of 'em on screen, change screen colors smoothly, whatever your heart desires).
But there's another way: the video chip is capable of generating a raster interrupt when it hits a specified scanline.
It's simple enough to use in theory. The following is a verbal description of the routine example in Jukka Tapanimäki's "C64 Pelintekijän Opas" (Technopress 1990, ISBN 951-832-016-0), and apparently this recipe was so much worth in gold that the publisher advertised that with BIG letters in the cover. As such, I try to say this in my own words.
sei to make sure you're not interrupted (it'd be very embarassing). Turn off IRQ interrupts (store $7f to $dc0d) and kernal (sic) ROM (flip the appropriate bit in $01) - the latter may not be needed, I think, but I may be terribly wrong. Store your raster interrupt routine's address to the IRQ vector ($fffe). Then enable the raster interrupt by storing $01 to $d01a, and be a nice paranoid lad and "acknowledge" a non-existing IRQ request with
Okay, but on which raster line this thing gets called? Simple - you store it to $d012 (and you may need to use the highest bit of $d011 too to store values larger than 256...). Oh, and if you do the
sei-mess with $d012-
cli routine, you can make the interrupt fire multiple times per frame - this is good if, for example, you've split the screen to horizontal panes and want the game screen to scroll and scoreboard to stay put. You can chain multiple raster interrupt points. This is often necessary - in my first program, I had three such things.
All righty then... after setting up the interrupt and set the scanline, just
cli then and do whatever you want in the main program. You're now multi-tasking, and have no need to mess with the raster thing - it gets called when it's Time.
Oh, actually making the raster interrupt routine would help, wouldn't it? =) There's nothing else to remember with it except that first, you need to "acknowledge" the interrupt (
lda $d019; sta $d019) and that your routine should end with
rti instead of
Sounds easy? Not necessarily.
All righty, I made my first raster interrupt-based program. Woohoo! But this is just the beginning of the headaches...
To get to the "tricks" section, and to remember why tricks with the C64 are hard, you need to realize this: machine language isn't infinitely fast. Yeah, you have a 8MHz video chip and a 1MHz processor (kind of like modern PCs with overkillingly fast GPUs), but you just can't always make the processor to do everything while the video chip moves stuff to screen. Raster interrupts one of the reasons why 6502 programming guides have clock cycle counts for each instruction in them.
Hope I won't see you in Bad Line.