Compare commits
17
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
aa526303e1 | ||
|
|
c3e494b2f7 | ||
|
|
635eb62ecc | ||
|
|
4e8466033e | ||
|
|
e9d9858151 | ||
|
|
77ed24e68a | ||
|
|
26dea2e586 | ||
|
|
8f22c90401 | ||
|
|
6570829e27 | ||
|
|
ef6c4d08c1 | ||
|
|
d6c53ed634 | ||
|
|
2a51ab6030 | ||
|
|
1969bb83bd | ||
|
|
d6b191a4c4 | ||
|
|
5c09056d7c | ||
|
|
fa9dd1c730 | ||
|
|
6ddc2c5df9 |
@@ -1,77 +0,0 @@
|
||||
name: Commit V36 Retail Soft decode
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- test/v36-retail-jfa-soft
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
commit-v36-soft:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: test/v36-retail-jfa-soft
|
||||
|
||||
- name: Apply V36 decode
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
python3 <<'PY'
|
||||
from pathlib import Path
|
||||
p = Path('src/outline/d3d9_hook.zig')
|
||||
s = p.read_text()
|
||||
if 'V36 RETAIL-SOFT' in s:
|
||||
raise SystemExit(0)
|
||||
start = s.index('/// V32 POLISH: hard 3px outline, no feather.')
|
||||
end = s.index('/// Debug: composite silhouette RT directly.')
|
||||
lines = [
|
||||
'/// V36 RETAIL-SOFT: keep the proven V34 JFA, soften only final decode.',
|
||||
'/// c0 = (screen_width, screen_height, core_radius_px, halo_radius_px).',
|
||||
'/// Uses the same two texture reads as V34: no 17-tap full-screen morphology.',
|
||||
'const jfa_decode_src =',
|
||||
' "ps_3_0\\n" ++',
|
||||
' "def c1, 0.0, 0.22, 0.82, -0.002\\n" ++',
|
||||
' "def c2, 1.0, 0.95, 0.58, 0.0\\n" ++',
|
||||
' "dcl_2d s0\\n" ++',
|
||||
' "dcl_2d s1\\n" ++',
|
||||
' "dcl_texcoord0 v0\\n" ++',
|
||||
' "texld r0, v0, s0\\n" ++',
|
||||
' "sub r1.xy, v0.xy, r0.xy\\n" ++',
|
||||
' "mul r1.xy, r1.xy, c0.xy\\n" ++',
|
||||
' "dp2add r1.z, r1, r1, c1.x\\n" ++',
|
||||
' "mul r3.x, c0.z, c0.z\\n" ++',
|
||||
' "mul r3.y, c0.w, c0.w\\n" ++',
|
||||
' "sub r4.x, r1.z, r3.y\\n" ++',
|
||||
' "cmp r6.w, r4.x, c1.x, c1.y\\n" ++',
|
||||
' "sub r4.x, r1.z, r3.x\\n" ++',
|
||||
' "cmp r6.w, r4.x, r6.w, c1.z\\n" ++',
|
||||
' "texld r5, v0, s1\\n" ++',
|
||||
' "add r5.x, r5.a, c1.w\\n" ++',
|
||||
' "cmp r6.w, r5.x, c1.x, r6.w\\n" ++',
|
||||
' "mov r6.xyz, c2.xyz\\n" ++',
|
||||
' "mov oC0, r6\\n";',
|
||||
'',
|
||||
'',
|
||||
]
|
||||
s = s[:start] + '\n'.join(lines) + s[end:]
|
||||
old = ' // V34: hard 3px edge unchanged; JFA seed precision is now full-float.\n c0 = [4]f32{ fw, fh, 3.0, 0.0 };'
|
||||
new_cpu = ' // V36: thin 1.5px core plus a subtle 3px halo.\n c0 = [4]f32{ fw, fh, 1.5, 3.0 };'
|
||||
if old not in s:
|
||||
raise SystemExit('V34 CPU decode constants not found')
|
||||
p.write_text(s.replace(old, new_cpu))
|
||||
PY
|
||||
|
||||
- name: Commit source
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
if git diff --quiet; then exit 0; fi
|
||||
git config user.name "github-actions[bot]"
|
||||
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
||||
git add src/outline/d3d9_hook.zig
|
||||
git commit -m "V36: soft Retail-style JFA decode"
|
||||
git push origin HEAD:test/v36-retail-jfa-soft
|
||||
@@ -1,55 +0,0 @@
|
||||
name: V36 ExitFix Baseline
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- test/v36-exitfix-baseline
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: mlugg/setup-zig@v2
|
||||
with:
|
||||
version: '0.16.0'
|
||||
|
||||
- name: Build
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
zig build all-variants -Doptimize=ReleaseSmall \
|
||||
-Dweirdperformance=false \
|
||||
-Doutline=true \
|
||||
-Dcustomassets=true \
|
||||
-Dtransmogfix=true
|
||||
|
||||
- name: Package
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
rm -rf package dist
|
||||
mkdir -p package/DLL package/Interface/AddOns/WeirdUtils_Outline dist
|
||||
cp zig-out/variants/outline.dll package/DLL/outline.dll
|
||||
cp src/outline/addon/Bindings.xml package/Interface/AddOns/WeirdUtils_Outline/
|
||||
cp src/outline/addon/Outline.lua package/Interface/AddOns/WeirdUtils_Outline/
|
||||
cp src/outline/addon/WeirdUtils_Outline.toc package/Interface/AddOns/WeirdUtils_Outline/
|
||||
printf '%s\n' \
|
||||
'V36 runtime + process-exit safety only.' \
|
||||
'Base runtime commit: 4bbee94388f98843b738e275fd9482576be80654.' \
|
||||
'Compared with V34, only src/outline/d3d9_hook.zig changes runtime behavior.' \
|
||||
'main branch is untouched.' \
|
||||
'WeirdPerformance is disabled in this standalone build and not modified.' \
|
||||
> package/README_TEST.txt
|
||||
(cd package && sha256sum DLL/outline.dll > SHA256SUMS.txt && zip -r ../dist/WeirdUtils_V36_EXITFIX_BASELINE.zip DLL Interface README_TEST.txt SHA256SUMS.txt)
|
||||
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: WeirdUtils-V36-EXITFIX-BASELINE
|
||||
path: dist/WeirdUtils_V36_EXITFIX_BASELINE.zip
|
||||
if-no-files-found: error
|
||||
@@ -1,55 +0,0 @@
|
||||
name: V37A DIP Passthrough
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- test/v37a-dip-passthrough
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: mlugg/setup-zig@v2
|
||||
with:
|
||||
version: '0.16.0'
|
||||
|
||||
- name: Build
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
zig build all-variants -Doptimize=ReleaseSmall \
|
||||
-Dweirdperformance=false \
|
||||
-Doutline=true \
|
||||
-Dcustomassets=true \
|
||||
-Dtransmogfix=true
|
||||
|
||||
- name: Package
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
rm -rf package dist
|
||||
mkdir -p package/DLL package/Interface/AddOns/WeirdUtils_Outline dist
|
||||
cp zig-out/variants/outline.dll package/DLL/outline.dll
|
||||
cp src/outline/addon/Bindings.xml package/Interface/AddOns/WeirdUtils_Outline/
|
||||
cp src/outline/addon/Outline.lua package/Interface/AddOns/WeirdUtils_Outline/
|
||||
cp src/outline/addon/WeirdUtils_Outline.toc package/Interface/AddOns/WeirdUtils_Outline/
|
||||
printf '%s\n' \
|
||||
'V37A DIP passthrough isolation test.' \
|
||||
'EndScene and DrawIndexedPrimitive vtable hooks are installed.' \
|
||||
'DIP detour performs no Outline capture/state/resource work and immediately calls original DIP.' \
|
||||
'Reset remains untouched.' \
|
||||
'Visible outline is intentionally absent in this diagnostic build.' \
|
||||
'main branch untouched; WeirdPerformance not modified.' \
|
||||
> package/README_TEST.txt
|
||||
(cd package && sha256sum DLL/outline.dll > SHA256SUMS.txt && zip -r ../dist/WeirdUtils_V37A_DIP_PASSTHROUGH.zip DLL Interface README_TEST.txt SHA256SUMS.txt)
|
||||
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: WeirdUtils-V37A-DIP-PASSTHROUGH
|
||||
path: dist/WeirdUtils_V37A_DIP_PASSTHROUGH.zip
|
||||
if-no-files-found: error
|
||||
@@ -1,55 +0,0 @@
|
||||
name: V37A EndScene Only
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- test/v37a-endscene-only
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: mlugg/setup-zig@v2
|
||||
with:
|
||||
version: '0.16.0'
|
||||
|
||||
- name: Build
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
zig build all-variants -Doptimize=ReleaseSmall \
|
||||
-Dweirdperformance=false \
|
||||
-Doutline=true \
|
||||
-Dcustomassets=true \
|
||||
-Dtransmogfix=true
|
||||
|
||||
- name: Package
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
rm -rf package dist
|
||||
mkdir -p package/DLL package/Interface/AddOns/WeirdUtils_Outline dist
|
||||
cp zig-out/variants/outline.dll package/DLL/outline.dll
|
||||
cp src/outline/addon/Bindings.xml package/Interface/AddOns/WeirdUtils_Outline/
|
||||
cp src/outline/addon/Outline.lua package/Interface/AddOns/WeirdUtils_Outline/
|
||||
cp src/outline/addon/WeirdUtils_Outline.toc package/Interface/AddOns/WeirdUtils_Outline/
|
||||
printf '%s\n' \
|
||||
'V37A EndScene-only isolation test.' \
|
||||
'Base: V37A no-Reset-hook + ExitFix.' \
|
||||
'Only IDirect3DDevice9::EndScene is hooked.' \
|
||||
'DrawIndexedPrimitive and Reset are untouched.' \
|
||||
'Visible outline is intentionally absent in this diagnostic build.' \
|
||||
'main branch untouched; WeirdPerformance not modified.' \
|
||||
> package/README_TEST.txt
|
||||
(cd package && sha256sum DLL/outline.dll > SHA256SUMS.txt && zip -r ../dist/WeirdUtils_V37A_ENDSCENE_ONLY.zip DLL Interface README_TEST.txt SHA256SUMS.txt)
|
||||
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: WeirdUtils-V37A-ENDSCENE-ONLY
|
||||
path: dist/WeirdUtils_V37A_ENDSCENE_ONLY.zip
|
||||
if-no-files-found: error
|
||||
@@ -1,54 +0,0 @@
|
||||
name: V37A No AutoRehook
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- test/v37a-no-autorehook
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: mlugg/setup-zig@v2
|
||||
with:
|
||||
version: '0.16.0'
|
||||
|
||||
- name: Build
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
zig build all-variants -Doptimize=ReleaseSmall \
|
||||
-Dweirdperformance=false \
|
||||
-Doutline=true \
|
||||
-Dcustomassets=true \
|
||||
-Dtransmogfix=true
|
||||
|
||||
- name: Package
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
rm -rf package dist
|
||||
mkdir -p package/DLL package/Interface/AddOns/WeirdUtils_Outline dist
|
||||
cp zig-out/variants/outline.dll package/DLL/outline.dll
|
||||
cp src/outline/addon/Bindings.xml package/Interface/AddOns/WeirdUtils_Outline/
|
||||
cp src/outline/addon/Outline.lua package/Interface/AddOns/WeirdUtils_Outline/
|
||||
cp src/outline/addon/WeirdUtils_Outline.toc package/Interface/AddOns/WeirdUtils_Outline/
|
||||
printf '%s\n' \
|
||||
'V37A no-auto-rehook isolation test.' \
|
||||
'Base: V37A radii-only + ExitFix.' \
|
||||
'Only runtime change: automatic lateRehookIfLost() call removed from RenderDraw.' \
|
||||
'Initial deferred D3D9 hook installation remains unchanged.' \
|
||||
'main branch untouched; WeirdPerformance not modified.' \
|
||||
> package/README_TEST.txt
|
||||
(cd package && sha256sum DLL/outline.dll > SHA256SUMS.txt && zip -r ../dist/WeirdUtils_V37A_NO_AUTOREHOOK.zip DLL Interface README_TEST.txt SHA256SUMS.txt)
|
||||
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: WeirdUtils-V37A-NO-AUTOREHOOK
|
||||
path: dist/WeirdUtils_V37A_NO_AUTOREHOOK.zip
|
||||
if-no-files-found: error
|
||||
@@ -1,55 +0,0 @@
|
||||
name: V37A No Reset Hook
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- test/v37a-no-reset-hook
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: mlugg/setup-zig@v2
|
||||
with:
|
||||
version: '0.16.0'
|
||||
|
||||
- name: Build
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
zig build all-variants -Doptimize=ReleaseSmall \
|
||||
-Dweirdperformance=false \
|
||||
-Doutline=true \
|
||||
-Dcustomassets=true \
|
||||
-Dtransmogfix=true
|
||||
|
||||
- name: Package
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
rm -rf package dist
|
||||
mkdir -p package/DLL package/Interface/AddOns/WeirdUtils_Outline dist
|
||||
cp zig-out/variants/outline.dll package/DLL/outline.dll
|
||||
cp src/outline/addon/Bindings.xml package/Interface/AddOns/WeirdUtils_Outline/
|
||||
cp src/outline/addon/Outline.lua package/Interface/AddOns/WeirdUtils_Outline/
|
||||
cp src/outline/addon/WeirdUtils_Outline.toc package/Interface/AddOns/WeirdUtils_Outline/
|
||||
printf '%s\n' \
|
||||
'V37A no-Reset-hook isolation test.' \
|
||||
'Base: V37A no-auto-rehook + ExitFix.' \
|
||||
'EndScene and DrawIndexedPrimitive hooks remain active.' \
|
||||
'Reset hook is NOT installed.' \
|
||||
'Visible outline rendering should still work.' \
|
||||
'main branch untouched; WeirdPerformance not modified.' \
|
||||
> package/README_TEST.txt
|
||||
(cd package && sha256sum DLL/outline.dll > SHA256SUMS.txt && zip -r ../dist/WeirdUtils_V37A_NO_RESET_HOOK.zip DLL Interface README_TEST.txt SHA256SUMS.txt)
|
||||
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: WeirdUtils-V37A-NO-RESET-HOOK
|
||||
path: dist/WeirdUtils_V37A_NO_RESET_HOOK.zip
|
||||
if-no-files-found: error
|
||||
@@ -1,51 +0,0 @@
|
||||
name: V37A Radii Only
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- test/v37a-radii-only
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: mlugg/setup-zig@v2
|
||||
with:
|
||||
version: '0.16.0'
|
||||
- name: Build
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
zig build all-variants -Doptimize=ReleaseSmall \
|
||||
-Dweirdperformance=false \
|
||||
-Doutline=true \
|
||||
-Dcustomassets=true \
|
||||
-Dtransmogfix=true
|
||||
- name: Package
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
rm -rf package dist
|
||||
mkdir -p package/DLL package/Interface/AddOns/WeirdUtils_Outline dist
|
||||
cp zig-out/variants/outline.dll package/DLL/outline.dll
|
||||
cp src/outline/addon/Bindings.xml package/Interface/AddOns/WeirdUtils_Outline/
|
||||
cp src/outline/addon/Outline.lua package/Interface/AddOns/WeirdUtils_Outline/
|
||||
cp src/outline/addon/WeirdUtils_Outline.toc package/Interface/AddOns/WeirdUtils_Outline/
|
||||
printf '%s\n' \
|
||||
'V37A isolation test.' \
|
||||
'Base: V36 + ExitFix (stable in user test).' \
|
||||
'Only runtime change: radii 1.5/3.0 -> 1.35/3.20.' \
|
||||
'V36 decode shader remains unchanged.' \
|
||||
'main branch untouched; WeirdPerformance not modified.' \
|
||||
> package/README_TEST.txt
|
||||
(cd package && sha256sum DLL/outline.dll > SHA256SUMS.txt && zip -r ../dist/WeirdUtils_V37A_RADII_ONLY.zip DLL Interface README_TEST.txt SHA256SUMS.txt)
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: WeirdUtils-V37A-RADII-ONLY
|
||||
path: dist/WeirdUtils_V37A_RADII_ONLY.zip
|
||||
if-no-files-found: error
|
||||
@@ -0,0 +1,73 @@
|
||||
name: V40 Attached Model Outline Test
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- test/v40-attached-model-outline
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
build-v40:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout V40 branch
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Install Zig
|
||||
uses: mlugg/setup-zig@v2
|
||||
with:
|
||||
version: '0.16.0'
|
||||
|
||||
- name: Build standalone variants
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
zig build all-variants -Doptimize=ReleaseSmall \
|
||||
-Dweirdperformance=false \
|
||||
-Doutline=true \
|
||||
-Dcustomassets=true \
|
||||
-Dtransmogfix=true
|
||||
|
||||
- name: Assemble V40 outline-only test package
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
rm -rf package dist
|
||||
mkdir -p package/DLL
|
||||
mkdir -p package/Interface/AddOns/WeirdUtils_Outline
|
||||
mkdir -p dist
|
||||
|
||||
cp zig-out/variants/outline.dll package/DLL/outline.dll
|
||||
cp src/outline/addon/Bindings.xml package/Interface/AddOns/WeirdUtils_Outline/Bindings.xml
|
||||
cp src/outline/addon/Outline.lua package/Interface/AddOns/WeirdUtils_Outline/Outline.lua
|
||||
cp src/outline/addon/WeirdUtils_Outline.toc package/Interface/AddOns/WeirdUtils_Outline/WeirdUtils_Outline.toc
|
||||
|
||||
printf '%s\n' \
|
||||
'WeirdUtils V40 Attached Model Outline' \
|
||||
'Base: exact V38 Retail Polish + AutoTarget + AutoRehook + ExitFix.' \
|
||||
'main is untouched.' \
|
||||
'WeirdPerformance is disabled in this standalone build and not modified.' \
|
||||
'Engine-proven WoW 1.12.1 attachment layout from 0x712F70:' \
|
||||
'- child +0x1CC = parent/root CM2Model' \
|
||||
'- child +0x1D0 = attachment id' \
|
||||
'- root +0x1DC = child-list head' \
|
||||
'- child +0x1E4 = next sibling' \
|
||||
'V40 makes direct attached M2 models inherit the root target outline.' \
|
||||
'No new hook, no linked-list traversal, no game-memory writes.' \
|
||||
> package/README_TEST.txt
|
||||
|
||||
(
|
||||
cd package
|
||||
sha256sum DLL/outline.dll > SHA256SUMS.txt
|
||||
zip -r ../dist/WeirdUtils_V40_ATTACHED_MODEL_OUTLINE.zip DLL Interface README_TEST.txt SHA256SUMS.txt
|
||||
)
|
||||
|
||||
- name: Upload V40 package
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: WeirdUtils-V40-ATTACHED-MODEL-OUTLINE
|
||||
path: dist/WeirdUtils_V40_ATTACHED_MODEL_OUTLINE.zip
|
||||
if-no-files-found: error
|
||||
+4
-1
@@ -1053,7 +1053,10 @@ pub export fn DllMain(
|
||||
switch (reason) {
|
||||
1 => install(),
|
||||
0 => {
|
||||
// Process-exit safety only; runtime Outline behavior is unchanged.
|
||||
// ExitFix: when lpReserved is non-null, Windows is terminating the
|
||||
// whole process. Do not call into D3D9/COM or other DLLs from
|
||||
// DLL_PROCESS_DETACH during global teardown; the OS will reclaim
|
||||
// those resources. Keep full uninstall for explicit FreeLibrary.
|
||||
if (reserved == null) uninstall();
|
||||
},
|
||||
else => {},
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
-- Outline addon (embedded in DLL, loaded from memory)
|
||||
-- Part of WeirdUtils - only loaded when outline module is compiled
|
||||
|
||||
OUTLINE_VERSION = 1
|
||||
OUTLINE_VERSION = 40
|
||||
|
||||
BINDING_HEADER_OUTLINE = "Outline"
|
||||
|
||||
|
||||
+106
-14
@@ -57,6 +57,14 @@ var orig_reset: usize = 0;
|
||||
var d3d9_vtable: ?[*]usize = null;
|
||||
var hooks_installed: bool = false;
|
||||
|
||||
/// ExitFix: once shutdown begins, no code path may reinstall D3D9 hooks.
|
||||
var shutdown_started: bool = false;
|
||||
|
||||
pub fn beginShutdown() void {
|
||||
shutdown_started = true;
|
||||
}
|
||||
|
||||
|
||||
// Sticky diagnostics for the in-game OutlineDebug() command.
|
||||
pub var debug_endscene_seen: bool = false;
|
||||
pub var debug_dip_seen: bool = false;
|
||||
@@ -114,6 +122,7 @@ pub var debug_late_rehook_succeeded: bool = false;
|
||||
/// If the current entries are no longer ours, chain whatever is there now as
|
||||
/// the new originals, then patch the three entries again.
|
||||
pub fn lateRehookIfLost() bool {
|
||||
if (shutdown_started) return false;
|
||||
debug_late_rehook_attempted = true;
|
||||
|
||||
const cur = getD3D9VTable() orelse return false;
|
||||
@@ -732,26 +741,40 @@ const jfa_prop_src =
|
||||
"mov oC0.xy, r8.xy\n" ++
|
||||
"mov oC0.zw, c1.xx\n";
|
||||
|
||||
/// V36 RETAIL-SOFT: keep the proven V34 JFA, soften only final decode.
|
||||
/// V38 RETAIL-POLISH: keep the proven V34/V36/V37 JFA and refine only
|
||||
/// the final alpha profile. Still only two texture reads.
|
||||
/// c0 = (screen_width, screen_height, core_radius_px, halo_radius_px).
|
||||
/// Uses the same two texture reads as V34: no 17-tap full-screen morphology.
|
||||
const jfa_decode_src =
|
||||
"ps_3_0\n" ++
|
||||
"def c1, 0.0, 0.22, 0.82, -0.002\n" ++
|
||||
"def c2, 1.0, 0.95, 0.58, 0.0\n" ++
|
||||
// c1 = zero, one, halo alpha, -interior threshold
|
||||
"def c1, 0.0, 1.0, 0.17, -0.002\n" ++
|
||||
// pale Retail-like yellow-green
|
||||
"def c2, 1.0, 0.96, 0.62, 0.0\n" ++
|
||||
// core alpha
|
||||
"def c3, 0.84, 0.0, 0.0, 0.0\n" ++
|
||||
"dcl_2d s0\n" ++
|
||||
"dcl_2d s1\n" ++
|
||||
"dcl_texcoord0 v0\n" ++
|
||||
// Nearest JFA seed and pixel-space squared distance.
|
||||
"texld r0, v0, s0\n" ++
|
||||
"sub r1.xy, v0.xy, r0.xy\n" ++
|
||||
"mul r1.xy, r1.xy, c0.xy\n" ++
|
||||
"dp2add r1.z, r1, r1, c1.x\n" ++
|
||||
// Squared core and halo radii.
|
||||
"mul r3.x, c0.z, c0.z\n" ++
|
||||
"mul r3.y, c0.w, c0.w\n" ++
|
||||
"sub r4.x, r1.z, r3.y\n" ++
|
||||
"cmp r6.w, r4.x, c1.x, c1.y\n" ++
|
||||
"sub r4.x, r1.z, r3.x\n" ++
|
||||
"cmp r6.w, r4.x, r6.w, c1.z\n" ++
|
||||
// Smooth halo factor = saturate((halo² - dist²) / (halo² - core²)).
|
||||
"sub r3.z, r3.y, r3.x\n" ++
|
||||
"rcp r3.z, r3.z\n" ++
|
||||
"sub r4.x, r3.y, r1.z\n" ++
|
||||
"mul r4.x, r4.x, r3.z\n" ++
|
||||
"max r4.x, r4.x, c1.x\n" ++
|
||||
"min r4.x, r4.x, c1.y\n" ++
|
||||
"mul r6.w, r4.x, c1.z\n" ++
|
||||
// Solid-but-soft core inside the inner radius.
|
||||
"sub r4.y, r1.z, r3.x\n" ++
|
||||
"cmp r6.w, r4.y, r6.w, c3.x\n" ++
|
||||
// Never paint over the original model interior.
|
||||
"texld r5, v0, s1\n" ++
|
||||
"add r5.x, r5.a, c1.w\n" ++
|
||||
"cmp r6.w, r5.x, c1.x, r6.w\n" ++
|
||||
@@ -996,10 +1019,79 @@ fn hkDIP(
|
||||
) callconv(hook.cc.stdcall) i32 {
|
||||
debug_dip_seen = true;
|
||||
|
||||
// Isolation test: keep the DIP vtable detour installed, but do no
|
||||
// Outline state capture/resource work here. Call the original directly.
|
||||
const OrigDIP = *const fn (*anyopaque, u32, i32, u32, u32, u32, u32) callconv(hook.cc.stdcall) i32;
|
||||
const origFn: OrigDIP = @ptrFromInt(orig_dip);
|
||||
|
||||
// ---- Cache outline draws for EndScene replay ----
|
||||
if (model_hook.rendering_outline) {
|
||||
debug_outline_dip_seen = true;
|
||||
const model_ptr = model_hook.current_model;
|
||||
const color = tracker.getModelColor(model_ptr) orelse
|
||||
return origFn(device, prim_type, base_vtx, min_vtx, num_verts, start_idx, prim_count);
|
||||
const category = tracker.getModelCategory(model_ptr);
|
||||
|
||||
// Ensure resources will be available for replay in EndScene
|
||||
if (!shaders_attempted) ensureShaders(device);
|
||||
ensureResources(device);
|
||||
if (outline_ps == null or rt_silhouette_surf == null)
|
||||
return origFn(device, prim_type, base_vtx, min_vtx, num_verts, start_idx, prim_count);
|
||||
|
||||
// Cache if room available
|
||||
if (cached_draw_count < MAX_CACHED_DRAWS) {
|
||||
const idx = cached_draw_count;
|
||||
var draw = &cached_draws[idx];
|
||||
|
||||
// Draw parameters
|
||||
draw.prim_type = prim_type;
|
||||
draw.base_vtx = base_vtx;
|
||||
draw.min_vtx = min_vtx;
|
||||
draw.num_verts = num_verts;
|
||||
draw.start_idx = start_idx;
|
||||
draw.prim_count = prim_count;
|
||||
|
||||
// Outline info
|
||||
draw.color = color;
|
||||
draw.category = category;
|
||||
|
||||
// Capture current GPU state (AddRef COM objects to keep them alive)
|
||||
deviceGetStreamSource(device, 0, &draw.vb, &draw.vb_offset, &draw.vb_stride);
|
||||
// GetStreamSource AddRef's the VB - we keep the ref until replay
|
||||
draw.ib = deviceGetIndices(device);
|
||||
// GetIndices AddRef's the IB
|
||||
draw.vertex_decl = deviceGetPtr(device, types.VT.GetVertexDeclaration);
|
||||
// GetVertexDeclaration AddRef's
|
||||
draw.vertex_shader = deviceGetPtr(device, types.VT.GetVertexShader);
|
||||
// GetVertexShader AddRef's
|
||||
for (0..4) |stage| {
|
||||
draw.tex[stage] = deviceGetTexture(device, @intCast(stage));
|
||||
draw.alpha_op[stage] = deviceGetTSS(device, @intCast(stage), types.D3DTSS.ALPHAOP);
|
||||
draw.alpha_arg1[stage] = deviceGetTSS(device, @intCast(stage), types.D3DTSS.ALPHAARG1);
|
||||
draw.alpha_arg2[stage] = deviceGetTSS(device, @intCast(stage), types.D3DTSS.ALPHAARG2);
|
||||
}
|
||||
draw.pixel_shader = deviceGetPtr(device, types.VT.GetPixelShader);
|
||||
draw.state_block = deviceCreateStateBlock(device);
|
||||
if (draw.state_block != null) debug_state_block_seen = true;
|
||||
draw.alpha_test_enable = deviceGetRS(device, types.D3DRS.ALPHATESTENABLE);
|
||||
draw.alpha_ref = deviceGetRS(device, types.D3DRS.ALPHAREF);
|
||||
draw.alpha_func = deviceGetRS(device, types.D3DRS.ALPHAFUNC);
|
||||
draw.alpha_blend_enable = deviceGetRS(device, types.D3DRS.ALPHABLENDENABLE);
|
||||
draw.src_blend = deviceGetRS(device, types.D3DRS.SRCBLEND);
|
||||
draw.dst_blend = deviceGetRS(device, types.D3DRS.DESTBLEND);
|
||||
|
||||
// Capture VS constants (bone matrices, world/view/proj transforms)
|
||||
deviceGetVSConstF(device, 0, &draw.vs_consts, MAX_VS_CONST_REGS);
|
||||
|
||||
cached_draw_count = idx + 1;
|
||||
frame_has_outlines = true;
|
||||
debug_cached_draw_seen = true;
|
||||
}
|
||||
|
||||
// DEBUG23: no stencil writes. Preserve WoW's D3D state and draw once.
|
||||
// The cached geometry is replayed later into the silhouette RT.
|
||||
return origFn(device, prim_type, base_vtx, min_vtx, num_verts, start_idx, prim_count);
|
||||
}
|
||||
|
||||
// ---- Normal path ----
|
||||
return origFn(device, prim_type, base_vtx, min_vtx, num_verts, start_idx, prim_count);
|
||||
}
|
||||
|
||||
@@ -1345,8 +1437,8 @@ fn runJfaPipeline(device: *anyopaque) void {
|
||||
if (saved_rt0) |rt| deviceSetRenderTarget(device, 0, rt);
|
||||
deviceSetTexture(device, 0, rt_jfa_a_tex);
|
||||
deviceSetTexture(device, 1, rt_silhouette_tex);
|
||||
// V37A isolation test: V37 radii only, V36 decode shader unchanged.
|
||||
c0 = [4]f32{ fw, fh, 1.35, 3.20 };
|
||||
// V38: slightly stronger 1.5px core with a subtler 3.1px falloff.
|
||||
c0 = [4]f32{ fw, fh, 1.50, 3.10 };
|
||||
deviceSetPSConstF(device, 0, &c0);
|
||||
deviceSetPtr(device, types.VT.SetPixelShader, jfa_decode_ps.?);
|
||||
deviceSetRS(device, types.D3DRS.ALPHABLENDENABLE, 1);
|
||||
@@ -1554,14 +1646,14 @@ fn getD3D9VTable() ?[*]usize {
|
||||
|
||||
pub fn installHooks() bool {
|
||||
if (hooks_installed) return true;
|
||||
if (shutdown_started) return false;
|
||||
|
||||
const vtable_ptr = getD3D9VTable() orelse return false;
|
||||
d3d9_vtable = vtable_ptr;
|
||||
|
||||
// Isolation test: hook EndScene + DrawIndexedPrimitive.
|
||||
// Reset remains untouched.
|
||||
if (!patchVtableEntry(vtable_ptr, types.VT.EndScene, @intFromPtr(&hkEndScene), &orig_endscene)) return false;
|
||||
if (!patchVtableEntry(vtable_ptr, types.VT.DrawIndexedPrimitive, @intFromPtr(&hkDIP), &orig_dip)) return false;
|
||||
if (!patchVtableEntry(vtable_ptr, types.VT.Reset, @intFromPtr(&hkReset), &orig_reset)) return false;
|
||||
|
||||
hooks_installed = true;
|
||||
return true;
|
||||
|
||||
@@ -94,8 +94,10 @@ fn renderDrawDetour(this: u32, view_matrix: u32, batch_data: u32, batch_indices:
|
||||
api.initD3D9Deferred();
|
||||
}
|
||||
|
||||
// Isolation test: keep the initial deferred D3D9 hook install, but do not
|
||||
// repeatedly verify/rewrite the live vtable while rendering.
|
||||
// AutoFix: OutlineDebug() previously performed lateRehookIfLost() by hand.
|
||||
// Check periodically from this always-active native model hook instead.
|
||||
autoRepairD3D9Hooks();
|
||||
|
||||
// Skip reordering if nothing to outline or too many batches
|
||||
if (!tracker.enabled or !tracker.hasTargets() or batch_count == 0 or batch_count > MAX_REORDER) {
|
||||
render_draw_hook.callOriginal(.{ this, view_matrix, batch_data, batch_indices, batch_count });
|
||||
@@ -111,7 +113,7 @@ fn renderDrawDetour(this: u32, view_matrix: u32, batch_data: u32, batch_indices:
|
||||
const idx_u: u32 = @bitCast(indices[i]);
|
||||
const model_ptr = hook.readMem(u32, batch_data +% idx_u *% 0x40 +% 4);
|
||||
if (model_ptr != 0) {
|
||||
if (tracker.findOutlineEntry(model_ptr) != null) {
|
||||
if (tracker.findOutlineEntryIncludingAttachment(model_ptr) != null) {
|
||||
outline_count += 1;
|
||||
} else if (tracker.isGameObjectModel(model_ptr)) {
|
||||
game_obj_count += 1;
|
||||
@@ -135,7 +137,7 @@ fn renderDrawDetour(this: u32, view_matrix: u32, batch_data: u32, batch_indices:
|
||||
const batch_idx = indices[i];
|
||||
const idx_u: u32 = @bitCast(batch_idx);
|
||||
const model_ptr = hook.readMem(u32, batch_data +% idx_u *% 0x40 +% 4);
|
||||
if (model_ptr != 0 and tracker.findOutlineEntry(model_ptr) != null) {
|
||||
if (model_ptr != 0 and tracker.findOutlineEntryIncludingAttachment(model_ptr) != null) {
|
||||
reordered_indices[outline_pos] = batch_idx;
|
||||
outline_pos += 1;
|
||||
} else if (model_ptr != 0 and tracker.isGameObjectModel(model_ptr)) {
|
||||
@@ -191,7 +193,7 @@ fn drawBatchProjDetour(ctx: u32) callconv(hook.cc.thiscall) void {
|
||||
else
|
||||
0;
|
||||
|
||||
const entry = if (model_ptr != 0) tracker.findOutlineEntry(model_ptr) else null;
|
||||
const entry = if (model_ptr != 0) tracker.findOutlineEntryIncludingAttachment(model_ptr) else null;
|
||||
|
||||
if (entry != null) {
|
||||
// This batch is an outline target - signal the DIP hook
|
||||
|
||||
@@ -12,6 +12,15 @@ pub const MODEL_OWNER_DIRECT: usize = 0x28;
|
||||
/// model + this → render callback owner pointer (set by SetRenderCallbacks).
|
||||
pub const MODEL_OWNER_CALLBACK: usize = 0x3C0;
|
||||
|
||||
/// V40: parent/root CM2Model for an attached model.
|
||||
/// Proven from WoW 1.12.1 build 5875 function 0x712F70:
|
||||
/// child+0x1CC = root, child+0x1D0 = attachment id,
|
||||
/// root+0x1DC = child-list head, child+0x1E4 = next sibling.
|
||||
pub const MODEL_ATTACHMENT_PARENT: usize = 0x1CC;
|
||||
pub const MODEL_ATTACHMENT_ID: usize = 0x1D0;
|
||||
pub const MODEL_CHILD_HEAD: usize = 0x1DC;
|
||||
pub const MODEL_NEXT_SIBLING: usize = 0x1E4;
|
||||
|
||||
// =============================================================================
|
||||
// Render context
|
||||
// =============================================================================
|
||||
|
||||
@@ -109,8 +109,11 @@ pub fn initD3D9Deferred() void {
|
||||
/// Remove all outline hooks. Called during DLL_PROCESS_DETACH.
|
||||
pub fn cleanup() void {
|
||||
if (g_is_hook_owner) {
|
||||
d3d9_hook.removeHooks();
|
||||
// ExitFix: stop any future self-heal first, then detach the model hooks
|
||||
// that can call lateRehookIfLost(), and only then tear down D3D9.
|
||||
d3d9_hook.beginShutdown();
|
||||
model_hook.removeHooks();
|
||||
d3d9_hook.removeHooks();
|
||||
log.close();
|
||||
mod_mutex.release(&g_mutex);
|
||||
}
|
||||
|
||||
+26
-2
@@ -79,6 +79,19 @@ pub fn findOutlineEntry(model_ptr: u32) ?*const types.OutlineEntry {
|
||||
return null;
|
||||
}
|
||||
|
||||
/// V40: resolve a live attached M2 to the already-tracked root model.
|
||||
/// 0x712F70 writes the root CM2Model pointer directly to child+0x1CC.
|
||||
/// We only read that fixed field and compare the value; the parent pointer is
|
||||
/// never dereferenced here.
|
||||
pub fn findOutlineEntryIncludingAttachment(model_ptr: u32) ?*const types.OutlineEntry {
|
||||
if (findOutlineEntry(model_ptr)) |entry| return entry;
|
||||
if (model_ptr == 0) return null;
|
||||
|
||||
const parent = hook.readMem(u32, model_ptr + o.MODEL_ATTACHMENT_PARENT);
|
||||
if (parent == 0 or parent == model_ptr) return null;
|
||||
return findOutlineEntry(parent);
|
||||
}
|
||||
|
||||
/// Check if any outline targets are tracked this frame.
|
||||
pub fn hasTargets() bool {
|
||||
return tracked_obj_count > 0;
|
||||
@@ -86,7 +99,7 @@ pub fn hasTargets() bool {
|
||||
|
||||
/// Get the outline colour for a model, or null if not tracked.
|
||||
pub fn getModelColor(model_ptr: u32) ?u32 {
|
||||
const entry = findOutlineEntry(model_ptr) orelse return null;
|
||||
const entry = findOutlineEntryIncludingAttachment(model_ptr) orelse return null;
|
||||
return switch (entry.category) {
|
||||
.target => types.COLOR_TARGET,
|
||||
.raid_marked => if (entry.raid_mark > 0 and entry.raid_mark <= 8)
|
||||
@@ -100,7 +113,7 @@ pub fn getModelColor(model_ptr: u32) ?u32 {
|
||||
|
||||
/// Get the outline category for a model.
|
||||
pub fn getModelCategory(model_ptr: u32) types.ModelCategory {
|
||||
const entry = findOutlineEntry(model_ptr) orelse return .none;
|
||||
const entry = findOutlineEntryIncludingAttachment(model_ptr) orelse return .none;
|
||||
return entry.category;
|
||||
}
|
||||
|
||||
@@ -136,6 +149,7 @@ pub fn classifyModel(model_ptr: u32) void {
|
||||
// Read the model's back-pointers to its owning game object.
|
||||
const owner_direct = hook.readMem(u32, model_ptr + o.MODEL_OWNER_DIRECT);
|
||||
const owner_callback = hook.readMem(u32, model_ptr + o.MODEL_OWNER_CALLBACK);
|
||||
const attachment_parent = hook.readMem(u32, model_ptr + o.MODEL_ATTACHMENT_PARENT);
|
||||
|
||||
// Match against tracked outline objects (target, raid marks, dead players).
|
||||
if (tracked_obj_count > 0 and frame_outline_count < MAX_OUTLINE_MODELS) {
|
||||
@@ -149,6 +163,16 @@ pub fn classifyModel(model_ptr: u32) void {
|
||||
}
|
||||
}
|
||||
|
||||
// V40: attached weapons, shields and other M2 children inherit the
|
||||
// selected root's outline. This is only a value comparison; no traversal.
|
||||
if (attachment_parent != 0 and attachment_parent != model_ptr and
|
||||
findOutlineEntry(model_ptr) == null and frame_outline_count < MAX_OUTLINE_MODELS)
|
||||
{
|
||||
if (findOutlineEntry(attachment_parent)) |parent_entry| {
|
||||
addOutlineEntry(model_ptr, parent_entry.category, parent_entry.raid_mark);
|
||||
}
|
||||
}
|
||||
|
||||
// Match against game object pointers (for render ordering).
|
||||
if (game_obj_ptr_count > 0 and game_obj_model_count < MAX_GAME_OBJ_MODELS) {
|
||||
for (game_obj_ptrs[0..game_obj_ptr_count]) |go_ptr| {
|
||||
|
||||
Reference in New Issue
Block a user