Skip to content
FreeDOSDeep Dive Published Updated 7 min readViews unavailable

VGA Mode 13h: Chain-4 Addressing and the 64 KiB Framebuffer

Map Mode 13h pixels correctly by deriving the 320-byte stride, chain-4 plane selection, 64 KiB aperture limits, and page and palette boundaries.

VGA BIOS mode 13h is remembered as a simple 320-by-200, 256-index-color screen. A program can address a pixel with a linear-looking formula, but the adapter is still a four-plane device. The familiar byte-array interface is made possible by VGA chain-4 addressing, which selects one plane from the low address bits and maps successive host addresses across the four planes. That distinction matters when applications draw directly, page memory, share the video BIOS, or try to generalize a Mode 13h routine to another VGA mode.

The scope here is the conventional IBM VGA-compatible BIOS Mode 13h presentation. It does not claim every clone supports identical memory paging or undocumented register tricks, and it does not describe VBE linear-framebuffer modes. Use the BIOS or a documented video API when the program needs portability beyond this specific mode.

Pixel address and visible byte count

The visible raster contains 320 columns and 200 rows. For a zero-based pixel coordinate, the conventional packed host offset is:

offset = y * 320 + x

The bounds are 0 <= x < 320 and 0 <= y < 200. The last visible pixel is offset 63,999 decimal, or F9FFh. The image therefore occupies 64,000 bytes of the conventional A0000h display aperture. A 64 KiB aperture contains 65,536 byte addresses, leaving 1,536 bytes beyond the visible frame. That arithmetic does not imply a second complete page is available in the conventional Mode 13h layout.

In 16-bit code, an unchecked multiplication or index can wrap a 16-bit offset. Validate coordinates before calculating, use a wider intermediate if available, and verify that the computed address stays within the mode’s visible byte range. A000:0000 is a segment:offset spelling of the physical aperture in real mode, not a general protected-mode mapping request.

How chain-4 creates a linear-looking view

The VGA has four 64 KiB memory maps/planes, but the CPU interface does not expose them as four simultaneous byte arrays in this mode. The Sequencer Memory Mode register’s Chain 4 bit uses the low two address bits to select which map is accessed. The IBM technical reference also specifies that all maps should be enabled in the Map Mask register while chain-4 mode is selected. In a common Mode 13h configuration, host offset n therefore routes to plane n & 3 and plane byte offset n >> 2.

For example, consecutive host bytes 0, 1, 2, and 3 select maps 0, 1, 2, and 3 at plane offset 0. Host byte 4 returns to map 0 at plane offset 1. The program sees a consecutive byte stream because the adapter performs this interleave. If code clears the chain-4 bit, restricts the map mask, or changes the memory map, the same A000 write no longer behaves as the expected pixel store.

This is why a Mode 13h formula should not be described as proof that VGA memory is inherently packed. It is a mode-specific mapping contract. A 16-color planar mode uses different register state and bit calculations; a VBE mode can expose a pitch and pixel format that differ from both. Do not carry the Mode 13h address formula into another mode without querying its layout.

A bounded pixel write

For code that deliberately owns Mode 13h, a safe helper validates the coordinates, computes the offset with a wide intermediate, and writes only within the visible region. The following is language-neutral pseudocode because far-pointer declarations and I/O privileges depend on the DOS compiler and execution environment:

bool put_pixel_13(unsigned x, unsigned y, unsigned color) {
    if (x >= 320 || y >= 200 || color > 255) return false;
    uint32_t offset = (uint32_t)y * 320u + x;
    if (offset >= 64000u) return false;
    vga_a000[offset] = (uint8_t)color;
    return true;
}

The palette index is not an RGB triple. The VGA DAC maps the index to output levels, and the current DAC contents determine the visible color. A program that needs a particular palette must establish or query that palette through documented VGA BIOS or adapter services, and it must restore shared display state if that is part of its contract.

Mode set through INT 10h function AH=00h, AL=13h initializes a standard interface on supporting BIOSes. It can clear display memory and change the prior text state. Capture the old mode and any display state the application promises to restore before setting the new mode. A basic restoration call is not sufficient if the application also changed the DAC, page origin, fonts, or other VGA registers.

Page flipping is not automatic in Mode 13h

The visible frame fits just under 64 KiB, which tempts code to place a second screen after it and change a start address. Standard Mode 13h does not itself promise two conventional full-screen pages in the 64 KiB aperture. A card may contain more memory and VGA can expose start-address and addressing controls, but page organization depends on register setup, scanout addressing, and the adapter’s memory. A custom page-flipping implementation must establish those details and reserve the source/destination areas explicitly.

For a conservative double buffer, keep the off-screen image in conventional or extended memory managed by the relevant DOS/XMS/DPMI API, then copy or convert to the visible aperture. The copy must fit the timing and memory-access rules of the target. A software buffer can cost additional conventional memory and bandwidth; a faster transfer path must be justified by measurements and obey the memory manager’s ownership contract.

Do not assume that setting the BIOS text-page selector will flip a Mode 13h framebuffer. The documented page API is mode- and BIOS-dependent, and standard graphics mode capabilities differ from text pages. If smooth page switching is essential, select a mode whose documented interface reports the needed framebuffer organization, such as a VBE mode with validated attributes and pitch.

Boundary and state failures

If pixels wrap at the right edge, a hard-coded row width or coordinate limit is wrong. If every fourth pixel is missing or colors repeat in groups, inspect chain-4 and plane-mask state. If the image appears shifted, check the start address, mode, display origin, and whether another component modified VGA registers. If writes work until a BIOS text call, the program likely assumed exclusive control after handing it back.

Direct writes also bypass DOS standard output and shell redirection. They are display operations, not console-stream output. A utility that must operate in batch mode needs a text fallback through DOS handles. Do not mix raw screen drawing with an ANSI driver or another application that concurrently owns the display without a defined coordination mechanism.

Acceptance checks for a Mode 13h renderer

Use four corner pixels, row-boundary pixels, and a checkerboard to verify the address formula. Test x values 0 and 319, y values 0 and 199, and ensure the last write stays at offset F9FFh. Draw each color index in a diagnostic strip, record palette state, and distinguish incorrect index writes from incorrect DAC mapping. Confirm a write does not modify bytes outside the planned visible or off-screen region.

Run on the exact emulator or physical VGA adapter in scope. Record BIOS, mode number, chain-4 configuration if directly inspected, palette, emulator scaling, and whether the program uses BIOS-only or direct-register initialization. Test entry from at least one text mode, normal exit restoration, error exit, and return after a child program. This is a test plan, not a claim that a VGA card is attached to the current authoring host.

Mode 13h is convenient because a VGA mapping makes each visible pixel look like one byte. Keep the scope precise: validate the mode, preserve the adapter state you change, bound every offset, and treat chain-4 as the hardware mechanism behind the simplified formula rather than as a universal framebuffer standard.

Related:

Sources:

Comments