Commit Graph

37 Commits

Author SHA1 Message Date
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 bad3126973 build: enable SSE4.1+FMA+AVX for silicon_sse compilation unit
Was compiling with baseline SSE2 only. Now matches bone_sse target.
Free wins: packParticleColor 1.2x->4.6x, rotateMatByQuat 3.4x->4.0x,
normalizeVec3 1.1x->1.8x, mulMat3x4InPlace 1.4x->1.7x.
2026-03-17 00:27:48 -07:00
MarcelineVQ 4ed5495219 bench: dual BASELINE/SSE with parity check — 2177 vs 2112 cycles, PASS 2026-03-16 12:10:51 -07:00
MarcelineVQ 93100a1a7e bench: add transform44 SSE benchmark — 288 cycles/call baseline (8 bones, 4 animated) 2026-03-16 11:30:06 -07:00
MarcelineVQ 5d41cd03a3 bone_sse: V4 FMA matmul, enable SSE4.1+FMA+AVX target 2026-03-16 10:54:25 -07:00
MarcelineVQ 008db88403 bone_sse: replace matMul/ftol/vec3SqMag with pure Zig, fix visual artifacts
Root cause of billboard visual artifacts: callVec3SqMag used inline asm
to call game's x87 vec3SqMag (0x4549F0) with fstps to capture ST0.
With SSE2 codegen, the x87/SSE state interaction caused corrupted float
values in billboard bone matrices (mat[0][2] wildly wrong).

Replaced with pure Zig: x*x + y*y + z*z — no x87, no inline asm.

Also replaced:
- matMul (0x74A7C0): pure Zig f64 scalar matmul, no alignment needs
- callFtol (0x40A2B0): f64 intermediate + @intFromFloat (cvttsd2si)

Architecture: bone_sse.zig is REF code compiled with SSE2, called as
cdecl from thiscall wrapper in transform44.zig (cross-object to prevent
LLVM inlining AND ESP alignment into thiscall frame).

A/B: other hooks gated behind AB_OTHER_HOOKS=false for isolated testing.
2026-03-16 10:10:02 -07:00
MarcelineVQ 3a031803ef bone_sse: pure Zig SSE/FMA reimplementation, zero game function calls
Replace bone_sse.zig with a complete pure Zig implementation compiled
with SSE4.1 + FMA + AVX. All 18 game function calls replaced:

- findInterpIdx (0x713D50): temporal-coherence keyframe search
- interpAnimKF (0x713EA0): CompQuat lerp for rotation keyframes
- extractByte (0x71AE90): byte keyframe extraction
- getInterpolatedFloat (0x71AF20): float track with direct blend read
- callFtol (0x40A2B0): @intFromFloat replaces x87 __ftol
- callVec3SqMag (0x4549F0): inline FMA dot product
- callGetIndexOffset/callSetShortValue (0x71AFF0/0x71B010): direct ri16
- matMul (0x74A7C0): V4 FMA matmul (broadcast + 3 @mulAdd per row)
- buildRotFn (0x74B6B5): inline quat→matrix
- rotateQuat (0x7BDDB0): quat→matrix then FMA matmul
- scaleMat (0x7BDCA0): inline scale from vec3 ptr
- applyTrans (0x7BDC40): inline FMA dot product translation

Only 2 game calls remain:
- 0x409AEF: one-time atexit init (boneKeyframeLoop)
- 0x7B5F60: IsParticleBufferEmpty (reads game particle state)

Child recursion calls transformMatrix4x4_SSE directly instead of
going through the hook at 0x714260.

Detour cleaned up: REF is baseline, SSE activates via ab_use_custom
toggle. Diagnostic/bisect/FPU-comparison scaffolding removed.
build.zig: bone_sse gets dedicated target with sse4_1+fma+avx features.
2026-03-15 18:16:07 -07:00
MarcelineVQ 36ce1a05ce bone_sse_ref: fix M2 black screen — 5 bugs found via asm comparison
Assembly-level comparison of compiled REF against original 0x714260 revealed:

1. Billboard cross product sign error (types 0x10/0x20): computed +cross
   instead of -cross for components 0/1, corrupting billboard bone matrices
2. colorAnimLoop wrong count field: read model_hdr+0x6C instead of +0x64
3. colorAnimLoop wrong gate offset: checked anim_data+0x04 instead of +0x0C
4. Timestamp delta guard inverted: REF guarded on cur_ts!=0 and always
   wrote to this+0x4C; original guards on this+0x4C!=0 first and never
   seeds the field (something else initializes it)
5. Section 5 emitter_ctx cached instead of re-read after matMul call

Also: build REF with x87-only target (subtract SSE/SSE2 features) to
match original's FLD/FMUL/FSTP codegen, and use callVec3SqMag for all
magnitude computations instead of inline SSE math.

Remaining known issues (not yet fixed):
- texAnimLoop alpha track missing crossfade blend
- colorAnimLoop missing crossfade blend
- Missing word animation section (model_hdr+0x6C/0x70)
- Bisect infrastructure and diagnostic code still present (test scaffolding)
2026-03-15 15:04:05 -07:00
MarcelineVQ 55b4931fcb bench: map WoW PE sections for full-fidelity benchmarking, add silicon SSE
Major bench harness upgrade:
- Maps WoW .text (4MB) and .rdata (160KB) at original virtual addresses
  instead of individual function byte arrays. All CALL targets and float
  constants resolve automatically -- no more manual mapGameConstants().
- Bench binary linked at 0x10000000 to avoid address conflict with WoW
  PE sections at 0x400000-0xD00000.

Added silicon_sse.zig: 18 pure math functions extracted from silicon.zig
as export fn (C ABI) for standalone compilation. Covers frustum culling,
bounding volume ops, quaternion slerp, matrix multiplies, trig, etc.

Silicon benchmark results (all 14 new entries pass correctness):
  checkBoxLineIntersect: 3.2x (72->22)  -- slab AABB intersection
  rotateMatByQuat:       3.1x (172->54) -- quat->mat + mat multiply
  quatSlerp:             2.5x (454->178)
  createZRotMat3x3:      2.5x (140->55)
  createRotMat3x4:       2.2x (163->73)
  normalizeVec3InPlace:  1.8x (34->18)
  mulMat3x4InPlace:      1.6x (106->66) -- MISMATCH (layout diff, needs investigation)
  classifyPointFrustum:  1.5x (60->40)
  mulMat3x4:             1.2x (64->52)  -- MISMATCH (same layout issue)

Two MISMATCH entries on mat3x4 multiply -- likely row/column order
difference between original and our implementation. Correctness needs
verification against game behavior.
2026-03-15 12:04:02 -07:00
MarcelineVQ da7155a404 bone_sse: fix ribbon emitter offsets (#18-19), teardown guard
Bug #18: Ribbon emitter track offsets completely wrong. Position was
entry+0x24, actual tracks from assembly (0x716402-0x716AA9):
  Track 1 (Vec3): gate=+0x1C, AnimData=+0x10, output=+0x00
  Track 2 (Vec3): gate=+0x38, AnimData=+0x2C, output=+0x30
  Track 3 (float): gate=+0x70, AnimData=+0x64, output=+0x80
  Track 4 (Vec3): gate=+0x54, AnimData=+0x48, output=+0x50

Bug #19: Track 4 output was +0xA0 (should be +0x50), and tracks 2/4
were float (should be Vec3). Wrong output offsets corrupted stack data,
causing bone_rt pointer to contain float bit patterns.

Teardown: hook World_HandleLogoutCleanup (0x491180) instead of
CleanupWorldAndEntities (0x66FC40). Fires at START of logout sequence
before any Lua callbacks trigger model processing on freed data.
Prologue: PUSH ESI/EDI, epilogue: POP EDI/ESI, JMP (tail call).

Also: added bone_sse_reference.zig as separate compilation unit for
A/B testing the proven-working version independently.
2026-03-15 02:22:18 -07:00
MarcelineVQ 3c9a95d51e ssemaths: extract UnitXP math polyfill hooks into standalone module
Moved math_sse.zig and all 17 hook declarations + CriticalSection spin
count optimization from transform44 into new ssemaths module. Off by
default (-Dssemaths=true to enable).

transform44 retains its profiling hooks and blit_hub optimization.
ssemaths is a clean standalone module with its own mutex, install/remove
lifecycle, and lateInit for post-UnitXP hook clobbering.

Added performance note to math_sse.zig documenting that hook-based
replacement adds ~5-8 cycles overhead that makes small functions slower,
and that in-place patching is the path to realize the full 2-4x gains
shown in inlined benchmarks.
2026-03-14 22:28:31 -07:00
MarcelineVQ db28746182 bench: add x86 Linux micro-benchmark harness for math_sse functions
Extracts original x87 FPU bytes from WoW.exe via Ghidra, mmaps them
executable, and benchmarks against our SSE replacements. Covers all 17
UnitXP polyfill functions with correctness validation and cycle counts.

Maps a page at 0x7ff000 for the float 1.0 constant referenced by
rotMat3x3/rotMat4x4/planeNormal via absolute address 0x7ff9d8.

Build: zig build bench / zig build run-bench
2026-03-14 19:29:41 -07:00
MarcelineVQ 2b9b5bc043 bone_sse: assembly-verified reimplementation of transformMatrix4x4
13 bugs fixed by comparing against full assembly dump (5317 instructions):
- Emitter check: this+0x188 -> this+0x1D8
- Animation time: added FILD*time_scale pattern for both primary (+0xB0)
  and secondary (+0xDC) slots
- Conditional multiply: bone_local *= *(bone_rt+0xF0) was missing
- Billboard post-processing: 4 switch cases (types 8/16/32/64) implemented
- Color animation loop bound: model_hdr+0x64 -> +0x6C
- Bone keyframe data stride: 0x24 -> 0x54
- Ribbon emitter output stride: 0x15C -> 0x170
- Particle data/output strides: 0x1FC/0x17C -> 0x1F8/0x16C
- Child SceneObject offsets: attach_idx +0x184->+0x1D4, next +0x190->+0x1E4
- Root bone parent: identity -> this+0xFC

New files:
- BONE_SSE_PROGRESS.md: section-by-section verification status
- t44_full_asm.txt: complete function assembly (ground truth)
- t44_helpers_asm.txt: all 12 helper function assemblies
- math_sse.zig: 18 x87->SSE polyfill stubs (VanillaFixes integration)

Also: OnWorldUpdate hook for true per-frame counting, DUMP_FRAMES=450.
SSE dispatch currently disabled while particle sections are being verified.
2026-03-14 17:34:37 -07:00
MarcelineVQ 692a02ed2c Move file cache to standalone module, add timer fix, fix refcount crashes
File cache (filecache module):
- Moved from transform44 sub-module to standalone src/filecache/
- 2-way set-associative cache (32768 sets x 2 ways) with FNV-1a hash + finalizer
- Fixed negative cache hit crash: zero output params before returning 0
  (FindFileInArchive reuses filename slot for out_outer_archive)
- Fixed path 2 crash: set out_outer_archive on all cache hit paths
- Fixed stale block_entry crash: cache block index instead of raw pointer,
  recompute from archive+0x290 on each hit
- Fixed archive-freed crash: use game's FindAndIncrementResourceReference
  (0x650780) instead of manual +0x38 increment -- validates archive is alive
- Periodic stats dump with projected time savings (hit=~1000cy vs miss=~30000cy)

Timer fix (transform44 sub-module, ported from VanillaFixes):
- TSC calibration via QPC reference over 500ms
- Enables TSC mode if game was using GetTickCount fallback
- NtSetTimerResolution for 0.5ms OS timer granularity
- SetProcessInformation to disable Windows 11 power throttling
- Always-on (no A/B toggle -- no measurable impact on Wine/Linux)
2026-03-14 14:57:58 -07:00
MarcelineVQ 55735d7b9e Add MPQ archive file cache: skip redundant chain walks on repeat file opens
Hook File_FindInArchive (0x6549a0) with a direct-mapped filename-verified
cache. First open does the full MPQ chain walk (~60K cycles), subsequent
opens hit the cache (~300 cycles). 80% hit rate in gameplay testing.

Cache design: 16384 entries, FNV-1a hash for slot index, raw filename
comparison (128 bytes) for collision safety. Stores outer_archive,
inner_archive, and block_entry per file. Negative cache for not-found files.
Refcount at +0x38 incremented on all output archives to match original
File_FindInArchive behavior (verified via Ghidra: FindAndIncrementResourceReference
at 0x650780, DecrementResourceReference at 0x6507e0).

Also: default build changed to ReleaseFast (works around Zig fastcall inreg
bug in Debug mode), logging gate changed to != ReleaseSmall, file cache
integrated as transform44 sub-module with A/B comparison timing in readout.
2026-03-13 23:05:38 -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 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 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 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 541b9c97f0 Rename pngscreenshot to pngscreenshots 2026-03-08 22:09:38 -07:00
MarcelineVQ 2c4132ead7 Rename screenshot module to pngscreenshot
Less generic DLL name for distribution.
2026-03-08 15:48:16 -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
MarcelineVQ 528df27780 Add minimap tracking dropdown with Wrath-style NPC icons
Take over native MiniMapTrackingFrame to show a tracking spell
dropdown (Hunter Track X, Sense Undead/Demons, Find Herbs/Minerals)
plus NPC tracking categories with icons extracted from the 3.3.5
client (Auctioneer, Flight Master, Mailbox, Repair, etc.).
2026-03-07 17:20:43 -08:00
MarcelineVQ 4f195c248f Auto-embed addon and asset files at compile time
build.zig scans module addon/ and assets/ directories, passes file
lists as build options. main.zig uses comptime helpers to @embedFile
each path and build the AddonPrefix table automatically. Adding or
removing files no longer requires editing main.zig.

Also renames markers addon files to match WoW addon name
(Markers.toc → WorldMarkers.toc, Markers.lua → WorldMarkers.lua)
and auto-generates loadAddonsDetour from the same module metadata.
2026-03-07 13:13:49 -08:00
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
MarcelineVQ 0783f3b0dd Remove redundant full variant from all-variants build
weirdutils.dll already serves this purpose.
2026-03-05 11:21:41 -08:00
MarcelineVQ 00749d5745 Add bigcursor module stub, rename combatlog to logsessions, bump session timer to 60min
- New bigcursor module skeleton with build integration and mutex
- Rename combatlog module to logsessions (directory, files, build options,
  imports, console prefixes, mutex name, DLL variant, docs)
- Increase log session continuation threshold from 30 to 60 minutes
- Update DLL_README log sessions section
2026-03-04 15:14:04 -08:00
MarcelineVQ 4af033d01d Rename dataassets→customassets, Markers→WorldMarkers, prefix all mutexes
- dataassets module renamed to customassets everywhere (build flag,
  source, DLL variant name, docs)
- Markers addon renamed to WorldMarkers (addon path, .toc, .lua,
  Bindings.xml header, Lua globals, debug log prefix, mutex name)
- All 9 module mutexes now use WeirdUtils_ prefix to avoid
  collisions with other DLLs in the same process
2026-03-03 10:26:17 -08:00
MarcelineVQ c00ea75d59 Rename looseassets module to dataassets 2026-03-02 23:55:26 -08:00
MarcelineVQ c04680788d Fix release-mode crashes: inline asm register clobbers and fastcall ABI
Root cause: hook.fastcall used "r" constraints + explicit MOV to set
ECX/EDX. LLVM can allocate "r" inputs to clobbered registers, causing
cross-assignment (ecx_in→EDX, edx_in→ECX) or function address stomping
when func lands in ECX/EDX. Debug works by luck (trivial regalloc);
Release optimizes aggressively and hits the conflicts.

Fix: explicit "{ecx}", "{edx}", "{eax}" register constraints in zhook
fastcall — compiler places values directly, no MOV needed, no ambiguity.

Also fix 9 inline asm blocks across main.zig, interact.zig,
screenshot.zig, markers.zig missing ECX/EDX clobbers after CALL
instructions. Without clobbers the optimizer assumes registers retain
input values after the call — stale reuse in release builds.

Other changes in this commit:
- Rename markers→worldmarkers (build flag, DLL, Lua table)
- Rename assetfix→looseassets
- lua.zig: add .never_tail to pushcclosure, pcall, openlib, pushnumber
- Move internal marker functions into WorldMarkers Lua table via openlib
- Remove unused GetCurrentAreaId function
- Fix cleanup_file_handle_hook.original() → .callOriginal()
2026-03-02 23:38:04 -08:00
MarcelineVQ 475070e910 Fix marker crash on logout and add module lifecycle table
The marker cleanup hook on CleanupWorldAndEntities was never installed —
markers.installHooks() was missing from install() in main.zig. Entities
created via WorldMarker were never cleaned up before the game's atexit
handler iterated the hash table over freed heap memory.

Key changes:
- Add markers.installHooks() call (the actual crash fix)
- Replace manual install/uninstall/shutdown lists with a single modules
  table that drives all three phases — prevents this class of bug
- Gate marker Lua functions, addon, and keybindings behind isActive()
  so they're skipped when another DLL owns the hooks
- Add world_cleanup_hook.detach() to removeHooks() (was missing)
- Migrate from vendored libs/hook to external zhook dependency
- Unify installHooks return types to void across all modules
- Add diagnostic logging to marker cleanup (temporary, for testing)
2026-03-02 07:34:18 -08:00
MarcelineVQ 2cca8f4b53 Add assetfix, transmogfix, minimapicons modules; fix assetfix disk-vs-MPQ priority
Assetfix: hook CheckFileExistence to serve loose Data\ files. The original
flags|1 approach failed because game paths contain backslashes, causing
CheckFileExistence to skip BuildFilePath and check the raw path (no Data\
prefix). Fix: write the correct Data\-prefixed disk path to the output buffer
directly and return 1, bypassing the original function for hash map hits.
This preserves hook chaining (filename argument is never transformed).

Also adds transmogfix (transmog update coalescing), minimapicons (stub),
new build options for all three modules, mutex-based multi-DLL safety,
embed .skin data into .m2 models, and various module improvements.
2026-02-28 14:07:53 -08:00
MarcelineVQ a8ebe21b0d Add hook 5 (loadModelFromFileAsync), combatlog stub, framecrash vtable hooks, marker assets
Hook 5 intercepts loadModelFromFileAsync (0x71d4e0) to synchronously load M2
model data for fake in-memory file contexts. processLoadedModelData returns 1
and entities are created, but file context cleanup is currently skipped (leaks
0x60 bytes per load) due to a crash in the cleanup path, and there's a later
EIP=0 crash during the game main loop that needs investigation.

Also adds: combatlog module stub, framecrash anchor vtable hooks (GetRelativeTo
and GetWidth/GetHeight crash guards), embedded Raid_UI_FX model assets with
skins and textures, WU_XYZ debug model.
2026-02-27 16:47:42 -08:00
MarcelineVQ 37d42d09c2 Add markers module, framecrash stub, debug console, build-flag wiring
Markers: client-side world object system using CreateGameObject. Places
M2 models at arbitrary world positions via Lua commands (/mark test,
/mark pos). Includes embedded addon, xyz.m2/blp assets served from DLL
memory, position helpers from unit movement struct, and object lifecycle
management (create, cleanup, reposition, alpha, animation).

Framecrash: stub module with reference to crash at 0x007A2452.

Console: debug output via AllocConsole/WriteConsoleA, compiles out
entirely in non-Debug builds. Used by markers and file serve logging.

Build: markers added to feature flag matrix and all-variants step.
Main: conditional markers import, Lua function registration, embedded
addon + asset file serving, console init/deinit lifecycle.

Outline README: added misc planned features and debug mode notes.
2026-02-26 15:30:21 -08:00
MarcelineVQ cd7e585412 Restructure modules with per-module addon subdirs
- Each module (outline, interact, screenshot) now has its own addon/
  subdir with .toc, .lua, and Bindings.xml
- Core WeirdUtils addon lives in src/core/addon/
- build.zig supports compile-time feature gating via -D options
- main.zig uses build_options for conditional imports and addon embedding
- Module addons only load when their module is compiled in
- 'zig build all-variants' produces full.dll + 3 single-module DLLs
2026-02-25 19:15:08 -08:00
MarcelineVQ b7f293c8c5 Initial commit: WeirdUtils DLL for WoW 1.12.1
Lua protection bypass, embedded addon loading, async PNG screenshots
with self-contained deflate compressor (store + fixed Huffman).
15KB ReleaseSmall.
2026-02-23 16:02:55 -08:00