D8696 : Collision type flags? = D8697 for F576 path 0x1: Collision object with different radii - within atmosphere 0x2: Distance valid? 0x10: Used for cargo 0x20: Within starport effect region 0x40: Landing 0x80: Crash D8697 : More type flags, only set in F576 path D8698 : Collision object index, F576 path only D8699 : 0 => landing, !0 => crash D8700 : Set at start to 0 or 0xff - planet crash mask D8701 : Chunk val for F576 path D8702 : Parent object ptr D8703 : Distance from object, 64-bit value D8704 : high dword of D8703 D8705 : Altitude, 64-bit value D8706 : high dword of D8705 D8707 : Planet var: 0: out of radius, 1: collision, -1: inside radius void F568 (p1, p2, p3, p4, p5, p6, p7) { b[D8700] = 0; F570 (p1, p2, p3, p4, p5, p6, p7); } void F569 (p1, p2, p3, p4, p5, p6, p7) { b[D8700] = 0xff; F570 (p1, p2, p3, p4, p5, p6, p7); } void F570 (PhysObj *p1, PhysObjList *p2, int flags, int parentindex, PhysObj **parptr, uint distance, int padindex) { b[D8696] = b[D8697] = b[D8698] = b[D8701] = 0; [D8703] = -1; b[D8707] = 0; if (b[p1+0x56] != 0) // valid parent object { [D8702] = esi = F1532 (b[p1+0x56], p2); // parent ptr memcpy (sb, p1+0x3e, 6*4); // Copy position s1.b3 = F575 (sb, p1, esi); if ([p1+0x148] != 0) { // decrement delay if ([D9155]/2 <= [p1+0x148]) [p1+0x148] -= [D9155]/2; else [p1+0x148] = 0; } else { // rot. FOR switching if (s1.b3 & 2) if (!b[p1+0x57]) { F572 (p1, esi); [p1+0x148] = 0x7f; } else if (b[p1+0x57]) { F573 (p1, esi); [p1+0x148] = 0x7f; } } } b[p4] = [p1+0x56]; s1.b3 = b[D8696]; for (edi=0x72, eax=p2+0x72, s2=eax; edi>0; edi--, s2--) { if (!(b[s2] & 4)) continue; // non-physical object? if (edi == b[p1+0x86]) continue; // self esi = F1532 (edi, p2); // target obj ptr if (b[esi+0x8b] != 0) contine; // rendering exclusion? if (b[p4] != b[esi+0x56]) continue; // not same parent if ([esi+0x99]==0 && [p1+0x99]!=0) continue; if (b[p1+0x57] != b[esi+0x57) { F1677 (sb, p1); F1677 (sb2, esi); // global vectors Vec64Sub (sb, sb2); // relative vector } else { memcpy (sb, p1+0x3e, 6*4); Vec64Sub (sb, esi+0x3e); // relative vector } F575 (sb, p1, esi); // collide } b[D8696] |= s1.b3; // rval from parent collision test if ([D8704] != 0 || [D8703] < 0) [p6] = -1; else [p6] = [D8703]; // distance [p5] = [D8702]; // parent object ptr b[p7] = b[D8701] & 0x1f; // pad index? b[p4] = b[D8698]; // collision object index b[p3] = b[D8696]; // flags return b[D8696]; } // negates x, swaps y/z void F571 (Mat32 *p1) { s3 = [p1+0x18]; s2 = [p1+0x1c]; s1 = [p1+0x20]; [p1+0x18] = [p1+0xc]; [p1+0x1c] = [p1+0x10]; [p1+0x29] = [p1+0x14]; [p1+0xc] = s3; [p1+0x10] = s2; [p1+0x14] = s1; -[p1+0x0]; -[p1+0x4]; -[p1+0x8]; } // Switch to rot. FOR void F572 (PhysObj *p1, OrbitalObj *p2) { edi = Vec64Truncate (p1+0x3e, 0x1c); Vec32 tv = (Vec64)[p1+0x3e]; VecMatTMul (&tv, &tv, p2); // Transform position F1517 (p1+0x3e, &tv, edi); // shift back MatTMatMul (p1, p1, p2); // Transform orientation [p1+0x58] = b[D8811] - 1; // Set last update frame b[p1+0x57] = 1; VecMatTMul (p1+0x8c, p1+0x8c, p2); // Transform velocity } // Switch to linear FOR void F573 (PhysObj *p1, OrbitalObj *p2) { edi = Vec64Truncate (p1+0x3e, 0x1c); Vec32 tv = (Vec64)[p1+0x3e]; VecMatMul (&tv, &tv, p2); // Transform position F1517 (p1+0x3e, &tv, edi); // shift back MatMatMul (p1, p1, p2); // Transform orientation // [p1+0x58] = b[D8811] - 1; // Missing? b[p1+0x57] = 0; VecMatMul (p1+0x8c, p1+0x8c, p2); // Transform velocity } // Gets distance between two objects void F574 (int *distance, Vec64 *relpos, PhysObj *obj1, PhysObj *obj2) { b[D8698] = b[D8697] = b[D8698] = 0; b[D8700] = b[D8701] = 0; [D8703] = -1; b[D8701] = 0; F575 (p2, p3, p4); if ([D8704] != 0 || [D8703] < 0) [p1] = -1; else [p1] = [D8703]; } // Big collision func - handles planet/starport landings too int F575 (Vec64 *relpos, PhysObj *obj1, PhysObj *obj2) { memcpy (s-0x38, p1, 6*4); // save relpos Vec64Abs (p1, p1); Int64Add64 (s-8, [p1], [p1+4], [p1+8], [p1+0xc]); Int64Add64 (s-8, [s-8], [s-4], [p1+0x10], p1+0x14]); // |x|+|y|+|z| Int64ArithShift (s-8, -1); Int64Sub64 (s-8, [s-8], [s-4], [p2+0x138], [p2+0x13c]); if ([s-4] >= 0) { Int64Sub64 (s-8, [s-8], [s-4], [p3+0x138], [p3+0x13c]); if ([s-4] >= 0) return 0; // no interaction } b[D8707] = 0; if (b[p3+0x14c] < 0) // Complex object { if (F576 (p2, p3, s-0x38) == 0) { if (b[D8707] == 0) { // out of planet radius? F578 (p2, p3); return b[D8696]; } // passes through planet collision... } else return b[D8696]; } else { // simple object eax = F577 (&s3, p2, p3, [s-0x38], [s-0x34], ..., p1); if (eax == 0) { if (b[p3+0x86] != b[p2+0x56]) { // not current parent F578 (p2, p3); return b[D8696]; } b[D8707] = 2; // starport thing? } else return b[D8696]; } // more stuff. Planet collision only? b[D8696] |= 2; s4 = abs([p2+0x8c])+abs([p2+0x90])+abs([p2+0x94]); if (b[D8707] == 1) { // surface hit memcpy (s-0x50, s-0x38, 6*4); Vec64Truncate (s-0x50, 0x1c); [s-0x80]=[s-0x50]; [s-0x7c]=[s-0x48]; [s-0x78]=[s-0x40]; F1503 (s-0x80, 0x7fffffff); // set magnitude } else { [s-0x80]=[s-0x38]; [s-0x7c]=[s-0x30]; [s-0x78]=[s-0x28]; F1519 (s-0x80, s-0x80); // fix31 normalise } esi = Vec32Dot (p2+0xc, s-0x80); if (s4<=0x258 && w[p2+0x9e]==-1 && esi >= 0x78000000) { b[D8696] |= 0x40; // set landed b[D8696] &= 0x7f; // clear collision b[D8699] = 0; } else b[D8699] = b[D8700]; // some sort of masking thing s6 = F1538 ([p2+0x82]); edx = F1538 ([p3+0x82]); if (b[D8707] == 1) { Int64Sub64 (s-0x20, [p2+0x140], [p2+0x144], [D8705], [D8706]); Vec64 tdv = (Vec32)[s-0x80] * [s-0x20]; Vec64Add (p2+0x3e, p2+0x3e, &tdv); // modify height by diff } else { eax = [edx+0x2c] << 16; esi = [edx+0x14] + [edx+0x18]; edx = esi - [s6+0x14] - [s6+0x18]; s5 = [s6+0x30] << 16; if (edx != 0) s5 >>= edx; if ((eax += s5) < 0) { eax >>= 1; s3++; } Vec32 tv = (Vec64)[s-0x38]; F1504 (&tv, eax, s3); // magnitude setter eax = 0x20 - ((0x37 - esi) + 1); (Vec64)[p2+0x3e] = (Vec32)tv << eax; // set height to radius } if (b[D8699] != 0) { // collision, not landing b[D8696] |= 0x80; if (b[p2+0x86] == b[D8857]) // player object! Woo! { // bounce player object } else if ([p2+0x82] > 0xd && (b[p2+0x87] == 0xb || b[p2+0x87] == 0xe)) { // bounce AI object... } } else { // reorientate } if ([p3+0x140] != [p3+0x138]) b[D8696] |= 1; if (b[D8698] == 0) { b[D8698] = b[p3+0x86]; [D8702] = p3; } return b[D8696]; } // Only one heirachial layer // word stream backwards from model+0x34 // primary radius defined by PhysObj+0x140 // word stream : first word distance in local units // second word &7 => direction, rest => radius (local units) // scale: everything shifted by 0x17 - model+0x14 F576 (PhysObj *obj1, PhysObj *obj2, Vec64 *relpos) { b[D8697] = 0; eax = F1538 ([p1+0x82]); // get model info s3 = 0x17 - [eax+0x14]; // scale s1 = [eax+0x34]; // collision data ebx = [p1+0x140]; // "real" radius? Vec64Copy (s-0x24, p3); while (1) { al = F579 (&s2.b3, p1, p2, s-0x24, ebx); // do collision if (al > 0) b[D8697] |= 0x80; // default action? if (b[D8697] != 0) { // Hmm. b[D8698] = b[p2+0x86]; // collision object index [D8702] = p2; // collision object b[D8696] = b[D8697]; b[D8701] = s2.b3; // debug thing? ebx from F582 } if (al >= 0) return 0; // collision if (b[p1+0x14c] >= 0) return -1; // impossible - not called s1 -= 2; eax = w[s1]; // distance (local units) if (eax == 0) return -1; // Not collision s1 -= 2; ebx = w[si]; // radius | direction switch (ebx & 6) { case 0: Vec32Copy (s-0x30, p1); break; case 2: Vec32Copy (s-0x30, p1+0xc); break; case 4: Vec32Copy (s-0x30, p1+0x18); break; } if (ebx & 1) Vec32Neg (s-0x30); [s-0x30] = ([s-0x30] >> 16) * eax; [s-0x2c] = ([s-0x2c] >> 16) * eax; [s-0x28] = ([s-0x28] >> 16) * eax; ebx = (ebx & 0xfff8) << 15; if (s3 != 0) { Vec32ShiftR (s-0x30, s3); ebx >>= s3; } Int64Add32 (s-0x24, [p3+0x0], [p3+0x4], [s-0x30]); Int64Add32 (s-0x1c, [p3+0x8], [p3+0xc], [s-0x30]); Int64Add32 (s-0x14, [p3+0x10], [p3+0x14], [s-0x30]); } } // Simple radius collision function // returns 0: collision, -1: no collision int F577 (int *p1, PhysObj *obj1, PhysObj *p2, Vec64 relpos, Vec64 *abspos) { s1 = p5->xh | p5->yh | p5->zh | [p3+0x13c]; if (s1 != 0) ebx = FindMSB (s1) + 3; else ebx = FindMSB (p5->xl | p5->yl | p5->zl | [p3+0x138]) - 0x1d; if (ebx<=0) { s2 = [p2+0x140] + [p3+0x138] << -ebx; // assumption? bug? p4.xl >>= -ebx; p4.yl >>= -ebx; p4.zl >>= -ebx; } else { Vec64Shift (&p4, ebx); Int64Add64 (&s4, [p3+0x138], [p3+0x13c], [p2+0x138], [p2+0x13c]); Int64ArithShift (&s4, -ebx); s2 = s4; } [p1] = F1522 (p4.xl) + F1522 (p4.yl) + F1522 (p4.zl); if (F1522 (s2) > [p1]) return 0; // collision b[D8696] |= 2; [D8703] = F1502 ([p1]>>1) * 2; // distance to object if ([D8703] < 0) [D8703] = 0; // impossible? [D8704] = 0; Int64ArithShift (D8703, ebx); // correct distance if ([p3+0x140] != [p3+0x138]) b[D8696] |= 1; // different radii... return -1; // no collision } // radius and pos in same units. // Velocity? <16? // damage - use veldiffmag // veldiffmag should be *negative* // otherwise ignore. // Direction: Vec64Sub (colldir, p2+0x3e, p1+0x3e); // pos2 relative to pos1 shift = Vec64Truncate (colldir, 0xd); Vec64to32 (colldir32, colldir); Int64Add (combrad, [p1+0x138], [p2+0x138]); Vec64Mul (colloff, colldir, combrad); Vec64Shift (colloff, shift); Vec64Add (p2+0x3e, p1+0x3e, colloff); // Velocity: Vec32Sub (veldiff, p2+0x8c, p1+0x8c); // vel2 relative to vel1 veldiffmag = -2 * Vec32Dot (colldir32, veldiff); Vec32Mul (veldiff, colldir32, veldiffmag); Vec32Add (p2+0x8c, p2+0x8c, veldiff); // Position offset Int64Add64 (ebp-0x20, [p1+0x138], [p1+0x13c], [p2+0x138], [p2+0x13c]); if ([ebp-0x1c]) radshift = FindMSB ([ebp-0x1c]) + 3; else radshift = FindMSB ([ebp-20]) - 0x1d; Int64ArithShift (ebp-0x20, -radshift); Vec32Mul (colloff, colldir, [ebp-0x20]); SignExtend (colloff); Vec64Shift (colloff, radshift); Vec64Add (p2+0x3e, p1+0x3e, colloff); stack: ebp-0x18: Vec64 colldir ebp-0x20: Int64 combrad ebp-0x38: Vec64 colloff ebp-0x3c: int dirshift ebp-0x48: Vec32 colldir32 ebp-0x54: Vec32 veldiff ebp-0x58: int radshift ; Direction ; Vec64Sub (colldir, p2+0x3e, p1+0x3e) lea eax, [ebx+0x3e] push eax lea eax, [esi+0x3e] push eax lea eax, [ebp-0x18] push eax call FUNC_001662_Vec64Sub add esp, 12 ; shift = Vec64Truncate (colldir, 0xd); push dword 0x1e ; 0x1f? 0x1e? lea eax, [ebp-0x18] push eax call FUNC_001658_Vec64Truncate add esp, 8 mov [ebp-0x3c], eax ; Vec64to32 (colldir32, colldir); mov eax, [ebp-0x18] mov [ebp-0x48], eax mov eax, [ebp-0x10] mov [ebp-0x44], eax mov eax, [ebp-0x8] mov [ebp-0x40], eax ; Velocity ; Vec32Sub (veldiff, p2+0x8c, p1+0x8c) mov eax, [esi+0x8c] sub eax, [ebx+0x8c] mov [ebp-0x54], eax mov eax, [esi+0x90] sub eax, [ebx+0x90] mov [ebp-0x50], eax mov eax, [esi+0x94] sub eax, [ebx+0x94] mov [ebp-0x4c], eax ; veldiffmag = -2 * Vec32Dot (colldir32, veldiff) push dword [ebp-0x54] push dword [ebp-0x48] call FUNC_001521 add esp, 8 push eax push dword [ebp-0x50] push dword [ebp-0x44] call FUNC_001521 add esp, 8 pop edx add eax, edx push eax push dword [ebp-0x4c] push dword [ebp-0x40] call FUNC_001521 add esp, 8 pop edx add eax, edx add eax, eax neg eax ; Vec32Mul (veldiff, colldir32, veldiffmag) mov edi, eax push edi push dword [ebp-0x48] call FUNC_001521 add esp, 8 mov [ebp-0x54], eax push edi push dword [ebp-0x44] call FUNC_001521 add esp, 8 mov [ebp-0x50], eax push edi push dword [ebp-0x40] call FUNC_001521 add esp, 8 mov [ebp-0x4c], eax ; Vec32Add (p2+0x8c, p2+0x8c, veldiff) mov eax, [ebp-0x54] add [esi+0x8c], eax mov eax, [ebp-0x50] add [esi+0x90], eax mov eax, [ebp-0x4c] add [esi+0x94], eax ; Position offset - unnecessary. push dword [esi+0x13c] push dword [esi+0x138] push dword [ebx+0x13c] push dword [ebx+0x138] lea eax, [ebp-0x20] push eax call FUNC_001333_Int64Add64 add esp, 20 ; if ([ebp-0x1c]) shift = FindMSB ([ebp-0x1c]) + 3; ; else shift = FindMSB ([ebp-20]) - 0x1d; cmp dword [ebp-0x1c], 0 jz .lowrad push dword [ebp-0x1c] call FUNC_001656_FindMSB add esp, 4 add eax, 3 jmp .highrad .lowrad: push dword [ebp-0x20] call FUNC_001656_FindMSB add esp, 4 sub eax, 0x1d .highrad: mov [ebp-0x58], eax ; Int64ArithShift (ebp-0x20, -msb); neg eax push eax lea eax, [ebp-0x20] push eax call FUNC_001341_Int64ArithShift add esp, 8 ; Vec32Mul (colloff, colldir, [ebp-0x20]); ; SignExtend (colloff); mov edi, [ebp-0x20] push edi push dword [ebp-0x48] call FUNC_001521 add esp, 8 cdq mov [ebp-0x38], eax mov [ebp-0x34], edx push edi push dword [ebp-0x44] call FUNC_001521 add esp, 8 cdq mov [ebp-0x30], eax mov [ebp-0x2c], edx push edi push dword [ebp-0x40] call FUNC_001521 add esp, 8 cdq mov [ebp-0x28], eax mov [ebp-0x24], edx ; Vec64Shift (colloff, shift); push dword [ebp-0x58] lea eax, [ebp-0x38] push eax call FUNC_001660_Vec64Shift add esp, 8 ; Vec64Add (p2+0x3e, p1+0x3e, colloff); lea eax, [ebx+0x3e] push eax lea eax, [ebp-0x38] push eax call FUNC_001661_Vec64Add add esp, 12 Vec64Copy... to p2+0x3e // Collision damage function, obj1 vs. obj2 void F578 (PhysObj *obj1, PhysObj *obj2) { b[D8696] |= 0x80; if (b[p1+0x56]==b[p2+0x86] || b[p2+0x87]==1) // parent or... { [p1+0x8c] = -[p1+0x8c] >> 2; [p1+0x90] = -[p1+0x90] >> 2; [p1+0x94] = -[p1+0x94] >> 2; // bounce... esi = abs([p1+0x8c])+abs([p1+0x90])+abs([p1+0x94]); if ([p1+0x82] <= 0xd) return; // missile F953 (p1, esi, 0); return; } [p1+0x8c] = [p2+0x8c] = [p1+0x8c] + [p2+0x8c] >> 1; [p1+0x90] = [p2+0x90] = [p1+0x90] + [p2+0x90] >> 1; [p1+0x94] = [p2+0x94] = [p1+0x94] + [p2+0x94] >> 1; // equalise speed if (b[D8700] == 0) return; if ([p1+0x82] <= 0xd || [p2+0x82] <= 0xd) return; // BUG!! if (w[p2+0xe4] <= w[p1+0xe4]) { F953 (p2, w[p2+0xe4]*2, b[p1+0x86]); F953 (p1, w[p2+0xe4]*2, b[p2+0x86]); // damage! } else { F953 (p2, w[p1+0xe4]*2, b[p1+0x86]); F953 (p1, w[p1+0xe4]*2, b[p2+0x86]); } } struct CollInfo { Vec32 relpos; MeshNormal *pNorm; MeshVertex *pVtx; int meshzoom; int vecscale; } // Translation wrapper for complex collision func F582 int F579 (char *p1, PhysObj *obj1, PhysObj *obj2, Vec64 *meshpos, int radius) { CollInfo c; ebx = F1538 ([p3+0x82]); c.pNorm = [ebx+0xc]; c.pVertex = [ebx+0x4]; c.meshzoom = [ebx+0x14] + [ebx+0x18]; c.vecscale = Vec64Truncate (p4, 0x1c); // s1 = distance shifted Vec64to32 (&c.relpos, p4); eax = c.vecscale - c.meshzoom + 0x17; // distance shifted minus distance req'd if (eax < 0) { c.vecscale -= eax; Vec32ShiftR (&c.relpos, eax); } if (c.vecscale < 0) p5 <<= -c.vecscale; else if (c.vecscale > 0) p5 >>= c.vecscale; // compensate with radius if (b[p2+0x57] == 0 || b[p2+0x56] != b[p3+0x86]) VecMatTMul (&c.relpos, &c.relpos, p3); // Correct relative position return F582 (p1, &c, [ebx+0x34], p3, p5); } // Heirachial object function // recursively calls F582 for a child chunk int F580 (char *p1, CollInfo *collinfo, int modelidx, int vertexidx, int orientation, int radius, PhysObj *obj) { CollInfo c; Vec32 tv; esi = F1538 (p3); // erk c.pNorm = [esi+0xc]; c.pVertex = [esi+0x4]; c.meshzoom = [esi+0x14] + [esi+0x18]; c.vecscale = collinfo->vecscale; s2 = [collinfo->pVtx + (p4>>1)*6]; s1 = w[collinfo->pVtx + (p4>>1)*6 + 4]; if (b[p4] & 1) tv.x = -s2.b2; else tv.x = s2.b2; tv.y = s2.b3; tv.z = s1.b0; eax = collinfo->meshzoom - collinfo->vecscale; if (eax < 0) Vec32RShift (&tv, -eax); else Vec32LShift (&tv, eax); Vec32Subtract (&tv, &collinfo->relpos, &tv); if (b[p5] == 0) Vec32Copy (&c.relpos, &tv); else { if (p5 & 0x20) tv.x = -tv.x; if (p5 & 0x10) tv.y = -tv.y; if (p5 & 0x8) tv.z = -tv.z; switch (p5 & 7) { case 0: c.relpos.x = tv.x; c.relpos.y = tv.y; c.relpos.z = tv.z; break; case 1: c.relpos.x = tv.z; c.relpos.y = tv.x; c.relpos.z = tv.y; break; case 2: c.relpos.x = tv.y; c.relpos.y = tv.z; c.relpos.z = tv.x; break; case 3: c.relpos.x = tv.z; c.relpos.y = tv.y; c.relpos.z = tv.x; break; case 4: c.relpos.x = tv.y; c.relpos.y = tv.x; c.relpos.z = tv.z; break; case 5: c.relpos.x = tv.x; c.relpos.y = tv.z; c.relpos.z = tv.y; break; } } return F582 (p1, &c, [esi+0x34], p7, p6); } // Collision check against terrain CollStream *F581 (int *rval, CollStream *coll, PhysObj *obj, int radius, CollInfo *collinfo) { eax = b[p2]; edx = b[p2+1]; ebx = b[p2+2]; s2 = b[p2+5]<<8 | b[p2+4]; s1 = b[p2+3]; b[D8707] = 0xff; s4 = [[collinfo->pVtx + 6*(eax>>1)]; s3 = w[[collinfo->pVtx + 6*(eax>>1) + 4]; if (eax&1) tv.x = -s4.b2; else tv1.x = s4.b2; tv1.y = s4.b3; tv1.z = s3.b0; s4 = [[collinfo->pVtx + 6*(edx>>1)]; s3 = w[[collinfo->pVtx + 6*(edx>>1) + 4]; if (edx&1) tv2.x = -s4.b2; else tv2.x = s4.b2; tv2.y = s4.b3; tv2.z = s3.b0; s4 = [[collinfo->pVtx + 6*(ebx>>1)]; s3 = w[[collinfo->pVtx + 6*(ebx>>1) + 4]; if (ebx&1) tv3.x = -s4.b2; else tv3.x = s4.b2; tv3.y = s4.b3; tv3.z = s3.b0; s4 = [[collinfo->pVtx + 6*(s1>>1)]; s3 = w[[collinfo->pVtx + 6*(s1>>1) + 4]; if (s1&1) tv4.x = -s4.b2; else tv4.x = s4.b2; tv4.y = s4.b3; tv4.z = s3.b0; eax = collinfo->meshzoom - collinfo->vecscale; if (eax < 0) Right-shift tv1 to tv4 else left shift tv1 to tv4 tv2 -= tv1; tv3 -= tv1; tv4 -= tv1; tv1 -= collinfo->relpos; s5 = F1466 (&tv1); s8 = [p3+0x138]; s7 = [p3+0x13c]; Int64ArithShift (&s8, -collinfo->vecscale); if (s5-s8 >= p4) { [p1] = -1; b[D8707] = 0; return F1822 (p2+6); } if (tv1.x != 0) { tv5.x = tv1.x; tv5.y = tv2.y; tv5.z = 0; edi = F1466 (&tv5); if (tv5.x < 0) { ebx = F1523 (-tv5.x, edi); if (ebx<0) ebx = 0x7fffffff; else ebx = -ebx; } else { ebx = F1523 (tv5.x, edi); if (ebx<0) ebx = 0x7fffffff; } if (tv5.y < 0) { esi = F1523 (-tv5.y, edi); if (esi<0) esi = 0x7fffffff; else esi = -esi; } else { esi = F1523 (tv5.y, edi); if (esi<0) esi = 0x7fffffff; } tv6 = { esi, ebx, 0 }; tv7 = { -ebx, esi, 0 }; tv8 = { 0, 0, 0x7fffffff }; tv1.y = edi; } else { tv6 = { 0, 0, 0x7fffffff }; tv7 = { 0, 0x7fffffff, 0 }; tv8 = { 0, 0, 0x7fffffff }; } if (tv1.y != 0) { tv9.x = 0; tv9.y = tv1.y; tv9.z = tv1.z; edi = F1466 (&tv9); if (tv9.y < 0) { ebx = F1523 (-tv9.y, edi); if (ebx<0) ebx = 0x7fffffff; else ebx = -ebx; } else { ebx = F1523 (tv9.y, edi); if (ebx<0) ebx = 0x7fffffff; } if (tv9.z < 0) { esi = F1523 (-tv9.z, edi); if (esi<0) esi = 0x7fffffff; else esi = -esi; } else { esi = F1523 (tv9.z, edi); if (esi<0) esi = 0x7fffffff; } tv6.z = F1521 (tv6.y, ebx); tv6.y = F1521 (tv6.y, esi); tv7.z = F1521 (tv7.y, ebx); tv7.y = F1521 (tv7.y, esi); tv8.y = -ebx; tv8.z = esi; } tv1 = { 0, 0, s4 }; VecMatMul (&tv2, &tv2, &tv876); VecMatMul (&tv3, &tv3, &tv876); VecMatMul (&tv4, &tv4, &tv876); p2 = F1876 (&s6, 0x77359400>>collinfo->vecscale, p3, 0, p2+6, &tv1, &tv2, s2, 0, 0, 0, 1); if (p4 >> 0x10 > s6) [p1] = 0; else [p1] = -1; edx = 0x77359400 >> collinfo->vecscale; // max height if (edx > s6) { [D8703] = s6; [D8704] = s6 >> 31; Int64ArithShift (D8703, collinfo->vecscale); } // altitude [D8705] = [D8703]; [D8706] = [D8704]; if ([p1] == 0) { [D8703] = [D8704] = 0; b[D8707] = 1; } return p2; } // processes collstream versus sphere // returns 0: collision, -1: no collision 1: nothing happened // first byte type, second byte returned on collision? // second byte ORed with b[D8769]. If 0x80 not set, no collision, just mark. // 0x80 of b[D8769] only set on collision int F582 (char *p1, CollInfo *collinfo, CollStream *coll, PhysObj *obj, int radius) { for (esi=p3, ebx=b[esi++]; ebx != 0; ebx = b[esi++]) { s1 = b[esi++]; if (ebx & 0x20) // animation thing - optional disabling { edx = w[p4+b[esi++]*2+0x9c]; eax = b[esi++]; edx >>= eax & 0x1f; if ((edx^(eax>>7))&1) switch (ebx & 0xc0) { case 0: edi = b[esi++]; if (edi == 0xff) { esi = F1822 (esi+6); continue; } if (edi == 0) continue; while (b[esi++] != 0); continue; case 0x40: while (b[esi++] != 0); continue; case 0x80: esi += 4; continue; case 0xc0: while (b[esi++] != 0); continue; } } switch (ebx & 0xc0) { case 0: edi = b[esi++]; if (edi == 0xff) { esi = F581 (&s2, esi, p4, p5, p2); if (s2 == 0) { b[D8697] |= s1; b[p1] = ebx; return 0; } else { b[D8697] |= s1 & 0x7f; continue; } } for (; edi != 0; edi = b[esi++]) { eax = F583 (p5, edi, p2); if (eax != 0) { b[D8697] |= s1 & 0x7f; b[p1] = ebx; return -1; } // if any outside, no collision } continue; case 0x40: // if outside all, don't collide do { edi = b[esi++]; if (edi == 0) { b[D8697] |= s1 & 0x7f; b[p1] = ebx; return -1; // not collision } } while (F583 (p5, edi, p2) != 0); while (b[esi++] != 0); continue; case 0x80: // J2525 edi = (b[esi++] << 8) | b[esi++]; // recursion - model edx = b[esi++]; eax = b[esi++]; // orientation, vertex eax = F580 (p1, p2, edi, eax, edx, p5, p4); b[D8701] |= [p1]; if (eax < 0) { // exclusion case b[D8697] |= s1 & 0x7f; b[p1] = ebx; return -1; } if (eax > 0) continue; // no collision found b[D8697] |= s1; if (!(s1&0x80)) continue; // Only mark, not return b[p1] = ebx; return 0; case 0xc0: // if inside all and s1&0x80, collide do { edi = b[esi++]; if (edi == 0) { b[D8697] |= s1; if (s1&0x80) { b[p1] = ebx; return 0; } } } while (F583 (p5, edi, p2) == 0); while (b[esi++] != 0); continue; } } b[p1] = 0; return 1; } // Collides sphere with "surface" - dependent on normal? // Ah. Returns zero if sphere intersects or is inside plane, else 1. int F583 (int radius, int surfaceindex, CollInfo *collinfo) { s2 = [collinfo->pNorm + (p2>>1)*6 - 6]; s1 = w[collinfo->pNorm + (p2>>1)*6 - 2]; // expanded normal s4 = [collinfo->pVtx + (s2.b1>>1)*6]; s3 = w[collinfo->pVtx + (s2.b1>>1)*6 + 4]; // expanded vertex if (p2&1) s2.b2 = -s2.b2; tv1.x = s2.b2 << 8; tv1.y = s2.b3 << 8; tv1.z = s1.b0 << 8; if (s2.b0&1) s4.b2 = -s4.b2; eax = c.meshzoom - c.vecscale; if (eax < 0) { tv2.x = s4.b2 >> -eax; tv2.y = s4.b3 >> -eax; tv2.z = s3.b0 >> -eax; } else { tv2.x = s4.b2 << eax; tv2.y = s4.b3 << eax; tv2.z = s3.b0 << eax; } Vec32Subtract (&tv2, &collinfo->relpos); ebx = abs (tv2.x) + abs (tv2.y) + abs (tv2.z); eax = FindMSB (ebx) - 0xd; if (eax < 0) eax = 0; edx = (tv2.x>>eax)*tv1.x + (tv2.y>>eax)*tv1.y + (tv2.z>>eax)*tv1.z; edx = -2 * edx; return edx >= (p1 >> eax); } cmp dword [logfile], 0 jnz .endopen push dword pLogAttrib push dword pLogName call _fopen add esp,byte +0x8 mov [logfile], eax .endopen: ; Print "Collision!" push dword pLogString push dword [logfile] call _fprintf call _fflush add esp, 8 ; Obj1 stats: ;radius push dword [ebx+0x138] push dword [ebx+0x13c] ;vel push dword [ebx+0x94] push dword [ebx+0x90] push dword [ebx+0x8c] ;position push dword [ebx+0x4e] push dword [ebx+0x52] push dword [ebx+0x46] push dword [ebx+0x4a] push dword [ebx+0x3e] push dword [ebx+0x42] ;index movzx eax, byte [ebx+0x86] push eax push dword pLogString2 push dword [logfile] call _fprintf call _fflush add esp, 56 ; Obj2 stats: ;radius push dword [esi+0x138] push dword [esi+0x13c] ;vel push dword [esi+0x94] push dword [esi+0x90] push dword [esi+0x8c] ;position push dword [esi+0x4e] push dword [esi+0x52] push dword [esi+0x46] push dword [esi+0x4a] push dword [esi+0x3e] push dword [esi+0x42] ;index movzx eax, byte [esi+0x86] push eax push dword pLogString2 push dword [logfile] call _fprintf call _fflush add esp, 56 ; Direction ; Vec64Sub (colldir, p2+0x3e, p1+0x3e) push esi lea esi, [esi+0x3e] lea edi, [ebp-0x18] mov ecx, 6 rep movsd pop esi push dword [ebp-0x8] push dword [ebp-0x4] push dword [ebp-0x10] push dword [ebp-0xc] push dword [ebp-0x18] push dword [ebp-0x14] push dword pLogString7 push dword [logfile] call _fprintf call _fflush add esp, 32 lea eax, [ebx+0x3e] push eax lea eax, [ebp-0x18] push eax call FUNC_001662_Vec64Sub add esp, 8 push dword [ebp-0x8] push dword [ebp-0x4] push dword [ebp-0x10] push dword [ebp-0xc] push dword [ebp-0x18] push dword [ebp-0x14] push dword pLogString7 push dword [logfile] call _fprintf call _fflush add esp, 32 ; shift = Vec64Truncate (colldir, 0xd); push dword 0x1e ; 0x1f? 0x1e? lea eax, [ebp-0x18] push eax call FUNC_001658_Vec64Truncate add esp, 8 push dword [ebp-0x8] push dword [ebp-0x4] push dword [ebp-0x10] push dword [ebp-0xc] push dword [ebp-0x18] push dword [ebp-0x14] push dword pLogString7 push dword [logfile] call _fprintf call _fflush add esp, 32 ; Vec64to32 (colldir32, colldir); ; Vec32Normalise (colldir32); mov eax, [ebp-0x18] mov [ebp-0x48], eax mov eax, [ebp-0x10] mov [ebp-0x44], eax mov eax, [ebp-0x8] mov [ebp-0x40], eax lea eax, [ebp-0x48] push eax lea eax, [ebp-0x48] push eax call FUNC_001519 add esp, 8 push dword [ebp-0x40] push dword [ebp-0x44] push dword [ebp-0x48] push dword pLogString4 push dword [logfile] call _fprintf call _fflush add esp, 20 ; Velocity ; Vec32Sub (veldiff, p2+0x8c, p1+0x8c) mov eax, [esi+0x8c] sub eax, [ebx+0x8c] mov [ebp-0x54], eax mov eax, [esi+0x90] sub eax, [ebx+0x90] mov [ebp-0x50], eax mov eax, [esi+0x94] sub eax, [ebx+0x94] mov [ebp-0x4c], eax push dword [ebp-0x4c] push dword [ebp-0x50] push dword [ebp-0x54] push dword pLogString5 push dword [logfile] call _fprintf call _fflush add esp, 20 ; veldiffmag = -2 * Vec32Dot (colldir32, veldiff) push dword [ebp-0x54] push dword [ebp-0x48] call FUNC_001521 add esp, 8 push eax push dword [ebp-0x50] push dword [ebp-0x44] call FUNC_001521 add esp, 8 pop edx add eax, edx push eax push dword [ebp-0x4c] push dword [ebp-0x40] call FUNC_001521 add esp, 8 pop edx add eax, edx push eax push dword pLogString6 push dword [logfile] call _fprintf call _fflush add esp, 8 pop eax ; -2 times, check negative. add eax, eax neg eax test eax, eax jl near JUMP_002457 ; Vec32Mul (veldiff, colldir32, veldiffmag) mov edi, eax push edi push dword [ebp-0x48] call FUNC_001521 add esp, 8 mov [ebp-0x54], eax push edi push dword [ebp-0x44] call FUNC_001521 add esp, 8 mov [ebp-0x50], eax push edi push dword [ebp-0x40] call FUNC_001521 add esp, 8 mov [ebp-0x4c], eax push dword [ebp-0x4c] push dword [ebp-0x50] push dword [ebp-0x54] push dword pLogString5 push dword [logfile] call _fprintf call _fflush add esp, 20 ; Vec32Add (p2+0x8c, p2+0x8c, veldiff) mov eax, [ebp-0x54] add [esi+0x8c], eax mov eax, [ebp-0x50] add [esi+0x90], eax mov eax, [ebp-0x4c] add [esi+0x94], eax ; Apply damage. veldiffmag * w[p2+0xe4] / factor push dword [esi+0x82] call FUNC_001538 add esp, 4 mov eax, [eax+0x38] movzx eax, word [eax+0x6] xor edx, edx mul edi mov ecx, 10000 div ecx mov edi, eax movzx eax, byte [esi+0x86] push eax push edi push ebx call FUNC_000953 add esp,byte +0xc movzx eax, byte [ebx+0x86] push eax push edi push esi call FUNC_000953 add esp,byte +0xc