v3 with @@c++(*(float*)..) STILL produced 0.000000 across the board.
Conclusion: cdb's .printf %f is unreliable for our use case — possibly
doesn't handle the float-to-double promotion in varargs the way C
printf does, or has a deeper limitation we don't have time to debug.
Pivoting to: print all floats as 32-bit hex bits via %08X, reinterpret
in the Python analysis pipeline via struct.unpack('<f', bytes.fromhex(...))
to recover IEEE 754 single-precision values.
This bypasses cdb's float formatting entirely. Integer reads (which
work — substeps, insertType, collide flag, isWater) stay as %d.
The smoking gun: BP6's check_walkable threshold should be 0.0871556997
(cos 85°) per the decomp call site at acclient_2013_pseudo_c.txt:273202.
v4's BP6 should output threshold_h=0x3DB283D7. If it does, the
infrastructure is sound and we can proceed to all 9 scenarios.
v3 capture preserved as retail-v3-cpp-zero-floats.log audit trail.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
74 lines
4.5 KiB
Text
74 lines
4.5 KiB
Text
$$
|
|
$$ Phase A6.P1 cdb probe spike v4 — 2026-05-21
|
|
$$
|
|
$$ v4 changes (after v3 still produced 0.000000 for all floats):
|
|
$$ - All float fields output as 32-bit hex via %08X. Analysis side
|
|
$$ (Python) reinterprets bytes via struct.unpack('<f', bytes.fromhex(...))
|
|
$$ to get the IEEE 754 single-precision value.
|
|
$$ - This bypasses cdb .printf's apparently-broken %f handling entirely.
|
|
$$ v2 used dwo() + %f (zeros). v3 used @@c++(*(float*)..) + %f (also
|
|
$$ zeros). %X with dwo() returns the raw 32-bit value, which we know
|
|
$$ works because the integer reads (substeps, insertType) produced
|
|
$$ real values in v2/v3.
|
|
$$
|
|
$$ v3 changes (history): added @@c++(*(float*)...) for floats — didn't help.
|
|
$$ v2 changes (history): fixed all offsets via PDB dt dump + BP6 symbol.
|
|
$$
|
|
$$ Calling convention: all functions __thiscall. ecx = this; non-this
|
|
$$ args at [esp+4], [esp+8], [esp+0xC] in order, after the return
|
|
$$ address at [esp+0].
|
|
$$
|
|
$$ Field offsets used (from PDB dt dump):
|
|
$$ Plane: N.x +0x00, N.y +0x04, N.z +0x08, d +0x0c
|
|
$$ CSphere: center.x +0x00, .y +0x04, .z +0x08, radius +0x0c
|
|
$$ CPolygon: plane +0x20
|
|
$$ SPHEREPATH: collide +0x104, insert_type +0x154, walk_interp +0x1bc,
|
|
$$ walkable_allowance +0x1b8
|
|
$$ CTransition:object_info +0x000, sphere_path +0x020
|
|
$$ (sphere_path.walk_interp = trans+0x1dc)
|
|
$$
|
|
$$ Output format for floats: name_h=0xHHHHHHHH (lowercase _h suffix
|
|
$$ marks "hex bits, reinterpret as IEEE 754 single"). E.g. BP6's
|
|
$$ threshold value 0.0871556997 = 0x3DB283D7.
|
|
$$
|
|
|
|
.logopen /t a6-probe-${ARG_LOG_TAG}.log
|
|
.sympath C:\Users\erikn\source\repos\acdream\refs
|
|
.symopt+ 0x40
|
|
.reload /f acclient.exe
|
|
|
|
r $t0 = 0
|
|
r $t1 = 0
|
|
r $t2 = 0
|
|
r $t3 = 0
|
|
r $t4 = 0
|
|
r $t5 = 0
|
|
r $t6 = 0
|
|
r $t7 = 0
|
|
|
|
$$ BP1: CTransition::transitional_insert(this, sub_step_count)
|
|
bp acclient!CTransition::transitional_insert "r $t1 = @$t1 + 1; r $t0 = @$t0 + 1; .printf /D \"[BP1] transitional_insert hit#%d substeps=%d insertType=%d\\n\", @$t1, dwo(@esp+4), dwo(@ecx+0x174); .if (@$t0 >= 50000) { qd } .else { gc }"
|
|
|
|
$$ BP2: CTransition::step_up(this, step_up_normal)
|
|
bp acclient!CTransition::step_up "r $t2 = @$t2 + 1; r $t0 = @$t0 + 1; .printf /D \"[BP2] step_up hit#%d walkAllow_h=0x%08X normalZ_h=0x%08X\\n\", @$t2, dwo(@ecx+0x1d8), dwo(poi(@esp+4)+8); .if (@$t0 >= 50000) { qd } .else { gc }"
|
|
|
|
$$ BP3: SPHEREPATH::set_collide(this, collision_normal)
|
|
bp acclient!SPHEREPATH::set_collide "r $t3 = @$t3 + 1; r $t0 = @$t0 + 1; .printf /D \"[BP3] set_collide hit#%d nx_h=0x%08X ny_h=0x%08X nz_h=0x%08X\\n\", @$t3, dwo(poi(@esp+4)+0), dwo(poi(@esp+4)+4), dwo(poi(@esp+4)+8); .if (@$t0 >= 50000) { qd } .else { gc }"
|
|
|
|
$$ BP4: BSPTREE::find_collisions(this, transition, walkable_allowance)
|
|
bp acclient!BSPTREE::find_collisions "r $t4 = @$t4 + 1; r $t0 = @$t0 + 1; .printf /D \"[BP4] find_collisions hit#%d collide=%d insertType=%d walkAllow_h=0x%08X\\n\", @$t4, dwo(poi(@esp+4)+0x124), dwo(poi(@esp+4)+0x174), dwo(@esp+8); .if (@$t0 >= 50000) { qd } .else { gc }"
|
|
|
|
$$ BP5: CPolygon::adjust_sphere_to_plane(this, sphere_path, sphere, movement)
|
|
$$ 13 floats: plane.N + plane.d + sphere.center + sphere.radius + walk_interp + movement.xyz
|
|
bp acclient!CPolygon::adjust_sphere_to_plane "r $t5 = @$t5 + 1; r $t0 = @$t0 + 1; .printf /D \"[BP5] adjust_sphere hit#%d Nx_h=0x%08X Ny_h=0x%08X Nz_h=0x%08X d_h=0x%08X cx_h=0x%08X cy_h=0x%08X cz_h=0x%08X r_h=0x%08X winterp_h=0x%08X mvx_h=0x%08X mvy_h=0x%08X mvz_h=0x%08X\\n\", @$t5, dwo(@ecx+0x20), dwo(@ecx+0x24), dwo(@ecx+0x28), dwo(@ecx+0x2c), dwo(poi(@esp+8)+0), dwo(poi(@esp+8)+4), dwo(poi(@esp+8)+8), dwo(poi(@esp+8)+0xc), dwo(poi(@esp+4)+0x1bc), dwo(poi(@esp+0xc)+0), dwo(poi(@esp+0xc)+4), dwo(poi(@esp+0xc)+8); .if (@$t0 >= 50000) { qd } .else { gc }"
|
|
|
|
$$ BP6: CTransition::check_walkable(this, threshold)
|
|
$$ Expected threshold_h = 0x3DB283D7 (= 0.0871556997, cos 85°) per decomp.
|
|
bp acclient!CTransition::check_walkable "r $t6 = @$t6 + 1; r $t0 = @$t0 + 1; .printf /D \"[BP6] check_walkable hit#%d threshold_h=0x%08X\\n\", @$t6, dwo(@esp+4); .if (@$t0 >= 50000) { qd } .else { gc }"
|
|
|
|
$$ BP7: COLLISIONINFO::set_contact_plane(this, plane, is_water)
|
|
bp acclient!COLLISIONINFO::set_contact_plane "r $t7 = @$t7 + 1; r $t0 = @$t0 + 1; .printf /D \"[BP7] set_contact_plane hit#%d Nx_h=0x%08X Ny_h=0x%08X Nz_h=0x%08X d_h=0x%08X isWater=%d\\n\", @$t7, dwo(poi(@esp+4)+0), dwo(poi(@esp+4)+4), dwo(poi(@esp+4)+8), dwo(poi(@esp+4)+0xc), dwo(@esp+8); .if (@$t0 >= 50000) { qd } .else { gc }"
|
|
|
|
.printf "a6-probe v4 armed: hex-bits float output, threshold=50000 total hits\\n"
|
|
|
|
g
|