Skip to content

dos_env ​

Tool tools/emu/dos_env (library, Emulators). A small DOS, BIOS and PC for tools/emu/dos_emu/, so a whole 16-bit program can run headless.

A library: other tools and your own scripts import it. Source on GitHub.

Its own help ​

This is the help text in the tool itself, as ./gameframe tool dos_env prints it.

text
A small DOS, BIOS and PC for tools/emu/dos_emu/, so a whole 16-bit program can run headless.

    from dos_emu import DosEmu, ProgramStopped
    from dos_env import DosEnv
    emu = DosEmu('target/game/GAME.EXE')
    env = DosEnv(emu, root='target/game', overlay='derived/run')   # files, KERNEL, ports, BIOS
    try:
        emu.run_range(emu.entry, '1000:ca59')      # from the program's entry to a chosen point
        emu.run_to('1000:ca59')                    # then carry on (run_range resets the stack)
    except ProgramStopped as stop:
        print('exit code', stop.args[0])
    print(env.log[-20:])                           # what the program asked of DOS, in order

What it provides:
  - DOS (INT 21h): files under `root` (names matched without case). A file the program writes
    is saved to `overlay` when closed (and kept in `env.written`); root is never written, and
    a file only opened read/write (Pascal's default) is not saved at all. Later opens read the
    overlay's copy first. handles, seek, find first/next with the
    DTA, current drive and directory, date and time (fixed: `env.clock`, so runs repeat
    exactly), version 5.0, interrupt vectors (kept in a table; nothing is ever called through
    them), device information, and exit (ends the run with ProgramStopped(exit code)).
  - DPMI16 KERNEL imports (Borland Pascal 7, Windows 3.x): GlobalAlloc / GlobalLock (64 KB
    selectors in a row, 8 apart, for blocks over 64 KB), GlobalFree, GetFreeSpace, InitTask.
  - Ports: VGA status (0x3DA) alternates so retrace waits end; the DAC (0x3C8/0x3C9) is kept
    in `env.dac` (256 x RGB, 6-bit); PIT, PIC, keyboard, joystick, Sound Blaster and AdLib
    ports answer with safe constant values. Every port write is counted in `env.ports`.
  - BIOS: INT 10h (video modes, recorded in `env.video_mode`), INT 16h (no key waiting),
    INT 33h (no mouse), INT 1Ah and the tick count at 0040:006C (`env.ticks`, one tick per
    128 reads of it, so wait-for-the-next-tick loops end).
  - DPMI (INT 31h): descriptors, DOS memory, interrupt and exception vectors, version, memory
    information; calls into real mode are skipped. INT 2Fh answers "nothing installed".
  - The timer: IRQ 0 goes to INT 8's handler (the program's, or the BIOS's, which counts the
    tick) at the rate the program sets on the PIT, counted in instructions: `ips` per second
    (default 25 million, a fast 486). `env.irq0_count` counts deliveries.
Anything else stops the run with its name (the emulator's own message), so you know what to
add. It does not emulate sound output, a real keyboard (use env.keys), or DPMI services
beyond what is listed.

Named by ​

Skills: re-observe, re-emulate, re-verify.

Code: Apache 2.0. Content: CC0 1.0. No game material: bring your own copy.