Compare commits

...

20 Commits

Author SHA1 Message Date
Dusk-92 77ed24e68a Remove temporary V38 build workflow 2026-08-29 11:54:21 +02:00
Dusk-92 26dea2e586 Temporary: build V38 Retail Polish 2026-08-29 11:53:25 +02:00
Dusk-92 8f22c90401 V38: refine Retail core and halo balance 2026-08-29 11:53:13 +02:00
Dusk-92 6570829e27 Remove temporary V37.1 ExitFix build workflow 2026-08-29 11:48:19 +02:00
Dusk-92 ef6c4d08c1 Temporary: build V37.1 ExitFix 2026-08-29 11:47:09 +02:00
Dusk-92 d6c53ed634 V37.1 ExitFix: skip heavy cleanup during process termination 2026-08-29 11:46:58 +02:00
Dusk-92 2a51ab6030 V37.1 ExitFix: detach model hooks before D3D9 cleanup 2026-08-29 11:46:48 +02:00
Dusk-92 1969bb83bd V37.1 ExitFix: prevent D3D9 rehook during shutdown 2026-08-29 11:46:39 +02:00
Dusk-92 d6b191a4c4 Remove temporary V37 build workflow 2026-08-29 11:39:26 +02:00
Dusk-92 5c09056d7c Temporary: build V37 Retail Falloff 2026-08-29 11:38:13 +02:00
Dusk-92 fa9dd1c730 V37: add smooth Retail-style radial falloff 2026-08-29 11:38:01 +02:00
Dusk-92 6ddc2c5df9 Remove temporary V36 source commit workflow 2026-08-29 11:33:04 +02:00
github-actions[bot] 4bbee94388 V36: soft Retail-style JFA decode 2026-08-29 09:32:44 +00:00
Dusk-92 a36ce6ea76 Temporary: commit V36 Retail Soft decode 2026-08-29 11:32:34 +02:00
Dusk-92 db472789d3 Remove temporary V36 Retail Soft build workflow 2026-08-29 11:32:13 +02:00
Dusk-92 f95ab007d2 Fix V36 build workflow YAML 2026-08-29 11:31:02 +02:00
Dusk-92 0ea0c4a94c Temporary: build V36 Retail Soft 2026-08-29 11:30:20 +02:00
Dusk-92 09863ad9e3 Remove invalid temporary V36 patch workflow 2026-08-29 11:30:04 +02:00
Dusk-92 c82f2b9e52 Fix temporary V36 patch workflow syntax 2026-08-29 11:29:20 +02:00
Dusk-92 49a8644d13 Temporary: patch V36 soft Retail decode 2026-08-29 11:28:43 +02:00
3 changed files with 54 additions and 24 deletions
+8 -2
View File
@@ -1048,11 +1048,17 @@ comptime {
pub export fn DllMain(
_: ?*anyopaque,
reason: u32,
_: ?*anyopaque,
reserved: ?*anyopaque,
) callconv(WINAPI) std.os.windows.BOOL {
switch (reason) {
1 => install(),
0 => uninstall(),
0 => {
// 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 => {},
}
return @enumFromInt(1);
+42 -21
View File
@@ -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,34 +741,45 @@ const jfa_prop_src =
"mov oC0.xy, r8.xy\n" ++
"mov oC0.zw, c1.xx\n";
/// V32 POLISH: hard 3px outline, no feather.
/// c0 = (screen_width, screen_height, radius_px=3, 0).
/// The shader squares radius_px and emits a binary 0/1 edge alpha.
/// 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).
const jfa_decode_src =
"ps_3_0\n" ++
"def c1, 0.0, 1.0, -0.002, 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 seed and pixel-space squared distance.
// 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, c0.w\n" ++
// Seed colour.
"texld r2, r0, s1\n" ++
// Hard radius test: dist² < radius² => alpha 1, otherwise 0.
"mov r3.x, c0.z\n" ++
"mul r3.x, r3.x, r3.x\n" ++
"sub r3.y, r1.z, r3.x\n" ++
"mov r6.w, c1.y\n" ++
"cmp r4.w, r3.y, c0.w, r6.w\n" ++
// Do not paint over the model interior.
"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" ++
// 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.z\n" ++
"cmp r4.w, r5.x, c0.w, r4.w\n" ++
"mov r4.xyz, r2.xyz\n" ++
"mov oC0, r4\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";
/// Debug: composite silhouette RT directly. Forces alpha to 1.0 where silhouette
/// has any content (alpha >= 0.002), 0.0 elsewhere. Bypasses JFA entirely.
@@ -1417,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);
// V34: hard 3px edge unchanged; JFA seed precision is now full-float.
c0 = [4]f32{ fw, fh, 3.0, 0.0 };
// 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);
@@ -1626,6 +1646,7 @@ 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;
+4 -1
View File
@@ -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);
}