Skip to content
RetrogamingDeep Dive Published Updated 7 min readViews unavailable

Sega Saturn VDP2: Scroll Planes, Priorities, and Color Calculation

Understand Saturn VDP2 plane generation, VRAM pattern tables, per-line scrolling, priority decisions, and composition with the VDP1 image.

The Sega Saturn’s VDP2 generates background and scrolling-plane imagery and combines it with the output of VDP1, the processor responsible for drawing sprites and polygons into frame buffers. VDP2 is not a simple “background layer behind all sprites” unit. It has multiple normal scroll planes, rotation-capable rendering modes, line and cell scroll controls, configurable pattern data, priorities, and color-calculation rules. The final pixel depends on the source plane, per-character or per-dot attributes, registers, and the timing state used for composition.

This architecture explains why a Saturn game can have a correct-looking VDP1 polygon image but still show incorrect 2D priority, scrolling, transparency, or color effects. An emulator must treat VDP1 and VDP2 as related image producers with a programmable compositor, not collapse them into a single host GPU draw order. The VDP2 manual is the authoritative reference for register layouts and conditions; modern emulator code can help identify implementation and test boundaries but should not replace the manual’s definitions.

Identify the planes and their roles

VDP2 provides normal background planes commonly labeled NBG0 through NBG3, as well as rotation-capable plane functionality. It also has back-screen and line-color facilities. Each plane has configuration for map or bitmap organization, character data, scroll values, color format, and display enable. The exact combinations are constrained by VDP2 mode and VRAM allocation; not every plane can use every format simultaneously.

For cell-based backgrounds, pattern-name data selects character patterns and associated attributes from VRAM. Pattern data then supplies pixel indices or color values according to the selected bit depth and color mode. Bitmap modes instead interpret a region of VRAM directly as pixel data. The renderer must account for pattern-name table layout, character size, plane size, and address calculation; a visually similar tilemap abstraction can be wrong if it assumes a generic console map format.

Line scroll and vertical cell scroll add another dimension. A plane may use scroll values that vary by line or cell, enabling wavy water, parallax, and localized movement. Rotation parameter tables allow transformations that are not expressible as one constant plane offset. The tables are structured data in VRAM, and the appropriate parameter set can vary by raster line. Treat them as inputs to the VDP2 pipeline rather than precomputing one global affine transform for the whole frame.

Priority and VDP1 composition

VDP2 assigns priority to plane output and uses those values when determining which source appears at a pixel. Priority can be affected by plane settings and by attributes associated with cell or dot data. VDP1’s framebuffer is another source that VDP2 composites into the output according to VDP2 priority and color-calculation settings. Therefore, a polygon is not invariably drawn on top of every background, and the plane order is not a universal static stack.

Color calculation can combine source colors under programmed conditions, including transparency and ratio controls. The exact result depends on the source’s priority and applicable calculation mode. Do not approximate all effects with alpha blending in a modern API: the Saturn’s color format, coefficient rules, and source selection can differ from floating-point blending. A correct implementation should evaluate the VDP2 conditions and produce the target color before applying host display conversion.

The compositor also depends on line timing and buffer state. VDP1 writes its rendered output to a framebuffer; VDP2 reads that image as part of its own output generation. If the emulator reads an old framebuffer or applies priority after a host-side postprocess, it may show one-frame lag or incorrect intersections. Define when VDP1 output becomes visible to VDP2 and validate the ordering with a test scene.

Allocate VRAM as part of the renderer contract

VDP2 VRAM is shared among pattern-name tables, character patterns, line-scroll tables, rotation parameter tables, and other data. A title may use a layout tailored to its screen modes. When the emulated memory mapping is wrong, symptoms can resemble bad tile decoding: characters are corrupted, scroll jumps, or rotation data seems random. Log the source addresses and register configuration before modifying rendering code.

Color RAM mode determines how color entries are stored and interpreted. The manual describes selectable CRAM layouts and color formats. The emulator must apply the correct mode to address calculation and channel extraction. Verify palette entries at the memory boundary, not only after RGB conversion; host color-space and gamma configuration can produce separate visual differences.

Do not normalize or rewrite VRAM contents merely to suit the host renderer. Preserve Saturn-visible addresses and let a translation layer convert pattern data into GPU textures. If a cache is used, invalidate it on every relevant VRAM write and register mode change. Cache keys should include formats and mapping state, not only the base address.

Debug plane and priority defects

When a layer disappears or appears above the wrong object, capture a small scene and inspect one pixel location through the pipeline. Identify which plane or VDP1 source contributes at that coordinate, the source pattern or framebuffer address, color index, priority, transparency, and color-calculation settings. Then verify which VRAM/register write last established those values.

Separate errors into stages: input register decoding, VRAM address generation, source pixel extraction, priority selection, color calculation, and host output. A capture of the final frame is useful, but a per-plane debug view can isolate the failing stage. Temporarily show NBG planes separately, visualize priority values as colors, and display VDP1 independently. Keep these diagnostics opt-in; they should not alter emulated hardware state.

Test multiple plane modes and the interactions that stress composition: scrolling behind polygons, priority changes by character, line scroll, rotation, color calculation, and VDP1 transparency. Use a known homebrew or emulator test suite with expected frames and register traces. Commercial games are useful integration tests but rarely isolate a single compositor rule.

Timing and accuracy boundaries

A frame-based implementation can be adequate for static screens but may fail raster effects that change scroll or priority mid-frame. Determine which register changes are sampled at frame start, line start, or particular access times from the VDP2 manual and hardware tests. Avoid assuming that every register is live immediately or latched uniformly.

For line-scroll and rotation effects, retain a raster-indexed view of the parameter data rather than reading one value at frame start. A game can update a parameter table as the display progresses, and VDP2’s sampling rules determine which line sees the change. Test updates before, during, and after the relevant scanline fetch window. If your implementation batches rendering, flush or version the affected cached plane state at a documented boundary so later register writes do not rewrite already-emitted lines.

A modern GPU implementation also needs to account for format conversion and cache invalidation. A texture cache keyed only by pattern address can return stale pixels after a VRAM write, color RAM mode switch, character format change, or display enable update. Track the source memory ranges and decoding modes that each cached surface depends on. In a software reference renderer, keep the VDP2 source pixel and priority as separate values until composition; collapsing them early makes priority and color-calculation mismatches harder to inspect.

Document any limitations around per-dot priority or line timing explicitly. A full-frame approximation may be a useful performance mode, but it should not be called accurate for raster effects until a test demonstrates the expected register sampling and output ordering.

VDP1 and VDP2 interactions have complicated timing, and documentation coverage can vary for edge conditions. If an implementation deliberately approximates a feature, identify the affected mode and keep it separate from validated behavior. A visually close screenshot is not enough to claim cycle accuracy. Compare intermediate events, frame-buffer selection, and register sampling wherever the title relies on raster composition.

Acceptance criteria

A VDP2 implementation should demonstrate correct plane addressing and format, scroll modes, rotation data, VRAM/CRAM interpretation, VDP1 composition, priority and color calculation, and the register sampling behavior it claims to support. Regression tests should include isolated plane images and mixed VDP1/VDP2 scenes. Document Saturn region/model, emulator version, test content hash, and any known approximation.

VDP2’s value comes from its programmable composition pipeline. Treat planes, rotation, VDP1 input, VRAM layout, priority, and color calculation as separate but ordered stages. That model makes Saturn graphics bugs diagnosable and prevents a modern GPU’s convenient layer stack from silently replacing the console’s actual rules.

Related:

Sources:

Comments