Skip to content

Raster Effects

Changing the picture while it is being drawn

A raster effect changes a video register partway down the screen, so the part of the picture below the change looks different. Colour bars, split screens, opened borders and extra sprites all come from it. The Commodore 64 does it with a raster interrupt, the Amiga with its copper, and the Spectrum, which has neither, by counting clock cycles from its one interrupt a frame.

A television builds its picture one line at a time, top to bottom, fifty or sixty times a second. A home computer’s video chip reads the same registers for every line, so a colour or scroll value set once applies to the whole screen. Change a register while the picture is being drawn, though, and everything below that point uses the new value. That is a raster effect, and it was the way 1980s programmers got more out of a video chip than its specification promised: more colours than the palette allowed on one screen, more sprites than the hardware had, a scrolling playfield above a score panel that stays still, and pictures in a border that was meant to be blank.

Atari’s De Re Atari explained the idea to programmers in 1982. Drawing the screen “takes about 17,000 microseconds, which looks instantaneous to the human eye, but is a long time in the time scale that the computer works in. The computer has plenty of time to change the parameters of the screen display while it is being drawn.” The catch, the guide went on, is that the change must happen “at exactly the same time each time the screen is drawn”. Every raster effect is a way of meeting that condition, and each machine offered a different amount of help.

Fast facts

  • Principle: write to a video register when the beam reaches a chosen line, and again every frame.
  • Atari VCS (1977): no screen memory at all; every line is set up by the program as the beam draws it.
  • Atari 400/800: a display list interrupt from the ANTIC chip at the end of a chosen line.
  • Commodore 64: a raster interrupt from the VIC-II at any line, set in $D012 with bit 8 in bit 7 of $D011.
  • Amiga: the copper, a coprocessor that waits for beam positions and writes registers itself.
  • ZX Spectrum: no raster interrupt; one interrupt per frame, and the program counts clock cycles from it.

Racing the beam

The idea is older than the machines that made it famous. Atari’s Video Computer System, shown at the summer Consumer Electronics Show in 1977, has no memory for a picture. Its graphics chip, the TIA, holds only the line being drawn. The Stella Programmer’s Guide says the picture “is drawn one line at time by having the microprocessor enter the data for that line”, so the processor “must be ‘one step ahead’ of the electron beam on each line”, with 76 machine cycles per line to do it. On the Atari 2600, changing a colour halfway down the screen is not a trick. It is how every picture is made.

Atari’s home computers of 1979 gave programmers help. Their display chip, ANTIC, reads a list of instructions describing the screen, and any instruction can carry an interrupt bit. When ANTIC reaches the last line of that part of the screen, it interrupts the 6502, which changes a colour register, a player’s position or the character set before the next line is drawn. De Re Atari called the display list interrupt “one of the most powerful capabilities built into the ATARI Home Computer” and “one of the least accessible”, because it needed assembly language and exact timing. See Atari 8-bit.

On the Commodore 64

The VIC-II counts the lines it draws and compares the count with a line number the program has stored. When they match it sets bit 0 of $D019, and if bit 0 of $D01A is set it interrupts the processor. A PAL screen has 312 lines and an NTSC one 262 or 263, so eight bits cannot name them all: the low eight bits of the line go in $D012 and the ninth in bit 7 of $D011. The flag in $D019 stays set until the program writes a 1 to it. Christian Bauer’s description of the chip spells out what happens to a handler that forgets: “the interrupt will be triggered again immediately”.

Commodore’s Programmer’s Reference Guide sold the feature on what it allowed: “This powerful interrupt structure lets you use split screen modes. For instance you can have half of the screen bitmapped, half text, more than 8 sprites at a time, etc. The secret is to use interrupts properly.” Gary Liddon’s machine-code column in ZZAP!64 in September 1987 put it in players’ terms: “all those games that have the top half of the screen scrolling and the bottom half of the screen stationary are using raster interrupts.” After the playfield’s scroll is set at the top of the screen, an interrupt halfway down “zeros the scroll registers”, and “the rest of the screen is then stationary”.

The raster interrupts entry covers the C64 mechanism in full, with tested chains of interrupts. The short program below shows the whole idea in one place. It asks for an interrupt on line 260, which needs the ninth bit, and then changes the border colour on each of the next sixteen lines by waiting for $D012 to change. On a PAL machine those lines are in the lower border, below the text, where the VIC-II never stops the processor, and the result is a band of colour bars under a working BASIC screen.

Assembly
; raster bars in the lower border (ACME syntax, PAL)
; load and RUN: the BASIC line starts the program at 2061
        * = $0801
        !word basend, 10
        !byte $9e
        !text "2061"
        !byte 0
basend  !word 0

start   sei
        lda #$7f
        sta $dc0d           ; switch off CIA 1's timer interrupts
        lda $dc0d           ; and clear any that are waiting
        lda #<bars
        sta $0314           ; point the KERNAL's IRQ vector at bars
        lda #>bars
        sta $0315
        lda #<260
        sta $d012           ; interrupt on line 260 ($104): low byte here...
        lda $d011
        ora #$80            ; ...and bit 8 in bit 7 of $d011
        sta $d011
        lda #$01
        sta $d01a           ; enable the raster interrupt
        sta $d019           ; clear any raster interrupt already flagged
        cli
        rts

bars    ldx #0
-       lda colours,x
        ldy $d012           ; the line we are on now
wait    cpy $d012
        beq wait            ; wait for the next line to start...
        sta $d020           ; ...and change the border colour
        inx
        cpx #16
        bne -
        lda #14
        ldy $d012
w2      cpy $d012
        beq w2
        sta $d020           ; back to light blue for the rest of the frame
        lda #$01
        sta $d019           ; acknowledge the interrupt
        jmp $ea31           ; the KERNAL's clock, cursor and keyboard, then return

colours !byte 6,4,14,3,1,3,14,4,6,2,8,7,1,7,8,2

The handler spends sixteen lines in a loop, about a thousand cycles a frame that the main program does not get. That is the C64’s bargain: the chip says when, but the processor does the work. The Raster splits pattern shows the simpler two-colour split.

Timing is the hard part

The interrupt is punctual; the handler is not quite. The processor finishes the instruction it is running before it answers, and 6510 instructions take 2 to 7 cycles, so the handler starts a few cycles later in some frames than in others. One cycle is 8 pixels of screen, so a colour change made this way can have a ragged edge. Two more things get in the way:

  • Badlines. On the first line of every character row inside the display window, the VIC-II stops the processor for 40 to 43 cycles to fetch the row’s character codes, Bauer’s section 3.5 explains. Code timed to the cycle has to allow for them, which is why the example above works in the border, where there are none.
  • PAL and NTSC. A PAL 6569 has 312 lines of 63 cycles; the NTSC 6567R8 has 263 lines of 65 cycles, and the early 6567R56A 262 lines of 64. An effect timed for one runs out of step on the others, and a line such as 280 does not exist on an NTSC machine at all.

For effects that must land on one exact cycle, programmers wrote stable raster routines, which find out how late the interrupt was and wait out the difference.

The VIC-II tricks

In December 1986 a disk arrived at ZZAP!64 from “some ‘Dutch 64 freaks’ called the 1001 Crew”. On it was a full-screen picture made of 58 or 112 expanded sprites, “some of which are ‘in’ the top and side borders”. The magazine’s Compunet columnist was baffled: “I’ve no idea how it’s done, but I hope someone puts the effect to good use in a game!” Four months later Andrew Braybrook, writing his diary of Morpheus in the same magazine, was “unhappy about using sprites in the border as it could be exploiting a video-chip bug. This may not work on some machines or it could cause damage.”

Neither the columnist nor Braybrook knew yet how the trick worked. These raster tricks went beyond changing a colour or scroll value: the writes made the VIC-II skip or repeat its own internal steps.

The registers involved are all in Commodore’s manual. What the manual does not describe is the logic behind them, and the tricks depend on that logic. The VIC-II switches its border on and off by comparing the beam’s position with a few fixed values, and Christian Bauer’s 1996 description of the chip explains the weakness: “The comparisons only match if the values are reached precisely. There is no comparison with an interval.” Change the screen height between the two possible bottom lines and neither comparison matches, so the border never starts. In the same way, the chip decides whether a raster line is a badline, the line on which it fetches a new row of characters, by comparing the low three bits of the line number with the vertical scroll value in $D011. Change the scroll value and a program can make a badline happen early, late, twice or not at all.

The stable timing and PAL/NTSC differences described above apply to these tricks too.

Each trick has its own entry with a fuller explanation. The dates are from the demo scene’s own list of first appearances, a community record open to correction.

Trick The write What it gives First listed
Top and bottom border Clear RSEL, bit 3 of $D011, on lines 248–250, switching to 24 rows so the chip misses the line where it would switch the border on Sprites shown above and below the screen Flash/FCG, Intro, October 1985
Side borders Clear CSEL, bit 3 of $D016, in exactly cycle 56 of every line, switching to 38 columns Sprites shown beside the screen TSI/1001, Border Letter I, April 1986
FLD Keep moving the fine-scroll bits in $D011 so the next badline never comes A gap of blank lines that pushes the screen down 1986
Linecrunch Cancel a badline after one line of a character row The screen moves up without copying memory 1987
VSP Start a badline late in the line with a write to $D011 The whole screen moves sideways a character per cycle of delay JCB/Meanteam, VSP&IK+, October 1987
AGSP VSP for the horizontal position plus linecrunch for the vertical The whole screen placed anywhere without copying memory 1988
FLI Force a badline on every line and switch screen memory with $D018 New screen-memory colours on every pixel line instead of every eighth Solomon/Beyond Force, Charlatan, January 1989
Sprite stretching Clear and set a sprite’s Y-expansion bit in $D017 on each line The same row of sprite data shown again, so a sprite can be any height Bob/Triad, Cocktail, February 1989

The names were not fixed. VSP, short for Variable Screen Positioning, is also called HSP and DMA delay, and Bauer’s document describes it as DMA delay.

Later picture modes stacked these tricks with others. Crossbow and DeeKay of the German group Crest are credited with a series of them, from UFLI in 1996, which puts a layer of sprites under an FLI picture, to NUFLI in 2009.

Every trick takes processor time, and some take most of it. The VIC-II stops the processor for 40 to 43 cycles on each badline, so FLI, which makes every line a badline, leaves little time for anything else while the picture is on screen. Some leave marks. FLI leaves a stripe three character cells wide down the left of the picture, 12 multicolour pixels, where the colours cannot be chosen freely. FLI pictures leave it blank or design around it. VSP corrupts memory on some C64s, a fault traced to the machine’s DRAM in 2013.

Sprite multiplexing, the most common raster effect in games, uses the same interrupts more plainly: once the beam has drawn a sprite, the program moves it further down the screen to be drawn again, so eight hardware sprites can show many more objects.

On the Amiga: the copper

The Amiga does not need the processor for most of this. Its copper, a coprocessor inside the Agnus chip, runs a list of instructions every frame: WAIT for a beam position, MOVE a value into a register. Commodore’s Hardware Reference Manual says it “can control nearly the entire graphics system, freeing the 680x0 to execute program logic”, and that while it waits “it does not use the memory bus at all”.

It is cheap rather than free. When a WAIT is satisfied, the manual says, “the Copper steals memory cycles from either the blitter or the 680x0” to make its writes, each MOVE taking four memory-cycle times. A gradient that changes one colour on every line of a PAL screen costs about 1,300 memory cycles a frame, out of the roughly 71,000 the manual’s figure of 227.5 per line allows, and the processor does none of the work. By 1994 The One could say that nearly every Amiga game “uses the Copper list to graduate the colour of the ground and sky”. The pattern Copper Colour Bars builds one.

When the processor does have to act at a particular line, the copper can interrupt it with a MOVE to the INTREQ register; the raster interrupts entry shows how.

On the Spectrum: counting cycles

The ZX Spectrum has no raster interrupt and no coprocessor. Its ULA interrupts the Z80 once a frame, 50 times a second, at the end of each picture, and the ROM uses that interrupt to scan the keyboard. A program that wants to change something partway down the screen has to count. Each scan line lasts 224 T-states (processor clock cycles), and on a 16K or 48K machine the first line of the screen begins 14,336 T-states after the interrupt. A routine that waits exactly the right number of cycles after the interrupt, then makes a change every 224 cycles, stays in step with the beam.

The best-known Spectrum example was Dominic Robinson’s “Rainbow Processor”, used on the title and high-score screens of Uridium and Zynaps. The Spectrum normally allows two colours in each 8×8 square. Robinson’s routine rewrote the colour attributes for every pixel line instead, and Your Sinclair printed it as a type-in in August 1987. In his words it gave “a different colour on each pixel line, in a band twenty characters wide in the centre of the screen”. It ran from an Interrupt Mode 2 handler “to keep it synchronised with the generation of the TV picture”. The price was the processor’s attention: “The deeper the display you use, the less processor time will be available for Basic or any other code you have running. For this reason the rainbow effect can only really be used for title screens and special effects.”

Sinclair User explained the method to a reader in December 1988. Because 224 T-states are “not long enough” to rewrite all 32 attributes of a row, a band narrower than the screen was all a routine could manage, and getting the timing right meant adjusting it “by adding or removing the odd NOP instruction”. It was hard work, the magazine warned, “because as soon as your timing goes astray the screen image becomes very jumbled”.

The timing is harder than the C64’s for another reason. When the ULA is fetching screen data, it holds up any processor access to the lower 16K of RAM, so code running there, or touching the screen, runs at a speed that depends on where the beam is (contended memory). Some games turned the ULA’s activity into a clock instead. Reading a port that nothing answers returns whatever is on the data bus, and while the screen is being drawn that is the byte the ULA has just fetched. Alessandro Grussu’s Spectrumpedia names Arkanoid, Cobra, Short Circuit and Sidewize among the games that used this “floating bus” to find out where the beam was.

On Nintendo’s consoles

The NES’s PPU has no line counter a program can set. Games that wanted a still status bar above a scrolling world used the sprite 0 hit flag, bit 6 of $2002: they placed sprite 0 over the background at a known point and polled the flag until it was set. NESdev’s documentation gives the reason: it lets the processor “know its approximate location on the screen so it can time mid-screen writes to hardware registers”, as in Super Mario Bros. Cartridges could add the missing counter. The MMC3 mapper counts lines by watching one of the PPU’s address lines, which rises about once per line, and interrupts the processor when its count runs out.

The Super NES built the idea into the console. Its HDMA channels transfer small amounts of data during horizontal blanking, allowing display-register values to change between scan lines. The program prepares a table and the hardware works through it a line at a time, as the public Fullsnes DMA reference describes. Changing the Mode 7 transformation between lines can turn a flat rotating map into a floor that recedes into the distance.

How the machines compare

Machine What finds the line Who makes the change
Atari VCS The program, line by line, with WSYNC to wait for the next one The processor, on every line
Atari 400/800 ANTIC, from a bit in the display list The processor, in an interrupt
Commodore 64 The VIC-II’s raster compare The processor, in an interrupt
Amiga The copper’s WAIT The copper itself
ZX Spectrum The program, counting T-states from the frame interrupt The processor
NES Sprite 0 hit, or a counter on the cartridge The processor
Super NES HDMA, from a table The DMA hardware

Sources

  • Atari, De Re Atari (Atari Program Exchange, 1982), section 5, “Display List Interrupts”, p. 5-1: the 17,000-microsecond screen, changing parameters “at exactly the same time each time”, ANTIC’s interrupt bit and the DLI as “one of the most powerful capabilities”.
  • Steve Wright, Stella Programmer’s Guide (Atari, 1979), introduction: the picture drawn one line at a time, “one step ahead” of the beam, 76 machine cycles per line.
  • Video Games, vol. 1 no. 3, December 1982, pp. 44-45: the VCS’s debut at the summer Consumer Electronics Show in 1977.
  • Commodore, Commodore 64 Programmer’s Reference Guide (1982), pp. 150-151: the raster compare, the latched interrupt flags “cleared by writing a 1”, and split screens.
  • Christian Bauer, The MOS 6567/6569 video controller (VIC-II) and its application in the Commodore 64 (1996): lines and cycles per line for the 6569, 6567R8 and 6567R56A (section 3.4); badlines and the 40-43 stolen cycles (3.5); the border comparisons (3.9); the raster interrupt and the $D019 latch (3.12); the border, FLD, FLI, DMA delay and sprite stretching tricks (3.14).
  • ZZAP!64 issue 20, December 1986, p. 131: the 1001 Crew’s border-opening demos. Issue 24, April 1987, p. 90: Andrew Braybrook’s Morpheus diary.
  • Gary Liddon, “Raster interrupts drive Mr Liddon off the rails”, ZZAP!64 issue 29, September 1987, p. 68: split-screen scrolling with raster interrupts.
  • Codebase64 wiki, “Demo records and world firsts” (community list, web, secondary): first appearances of the border, FLD, linecrunch, VSP, AGSP, FLI and sprite-stretching effects. https://codebase64.net/doku.php?id=vic:demo:demo_world_records_and_world_firsts
  • Codebase64 wiki, “FLI”, “Any Given Screen Positioning (AGSP)” and “Horizontal Screen Positioning (HSP)” (web, secondary): FLI’s left-edge limitation, the AGSP combination and the names used for VSP.
  • “World firsts and records”, Recollection (web, secondary; based on the Codebase64 world-firsts list): Crest’s later FLI picture modes. https://www.atlantis-prophecy.org/recollection/?load=world_of_demos
  • Linus Åkesson, “Safe VSP”, 20 March 2013: the investigation of VSP memory corruption. https://www.linusakesson.net/scene/safevsp/index.php
  • Amiga Hardware Reference Manual, 3rd edition (Commodore-Amiga, Addison-Wesley, 1991), chapter 2, “Coprocessor Hardware”, pp. 19-20: the copper “freeing the 680x0”, not using the bus while it waits, stealing cycles from the blitter or the 680x0, and instruction timings; chapter 6, “Blitter Hardware”, pp. 193-194: DMA priorities and 227.5 memory cycles per line.
  • David Upchurch, work-in-progress feature on Guardian, The One issue 66, March 1994: the copper list and graduated ground and sky.
  • Adrian Dickens, Spectrum Hardware Manual, 2nd edition (Melbourne House), chapters 7 and 8: the ULA’s interrupt 50 times a second, at the end of each video frame, used to scan the keyboard.
  • Chris Smith, The ZX Spectrum ULA: How to Design a Microcomputer (ZX Design and Media, 2010), chapter 21: the frame interrupt and the 224 T-state scan line.
  • Alessandro Grussu, Spectrumpedia, volume 1 (English edition, CC BY-NC-ND 4.0), p. 110: contended memory beginning 14,336 T-states after the interrupt, and the floating bus in Arkanoid, Cobra, Short Circuit and Sidewize.
  • Dominic Robinson, “Star Tip 1”, Your Sinclair issue 20, August 1987, p. 55: the Rainbow Processor, used in Uridium and Zynaps.
  • Sinclair User issue 81, December 1988, pp. 115-116: readers’ questions, how the Rainbow Processor in Uridium works.
  • NESdev Wiki, “PPU registers” and “MMC3” (community references, web, secondary): the sprite 0 hit used to time mid-screen writes, as in Super Mario Bros.; the MMC3 counter clocked by PPU address line A12. https://www.nesdev.org/wiki/PPU_registers, https://www.nesdev.org/wiki/MMC3
  • Martin Korth, Fullsnes, “SNES DMA Transfers” and “SNES DMA and HDMA Channel 0..7 Registers” (public technical reference): H-blank transfers and the HDMA table. https://problemkaputt.de/fullsnes.htm#snesdmatransfers

The C64 listing was assembled with ACME and run in the VICE emulator (x64sc) as a PAL machine.

See also

Checked. Verified against primary sources and signed off by a person.