INT 10h Palette Services: EGA Attribute Mapping, VGA DAC State, and Restoration
Change EGA and VGA colors through BIOS palette services while keeping attribute mapping, DAC values, blink state, and restore behavior distinct.
The PC video BIOS exposes palette services through INT 10h, function AH=10h. The name “palette” covers more than one layer. On EGA-compatible modes, attribute values select palette registers, and those registers map to adapter color values. VGA adds a digital-to-analog converter (DAC) palette for mapping color indexes to output levels. Changing an attribute palette register is not automatically the same operation as changing a VGA DAC entry.
This distinction is essential when a program paints a screen, shares the display with another DOS utility, or tries to restore the previous console appearance. BIOS functions are adapter- and mode-dependent. A BIOS call that is meaningful on EGA/VGA may be unsupported or behave differently on CGA, MCGA, a clone, or a virtual video BIOS. Probe the active adapter and mode, use only documented services for that target, and keep a fallback that does not require custom colors.
The EGA/VGA attribute palette path
The documented AX=1000h call sets one palette register. BL selects the register and BH provides the value. AX=1002h loads the set of palette registers from an array addressed by ES:DX; the documented table contains 16 palette values plus an overscan/border value. Ralf Brown’s Interrupt List and the IBM PS/2 BIOS reference describe these call forms and adapter-specific constraints.
An illustrative single-register operation looks like this:
mov ax, 1000h ; INT 10h, set one palette register
mov bl, 01h ; select palette register 1
mov bh, 04h ; write adapter color value 4
int 10h
The BH value is not an RGB triplet. It is an adapter color value interpreted by the palette hardware and current mode. Do not label it “red” or assume its result without checking the active palette and adapter. Some BIOS references advise clearing BH on calls such as bulk palette updates to avoid compatibility issues; follow the exact service documentation and test on the supported machine.
The bulk AX=1002h call takes a pointer to the palette list, and the BIOS consumes the array synchronously as part of the call. Ensure that the data is accessible at ES:DX, remains within a valid real-mode segment, and contains all documented entries. Never point at a near pointer in the wrong segment or use a stack buffer whose lifetime or address is uncertain.
Blink and background intensity share a control bit
Text attributes commonly encode foreground and background colors. On compatible EGA/VGA systems, BIOS AX=1003h selects whether the shared attribute bit provides background intensity or blinking. BL=00h enables background intensity; BL=01h enables blinking. This is global display state, not a per-character setting. Changing it can make existing text backgrounds brighter or cause characters to blink, even though no text cells were rewritten.
An application that changes blink mode should record the previous state when the target BIOS supports a reliable readback path and restore it on normal exit. Do not infer the current setting solely from the visible screen: a dark background can be either a palette value or the effect of blink-mode configuration. Pre-VGA adapters may not offer the same query mechanisms, and BIOS documentation notes version-specific ways to inspect VGA state.
If a program is terminated abnormally, its cleanup routine may not run. For a utility that temporarily changes a user’s console, consider a startup path that resets the mode and palette or provide a documented recovery key. Do not expect a shell prompt, ANSI driver, or another program to reconstruct a palette it did not save.
VGA DAC operations are another layer
The VGA DAC maps palette indexes to analog red, green, and blue output values. BIOS implementations provide DAC-related subfunctions under the same AH=10h family, but their registers and data formats are different from the EGA attribute palette mapping. The adapter’s DAC component and VGA BIOS reference determine the valid entry count, component precision, and call behavior. Avoid reusing an EGA register table as if it were a list of DAC RGB triples.
When debugging a wrong color, identify which stage is wrong. A text cell’s attribute may select a different palette entry than expected; the EGA/VGA attribute controller may map that entry differently; the VGA DAC may map the selected index to unexpected component levels; or a monitor profile may alter the perceived result. Log the video mode, the written register index, the written value, and any readback result before changing direct hardware registers.
Do not program VGA ports behind the BIOS while also relying on BIOS palette state. Direct writes can desynchronize what the BIOS believes from what the adapter currently displays. Use a single ownership model: BIOS services for a simple compatible utility, or a deliberate video driver for a program that owns the adapter. Mixing layers without saving and restoring state makes later BIOS calls unpredictable.
A small swatch test is better than guessing
Build a disposable test that writes labeled swatches using known foreground/background attribute pairs. Change one register at a time and record which swatches changed. Restore the original palette before exiting. Repeat under the exact mode and video BIOS in scope. A change to a palette register can affect every displayed character using that entry, not just the program’s own window.
For a graphics mode that directly uses indexed colors, test DAC mappings separately from text attributes. Use a small gradient or color bar with known index values. Capture screenshots or record analyzer measurements where exact colors matter. A visually correct result in one emulator does not demonstrate that the DAC values or attribute indexes match physical VGA hardware.
Run failure-path tests too: invalid adapter, unsupported subfunction, exit through each menu path, Ctrl-C, and an application error after a palette change. If the program stores a snapshot, test that restoration uses the same adapter and mode and that its buffer includes every field the BIOS API expects. If no supported readback exists, either constrain the software to a known startup state or avoid changing the shared state.
Preserve mode and palette state together
A palette belongs to a mode and adapter configuration. Changing video mode can reset or reinterpret palette values, so restore operations should happen in a deliberate order: save state while it is valid; set the intended mode; then restore the corresponding palette and blink/intensity policy. Do not restore a palette snapshot from one mode into another unless the video BIOS documentation explicitly supports the transfer.
The BIOS service may not expose a complete portable snapshot on every adapter. Prefer documented read calls for the specific hardware, and treat unavailable fields as unknown rather than filling them with guessed defaults. If the program is only a text utility, consider leaving the existing palette alone or changing a single documented register with a known original value. Simpler ownership reduces the chance of leaving the user’s console in a confusing state.
Acceptance testing should prove that the baseline screen is captured, the intended colors change, unrelated attributes remain understood, every exit path restores state, and a basic text mode still works after an error. Record adapter class, BIOS/emulator, mode, INT 10h subfunctions, and before/after values. “The screen looked right once” is not a compatibility guarantee.
Related:
- DOS Video BIOS INT 10h: Modes, Pages, Cursor State, and Compatibility
- VESA VBE on FreeDOS: Discover Modes Before Touching the Framebuffer
Sources: