Skip to content

Measure a function that walks the game's data structures under the emulator ​

What to know ​

A function that reads pointers into loaded data (a graph, lists, tables) can still be measured under Unicorn without running the game's loader: lay the structures out in scratch memory exactly as the loader does, and point the game's globals at them. POD's path tracker and order update (measure/race_paths.py) were measured this way on Beltane's whole path graph, 20,000 cases each, and the port matched every one.

  • Read the loader first for the run-time layout, which differs from the file: POD's links point at nodes and at a run of section points chosen by an index, its section entries overlap a 16-bit field with a pointer, and the "first list" of a node is the one the game walks as its links out.
  • Set the guard globals. A function can return at once on a global the loader sets. POD's tracker does nothing while DAT_00539280 (the first link's points) is 0, and the first 2,000 cases all came back unchanged until it was set.
  • Make side effects harmless where the case does not test them: the tracker calls the order update, which returns at once when the car stands first.
  • Stop before library calls that need the C runtime's thread data: POD's format_time calls Watcom's sprintf, which faults under Unicorn (UC_ERR_WRITE_UNMAPPED). Stopping at the call and reading its arguments from the stack measures the function's own work: emu.call(addr, args, until=CALL_SITE)['stack'].
  • Load a control word before the call when the code uses the FPU (emu.call(..., fpu_cw=0x037f); x87-magic-add-rounding).
  • Bias the random cases towards the branches: points near a gate's plane, trackers at a link's last point, cars on the same lap.

Keep each case as a JSON line with the original's answer; the port's test reads the file and checks every line (crates/pod-race/tests/measured.rs).

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