Skip to content
FreeDOSDeep Dive Published Updated 7 min readViews unavailable

VGA Text Memory and CRTC Pages: Direct DOS Screen Ownership

Understand color and monochrome text apertures, character/attribute cells, CRTC start addresses, and when direct screen writes conflict with BIOS state.

Direct text output to VGA memory can be much faster than issuing one BIOS call for every character, but it is safe only when the program knows which video mode and adapter state it owns. In compatible color text modes, character and attribute bytes are commonly visible through the B8000h aperture; monochrome-compatible text modes commonly use B0000h. VGA memory is organized through planes and controller registers, so those conventional addresses are not universal pointers for every mode.

Text-mode display state also includes the CRT controller’s start address. A display page is not just a DOS buffer; the CRTC chooses which part of video memory is scanned for output. Direct writes can update an off-screen region, and changing the start-address registers can scroll or flip the visible page, but both operations must agree with the current adapter mode, memory mapping, and BIOS-maintained page state.

A text cell is two bytes, not a string character

In the common compatible text-memory layout, each cell occupies a character byte followed by an attribute byte. The character byte selects a glyph from the active character map. The attribute controls foreground/background color and, depending on mode and adapter configuration, blink or other display behavior. A run of ASCII bytes written contiguously without attribute bytes will alternate between characters and attributes and usually display as corruption.

The memory aperture and row layout depend on the active mode. Do not assume 80 columns, 25 rows, a fixed page size, or an 8-by-16 font. Query or set a known BIOS video mode first, obtain the relevant geometry and page state through the BIOS or a documented adapter interface, and calculate each cell address from the actual row stride. In graphics modes, the same address window may be planar or packed graphics memory rather than text cells.

The conventional color and monochrome memory windows are selected by the adapter’s memory-map configuration. On VGA, graphics-controller and sequencer state affect how CPU accesses map into planes; a text-mode layout should not be assumed after a program leaves text mode or manipulates those registers. A direct writer should either establish a known BIOS mode and leave plane mapping untouched, or save and configure every relevant register it depends on. The second choice is a driver-level commitment, not a harmless optimization.

Character and attribute bytes are interpreted through the active character generator and attribute-controller state. The same byte can select a different glyph after a font change. A color attribute may use its high bit for blink or background intensity depending on the mode configuration. If an application modifies fonts or palette mappings, a memory dump alone is not enough to explain what appeared on the monitor.

Video memory is shared state. A BIOS INT 10h call, TSR, terminal driver, or another application can change mode, page, font, palette, or cursor position while a program has direct assumptions cached. An ordinary single-task DOS program can usually assume it owns the display until it launches a child, but that assumption must be revisited after EXEC returns or after code yields to a resident multitasker.

CRTC start address and page selection

The VGA CRT controller provides start-address high and low registers, accessed through the selected color or monochrome index/data port pair. The active I/O base is determined by video state; software should not blindly write 3D4h/3D5h on a monochrome configuration that uses 3B4h/3B5h. The start-address value determines where display scanout begins in the adapter’s display memory. Address units and wrapping depend on the programmed CRTC mode and memory organization.

For a conventional text mode, BIOS page selection is usually the safer API: INT 10h/AH=05h asks firmware to select a display page using its model-specific contract. Direct CRTC writes are appropriate when the application deliberately owns the VGA-compatible hardware and has preserved the full register state it will alter. Do not combine BIOS page bookkeeping with ad hoc CRTC changes and then expect subsequent BIOS cursor or scroll calls to target the page you intended.

When writing CRTC registers, preserve reserved bits and modify only documented fields. A mode change often reprograms a group of registers; changing one start-address byte at the wrong moment can briefly point scanout to an invalid region or cause visual tearing. If a smooth page flip matters, update the start address at a safe display boundary when the adapter and timing model permit it. Do not claim tear-free behavior on an arbitrary VGA clone without testing its timing.

The start address is not interchangeable with the DOS notion of a display page number. BIOS page selection can translate a page number to a controller start value based on the current mode and geometry. A direct hardware application must perform that translation for the active CRTC addressing mode and account for wrap or memory limits. If the application edits only the low start-address byte, it can point at the wrong region once the start address exceeds 255 address units; update high and low fields consistently.

Restore state instead of leaving a broken console

Before direct access, record the mode, active page, cursor shape and position, and any CRTC registers the program will change. If the application changes fonts or palette state, record those separately. On normal exit, restore the previous state through a documented BIOS restore path when possible. If the program crashes, direct hardware state may remain changed until the user resets or a later program reinitializes the adapter; provide an escape key or recovery command for long-running tools.

Do not clear the screen by writing a guessed number of words to B8000h. If the mode is monochrome, graphics, 132-column, or a vendor extension, that can write to the wrong aperture or cover the wrong amount of memory. Prefer BIOS clear/scroll services when portability matters. For a fixed known mode, calculate row and page spans from the adapter’s documented parameters and bound every write.

Direct writes also bypass BIOS-maintained cursor state. After rendering through memory, update cursor state using the correct BIOS function or the cursor-location registers expected by the active page. If a later BIOS call writes a line, it may overwrite content or move a cursor based on stale page state. Decide whether BIOS or the application owns text output and keep that ownership consistent.

Safe diagnostic procedure

Begin with a known emulator or adapter in an explicit text mode. Capture the current mode, page, cursor, and register state. Write a small pattern to one cell in the intended page, verify its character and attribute, then restore it. Check the chosen aperture and row stride against the target mode before testing a full-screen buffer. Do not use random values in CRTC timing or mode-control registers to discover a page address.

For an issue that occurs only after a child process, verify whether the child changed the video mode and whether the parent restores it. For an issue in a DOS window or emulator, determine whether the environment virtualizes VGA ports or maps video memory differently. Compare BIOS API behavior and direct-memory behavior in the same mode before concluding that the hardware is faulty.

Acceptance checks should include color and monochrome-compatible modes if both are claimed, a child program that changes modes, a page switch, a graphics mode where text memory assumptions must be rejected, and a cleanup path that returns to the original screen. Verify that the screen contents, cursor, and selected page are all restored, not just that the display lights up.

For a deterministic regression test, write one character with a known attribute at the first and last cell of a selected page, compare the expected offsets, then restore the original bytes. If exercising a start-address change, use a known mode and a harmless pattern in an off-screen region before making it visible. Capture CRTC index/data values before and after, and confirm that active page and cursor still agree with BIOS state. A virtual VGA can validate register sequencing, but it cannot prove every physical clone has the same timing or page-wrap behavior.

Direct VGA text output is a performance technique with an ownership cost. Use BIOS interfaces for portable text, and use direct memory or CRTC writes only after mode, aperture, page, addressing units, and restoration policy are explicit. A plausible B8000h pointer is not proof that the current display is an 80-by-25 color text screen.

Related:

Sources:

Comments