forked from Ports/goldeneye-pc-port
D158: KF7 muzzle-flash stackpad2[-8] negative stack write -> crash on fire
gunUpdateAndFire's KF7 branch (`mdlhdr->Skeleton == &skeleton_gun_kf7`) does `((f32*)stackpad2)[-8] = ...` then reads it back into matrix_scalar_multiply -- a decomp register-allocation stackpad: a scratch f32 the N64 compiler placed 32 bytes below the `u8 stackpad2[4]` local. GCC's x86-64 stack layout is different, so the negative index scribbles into an unrelated stack slot (return-address / saved-reg area) -> 0xc000001d illegal-instruction the moment you fire a KF7. Found via scripted-input (walk+fire) testing: 12 campaign levels survived a firefight script, Caverns (-level_39) crashed reproducibly on a settled machine at gunfire.c:817. addr2line -> gunUpdateAndFire. The KF7 is a common campaign weapon (Facility/Surface/Caverns guards) so this would hit the user early. Fix: real `f32 kf7_flashscale` local under #ifdef PORT; N64 stackpad expression kept under #else. Caverns now survives repeated fire to frame 1500+; -level_09 unregressed. PORT-LEARNINGS §A (stackpad hazard).
This commit is contained in:
1 parent
3e5720c01b
commit
d439dfeaeb
1 file changed
+18
@@ -368,6 +368,16 @@ void gunUpdateAndFire(GUNHAND handnum)
|
||||
s32 sw7mtxidx;
|
||||
s32 shellidx;
|
||||
u8 stackpad2[4];
|
||||
#ifdef PORT
|
||||
/* D157-adjacent: `((f32 *)stackpad2)[-8]` (lines below) is a decomp
|
||||
* register-allocation stackpad hack — a scratch f32 the N64 compiler
|
||||
* placed 32 bytes *below* stackpad2. GCC's x86-64 stack layout is
|
||||
* different, so that negative index writes into an unrelated slot
|
||||
* (return-address / saved-reg area) → 0xc000001d illegal-instruction on
|
||||
* the KF7-muzzle-flash path (found firing on Caverns, M-30). Use a real
|
||||
* local; N64 keeps the stackpad expression under #else. */
|
||||
f32 kf7_flashscale;
|
||||
#endif
|
||||
|
||||
flashvisptr = NULL;
|
||||
flashdata = NULL;
|
||||
@@ -814,9 +824,17 @@ void gunUpdateAndFire(GUNHAND handnum)
|
||||
flashpos.x = (((((f32 *) nodepos)[0] * flashmtx.m[0][0]) + (((f32 *) nodepos)[1] * flashmtx.m[1][0])) + (((f32 *) nodepos)[2] * flashmtx.m[2][0])) + flashmtx.m[3][0];
|
||||
flashpos.y = (((((f32 *) nodepos)[0] * flashmtx.m[0][1]) + (((f32 *) nodepos)[1] * flashmtx.m[1][1])) + (((f32 *) nodepos)[2] * flashmtx.m[2][1])) + flashmtx.m[3][1];
|
||||
flashpos.z = (((((f32 *) nodepos)[0] * flashmtx.m[0][2]) + (((f32 *) nodepos)[1] * flashmtx.m[1][2])) + (((f32 *) nodepos)[2] * flashmtx.m[2][2])) + flashmtx.m[3][2];
|
||||
#ifdef PORT
|
||||
kf7_flashscale = IDO_POINT_ONE * flashscale;
|
||||
#else
|
||||
((f32 *) stackpad2)[-8] = IDO_POINT_ONE * flashscale;
|
||||
#endif
|
||||
matrix_4x4_align(&flash2mtx, (randomGetNext() * (1.0f / M_U32_MAX_VALUE_F)) * M_TAU_F, -flashpos.x, -flashpos.y, -flashpos.z);
|
||||
#ifdef PORT
|
||||
matrix_scalar_multiply(kf7_flashscale, flash2mtx.m[0]);
|
||||
#else
|
||||
matrix_scalar_multiply(((f32 *) stackpad2)[-8], flash2mtx.m[0]);
|
||||
#endif
|
||||
matrix_4x4_set_rotation_axis_angle(&aimmtx, 0, gunofs.x - hand->field_A38, gunofs.y - hand->field_A3C, gunofs.z - hand->field_A40);
|
||||
matrix_4x4_multiply_in_place(&aimmtx, &flash2mtx);
|
||||
matrix_row_3_scalar_multiply(flashext, flash2mtx.m[0]);
|
||||
|
||||
Reference in new issue
Block a user