- 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
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()
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)
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.
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.
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.
- 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