Skip to content

Native v86 Emulation

ENiGMA½ includes a built-in x86/DOS emulator powered by v86 — a JavaScript x86 emulator that runs entirely within Node.js. The v86_door module boots a FreeDOS disk image and bridges COM1 directly to the user’s connection, with no external emulator installed on the server.


  1. ENiGMA½ generates the appropriate drop file for the user (DORINFO, DOOR.SYS, etc.)
  2. The drop file is written into a small in-memory FAT12 floppy image — no temp files on disk
  3. v86 boots the op-supplied FreeDOS disk image from the hard drive (C:)
  4. The drop file floppy is mounted as A: in FreeDOS
  5. The door’s AUTOEXEC.BAT copies the drop file from A: and launches the game
  6. COM1 serial I/O is bridged directly between v86 and the user’s connection
  7. When the door exits and FreeDOS powers off, the session ends cleanly

v86 requires SeaBIOS and a VGA BIOS image. The ENiGMA½ installer (misc/install.sh) downloads these automatically to misc/v86_bios/. To download manually:

Terminal window
mkdir -p misc/v86_bios
curl -fL https://github.com/copy/v86/raw/master/bios/seabios.bin -o misc/v86_bios/seabios.bin
curl -fL https://github.com/copy/v86/raw/master/bios/vgabios.bin -o misc/v86_bios/vgabios.bin

You need a raw FreeDOS disk image (.img) with your door game pre-installed. Raw .img images are fully compatible between QEMU, DOSBox-X, and v86 — set up your image with QEMU or DOSBox-X, then point v86_door at it on the production server.


ItemRequiredDescription
nameYesDoor name. Used as a key for tracking concurrent sessions.
imageYesPath to the raw FreeDOS disk image (.img).
dropFileTypeNoDrop file to generate and inject onto the A: floppy: DORINFO, DOOR, or DOOR32. Omit if the door needs no drop file. The connection is always reported as serial — the guest sees COM1.
runBatchNoMulti-line batch script written to A:\RUN.BAT at runtime. Supports variable substitution. See One Image, Multiple Doors.
nodeMaxNoMax concurrent sessions. 0 = unlimited.
tooManyArtNoArt spec to display when nodeMax is exceeded.
memoryMbNoGuest RAM in MB. Default: 64.
biosPathNoPath to SeaBIOS image. Default: misc/v86_bios/seabios.bin.
vgaBiosPathNoPath to VGA BIOS image. Default: misc/v86_bios/vgabios.bin.
dropFileTypeFilename on A:
DORINFODORINFOx.DEF (x = node-based suffix per spec)
DOORDOOR.SYS
DOOR32door32.sys

When runBatch is set, ENiGMA replaces the following variables before writing RUN.BAT:

VariableDescriptionExample
{dropFile}Drop file filenameDORINFO1.DEF
{node}Node number1
{baud}Baud rate57600

Single-player door (PimpWars):

doorPimpWars: {
desc: Playing PimpWars
module: v86_door
config: {
name: PimpWars
image: /path/to/images/freedos_doors.img
dropFileType: DORINFO
nodeMax: 1
tooManyArt: DOORMANY
runBatch:
'''
@ECHO OFF
C:\FOSSIL\X00.SYS
COPY A:\{dropFile} C:\DOORS\PW\
CD C:\DOORS\PW
PW.EXE {node}
ECHO Returning to BBS, please wait... > COM1
'''
}
}

Multi-node door with shared game state (TradeWars 2002):

doorTradeWars2002: {
desc: TradeWars 2002
module: v86_door
config: {
name: TradeWars2002
image: /path/to/images/tw2002.img
dropFileType: DORINFO
nodeMax: 4
tooManyArt: DOORMANY
runBatch:
'''
@ECHO OFF
C:\FOSSIL\X00.SYS
C:\FREEDOS\BIN\SHARE.COM
COPY A:\{dropFile} C:\DOORS\TW2\{dropFile}
CD C:\DOORS\TW2
TW2.EXE
C:\FREEDOS\BIN\FDAPM POWEROFF
'''
}
}

Your disk image must contain:

  • A working FreeDOS installation
  • Your door game(s) installed (e.g. C:\DOORS\PIMPWARS\)
  • Optionally, a FOSSIL driver such as X00 — required by most classic DOS doors
  • An AUTOEXEC.BAT (or FDAUTO.BAT) that calls A:\RUN.BAT and powers off

Set up your image’s AUTOEXEC.BAT once. ENiGMA writes RUN.BAT to A: at runtime with the door-specific launch commands:

Terminal window
CALL A:\RUN.BAT
ECHO Shutting down, please wait... > COM1
FDAPM POWEROFF
  • CALL A:\RUN.BAT — executes the per-door launch script ENiGMA injects at runtime
  • ECHO ... > COM1 — sends a message to the user’s terminal while FreeDOS shuts down (can take a few seconds)
  • FDAPM POWEROFF — shuts FreeDOS down cleanly; placed after the CALL so it always fires even if the door crashes

Because RUN.BAT is generated at runtime, a single FreeDOS image can host multiple doors. Each door has its own menu entry pointing at the same image path with a different runBatch:

doorPimpWars: {
module: v86_door
config: {
name: PimpWars
image: /path/to/images/freedos_doors.img
dropFileType: DORINFO
nodeMax: 1
runBatch:
'''
COPY A:\{dropFile} C:\DOORS\PW\
C:\FOSSIL\X00.SYS
CD C:\DOORS\PW
PW.EXE {node}
ECHO Returning to BBS, please wait... > COM1
'''
}
}
doorSmurfCombat: {
module: v86_door
config: {
name: SmurfCombat
image: /path/to/images/freedos_doors.img // same image
dropFileType: DOOR
nodeMax: 1
runBatch:
'''
COPY A:\{dropFile} C:\DOORS\SMURF\
C:\FOSSIL\X00.SYS
CD C:\DOORS\SMURF
SMURF.EXE {node}
ECHO Returning to BBS, please wait... > COM1
'''
}
}

Most classic DOS doors use the FOSSIL serial interface for COM1 I/O. If your door fails to start or falls back to local mode, a FOSSIL driver is needed. X00 works well with v86.

Load it from runBatch (per-door, recommended) rather than FDCONFIG.SYS (global):

Terminal window
C:\FOSSIL\X00.SYS

Or in FDCONFIG.SYS if all doors on the image need it:

DEVICE=C:\FOSSIL\X00.SYS

Creating and Configuring Images with oputil v86

Section titled “Creating and Configuring Images with oputil v86”

ENiGMA½ ships two oputil subcommands for working with disk images without needing QEMU or DOSBox-X installed on the server:

oputil.js v86 console <image.img> Boot and wire COM1 to this terminal (interactive)
oputil.js v86 desktop <image.img> Boot in a full VGA browser session

console — best for doors that output entirely through COM1 (most doors). Use CTTY COM1 in the image’s FDAUTO.BAT to redirect all I/O. Ctrl+] exits and saves changes back to the image file automatically.

desktop — boots the image in a small local HTTP server and opens your browser to a full VGA canvas. Use this for setup programs that write directly to VGA (e.g. door configuration wizards). Click Save Image to write changes back to the image file on the server — no browser download dialog appears.

Terminal window
# Interactive COM1 terminal
node core/oputil/oputil_main.js v86 console /path/to/tw2002.img
# Full VGA browser session (opens browser automatically)
node core/oputil/oputil_main.js v86 desktop /path/to/tw2002.img --port 18086

See also: oputil.js fat for listing and copying files into images without booting them.

Terminal window
# Create a 500MB raw image
qemu-img create -f raw freedos_mygame.img 500M
# Install FreeDOS (boot from CD)
qemu-system-i386 -hda freedos_mygame.img -cdrom FD14CD.iso -boot d
# Boot into FreeDOS to install your door
qemu-system-i386 -hda freedos_mygame.img
# Transfer files from host using QEMU's vfat driver — files appear on D:
qemu-system-i386 -hda freedos_mygame.img -hdb fat:/path/to/door/files

DOSBox-X is a graphical alternative for image setup on Windows, macOS, and Linux. See the DOSBox-X documentation for imgmount.

FreeDOS Boot Configuration for Fast Startup

Section titled “FreeDOS Boot Configuration for Fast Startup”

For ~5 second boot times, configure FreeDOS to use Emergency Mode (no memory managers, no networking). In FDCONFIG.SYS:

MENUDEFAULT=5,0

Ensure the 5? config block loads your FOSSIL driver:

5?DEVICE=C:\FOSSIL\X00.SYS
5?SHELL=C:\FreeDOS\BIN\COMMAND.COM C:\FreeDOS\BIN /E:1024 /P=C:\FDAUTO.BAT