- 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.
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).
- 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.
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
- 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.
- 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).
- 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.
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.
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.
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).
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.
- DLL_README.md: full feature description, GetSpellInfo API, module name in dev API list
- RELEASE_NOTES.md: updated DPSLog entry with WotLK parity details, removed from gaps list
- README.md: updated module table
si_ftol: 9-byte naked asm using FISTTP (SSE3 truncate-from-x87) replaces
the 39-byte FSTCW/FLDCW/FISTP rounding mode dance. 4 vs 7 cycles (1.7x).
13.2M calls/7.5s in-game -- ~13ms savings per period.
Benchmark: patch-in-place at mapped 0x40A2B0, test parity across 19 values,
best-of-5 timing with varying inputs. Framework for all silicon functions.
Also disabled h67 (ConvertPixelsToScreenAlt) probe -- game passes ECX=0
as valid input, thiscall probe crashes on null this.
callFtol: use f32 multiply instead of f64 intermediate. Parity holds --
the delta*scale product is well within f32 precision range.
fastMod: replace integer modulo (idiv, ~25 cycles) with conditional
subtract (~2 cycles) for looping animation frame computation. Falls
back to real modulo for large time skips (alt-tab, etc).
3609 cycles (-14% vs 4176 baseline), parity PASS.
findInterpIdx now returns {idx0, idx1, t} as a struct instead of writing
all three to the output buffer. Only output[0] is written for next-frame
cache persistence. All 29 call sites updated to use returned values.
3574 cycles (-14% vs 4176 baseline), was 3841 (-8%). Parity PASS.