acdream/docs/research/acclient_function_map.md
Erik 83b020499b 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>
2026-04-25 17:44:07 +02:00

12 KiB
Raw Permalink Blame History

acclient.exe Decompiled Function Map

Hand-curated cross-port index: maps select retail functions to our C# implementations + ACE / ACME equivalents + struct-offset notes. This is the cross-port index, not the authoritative name list.

For raw symbol→address lookup the authoritative source is docs/research/named-retail/symbols.json (18,366 entries from refs/acclient.pdb, the Sept 2013 EoR build PDB). Regenerate via py tools/pdb-extract/pdb_extract.py refs/acclient.pdb. Several addresses below were corrected against symbols.json in commit that closed issue #9 — match by name when in doubt.

Mapped from 22,225 decompiled functions (688K lines of C, the docs/research/decompiled/ Ghidra chunks) against ACE's C# physics port and ACME's ClientReference.cs. Now augmented by the named retail decomp at docs/research/named-retail/.

CPhysicsObj (chunk_00510000.c, chunk_00500000.c)

Addresses corrected against symbols.json 2026-04-25 (issue #9 sweep). All entries were off by ~0xC00-0x800 (different build revision than our binary). PDB names are ground truth; previous hand-curated addresses pointed mid-body.

Address (PDB) Was Method Description
0x00515D10 0x515020 CPhysicsObj::update_object Top-level per-frame update
0x00510700 0x5111D0 CPhysicsObj::UpdatePhysicsInternal Euler integration: pos += vel*dt + 0.5*accel*dt²
0x00510950 0x511420 CPhysicsObj::calc_acceleration Sets gravity (-9.8 Z) when Gravity flag set
0x005113F0 0x511EC0 CPhysicsObj::set_velocity Stores velocity, clamps to MaxVelocity (50.0)
0x005114D0 0x511FA0 CPhysicsObj::set_local_velocity Body→world transform then set_velocity
0x00511310 0x511DE0 CPhysicsObj::set_on_walkable Sets/clears OnWalkable transient flag
0x00513FD0 0x511560 CPhysicsObj::report_collision_start Fires environment collision callback
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

Offset Field Type
+0xA8 State (PhysicsState flags) uint
+0xAC TransientState uint
+0xB0 Elasticity float
+0xD8 LastUpdateTime double
+0xE0/E4/E8 Velocity XYZ float[3]
+0xEC/F0/F4 Acceleration XYZ float[3]
+0xF8/FC/100 Omega XYZ float[3]
+0x12C WeenieObject ptr ptr
+0x130/134/138 Ground normal XYZ float[3]

CMotionInterp (chunk_00520000.c)

Addresses corrected against symbols.json 2026-04-25 (issue #9 sweep). All entries were off by ~0xBE0-0xC10 bytes (consistent delta within this class — same build-revision skew). Old addresses in column 2 are kept for traceability against existing comments.

Address (PDB) Was (mid-body) Method Description
0x00527AA0 0x5286B0 CMotionInterp::get_jump_v_z Jump Z velocity (delegates to WeenieObj)
0x00527A50 0x528660 CMotionInterp::jump_charge_is_allowed Can charge jump?
0x005279E0 0x5285E0 CMotionInterp::motion_allows_jump Current anim permits jump?
0x005282B0 0x528EC0 CMotionInterp::jump_is_allowed Top-level jump permission
0x005280C0 0x528CD0 CMotionInterp::get_leave_ground_velocity Full 3D launch vector
0x00528780 0x529390 CMotionInterp::jump Initiate jump
0x00528B00 0x529710 CMotionInterp::LeaveGround Reset jump state on airborne
0x00528AC0 0x5296D0 CMotionInterp::HitGround Landing handler
0x00527D50 0x528960 CMotionInterp::get_state_velocity Compute velocity for current motion
0x00527E40 0x528A50 CMotionInterp::StopCompletely Reset to Ready/idle
0x00528010 0x5287F0 CMotionInterp::adjust_motion Apply pending motion adjustments
0x005287E0 0x5293F0 CMotionInterp::apply_raw_movement Raw→interpreted state conversion
0x00528870 0x529210 CMotionInterp::apply_current_movement Set physics velocity from interpreted state
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

Offset Field ACE name
+0x04 WeenieObject ptr WeenieObj
+0x08 PhysicsObject ptr PhysicsObj
+0x14 RawMotionState start RawState
+0x20 ForwardCommand RawState.ForwardCommand
+0x28 ForwardSpeed RawState.ForwardSpeed
+0x2C SideStepCommand RawState.SideStepCommand
+0x38 TurnCommand RawState.TurnCommand
+0x44 InterpretedMotionState start InterpretedState
+0x4C InterpretedState.ForwardCommand
+0x50 InterpretedState.ForwardSpeed
+0x70 StandingLongJump bool
+0x74 JumpExtent float
+0x7C MyRunRate float

CLandBlockStruct (chunk_00530000.c)

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 those, the old address may still be useful via Ghidra chunk inspection. Where PDB has the name, use the corrected address.

Address (PDB) Was Method Description
(no S_PUB32) 0x531D10 CLandBlockStruct::IsSWtoNECut Split direction helper (inner). PDB at 0x531D10 = ConstructPolygonsIsSWtoNECut is likely inlined. Check pseudo-C 0x531D10 neighborhood for the inline.
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)

Issue #9 sweep, 2026-04-25. Several entries are not in PDB public symbols (private/inlined). release_all, init_static_objs, release_visible_cells, grab_visible_cells all corrected.

Address (PDB) Was Method Description
(no S_PUB32) 0x530690 CLandBlock::Init Likely inlined ctor; not exported.
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)

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 are kept for legacy compatibility; addresses unchanged from the Ghidra chunk analysis. Re-derive via acclient.c cross-reference.

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)

Issue #9 sweep, 2026-04-25. Many of these names don't appear verbatim in PDB; either the actual class is CCylSphere / CSphere differently scoped, or the methods are private/inlined. A few addresses now pointed to entirely different functions — for example 0x5387C0 claimed CTransition::find_collisions but PDB shows that address is CPolygon::polygon_hits_sphere. Use acclient_2013_pseudo_c.txt to re-derive these as ground truth. See ISSUES.md #9 closure for the verification pass.

Address (legacy) Method (legacy name) Notes
0x5384E0 Sphere::SphereIntersectsRay Not in PDB at this address; re-derive.
0x539500 Polygon::sphere_intersects_poly Not in PDB; re-derive.
0x539750 Polygon::sphere_intersects_solid PDB at 0x539750 = CMaterial::SetDiffuseSimple — wrong class assignment.
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)

vtable offset ACE method Called from
+0x30 InqJumpVelocity get_jump_v_z
+0x34 InqRunRate get_state_velocity
+0x3C CanJump jump_is_allowed
+0x4C HandleCollisionEnd report_collision_end
+0x50 HandleCollisionStart handle_obj_collision
+0x54 HandleMissileCollision handle_obj_collision
+0x58 HandleEnvironmentCollision report_collision_start

PhysicsEngine (chunk_00450000.c)

Address (legacy) Method Description
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.