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.
This commit is contained in:
@@ -27,10 +27,10 @@ const module_list = [_]ModuleDesc{
|
||||
.{ .name = "healtextfix", .desc = "Enable SuperWoW heal text fix" },
|
||||
.{ .name = "bigcursor", .desc = "Enable big cursor module" },
|
||||
.{ .name = "clickthrough", .desc = "Enable GO click-through (enlarge GO model bounds)" },
|
||||
.{ .name = "dpslog", .desc = "Enable structured combat log events for addons", .default = false },
|
||||
.{ .name = "dpslog", .desc = "Enable structured combat log events for addons" },
|
||||
.{ .name = "transform44", .desc = "Enable transformMatrix4x4 hook", .default = false },
|
||||
.{ .name = "addonperf", .desc = "Enable addon memory/CPU profiling API" },
|
||||
.{ .name = "filecache", .desc = "Enable MPQ archive file cache", .default = false },
|
||||
.{ .name = "addonperf", .desc = "Enable addon memory/CPU profiling API", .default = false },
|
||||
.{ .name = "filecache", .desc = "Enable MPQ archive file cache" },
|
||||
.{ .name = "ssemaths", .desc = "Enable UnitXP x87 math polyfill replacements (SSE)", .default = false },
|
||||
.{ .name = "silicon", .desc = "Enable SSE2 math replacements (ported from libSiliconPatch)", .default = false },
|
||||
};
|
||||
@@ -71,6 +71,14 @@ pub fn build(b: *std.Build) void {
|
||||
.optimize = .ReleaseFast,
|
||||
}),
|
||||
});
|
||||
const bone_sse_ref_obj = b.addObject(.{
|
||||
.name = "bone_sse_ref",
|
||||
.root_module = b.createModule(.{
|
||||
.root_source_file = b.path("src/transform44/bone_sse_reference.zig"),
|
||||
.target = target,
|
||||
.optimize = .ReleaseFast,
|
||||
}),
|
||||
});
|
||||
const math_sse_obj = b.addObject(.{
|
||||
.name = "math_sse",
|
||||
.root_module = b.createModule(.{
|
||||
@@ -95,6 +103,7 @@ pub fn build(b: *std.Build) void {
|
||||
});
|
||||
lib.root_module.addObject(clip_sse_obj);
|
||||
lib.root_module.addObject(bone_sse_obj);
|
||||
lib.root_module.addObject(bone_sse_ref_obj);
|
||||
lib.root_module.addObject(math_sse_obj);
|
||||
b.installArtifact(lib);
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -22,6 +22,7 @@ extern fn rayTriangleIntersection(u32, u32, u32, u32, u32, u32) u32;
|
||||
extern fn rotateMatrixByAxisAngle(u32, u32, u32, u32) void;
|
||||
extern fn multiplyMatrix4x4(u32, u32, u32) u32;
|
||||
extern fn transformMatrix4x4_SSE(u32, u32, u32, u32, u32) void;
|
||||
extern fn transformMatrix4x4_REF(u32, u32, u32, u32, u32) void;
|
||||
|
||||
pub const module_name: [*:0]const u8 = "transform44";
|
||||
|
||||
@@ -47,6 +48,13 @@ var last_frame_tsc: u64 = 0; // frame-to-frame TSC for total frame time
|
||||
// Flips every DUMP_FRAMES so each dump period is purely one mode.
|
||||
pub var ab_use_custom: bool = false;
|
||||
|
||||
// Teardown guard: set true when CleanupWorldAndEntities fires.
|
||||
// During teardown, SceneObject data may be partially freed — our SSE code
|
||||
// must not process it. Falls back to original function which the game
|
||||
// controls. NOTE: binary patching (instead of hooking) would avoid this
|
||||
// issue entirely since the patched code IS the original entry point.
|
||||
var teardown_active: bool = false;
|
||||
|
||||
|
||||
// Persistent blit totals per A/B mode — NOT reset each dump period.
|
||||
// Accumulates across all dump periods so rare blits still show up.
|
||||
@@ -236,8 +244,10 @@ fn transformDetour(this: u32, edx: u32, mat1: u32, mat2: u32, mat3: u32, mat4: u
|
||||
t44_depth +|= 1;
|
||||
if (t44_depth > prof.t44_max_depth) prof.t44_max_depth = t44_depth;
|
||||
|
||||
if (ab_use_custom) {
|
||||
transformMatrix4x4_SSE(this, mat1, mat2, mat3, mat4);
|
||||
if (ab_use_custom and !teardown_active) {
|
||||
// Using reference version for stress testing
|
||||
_ = transformMatrix4x4_SSE;
|
||||
transformMatrix4x4_REF(this, mat1, mat2, mat3, mat4);
|
||||
} else {
|
||||
transform_hook.callOriginal(.{ this, edx, mat1, mat2, mat3, mat4 });
|
||||
}
|
||||
@@ -320,6 +330,23 @@ fn worldUpdateDetour(frame_count: u32) callconv(hook.cc.fastcall) void {
|
||||
}
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// Hook: World_HandleLogoutCleanup (0x491180)
|
||||
// Fires at the START of the logout/disconnect cleanup sequence, BEFORE any
|
||||
// model data is freed. Sets teardown_active flag so our SSE code falls back
|
||||
// to the original function during the entire cleanup chain.
|
||||
// NOTE: binary patching instead of hooking would avoid this issue entirely.
|
||||
// =============================================================================
|
||||
|
||||
const TeardownFn = fn () callconv(.{ .x86_stdcall = .{} }) void;
|
||||
var teardown_hook: hook.Detour(TeardownFn) = .{};
|
||||
|
||||
fn teardownDetour() callconv(.{ .x86_stdcall = .{} }) void {
|
||||
teardown_active = true;
|
||||
teardown_hook.callOriginal(.{});
|
||||
teardown_active = false;
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// Hook: RenderTextureQuads (0x76FB00)
|
||||
// __fastcall(ECX=RenderBatch*) — no stack params, RET
|
||||
@@ -1379,6 +1406,7 @@ pub fn installHooks() void {
|
||||
_ = render_frame_hook.attach(0x707680, &renderFrameDetour);
|
||||
_ = exec_render_pass_hook.attach(0x708900, &execRenderPassDetour);
|
||||
_ = world_update_hook.attach(0x482EA0, &worldUpdateDetour);
|
||||
_ = teardown_hook.attach(0x491180, &teardownDetour);
|
||||
_ = render_quads_hook.attach(0x76FB00, &renderQuadsDetour);
|
||||
_ = movement_hook.attach(0x616620, &movementDetour);
|
||||
_ = interp_kf_hook.attach(0x713ea0, &interpKfDetour);
|
||||
@@ -1465,6 +1493,7 @@ pub fn removeHooks() void {
|
||||
render_frame_hook.detach();
|
||||
exec_render_pass_hook.detach();
|
||||
world_update_hook.detach();
|
||||
teardown_hook.detach();
|
||||
render_quads_hook.detach();
|
||||
movement_hook.detach();
|
||||
interp_kf_hook.detach();
|
||||
|
||||
Reference in New Issue
Block a user