Skip to content
Techniques & Technology

Raster Effects

Per-scanline graphics tricks

Raster effects change graphics parameters during screen drawing, creating colour bars, split screens, and effects beyond normal hardware limits.

commodore-64commodore-amigasinclair-zx-spectrumnintendo-entertainment-system graphicseffectstechnical 1977–present

Overview

The CRT beam draws the screen one scanline at a time, top to bottom. Most game state stays the same throughout that draw — but it doesn't have to. Raster effects exploit timing: change a hardware register during the beam's pass, and the screen below that point reflects the new value. Change the background colour at line 100 and you have two coloured regions. Chain dozens of changes for rainbow stripes. Reposition a sprite after it's been drawn to multiplex it. The technique unlocks visuals that the spec sheet says are impossible.

Cycle-accurate timing is critical: the CPU has to write the right register at the right beam position, every frame, without drift. The game-level effort to get this stable across PAL/NTSC and across long routines is what made the C64 demoscene the discipline it became.

Common effects

EffectWhat it does
Colour barsChange $D020 (border) or $D021 (background) per scanline → coloured stripes
Split screenChange graphics mode partway down → status bar in text mode above gameplay in bitmap mode
Sprite multiplexingReposition sprite registers after the sprite has drawn → reuse 8 hardware sprites for 16+ on-screen sprites
Scroll splitsChange scroll position partway down → static HUD over scrolling playfield
More coloursMore palette entries by changing palette mid-frame (Amiga Copper rainbows)
FLI / DYCP / NUFLIDemo-scene C64 modes that exploit per-line tricks for colour-per-cell
Mode-7 effectsPer-scanline matrix change creates ground-plane perspective on SNES

Implementation

Raster interrupts

The C64's VIC-II generates a configurable interrupt at a chosen scanline ($D012). The IRQ handler runs at exactly the moment the beam reaches that line — the CPU writes its registers immediately, the screen below reflects the change. Multiple raster IRQs per frame are common; chained handlers can make per-scanline changes.

See Raster Interrupts for the C64 specifics.

Copper (Amiga)

The Amiga's Copper is a co-processor running its own program in parallel with the CPU. The Copper waits for specific raster positions and writes specific registers. A "Copper list" of (WAIT, MOVE) instructions can change palette, scroll, bitplane pointers per scanline with no CPU intervention. This is what makes Amiga rainbows essentially free.

See Copper for the chip's design.

NES sprite-zero hit

The NES PPU sets a "sprite-zero hit" bit ($2002 bit 6) when sprite 0's first non-transparent pixel collides with a non-transparent BG pixel. Games place sprite 0 at a known scanline (typically the top of the gameplay area) and poll the bit to detect when the beam passes it. The CPU then changes scroll registers ($2005) for the scanlines below — status bar above, scrolled playfield below.

MMC3 IRQ (NES)

The MMC3 mapper has a counter that decrements on every rising edge of PPU A12 (which happens once per scanline during sprite/BG fetches). When it reaches zero it fires an IRQ — gives the CPU per-scanline control. Used by Battletoads, Castlevania III, Mega Man 3+. Different on PAL vs NTSC due to different scanline counts.

Cycle counting (Spectrum)

The Spectrum has no raster IRQ — only a frame-rate IRQ at the start of every frame. Per-scanline tricks require cycle-counting from that interrupt: "wait exactly N T-states from frame start, then do the write." Famously hard to keep accurate across the contended-memory regions. Black Lamp and various demoscene Spectrum effects use this.

Notable C64 raster effects

EffectWhat it doesFamous example
Border opening (top/bottom)Disable $D011 bit 3 at the right line to remove top/bottom bordersMost demos
Side-border openingToggle $D016 bit 3 at the right cycle to remove side bordersTrickier; demos like Krestology
FLI (Flexible Line Interpretation)Change colour memory pointer every scanline → 16 colours per character cellCrest's FLI Designer, FLI Editor
DYCP (Different Y Char Position)Move text characters at sub-character vertical resolutionCommon scroller effect
VSP (Variable Screen Position)Change $D016 mid-line to shift the screen's startMayhem in Monsterland, demos
Sprite stretchingRe-enable Y-expand mid-spriteVisual effect for stretchy logos
Hi-res rastersChange colour every cycle for Atari-style coloured stripesCommon backdrop

Cycle-accurate timing

Raster effects are extremely demanding on timing:

  • Stable raster — the IRQ has to fire at a predictable cycle, but interrupt latency varies by 0-7 cycles depending on what instruction was executing. Demoscene technique: NOP-pad the routine before the IRQ fires to absorb the variance.
  • Badlines on C64 — every 8th scanline the VIC-II steals 40-43 cycles for memory access, breaking inner-loop timing. Demos work around this with carefully-placed code.
  • PAL vs NTSC — different scanline counts (312 vs 263) and per-line cycle counts (63 vs 65 PAL/NTSC). Effects timed for one region desync on the other.

See Stable Raster for the C64 demoscene technique of getting cycle-perfect raster IRQ.

Per-platform comparison

PlatformMechanismCost
C64 / VIC-IIRaster IRQ at any lineCPU-bound; effects compete with game logic for cycles
Amiga / CopperCopper list runs in parallelFree — Copper doesn't steal CPU time
NES / sprite-0 + MMC3Sprite-zero hit + mapper IRQCPU polling (sprite-0) or hardware IRQ (MMC3); per-scanline is doable
SNES / HDMAHardware DMA per scanlineFree for direct register changes; fixed-pattern only
Spectrum / cycle-countCycle-counting from frame IRQHardest — no raster IRQ; contention complicates timing

See also