particle: faithful RenderParticleSprites recreation, A/B verified
Full recreation of RenderParticleSprites (0x7B2A50, 2688 bytes) in particle_sse.zig. All 5 code paths: 2D billboard, 3D billboard, 2D+rotation (sin/cos), 3D+rotation (axis-angle matrix), tail particles. Key fixes during verification: - colorCtx address: removed Ghidra's spurious -0x12 offset - calcColor arg2: pass raw u32 from emitter+0x1A8, not truncated - Texture coord lookups: +8 offset to match assembly's eax increment between position and texcoord reads in the vertex loop Verified in-game: particles render identically in CUSTOM vs BASELINE. Next: optimize with SSE (inline calcColor, V4 vertex math).
This commit is contained in:
@@ -23,6 +23,7 @@ extern fn rotateMatrixByAxisAngle(u32, u32, u32, u32) void;
|
||||
extern fn multiplyMatrix4x4(u32, u32, u32) u32;
|
||||
extern fn transformImpl_SSE(u32, u32, u32, u32, u32) callconv(.c) void;
|
||||
extern fn calcColorValues_SSE(u32, u32, u32, u32, u32, u32, u32) callconv(.{ .x86_thiscall = .{} }) void;
|
||||
extern fn renderParticleSprites_SSE(u32, u32, u32) callconv(.{ .x86_thiscall = .{} }) u32;
|
||||
|
||||
/// Thiscall wrapper for the SSE implementation. Lives here (baseline SSE2 unit)
|
||||
/// so LLVM can't inline transformImpl_SSE's alignment into the thiscall frame.
|
||||
@@ -925,7 +926,14 @@ fn glyphDetour(a: u32, b: u32, c: u32, d: u32) callconv(hook.cc.fastcall) ?*anyo
|
||||
return ret;
|
||||
}
|
||||
fn particleDetour(a: u32, b: u32, c: u32, d: u32) callconv(hook.cc.fastcall) ?*anyopaque {
|
||||
// a=ECX(emitter), b=EDX(unused), c=particleData, d=vertexBuffers
|
||||
const s = rdtsc();
|
||||
if (ab_use_custom) {
|
||||
const result = renderParticleSprites_SSE(a, c, d);
|
||||
prof.particle_cycles +|= rdtsc() - s;
|
||||
prof.particle_calls +|= 1;
|
||||
return @ptrFromInt(result);
|
||||
}
|
||||
const ret = particle_hook.callOriginal(.{ a, b, c, d });
|
||||
prof.particle_cycles +|= rdtsc() - s;
|
||||
prof.particle_calls +|= 1;
|
||||
|
||||
Reference in New Issue
Block a user