Skip to content

Running the original's renderer on a snapshot of the game ​

What to know ​

2026-10-24, Hardwar's snapemu.py, Hardwar's render_truth.py.

A software renderer needs the whole loaded game to draw anything: the world's objects, the shapes, the textures, the remap tables, the back end's tables. Building that in an emulator by hand is not practical. A whole-process snapshot (Hardwar's vm_snapshot.py) already holds it all. Mapped back into Unicorn, the game's own flight_display and scene_draw draw a frame exactly as the game would, from the snapshot's state, and nothing but the window's sizes needs setting. That gives an exact 8-bit reference frame (and every polygon Draw3D rasterises) for a state the port can also load (the snapshot was taken after loading save 3).

How:

  • Map every region of the snapshot at its address; the image's code is in it too (Wine maps the sections writable). Point the import table at stubs; stop on any import without one.
  • Give Unicorn a GDT. Watcom code saves and restores GS (push gs ... pop gs, 0x450888). With no descriptor table, Unicorn's pop gs left the stack segment 16-bit and the next push wrote at ESP & 0xffff ("invalid access at 0xdf94"). One flat data descriptor loaded into DS, ES, SS, FS and GS fixes it.
  • Set the x87 control word again (0x0c7f): a snapshot holds memory, not registers.
  • Enter below the DirectX calls: flight_draw touches DirectInput and DirectDraw objects whose code is not in the snapshot. Build the packet with flight_display (0x4962cc, EAX the pilot from player_pilot 0x447d48) and call scene_draw (0x48cfac) with it.
  • For an 8-bit frame: 0x55468c = 0, the row table 0x55469c over a buffer, base 0x554690, pitch 0x554694, height 0x554698, screen size 0x5999dc/0x5999e0/0x599a28/0x599a2c, window 0x59a160..0x59a16c. A paused console leaves 640 × 400 in several of these; miss one and the frame stops at row 400.
  • The clipper loops for ever on a polygon with no inside vertex; its callers drop those first (the AND of the outcodes). A random-input harness must do the same.
  • A polygon's +0x20 is a resource handle, not a material: map handles to sprites by matching the texture's pixels (res_lock 0x499acc) against the pack's .SPR files.

Candidate for GameFrame (a snapshot mode for pe32_emu, and the GDT pitfall).

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