Emulating a range of code inside a big message handler
What to know
2026-10-24, Hardwar's flight.py.
VhSlotControl (0x47b1e0) is one 12.9 KB function with a 0x1f0-byte frame; the flight step is a stretch of its 0x104 case, not a function. GameFrame's pe32_emu.call sets ESP just under its stack top, so [ESP+0x1ec] lies past the mapped stack and the run fails.
What works: allocate a block on the emulator's heap, point ESP into the middle of it, write the handler's frame words the range reads (here +0x1ec the slot index, +0x1c8 a pointer to dt_ms, +0x1bc the slot's user area), set the registers the range expects (EBP the vehicle, EDI a pointer to dt_fix) and run uc.emu_start(start, end). Calls inside the range push below ESP, inside the block. Read which frame words a range uses with a grep for esp + over its disassembly first.
A routine with side effects outside the state under test (here the event routine 0x432328, sound and HUD) can be made a RET by writing 0xc3 over its first byte and hooking the address to record EAX: uc.hook_add(UC_HOOK_CODE, fn, begin=addr, end=addr).
Linear disassembly of the whole code section (objdump -d on a copy of the EXE with the sections' virtual sizes set to their raw sizes and the data directories cleared) desyncs at jump tables, such as the ten words at 0x47b1b8, but resynchronises within a few instructions; check a function's first instruction by address before reading it.