Commit Graph

304 Commits

Author SHA1 Message Date
Dusk-92 855ea340cc Fix V8 registerFunction asm build 2026-08-28 17:39:31 +02:00
Dusk-92 17af79dff4 Fix V8 FrameScript registration ABI 2026-08-28 17:37:45 +02:00
Dusk-92 126f617ca1 Fix V8 OutlineCommand ABI to receive Lua state in ECX 2026-08-28 17:27:24 +02:00
Dusk-92 dbdb513e94 Use x86 fastcall for OutlineCommand callback 2026-08-28 17:09:38 +02:00
Dusk-92 5fe9a92672 Force Outline Lua calls through x86 register asm 2026-08-28 17:04:59 +02:00
Dusk-92 bbcc70fa0d Fix Outline Lua API calls on safe core V5 2026-08-28 16:54:46 +02:00
Dusk-92 68c0ad2b75 Use minimal standalone core for Outline CustomAssets and TransmogFix 2026-08-28 16:46:54 +02:00
Dusk-92 f4cbacb7f9 Fix DllMain return type for Zig 0.16 2026-08-28 15:12:18 +02:00
MarcelineVQ 727a4cc229 Scrub remaining absolute machine paths from module docs 2026-08-01 18:04:54 -07:00
MarcelineVQ 1d41a029a8 Scrub local machine paths from docs
Replace absolute /home/august/... references with neutral placeholders and
drop TODO.md links to plan files that only exist locally.
2026-07-27 21:49:44 -07:00
MarcelineVQ b12fc820ef Publish source: Unlicense, public README, repo hygiene
The remote was previously a distribution-only point for pre-built DLLs.
This opens the source.

- LICENSE: Unlicense, with a GPL-3.0 carve-out for src/dpslog/WeirdDPSMate
  (a DPSMate fork that keeps its own license)
- README.md replaces the stale internal one with the user-facing docs from
  DLL_README.md, swapping the 'Why No Source Code?' section for build and
  layout notes. DLL_README.md is dropped; one README now serves both.
- RELEASING.md: drop the trim-the-README-per-release dance and the
  remote/WeirdUtils/ distribution clone, both obsolete now
- gitignore agent/editor scratch, build caches, the vendored WSBT addon,
  and the WeirdThreat/uwu-logs checkouts (separate upstream repos)
- Commit outstanding module work: superweirdo, clickthrough portal visuals,
  transform44 decompiles, worldmarkers demo presets, tools/
2026-07-27 21:47:55 -07:00
MarcelineVQ f500147fc7 weirdperformance: f64-intermediate bone transform to eliminate spell/doodad z-fighting
Adds bone_sse64.zig as an f64-intermediate port of transformMatrix4x4, used as
the active hook. M2 bone matrices are built and multiplied as [16]f64 and only
narrow to f32 on final store into the bone output buffer -- matching the x87
original's rounding profile (wide intermediates, single f32 store) and keeping
M2 vertex positions aligned with the terrain/projected-texture pipeline.

Also fixes, in both bone_sse (f32) and bone_sse64:

- Pre-billboard tx/ty/tz accumulation order (row 0 = pz+px+py; rows 1/2 = pz+py+px)
- Post-billboard pos_y/pos_z accumulation order (py+pz+px)
- Post-billboard scale-recompute accumulation order (row0 + row2 + row1)
- Billboard types 2/4 normalize using f64 intermediates (load-bearing for camera
  basis vectors -- pure f32 drifted from x87 by a ULP per axis and caused
  particle emitters to jitter on camera motion)

Additional bone_sse64-specific changes:

- Local attachmentRecursion64 that recurses into transformImpl_SSE64 instead of
  bone_sse.transformImpl_SSE, so attached child models stay on the f64 path
- child_padding (this+0x84) computed with f64 intermediates

bone_sse remains the reference f32 implementation; its struct fields, inline
helpers, and section-loop fns are now `pub` so bone_sse64 can share them
(types/interpolation helpers/post-loop loops). Artifact size is unchanged.

build.zig adds bench_bone_sse64 object; src/bench/main.zig runs the new variant
through the same warmup/timing harness and prints SSE vs SSE64 vs BASELINE
cycles plus a parity check.
2026-04-16 22:58:09 -07:00
MarcelineVQ 37c96eb577 worldmarkers: revert locale encoding -- not a real issue on Windows
C runtime starts in "C" locale (dot decimals) on all platforms.
WoW doesn't call setlocale. The integer encoding was unnecessary
and would break sync with older builds.
2026-04-13 13:49:53 -07:00
MarcelineVQ 6a3812a0ab worldmarkers: locale-safe coordinate encoding, clear markers on group leave
Addon messages now encode coordinates as integers (*1000) to avoid
locale-dependent decimal separators breaking cross-client sync.

DLL detects group leave via LEADER_GUID dropping to zero and clears
all markers locally -- no addon permission checks needed.
2026-04-13 13:37:09 -07:00
MarcelineVQ 83dda7b5ae silicon_sse: fix over-cull of straddling objects in frustumCullBBox
si_frustumCullBBox (0x686000, center+radius variant) was culling any
bounding volume whose center had view-space z < 0, but an object whose
center is behind the camera can still have its front extent inside the
frustum (think of standing next to a big WMO -- the building's center
can be a few units behind you while its front wall is still in frame).

Use the bounding sphere rather than the center point: only cull when
the closest point of the sphere is itself behind the camera, i.e.
center.z + |radius| < 0. Straddling cases now fall through to the
near-plane passthrough and get rendered.

si_frustumCullBBox8 (0x686180, 8-corner variant) already does the
right thing here -- it only returns "all behind" when every transformed
corner has z < 0, which is a true convex-hull test for an AABB.
2026-04-11 13:41:34 -07:00
MarcelineVQ 27b9254ab8 weirdperformance: consolidate luastr and luavm as sub-modules
Drop the top-level luastr and luavm module flags and wire both through
weirdperformance, matching the existing luaalloc/luagc sub-module pattern.
Also removes luavm's A/B rdtsc instrumentation now that the newlstr hash
pre-check is production-only.

 - build.zig: remove luastr/luavm from module_list
 - DLL_README.md: add Lua Runtime bullet under Performance, swap
   em/en-dashes for ASCII
 - src/luavm/: delete (files moved into src/weirdperformance/ which was
   already the tracked location in HEAD)
2026-04-11 13:21:51 -07:00
MarcelineVQ 039cec1806 luagc: 5.1 incremental GC with timing, stress tests, pre-alloc hooks (BROKEN)
Current state CRASHES on load due to pre-alloc hooks with wrong calling
conventions. pushcclosure hook is still enabled with partially disabled
others. Needs all pre-alloc hooks disabled or CCs fixed before use.

Implemented:
- Full 5.1 tri-color incremental GC
- 5.1-style singlestep budget loop (replaces chunk-based approach)
- Per-step rdtsc timing (ZGCStats returns max_step_us, atomic_us)
- Configurable gcstepsize/gcstepmul/gcpause via ZGCTune()
- Pre-alloc GC hooks for 7 API functions (5.1 luaC_checkGC pattern)
- Stress test addon: /gclife, /gcsweep, /gccompare

Broken:
- Pre-alloc hooks have CC mismatches causing immediate crash on load
- pushfstring is cdecl variadic, not fastcall (removed)
- pushstring has ambiguous CC (removed, covered by pushlstring)
- pushcclosure hook still active -- may be causing the crash
- Half-initialized objects cause garbage gcptr under heavy stress

weirdperformance: re-enabled luagc.install() + luastr + luavm
2026-04-11 13:03:37 -07:00
MarcelineVQ 8d3460cf1e luagc: per-step timing, forced GC honoring, weirdperformance compat
- Per-step rdtsc timing: ZGCStats returns max_step_us and atomic_us
- AllocBench /zgcstats frame shows step/atomic timing with color coding
- /gccompare command for timing forced GC cycles
- Honor lua_setgcthreshold forced collections (collectgarbage() with low
  threshold now triggers GC instead of being silently ignored)
- Disable luaalloc in weirdperformance when luagc is active (no conflict)
- Closures go to grayagain (covers all upvalue mutation paths)
2026-04-11 10:29:39 -07:00
MarcelineVQ ce5a2408d5 luagc: complete incremental GC -- no crashes, no addon errors on /reload
Closures, threads, and protos all go to grayagain for atomic re-traversal.
This covers all upvalue/stack/compiler mutations between mark steps without
needing to hook every individual write site.

Additional fixes this round:
- LUA_TUPVAL handling in markObject (5.1 reallymarkobject pattern)
- isCleared: strings never cleared from weak tables (5.1 lstring.c:337)
- Unified cleartable matching 5.1 (key OR value cleared removes entry)
- Clear stale weak flags when metatable is NULL
- lua_replace barrier hook (0x6F32B0) for upvalue pseudo-index writes
- Compiler barrier hooks (create_constant, finish_function) -- installed
  but superseded by proto grayagain
- fullgc abandon walks all objects with makewhite before restart
- Removed old separate clearWeakValues/clearWeakKeys

CHUNK_SIZE=5000, confirmed incremental: mark=46, sweep=184 on large heaps.
No crashes or addon errors through enter world, /reload, logout/login cycles.
2026-04-11 09:51:26 -07:00
MarcelineVQ a88d1f8411 luagc: complete Lua 5.1 incremental GC -- no crashes
Full 5.1 incremental GC port with CHUNK_SIZE=5000. All crash scenarios
resolved: enter world, logout/login, /reload, /gcstress.

Compiler barriers (verified from Ghidra):
- Hook lua_parser_create_constant (0x6FD400) and
  lua_parser_finish_function (0x6FCB00)
- ECX = LexState in all callers (not FuncState)
- Proto via: LexState+0x30 -> FuncState, FuncState+0x00 -> Proto
- Barrier-back: if proto is BLACK during mark, gray + grayagain

String/upvalue resurrection:
- Hook luaS_newlstr (0x6F9D00) -- resurrect dead strings from intern
- Hook luaF_findupval (0x6F9F10) -- resurrect dead open upvalues
- Birth mark patches for strings (0x6F9DC1) and upvalues (0x6F9F4A)

Other:
- Volatile reads/writes for all foreign memory access
- Fix upvalue traversal: dereference v pointer not inline value
- Remove bootstrap (luaC_link hook covers all objects except mainthread)
- Mainthread makewhite in markroot
- Remove 5.1 removeentry from traverseTable (5.0 tables don't expect TNONE)
- Clear stale weak flags when metatable is NULL
- fullgc abandon when lua_setgcthreshold forces GC mid-cycle

Remaining: /reload causes addon errors ("attempt to call a number value").
Not a crash -- investigation needed for the specific collection difference.
2026-04-10 23:58:50 -07:00
MarcelineVQ 72627d4123 luagc: complete 5.1 incremental GC integration -- string/upval resurrection
Critical fix: hook luaS_newlstr (0x6F9D00) for dead string resurrection
during incremental sweep. When the string intern table returns an existing
string with otherwhite (dead but not yet swept), flip its white bits to
resurrect it. Without this, code gets references to strings that sweep
will free, causing hash chain crashes. Matches 5.1 lstring.c:88.

Also:
- Upvalue resurrection: hook luaF_findupval (0x6F9F10), same pattern
- Upvalue birth mark: patch 0x6F9F4A so new open upvalues get currentwhite
- Volatile reads/writes on all memory accessors (foreign memory via @ptrFromInt)
- Fix upvalue traversal: dereference v pointer (+0x08) not inline value (+0x10)
- Fix upvalue birth mark address (0x6F9F4A not 0x6F9F48 -- immediate is last byte)
- Correct hook target: luaS_newlstr does intern lookup, not lua_create_string_object

CHUNK_SIZE=5000 (true incremental). Multi-step mark cycles confirmed working.
2026-04-10 15:30:56 -07:00
MarcelineVQ 1ec97731d5 luagc: fix upvalue value read (dereference v pointer, not inline offset)
Open upvalues have v pointing to the Lua stack. Closed upvalues have v
pointing to the inline copy at upval+0x10. Reading upval+0x10 directly
was wrong for open upvalues -- gave stale/garbage data, causing
markObject to be called with invalid pointers (e.g. 0x3).

Fix: dereference upval->v at +0x08 to get the actual TValue location.
Also: volatile reads on all readU8/readU32/writeU8/writeU32 (correct
for foreign memory access via @ptrFromInt).
2026-04-10 00:21:49 -07:00
MarcelineVQ e996796d39 luagc: Lua 5.1 tri-color GC with full forward barrier coverage
Major port of Lua 5.1 incremental GC patterns:

Tri-color system:
- Two-white (WHITE0/WHITE1) with currentwhite flip in atomic phase
- Objects born currentwhite via hooked luaC_link (0x6F7B20)
- String birth mark patched to currentwhite at each flip
- isDead: otherwhite check with FIXED exception for WoW
- makewhite on survivors (preserves KEYWEAK/VALUEWEAK/FIXED)
- Bootstrap: first cycle sets all existing objects to currentwhite

Mark system (5.1 reallymarkobject/propagatemark):
- Strings: stringmark inline (no gray stack)
- Userdata: go black inline, mark metatable
- Tables: gray2black, traverse, black2gray if weak
- Threads: NEVER black, always grayagain (re-traversed in atomic)
- Closures: go black normally

Forward barriers (5.1 luaC_barrierf at every write site):
- OP_SETUPVAL: VM patch at 0x6F8A97 with naked asm trampoline
- lua_setmetatable (0x6F4020): hooked, barrier on new metatable
- lua_setupvalue (0x6F47B0): hooked, barrier grays closure
- lua_setfenv (0x6F40D0): hooked, barrier grays object

Backward barriers (5.1 luaC_barrierback):
- lua_table_set_value (0x6FA840): black2gray + grayagain
- lua_table_set_int_key (0x6FAD80): black2gray + grayagain

Atomic phase (5.1 ordering):
- propagateall, re-traverse weak tables, mark running thread,
  grayagain drain, separateudata, marktmu, cleartable, flip white

Status: enters world successfully with CHUNK_SIZE=5000 (incremental).
Crashes on UI reload (different crash pattern -- NULL+8 deref in mark,
not the old hash chain crash). Progress from "crashes on enter world"
to "crashes on UI reload."
2026-04-09 23:50:37 -07:00
MarcelineVQ 54d1b69f0e luagc: incremental GC fixes (weak tables, isAlive, grayagain, lua_close)
- Weak tables mark strong dimension (condmarkobject pattern)
- isAlive matches WoW binary (raw marked != 0)
- Write barriers use grayagain (barrier-back, prevents livelock)
- removekey sets dead keys to LUA_TNONE
- lua_close hook resets GC state before teardown
- lua_setgcthreshold hook prevents threshold stomping
- Stack nilling in traverseThread
- Sweep order: rootudata -> strings -> rootgc
- Birth mark scoped to string sweep only
2026-04-09 17:25:13 -07:00
MarcelineVQ 1ea1d6655b luagc: from-scratch incremental GC with slab allocator
Replace WoW's stop-the-world Lua 5.0 GC with a fully custom incremental
mark+sweep. The module owns both allocation (slab allocator) and collection.

Key components:
- Slab allocator (luaalloc.zig): copied from weirdperformance, stripped of
  generational age bitmaps. Hooks memory_pool_allocate + lua_gc_step.
- Incremental mark: tri-color with gray stack, write barriers on table writes.
  Correctly handles weak table strong/weak dimensions (condmarkobject).
- From-scratch sweep: cursor-based rootgc, rootudata, chunked string buckets.
  Sweep order matches native (rootudata -> strings -> rootgc).
- Weak table detection: scans metatable for __mode, sets KEYWEAK/VALUEWEAK.
- Weak clearing: removekey semantics (nil value + TNONE dead keys).
- Birth mark scoped to string sweep only (rootgc objects prepend to head).
- Stack nilling: traverseThread nils slots above L->top matching native.
- Hooks lua_setgcthreshold to prevent external threshold stomping.

Native functions retained: lua_gc_free_object (type dispatch), luaCallUserDataGC
(__gc finalizers), luaC_separateudata (dead udata separation).
2026-04-09 16:34:16 -07:00
MarcelineVQ cdc3240756 luagc: generational machinery (write barrier + age bitmap + minor/major cycles)
Adds the infrastructure for generational GC on top of the incremental sweep:

- luaalloc: per-page age bitmap (1 bit per slot) lazily allocated with each
  slab page. Public isOld/setOld/setYoung/clearAllAges API. Segment-indexed
  for O(1) lookup in the write barrier.

- luagc: write barrier via Detour on lua_table_set_value. Records touched
  old tables in a 4096-entry set. Pure bitmap read on every table write.

- luagc: minor/major cycle distinction. First collection, touched overflow,
  and every 32nd minor are forced to major. Major clears the age bitmap and
  touched set; minor preserves both. cycleFinish repopulates the bitmap by
  walking rootgc after a full sweep completes.

Both cycles still run lua_gc_full_collection for now -- the custom minor
mark that actually skips untouched old objects is the next layer.

Previous crash investigations proved Detours on lua_table_set_value are
safe; earlier failures were from simultaneous marked-byte modifications,
not the Detour itself.
2026-04-08 08:37:40 -07:00
MarcelineVQ d6711901df multi-module cleanup: daily logs, luaalloc enable, minimap texture fix
- logsessions: switch from timestamped per-session files to daily rotation
  (WoWCombatLog_YYYY_MM_DD.txt), remove path pointer overwrites, persist
  paths across logout so redirects keep working
- logging: add append file mode (openAppend) for daily log rotation
- minimapicons: clear texture binding after blip render to fix stale
  texture with Silicon d3d9 layer
- weirdperformance: enable luaalloc slab allocator (was disabled for testing)
- worldmarkers: extract FN_SET_UNIT_POSITION to offsets, use lua.typeOf
  helper, update doc comments for renamed API
- delete unused guidcache standalone test module
2026-04-06 17:51:29 -07:00
MarcelineVQ 49f3f2452c fix: move CheckFileExistence gate NOPs to core file hooks
File_FindInArchive has two conditional jumps that skip calling
CheckFileExistence. Without NOPing them, preloadFileWithFlags
never reaches our hook and the game skips Bindings.xml loading
for embedded addons. This was previously only done by the
customassets module, so standalone variant DLLs (without
customassets) failed to load addon keybindings.
2026-04-06 17:42:32 -07:00
MarcelineVQ 5f33944fda luavm: strip to newlstr-only, add Detour overhead bench
A/B results: hash_lookup prefetch/cache both regressed (original is
near-optimal at 59 bytes), VM opcode SSE2 patches were break-even.
Only luaS_newlstr hash pre-check shows consistent 40-45% per-call win.

Drop hash_lookup hook, VM jump table patches, and resize hook. Keep
newlstr Detour with per-call A/B rdtsc and OnWorldUpdate periodic dump.

Add GC_WRITE_BARRIER.md documenting the barrier globals at 0xCEEAC0/C4
found in lua_vm_execute (useful for luagc module).

bench: add Detour overhead micro-benchmark. Simulates zhook's
JMP+trampoline mechanism on mmap'd executable pages. Result: 5 cyc/call
overhead -- negligible vs the ~100 cyc/call newlstr savings.
2026-04-06 16:04:02 -07:00
MarcelineVQ f58c100bf5 luavm: new module targeting top 3 Lua VM hotspots (4.5% CPU combined)
Three hooks from perf profiling (34M samples):
- lua_table_get_hash_element (1.65%): prefetch next chain node
- luaS_newlstr (1.35%): hash pre-check before memcmp (Lua 5.0->5.1 fix)
- lua_vm_execute (1.50%): jump table patches for MOVE (MOVDQU),
  ADD/SUB/MUL/DIV (SSE2 replacing x87)

Default off (-Dluavm=true to enable). Arithmetic slow path verified
against disasm: __fastcall(ECX=L, EDX=R(A), stack: opB, opC, tm_id),
callee cleans (RET 0xC).
2026-04-06 01:11:11 -07:00
MarcelineVQ c600050d87 interact: add Loot Corpse binding (single-corpse loot mode)
LootAllCorpses now accepts an optional count argument to cap the queue.
LootAllCorpses(1) loots the nearest corpse and stops.
2026-04-06 00:57:07 -07:00
MarcelineVQ d1e2455fed luagc: working incremental sweep via list truncation (5s -> 120ms worst)
Rootgc sweep chunked by temporarily NULLing a next pointer and calling
the original lua_gc_remove_objects on the truncated sublist. Swept
survivors are detached to a separate list to prevent re-sweeping.
Lists reconnected after final chunk.

Birth-mark via binary patch of luaC_link immediate byte (0x6F7B37)
ensures new objects born during sweep survive.

Profiling shows sweep chunks at 0-9ms each (was 225ms avg, 5s worst).
Remaining bottleneck: atomic mark (80ms) + udata/string sweep (44-92ms).
2026-04-05 11:42:21 -07:00
MarcelineVQ 4e0a1934fb luagc: incremental GC module (disabled), realistic AllocBench
Incremental GC: atomic mark + batched rootgc sweep. Crashes from
objects born white during sweep -- needs birth-mark barrier fix.
Link hook (luaC_link) calling convention verified but interaction
with sweep_ptr at list head needs solving. Disabled pending fix.

AllocBench: realistic addon-like data structures (combat events,
player damage breakdowns with metatables, aura trackers with
closures). Cross-references shared spell/unit caches. These
complex structures reveal GC as the true stutter source -- simple
flat objects don't trigger meaningful GC pauses.

Removed arena pre-reservation (was fragmenting 32-bit address space).
2026-04-05 10:35:24 -07:00
MarcelineVQ deaeaa1450 luaalloc: profile-tuned size classes, 84MB -> 35MB waste reduction
Profiled 67M Lua allocations to find hot sizes. Lua table hash nodes
are 40 bytes, so hash tables produce allocs at 80, 160, 320, 640,
1280, 2560 (2..64 nodes). Added classes at these exact sizes.

Fixed size class LUT: was 16-byte granularity (size 22 mapped to
class 32 instead of 24). Now direct 1:1 lookup table, 4KB, one
byte load per alloc with zero computation.

Other changes:
- Removed pool_ctx==0 passthrough and seg_val==0 fallback (dead code)
- Removed pool_ctx param from slabFree/slabRealloc
- Added optional PROFILE mode with size histogram dump to log file
- Added AllocBench addon (/allocbench) for in-game benchmarking
2026-04-05 00:25:59 -07:00
MarcelineVQ f213f9b617 perf: move luaalloc into weirdperformance, wire clip SSE hook (1.9x)
- luaalloc moved from standalone module to weirdperformance sub-module
- ClipPolygonToSinglePlane SSE hook wired up (410->206 cyc, 2.55% CPU)
- Eliminated calling convention wrappers: clip_sse (fastcall),
  bone_sse (thiscall) match hook conventions directly
2026-04-04 22:39:17 -07:00
MarcelineVQ 21905799c5 perf: SSE frustum culling -- AABB test, 8-corner occlusion, behind-camera fix
Hook 0x686940 (testAABBFrustum): SSE center/extent P-vertex method replaces
x87 sign-bit corner selection. ~160M cycles in profile, 50% rejection rate.

Hook 0x686180 (FrustumCullBoundingBox 8-corner): SSE replacement transforms
all 8 AABB corners through view-proj, horizon buffer scan with 4-wide test.

Fix behind-camera bug in both FrustumCullBoundingBox variants (0x686000,
0x686180): original returned 0 for behind-camera objects, callers interpret
0 as "visible, render it". Now returns 2 (occluded) when all geometry is
behind the camera (Z < 0 in clip space).
2026-04-04 18:59:06 -07:00
MarcelineVQ 0a37b1096e luaalloc: segment-table lookup, VirtualAlloc pages, 1560ms (was 2000ms)
Replace 4-byte per-allocation header with 64KB segment table for O(1)
class lookup. VirtualAlloc guarantees 64KB-aligned pages, so ptr>>16
maps directly to the class index. Zero per-allocation overhead.

- VirtualAlloc for slab pages (guaranteed 64KB alignment)
- VirtualAlloc for large allocs (>4096) with size+magic header
- pool_ctx==0 passthrough for non-Lua callers
2026-04-04 18:09:36 -07:00
MarcelineVQ 1cae8c9781 luaalloc: pure Zig slab allocator replacing WoW's 6-class pool
WoW's memory_pool_allocate (0x6FAE90) does O(classes * pages) linear
scan on every free/realloc to find which pool owns a pointer. Our slab
stores slot size in a 4-byte header for O(1) lookup.

Baseline 2000ms -> testing with allocator enabled next.

- 15 size classes (16-4096) vs WoW's 6 (16-256)
- @memcpy for cross-class realloc (WoW uses manual dword loop)
- Large allocs (>4092 usable) fall through to game heap
- No C dependencies (replaces mimalloc which couldn't cross-compile)
2026-04-04 17:31:08 -07:00
MarcelineVQ b58234f176 clickthrough: filter non-interactable NPCs, skip cascade in GM mode
NPC priority pass now whitelists standard vanilla interaction flags
(0x7FFF: gossip through repair) instead of treating any non-zero
npc_flags as interactable. Fixes void zones and visual-effect NPCs
(e.g. C'Thun Portal, npc_flags=0x2000000) blocking player selection.

Cascade raycast disabled entirely in GM mode (PLAYER_FLAGS_GM) so
GMs get unfiltered targeting.
2026-04-04 10:56:32 -07:00
MarcelineVQ 7a32d81fbb fix: allow multiple variant DLLs to coexist (fixes #7, fixes #4)
Remove the core mutex that prevented secondary DLLs from installing
shared infrastructure hooks (Lua registration, file serving, engine
init/shutdown). zhook already has explicit E9-chain detection -- each
DLL's trampoline chains to the previous DLL's detour, and per-module
mutexes still prevent duplicate module hooks. DLL_PROCESS_DETACH fires
in reverse load order so detach unwinds correctly.
2026-04-01 13:58:38 -07:00
MarcelineVQ 5e0b8c768c fix: remove filecache hook on shutdown to prevent SGroupPtr crash
weirdperformance's filecache hook (File_FindInArchive) stayed active
during game teardown, returning stale archive/block pointers after
Storm freed its MPQ archives. This corrupted heap metadata, causing
ERROR #124 (SGroupPtr invalid block) on game close.

Set remove_on_shutdown=true so the hook is detached during
logoutDetour before Storm archive teardown begins.

Also wires up superweirdo module and clickthrough lateInit.
2026-03-31 21:25:14 -07:00
MarcelineVQ 96687bfaaa clickthrough: block unusable player-summoned portals and rituals
Filter ritual (type 18) and mage portal (type 22) GOs whose creator
is a player not in the local player's party or raid. Completely
unclickable, not just deprioritized.

Also:
- Add wow.isInGroup() shared group membership check (party + raid)
- Add party/raid addresses to shared offsets.zig
- Fix dpslog party member GUID address (was 0xBC7600, correct: 0xBC6F48)
  Verified from client's is_player_in_allowed_list @ 0x4e7f70
2026-03-28 11:42:38 -07:00
MarcelineVQ db675c7a7e fix: MSVC ABI, heap allocator, deferred timer - vanillafixes compat
- Restore MSVC ABI (was accidentally GNU since v0.6.0, broke .CRT section)
- Replace game allocator with Windows process heap for filecache and
  libdeflate malloc/free - game allocator not initialized during DllMain
  when injected via CreateRemoteThread
- Defer timer calibration (Sleep 500ms) to lateInit - blocks under
  loader lock during DllMain
- Remove exported malloc/free symbols from DLL
- Eliminate addObject compilation units for SSE files - direct @import
  with AVX target instead
- Heap-allocate filecache (was 9.3MB static BSS)
- Strip transform44 of performance/ externs, pure profiling only
- Rename performance/ to weirdperformance/ to match module convention
- Skip default-off modules in all-variants build step
- Remove dead debug vars and stride logging from particle_sse
2026-03-28 05:31:31 -07:00
MarcelineVQ dd745e9728 fix: guard getObjectByGUID against NULL object manager
Crash during world teardown when minimap hooks call into WoW's
FindObjectByGUID while the object manager at 0xB41414 is already NULL.
2026-03-26 23:10:35 -07:00
MarcelineVQ 14ba112b0d perf: fix deferred divide precision, threadlocal TLS, MSVC target
Removed deferred divide from both ray-tri functions -- the det-scaled
epsilon comparisons lose precision for near-parallel rays, potentially
accepting triangles the original rejects. Downstream SetupBoxFrustum
then writes to wrong globals near 0xCE6738 (SGroupPtr), causing
ERROR #124 on exit.

inflate_hook: replaced manual FS:0x24 thread ID pool with Zig native
threadlocal. Fixes potential crash on Wine where FS segment layout
may differ.

Build: switched from GNU to MSVC ABI (4-5K smaller per DLL, no
.eh_frame unwind tables). Added setjmp.h stub for libdeflate MSVC
build. Added noperf build variant (zig build noperf).
2026-03-26 11:38:33 -07:00
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