Commit Graph

123 Commits

Author SHA1 Message Date
MarcelineVQ d9701c528d Add glyph shadow cache: direct-mapped O(1) bypass for game's 4-bucket hash table
GetOrCreateCharacterGlyph (0x5ca2d0) is the #2 CPU hotspot at 3.65%.
The game's glyph cache uses only 4 hash buckets for ~95 ASCII chars,
causing ~24-entry chain walks with pointer chasing on every lookup.
Text measurement (99.8% of calls) re-walks these chains per character,
thousands of times per frame during UI updates.

Shadow cache: 4096-entry direct-mapped array with Murmur2 hash,
keyed on (FontObject*, charCode, param2). Cache hit returns the
cached float width via FPU ST(0) inline asm, skipping the chain
walk entirely. Gated behind ab_use_custom for A/B benchmarking.
2026-03-13 11:55:17 -07:00
MarcelineVQ 79d9521953 Refactor addon system: derive module list from build.zig, prune inactive prefixes at runtime
- Eliminate hardcoded module_names in addons.zig — now derived from
  build.zig via all_module_names build option
- Add module_active.zig runtime registry: main.zig registers isActive
  pointers during install(), addons.zig queries them without importing
  each module directly
- Prune embedded file prefixes at startup: after all modules claim
  mutexes, build a runtime active_prefixes table excluding modules we
  don't own. findEmbeddedFile searches only active entries — no
  per-lookup isActive check on the hot path
- Tag both addon and asset prefixes with module_name so pruning applies
  to all embedded files for a module
- Rename src/markers/ → src/worldmarkers/, src/outline/api.zig →
  src/outline/outline.zig to follow {name}/{name}.zig convention
2026-03-13 11:40:49 -07:00
MarcelineVQ c770e053aa Add addonperf stub module for TBC+ addon profiling API
Registers GetAddOnMemoryUsage, UpdateAddOnMemoryUsage, GetAddOnCPUUsage,
UpdateAddOnCPUUsage, ResetAddOnCPUUsage, and GetScriptCPUUsage as global
Lua functions. All stubs for now — implementation will hook lua_Alloc
and FrameScript dispatch for per-addon tracking.
2026-03-12 23:38:36 -07:00
MarcelineVQ 751063b4b0 Fix addon files not loading: use @hasDecl instead of @hasField
@hasField only works on struct fields, not module declarations.
build_options is a module, so @hasField always returned false,
silently skipping all addon file embedding and registration.
2026-03-12 23:35:18 -07:00
MarcelineVQ 2b22f59824 Add shared D3D9 device vtable helper module
Extracts direct IDirect3DDevice9 COM vtable wrappers for use by
multiple modules (outline, transform44) bypassing GxDevice abstraction.
2026-03-12 19:13:24 -07:00
MarcelineVQ 0807612699 Add ReleaseFast SSE build unit, weather override Lua API, and research notes
build.zig: add clip_sse.zig as separate ReleaseFast compilation unit,
enable SSE/SSE2 target features, disable dpslog default.
main.zig: register SetWeatherOverride Lua func, call transform44.lateInit
for blit_hub hook capture.
RESEARCH.md: document GxDevice wrappers, weather control, RTQ batching.
2026-03-12 18:46:54 -07:00
MarcelineVQ fc7f6d637b Add SSE multiplyMatrix4x4 hook (0x7bc6a0) with A/B benchmark — 4.3x speedup
Standalone SSE 4x4 matrix multiply replacing 542 bytes of x87 FPU.
Refactored rotateMatrixByAxisAngle to call the new function (with temp
buffer to avoid aliasing). All 5 SSE replacements now confirmed winners:
clip (4x), triplane (10x), rotmat (4.3x), raytri (1.3x), matmul (4.3x).
2026-03-12 18:44:02 -07:00
MarcelineVQ 53fb100368 Fix bone count: model container is at this+0x30 not this+0x2C
Ghidra decompiler swapped the two fields. Assembly verification shows:
  +0x2C = animation_context_ptr (sync check at +0x10)
  +0x30 = model_container_ptr (+0x130 = M2 model header)
Bone count chain: *(*(*(this+0x30) + 0x130) + 0x34)
2026-03-12 11:45:35 -07:00
MarcelineVQ 484a988c77 Update RESEARCH.md with corrected SceneObject->M2 pointer chain 2026-03-12 11:35:12 -07:00
MarcelineVQ f46e5d07f4 Fix bone count read: add missing +0x130 indirection to M2 header 2026-03-12 11:29:42 -07:00
MarcelineVQ 83a55150b9 Fix overflow panic: all profiling counters to u64 with saturating ops 2026-03-12 11:19:48 -07:00
MarcelineVQ 1f4f2b03c4 Increase profiling dump interval to 600 frames (~10s) 2026-03-12 11:10:15 -07:00
MarcelineVQ 67ffaa7315 Add frame time percentages to render pipeline profiling
Track frame-to-frame wall time via rdtsc delta at executeSceneRenderPass.
Stats dump now shows each function's cycles as % of total frame time,
plus rough ms estimate at 3GHz. Helps identify which functions dominate.
2026-03-12 11:06:58 -07:00
MarcelineVQ cfc252f161 Add render pipeline profiling: 5 hooks across render/movement path
Hooks executeSceneRenderPass (0x708900), renderFrame (0x707680),
transformMatrix4x4 (0x714260), RenderTextureQuads (0x76FB00), and
CMovement::ProcessUnitMovementUpdate (0x616620).

Unified stats dump every 180 render passes shows per-frame call counts,
cycle costs, bone counts, recursion depth, and quad item counts.
2026-03-12 11:03:23 -07:00
MarcelineVQ b771d7a982 Save decompiled inner functions for transform44 reference
Ghidra decompilation of all inner functions called by transformMatrix4x4,
plus the full 2263-line main function decompilation.
2026-03-12 10:55:19 -07:00
MarcelineVQ 572635dd9f Add transform44 profiling hook and inner function analysis
Phase 1 profiling: hooks transformMatrix4x4 (0x714260) to measure call
frequency, early-exit rate, cycle cost, bone counts, and recursion depth.
Dumps stats every 500 calls.

Decompiled and analyzed all 11 inner functions. Key findings:
- findInterpolationIndices already has good temporal coherence (linear scan)
- Matrix math (scale, translate) uses x87 FPU — SSE candidates
- Game already has SSE matrix multiply used by rotateMatrixByQuaternion
- interpolateAnimationKeyframes does 4-component lerp — textbook SSE
2026-03-12 10:49:27 -07:00
MarcelineVQ c7a293bec4 Add research notes for SuperWoW events and transformMatrix4x4 analysis 2026-03-12 10:38:11 -07:00
MarcelineVQ 48ebbdfe52 Minor: clickthrough log to console only, ignore assets_backup dirs 2026-03-12 10:36:50 -07:00
MarcelineVQ 9965a50aab Add transform44 module stub for M2 bone transform optimization
Wires transform44 into build system and main.zig module table.
Module skeleton with mutex/logger, no hooks yet — analysis in progress.
2026-03-12 10:36:36 -07:00
MarcelineVQ 5927568fe8 Refactor addon system to be data-driven from build.zig
Build options now provide addon_name, addon_hidden, and file lists per
module. addons.zig derives everything from these — no hardcoded module
list. Added addon_hidden flag (WorldMarkers uses it to stay unlisted).
Changed dpslog default to enabled.
2026-03-12 10:36:24 -07:00
MarcelineVQ e0da2791d9 Fix dpslog dynamic slot search and environmental damage params
Resize hook now expands event array to 801 slots. Dynamic slot search
scans from slot 650 for first empty entry (compatible with SuperWoW).
Fixed ProcessEnvironmentalDamage parameter order — Ghidra mislabeled
damageSource as damage. Lua chat output now fires only on first subevent.
2026-03-12 10:35:44 -07:00
MarcelineVQ 65bc234c08 Add dpslog module: unified COMBAT_LOG_EVENT with 35 subevents
Hook 23 packet handlers / internal functions to fire a single
COMBAT_LOG_EVENT with WotLK-style subevent strings and structured
args (spellId, amount, school, etc.) for addon consumption.

Event registration writes directly into the internal FrameScript
event table at slot 650, with a resize_lua_event_array hook that
expands capacity to 700 when needed (compatible with SuperWoW).

Includes Lua tracker addon (WeirdUtils_DPSLog) with popup checklist
UI, per-subevent chat output, and /dpslog slash command.
2026-03-11 21:45:24 -07:00
MarcelineVQ 3fdda58f09 Fix marker placement over game objects with terrain-only re-raycast
When cursor hits an object (hitType=2), re-call WorldIntersectionTest
with flags=0 to get terrain position behind it. Replaces the GUID-based
unit position lookup which failed for GOs (no movement struct).
2026-03-10 14:10:25 -07:00
MarcelineVQ 3e37b96788 Consolidate shared game offsets and accessor functions
Extract duplicated WoW 1.12.1 addresses and game accessor functions
into shared modules (src/offsets.zig, src/wow.zig), replacing 5+
copies of getObjectByGUID, isInBattleground, isValidPtr, etc.

- src/offsets.zig: shared address constants (object manager, descriptor
  fields, map/zone, core function addresses, D3D9/GX)
- src/wow.zig: shared accessor functions (pointer validation, object
  manager traversal, field reads, unit helpers, battleground detection,
  game function wrappers, raid target cache)
- Update 10 modules to import from shared instead of inline constants
- Remove outline/wow.zig (promoted to src/wow.zig)
- Trim outline/offsets.zig and markers/offsets.zig to module-specific only
2026-03-10 13:53:29 -07:00
MarcelineVQ 1a9f0c237e Add outline Idris research notes 2026-03-10 13:27:45 -07:00
MarcelineVQ 7462f424e0 Add dpslog research notes for packet handlers and event registration 2026-03-10 13:27:43 -07:00
MarcelineVQ 82cf5475b5 Add clickthrough research docs for allowlist and BG objects 2026-03-10 13:27:23 -07:00
MarcelineVQ 0f14213b0b Add logging module with auto-prefix, route all output through Logger
Replace console.zig with logging.zig: per-module Logger with auto
[name] prefix, optional file output, and destination routing. Convert
all modules from manual [name] prefixes and global con.print to Logger
instances. Remove redundant "Module loaded" lines. Replace
OutputDebugStringA in outline/tracker with Logger. Add dpslog module
with structured combat log events (SPELL_DMG, PERIODIC, HEAL, MELEE).
Add clickthrough module and bigcursor D3D9 cursor scaling.
2026-03-10 13:26:45 -07:00
MarcelineVQ e403ee18f2 Disable world markers in battlegrounds via Map.dbc mapType check
Reads current map type from ObjMgr+0xCC -> Map.dbc row+0x08 and blocks
marker placement when mapType == 3 (battleground). Clearing markers
still works in BGs. Shows "World Markers unavailable in battlegrounds."
via the existing deny message system.
2026-03-10 11:29:13 -07:00
MarcelineVQ d4e9c0417a Remove debug logging, update DLL_README with clickthrough 2026-03-09 22:42:57 -07:00
MarcelineVQ d155914059 Add NPC click-through and fix NPC_FLAGS descriptor offset
Player hit → re-raycast without players, accept interactable NPCs
(npc_flags != 0: vendors, quest givers, flight masters, etc.) or GOs.
Unit hit → re-raycast GO-only, accept interactable GOs.

Fix DESC_NPC_FLAGS: was 0x8D*4 (0x234), should be 0x93*4 (0x24C) —
field index includes OBJECT_END (0x06) base, matching minimapicons.
2026-03-09 21:34:33 -07:00
MarcelineVQ 85682f186b Add clickthrough module: GO click-through via dual WorldIntersectionTest
Hooks WorldIntersectionTest (0x480DF0) to detect when the raycast hits a
unit/player, then re-calls the original with GO-only flags (0x04). If an
interactable GO is behind the unit/player on the same ray, replaces the
hit result so the game targets the GO instead.

Uses CallSpellCastHandler (0x5F8800) for interactability filtering —
any usable GO (mailboxes, soulwells, portals, etc.) triggers click-through.
2026-03-09 20:58:56 -07:00
MarcelineVQ d325c9f684 Use hook.cc.* aliases and migrate remaining hook.fastcall calls
Replace all local calling convention declarations (const fc/tc/sc)
with hook.cc.fastcall/thiscall/stdcall from zhook. Migrate remaining
17 hook.fastcall() inline asm call sites to hook.call() with typed
function pointers.
2026-03-09 11:16:52 -07:00
MarcelineVQ 9c96a94dc1 Migrate inline asm call sites to hook.call()
Replace hand-written inline asm blocks with hook.call() typed function
pointer dispatch across 10 files. Also migrates 4 D3D9 COM vtable
NULL-dispatch blocks using ?*anyopaque optional pointers.

Net removal: ~350 lines of inline asm replaced by single-line calls.
2026-03-09 10:28:55 -07:00
MarcelineVQ b688a3dee9 Add Oranges (Refreshment Table) tracking to minimap icons 2026-03-08 22:09:44 -07:00
MarcelineVQ 541b9c97f0 Rename pngscreenshot to pngscreenshots 2026-03-08 22:09:38 -07:00
MarcelineVQ b6a2d066f7 Hide own summoned units (e.g. repair bot) from minimap icons
Cache local player GUID per enumeration cycle and compare against
UNIT_FIELD_SUMMONEDBY before showing a summoned unit's blip.
2026-03-08 19:20:17 -07:00
MarcelineVQ 8816cc14fd Add "Hide in Cities" toggle to minimap icons dropdown
Reads zone ID from 0xB4E314 and suppresses NPC/GO tracking in capital
cities (SW, IF, Darn, Org, TB, UC, Alah'Thalas) when enabled. Castle
icon converted from WC3-style PNG via png2blp.
2026-03-08 19:06:18 -07:00
MarcelineVQ 7bbce3b8a9 Use race-based faction check and CallSpellCastHandler for GO interactability
Replace faction template comparison with race-based same-faction check
since faction template is dynamically overwritten in cross-faction groups.
Uses bitmask lookup for Alliance/Horde races (including High Elf/Goblin).

Replace GO flag checks with CallSpellCastHandler (0x5f8800) — the same
virtual dispatch the game's cursor system uses to determine if a GO is
interactable. This correctly handles enemy-summoned mailboxes and
brainwashers that have no distinguishing descriptor flags.
2026-03-08 17:44:54 -07:00
MarcelineVQ 08cbbb2b8e Add faction/interactability filtering to minimap icons
Filter hostile units, wrong-faction summoned NPCs, and non-interactable
game objects from minimap tracking. Dynamic checks (UnitReaction, owner
faction, GO_FLAG_NO_INTERACT) run every frame since group membership can
change. GUID cache still handles static classification (NPC flags/subname).

Also fix missing ECX clobber in outline UnitReaction inline asm.
2026-03-08 17:15:17 -07:00
MarcelineVQ 2c4132ead7 Rename screenshot module to pngscreenshot
Less generic DLL name for distribution.
2026-03-08 15:48:16 -07:00
MarcelineVQ 4e4743afed Optimize minimap icons hot path and add Trade/Brainwasher icons
Performance:
- GUID->blip result cache (256-entry direct-mapped) skips classification
  after first match; only position lookup remains per-frame
- Active NPC flag bitmask rejects most objects before the 16-entry loop
- Split tracking by object type (unit vs GO) for early exit
- Per-frame minimap info cache (center/radius/scale read once per cycle)
- Skip subname/entry reads when no filters are active
- Batch draw calls by texture (sort blips, one GxRsSet per unique texture)
- Split drawMinimapTexture into getGxTex + drawMinimapBlip for batching

Assets:
- Add Trade.blp icon (INV_Potion_85 derived) for Trade Goods vendors
- Update Brainwasher.blp with stark contrast version, downsized to 32x32
- Add png2blp.py converter (PNG to BLP2 DXT3 with mipmaps)
2026-03-08 15:33:42 -07:00
MarcelineVQ 3a84185c07 Reorder minimap tracking categories and update addon system docs 2026-03-08 14:02:02 -07:00
MarcelineVQ bd111e8b3c Fix missing ECX/EDX clobbers in minimapicons inline asm
All inline asm call blocks must clobber ECX and EDX since callees
destroy them. Without clobbers, ReleaseSmall reuses register values
the callee already overwrote, causing NULL dereference crashes.
2026-03-08 13:46:53 -07:00
MarcelineVQ eb7b7a94e4 Clean up minimap icons: remove WMO filtering, cache active tracking, namespace Lua API
Remove unused indoor/outdoor WMO filtering and gray blip tinting.
Cache active tracking state in a bool refreshed on config change
instead of scanning all entries per-object per-frame. Move
SetObjectTypeBlip into WeirdUtils table to keep it out of the
global namespace. Add minimap tracking section to DLL_README.
2026-03-08 13:37:44 -07:00
MarcelineVQ 95df207eb8 Hide embedded addons from login addon list via +0x29 flag
All embedded addons now register through LoadAddonTOC (no more
separate hidden loading path). For addons marked hidden, walk the
addon linked list after registration and set the +0x29 exclusion
byte so DeserializeAddonData skips them when building the flat
display array. Removes the LoadAddonsRecursively hook since the
game's native LoadAddonRecursive handles all addon loading.
2026-03-08 13:13:46 -07:00
MarcelineVQ 7ccab8f802 Extract addon management into addons.zig with is_active gating
Move embedded file table, addon registration hooks, and loading logic
from main.zig into addons.zig. Each module's is_active callback gates
addon loading on mutex ownership so individual DLLs only load addons
for modules they control. Addon hooks are skipped entirely at comptime
when no addon-bearing modules are compiled in.

Also consolidates CheckFileExistence hook — customassets no longer hooks
it directly, instead exporting looseFilesLookup for main.zig's hook.
2026-03-08 12:59:51 -07:00
MarcelineVQ 9e4cbe4aaf Hook CheckFileExistence so game natively loads addon Bindings.xml
Move the CheckFileExistence (0x654DD0) hook from customassets into
main.zig's core file hooks. Embedded files now pass the game's
preloadFileWithFlags check, so LoadAddonRecursive handles Bindings.xml
loading naturally — respecting addon enabled/disabled state. Only hidden
addons still need explicit binding loading.
2026-03-08 12:37:59 -07:00
MarcelineVQ 00e7e8b472 Use [WeirdUtils] prefix in addon TOC titles for consistent display 2026-03-08 12:24:52 -07:00
MarcelineVQ d2f91fe8c2 Replace screenshot addon with screenshotQuality CVar
Remove the embedded Screenshot addon (TOC + Lua) and WeirdUtilsScreenshot()
Lua function. Compression quality is now controlled entirely via a CVar
(saved to config.wtf), read fresh on each screenshot. CVar 0 disables PNG
and falls through to original TGA.
2026-03-08 12:24:19 -07:00