Accelerated DOS video driver.
Find a file
2026-04-13 19:43:17 -05:00
test Initial commit. 2026-04-13 19:40:45 -05:00
.gitignore Initial commit. 2026-04-13 19:40:45 -05:00
accelVid.c Initial commit. 2026-04-13 19:40:45 -05:00
accelVid.h Initial commit. 2026-04-13 19:40:45 -05:00
atiMach64.c Initial commit. 2026-04-13 19:40:45 -05:00
banshee.c Initial commit. 2026-04-13 19:40:45 -05:00
cirrusGd54.c Initial commit. 2026-04-13 19:40:45 -05:00
cirrusLaguna.c Initial commit. 2026-04-13 19:40:45 -05:00
demo.c Initial commit. 2026-04-13 19:40:45 -05:00
Makefile Initial commit. 2026-04-13 19:40:45 -05:00
matroxMga.c Initial commit. 2026-04-13 19:40:45 -05:00
nvidia.c Initial commit. 2026-04-13 19:40:45 -05:00
pci.c Initial commit. 2026-04-13 19:40:45 -05:00
pci.h Initial commit. 2026-04-13 19:40:45 -05:00
README.md Minor doc change 2026-04-13 19:43:17 -05:00
s3Trio.c Initial commit. 2026-04-13 19:40:45 -05:00
sis.c Initial commit. 2026-04-13 19:40:45 -05:00
trident.c Initial commit. 2026-04-13 19:40:45 -05:00
tsengW32.c Initial commit. 2026-04-13 19:40:45 -05:00
vgaCommon.c Initial commit. 2026-04-13 19:40:45 -05:00
vgaCommon.h Initial commit. 2026-04-13 19:40:45 -05:00

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

  1. Create a new source file (e.g., newchip.c)
  2. Include accelVid.h, vgaCommon.h, and pci.h
  3. Define a static AccelDriverT with your function pointers
  4. Use shared helpers for boilerplate:
    • vesaFindAndSetMode() for VESA mode enumeration and setting
    • dpmiMapFramebuffer() for DPMI physical address mapping
    • pciSizeBar() for PCI BAR size detection
  5. Leave unsupported operations as NULL -- the driver manager installs software fallbacks automatically
  6. Add a registration function: void newchipRegisterDriver(void)
  7. 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