# 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 = `ConstructPolygons` — `IsSWtoNECut` 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.