111 lines
7.3 KiB
Text
111 lines
7.3 KiB
Text
* OH1 walk-oracle capture: PARTS (2026-09-02). The high-hit-rate script --
|
|
* CPhysicsPart::Draw and RenderDeviceD3D::DrawMeshInternal fire far more
|
|
* often per frame than DrawCells/DrawEnvCell/DrawBuilding (once per resident
|
|
* part vs. once per cell/building). Frame count default 3 (substitute
|
|
* <FRAMES>) to keep the trap cost bounded -- see
|
|
* claude-memory/project_retail_debugger.md's "High hit rates lag the game"
|
|
* watchout. Every bp action here is ONE .printf plus a handful of poi reads,
|
|
* per the task's own instruction; no .while loops, no nested nested calls.
|
|
*
|
|
* AUTO-DETACH: same fall-through + top-level qd recipe as
|
|
* oh-capture-walk.cdb.template / tools/cdb/pview-spiral2.cdb. Never qd
|
|
* inside a bp action.
|
|
*
|
|
* LINE FORMATS:
|
|
* F <n> -- unchanged from FW0
|
|
* P <cellid> <ox> <oy> <oz> <qw> <qx> <qy> <qz> -- unchanged from FW0
|
|
* PD gfx=<ptr> did=<hex> force=<0|1> cell=<hex> -- NEW.
|
|
* CPhysicsPart::Draw @0x0050D7A0 entry. gfx = the resolved
|
|
* CGfxObj* for the part's current degrade level (this->gfxobj[deg_level]);
|
|
* did = that GfxObj's DataID (see OPEN QUESTION below -- offset
|
|
* unconfirmed, placeholder token); force = the arg2 force flag (0 =
|
|
* ordinary CShadowPart::draw call, 1 = DrawBuilding's forced
|
|
* portal-only pass); cell = the LAST cell DID a DrawPartCell breakpoint
|
|
* saw (best-effort call-context correlation -- see note below, this can
|
|
* be STALE for the first part drawn after a building's force pass and
|
|
* before the frame's first ordinary object cell).
|
|
* DM gfx=<ptr> did=<hex> force=<0|1> bound=<0|1|2> cell=<hex> -- NEW.
|
|
* RenderDeviceD3D::DrawMeshInternal @0x0059F360 entry. gfx/did are read
|
|
* DIRECTLY from arg2 (no degrade-level resolution needed -- this is the
|
|
* already-selected CGfxObj*, cheaper/more reliable than the PD line's
|
|
* read); force = arg3; bound = arg4 (BoundingType: 0=OUTSIDE,
|
|
* 1=PARTIALLY_INSIDE, 2=ENTIRELY_INSIDE per
|
|
* oh1-built-mesh-view-contract.md's viewconeCheck table); cell = same
|
|
* best-effort DrawPartCell correlation as PD.
|
|
* There is no separate printed line for RenderDeviceD3D::DrawPartCell -- it
|
|
* is instrumented SILENTLY (register store only, no .printf) purely to
|
|
* supply the "cell" field above. DrawPartCell's own arg2 IS the cell DID
|
|
* directly (acclient_2013_pseudo_c.txt:429177 -- DrawObjCell calls
|
|
* "DrawPartCell(this, arg2->m_DID.id, &arg2->vtable, 0)"), so this is a
|
|
* clean 1-instruction, zero-.printf hook cheap enough to run every part
|
|
* draw's containing cell-walk turn.
|
|
*
|
|
* OFFSETS (VERIFY-IN-RECON -- see oh-recon.cdb's dt list):
|
|
* CPhysicsPart+0x14 = deg_level, +0x1C = draw_state, +0x20 = gfxobj,
|
|
* +0x24 = gfxobj_scale, +0x78 = draw_pos, +0xC0 = material, +0xC4 =
|
|
* surfaces, +0xDC = m_current_render_frame_num, +0xE0 = physobj.
|
|
* +0x1C/+0x20/+0xC0/+0xC4/+0xDC/+0xE0 are TRIPLE-confirmed: OH1's own
|
|
* Ghidra table (oh1-built-mesh-view-contract.md "View state"/"Built
|
|
* content and stamps") cites them independently, AND they fall out of
|
|
* acclient.h:31151-31173's field order (CYpt float @0x00, viewer_heading
|
|
* Vector3 @0x04, degrades ptr @0x10, deg_level uint @0x14, deg_mode int
|
|
* @0x18, draw_state int @0x1C, gfxobj ptr @0x20, ...). +0x14 (deg_level)
|
|
* is ONLY the acclient.h-order derivation -- OH1 never independently
|
|
* Ghidra-cited that specific field, though its immediate neighbors
|
|
* (+0x1C, +0x20) are both confirmed, which is reassuring but not proof.
|
|
* Confirm with `dt acclient!CPhysicsPart` in oh-recon.cdb before trusting
|
|
* the PD line's degrade-level GfxObj resolution.
|
|
* CGfxObj+0x6C = constructed_mesh, +0x70 = use_built_mesh, +0x90 =
|
|
* drawing_sphere, +0x94 = drawing_bsp -- same triple-confirmation
|
|
* (OH1 table + acclient.h:31712-31731 field order, matched exactly).
|
|
* Not directly read by this script, listed for completeness/cross-check.
|
|
* RenderDeviceD3D::DrawMeshInternal(this@ecx, CGfxObj* arg2, uint8 arg3,
|
|
* BoundingType arg4) -- arg2 @ esp+4, arg3 @ esp+8, arg4 @ esp+0xC.
|
|
* Signature: acclient_2013_pseudo_c.txt:427965 ("this @ ecx" annotation,
|
|
* same shape as the already-proven DrawBuilding/DrawEnvCell hooks).
|
|
* CPhysicsPart::Draw(this, int32 arg2) -- plain __thiscall, this=ecx,
|
|
* arg2 (force) @ esp+4. Signature: acclient_2013_pseudo_c.txt:274964.
|
|
* RenderDeviceD3D::DrawPartCell(this@ecx, uint32 arg2, CPartCell* arg3,
|
|
* uint32 arg4) -- arg2 (cell DID) @ esp+4. Signature:
|
|
* acclient_2013_pseudo_c.txt:429198.
|
|
*
|
|
* RESOLVED 2026-09-02 (lead): DBObj::m_DID is at +0x28. DBObj : Interface lays out vfptr@0, m_dataCategory@4, m_bLoaded@8, m_timeStamp(8-byte)@0x10, m_pNext@0x18, m_pLast@0x1C, m_pMaintainer@0x20, m_numLinks@0x24, m_DID@0x28; DBObj is the FIRST base of CGfxObj and of CObjCell (via SerializeUsingPackDBObj), and CEnvCell+0x28 is the offset every FW0 capture already proved. oh-recon.cdb's dt acclient!DBObj re-confirms. Original note kept below for provenance:
|
|
* GfxObj DataID offset. CGfxObj : DBObj (acclient.h:31712), and DBObj's
|
|
* own m_DID field (acclient.h:27579) sits behind an "Interface" vtable
|
|
* base, a `long double` timestamp, and several pointers whose EXACT
|
|
* compiler-inserted padding this research could not hand-derive with
|
|
* confidence (x86 MSVC alignment of the `long double`/double member under
|
|
* DBObj's own __declspec(align(4)) is genuinely ambiguous from the header
|
|
* text alone). DO NOT trust the placeholder below. Replace
|
|
* 0x28 with the real hex offset oh-recon.cdb's
|
|
* `dt acclient!CGfxObj` / `dt acclient!DBObj` output reports for m_DID
|
|
* before running this script for real. There is no runner-substituted
|
|
* default for this token (oh-run-capture.ps1 only fills <LOG>/<FRAMES>) --
|
|
* hand-edit the two `0x28` occurrences below.
|
|
*
|
|
* CALLING-CONVENTION NOTE: CPhysicsPart::Draw and DrawMeshInternal both use
|
|
* the proven "this@ecx (or plain thiscall), remaining args on the stack
|
|
* starting at esp+4" shape already exercised by the FW0 BLD/DI hooks, so
|
|
* this script's stack reads carry the SAME confidence as those. This is
|
|
* NOT true of the alpha-list functions in oh-capture-alpha-depth.cdb.template
|
|
* -- see that file's own calling-convention note.
|
|
*
|
|
* BEFORE USE: replace <FRAMES> (plain decimal digits), <LOG> (output path),
|
|
* and BOTH occurrences of 0x28 (see OPEN QUESTION above).
|
|
* <VPOS> is pre-resolved to Render::viewer_pos @0x0081ef00, same as
|
|
* oh-capture-walk.cdb.template.
|
|
|
|
.logopen <LOG>
|
|
.sympath C:\Users\erikn\source\repos\acdream\refs
|
|
.symopt+ 0x40
|
|
.reload /f acclient.exe
|
|
r $t0 = 0
|
|
r $t5 = 0
|
|
bp 00453aa0 "r $t0 = @$t0 + 1; .printf \"F %d\\n\", @$t0; .printf \"P %08x %08x %08x %08x %08x %08x %08x %08x\\n\", poi(0081ef00+4), poi(0081ef00+0x3c), poi(0081ef00+0x40), poi(0081ef00+0x44), poi(0081ef00+8), poi(0081ef00+0xc), poi(0081ef00+0x10), poi(0081ef00+0x14); .if (@$t0 < 0n<FRAMES>) { gc }"
|
|
bp 005a07a0 "r $t5 = poi(@esp+4); gc"
|
|
bp 0050d7a0 "r $t6 = poi(poi(@ecx+0x20) + poi(@ecx+0x14)*4); .if (@$t6 != 0) { .printf \"PD gfx=%08x did=%08x force=%d cell=%08x\\n\", @$t6, poi(@$t6+0x28), poi(@esp+4), @$t5 } .else { .printf \"PD gfx=00000000 did=00000000 force=%d cell=%08x\\n\", poi(@esp+4), @$t5 }; gc"
|
|
bp 0059f360 "r $t7 = poi(@esp+4); .if (@$t7 != 0) { .printf \"DM gfx=%08x did=%08x force=%d bound=%d cell=%08x\\n\", @$t7, poi(@$t7+0x28), by(@esp+8), poi(@esp+0xc), @$t5 } .else { .printf \"DM gfx=00000000 did=00000000 force=%d bound=%d cell=%08x\\n\", by(@esp+8), poi(@esp+0xc), @$t5 }; gc"
|
|
g
|
|
.echo ===DETACHING===
|
|
qd
|
|
.logclose
|