diff --git a/docs/compaction-handoff.md b/docs/compaction-handoff.md new file mode 100644 index 0000000..c828294 --- /dev/null +++ b/docs/compaction-handoff.md @@ -0,0 +1,165 @@ +# Compaction Handoff + +Current date/time context: 2026-06-20/21, local timezone America/Chicago. + +## Current Installed State + +- Latest commit: `64ddf7a Trace GPS provider filters`. +- Installed RED4ext plugin: + `Cyberpunk 2077/red4ext/plugins/EdgeWeightGPS/EdgeWeightGPS.dll`. +- Installed build is read-only. It should not alter route behavior. +- Plugin log is cleared and empty before the next test: + `Cyberpunk 2077/red4ext/plugins/EdgeWeightGPS/EdgeWeightGPS.log`. +- Game is cold as of the latest user message. + +## New Toolbox Tools + +The Fedora toolbox `2077` now has: + +- `rizin` 0.7.4 +- `python3-capstone` 5.0.5 +- `python3-pefile` 2024.8.26 + +If adding Python-only tooling, create/use a venv and maintain `requirements.txt` +instead of one-off pip installs. + +## Active Probe Configuration + +In `red4ext/EdgeWeightGPS/src/Main.cpp`: + +- `kEnableGpsProviderClassPatch = false` +- `kEnableGpsProviderClassPatchTrace = false` +- `kEnableGpsTraceHooks = true` +- `kEnableGpsQueryLifecycleHooks = false` +- `kEnableGpsLocalSearchHooks = true` +- `kEnableRouteUiTraceHooks = false` + +Active hooks: + +- `GPSSearch 0x44f054` +- `GPSRouteProducer 0x44cc7c` +- `GPSEdgeCost 0x44f838` +- filtered provider filter `0x44ff68` +- base provider filter `0x450b08` + +The filter probe records pass/fail totals by GPS point class and by bits in +`point + 0x10`, tested against provider masks at `+0x108` and `+0x10a`. + +## Why This Probe Exists + +Data and behavior patches tested so far: + +- Traffic `maxSpeed` patches affected NPC freeway speed but not GPS route + choice. +- Lane connection probability patches did not change GPS route choice. +- Global cost-table patch produced weird routing but mostly confirmed we were + near the solver, not a clean highway preference knob. +- Provider class override patches fired correctly but produced no perceptible + route change after preserving vanilla class `14`. + +Static disassembly clarified the provider split: + +- Provider vtable slot `+0x08` is an admissibility filter, not cost. +- Provider vtable slot `+0x10` is geometric edge cost, multiplying distance by + `provider[0x08 + class * 4]`. +- We patched only slot `+0x10` inputs. If slot `+0x08` filtering dominates the + candidate graph, those cost changes can fire and still not visibly steer GPS. + +## Important Native Findings + +GPS pipeline landmarks: + +- shared query submit: `0x70a42c` +- query dispatch: `0x70a570` +- route producer: `0x44cc7c` +- local search loop: `0x44f054` +- edge cost: `0x44f838` +- query result fetch: `0x7094b8` + +The search loop is A*/Dijkstra-like: + +- initialize/open list with start node +- pop best node +- check destination handle +- traverse adjacent lane handles +- call provider filter +- call provider cost +- update candidate cost/best predecessor + +Provider details: + +- Base provider vtable RVA: `0x2ae6120` +- Filtered provider vtable RVA: `0x2ae60f8` +- Base provider constructor `0x451158` fills 64 class multipliers with `1.0` + and sets mask `+0x108` to `0xffff`. +- Filtered provider constructor `0x44b9b4` changes vtable to `0x2ae60f8`. +- Filtered provider commonly has class `14 = 0.05`; preserve this unless + deliberately testing it. + +Route result records: + +- `0x7094b8` output records are 0x28-byte route segment records. +- `h00` in those records matches `worldTrafficLanePersistent.nodeRefHash`. +- Route records can be joined to `work/raw-segment-json/all.traffic_persistent.json`. +- The low byte of route-record `u08` is not the same as the search point class. + +## Next User Test + +Ask the user to run the usual routine: + +1. Launch game. +2. Hit Continue on main menu. +3. Hit Space to Continue. +4. Wait for minimap/GPS to settle. +5. Open map. +6. Plot the usual three routes plus one custom highway-ish target. +7. Close game. + +Ask for timestamps for: + +- Space-to-Continue +- map open +- each route click +- game cold + +After the run: + +1. Archive the log to `logs/EdgeWeightGPS_provider_filter_probe_