← Blog
0.7.0 · RETROPIE · SYSTEM #74

DOS x86 Real-Mode Core — System #74 (sigil-retropie 3d01c73)

June 23, 2026 · sigil-retropie 3d01c73 · Sigil-Docs
retropie dos x86 emulation 0.7.0

System #74 lands — DOS x86 real-mode emulation. cores/dos_core.sg is a full x86 real-mode CPU emulator written in Sigil: 7 opcode dispatch groups, ModRM EA, 8/16-bit register file, INT 21h DOS API stubs, INT 10h BIOS video, VGA mode 13h 320×200×256 framebuffer. .COM loader at CS:0x0100. Savestate 65792 B. VGA pixels flushed to ARGB display each frame.


CPU emulator

x86 real-mode opcode dispatch groups

MOV
All forms: reg-reg, reg-mem, mem-reg, imm-to-reg, imm-to-mem — all via ModRM effective address calculation.
ADD/SUB/CMP/AND/OR/XOR
Both immediate and r/m variants. FLAGS updated on arithmetic and logical operations.
INC/DEC
Register and memory forms. Partial FLAGS update (CF preserved, others set per result).
Jcc / JMP / CALL / RET
All conditional jumps (JZ/JNZ/JC/JNC/JS/JNS/JO/JNO/JP/JNP/JL/JGE/JLE/JG), near/short JMP, near CALL, near RET.
PUSH / POP
16-bit register stack — SP decrements/increments by 2; operates on the SS segment at the current SP.
String ops + LOOP
MOVSB/LODSB/STOSB with SI/DI/CX; LOOP; SHR/SHL (immediate count); MUL (unsigned 8/16-bit).
LEA
Load Effective Address — computes the ModRM EA and stores the offset (not the value at that address) in the destination register.

ModRM effective address calculation covers all four mod values: mod=00 (indirect, no displacement), mod=01 (base + disp8, sign-extended), mod=10 (base + disp16), mod=11 (register operand, no memory access). Register file: AX/BX/CX/DX (with AH/AL/BH/BL/CH/CL/DH/DL byte aliases), SI/DI/SP/BP, CS/DS/SS/ES, IP, FLAGS.


DOS + BIOS stubs and VGA output

INT 21h DOS API stubs (read/write/open/close/exit)

AH=01h / AH=08h
Character input — returns a synthetic character in AL. AH=01h echoes; AH=08h is raw (no echo).
AH=02h
Character output — DL byte written to the display output channel.
AH=09h
String output — DS:DX points to a $-terminated string; each byte is emitted to the display output channel.
AH=3Ch / AH=3Dh / AH=3Eh
Create file (3Ch), open file (3Dh), close file (3Eh) — stubbed against the VFS; returns a synthetic file handle in AX.
AH=3Fh / AH=40h
Read file (3Fh): BX=handle, CX=byte count, DS:DX=buffer — reads from the VFS into the emulator's flat address space. Write file (40h): same register convention, writes out.
AH=4Ch
Exit program — AL=exit code. Halts the emulator dispatch loop and returns control to dos_app.sg.

These stubs cover the minimal DOS API surface used by most .COM games and demos: console I/O, file read, and clean exit. Unimplemented AH values return AX=0 (no-op) and continue dispatch without halting.


INT 10h BIOS video + VGA mode 13h framebuffer

AH=00h — set video mode
Mode 13h (AL=0x13): 320×200, 256 colours. Sets vga_mode=0x13 and clears the 64 000-byte framebuffer at 0xA0000. Other mode values are accepted silently (stub).
AH=0Ch — write pixel
AL=colour index, CX=x (0–319), DX=y (0–199). Writes mem[0xA0000 + y*320 + x] = AL. Out-of-bounds coordinates are clamped.

VGA mode 13h: the framebuffer is a linear 64 000-byte array (320×200 bytes) at segment 0xA000 (physical 0xA0000). Each byte is a palette index into the 256-colour palette. Each frame the emulator flushes the palette-indexed framebuffer to a 320×200 ARGB display buffer, then integer-scales to the output resolution — maintaining the authentic 4:3 aspect ratio on the SRDX framebuffer tile.

.COM loader: DOS .COM files are flat binary images. The emulator loads the file into the flat 64 KB address space at offset 0x0100 (the Program Segment Prefix occupies 0x00000x00FF), then sets CS=DS=SS=ES=0x0000, IP=0x0100, SP=0xFFFE, and begins opcode dispatch. Savestate: 65 792 B — register file + FLAGS + full 64 KB memory image + VGA framebuffer state.


EL0 app and launcher

dos_app.sg + sys_launch.sg system #74

el0/dos_app.sg
The EL0 application — loads /roms/dos/game.com from the VFS into the emulator's flat 64 KB address space at CS:0x0100, then enters the dos_core dispatch loop. 2P input routed via ev_overlay: P1/P2 keystroke events are mapped to DOS keyboard scancodes and injected into the emulator's keyboard buffer before each dispatch tick.
display scaling
dos_core VGA output is integer-scaled from 320×200 to the SRDX framebuffer tile, maintaining the authentic aspect ratio. The palette-to-ARGB conversion runs once per frame; only dirty lines are re-blitted.
ui/sys_launch.sg
System selector entry for system #74 → /apps/dos. System #74 joins the RetroPie lineup alongside systems 1–73.