CTR-ModSDK/ghidra/Particles.c
2024-04-14 04:42:54 -07:00

1629 lines
48 KiB
C

// Particle_FuncPtr_PotionShatter
void FUN_8003eae0(int param_1)
{
short sVar2;
int iVar1;
if (*(short *)(param_1 + 0x30) < 0x578) {
if (*(short *)(param_1 + 0x28) != 0) goto LAB_8003ebc8;
// Get random number
iVar1 = FUN_8003ea28();
*(short *)(param_1 + 0x28) = (short)iVar1 + (short)(iVar1 / 800) * -800 + -400;
// Get random number
iVar1 = FUN_8003ea28();
*(short *)(param_1 + 0x38) = (short)iVar1 + (short)(iVar1 / 800) * -800 + -400;
// Get random number
iVar1 = FUN_8003ea28();
sVar2 = (short)((uint)iVar1 >> 8);
if (iVar1 < 0) {
sVar2 = (short)((uint)(iVar1 + 0xff) >> 8);
}
*(short *)(param_1 + 0x50) = (short)iVar1 + sVar2 * -0x100 + 0x100;
}
if (*(short *)(param_1 + 0x28) == 0) {
return;
}
LAB_8003ebc8:
if (*(int *)(param_1 + 0x20) == 0x45) {
if (0 < *(int *)(param_1 + 100)) {
*(int *)(param_1 + 100) = *(int *)(param_1 + 100) + -0x1200;
}
}
else {
if (0 < *(int *)(param_1 + 0x5c)) {
*(int *)(param_1 + 0x5c) = *(int *)(param_1 + 0x5c) + -0x1200;
}
}
return;
}
// Particle_FuncPtr_SpitTire
void FUN_8003ec18(int param_1)
{
int iVar1;
int iVar2;
if (*(int *)(param_1 + 0x2c) >> 8 < *(int *)(*(int *)(param_1 + 0x20) + 0x48) + 0x10)
{
// Get random number
iVar1 = FUN_8003ea28();
*(short *)(param_1 + 0x28) = (short)iVar1 + (short)(iVar1 / 0x1640) * -0x1640 + -0xb20;
// Get random number
iVar1 = FUN_8003ea28();
iVar2 = *(int *)(param_1 + 0x4c);
*(short *)(param_1 + 0x38) = (short)iVar1 + (short)(iVar1 / 0x1640) * -0x1640 + -0xb20;
if (iVar2 == 0x1000)
{
// Get random number
iVar1 = FUN_8003ea28();
*(short *)(param_1 + 0x30) = (short)iVar1 + (short)(iVar1 / 0x12c0) * -0x12c0 + 0x1900;
iVar1 = *(int *)(*(int *)(param_1 + 0x20) + 0x48);
*(undefined4 *)(param_1 + 0x4c) = 0xfff;
}
else {
if (iVar2 == 0xfff) {
iVar1 = FUN_8003ea28();
*(short *)(param_1 + 0x30) = (short)iVar1 + (short)(iVar1 / 800) * -800 + 8000;
iVar1 = *(int *)(*(int *)(param_1 + 0x20) + 0x48);
*(undefined4 *)(param_1 + 0x4c) = 0xffe;
}
else {
if (iVar2 != 0xffe) {
return;
}
// Get random number
iVar1 = FUN_8003ea28();
*(short *)(param_1 + 0x30) = (short)iVar1 + (short)(iVar1 / 800) * -800 + 6000;
iVar1 = *(int *)(*(int *)(param_1 + 0x20) + 0x48);
*(undefined2 *)(param_1 + 0x50) = 0xf801;
}
}
*(int *)(param_1 + 0x2c) = (iVar1 + 0x10) * 0x100;
}
return;
}
// Particle_FuncPtr_ExhaustUnderwater
void FUN_8003ee20(int param_1)
{
int iVar1;
uint uVar2;
if (
(3 < (*(int *)(param_1 + 0x2c) >> 8) + *(int *)(*(int *)(param_1 + 0x20) + 0x48)) &&
// framesLeftInLife
(*(short *)(param_1 + 0x10) < 0x1b)
)
{
// bubblepop
iVar1 = *(int *)(PTR_DAT_8008d2ac + 0x2134);
// save iconGroup
*(int *)(param_1 + 0xc) = iVar1;
if (iVar1 != 0)
{
// actually the first icon pointer in the array,
// not the pointer to the array itself
// param1->8 = iconGroup->icons[0]
*(undefined4 *)(param_1 + 8) = *(undefined4 *)(iVar1 + 0x14);
}
// Get random number
uVar2 = FUN_8003ea28();
*(uint *)(param_1 + 0x44) = uVar2 & 0xfff;
*(undefined2 *)(param_1 + 0x10) = 0;
}
return;
}
// Particle_OnDestroy
void FUN_8003eeb0(int param_1)
{
int *piVar1;
piVar1 = *(int **)(param_1 + 4);
while (piVar1 != (int *)0x0)
{
piVar1 = (int *)*piVar1;
// LIST_AddFront
// free list of Oscillator Pool
FUN_80031744(PTR_DAT_8008d2ac + 0x19c0);
}
return;
}
// Particle_UpdateList
void FUN_8003eefc(int **param_1,int **param_2)
{
ushort uVar1;
ushort uVar2;
short sVar3;
int iVar4;
int iVar5;
uint uVar6;
int *piVar7;
int **ppiVar8;
int **ppiVar9;
int *piVar10;
int **ppiVar11;
int **ppiVar12;
if (param_2 != (int **)0x0) {
do
{
// get frames remaining in particle life,
// offset 0x10
sVar3 = *(short *)(param_2 + 4);
// particle->next
ppiVar12 = (int **)*param_2;
// framesLeftInLife -= 1
*(short *)(param_2 + 4) = sVar3 + -1;
// if particle is dead
if ((short)(sVar3 + -1) == -1) {
LAB_8003f2dc:
// Particle_OnDestroy
FUN_8003eeb0(param_2);
// LIST_AddFront
// free list of particle pool
FUN_80031744(PTR_DAT_8008d2ac + 0x1998,param_2);
// decrease number of particles
*(int *)(PTR_DAT_8008d2ac + 0x1ca4) = *(int *)(PTR_DAT_8008d2ac + 0x1ca4) + -1;
// particle = particle->next
*(int ***)param_1 = ppiVar12;
}
// if particle is not dead
else
{
// particle offset 0x12 (flags)
uVar1 = *(ushort *)((int)param_2 + 0x12);
if ((uVar1 & 8) != 0) goto LAB_8003f2dc;
if ((uVar1 & 0x1000) != 0)
{
// copy pos Axis to rot Axis?
// X, Y, Z, offsets 0x24-0x74
param_2[0xf] = param_2[9];
param_2[0x15] = param_2[0xb];
param_2[0x11] = param_2[0xd];
if ((uVar1 & 0x4000) == 0) {
param_2[0x1d] = param_2[0x1e];
}
}
// flagsAxis
piVar10 = param_2[5];
// offset 4 (unknown pointer)
ppiVar8 = (int **)param_2[1];
// particle offset 0x24
ppiVar11 = param_2 + 9;
if (piVar10 != (int *)0x0)
{
// particle offset 0x28
ppiVar9 = param_2 + 10;
// loop through each axis of animation (x, y, z)
do
{
// if axis is disabled, check next
if (((uint)piVar10 & 1) == 0) goto LAB_8003f1f4;
// pos = pos + vel
*ppiVar11 = (int *)((int)*ppiVar11 + (int)*(short *)ppiVar9);
// vel = vel + accel
sVar3 = *(short *)ppiVar9 + *(short *)((int)ppiVar9 + 2);
*(short *)ppiVar9 = sVar3;
// if axis is disabled, check next
if ((((int)piVar10 >> 0x10 & 1U) == 0) || (ppiVar8 == (int **)0x0)) goto LAB_8003f1f4;
if ((*(ushort *)(ppiVar8 + 2) & 8) == 0) {
if ((*(ushort *)(ppiVar8 + 2) & 0x10) == 0) {
*ppiVar11 = (int *)((int)*ppiVar11 - (int)*(short *)((int)ppiVar8 + 10));
}
else {
*(short *)ppiVar9 = sVar3 - *(short *)((int)ppiVar8 + 10);
}
}
// confetti frame timer
iVar4 = *(int *)(PTR_DAT_8008d2ac + 0x1cf0);
switch((uint)*(ushort *)(ppiVar8 + 2) & 7) {
case 0:
// Sine(angle)
iVar4 = FUN_8003d184((int)((uint)*(ushort *)(ppiVar8 + 3) *
(iVar4 + *(short *)((int)ppiVar8 + 0xe))) >> 5);
goto switchD_8003f074_caseD_7;
case 1:
// Sine(angle)
iVar4 = FUN_8003d184((int)((uint)*(ushort *)(ppiVar8 + 3) *
(iVar4 + *(short *)((int)ppiVar8 + 0xe))) >> 6);
if (iVar4 < 0) {
iVar4 = -iVar4;
}
uVar6 = iVar4 << 1;
break;
case 2:
uVar6 = (int)((uint)*(ushort *)(ppiVar8 + 3) *
(iVar4 + *(short *)((int)ppiVar8 + 0xe))) >> 4 & 0x1fff;
break;
case 3:
uVar6 = (int)((uint)*(ushort *)(ppiVar8 + 3) *
(iVar4 + *(short *)((int)ppiVar8 + 0xe))) >> 3 & 0x3fff;
if (0x2000 < uVar6) {
uVar6 = 0x4000 - uVar6;
}
break;
case 4:
iVar5 = iVar4 + *(short *)((int)ppiVar8 + 0xe);
iVar4 = -0x1000;
if (((int)((uint)*(ushort *)(ppiVar8 + 3) * iVar5) >> 6 & 0x400U) != 0) {
iVar4 = 0x1000;
}
goto switchD_8003f074_caseD_7;
case 5:
// Get random number
iVar4 = FUN_8003ea28();
uVar6 = iVar4 >> 3;
break;
case 6:
// get random number (alternative way)
iVar4 = FUN_8003eaac((int)*(short *)((int)ppiVar8 + 10));
uVar6 = iVar4 >> 3;
break;
default:
goto switchD_8003f074_caseD_7;
}
iVar4 = uVar6 - 0x1000;
switchD_8003f074_caseD_7:
iVar4 = (int)((iVar4 + *(short *)((int)ppiVar8 + 0x12)) * (uint)*(ushort *)(ppiVar8 + 4)
) >> 0xc;
if ((int)*(short *)((int)ppiVar8 + 0x16) < iVar4) {
iVar4 = (int)*(short *)((int)ppiVar8 + 0x16);
}
if (iVar4 < (int)*(short *)(ppiVar8 + 5)) {
iVar4 = (int)*(short *)(ppiVar8 + 5);
}
if ((*(ushort *)(ppiVar8 + 2) & 0x10) == 0) {
*ppiVar11 = (int *)((int)*ppiVar11 + iVar4);
}
else {
*(short *)ppiVar9 = *(short *)ppiVar9 + (short)iVar4;
}
*(short *)((int)ppiVar8 + 10) = (short)iVar4;
ppiVar8 = (int **)*ppiVar8;
// next axis to animate
LAB_8003f1f4:
ppiVar9 = ppiVar9 + 2;
piVar10 = (int *)((int)((uint)piVar10 & 0xfffeffff) >> 1);
ppiVar11 = ppiVar11 + 2;
} while (piVar10 != (int *)0x0);
}
// if particle has function pointer (offset 0x1C)
if (param_2[7] != (int *)0x0)
{
// execute function for this particle
(*(code *)param_2[7])(param_2);
}
// flagsAxis
uVar2 = *(ushort *)(param_2 + 5);
if (((uVar1 & 1) != 0) &&
((((uVar2 & 0x20) != 0 && ((int)param_2[0x13] < 1)) ||
(((uVar2 & 0x40) != 0 && ((int)param_2[0x15] < 1)))))) goto LAB_8003f2dc;
if ((uVar1 & 2) != 0)
{
piVar10 = (int *)0x0;
// colorR !=0, get colorR.startVal
if (((uVar2 & 0x80) != 0) && (0 < (int)param_2[0x17])) {
piVar10 = param_2[0x17];
}
// colorG !=0, get colorG.startVal
if (((uVar2 & 0x100) != 0) && (0 < (int)param_2[0x19])) {
piVar10 = (int *)((uint)piVar10 | (uint)param_2[0x19]);
}
// colorB !=0, get colorB.startVal
if (((uVar2 & 0x200) != 0) && (0 < (int)param_2[0x1b])) {
piVar10 = (int *)((uint)piVar10 | (uint)param_2[0x1b]);
}
if ((int)piVar10 < 0x800) goto LAB_8003f2dc;
}
param_1 = param_2;
if (
// if TireAxis is in use
((*(ushort *)(param_2 + 5) & 0x400) != 0) &&
// get particle->ptrIconGroup
(piVar10 = param_2[3], piVar10 != (int *)0x0)
)
{
// axis[0xA] (TireAxis)
piVar7 = param_2[0x1d];
if ((int)piVar7 < 0)
{
if ((*(ushort *)((int)param_2 + 0x12) & 0x100) == 0) {
if ((*(ushort *)((int)param_2 + 0x12) & 0x200) == 0) {
piVar7 = (int *)0x0;
}
else {
LAB_8003f3c4:
piVar7 = (int *)((int)piVar7 + (int)*(short *)(param_2 + 0x1e) * -2);
*(short *)((int)param_2 + 0x7a) = -*(short *)((int)param_2 + 0x7a);
*(short *)(param_2 + 0x1e) = -*(short *)(param_2 + 0x1e);
}
}
else {
piVar7 = piVar7 + (int)*(short *)((int)piVar10 + 0x12) * 0x40;
}
}
else {
iVar4 = (int)*(short *)((int)piVar10 + 0x12) * 0x100;
if ((int)piVar7 < iVar4) goto LAB_8003f3f8;
if ((*(ushort *)((int)param_2 + 0x12) & 0x100) == 0) {
if ((*(ushort *)((int)param_2 + 0x12) & 0x200) != 0) goto LAB_8003f3c4;
piVar7 = (int *)(iVar4 + -1);
}
else {
piVar7 = piVar7 + (int)*(short *)((int)piVar10 + 0x12) * 0x3fffffc0;
}
}
param_2[0x1d] = piVar7;
}
}
LAB_8003f3f8:
param_2 = ppiVar12;
} while (ppiVar12 != (int **)0x0);
}
return;
}
// Particle_UpdateAllParticles
void FUN_8003f434(void)
{
// if PauseAllThreads is diabled
if ((*(uint *)PTR_DAT_8008d2ac & 0x10) == 0)
{
// world-space particles (exhaust on cars)
FUN_8003eefc(PTR_DAT_8008d2ac + 0x1c9c,*(undefined4 *)(PTR_DAT_8008d2ac + 0x1c9c));
// Draw "heat" particles that warp the screen
// (above fire in tiger temple flamejet and player missiles)
FUN_8003eefc(PTR_DAT_8008d2ac + 0x1ca0,*(undefined4 *)(PTR_DAT_8008d2ac + 0x1ca0));
}
return;
}
// Particle_BitwiseClampByte
// only called from Particle_SetColors
int FUN_8003f48c(int *param_1)
{
int iVar1;
iVar1 = *param_1;
// min value
if (iVar1 < 0) {
iVar1 = 0;
*param_1 = 0;
}
else
{
// max value
if (0xff00 < iVar1) {
iVar1 = 0xff00;
*param_1 = 0xff00;
}
}
// shift down a byte
return iVar1 >> 8;
}
// Particle_SetColors
// called from RenderList and CreateInstance
uint FUN_8003f4c4(uint param_1,uint param_2,int param_3)
{
uint uVar1;
uint uVar2;
if ((param_1 & 0x80) == 0)
{
// draw white
uVar2 = 0x1000000;
if ((param_2 & 0x80) != 0)
{
// draw white, with alpha clipping
uVar2 = 0x3000000;
}
}
else
{
// Particle_BitwiseClampByte (red)
uVar1 = FUN_8003f48c(param_3 + 0x5c);
// red
uVar2 = uVar1;
if ((param_1 & 0x100) != 0)
{
// Particle_BitwiseClampByte (green)
uVar2 = FUN_8003f48c(param_3 + 0x64); // 0x64 = 100
}
// green
uVar2 = uVar1 | uVar2 << 8;
if ((param_1 & 0x200) != 0)
{
// Particle_BitwiseClampByte (blue)
uVar1 = FUN_8003f48c(param_3 + 0x6c);
}
// blue
uVar2 = uVar2 | uVar1 << 0x10;
if ((param_2 & 0x80) != 0)
{
// enable alpha clipping
uVar2 = uVar2 | 0x2000000;
}
}
// returns 0xXXBBGGRR
// BB for blue, GG for green, RR for red, XX for flags
return uVar2;
}
// Particle_RenderList
void FUN_8003f590(int param_1,int *param_2)
{
char cVar1;
ushort uVar2;
ushort uVar3;
short sVar4;
uint uVar5;
int iVar6;
uint *puVar7;
int iVar8;
int iVar9;
uint uVar10;
int iVar11;
uint uVar12;
uint uVar13;
uint *puVar14;
int iVar15;
uint uVar16;
uint uVar17;
int iVar18;
uint uVar19;
undefined4 uVar20;
uint uVar21;
undefined4 uVar22;
undefined4 uVar23;
uint *puVar24;
uint *puVar25;
uint uVar26;
// PushBuffer_SetPsyqGeom
FUN_80042910(param_1);
// pushBuffer -> 0x28 (matrix)
DAT_1f800000 = *(undefined4 *)(param_1 + 0x28);
DAT_1f800004 = *(undefined4 *)(param_1 + 0x2c);
DAT_1f800008 = *(undefined4 *)(param_1 + 0x30);
DAT_1f80000c = *(undefined4 *)(param_1 + 0x34);
DAT_1f800010 = DAT_1f800010 & 0xffff0000 | (uint)*(ushort *)(param_1 + 0x38);
setCopControlWord(2,0x4000,DAT_1f800000);
setCopControlWord(2,0x4800,DAT_1f800004);
setCopControlWord(2,0x5000,DAT_1f800008);
setCopControlWord(2,0x5800,DAT_1f80000c);
setCopControlWord(2,0x6000,DAT_1f800010);
// pushBuffer ptrOT
DAT_1f800020 = *(int *)(param_1 + 0xf4);
// pushBuffer cameraID
cVar1 = *(char *)(param_1 + 0x108);
// another matrix
DAT_1f800024 = *(int *)(param_1 + 0x7c) << 2;
DAT_1f800028 = *(int *)(param_1 + 0x80) << 2;
DAT_1f80002c = *(int *)(param_1 + 0x84) << 2;
// backBuffer->primMem.curr
puVar7 = *(uint **)(*(int *)(PTR_DAT_8008d2ac + 0x10) + 0x80);
if (
// get the number of bytes needed to draw particles
puVar7 + *(int *)(PTR_DAT_8008d2ac + 0x1ca4) * 10 <
// end of PrimMem, minus 0x100,
// make sure to leave enough memory behind for [something else, idk]
*(uint **)(*(int *)(PTR_DAT_8008d2ac + 0x10) + 0x84)
)
{
if (param_2 != (int *)0x0)
{
puVar25 = puVar7 + 8;
puVar24 = puVar7;
do {
puVar7 = puVar24;
if (
(
// no driverID
((int)*(char *)((int)param_2 + 0x19) == -1) ||
// driverID == index
((int)*(char *)((int)param_2 + 0x19) == (int)cVar1)
) &&
// ptrIconGroup
(iVar8 = param_2[3], iVar8 != 0)
)
{
uVar2 = *(ushort *)(param_2 + 5);
if ((uVar2 & 0x400) == 0)
{
// ptrIconArray
iVar8 = param_2[2];
}
else
{
// colorA
iVar18 = param_2[0x1d] >> 8;
if (iVar18 < 0) {
iVar18 = 0;
}
// number of icons in group
if ((int)*(short *)(iVar8 + 0x12) <= iVar18) {
iVar18 = (int)*(short *)(iVar8 + 0x12) + -1;
}
if (iVar18 < 0)
{
// skip this particle,
// go to next particle
goto LAB_800402b0;
}
// change pointer to current icon, from group array
iVar8 = *(int *)(iVar8 + iVar18 * 4 + 0x14);
param_2[2] = iVar8;
}
iVar18 = 0;
if (iVar8 != 0)
{
uVar3 = *(ushort *)((int)param_2 + 0x12);
uVar26 = (uint)uVar3;
iVar11 = param_2[9] >> 6;
iVar9 = param_2[0xd] >> 6;
iVar15 = param_2[0xb] >> 6;
if (
((uVar3 & 0x800) != 0) &&
// instance that particle is attached to?
(iVar6 = param_2[8], iVar6 != 0)
)
{
// InstDrawPerPlayer = &Instance->InstDrawPerPlayer[cVar1]
iVar18 = iVar6 + (int)cVar1 * 0x88 + 0x74;
// 0xB8 (flags per player)
if ((*(uint *)(iVar18 + 0x44) & 0x40) == 0)
{
// skip this particle,
// go to next particle
goto LAB_800402b0;
}
iVar11 = iVar11 + *(int *)(iVar6 + 0x44) * 4;
if ((uVar3 & 0x8000) == 0) {
iVar15 = iVar15 + *(int *)(iVar6 + 0x48) * 4;
}
iVar9 = iVar9 + *(int *)(iVar6 + 0x4c) * 4;
// 0xB8 (flags per player)
if ((*(uint *)(iVar18 + 0x44) & 0x100) != 0) {
iVar18 = 0;
}
}
uVar12 = iVar11 - DAT_1f800024;
iVar15 = iVar15 - DAT_1f800028;
uVar5 = uVar12;
if ((int)uVar12 < 0) {
uVar5 = -uVar12;
}
iVar9 = iVar9 - DAT_1f80002c;
if ((int)uVar5 < 0x7531) {
iVar11 = iVar15;
if (iVar15 < 0) {
iVar11 = -iVar15;
}
if (iVar11 < 0x7531) {
iVar11 = iVar9;
if (iVar9 < 0) {
iVar11 = -iVar9;
}
if (iVar11 < 0x7531) {
setCopReg(2,0,uVar12 & 0xffff | iVar15 * 0x10000);
setCopReg(2,0x800,iVar9);
// llv0 cop2 $04A6012 v0 * light matrix
copFunction(2,0x4a6012);
uVar20 = getCopReg(2,0xc800);
uVar22 = getCopReg(2,0xd000);
uVar23 = getCopReg(2,0xd800);
setCopControlWord(2,0x2800,uVar20);
setCopControlWord(2,0x3000,uVar22);
setCopControlWord(2,0x3800,uVar23);
iVar9 = getCopReg(2,0xd800);
if ((-1 < iVar9) && (iVar9 <= (int)*(short *)((int)param_2 + 0x1a) << 2))
{
// Particle_SetColors
uVar5 = FUN_8003f4c4((uint)uVar2,uVar26,param_2);
if ((uVar3 & 0x1000) == 0) {
uVar12 = 0x2000;
iVar9 = 0;
uVar13 = 0x1000;
uVar19 = 0;
uVar21 = 0x1000;
if ((uVar2 & 8) == 0) {
if ((uVar2 & 0x10) == 0) {
if ((uVar2 & 0x20) != 0) {
uVar12 = param_2[0x13] << 1;
uVar13 = (int)uVar12 >> 1;
}
if ((uVar2 & 0x40) != 0) {
uVar13 = param_2[0x15];
}
}
else {
uVar12 = param_2[0x11];
// approximate trigonometry
sVar4 = (short)*(int *)(&DAT_800845a0 + (uVar12 & 0x3ff) * 4);
uVar13 = *(int *)(&DAT_800845a0 + (uVar12 & 0x3ff) * 4) >> 0x10;
if ((uVar12 & 0x400) == 0) {
uVar10 = SEXT24(sVar4);
if ((uVar12 & 0x800) != 0) {
uVar17 = -uVar13;
goto LAB_8003ff30;
}
}
else {
uVar17 = SEXT24(sVar4);
uVar10 = uVar13;
if ((uVar12 & 0x800) == 0) {
uVar13 = -uVar17;
}
else {
LAB_8003ff30:
uVar10 = -uVar10;
uVar13 = uVar17;
}
}
if ((uVar2 & 0x20) == 0) {
if ((uVar2 & 0x40) != 0) {
iVar11 = param_2[0x15];
iVar9 = -uVar10 * iVar11;
uVar12 = (uVar13 & 0x7fff) << 1 | uVar10 << 0x11;
goto LAB_8004000c;
}
uVar12 = (uVar13 & 0x7fff) << 1 | uVar10 << 0x11;
iVar9 = uVar10 * -0x10000;
uVar13 = uVar13 & 0xffff;
}
else {
iVar15 = param_2[0x13];
if ((uVar2 & 0x40) == 0) {
uVar12 = (int)(uVar13 * iVar15) >> 0xc;
uVar13 = uVar12 & 0xffff;
iVar9 = (int)(uVar10 * iVar15) >> 0xc;
uVar12 = (uVar12 & 0x7fff) << 1 | iVar9 << 0x11;
iVar9 = iVar9 * -0x10000;
}
else {
iVar11 = param_2[0x15];
iVar9 = -uVar10 * iVar11;
uVar12 = (int)(uVar13 * iVar15) >> 0xb & 0xffffU |
((int)(uVar10 * iVar15) >> 0xb) << 0x10;
LAB_8004000c:
iVar9 = (iVar9 >> 0xc) << 0x10;
uVar13 = (int)(uVar13 * iVar11) >> 0xc & 0xffff;
}
}
}
goto LAB_80040074;
}
if ((uVar2 & 0x10) == 0) {
uVar21 = param_2[0xf];
// approximate trigonometry
sVar4 = (short)*(int *)(&DAT_800845a0 + (uVar21 & 0x3ff) * 4);
uVar13 = *(int *)(&DAT_800845a0 + (uVar21 & 0x3ff) * 4) >> 0x10;
if ((uVar21 & 0x400) == 0) {
uVar10 = SEXT24(sVar4);
if ((uVar21 & 0x800) != 0) {
uVar19 = -uVar13;
goto LAB_8003fdec;
}
}
else {
uVar19 = SEXT24(sVar4);
uVar10 = uVar13;
if ((uVar21 & 0x800) == 0) {
uVar13 = -uVar19;
}
else {
LAB_8003fdec:
uVar10 = -uVar10;
uVar13 = uVar19;
}
}
if ((uVar2 & 0x20) == 0) {
uVar21 = uVar13 & 0xffff;
if ((uVar2 & 0x40) != 0) {
iVar11 = param_2[0x15];
goto LAB_8003fe90;
}
uVar13 = uVar21 | uVar10 << 0x10;
uVar19 = uVar10 * -0x10000;
}
else {
iVar15 = param_2[0x13];
if ((uVar2 & 0x40) != 0) {
iVar11 = param_2[0x15];
uVar12 = iVar15 << 1 & 0xffff;
LAB_8003fe90:
uVar19 = uVar10 * -0x10000;
uVar21 = uVar13 & 0xffff;
uVar13 = (int)(uVar13 * iVar11) >> 0xc & 0xffff;
iVar11 = (int)(uVar10 * iVar11) >> 0xc;
goto LAB_8003feac;
}
uVar12 = iVar15 << 1 & 0xffff;
iVar11 = (int)(uVar10 * iVar15) >> 0xc;
uVar21 = (int)(uVar13 * iVar15) >> 0xc & 0xffff;
uVar13 = uVar21 | iVar11 << 0x10;
uVar19 = iVar11 * -0x10000;
}
}
else {
uVar12 = param_2[0xf];
// approximate trigonometry
sVar4 = (short)*(int *)(&DAT_800845a0 + (uVar12 & 0x3ff) * 4);
uVar13 = *(int *)(&DAT_800845a0 + (uVar12 & 0x3ff) * 4) >> 0x10;
if ((uVar12 & 0x400) == 0) {
uVar10 = SEXT24(sVar4);
if ((uVar12 & 0x800) != 0) {
uVar21 = -uVar13;
goto LAB_8003fac0;
}
}
else {
uVar21 = SEXT24(sVar4);
uVar10 = uVar13;
if ((uVar12 & 0x800) == 0) {
uVar13 = -uVar21;
}
else {
LAB_8003fac0:
uVar10 = -uVar10;
uVar13 = uVar21;
}
}
uVar12 = param_2[0x11];
// approximate trigonometry
sVar4 = (short)*(int *)(&DAT_800845a0 + (uVar12 & 0x3ff) * 4);
uVar17 = *(int *)(&DAT_800845a0 + (uVar12 & 0x3ff) * 4) >> 0x10;
if ((uVar12 & 0x400) == 0) {
uVar16 = SEXT24(sVar4);
if ((uVar12 & 0x800) != 0) {
uVar21 = -uVar17;
goto LAB_8003fb18;
}
}
else {
uVar21 = SEXT24(sVar4);
uVar16 = uVar17;
if ((uVar12 & 0x800) == 0) {
uVar17 = -uVar21;
}
else {
LAB_8003fb18:
uVar16 = -uVar16;
uVar17 = uVar21;
}
}
if ((uVar2 & 0x20) == 0) {
if ((uVar2 & 0x40) == 0) {
iVar9 = uVar13 * -uVar16;
iVar11 = uVar17 * uVar13;
iVar15 = uVar10 * uVar16;
iVar6 = -uVar10 * uVar17;
goto LAB_8003fd5c;
}
iVar11 = param_2[0x15];
uVar21 = uVar13 & 0xffff;
uVar12 = (uVar17 & 0x7fff) << 1 | uVar16 << 0x11;
uVar19 = (int)(uVar10 * uVar16) >> 0xc & 0xffffU |
((int)(-uVar10 * uVar17) >> 0xc) << 0x10;
iVar9 = (((int)(uVar13 * -uVar16) >> 0xc) * iVar11 >> 0xc) << 0x10;
uVar13 = ((int)(uVar17 * uVar13) >> 0xc) * iVar11 >> 0xc & 0xffff;
iVar11 = (int)(uVar10 * iVar11) >> 0xc;
}
else {
iVar15 = param_2[0x13];
if ((uVar2 & 0x40) == 0) {
uVar13 = (int)(uVar13 * iVar15) >> 0xc;
uVar16 = (int)(uVar16 * iVar15) >> 0xc;
iVar9 = uVar13 * -uVar16;
uVar17 = (int)(uVar17 * iVar15) >> 0xc;
iVar11 = uVar17 * uVar13;
uVar10 = (int)(uVar10 * iVar15) >> 0xc;
iVar15 = uVar10 * uVar16;
iVar6 = -uVar10 * uVar17;
LAB_8003fd5c:
uVar21 = uVar13 & 0xffff;
uVar12 = (uVar17 & 0x7fff) << 1 | uVar16 << 0x11;
iVar9 = (iVar9 >> 0xc) << 0x10;
uVar13 = iVar11 >> 0xc & 0xffffU | uVar10 << 0x10;
uVar19 = iVar15 >> 0xc & 0xffffU | (iVar6 >> 0xc) << 0x10;
goto LAB_80040074;
}
iVar11 = param_2[0x15];
uVar21 = uVar13 & 0xffff;
uVar12 = (int)(uVar17 * iVar15) >> 0xb & 0xffffU |
((int)(uVar16 * iVar15) >> 0xb) << 0x10;
uVar19 = (int)(uVar10 * uVar16) >> 0xc & 0xffffU |
((int)(-uVar10 * uVar17) >> 0xc) << 0x10;
iVar9 = (((int)(uVar13 * -uVar16) >> 0xc) * iVar11 >> 0xc) << 0x10;
uVar13 = ((int)(uVar17 * uVar13) >> 0xc) * iVar11 >> 0xc & 0xffff;
iVar11 = (int)(uVar10 * iVar11) >> 0xc;
}
LAB_8003feac:
uVar13 = uVar13 | iVar11 << 0x10;
}
LAB_80040074:
setCopControlWord(2,0,uVar12);
setCopControlWord(2,0x800,iVar9);
setCopControlWord(2,0x1000,uVar13);
setCopControlWord(2,0x1800,uVar19);
setCopControlWord(2,0x2000,uVar21);
puVar25[-7] = uVar5 | 0x2c000000;
puVar25[-5] = *(uint *)(iVar8 + 0x14);
puVar25[-3] = *(uint *)(iVar8 + 0x18) & 0xff9fffff | (uVar26 & 0x60) << 0x10;
*(undefined2 *)(puVar25 + -1) = *(undefined2 *)(iVar8 + 0x1c);
*(undefined2 *)(puVar25 + 1) = *(undefined2 *)(iVar8 + 0x1e);
iVar9 = ((uint)*(byte *)(iVar8 + 0x18) - (uint)*(byte *)(iVar8 + 0x14)) + 1;
uVar26 = iVar9 * 2;
iVar8 = ((uint)*(byte *)(iVar8 + 0x1d) - (uint)*(byte *)(iVar8 + 0x15)) + 1;
iVar11 = iVar8 * 2;
if ((uVar3 & 0x400) != 0) {
uVar26 = iVar9 * 0x10;
iVar11 = iVar8 * 0x10;
}
uVar5 = -uVar26 & 0xffff | iVar11 * -0x10000;
setCopReg(2,0x800,0);
// loop counter
iVar8 = 0;
// for iVar8 = 0; iVar8 < 4; iVar8++
// get four xy positions of quad
do
{
setCopReg(2,0,uVar5);
// RTPS - Perspective Transformation (single)
copFunction(2,0x180001);
if (iVar8 == 1) {
uVar5 = -uVar26 & 0xffff | iVar11 << 0x10;
// screenspace pos xy
uVar12 = getCopReg(2,0xe);
// offset 0x10
puVar24[4] = uVar12;
}
else {
if (iVar8 < 2) {
if (iVar8 == 0) {
uVar5 = uVar26 & 0xffff | iVar11 * -0x10000;
// screenspace pos xy
uVar12 = getCopReg(2,0xe);
// offset 0x8
puVar24[2] = uVar12;
DAT_1f800030 = getCopReg(2,0x13);
}
}
else {
if (iVar8 == 2) {
uVar5 = uVar26 & 0xffff | iVar11 << 0x10;
// screenspace pos xy
uVar12 = getCopReg(2,0xe);
// offset 0x18
puVar24[6] = uVar12;
}
else {
if (iVar8 == 3)
{
// screenspace pos xy
uVar12 = getCopReg(2,0xe);
// offset 0x0
*puVar25 = uVar12;
}
}
}
}
// increment loop counter
iVar8 = iVar8 + 1;
} while (iVar8 < 4);
}
else
{
// rotation matrix of view
setCopControlWord(2,0,DAT_1f800000);
setCopControlWord(2,0x800,DAT_1f800004);
setCopControlWord(2,0x1000,DAT_1f800008);
setCopControlWord(2,0x1800,DAT_1f80000c);
setCopControlWord(2,0x2000,DAT_1f800010);
// translation 0,0,0
setCopReg(2,0,0);
setCopReg(2,0x800,0);
if ((uVar2 & 0x20) == 0) {
setCopReg(2,0x1000,param_2[0xf] - param_2[9] >> 6 & 0xffffU |
(param_2[0x15] - param_2[0xb] >> 6) << 0x10);
setCopReg(2,0x1800,param_2[0x11] - param_2[0xd] >> 6);
}
else {
iVar8 = param_2[0x13];
setCopReg(2,0x1000,(uint)((param_2[0xf] - param_2[9] >> 6) * iVar8) >> 0x10
| ((param_2[0x15] - param_2[0xb] >> 6) * iVar8 >> 0x10)
<< 0x10);
setCopReg(2,0x1800,(param_2[0x11] - param_2[0xd] >> 6) * iVar8 >> 0x10);
}
// RTPT - Perspective Transformation (triple)
copFunction(2,0x280030);
uVar5 = uVar5 | 0x50000000;
if ((uVar3 & 0x2000) == 0) {
uVar12 = param_2[0x1d];
puVar24[3] = uVar5;
puVar24[5] = uVar12;
}
else {
uVar12 = param_2[0x1d];
puVar24[5] = uVar5;
puVar24[3] = uVar12;
}
param_2[0x1e] = uVar5;
puVar24[1] = uVar26 & 0x60 | 0xe1000a00;
puVar24[2] = 0;
uVar26 = getCopReg(2,0xc);
puVar24[4] = uVar26;
uVar26 = getCopReg(2,0xd);
puVar24[6] = uVar26;
DAT_1f800030 = getCopReg(2,0x11);
}
if (iVar18 == 0) {
uVar5 = (DAT_1f800030 >> 8) + (int)*(char *)(param_2 + 6);
uVar26 = uVar5;
if ((int)uVar5 < 0) {
uVar26 = 0;
}
iVar8 = DAT_1f800020;
if (0x3ff < (int)uVar5) {
uVar26 = 0x3ff;
}
}
else {
uVar26 = DAT_1f800030 >> 5;
if (DAT_1f800030 >> 5 < (int)(uint)*(ushort *)(iVar18 + 0x68)) {
uVar26 = (uint)*(ushort *)(iVar18 + 0x68);
}
if ((int)(uint)*(ushort *)(iVar18 + 0x6a) < (int)uVar26) {
uVar26 = (uint)*(ushort *)(iVar18 + 0x6a);
}
iVar8 = *(int *)(iVar18 + 0x70);
}
puVar14 = (uint *)(iVar8 + uVar26 * 4);
if ((uVar3 & 0x1000) == 0) {
puVar25 = puVar25 + 10;
*puVar24 = *puVar14 | 0x9000000;
puVar7 = puVar24 + 10;
}
else {
puVar25 = puVar25 + 7;
*puVar24 = *puVar14 | 0x6000000;
puVar7 = puVar24 + 7;
}
*puVar14 = (uint)puVar24 & 0xffffff;
}
}
}
}
}
}
LAB_800402b0:
// linked list, get next node
param_2 = (int *)*param_2;
puVar24 = puVar7;
// until you hit nullptr
} while (param_2 != (int *)0x0);
}
// backBuffer->primMem.curr
*(uint **)(*(int *)(PTR_DAT_8008d2ac + 0x10) + 0x80) = puVar7;
}
return;
}
// Particle_Init
// param2 - IconGroup
undefined4 * FUN_80040308(undefined4 param_1,int param_2,ushort *param_3)
{
ushort uVar1;
undefined4 *puVar2;
undefined *puVar3;
short sVar4;
undefined4 *puVar5;
undefined4 *puVar6;
int iVar7;
uint uVar8;
undefined4 uVar9;
undefined4 *puVar10;
undefined4 uVar11;
undefined4 uVar12;
ushort uVar13;
int iVar14;
ushort *puVar15;
uint uVar16;
uint uVar17;
undefined4 local_60 [12];
int local_30;
undefined4 *local_2c;
// ordinary particle
local_30 = 0;
// LIST_RemoveFront
// first free item in Particle Pool
puVar5 = (undefined4 *)FUN_8003186c(PTR_DAT_8008d2ac + 0x1998);
uVar17 = 0;
// if particle allocated correctly
if (puVar5 != (undefined4 *)0x0)
{
// increment number of particles
*(int *)(PTR_DAT_8008d2ac + 0x1ca4) = *(int *)(PTR_DAT_8008d2ac + 0x1ca4) + 1;
// ptrIconGroup (sprite animation?)
puVar5[3] = param_2;
// if group is invalid
if (
(
// if nullptr
(param_2 == 0) ||
// if there are no icons in group
(*(short *)(param_2 + 0x12) == 0)
) ||
// if there are still no icons in group
(*(short *)(param_2 + 0x12) < 1)
)
{
// erase ptrIconGroup and ptrIcons
puVar5[3] = 0;
puVar5[2] = 0;
}
// if group is valid
else
{
// keep ptr to icon array
puVar5[2] = *(undefined4 *)(param_2 + 0x14);
}
// safe-check nullptr
if (param_3 != (ushort *)0x0)
{
// emitterChunk offset 0x0 (flags)
uVar1 = *param_3;
// always != 0, except last chunk
if (uVar1 != 0)
{
local_2c = local_60;
// emitterChunk offset 0x12
puVar15 = param_3 + 9;
do
{
// emitterChunk offset 0x12-0x10 (0x2),
// used as an offset for writing particle
uVar16 = (uint)*(byte *)(puVar15 + -8);
// if initOffset is invalid, assume
// this is not axis-related (not AxisInit)
if (*(byte *)(puVar15 + -8) == 0xc)
{
// if not an AxisInit or (other?),
// then assume this is a FuncInit
if ((uVar1 & 0xc0) == 0)
{
// emitterChunk offset 0x12-0xE (0x4)
// function pointer to animate particle (can be nullptr)
puVar5[7] = *(undefined4 *)(puVar15 + -7);
// emitterChunk offset 0x12-0xA (0x8)
// flags, passed to SetColors
*(ushort *)((int)puVar5 + 0x12) = puVar15[-5];
// emitterChunk offset 0x12-0x8 (0xA)
// number of frames in particle life
*(ushort *)(puVar5 + 4) = puVar15[-4];
uVar17 = uVar17 | 0x1000;
// emitterChunk offset 0x12-0x6 (0xC)
// ordinary particle, or heatWarp particle
local_30 = *(int *)(puVar15 + -3);
}
}
// if not color/funcPtr initializer
else {
if ((uVar1 & 0x80) == 0)
{
// if this is not a memcpy Init
if ((uVar1 & 0x40) == 0)
{
// assume AxisInit emitter
// === pos init ===
// value
iVar14 = 0;
// if base value exists
if ((uVar1 & 1) != 0)
{
// emitterChunk offset 0x12-0xE (0x4)
iVar14 = *(int *)(puVar15 + -7);
}
if ((uVar1 & 8) != 0)
{
// RNG
// emitterChunk offset 0x12-0x6 (0xC)
iVar7 = FUN_8003ea6c(*(undefined4 *)(puVar15 + -3));
iVar14 = iVar14 + iVar7;
}
// particle + offset * 2
// determines which axis is initialized
puVar6 = puVar5 + uVar16 * 2;
// 0x24 - position
puVar6[9] = iVar14;
// === vel init ===
// velocity
uVar13 = 0;
// if base vel exists
if ((uVar1 & 2) != 0)
{
// emitterChunk offset 0x12-0xA (0x8)
uVar13 = puVar15[-5];
}
if ((uVar1 & 0x10) != 0)
{
// RNG
// emitterChunk offset 0x12-0x2 (0x10)
sVar4 = FUN_8003ea6c((int)(short)puVar15[-1]);
uVar13 = uVar13 + sVar4;
}
// 0x28 - velocity
*(ushort *)(puVar6 + 10) = uVar13;
// === accel init ===
// acceleration
uVar13 = 0;
// if base accel exists
if ((uVar1 & 4) != 0)
{
// emitterChunk offset 0x12-0x8 (0xA)
uVar13 = puVar15[-4];
}
if ((uVar1 & 0x20) != 0)
{
// RNG
// emitterChunk offset 0x12
sVar4 = FUN_8003ea6c((int)(short)*puVar15);
uVar13 = uVar13 + sVar4;
}
// 0x2A - acceleration
*(ushort *)((int)puVar6 + 0x2a) = uVar13;
uVar17 = uVar17 | 1 << (uVar16 & 0x1f);
}
// & 0x40 == 1
else
{
if ((uVar17 & 1 << (uVar16 + 0x10 & 0x1f)) == 0)
{
// LIST_RemoveFront
// first free member in Oscillator Pool
iVar14 = FUN_8003186c(PTR_DAT_8008d2ac + 0x19c0);
// struct Oscillator*
if (iVar14 == 0) goto LAB_800406f8;
local_2c[uVar16] = iVar14;
}
else
{
// struct Oscillator*
iVar14 = local_2c[uVar16];
}
// lazy memcpy
// src: emitterChunk offset 0x12+0x2 (0x14)
// dst: iVar14 + 8
// size: 0x10
uVar11 = *(undefined4 *)(puVar15 + 3);
uVar12 = *(undefined4 *)(puVar15 + 5);
uVar9 = *(undefined4 *)(puVar15 + 7);
*(undefined4 *)(iVar14 + 8) = *(undefined4 *)(puVar15 + 1);
*(undefined4 *)(iVar14 + 0xc) = uVar11;
*(undefined4 *)(iVar14 + 0x10) = uVar12;
*(undefined4 *)(iVar14 + 0x14) = uVar9;
// emitterChunk offset 0x12+0x2 (0x14)
if ((puVar15[1] & 0x20) != 0)
{
// related to confetti frame timer
*(short *)(iVar14 + 0xe) =
*(short *)(iVar14 + 0xe) - *(short *)(PTR_DAT_8008d2ac + 0x1cf0);
}
// emitterChunk offset 0x12+0x2 (0x14)
if ((puVar15[1] & 7) == 6)
{
*(undefined2 *)(iVar14 + 10) = *(undefined2 *)(iVar14 + 0xe);
}
uVar17 = uVar17 | 1 << (uVar16 + 0x10 & 0x1f);
uVar8 = 1 << (uVar16 & 0x1f);
// if axis is not in use
if ((uVar17 & uVar8) == 0)
{
uVar17 = uVar17 | uVar8;
puVar6 = puVar5 + uVar16 * 2;
// startVal = 0
puVar6[9] = 0;
// velocity = 0
*(undefined2 *)(puVar6 + 10) = 0;
// accel = 0
*(undefined2 *)((int)puVar6 + 0x2a) = 0;
}
}
}
// & 0x80 == 1
else
{
if ((uVar17 & 1 << (uVar16 + 0x10 & 0x1f)) != 0)
{
// struct Oscillator*
iVar14 = local_2c[uVar16];
// emitterChunk offset 0x12+0x6 (0x18)
if (puVar15[3] != 0)
{
// RNG
// emitterChunk offset 0x12+0x6 (0x18)
sVar4 = FUN_8003ea6c((uint)puVar15[3]);
*(short *)(iVar14 + 0xc) = *(short *)(iVar14 + 0xc) + sVar4;
}
// emitterChunk offset 0x12+0x8 (0x1A)
if ((int)(short)puVar15[4] != 0)
{
// RNG
// emitterChunk offset 0x12+0x8 (0x1A)
sVar4 = FUN_8003ea6c((int)(short)puVar15[4]);
*(short *)(iVar14 + 0xe) = *(short *)(iVar14 + 0xe) + sVar4;
}
// emitterChunk offset 0x12+0xA (0x1C)
if (puVar15[5] != 0)
{
// RNG
// emitterChunk offset 0x12+0xA (0x1C)
sVar4 = FUN_8003ea6c((uint)puVar15[5]);
*(short *)(iVar14 + 0x10) = *(short *)(iVar14 + 0x10) + sVar4;
}
// emitterChunk offset 0x12+0xC (0x1E)
if ((int)(short)puVar15[6] != 0)
{
// RNG
// emitterChunk offset 0x12+0xC (0x1E)
sVar4 = FUN_8003ea6c((int)(short)puVar15[6]);
*(short *)(iVar14 + 0x12) = *(short *)(iVar14 + 0x12) + sVar4;
}
// emitterChunk offset 0x12+0xE (0x20)
if ((int)(short)puVar15[7] != 0)
{
// RNG
// emitterChunk offset 0x12+0xE (0x20)
sVar4 = FUN_8003ea6c((int)(short)puVar15[7]);
*(short *)(iVar14 + 0x14) = *(short *)(iVar14 + 0x14) + sVar4;
}
// emitterChunk offset 0x12+0x10 (0x22)
if ((int)(short)puVar15[8] != 0)
{
// RNG
// emitterChunk offset 0x12+0x10 (0x22)
sVar4 = FUN_8003ea6c((int)(short)puVar15[8]);
*(short *)(iVar14 + 0x16) = *(short *)(iVar14 + 0x16) + sVar4;
}
}
}
}
LAB_800406f8:
// every particle emitter metadata
// is divided into 0x24-byte chunks
// next particle emitter chunk
param_3 = param_3 + 0x12;
// get flag of next type,
// while (!= 0) checks validity
uVar1 = *param_3;
// next particle emitter chunk
puVar15 = puVar15 + 0x12;
} while (uVar1 != 0);
}
}
// shift flags down (top 2 bytes)
uVar16 = (int)uVar17 >> 0x10;
puVar6 = local_60;
// particle offset 0x4
puVar2 = puVar5 + 1;
// check all bits
while (uVar16 != 0)
{
// backup particle offset 0x4 (why?)
puVar10 = puVar2;
// if bit is on
if ((uVar16 & 1) != 0)
{
// new value of particle offset 0x4
puVar10 = (undefined4 *)*puVar6;
// set particle offset 0x4
*(undefined4 **)puVar2 = puVar10;
}
// next bit
uVar16 = (int)uVar16 >> 1;
// count bit index
puVar6 = puVar6 + 1;
// set new value, or restore old value (why?)
puVar2 = puVar10;
}
// particle -> 0x4 -> 0x0 = 0
*puVar2 = 0;
// if flag was not set in the previous loop
if ((uVar17 & 0x1000) == 0)
{
// sep 3
// printf("particle initializer w/o PARTICLEFIELD_SPECIAL\n");
// clear function
puVar5[7] = 0;
// no flags passed to SetColor
*(undefined2 *)((int)puVar5 + 0x12) = 0;
// zero life in this particle
*(undefined2 *)(puVar5 + 4) = 0;
// erase pointers
puVar5[2] = 0;
puVar5[3] = 0;
}
puVar5[5] = uVar17 & 0xffffefff;
puVar3 = PTR_DAT_8008d2ac;
// ordinary particle
if (local_30 == 0)
{
// linked list, first member of struct is the pointer to next
*puVar5 = *(undefined4 *)(PTR_DAT_8008d2ac + 0x1c9c);
*(undefined4 **)(puVar3 + 0x1c9c) = puVar5;
}
// heatwarp particle
else
{
// linked list, first member of struct is the pointer to next
*puVar5 = *(undefined4 *)(PTR_DAT_8008d2ac + 0x1ca0);
*(undefined4 **)(puVar3 + 0x1ca0) = puVar5;
}
// particle offset 0x12, flags for alpha in SetColor
uVar1 = *(ushort *)((int)puVar5 + 0x12);
*(undefined2 *)((int)puVar5 + 0x1a) = 0x400;
*(undefined *)((int)puVar5 + 0x19) = 0xff;
// offset 0x18
*(undefined *)(puVar5 + 6) = 0;
if ((uVar1 & 0x1000) != 0) {
if ((uVar1 & 0x4000) == 0)
{
// Particle_SetColors
uVar17 = FUN_8003f4c4(uVar17,(uint)*(ushort *)((int)puVar5 + 0x12),puVar5);
puVar5[0x1d] = uVar17 | 0x50000000;
puVar5[0x1e] = uVar17 | 0x50000000;
}
else
{
// ???
uVar9 = 0x50000000;
if ((uVar1 & 0x80) != 0)
{
// ??? + Alpha clipping
uVar9 = 0x52000000;
}
puVar5[0x1d] = uVar9;
}
}
}
return puVar5;
}