Add-on

game-toolkit-dosvideo

DOS-era PC video, emulated at the register level, with a beam-accurate CRT.

v0.2.2 EUPL-1.2

VGA (mode 13h, Mode X, 16-colour planar, text), EGA, CGA with composite artifact colours and snow, Hercules, Tandy 1000 and VESA SVGA. Your game is ordinary Rust; what is emulated is the display adapter, its memory, its registers, its timing and the electron beam reading it out while you write.

Cargo.toml
[dependencies]
game-toolkit-dosvideo = "0.2"

Play

Try it here.

Built for the browser from v0.2.2. Click into a running demo for keyboard input.

Features

What it does.

Six adapters

VGA, EGA, CGA, Hercules, Tandy 1000 and VESA SVGA (VBE 1.2 and 2.0), each with its own memory layout, BIOS modes and quirks.

A clock, a bus and a beam

Writes land while the beam scans. Raster bars, split screens and tearing happen for the same reasons they did in 1992.

Ports or helpers

Program it through OUT 3C8h and pokes into A000:0000, or through helpers that do the same thing with less typing.

Looking like a CRT

VGA monitor, TV, green and amber phosphor presets, composite artifact colours and CGA snow.

The PC speaker

One square wave, no volume control, and all the tricks: PWM samples and synthie tracker songs on a single channel.

Code

What it looks like.

src/main.rs
use game_toolkit_dosvideo::prelude::*;

struct Hello;

impl DosGame for Hello {
    fn init(dos: &mut Dos) -> anyhow::Result<Self> {
        dos.set_mode(0x13); // INT 10h, AX=0013h
        Ok(Self)
    }

    fn step(&mut self, dos: &mut Dos) {
        // while (inp(0x3DA) & 8); while (!(inp(0x3DA) & 8));
        dos.wait_vretrace();
        dos.set_palette(1, [63, 0, 0]); // OUT 3C8h / 3C9h
        dos.fill(0xA0000 + 100 * 320, 320, 1); // a red line in A000:7D00
        if dos.key(sc::ESC) {
            dos.exit();
        }
    }
}

fn main() -> anyhow::Result<()> {
    run::<Hello>(DosConfig::new("hello", Adapter::Vga))
}

More

The rest of the family.