| test | ||
| .gitignore | ||
| accelVid.c | ||
| accelVid.h | ||
| atiMach64.c | ||
| banshee.c | ||
| cirrusGd54.c | ||
| cirrusLaguna.c | ||
| demo.c | ||
| Makefile | ||
| matroxMga.c | ||
| nvidia.c | ||
| pci.c | ||
| pci.h | ||
| README.md | ||
| s3Trio.c | ||
| sis.c | ||
| trident.c | ||
| tsengW32.c | ||
| vgaCommon.c | ||
| vgaCommon.h | ||
DOS Accelerated Video Driver Framework
Hardware-accelerated 2D video drivers for DOS/DJGPP. Programs the acceleration engines on PCI video cards directly -- no VESA, no BIOS calls for rendering. A common API lets applications use acceleration without knowing which chip is present.
Supported Video Cards
S3 (s3Trio.c)
| Chip | Device ID | Notes |
|---|---|---|
| Trio32 | 0x8810 | |
| Trio64 | 0x8811 | MMIO at LFB+16MB |
| Trio64V+ | 0x8814 | MMIO at LFB+16MB |
| ViRGE | 0x5631 | MMIO, 3D engine ignored |
| ViRGE/VX | 0x883D | |
| ViRGE/DX/GX | 0x8A01 | |
| ViRGE/GX2 | 0x8A10 | |
| ViRGE/MX | 0x8C01, 0x8C03 | |
| Savage3D | 0x8A20, 0x8A21 | |
| Savage4 | 0x8A22 | |
| Savage/MX | 0x8C10, 0x8C11 | |
| Savage/IX | 0x8C12, 0x8C13 | |
| Savage 2000 | 0x9102 | |
| Vision864 | 0x88C0, 0x88C1 | I/O only (no MMIO) |
| Vision868 | 0x8880 | I/O only |
| Vision964 | 0x88D0 | I/O only |
| Vision968 | 0x88F0, 0x88F1 | I/O only |
Hardware ops: RectFill, PatFill, BitBlt, HostBlit, ColorExpand, LineDraw, HwCursor, Clip
ATI Mach64 / Rage (atiMach64.c)
| Chip | Device ID | Notes |
|---|---|---|
| Mach64 GX | 0x4758 | I/O only |
| Mach64 CX | 0x4358 | I/O only |
| Mach64 CT | 0x4354 | MMIO at end of aperture |
| Mach64 ET | 0x4554 | |
| Mach64 VT | 0x5654, 0x5655 | |
| 3D Rage II | 0x4754, 0x4755 | |
| Rage Pro | 0x4750, 0x4752 | |
| Rage 128 | 0x5245, 0x5246, 0x524B, 0x524C | |
| Rage 128 Pro | 0x5046, 0x5052 |
Hardware ops: RectFill, PatFill, BitBlt, HostBlit, ColorExpand, LineDraw, HwCursor, Clip
Matrox MGA (matroxMga.c)
| Chip | Device ID | Notes |
|---|---|---|
| Millennium (MGA2064W) | 0x0519 | Separate MMIO BAR |
| Mystique (MGA1064SG) | 0x051A | |
| G100 | 0x1000, 0x1001 | |
| G200 | 0x0520, 0x0521 | |
| G400 | 0x0525 | |
| G450 | 0x2527 |
Hardware ops: RectFill, PatFill, BitBlt, HostBlit, ColorExpand, LineDraw, HwCursor, Clip
3dfx (banshee.c)
| Chip | Device ID | Notes |
|---|---|---|
| Banshee | 0x0003 | MMIO + launch area for data |
| Voodoo3 | 0x0005 |
Hardware ops: RectFill, PatFill, BitBlt, HostBlit, ColorExpand, LineDraw, HwCursor, Clip
Cirrus Logic GD54xx (cirrusGd54.c)
| Chip | Device ID | Notes |
|---|---|---|
| GD5434 | 0x00A0, 0x00A8 | BLT via GR registers |
| GD5436 | 0x00AC | |
| GD5446 | 0x00B8 | |
| GD5480 | 0x00BC |
Hardware ops: RectFill, BitBlt, HostBlit, ColorExpand, HwCursor
Cirrus Logic Laguna (cirrusLaguna.c)
| Chip | Device ID | Notes |
|---|---|---|
| GD5462 | 0x00D0 | MMIO, different engine from GD54xx |
| GD5464 | 0x00D4 | |
| GD5465 | 0x00D6 |
Hardware ops: RectFill, BitBlt, HostBlit, ColorExpand, HwCursor, Clip
Nvidia RIVA / TNT (nvidia.c)
| Chip | Device ID | Notes |
|---|---|---|
| RIVA 128 | 0x0018 | PGRAPH subchannel interface |
| RIVA 128 ZX | 0x0019 | |
| TNT | 0x0020 | |
| TNT2 | 0x0028 | |
| TNT2 Ultra | 0x0029 | |
| TNT2 M64 | 0x002D | |
| Vanta | 0x002C |
Hardware ops: RectFill, BitBlt, HostBlit, HwCursor, Clip
Tseng ET4000/W32 (tsengW32.c)
| Chip | Device ID | Notes |
|---|---|---|
| W32 | 0x3202 | ACL engine via I/O ports |
| W32i | 0x3205 | |
| W32p rev A | 0x3206 | HwCursor on W32p only |
| W32p rev B | 0x3207 | |
| W32p rev C | 0x3208 | |
| W32p rev D | 0x4702 |
Hardware ops: RectFill, BitBlt, HostBlit, HwCursor (W32p only)
Trident TGUI (trident.c)
| Chip | Device ID | Notes |
|---|---|---|
| TGUI9440 | 0x9440 | GER engine via I/O ports |
| TGUI9660 | 0x9660 | |
| TGUI9680 | 0x9680 | |
| ProVidia 9685 | 0x9685 | |
| Blade3D | 0x9880 | |
| CyberBlade | 0x9910 |
Hardware ops: RectFill, BitBlt, HostBlit, HwCursor
SiS (sis.c)
| Chip | Device ID | Notes |
|---|---|---|
| 6326 | 0x6326 | MMIO queue-based engine |
| 300 | 0x0300 | |
| 305 | 0x0305 | |
| 315 | 0x0315 | |
| 330 | 0x0330 |
Hardware ops: RectFill, BitBlt, HostBlit, HwCursor, Clip
Capability Matrix
Operations not implemented in hardware get automatic software fallbacks. Every function pointer is always callable -- callers never need to check for NULL.
| Operation | S3 | ATI | Matrox | 3dfx | CL 54xx | CL Laguna | Nvidia | Tseng | Trident | SiS |
|---|---|---|---|---|---|---|---|---|---|---|
| RectFill | HW | HW | HW | HW | HW | HW | HW | HW | HW | HW |
| PatFill | HW | HW | HW | HW | sw | sw | sw | sw | sw | sw |
| BitBlt | HW | HW | HW | HW | HW | HW | HW | HW | HW | HW |
| HostBlit | HW | HW | HW | HW | HW | HW | HW | HW | HW | HW |
| ColorExpand | HW | HW | HW | HW | HW | HW | sw | sw | sw | sw |
| LineDraw | HW | HW | HW | HW | sw | sw | sw | sw | sw | sw |
| HwCursor | HW | HW | HW | HW | HW | HW | HW | HW* | HW | HW |
| Clip | HW | HW | HW | HW | sw | HW | HW | sw | sw | HW |
HW = hardware accelerated, sw = software fallback *HW cursor on W32p only; W32/W32i have no cursor hardware
API Usage
Basic Lifecycle
#include "accelVid.h"
// Declare registration functions for the drivers you want
extern void s3RegisterDriver(void);
extern void atiRegisterDriver(void);
// ... etc
int main(void) {
// 1. Register drivers (order = detection priority)
s3RegisterDriver();
atiRegisterDriver();
// 2. Detect hardware
AccelDriverT *drv = accelDetect();
if (!drv) {
printf("No supported video card found\n");
return 1;
}
// 3. Initialize with a video mode
AccelModeRequestT req;
req.width = 640;
req.height = 480;
req.bpp = 16;
if (!accelInit(drv, &req)) {
printf("Failed to set video mode\n");
return 1;
}
// Mode info is now available
printf("Mode: %dx%dx%d pitch=%d\n",
drv->mode.width, drv->mode.height,
drv->mode.bpp, drv->mode.pitch);
// 4. Draw
drv->rectFill(drv, 0, 0, 640, 480, 0x001F); // blue
drv->waitIdle(drv);
// 5. Shut down
accelShutdown(drv);
return 0;
}
Drawing Operations
All drawing functions take the driver pointer as the first argument. Colors are packed in the display's native pixel format.
// Solid rectangle fill
drv->rectFill(drv, x, y, w, h, color);
// 8x8 mono pattern fill (1=fg, 0=bg, MSB first, 8 bytes)
uint8_t checkerboard[8] = {
0xAA, 0x55, 0xAA, 0x55,
0xAA, 0x55, 0xAA, 0x55
};
drv->rectFillPat(drv, x, y, w, h, checkerboard, fgColor, bgColor);
// Screen-to-screen blit (handles overlapping regions)
drv->bitBlt(drv, srcX, srcY, dstX, dstY, w, h);
// CPU-to-screen blit (transfer RAM buffer to VRAM)
// srcBuf = packed pixels in display format, srcPitch = byte stride
drv->hostBlit(drv, buffer, pitch, dstX, dstY, w, h);
// Monochrome color expansion (1bpp -> full color)
// Each 1-bit becomes fg, each 0-bit becomes bg
// srcBuf = packed MSB-first mono bitmap, srcPitch = byte stride
drv->colorExpand(drv, glyphData, 1, dstX, dstY, 8, 16, fg, bg);
// Bresenham line draw (inclusive endpoints)
drv->lineDraw(drv, x1, y1, x2, y2, color);
// Hardware clip rectangle
drv->setClip(drv, clipX, clipY, clipW, clipH);
Hardware Cursor
// Define a cursor image (64x64 max, AND/XOR masks)
HwCursorImageT cursor;
cursor.width = 16;
cursor.height = 16;
cursor.hotX = 0;
cursor.hotY = 0;
memset(cursor.andMask, 0xFF, sizeof(cursor.andMask)); // transparent
memset(cursor.xorMask, 0x00, sizeof(cursor.xorMask));
// ... fill in actual cursor shape ...
// Upload and enable
drv->setCursor(drv, &cursor);
drv->showCursor(drv, true);
// Move (call on every mouse poll)
drv->moveCursor(drv, mouseX, mouseY);
// Hide
drv->showCursor(drv, false);
Checking Capabilities
The caps field indicates which operations are hardware-accelerated.
Software fallbacks are always installed, so you can call any operation
regardless of caps. Use caps to make optimization decisions:
if (drv->caps & ACAP_COLOR_EXPAND) {
// Use color expansion for text -- 16x less bus traffic
drv->colorExpand(drv, glyph, 1, x, y, 8, 16, fg, bg);
} else {
// Software fallback is installed but may be slow --
// consider pre-rendering text to a RAM buffer instead
drv->colorExpand(drv, glyph, 1, x, y, 8, 16, fg, bg);
}
if (drv->caps & ACAP_HW_CURSOR) {
// Hardware cursor eliminates cursor dirty rectangles
drv->setCursor(drv, &cursorImage);
drv->showCursor(drv, true);
}
Synchronization
The acceleration engine runs asynchronously. Drawing functions return
immediately after queuing the command. Use waitIdle before reading
from VRAM or when you need all pending operations to complete:
drv->rectFill(drv, 0, 0, 100, 100, color1);
drv->rectFill(drv, 50, 50, 100, 100, color2);
drv->bitBlt(drv, 0, 0, 200, 0, 150, 150);
// Wait for everything to finish before reading VRAM
drv->waitIdle(drv);
uint16_t pixel = *(uint16_t *)(drv->mode.framebuffer + offset);
Mode Information
After accelInit succeeds, drv->mode contains:
| Field | Description |
|---|---|
width |
Horizontal resolution in pixels |
height |
Vertical resolution in pixels |
bpp |
Bits per pixel (8, 15, 16, or 32) |
pitch |
Bytes per scanline (may exceed width * bpp/8) |
framebuffer |
Direct pointer to the linear framebuffer |
vramSize |
Total video RAM in bytes |
offscreenBase |
Byte offset where offscreen VRAM begins |
The framebuffer pointer can be used for direct pixel access when the acceleration engine doesn't offer a suitable operation.
Adding a New Driver
- Create a new source file (e.g.,
newchip.c) - Include
accelVid.h,vgaCommon.h, andpci.h - Define a static
AccelDriverTwith your function pointers - Use shared helpers for boilerplate:
vesaFindAndSetMode()for VESA mode enumeration and settingdpmiMapFramebuffer()for DPMI physical address mappingpciSizeBar()for PCI BAR size detection
- Leave unsupported operations as NULL -- the driver manager installs software fallbacks automatically
- Add a registration function:
void newchipRegisterDriver(void) - Add the source file to the Makefile and call the registration
function from
main()
See trident.c (simplest driver) or matroxMga.c (most complete)
as reference implementations.
Building
Requires a DJGPP cross-compiler targeting i586-pc-msdosdjgpp.
make # build bin/demo.exe
make clean # remove build artifacts
The Makefile expects the DJGPP toolchain at $HOME/djgpp/djgpp.
Override with make DJGPP_PREFIX=/path/to/djgpp.
Compiler flags: -O2 -Wall -Wextra -Werror -march=i486 -mtune=i586
Testing
The test/ directory contains an 86Box configuration for testing
with an emulated S3 Trio64. See test/README.txt for setup
instructions.
demo.exe [width height bpp]
Default mode: 640x480x16. Controls: SPACE cycles demos, B runs benchmarks, ESC exits.
Project Structure
accelVid.h Driver abstraction and manager API
accelVid.c Driver manager, software fallbacks
pci.h / pci.c PCI configuration space access
vgaCommon.h / .c Shared VGA registers, VESA, DPMI helpers
s3Trio.c S3 Trio/ViRGE/Savage/Vision driver
atiMach64.c ATI Mach64 / Rage driver
matroxMga.c Matrox Millennium / Mystique / G-series driver
banshee.c 3dfx Banshee / Voodoo3 driver
cirrusGd54.c Cirrus Logic GD5434/36/46/80 driver
cirrusLaguna.c Cirrus Logic Laguna GD5462/64/65 driver
nvidia.c Nvidia RIVA 128 / TNT family driver
tsengW32.c Tseng ET4000/W32 family driver
trident.c Trident TGUI / Blade / CyberBlade driver
sis.c SiS 6326/300/315 driver
demo.c Test/demo application
Makefile DJGPP cross-compilation build
PLAN.md Architecture plan and chipset reference
test/ 86Box test configuration and setup guide