How the Genesis drew worlds.
We start from the very beginning — what a digital picture even is — assuming you know nothing about computer graphics. Once the vocabulary is solid, we follow a frame through Sega's remarkable Video Display Processor: tiles, palettes, planes and sprites, drawn a scanline at a time. Then we watch how emulators reproduce it. Sixteen modules, each with live, software-rendered labs so you can paint, scroll and break every idea, not just read it. No game artwork ships with this page; every image is drawn procedurally in your browser.
2D graphics fundamentals
Pixels, 8×8 tiles, indexed palettes, tilemaps, scrolling and sprites — the universal vocabulary of 2D console graphics, explained from zero.
The Sega VDP
The 315-5313 chip, its three memories, planes A/B and the window, the sprite engine's hard limits, raster effects, and shadow/highlight.
Emulating the VDP
Rendering a frame scanline by scanline, the genuinely hard parts of accuracy and timing, and how to see it all in a real emulator.
2D graphics fundamentals
This first part is pure fundamentals — nothing about any specific chip yet. It's the toolkit that every 2D console is built from: pixels, tiles, palettes, tilemaps, scrolling and sprites. We build the vocabulary one word at a time, and you can paint and drag each idea in a live lab. If a term is ever used before it's explained, that's a bug; tell us. Everything in Parts II and III is just these six ideas wired into silicon.
Pictures as pixels
Let's start with what a picture on a screen physically is. Lean in close to any display — a phone, or the family CRT the Genesis was plugged into — and the image falls apart into a grid of tiny glowing dots. Each dot is a pixel (from “picture element”), and it can show exactly one colour at a time. Step back and your eye fuses the grid into a smooth image. That's all a digital picture is: a rectangular grid of single-colour dots.
To put a picture inside a computer, we need a way to write one colour
as numbers. The trick — borrowed from your own eyes, which sense
colour with three kinds of cone cell — is to describe every colour as
a mix of red, green and blue light. Three numbers,
each from 0 (none) to 255 (full), and any colour on screen falls out:
(255, 0, 0) is pure red,
(255, 255, 255) is white,
(0, 0, 0) is black. This scheme is
RGB,
and each number is a channel. (Module 03 shows the
Genesis storing colour far more thriftily than this — but the idea is
the same.)
String it together: one picture = a grid of pixels; one pixel = three numbers. So a whole picture is a long, ordered list of numbers, row after row. The block of memory holding that list for the image on screen has a name you'll hear all course: the framebuffer. Draw into the framebuffer and you've drawn onto the screen. The resolution is the grid's size — and on 1988 hardware, every pixel cost precious memory, which is exactly why the Genesis almost never stores pictures pixel-by-pixel. It stores tiles. That's Module 02.
A mosaic portrait is thousands of small single-colour tiles. Up close: coloured squares. Across the room: a face. A pixel grid is a mosaic you can repaint sixty times a second — and the framebuffer is the numbered order sheet saying which tile goes where.
Play with the idea below. The little scene is repainted from scratch at whatever grid size you pick — drag the resolution from a chunky 8 × 8 up and watch detail appear as pixels shrink. Then switch off channels: with only R lit, you're literally seeing one third of the framebuffer's numbers. Hover any pixel to read its three values.
- A digital image is a grid of pixels; each pixel is one colour, classically three RGB numbers.
- The framebuffer is the memory holding those numbers for the on-screen image.
- Resolution = the grid's size; more pixels means finer detail and more memory.
- Storing whole pictures pixel-by-pixel was too costly in 1988 — the Genesis stores small reusable tiles instead (Module 02).
Tiles & patterns
Module 01 ended with a warning: a whole-screen framebuffer is expensive. A 320 × 224 picture at even one byte per pixel is about 70 KB, and the Genesis has only 64 KB of video memory for everything. Storing the screen as loose pixels simply doesn't fit. So the machine does what a bricklayer does: it builds big pictures out of small, reusable units. That unit is the tile (Sega's manuals call it a pattern, or a cell): a fixed 8 × 8 square of pixels.
A tile is stored once in memory and referenced from many places on screen. A brick wall isn't 40 different pictures of bricks — it's one brick tile, placed a few hundred times. This reuse is the whole reason 2D consoles could show rich screens in tiny memory, and every idea in Part I builds on it.
Now, how many bits does one pixel of a tile take? Not 24. A Genesis tile pixel is 4 bits — a 4bpp number from 0 to 15. That's not enough to name a colour directly, so it doesn't: the 4-bit value is an index into a list of 16 colours (the palette, Module 03). Index 0 is special — it means “transparent”, letting whatever is behind show through. Count the memory: 64 pixels × 4 bits = 256 bits = 32 bytes per tile. In 64 KB of VRAM you can hold around 2,000 unique tiles — a whole game's worth of building blocks.
A tile is a rubber stamp. You carve a small design once, then press it onto the page wherever you want — a hundred identical bricks from one stamp, cheap as ink. The Genesis screen is a page stamped from a tray of a few hundred tiles; the trick is choosing stamps that recombine into everything a level needs.
The lab is a real 8×8 tile editor. Pick one of the 16 palette indices and paint the grid; watch the tile repeat seamlessly on the right — exactly what happens when the same pattern is placed across a background. Index 0 (the checkered swatch) stays transparent. You've just authored 32 bytes of VRAM.
- The Genesis builds every picture from reusable 8×8 tiles (patterns / cells), not a full framebuffer.
- Each tile pixel is 4 bits (4bpp) — an index 0–15 into a 16-colour palette, not a colour itself. Index 0 = transparent.
- One tile is 64 × 4 bits = 32 bytes; 64 KB of VRAM holds roughly 2,000 unique tiles.
- Reuse is the whole game: rich screens fit in tiny memory because the same stamp appears everywhere.
Palettes & colour
Module 02 left a gap: a tile pixel is a number 0–15, but a number isn't a colour. The bridge is a palette — a little lookup table. Entry 0 holds one colour, entry 1 another, up to entry 15. A tile pixel of value 6 means “whatever colour sits in slot 6.” This is indexed colour, and it is the beating heart of retro graphics. Two payoffs fall out immediately: pixels stay tiny (4 bits, not 24), and you can recolour an entire tile — day to night, hero's palette swap — by changing 16 table entries instead of every pixel.
The Genesis keeps its palettes in a dedicated 128-byte memory called CRAM, holding 64 colour entries total, arranged as 4 lines of 16. Any given tile picks one of those four lines (Module 04), so a tile always sees 16 colours — but different tiles can point at different lines, so the whole screen can show up to 61 colours at once (64 minus the shared transparent slot in each line, roughly). That constraint — 16 colours per tile, from one of four lines — shapes how Genesis art was drawn from day one.
And how is one CRAM colour stored? Not as 8 bits per channel. Each
colour is 9 bits: 3 bits each of blue, green and red
— packed as 0000 BBB0 GGG0 RRR0 in a 16-bit
word (this is
9-bit BGR).
Three bits per channel means 8 levels each, so the
master palette the hardware can make is
8 × 8 × 8 = 512 colours.
A game chooses 64 of those 512 to be live at any moment. (Module 12
shows a trick that effectively triples this by dimming and brightening
— but the base is 512.)
A paint-by-numbers canvas has numbered regions and a small tray of numbered paints. The canvas (your tiles) only stores numbers; the tray (the palette) holds the actual colours. Swap the tray for an autumn one and the same numbered canvas repaints itself in browns — no region redrawn. The Genesis has four little trays of sixteen paints, mixed from a master set of exactly 512.
The lab is a live CRAM editor. Click any of the 64 swatches, then set its blue, green and red to one of 8 levels each — the raw 9-bit value and its hex CRAM word update as you go. Notice how coarse 8 levels is, and how much character artists wrung from it anyway.
- Indexed colour: a tile pixel is an index into a 16-colour palette; recolour the table and the whole tile changes.
- CRAM holds 64 entries as 4 lines of 16; a tile uses one line, so 16 colours per tile.
- Each colour is 9-bit BGR — 3 bits (8 levels) per channel — from a master set of 8³ = 512 colours.
- Index 0 in a line reads as transparent; shadow/highlight (Module 12) stretches the palette further.
Nametables & the tilemap
We have tiles (Module 02) and colours for them (Module 03). Now we arrange them into a picture. The background isn't stored as pixels; it's stored as a grid of references — “cell (5,3) uses tile 42.” That grid is the nametable (Sega's word for a tilemap), and it is astonishingly cheap: one screen of background is a few kilobytes of tile numbers, pointing into the tiles you already stored once.
Each nametable cell is a single 16-bit word, and it carries more than a tile number. Bit by bit it packs: the low 11 bits are the tile index (which of up to 2,048 patterns); then a horizontal-flip bit and a vertical-flip bit (so one stored tile can face four ways — huge memory savings for symmetric art); then 2 bits of palette line (Module 03's four lines); and the top bit is priority, which decides whether this tile sits in the front or back layer when planes and sprites overlap (Modules 09 and 12). One word, and the tile is fully specified: what, which colours, which way up, how near.
Flip and palette bits are the frugal genius of the scheme. A perfectly symmetric arch needs only its left half stored; the right half is the same tiles with the H-flip bit set. A recoloured enemy is the same tiles pointing at a different palette line. On a machine with 64 KB of VRAM, every one of these tricks is bytes back in the bank.
A wedding planner doesn't glue photos of guests onto a floor plan; they write names in a grid of chairs. The nametable is that seating chart: each cell just names a tile from the tray and adds a couple of notes — face this way, wear this palette, sit up front. Rearranging the party is rewriting names, not repainting faces.
The lab is a working nametable. Pick a brush tile from the strip, set its palette line, flips and priority, then click cells to place it — and watch the decoded 16-bit word for the last cell you touched. Build a little scene; every cell you set is two bytes of tilemap.
- A background is a nametable (tilemap): a grid of 16-bit cells naming which tile fills each position.
- Each cell packs priority (1) · palette line (2) · V-flip (1) · H-flip (1) · tile index (11).
- Flip and palette bits let one stored tile face four ways and wear four colour sets — big VRAM savings.
- The nametable is tiny compared to a pixel framebuffer, which is exactly why it fits and can scroll (Module 05).
Scrolling
A nametable (Module 04) can describe a background larger than the screen — the Genesis planes can be up to 64 × 32, 64 × 64 or 128 × 32 cells, well past the ~40×28 the TV shows. Only a window onto that map is visible at any moment. Move the window and the world appears to move — that's scrolling, and it is why side-scrollers exist. The revolutionary part: you don't redraw anything. You change a small scroll register, and the VDP simply starts reading the map from a different offset. Moving a whole world costs a single number.
Two things make it seamless. First, the plane wraps: read past the right edge and you wrap to the left, so a map only a little wider than the screen can scroll forever if it's designed to tile. Second, the offset is in pixels, not cells, so motion is smooth to the pixel even though the map is stored in 8-pixel cells — the VDP fetches a whole cell and shows the correct 8-pixel-wide slice. Games stream fresh tiles into the columns and rows about to appear at the edges, so an endless level lives in a plane barely bigger than the screen.
The Genesis offers this on two independent planes at once (Module 09), and with per-line and per-cell variations (Module 11) that produce parallax and wobble. But the core is this module's one idea: a big map, a small window, and a register that slides one over the other.
Lay a long paper map on a desk and slide a cardboard frame across it: you see only the framed patch, and sliding the frame reveals new country without moving the map. The scroll register is where you've slid the frame. Loop the map into a ring and you can slide forever.
The lab shows a plane far larger than its viewport. Drag the scroll X and Y (or hit auto-scroll) and watch the window glide over the map, wrapping at the edges — the minimap shows where the visible rectangle sits on the whole 64×32 plane.
- A plane can be far bigger than the screen; only a window is visible, and moving the window = scrolling.
- Scrolling costs a scroll-register write, not a redraw — the VDP just reads the map from a new offset.
- Planes wrap seamlessly, and offsets are per-pixel, so motion is smooth despite 8-pixel cells.
- Endless levels stream new tiles into the edges of a plane only slightly larger than the screen.
Sprites
Backgrounds are locked to their grid: a nametable cell is always at a cell position. But a game needs things that move independently of the grid — Sonic, a ring, a laser. Those are sprites: groups of tiles the VDP places at any pixel position, over the planes, without disturbing the background at all. A sprite is defined not in the tilemap but in a separate list — the sprite attribute table — and the VDP composites it on top as it draws.
A Genesis sprite can be up to 4×4 cells (32×32 pixels) from a single entry, and each entry stores: the sprite's Y and X position, its size in cells, a link field (the index of the next sprite to process — sprites form a linked list), and the familiar attribute bits — palette line, H/V flip and priority. Priority is what lets a character walk behind a foreground pillar: a high-priority background tile can out-rank a low-priority sprite. That single bit, shared with Module 04's nametable, is how the whole scene interleaves in depth without a per-pixel depth buffer.
Big characters are just several sprites linked together and moved in lockstep — Sonic is a little flock of sprites. That flexibility is free-ish, but not unlimited: the VDP can only process so many sprites per scanline before it runs out of time, which is the hard, visible limit we dig into in Module 10.
A background painting is fixed, but the animator lays felt cut-outs on top and slides them around to tell the story. A sprite is a felt figure: it floats over the scene, can be flipped, tinted with a palette line, and told to tuck behind a foreground cut-out. Nothing underneath is touched — lift the figure and the painting is intact.
The lab composes a small sprite from a 3×3 grid of tiles. Drag it over the background; toggle H/V flip; and flip its priority to send it behind the brick wall (high-priority background) or back in front. That toggle is the entire depth model of the machine.
- Sprites are tile groups positioned freely over the planes, defined in a separate attribute table, not the tilemap.
- Each entry stores position, size (up to 4×4 cells), a link to the next sprite, palette, flip and priority.
- The priority bit — shared with nametable cells — is how sprites pass in front of or behind background layers.
- Large characters are several linked sprites; the cost is the per-scanline sprite limit (Module 10).
The Sega VDP
Now we put the Part I toolkit into real silicon. The Genesis draws everything with one chip — the VDP, the Video Display Processor — that owns three separate memories, two scrolling planes plus a window, a sprite engine, and a bag of raster and colour tricks. These seven modules cover the chip, its memory, its planes, the sprite engine's famous limits, per-line scroll effects, shadow/highlight, and the DMA pipeline that feeds it. From here on we name real hardware, but every piece maps back to a fundamental you already know.
Meet the VDP
The Genesis graphics chip is the VDP, part number 315-5313, descended from the Texas Instruments TMS9918 line by way of the Sega Master System's VDP (the YM7101/315-5313 lineage). It is a fixed-function tile-and-sprite engine: you don't program it with code, you configure it through two dozen internal registers and feed it data. It renders 256×224 (H32) or 320×224 (H40) pixels on NTSC — 240 lines on PAL — one scanline at a time, sixty (or fifty) times a second.
The VDP sits at the centre of the console's video world. The main CPU — a Motorola 68000 at 7.67 MHz — writes tiles, tilemaps, palettes and sprite lists to the VDP and sets its registers. The VDP owns three private memories (Module 08), does all the compositing, and scans the finished image out to the TV. It also generates the two interrupts games live by: a VBlank once per frame (level 6 on the 68000) and a programmable HBlank (level 4) after a chosen line — the timer that makes mid-screen tricks possible.
Calling the VDP “just a graphics chip” undersells its role as traffic cop: it arbitrates access to VRAM between its own rendering and the CPU's writes, runs the DMA engine that blasts data into video memory (Module 13), and even passes the Z80 sound CPU's world by sharing the bus. Everything you see on a Genesis passed through this one chip.
On the numbers. “Blast processing,” Sega's famous slogan, was marketing for fast DMA into VRAM — real, but not a magic mode. The honest figures are the ones above: 64 colours of 512, two planes, a hard sprite budget, and a scanline clock. The artistry was in spending them.
- The VDP (315-5313) is a fixed-function tile/sprite engine you configure through registers, not code.
- It renders 320×224 (H40) or 256×224 (H32), 224 NTSC lines / 240 PAL, one scanline at a time.
- It owns three memories, composites planes + sprites, and raises VBlank and programmable HBlank interrupts.
- “Blast processing” was fast-DMA marketing — the real budget is 64/512 colours, two planes and a sprite limit.
VRAM, CRAM & VSRAM
The VDP doesn't draw from the 68000's work RAM. It has its own memory, and — a detail that trips up newcomers — it's actually three separate memories, each purpose-built. Keeping them distinct lets the hardware read all three simultaneously while building a scanline, which is the only way it keeps up with the beam.
The sizes tell a story. 64 KB of VRAM is the whole graphical world — every tile, map and sprite must fit, which is why Modules 02 and 04 were so obsessed with reuse. CRAM is tiny because indexed colour (Module 03) needs only 64 entries. And VSRAM is tiny and weird — 80 bytes — because it does exactly one narrow job: remember how far up or down each pair of columns has scrolled.
The CPU can't touch these memories directly like normal RAM. It reaches them through the VDP's data and control ports: set an address, then stream words in. During active display the VDP is busy with the beam, so writes mostly happen during VBlank — or via DMA, which muscles data in fast (Module 13). This port-and-timing dance is the source of half of Part III's emulation headaches.
A typical 64 KB VRAM layout — proportions vary per game, but tiles dominate; the maps, sprite list and scroll table are comparatively tiny.
Think of a print shop: a big rack of carved stamps and layout sheets (VRAM), a small tray of ink pots (CRAM), and a slim notebook of margin settings (VSRAM). Three stores, three jobs, all reachable at once — because the press can't wait for one clerk to fetch everything in turn.
- The VDP has three private memories, read in parallel while a scanline is built.
- VRAM (64 KB) holds tiles, the plane and window nametables, the sprite table and the H-scroll table.
- CRAM (128 bytes) holds the 64 palette colours; VSRAM (80 bytes) holds per-column vertical scroll.
- The CPU reaches them only through the VDP's ports (or DMA), mostly during VBlank — a timing dance that matters in Part III.
Planes A, B & the window
The VDP composites two full scrolling planes — Plane A and Plane B — each its own nametable (Module 04), each with its own scroll registers (Module 05). Plane B is usually the far background, Plane A the nearer one, and sprites float over both. Because each plane scrolls on its own numbers, you can move them at different speeds: shift the far plane slowly and the near plane quickly, and your eye reads the difference as distance. That's parallax, and it is the signature look of 16-bit side-scrollers.
Depth between the two planes isn't only front-to-back order — the priority bit (Module 04) interleaves them per tile. A high-priority Plane A tile can sit above Plane B, while a low-priority Plane A tile tucks beneath it, so foliage, bridges and foreground arches can weave through the scene. Add the sprite priority bit (Module 06) and the VDP resolves a surprisingly rich depth order from just one bit per element.
The third layer is the window: a rectangular area, locked to Plane A's tiles but not scrolled, pinned to screen coordinates. Games carve the window out for status bars, score displays and life meters — the strip that stays put while the world scrolls beneath it. It isn't a third scroll plane; it's a fixed cut-out of Plane A that the VDP draws instead of the scrolling version wherever the window is enabled.
On a stage, painted backdrops hang on rails at different depths and slide at different rates to suggest travel — the far mountain backdrop crawls, the near hedge rushes past. Plane B and Plane A are those flats; sliding them at different speeds is parallax. The window is the proscenium arch — bolted to the theatre, never moving with the scenery.
The lab runs a real two-plane parallax scene. Plane B carries a distant starfield and mountains; Plane A the near ground and trees. Set each plane's speed and watch depth appear and vanish — set them equal and the world flattens; spread them and it leaps into 3D.
- The VDP composites two independent scroll planes, A and B, plus a fixed window region of Plane A.
- Scrolling the planes at different speeds produces parallax — the core depth illusion of the era.
- The per-tile priority bit interleaves planes (and sprites) in depth without any depth buffer.
- The window is a non-scrolling cut-out of Plane A, used for HUDs and status bars.
The sprite engine & its limits
Sprites (Module 06) feel free, but the VDP builds them under a strict clock. It doesn't draw sprites whole; it assembles each scanline by walking the sprite list and fetching the tile row each visible sprite contributes to that line. It has a fixed budget of time per line, and that budget translates into two hard ceilings.
- Sprites per line. In H40 (320-pixel) mode the VDP can process 20 sprites on any one scanline; in H32 (256-pixel) mode, 16. Sprites past that number on a line simply aren't drawn there.
- Sprite pixels per line. Independently, it can only fetch 320 sprite-pixels of tile data per line in H40 (256 in H32). Twenty small sprites or a few wide ones can hit this first.
Whichever ceiling you hit first, the sprites processed later in the list drop out for that scanline — the classic sprite overflow. (The total number of sprites on screen also has a cap — up to 80 in H40, 64 in H32 — but the per-line limit is what you actually see.) Games fight it constantly: they alternate which sprites drop between frames, so the loss spreads out as flicker rather than a permanent hole; they order the sprite list so important objects come first; and they keep bosses narrow on any single line. That flicker in a busy shoot-'em-up isn't a bug — it's the sprite engine gracefully running out of time.
A small ferry loads cars in the order they queued, until either twenty cars are aboard or the deck's length is used up — whichever comes first. Cars past the limit wait for the next sailing. The VDP's scanline is that ferry: it boards sprites in list order until the count or the pixel-length runs out, and the rest are simply left off the line.
The lab makes the limit tangible. Add sprites and widen them; drag the scanline (the blue bar) across the field. On that line, sprites are boarded in list order until the count or the pixel budget is spent — the surplus are struck out in red, exactly as the hardware would drop them. Switch between H40 (20 / 320px) and H32 (16 / 256px) to feel the different ceilings.
- The VDP builds sprites per scanline under a fixed time budget, giving two hard ceilings.
- Per line: 20 sprites (H40) / 16 (H32), and 320 sprite-pixels (H40) / 256 (H32) — whichever is hit first.
- Surplus sprites drop for that line; alternating the dropouts between frames turns loss into flicker.
- On-screen totals cap near 80 (H40) / 64 (H32), but the per-line limit is what players actually see.
Scroll modes & raster effects
Module 05 scrolled a whole plane by one number. The VDP is far more flexible than that. Horizontal scroll has three modes: whole plane (one offset for everything), per 8-pixel cell row (each row of cells can scroll separately), and — the powerful one — per scanline, where every single line reads its own horizontal offset from a table in VRAM. Vertical scroll has two: whole plane, or per 2-cell column, whose offsets live in that odd little 80-byte VSRAM.
Per-line horizontal scroll is a special effect generator all by itself. Feed the scroll table a sine wave and each scanline shifts a little differently, so a flat plane ripples — instant water, heat haze, or a wobbling dream sequence. Because the offsets are just a table the CPU updates, the pattern can animate every frame.
The deeper trick is timing. Module 07's programmable HBlank interrupt lets the CPU change VDP registers partway down the frame. Reprogram the scroll, or the palette, or the backdrop colour at line 120 and the top and bottom halves of the screen behave differently — a raster split. This is how a status bar stays fixed while the world scrolls, how skies gradient through more colours than a palette holds, and how pseudo-3D road games bend the road. The whole visual vocabulary of “the Genesis doing something impossible” is per-line scroll plus mid-frame register writes.
Imagine each slat of a Venetian blind showing one line of the picture, and being free to slide sideways on its own. Nudge each slat by a little more than the one above and the straight image bends into a ripple — that's per-line scroll. Now imagine reaching in halfway down and re-hanging the lower slats with different settings — that's a raster split.
The lab drives a per-line horizontal scroll over a reflected scene. The lower half is a mirror image whose every scanline gets a sine offset — raise the amplitude and change the frequency to shape the water. This is the exact effect a Genesis produces by writing a sine table into the H-scroll region of VRAM.
- Horizontal scroll can be per-plane, per-cell-row, or per-scanline; vertical can be per-plane or per-2-cell-column (VSRAM).
- Per-line horizontal scroll ripples a flat plane into water, heat haze and wobble.
- The HBlank interrupt lets the CPU change registers mid-frame — a raster split — for fixed HUDs, sky gradients and road bends.
- Most “impossible” Genesis visuals are per-line scroll plus mid-frame register writes.
Shadow, highlight & colour tricks
Sixty-four colours (Module 03) is not many, and the VDP has a mode that quietly stretches them: shadow/highlight. When enabled, every pixel can be drawn at one of three intensities — normal, shadow (roughly half brightness), or highlight (raised toward white). The same 64 colours now cover three tonal bands, so a scene reads as having far more shades than the palette literally holds — dusk, spotlights, transparency-like darkening, all without spending extra CRAM entries.
What decides a pixel's band is a clever reuse of the priority bit across planes and sprites. Low-priority background under high-priority nothing falls into shadow; specific sprite colours can force highlight or shadow onto whatever's beneath them; and a couple of special sprite palette indices act as operators rather than colours — one darkens the region it covers, another brightens it. Games used sprites purely as shadow-casters: an invisible sprite whose only job is to dim the ground beneath a character into a drop shadow, or to pool light under a lamp.
It's an approximation, and it has rules and edge cases the manuals spell out in fiddly detail — but the payoff was real: transparency-like effects on a machine with no true alpha blending, and a palette that punches above its 64 entries. Sonic's spinning-ball translucency, watery caves and moody boss arenas all lean on it.
Take one photograph and print it three ways — normal, half-stop dark, half-stop bright — then cut and collage them into a single picture. You've tripled the tonal range without a single new colour of ink. Shadow/highlight is the VDP doing that collage per pixel, live, from one 64-colour palette.
The lab lets you drag a zone over a colourful scene and set it to shadow or highlight, then toggle the whole mode on and off. Shadow halves the intensity under the zone; highlight lifts it. Same colours underneath — three different tiers on top.
- Shadow/highlight mode draws each pixel at normal, half (shadow) or raised (highlight) intensity.
- It effectively triples the tonal range of the same 64 colours — depth and transparency-like effects for free.
- The priority bit and special sprite indices act as operators that darken or brighten regions beneath them.
- Invisible “shadow-caster” sprites are how many games pooled shade under characters and lights.
DMA & the display pipeline
A frame is a race against the beam. While the VDP is scanning out the visible 224 lines, it needs VRAM for itself, so the CPU can only pour in new tiles, maps and sprite lists during the blanking periods — the short gaps when the beam is off-screen. There's a wide gap each frame (vertical blank) and a sliver at the end of every line (horizontal blank). Fit your updates into those gaps, or you fight the VDP for the bus and corrupt the display.
Doing that with the CPU one word at a time is far too slow for a whole screen of tiles. So the VDP has a DMA engine: tell it a source in 68000 memory, a destination in VRAM, and a length, and it streams the whole block in by itself, much faster than software stores. There are three flavours — a memory-to-VRAM copy (bulk uploads of graphics), a VRAM-to-VRAM copy, and a fast VRAM fill. Sega's “blast processing” slogan was, stripped of marketing, largely this: DMA fast enough to swap big chunks of the screen between frames.
The catch is that DMA also wants the bus, so a big transfer eats into the same blanking budget — run it too long and you steal time from the next frame, or must start it during VBlank precisely. Balancing DMA size against the blanking window is one of the core rhythms of Genesis programming, and reproducing that rhythm exactly is a real chore for emulators (Module 15).
A theatre can only change the set during the interval, not mid-scene. Blanking is that interval, and DMA is the loading dock's forklift: instead of a stagehand walking props on one at a time, it wheels the whole new backdrop in at once. But the forklift blocks the corridor while it runs — take too long and you're still restocking when the curtain rises.
- The CPU/DMA can safely write video memory only during blanking, when the VDP isn't using it — mainly VBlank.
- DMA copies whole blocks from 68000 memory into VRAM/CRAM/VSRAM far faster than CPU stores (three modes: copy, VRAM-copy, fill).
- “Blast processing” was, in plain terms, DMA fast enough to swap large screen regions between frames.
- DMA competes for the bus and the blanking budget — timing it against the frame is a core Genesis skill (and an emulation headache).
Emulating the VDP
Finally: how does software on your PC stand in for that chip? A VDP emulator has to composite planes and sprites a scanline at a time just like the hardware, honour the sprite limits and shadow/highlight rules exactly, and — hardest of all — reproduce the razor-edge timing of mid-frame register writes and DMA. These three modules connect the whole course to real, open-source emulators: Genesis Plus GX and BlastEm.
Scanline rendering
The tempting way to emulate a 2D chip is to draw each whole plane, then the sprites, then hand over a finished frame. It's simpler, faster — and wrong for the Genesis. The real VDP produces the image one scanline at a time, and a game can change almost anything between lines: the scroll, the palette, the backdrop, even which plane is where. An accurate emulator must therefore do the same — a scanline renderer — compositing each of the 224 lines in lockstep with the CPU, so a register write on line 120 affects lines 120 onward and not a pixel above.
Per line, the emulator does what the hardware does: read the scroll for this line, fetch the right row of tiles from planes B and A, walk the sprite list gathering up to the per-line budget (Module 10), resolve priority and shadow/highlight per pixel, and emit 320 (or 256) finished pixels. Both Genesis Plus GX and BlastEm are built around exactly this loop; BlastEm goes further and models the VDP at close to per-pixel cycle granularity, which is what lets it reproduce effects that change registers within a single line.
The lab below is a scanline renderer. Watch the raster beam (the blue bar) sweep top to bottom, compositing planes and a sprite one line at a time; below the beam the frame isn't drawn yet. Move the split slider and a mid-frame register change repaints the backdrop from that line down — precisely the mechanism a real emulator must honour to the exact scanline.
A tapestry can't be reasoned about as finished cloth if the weaver swaps threads mid-row. A VDP emulator is the weaver: it lays the picture one row at a time, and whatever the CPU hands it before a row is what that row is woven from. Skip ahead to the finished cloth and you lose every mid-frame thread change — which, on the Genesis, is half the artistry.
- The VDP builds the image one scanline at a time; games change scroll, palette and backdrop between lines.
- An accurate emulator composites each line in lockstep with the CPU, so mid-frame writes land on the right lines.
- Per line it reads scroll, fetches plane rows, gathers sprites under the per-line budget, and resolves priority + shadow/highlight.
- Genesis Plus GX and BlastEm are built on this loop; BlastEm models near per-pixel timing for within-line effects.
The hard parts
Scanline rendering (Module 14) gets you a long way. The remaining difficulty is almost all timing: games were written against the VDP's exact clock, and cutting corners on when things happen breaks the very effects that make Genesis games look special.
1 · Mid-line register changes
The nastiest case: a game changes a VDP register partway across a single scanline, so the left of a line uses one scroll or palette and the right uses another. A renderer that only re-reads state at the start of each line gets these wrong. Faithfully handling them means stepping the VDP and CPU in lockstep at close to pixel granularity — the reason BlastEm exists and is built the way it is. Genesis Plus GX handles the common cases well; the exotic ones are where accuracy projects earn their keep.
2 · DMA timing & the FIFO
Module 13's DMA has to be modelled with its real cost: it steals bus cycles, its rate differs during active display versus blanking, and the VDP's write FIFO can stall the CPU when it fills. Get the DMA rate slightly wrong and a game either uploads more than the hardware could — showing graphics too early — or corrupts VRAM because the emulator let a write land while the real VDP would have been busy.
3 · Sprite-overflow & masking accuracy
Module 10's limits must be reproduced exactly, including the order sprites drop, the sprite-masking rules (special sprites at x=0 that hide others), and the overflow flag games read. Get it merely “close” and flicker patterns differ, or a game that uses a masking sprite to hide the status area leaks graphics. These are the corner cases regression-tested against real hardware captures.
4 · The CPU/VDP bus dance
The 68000 and VDP share a bus, and the exact stall a CPU write incurs when the VDP is busy is observable — some games time code by it. Model the arbitration too loosely and timing-sensitive intros, raster splits and sample playback drift out of sync.
Re-recording a film's soundtrack is easy until you must match lip movements to the exact frame. VDP emulation is the same: drawing the right pixels is the easy 90%; making every register write, DMA burst and bus stall land on the exact cycle — so the lips match — is the stubborn last 10% that separates “runs” from “accurate.”
- The residual difficulty is timing: games depend on when the VDP does things, not just what.
- Mid-line register changes demand near per-pixel CPU/VDP stepping — BlastEm's reason for being.
- DMA cost, rate and the write FIFO must be modelled, or transfers desync and VRAM corrupts.
- Sprite overflow order, masking and flags, and CPU-write bus stalls, are all observable and must match hardware.
Try it in an emulator
You now have the full picture, so let's make it hands-on. Open a debugging-friendly emulator — Genesis Plus GX (its debug/libretro builds) or BlastEm (whose built-in debugger is superb) — and read a running game with this course's eyes.
- VRAM / tile viewer — see Module 02's raw 8×8 patterns laid out in the 64 KB of VRAM. Watch them change as the game DMAs new graphics in (Module 13).
- Nametable / plane viewer — Module 04 and 09 made visible: inspect planes A and B, the window, and how scroll offsets slide them.
- CRAM / palette viewer — the four lines of 16 from Module 03, updating live; watch palette cycling and mid-frame palette splits.
- Sprite viewer — the attribute table from Module 06, the link order, sizes and priorities; a good viewer flags per-line overflow (Module 10).
- Register & raster view — where the VDP's two dozen registers live, and (in BlastEm) how they change per scanline — Module 11's raster effects, caught in the act.
- DMA / bus trace — Module 13 as a timeline: when transfers fire, how long they take, how they fit the blanking window.
An emulator's debugger looks like a wall of arbitrary panes — until you've walked the hangar and seen the tiles, planes, palettes and sprites each pane shows. You've just walked the VDP's hangar. Every window in that debugger is wired to a module you've now touched.
A great closing exercise: load a game with obvious parallax, open the plane viewer, and watch planes A and B scroll at different speeds (Module 09). Then find a water level and open the raster/register view to catch the per-line scroll table rippling (Module 11). Finally, step a frame and watch the scanline counter tick — you're no longer staring at mystery windows; you're watching a pipeline you know stage by stage.
- You can follow a Genesis pixel from a 4-bit tile index to a colour to a composited scanline on a CRT.
- You know the VDP's three memories, its two planes and window, its sprite limits, and its raster and colour tricks.
- You can read an emulator's VRAM, plane, CRAM, sprite and register views as a live map of everything in Parts I and II.
- Grounded throughout in the open-source emulators Genesis Plus GX and BlastEm — go run one and poke it.