Commit Graph

259 Commits

Author SHA1 Message Date
MarcelineVQ bf5a7aa624 perf: GUID cache with destruction hook, remove glyph cache
GUID lookup cache: 4096-entry direct-mapped with proper invalidation.
MoveObjectToDeletedList (0x464920) hook evicts entries AFTER the
original runs (prevents re-caching from internal FindObjectByGUID call).
DestroyObjectManager (0x467700) hook flushes on zone change/logout.
93% hit rate, 1.15x speedup on FindObjectByGUID (10K+ calls/frame).

Glyph shadow cache removed: game has internal glyph cache at
GetOrCreateCharacterGlyph (0x5CA2D0). Our hook only saw cache misses
(~30/frame), providing no benefit. The 3.65% perf profile was the
game's own hash table work, not redundant computation.

Standalone guidcache module for isolated testing.
2026-03-26 04:14:34 -07:00
MarcelineVQ 1f318a8565 perf: GUID lookup cache (97% hit, 2.6x)
FindObjectByGUID (0x464890): 4096-entry direct-mapped cache with
validate-on-hit. 97% hit rate at 10K+ calls/frame, reducing from
0.8% to 0.3% frame time. Validates cached pointers by checking
GUID at obj+0x30/+0x34 on every hit.

AddToSpatialGrid (0x6816F0): SSE rewrite attempted, no measurable
gain (memory-bound linked list ops dominate). Not shipped.
2026-03-25 14:46:56 -07:00
MarcelineVQ ad33eb9b90 perf: SSE ray_tri_indexed_int (2.2x), new profiling hooks
rayTriIntersectIndexedInt (0x7C2C40): SSE Moller-Trumbore with deferred
divide, matching original's epsilon thresholds. Parity-tested against
original for edge hits, backfaces, parallel rays, and per-triangle t/uv.
JMP-patched in weirdperformance.

Added transform44 profiling hooks for ray_tri_indexed_int (0x7C2C40)
and ProcessStaticObjectsCulling (0x683BF0).

Bench: added rayTriIndexedInt bench with exhaustive parity tests.
2026-03-25 13:36:33 -07:00
MarcelineVQ 41ca30cfd5 perf: SSE spatial culling, inlined ray-tri, clickthrough CC fix
PerformSpatialCulling (0x6B8C60): Zig rewrite with SSE outcode
computation. 1.4x speedup, JMP-patched in weirdperformance.

performCollisionDetection (0x6B88E0): fully inlined SSE Moller-Trumbore
ray-triangle intersection, eliminating 4 SetVector3 calls and the
ray_tri function pointer call per triangle. ~22 cyc/tri in bench.

Both graduated from transform44 A/B testing to production JMP patches.

entity_sse.zig: reimplementations of UpdateEntityAndChunksPositions and
updateEntitiesInBounds (A/B tested, 1.2x bench, not shipped - memory
bound with negligible real-world gain).

clickthrough: fixed CheckObjectTypePermissions hook from fastcall to
thiscall (ECX preservation), fixed ClntObjMgrObjectPtr from fastcall(4)
to fastcall(5) with correct arg count.

bench: added performCollisionDetection bench with synthetic mesh data
and patched FindOrCreateHashEntry stub.
2026-03-25 12:34:57 -07:00
MarcelineVQ 28514c029c clickthrough: cascade raycast with custom CanTargetEntity filter bits
Replace the re-raycast approach with a priority cascade: loot > GO > NPC
> normal. Each pass uses custom flag bits (0x01/02/04 in upper byte) that
our CanTargetEntity hook reads to exclude non-matching objects at the
raycast level. Terrain/WMO occlusion applies per pass.

Hook CanTargetEntity (0x480610) for per-object filtering: strips custom
bits before calling original, then checks lootable/interactable/NPC
based on which pass is active. Objects that don't match the current pass
return NULL (invisible to raycast, ray continues through them).

Fix isLootable: UNIT_DYNAMIC_FLAGS was at wrong descriptor offset
(0x96*4=0x258, should be 0x8F*4=0x23C per server UpdateFields index 143).
Also add UNIT_DYNFLAG_TAPPED and UNIT_DYNFLAG_TAPPED_BY_PLAYER offsets.
Fix isLootable base pointer: use getDescriptor (obj+0x08) not
getUnitDescriptor (obj+0x110), consistent with getNpcFlags and all
other descriptor reads in the project.
2026-03-25 01:30:16 -07:00
MarcelineVQ e78ebfd74d particle: fix tail texcoords and transformVec4 input size
Tail vertices V0/V1 read texture U/V from wrong addresses (no offset
from base instead of +8/+16 stride). Assembly reads 0x87D734/738 for
V0 and 0x87D73C/740 for V1, not the base 0x87D72C/730. This made both
base vertices share UVs, collapsing the texture and causing light beams
to taper to a point instead of maintaining width.

Also fix transformVec4 input: must be [4]f32 with w=0.0, not [3]f32.
The function reads all 4 components including [EDX+0xC]. Reading past
a 3-element array produced garbage w values that corrupted the velocity
transform, causing tail particles to extend wildly.

Fixed in both SSE and reference implementations.
2026-03-24 22:01:32 -07:00
MarcelineVQ 9a3e06a7cc core: disableAll only removes module hooks, core stays until DLL unload
Core hooks (file serving, Lua registration, engine init/shutdown) are
shared infrastructure that other loaded DLLs depend on. Only release
them in uninstall (DLL_PROCESS_DETACH), never via the runtime API.
2026-03-24 18:52:51 -07:00
MarcelineVQ d748978d1c core: add mutex to prevent double-hooking shared infrastructure
When both weirdutils.dll and a standalone module DLL are loaded,
the core mutex (Local\WeirdUtils_weirdutils_<PID>) ensures only one
installs the shared hooks (file serving, Lua registration, engine
init/shutdown). Module hooks are unaffected (own mutexes). Addon
registration runs for every DLL since LoadAddonTOC is idempotent.
2026-03-24 18:03:42 -07:00
MarcelineVQ 4629ea71d6 rename performance to weirdperformance, move file cache hook into module
Move fileFindDetour from main.zig into filecache.zig with its own
install/remove. Remove file_cache import and all references from
main.zig. Rename module to weirdperformance throughout (build flag,
module_name, source file, main.zig variable).
2026-03-24 17:48:22 -07:00
MarcelineVQ 979e5729bc perf: consolidate filecache, timer calibration into performance module
Move filecache.zig and timer_fix.zig from standalone modules into
src/performance/. Filecache no longer has its own hooks/mutex — stats
are dumped by performance's worldupdate hook. Timer calibration runs
during performance install instead of transform44. Remove filecache
from build module list (enabled automatically with performance).
Merge DLL_README sections into single Performance entry.
2026-03-24 17:28:19 -07:00
MarcelineVQ 3cab0db8c8 addons: prefix Outline and Log Sessions TOC titles with [WeirdUtils] 2026-03-24 17:09:08 -07:00
MarcelineVQ c7a35c3c2f worldmarkers: use shared wow.zig utilities, remove dead code
Replace custom getNameFromGUID with wow.getNameByGUID, use wow.readGUID
for GUID comparisons, remove getPlayerGUID wrapper. Drop unused
PARTY_MEMBER_GUIDS, FN_NAME_CACHE_LOOKUP, NAME_CACHE_OBJ from offsets.
2026-03-24 17:07:59 -07:00
MarcelineVQ a7fe79c668 minimapicons: replace quest available icon with pfQuest-derived grayscale version 2026-03-24 17:01:40 -07:00
MarcelineVQ 7b1f13b138 docs: update clickthrough and minimapicons descriptions, add Find Fish tracking, remove /tracking slash command 2026-03-24 15:22:18 -07:00
MarcelineVQ 80a7cdea3f inflate: thread-local libdeflate with gnu ABI — 2.2x speedup, 100% coverage
Root cause of crashes was thread safety: libdeflate's decompressor struct
has mutable decode tables rebuilt per-block, so sharing between main thread
and FMOD audio thread caused wild writes. Fixed with a thread-local pool
keyed by Windows thread ID (FS:[0x24]).

Switched build ABI from msvc to gnu — eliminates stub headers, libdeflate
uses Zig's bundled MinGW libc. Relaxed zlib header filter from == 0x78 to
(CMF & 0x0F) == 0x08 to catch both 32K and 4K window sizes.

Benchmarked: stock=2681ms, per-call-alloc=1304ms (2.05x), tls=1194ms (2.2x)
on 84k calls. Zero errors, zero fallbacks in production.
2026-03-24 14:57:28 -07:00
MarcelineVQ b612e6f953 inflate: fair timing comparison — 2.4x speedup confirmed
Fixed apples-to-apples comparison: track orig time only for calls where
libdeflate also ran. Previous numbers were misleading (all calls vs subset).

Results (same calls compared):
  Loading: 3352 matched calls, orig=160ms fast=66ms (2.4x)
  Gameplay: 150 matched calls, orig=5ms fast=2ms (2.5x)
  Projected total saving: ~1.76s off loading, ~100ms/period gameplay

Also fixed: thread safety (main thread only), zlib header validation,
input buffer save (256KB static), separate output buffer, FreeMemory
4-param calling convention.

Remaining: 8% failures (277/3352), not yet running on all threads.
2026-03-24 04:41:09 -07:00
MarcelineVQ 21ac8df11e inflate: research doc, saved-input fix for buffer modification bug
DecompressData_WithOptions modifies the input buffer during overlap
handling. Our hook must save the input before calling the original,
then pass the saved copy to libdeflate. Also documents all compression
types, function signatures, and bugs found during integration.

libdeflate sanity test passes (hello → hello, cpu_features=0x8000001F).
2026-03-24 04:20:11 -07:00
MarcelineVQ 2b11ae5cf1 inflate: logging reveals 100% zlib (type 0x02), standard 78 9C header
All 93K decompression calls during loading are pure zlib (type 0x02).
Header bytes 78 9C confirm standard zlib-wrapped deflate. No PKWare,
bzip2, or ADPCM observed.

Volume: 170MB compressed → 380MB decompressed in 2.9s during loading,
~5K calls/period during gameplay.

Format: [0x02] [zlib_stream...] — straightforward for libdeflate.
Previous crashes were from reading out_size AFTER original modified it
and from writing to out_buf unsafely.
2026-03-24 03:49:44 -07:00
MarcelineVQ 59ef452f22 perf: libdeflate inflate timing hook — runs both, compares results
Hooks DecompressData_WithOptions (0x661A80) to run both the original
zlib inflate and libdeflate on the same data. Times both, logs the
comparison every ~450 frames, counts mismatches.

malloc/free provided via game's Storm memory manager (SMemAlloc/SMemFree)
since we link without libc on the msvc target.

libdeflate compiled with -g0 to avoid .debug_frame COFF section name
warning. AVX-512 disabled (32-bit), SSE2/AVX2 paths active.
2026-03-24 03:01:15 -07:00
MarcelineVQ fb27ff54a0 perf: vendor libdeflate for fast inflate replacement
Vendored libdeflate decompress-only C sources into src/performance/.
Compiled as static lib (x86-windows-gnu for libc headers), linked into
the DLL. AVX-512 disabled (not available on 32-bit x86), SSE2/AVX2
paths active.

Target: replace WoW's embedded zlib inflate (~3% CPU) with libdeflate's
~2.3x faster implementation. Hook integration next.
2026-03-24 02:27:51 -07:00
MarcelineVQ 62bcf11d58 perf: performance module on by default, includes silicon patches
- performance module default=true, transform44 and silicon default=false
- Silicon JMP patches (22 functions) moved into performance.zig directly
- Single flag: 'zig build' gives all optimizations, zero profiling
- Dev mode: 'zig build -Dtransform44=true' for A/B testing
2026-03-24 01:24:42 -07:00
MarcelineVQ 3b48b500ec perf: new 'performance' module — zero-overhead production SSE hooks
Clean module at src/performance/ with all verified permanent
optimizations and zero profiling overhead. No rdtsc, no A/B testing,
no probe counters, no dumpStats.

Hooks: transformMatrix4x4 bone SSE, RenderParticleSprites SSE,
GetOrCreateCharacterGlyph cache, OnWorldUpdate cache reset,
teardown guard.

SSE compilation units (bone_sse, particle_sse, clip_sse, silicon_sse)
moved to src/performance/ as canonical location.

Build: zig build -Dperformance=true -Dsilicon=true
(transform44 module remains available for profiling/development)
2026-03-24 01:21:10 -07:00
MarcelineVQ 2f0e8a8bc0 fix: particle color byte masking, add reference version
Color channel packing missing & 0xFF after >> 14 extraction — upper
bits bled into adjacent channels causing broken particle fading.
Same class of bug as the alpha output fix earlier.

Added particle_sse_reference.zig (faithful recreation from commit
574f96f) as a separate compilation unit for correctness comparison.
2026-03-24 01:08:01 -07:00
MarcelineVQ 112246e687 perf: make all verified optimizations permanent, remove A/B toggles
- Glyph cache: unconditional (was A/B toggled)
- RenderParticleSprites SSE: unconditional (was A/B toggled)
- transform44 bone SSE: already permanent (teardown guard only)
- processLinkedListCollision: already permanent (JMP patch)
- frustumCullBoundingBox: already permanent (JMP patch)
- silicon functions (ftol, normalize, matmul, etc.): already permanent

Also adds decompilation of UpdateEntityAndChunksPositions — analyzed
but not optimizable (game function calls dominate, math is ~50 cycles
of the ~375 cycle total).
2026-03-24 00:44:18 -07:00
MarcelineVQ 3d872fdb1e spritequad: recreation + analysis (disabled, no improvement)
Faithful recreation of RenderSpriteQuads (0x5A0F50) with hoisted
invariant division and inlined DisplayMode_CalculateOffset. No
measurable improvement — cost is dominated by getAdapterInfo (7
sub-calls to D3D device per invocation × 3203 calls/frame) and
DrawPrimitive/DrawIndexedPrimitive virtual dispatch.

Added decompilation and assembly dumps for future reference.
2026-03-24 00:36:37 -07:00
MarcelineVQ 1046c0a4e3 particle: WIP setupParticleRendering recreation (disabled)
Faithful recreation attempt of SetupParticleRendering (0x7B3D20).
All game function CCs verified from assembly. Vertex buffer setup
works (8 verts produced), but D3D draw submission doesn't produce
visible output. Disabled pending investigation of GfxDeviceMethod
param struct layout. The function remains as timing-only pass-through.

Fixes found during work:
- max_particle_sprites global: 0xCF58F4 → 0xCF5B60
- billboard_matrix global: 0xCF5898 → 0xCF5888
- index_buffer_6/12: 0xCF58D0/D4 → 0xCF5BAC/0xCF5AF4
- BuildIndexBuffer takes renders_count not field_28
- Identity matrices must be mutable (game writes to them)
2026-03-24 00:25:12 -07:00
MarcelineVQ a73b5273fd research: Ghidra decompilation of SetupParticleRendering (326 lines)
10% of frame time, ~275 calls/frame, ~5800 cyc/call. Builds identity
matrices (32 stores of dead work), does 1-5 matmul calls, copies to
g_worldMatrix global. Translation matrix is identity+offset — matmul
chain can be simplified to direct computation.
2026-03-23 22:50:49 -07:00
MarcelineVQ 5373686bd4 particle: V4 vertex store, inline for unroll — ~42% total reduction
- V4 store (vmovups) writes xyz+color as one 16-byte op instead of 4
  scalar stores. Unaligned but still 1 μop on modern CPUs.
- inline for unrolls 4-vertex loops, letting LLVM schedule stores
  across vertices and fill pipeline bubbles.
- Hoisted world_pos to locals to prevent array re-reads.
- A/B: BASELINE ~433ms → CUSTOM ~299ms (~31% per-period reduction).
  Total from original: 520ms → 299ms = 42% reduction.
2026-03-23 22:47:50 -07:00
MarcelineVQ 379fcb62eb particle: contiguous vertex writes, skip normals, stride logging
- Detected interleaved 24-byte vertex layout: xyz(12)+color(4)+uv(8).
  Fast path writes 6 sequential u32s instead of scattered stores.
- Normal stride=0 (shared global) — write once in writeback, not 4x.
- Added stride_info export + logging for vertex layout analysis.
- A/B: ~30% peak reduction, baseline also improved due to less overhead.
2026-03-23 22:41:16 -07:00
MarcelineVQ 0d994db4b3 particle: VBState all paths, cached setupRender, @mulAdd — ~25% speedup
- VBState caching on all 5 vertex paths (was only 2D and sin/cos).
  Eliminates pointer re-reads: load once, emit 4 vertices, writeback.
- Cache setupRender() result per-frame via static + resetParticleCache()
  called from worldUpdateDetour. Saves ~7K function calls/frame.
- @mulAdd throughout for FMA codegen on vertex position and texcoord.
- A/B verified: BASELINE ~521ms → CUSTOM ~387ms (~25% reduction).
2026-03-23 22:29:12 -07:00
MarcelineVQ 1dc1350645 particle: inline calcColor + mat*vec3, VBState caching — ~20% speedup
- Inline calcColor: eliminates function call, allows OoO overlap of
  cache misses on colorCtx with vertex math. Pow path falls back to
  game function.
- Inline mat*vec3 transform: V4 FMA chain replaces call to 0x7BCA80.
- VBState: cache VB pointers/strides in locals, write back once after
  4 vertices. Eliminates ~80 pointer re-reads per particle.
- @mulAdd throughout vertex loops for FMA codegen.
- A/B verified: BASELINE ~470ms → CUSTOM ~382ms (~20% reduction).
2026-03-23 22:22:31 -07:00
MarcelineVQ 574f96f661 particle: faithful RenderParticleSprites recreation, A/B verified
Full recreation of RenderParticleSprites (0x7B2A50, 2688 bytes) in
particle_sse.zig. All 5 code paths: 2D billboard, 3D billboard,
2D+rotation (sin/cos), 3D+rotation (axis-angle matrix), tail particles.

Key fixes during verification:
- colorCtx address: removed Ghidra's spurious -0x12 offset
- calcColor arg2: pass raw u32 from emitter+0x1A8, not truncated
- Texture coord lookups: +8 offset to match assembly's eax increment
  between position and texcoord reads in the vertex loop

Verified in-game: particles render identically in CUSTOM vs BASELINE.
Next: optimize with SSE (inline calcColor, V4 vertex math).
2026-03-23 22:12:17 -07:00
MarcelineVQ d205693dbb particle: Ghidra decompilations, particle_sse.zig scaffold, bench
- Ghidra C decompilation of RenderParticleSprites (422 lines) and 5
  helper functions (calculateColorValues, matVec3Transform, etc.)
- particle_sse.zig with calcColorValues_SSE (10.7x bench but cache-miss
  bound in-game — needs inlining into full function replacement)
- Bench harness for calcColorValues with correctness check
- build.zig: particle_sse as separate ReleaseFast compilation unit
- colorDetour reverted to pass-through (SSE has no in-game effect due
  to L1 cache misses on scattered ColorCtx structs)
2026-03-23 21:56:57 -07:00
MarcelineVQ fec9ac9952 research: particle system SSE optimization analysis
Assembly dumps and research doc for RenderParticleSprites (1.73% CPU),
calculateColorValues (0.63%), SetupParticleRendering, and
ProcessActiveParticles. Identifies SSE opportunities: V4 color interp,
billboard vertex math, rotation block. Plan for particle_sse.zig.
2026-03-23 21:23:19 -07:00
MarcelineVQ 4b5fcd6fa6 perf: glyph cache A/B testing, fast hash, frustumCull rcpss+cvtss2si
- glyph cache: add A/B toggle so BASELINE/CUSTOM periods alternate
  between original function and shadow cache. Swap Murmur2 hash for
  fast golden-ratio integer mix (3 insns vs multi-step).
- frustumCullBBox: fastRecip (vrcpss+NR) and cvtss2si replace vdivss
  and @round bloat. 2.0x speedup (was 1.6x).
- Fix all Zig operator precedence bugs in silicon_sse: & and | bind
  looser than == in Zig, so (flags & 0x8 == 0) was always false.
  Affected frustumCullBBox and processLinkedListCollision.
2026-03-23 21:15:15 -07:00
MarcelineVQ 0576a06ef0 fix: Zig operator precedence bugs in silicon SSE functions
All bitwise & and | comparisons were missing parentheses — Zig's ==
and != bind tighter than & and |, so `flags & 0x8 == 0` parsed as
`flags & (0x8 == 0)` = `flags & 0` = always 0.

Affected: si_frustumCullBBox (behind-camera check never ran, occlusion
flag check always passed), si_processLinkedListCollision (early-out
never triggered, node skip broken, AABB hit test only checked X-axis).

Also adds fastRecip (vrcpss+NR) and cvtss2si helpers for frustumCull
perspective divide optimization (2.0x speedup, was 1.6x).
2026-03-23 20:57:19 -07:00
MarcelineVQ 035355b757 perf: FrustumCullBoundingBox SSE replacement, 1.6x speedup
- silicon_sse: si_frustumCullBBox (0x686000) — inline V4 mat*vec3
  transforms, SSE perspective divide, 4-wide horizon buffer scan.
  Benched 1.6x (117→72 cyc/call). Installed via JMP patch (544 bytes,
  won't fit in 380-byte original).
- bench: add frustumCullBBox benchmark with mapped globals, identity
  matrices, and horizon buffer test fixture.
- Remove patch table entry for frustumCullBBox, install via detour hook
  instead (allows future A/B testing if needed).
2026-03-23 20:46:28 -07:00
MarcelineVQ 7819d6d914 perf: findInterpIdx dedup, processLinkedListCollision SSE, permanent t44
- bone_sse: deduplicate findInterpIdx calls in bone loop — rotation's
  search result reused for scale/translation when tracks share temporal
  structure (canReuseInterp guard). Est. ~23% bone loop cycle reduction.
- silicon: SSE replacement for processLinkedListCollision (0x6ABC40,
  1.57% CPU). V4 AABB overlap test replaces 6 x87 FCOMP/FNSTSW.
  Benched at 3.2x speedup (378→115 cyc/call, 8 nodes).
- transform44: remove A/B toggle, always use SSE path (teardown guard
  kept). A/B infrastructure remains for other hooks.
- bench: add processLinkedListCollision benchmark with fake linked list
  test fixture and stubbed addGeometryToBuffer.
2026-03-23 20:27:26 -07:00
MarcelineVQ b0b70a744e dpslog: queued log writer, raid roster fix, shutdown hook, minimap icon fixes
Log file writer queues events and flushes after 3s delay, re-resolving
GUIDs at write time so names from later packets can fill in. Flush
triggers on each new event (for old entries) and on DestroyObjectManager
hook before the object manager is torn down.

- Fix raid roster access: 0xB712A8 is a flat array, not pointer-to-array
- Fix SPELL_GO hit targets: full u64 GUIDs, not packed
- Fix GetLocalizedText calling convention: __fastcall not __cdecl
- Fix isUnknownName filtering at dpslog use sites (not in shared wow.zig)
- Fix dropdown icon tCoords persisting across reload
- Add pfQuest-style quest available icon (gold exclamation mark BLP)
- Hook DestroyObjectManager for log flush instead of World_HandleLogoutCleanup
- Null GUID handling: nil name, 0x80000000 flags in both Lua and file paths
- Document combat log file writer in DLL_README
2026-03-20 15:03:04 -07:00
MarcelineVQ f70bffef45 dpslog: WotLK combat log file writer, null GUID handling, unique chat handlers
- Write WotLK-format CSV to Logs\WeirdCombatLog.txt when /combatlog is
  active (checks COMBAT_LOG_HANDLE at 0xB50544). Resolves names, flags,
  spell names eagerly per event via same CLEU buffer resolution as
  CombatLogGetCurrentEventInfo. Uses Win32 WriteFile with OS caching.

- Null GUIDs output as 0x0000000000000000,nil,0x80000000,0x0 matching
  WotLK format. Empty resolved names output as nil not "".

- DPSLog addon: every subevent has unique chat handler with correct name
  via factory functions.

- DAMAGE_SHIELD scans victim's auras (not attacker's) — shield owner
  is the victim in the packet.
2026-03-19 17:05:24 -07:00
MarcelineVQ 7c64660c81 dpslog: damage shield spell ID, unique chat handlers
- DAMAGE_SHIELD now resolves spell ID by scanning the victim's (shield
  owner's) aura descriptors for SPELL_AURA_DAMAGE_SHIELD (effect 15)
  matching the packet school. Uses new deferred cleuDamageShieldSpell
  buffer entry resolved lazily at CombatLogGetCurrentEventInfo time.

- Fix: scan victim's auras, not attacker's — the shield aura (Thorns,
  Retribution Aura) is on the unit being hit, not the one hitting.

- DPSLog addon: every unique subevent now has its own chat handler
  with correct name. Factory functions replace shared handlers that
  were printing wrong subevent names (e.g. "SPELL_DAMAGE" for all
  damage types).

- Remove CombatLogGetCurrentEventInfo rdtsc profiling (measured ~12k
  cycles/call = ~4us, negligible).
2026-03-19 14:37:08 -07:00
MarcelineVQ 89f9936fa4 dpslog: lazy resolution, aura caster tracking, creature names, crash fixes
- Defer all name resolution, flag computation, and spell lookups to
  CombatLogGetCurrentEventInfo() request time. Fire functions store
  only raw GUIDs (cleuGuid) and spell IDs (cleuSpellId). Resolution
  happens lazily when addons call the function, after packet/update
  processing is complete and the object manager is stable.

- Add aura caster tracking: cast ring buffer (32 entries) records
  (caster, target, spellId) from SPELL_GO hit targets. Aura applied
  hook correlates with recent casts to infer caster. Persistent cache
  (128 entries) maps (unitGUID, slot) -> casterGUID for aura removal.

- Fix creature name resolution: use CGUnit_C::GetNameFromCacheOrUnknown
  (0x609210) via object pointer for non-player GUIDs. Safe during lazy
  resolution since object manager is stable at that point.

- Fix isInRaid crash: validate raid roster entry pointers with
  isValidPtr before dereferencing. Offline raid members have stale
  entry pointers (value 4) that passed the != 0 check but crashed
  on deref. Same pattern worldmarkers already guards against.

- Strip name/school parameters from all 14 fire functions — no longer
  needed since resolution is deferred. Reduces per-event work to just
  storing raw IDs in the CLEU buffer.
2026-03-19 13:55:48 -07:00
MarcelineVQ 60ee3ae1d1 dpslog: fix handler table swaps not surviving relog
InitializeGameEngine re-registers all packet handlers on every login,
overwriting our swaps. The NetClient pointer may be reused so comparing
it doesn't detect re-registration. Fix: unconditionally reset swap_count
and re-install all swaps whenever InitializeGameEngine fires.
2026-03-18 18:43:40 -07:00
MarcelineVQ 34bb70dc8b dpslog: single CombatLogGetCurrentEventInfo call per event
Both DPSMate and WSBT adapters now call CombatLogGetCurrentEventInfo()
exactly once per event, unpacking all args into p1..p12 locals.
Remove redundant relevance check in WSBT profiling wrapper.
2026-03-18 17:47:53 -07:00
MarcelineVQ d84f723539 dpslog: handler table swaps, CombatLogGetCurrentEventInfo, unit flags, boolean fix
Major architectural changes:

- Migrate 12 packet handlers from JMP-patching Detours to NetClient opcode
  handler table pointer swaps. No code bytes modified — only heap pointers.
  Invisible to Warden memory scans. Hook InitializeGameEngine (0x401570,
  __thiscall) to install swaps after all handlers are registered.

- Implement CombatLogGetCurrentEventInfo() — WotLK-style lazy arg retrieval.
  Event fires with no args; addons call the function to get all fields from
  a C-side buffer. No arg count limit (bypasses ExecuteLuaCallback 19-arg cap).
  Includes unit flags, raid flags, and all suffix fields.

- Compute COMBATLOG_OBJECT_* unit flags: affiliation (MINE/PARTY/RAID/OUTSIDER),
  reaction (FRIENDLY/NEUTRAL/HOSTILE via UnitReaction), control (PLAYER/NPC),
  type (PLAYER/NPC/PET/GUARDIAN/OBJECT via SUMMONEDBY check), special (TARGET),
  and raid target markers.

- Fix boolean fields (critical/glancing/crushing): changed from %d (Lua number 0,
  which is TRUTHY) to nil/"1" via boolToLua(). Details addon was counting every
  hit as critical because it uses truthiness checks.

- SPELL_INSTAKILL now fires from SPELLLOGEXECUTE (has caster GUID).
  Standalone SMSG_SPELLINSTAKILLLOG handler is pass-through only.

- SPELL_EXTRA_ATTACKS now uses target GUID from packet (was discarded).

- SPELL_CAST_START/SUCCESS now parse spell target from packet.

- SPELL_DRAIN subevent added for instant power drain effects.

- Rename event from COMBAT_LOG_EVENT to COMBAT_LOG_EVENT_UNFILTERED.

- Update DPSMate and WSBT CLEU adapters to use CombatLogGetCurrentEventInfo().

- Remove unnecessary `or 0` guards on numeric fields (always non-nil from C).
2026-03-18 16:55:27 -07:00
MarcelineVQ fc762ac200 dpslog: CLEU rename, DPSMate absorb pipeline, WSBT adapter, module version API
- Rename COMBAT_LOG_EVENT -> COMBAT_LOG_EVENT_UNFILTERED across Zig/Lua
- DPSMate CLEU adapter: absorb pipeline (SetUnregisterVariables, Absorb,
  ConfirmAbsorbApplication, UnregisterAbsorb), BuildFail type 2/3,
  "(Periodic)" suffix, removed dead handler
- WSBT (Weird Scrolling Battle Text): CLEU adapter fork of MSBT with
  dispatch table, A/B combat profiling, selective event unregistration
- Module version API: GetWeirdUtilsVersion(name?) Lua function + WeirdUtils
  global table, additive across independent DLLs. Build system passes
  per-module version strings via build_options.
- Hook Glue_LoadScriptFunctions (0x46ABB0) for login screen availability
- Rename lsf_hook -> register_commands_hook (real name: Player_LoadScriptFunctions)
- lua.zig: add setglobal/getglobal via LUA_GLOBALSINDEX (-10001)
2026-03-18 14:20:16 -07:00
MarcelineVQ 86da3bcc03 dpslog: DPSMate CLEU adapter with per-combat A/B profiling
Adds DPSMate_CLEUAdapter.lua -- replaces DPSMate's string-parsing
CHAT_MSG_* system with structured COMBAT_LOG_EVENT data from our DLL.

Adapter maps CLEU subevents directly to DPSMate.DB API calls:
DamageDone, DamageTaken, EnemyDamage, Healing, HealingTaken,
DeathHistory, Kick, Dispels, BuildBuffs, CCBreaker, etc.
Eliminates all strfind pattern matching from the combat log path.

Toggle: /dpscleu (on/off/status)
Benchmark: /dpsbench -- always-on per-combat A/B profiling.
  Resets at combat start, reports at combat end, flips mode for next
  combat. Reports events, total ms, us/event, GC delta, and percentage
  comparison between CLEU and original modes.

Starts in CLEU mode by default.
2026-03-18 01:12:04 -07:00
MarcelineVQ 56f5c0405d dpslog: WotLK CLEU parity — overkill, overheal, spell names, unit names, GetSpellInfo
Full WotLK 3.3.5 COMBAT_LOG_EVENT_UNFILTERED layout parity:

Event structure:
- Base: subevent, sourceGUID, sourceName, destGUID, destName
- Spell prefix: spellId, spellName, spellSchool
- All suffix field orders match WotLK (blocked before absorbed, etc.)

New fields:
- overkill (-1 if alive) on all _DAMAGE events
- overheal on SPELL_HEAL and SPELL_PERIODIC_HEAL
- sourceName/destName via getNameByGUID (name cache 0x55F080)
- spellName via SpellRec+0x1E0+locale*4 (verified from SuperWoW)
- glancing/crushing as separate booleans (was packed flags)
- amountMissed field (0 — downstream hook lacks amount)

New hooks:
- ProcessStandardPowerGainMessage (0x62CA00) for SPELL_ENERGIZE with
  actual amount and powerType from SMSG_SPELLENERGIZELOG (opcode 0x151)
- Periodic energize: divide by power display factor (rage/10, happiness/1000)

Leech/drain reclassification:
- Drain Life routed through SPELL_PERIODIC_LEECH (aura 53 check in spell DB)
- SPELL_HEAL suppressed for leech spells (covered by leech event)
- Power leech (aura 64): gainMultiplier read as f32, >0 = LEECH, ==0 = DRAIN
- _LEECH/_DRAIN suffix: amount, powerType(-2=health), extraAmount

Lua API:
- GetSpellInfo(spellId) -> name, rank, icon, castTime, minRange, maxRange, spellId
  Matches WotLK returns. DBC addresses verified from nampower + Ghidra:
  SpellRange.dbc (0xC0D79C), SpellIcon.dbc (0xC0D7EC),
  SpellCastTimes.dbc (0xC0D878). SpellRec offsets from nampower struct.

Reference docs:
- WOTLK_CLEU_SPEC.md: full suffix spec from Blizzard_CombatLog.lua + Skada
- WARDEN_CONCERNS.md: hook risk analysis and remaining parity gaps
2026-03-18 00:08:42 -07:00
MarcelineVQ 76f0691540 dpslog: fix DAMAGE_SPLIT aura offset (0x178->0x16C for client Spell.dbc), fix SPELL_EXTRA_ATTACKS count, DEFLECT note, EXHAUSTED note 2026-03-17 16:02:39 -07:00
MarcelineVQ aadd467976 dpslog: SPELL_EXTRA_ATTACKS now includes count (EDX was the count all along, not unused) 2026-03-17 15:18:21 -07:00