Mode X in Turbo Pascal, Part 1: Planar Memory and Pages
Mode 13h is the famous VGA “easy mode”: one byte per pixel, 320x200, 256 colors, linear memory. It is perfect for first experiments and still great for teaching rendering basics. But old DOS games that felt smoother than your own early experiments usually did not stop there. They switched to Mode X style layouts where planar memory, off-screen pages, and explicit register control gave better composition options and cleaner timing.
This first article in the series is about that mental model. Before writing sprite engines, tile systems, or palette tricks, you need to understand what the VGA memory controller is really doing. If the model is wrong, every optimization turns into folklore.
If you have not read Mode 13h Graphics in Turbo Pascal, do that first. It gives the baseline we are now deliberately leaving behind.
Why Mode X felt “faster” in real games
The practical advantage was not raw arithmetic speed. The advantage was control over layout and buffering:
- You could keep multiple pages in video memory.
- You could build into a hidden page and flip start address.
- You could organize writes in ways that matched planar hardware better.
- You could avoid tearing without full-frame copies every frame.
What looked like magic in magazines was mostly disciplined memory mapping plus stable frame pacing.
The key shift: from linear bytes to planes
In Mode X style operation, pixel bytes are distributed across four planes. Adjacent pixel columns are not consecutive memory bytes in the way Mode 13h beginners expect. Instead, pixel ownership rotates by plane. That means one memory offset can represent four neighboring pixels depending on which plane is currently enabled for writes.
The control knobs are VGA registers:
- Sequencer map mask: choose writable plane(s).
- Graphics controller read map select: choose readable plane.
- CRTC start address: choose which memory area is currently displayed.
Once you accept that “address + selected plane = pixel target,” most confusing behavior suddenly becomes deterministic.
Entering a workable 320x240-like unchained setup
Many implementations start by setting BIOS mode 13h and then unchaining to get planar behavior while keeping convenient geometry assumptions. Exact register recipes vary by card and emulator, so treat this as a pattern, not sacred scripture.
procedure SetModeX;
begin
asm
mov ax, $0013
int $10
end;
{ Disable chain-4 and odd/even, enable all planes }
Port[$3C4] := $04; Port[$3C5] := $06; { Memory Mode }
Port[$3C4] := $02; Port[$3C5] := $0F; { Map Mask }
{ Graphics controller tweaks for unchained access }
Port[$3CE] := $05; Port[$3CF] := $40;
Port[$3CE] := $06; Port[$3CF] := $05;
end;
Do not panic if this looks low-level. Turbo Pascal is excellent at this style of direct hardware work because compile-run cycles are fast and failures are usually immediately observable.
Plotting one pixel with plane selection
A minimal pixel routine makes the model tangible. X chooses plane and byte offset; Y chooses row stride component.
procedure PutPixelX(X, Y: Integer; C: Byte);
var
Offset: Word;
PlaneMask: Byte;
begin
Offset := (Y * 80) + (X shr 2);
PlaneMask := 1 shl (X and 3);
Port[$3C4] := $02;
Port[$3C5] := PlaneMask;
Mem[$A000:Offset] := C;
end;
The 80 stride comes from 320/4 bytes per row in planar addressing. That single number is where many beginner bugs hide, because linear assumptions die hard.
Pages and start address flipping
A stronger reason to adopt Mode X is page strategy. If your card memory budget allows it, maintain two or more page regions in VRAM. Render into non-visible page, then point CRTC start address at the finished page. That is cheaper and cleaner than copying full frames through CPU-visible loops every tick.
Conceptually:
displayPageis what CRTC shows.drawPageis where your renderer writes.- End of frame: swap roles and update CRTC start.
The code details differ by implementation, but the discipline is universal: never draw directly into the page currently being scanned out unless you enjoy tear artifacts as design motif.
Practical debugging advice
When output is wrong, do not “optimize harder.” Validate one axis at a time:
- Fill one plane with a color and confirm stripe pattern.
- Write known values at fixed offsets and read back by plane.
- Verify start-address page flip without any sprite code.
- Only then add primitives and scene logic.
This sequence saves hours. Most graphics bugs in this phase are addressing bugs, not “algorithm bugs.”
Where we go next
In Part 2, we build practical drawing primitives (lines, rectangles, clipped blits) that respect planar layout instead of fighting it:
Related context:
Mode X is not difficult because it is old. It is difficult because it requires a precise mental model. Once that model clicks, the hardware starts to feel less like a trap and more like an instrument.