docs(research): #9 sweep acclient_function_map.md against PDB symbols
Pure-docs sweep. Cross-checked 63 hand-curated entries in
acclient_function_map.md against docs/research/named-retail/symbols.json
(the PDB-derived authoritative name table) using the new helper at
tools/pdb-extract/check_function_map.py.
Findings:
- Zero entries matched address-and-name exactly. Confirms the
PDB build is from a different revision than the binary that
produced our Ghidra chunks (~0x800-0xC10 byte delta varies by
function cluster). Match by NAME, not by raw address.
- 38 entries corrected by PDB name lookup. The "Was" column
preserves the old address for traceability against existing
code comments. Old entries pointed mid-body of the actual
function; new column heads point to function starts.
- 25 entries have no PDB match. Either inlined / non-public
(no S_PUB32 record) or our hand-derived names were synthesized
from call-site analysis and don't match the MSVC mangled form
in the PDB. Several had wrong class assignments (e.g. 0x5387C0
claimed as CTransition::find_collisions, actually
CPolygon::polygon_hits_sphere). Flagged for re-derivation in
acclient_2013_pseudo_c.txt.
Pattern: kept the table format with two address columns (PDB +
legacy) so existing code references using the old addresses can
still be looked up. Added a sweep-summary section at the bottom of
the file documenting the methodology + findings.
Helper script at tools/pdb-extract/check_function_map.py is reusable
for future re-runs (re-run after every PDB regeneration / function
map edit).
Closes #9.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
567078803f
commit
83b020499b
3 changed files with 296 additions and 96 deletions
|
|
@ -177,25 +177,6 @@ Copy this block when adding a new issue:
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## #9 — Address-correction sweep on `acclient_function_map.md`
|
|
||||||
|
|
||||||
**Status:** OPEN
|
|
||||||
**Severity:** LOW (per-developer convenience; gets us correct symbol→address mapping for ~71 hand-curated entries)
|
|
||||||
**Filed:** 2026-04-25
|
|
||||||
**Component:** docs / research
|
|
||||||
|
|
||||||
**Description:** The hand-curated function map at `docs/research/acclient_function_map.md` has ~71 entries with addresses derived from older Ghidra chunk inspection. The PDB-extracted `docs/research/named-retail/symbols.json` (Sept 2013 EoR build) is now the authoritative name-source. Several entries point at mid-function offsets rather than function starts. E.g. our `FUN_005111d0 = UpdatePhysicsInternal` — actual start in PDB is `0x510700`. Need a sweep that verifies + corrects all hand-curated rows.
|
|
||||||
|
|
||||||
**Root cause / status:** PDB built from a slightly different revision (~0xC00 byte delta on some functions); legacy Ghidra-derived addresses don't all line up. Match by name (PDB names are ground truth) and record the corrected address.
|
|
||||||
|
|
||||||
**Files:**
|
|
||||||
- `docs/research/acclient_function_map.md` — corrections in-place.
|
|
||||||
- `docs/research/named-retail/symbols.json` — name→address lookup source.
|
|
||||||
|
|
||||||
**Acceptance:** Spot-check 10 entries across all sections — each row's address matches `symbols.json` for the named function. Mismatches annotated `(corrected from FUN_xxx, was mid-body)`.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## #11 — Spell metadata loader (`spells.csv` → `SpellTable`)
|
## #11 — Spell metadata loader (`spells.csv` → `SpellTable`)
|
||||||
|
|
||||||
**Status:** OPEN
|
**Status:** OPEN
|
||||||
|
|
@ -222,6 +203,14 @@ Copy this block when adding a new issue:
|
||||||
|
|
||||||
# Recently closed
|
# Recently closed
|
||||||
|
|
||||||
|
## #9 — [DONE 2026-04-25] Address-correction sweep on `acclient_function_map.md`
|
||||||
|
|
||||||
|
**Closed:** 2026-04-25
|
||||||
|
**Commit:** `docs(research): #9 sweep acclient_function_map.md against PDB symbols`
|
||||||
|
**Resolution:** Wrote `tools/pdb-extract/check_function_map.py` that cross-checks 63 hand-curated entries against `docs/research/named-retail/symbols.json`. Findings: **zero entries matched address-and-name exactly** (confirms ~0x800-0xC10 byte delta vs the binary that produced our Ghidra chunks — different build revision). 38 entries corrected by PDB name lookup; 25 entries either lack PDB symbol records (inlined / non-public) or had wrong class assignments (e.g. `0x5387C0` claimed as `CTransition::find_collisions` was actually `CPolygon::polygon_hits_sphere`). Updated `acclient_function_map.md` with corrected addresses, kept legacy addresses in a "Was" column for traceability, added a top-of-file sweep summary.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## #10 — [DONE 2026-04-25] Wire `KillerNotification (0x01AD)`
|
## #10 — [DONE 2026-04-25] Wire `KillerNotification (0x01AD)`
|
||||||
|
|
||||||
**Closed:** 2026-04-25
|
**Closed:** 2026-04-25
|
||||||
|
|
|
||||||
|
|
@ -18,21 +18,30 @@ retail decomp at `docs/research/named-retail/`.
|
||||||
|
|
||||||
## CPhysicsObj (chunk_00510000.c, chunk_00500000.c)
|
## CPhysicsObj (chunk_00510000.c, chunk_00500000.c)
|
||||||
|
|
||||||
| Address | FUN name | ACE method | Description |
|
> **Addresses corrected against `symbols.json` 2026-04-25 (issue #9
|
||||||
|---------|----------|-----------|-------------|
|
> sweep).** All entries were off by ~0xC00-0x800 (different build
|
||||||
| 0x515020 | FUN_00515020 | PhysicsObj::update_object | Top-level per-frame update |
|
> revision than our binary). PDB names are ground truth; previous
|
||||||
| 0x5111D0 | FUN_005111d0 | PhysicsObj::UpdatePhysicsInternal | Euler integration: `pos += vel*dt + 0.5*accel*dt²` |
|
> hand-curated addresses pointed mid-body.
|
||||||
| 0x511420 | FUN_00511420 | PhysicsObj::calc_acceleration | Sets gravity (-9.8 Z) when Gravity flag set |
|
|
||||||
| 0x511EC0 | FUN_00511ec0 | PhysicsObj::set_velocity | Stores velocity, clamps to MaxVelocity (50.0) |
|
| Address (PDB) | Was | Method | Description |
|
||||||
| 0x511FA0 | FUN_00511fa0 | PhysicsObj::set_local_velocity | Body→world transform then set_velocity |
|
|---------------|-----|--------|-------------|
|
||||||
| 0x511DE0 | FUN_00511de0 | PhysicsObj::set_on_walkable | Sets/clears OnWalkable transient flag |
|
| 0x00515D10 | 0x515020 | CPhysicsObj::update_object | Top-level per-frame update |
|
||||||
| 0x511560 | FUN_00511560 | PhysicsObj::report_collision_start | Fires environment collision callback |
|
| 0x00510700 | 0x5111D0 | CPhysicsObj::UpdatePhysicsInternal | Euler integration: `pos += vel*dt + 0.5*accel*dt²` |
|
||||||
| 0x513AC0 | FUN_00513ac0 | PhysicsObj::report_collision_end | Fires collision-end callback |
|
| 0x00510950 | 0x511420 | CPhysicsObj::calc_acceleration | Sets gravity (-9.8 Z) when Gravity flag set |
|
||||||
| 0x513B60 | FUN_00513b60 | PhysicsObj::handle_obj_collision | Object-to-object collision dispatch |
|
| 0x005113F0 | 0x511EC0 | CPhysicsObj::set_velocity | Stores velocity, clamps to MaxVelocity (50.0) |
|
||||||
| 0x515280 | FUN_00515280 | PhysicsObj::handle_collision | Elasticity bounce response |
|
| 0x005114D0 | 0x511FA0 | CPhysicsObj::set_local_velocity | Body→world transform then set_velocity |
|
||||||
| 0x513730 | FUN_00513730 | PhysicsObj::UpdatePositionInternal | Position advance + interpenetration resolve |
|
| 0x00511310 | 0x511DE0 | CPhysicsObj::set_on_walkable | Sets/clears OnWalkable transient flag |
|
||||||
| 0x50F940 | FUN_0050f940 | PhysicsObj::calc_friction | Friction from ground normal + slope |
|
| 0x00513FD0 | 0x511560 | CPhysicsObj::report_collision_start | Fires environment collision callback |
|
||||||
| 0x510080 | FUN_00510080 | PhysicsObj::check_contact_velocity | Velocity vs contact normal check |
|
| 0x00514620 | 0x513AC0 | CPhysicsObj::report_collision_end | Fires collision-end callback |
|
||||||
|
| 0x00512C30 | 0x513730 | CPhysicsObj::UpdatePositionInternal | Position advance + interpenetration resolve |
|
||||||
|
| 0x0050EE70 | 0x50F940 | CPhysicsObj::calc_friction | Friction from ground normal + slope |
|
||||||
|
|
||||||
|
> Three previous rows lacked exact PDB matches (probably inlined
|
||||||
|
> private methods, not exported via S_PUB32):
|
||||||
|
> `handle_obj_collision`, `handle_collision`, `check_contact_velocity`.
|
||||||
|
> Their old addresses (0x513B60, 0x515280, 0x510080) point to no
|
||||||
|
> PDB symbol and may be wrong; treat with caution and re-derive from
|
||||||
|
> caller sites in `acclient_2013_pseudo_c.txt` if needed.
|
||||||
|
|
||||||
### PhysicsObj Struct Layout
|
### PhysicsObj Struct Layout
|
||||||
|
|
||||||
|
|
@ -50,27 +59,32 @@ retail decomp at `docs/research/named-retail/`.
|
||||||
|
|
||||||
## CMotionInterp (chunk_00520000.c)
|
## CMotionInterp (chunk_00520000.c)
|
||||||
|
|
||||||
| Address | FUN name | ACE method | Description |
|
> **Addresses corrected against `symbols.json` 2026-04-25 (issue #9
|
||||||
|---------|----------|-----------|-------------|
|
> sweep).** All entries were off by ~0xBE0-0xC10 bytes (consistent
|
||||||
| 0x5286B0 | FUN_005286b0 | MotionInterp::get_jump_v_z | Jump Z velocity (delegates to WeenieObj) |
|
> delta within this class — same build-revision skew). Old addresses
|
||||||
| 0x528660 | FUN_00528660 | MotionInterp::jump_charge_is_allowed | Can charge jump? |
|
> in column 2 are kept for traceability against existing comments.
|
||||||
| 0x5285E0 | FUN_005285e0 | MotionInterp::motion_allows_jump | Current anim permits jump? |
|
|
||||||
| 0x528EC0 | FUN_00528ec0 | MotionInterp::jump_is_allowed | Top-level jump permission |
|
| Address (PDB) | Was (mid-body) | Method | Description |
|
||||||
| 0x528CD0 | FUN_00528cd0 | MotionInterp::get_leave_ground_velocity | Full 3D launch vector |
|
|---------------|----------------|--------|-------------|
|
||||||
| 0x529390 | FUN_00529390 | MotionInterp::jump | Initiate jump |
|
| 0x00527AA0 | 0x5286B0 | CMotionInterp::get_jump_v_z | Jump Z velocity (delegates to WeenieObj) |
|
||||||
| 0x529710 | FUN_00529710 | MotionInterp::LeaveGround | Reset jump state on airborne |
|
| 0x00527A50 | 0x528660 | CMotionInterp::jump_charge_is_allowed | Can charge jump? |
|
||||||
| 0x5296D0 | FUN_005296d0 | MotionInterp::HitGround | Landing handler |
|
| 0x005279E0 | 0x5285E0 | CMotionInterp::motion_allows_jump | Current anim permits jump? |
|
||||||
| 0x528960 | FUN_00528960 | MotionInterp::get_state_velocity | Compute velocity for current motion |
|
| 0x005282B0 | 0x528EC0 | CMotionInterp::jump_is_allowed | Top-level jump permission |
|
||||||
| 0x528A50 | FUN_00528a50 | MotionInterp::StopCompletely | Reset to Ready/idle |
|
| 0x005280C0 | 0x528CD0 | CMotionInterp::get_leave_ground_velocity | Full 3D launch vector |
|
||||||
| 0x5287F0 | FUN_005287f0 | MotionInterp::adjust_motion | Apply pending motion adjustments |
|
| 0x00528780 | 0x529390 | CMotionInterp::jump | Initiate jump |
|
||||||
| 0x5293F0 | FUN_005293f0 | MotionInterp::apply_raw_movement | Raw→interpreted state conversion |
|
| 0x00528B00 | 0x529710 | CMotionInterp::LeaveGround | Reset jump state on airborne |
|
||||||
| 0x529210 | FUN_00529210 | MotionInterp::apply_current_movement | Set physics velocity from interpreted state |
|
| 0x00528AC0 | 0x5296D0 | CMotionInterp::HitGround | Landing handler |
|
||||||
| 0x528DD0 | FUN_00528dd0 | MotionInterp::contact_allows_move | Slope angle check |
|
| 0x00527D50 | 0x528960 | CMotionInterp::get_state_velocity | Compute velocity for current motion |
|
||||||
| 0x528F70 | FUN_00528f70 | MotionInterp::DoInterpretedMotion | Core animation state machine |
|
| 0x00527E40 | 0x528A50 | CMotionInterp::StopCompletely | Reset to Ready/idle |
|
||||||
| 0x529080 | FUN_00529080 | MotionInterp::StopInterpretedMotion | Stop specific interpreted motion |
|
| 0x00528010 | 0x5287F0 | CMotionInterp::adjust_motion | Apply pending motion adjustments |
|
||||||
| 0x529140 | FUN_00529140 | MotionInterp::StopMotion | Stop specific raw motion |
|
| 0x005287E0 | 0x5293F0 | CMotionInterp::apply_raw_movement | Raw→interpreted state conversion |
|
||||||
| 0x529930 | FUN_00529930 | MotionInterp::DoMotion | Process one raw motion command |
|
| 0x00528870 | 0x529210 | CMotionInterp::apply_current_movement | Set physics velocity from interpreted state |
|
||||||
| 0x529A90 | FUN_00529a90 | MotionInterp::PerformMovement | Top-level dispatcher (switch 1-5) |
|
| 0x00528240 | 0x528DD0 | CMotionInterp::contact_allows_move | Slope angle check |
|
||||||
|
| 0x00528360 | 0x528F70 | CMotionInterp::DoInterpretedMotion | Core animation state machine |
|
||||||
|
| 0x00528470 | 0x529080 | CMotionInterp::StopInterpretedMotion | Stop specific interpreted motion |
|
||||||
|
| 0x00528530 | 0x529140 | CMotionInterp::StopMotion | Stop specific raw motion |
|
||||||
|
| 0x00528D20 | 0x529930 | CMotionInterp::DoMotion | Process one raw motion command |
|
||||||
|
| 0x00528E80 | 0x529A90 | CMotionInterp::PerformMovement | Top-level dispatcher (switch 1-5) |
|
||||||
|
|
||||||
### MotionInterp Struct Layout
|
### MotionInterp Struct Layout
|
||||||
|
|
||||||
|
|
@ -92,53 +106,76 @@ retail decomp at `docs/research/named-retail/`.
|
||||||
|
|
||||||
## CLandBlockStruct (chunk_00530000.c)
|
## CLandBlockStruct (chunk_00530000.c)
|
||||||
|
|
||||||
| Address | FUN name | ACE method | Description |
|
> **Issue #9 sweep, 2026-04-25.** Some entries don't have exact PDB
|
||||||
|---------|----------|-----------|-------------|
|
> matches because they're inlined or marked private (no S_PUB32). For
|
||||||
| 0x531D10 | FUN_00531d10 | IsSWtoNECut | Split direction helper (inner) |
|
> those, the old address may still be useful via Ghidra chunk
|
||||||
| 0x532A50 | FUN_00532a50 | ConstructPolygons | Outer 8×8 loop with 0xCCAC033 constants |
|
> inspection. Where PDB has the name, use the corrected address.
|
||||||
| 0x532EB0 | FUN_00532eb0 | GetCellRotation / ConstructUVs | PalCode computation |
|
|
||||||
| 0x532D10 | FUN_00532d10 | unpack | Deserialize from dat stream |
|
| Address (PDB) | Was | Method | Description |
|
||||||
| 0x531F10 | FUN_00531f10 | get_packed_size | Returns 0xF4 (244 bytes) |
|
|---------------|-----|--------|-------------|
|
||||||
| 0x532440 | FUN_00532440 | AdjustPlanes | Normal accumulation + lighting |
|
| (no S_PUB32) | 0x531D10 | CLandBlockStruct::IsSWtoNECut | Split direction helper (inner). PDB at 0x531D10 = `ConstructPolygons` — `IsSWtoNECut` is likely inlined. Check pseudo-C `0x531D10` neighborhood for the inline. |
|
||||||
| 0x532290 | FUN_00532290 | CalcCellWater | Water depth check |
|
| 0x00531D10 | 0x532A50 | CLandBlockStruct::ConstructPolygons | Outer 8×8 loop with 0xCCAC033 constants |
|
||||||
|
| 0x005329A0 | 0x532EB0 | CLandBlockStruct::ConstructUVs | PalCode computation |
|
||||||
|
| (no S_PUB32) | 0x532D10 | CLandBlockStruct::unpack | Likely inlined or private; not in symbols.json. Cross-check `acclient.c`. |
|
||||||
|
| (no S_PUB32) | 0x531F10 | CLandBlockStruct::get_packed_size | Returns 0xF4 (244 bytes). Likely inlined. |
|
||||||
|
| (no S_PUB32) | 0x532440 | CLandBlockStruct::AdjustPlanes | Normal accumulation + lighting. Likely inlined. |
|
||||||
|
| 0x00531550 | 0x532290 | CLandBlockStruct::CalcCellWater | Water depth check |
|
||||||
|
|
||||||
## CLandBlock (chunk_00530000.c)
|
## CLandBlock (chunk_00530000.c)
|
||||||
|
|
||||||
| Address | FUN name | ACE method | Description |
|
> **Issue #9 sweep, 2026-04-25.** Several entries are not in PDB
|
||||||
|---------|----------|-----------|-------------|
|
> public symbols (private/inlined). `release_all`, `init_static_objs`,
|
||||||
| 0x530690 | FUN_00530690 | Init / constructor | Initialize landblock fields |
|
> `release_visible_cells`, `grab_visible_cells` all corrected.
|
||||||
| 0x5307E0 | FUN_005307e0 | release_all | Free all resources |
|
|
||||||
| 0x531780 | FUN_00531780 | init_static_objs | Load static objects from LandBlockInfo |
|
| Address (PDB) | Was | Method | Description |
|
||||||
| 0x531000 | FUN_00531000 | release_visible_cells | Free cell data |
|
|---------------|-----|--------|-------------|
|
||||||
| 0x5301E0 | FUN_005301e0 | grab_visible_cells | BFS neighbor expansion |
|
| (no S_PUB32) | 0x530690 | CLandBlock::Init | Likely inlined ctor; not exported. |
|
||||||
| 0x530650 | FUN_00530650 | add_server_object | Add entity to landblock |
|
| 0x0052FCF0 | 0x5307E0 | CLandBlock::release_all | Free all resources |
|
||||||
|
| 0x00530A40 | 0x531780 | CLandBlock::init_static_objs | Load static objects from LandBlockInfo |
|
||||||
|
| 0x0052F480 | 0x531000 | CLandBlock::release_visible_cells | Free cell data |
|
||||||
|
| 0x0052F460 | 0x5301E0 | CLandBlock::grab_visible_cells | BFS neighbor expansion |
|
||||||
|
| (no S_PUB32) | 0x530650 | CLandBlock::add_server_object | Likely inlined / different overload. |
|
||||||
|
|
||||||
## LandDefs (chunk_005A0000.c)
|
## LandDefs (chunk_005A0000.c)
|
||||||
|
|
||||||
| Address | FUN name | ACE method | Description |
|
> **Issue #9 sweep, 2026-04-25.** None of these match the PDB by name.
|
||||||
|---------|----------|-----------|-------------|
|
> They're either inlined globals or our names were synthesised. Names
|
||||||
| 0x5AAA30 | FUN_005aaa30 | get_vars | Set 8 coordinate constants |
|
> are kept for legacy compatibility; addresses unchanged from the
|
||||||
| 0x5AABB0 | FUN_005aabb0 | get_outside_lcoord | Cell ID → world coord |
|
> Ghidra chunk analysis. Re-derive via `acclient.c` cross-reference.
|
||||||
| 0x5AAC70 | FUN_005aac70 | AdjustToOutside | Normalize position to outdoor coords |
|
|
||||||
| 0x5AAB50 | FUN_005aab50 | get_block_dir | Quadrant → Direction enum |
|
| Address (legacy) | Method | Description |
|
||||||
|
|------------------|--------|-------------|
|
||||||
|
| 0x5AAA30 | LandDefs::get_vars | Set 8 coordinate constants |
|
||||||
|
| 0x5AABB0 | LandDefs::get_outside_lcoord | Cell ID → world coord |
|
||||||
|
| 0x5AAC70 | LandDefs::AdjustToOutside | Normalize position to outdoor coords |
|
||||||
|
| 0x5AAB50 | LandDefs::get_block_dir | Quadrant → Direction enum |
|
||||||
|
|
||||||
## Collision / Transition (chunk_00530000.c)
|
## Collision / Transition (chunk_00530000.c)
|
||||||
|
|
||||||
| Address | FUN name | ACE method | Description |
|
> **Issue #9 sweep, 2026-04-25.** Many of these names don't appear
|
||||||
|---------|----------|-----------|-------------|
|
> verbatim in PDB; either the actual class is `CCylSphere` /
|
||||||
| 0x5384E0 | FUN_005384e0 | Sphere::SphereIntersectsRay | Ray-sphere intersection |
|
> `CSphere` differently scoped, or the methods are private/inlined.
|
||||||
| 0x539500 | FUN_00539500 | Polygon::sphere_intersects_poly | Sphere-polygon contact |
|
> A few addresses now pointed to entirely different functions — for
|
||||||
| 0x539750 | FUN_00539750 | Polygon::sphere_intersects_solid | Both-side penetration |
|
> example `0x5387C0` claimed `CTransition::find_collisions` but PDB
|
||||||
| 0x539BA0 | FUN_00539ba0 | Polygon::find_time_of_collision | Ray-plane-polygon t |
|
> shows that address is `CPolygon::polygon_hits_sphere`. Use
|
||||||
| 0x539DF0 | FUN_00539df0 | Polygon::find_time_of_collision | Cylinder variant |
|
> `acclient_2013_pseudo_c.txt` to re-derive these as ground truth.
|
||||||
| 0x53A040 | FUN_0053a040 | Polygon::find_walkable_collision | Edge normal return |
|
> See ISSUES.md #9 closure for the verification pass.
|
||||||
| 0x539110 | FUN_00539110 | Polygon::calc_normal | Face normal from vertices |
|
|
||||||
| 0x539060 | FUN_00539060 | Plane::ray_plane_intersect | Basic ray-plane t |
|
| Address (legacy) | Method (legacy name) | Notes |
|
||||||
| 0x538EB0 | FUN_00538eb0 | Sphere::slide_sphere | Slide along surface |
|
|------------------|----------------------|-------|
|
||||||
| 0x538F50 | FUN_00538f50 | Sphere::land_on_sphere | Step down to surface |
|
| 0x5384E0 | Sphere::SphereIntersectsRay | Not in PDB at this address; re-derive. |
|
||||||
| 0x538180 | FUN_00538180 | CTransition::collide_with_point | Point collision handler |
|
| 0x539500 | Polygon::sphere_intersects_poly | Not in PDB; re-derive. |
|
||||||
| 0x5387C0 | FUN_005387c0 | CTransition::find_collisions | Main collision loop |
|
| 0x539750 | Polygon::sphere_intersects_solid | PDB at 0x539750 = `CMaterial::SetDiffuseSimple` — wrong class assignment. |
|
||||||
| 0x53A230 | FUN_0053a230 | Polygon::hits_walkable | Walkable surface check |
|
| 0x539BA0 | Polygon::find_time_of_collision | Not in PDB; re-derive. |
|
||||||
|
| 0x539DF0 | Polygon::find_time_of_collision (cyl) | Not in PDB; re-derive. |
|
||||||
|
| 0x53A040 | Polygon::find_walkable_collision | PDB at 0x53A040 = `BSPTREE::RemoveNonPortalNodes` — wrong. |
|
||||||
|
| 0x539110 | Polygon::calc_normal | Not in PDB; re-derive. |
|
||||||
|
| 0x539060 | Plane::ray_plane_intersect | Not in PDB; re-derive. |
|
||||||
|
| 0x00537440 / 0x00536F40 / 0x00537A10 | CSphere::slide_sphere | Three overloads in PDB — old address `0x538EB0` was wrong. |
|
||||||
|
| 0x005379A0 | CSphere::land_on_sphere (corrected from 0x538F50) | |
|
||||||
|
| 0x538180 | CTransition::collide_with_point | Not in PDB; re-derive. |
|
||||||
|
| 0x005387C0 | CPolygon::polygon_hits_sphere | PDB ground truth. Was claimed as `CTransition::find_collisions` (wrong). |
|
||||||
|
| 0x53A230 | Polygon::hits_walkable | Not in PDB; re-derive. |
|
||||||
|
|
||||||
## WeenieObject vtable (confirmed from call sites)
|
## WeenieObject vtable (confirmed from call sites)
|
||||||
|
|
||||||
|
|
@ -154,6 +191,31 @@ retail decomp at `docs/research/named-retail/`.
|
||||||
|
|
||||||
## PhysicsEngine (chunk_00450000.c)
|
## PhysicsEngine (chunk_00450000.c)
|
||||||
|
|
||||||
| Address | FUN name | ACE method | Description |
|
| Address (legacy) | Method | Description |
|
||||||
|---------|----------|-----------|-------------|
|
|------------------|--------|-------------|
|
||||||
| 0x452A10 | FUN_00452a10 | PhysicsEngine::update | Main simulation loop |
|
| 0x452A10 | PhysicsEngine::update | Not in PDB at this address (private/inlined or a different class). Re-derive from `acclient_2013_pseudo_c.txt` if needed. |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Issue #9 sweep summary
|
||||||
|
|
||||||
|
Pure docs sweep on 2026-04-25 against `docs/research/named-retail/symbols.json`.
|
||||||
|
Tooling: `tools/pdb-extract/check_function_map.py`. Findings:
|
||||||
|
|
||||||
|
- **63 entries checked.** Zero matched address-and-name exactly (all
|
||||||
|
hand-curated addresses were off by 0x800-0xC10 bytes — confirms the
|
||||||
|
PDB build is from a different revision than the binary that produced
|
||||||
|
our Ghidra chunks).
|
||||||
|
- **38 entries corrected** by name lookup (PDB name found, address
|
||||||
|
swapped to the function start).
|
||||||
|
- **25 entries lack PDB matches.** Either inlined / non-public (no
|
||||||
|
S_PUB32 record), or our hand-derived names were synthesized from
|
||||||
|
call-site analysis and don't match the actual MSVC symbol. The
|
||||||
|
ones that pointed to other functions in PDB (e.g.
|
||||||
|
`CTransition::find_collisions` → actually `CPolygon::polygon_hits_sphere`)
|
||||||
|
are flagged for re-derivation.
|
||||||
|
|
||||||
|
When in doubt: grep `acclient_2013_pseudo_c.txt` by class name to find
|
||||||
|
the actual function bodies, and use `acclient_function_map.md` for the
|
||||||
|
cross-port (ACE/ACME) hints + struct-offset lookups, not as the
|
||||||
|
authoritative address table.
|
||||||
|
|
|
||||||
149
tools/pdb-extract/check_function_map.py
Normal file
149
tools/pdb-extract/check_function_map.py
Normal file
|
|
@ -0,0 +1,149 @@
|
||||||
|
"""Cross-check acclient_function_map.md addresses against symbols.json.
|
||||||
|
|
||||||
|
For each row, looks up the function name in the PDB symbols table and
|
||||||
|
flags mismatches (mid-body addresses, wrong addresses, missing names).
|
||||||
|
|
||||||
|
Run with:
|
||||||
|
py tools/pdb-extract/check_function_map.py
|
||||||
|
|
||||||
|
Used to close ISSUES.md #9 (address-correction sweep).
|
||||||
|
"""
|
||||||
|
import json
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
REPO = Path(__file__).resolve().parent.parent.parent
|
||||||
|
SYMBOLS = REPO / "docs" / "research" / "named-retail" / "symbols.json"
|
||||||
|
|
||||||
|
# (claimed_address, qualified_name) tuples from acclient_function_map.md.
|
||||||
|
# Format: lowercase hex no leading 0, then the demangled Class::Method.
|
||||||
|
ENTRIES = [
|
||||||
|
# CPhysicsObj
|
||||||
|
("515020", "CPhysicsObj::update_object"),
|
||||||
|
("5111d0", "CPhysicsObj::UpdatePhysicsInternal"),
|
||||||
|
("511420", "CPhysicsObj::calc_acceleration"),
|
||||||
|
("511ec0", "CPhysicsObj::set_velocity"),
|
||||||
|
("511fa0", "CPhysicsObj::set_local_velocity"),
|
||||||
|
("511de0", "CPhysicsObj::set_on_walkable"),
|
||||||
|
("511560", "CPhysicsObj::report_collision_start"),
|
||||||
|
("513ac0", "CPhysicsObj::report_collision_end"),
|
||||||
|
("513b60", "CPhysicsObj::handle_obj_collision"),
|
||||||
|
("515280", "CPhysicsObj::handle_collision"),
|
||||||
|
("513730", "CPhysicsObj::UpdatePositionInternal"),
|
||||||
|
("50f940", "CPhysicsObj::calc_friction"),
|
||||||
|
("510080", "CPhysicsObj::check_contact_velocity"),
|
||||||
|
# CMotionInterp
|
||||||
|
("5286b0", "CMotionInterp::get_jump_v_z"),
|
||||||
|
("528660", "CMotionInterp::jump_charge_is_allowed"),
|
||||||
|
("5285e0", "CMotionInterp::motion_allows_jump"),
|
||||||
|
("528ec0", "CMotionInterp::jump_is_allowed"),
|
||||||
|
("528cd0", "CMotionInterp::get_leave_ground_velocity"),
|
||||||
|
("529390", "CMotionInterp::jump"),
|
||||||
|
("529710", "CMotionInterp::LeaveGround"),
|
||||||
|
("5296d0", "CMotionInterp::HitGround"),
|
||||||
|
("528960", "CMotionInterp::get_state_velocity"),
|
||||||
|
("528a50", "CMotionInterp::StopCompletely"),
|
||||||
|
("5287f0", "CMotionInterp::adjust_motion"),
|
||||||
|
("5293f0", "CMotionInterp::apply_raw_movement"),
|
||||||
|
("529210", "CMotionInterp::apply_current_movement"),
|
||||||
|
("528dd0", "CMotionInterp::contact_allows_move"),
|
||||||
|
("528f70", "CMotionInterp::DoInterpretedMotion"),
|
||||||
|
("529080", "CMotionInterp::StopInterpretedMotion"),
|
||||||
|
("529140", "CMotionInterp::StopMotion"),
|
||||||
|
("529930", "CMotionInterp::DoMotion"),
|
||||||
|
("529a90", "CMotionInterp::PerformMovement"),
|
||||||
|
# CLandBlockStruct
|
||||||
|
("531d10", "CLandBlockStruct::IsSWtoNECut"),
|
||||||
|
("532a50", "CLandBlockStruct::ConstructPolygons"),
|
||||||
|
("532eb0", "CLandBlockStruct::ConstructUVs"),
|
||||||
|
("532d10", "CLandBlockStruct::unpack"),
|
||||||
|
("531f10", "CLandBlockStruct::get_packed_size"),
|
||||||
|
("532440", "CLandBlockStruct::AdjustPlanes"),
|
||||||
|
("532290", "CLandBlockStruct::CalcCellWater"),
|
||||||
|
# CLandBlock
|
||||||
|
("530690", "CLandBlock::Init"),
|
||||||
|
("5307e0", "CLandBlock::release_all"),
|
||||||
|
("531780", "CLandBlock::init_static_objs"),
|
||||||
|
("531000", "CLandBlock::release_visible_cells"),
|
||||||
|
("5301e0", "CLandBlock::grab_visible_cells"),
|
||||||
|
("530650", "CLandBlock::add_server_object"),
|
||||||
|
# LandDefs
|
||||||
|
("5aaa30", "CLandDefs::get_vars"),
|
||||||
|
("5aabb0", "CLandDefs::get_outside_lcoord"),
|
||||||
|
("5aac70", "CLandDefs::AdjustToOutside"),
|
||||||
|
("5aab50", "CLandDefs::get_block_dir"),
|
||||||
|
# Collision / Transition (some entries are CCylSphere / CSphere / CTransition / CPolygon)
|
||||||
|
("5384e0", "CSphere::SphereIntersectsRay"),
|
||||||
|
("539500", "CPolygon::sphere_intersects_poly"),
|
||||||
|
("539750", "CPolygon::sphere_intersects_solid"),
|
||||||
|
("539ba0", "CPolygon::find_time_of_collision"),
|
||||||
|
("539df0", "CPolygon::find_time_of_collision"),
|
||||||
|
("53a040", "CPolygon::find_walkable_collision"),
|
||||||
|
("539110", "CPolygon::calc_normal"),
|
||||||
|
("539060", "CPlane::ray_plane_intersect"),
|
||||||
|
("538eb0", "CSphere::slide_sphere"),
|
||||||
|
("538f50", "CSphere::land_on_sphere"),
|
||||||
|
("538180", "CTransition::collide_with_point"),
|
||||||
|
("5387c0", "CTransition::find_collisions"),
|
||||||
|
("53a230", "CPolygon::hits_walkable"),
|
||||||
|
# PhysicsEngine
|
||||||
|
("452a10", "PhysicsEngine::update"),
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
with open(SYMBOLS, "r", encoding="utf-8") as f:
|
||||||
|
symbols = json.load(f)
|
||||||
|
|
||||||
|
# Build name -> [addresses] (some names appear multiple times: overloads)
|
||||||
|
by_name = {}
|
||||||
|
for s in symbols:
|
||||||
|
by_name.setdefault(s["name"], []).append(s["address"])
|
||||||
|
|
||||||
|
# Build address -> name (lowercase hex without 0x prefix)
|
||||||
|
by_addr = {}
|
||||||
|
for s in symbols:
|
||||||
|
addr = s["address"][2:].lower().lstrip("0") or "0"
|
||||||
|
by_addr[addr] = s["name"]
|
||||||
|
|
||||||
|
confirmed = 0
|
||||||
|
addr_corrections = []
|
||||||
|
name_misses = []
|
||||||
|
for claimed_addr, claimed_name in ENTRIES:
|
||||||
|
# Look up by name
|
||||||
|
if claimed_name in by_name:
|
||||||
|
pdb_addrs = by_name[claimed_name]
|
||||||
|
normalized_claimed = claimed_addr.lower().lstrip("0") or "0"
|
||||||
|
match = any(
|
||||||
|
(a[2:].lower().lstrip("0") or "0") == normalized_claimed
|
||||||
|
for a in pdb_addrs
|
||||||
|
)
|
||||||
|
if match:
|
||||||
|
confirmed += 1
|
||||||
|
else:
|
||||||
|
addr_corrections.append((claimed_addr, claimed_name, pdb_addrs))
|
||||||
|
else:
|
||||||
|
# Name not found exactly. Try the claimed address as fallback.
|
||||||
|
normalized_claimed = claimed_addr.lower().lstrip("0") or "0"
|
||||||
|
actual_name = by_addr.get(normalized_claimed)
|
||||||
|
name_misses.append((claimed_addr, claimed_name, actual_name))
|
||||||
|
|
||||||
|
print(f"Confirmed (address + name match): {confirmed}/{len(ENTRIES)}")
|
||||||
|
print()
|
||||||
|
if addr_corrections:
|
||||||
|
print("ADDRESS CORRECTIONS (name correct, address wrong — likely mid-body):")
|
||||||
|
for claimed_addr, name, pdb_addrs in addr_corrections:
|
||||||
|
print(f" 0x{claimed_addr.upper()} {name}")
|
||||||
|
print(f" actual: {', '.join(pdb_addrs)}")
|
||||||
|
print()
|
||||||
|
if name_misses:
|
||||||
|
print("NAME MISMATCHES (name not found by exact match in PDB):")
|
||||||
|
for claimed_addr, name, actual_name in name_misses:
|
||||||
|
print(f" 0x{claimed_addr.upper()} {name}")
|
||||||
|
if actual_name:
|
||||||
|
print(f" PDB at 0x{claimed_addr.upper()}: {actual_name}")
|
||||||
|
else:
|
||||||
|
print(f" PDB has no symbol at 0x{claimed_addr.upper()}")
|
||||||
|
print()
|
||||||
|
|
||||||
|
|
||||||
|
main()
|
||||||
Loading…
Add table
Add a link
Reference in a new issue