From 2018ca45fa0c8bdd3b028fac351cbfa710e17e52 Mon Sep 17 00:00:00 2001 From: MarcelineVQ Date: Sat, 14 Mar 2026 17:45:46 -0700 Subject: [PATCH] bone_sse: fix IsParticleBufferEmpty calling convention MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Was __stdcall with stack param — would corrupt stack for every visible particle emitter. Fixed to __fastcall(ECX=ptr) matching assembly at 0x717EB8: MOV ECX,[EBP-0x10]; CALL 0x7B5F60. Plain RET, no stack cleanup. Bug #14 found during final verification pass. --- src/transform44/bone_sse.zig | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/transform44/bone_sse.zig b/src/transform44/bone_sse.zig index e7aa5e5..474885b 100644 --- a/src/transform44/bone_sse.zig +++ b/src/transform44/bone_sse.zig @@ -1908,8 +1908,10 @@ fn additionalParticleLoops(this: u32, model_hdr: u32) void { buf_active = 1; } else { // Call IsParticleBufferEmpty (0x7B5F60) - const isEmptyFn: *const fn (u32) callconv(.{ .x86_stdcall = .{} }) u32 = @ptrFromInt(0x7B5F60); - if (isEmptyFn(@intFromPtr(&local_14)) != 0) { + // Assembly: MOV ECX,[EBP-0x10]; CALL 0x7B5F60 + // __thiscall(ECX=ptr), plain RET, returns 0 or 1 in EAX + const isEmptyFn: *const fn (u32) callconv(.{ .x86_fastcall = .{} }) u32 = @ptrFromInt(0x7B5F60); + if (isEmptyFn(local_14) != 0) { buf_active = 1; } }