Files
2077-gps-mod/docs/red4ext-logging-shim.md
T
2026-06-20 12:47:30 -05:00

144 lines
6.9 KiB
Markdown

# RED4ext logging shim
`EdgeWeightGPS` is a RED4ext plugin used to probe native GPS/mappin code paths
without changing gameplay data.
It writes `EdgeWeightGPS.log` beside the installed DLL:
```text
Cyberpunk 2077/red4ext/plugins/EdgeWeightGPS/EdgeWeightGPS.log
```
Current behavior:
- Logs plugin load/unload.
- Logs the RED4ext plugin handle and SDK pointer value passed to `Main`.
- Registers Running game-state callbacks so route tests can be timestamped.
- Hooks selected native wrappers and cores around `GPSSystem`, mappin tracking,
world-map mappin selection, and map path framing.
- Hooks `JournalManager.TrackEntry` at RVA `0x5944fc`, which is the native
handoff used by quest/objective world-map route plotting.
- Dumps the `JournalManager` listener array at offsets `0x210`/`0x21c` and the
listener vtable slots `0x28`, `0x30`, and `0x50`, matching the indirect calls
made by the native `TrackEntry` implementation.
- Hooks the non-default journal listener callbacks seen during route plotting:
`0xea89a8`, `0xea8958`, `0xe63f80`, `0xe63e6c`, `0xe63f00`,
`0x8d136c`, `0x431a34`, `0x55a4e4`, and `0x14de238`.
- For those listener callbacks, logs the listener object, event pointer, common
object fields, and vtable slots on candidate nested owner/service objects.
- Hooks the route handoff found from the journal listener bridge:
`0x598250`, `0x13763d8`, `0xaa62d0`, `0xaa6330`, `0x27abd7c`, and
`0x5625a4`.
- Logs mappin route-event fields, active/deactive route keys, the mappin
active-route map at `system + 0x1a0`, and the route observer list at
`system + 0x280`.
- Hooks the route observer callbacks reached by route activation/deactivation:
`0xaa6610`, `0xaa6628`, `0xaa63e0`, `0x27b10c0`, `0x295d4a0`, and
`0x286a85c`.
- Logs the route entry pointer and route object pointer passed to those
observers, including route object vtable slots and common fields such as the
active byte at offset `0x84`, the service lookup key at offset `0x8c`, and
the runtime observer1 service-owner path used before its vtable `0x220`
lookup.
- Hooks observer1's generic service lookup at `0x287c44`, filters it to the
runtime type pointer at `.data` RVA `0x342f6a8`, logs the returned service
object and slot `0x220`, then dynamically hooks that service `0x220` route
lookup to log its route-id output handle.
- The observer1 service branch was later identified as a false positive:
`0x287c44` returns the `JournalManager` object (`vtable 0x1430f0890`) and
the dynamic slot `0x220` resolves route IDs to readable journal/UI metadata
strings such as `internet`, `home`, `clubs`, and `arasaka`. It is now left in
the source but no longer attached in the active probe.
- Hooks the GPS query lifecycle found from the `RunGPSQuery`/`UpdateGPSQuery`
native registration cluster:
`0x29bd128` (`RunGPSQuery` body), `0x29bd254` (`UpdateGPSQuery` body),
`0x70a42c` (shared query submitter), `0x70a570` (low-level query dispatch),
and `0x7094b8` (query result/path fetch).
- Logs query endpoints, returned query IDs, shared submitter return RVAs, query
state fields, result-fetch success, and summarized path buffers/point counts.
- Resolves the native mappin system when one of those paths fires, logs relevant
vtable slot addresses, and temporarily hooks the route-adjacent slots.
Current route-probe focus:
- `FrameMappinPath` wrapper/core: `0x27c4314`, `0x27bc1ec`
- `SetSelectedMappin` wrappers/core: `0x27c4a38`, `0x27c4944`,
`0x27c49c4`, `0x27c1684`
- `TrackCustomPositionMappin` wrapper/core: `0x27c4aac`, `0x27c2318`
- mappin-system slots `0x1f0`, `0x280`, and `0x2f0`
- `JournalManager.TrackEntry` implementation: `0x5944fc`
- non-default `TrackEntry` listener callbacks listed above
- journal/mappin route bridge candidate: `0x598250`
- mappin route-event enqueue: `0x13763d8`
- mappin route-event handler: `0xaa62d0`
- mappin route activate/deactivate: `0xaa6330`, `0x27abd7c`
- mappin route observer callbacks: `0xaa6610`, `0xaa6628`, `0xaa63e0`,
`0x27b10c0`, `0x295d4a0`, `0x286a85c`
- observer1 service lookup and returned service route lookup:
`0x287c44`, dynamic service vtable slot `0x220` (disabled after being
classified as journal metadata)
- route-build candidate called by the bridge: `0x5625a4`
- GPS query lifecycle: `0x29bd128`, `0x29bd254`, `0x70a42c`, `0x70a570`,
`0x7094b8`
Quest/objective pins did not fire the mappin tracking hooks in live tests. The
REDscript decompile shows that those pins call `JournalManager.TrackEntry`
instead, so the current useful runtime question is which native listener reacts
to tracked-entry changes.
Most recent controlled test:
- `06:31:43`: user hit Continue / GPS tick logged.
- `06:32:02`: automatic `TrackEntry` during load, no route input.
- `06:32:27`: map opened.
- `06:32:44`, `06:32:50`, `06:32:56`: deliberate quest/objective route plots
produced `JournalManager::TrackEntry` calls from return RVA `0x26ac34e`.
- After map open, the journal listener count rose to 254. Most listener entries
dispatch to no-op `0x14a700`; the non-default callbacks above are the current
drill-down targets.
Newest controlled test:
- User clock `01:05`: Continue on the main menu. The log saw
`GPSSystem/Tick`.
- User clock `01:27`: Space to continue. The log saw automatic
`JournalManager.TrackEntry`, a dense `JournalRouteBridge` burst, and thirty
`RouteBuildCandidate 0x5625a4` calls. About 5.5 seconds later the mappin route
activation/deactivation functions fired.
- User clock `01:52`: map open. Hovering icons produced the expected
`SetSelectedMappin` bursts.
- Deliberate quest route clicks produced `JournalManager.TrackEntry`, route
event enqueue calls for old-route-off/new-route-on, and route event handler
calls roughly 11-18 ms later.
- Custom pin routing used the separate custom-position mappin path, then the
shared route activate/deactivate helper.
Latest observer1 probe result:
- The `Observer1ServiceLookup` hook fired, but it proved observer1 is not route
solving. It returned the same `JournalManager` vtable seen in earlier journal
traces, and its slot `0x220` resolved numeric route IDs into journal/UI
category strings. That branch is closed as marker metadata.
Current static lead:
- `RunGPSQuery` and `UpdateGPSQuery` are registered native thunks at
`0x29bd5ac` and `0x29bd6c8`. Their deeper bodies are `0x29bd128` and
`0x29bd254`.
- `RunGPSQuery` submits a query through a subsystem reached via an object field
at `+0x130`, returning a query ID or `-1`.
- `UpdateGPSQuery` fetches a completed query result through `0x7094b8`, copies a
path point buffer, and writes the resulting point array for script/UI
consumption.
- The shared submitter `0x70a42c` is also used by non-GPS navigation callers,
so return RVAs and query IDs are important for separating map GPS from traffic
or AI path requests.
Build and install from the Fedora toolbox:
```bash
toolbox run -c 2077 ./tools/install_red4ext_shim.sh
```
This shim is read-only. It does not enable any of the archived traffic data patches.