Comanche Gold (demo) -- PARKED

NovaLogic, 1998, software voxel renderer. Fixture: test/binaries/win98-games-a-d/Commanche Gold-DEMO-SW.EXE (InstallShield self-extractor, an IS5 Disk1).

Install (works, headless)

Game

Boots to the Pilot Roster -> Duty Roster -> Gold Operations -> Swift Justice -> Delta Patrol briefing (keyboard Enter). The briefing never advances, because the main loop busy-waits on a tick counter (exe+0x4bb8a4: cmp ebx,[0x4e76f0]; ja -- 4 ticks) that only the 33 ms timeSetEvent callback (exe+0x4d95a0, periodic) advances.

The callback dies after 7 ticks, the same way on the winmm timer thread (default) and injected on the main thread (--no-mm-timer-thread --async-mm-timer): EIP=0 from a ret at exe+0x40c414, ESP ~0x37A00 above the thread's stack top. Every 4th tick it calls exe+0x4d11d0 (DirectSound streaming: IDirectSoundBuffer::GetCurrentPosition, then a mixer); the routine exe+0x40bfd5..0x40c414 is generated code (exe+0x40be5b stores into 0x40bff0, rewriting a mov eax,[0x40a0c8]) and keeps registers in globals (0x40a0a0..0x40a0c8). Not the uop tier (--no-uop same), no code-write retirements (--trace-code-writes: the patch lands before decode). Mounting a wsetup.cfg with MMX=0 or sound=0 (--vfs-mount) did not change it either (override not verified to take effect).

Next step: an instruction-level ESP trace across one 4th-tick callback (--trace-at on exe+0x4d11d0 and the mixer's entry) to find where ESP is repointed and why it is not restored.

Root cause of the callback crash (claude:202b4b39, 2026-10-06)

Not a stack or SMC bug: a startup race in the game that our slower CPU loses. The "ESP ~0x37A00 above the thread's stack top" is the timer thread executing an invalid instruction head the mixer was patched with.

What would fix it (none done): make the pre-init work fast enough. Either a decode-time fold for the byte-compare _stricmp loop (a two-stream scan; 0x4e0bfc..0x4e0c08 is a SELFEXIT loop the matcher cannot see today), or a per-app guest-clock dilation. The browser has not been tried: its clock is real time, so it should behave like --real-ticks and lose by a hair.

Status 2026-10-06: parked again (claude:202b4b39) with the root cause above; TODOS NEW-GAME-COMANCHE-GOLD-DEMO-20261006.

The _stricmp fold, tried (claude:202b4b39, 2026-10-06 evening)

Built and measured on branch claude/crt-stricmp-fold (051a901e): handler 501 folds a whole C-locale _stricmp call at 0x4e0be0, handler 500 its loop. It is exact (unit test: every register, flag and stack slot) and 18x faster per call in bench-loops (61 vs 1094 ns). It does not win this race.

What is left: make the game's timer wait for main (a per-app guest-clock dilation for startup, or start the mm timer thread's clock at the first timeGetTime/mixer call instead of timeSetEvent), which is a design call, not a fold.