Files
WeirdUtils/docs/outline-validation.md
T
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

85 lines
3.8 KiB
Markdown

# Outline Validation Checklist
## Build
- [ ] `zig build` succeeds with no errors (x86 windows-msvc target)
- [ ] Output DLL present at `zig-out/lib/weirdutils.dll`
## Existing Feature Regression
- [ ] DLL loads without crash (inject into WoW 1.12.1)
- [ ] `/wu version` responds correctly
- [ ] `/wu test` calls C function and returns string
- [ ] Screenshot hook works (`/wu ss`, PNG output)
- [ ] Interact/loot bindings work (InteractNearest, LootAllCorpses)
- [ ] Addon loads on login (green "WeirdUtils loaded" message)
## Outline Subsystem
### Commands
- [ ] `/wu outline` shows ON/OFF status
- [ ] `/wu outline on` enables outlines
- [ ] `/wu outline off` disables outlines
- [ ] `/wu` help text includes outline commands
### Dead Player Outlines
- [ ] Dead friendly players in party/raid show cyan outline
- [ ] Outline is visible through walls (no depth test)
- [ ] Outline disappears when player is resurrected
- [ ] Skeleton corpses are NOT outlined
### Raid Mark Outlines
- [ ] Units with raid icons (Star through Skull) show coloured outlines
- [ ] Each icon has a distinct colour
- [ ] Outlines update when raid marks change
- [ ] Outlines respect terrain occlusion (depth test enabled)
### Target Outline
- [ ] Current target shows golden amber outline
- [ ] Outline changes when target changes
- [ ] Outline clears when target is deselected
- [ ] Outline respects terrain occlusion
### Rendering Quality
- [ ] Outlines are clean (no jagged edges or flicker)
- [ ] Outline thickness is consistent across distances
- [ ] Normal model renders correctly on top of outline
- [ ] No visible render state leakage to other models
- [ ] Non-outlined units don't cover outline pixels (stencil test)
### Performance
- [ ] No noticeable FPS drop in normal gameplay
- [ ] No FPS drop in 40-player raid with multiple outlines
- [ ] Frame rate stable when toggling outlines on/off
### Edge Cases
- [ ] D3DX DLL not present → outlines gracefully disabled (no crash)
- [ ] No targets tracked → zero overhead (fast path)
- [ ] `/wu outline off` → DIP hook passes through immediately
- [ ] Device Reset (resolution change) → shaders recreated properly
## Hook Prologue Verification (Ghidra)
Verified 2026-02-23 using Ghidra MCP against WoW.exe 1.12.1 (build 5875, 4,907,008 bytes).
### Method
Raw bytes read from each hook target address via `get_bytes`. Instruction boundaries decoded to confirm the `prologue_size` parameter passed to `hook.prepare()` lands on a clean instruction boundary. A mid-instruction cut would corrupt the trampoline - the copied bytes would decode as a different instruction when followed by the trampoline's JMP.
### Results
| Address | Function | Prologue bytes | Decoded | Boundary | Safe | Fixups |
|---------|----------|---------------|---------|----------|------|--------|
| `0x0070b360` | `CM2SceneRenderDraw` | `55 8B EC 81 EC 80 00 00 00` | `PUSH EBP; MOV EBP,ESP; SUB ESP,0x80` | +1,+3,**+9** | 9B | none |
| `0x00710b90` | `CM2Model_ManageRenderListNode` | `55 8B EC 8B 45 08` | `PUSH EBP; MOV EBP,ESP; MOV EAX,[EBP+8]` | +1,+3,**+6** | 6B | none |
| `0x0070cb30` | `CM2Scene_DrawBatchProjected` | `55 8B EC 83 EC 10` | `PUSH EBP; MOV EBP,ESP; SUB ESP,0x10` | +1,+3,**+6** | 6B | none |
### Fix applied
`CM2SceneRenderDraw` prologue changed from 6 to **9** bytes in `src/outline/model_hook.zig`. The original 6-byte value would have split the `SUB ESP, 0x80` instruction (opcode `81 EC` + 4-byte immediate, spanning offset +3 to +9). The trampoline would have executed `81 EC 80 E9 xx xx` as `SUB ESP, <corrupted>`, leading to stack corruption and a crash.
### No other changes needed
- All three prologues contain only register/memory instructions (no `E8 CALL` or `E9 JMP`), so `rel32_fixups` remains `&.{}`.
- The 4-byte NOP padding (bytes 5-8) at `0x0070b360` after the 5-byte `E9 JMP` is harmless - it is never executed (execution jumps to the detour thunk).