Ghidra decompilation environment stood up on Linux (headless, no sudo): JDK 21 + Ghidra 12.1.2 in ~/tools, reusing the existing analyzed project at tools/ghidra_project/ from the prior Windows session instead of starting fresh. FPS-coupling investigation: traced the main game loop's per-frame path and found the real root cause - compute_frame_delta_ticks_60hz_min1_clamp (0x4092D0) computes correct delta-time from timeGetTime(), but clamps the minimum return value to 1 tick even when zero ticks truly elapsed, causing simulation speed to scale with framerate above 60fps. First patch attempt (NOP the clamp) crashed on level load because the shared delta value has 203 read sites across 40+ functions and only 2 were checked for zero-safety; reverted and archived as a documented lesson. The corrected fix (busy-wait instead of lying) is designed but not yet built. Pause-loop hang fixed: the pause command handler blocks the Windows message queue in a tight GetAsyncKeyState polling loop (found while locating the cheat code handler), which trips modern Windows' "Not Responding" hang detection if left paused too long, permanently disconnecting input. Patched (HAVOC_NOCD_PAUSEFIX_v1.EXE) to pump one message per loop iteration via the game's own existing message-drain function; confirmed fixed by play-testing, including the related "alt-tab while paused resets to menu" symptom. A separate "alt-tab while not paused" reset symptom remains open. New tracking docs: docs/FUNCTIONS.md (function-by-function RE progress), docs/PATCH_VERSIONS.md (binary patch version log), docs/LEVEL_NOTES.md (level/AI design quirks for the Remaster variant). Extended docs/PATCHES.md and docs/METHODOLOGY.md with full discovery narratives including dead ends.
28 lines
3 KiB
Markdown
28 lines
3 KiB
Markdown
# Patched Binary Version Log
|
|
|
|
Tracks every patched `HAVOC_NOCD*.EXE` variant we've built, working or not. All binaries are
|
|
gitignored (copyrighted game code) -- this file is the durable record of what was tried.
|
|
|
|
Non-working / superseded binaries live in `archive/`. The current best-known-working one for
|
|
each patch line stays at the repo root so tooling (Ghidra project, scripts) doesn't need
|
|
updating every iteration.
|
|
|
|
| File | Based on | Patch (see `docs/PATCHES.md`) | Status | Notes |
|
|
|---|---|---|---|---|
|
|
| `HAVOC_NOCD.EXE` | `HAVOC.EXE` | Copy-protection + NOCD patch set (full table in `docs/PATCHES.md`) | **Working, in active use** | The baseline. Boots and plays correctly; FPS-coupling bug still present (mitigated via dgVoodoo config, not a binary patch) |
|
|
| `archive/HAVOC_NOCD_FPSFIX_v1.EXE` | `HAVOC_NOCD.EXE` | NOP the 9-byte min-1-tick clamp at FO `0x0871d` | **Broken -- archived** | Crashes on level load. Root cause: only 2 of 203 read sites of the shared delta value (`DAT_0047c488`) were checked for zero-safety before patching; one of the ~38 unaudited consumer functions almost certainly divides by it. See `docs/PATCHES.md` "FPS-coupling" section for the full writeup |
|
|
| `HAVOC_NOCD_FPSFIX_v2.EXE` (not yet built) | `HAVOC_NOCD.EXE` | Same 9-byte region, corrected: turn the clamp into a busy-wait spin instead of a lie (see `docs/PATCHES.md`) | *(design only, deprioritized)* | Preserves "return value is never 0" for all 203 read sites while still fixing the actual bug. Paused in favor of the pause-loop hang fix and the "maximized = 2x normal speed" lead, which turned out to be a separate mechanism -- see `docs/FUNCTIONS.md` |
|
|
| `HAVOC_NOCD_PAUSEFIX_v1.EXE` | `HAVOC_NOCD.EXE` | Redirect the pause-loop's back-edge through a small code cave that pumps one Windows message per iteration (FO `0x1fbcf` + cave at FO `0x66fdf`, see `docs/PATCHES.md`) | **Working, confirmed by play-test** | Fixes the "greys out / Not Responding, TAB stops working" hang when paused too long, and the "alt-tab while paused resets to menu" symptom (same root cause). Does NOT fix a separate symptom: alt-tab while *not* paused still resets to menu -- that's a different, still-open bug, see `docs/FUNCTIONS.md`. Isolated fix, doesn't touch the FPS-coupling code path |
|
|
|
|
## Conventions
|
|
|
|
- Version suffix `_v2`, `_v3`, ... increments per patch *line* (e.g. all FPS-coupling fix
|
|
attempts), not globally across every patch ever made to the binary.
|
|
- A version only earns a plain (non-archived) spot at the repo root once it's confirmed
|
|
working by play-testing. Anything superseded or confirmed broken moves to `archive/`
|
|
immediately -- don't leave dead/broken binaries at the root where they could get mixed
|
|
up with the current candidate.
|
|
- Every entry here should link back to the relevant `docs/PATCHES.md` section for the actual
|
|
byte-level detail; this file is the index/status tracker, not the technical writeup.
|
|
- Update this table in the same commit/session as any patch build or status change (working
|
|
-> broken, experimental -> confirmed, etc).
|