CTR-ModSDK/ghidra/232.c
2024-02-05 03:03:35 -05:00

7513 lines
196 KiB
C

// 232: 37/37
// AH_WarpPad_GetSpawnPosRot
int FUN_800abafc(short *param_1)
{
int iVar1;
int iVar2;
// loop through all warppad threads in thread bucket
iVar1 = *(int *)(PTR_DAT_8008d2ac + 0x1b90);
while( true )
{
// if next thread is not found
if (iVar1 == 0)
{
// quit
return 0;
}
// thread -> instance
iVar2 = *(int *)(iVar1 + 0x34);
// If a warppad is found that belongs to the previous level
if ((int)*(short *)(*(int *)(iVar1 + 0x30) + 0x6c) == *(int *)(PTR_DAT_8008d2ac + 0x1eb4))
{
// then run the second half of the function
break;
}
// go to next warppad
iVar1 = *(int *)(iVar1 + 0x10);
}
// cosine (instance -> instDef -> rotY)
iVar1 = FUN_8003d1c0((int)*(short *)(*(int *)(iVar2 + 0x2c) + 0x38));
*param_1 = *(short *)(iVar2 + 0x44) + (short)((iVar1 << 10) >> 0xc);
param_1[1] = *(short *)(iVar2 + 0x48);
// sine (instance -> instDef -> rotY)
iVar1 = FUN_8003d184((int)*(short *)(*(int *)(iVar2 + 0x2c) + 0x38));
param_1[2] = *(short *)(iVar2 + 0x4c) + (short)(iVar1 * -0x400 >> 0xc);
// &inst -> instDef -> rot[0]
return *(int *)(iVar2 + 0x2c) + 0x36;
}
// AH_WarpPad_AllWarppadNum
void FUN_800abbdc(void)
{
int iVar1;
int iVar2;
int iVar3;
int iVar4;
// loop through all warppad threads in thread bucket
for (iVar4 = *(int *)(PTR_DAT_8008d2ac + 0x1b90); iVar4 != 0; iVar4 = *(int *)(iVar4 + 0x10))
{
// thread -> object
iVar2 = *(int *)(iVar4 + 0x30);
// 01s digit
// obj -> WarpnumInst1
iVar3 = *(int *)(iVar2 + 8);
if (
(
// if instance is valid
(iVar3 != 0) &&
// 01s digit, number of item required to open warppad
(iVar1 = (int)*(short *)(iVar2 + 0x6a), iVar1 != 0)
) &&
// DCxDemo says:
// 1 to 8 is taken from mpk i guess, 0, 9 and X are seprate models
(iVar1 != 9)
)
{
// update instance data, depending on digit,
// pull directly from the header, dont use distance for LOD
// warppadObj -> inst -> xxx
// warppadObj -> inst -> model -> header[digit] -> xxx
// xxx = ptrCommandList
*(undefined4 *)(iVar3 + 200) =
*(undefined4 *)(iVar1 * 0x40 + *(int *)(*(int *)(iVar3 + 0x18) + 0x14) + -0x20);
// xxx = ptrColors
*(undefined4 *)(*(int *)(iVar2 + 8) + 0xd0) =
*(undefined4 *)
(*(short *)(iVar2 + 0x6a) * 0x40 + *(int *)(*(int *)(*(int *)(iVar2 + 8) + 0x18) + 0x14)
+ -0x14);
// xxx = ptrTexLayout
*(undefined4 *)(*(int *)(iVar2 + 8) + 0xcc) =
*(undefined4 *)
(*(short *)(iVar2 + 0x6a) * 0x40 + *(int *)(*(int *)(*(int *)(iVar2 + 8) + 0x18) + 0x14)
+ -0x18);
// xxx = ptrFrameData
*(undefined4 *)(*(int *)(iVar2 + 8) + 0xc0) =
*(undefined4 *)
(*(short *)(iVar2 + 0x6a) * 0x40 + *(int *)(*(int *)(*(int *)(iVar2 + 8) + 0x18) + 0x14)
+ -0x1c);
}
// 10s digit
// obj -> WarpnumInst2
iVar3 = *(int *)(iVar2 + 0xc);
if (
// if instance is valid
(iVar3 != 0) &&
// if 10s digit is not zero
(*(short *)(iVar2 + 0x68) != 0)
)
{
// update instance data, depending on digit,
// pull directly from the header, dont use distance for LOD
// can only ever be '1', hard-coded to header[1]
// warppadObj -> inst -> xxx
// warppadObj -> inst -> model -> header[1] -> xxx
// xxx = ptrCommandList
*(undefined4 *)(iVar3 + 200) = *(undefined4 *)(*(int *)(*(int *)(iVar3 + 0x18) + 0x14) + 0x20)
;
// xxx = ptrColors
*(undefined4 *)(*(int *)(iVar2 + 0xc) + 0xd0) =
*(undefined4 *)(*(int *)(*(int *)(*(int *)(iVar2 + 0xc) + 0x18) + 0x14) + 0x2c);
// xxx = ptrTexLayout
*(undefined4 *)(*(int *)(iVar2 + 0xc) + 0xcc) =
*(undefined4 *)(*(int *)(*(int *)(*(int *)(iVar2 + 0xc) + 0x18) + 0x14) + 0x28);
// xxx = ptrVertexLayout
*(undefined4 *)(*(int *)(iVar2 + 0xc) + 0xc0) =
*(undefined4 *)(*(int *)(*(int *)(*(int *)(iVar2 + 0xc) + 0x18) + 0x14) + 0x24);
}
}
return;
}
// AH_WarpPad_MenuBoxFuncPtr
void FUN_800abd80(int param_1)
{
// MENUBOX_Hide
FUN_800469c8();
// If row selected is 0
if (*(short *)(param_1 + 0x1a) == 0)
{
// Turn on CTR Challenge Mode
*(uint *)(PTR_DAT_8008d2ac + 8) = *(uint *)(PTR_DAT_8008d2ac + 8) | 8;
}
// if row selected is 1
else if (*(short *)(param_1 + 0x1a) == 1)
{
// Turn on Relic Mode
*(uint *)PTR_DAT_8008d2ac = *(uint *)PTR_DAT_8008d2ac | 0x4000000;
}
return;
}
// AH_WarpPad_SpinRewards
// param1 - instance of warppad
// param2 - object of warppad
// param3 - 0,1,2
// param4-6, warppad x,y,z
void FUN_800abdfc(int param_1,int param_2,short param_3,int param_4,int param_5,int param_6)
{
short sVar1;
int iVar2;
int iVar3;
// convert 3 rotation shorts into rotation matrix
FUN_8006c2a4(param_1 + 0x30,param_2 + 0x28);
// instance -> model -> modelID
sVar1 = *(short *)(*(int *)(param_1 + 0x18) + 0x10);
// if not trophy
if (sVar1 != 0x62)
{
// Gem
if (sVar1 == 0x5f) {
iVar3 = param_2 + 0x50;
}
else
{
// relic
if (sVar1 == 0x61) {
iVar3 = param_2 + 0x58;
}
else
{
// if not token
if (sVar1 != 0x7d) goto LAB_800abe94;
// if it is a token
iVar3 = param_2 + 0x60;
}
}
// Vector_SpecLightSpin3D
FUN_8005741c(param_1,param_2 + 0x28,iVar3);
}
LAB_800abe94:
// Sine(angle)
iVar2 = FUN_8003d184((int)*(short *)(param_2 + (int)param_3 * 2 + 0x6e));
iVar3 = (int)param_3 * 0x555;
*(int *)(param_1 + 0x48) = param_5 + ((iVar2 << 6) >> 0xc) + 0x100;
// Sine(angle)
iVar2 = FUN_8003d184(iVar3 + *(short *)(param_2 + 0x4a));
*(int *)(param_1 + 0x44) = param_4 + (iVar2 * 0xa0 >> 0xc);
// Cosine(angle)
iVar3 = FUN_8003d1c0(iVar3 + *(short *)(param_2 + 0x4a));
*(int *)(param_1 + 0x4c) = param_6 + (iVar3 * 0xa0 >> 0xc);
return;
}
// AH_WarpPad_ThTick
void FUN_800abf48(int param_1)
{
bool bVar1;
short sVar2;
short sVar3;
int iVar4;
byte *pbVar5;
undefined2 uVar6;
int iVar7;
uint uVar8;
int iVar9;
int iVar10;
undefined4 uVar11;
undefined *puVar12;
int *piVar13;
short *psVar14;
int iVar15;
undefined *puVar16;
int *piVar17;
int iVar18;
int *piVar19;
int iVar20;
byte abStack48 [8];
// rewardScale
sVar2 = 0x100;
// get object
piVar19 = *(int **)(param_1 + 0x30);
// offset 0x28 of cameraDC
// visible instances from quadblock
piVar13 = *(int **)(PTR_DAT_8008d2ac + 0x14c0);
// get instance
iVar20 = *(int *)(param_1 + 0x34);
iVar4 = *piVar13;
// pointer to P1 (9900C)
iVar18 = *(int *)(PTR_DAT_8008d2ac + 0x24ec);
// assume warppad is not visible
bVar1 = false;
// loop through all visible instances
while (iVar4 != 0)
{
iVar4 = *piVar13;
piVar13 = piVar13 + 1;
// visible instance == warppad instance
if (iVar4 == iVar20) {
// make instances in warppad visible
bVar1 = true;
break;
}
iVar4 = *piVar13;
}
// if the warp pad is visible,
// then draw stuff in the warp pad
if (bVar1)
{
// 4 CLOSED instances
iVar4 = *piVar19;
if (iVar4 != 0)
{
// make visible
*(uint *)(iVar4 + 0x28) = *(uint *)(iVar4 + 0x28) & 0xffffff7f;
}
iVar4 = piVar19[1];
if (iVar4 != 0)
{
// make visible
*(uint *)(iVar4 + 0x28) = *(uint *)(iVar4 + 0x28) & 0xffffff7f;
}
iVar4 = piVar19[2];
if (iVar4 != 0)
{
// make visible
*(uint *)(iVar4 + 0x28) = *(uint *)(iVar4 + 0x28) & 0xffffff7f;
}
iVar4 = piVar19[3];
if (iVar4 != 0)
{
// make visible
*(uint *)(iVar4 + 0x28) = *(uint *)(iVar4 + 0x28) & 0xffffff7f;
}
// beam
iVar4 = piVar19[4];
if (iVar4 != 0)
{
// make visible
*(uint *)(iVar4 + 0x28) = *(uint *)(iVar4 + 0x28) & 0xffffff7f;
}
// 2 wisps
iVar4 = 0;
piVar13 = piVar19;
do {
iVar7 = piVar13[5];
if (iVar7 != 0)
{
// make visible
*(uint *)(iVar7 + 0x28) = *(uint *)(iVar7 + 0x28) & 0xffffff7f;
}
iVar4 = iVar4 + 1;
piVar13 = piVar13 + 1;
} while (iVar4 < 2);
// 3 rewards
iVar4 = 0;
piVar13 = piVar19;
do {
iVar7 = piVar13[7];
if (iVar7 != 0)
{
// make visible
*(uint *)(iVar7 + 0x28) = *(uint *)(iVar7 + 0x28) & 0xffffff7f;
}
iVar4 = iVar4 + 1;
piVar13 = piVar13 + 1;
} while (iVar4 < 3);
}
// warppad is far away
else
{
// 4 CLOSED instances
iVar4 = *piVar19;
if (iVar4 != 0)
{
// make invisible
*(uint *)(iVar4 + 0x28) = *(uint *)(iVar4 + 0x28) | 0x80;
}
iVar4 = piVar19[1];
if (iVar4 != 0)
{
// make invisible
*(uint *)(iVar4 + 0x28) = *(uint *)(iVar4 + 0x28) | 0x80;
}
iVar4 = piVar19[2];
if (iVar4 != 0)
{
// make invisible
*(uint *)(iVar4 + 0x28) = *(uint *)(iVar4 + 0x28) | 0x80;
}
iVar4 = piVar19[3];
if (iVar4 != 0)
{
// make invisible
*(uint *)(iVar4 + 0x28) = *(uint *)(iVar4 + 0x28) | 0x80;
}
// beam
iVar4 = piVar19[4];
iVar7 = 0;
piVar13 = piVar19;
if (iVar4 != 0)
{
// make invisible
*(uint *)(iVar4 + 0x28) = *(uint *)(iVar4 + 0x28) | 0x80;
}
// wisps
do {
iVar4 = piVar13[5];
if (iVar4 != 0)
{
// make invisible
*(uint *)(iVar4 + 0x28) = *(uint *)(iVar4 + 0x28) | 0x80;
}
iVar7 = iVar7 + 1;
piVar13 = piVar13 + 1;
} while (iVar7 < 2);
// rewards
iVar4 = 0;
piVar13 = piVar19;
do {
iVar7 = piVar13[7];
if (iVar7 != 0)
{
// make invisible
*(uint *)(iVar7 + 0x28) = *(uint *)(iVar7 + 0x28) | 0x80;
}
iVar4 = iVar4 + 1;
piVar13 = piVar13 + 1;
} while (iVar4 < 3);
}
// make warppad invisible
*(uint *)(iVar20 + 0x28) = *(uint *)(iVar20 + 0x28) | 0x80;
// Get instance from driver object
iVar10 = *(int *)(iVar18 + 0x1c);
// get difference between Player and WarpPad coordinates
iVar4 = *(int *)(iVar20 + 0x44) - *(int *)(iVar10 + 0x44);
iVar7 = *(int *)(iVar20 + 0x48) - *(int *)(iVar10 + 0x48);
iVar10 = *(int *)(iVar20 + 0x4c) - *(int *)(iVar10 + 0x4c);
// Get distance from player and warp pad
iVar4 = iVar4 * iVar4 + iVar7 * iVar7 + iVar10 * iVar10;
if (
(
(
// Trophy tracks
((*(short *)(piVar19 + 0x1b) < 0x10) && (iVar4 < 0x144000)) ||
(
// Slide Col or Turbo Track
((uint)*(ushort *)(piVar19 + 0x1b) - 0x10 < 2 && (iVar4 < 0x90000))
)
) ||
(
// Battle tracks
((uint)*(ushort *)(piVar19 + 0x1b) - 0x12 < 7 && (iVar4 < 0x144000))
)
) ||
(
// Gem Cup portals
(99 < *(short *)(piVar19 + 0x1b) && (iVar4 < 0x90000))
)
)
{
// If closest warppad changed this frame
if ((DAT_800b4e86 != -1) && (DAT_800b4e86 != *(short *)(piVar19 + 0x1b)))
// dont give hint
goto LAB_800ac518;
// === warppad didn't change this frame ===
// Choose if a hint is needed or not
// save warppad ID nearest
DAT_800b4e86 = *(short *)(piVar19 + 0x1b);
// if warppad is a gem cup
if (99 < (int)*(short *)(piVar19 + 0x1b))
{
// if aku is not giving a hint
if (DAT_8008d874 == 0)
{
// draw a string of cup name "Red Cup", "Green Cup", etc
FUN_80022878(
// string
*(undefined4 *)
((int)*(short *)(&DAT_80084114 +
((int)(((uint)*(ushort *)(piVar19 + 0x1b) - 100) * 0x10000) >>
0xd)) * 4 + DAT_8008d878),
// gGT->tileView[0].rect (midpoint X)
(int)(((uint)*(ushort *)(PTR_DAT_8008d2ac + 0x184) +
((int)((uint)*(ushort *)(PTR_DAT_8008d2ac + 0x188) << 0x10) >> 0x11)) *
0x10000) >> 0x10,
// gGT->tileView[0].rect (bottom Y - 0x1E)
(int)(((uint)*(ushort *)(PTR_DAT_8008d2ac + 0x186) +
(uint)*(ushort *)(PTR_DAT_8008d2ac + 0x18a) + -0x1e) * 0x10000) >> 0x10,
1,0xffff8000);
}
// if hint is not unlocked
if ((DAT_8008fbb4 & 0x20000) == 0)
{
// Gem Cups Hint
uVar11 = 0x1b;
// 1s digit == 0 (warppad unlocked),
// skip CLOSED instances, and dont give hint
if (piVar19[2] == 0) goto LAB_800ac860;
LAB_800ac500:
// give aku hint
FUN_80035e20(uVar11,0);
}
goto LAB_800ac518;
}
// === Not Gem Cup ===
// if aku is not giving a hint
if (DAT_8008d874 == 0)
{
// draw a string, MetaDataLEV
FUN_80022878(
// string
*(undefined4 *)
((int)(short)(&DAT_80083a88)[(int)*(short *)(piVar19 + 0x1b) * 0xc] * 4 +
DAT_8008d878),
// gGT->tileView[0].rect (midpoint X)
(int)(((uint)*(ushort *)(PTR_DAT_8008d2ac + 0x184) +
((int)((uint)*(ushort *)(PTR_DAT_8008d2ac + 0x188) << 0x10) >> 0x11)) * 0x10000) >> 0x10,
// gGT->tileView[0].rect (bottom Y - 0x1E)
(int)(((uint)*(ushort *)(PTR_DAT_8008d2ac + 0x186) +
(uint)*(ushort *)(PTR_DAT_8008d2ac + 0x18a) + -0x1e) * 0x10000) >> 0x10,
1, 0xffff8000);
}
// if not Slide Col
if (*(short *)(piVar19 + 0x1b) != 0x10)
{
if (
// anything except 0x11-0x18, all trophy tracks
(7 < (ushort)(*(short *)(piVar19 + 0x1b) - 0x11U)) &&
// if dont have hint "you must have more trophies"
((DAT_8008fbb0 & 0x1000000) == 0)
)
{
// 1s digit == 0 (warppad unlocked),
// skip code for CLOSED instances
if (piVar19[2] == 0) goto LAB_800ac860;
// If track is not beaten (key is not floating above warppad)
// object -> instance -> model -> modelID != STATIC_KEY
if (*(short *)(*(int *)(*piVar19 + 0x18) + 0x10) != 99)
{
// give Aku hint for needing more trophies
uVar11 = 2;
// give hint, then goto LAB_800ac518 right after
goto LAB_800ac500;
}
}
// dont give hint
goto LAB_800ac518;
}
// === If Slide Col ===
// if aku hint is unlocked, dont give hint
if ((DAT_8008fbb4 & 0x40000) != 0) goto LAB_800ac518;
// If hint is not unlocked, give hint
// Must get 10 relics hint
uVar11 = 0x1c;
// give hint, then goto LAB_800ac518 right after
if (piVar19[2] != 0) goto LAB_800ac500;
}
else
{
// erase warppad name displayed on-screen,
// NOP at 800ac514 to keep the ID at address for debugging
DAT_800b4e86 = -1;
LAB_800ac518:
// if 1s digit (warppad locked)
// adjust all instances to face camera
if (piVar19[2] != 0)
{
// angle between camera and warppad
sVar2 = ratan2(*(int *)(iVar20 + 0x44) - (int)*(short *)(PTR_DAT_8008d2ac + 0x168),
*(int *)(iVar20 + 0x4c) - (int)*(short *)(PTR_DAT_8008d2ac + 0x16c));
// if no 10s digit
if (piVar19[3] == 0) {
iVar18 = (int)-sVar2;
// Cos(angle)
iVar4 = FUN_8003d1c0(iVar18);
*(int *)(piVar19[2] + 0x44) = *(int *)(iVar20 + 0x44) + (iVar4 * -0x80 >> 0xc);
// Sine(angle)
iVar4 = FUN_8003d184(iVar18);
*(int *)(piVar19[2] + 0x4c) = *(int *)(iVar20 + 0x4c) + (iVar4 * -0x80 >> 0xc);
// Cos(angle)
iVar4 = FUN_8003d1c0(iVar18);
*(int *)(*piVar19 + 0x44) = *(int *)(iVar20 + 0x44) + ((iVar4 << 7) >> 0xc);
// Sine(angle)
iVar4 = FUN_8003d184(iVar18);
*(int *)(*piVar19 + 0x4c) = *(int *)(iVar20 + 0x4c) + ((iVar4 << 7) >> 0xc);
}
// if 10s digit
else {
iVar18 = (int)-sVar2;
// Cos(angle)
iVar4 = FUN_8003d1c0(iVar18);
*(int *)(*piVar19 + 0x44) = *(int *)(iVar20 + 0x44) + (iVar4 * 0xc0 >> 0xc);
// Sine(angle)
iVar4 = FUN_8003d184(iVar18);
*(int *)(*piVar19 + 0x4c) = *(int *)(iVar20 + 0x4c) + (iVar4 * 0xc0 >> 0xc);
// Cos(angle)
iVar4 = FUN_8003d1c0(iVar18);
*(int *)(piVar19[1] + 0x44) = *(int *)(iVar20 + 0x44) + ((iVar4 << 6) >> 0xc);
// Sine(angle)
iVar4 = FUN_8003d184(iVar18);
*(int *)(piVar19[1] + 0x4c) = *(int *)(iVar20 + 0x4c) + ((iVar4 << 6) >> 0xc);
// Cos(angle)
iVar4 = FUN_8003d1c0(iVar18);
*(int *)(piVar19[3] + 0x44) = *(int *)(iVar20 + 0x44) + (iVar4 * -0x40 >> 0xc);
// Sine(angle)
iVar4 = FUN_8003d184(iVar18);
*(int *)(piVar19[3] + 0x4c) = *(int *)(iVar20 + 0x4c) + (iVar4 * -0x40 >> 0xc);
// Cos(angle)
iVar4 = FUN_8003d1c0(iVar18);
*(int *)(piVar19[2] + 0x44) = *(int *)(iVar20 + 0x44) + (iVar4 * -0xa0 >> 0xc);
// Sine(angle)
iVar4 = FUN_8003d184(iVar18);
*(int *)(piVar19[2] + 0x4c) = *(int *)(iVar20 + 0x4c) + (iVar4 * -0xa0 >> 0xc);
}
piVar13 = piVar19 + 10;
*(undefined2 *)(piVar19 + 10) = 0;
*(undefined2 *)(piVar19 + 0xb) = 0;
// spin rate of item
// required to unlock warppad
*(short *)((int)piVar19 + 0x2a) = *(short *)((int)piVar19 + 0x2a) + 0x40;
// convert 3 rotation shorts into rotation matrix
FUN_8006c2a4(*piVar19 + 0x30,piVar13);
// thread -> model -> modelID == Gem
if (*(short *)(*(int *)(*piVar19 + 0x18) + 0x10) == 0x5f) {
uVar8 = *(uint *)(PTR_DAT_8008d2ac + 0x1cec) / 0x3c;
iVar4 = (int)((uVar8 - (((uint)((ulonglong)uVar8 * 0xcccccccd >> 0x20) & 0xfffffffc) +
uVar8 / 5)) * 0x10000) >> 0xd;
*(uint *)(*piVar19 + 0x24) =
(int)*(short *)((int)&DAT_80084116 + iVar4) << 0x14 |
(int)*(short *)((int)&DAT_80084118 + iVar4) << 0xc |
(int)*(short *)((int)&DAT_8008411a + iVar4) << 4;
}
iVar4 = *piVar19;
// modelID
sVar2 = *(short *)(*(int *)(iVar4 + 0x18) + 0x10);
// trophy
if (sVar2 == 0x62) {
return;
}
// not key
if (sVar2 != 99)
{
// relic
if (sVar2 == 0x61)
{
// Vector_SpecLightSpin3D
FUN_8005741c(iVar4,piVar13,piVar19 + 0x16);
return;
}
// token
if (sVar2 == 0x7d)
{
// Vector_SpecLightSpin3D
FUN_8005741c(iVar4,piVar13,piVar19 + 0x18);
return;
}
// if this is not a gem
if (sVar2 != 0x5f) {
return;
}
}
// Vector_SpecLightSpin3D
FUN_8005741c(iVar4,piVar13,piVar19 + 0x14);
return;
}
}
// Assume Unlocked
LAB_800ac860:
// If dist>0x9000, and if not in warppad, then DontLoadLevelYet,
// warp animation can push you outside 0x9000, so the 0x1d offset is a fallback
if ((0x8fff < iVar4) && (*(short *)(piVar19 + 0x1d) == 0)) goto LAB_800acef8;
// Set Character IDs of AIs
// param_1 will always be P1 Character ID
FUN_800327dc((int)DAT_80086e84);
// Get the track "speed champion" scrapped idea from Aug 14,
// make this driver spawn in 1st place on the track out of 8 drivers,
// If that driver is Crash-Pura, and does not match P1's driver
if ((*(short *)(&DAT_80083a96 + (int)*(short *)(piVar19 + 0x1b) * 0x18) < 8) &&
(iVar7 = 0,
*(short *)(&DAT_80083a96 + (int)*(short *)(piVar19 + 0x1b) * 0x18) !=
// Player / AI structure + 0x4a shows driver index (0-7)
// character ID
(&DAT_80086e84)[*(byte *)(iVar18 + 0x4a)]))
{
// loop counter
iVar10 = 1;
// &data.kartSpawnOrderArray[1]
puVar12 = &DAT_8008d69d;
// &data.characterIDs[1]
psVar14 = &DAT_80086e86;
// Make drivers spawn in their usual order,
// but P1 in the back, put speed champion first,
// and put Pura where the speed champion would've gone
// for iVar10 = 1; iVar10 < 8; iVar10++
do
{
// If Speed Champion equals Character ID
if (*(short *)(&DAT_80083a96 + (int)*(short *)(piVar19 + 0x1b) * 0x18) == *psVar14) {
*puVar12 = 0;
iVar7 = iVar10;
}
else {
if (iVar10 == 7) {
DAT_8008d6a0._3_1_ = (undefined)iVar7;
}
else {
*puVar12 = (char)iVar10;
}
}
// increment unknown pointer
puVar12 = puVar12 + 1;
// increment loop counter
iVar10 = iVar10 + 1;
// increment character ID pointer
// to next index of the array
psVar14 = psVar14 + 1;
} while (iVar10 < 8);
}
// If "speed champion" is an invalid choice, just randomize
else
{
// i = 1; i < 8; i++
// arr[i] = i;
pbVar5 = abStack48 + 1;
iVar7 = 1;
do {
*pbVar5 = (byte)iVar7;
iVar10 = iVar7 + 1;
pbVar5 = abStack48 + iVar7 + 1;
iVar7 = iVar10;
} while (iVar10 < 8);
// i = 0; i < 7; i++
iVar7 = 0;
do {
uVar8 = FUN_8006c684(&DAT_8008d668);
iVar10 = 7 - iVar7;
if (iVar10 == 0) trap(0x1c00);
if ((iVar10 == -1) && ((uVar8 & 0xfff) == 0x80000000)) trap(0x1800);
iVar10 = (int)(uVar8 & 0xfff) % iVar10 + 1;
iVar9 = iVar10 * 0x10000 >> 0x10;
// kartSpawnOrderArray
(&DAT_8008d69c)[abStack48[iVar9]] = (char)iVar7;
// another loop of 7
while (iVar9 < 7) {
sVar3 = (short)iVar10;
iVar10 = iVar10 + 1;
iVar9 = iVar10 * 0x10000 >> 0x10;
abStack48[(int)sVar3] = abStack48[(int)sVar3 + 1];
}
iVar7 = iVar7 + 1;
} while (iVar7 < 7);
}
// manipulate spawn data to make
// P1 spawn in 8th place on track
DAT_8008d69c = 7;
// TitleFlag_IsTransitioning
iVar7 = FUN_80043f44();
// If transitioning then DontLoadLevelYet,
// cause loading level has already been decided
if (iVar7 != 0) goto LAB_800acef8;
iVar7 = (int)*(short *)(piVar19 + 0x1b);
uVar8 = (uint)*(ushort *)(piVar19 + 0x1b);
// if warppad is not a cup
if (iVar7 < 100)
{
// if entered Slide or Turbo Track
if ((uVar8 - 0x10 & 0xffff) < 2)
{
// warp for 2 seconds, then assume relic race, load immediately
// boolEnteredWarppad
*(undefined2 *)(piVar19 + 0x1d) = 1;
// increase frames spent warping
*(short *)((int)piVar19 + 0x76) = *(short *)((int)piVar19 + 0x76) + 1;
// VehPtr_Warp_Init
*(undefined4 *)(iVar18 + 0x54) = 0x80068e04;
// If [???] then DontLoadLevelYet
if (*(short *)((int)piVar19 + 0x76) < 0x3d) goto LAB_800acef8;
iVar18 = (int)*(short *)(piVar19 + 0x1b);
// when loading is done, add flag for Relic Race
DAT_8008d100 = DAT_8008d100 | 0x4000000;
// when loading is done, remove flag for In Adventure Arena
DAT_8008d104 = DAT_8008d104 | 0x100000;
}
// if not Slide or Turbo Track
else
{
// if levID is 0x12, 0x13, 0x15, 0x17,
// any crystal challenge portal
if ((((uVar8 - 0x12 & 0xffff) < 2) || (iVar7 == 0x15)) || (iVar7 == 0x17))
{
// give hint if needed, then load level after 2 seconds of warping
// boolEnteredWarppad
*(undefined2 *)(piVar19 + 0x1d) = 1;
// increase frames warping
*(short *)((int)piVar19 + 0x76) = *(short *)((int)piVar19 + 0x76) + 1;
// VehPtr_Warp_Init
*(undefined4 *)(iVar18 + 0x54) = 0x80068e04;
// If [???] then DontLoadLevelYet
if (*(short *)((int)piVar19 + 0x76) < 0x3d) goto LAB_800acef8;
// If hint is not unlocked
if ((DAT_8008fbb4 & 0x8000) == 0)
{
// give Aku hint:
// "collect every crystal in arena"
FUN_80035e20(0x19,1);
}
// Check if Aku Aku is giving a hint,
// 0 - speaking,
// 1 - gone
// AH_MaskHint_boolCanSpawn
uVar8 = FUN_800b3f88();
// If Aku is speaking, then DontLoadLevelYet
if ((uVar8 & 0xffff) == 0) goto LAB_800acef8;
// when loading is done, remove flag for In Adventure Arena
DAT_8008d104 = DAT_8008d104 | 0x100000;
// set "originalEventTime" for Crystal Challenge
*(undefined4 *)(PTR_DAT_8008d2ac + 0x1d84) =
*(undefined4 *)(&DAT_800b4e88 + ((int)*(short *)(piVar19 + 0x1b) + -0x12) * 4);
iVar18 = (int)*(short *)(piVar19 + 0x1b);
// when loading is done, add flag for Crystal Challenge
DAT_8008d100 = DAT_8008d100 | 0x8000000;
}
// if not crystal challenge portal
else
{
// if levID for this hub, < 0x10,
// for all tracks except Slide and Turbo Track
if (iVar7 < 0x10)
{
// 0x8fba4 is where the adventure profile (currently loaded) begins,
// 6th bit is where trophy starts
// If Trophy has already been awarded for this track
if (((uint)(&DAT_8008fba4)[(int)(iVar7 + 6U) >> 5] >> (iVar7 + 6U & 0x1f) & 1) != 0)
{
// if you already have a key on this hub
if (
// if hubID (1 for n sanity, 2 for lost ruin, etc)
(int)*(short *)(&DAT_800b4e7c + (int)(short)(&DAT_80083a80)[iVar7 * 0xc] * 2)
// <= numKeys you have
<= *(int *)(PTR_DAT_8008d2ac + 0x1e38)
)
{
if (0x3c < *(short *)((int)piVar19 + 0x76))
{
if (
// if MenuBox is not open
(DAT_8008d4b0 == 0) &&
// If you're in Adventure Arena
((*(uint *)PTR_DAT_8008d2ac & 0x100000) != 0)
)
{
// menubox->0x1a (row)
DAT_800b4e6a =
// check if token is unlocked, then row = 1 (relic race)
(ushort)((uint)(&DAT_8008fba4)[(int)(iVar7 + 0x4cU) >> 5] >>
(iVar7 + 0x4cU & 0x1f)) & 1;
// open CTR Challenge / Relic MenuBox
FUN_80046990(&DAT_800b4e50);
// open MenuBox
DAT_8008d4b0 = 1;
}
// check if MenuBox is hidden
uVar8 = FUN_800469dc(&DAT_800b4e50);
// if it is, then the user chose an event
if ((uVar8 & 0xffff) != 0)
{
// If player did not choose CTR Token Race,
// Give Relic Aku Hint
iVar7 = 0x1d;
// if player chose CTR Token Race
if ((*(uint *)(PTR_DAT_8008d2ac + 8) & 8) != 0)
{
// Give CTR Token Aku Hint
iVar7 = 0x1a;
}
// 0x8fba4 is where the adventure profile (currently loaded) begins,
// if aku hint is not unlocked...
if (((uint)(&DAT_8008fba4)[(int)(iVar7 + 0x76U) >> 5] >> (iVar7 + 0x76U & 0x1f) &
1) == 0)
{
// unlock hint (CTR challenge or Relic)
FUN_80035e20(iVar7,1);
}
// Check if Aku Aku is giving a hint,
// 0 - speaking,
// 1 - gone
// AH_MaskHint_boolCanSpawn
uVar8 = FUN_800b3f88();
// if aku is gone
if ((uVar8 & 0xffff) != 0) {
DAT_8008d4b0 = 0;
// boolEnteredWarppad (to prevent running code again)
*(undefined2 *)(piVar19 + 0x1d) = 0;
// when loading is done, remove flag for "in adventure arena"
DAT_8008d104 = DAT_8008d104 | 0x100000;
FUN_8003cfc0((int)*(short *)(piVar19 + 0x1b));
}
}
}
// frames warping
if (*(short *)((int)piVar19 + 0x76) < 0x400) {
*(short *)((int)piVar19 + 0x76) = *(short *)((int)piVar19 + 0x76) + 1;
}
// boolEnteredWarppad
*(undefined2 *)(piVar19 + 0x1d) = 1;
// VehPtr_Warp_Init
*(undefined4 *)(iVar18 + 0x54) = 0x80068e04;
// DontLoadLevelYet
goto LAB_800acef8;
}
// if you have the trophy, but not the hub key,
// === Not Possible, already determined warppad unlocked ===
goto LAB_800ace34;
}
}
// ELSE is not possible,
// just designed not to run unless GOTO happens,
// which still isn't possible either
else {
LAB_800ace34:
// 6th bit is where trophy starts
uVar8 = (int)*(short *)(piVar19 + 0x1b) + 6;
// If you already have this trophy unlocked
if ((((uint)(&DAT_8008fba4)[(int)uVar8 >> 5] >> (uVar8 & 0x1f) & 1) != 0) &&
(((uint)(&DAT_8008fba4)
// 0x5d is where key bits start
// If a boss key is not unlocked
[(int)((int)(short)(&DAT_80083a80)[(int)*(short *)(piVar19 + 0x1b) * 0xc] + 0x5dU) >> 5]
>> ((int)(short)(&DAT_80083a80)[(int)*(short *)(piVar19 + 0x1b) * 0xc] + 0x5dU & 0x1f)
// If [???] then DontLoadLevelYet
& 1) == 0)) goto LAB_800acef8;
}
// if trophy has not been awarded on track [ anything < 16 ],
// then warp for 2 seconds, then start loading track
// boolEnteredWarppad
*(undefined2 *)(piVar19 + 0x1d) = 1;
// increment frames warping
*(short *)((int)piVar19 + 0x76) = *(short *)((int)piVar19 + 0x76) + 1;
// VehPtr_Warp_Init
*(undefined4 *)(iVar18 + 0x54) = 0x80068e04;
// If [???] then DontLoadLevelYet
if (*(short *)((int)piVar19 + 0x76) < 0x3d) goto LAB_800acef8;
iVar18 = (int)*(short *)(piVar19 + 0x1b);
// when loading is done, remove flag for "in adventure arena"
DAT_8008d104 = DAT_8008d104 | 0x100000;
}
}
}
// if just entered a cup
// [100 + cupID]
else
{
// boolEnteredWarppad
*(undefined2 *)(piVar19 + 0x1d) = 1;
// increment frames warping
*(short *)((int)piVar19 + 0x76) = *(short *)((int)piVar19 + 0x76) + 1;
// VehPtr_Warp_Init
*(undefined4 *)(iVar18 + 0x54) = 0x80068e04;
puVar12 = PTR_DAT_8008d2ac;
// If [???] then DontLoadLevelYet
if (*(short *)((int)piVar19 + 0x76) < 0x3d) goto LAB_800acef8;
// for loop counts backwards
iVar18 = 7;
puVar16 = PTR_DAT_8008d2ac + 0x1c;
// when loading is done, remove flag for "in adventure arena"
DAT_8008d104 = DAT_8008d104 | 0x100000;
// set track index to zero (first track)
*(undefined4 *)(PTR_DAT_8008d2ac + 0x1e5c) = 0;
// when loading is done, add flag for Adventure Cup
DAT_8008d100 = DAT_8008d100 | 0x10000000;
// set cup index to the cup you entered
*(int *)(puVar12 + 0x1e58) = (int)((uVar8 - 100) * 0x10000) >> 0x10;
// set all cup points to zero
do {
*(undefined4 *)(puVar16 + 0x1e60) = 0;
iVar18 = iVar18 + -1;
puVar16 = puVar16 + -4;
} while (-1 < iVar18);
// LEV to load, advCupTrackIDs[trackIndex*4 + ...]
iVar18 = (int)*(short *)(&DAT_800840a4 +
*(int *)(PTR_DAT_8008d2ac + 0x1e5c) * 4 +
((int)((uVar8 - 100) * 0x10000) >> 0xc));
}
// MainRaceTrack_RequestLoad
FUN_8003cfc0(iVar18);
// DontLoadLevelYet
LAB_800acef8:
// Spin the electric outline
if (
// if warppad portal exists
(piVar19[4] != 0) &&
// only spin once every two frames, electric look
((*(uint *)(PTR_DAT_8008d2ac + 0x1cec) & 1) != 0)
)
{
*(undefined2 *)(piVar19 + 0x10) = 0;
iVar18 = FUN_8003ea28();
*(undefined2 *)(piVar19 + 0x11) = 0;
// warppad portal spin
*(short *)((int)piVar19 + 0x42) =
*(short *)((int)piVar19 + 0x42) +
((short)(iVar18 >> 3) + (short)((iVar18 >> 3) / 6) * -6 + 1) * 0x200;
// convert 3 rotation shorts into rotation matrix
FUN_8006c2a4(piVar19[4] + 0x30,piVar19 + 0x10);
}
iVar18 = 0;
iVar7 = 0x200000;
piVar13 = piVar19;
piVar17 = piVar19;
// loop through two particles in warppad
do {
// if particle instances exist
if (piVar13[5] != 0)
{
// max height of particle 1
iVar10 = 0x600;
// if not close to a warppad
if (DAT_800b4e86 != -1)
{
// max height of particle 2
iVar10 = 0x400;
}
*(undefined2 *)(piVar17 + 0xc) = 0;
*(undefined2 *)(piVar17 + 0xd) = 0;
// warppad particle spin rate
*(short *)((int)piVar17 + 0x32) = *(short *)((int)piVar17 + 0x32) + 0x100;
// warppad particle spin
// convert 3 rotation shorts into rotation matrix
FUN_8006c2a4(piVar13[5] + 0x30,piVar19 + iVar18 * 2 + 0xc);
iVar9 = piVar13[5];
// particle rise rate (= 0x20)
iVar15 = iVar7 >> 0x10;
// if particle hsa not reached max height
if (*(int *)(iVar9 + 0x48) < *(int *)(iVar20 + 0x48) + iVar10)
{
// increase height
*(int *)(iVar9 + 0x48) = *(int *)(iVar9 + 0x48) + iVar15;
iVar9 = piVar13[5];
if (*(int *)(iVar9 + 0x48) < *(int *)(iVar20 + 0x48) + iVar15 * 4) {
*(short *)(iVar9 + 0x22) = *(short *)(iVar9 + 0x22) + -0x380;
}
else {
if (iVar15 == 0) {
trap(0x1c00);
}
if ((iVar15 == -1) && (iVar10 == -0x80000000)) {
trap(0x1800);
}
if (iVar10 / iVar15 == 0) {
trap(0x1c00);
}
*(short *)(iVar9 + 0x22) = *(short *)(iVar9 + 0x22) + (short)(0xc00 / (iVar10 / iVar15));
}
}
// if max height was reached
else
{
// respawn particle
*(int *)(iVar9 + 0x48) = *(int *)(iVar20 + 0x48);
*(undefined2 *)(piVar13[5] + 0x22) = 0x1000;
iVar9 = FUN_8003ea28();
iVar9 = iVar9 >> 3;
iVar10 = iVar9;
if (iVar9 < 0) {
iVar10 = iVar9 + 0xfff;
}
*(short *)((int)piVar17 + 0x32) = (short)iVar9 + (short)(iVar10 >> 0xc) * -0x1000;
}
}
// += 0x10
iVar7 = iVar7 + 0x100000;
piVar17 = piVar17 + 2;
iVar18 = iVar18 + 1;
piVar13 = piVar13 + 1;
} while (iVar18 < 2);
// spin rate item inside unlocked warppad
*(short *)((int)piVar19 + 0x2a) = *(short *)((int)piVar19 + 0x2a) + 0x80;
// get distance from driver,
// calculate rewardScale for rewards in portal
iVar18 = iVar4 + -0x900000;
if (0x900000 < iVar4) {
if (0x900000 < iVar18) {
iVar18 = 0x900000;
}
sVar2 = (short)(((0x900000 - iVar18) * 0x100) / 0x900000);
}
iVar4 = 0;
piVar13 = piVar19;
piVar17 = piVar19;
// loop through 3 items in warppad,
// can be trophy, token, relic, gem,
// only a max of 3 items can exist
do
{
*(undefined2 *)(piVar19 + 0xb) = 0x155;
// if instance of item in warppad is valid
if (piVar13[7] != 0)
{
// AH_WarpPad_SpinRewards
FUN_800abdfc
(piVar13[7],piVar19,(int)(short)iVar4,*(undefined4 *)(iVar20 + 0x44),
*(undefined4 *)(iVar20 + 0x48),*(undefined4 *)(iVar20 + 0x4c));
// instance -> model -> modelID
sVar3 = *(short *)(*(int *)(piVar13[7] + 0x18) + 0x10);
iVar18 = 0x2000;
// if model is token or relic
if ((sVar3 != 0x7d) && (iVar18 = 0x2800, sVar3 == 0x61)) {
iVar18 = 0x1800;
}
// Set Scale (x, y, z)
uVar6 = (undefined2)((uint)(iVar18 * (int)sVar2) >> 8);
*(undefined2 *)(piVar13[7] + 0x1c) = uVar6;
*(undefined2 *)(piVar13[7] + 0x1e) = uVar6;
*(undefined2 *)(piVar13[7] + 0x20) = uVar6;
if ((int)sVar2 == 0)
{
// make invisible
*(uint *)(piVar13[7] + 0x28) = *(uint *)(piVar13[7] + 0x28) | 0x80;
}
else
{
// make visible
*(uint *)(piVar13[7] + 0x28) = *(uint *)(piVar13[7] + 0x28) & 0xffffff7f;
}
}
piVar13 = piVar13 + 1;
iVar4 = iVar4 + 1;
*(short *)((int)piVar17 + 0x6e) = *(short *)((int)piVar17 + 0x6e) + 0x20;
*(short *)((int)piVar19 + 0x4a) = *(short *)((int)piVar19 + 0x4a) + 4;
piVar17 = (int *)((int)piVar17 + 2);
} while (iVar4 < 3);
// === Naughty Dog mistake ===
// This is impossible, even with hacks,
// it will never trigger, cause the function
// already determined no CLOSED instances
// if CLOSED instances exist, erase them
if (piVar19[2] != 0)
{
// INSTANCE_Death
FUN_80030aa8(piVar19[2]);
FUN_80030aa8(piVar19[3]);
FUN_80030aa8(piVar19[1]);
FUN_80030aa8(piVar19[0]);
}
return;
}
// AH_WarpPad_ThDestroy
void FUN_800ad2c8(int param_1)
{
int *piVar1;
int iVar2;
int *piVar3;
// Get warppad object from thread
piVar3 = *(int **)(param_1 + 0x30);
// if instance exists
if (piVar3[2] != 0)
{
// INSTANCE_Death
FUN_80030aa8();
// nullptr
piVar3[2] = 0;
}
// if instance exists
if (piVar3[3] != 0)
{
// INSTANCE_Death
FUN_80030aa8();
// nullptr
piVar3[3] = 0;
}
// if instance exists
if (piVar3[1] != 0)
{
// INSTANCE_Death
FUN_80030aa8();
// nullptr
piVar3[1] = 0;
}
// if instance exists
if (*piVar3 != 0)
{
// INSTANCE_Death
FUN_80030aa8();
// nullptr
*piVar3 = 0;
}
iVar2 = 0;
piVar1 = piVar3;
// if instance exists
if (piVar3[4] != 0)
{
// INSTANCE_Death
FUN_80030aa8();
// nullptr
piVar3[4] = 0;
}
do
{
// if instance exists
if (piVar1[5] != 0)
{
// INSTANCE_Death
FUN_80030aa8();
// nullptr
piVar1[5] = 0;
}
iVar2 = iVar2 + 1;
piVar1 = piVar1 + 1;
} while (iVar2 < 2);
iVar2 = 0;
do
{
// if instance exists
if (piVar3[7] != 0)
{
// INSTANCE_Death
FUN_80030aa8();
// nullptr
piVar3[7] = 0;
}
iVar2 = iVar2 + 1;
piVar3 = piVar3 + 1;
} while (iVar2 < 3);
return;
}
// AH_WarpPad_LInB
void FUN_800ad3ec(int param_1)
{
char cVar1;
ushort uVar2;
undefined *puVar3;
int iVar4;
int *piVar5;
uint uVar6;
undefined2 uVar7;
int iVar8;
int *piVar9;
short sVar10;
undefined4 uVar11;
undefined4 uVar12;
undefined4 uVar13;
int iVar14;
undefined4 *puVar15;
int iVar16;
int iVar17;
int *piVar18;
int iVar19;
undefined4 local_40;
undefined2 local_3c;
undefined4 local_38;
undefined4 local_34;
undefined4 local_30;
undefined2 local_2c;
iVar17 = 0;
iVar19 = -1;
iVar14 = 0;
// If a thread already exists for this Instance
if (*(int *)(param_1 + 0x6c) != 0) {
// quit
return;
}
// THREAD_BirthWithObject
// 0x78 = size
// 0 = no relation to param4
// 0x200 = MediumStackPool
// 0x5 = warppad thread bucket
iVar4 = FUN_8004205c(0x780205,FUN_800abf48,s_warppad_800ab9f4,0);
// Give the thread to Instance
*(int *)(param_1 + 0x6c) = iVar4;
// If the thread failed
if (iVar4 == 0)
{
// Quit
return;
}
// Give Instance to Thread
*(int *)(iVar4 + 0x34) = param_1;
// set funcThDestroy, AH_WarpPad_ThDestroy
*(undefined4 *)(iVar4 + 0x24) = 0x800ad2c8;
// set modelID to zero ??
*(undefined2 *)(iVar4 + 0x44) = 0;
// Get warppad object from thread
piVar18 = *(int **)(iVar4 + 0x30);
// make invisible
*(uint *)(param_1 + 0x28) = *(uint *)(param_1 + 0x28) | 0x80;
// initialize warppad object
*(undefined2 *)(piVar18 + 0x1b) = 0;
*(undefined2 *)(piVar18 + 0x1d) = 0;
*(undefined2 *)((int)piVar18 + 0x76) = 0;
// first character in Inst name
cVar1 = *(char *)(param_1 + 0x10);
iVar8 = 8;
puVar3 = PTR_DAT_8008d2ac;
while (
PTR_DAT_8008d2ac = puVar3,
// if this Instance has a string
cVar1 != '\0'
)
{
// get warppad ID by parsing Instance string
// changing warppad#6 to warppad#0 will change
// roo's tubes portal to dingo canyon
sVar10 = *(short *)(piVar18 + 0x1b);
*(short *)(piVar18 + 0x1b) = sVar10 * 10;
*(ushort *)(piVar18 + 0x1b) =
sVar10 * 10 + ((ushort)*(byte *)(param_1 + (short)iVar8 + 8) - 0x30);
iVar8 = iVar8 + 1;
// change the value, then never use it again???
cVar1 = *(char *)(param_1 + (iVar8 * 0x10000 >> 0x10) + 8);
puVar3 = PTR_DAT_8008d2ac;
}
iVar8 = (int)*(short *)(piVar18 + 0x1b);
// trophy tracks
if (iVar8 < 0x10)
{
// 0x8fba4 is where the adventure profile (currently loaded) begins
// if trophy is not unlocked on this track
if (((uint)(&DAT_8008fba4)[(int)(iVar8 + 6U) >> 5] >> (iVar8 + 6U & 0x1f) & 1) == 0) {
// numTrophies
iVar14 = *(int *)(puVar3 + 0x1e30);
// STATIC_TROPHY
iVar17 = 0x62;
}
// if trophy is unlocked on this track
else {
// numKeys
iVar14 = *(int *)(puVar3 + 0x1e38);
// get number of keys needed to unlock this warppad, with a trophy
iVar19 = (int)*(short *)(&DAT_800b4e7c + (int)(short)(&DAT_80083a80)[iVar8 * 0xc] * 2);
// STATIC_KEY
iVar17 = 99;
}
}
// not trophy track
else
{
// slide col
if (iVar8 == 0x10)
{
// gGT->numRelics
iVar14 = *(int *)(puVar3 + 0x1e34);
// STATIC_RELIC
iVar17 = 0x61;
}
// not slide col
else
{
// turbo track
if (iVar8 == 0x11)
{
// STATIC_GEM
iVar17 = 0x5f;
uVar6 = 0x6a;
iVar8 = 0;
do
{
// 0x8fba4 is where the adventure profile (currently loaded) begins
if (((uint)(&DAT_8008fba4)[(int)uVar6 >> 5] >> (uVar6 & 0x1f) & 1) != 0) {
iVar14 = iVar14 + 1;
}
iVar16 = iVar8 + 1;
uVar6 = iVar8 + 0x6b;
iVar8 = iVar16;
} while (iVar16 < 5);
}
// not turbo track
else
{
// battle tracks
if ((((uint)*(ushort *)(piVar18 + 0x1b) - 0x12 < 2) || (iVar8 == 0x15)) ||
(uVar6 = (uint)*(ushort *)(piVar18 + 0x1b) - 100, iVar8 == 0x17)) {
// gGT->numKeys
iVar14 = *(int *)(puVar3 + 0x1e38);
// STATIC_KEY
iVar17 = 99;
}
// not battle tracks
else
{
// (wrappadID-100) < 5,
// for 5 gem cup warppads
if ((uVar6 & 0xffff) < 5)
{
// STATIC_TOEKN
iVar17 = 0x7d;
// number of each type of Token (red,green,blue,yellow,purple)
iVar14 = *(int *)(puVar3 + ((int)(uVar6 * 0x10000) >> 0xe) + 0x1e40);
}
}
}
}
}
// if requirement number was not given
if (iVar19 < 0)
{
// STATIC_TOKEN
// if tokens are needed to open the warppad
if (iVar17 == 0x7d)
{
// four tokens are needed to open
iVar19 = 4;
}
else
{
// STATIC_GEM
// if gems are needed to open the warppad
if (iVar17 == 0x5f)
{
// five gems are needed to open the warppad
iVar19 = 5;
}
// if trophies are needed to open the warppad
else
{
// get number of trophies needed to open the warppad
iVar19 = (int)*(short *)(&DAT_80083a90 + (int)*(short *)(piVar18 + 0x1b) * 0x18);
}
}
}
// if warppad is unlocked,
// requirement <= collected
if (iVar19 <= iVar14)
{
piVar18[2] = 0;
piVar18[3] = 0;
piVar18[1] = 0;
// no reqObj instance
*piVar18 = 0;
*(undefined2 *)((int)piVar18 + 0x6a) = 0;
// thread -> 0x44 (modelID) = 1??
*(undefined2 *)(iVar4 + 0x44) = 1;
// if model of static beam does not exist
if (*(int *)(puVar3 + 0x234c) == 0)
{
// dont make an instance of it
piVar18[4] = 0;
}
else
{
// 800aba10
// "beam"
// 0x234c = 0x7b (STATIC_BEAM) of 0x2160 array
// INSTANCE_Birth3D -- ptrModel, name, thread
iVar14 = FUN_8003086c(*(int *)(puVar3 + 0x234c),&DAT_800aba10,iVar4);
// save instance
piVar18[4] = iVar14;
// copy position and scale from one instance to another
uVar11 = *(undefined4 *)(param_1 + 0x34);
uVar12 = *(undefined4 *)(param_1 + 0x38);
uVar13 = *(undefined4 *)(param_1 + 0x3c);
*(undefined4 *)(iVar14 + 0x30) = *(undefined4 *)(param_1 + 0x30);
*(undefined4 *)(iVar14 + 0x34) = uVar11;
*(undefined4 *)(iVar14 + 0x38) = uVar12;
*(undefined4 *)(iVar14 + 0x3c) = uVar13;
uVar11 = *(undefined4 *)(param_1 + 0x44);
uVar12 = *(undefined4 *)(param_1 + 0x48);
uVar13 = *(undefined4 *)(param_1 + 0x4c);
*(undefined4 *)(iVar14 + 0x40) = *(undefined4 *)(param_1 + 0x40);
*(undefined4 *)(iVar14 + 0x44) = uVar11;
*(undefined4 *)(iVar14 + 0x48) = uVar12;
*(undefined4 *)(iVar14 + 0x4c) = uVar13;
*(undefined4 *)(piVar18[4] + 0x44) = *(undefined4 *)(param_1 + 0x44);
*(undefined4 *)(piVar18[4] + 0x48) = *(undefined4 *)(param_1 + 0x48);
*(undefined4 *)(piVar18[4] + 0x4c) = *(undefined4 *)(param_1 + 0x4c);
// set the alpha scale
*(undefined2 *)(piVar18[4] + 0x22) = 0xc00;
}
iVar14 = 0;
piVar5 = piVar18;
do
{
// if model is not loaded for warppad spiral dots
if (*(int *)(PTR_DAT_8008d2ac + 0x2350) == 0)
{
// dont make an instance of it
piVar5[5] = 0;
}
// if model is loaded for warppad spiral dots
else
{
// bottomRing
// INSTANCE_Birth3D -- ptrModel, name, thread
iVar17 = FUN_8003086c(*(int *)(PTR_DAT_8008d2ac + 0x2350),s_bottomRing_800aba18,
iVar4);
// save instance of bottomRing
piVar5[5] = iVar17;
// copy position and rotation from one instance to the other
uVar11 = *(undefined4 *)(param_1 + 0x34);
uVar12 = *(undefined4 *)(param_1 + 0x38);
uVar13 = *(undefined4 *)(param_1 + 0x3c);
*(undefined4 *)(iVar17 + 0x30) = *(undefined4 *)(param_1 + 0x30);
*(undefined4 *)(iVar17 + 0x34) = uVar11;
*(undefined4 *)(iVar17 + 0x38) = uVar12;
*(undefined4 *)(iVar17 + 0x3c) = uVar13;
uVar11 = *(undefined4 *)(param_1 + 0x44);
uVar12 = *(undefined4 *)(param_1 + 0x48);
uVar13 = *(undefined4 *)(param_1 + 0x4c);
*(undefined4 *)(iVar17 + 0x40) = *(undefined4 *)(param_1 + 0x40);
*(undefined4 *)(iVar17 + 0x44) = uVar11;
*(undefined4 *)(iVar17 + 0x48) = uVar12;
*(undefined4 *)(iVar17 + 0x4c) = uVar13;
// set position again, this time alter height
*(undefined4 *)(piVar5[5] + 0x44) = *(undefined4 *)(param_1 + 0x44);
*(int *)(piVar5[5] + 0x48) = *(int *)(param_1 + 0x48) + iVar14 * 0x400;
*(undefined4 *)(piVar5[5] + 0x4c) = *(undefined4 *)(param_1 + 0x4c);
// set the alpha scale
*(undefined2 *)(piVar5[5] + 0x22) = 0x400;
}
iVar14 = iVar14 + 1;
piVar5 = piVar5 + 1;
} while (iVar14 < 2);
// prizes
iVar14 = 0;
sVar10 = 0;
piVar5 = piVar18;
piVar9 = piVar18;
do {
// wipe pointer to prize instance
piVar5[7] = 0;
// offsets 0x6e, 0x70, 0x72,
// 0/3, 1/3, 2/3
*(short *)((int)piVar9 + 0x6e) = sVar10;
sVar10 = sVar10 + 0x555;
piVar9 = (int *)((int)piVar9 + 2);
iVar14 = iVar14 + 1;
piVar5 = piVar5 + 1;
} while (iVar14 < 3);
iVar14 = 0;
// erase spinRot_Prize
*(undefined2 *)(piVar18 + 10) = 0;
*(undefined2 *)((int)piVar18 + 0x2a) = 0;
*(undefined2 *)(piVar18 + 0xb) = 0;
// erase spinRot_Beam
// offset 0x40, 0x42, 0x44
*(undefined2 *)(piVar18 + 0x10) = 0;
*(undefined2 *)((int)piVar18 + 0x42) = 0;
*(undefined2 *)(piVar18 + 0x11) = 0;
// erase spinRot_Wisp1 and spinRot_Wisp2
// iVar14=0: write 0x30, 0x32, 0x34
// iVar14=1: write 0x38, 0x3A, 0x3C
piVar5 = piVar18;
do {
*(undefined2 *)(piVar5 + 0xc) = 0;
*(undefined2 *)((int)piVar5 + 0x32) = 0;
*(undefined2 *)(piVar5 + 0xd) = 0;
iVar14 = iVar14 + 1;
piVar5 = piVar5 + 2;
} while (iVar14 < 2);
// initialize prize instances
sVar10 = *(short *)(piVar18 + 0x1b);
iVar14 = (int)*(short *)(piVar18 + 0x1b);
if (iVar14 < 0x10)
{
// If trophy is not unlocked,
// loop through 3 rewards, then return
// 0x8fba4 is where the adventure profile (currently loaded) begins
if (((uint)(&DAT_8008fba4)[(int)(iVar14 + 6U) >> 5] >> (iVar14 + 6U & 0x1f) & 1) == 0) {
local_40 = DAT_800aba24;
local_3c = DAT_800aba28;
// 3 prize instances, then return
iVar14 = 0;
iVar17 = 0;
piVar5 = piVar18;
do {
puVar15 = (undefined4 *)((int)&local_40 + iVar14 * 2);
// INSTANCE_Birth3D -- ptrModel, name, thread
iVar19 = FUN_8003086c(*(undefined4 *)
(PTR_DAT_8008d2ac + (int)*(short *)puVar15 * 4 + 0x2160),
s_prize1_800aba2c,iVar4);
piVar5[7] = iVar19;
// copy position and rotation from one instance to the other
uVar11 = *(undefined4 *)(param_1 + 0x34);
uVar12 = *(undefined4 *)(param_1 + 0x38);
uVar13 = *(undefined4 *)(param_1 + 0x3c);
*(undefined4 *)(iVar19 + 0x30) = *(undefined4 *)(param_1 + 0x30);
*(undefined4 *)(iVar19 + 0x34) = uVar11;
*(undefined4 *)(iVar19 + 0x38) = uVar12;
*(undefined4 *)(iVar19 + 0x3c) = uVar13;
uVar11 = *(undefined4 *)(param_1 + 0x44);
uVar12 = *(undefined4 *)(param_1 + 0x48);
uVar13 = *(undefined4 *)(param_1 + 0x4c);
*(undefined4 *)(iVar19 + 0x40) = *(undefined4 *)(param_1 + 0x40);
*(undefined4 *)(iVar19 + 0x44) = uVar11;
*(undefined4 *)(iVar19 + 0x48) = uVar12;
*(undefined4 *)(iVar19 + 0x4c) = uVar13;
// Sine(angle)
iVar19 = FUN_8003d184(iVar17);
*(int *)(piVar5[7] + 0x44) = *(int *)(param_1 + 0x44) + (iVar19 * 0xc0 >> 0xc);
*(int *)(piVar5[7] + 0x48) = *(int *)(param_1 + 0x48) + 0x100;
// Cosine(angle)
iVar19 = FUN_8003d1c0(iVar17);
*(int *)(piVar5[7] + 0x4c) = *(int *)(param_1 + 0x4c) + (iVar19 * 0xc0 >> 0xc);
sVar10 = *(short *)puVar15;
// relic
if (sVar10 == 0x61)
{
// color
*(undefined4 *)(piVar5[7] + 0x24) = 0x20a5ff0;
// specular light
*(uint *)(piVar5[7] + 0x28) = *(uint *)(piVar5[7] + 0x28) | 0x20000;
// scale (x, y, z)
*(undefined2 *)(piVar5[7] + 0x1c) = 0x1800;
*(undefined2 *)(piVar5[7] + 0x1e) = 0x1800;
*(undefined2 *)(piVar5[7] + 0x20) = 0x1800;
}
else
{
// token
if (sVar10 == 0x7d)
{
iVar19 = (int)(short)(&DAT_80083a92)[(int)*(short *)(piVar18 + 0x1b) * 0xc];
// instance color
*(uint *)(piVar5[7] + 0x24) =
(int)(short)(&DAT_80084116)[iVar19 * 4] << 0x14 |
(int)(short)(&DAT_80084118)[iVar19 * 4] << 0xc |
(int)(short)(&DAT_8008411a)[iVar19 * 4] << 4;
// specular lighting
*(uint *)(piVar5[7] + 0x28) = *(uint *)(piVar5[7] + 0x28) | 0x30000;
iVar19 = iVar19 * 6;
*(undefined2 *)(piVar18 + 0x18) = *(undefined2 *)(&DAT_800b4e1c + iVar19);
*(undefined2 *)((int)piVar18 + 0x62) = *(undefined2 *)(&DAT_800b4e1e + iVar19)
;
*(undefined2 *)(piVar18 + 0x19) = *(undefined2 *)(&DAT_800b4e20 + iVar19);
iVar19 = piVar5[7];
uVar7 = 0x2000;
}
// trophy
else {
iVar19 = piVar5[7];
uVar7 = 0x2800;
}
*(undefined2 *)(iVar19 + 0x1c) = uVar7;
*(undefined2 *)(piVar5[7] + 0x1e) = uVar7;
*(undefined2 *)(piVar5[7] + 0x20) = uVar7;
}
iVar17 = iVar17 + 0x555;
iVar14 = iVar14 + 1;
piVar5 = piVar5 + 1;
} while (iVar14 < 3);
return;
}
// === if trophy is unlocked ===
*(undefined2 *)(iVar4 + 0x44) = 2;
puVar3 = PTR_DAT_8008d2ac;
// 0x8fba4 is where the adventure profile (currently loaded) begins,
// if no relic has been awarded on this track
if (((uint)(&DAT_8008fba4)[(int)((int)*(short *)(piVar18 + 0x1b) + 0x16U) >> 5] >>
((int)*(short *)(piVar18 + 0x1b) + 0x16U & 0x1f) & 1) == 0)
{
// Relic Prize
*(undefined2 *)(iVar4 + 0x44) = 3;
// INSTANCE_Birth3D -- ptrModel, name, thread
iVar14 = FUN_8003086c(*(undefined4 *)(puVar3 + 0x22e4),s_prize2_800aba34,iVar4);
piVar18[7] = iVar14;
// relic color
*(undefined4 *)(iVar14 + 0x24) = 0x20a5ff0;
// specular light
*(uint *)(piVar18[7] + 0x28) = *(uint *)(piVar18[7] + 0x28) | 0x20000;
*(undefined2 *)(piVar18 + 0x16) = DAT_800b4dfc;
*(undefined2 *)((int)piVar18 + 0x5a) = DAT_800b4dfe;
iVar14 = piVar18[7];
*(undefined2 *)(piVar18 + 0x17) = DAT_800b4e00;
// copy position and rotation from one instance to the other
uVar12 = *(undefined4 *)(param_1 + 0x34);
uVar13 = *(undefined4 *)(param_1 + 0x38);
uVar11 = *(undefined4 *)(param_1 + 0x3c);
*(undefined4 *)(iVar14 + 0x30) = *(undefined4 *)(param_1 + 0x30);
*(undefined4 *)(iVar14 + 0x34) = uVar12;
*(undefined4 *)(iVar14 + 0x38) = uVar13;
*(undefined4 *)(iVar14 + 0x3c) = uVar11;
uVar12 = *(undefined4 *)(param_1 + 0x44);
uVar13 = *(undefined4 *)(param_1 + 0x48);
uVar11 = *(undefined4 *)(param_1 + 0x4c);
*(undefined4 *)(iVar14 + 0x40) = *(undefined4 *)(param_1 + 0x40);
*(undefined4 *)(iVar14 + 0x44) = uVar12;
*(undefined4 *)(iVar14 + 0x48) = uVar13;
*(undefined4 *)(iVar14 + 0x4c) = uVar11;
// change position again
*(undefined4 *)(piVar18[7] + 0x44) = *(undefined4 *)(param_1 + 0x44);
*(int *)(piVar18[7] + 0x48) = *(int *)(param_1 + 0x48) + 0x100;
*(undefined4 *)(piVar18[7] + 0x4c) = *(undefined4 *)(param_1 + 0x4c);
// set scale (x, y, z)
*(undefined2 *)(piVar18[7] + 0x1c) = 0x1800;
*(undefined2 *)(piVar18[7] + 0x1e) = 0x1800;
*(undefined2 *)(piVar18[7] + 0x20) = 0x1800;
}
puVar3 = PTR_DAT_8008d2ac;
// bit flag of CTR Token
uVar6 = (int)*(short *)(piVar18 + 0x1b) + 0x4c;
// 0x8fba4 is where the adventure profile (currently loaded) begins,
// if CTR Token has not been awarded for this track
if (((uint)(&DAT_8008fba4)[(int)uVar6 >> 5] >> (uVar6 & 0x1f) & 1) != 0) {
return;
}
// Token Prize
sVar10 = (&DAT_80083a92)[(int)*(short *)(piVar18 + 0x1b) * 0xc];
*(undefined2 *)(iVar4 + 0x44) = 3;
// INSTANCE_Birth3D -- ptrModel, name, thread
iVar14 = FUN_8003086c(*(undefined4 *)(puVar3 + 0x2354),s_prize2_800aba34,iVar4);
iVar17 = (int)sVar10;
piVar18[8] = iVar14;
// color of CTR Token
*(uint *)(iVar14 + 0x24) =
(int)(short)(&DAT_80084116)[iVar17 * 4] << 0x14 |
(int)(short)(&DAT_80084118)[iVar17 * 4] << 0xc |
(int)(short)(&DAT_8008411a)[iVar17 * 4] << 4;
// specular lighting
*(uint *)(piVar18[8] + 0x28) = *(uint *)(piVar18[8] + 0x28) | 0x30000;
iVar17 = iVar17 * 6;
*(undefined2 *)(piVar18 + 0x18) = *(undefined2 *)(&DAT_800b4e1c + iVar17);
*(undefined2 *)((int)piVar18 + 0x62) = *(undefined2 *)(&DAT_800b4e1e + iVar17);
iVar14 = piVar18[8];
*(undefined2 *)(piVar18 + 0x19) = *(undefined2 *)(&DAT_800b4e20 + iVar17);
// copy position and rotation from one instance to the other
uVar12 = *(undefined4 *)(param_1 + 0x34);
uVar13 = *(undefined4 *)(param_1 + 0x38);
uVar11 = *(undefined4 *)(param_1 + 0x3c);
*(undefined4 *)(iVar14 + 0x30) = *(undefined4 *)(param_1 + 0x30);
*(undefined4 *)(iVar14 + 0x34) = uVar12;
*(undefined4 *)(iVar14 + 0x38) = uVar13;
*(undefined4 *)(iVar14 + 0x3c) = uVar11;
uVar12 = *(undefined4 *)(param_1 + 0x44);
uVar13 = *(undefined4 *)(param_1 + 0x48);
uVar11 = *(undefined4 *)(param_1 + 0x4c);
*(undefined4 *)(iVar14 + 0x40) = *(undefined4 *)(param_1 + 0x40);
*(undefined4 *)(iVar14 + 0x44) = uVar12;
*(undefined4 *)(iVar14 + 0x48) = uVar13;
*(undefined4 *)(iVar14 + 0x4c) = uVar11;
// set position again
*(undefined4 *)(piVar18[8] + 0x44) = *(undefined4 *)(param_1 + 0x44);
*(int *)(piVar18[8] + 0x48) = *(int *)(param_1 + 0x48) + 0x100;
*(undefined4 *)(piVar18[8] + 0x4c) = *(undefined4 *)(param_1 + 0x4c);
// set scale (x, y, z)
*(undefined2 *)(piVar18[8] + 0x1c) = 0x2000;
*(undefined2 *)(piVar18[8] + 0x1e) = 0x2000;
*(undefined2 *)(piVar18[8] + 0x20) = 0x2000;
return;
}
if ((ushort)(sVar10 - 0x10U) < 2) {
*(undefined2 *)(iVar4 + 0x44) = 2;
puVar3 = PTR_DAT_8008d2ac;
// 0x8fba4 is where the adventure profile (currently loaded) begins
if (((uint)(&DAT_8008fba4)[(int)((int)*(short *)(piVar18 + 0x1b) + 0x16U) >> 5] >>
((int)*(short *)(piVar18 + 0x1b) + 0x16U & 0x1f) & 1) != 0) {
return;
}
*(undefined2 *)(iVar4 + 0x44) = 4;
// INSTANCE_Birth3D -- ptrModel, name, thread
iVar14 = FUN_8003086c(*(undefined4 *)(puVar3 + 0x22e4),s_prize2_800aba34,iVar4);
piVar18[7] = iVar14;
// color
*(undefined4 *)(iVar14 + 0x24) = 0x20a5ff0;
// specular lighting
*(uint *)(piVar18[7] + 0x28) = *(uint *)(piVar18[7] + 0x28) | 0x20000;
*(undefined2 *)(piVar18 + 0x16) = DAT_800b4dfc;
*(undefined2 *)((int)piVar18 + 0x5a) = DAT_800b4dfe;
iVar14 = piVar18[7];
*(undefined2 *)(piVar18 + 0x17) = DAT_800b4e00;
// copy position and rotation from one instance to the other
uVar12 = *(undefined4 *)(param_1 + 0x34);
uVar13 = *(undefined4 *)(param_1 + 0x38);
uVar11 = *(undefined4 *)(param_1 + 0x3c);
*(undefined4 *)(iVar14 + 0x30) = *(undefined4 *)(param_1 + 0x30);
*(undefined4 *)(iVar14 + 0x34) = uVar12;
*(undefined4 *)(iVar14 + 0x38) = uVar13;
*(undefined4 *)(iVar14 + 0x3c) = uVar11;
uVar12 = *(undefined4 *)(param_1 + 0x44);
uVar13 = *(undefined4 *)(param_1 + 0x48);
uVar11 = *(undefined4 *)(param_1 + 0x4c);
*(undefined4 *)(iVar14 + 0x40) = *(undefined4 *)(param_1 + 0x40);
*(undefined4 *)(iVar14 + 0x44) = uVar12;
*(undefined4 *)(iVar14 + 0x48) = uVar13;
*(undefined4 *)(iVar14 + 0x4c) = uVar11;
// set position again
*(undefined4 *)(piVar18[7] + 0x44) = *(undefined4 *)(param_1 + 0x44);
*(int *)(piVar18[7] + 0x48) = *(int *)(param_1 + 0x48) + 0x100;
*(undefined4 *)(piVar18[7] + 0x4c) = *(undefined4 *)(param_1 + 0x4c);
iVar14 = piVar18[7];
uVar7 = 0x1800;
}
else {
if ((((ushort)(sVar10 - 0x12U) < 2) || (iVar14 == 0x15)) || (iVar14 == 0x17)) {
local_38 = DAT_800aba3c;
local_34 = DAT_800aba40;
local_30 = DAT_800aba44;
local_2c = DAT_800aba48;
*(undefined2 *)(iVar4 + 0x44) = 2;
puVar3 = PTR_DAT_8008d2ac;
uVar6 = (int)*(short *)((int)&local_38 + ((int)*(short *)(piVar18 + 0x1b) + -0x12) * 2) +
0x6f;
// 0x8fba4 is where the adventure profile (currently loaded) begins
if (((uint)(&DAT_8008fba4)[(int)uVar6 >> 5] >> (uVar6 & 0x1f) & 1) != 0) {
return;
}
*(undefined2 *)(iVar4 + 0x44) = 4;
// INSTANCE_Birth3D -- ptrModel, name, thread
iVar14 = FUN_8003086c(*(undefined4 *)(puVar3 + 0x2354),s_prize2_800aba34,iVar4);
piVar18[7] = iVar14;
// color
*(uint *)(iVar14 + 0x24) =
(int)DAT_80084136 << 0x14 | (int)DAT_80084138 << 0xc | (int)DAT_8008413a << 4;
// specular lighting
*(uint *)(piVar18[7] + 0x28) = *(uint *)(piVar18[7] + 0x28) | 0x20000;
*(undefined2 *)(piVar18 + 0x18) = DAT_800b4e34;
*(undefined2 *)((int)piVar18 + 0x62) = DAT_800b4e36;
iVar14 = piVar18[7];
*(undefined2 *)(piVar18 + 0x19) = DAT_800b4e38;
}
else {
if (4 < (ushort)(sVar10 - 100U)) {
return;
}
*(undefined2 *)(iVar4 + 0x44) = 2;
puVar3 = PTR_DAT_8008d2ac;
uVar2 = *(ushort *)(piVar18 + 0x1b);
// 0x8fba4 is where the adventure profile (currently loaded) begins
if (((uint)(&DAT_8008fba4)[(int)((int)*(short *)(piVar18 + 0x1b) + 6U) >> 5] >>
((int)*(short *)(piVar18 + 0x1b) + 6U & 0x1f) & 1) != 0) {
return;
}
*(undefined2 *)(iVar4 + 0x44) = 4;
// INSTANCE_Birth3D -- ptrModel, name, thread
iVar14 = FUN_8003086c(*(undefined4 *)(puVar3 + 0x22dc),s_prize2_800aba34);
iVar17 = (int)(((uint)uVar2 - 100) * 0x10000) >> 0x10;
piVar18[7] = iVar14;
// color
*(uint *)(iVar14 + 0x24) =
(int)(short)(&DAT_80084116)[iVar17 * 4] << 0x14 |
(int)(short)(&DAT_80084118)[iVar17 * 4] << 0xc |
(int)(short)(&DAT_8008411a)[iVar17 * 4] << 4;
// specular light
*(uint *)(piVar18[7] + 0x28) = *(uint *)(piVar18[7] + 0x28) | 0x20000;
*(undefined2 *)(piVar18 + 0x14) = (&DAT_800b4ddc)[iVar17 * 3];
*(undefined2 *)((int)piVar18 + 0x52) = (&DAT_800b4dde)[iVar17 * 3];
iVar14 = piVar18[7];
*(undefined2 *)(piVar18 + 0x15) = (&DAT_800b4de0)[iVar17 * 3];
}
// copy position and rotation from one instance to the other
uVar12 = *(undefined4 *)(param_1 + 0x34);
uVar13 = *(undefined4 *)(param_1 + 0x38);
uVar11 = *(undefined4 *)(param_1 + 0x3c);
*(undefined4 *)(iVar14 + 0x30) = *(undefined4 *)(param_1 + 0x30);
*(undefined4 *)(iVar14 + 0x34) = uVar12;
*(undefined4 *)(iVar14 + 0x38) = uVar13;
*(undefined4 *)(iVar14 + 0x3c) = uVar11;
uVar12 = *(undefined4 *)(param_1 + 0x44);
uVar13 = *(undefined4 *)(param_1 + 0x48);
uVar11 = *(undefined4 *)(param_1 + 0x4c);
*(undefined4 *)(iVar14 + 0x40) = *(undefined4 *)(param_1 + 0x40);
*(undefined4 *)(iVar14 + 0x44) = uVar12;
*(undefined4 *)(iVar14 + 0x48) = uVar13;
*(undefined4 *)(iVar14 + 0x4c) = uVar11;
// set position again
*(undefined4 *)(piVar18[7] + 0x44) = *(undefined4 *)(param_1 + 0x44);
*(int *)(piVar18[7] + 0x48) = *(int *)(param_1 + 0x48) + 0x100;
*(undefined4 *)(piVar18[7] + 0x4c) = *(undefined4 *)(param_1 + 0x4c);
iVar14 = piVar18[7];
uVar7 = 0x2000;
}
// set scale (x, y, z)
*(undefined2 *)(iVar14 + 0x1c) = uVar7;
*(undefined2 *)(piVar18[7] + 0x1e) = uVar7;
*(undefined2 *)(piVar18[7] + 0x20) = uVar7;
return;
}
// =======================
// From this point on, it is assumed
// that the warppad is locked
// =======================
// unlock requirment < 10
if (iVar19 < 10)
{
// no 10s digit, just 1s digit
*(short *)((int)piVar18 + 0x68) = 0;
*(short *)((int)piVar18 + 0x6a) = (short)iVar19;
}
else
{
// 10s digit and 1s digit
*(short *)((int)piVar18 + 0x68) = 1;
*(short *)((int)piVar18 + 0x6a) = (short)iVar19 + -10;
}
// initialize "required object" that floats
// above the warppad, showing what is needed
// INSTANCE_Birth3D -- ptrModel, name, thread
iVar14 = FUN_8003086c(*(undefined4 *)(PTR_DAT_8008d2ac + iVar17 * 4 + 0x2160),
s_reqObj_800ab9fc,iVar4);
// save reqObj instance in warppad
*piVar18 = iVar14;
// copy rotation from warppad to reqObj
uVar11 = *(undefined4 *)(param_1 + 0x34);
uVar12 = *(undefined4 *)(param_1 + 0x38);
uVar13 = *(undefined4 *)(param_1 + 0x3c);
*(undefined4 *)(iVar14 + 0x30) = *(undefined4 *)(param_1 + 0x30);
*(undefined4 *)(iVar14 + 0x34) = uVar11;
*(undefined4 *)(iVar14 + 0x38) = uVar12;
*(undefined4 *)(iVar14 + 0x3c) = uVar13;
// get position from some other instance
uVar11 = *(undefined4 *)(param_1 + 0x44);
uVar12 = *(undefined4 *)(param_1 + 0x48);
uVar13 = *(undefined4 *)(param_1 + 0x4c);
*(undefined4 *)(iVar14 + 0x40) = *(undefined4 *)(param_1 + 0x40);
// set position of this instance
*(undefined4 *)(iVar14 + 0x44) = uVar11;
*(undefined4 *)(iVar14 + 0x48) = uVar12;
*(undefined4 *)(iVar14 + 0x4c) = uVar13;
// increase posY, to make reqObj float in air
*(int *)(*piVar18 + 0x48) = *(int *)(*piVar18 + 0x48) + 0x100;
// set scale (x, y, z)
*(undefined2 *)(*piVar18 + 0x1c) = 0x2000;
*(undefined2 *)(*piVar18 + 0x1e) = 0x2000;
*(undefined2 *)(*piVar18 + 0x20) = 0x2000;
// if reqObj is not trophy
if (iVar17 != 0x62) {
// Relic
if (iVar17 == 0x61)
{
// Relic blue color
*(undefined4 *)(*piVar18 + 0x24) = 0x20a5ff0;
iVar14 = *piVar18;
// warppadObj->specLightRelic
*(undefined2 *)(piVar18 + 0x16) = DAT_800b4dfc;
*(undefined2 *)((int)piVar18 + 0x5a) = DAT_800b4dfe;
*(undefined2 *)(piVar18 + 0x17) = DAT_800b4e00;
}
else
{
// Key
if (iVar17 == 99)
{
// Set Key Color
*(undefined4 *)(*piVar18 + 0x24) = 0xdca6000;
iVar14 = *piVar18;
// warppadObj->specLightGem
*(undefined2 *)(piVar18 + 0x14) = DAT_800b4ddc;
*(undefined2 *)((int)piVar18 + 0x52) = DAT_800b4dde;
*(undefined2 *)(piVar18 + 0x15) = DAT_800b4de0;
}
else
{
// Gem
if (iVar17 == 0x5f)
{
// Set Gem Color
*(uint *)(*piVar18 + 0x24) =
(int)DAT_80084116 << 0x14 | (int)DAT_80084118 << 0xc | (int)DAT_8008411a << 4;
iVar14 = *piVar18;
// warppadObj->specLightGem
*(undefined2 *)(piVar18 + 0x14) = DAT_800b4ddc;
*(undefined2 *)((int)piVar18 + 0x52) = DAT_800b4dde;
*(undefined2 *)(piVar18 + 0x15) = DAT_800b4de0;
}
else
{
// If this is not token
if (iVar17 != 0x7d) goto LAB_800ad920;
// If this is token...
iVar17 = (int)(((uint)*(ushort *)(piVar18 + 0x1b) - 100) * 0x10000) >> 0x10;
// Set Token Color
*(uint *)(*piVar18 + 0x24) =
(int)(short)(&DAT_80084116)[iVar17 * 4] << 0x14 |
(int)(short)(&DAT_80084118)[iVar17 * 4] << 0xc |
(int)(short)(&DAT_8008411a)[iVar17 * 4] << 4;
iVar17 = iVar17 * 6;
iVar14 = *piVar18;
// warppadObj->specLightToken
*(undefined2 *)(piVar18 + 0x18) = *(undefined2 *)(&DAT_800b4e1c + iVar17);
*(undefined2 *)((int)piVar18 + 0x62) = *(undefined2 *)(&DAT_800b4e1e + iVar17);
*(undefined2 *)(piVar18 + 0x19) = *(undefined2 *)(&DAT_800b4e20 + iVar17);
}
}
}
// specular lighting
*(uint *)(iVar14 + 0x28) = *(uint *)(iVar14 + 0x28) | 0x20000;
}
LAB_800ad920:
// DAT_800aba04
// "x"
// INSTANCE_Birth3D -- ptrModel, name, thread
iVar14 = FUN_8003086c(*(undefined4 *)(PTR_DAT_8008d2ac + 0x231c),&DAT_800aba04,iVar4);
piVar18[1] = iVar14;
// copy position from another instance
*(undefined4 *)(iVar14 + 0x44) = *(undefined4 *)(param_1 + 0x44);
*(undefined4 *)(piVar18[1] + 0x48) = *(undefined4 *)(param_1 + 0x48);
*(undefined4 *)(piVar18[1] + 0x4c) = *(undefined4 *)(param_1 + 0x4c);
// set rotation to identity matrix
*(undefined4 *)(piVar18[1] + 0x30) = 0x1000;
*(undefined4 *)(piVar18[1] + 0x34) = 0;
*(undefined4 *)(piVar18[1] + 0x38) = 0x1000;
*(undefined4 *)(piVar18[1] + 0x3c) = 0;
*(undefined2 *)(piVar18[1] + 0x40) = 0x1000;
// set height
*(int *)(piVar18[1] + 0x48) = *(int *)(piVar18[1] + 0x48) + 0x100;
// set scale (x, y, z)
*(undefined2 *)(piVar18[1] + 0x1c) = 0x2000;
*(undefined2 *)(piVar18[1] + 0x1e) = 0x2000;
*(undefined2 *)(piVar18[1] + 0x20) = 0x2000;
iVar14 = *(int *)(*(int *)(piVar18[1] + 0x18) + 0x14);
// instance flag to always face camera
*(ushort *)(iVar14 + 0x16) = *(ushort *)(iVar14 + 0x16) | 1;
// ======= Number Instance 10s =======
if (*(short *)(piVar18 + 0x1a) == 0) {
piVar18[3] = 0;
}
else
{
// model 0x38: STATIC_BIG1 (1-8)
// INSTANCE_Birth3D -- ptrModel, name, thread
iVar14 = FUN_8003086c(*(undefined4 *)(PTR_DAT_8008d2ac + 0x2240),s_warpnum_800aba08,
iVar4);
// copy the instance
piVar18[3] = iVar14;
// copy position from another instance
*(undefined4 *)(iVar14 + 0x44) = *(undefined4 *)(param_1 + 0x44);
*(undefined4 *)(piVar18[3] + 0x48) = *(undefined4 *)(param_1 + 0x48);
*(undefined4 *)(piVar18[3] + 0x4c) = *(undefined4 *)(param_1 + 0x4c);
// set rotation to identity matrix
*(undefined4 *)(piVar18[3] + 0x30) = 0x1000;
*(undefined4 *)(piVar18[3] + 0x34) = 0;
*(undefined4 *)(piVar18[3] + 0x38) = 0x1000;
*(undefined4 *)(piVar18[3] + 0x3c) = 0;
*(undefined2 *)(piVar18[3] + 0x40) = 0x1000;
// set height
*(int *)(piVar18[3] + 0x48) = *(int *)(piVar18[3] + 0x48) + 0x100;
// set scale
*(undefined2 *)(piVar18[3] + 0x1c) = 0x2000;
*(undefined2 *)(piVar18[3] + 0x1e) = 0x2000;
*(undefined2 *)(piVar18[3] + 0x20) = 0x2000;
// instance of warppad num
iVar14 = piVar18[3];
iVar17 = 0;
// instance -> model -> numHeaders
if (0 < *(short *)(*(int *)(iVar14 + 0x18) + 0x12))
{
// loop through all headers
do
{
// modelHeader
iVar14 = iVar17 * 0x40 + *(int *)(*(int *)(iVar14 + 0x18) + 0x14);
// set flag to always face camera
*(ushort *)(iVar14 + 0x16) = *(ushort *)(iVar14 + 0x16) | 1;
iVar14 = piVar18[3];
// increment counter
iVar17 = iVar17 + 1;
} while (iVar17 < *(short *)(*(int *)(iVar14 + 0x18) + 0x12));
}
}
// ======= Number Instance 1s =======
// STATIC_BIG1 (1-8)
iVar14 = 0x38;
if (*(short *)((int)piVar18 + 0x6a) == 0)
{
// '0' number
iVar14 = 0x6d;
}
else
{
if (*(short *)((int)piVar18 + 0x6a) == 9)
{
// '9' number
iVar14 = 0x6e;
}
}
// INSTANCE_Birth3D -- ptrModel, name, thread
iVar14 = FUN_8003086c(*(undefined4 *)(PTR_DAT_8008d2ac + iVar14 * 4 + 0x2160),
s_warpnum_800aba08,iVar4);
// copy pointer to instance
piVar18[2] = iVar14;
// set position
*(undefined4 *)(iVar14 + 0x44) = *(undefined4 *)(param_1 + 0x44);
*(undefined4 *)(piVar18[2] + 0x48) = *(undefined4 *)(param_1 + 0x48);
*(undefined4 *)(piVar18[2] + 0x4c) = *(undefined4 *)(param_1 + 0x4c);
// set rotation to identity matrix
*(undefined4 *)(piVar18[2] + 0x30) = 0x1000;
*(undefined4 *)(piVar18[2] + 0x34) = 0;
*(undefined4 *)(piVar18[2] + 0x38) = 0x1000;
*(undefined4 *)(piVar18[2] + 0x3c) = 0;
*(undefined2 *)(piVar18[2] + 0x40) = 0x1000;
// set height
*(int *)(piVar18[2] + 0x48) = *(int *)(piVar18[2] + 0x48) + 0x100;
// set scale
*(undefined2 *)(piVar18[2] + 0x1c) = 0x2000;
*(undefined2 *)(piVar18[2] + 0x1e) = 0x2000;
*(undefined2 *)(piVar18[2] + 0x20) = 0x2000;
// instance
iVar14 = piVar18[2];
// loop counter
iVar17 = 0;
// instance -> model -> numHeaders
if (0 < *(short *)(*(int *)(iVar14 + 0x18) + 0x12))
{
// loop through all headers
do
{
// modelHeader
iVar14 = iVar17 * 0x40 + *(int *)(*(int *)(iVar14 + 0x18) + 0x14);
// flags
*(ushort *)(iVar14 + 0x16) = *(ushort *)(iVar14 + 0x16) | 1;
iVar14 = piVar18[2];
// index
iVar17 = iVar17 + 1;
} while (iVar17 < *(short *)(*(int *)(iVar14 + 0x18) + 0x12));
}
// beam
piVar18[4] = 0;
// 2 rings
iVar14 = 1;
piVar5 = piVar18 + 1;
do {
piVar5[5] = 0;
iVar14 = iVar14 + -1;
piVar5 = piVar5 + -1;
} while (-1 < iVar14);
// 3 prizes
iVar14 = 2;
piVar18 = piVar18 + 2;
do {
piVar18[7] = 0;
iVar14 = iVar14 + -1;
piVar18 = piVar18 + -1;
} while (-1 < iVar14);
return;
}
// AH_Garage_ThDestroy
void FUN_800ae8a0(int param_1)
{
int iVar1;
// thread -> object
iVar1 = *(int *)(param_1 + 0x30);
// if garage -> garagetop exists
if (*(int *)(iVar1 + 8) != 0)
{
// INSTANCE_Death
FUN_80030aa8();
// erase pointer
*(undefined4 *)(iVar1 + 8) = 0;
}
return;
}
// AH_Garage_Open
void FUN_800ae8e0(int param_1,int param_2)
{
undefined4 uVar1;
int iVar2;
int *piVar3;
// thread -> modelIndex == "player" of any kind
if (*(short *)(param_2 + 0x44) == 0x18)
{
// collisionDataScratchpad -> thread -> object
piVar3 = *(int **)(*(int *)(param_1 + 0x18) + 0x30);
// collisionDataScratchpad -> thread -> instance
iVar2 = *(int *)(*(int *)(param_1 + 0x18) + 0x34);
if (
// if door is not opening
(*piVar3 != 1) &&
// if door is closed,
// if posY is the same as instDef posY
(*(int *)(iVar2 + 0x48) == (int)*(short *)(*(int *)(iVar2 + 0x2c) + 0x32))
)
{
// if you are not in gemstone valley
// play sound of normal boss door opening
uVar1 = 0x95;
// Level ID
// if you are in Gemstone Valley
if (*(int *)(PTR_DAT_8008d2ac + 0x1a10) == 0x19)
{
// play sound of oxide door opening
uVar1 = 0x96;
}
// Play sound
FUN_80028468(uVar1,1);
}
// door is now opening
*piVar3 = 1;
// enable access through a door (disable collision)
DAT_8008d728 = DAT_8008d728 | 1;
}
return;
}
// WARNING: Globals starting with '_' overlap smaller symbols at the same address
// AH_Garage_ThTick
void FUN_800ae988(int param_1)
{
bool bVar1;
undefined *puVar2;
uint uVar3;
int iVar4;
uint uVar5;
int iVar6;
int iVar7;
undefined4 uVar8;
int *piVar9;
int iVar10;
int iVar11;
undefined4 local_60;
undefined4 local_5c;
undefined2 local_58;
undefined4 local_50;
undefined4 local_4c;
undefined2 local_48;
undefined4 local_40;
undefined4 local_3c;
undefined2 local_38;
int local_30;
int local_2c;
int local_28;
puVar2 = PTR_DAT_8008d2ac;
bVar1 = true;
// array track to load boss
local_60 = DAT_800aba4c;
local_5c = DAT_800aba50;
local_58 = DAT_800aba54;
// bossID
local_50 = DAT_800aba58;
local_4c = DAT_800aba5c;
local_48 = DAT_800aba60;
// get object from thread
piVar9 = *(int **)(param_1 + 0x30);
// get instance from thread
iVar10 = *(int *)(param_1 + 0x34);
// player -> instance
iVar11 = *(int *)(*(int *)(PTR_DAT_8008d2ac + 0x24ec) + 0x1c);
// if door is not opening or closing
if (*piVar9 == 0)
{
// if door is fully closed
if (piVar9[1] == 0) {
uVar5 = 0xffcfdfff;
uVar3 = *(uint *)(iVar10 + 0x28) | 0x1000;
}
// if door is not fully closed
else
{
// subtract frame timer
iVar4 = piVar9[1] - *(int *)(PTR_DAT_8008d2ac + 0x1d04);
piVar9[1] = iVar4;
// if countdown is not done, dont close door
if (0 < iVar4) goto LAB_800aeb6c;
// if you are not in gemstone valley
// play sound of normal boss door opening
uVar8 = 0x95;
// Level ID
// if you are in Gemstone Valley
if (*(int *)(puVar2 + 0x1a10) == 0x19)
{
// play sound of oxide door opening
uVar8 = 0x96;
}
// Play sound
FUN_80028468(uVar8,1);
// erase cooldown
piVar9[1] = 0;
// door is closing
*piVar9 = -1;
uVar3 = *(uint *)(iVar10 + 0x28);
uVar5 = 0xffffff7f;
}
*(uint *)(iVar10 + 0x28) = uVar3 & uVar5;
}
// if door is opening or closing
// *piVar9 is 1 for opening, or -1 for closing
else
{
// increment animation by 0x20 in either direction
iVar4 = *(int *)(iVar10 + 0x48) + *piVar9 * 0x20;
*(int *)(iVar10 + 0x48) = iVar4;
// instance -> instDef -> posY
iVar6 = (int)*(short *)(*(int *)(iVar10 + 0x2c) + 0x32);
// if door gone past the top (height=0x300)
if (iVar6 + 0x300 < iVar4)
{
// dont go higher than top
*(int *)(iVar10 + 0x48) = iVar6 + 0x300;
// door is now open (not moving)
*piVar9 = 0;
// cooldown, 2 seconds
piVar9[1] = 0x780;
// make invisible
*(uint *)(iVar10 + 0x28) = *(uint *)(iVar10 + 0x28) | 0x80;
}
// if not past top
else
{
// if door has gone past bottom
if (iVar4 < iVar6)
{
// dont go lower than bottom
*(int *)(iVar10 + 0x48) = iVar6;
// door is now closed (not moving)
*piVar9 = 0;
// erase cooldown
piVar9[1] = 0;
// remove access (enable collision)
DAT_8008d728 = DAT_8008d728 & 0xfffffffe;
}
// if not past bottom, and not past top
else
{
// if garagetop instance exists
if (piVar9[2] != 0)
{
// rotation of garagetop
*(short *)(piVar9 + 3) = *(short *)(piVar9 + 3) + (short)*piVar9 * 0x40;
// convert 3 rotation shorts into rotation matrix
FUN_8006c2a4(piVar9[2] + 0x30,piVar9 + 3);
}
}
}
*(uint *)(iVar10 + 0x28) = *(uint *)(iVar10 + 0x28) & 0xffffefff | 0x302000;
}
LAB_800aeb6c:
iVar4 = 0;
// Level ID
// If you're in Gemstone Valley
if (*(int *)(PTR_DAT_8008d2ac + 0x1a10) == 0x19)
{
uVar3 = 0x5e;
do
{
// 0x8fba4 is where the adventure profile (currently loaded) begins
if (((uint)(&DAT_8008fba4)[(int)uVar3 >> 5] >> (uVar3 & 0x1f) & 1) == 0)
{
goto LAB_800aebd0;
}
iVar6 = iVar4 + 1;
uVar3 = iVar4 + 0x5f;
iVar4 = iVar6;
} while (iVar6 < 4);
}
// If you're not in Gemstone Valley
else
{
// Get Level ID - 0x1a: warp room (1-4)
iVar6 = (*(int *)(PTR_DAT_8008d2ac + 0x1a10) + -0x1a) * 8;
do {
if (((uint)(&DAT_8008fba4)[(int)((int)*(short *)(&DAT_800840f4 + iVar6) + 6U) >> 5] >>
((int)*(short *)(&DAT_800840f4 + iVar6) + 6U & 0x1f) & 1) == 0)
goto LAB_800aebd0;
iVar4 = iVar4 + 1;
iVar6 = iVar6 + 2;
} while (iVar4 < 4);
}
goto LAB_800aec34;
LAB_800aebd0:
bVar1 = false;
LAB_800aec34:
iVar7 = *(int *)(iVar10 + 0x2c);
iVar4 = *(int *)(iVar11 + 0x44) - (int)*(short *)(iVar7 + 0x30);
iVar6 = *(int *)(iVar11 + 0x48) - (int)*(short *)(iVar7 + 0x32);
iVar7 = *(int *)(iVar11 + 0x4c) - (int)*(short *)(iVar7 + 0x34);
// if in a state where you're seeing the boss key open an adv door,
// or some other kind of cutscene where you can't move
if ((*(uint *)(PTR_DAT_8008d2ac + 8) & 4) != 0) {
return;
}
// check distance
if (0x143fff < iVar4 * iVar4 + iVar6 * iVar6 + iVar7 * iVar7) goto LAB_800aede0;
// string for LNG
local_40 = DAT_800aba58;
local_3c = DAT_800aba5c;
local_38 = DAT_800aba60;
// if aku is not giving a hint
if (DAT_8008d874 == 0)
{
// draw string, lng_challenge
FUN_80022878(*(undefined4 *)
((int)*(short *)(&DAT_8008413c +
(int)*(short *)((int)&local_40 +
// Level ID - 0x19: Adventure Hub 0 - 4
(*(int *)(PTR_DAT_8008d2ac + 0x1a10) + -0x19) * 2)
* 2) * 4 + DAT_8008d878),
(int)(((uint)*(ushort *)(puVar2 + 0x184) +
((int)((uint)*(ushort *)(puVar2 + 0x188) << 0x10) >> 0x11)) * 0x10000) >>
0x10,(int)(((uint)*(ushort *)(puVar2 + 0x186) + (uint)*(ushort *)(puVar2 + 0x18a) +
-0x1e) * 0x10000) >> 0x10,1,0xffff8000);
}
if (bVar1) goto LAB_800aede8;
// if this is gemstone valley
if (*(int *)(PTR_DAT_8008d2ac + 0x1a10) == 0x19)
{
// if hint is not unlocked "need 4 keys for oxide"
if ((DAT_8008fbb0 & 0x4000000) == 0)
{
// need four keys to race oxide
uVar8 = 4;
LAB_800aedd4:
// request mask hint
FUN_80035e20(uVar8,0);
}
}
// not gemstone valley
else
{
// if hint is not unlocked "to access this boss garage..."
if ((DAT_8008fbb0 & 0x2000000) == 0)
{
// Need four trophies to enter boss
uVar8 = 3;
goto LAB_800aedd4;
}
}
LAB_800aede0:
if (!bVar1) {
return;
}
LAB_800aede8:
DAT_1f800108 = *(undefined2 *)(*(int *)(iVar10 + 0x2c) + 0x30);
DAT_1f80010a = *(undefined2 *)(*(int *)(iVar10 + 0x2c) + 0x32);
DAT_1f80010c = *(undefined2 *)(*(int *)(iVar10 + 0x2c) + 0x34);
DAT_1f80010e = 0x300;
_DAT_1f800110 = 0x90000;
// AH_Garage_Open
DAT_1f800130 = FUN_800ae8e0;
DAT_1f800114 = 0x73;
DAT_1f800120 = param_1;
// Open garage door when player gets within radius of door
FUN_800425d4(*(undefined4 *)(PTR_DAT_8008d2ac + 0x1b2c),&DAT_1f800108,0);
// Sine(angle)
iVar4 = FUN_8003d184((int)*(short *)(*(int *)(iVar10 + 0x2c) + 0x38));
local_30 = (int)*(short *)(*(int *)(iVar10 + 0x2c) + 0x30) + (iVar4 * -0x280 >> 0xc);
local_2c = (int)*(short *)(*(int *)(iVar10 + 0x2c) + 0x32);
// Cosine(angle)
iVar4 = FUN_8003d1c0((int)*(short *)(*(int *)(iVar10 + 0x2c) + 0x38));
puVar2 = PTR_DAT_8008d2ac;
local_28 = (int)*(short *)(*(int *)(iVar10 + 0x2c) + 0x34) + (iVar4 * -0x280 >> 0xc);
iVar10 = *(int *)(iVar11 + 0x44) - local_30;
iVar4 = *(int *)(iVar11 + 0x48) - local_2c;
iVar11 = *(int *)(iVar11 + 0x4c) - local_28;
if (iVar10 * iVar10 + iVar4 * iVar4 + iVar11 * iVar11 < 0x40000) {
*(undefined2 *)(PTR_DAT_8008d2ac + 0x139c) = 0;
*(undefined2 *)(puVar2 + 0x139e) = 0xfd56;
}
if (*(short *)(PTR_DAT_8008d2ac + 0x139a) == 0)
{
// when loading is done, remove flag for In Adventure Arena
DAT_8008d104 = DAT_8008d104 | 0x100000;
// when loading is done, add flag for Boss Mode
DAT_8008d100 = DAT_8008d100 | 0x80000000;
if (
// Level ID
// If you're in Gemstone Valley
(*(int *)(PTR_DAT_8008d2ac + 0x1a10) == 0x19) &&
// If you have all 18 relics
(*(int *)(PTR_DAT_8008d2ac + 0x1e34) == 0x12)
)
{
// set string index (0-5) to "N Oxide's Final Challenge"
*(undefined4 *)(PTR_DAT_8008d2ac + 0x1eb8) = 5;
}
else
{
// set boss ID
*(int *)(PTR_DAT_8008d2ac + 0x1eb8) =
// Level ID - 0x19: Adventure Hub (0-4)
(int)*(short *)((int)&local_50 + (*(int *)(PTR_DAT_8008d2ac + 0x1a10) + -0x19) * 2);
}
// Set the boss character
DAT_80086e86 = *(undefined2 *)
(&DAT_80083a94 +
(int)*(short *)((int)&local_60 +
// Level ID - 0x19: Adventure Hub (0-4)
(*(int *)(PTR_DAT_8008d2ac + 0x1a10) + -0x19) * 2) * 0x18);
// TitleFlag_SetDrawOrder
FUN_80043f8c(1);
// Level ID - 0x19: Adventure Hub (0-4)
FUN_8003cfc0((int)*(short *)((int)&local_60 + (*(int *)(PTR_DAT_8008d2ac + 0x1a10) + -0x19) * 2)
);
}
return;
}
// AH_Garage_LInB
void FUN_800af070(int param_1)
{
short sVar1;
bool bVar2;
int iVar3;
int iVar4;
uint uVar5;
int iVar6;
undefined4 uVar7;
undefined4 uVar8;
undefined4 uVar9;
undefined4 *puVar10;
bVar2 = true;
// if this Instance's thread exists
if (*(int *)(param_1 + 0x6c) != 0)
{
// quit
return;
}
// THREAD_BirthWithObject
// 0x14 = size
// 0 = no relation to param4
// 0x300 = SmallStackPool
// 0x3 = static thread bucket
iVar3 = FUN_8004205c(0x140303,FUN_800ae988,s_garage_800aba64,0);
// give thread to Instance
*(int *)(param_1 + 0x6c) = iVar3;
// if the thread failed to build
if (iVar3 == 0)
{
// quit
return;
}
// get the Garage object attached to the thread
puVar10 = *(undefined4 **)(iVar3 + 0x30);
// give Instance to thread
*(int *)(iVar3 + 0x34) = param_1;
// set OnDestroy, AH_Garage_ThDestroy
*(undefined4 *)(iVar3 + 0x24) = 0x800ae8a0;
*puVar10 = 0;
puVar10[1] = 0;
// if instance -> model -> modelID is Oxide's Door
if (*(short *)(*(int *)(param_1 + 0x18) + 0x10) == 0x77)
{
// Garage -> garagetop = nullptr
puVar10[2] = 0;
}
// if this is not oxide's door
else
{
// make a "garagetop" to make door appear to roll up
// INSTANCE_Birth3D -- ptrModel, name, thread
iVar4 = FUN_8003086c(*(undefined4 *)(PTR_DAT_8008d2ac + 0x2398),s_garagetop_800aba6c,
iVar3);
// copy pointer of instance, to "Garage" object
puVar10[2] = iVar4;
// copy rotation from one instance to the other
uVar7 = *(undefined4 *)(param_1 + 0x34);
uVar8 = *(undefined4 *)(param_1 + 0x38);
uVar9 = *(undefined4 *)(param_1 + 0x3c);
*(undefined4 *)(iVar4 + 0x30) = *(undefined4 *)(param_1 + 0x30);
*(undefined4 *)(iVar4 + 0x34) = uVar7;
*(undefined4 *)(iVar4 + 0x38) = uVar8;
*(undefined4 *)(iVar4 + 0x3c) = uVar9;
// get position from Garage instance
uVar7 = *(undefined4 *)(param_1 + 0x44);
uVar8 = *(undefined4 *)(param_1 + 0x48);
uVar9 = *(undefined4 *)(param_1 + 0x4c);
*(undefined4 *)(iVar4 + 0x40) = *(undefined4 *)(param_1 + 0x40);
// set position of GarageTop instance
*(undefined4 *)(iVar4 + 0x44) = uVar7;
*(undefined4 *)(iVar4 + 0x48) = uVar8;
*(undefined4 *)(iVar4 + 0x4c) = uVar9;
// Sine(angle)
iVar4 = FUN_8003d184((int)*(short *)(*(int *)(param_1 + 0x2c) + 0x38));
// continue setting GarageTop position
*(int *)(puVar10[2] + 0x44) = *(int *)(param_1 + 0x44) + (iVar4 * 0x4c >> 0xc);
*(int *)(puVar10[2] + 0x48) = *(int *)(param_1 + 0x48) + 0x300;
// Cosine(angle)
iVar4 = FUN_8003d1c0((int)*(short *)(*(int *)(param_1 + 0x2c) + 0x38));
// continue setting GarageTop position
*(int *)(puVar10[2] + 0x4c) = *(int *)(param_1 + 0x4c) + (iVar4 * 0x4c >> 0xc);
*(undefined *)(puVar10[2] + 0x50) = 0xfe;
}
iVar4 = 0;
// Level ID
// If you're in Gemstone Valley
if (*(int *)(PTR_DAT_8008d2ac + 0x1a10) == 0x19) {
// ripper roo boss key
uVar5 = 0x5e;
// check four boss keys
do
{
iVar6 = iVar4 + 1;
// 0x8fba4 is where the adventure profile (currently loaded) begins,
// if this boss key is not unlocked
if (((uint)(&DAT_8008fba4)[(int)uVar5 >> 5] >> (uVar5 & 0x1f) & 1) == 0)
{
// boss is not open
goto LAB_800af254;
}
// next bit = loop index + 0x5f
uVar5 = iVar4 + 0x5f;
iVar4 = iVar6;
} while (iVar6 < 4);
bVar2 = true;
}
// if not gemstone valley
else {
iVar6 = (*(int *)(PTR_DAT_8008d2ac + 0x1a10) + -0x1a) * 8;
// check all four tracks on hub
do {
iVar4 = iVar4 + 1;
// 0x8fba4 is where the adventure profile (currently loaded) begins,
// if any trophy on this hub is not unlocked
if (((uint)(&DAT_8008fba4)[(int)((int)*(short *)(&DAT_800840f4 + iVar6) + 6U) >> 5] >>
((int)*(short *)(&DAT_800840f4 + iVar6) + 6U & 0x1f) & 1) == 0)
{
// boss is not open
goto LAB_800af254;
}
iVar6 = iVar6 + 2;
} while (iVar4 < 4);
}
LAB_800af2b8:
// if boss is open
if (bVar2)
{
// 0x8fba4 is where the adventure profile (currently loaded) begins
// check if boss was NOT beaten on this hub
if (((uint)(&DAT_8008fba4)
// BeatBossPrize, bit index in profile,
// convert bit index to byte index
[(int)((uint)(ushort)&DAT_80084098
[*(int *)(PTR_DAT_8008d2ac + 0x1a10) + -0x19] << 0x10) >> 0x15] >>
// from the byte, find the bit within the byte
(&DAT__80084098[*(int *)(PTR_DAT_8008d2ac + 0x1a10) + -0x19] & 0x1fU) & 1) == 0)
{
// if boss was not beaten
// thread -> 0x44
*(undefined2 *)(iVar3 + 0x44) = 1;
}
else
{
// if boss was beaten
// thread -> 0x44
*(undefined2 *)(iVar3 + 0x44) = 2;
}
}
// if boss is not open
else
{
// thread -> 0x44
*(undefined2 *)(iVar3 + 0x44) = 0;
}
// instance -> instDef -> rotation
*(undefined2 *)(puVar10 + 3) = *(undefined2 *)(*(int *)(param_1 + 0x2c) + 0x36);
*(undefined2 *)((int)puVar10 + 0xe) = *(undefined2 *)(*(int *)(param_1 + 0x2c) + 0x38);
*(undefined2 *)(puVar10 + 4) = *(undefined2 *)(*(int *)(param_1 + 0x2c) + 0x3a);
*(undefined *)(param_1 + 0x50) = 1;
// instance -> instDef -> posY
sVar1 = *(short *)(*(int *)(param_1 + 0x2c) + 0x32);
*(undefined *)(param_1 + 0x53) = 0;
*(undefined *)(param_1 + 0x51) = *(undefined *)(param_1 + 0x50);
// split line = posY + 0x300
*(short *)(param_1 + 0x56) = sVar1 + 0x300;
return;
// boss is not open
LAB_800af254:
bVar2 = false;
// go to end of search
goto LAB_800af2b8;
}
// AH_SaveObj_ThDestroy
void FUN_800af3a4(int param_1)
{
int *piVar1;
// thread -> object
piVar1 = *(int **)(param_1 + 0x30);
if (*piVar1 != 0)
{
// INSTANCE_Death
FUN_80030aa8();
*piVar1 = 0;
}
return;
}
// AH_SaveObj_ThTick
void FUN_800af3e4(int param_1)
{
short sVar1;
ushort uVar2;
int iVar3;
int iVar4;
int iVar5;
uint uVar6;
undefined *puVar7;
int iVar8;
int iVar9;
int *piVar10;
int iVar11;
short local_28;
short local_26;
short local_24;
short local_20;
short local_1e;
short local_1c;
puVar7 = PTR_DAT_8008d2ac;
// Get P1 driver object
iVar11 = *(int *)(PTR_DAT_8008d2ac + 0x24ec);
// get instance from thread
iVar9 = *(int *)(param_1 + 0x34);
// P1 instance from driver object
iVar8 = *(int *)(iVar11 + 0x1c);
// Get difference in positions between instances
iVar3 = *(int *)(iVar9 + 0x44) - *(int *)(iVar8 + 0x44);
iVar4 = *(int *)(iVar9 + 0x48) - *(int *)(iVar8 + 0x48);
iVar5 = *(int *)(iVar9 + 0x4c) - *(int *)(iVar8 + 0x4c);
// get object from thread
piVar10 = *(int **)(param_1 + 0x30);
// get distance from player instance and thread object instance
iVar3 = iVar3 * iVar3 + iVar4 * iVar4 + iVar5 * iVar5;
if ((*(ushort *)(piVar10 + 1) & 1) == 0)
{
if (
// If game is not paused
((*(uint *)PTR_DAT_8008d2ac & 0xf) != 0) ||
// If driver is too far away from screen
(0x8ffff < iVar3)
)
{
// dont trigger menu, but play
// sound of the load/save screen
goto LAB_800af72c;
}
// If hint is not unlocked
if ((DAT_8008fbb0 & 0x10000000) == 0)
{
// Aku Hint "This is the load/save screen..."
FUN_80035e20(6,0);
}
if (
(*(short *)(iVar11 + 0x38c) < 0x80) &&
(
// Check if Aku Aku is giving a hint,
// 0 - speaking,
// 1 - gone
// AH_MaskHint_boolCanSpawn
uVar6 = FUN_800b3f88(),
// if aku is gone
(uVar6 & 0xffff) != 0
)
)
{
uVar2 = *(short *)((int)piVar10 + 6) - 1;
*(ushort *)((int)piVar10 + 6) = uVar2;
// if scanline goes past the top
if ((int)((uint)uVar2 << 0x10) < 0)
{
// desired transition position (x,y,z)
local_28 = **(short **)(*(int *)(*(int *)(PTR_DAT_8008d2ac + 0x160) + 0x144) + 4) +
(short)((int)*(short *)(iVar9 + 0x30) * 0x19 >> 7);
local_26 = *(short *)(*(int *)(*(int *)(*(int *)(PTR_DAT_8008d2ac + 0x160) + 0x144) + 4) + 2
) + (short)((int)*(short *)(iVar9 + 0x36) * 0x19 >> 7);
local_24 = *(short *)(*(int *)(*(int *)(*(int *)(PTR_DAT_8008d2ac + 0x160) + 0x144) + 4) + 4
) + (short)((int)*(short *)(iVar9 + 0x3c) * 0x19 >> 7);
// desired transition rotation (x,y,z)
local_20 = *(short *)(*(int *)(*(int *)(*(int *)(PTR_DAT_8008d2ac + 0x160) + 0x144) + 4) + 6
) + DAT_800b4ea4;
local_1e = *(short *)(*(int *)(*(int *)(*(int *)(PTR_DAT_8008d2ac + 0x160) + 0x144) + 4) + 8
) + DAT_800b4ea6;
local_1c = *(short *)(*(int *)(*(int *)(*(int *)(PTR_DAT_8008d2ac + 0x160) + 0x144) + 4) +
10) + DAT_800b4ea8;
// pointer to P1 CameraDC
puVar7 = PTR_DAT_8008d2ac + 0x1498;
// 0x80058c44 is an empty function that does nothing
*(undefined4 *)
// driver->instance->thread->funcThTick = 0x80058c44
(*(int *)(*(int *)(*(int *)(PTR_DAT_8008d2ac + 0x24ec) + 0x1c) + 0x6c) + 0x2c) = 0x80058c44;
// Set CameraDC's desired position and rotation,
// then begin the transition by setting flag
FUN_8001a054(puVar7,&local_28,&local_20);
FUN_800263fc(iVar11,0,0);
puVar7 = PTR_DAT_8008d2ac;
*(ushort *)(piVar10 + 1) = *(ushort *)(piVar10 + 1) | 1;
// backup HUD flags while driver sees Save/Load screen
piVar10[2] = (uint)(byte)puVar7[0x1d31];
// clear HUD flags
puVar7[0x1d31] = 0;
}
goto LAB_800af72c;
}
}
else {
if (*(short *)(iVar11 + 0x38c) < 0x101)
{
// view common.h CameraDC->0x70 flag for 0x1508
// if camera is not transitioning
if (((*(uint *)(PTR_DAT_8008d2ac + 0x1508) & 0x200) == 0) &&
((*(ushort *)(piVar10 + 1) & 4) == 0))
{
// instance -> thread -> funcThTick = 0
*(undefined4 *)(*(int *)(iVar8 + 0x6c) + 0x2c) = 0;
*(ushort *)(piVar10 + 1) = *(ushort *)(piVar10 + 1) | 4;
puVar7[0x1d31] = *(undefined *)(piVar10 + 2);
}
// if camera is transitioning
else
{
// Check the flag again
uVar6 = *(uint *)(PTR_DAT_8008d2ac + 0x1508);
// if transition reached it's destination position
if ((uVar6 & 0x800) != 0)
{
// if it is not time to return to player
if ((*(ushort *)(piVar10 + 1) & 2) == 0)
{
*(ushort *)(piVar10 + 1) = *(ushort *)(piVar10 + 1) | 2;
// LoadSave_GetTrackID
FUN_800485a8();
// enable menubox for green load/save screen
FUN_80046990(&DAT_80085b5c);
}
// if it is time to return to player
else
{
if (
// if you aren't already returning to player
((uVar6 & 0x400) == 0) &&
// if there's no MenuBox active
(DAT_8008d908 == 0)
)
{
// toggle flag to return, this either snaps back
// or transitions back depending on & 0x200 (like 0x600 or 0xe00)
*(uint *)(PTR_DAT_8008d2ac + 0x1508) = uVar6 | 0x400;
}
}
}
}
goto LAB_800af72c;
}
*(undefined2 *)(piVar10 + 1) = 0;
}
*(undefined2 *)((int)piVar10 + 6) = 0xf;
LAB_800af72c:
// first member of object is instance???
iVar4 = *piVar10;
if (iVar4 != 0)
{
// instance -> animation frame
sVar1 = *(short *)(iVar4 + 0x54);
// INSTANCE_GetNumAnimFrames
iVar4 = FUN_80030f58(iVar4,0);
// if animation is not finished
if ((int)sVar1 + 1 < iVar4)
{
// increment animation frame
*(short *)(*piVar10 + 0x54) = *(short *)(*piVar10 + 0x54) + 1;
}
// if animation is finished,
// reset animation, and play sound
else
{
// SquareRoot0
iVar3 = FUN_8006c618(iVar3);
// get square root to have "true" distance
// multiply by 1.5f
// mul 3, divide 2
iVar3 = iVar3 * 3 >> 1;
// play sound at max volume
uVar6 = 0xff;
// if distance is large
if (300 < iVar3)
{
// calculate volume based on distance,
// mapping perentage between min-max distance,
// to a volume 0 - 0xff
uVar6 = FUN_80058f9c(iVar3,300,6000,0xff,0);
}
// OtherFX_Play_LowLevel
// Play save/load screen sound
FUN_800284d0(0x99,1,(uVar6 & 0xff) << 0x10 | 0x8080);
// reset animation
*(undefined2 *)(*piVar10 + 0x54) = 0;
}
}
return;
}
// AH_SaveObj_LInB
void FUN_800af7f0(int param_1)
{
undefined *puVar1;
int iVar2;
undefined4 uVar3;
undefined4 uVar4;
undefined4 uVar5;
int *piVar6;
undefined2 local_18;
undefined2 local_16;
undefined2 local_14;
// if this Instance's thread is not valid
if (*(int *)(param_1 + 0x6c) == 0)
{
// THREAD_BirthWithObject
// 0xc = size
// 0 = no relation to param4
// 0x300 = SmallStackPool
// 0x3 = static thread bucket
iVar2 = FUN_8004205c(0xc0303,FUN_800af3e4,s_saveobj_800aba78,0);
// give the thread to Instance
*(int *)(param_1 + 0x6c) = iVar2;
// if the thread was built properly
if (iVar2 != 0)
{
// get the object attached to the thread
piVar6 = *(int **)(iVar2 + 0x30);
// give Instance to the thread
*(int *)(iVar2 + 0x34) = param_1;
// AH_SaveObj_ThDestroy
*(undefined4 *)(iVar2 + 0x24) = 0x800af3a4;
// initialize object
*(undefined2 *)(piVar6 + 1) = 0;
// scanline frame
*(undefined2 *)((int)piVar6 + 6) = 0;
puVar1 = PTR_DAT_8008d2ac;
// make invisible
*(uint *)(param_1 + 0x28) = *(uint *)(param_1 + 0x28) | 0x80;
// LEV -> numSpawn1
if (*(int *)(*(int *)(puVar1 + 0x160) + 0x140) == 0) {
*piVar6 = 0;
}
// if numSpawn1 is more than zero
else
{
// DAT_800aba80
// "scan"
// INSTANCE_Birth3D -- ptrModel, name, thread
iVar2 = FUN_8003086c(*(undefined4 *)(puVar1 + 0x2340),&DAT_800aba80);
puVar1 = PTR_DAT_8008d2ac;
*piVar6 = iVar2;
uVar3 = *(undefined4 *)(param_1 + 0x34);
uVar4 = *(undefined4 *)(param_1 + 0x38);
uVar5 = *(undefined4 *)(param_1 + 0x3c);
*(undefined4 *)(iVar2 + 0x30) = *(undefined4 *)(param_1 + 0x30);
*(undefined4 *)(iVar2 + 0x34) = uVar3;
*(undefined4 *)(iVar2 + 0x38) = uVar4;
*(undefined4 *)(iVar2 + 0x3c) = uVar5;
// get position from some other instance
uVar3 = *(undefined4 *)(param_1 + 0x44);
uVar4 = *(undefined4 *)(param_1 + 0x48);
uVar5 = *(undefined4 *)(param_1 + 0x4c);
*(undefined4 *)(iVar2 + 0x40) = *(undefined4 *)(param_1 + 0x40);
// set position of this instance
*(undefined4 *)(iVar2 + 0x44) = uVar3;
*(undefined4 *)(iVar2 + 0x48) = uVar4;
*(undefined4 *)(iVar2 + 0x4c) = uVar5;
// LEV -> ptrSpawn1
local_18 = *(undefined2 *)(*(int *)(*(int *)(*(int *)(puVar1 + 0x160) + 0x144) + 4) + 6);
local_16 = *(undefined2 *)(*(int *)(*(int *)(*(int *)(puVar1 + 0x160) + 0x144) + 4) + 8);
local_14 = *(undefined2 *)(*(int *)(*(int *)(*(int *)(puVar1 + 0x160) + 0x144) + 4) + 10);
// convert 3 rotation shorts into rotation matrix
FUN_8006c2a4(*piVar6 + 0x30,&local_18);
puVar1 = PTR_DAT_8008d2ac;
// LEV -> ptrSpawn1
*(int *)(*piVar6 + 0x44) =
(int)**(short **)(*(int *)(*(int *)(PTR_DAT_8008d2ac + 0x160) + 0x144) + 4);
// LEV -> ptrSpawn1
*(int *)(*piVar6 + 0x48) =
(int)*(short *)(*(int *)(*(int *)(*(int *)(puVar1 + 0x160) + 0x144) + 4) + 2);
// LEV -> ptrSpawn1
*(int *)(*piVar6 + 0x4c) =
(int)*(short *)(*(int *)(*(int *)(*(int *)(puVar1 + 0x160) + 0x144) + 4) + 4);
*(undefined *)(*piVar6 + 0x50) = 0xf8;
}
}
}
return;
}
// AH_Door_ThDestroy
void FUN_800af9f8(int param_1)
{
int *piVar1;
int iVar2;
// get door object attached to thread
piVar1 = *(int **)(param_1 + 0x30);
// if the door is valid
if (*piVar1 != 0)
{
// INSTANCE_Death
FUN_80030aa8();
*piVar1 = 0;
}
// loop through 4 keys
iVar2 = 0;
do {
iVar2 = iVar2 + 1;
// INSTANCE_Death
FUN_80030aa8(piVar1[1]);
piVar1[1] = 0;
piVar1 = piVar1 + 1;
} while (iVar2 < 4);
return;
}
// WARNING: Removing unreachable block (ram,0x800b00f0)
// AH_Door_ThTick
void FUN_800afa60(int param_1)
{
bool bVar1;
undefined *puVar2;
ushort uVar3;
int iVar4;
uint uVar5;
short sVar6;
int iVar7;
undefined4 uVar8;
int *piVar9;
undefined4 uVar10;
undefined4 uVar11;
int iVar12;
int iVar13;
int *piVar14;
int iVar15;
int *piVar16;
int iVar17;
int iVar18;
short local_60;
short local_5e;
short local_5c;
short local_58;
undefined2 local_56;
undefined2 local_54;
undefined2 local_50;
short local_4e;
undefined2 local_4c;
undefined4 local_48;
undefined4 local_44;
undefined4 local_40;
undefined4 local_3c;
undefined4 local_38;
undefined2 local_34;
undefined *local_30;
// P1 CameraDC
local_30 = PTR_DAT_8008d2ac + 0x1498;
// get instance from thread
iVar15 = *(int *)(param_1 + 0x34);
// P1 driver object
iVar17 = *(int *)(PTR_DAT_8008d2ac + 0x24ec);
// thread object
// Offset 0xD of object is "Door ID"
piVar14 = *(int **)(param_1 + 0x30);
// Assume door is closed
bVar1 = false;
// check if the door that the player approached is open
if (
(
(
// If you are on N Sanity Beach
(*(int *)(PTR_DAT_8008d2ac + 0x1a10) == 0x1a) &&
(
(
// 0x40 -> Door open from Beach to Glacier
(
// if the door approached is Beach -> Glacier
*(short *)(piVar14 + 0xd) == 4 &&
// If that door is open
((DAT_8008fbb0 & 0x40) != 0)
) ||
(
(
// If you are on N Sanity Beach
*(int *)(PTR_DAT_8008d2ac + 0x1a10) == 0x1a &&
(
(
// if door approached is beach -> gemstone valley
*(short *)(piVar14 + 0xd) == 5 &&
// 0x40 -> Door open from Beach to Gemstone Valley
((DAT_8008fbb0 & 0x10) != 0)
)
)
)
)
)
)
) ||
// Check gemstone valley and the door to Gem Cup room
((*(int *)(PTR_DAT_8008d2ac + 0x1a10) == 0x19 && ((DAT_8008fbb0 & 0x20) != 0)))) ||
// Check Lost Ruins and the door to Glacier Park
(((*(int *)(PTR_DAT_8008d2ac + 0x1a10) == 0x1b && ((DAT_8008fbb0 & 0x80) != 0)) ||
// Check Glacier Park and the door to Citadel City
((*(int *)(PTR_DAT_8008d2ac + 0x1a10) == 0x1c && ((DAT_8008fbb0 & 0x100) != 0)))))
)
{
// door is open
bVar1 = true;
}
// Cosine(angle)
iVar4 = FUN_8003d1c0((int)*(short *)(*(int *)(iVar15 + 0x2c) + 0x38));
// X distance of player and door
iVar13 = (*(int *)(iVar15 + 0x44) + (iVar4 * 0x300 >> 0xc)) -
*(int *)(*(int *)(iVar17 + 0x1c) + 0x44);
// Y distance of player and door
iVar12 = *(int *)(iVar15 + 0x48) - *(int *)(*(int *)(iVar17 + 0x1c) + 0x48);
// Sine(angle)
iVar4 = FUN_8003d184((int)*(short *)(*(int *)(iVar15 + 0x2c) + 0x38));
// Z distance of player and door
iVar4 = (*(int *)(iVar15 + 0x4c) + (iVar4 * 0x300 >> 0xc)) -
*(int *)(*(int *)(iVar17 + 0x1c) + 0x4c);
// distance from player and door
iVar4 = iVar13 * iVar13 + iVar12 * iVar12 + iVar4 * iVar4;
// If player is close to a door
if (iVar4 < 0x90000)
{
// if door is open
if (bVar1)
{
// enable access through a door (disable collision)
DAT_8008d728 = DAT_8008d728 | 2;
}
// if door is locked
else
{
// remove access (enable collision)
DAT_8008d728 = DAT_8008d728 & 0xfffffffd;
}
}
// If this is N Sane Beach
if (*(int *)(PTR_DAT_8008d2ac + 0x1a10) == 0x1a) {
// if this is beach -> gemstone,
// must have 1 key
sVar6 = 1;
// If this is door from beach -> glacier
if (*(short *)(piVar14 + 0xd) == 4)
{
// must have 2 keys
sVar6 = 2;
}
}
// If not N Sane Beach
else
{
// get number of keys for whichever door is on the hub
sVar6 = *(short *)(&DAT_800b4e7c + (*(int *)(PTR_DAT_8008d2ac + 0x1a10) + -0x19) * 2);
}
// if in a state where you're seeing the boss key open an adv door,
// or some other kind of cutscene where you can't move
if ((*(uint *)(PTR_DAT_8008d2ac + 8) & 4) != 0) {
return;
}
// If door is open
if (bVar1)
{
// CameraDC->flag & 0x200 (camera transition, watch door open)
if ((*(uint *)(local_30 + 0x70) & 0x200) != 0)
{
// quit, come back when camera transition ends
return;
}
// check if hint is unlocked
uVar5 = DAT_8008fbb0 & 0x20000000;
// "Congrats on opening this new area..."
uVar8 = 7;
joined_r0x800b06ec:
// if hint is not unlocked
if (uVar5 == 0)
{
// request to give hint
FUN_80035e20(uVar8,0);
}
return;
}
if (
// if player is far from the door
(0x8ffff < iVar4) &&
((*(ushort *)(piVar14 + 7) & 0x10) == 0)
)
{
return;
}
// get number of keys required to open door
iVar4 = (int)sVar6;
// if player has less than that amount
if (*(int *)(PTR_DAT_8008d2ac + 0x1e38) < iVar4)
{
// if one key is required
if (iVar4 == 1)
{
// check if hint is unlocked
uVar5 = DAT_8008fbb0 & 0x8000000;
// Aku Hint "You must have a boss key"
uVar8 = 5;
}
// not one...
else
{
// if not 2...
if (iVar4 != 2)
{
// no hint for that
return;
}
// if 2 keys are needed to enter
// check if hint is unlocked
uVar5 = DAT_8008fbb4 & 0x100;
// Aku Hint "You must have two boss keys"
uVar8 = 0x12;
}
goto joined_r0x800b06ec;
}
// if camera is not transitioning out (yet),
// while keys are still spinning in air
if ((*(ushort *)(piVar14 + 7) & 1) == 0) {
if (*(short *)((int)piVar14 + 0x1e) != 0) {
*(short *)((int)piVar14 + 0x1e) = *(short *)((int)piVar14 + 0x1e) + -1;
goto LAB_800b0404;
}
// If the game is paused
if ((*(uint *)PTR_DAT_8008d2ac & 0xf) != 0)
{
goto LAB_800b0404;
}
// If you are here, game must not be paused
// VehPtr_Freeze_Init
*(undefined4 *)(iVar17 + 0x54) = 0x80062d04;
*(ushort *)(piVar14 + 7) = *(ushort *)(piVar14 + 7) | 0x10;
// if timer is less than four full seconds
if (*(short *)((int)piVar14 + 0x26) < 0x78)
{
// wait for driver->speedApprox to slow
// to near-halt before starting
if (*(short *)(iVar17 + 0x38e) < 0x80) {
local_60 = -0xc98;
local_5e = 0x99f;
local_5c = 0x232;
// if keys are not spawned, create them
if (piVar14[1] == 0) {
iVar12 = 0;
piVar9 = piVar14;
// if number of keys is more than zero
if (0 < iVar4)
{
// spawn instances for every key you have,
// this makes them spin in a circle before
// seeing the doors animate open
do
{
// DAT_800aba88
// "key"
// INSTANCE_Birth3D -- ptrModel, name, thread
iVar13 = FUN_8003086c(*(undefined4 *)(PTR_DAT_8008d2ac + 0x22ec),&DAT_800aba88
,param_1);
piVar9[1] = iVar13;
// Set Key Color
*(undefined4 *)(iVar13 + 0x24) = 0xdca6000;
// specular lighting
*(uint *)(piVar9[1] + 0x28) = *(uint *)(piVar9[1] + 0x28) | 0x20000;
puVar2 = PTR_DAT_8008d2ac;
*(short *)(piVar14 + 9) = *(short *)(piVar14 + 9) + 1;
iVar7 = piVar9[1];
// driver -> instSelf
iVar13 = *(int *)(*(int *)(puVar2 + 0x24ec) + 0x1c);
uVar11 = *(undefined4 *)(iVar13 + 0x34);
uVar8 = *(undefined4 *)(iVar13 + 0x38);
uVar10 = *(undefined4 *)(iVar13 + 0x3c);
*(undefined4 *)(iVar7 + 0x30) = *(undefined4 *)(iVar13 + 0x30);
*(undefined4 *)(iVar7 + 0x34) = uVar11;
*(undefined4 *)(iVar7 + 0x38) = uVar8;
*(undefined4 *)(iVar7 + 0x3c) = uVar10;
// Get position from some other instance
uVar11 = *(undefined4 *)(iVar13 + 0x44);
uVar8 = *(undefined4 *)(iVar13 + 0x48);
uVar10 = *(undefined4 *)(iVar13 + 0x4c);
*(undefined4 *)(iVar7 + 0x40) = *(undefined4 *)(iVar13 + 0x40);
// set position of this instance
*(undefined4 *)(iVar7 + 0x44) = uVar11;
*(undefined4 *)(iVar7 + 0x48) = uVar8;
*(undefined4 *)(iVar7 + 0x4c) = uVar10;
// set scale to zero
*(undefined2 *)(piVar9[1] + 0x1c) = 0;
*(undefined2 *)(piVar9[1] + 0x1e) = 0;
*(undefined2 *)(piVar9[1] + 0x20) = 0;
// driver -> instance -> posX
*(undefined4 *)(piVar9[1] + 0x44) =
*(undefined4 *)(*(int *)(*(int *)(puVar2 + 0x24ec) + 0x1c) + 0x44);
// driver -> instance -> posY
*(undefined4 *)(piVar9[1] + 0x48) =
*(undefined4 *)(*(int *)(*(int *)(puVar2 + 0x24ec) + 0x1c) + 0x48);
iVar12 = iVar12 + 1;
// driver -> instance -> posZ
*(undefined4 *)(piVar9[1] + 0x4c) =
*(undefined4 *)(*(int *)(*(int *)(puVar2 + 0x24ec) + 0x1c) + 0x4c);
piVar9 = piVar9 + 1;
} while (iVar12 < iVar4);
}
puVar2 = PTR_DAT_8008d2ac;
// Make a backup of HUD variable
piVar14[8] = (uint)(byte)PTR_DAT_8008d2ac[0x1d31];
// Disable HUD
puVar2[0x1d31] = 0;
// For watching hub doors animate open
}
// get number of keys
iVar4 = (int)sVar6;
iVar12 = 0;
// if more than zero
if (0 < iVar4) {
piVar16 = piVar14 + 10;
piVar9 = piVar14;
// loop through all keys
do {
iVar13 = piVar9[1];
if (iVar13 != 0)
{
// if scale < 0xa00
if (*(short *)(iVar13 + 0x1c) < 0xa00)
{
// increase scale on X, Y, Z
*(short *)(iVar13 + 0x1c) = *(short *)(iVar13 + 0x1c) + 0x40;
*(short *)(piVar9[1] + 0x1e) = *(short *)(piVar9[1] + 0x1e) + 0x40;
*(short *)(piVar9[1] + 0x20) = *(short *)(piVar9[1] + 0x20) + 0x40;
}
// get posY
iVar13 = *(int *)(piVar9[1] + 0x48);
// if key posY is less than (player posY + 0xa0)
if (iVar13 < *(int *)(*(int *)(*(int *)(PTR_DAT_8008d2ac + 0x24ec) + 0x1c) + 0x48) +
0xa0)
{
// increase key posY
*(int *)(piVar9[1] + 0x48) = iVar13 + 4;
}
if (1 < iVar4) {
if (iVar4 == 0) {
trap(0x1c00);
}
iVar18 = iVar12 * (0x1000 / iVar4);
// Sine(angle)
iVar13 = FUN_8003d184(*(short *)(piVar14 + 0xc) + iVar18,piVar16);
iVar7 = (int)*(short *)(piVar9[1] + 0x1c);
if (iVar7 < 0) {
iVar7 = iVar7 + 0x1f;
}
*(int *)(piVar9[1] + 0x44) =
*(int *)(*(int *)(*(int *)(PTR_DAT_8008d2ac + 0x24ec) + 0x1c) + 0x44) +
((iVar7 >> 5) * iVar13 >> 0xc);
// Cosine(angle)
iVar13 = FUN_8003d1c0(*(short *)(piVar14 + 0xc) + iVar18);
iVar7 = (int)*(short *)(piVar9[1] + 0x1c);
if (iVar7 < 0) {
iVar7 = iVar7 + 0x1f;
}
*(int *)(piVar9[1] + 0x4c) =
*(int *)(*(int *)(*(int *)(PTR_DAT_8008d2ac + 0x24ec) + 0x1c) + 0x4c) +
((iVar7 >> 5) * iVar13 >> 0xc);
}
// Vector_SpecLightSpin3D
FUN_8005741c(piVar9[1],piVar16,&local_60);
// convert 3 rotation shorts into rotation matrix
FUN_8006c2a4(piVar9[1] + 0x30,piVar16);
}
iVar12 = iVar12 + 1;
piVar9 = piVar9 + 1;
} while (iVar12 < iVar4);
}
*(undefined2 *)(piVar14 + 10) = 0;
*(undefined2 *)(piVar14 + 0xb) = 0;
// increment frame counter
sVar6 = *(short *)((int)piVar14 + 0x26) + 1;
*(short *)((int)piVar14 + 0x26) = sVar6;
// spin rate of key
*(short *)((int)piVar14 + 0x2a) = *(short *)((int)piVar14 + 0x2a) + 0x40;
*(short *)(piVar14 + 0xc) = *(short *)(piVar14 + 0xc) + 0x10;
// play four distorted "token unlock" sounds,
// then play some dramatic sound, then play
// sound of doors creeking open
if (sVar6 == 10)
{
// OtherFX_Play_LowLevel
FUN_800284d0(0x67,1,0xff7680);
}
else {
if (sVar6 == 0xf)
{
// OtherFX_Play_LowLevel
FUN_800284d0(0x67,1,0xeb8080);
}
else {
if (sVar6 == 0x14)
{
// OtherFX_Play_LowLevel
FUN_800284d0(0x67,1,0xd78a80);
}
else {
if (sVar6 == 0x19)
{
// OtherFX_Play_LowLevel
FUN_800284d0(0x67,1,0xc39480);
}
else {
if (sVar6 == 0x50)
{
// sound of hub doors unlocking ??
// or just a dramatic sound ??
// point is it's right before doors
// "creek" open
uVar8 = 0x93;
}
else
{
// doors "creek" open
uVar8 = 0x94;
if (sVar6 != 0x78) goto LAB_800b0404;
}
// Play Sound
FUN_80028468(uVar8,1);
}
}
}
}
}
goto LAB_800b0404;
}
// After four full seconds,
// start the camera zoom-out
// Cosine(angle)
iVar4 = FUN_8003d1c0((int)*(short *)(*(int *)(iVar15 + 0x2c) + 0x38));
// Cosine(angle)
iVar12 = FUN_8003d1c0((int)*(short *)(*(int *)(iVar15 + 0x2c) + 0x38) + 0x400);
// desired posX for transition
local_60 = *(short *)(iVar15 + 0x44) + (short)(iVar4 * 0x312 >> 0xc) +
(short)(iVar12 * 0x600 >> 0xc);
// desired posY for transition
local_5e = *(short *)(iVar15 + 0x48) + 0x17a;
// Sine(angle)
iVar4 = FUN_8003d184((int)*(short *)(*(int *)(iVar15 + 0x2c) + 0x38));
// Sine(angle)
iVar12 = FUN_8003d184((int)*(short *)(*(int *)(iVar15 + 0x2c) + 0x38) + 0x400);
// desired posZ for transition
local_5c = *(short *)(iVar15 + 0x4c) + (short)(iVar4 * 0x312 >> 0xc) +
(short)(iVar12 * 0x600 >> 0xc);
// desired rotation for transition
local_58 = *(short *)(*(int *)(iVar15 + 0x2c) + 0x36) + 0x800;
local_56 = *(undefined2 *)(*(int *)(iVar15 + 0x2c) + 0x38);
local_54 = *(undefined2 *)(*(int *)(iVar15 + 0x2c) + 0x3a);
// set desired position and rotation for CamerDC transition
FUN_8001a054(PTR_DAT_8008d2ac + 0x1498,&local_60,&local_58);
// GAMEPAD_JogCon2
FUN_800263fc(iVar17,0,0);
// start camera out transition (in "else" below)
uVar3 = *(ushort *)(piVar14 + 7) | 1;
}
// if camera is transitioning out,
// after keys are done spinning in air
else {
// set transition out to take two full seconds (can't patch?)
*(undefined2 *)((int)piVar14 + 0x1e) = 0x3c;
if (((*(uint *)(local_30 + 0x70) & 0x200) != 0) || ((*(ushort *)(piVar14 + 7) & 4) != 0)) {
if (((*(uint *)(local_30 + 0x70) & 0x800) != 0) && ((*(ushort *)(piVar14 + 7) & 2) == 0)) {
*(ushort *)(piVar14 + 7) = *(ushort *)(piVar14 + 7) | 2;
}
goto LAB_800b0404;
}
// VehPtr_Driving_Init
*(undefined4 *)(iVar17 + 0x54) = 0x80062b74;
uVar3 = *(ushort *)(piVar14 + 7) | 4;
}
*(ushort *)(piVar14 + 7) = uVar3;
LAB_800b0404:
puVar2 = PTR_DAT_8008d2ac;
if ((*(ushort *)(piVar14 + 7) & 1) == 0) {
return;
}
// if doors are 90 degrees open,
// then allow passage, and quit function
if (0x3ff < *(short *)((int)piVar14 + 0x16))
{
// get level ID
iVar15 = *(int *)(PTR_DAT_8008d2ac + 0x1a10);
if (
(
// if this is N Sane Beach
(iVar15 == 0x1a) &&
// if this is door #4 (beach -> glacier)
(*(short *)(piVar14 + 0xd) == 4)
// if this is lost ruins (ruins -> glacier)
) || (iVar15 == 0x1b)
)
{
// open all doors to glacier
DAT_8008fbb0 = DAT_8008fbb0 | 0xc0;
}
else
{
if (
// if this is N Sane Beach
(iVar15 == 0x1a) &&
// Door #5 (beach -> ruins)
(*(short *)(piVar14 + 0xd) == 5)
)
{
// record that door is open
DAT_8008fbb0 = DAT_8008fbb0 | 0x10;
}
else
{
// Gemstone valley (cup door)
if (*(int *)(PTR_DAT_8008d2ac + 0x1a10) == 0x19)
{
// record that door is open
DAT_8008fbb0 = DAT_8008fbb0 | 0x20;
}
// Glacier Park (glacier -> citadel)
else
{
// record that door is open
DAT_8008fbb0 = DAT_8008fbb0 | 0x100;
}
}
}
*(uint *)(local_30 + 0x70) = *(uint *)(local_30 + 0x70) | 0x400;
// VehPtr_Driving_Init
*(undefined4 *)(iVar17 + 0x54) = 0x80062b74;
*(ushort *)(piVar14 + 7) = *(ushort *)(piVar14 + 7) & 0xffef | 4;
// bring HUD back
puVar2[0x1d31] = *(undefined *)(piVar14 + 8);
return;
}
// if doors are less than 90 degrees open
local_48 = DAT_800aba8c;
local_44 = DAT_800aba90;
local_40 = DAT_800aba94;
local_3c = DAT_800aba98;
local_38 = DAT_800aba9c;
local_34 = DAT_800abaa0;
// right-hand door rotX
local_60 = *(short *)(piVar14 + 5);
// increase opening rotation by 0x10 per frame
*(short *)((int)piVar14 + 0x16) = *(short *)((int)piVar14 + 0x16) + 0x10;
// right-hand door rotY and rotZ
local_5e = *(short *)(*(int *)(iVar15 + 0x2c) + 0x38) - *(short *)((int)piVar14 + 0x16);
local_5c = *(short *)(piVar14 + 6);
// left-hand door rot[x,y,z]
local_50 = *(undefined2 *)(piVar14 + 5);
local_4e = *(short *)(*(int *)(iVar15 + 0x2c) + 0x38) + *(short *)((int)piVar14 + 0x16);
local_4c = *(undefined2 *)(piVar14 + 6);
// convert 3 rotation shorts into rotation matrix
FUN_8006c2a4(iVar15 + 0x30,&local_50);
// convert 3 rotation shorts into rotation matrix
FUN_8006c2a4(*piVar14 + 0x30,&local_60);
// if less than 11 frames have passed,
// decrease key scale, then quit function
if (*(short *)((int)piVar14 + 0x32) < 0xb) {
iVar15 = 0;
piVar9 = piVar14;
// loop through 4 keys
do
{
// if instance exists
if (piVar9[1] != 0)
{
// decrease scale of key,
// by using array of values per frame
*(undefined2 *)(piVar9[1] + 0x1c) =
*(undefined2 *)((int)&local_48 + (int)*(short *)((int)piVar14 + 0x32) * 2);
*(undefined2 *)(piVar9[1] + 0x1e) =
*(undefined2 *)((int)&local_48 + (int)*(short *)((int)piVar14 + 0x32) * 2);
*(undefined2 *)(piVar9[1] + 0x20) =
*(undefined2 *)((int)&local_48 + (int)*(short *)((int)piVar14 + 0x32) * 2);
}
iVar15 = iVar15 + 1;
piVar9 = piVar9 + 1;
} while (iVar15 < 4);
// increase frame
*(short *)((int)piVar14 + 0x32) = *(short *)((int)piVar14 + 0x32) + 1;
return;
}
// if 11 or more frames have passed,
// destroy four key instances. INSTANCE_Death
// is internally nullptr-safe-checked
iVar15 = 0;
// loop through 4 keys
do {
iVar15 = iVar15 + 1;
// INSTANCE_Death
FUN_80030aa8(piVar14[1]);
piVar14[1] = 0;
piVar14 = piVar14 + 1;
} while (iVar15 < 4);
return;
}
// AH_Door_LInB
void FUN_800b072c(int param_1)
{
char cVar1;
short sVar2;
bool bVar3;
undefined *puVar4;
int iVar5;
int *piVar6;
int iVar7;
undefined4 uVar8;
undefined4 uVar9;
undefined4 uVar10;
int *piVar11;
undefined2 local_20;
short local_1e;
undefined2 local_1c;
undefined2 local_18;
short local_16;
undefined2 local_14;
// If this Instance already has a thread
if (*(int *)(param_1 + 0x6c) != 0)
{
// quit
return;
}
// 800abaa4 - "door" (not boss garage)
// THREAD_BirthWithObject
// 0x38 = size
// 0 = no relation to param4
// 0x300 = SmallStackPool
// 0x3 = static thread bucket
iVar5 = FUN_8004205c(0x380303,FUN_800afa60,&DAT_800abaa4,0);
// give the thread to the Instance
*(int *)(param_1 + 0x6c) = iVar5;
// if the thread failed to build
if (iVar5 == 0)
{
// quit
return;
}
iVar7 = 3;
// get the "door" object attached to thread
piVar11 = *(int **)(iVar5 + 0x30);
// give Instance to the thread
*(int *)(iVar5 + 0x34) = param_1;
// set OnDestroy, AH_Door_ThDestroy
*(undefined4 *)(iVar5 + 0x24) = 0x800af9f8;
piVar6 = piVar11 + 3;
// instance flags,
// this instance is always the left-hand door,
// and every left-hand door has one key hole
*(uint *)(param_1 + 0x28) = *(uint *)(param_1 + 0x28) | 0x1000;
do {
piVar6[1] = 0;
iVar7 = iVar7 + -1;
piVar6 = piVar6 + -1;
} while (-1 < iVar7);
// specLight?
*(undefined2 *)(piVar11 + 9) = 0;
*(undefined2 *)(piVar11 + 7) = 0;
*(undefined2 *)((int)piVar11 + 0x1e) = 0;
// frame timer
*(undefined2 *)((int)piVar11 + 0x26) = 0;
// keyShrinkFrame
*(undefined2 *)((int)piVar11 + 0x32) = 0;
// another vec3
*(undefined2 *)(piVar11 + 5) = 0;
*(undefined2 *)((int)piVar11 + 0x16) = 0;
*(undefined2 *)(piVar11 + 6) = 0;
// door ID
*(undefined2 *)(piVar11 + 0xd) = 0;
// instance->name[5],
// doorID
cVar1 = *(char *)(param_1 + 0xd);
iVar5 = 5;
while (cVar1 != '\0')
{
sVar2 = *(short *)(piVar11 + 0xd);
// get door ID from string
*(short *)(piVar11 + 0xd) = sVar2 * 10;
*(ushort *)(piVar11 + 0xd) = sVar2 * 10 + ((ushort)*(byte *)(param_1 + (short)iVar5 + 8) - 0x30);
// loop through index
iVar5 = iVar5 + 1;
cVar1 = *(char *)(param_1 + (iVar5 * 0x10000 >> 0x10) + 8);
}
// Level ID is Glacier Park
if (*(int *)(PTR_DAT_8008d2ac + 0x1a10) == 0x1c)
{
// STATIC_DOOR3
// door with two key holes
iVar5 = *(int *)(PTR_DAT_8008d2ac + 0x2434);
}
// Level ID is not Glacier Park
else
{
if (
// Level ID is N Sanity Beach
(*(int *)(PTR_DAT_8008d2ac + 0x1a10) == 0x1a) &&
// doorID == 5
(*(short *)(piVar11 + 0xd) == 5)
)
{
// STATIC_DOOR2
// door with no key holes
iVar5 = *(int *)(PTR_DAT_8008d2ac + 0x23fc);
// if it does not exist
if (iVar5 == 0)
{
// useless, this will never happen,
// also then instance would be nullptr,
// and instance->matrix would dereference
// nullptr and crash the game
*piVar11 = 0;
goto LAB_800b08b4;
}
}
// if not that door
else
{
// STATIC_DOOR
// door with one key hole
iVar5 = *(int *)(PTR_DAT_8008d2ac + 0x2348);
}
}
// DAT_800abaa4
// "door"
// INSTANCE_Birth3D -- ptrModel, name, thread
iVar5 = FUN_8003086c(iVar5,&DAT_800abaa4);
// spawn instance of right-hand door,
// which is not in LEV file, only built in thread
*piVar11 = iVar5;
LAB_800b08b4:
// instance flags
// | 0x8000 - reverse culling direction
*(uint *)(*piVar11 + 0x28) = *(uint *)(*piVar11 + 0x28) | 0x9000;
// right-hand instance
iVar5 = *piVar11;
// copy full matrix (position and rotation)
// from left-hand door to right-hand door
uVar8 = *(undefined4 *)(param_1 + 0x34);
uVar9 = *(undefined4 *)(param_1 + 0x38);
uVar10 = *(undefined4 *)(param_1 + 0x3c);
*(undefined4 *)(iVar5 + 0x30) = *(undefined4 *)(param_1 + 0x30);
*(undefined4 *)(iVar5 + 0x34) = uVar8;
*(undefined4 *)(iVar5 + 0x38) = uVar9;
*(undefined4 *)(iVar5 + 0x3c) = uVar10;
uVar8 = *(undefined4 *)(param_1 + 0x44);
uVar9 = *(undefined4 *)(param_1 + 0x48);
uVar10 = *(undefined4 *)(param_1 + 0x4c);
*(undefined4 *)(iVar5 + 0x40) = *(undefined4 *)(param_1 + 0x40);
*(undefined4 *)(iVar5 + 0x44) = uVar8;
*(undefined4 *)(iVar5 + 0x48) = uVar9;
*(undefined4 *)(iVar5 + 0x4c) = uVar10;
// set scaleX to -0x1000
*(undefined2 *)(*piVar11 + 0x1c) = 0xf000;
// reverse culling
*(uint *)(*piVar11 + 0x28) = *(uint *)(*piVar11 + 0x28) | 0x8000;
// Cosine(angle)
// doorInst->rot[Y]
iVar5 = FUN_8003d1c0((int)*(short *)(*(int *)(param_1 + 0x2c) + 0x38));
// right-hand door posX =
*(int *)(*piVar11 + 0x44) =
// left-hand door posX + cos(rotY) * 0x600 >> 0xC
// Cosine returns [0-0x1000] so addition is [0-0x600]
(int *)(param_1 + 0x44) + (iVar5 * 0x600 >> 0xc);
// right-hand door posX = left-hand door posX
*(undefined4 *)(*piVar11 + 0x48) = *(undefined4 *)(param_1 + 0x48);
// Sine(angle)
// doorInst->rot[Y]
iVar5 = FUN_8003d184((int)*(short *)(*(int *)(param_1 + 0x2c) + 0x38));
// right-hand door posX =
*(int *)(*piVar11 + 0x4c) =
// left-hand door posX + cos(rotY) * 0x600 >> 0xC
// Cosine returns [0-0x1000] so addition is [0-0x600]
*(int *)(param_1 + 0x4c) + (iVar5 * 0x600 >> 0xc);
// instance -> model -> headers
iVar5 = *(int *)(*(int *)(param_1 + 0x18) + 0x14);
// header -> flags: always face camera
*(ushort *)(iVar5 + 0x16) = *(ushort *)(iVar5 + 0x16) | 2;
puVar4 = PTR_DAT_8008d2ac;
// make "door" always face camera
iVar5 = *(int *)(*(int *)(*piVar11 + 0x18) + 0x14);
*(ushort *)(iVar5 + 0x16) = *(ushort *)(iVar5 + 0x16) | 2;
if (
// Level ID is N Sanity Beach
(((*(int *)(puVar4 + 0x1a10) == 0x1a) &&
// Check door to Gemstone Valley
(((*(short *)(piVar11 + 0xd) == 4 && ((DAT_8008fbb0 & 0x40) != 0)) ||
// Level ID is N Sanity Beach
((*(int *)(PTR_DAT_8008d2ac + 0x1a10) == 0x1a &&
// Check door to Glacier Park
((*(short *)(piVar11 + 0xd) == 5 && ((DAT_8008fbb0 & 0x10) != 0)))))))) ||
// Level ID is Gemstone Valley, check door to Cup room
((*(int *)(PTR_DAT_8008d2ac + 0x1a10) == 0x19 && ((DAT_8008fbb0 & 0x20) != 0)))) ||
// Level ID is Lost Ruins, check door to Glacier Park
(((*(int *)(PTR_DAT_8008d2ac + 0x1a10) == 0x1b && ((DAT_8008fbb0 & 0x80) != 0)) ||
// Level ID is Glacier Park, check door to Citadel City
((bVar3 = false, *(int *)(PTR_DAT_8008d2ac + 0x1a10) == 0x1c &&
(bVar3 = false, (DAT_8008fbb0 & 0x100) != 0)))))
)
{
// door has already been opened
bVar3 = true;
}
// if door has already been opened
if (bVar3)
{
// right-hand door rotX
local_20 = *(undefined2 *)(piVar11 + 5);
// rotation = 90 degrees
*(undefined2 *)((int)piVar11 + 0x16) = 0x400;
// right-hand door rotY = leftDoorInst->instDef->rot[Y] - 0x400
local_1e = *(short *)(*(int *)(param_1 + 0x2c) + 0x38) - *(short *)((int)piVar11 + 0x16);
local_1c = *(undefined2 *)(piVar11 + 6);
// left-hand door rotY = leftDoorInst->instDef->rot[Y] + 0x400
local_18 = *(undefined2 *)(piVar11 + 5);
local_16 = *(short *)(*(int *)(param_1 + 0x2c) + 0x38) + *(short *)((int)piVar11 + 0x16);
local_14 = *(undefined2 *)(piVar11 + 6);
// make matrices for both doors rotated open
// convert 3 rotation shorts into rotation matrix
FUN_8006c2a4(param_1 + 0x30,&local_18);
// convert 3 rotation shorts into rotation matrix
FUN_8006c2a4(*piVar11 + 0x30,&local_20);
}
return;
}
// AH_Map_LoadSave_Prim
void FUN_800b0b98(undefined2 *param_1,undefined *param_2,undefined4 param_3,int param_4)
{
uint uVar1;
uint uVar2;
uVar2 = *(uint *)(param_4 + 0xc);
uVar1 = 0;
if (uVar2 <= *(uint *)(param_4 + 0x10)) {
*(int *)(param_4 + 0xc) = uVar2 + 0x24;
uVar1 = uVar2;
}
if (uVar1 != 0)
{
// psyq macro setPolyG4
*(undefined *)(uVar1 + 3) = 8;
*(undefined *)(uVar1 + 7) = 0x38;
*(undefined *)(uVar1 + 4) = *param_2;
*(undefined *)(uVar1 + 5) = param_2[1];
*(undefined *)(uVar1 + 6) = param_2[2];
*(undefined *)(uVar1 + 0xc) = param_2[4];
*(undefined *)(uVar1 + 0xd) = param_2[5];
*(undefined *)(uVar1 + 0xe) = param_2[6];
*(undefined *)(uVar1 + 0x14) = param_2[8];
*(undefined *)(uVar1 + 0x15) = param_2[9];
*(undefined *)(uVar1 + 0x16) = param_2[10];
*(undefined *)(uVar1 + 0x1c) = param_2[0xc];
*(undefined *)(uVar1 + 0x1d) = param_2[0xd];
*(undefined *)(uVar1 + 0x1e) = param_2[0xe];
*(undefined2 *)(uVar1 + 8) = *param_1;
*(undefined2 *)(uVar1 + 10) = param_1[1];
*(undefined2 *)(uVar1 + 0x10) = param_1[2];
*(undefined2 *)(uVar1 + 0x12) = param_1[3];
*(undefined2 *)(uVar1 + 0x18) = param_1[4];
*(undefined2 *)(uVar1 + 0x1a) = param_1[5];
*(undefined2 *)(uVar1 + 0x20) = param_1[6];
*(undefined2 *)(uVar1 + 0x22) = param_1[7];
AddPrim(param_3);
}
return;
}
// AH_Map_LoadSave_Full
void FUN_800b0ce0
(short param_1,short param_2,int param_3,undefined4 param_4,ushort param_5,
uint param_6)
{
int iVar1;
int iVar2;
short *psVar3;
int iVar4;
short sVar5;
int iVar6;
short local_30 [8];
short local_20 [8];
// approximate trigonometry
iVar6 = *(int *)(&DAT_800845a0 + (param_6 & 0x3ff) * 4) >> 0x10;
sVar5 = (short)*(int *)(&DAT_800845a0 + (param_6 & 0x3ff) * 4);
if ((param_6 & 0x400) == 0) {
iVar1 = (int)sVar5;
iVar4 = iVar6;
if ((param_6 & 0x800) == 0) goto LAB_800b0d88;
iVar4 = -iVar6;
}
else {
iVar4 = (int)sVar5;
iVar1 = iVar6;
if ((param_6 & 0x800) == 0) {
iVar4 = -iVar4;
goto LAB_800b0d88;
}
}
iVar1 = -iVar1;
LAB_800b0d88:
iVar6 = 0;
do {
iVar2 = (iVar6 << 0x10) >> 0xe;
psVar3 = (short *)(iVar2 + param_3);
*(short *)((int)local_30 + iVar2) =
param_1 + (short)(((*psVar3 * iVar4 >> 0xc) + (psVar3[1] * iVar1 >> 0xc)) *
((((int)((uint)param_5 << 0x10) >> 0xd) / 5) * 0x10000 >> 0x10) >> 0xc) +
6;
iVar6 = iVar6 + 1;
*(short *)((int)local_30 + iVar2 + 2) =
param_2 + (short)(((psVar3[1] * iVar4 >> 0xc) - (*psVar3 * iVar1 >> 0xc)) *
(int)(short)param_5 >> 0xc) + 4;
} while (iVar6 * 0x10000 >> 0x10 < 4);
iVar6 = 0;
// draw 5 primitives (4 for outline, plus green middle)
do
{
// loop 4 times, 4 vertices
iVar1 = 0;
iVar4 = (iVar6 << 0x10) >> 0xe;
do {
iVar2 = (iVar1 << 0x10) >> 0xe;
*(short *)((int)local_20 + iVar2) =
*(short *)((int)local_30 + iVar2) + *(short *)((int)&DAT_800b4eac + iVar4);
iVar1 = iVar1 + 1;
*(short *)((int)local_20 + iVar2 + 2) =
*(short *)((int)local_30 + iVar2 + 2) + *(short *)((int)&DAT_800b4eae + iVar4);
} while (iVar1 * 0x10000 >> 0x10 < 4);
// AH_Map_LoadSave_Prim
FUN_800b0b98
(local_20,param_4,
// pointer to OT mem
*(undefined4 *)(PTR_DAT_8008d2ac + 0x147c),
// pointer to PrimMem struct
*(int *)(PTR_DAT_8008d2ac + 0x10) + 0x74);
param_4 = 0x800b5530;
iVar6 = iVar6 + 1;
} while (iVar6 * 0x10000 >> 0x10 < 5);
return;
}
// AH_Map_HubArrow
// can draw grey or flicker blue, used for drawing
// arrows to hubs, and for drawing player on the map
void FUN_800b0f18
(short param_1,short param_2,int param_3,undefined4 param_4,ushort param_5,
uint param_6)
{
int iVar1;
int iVar2;
short *psVar3;
int iVar4;
short sVar5;
int iVar6;
short local_30 [8];
short local_20 [8];
// approximate trigonometry
iVar6 = *(int *)(&DAT_800845a0 + (param_6 & 0x3ff) * 4) >> 0x10;
sVar5 = (short)*(int *)(&DAT_800845a0 + (param_6 & 0x3ff) * 4);
if ((param_6 & 0x400) == 0) {
iVar1 = (int)sVar5;
iVar4 = iVar6;
if ((param_6 & 0x800) == 0) goto LAB_800b0fc0;
iVar4 = -iVar6;
}
else {
iVar4 = (int)sVar5;
iVar1 = iVar6;
if ((param_6 & 0x800) == 0) {
iVar4 = -iVar4;
goto LAB_800b0fc0;
}
}
iVar1 = -iVar1;
LAB_800b0fc0:
// inner triangle
iVar6 = 0;
do {
iVar2 = (iVar6 << 0x10) >> 0xe;
psVar3 = (short *)(iVar2 + param_3);
// posX of each vertex
*(short *)((int)local_30 + iVar2) =
// posX + ...
param_1 + (short)(((*psVar3 * iVar4 >> 0xc) + (psVar3[1] * iVar1 >> 0xc)) *
((((int)((uint)param_5 << 0x10) >> 0xd) / 5) * 0x10000 >> 0x10) >> 0xc) +
6;
iVar6 = iVar6 + 1;
// posY of each vertex
*(short *)((int)local_30 + iVar2 + 2) =
// posY + ...
param_2 + (short)(((psVar3[1] * iVar4 >> 0xc) - (*psVar3 * iVar1 >> 0xc)) *
(int)(short)param_5 >> 0xc) + 4;
} while (iVar6 * 0x10000 >> 0x10 < 3);
// outer triangle
iVar6 = 0;
do {
iVar1 = 0;
iVar4 = (iVar6 << 0x10) >> 0xe;
do {
iVar2 = (iVar1 << 0x10) >> 0xe;
// posX outer = posX inner + [scale]
*(short *)((int)local_20 + iVar2) =
*(short *)((int)local_30 + iVar2) + *(short *)((int)&DAT_800b4ec0 + iVar4);
iVar1 = iVar1 + 1;
// posY outer = posY inner + [scale]
*(short *)((int)local_20 + iVar2 + 2) =
*(short *)((int)local_30 + iVar2 + 2) + *(short *)((int)&DAT_800b4ec2 + iVar4);
} while (iVar1 * 0x10000 >> 0x10 < 3);
// MENUBOX_DrawRwdTriangle
FUN_800453e8(local_20,param_4,
// pointer to OT mem
*(undefined4 *)(PTR_DAT_8008d2ac + 0x147c),
// pointer to PrimMem struct
*(int *)(PTR_DAT_8008d2ac + 0x10) + 0x74);
param_4 = 0x800b5540;
iVar6 = iVar6 + 1;
} while (iVar6 * 0x10000 >> 0x10 < 5);
return;
}
// AdvMap_HubArrowOutter
// only visible when adv doors are open
void FUN_800b1150
(undefined4 param_1,short param_2,int param_3,int param_4,uint param_5,short param_6)
{
bool bVar1;
short sVar2;
uint uVar3;
int iVar4;
uint uVar5;
int iVar6;
uint uVar7;
int iVar8;
int iVar9;
int iVar10;
int iVar11;
int iVar12;
int iVar13;
short sVar14;
undefined4 uVar15;
int iVar16;
iVar8 = (int)param_6;
param_3 = param_3 + *(short *)(&DAT_800b4fb0 + iVar8 * 4);
param_4 = param_4 + *(short *)(&DAT_800b4fb2 + iVar8 * 4);
uVar3 = *(uint *)(PTR_DAT_8008d2ac + 0x1cec);
if (iVar8 == 1) {
sVar14 = 0xff;
uVar15 = 0x40;
if ((uVar3 & 1) != 0) {
uVar15 = 0xe0;
}
iVar8 = 0x555;
uVar5 = param_5 >> 8 & 0xc;
param_3 = param_3 + *(short *)(&DAT_800b4fbc + uVar5);
param_4 = param_4 + *(short *)(&DAT_800b4fbe + uVar5);
}
else {
if ((iVar8 < 2) && (iVar8 == 0)) {
uVar15 = 0x40;
if ((uVar3 & 1) != 0) {
uVar15 = 0xe0;
}
sVar14 = (short)uVar15;
iVar8 = 0x200;
}
else {
uVar15 = 0x40;
if ((*(uint *)(PTR_DAT_8008d2ac + 0x1cec) & 1) != 0) {
uVar15 = 0xe0;
}
sVar14 = (short)uVar15;
iVar8 = 0x199;
param_5._0_2_ = (ushort)param_5 ^ 0x800;
}
}
iVar10 = 0;
do {
uVar5 = (~(uVar3 + (int)param_2 * 0xc) & 0x3f) + (2 - (int)(short)iVar10) * -6;
if (uVar5 < 0xc) {
iVar16 = (int)((uVar5 * 0x2aa + 0x1000) * 0x10000) >> 0x1a;
bVar1 = true;
uVar5 = 1;
iVar13 = 0;
if (iVar8 != -0xfff) {
iVar6 = 0;
iVar9 = 0;
do {
if (param_6 != 2) {
uVar5 = 0;
}
uVar7 = (int)(short)iVar13 + (int)(short)(ushort)param_5;
// approximate trigonometry
sVar2 = (short)*(int *)(&DAT_800845a0 + (uVar7 & 0x3ff) * 4);
iVar11 = *(int *)(&DAT_800845a0 + (uVar7 & 0x3ff) * 4) >> 0x10;
if ((uVar7 & 0x400) == 0) {
iVar12 = (int)sVar2;
if ((uVar7 & 0x800) != 0) {
iVar4 = -iVar11;
goto LAB_800b13b8;
}
}
else {
iVar4 = (int)sVar2;
iVar12 = iVar11;
if ((uVar7 & 0x800) == 0) {
iVar11 = -iVar4;
}
else {
LAB_800b13b8:
iVar12 = -iVar12;
iVar11 = iVar4;
}
}
iVar4 = (uVar5 & 1) + 0xc;
iVar11 = param_4 - (iVar16 * iVar11 >> iVar4);
iVar12 = param_3 + (((iVar16 << 3) / 5) * iVar12 >> iVar4);
if (!bVar1)
{
// CTR_Box_DrawWirePrims
FUN_80021500((int)(short)iVar9,(int)(short)iVar6,iVar12 * 0x10000 >> 0x10,
iVar11 * 0x10000 >> 0x10,(int)sVar14,uVar15,0xff,
// pointer to OT mem
*(undefined4 *)(PTR_DAT_8008d2ac + 0x147c),
// pointer to PrimMem struct
*(int *)(PTR_DAT_8008d2ac + 0x10) + 0x74);
}
bVar1 = false;
iVar13 = iVar13 + iVar8;
uVar5 = uVar5 + 1;
iVar6 = iVar11;
iVar9 = iVar12;
} while (iVar13 * 0x10000 >> 0x10 < iVar8 + 0xfff);
}
}
iVar10 = iVar10 + 1;
if (2 < iVar10 * 0x10000 >> 0x10) {
return;
}
} while( true );
}
// WARNING: Could not reconcile some variable overlaps
// AH_Map_HubItems
void FUN_800b14f4(undefined4 param_1,short *param_2)
{
short sVar1;
bool bVar2;
int iVar3;
uint uVar4;
int iVar5;
undefined4 uVar6;
short sVar7;
short sVar8;
short *psVar9;
short *psVar10;
int local_50;
undefined4 local_4c;
int local_48;
int local_40;
int local_3c;
int local_38;
int local_34;
int local_30;
int local_2c;
psVar10 = (short *)(&PTR_DAT_800b4ed4_800b4f9c)
[*(int *)(PTR_DAT_8008d2ac + 0x1a10) + -0x19];
if (*psVar10 != -1) {
psVar9 = psVar10 + 1;
do {
sVar8 = -1;
sVar8 = -1;
_sVar7 = 0xffffffff;
sVar7 = -1;
sVar7 = -1;
sVar1 = psVar9[2];
bVar2 = true;
if (sVar1 == -1) {
_sVar7 = 0;
// Level ID
// N Sanity Beach
if (*(int *)(PTR_DAT_8008d2ac + 0x1a10) == 0x1a)
{
// numKeys < 1
_sVar7 = (uint)(*(int *)(PTR_DAT_8008d2ac + 0x1e38) < 1);
}
LAB_800b17e8:
iVar5 = _sVar7 << 0x10;
sVar8 = sVar8;
sVar7 = (short)_sVar7;
LAB_800b17ec:
iVar5 = iVar5 >> 0x10;
}
else {
if (-1 < sVar1) {
sVar7 = sVar7;
if (sVar1 == 4) {
iVar3 = 0;
iVar5 = 0;
do {
uVar4 = (iVar5 >> 0x10) + 0x5e;
iVar3 = iVar3 + 1;
// 0x8fba4 is where the adventure profile (currently loaded) begins
if (((uint)(&DAT_8008fba4)[(int)uVar4 >> 5] >> (uVar4 & 0x1f) & 1) == 0) {
bVar2 = false;
break;
}
iVar5 = iVar3 * 0x10000;
} while (iVar3 * 0x10000 >> 0x10 < 4);
if (!bVar2) {
LAB_800b17e4:
sVar8 = 0;
goto LAB_800b17e8;
}
_sVar7 = DAT_8008fbb0 & 4;
}
else {
iVar5 = 0;
if (3 < sVar1) {
iVar5 = -0x10000;
sVar8 = sVar8;
if (sVar1 == 100) {
local_40 = (int)*psVar10 + -0x200;
local_3c = (int)*psVar9 + -0x100;
FUN_8004d8b4(param_1,&local_40,&local_3c);
// AH_Map_LoadSave_Full
FUN_800b0ce0
((int)(short)local_40,(int)(short)local_3c,&DAT_800b4fcc,
&DAT_800b4fdc,0x800,(int)psVar9[1]);
iVar5 = -0x10000;
}
goto LAB_800b17ec;
}
iVar3 = 0;
do {
iVar5 = iVar5 + 1;
// 0x8fba4 is where the adventure profile (currently loaded) begins
if (((uint)(&DAT_8008fba4)
[(int)((int)*(short *)(&DAT_800840f4 +
(iVar3 >> 0xf) +
// Level ID - 0x1a: warp room (1-4)
(*(int *)(PTR_DAT_8008d2ac + 0x1a10) + -0x1a) * 8) +
6U) >> 5] >>
((int)*(short *)(&DAT_800840f4 +
(iVar3 >> 0xf) +
// Level ID - 0x1a: warp room (1-4)
(*(int *)(PTR_DAT_8008d2ac + 0x1a10) + -0x1a) * 8) + 6U & 0x1f) &
1) == 0) {
bVar2 = false;
break;
}
iVar3 = iVar5 * 0x10000;
} while (iVar5 * 0x10000 >> 0x10 < 4);
if (!bVar2) goto LAB_800b17e4;
// 0x8fba4 is where the adventure profile (currently loaded) begins
_sVar7 = (uint)(&DAT_8008fba4)[(int)(*(int *)(PTR_DAT_8008d2ac + 0x1a10) + 0x44U) >> 5]
>> (*(int *)(PTR_DAT_8008d2ac + 0x1a10) + 0x44U & 0x1f) & 1;
}
sVar8 = 1;
iVar5 = -0x10000;
if (_sVar7 != 0) {
sVar8 = 2;
}
goto LAB_800b17ec;
}
if (sVar1 == -4) {
_sVar7 = (uint)(*(int *)(PTR_DAT_8008d2ac + 0x1e38) < 2);
goto LAB_800b17e8;
}
if (sVar1 < -3) {
if (sVar1 == -5) {
_sVar7 = (uint)(*(int *)(PTR_DAT_8008d2ac + 0x1e38) < 3);
goto LAB_800b17e8;
}
iVar5 = -1;
}
else {
if ((sVar1 == -3) || (sVar1 == -2)) {
_sVar7 = 0;
goto LAB_800b17e8;
}
iVar5 = -1;
}
}
if (-1 < iVar5) {
local_38 = (int)*psVar10 + -0x200;
local_34 = (int)*psVar9 + -0x100;
FUN_8004d8b4(param_1,&local_38,&local_34);
if ((iVar5 == 0) && (sRam800b5670 == 0))
{
// AH_Map_HubArrowOutter
FUN_800b1150
(param_1,(int)*param_2,local_38,local_34,
(int)((0x1000 - (uint)(ushort)psVar9[1]) * 0x10000) >> 0x10,1);
*param_2 = *param_2 + 1;
}
if ((*(uint *)(PTR_DAT_8008d2ac + 0x1cec) & 2) == 0) {
iVar5 = (int)sVar7 * 6;
}
else {
iVar5 = ((int)sVar7 * 2 + 1) * 3;
}
// AH_Map_HubArrow
FUN_800b0f18
((int)(short)local_38,(int)(short)local_34,&DAT_800b4fec,
iVar5 * 4 + -0x7ff4b008,0x800,(int)psVar9[1]);
}
if (-1 < sVar8) {
local_50 = (int)*psVar10;
local_4c = 0;
local_48 = (int)*psVar9;
if (sVar8 == 2) {
uVar6 = 3;
}
else {
uVar6 = 0x17;
if ((sVar8 == 1) && (uVar6 = 5, (*(uint *)(PTR_DAT_8008d2ac + 0x1cec) & 2) != 0)) {
uVar6 = 4;
}
}
if (sVar8 == 1) {
sRam800b5670 = sVar8;
local_30 = local_50;
local_2c = local_48;
// Get Icon Dimensions
FUN_8004d8b4(param_1,&local_30,&local_2c);
// AH_Map_HubArrowOutter
FUN_800b1150(param_1,(int)*param_2,local_30,local_2c,0,2);
*param_2 = *param_2 + 1;
}
// UI_Map_DrawRawIcon
FUN_8004dc44(param_1,&local_50,0x37,uVar6,0,0x1000);
}
psVar10 = psVar10 + 4;
psVar9 = psVar9 + 4;
} while (*psVar10 != -1);
}
return;
}
// AH_Map_Warppads
void FUN_800b1a18(undefined4 param_1,int param_2,short *param_3)
{
bool bVar1;
bool bVar2;
int iVar3;
int iVar4;
int iVar5;
int iVar6;
int iVar7;
int iVar8;
undefined4 local_30;
undefined4 local_2c;
iVar8 = 0;
iVar7 = 0x7fffffff;
// 0 - locked
// 1 - open for trophy
// 2 - unlocked all
// 3 - open for relic/token
// 4 - purple token or SlideCol/TurboTrack
if (param_2 != 0)
{
do {
bVar1 = false;
// thread -> instance
iVar6 = *(int *)(param_2 + 0x34);
bVar2 = false;
// thread->modelIndex
switch(*(undefined2 *)(param_2 + 0x44))
{
// grey, locked
case 0:
bVar2 = true;
iVar5 = 0x17;
break;
// trophy
case 1:
iVar5 = 5;
if ((*(uint *)(PTR_DAT_8008d2ac + 0x1cec) & 2) != 0) {
iVar5 = 4;
}
bVar1 = true;
break;
// red
case 2:
iVar5 = 3;
break;
// yellow
case 3:
iVar5 = 0xe;
break;
// rainbow
case 4:
iVar5 = (*(uint *)(PTR_DAT_8008d2ac + 0x1cec) >> 1 & 7) + 5;
break;
// black - unused
default:
bVar2 = true;
iVar5 = 0x15;
}
if (bVar1) {
local_30 = *(undefined4 *)(iVar6 + 0x44);
local_2c = *(undefined4 *)(iVar6 + 0x4c);
uRam800b5670 = 1;
// Get Icon Dimensions
FUN_8004d8b4(param_1,&local_30,&local_2c);
// AH_Map_HubArrowOutter
FUN_800b1150(param_1,(int)*param_3,local_30,local_2c,0,0);
*param_3 = *param_3 + 1;
}
// UI_Map_DrawRawIcon
FUN_8004dc44(param_1,iVar6 + 0x44,0x31,iVar5,0,0x1000);
if (
(!bVar2) &&
(
iVar5 = *(int *)(iVar6 + 0x44) -
*(int *)(*(int *)(*(int *)(PTR_DAT_8008d2ac + 0x24ec) + 0x1c) + 0x44),
iVar3 = *(int *)(iVar6 + 0x48) -
*(int *)(*(int *)(*(int *)(PTR_DAT_8008d2ac + 0x24ec) + 0x1c) + 0x48),
iVar4 = *(int *)(iVar6 + 0x4c) -
*(int *)(*(int *)(*(int *)(PTR_DAT_8008d2ac + 0x24ec) + 0x1c) + 0x4c),
// SquareRoot0
iVar5 = FUN_8006c618(iVar5 * iVar5 + iVar3 * iVar3 + iVar4 * iVar4), iVar5 < iVar7
)
)
{
// closest distance
iVar7 = iVar5;
// closest instance
iVar8 = iVar6;
}
// next thread
param_2 = *(int *)(param_2 + 0x10);
} while (param_2 != 0);
}
// if instance was found
if (iVar8 != 0)
{
// play warppad sound
FUN_8002e994(iVar7 << 1);
}
return;
}
// AH_Map_Main
// except instances, which are independent
void FUN_800b1c90(void)
{
int iVar1;
undefined *puVar2;
int iVar3;
undefined4 uVar4;
undefined2 local_20;
undefined2 local_1e [3];
// force disable speedometer
DAT_8008d000 = DAT_8008d000 & 0xfffffff7;
local_20 = 0;
uVar4 = *(undefined4 *)(PTR_DAT_8008d2ac + 0x24ec);
puVar2 = (&PTR_DAT_8008625c)[(uint)(byte)PTR_DAT_8008d2ac[0x1ca8] - 1];
iVar3 = 0;
iVar1 = FUN_80044094();
if (iVar1 == 0) {
FUN_80044088(1);
}
if (
// if Aku Hint is not unlocked
((DAT_8008fbb0 & 0x400000) == 0) &&
// TitleFlag_IsFullyOffScreen
(iVar1 = FUN_80043f28(), iVar1 != 0)
)
{
// Trigger Aku Hint:
// Welcome to Adventure Arena
FUN_80035e20(0,0);
}
// if there are zero players
// when does that happen?
if ((PTR_DAT_8008d2ac[0x1ca8] == '\0') &&
// if this is an AI, not a human
((*(uint *)(*(int *)(PTR_DAT_8008d2ac + 0x24ec) + 0x2c8) & 0x100000) != 0))
{
// force draw speedometer, not map, why?
DAT_8008d000 = 8;
}
// LEV -> ptrSpawn1 -> numPointers
if (**(int **)(*(int *)(PTR_DAT_8008d2ac + 0x160) + 0x134) != 0) {
iVar3 = (*(int **)(*(int *)(PTR_DAT_8008d2ac + 0x160) + 0x134))[1];
}
// if game is not paused
if ((*(uint *)PTR_DAT_8008d2ac & 0xf) == 0)
{
// Jump meter and landing boost
FUN_80051c64(uVar4);
}
// Check a HUD flag
if ((PTR_DAT_8008d2ac[0x1d31] & 0x10) == 0) {
local_1e[0] = 0;
uRam800b5670 = 0;
// UI_Map_DrawDrivers
FUN_8004dd5c(iVar3,*(undefined4 *)(PTR_DAT_8008d2ac + 0x1b2c),&local_20);
// AH_Map_Warppads
FUN_800b1a18(iVar3,*(undefined4 *)(PTR_DAT_8008d2ac + 0x1b90),local_1e);
// AH_Map_HubItems
FUN_800b14f4(iVar3,local_1e);
// UI_Map_DrawMap
FUN_8004d614(*(undefined4 *)(PTR_DAT_8008d2ac + 0x1ef8),
*(undefined4 *)(PTR_DAT_8008d2ac + 0x1efc),500,0xc3,
// pointer to PrimMem struct
*(int *)(PTR_DAT_8008d2ac + 0x10) + 0x74,
// pointer to OT mem
*(undefined4 *)(PTR_DAT_8008d2ac + 0x147c)
,1);
// Draw powerslide bar
FUN_80052250((int)*(short *)(puVar2 + 0x40),(int)*(short *)(puVar2 + 0x42),uVar4);
}
// UI_DrawNumRelic
FUN_80050f18((int)(((uint)*(ushort *)(puVar2 + 0x70) + 0x10) * 0x10000) >> 0x10,
(int)(((uint)*(ushort *)(puVar2 + 0x72) - 10) * 0x10000) >> 0x10,uVar4);
// UI_DrawNumKey
FUN_80050fc4((int)(((uint)*(ushort *)(puVar2 + 0x78) + 0x10) * 0x10000) >> 0x10,
(int)(((uint)*(ushort *)(puVar2 + 0x7a) - 10) * 0x10000) >> 0x10,uVar4);
// UI_DrawNumTrophy
FUN_80051070((int)(((uint)*(ushort *)(puVar2 + 0x80) + 0x10) * 0x10000) >> 0x10,
(int)(((uint)*(ushort *)(puVar2 + 0x82) - 10) * 0x10000) >> 0x10,uVar4);
return;
}
// AH_Pause_Destroy (and destroy thread)
void FUN_800b1ef8(void)
{
undefined4 *puVar1;
int *piVar2;
int iVar3;
int iVar4;
// if PAUSE object exists
if (DAT_800b5578 != 0)
{
iVar3 = DAT_800b5578 + 0xd0;
iVar4 = 0;
// loop through 14 instances, destroy them
do {
puVar1 = (undefined4 *)(iVar3 + 0xc);
iVar3 = iVar3 + -0x10;
// INSTANCE_Death
FUN_80030aa8(*puVar1);
iVar4 = iVar4 + 1;
} while (iVar4 * 0x10000 >> 0x10 < 0xe);
// thread from object
piVar2 = (int *)(DAT_800b5578 + 0xe0);
// erase pointer to PAUSE object
DAT_800b5578 = 0;
// This AdvPause thread is now dead
*(uint *)(*piVar2 + 0x1c) = *(uint *)(*piVar2 + 0x1c) | 0x800;
}
return;
}
// AH_Pause_Draw
// Draw everything except menuBox, and instances,
// which are able to have themselves drawn independently
void FUN_800b1f78(int param_1,ushort param_2)
{
ushort uVar1;
short sVar2;
undefined2 uVar3;
undefined4 uVar4;
uint uVar5;
uint uVar6;
int iVar7;
ushort *puVar8;
int iVar9;
int iVar10;
int iVar11;
undefined **ppuVar12;
int *piVar13;
int *piVar14;
short *psVar15;
short *psVar16;
ushort uVar17;
short local_e0 [4];
short local_d8;
undefined2 local_d6;
undefined2 local_d4;
undefined auStack208 [104];
ushort local_68;
short *local_60;
ushort local_58;
short local_50;
ushort local_48;
ushort local_40;
ushort local_38;
int local_30;
int local_2c;
iVar7 = (param_1 << 0x10) >> 0xd;
local_60 = (short *)(&DAT_800b5028 + iVar7);
local_58 = *(ushort *)(&DAT_800b502a + iVar7);
if (*(short *)(&DAT_800b502a + iVar7) < 0)
{
// MetaDataLEV
local_58 = (&DAT_80083a88)[(int)*local_60 * 0xc];
}
iVar7 = (int)((uint)local_58 << 0x10) >> 0xe;
local_68 = param_2;
// draw string
FUN_80022878(
*(undefined4 *)(iVar7 + DAT_8008d878),
(int)(short)(param_2 + 0x100),0xf,1,0xffff8000);
iVar11 = 0;
if ((DAT_8008d970 & 4) == 0) {
iVar11 = 3;
}
// DecalFont_GetLineWidth
iVar7 = FUN_800224d0(*(undefined4 *)(iVar7 + DAT_8008d878),1);
iVar9 = ((iVar7 << 0x10) >> 0x10) - ((iVar7 << 0x10) >> 0x1f) >> 1;
// Color data
ppuVar12 = &PTR_DAT_80081d70 + iVar11;
// Draw arrow pointing Left
FUN_80023190(
// largeFont
*(undefined4 *)(*(int *)(PTR_DAT_8008d2ac + 0x2124) + 0xf4),
((short)param_2 - iVar9) + 0xec,0x16,
// pointer to PrimMem struct
*(int *)(PTR_DAT_8008d2ac + 0x10) + 0x74,
// pointer to OT mem
*(undefined4 *)(PTR_DAT_8008d2ac + 0x147c),
// color data
*(undefined4 *)*ppuVar12,
*(undefined4 *)(*ppuVar12 + 4),
*(undefined4 *)(*ppuVar12 + 8),
*(undefined4 *)(*ppuVar12 + 0xc),
0,0x1000,0x800);
// loop counter
iVar7 = 0;
// Draw arrow pointing Right
FUN_80023190(
// largeFont
*(undefined4 *)(*(int *)(PTR_DAT_8008d2ac + 0x2124) + 0xf4),
iVar9 + (short)param_2 + 0x112,0x16,
// pointer to PrimMem struct
*(int *)(PTR_DAT_8008d2ac + 0x10) + 0x74,
// pointer to OT mem
*(undefined4 *)(PTR_DAT_8008d2ac + 0x147c),
// color data
*(undefined4 *)*ppuVar12,
*(undefined4 *)(*ppuVar12 + 4),
*(undefined4 *)(*ppuVar12 + 8),
*(undefined4 *)(*ppuVar12 + 0xc),
0,0x1000,0);
puVar8 = (ushort *)(DAT_800b5578 + 1);
psVar16 = DAT_800b5578;
// loop through 14 instances, reset flags
do
{
// increment loop counter
iVar7 = iVar7 + 1;
// wipe flags
// 2-byte for model and color
*psVar16 = -1;
psVar16 = psVar16 + 8;
// wipe flags
// 2-byte for visible or black
*puVar8 = *puVar8 & 0xfffe;
puVar8 = puVar8 + 8;
} while (iVar7 * 0x10000 >> 0x10 < 0xe);
sVar2 = local_60[2];
if (sVar2 == 1)
{
// loop counter
iVar11 = 0;
iVar7 = 0;
// for iVar11 = 0; iVar11 < 5; iVar11++
do {
*(undefined2 *)((int)local_e0 + (iVar7 >> 0xf)) = 0;
// increment loop counter
iVar11 = iVar11 + 1;
iVar7 = iVar11 * 0x10000;
} while (iVar11 * 0x10000 >> 0x10 < 5);
// loop counter
iVar11 = 0;
iVar7 = 0;
// for iVar11 = 0; iVar11 < 0x10; iVar11++
do {
uVar6 = (iVar7 >> 0x10) + 0x4c;
// 0x8fba4 is where the adventure profile (currently loaded) begins
if (((uint)(&DAT_8008fba4)[(int)uVar6 >> 5] >> (uVar6 & 0x1f) & 1) != 0) {
local_e0[(short)(&DAT_80083a92)[(iVar7 >> 0x10) * 0xc]] =
local_e0[(short)(&DAT_80083a92)[(iVar7 >> 0x10) * 0xc]] + 1;
}
// increment loop counter
iVar11 = iVar11 + 1;
iVar7 = iVar11 * 0x10000;
} while (iVar11 * 0x10000 >> 0x10 < 0x10);
// loop counter
iVar11 = 0;
iVar7 = 0;
// for iVar11 = 0; iVar11 < 4; iVar11++
do {
uVar6 = (iVar7 >> 0x10) + 0x6f;
// 0x8fba4 is where the adventure profile (currently loaded) begins
if (((uint)(&DAT_8008fba4)[(int)uVar6 >> 5] >> (uVar6 & 0x1f) & 1) != 0) {
local_d8 = local_d8 + 1;
}
// increment loop counter
iVar11 = iVar11 + 1;
iVar7 = iVar11 * 0x10000;
} while (iVar11 * 0x10000 >> 0x10 < 4);
// loop counter
uVar6 = 0;
piVar14 = (int *)(DAT_800b5578 + 6);
iVar7 = 0;
psVar16 = DAT_800b5578;
// loop through 5 CTR Tokens
// for uVar6 = 0; uVar6 < 5; uVar6++
do {
*psVar16 = (short)uVar6 + 9;
psVar16 = psVar16 + 8;
iVar9 = *piVar14;
iVar11 = (uint)local_68 + ((iVar7 >> 0x10) + -2) * 0x3c + 0xf0;
*(ushort *)((int)piVar14 + -10) = *(ushort *)((int)piVar14 + -10) | 1;
iVar10 = (uVar6 & 1) * 0x28;
// convert x
uVar4 = FUN_80047fb8(iVar11 * 0x10000 >> 0x10,0x100);
*(undefined4 *)(iVar9 + 0x44) = uVar4;
// convert y
uVar4 = FUN_80047fd8(iVar10 + 0x41,0x100);
*(undefined4 *)(iVar9 + 0x48) = uVar4;
piVar14 = piVar14 + 4;
// LoadSave_PrintInteger
FUN_80047f20(
(int)local_e0[iVar7 >> 0x10],
(iVar11 + 0x36) * 0x10000 >> 0x10,
iVar10 + 0x3a,0,0);
// draw a string "X"
FUN_80022878(&DAT_800abac0,(iVar11 + 0x24) * 0x10000 >> 0x10,iVar10 + 0x3e,2,0);
// increment loop counter
uVar6 = uVar6 + 1;
iVar7 = uVar6 * 0x10000;
} while ((int)(uVar6 * 0x10000) >> 0x10 < 5);
}
else {
if (sVar2 < 2) {
if (sVar2 == 0) {
local_48 = 0xffff;
local_40 = 0x15e;
local_38 = 0x50;
local_50 = *local_60 + -0x19;
local_30 = (int)local_50;
iVar7 = 0;
if (local_30 == 0) {
local_40 = 0x16d;
iVar7 = 4;
local_38 = 0x6e;
}
uVar17 = 0;
piVar14 = (int *)(DAT_800b5578 + -2);
local_2c = (int)(short)local_68;
iVar11 = 0;
psVar16 = DAT_800b5578;
do {
iVar11 = iVar11 >> 0x10;
uVar1 = local_48;
if (((int)(short)(&DAT_80083a80)[iVar11 * 0xc] == local_30) &&
(uVar1 = uVar17, iVar11 < 0x12)) {
if (local_30 != 0) {
*psVar16 = 0xe;
// 0x8fba4 is where the adventure profile (currently loaded) begins
if (((uint)(&DAT_8008fba4)[(int)(iVar11 + 6U) >> 5] >> (iVar11 + 6U & 0x1f) & 1) != 0)
{
*(ushort *)((int)piVar14 + 6) = *(ushort *)((int)piVar14 + 6) | 1;
}
piVar14 = piVar14 + 4;
psVar16 = psVar16 + 8;
}
iVar11 = (int)(short)uVar17;
// 0x8fba4 is where the adventure profile (currently loaded) begins
if (((uint)(&DAT_8008fba4)[(int)(iVar11 + 0x3aU) >> 5] >> (iVar11 + 0x3aU & 0x1f) & 1)
== 0) {
// 0x8fba4 is where the adventure profile (currently loaded) begins
if (((uint)(&DAT_8008fba4)[(int)(iVar11 + 0x28U) >> 5] >> (iVar11 + 0x28U & 0x1f) & 1)
== 0) {
*psVar16 = 6;
// 0x8fba4 is where the adventure profile (currently loaded) begins
if (((uint)(&DAT_8008fba4)[(int)(iVar11 + 0x16U) >> 5] >> (iVar11 + 0x16U & 0x1f) &
1) != 0) {
*(ushort *)((int)piVar14 + 6) = *(ushort *)((int)piVar14 + 6) | 1;
}
}
else {
*(ushort *)((int)piVar14 + 6) = *(ushort *)((int)piVar14 + 6) | 1;
*psVar16 = 7;
}
}
else {
*(ushort *)((int)piVar14 + 6) = *(ushort *)((int)piVar14 + 6) | 1;
*psVar16 = 8;
}
piVar13 = piVar14 + 4;
psVar15 = psVar16 + 8;
sVar2 = (short)iVar7;
if (local_30 == 0) {
iVar11 = *piVar13;
// convert x
uVar4 = FUN_80047fb8((uint)local_40 + local_2c + 0x1e,0x100);
*(undefined4 *)(iVar11 + 0x44) = uVar4;
// convert y
uVar4 = FUN_80047fd8((int)sVar2 + 0x2f,0x100);
*(undefined4 *)(iVar11 + 0x48) = uVar4;
}
else {
uVar6 = (int)(short)uVar17 + 0x4c;
*psVar15 = (&DAT_80083a92)[(int)(short)uVar17 * 0xc] + 9;
// 0x8fba4 is where the adventure profile (currently loaded) begins
if (((uint)(&DAT_8008fba4)[(int)uVar6 >> 5] >> (uVar6 & 0x1f) & 1) != 0) {
*(ushort *)((int)piVar14 + 0x16) = *(ushort *)((int)piVar14 + 0x16) | 1;
}
piVar13 = piVar14 + 8;
psVar15 = psVar16 + 0x10;
iVar11 = 0;
iVar9 = (uint)local_40 + local_2c;
do {
iVar10 = *(int *)(psVar15 + (int)(short)iVar11 * 8 + -0x12);
// convert x
uVar4 = FUN_80047fb8(iVar9 + (int)(short)iVar11 * 0x1e,0x100);
*(undefined4 *)(iVar10 + 0x44) = uVar4;
// convert y
uVar4 = FUN_80047fd8((int)sVar2 + 0x2f,0x100);
iVar11 = iVar11 + 1;
*(undefined4 *)(iVar10 + 0x48) = uVar4;
} while (iVar11 * 0x10000 >> 0x10 < 3);
}
iVar7 = iVar7 + 0x10;
// draw string, MetaDataLEV
FUN_80022878(*(undefined4 *)
((int)(short)(&DAT_80083a88)[(int)(short)uVar17 * 0xc] * 4 + DAT_8008d878)
,(int)(((uint)local_68 + (uint)local_38) * 0x10000) >> 0x10,
(int)(short)(sVar2 + 0x26),1,0);
piVar14 = piVar13;
psVar16 = psVar15;
uVar1 = local_48;
}
local_48 = uVar1;
uVar17 = uVar17 + 1;
iVar11 = (uint)uVar17 << 0x10;
} while ((short)uVar17 < 0x41);
// draw string, MetaDataCharacters
FUN_80022878(*(undefined4 *)
((int)*(short *)(&DAT_80086d88 + (int)local_60[3] * 0x10) * 4 + DAT_8008d878),
(int)(((uint)local_68 + (uint)local_38) * 0x10000) >> 0x10,
(iVar7 + 0x26) * 0x10000 >> 0x10,1,4);
if ((int)local_50 == 0)
{
// silver
iVar11 = 0x15;
// 0x8fba4 is where the adventure profile (currently loaded) begins,
// 80084098 is BeatBossPrize, index is hubID, boss on hub[0] is oxide.
// "if oxide is beaten"
if (((uint)(&DAT_8008fba4)[(int)((uint)(ushort)&DAT_80084098[0] << 0x10) >> 0x15] >>
(&DAT_80084098[0] & 0x1fU) & 1) != 0)
{
// grey
iVar11 = 1;
}
// Color data
ppuVar12 = &PTR_DAT_80081d70 + iVar11;
// DecalHUD_DrawPolyGT4
FUN_80023054(*(undefined4 *)(*(int *)(PTR_DAT_8008d2ac + 0x2128) + 0xf0),
(uint)local_40 + (int)(short)local_68 + 0x18,(int)(short)iVar7 + 0x2a,
// pointer to PrimMem struct
*(int *)(PTR_DAT_8008d2ac + 0x10) + 0x74,
// pointer to OT mem
*(undefined4 *)(PTR_DAT_8008d2ac + 0x147c),
// DecalHUD_DrawPolyGT4
*(undefined4 *)*ppuVar12,
*(undefined4 *)(*ppuVar12 + 4),
*(undefined4 *)(*ppuVar12 + 8),
*(undefined4 *)(*ppuVar12 + 0xc),
0,0x1000);
}
else {
*psVar16 = 5;
// 0x8fba4 is where the adventure profile (currently loaded) begins
if (((uint)(&DAT_8008fba4)
[(int)((uint)(ushort)u_b___a_80084098[(int)local_50] << 0x10) >> 0x15] >>
(u_b___a_80084098[(int)local_50] & 0x1fU) & 1) != 0) {
psVar16[1] = psVar16[1] | 1;
}
iVar11 = *(int *)(psVar16 + 6);
// convert x
uVar4 = FUN_80047fb8((uint)local_40 + (int)(short)local_68 + 0x1e,0x100);
psVar16 = psVar16 + 8;
*(undefined4 *)(iVar11 + 0x44) = uVar4;
// convert y
uVar4 = FUN_80047fd8((int)(short)iVar7 + 0x2f,0x100);
*(undefined4 *)(iVar11 + 0x48) = uVar4;
}
iVar11 = (int)(short)local_48;
if (-1 < iVar11) {
// draw string, MetaDataLEV
FUN_80022878(*(undefined4 *)((int)(short)(&DAT_80083a88)[iVar11 * 0xc] * 4 + DAT_8008d878)
,(int)(((uint)local_68 + (uint)local_38) * 0x10000) >> 0x10,
(iVar7 + 0x36) * 0x10000 >> 0x10,1,1);
*psVar16 = (&DAT_80083a92)[iVar11 * 0xc] + 9;
// 0x8fba4 is where the adventure profile (currently loaded) begins
if (((uint)(&DAT_8008fba4)[(int)((int)local_50 + 0x6eU) >> 5] >>
((int)local_50 + 0x6eU & 0x1f) & 1) != 0) {
psVar16[1] = psVar16[1] | 1;
}
iVar11 = *(int *)(psVar16 + 6);
// convert x
uVar4 = FUN_80047fb8((uint)local_40 + (int)(short)local_68 + 0x1e,0x100);
psVar16 = psVar16 + 8;
*(undefined4 *)(iVar11 + 0x44) = uVar4;
// convert y
uVar4 = FUN_80047fd8(((iVar7 + 0x10) * 0x10000 >> 0x10) + 0x2f,0x100);
*(undefined4 *)(iVar11 + 0x48) = uVar4;
}
if (local_50 == 0) {
uVar6 = 0;
piVar14 = (int *)(psVar16 + 6);
iVar7 = (int)(short)local_68;
do {
sVar2 = (short)uVar6;
uVar5 = (int)sVar2 + 0x6a;
*psVar16 = sVar2;
// 0x8fba4 is where the adventure profile (currently loaded) begins
if (((uint)(&DAT_8008fba4)[(int)uVar5 >> 5] >> (uVar5 & 0x1f) & 1) != 0) {
*(ushort *)((int)piVar14 + -10) = *(ushort *)((int)piVar14 + -10) | 1;
}
iVar11 = *piVar14;
// convert x
uVar4 = FUN_80047fb8(iVar7 + ((int)sVar2 + -2) * 0x3c + 0x100,0x100);
piVar14 = piVar14 + 4;
psVar16 = psVar16 + 8;
*(undefined4 *)(iVar11 + 0x44) = uVar4;
// convert y
uVar4 = FUN_80047fd8((uVar6 & 1) << 4 | 0x6a,0x100);
uVar6 = uVar6 + 1;
*(undefined4 *)(iVar11 + 0x48) = uVar4;
} while ((int)(uVar6 * 0x10000) >> 0x10 < 5);
}
}
}
else
{
if (sVar2 == 2)
{
// loop counter
iVar11 = 0;
iVar7 = 0;
// iVar11 = 0; iVar11 < 3; iVar11++
do {
*(undefined2 *)((int)local_e0 + (iVar7 >> 0xf)) = 0;
// increment loop counter
iVar11 = iVar11 + 1;
iVar7 = iVar11 * 0x10000;
} while (iVar11 * 0x10000 >> 0x10 < 3);
// loop counter
iVar11 = 0;
iVar7 = 0;
// iVar11 = 0; iVar11 < 18; iVar11++
do {
iVar7 = iVar7 >> 0x10;
// 0x8fba4 is where the adventure profile (currently loaded) begins
if (((uint)(&DAT_8008fba4)[(int)(iVar7 + 0x3aU) >> 5] >> (iVar7 + 0x3aU & 0x1f) & 1) == 0)
{
// 0x8fba4 is where the adventure profile (currently loaded) begins
if (((uint)(&DAT_8008fba4)[(int)(iVar7 + 0x28U) >> 5] >> (iVar7 + 0x28U & 0x1f) & 1) ==
0) {
// 0x8fba4 is where the adventure profile (currently loaded) begins
if (((uint)(&DAT_8008fba4)[(int)(iVar7 + 0x16U) >> 5] >> (iVar7 + 0x16U & 0x1f) & 1)
!= 0) {
local_e0[0] = local_e0[0] + 1;
}
}
else {
local_e0[1] = local_e0[1] + 1;
}
}
else {
local_e0[2] = local_e0[2] + 1;
}
// increment loop counter
iVar11 = iVar11 + 1;
iVar7 = iVar11 * 0x10000;
} while (iVar11 * 0x10000 >> 0x10 < 0x12);
// loop counter
uVar17 = 0;
piVar14 = (int *)(DAT_800b5578 + 6);
iVar7 = 0;
psVar16 = DAT_800b5578;
// for uVar17 = 0; uVar17 < 3; uVar17++
do {
*psVar16 = uVar17 + 6;
psVar16 = psVar16 + 8;
iVar9 = *piVar14;
iVar11 = (uint)local_68 + ((iVar7 >> 0x10) + -1) * 0x5a + 0xf6;
*(ushort *)((int)piVar14 + -10) = *(ushort *)((int)piVar14 + -10) | 1;
// convert x
uVar4 = FUN_80047fb8(iVar11 * 0x10000 >> 0x10,0x100);
*(undefined4 *)(iVar9 + 0x44) = uVar4;
// convert y
uVar4 = FUN_80047fd8(0x49,0x100);
*(undefined4 *)(iVar9 + 0x48) = uVar4;
piVar14 = piVar14 + 4;
FUN_80047f20((int)local_e0[iVar7 >> 0x10],(iVar11 + 0x19) * 0x10000 >> 0x10,0x49,0,0);
// draw string "X"
FUN_80022878(&DAT_800abac0,(iVar11 + 10) * 0x10000 >> 0x10,0x4e,2,0);
// increment loop counter
uVar17 = uVar17 + 1;
iVar7 = (uint)uVar17 << 0x10;
} while ((short)uVar17 < 3);
// DAT_8008d878 + 0x310
// "TOTAL"
sprintf(auStack208,s__s__d_800abac4,*(undefined4 *)(DAT_8008d878 + 0x310),
(int)local_e0[0] + (int)local_e0[1] + (int)local_e0[2]);
// draw the string
FUN_80022878(auStack208,(int)(((uint)local_68 + 0x100) * 0x10000) >> 0x10,0x6e,1,0xffff8000)
;
}
}
}
// DecalFont_GetLineWidth
iVar7 = FUN_800224d0(*(undefined4 *)(((int)((uint)local_58 << 0x10) >> 0xe) + DAT_8008d878),1);
iVar11 = iVar7 + 0x14;
if ((short)iVar7 < 0x20b) {
iVar11 = 0x21e;
}
iVar7 = 0;
sVar2 = (short)(((iVar11 << 0x10) >> 0x10) - ((iVar11 << 0x10) >> 0x1f) >> 1);
local_e0[0] = 0x10a - sVar2;
local_e0[1] = 0x20;
local_e0[2] = (short)iVar11 + -0x14;
local_e0[3] = 2;
// MENUBOX_DrawOuterRect_Edge (transparent)
FUN_80044f90(local_e0,&DAT_8008d438,0x20,*(undefined4 *)(*(int *)(PTR_DAT_8008d2ac + 0x10) + 0xa0)
);
local_e0[0] = 0x100 - sVar2;
local_e0[1] = 10;
local_e0[3] = 0x82;
local_e0[2] = (short)iVar11;
// Draw 2D Menu rectangle background
FUN_800457b0(local_e0,4,*(int *)(*(int *)(PTR_DAT_8008d2ac + 0x10) + 0xa0) + 0xc);
psVar15 = DAT_800b5578 + 3;
psVar16 = DAT_800b5578;
// loop through 14 instances,
// update render variables
do {
iVar11 = *(int *)(psVar15 + 3);
// if flags are 0xffff
if ((int)*psVar16 < 0)
{
// make invisible
*(uint *)(iVar11 + 0x28) = *(uint *)(iVar11 + 0x28) | 0x80;
}
// if model and color are valid
else
{
iVar9 = (int)*psVar16 * 0x14;
// make visible
uVar6 = *(uint *)(iVar11 + 0x28) & 0xfff8ff7f;
*(uint *)(iVar11 + 0x28) = uVar6;
*(uint *)(iVar11 + 0x28) = uVar6 | *(uint *)(&DAT_800b5068 + iVar9);
// if flag shows it should be drawn black
if ((psVar15[-2] & 1U) == 0)
{
// set color to black
*(undefined4 *)(iVar11 + 0x24) = 0;
// scale[w]
*(undefined2 *)(iVar11 + 0x22) = 0x1000;
// make visible
*(uint *)(iVar11 + 0x28) = *(uint *)(iVar11 + 0x28) & 0xfff8ff7f;
}
// if flag shows visible with color
else
{
// scale[w]
*(undefined2 *)(iVar11 + 0x22) = 0;
// set color of instance
*(uint *)(iVar11 + 0x24) =
(uint)(byte)(&DAT_800b5064)[iVar9] << 0x14 |
(uint)(byte)(&DAT_800b5065)[iVar9] << 0xc |
(uint)(byte)(&DAT_800b5066)[iVar9] << 4;
}
if (local_60[2] == 1)
{
uVar3 = 0x1000;
}
else {
if (local_60[2] == 0) {
uVar3 = *(undefined2 *)(&DAT_800b5062 + iVar9);
}
else {
uVar3 = (undefined2)((int)*(short *)(&DAT_800b5062 + iVar9) << 2);
}
}
// set scale
*(undefined2 *)(iVar11 + 0x20) = uVar3;
*(undefined2 *)(iVar11 + 0x1e) = uVar3;
*(undefined2 *)(iVar11 + 0x1c) = uVar3;
// set model
*(undefined4 *)(iVar11 + 0x18) =
*(undefined4 *)
(PTR_DAT_8008d2ac + (int)*(short *)(&DAT_800b5060 + iVar9) * 4 + 0x2160);
// convert 3 rotation shorts into rotation matrix
FUN_8006c2a4(iVar11 + 0x30,psVar16 + 2);
// if specular lighting
if ((*(uint *)(iVar11 + 0x28) & 0x70000) == 0x20000) {
local_d8 = *(short *)(&DAT_800b506c + iVar9);
local_d6 = *(undefined2 *)(&DAT_800b506e + iVar9);
local_d4 = *(undefined2 *)(&DAT_800b5070 + iVar9);
// Vector_SpecLightSpin2D
FUN_800572d0(iVar11,psVar16 + 2,&local_d8);
}
// if no spec light,
// which means vertex colors are used
else
{
// remove instance color
*(undefined4 *)(iVar11 + 0x24) = 0;
}
}
// loop index
iVar7 = iVar7 + 1;
psVar16 = psVar16 + 8;
// rotation of each item, spin rate 0x40 per frame
*psVar15 = (short)*(undefined4 *)(*(int *)(psVar15 + 3) + 0x44) * 0x10 +
(short)*(undefined4 *)(*(int *)(psVar15 + 3) + 0x48) * 0x20 + DAT_8008d970 * 0x40;
psVar15 = psVar15 + 8;
} while (iVar7 * 0x10000 >> 0x10 < 0xe);
return;
}
// AH_Pause_Update
void FUN_800b3144(void)
{
short sVar1;
undefined *puVar2;
undefined *puVar3;
undefined4 uVar4;
int iVar5;
undefined2 *puVar6;
int iVar7;
int iVar8;
undefined2 *puVar9;
int iVar10;
short sVar11;
// if there is no PAUSE object
if (DAT_800b5578 == (undefined2 *)0x0)
{
iVar10 = 0;
DAT_800b554e = 0;
// Level ID for Adventure Map (0 - 5) gemstone is 0
DAT_800b5552 = *(short *)(PTR_DAT_8008d2ac + 0x1a10) + -0x19;
// set pause page to the hub the driver is on
*(short *)(PTR_DAT_8008d2ac + 0x1d3a) = DAT_800b5552;
// THREAD_BirthWithObject
// 0 = size
// 0 = no relation to param4
// 0x300 = SmallStackPool
// 0xd = "other" thread bucket
uVar4 = FUN_8004205c(0x30d,0,s_PAUSE_800abacc,0);
puVar6 = &DAT_800b557c;
puVar9 = &DAT_800b5580;
// save pointer to PAUSE object
DAT_800b5578 = &DAT_800b557c;
// copy the pointer
DAT_800b565c = uVar4;
// create 14 instances,
// maximum amount of instances
// per page of adv pause screen
do
{
// INSTANCE_Birth3D -- ptrModel, name, thread
iVar5 = FUN_8003086c(*(undefined4 *)(PTR_DAT_8008d2ac + 0x22dc),s_pause_800abad4,uVar4);
*(int *)(puVar9 + 4) = iVar5;
puVar2 = PTR_DAT_8008d2ac;
// instance flags:
// make invisible (0x80)
// creditghost (0x400)
// specular light (0x20000)
*(uint *)(iVar5 + 0x28) = *(uint *)(iVar5 + 0x28) | 0x20480;
*(undefined **)(iVar5 + 0x74) = puVar2 + 5000;
puVar3 = PTR_DAT_8008d2ac;
iVar8 = 1;
// if more than 1 screen
if (1 < (byte)puVar2[0x1ca8]) {
iVar7 = 0x10000;
do {
iVar8 = iVar8 + 1;
*(undefined4 *)(iVar5 + (iVar7 >> 0x10) * 0x88 + 0x74) = 0;
iVar7 = iVar8 * 0x10000;
} while (iVar8 * 0x10000 >> 0x10 < (int)(uint)(byte)puVar3[0x1ca8]);
}
iVar10 = iVar10 + 1;
puVar9[2] = 0;
puVar9[1] = 0;
// wipe flags (0 for black)
// 2-byte for visible or black
*puVar9 = 0;
puVar9 = puVar9 + 8;
// wipe flags (0xffff for null)
// 2-byte for model and color
*puVar6 = 0xffff;
puVar6 = puVar6 + 8;
// set rotation to identity matrix
*(undefined4 *)(iVar5 + 0x30) = 0x1000;
*(undefined4 *)(iVar5 + 0x34) = 0;
*(undefined4 *)(iVar5 + 0x38) = 0x1000;
*(undefined4 *)(iVar5 + 0x3c) = 0;
*(undefined2 *)(iVar5 + 0x40) = 0x1000;
*(undefined4 *)(iVar5 + 0x4c) = 0x100;
} while (iVar10 * 0x10000 >> 0x10 < 0xe);
}
puVar2 = PTR_DAT_8008d2ac;
// If you press Left or Right
if ((DAT_8009a990 & 0xc) != 0) {
// If you dont press Left
if ((DAT_8009a990 & 4) == 0) {
// If you dont press Right
if ((DAT_8009a990 & 8) == 0)
{
// How is that possible?
goto LAB_800b3354;
}
// If you get to this point, it
// means you must have pressed Right
// Move to the right in adventure pause
sVar1 = *(short *)(PTR_DAT_8008d2ac + 0x1d3a);
DAT_800b554c = 1;
*(ushort *)(PTR_DAT_8008d2ac + 0x1d3a) = sVar1 + 1U;
// If you go past 6th page (relics)
if (6 < (ushort)(sVar1 + 1U))
{
// Go back to first page (gems)
*(undefined2 *)(puVar2 + 0x1d3a) = 0;
}
}
// If you press Left
else
{
// Move to the left in adventure pause
sVar1 = *(short *)(PTR_DAT_8008d2ac + 0x1d3a);
DAT_800b554c = -1;
*(ushort *)(PTR_DAT_8008d2ac + 0x1d3a) = sVar1 - 1U;
// if you go before the first page (gems)
if ((int)((uint)(ushort)(sVar1 - 1U) << 0x10) < 0)
{
// go to last page (relics)
*(undefined2 *)(puVar2 + 0x1d3a) = 6;
}
}
// Play sound
FUN_80028468(0,1);
}
LAB_800b3354:
sVar1 = DAT_800b554e + -1;
if ((DAT_800b554e < 1) &&
(sVar1 = DAT_800b554e, *(short *)(PTR_DAT_8008d2ac + 0x1d3a) != DAT_800b5552))
{
DAT_800b5550 = DAT_800b5552;
DAT_800b554e = 8;
DAT_800b5554 = DAT_800b554c;
sVar1 = DAT_800b554e;
DAT_800b5552 = *(short *)(PTR_DAT_8008d2ac + 0x1d3a);
}
DAT_800b554e = sVar1;
if ((int)DAT_800b554e < 5) {
iVar10 = (int)DAT_800b554e * -0x200;
if (iVar10 < 0) {
iVar10 = iVar10 + 3;
}
sVar11 = (short)(iVar10 >> 2) * DAT_800b554c;
sVar1 = DAT_800b5552;
}
else {
sVar11 = (8 - DAT_800b554e) * DAT_800b554c * 0x80;
sVar1 = DAT_800b5550;
}
// AH_Pause_Draw
FUN_800b1f78((int)sVar1,(int)sVar11);
return;
}
// AH_HintMenu_FiveArrows
void FUN_800b344c(int param_1,short param_2)
{
undefined *puVar1;
int iVar2;
// loop counter
iVar2 = 0;
// loop 5 times
do
{
puVar1 = &DAT_800b51c4;
// blink on even frames
if ((DAT_8008d970 & 2) != 0)
{
puVar1 = &DAT_800b51d0;
}
// AH_Map_HubArrow
FUN_800b0f18
(((int)(short)iVar2 * 0x32 + 0x95) * 0x10000 >> 0x10,(param_1 + 4) * 0x10000 >> 0x10,
&DAT_800b51b8,puVar1,0x800,(int)param_2);
// loop index
iVar2 = iVar2 + 1;
} while (iVar2 * 0x10000 >> 0x10 < 5);
return;
}
// AH_HintMenu_MaskPosRot
void FUN_800b351c(void)
{
int iVar1;
// convert 3 rotation shorts into rotation matrix
FUN_8006c2a4(DAT_8008d860 + 0x30,&DAT_800b51e4);
// instance of 3D talking mask for hints
iVar1 = DAT_8008d860;
// Set position
*(int *)(DAT_8008d860 + 0x44) = (int)DAT_800b51dc;
*(int *)(iVar1 + 0x48) = (int)DAT_800b51de;
*(int *)(iVar1 + 0x4c) = (int)DAT_800b51e0;
// set thread->object->offset 0x4
*(undefined2 *)(*(int *)(*(int *)(iVar1 + 0x6c) + 0x30) + 4) = DAT_800b51ec;
return;
}
// AH_HintMenu_MenuBoxFuncPtr
void FUN_800b3594(int param_1)
{
uint *puVar1;
ushort uVar2;
bool bVar3;
undefined *puVar4;
short sVar5;
uint uVar6;
int iVar7;
undefined4 *puVar8;
short sVar9;
int iVar10;
int iVar11;
short sVar12;
byte local_70 [64];
short local_30;
short local_2e;
undefined2 local_2c;
short local_2a;
bVar3 = false;
iVar11 = 0;
FUN_800399fc();
iVar10 = 0;
DAT_8008fbb0 = DAT_8008fbb0 | 0x400000;
sVar9 = DAT_800b54f4;
while (sVar5 = (short)iVar11, -1 < sVar9) {
uVar6 = ((int)*(short *)((int)&DAT_800b54f4 + ((iVar10 << 0x10) >> 0xf)) + -0x17b) / 2 +
0x76;
// 0x8fba4 is where the adventure profile (currently loaded) begins
if (((uint)(&DAT_8008fba4)[(int)uVar6 >> 5] >> (uVar6 & 0x1f) & 1) != 0) {
iVar11 = iVar11 + 1;
local_70[sVar5] = (byte)iVar10;
}
iVar10 = iVar10 + 1;
sVar9 = *(short *)((int)&DAT_800b54f4 + (iVar10 * 0x10000 >> 0xf));
}
sVar9 = (short)(iVar11 + 1);
if (sVar5 < *(short *)(param_1 + 0x1a)) {
*(short *)(param_1 + 0x1a) = sVar5;
}
if ((((iVar11 + 1) * 0x10000 >> 0x10) + -5 < (int)DAT_800b5664) &&
(DAT_800b5664 = (short)(iVar11 + -4), (iVar11 + -4) * 0x10000 < 0)) {
DAT_800b5664 = 0;
}
// if viewing a hint
if (DAT_800b5660 != 0) {
uVar2 = (&DAT_800b54f4)[local_70[*(short *)(param_1 + 0x1a)]];
// AH_HintMenu_MaskPosRot
FUN_800b351c();
if (0 < DAT_800b51ee) {
DAT_800b51ee = DAT_800b51ee + -1;
}
// If you press Cross, Square, Triangle, or Circle
if (((DAT_8009a990 & 0x40070) != 0) &&
// if no XA is playing anymore
((uVar6 = FUN_8006924c(), (uVar6 & 0xffff) != 0 || (DAT_800b51ee == 0))))
{
// not viewing hint anymore
DAT_800b5660 = 0;
// clear gamepad input (for menus)
FUN_80046404();
// TalkingMask_End
FUN_8006925c();
}
iVar11 = (int)((uint)uVar2 << 0x10) >> 0xe;
// DecalFont_DrawLine
FUN_80022878(*(undefined4 *)(iVar11 + DAT_8008d878),0x100,0x2c,1,0xffff8000);
// DecalFont_DrawMultiLine
iVar11 = FUN_80022b34(*(undefined4 *)(iVar11 + DAT_8008d878 + 4),0x96,0x3f,0x14e,2,0);
// DAT_8008d878 + 0x5e8
// "EXIT"
FUN_80022878(*(undefined4 *)(DAT_8008d878 + 0x5e8),0x100,(iVar11 + 0x4f) * 0x10000 >> 0x10,1,
0xffff8000);
// DAT_8008d878 + 0x5e8
// "EXIT"
// DecalFont_GetLineWidth
iVar10 = FUN_800224d0(*(undefined4 *)(DAT_8008d878 + 0x5e8),1);
iVar7 = (iVar10 + 6) * 0x10000;
local_30 = 0xff - (short)((iVar7 >> 0x10) - (iVar7 >> 0x1f) >> 1);
local_2c = (undefined2)(iVar10 + 6);
local_2e = (short)iVar11 + 0x4e;
local_2a = 0x11;
// CTR_Box_DrawClearBox
FUN_8002177c(&local_30,&DAT_8008d94c,1,
*(undefined4 *)(*(int *)(PTR_DAT_8008d2ac + 0x10) + 0xa0)
// pointer to PrimMem struct
,*(int *)(PTR_DAT_8008d2ac + 0x10) + 0x74);
local_2e = 0x3c;
local_30 = -0xe;
local_2c = 0x21c;
local_2a = 2;
// MENUBOX_DrawOuterRect_Edge (transparent)
FUN_80044f90(&local_30,&DAT_8008d438,0x20,
*(undefined4 *)(*(int *)(PTR_DAT_8008d2ac + 0x10) + 0xa0));
local_2e = 0x28;
local_2a = (short)iVar11 + 0x3b;
local_30 = -0xe;
local_2c = 0x21c;
// Draw 2D Menu rectangle background
FUN_800457b0(&local_30,4,*(int *)(*(int *)(PTR_DAT_8008d2ac + 0x10) + 0xa0) + 0xc);
return;
}
// If you press Up, Down, Cross, Square, Triangle, Circle
if ((DAT_8009a990 & 0x40073) == 0)
{
goto LAB_800b38cc;
}
// If you dont press Up
if ((DAT_8009a990 & 1) == 0) {
// If you dont press Down
if ((DAT_8009a990 & 2) == 0) {
// If you dont press Cross or Circle
if ((DAT_8009a990 & 0x50) == 0) {
// If you press Triangle or Square
if ((DAT_8009a990 & 0x40020) != 0)
{
// Play sound
FUN_80028468(2,1);
goto LAB_800b38c0;
}
}
// If you press Cross or Circle
else
{
// Play Sound
FUN_80028468(1,1);
if (*(short *)(param_1 + 0x1a) == sVar5) {
LAB_800b38c0:
bVar3 = true;
}
else
{
// If there is no loading in progress
if ((DAT_8008d0a4 == 0) && (DAT_8008d708 == 0)) {
// global maskInst = TalkingMask_Init
DAT_8008d860 = FUN_80069178();
DAT_800b51ee = 0x1e;
// TalkingMask_PlayXA
FUN_800691e4(DAT_8008d860,
(((int)(short)(&DAT_800b54f4)[local_70[*(short *)(param_1 + 0x1a)]]
+ -0x17b) -
((int)(short)(&DAT_800b54f4)[local_70[*(short *)(param_1 + 0x1a)]]
+ -0x17b >> 0x1f)) * 0x8000 >> 0x10);
// AH_HintMenu_MaskPosRot
FUN_800b351c();
// talking mask instance
iVar11 = DAT_8008d860;
puVar4 = PTR_DAT_8008d2ac;
puVar1 = (uint *)(DAT_8008d860 + 0x28);
// instance -> tileView = gGT->tileView_ui
*(undefined **)(DAT_8008d860 + 0x74) = PTR_DAT_8008d2ac + 5000;
*(uint *)(iVar11 + 0x28) = *puVar1 | 0x400;
iVar10 = 1;
// if more than 1 screen
if (1 < (byte)puVar4[0x1ca8]) {
iVar7 = 0x10000;
// loop through Instance DPPs
do
{
iVar10 = iVar10 + 1;
// clear instance->tileView per player
*(undefined4 *)(iVar11 + (iVar7 >> 0x10) * 0x88 + 0x74) = 0;
iVar7 = iVar10 * 0x10000;
} while (iVar10 * 0x10000 >> 0x10 < (int)(uint)(byte)puVar4[0x1ca8]);
}
// now viewing a hint
DAT_800b5660 = 1;
}
}
}
}
// If you press Down
else
{
// if you are not on the bottom row
if (*(short *)(param_1 + 0x1a) < sVar5)
{
// Play Sound
FUN_80028468(0,1);
// change which row is selected
*(short *)(param_1 + 0x1a) = *(short *)(param_1 + 0x1a) + 1;
}
}
}
// If you press Up
else
{
// if you are not on the top row
if (0 < *(short *)(param_1 + 0x1a))
{
// Play Sound
FUN_80028468(0,1);
// change the row selected
*(short *)(param_1 + 0x1a) = *(short *)(param_1 + 0x1a) + -1;
}
}
// clear gamepad input (for menus)
FUN_80046404();
LAB_800b38cc:
// Weapon_Mask_boolGoodGuy
uVar6 = FUN_80064be4(*(undefined4 *)(PTR_DAT_8008d2ac + 0x24ec));
// If they use Uka
if ((uVar6 & 0xffff) == 0)
{
// DAT_8008d878 + 0x5e4
// "UKA UKA HINTS"
puVar8 = (undefined4 *)(DAT_8008d878 + 0x5e4);
}
// If they use Aku
else
{
// DAT_8008d878 + 0x5e0
// "AKU AKU HINTS"
puVar8 = (undefined4 *)(DAT_8008d878 + 0x5e0);
}
// Draw the "Hints" string
FUN_80022878(*puVar8,0x100,0x2c,1,0xffff8000);
if ((int)DAT_800b5664 + 5 <= (int)*(short *)(param_1 + 0x1a)) {
DAT_800b5664 = *(short *)(param_1 + 0x1a) + -4;
}
if (*(short *)(param_1 + 0x1a) < DAT_800b5664) {
DAT_800b5664 = *(short *)(param_1 + 0x1a);
}
sVar12 = 5;
if ((int)sVar9 < (int)DAT_800b5664 + 5) {
sVar12 = sVar9;
}
// if scroll bar is not on top
if (0 < (int)DAT_800b5664)
{
// AH_HintMenu_FiveArrows,
// top of screen
FUN_800b344c(0x3f,0);
}
iVar10 = 0x10;
iVar11 = 0;
if (0 < (int)sVar12) {
do {
iVar7 = (int)DAT_800b5664 + (int)(short)iVar11;
if (iVar7 < sVar5) {
uVar6 = (uint)(ushort)(&DAT_800b54f4)[local_70[iVar7]];
}
else {
uVar6 = 0x17a;
}
iVar7 = iVar10 + 0x40;
iVar10 = iVar10 + 0x10;
// DAT_8008d878 + 0x5e8
// "EXIT"
FUN_80022878(*(undefined4 *)(((int)(uVar6 << 0x10) >> 0xe) + DAT_8008d878),0x100,
iVar7 * 0x10000 >> 0x10,1,0xffff8000);
iVar11 = iVar11 + 1;
} while (iVar11 * 0x10000 >> 0x10 < (int)sVar12);
}
// if scroll bar is not on bottom
if ((int)DAT_800b5664 + (int)sVar12 < (int)sVar9)
{
// AH_HintMenu_FiveArrows,
// bottom of screen
FUN_800b344c((iVar10 + 0x40) * 0x10000 >> 0x10,0x800);
}
local_30 = -0xe;
local_2c = 0x21c;
local_2e = (*(short *)(param_1 + 0x1a) - DAT_800b5664) * 0x10 + 0x4f;
local_2a = 0x11;
// CTR_Box_DrawClearBox
FUN_8002177c(&local_30,&DAT_8008d94c,1,
*(undefined4 *)(*(int *)(PTR_DAT_8008d2ac + 0x10) + 0xa0),
// pointer to PrimMem struct
*(int *)(PTR_DAT_8008d2ac + 0x10) + 0x74);
local_2e = 0x3c;
local_2a = 2;
local_30 = -0x14;
local_2c = 0x228;
// MENUBOX_DrawOuterRect_Edge (transparent)
FUN_80044f90(&local_30,&DAT_8008d438,0x20,
*(undefined4 *)(*(int *)(PTR_DAT_8008d2ac + 0x10) + 0xa0));
local_2e = 0x28;
local_2a = (short)iVar10 + 0x2b;
local_30 = -0x14;
local_2c = 0x228;
// Draw 2D Menu rectangle background
FUN_800457b0(&local_30,4,*(undefined4 *)(*(int *)(PTR_DAT_8008d2ac + 0x10) + 0xa0));
if (
(bVar3) ||
// If you dont press Start, Square, or Triangle
((DAT_8009a990 & 0x41020) != 0)
)
{
// clear gamepad input (for menus)
FUN_80046404();
// set desired MenuBox to pause MenuBox
DAT_8008d924 = FUN_80039dcc();
}
return;
}
// AH_MaskHint_Start
void FUN_800b3dd8(short param_1,uint param_2)
{
undefined uVar1;
undefined4 uVar2;
int iVar3;
uint uVar4;
int iVar5;
// mask is now talking
DAT_8008d888 = 1;
DAT_800b5574 = (undefined2)param_2;
// flag 0x76 is where hints start
// in adventure profile
uVar4 = (int)param_1 + 0x76;
// pointer to P1 player structure
iVar5 = *(int *)(PTR_DAT_8008d2ac + 0x24ec);
// make a copy of hint index
DAT_800b5558 = param_1;
// VehPtr_Freeze_Init
*(undefined4 *)(iVar5 + 0x54) = 0x80062d04;
// 0x8fba4 is where the adventure profile (currently loaded) begins
// unlock flag that says you've viewed this mask hint before.
(&DAT_8008fba4)[(int)uVar4 >> 5] = (&DAT_8008fba4)[(int)uVar4 >> 5] | 1 << (uVar4 & 0x1f);
// If this is "welcome to adventure arena"
if ((int)param_1 == 0)
{
// unlock two hints, since Aku talks for a while
DAT_8008fbb0 = DAT_8008fbb0 | 0x800000;
DAT_8008fbb4 = DAT_8008fbb4 | 0x4000;
}
// If Aku / Uka model pointer is nullptr
if (DAT_8008d0f0 == 0)
{
// This is the first time getting
// a hint on this instance of adv hub
// get mempack index
uVar2 = FUN_800335dc();
// Weapon_Mask_boolGoodGuy
uVar4 = FUN_80064be4(iVar5);
// LOAD_TalkingMask
FUN_800347d0(uVar2,(uint)((uVar4 & 0xffff) == 0));
// Take 90 frames to spawn (3 seconds)
DAT_800b566c = 0x5a;
}
// if model is not nullptr
else
{
// Take 20 frames to spawn (2/3 second)
DAT_800b566c = 0x14;
}
iVar3 = (param_2 & 1) * 6;
// loop counter
iVar5 = 0;
DAT_800b51f0 = *(undefined2 *)(&DAT_800b5200 + iVar3);
DAT_800b51f2 = *(undefined2 *)(&DAT_800b5202 + iVar3);
DAT_800b51f4 = *(undefined2 *)(&DAT_800b5204 + iVar3);
DAT_800b51f8 = *(undefined2 *)(&DAT_800b520c + iVar3);
DAT_800b51fa = *(undefined2 *)(&DAT_800b520e + iVar3);
DAT_800b51fc = *(undefined2 *)(&DAT_800b5210 + iVar3);
iVar3 = 0;
// for iVar5 = 0; iVar5 < 3; iVar5++
do
{
// Make a backup of Volume settings
uVar1 = howl_VolumeGet(iVar3 >> 0x10);
(&DAT_800b5668)[iVar3 >> 0x10] = uVar1;
// increment loop counter
iVar5 = iVar5 + 1;
iVar3 = iVar5 * 0x10000;
} while (iVar5 * 0x10000 >> 0x10 < 3);
return;
}
// AH_MaskHint_boolCanSpawn
uint FUN_800b3f88(void)
{
// 8008d874
// 0 - aku is gone,
// 1 - aku is speaking
// return 0, if aku is speaking -- can't spawn
// return 1, if aku is gone -- can spawn
return (uint)(DAT_8008d874 == 0);
}
// WARNING: Could not reconcile some variable overlaps
// AH_MaskHint_EnterAnim
// param_1 is [0 to 0x1000],
// 0x0000 is tiny and spinning,
// 0x1000 is large and facing camera
void FUN_800b3f98(int param_1)
{
short sVar1;
int iVar2;
int iVar3;
uint uVar4;
int iVar5;
int iVar6;
undefined2 local_40;
undefined2 local_3e;
undefined2 local_3c;
short local_38;
short local_36;
short local_34;
short local_30;
short local_2e;
short local_2c;
undefined auStack40 [2];
short local_26;
undefined4 local_20;
undefined4 local_1c;
undefined4 local_18;
gte_SetRotMatrix((MATRIX *)(PTR_DAT_8008d2ac + 0x168 + 0x28));
gte_SetTransMatrix((MATRIX *)(PTR_DAT_8008d2ac + 0x168 + 0x28));
// ldv0, some position
setCopReg(2,0,CONCAT22(DAT_800b51f2,DAT_800b51f0));
setCopReg(2,0x800,(uint)DAT_800b51f4);
// rtv0tr cop2 $0480012 v0 * rotmatrix + tr vector
copFunction(2,0x480012);
// CAM_ProcessTransition
local_20 = getCopReg(2,0xc800);
local_1c = getCopReg(2,0xd000);
local_18 = getCopReg(2,0xd800);
local_40 = (undefined2)local_20;
local_3e = (undefined2)local_1c;
local_3c = (undefined2)local_18;
// camera rotation, modified by some other rotation
local_38 = *(short *)(PTR_DAT_8008d2ac + 0x16e) - DAT_800b51f8;
local_36 = *(short *)(PTR_DAT_8008d2ac + 0x170) + DAT_800b51fa;
local_34 = *(short *)(PTR_DAT_8008d2ac + 0x172) - DAT_800b51fc;
// CAM_ProcessTransition
FUN_80018fec(&local_30,auStack40,&DAT_800b5560,&DAT_800b5568,&local_40,&local_38,
param_1);
if (DAT_800b566c + -0x14 < DAT_800b5218)
{
// set rotation based on frame
iVar2 = ((DAT_800b566c - DAT_800b5218) * 0x1000) / 0x14;
}
else
{
// set rotation to face forward
iVar2 = 0x1000;
}
DAT_800b555c = (param_1 << 0xf) >> 0xc;
// approximate trigonometry
sVar1 = (short)*(int *)(&DAT_800845a0 + (DAT_800b555c & 0x3ff) * 4);
iVar6 = *(int *)(&DAT_800845a0 + (DAT_800b555c & 0x3ff) * 4) >> 0x10;
if ((DAT_800b555c & 0x400) == 0) {
iVar3 = (int)sVar1;
if ((DAT_800b555c & 0x800) == 0) goto LAB_800b417c;
iVar5 = -iVar6;
}
else {
iVar5 = (int)sVar1;
iVar3 = iVar6;
if ((DAT_800b555c & 0x800) == 0) {
iVar6 = -iVar5;
goto LAB_800b417c;
}
}
iVar3 = -iVar3;
iVar6 = iVar5;
LAB_800b417c:
iVar2 = iVar2 * 0x32 >> 0xc;
local_26 = local_26 + (short)DAT_800b555c;
local_30 = local_30 + (short)(iVar3 * iVar2 >> 0xc);
local_2c = local_2c + (short)(iVar6 * iVar2 >> 0xc);
// convert 3 rotation shorts into rotation matrix
FUN_8006c2a4(DAT_8008d860 + 0x30,auStack40);
*(short *)(*(int *)(*(int *)(DAT_8008d860 + 0x6c) + 0x30) + 4) = (short)param_1 * 4 + -1;
iVar6 = DAT_8008d860;
uVar4 = ((int)DAT_8008d970 + *(int *)(PTR_DAT_8008d2ac + 0x1cec)) * 0x20;
// approximate trigonometry
iVar2 = *(int *)(&DAT_800845a0 + (uVar4 & 0x3ff) * 4);
if ((uVar4 & 0x400) == 0) {
iVar2 = iVar2 << 0x10;
}
iVar2 = iVar2 >> 0x10;
if ((uVar4 & 0x800) != 0) {
iVar2 = -iVar2;
}
// talking mask instance -> position
*(int *)(DAT_8008d860 + 0x44) = (int)local_30;
*(int *)(iVar6 + 0x48) = (int)(short)(local_2e + (short)(((iVar2 << 4) >> 0xc) * param_1 >> 0xc));
*(int *)(iVar6 + 0x4c) = (int)local_2c;
return;
}
// AH_MaskHint_SpawnParticles
// param_1 - number of particles to spawn
// param_3 - mask anim
void FUN_800b42b4(short param_1,undefined4 param_2,int param_3)
{
int iVar1;
int iVar2;
int iVar3;
param_3 = param_3 + 0x1000;
if (0x3fff < param_3) {
param_3 = 0x3fff;
}
// loop counter
iVar3 = 0;
if (0 < (int)param_1) {
do
{
// Create instance in particle pool of "hubdustpuff"
iVar1 = FUN_80040308(0,*(undefined4 *)(PTR_DAT_8008d2ac + 0x2154),param_2);
// talking mask instance
iVar2 = DAT_8008d860;
// if particle created properly
if (iVar1 != 0)
{
*(int *)(iVar1 + 0x24) = *(int *)(iVar1 + 0x24) + *(int *)(DAT_8008d860 + 0x44) * 0x100;
*(int *)(iVar1 + 0x2c) = *(int *)(iVar1 + 0x2c) + *(int *)(iVar2 + 0x48) * 0x100;
iVar2 = *(int *)(iVar2 + 0x4c);
*(char *)(iVar1 + 0x18) = *(char *)(iVar1 + 0x18) + -5;
*(int *)(iVar1 + 0x34) = *(int *)(iVar1 + 0x34) + iVar2 * 0x100;
*(int *)(iVar1 + 0x4c) = *(int *)(iVar1 + 0x4c) * param_3 >> 0xc;
*(undefined2 *)(iVar1 + 0x50) = (short)(*(short *)(iVar1 + 0x50) * param_3 >> 0xc);
}
// loop counter
iVar3 = iVar3 + 1;
} while (iVar3 * 0x10000 >> 0x10 < (int)param_1);
}
return;
}
// AH_MaskHint_End
void FUN_800b43cc(int param_1)
{
int iVar1;
int iVar2;
// loop counter
iVar2 = 0;
iVar1 = 0;
do {
iVar1 = iVar1 >> 0x10;
// restore backups of Volume settings from FUN_800b3dd8
howl_VolumeSet(iVar1,(uint)(byte)(&DAT_800b5668)[iVar1] +
((int)(((int)(short)(&DAT_800b54ec)[iVar1] -
(uint)(byte)(&DAT_800b5668)[iVar1]) * param_1) >> 0xc) & 0xff);
// increment loop counter
iVar2 = iVar2 + 1;
iVar1 = iVar2 * 0x10000;
} while (iVar2 * 0x10000 >> 0x10 < 3);
return;
}
// AH_MaskHint_Update
void FUN_800b4470(void)
{
undefined *puVar1;
short sVar2;
ushort uVar3;
int iVar4;
undefined4 *puVar5;
undefined4 uVar6;
undefined4 uVar7;
bool bVar8;
int iVar9;
ushort uStack696;
ushort uStack694;
ushort uStack692;
undefined2 uStack688;
undefined2 uStack686;
undefined2 uStack684;
short sStack682;
undefined auStack32 [8];
undefined auStack24 [8];
puVar1 = PTR_DAT_8008d2ac;
// Driver
iVar9 = *(int *)(PTR_DAT_8008d2ac + 0x24ec);
switch((int)((DAT_8008d874 - 1) * 0x10000) >> 0x10) {
case 0:
if (DAT_8008d708 != 0) {
return;
}
goto LAB_800b4b64;
case 1:
iVar9 = (int)*(short *)(iVar9 + 0x38e);
if (iVar9 < 0) {
iVar9 = -iVar9;
}
if (0x31 < iVar9) {
return;
}
if ((DAT_800b5574 & 1) == 0) {
*(undefined2 *)(PTR_DAT_8008d2ac + 0x150c) = DAT_800b5520;
*(undefined2 *)(puVar1 + 0x150e) = DAT_800b5522;
*(undefined2 *)(puVar1 + 0x1510) = DAT_800b5524;
*(undefined2 *)(puVar1 + 0x1514) = DAT_800b5528;
*(undefined2 *)(puVar1 + 0x1516) = DAT_800b552a;
*(undefined2 *)(puVar1 + 0x1518) = DAT_800b552c;
*(uint *)(puVar1 + 0x1508) = *(uint *)(puVar1 + 0x1508) | 8;
// CAM_FollowDriver_AngleAxis
FUN_80019128(puVar1 + 0x1498,*(undefined4 *)(puVar1 + 0x24ec),&uStack696,auStack32,auStack24);
// CAM_SetDesiredPosRot
FUN_8001a054(PTR_DAT_8008d2ac + 0x1498,auStack32,auStack24);
}
DAT_800b5570 = 0x3c;
goto LAB_800b46b4;
case 2:
if ((((DAT_800b5574 & 1) == 0) && ((*(uint *)(PTR_DAT_8008d2ac + 0x1508) & 0x800) == 0)) &&
(DAT_800b566c != 0x14)) {
return;
}
// TalkingMask_Init
DAT_8008d860 = FUN_80069178();
// CTR_MatrixToRot
// driver -> inst -> matrix
FUN_80021edc(&uStack696,*(int *)(iVar9 + 0x1c) + 0x30,0x11);
// rotation of driver
DAT_800b5568 = uStack694 & 0xfff;
DAT_800b556c = uStack692 & 0xfff;
DAT_800b556a = uStack696 & 0xfff;
// position of driver
DAT_800b5560 = *(undefined2 *)(*(int *)(iVar9 + 0x1c) + 0x44);
DAT_800b5562 = *(undefined2 *)(*(int *)(iVar9 + 0x1c) + 0x48);
DAT_800b5564 = *(undefined2 *)(*(int *)(iVar9 + 0x1c) + 0x4c);
*(undefined2 *)(*(int *)(*(int *)(DAT_8008d860 + 0x6c) + 0x30) + 4) = 0;
// AH_MaskHint_EnterAnim, first frame
FUN_800b3f98(0);
DAT_800b5218 = 0;
LAB_800b46b4:
DAT_8008d874 = DAT_8008d874 + 1;
break;
// Mask Spawning In (make whoooosh sounds)
case 3:
// on first frame, play sound
if (DAT_800b5218 == 0)
{
// OtherFX_Play_LowLevel
// play "whoosh" spawning sound
FUN_800284d0(0x100,1,0xff8080);
}
// If mask is spending 3 seconds spawning
if (DAT_800b566c == 0x5a)
{
// play multiple distored "whoosh"
// sounds on different frames
if (DAT_800b5218 == 10) {
uVar6 = 0;
uVar7 = 0xd78a80;
}
else {
if (DAT_800b5218 == 0x14) {
uVar6 = 1;
uVar7 = 0xaf9480;
}
else {
if (DAT_800b5218 == 0x19) {
uVar6 = 0;
uVar7 = 0x879e80;
}
else {
if (DAT_800b5218 != 0x1e) goto LAB_800b477c;
uVar6 = 1;
uVar7 = 0x5fa880;
}
}
}
// OtherFX_Play_LowLevel
// play "whoosh" with distortion
FUN_800284d0(0x100,uVar6,uVar7);
}
LAB_800b477c:
if (DAT_800b566c == 0) {
trap(0x1c00);
}
if ((DAT_800b566c == -1) && (DAT_800b5218 << 0xc == -0x80000000)) {
trap(0x1800);
}
// AH_MaskHint_EnterAnim
// use timer to spin and move mask,
// divide by number of frames it should take to finish animation
FUN_800b3f98((DAT_800b5218 << 0xc) / DAT_800b566c);
if (DAT_800b566c == 0) {
trap(0x1c00);
}
if ((DAT_800b566c == -1) && (DAT_800b5218 << 0xc == -0x80000000)) {
trap(0x1800);
}
// AH_MaskHint_SpawnParticles
// use timer to spin and move mask,
// divide by number of frames it should take to finish animation
FUN_800b42b4(3,&DAT_800b521c,(DAT_800b5218 << 0xc) / DAT_800b566c);
// If there is no mask model
if (DAT_8008d0f0 == 0) {
LAB_800b48dc:
if (DAT_800b5218 < DAT_800b566c) goto LAB_800b48f8;
}
// if the mask model exists
else
{
// If mask is finished spawning
if (DAT_800b566c <= DAT_800b5218)
{
if (((*(uint *)(puVar1 + 0x1508) & 0x800) != 0) || ((DAT_800b5574 & 1) != 0))
{
// AH_MaskHint_End
FUN_800b43cc(0x1000);
// AH_MaskHint_SpawnParticles
FUN_800b42b4(0x18,&DAT_800b5384,0x1000);
FUN_800691e4(DAT_8008d860,(int)DAT_800b5558);
// If you're in Adventure Arena
if (((*(uint *)PTR_DAT_8008d2ac & 0x100000) != 0) &&
((DAT_800b5558 != 0 && (DAT_800b5558 != 0x18)))) {
PTR_DAT_8008d2ac[0x1d31] = PTR_DAT_8008d2ac[0x1d31] | 0x10;
}
goto LAB_800b4b64;
}
goto LAB_800b48dc;
}
LAB_800b48f8:
// increment mask animation
DAT_800b5218 = DAT_800b5218 + 1;
}
if (DAT_800b566c == 0) {
trap(0x1c00);
}
if ((DAT_800b566c == -1) && (DAT_800b5218 << 0xc == -0x80000000)) {
trap(0x1800);
}
// AH_MaskHint_End
// use timer to spin and move mask,
// divide by number of frames it should take to finish animation
FUN_800b43cc((DAT_800b5218 << 0xc) / DAT_800b566c);
break;
// Mask Speaking
case 4:
bVar8 = false;
iVar9 = 0;
if (-1 < DAT_800b54f4) {
do {
iVar4 = iVar9 << 0x10;
iVar9 = iVar9 + 1;
if ((int)DAT_800b5558 ==
(*(short *)((int)&DAT_800b54f4 + (iVar4 >> 0xf)) + -0x17b) / 2) {
bVar8 = true;
break;
}
} while (-1 < *(short *)((int)&DAT_800b54f4 + (iVar9 * 0x10000 >> 0xf)));
}
if (bVar8)
{
// Weapon_Mask_boolGoodGuy
sVar2 = FUN_80064be4(*(undefined4 *)(PTR_DAT_8008d2ac + 0x24ec));
// if bad guy
if (sVar2 == 0)
{
// TO HEAR THIS HINT AGAIN ... UKA UKA HINTS
puVar5 = (undefined4 *)(DAT_8008d878 + 0x8c8);
}
// if good guy
else
{
// TO HEAR THIS HINT AGAIN ... AKU AKU HINTS
puVar5 = (undefined4 *)(DAT_8008d878 + 0x5dc);
}
// DecalFont_DrawMultiLine
sStack682 = FUN_80022b34(*puVar5,0x100,0xb4,400,2,0xffff8000);
// Draw Box
uStack688 = 0xfff6;
uStack684 = 0x214;
uStack686 = 0xb0;
sStack682 = sStack682 + 8;
FUN_800457b0(&uStack688,4,*(undefined4 *)(*(int *)(PTR_DAT_8008d2ac + 0x10) + 0xa0));
}
// AH_MaskHint_EnterAnim, last frame, face camera
FUN_800b3f98(0x1000);
uVar3 = DAT_800b5570 - 1;
if (
(
(
(DAT_800b5570 == 0) ||
(bVar8 = DAT_800b5570 == 1, DAT_800b5570 = uVar3, bVar8)
) &&
(
(
// if mask is speaking
sVar2 = FUN_8006924c(),
sVar2 != 0 ||
// If you press Triangle
((*(uint *)(PTR_DAT_8008d2b0 + 0x14) & 0x40000) != 0)
)
)
) &&
(
// finish speaking, start leaving
DAT_8008d874 = DAT_8008d874 + 1,
// If you're in Adventure Arena
(*(uint *)PTR_DAT_8008d2ac & 0x100000) != 0
)
)
{
PTR_DAT_8008d2ac[0x1d31] = PTR_DAT_8008d2ac[0x1d31] & 0xef;
}
break;
// Mask Leaving
case 5:
// AH_MaskHint_SpawnParticles
FUN_800b42b4(0x14,&DAT_800b5384,0x1000);
// play vanishing sound
FUN_80028468(0x101,1);
FUN_8006925c();
if ((DAT_800b5574 & 1) == 0)
{
// CameraDC 0x70 transition back to player
*(uint *)(puVar1 + 0x1508) = *(uint *)(puVar1 + 0x1508) | 0x400;
}
LAB_800b4b64:
DAT_8008d874 = DAT_8008d874 + 1;
break;
case 6:
// AH_MaskHint_End
// 0x1524 is offset 0x8c of CameraDC (fly-in timer)
FUN_800b43cc(0x1000 - *(short *)(PTR_DAT_8008d2ac + 0x1524));
if (((*(uint *)(puVar1 + 0x1508) & 0x200) == 0) || ((DAT_800b5574 & 1) != 0))
{
// AH_MaskHint_EnterAnim, first frame
FUN_800b3f98(0);
// AH_MaskHint_End
FUN_800b43cc(0);
DAT_800b5570 = 0;
if ((DAT_800b5574 & 1) != 0) {
DAT_800b5570 = 0x1e;
}
DAT_8008d874 = DAT_8008d874 + 1;
}
break;
case 7:
// AH_MaskHint_End
FUN_800b43cc(0);
DAT_800b5570 = DAT_800b5570 - 1;
if ((int)((uint)DAT_800b5570 << 0x10) < 1) {
FUN_80046404();
DAT_8008d874 = 0;
DAT_8008d888 = 0;
*(uint *)(PTR_DAT_8008d2ac + 8) = *(uint *)(PTR_DAT_8008d2ac + 8) & 0xffffbfff;
*(code **)(iVar9 + 0x54) = FUN_80062b74;
}
}
return;
}
// WARNING: Globals starting with '_' overlap smaller symbols at the same address
// AH_Sign_LInB
// hangs above wooden doors
void FUN_800b4c80(int param_1)
{
DAT_1f800118._0_2_ = *(short *)(param_1 + 0x34) >> 6;
DAT_1f800118._2_2_ = *(short *)(param_1 + 0x3a) >> 6;
_DAT_1f800144 = 0x3000;
DAT_1f800142 = 2;
_DAT_1f800148 = 0;
DAT_1f80011c._0_2_ = *(short *)(param_1 + 0x40) >> 6;
// gGT->level->ptr_mesh_info
DAT_1f80014c = **(undefined4 **)(PTR_DAT_8008d2ac + 0x160);
// posX + ?
DAT_1f800108 = *(short *)(param_1 + 0x44) + (ushort)DAT_1f800118 * 2;
DAT_1f800110 = DAT_1f800108 + (ushort)DAT_1f800118 * -4;
// posY + ?
DAT_1f80010a = *(short *)(param_1 + 0x48) + DAT_1f800118._2_2_ * 2;
DAT_1f800112 = DAT_1f80010a + DAT_1f800118._2_2_ * -4;
// posZ + ?
DAT_1f80010c = *(short *)(param_1 + 0x4c) + (ushort)DAT_1f80011c * 2;
DAT_1f800114 = DAT_1f80010c + (ushort)DAT_1f80011c * -4;
// COLL_SearchTree_FindQuadblock_Touching
FUN_8001eb0c(&DAT_1f800108,&DAT_1f800110,&DAT_1f800120,0);
if (DAT_1f80015e != 0) {
DAT_1f800118._0_2_ = -(ushort)DAT_1f800118;
DAT_1f80011c._0_2_ = -(ushort)DAT_1f80011c;
DAT_1f800118._2_2_ = -DAT_1f800118._2_2_;
}
// instance -> 0x70,
// bit-compressed normal vector
*(uint *)(param_1 + 0x70) =
(uint)(ushort)DAT_1f800118 & 0xff | ((uint)DAT_1f800118._2_2_ & 0xff) << 8 |
((uint)(ushort)DAT_1f80011c & 0xff) << 0x10;
return;
}