Files
WeirdUtils/docs/CLAUDE_PROPER_OBJECT_REGISTRATION_PLAN.md
T
MarcelineVQ 2aaa089c76 Add module control API, bigcursor with fractional scaling, shared mutex
Module control API:
- Three cdecl exports: WeirdUtils_IsModuleActive, WeirdUtils_DisableModule, WeirdUtils_DisableAll
- C header include/weirdutils_api.h for runtime DLL discovery
- All modules gain pub module_name, isActive(), shared mutex via src/mutex.zig
- build.zig refactored to module_list array of ModuleDesc

Bigcursor:
- D3D9 vtable hooks on SetCursorProperties/ShowCursor
- Scale2x/Scale3x pixel-art upscalers in pure Zig (replaces 12K-line hqx C)
- Bilinear resampler for fractional scales (1.0-4.0, default 1.2)
- Win32 cursor via CreateIconIndirect bypasses D3D9 32x32 limit
- FNV-1a hash cache for ~16 cursor bitmaps
- Lua API: SetCursorScale(n) / GetCursorScale()
- CVar cursorScale for Config.wtf persistence (tenths)

Other:
- Add dpslog module stub
- Docs and README updates
2026-03-06 13:27:35 -08:00

5.4 KiB

Proper Object Registration Plan (for Claude)

Goal

Stop ad-hoc list insertion and implement a correct, engine-native object creation/registration path for client-side markers in WoW 1.12.1.

Success = marker is visible in-world, no crash on create/destroy/toggle, and lifecycle uses native manager functions (not manual pointer surgery as primary path).


Current Status Summary (Read First)

  1. Crash fixed, visibility not fixed

    • We eliminated crash caused by callback slot garbage (obj+0x174) in manager iteration path.
    • Markers still invisible in both current test paths.
  2. What was tried

    • Path A: Allocate world object + attach model + manual insert into manager list (0x00C7CAEC).
    • Path B: CreateGameObject_WithProperties + fallback manual insertion if unlinked.
    • Both now create/destroy cleanly, still not rendering.
  3. Known engine behaviors

    • Manager iterator (AllocateGameObject region around 0x00683F80) uses positions at +0x5C/+0x60/+0x68 and calls render-management functions.
    • It may call callback pointer at +0x174 if non-zero.
    • List pointers can be low-bit tagged.
  4. Conclusion so far

    • List manipulation and crash stability are mostly solved.
    • Remaining blocker is likely incorrect native registration/state initialization, i.e. object not entering correct draw/classification path.

Mandatory Context Files

Read these before coding:

  1. research/marker-visibility-debug-log.md
  2. docs/M2_MODEL_SYSTEM.md
  3. research/dynamic-object-research.md
  4. src/markers/markers.zig
  5. Crash reference: /media/bigfaststore/games/twmoa_1172/Errors/2026-02-27 07.11.41 Crash.txt

Also review the CLI Ghidra skill:

  • ~/.claude/skills/ghidra-cli-wow-re/SKILL.md

Rules of Engagement

  1. Do not treat manual list insertion as final architecture.
  2. Do not trust decompiler signatures alone. Verify calling conventions from bytes/prologue/RET cleanup.
  3. Prefer discovering native add/remove APIs used by real visible objects.
  4. Every hypothesis must have an observable test log.
  5. No broad refactors until registration path is proven.

Execution Plan

Phase 1 - Identify canonical native registration path

Task 1.1: Recover true iterator and linkage semantics

  • Disassemble around 0x00683F80 (and nearby helpers) in detail.
  • Map exactly how nodes are traversed and linked (including pointer tagging and indirection via globals like 0x00C7CAE4/0x00C7CAEC).
  • Produce pseudocode with verified offsets and conditions.

Deliverable: short technical note: "Manager traversal/link semantics".

Task 1.2: Find native insertion/removal helpers

  • Find xrefs to 0x00C7CAEC and offsets +0x16C/+0x170.
  • Identify functions that insert/remove objects in production code.
  • Verify one candidate by callsite context (who calls it and when).

Deliverable: candidate helper function list with addresses + confidence.

Task 1.3: Find real creator path for visible world objects

  • Trace from known visible object creators (game objects/doodads/spell visuals) to registration.
  • Determine minimal required function chain from creation to render visibility.

Deliverable: canonical call chain diagram with function addresses.


Phase 2 - Build proper registration wrapper in markers module

Task 2.1: Implement native-path wrapper

  • Add a wrapper that uses discovered native creator/registration APIs.
  • Manual list insertion may remain only as fallback/diagnostic mode, not default.

Task 2.2: Lifecycle correctness

  • Ensure destroy path uses matching native teardown/unlink APIs.
  • Prevent double-unlink and callback garbage.

Task 2.3: Instrumentation

  • Keep concise debug logs for:
    • object pointer
    • model pointer
    • registration result path
    • destroy path confirmation

Deliverable: code in src/markers/markers.zig with clear mode labels.


Phase 3 - Validation protocol (must pass)

Run and capture logs for:

  1. /mark on
  2. visually confirm marker appears
  3. /mark off
  4. repeat 5+ times
  5. mode switching stress (testa/testb if retained)

Must pass:

  • no crash
  • no panic
  • marker visible at player position
  • clean destroy every cycle

If failed:

  • report exact failing step, log lines, and next smallest probe

Expected Outputs from Claude

  1. Updated code implementing native registration path.
  2. Updated research/marker-visibility-debug-log.md with:
    • what changed
    • what was validated
    • remaining unknowns (if any)
  3. Optional update to docs/M2_MODEL_SYSTEM.md for newly confirmed function semantics.
  4. Final summary:
    • root cause
    • final fix
    • evidence (logs + addresses)

Suggested Command Workflow (CLI Ghidra)

Use headless scripts via:

/home/august/.claude/skills/ghidra-cli-wow-re/scripts/run-analysis.sh /tmp/analysis.py

Focus scripts on:

  • xrefs to manager globals and list offsets
  • disassembly around candidate insertion helpers
  • call graph from visible object creation paths

Non-Goals (for this pass)

  • New marker visuals
  • Effects polish
  • Optimizations unrelated to visibility/registration correctness
  • Expanding to many marker types before first visible stable marker

Acceptance Criteria

  • Marker visibility achieved using engine-native registration path (or proven minimal wrapper around it)
  • No crash across repeated create/destroy
  • Documentation updated with verified semantics
  • Ad-hoc list surgery no longer required as primary behavior