Skip to content

A per-step recorder fits in the code section's mapped slack ​

What to know ​

2026-10-24, Hardwar's patch_recorder.py.

To record every flight step (the step's dt_ms, the world clock, the seeds, the input state) a sampler from outside is not enough: it misses most frames and is not atomic (GameFrame docs/observe/recording.md, "What a recording from outside cannot see"). A hook inside the step is.

Where to put it: Watcom's linker left BEGTEXT with a virtual size of 0 and a raw size of 0x116e00, so the loader maps it to the next section alignment (0x10000), up to 0x530000. Only 0x83 bytes at the end of the raw data are free, but 0x526e00-0x530000 is mapped and executable. Growing the section's raw size by 0x1000 and moving the later sections down in the file (their addresses stay) puts a 4 KB hook there without moving any code. The section was made writable too, so the hook keeps its file handle and buffer beside its code.

The hook replaces one call (call controls_read at 0x43ac72 in flight_frame), calls it, and then writes with the game's own imports (CreateFileA, WriteFile, Sleep). It saves every register and the flags. The step it records is the one the game used; the time the write takes is counted by the game's timer in the next step and recorded there.

Pitfall: pkill -f NAME run over SSH kills the SSH command itself, since its command line contains NAME (GameFrame knowhow vm-ssh-pkill-matches-itself, seen again here). Stop the game with its own prefix's wineserver -k (Hardwar's vm_run.sh stop`).

For GameFrame: the technique (grow a Watcom section into its mapped slack, hook one call, write with the game's own imports, hold the game between steps for a whole-process snapshot) would serve any 32-bit Windows game; probegen could gain a sibling that writes such hooks.

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