My back hurts... (#40)

* Finish THREAD I said, turns out I can't solve it

* Removing some duplicates

* my back
This commit is contained in:
Agung Firdaus 2023-04-11 00:41:22 +07:00 committed by GitHub
parent fcd54ab3c9
commit 6ef4877d41
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
29 changed files with 1079 additions and 426 deletions

View File

@ -57,7 +57,10 @@ struct Driver* BOTS_Driver_Init(int driverID)
t->modelIndex = 0x3f;
// [0x5a4, 0x5b8 not in common.h]
d->actionsFlagSet |= 0x100000;
// [&DAT_8008daf8] unknown use
// [need to finish]
sdata->gGT->numBotsCurrGame += 1;
BOTS_GotoStartingLine(d);
return d;
}

View File

@ -0,0 +1,23 @@
#include <common.h>
void DECOMP_RobotcarWeapons_Init(void)
{
int hub;
int lev = sdata->gGT->levelID;
// get hubID of level
hub = data.metaDataLEV[lev].hubID;
// If Level ID == 13
// If Level ID is Oxide Station
if (lev == 0xd) {
hub = 0;
}
if (hub != (unsigned int)-1)
{
// set pointer to boss weapon meta
*(unsigned int*)0x8008d8e8 = data.bossWeaponMetaPtr[hub];
}
return;
}

View File

@ -0,0 +1,38 @@
#include <common.h>
void DECOMP_MM_Characters_AnimateColors(unsigned char *colorData, short playerID, short flag)
{
char bVar1;
unsigned int uVar3;
int iVar4;
int *ptrColor;
ptrColor = data.ptrColor[playerID + 0x18];
iVar4 = 0;
if (flag == 0) {
uVar3 = sdata->frameCounter * 0x100 + playerID * 0x400;
// approximate trigonometry
iVar4 = data.trigApprox[uVar3];
if ((uVar3 & 0x400) == 0) {
iVar4 = iVar4 << 0x10;
}
iVar4 = iVar4 >> 0x10;
if ((uVar3 & 0x800) != 0) {
iVar4 = -iVar4;
}
}
if (0xc00 < iVar4) {
bVar1 = ((iVar4 << 7) >> 0xc);
}
colorData[0] = ptrColor[0] | bVar1;
colorData[1] = ptrColor[1] | bVar1;
colorData[2] = ptrColor[2] | bVar1;
colorData[3] = 0;
return;
}

View File

@ -0,0 +1,13 @@
#include <common.h>
void DECOMP_MM_Characters_BackupIDs(void) {
char i;
for (i = 0; i < 8; i++) {
// make a backup of DAT_80086e84 into DAT_8009a980 when you leave character
// selection, when you return to character selection, DAT_8009a980 is copied
// back to DAT_80086e84
data.characterIDs_backup[i] = data.characterIDs[i];
}
return;
}

View File

@ -0,0 +1,71 @@
#include <common.h>
// if NOP'd, you can type at 80086e84 while in selection,
// otherwise, 80086e84 will be reset to zero after typing
void DECOMP_MM_Characters_ClearInactivePlayers(void) {
struct GameTracker *gGT = sdata->gGT;
char cVar1;
int iVar2;
char *pcVar3;
int iVar4;
int iVar5;
int iVar6;
int iVar7;
// 8 bytes, backed up character IDs (maybe should've been arrays?)
int local_8 = OVR_230.characterIDBackup1;
int local_4 = OVR_230.characterIDBackup2;
// if number of players is not zero
if (gGT->numPlyrNextGame) {
iVar2 = 0;
for (iVar7 = 0; iVar7 < gGT->numPlyrNextGame; iVar7++) {
// get character ID
iVar2 = data.characterIDs[iVar7];
// if not a secret character
if (iVar2 < 8) {
// save -1 (used later in func)
*(char*)((int)&local_8 + iVar2) = 0xff;
}
}
}
// if you have more than 1 player
if (1 < sdata->gGT->numPlyrNextGame) {
for (iVar7 = 1; iVar7 < gGT->numPlyrNextGame; iVar7++) {
for (iVar6 = 0; iVar6 < iVar5; iVar6++) {
if (data.characterIDs[iVar2] == data.characterIDs[iVar6]) {
iVar2 = 0;
for (iVar5 = 0; iVar5 < 8; iVar5++) {
// get value from $sp
pcVar3 = (char *)((int)&local_8 + iVar2);
cVar1 = *pcVar3;
// if not -1,
// meaning this "was" a secret character
if (-1 < cVar1) {
// set character ID to non-secret character
data.characterIDs[iVar7] = (short)cVar1;
// set to -1
*pcVar3 = -1;
break;
}
}
}
}
}
}
return;
}

View File

@ -0,0 +1,192 @@
#include <common.h>
void DECOMP_MM_Characters_DrawWindows(char wheelFlag)
{
struct GameTracker* gGT = sdata->gGT;
undefined2 uVar2;
undefined2 uVar3;
undefined4 uVar4;
int iVar5;
int iVar6;
uint uVar7;
int iVar8;
short sVar9;
int iVar10;
short *psVar11;
struct TileView* tileview;
short *psVar13;
int iVar14;
undefined2 local_30;
short local_2e;
undefined2 local_2c;
if (wheelFlag != 0) {
// enable drawing wheels
*(unsigned int *)(gGT + 0x256c) |= 0x80;
}
// if number of players is not zero
if (gGT->numPlyrNextGame) {
for (iVar14 = 0; iVar14 < gGT->numPlyrNextGame; iVar14++)
{
psVar11 = ((short *)0x800b5a0c)[iVar14]
iVar6 = (short *)0x800b5a3c[iVar14]
// tileView
tileview = gGT->tileView[iVar14];
tileview->rect.x = *psVar11 + *(short *)(iVar6 + 0xa6);
// window width
uVar3 = *(unsigned int*)0x800b5a30;
// window height
uVar2 = *(unsigned int*)0x800b59dc;
tileview->rect.y = psVar11[1] + *(short *)(iVar6 + 0xa8);
// windowSize (X and Y)
tileview->aspectX = uVar3;
tileview->aspectY = uVar2;
// negative StartX
if ((short)tileview->rect.x < 0) {
tileview->aspectX -= tileview->rect.x;
tileview->rect.x = 0;
if ((short)tileview->aspectX < 0) {
tileview->aspectX = 0;
}
}
// negative StartY
if ((short)tileview->rect.y < 0) {
tileview->aspectY -= tileview->rect.y;
tileview->rect.y = 0;
if ((short)tileview->aspectY < 0) {
tileview->aspectY = 0;
}
}
// startX + sizeX out of bounds
if ((0x200 < (int)(short)tileview->rect.x + (int)(short)tileview->aspectX) &&
(tileview->aspectX = (short)(0x200 - (uint)(ushort)tileview->rect.x),
(int)((0x200 - (uint)(ushort)tileview->rect.x) * 0x10000) < 0)) {
tileview->rect.x = 0x200;
tileview->aspectX = 0;
}
// startY + sizeY out of bounds
if ((0xd8 < (int)(short)tileview->rect.y + (int)(short)tileview->aspectY) &&
(tileview->aspectY = (short)(0xd8 - (uint)(ushort)tileview->rect.y),
(int)((0xd8 - (uint)(ushort)tileview->rect.y) * 0x10000) < 0)) {
tileview->rect.y = 0xd8;
tileview->aspectY = 0;
}
// distanceToScreen
tileview->distanceToScreen_CURR = 0x100;
tileview->distanceToScreen_PREV = 0x100;
// tileView pos and rot to all zero
tileview->pos[0] = 0;
tileview->pos[1] = 0;
tileview->pos[2] = 0;
tileview->rot[0] = 0;
tileview->rot[1] = 0;
tileview->rot[2] = 0;
// player -> instance
iVar10 = gGT->drivers[iVar14].instSelf;
// Disable "AI flag"
iVar10->flags &= 0xffffff7f;
// if driver loaded is not human
if ((gGT->numPlyrNextGame <= iVar14) || (wheelFlag == 0))
{
// You are an AI (I think)
iVar10->flags |= 0x80;
}
// clear tileView in every InstDrawPerPlayer
iVar10->idpp[0].tileView = 0;
iVar10->idpp[1].tileView = 0;
iVar10->idpp[2].tileView = 0;
iVar10->idpp[3].tileView = 0;
// set tileView in InstDrawPerPlayer,
// so that each camera can only see one driver
iVar10->idpp[iVar14].tileView = puVar12;
psVar13 = &DAT_800b59f8[iVar14];
iVar10->animFrame = 0;
iVar10->vertSplit = 0;
uVar4 = MM_Characters_SearchModelByString(data.MetaDataCharacters[(int)*psVar13].name_Debug);
// set modelPtr in Instance
iVar10->modelPtr = uVar4;
// CameraDC, freecam mode
gGT->CameraDC[iVar6] = 3;
// Set position of player
iVar10->matrix.t[0] = *(int*)0x800b5360;
iVar10->matrix.t[1] = *(int*)0x800b5362;
iVar10->matrix.t[2] = *(int*)0x800b5364;
psVar11 = &DAT_800b5a24 + iVar6;
sVar9 = *psVar11 + -1;
// If no transition between players
if (*psVar11 == 0) {
// compare to character ID
if (*psVar13 != data.characterIDs[iVar6]) {
*psVar11 = (short)(*(int*)0x800b536e << 1);
&DAT_800b59f0[iVar6] = data.characterIDs[iVar6];
}
}
// if transition between players
else {
// get timer
*psVar11 = sVar9;
// if timer is before midpoint
if ((int)sVar9 < (int)DAT_800b536e) {
// make driver fly off screen
*psVar13 = (&DAT_800b59f0)[iVar6];
iVar5 = TitleFlag_MoveModels();
// direction moving
iVar6 = -(int)(short)(&DAT_800b59e8)[iVar6];
iVar8 = iVar5 * DAT_800b5370 >> 0xc;
}
// if timer is after midpoint
else {
// make new driver fly on screen
iVar5 = TitleFlag_MoveModels((int)sVar9 - (int)DAT_800b536e);
// direction moving
iVar8 = (int)(short)(&DAT_800b59e8)[iVar6];
iVar6 = (0x1000 - iVar5) * (int)DAT_800b5370 >> 0xc;
}
iVar10->matrix.t[0] += iVar6 * iVar8;
}
// driver rotation
local_2c = DAT_800b536c;
local_30 = DAT_800b5368;
local_2e = DAT_800b536a + *(short *)((int)&DAT_800b5a00 + ((iVar14 << 0x10) >> 0xf));
// convert 3 rotation shorts into rotation matrix
ConvertRotToMatrix(&iVar10->matrix.m[0][0], &local_30);
iVar10 = iVar14 * 0x10000;
}
}
return;
}

View File

@ -0,0 +1,37 @@
#include <common.h>
int DECOMP_MM_Characters_GetNextDriver(short dpad, char characterID)
{
char nextDriver;
char unlocked;
char newDriver;
// param_1 is the direction you hit on d-pad (up, down, left, right)
// param_2 is driver you currently have highlighted
// 800b5a18 is pointer to array of character icons
// each character icon is 0xc bytes large
// offset 4 is 4-byte array of which driver you get when you press on D-Pad
nextDriver = *(char*)0x800b5a1c[characterID] + dpad;
// offset 10 (0xA) determines if that driver is unlocked
unlocked = *(u_char*)0x800b5a22[bVar1];
// set new driver to the driver
// you'd get when pressing Up button
newDriver = nextDriver;
if (
// if desired driver is not unlocked
(unlocked != -1) &&
((sdata->GameProgress.unlocks)[unlocked] >> (unlocked & 1) == 0)) {
// set new driver to the driver you already have
newDriver = characterID;
}
// return new driver
return newDriver;
}

View File

@ -0,0 +1,14 @@
#include <common.h>
void DECOMP_MM_Characters_HideDrivers(void) {
char i;
struct GameTracker *gGT = sdata->gGT;
for (i = 0; i < 4; i++) {
TileView_Init(gGT->tileView[i], 0, 1);
// player structure's instane flags, make invisible
gGT->drivers[i].instSelf->flags |= 0x80;
}
return;
}

View File

@ -0,0 +1,93 @@
#include <common.h>
void DECOMP_MM_Characters_RestoreIDs(void) {
struct GameTracker *gGT = sdata->gGT;
short *currID;
int iVar3;
int iVar4;
char i;
// erase select bits
sdata->characterSelectFlags = 0;
OVR_230.transitionFrames = 0xc;
OVR_230.isMenuTransitioning = 0;
// This uses 80086e84, which controls character IDs
// loop 8 times
// shouldn't it only need to loop a maximum of 4 times?
for (i = 0; i < 8; i++)
{
// set character ID to the last ID you entered
data.characterIDs[i] = data.characterIDs_backup[i];
}
MM_Characters_SetMenuLayout();
// PTR_DAT_800b5a18 goes to CrashIconX
// This changes for the three menus
// 1P + 2P 800B4E80
// 3P 800B4F34
// 4P 800B4FE8
iVar3 = *(int*)0x800b5a18;
//
for (i = 0; i < 0xf; i++) {
// Changes ID of Icon without changing image of icon
// Changing Crash's ID at 800B50B4 makes it so going to
// Crash's Icon will teleport the cursor somehwere else
// Basically sets them to 0, 1, 2, 3, 4... up to 0xE,
// setting Oxide's manually to 0xF is needed to make his icon appear
OVR_230.characterIcon[*(short*)0x800b5a20[i]] = i;
}
// if number of players is not zero
if (gGT->numPlyrNextGame) {
iVar4 = 0
for (i = 0; i < gGT->numPlyrNextGame; i++) {
// Determine if this icon is unlocked (and drawing)
// get character ID
currID = data.characterIDs[i];
// get unlock requirement for this character
uVar1 = *(short *)(((int*)0x800b5a22)[currID]);
if (
// If Icon has an unlock requirement
(uVar1 != -1) &&
// If Character is Locked
(sdata->GameProgress.unlocks[currID] >> uVar1 & 1) == 0) {
// change character to Crash
*currID = 0;
}
iVar4 = i * 0x10000;
}
}
MM_Characters_ClearInactivePlayers();
// if number of players is not zero
if (gGT->numPlyrNextGame) {
for (i = 0; i < gGT->numPlyrNextGame; i++) {
// set name string ID to the character ID of each player.
// The string will only draw if both these variables match
(&DAT_800b59f8)[i] = data.characterIDs[i];
(&DAT_800b59f0)[i] = data.characterIDs[i];
// something to do with transitioning between icons
OVR_230.fill_isMenuTransitioning2[i] = 0;
// rotation of each driver, 90 degrees difference
(&DAT_800b5a00)[i] = (i * 0x400) + 400;
}
}
MM_Characters_DrawWindows(0);
return;
}

View File

@ -0,0 +1,23 @@
#include <common.h>
// Search for character model by string,
// specific to main menu lev, altered in oxide mod
struct Model* DECOMP_MM_Characters_SearchModelByString(int *name) {
struct Model** models;
struct Model* model;
// if LEV is valid
if (sdata->gGT->level1 != NULL)
return NULL;
models = sdata->gGT->level1->ptrModelsPtrArray;
// loop through all models until nullptr is found
for (model = models[0]; model != NULL; models += 1, model = models[0]) {
// if model exists, check first 4 bytes for name
if (*model == *name) {
// return model pointer
return model;
}
}
return NULL;
}

View File

@ -0,0 +1,74 @@
#include <common.h>
void MM_Characters_SetMenuLayout(void)
{
unsigned short unlocked;
char expand = 0;
char numPlyr = sdata->gGT->numPlyrNextGame;
int iVar3;
int i;
// By default, draw "Select character" in 3P menu
OVR_230.isRosterExpanded = 0;
// By default, array of character IDs is
// grabbed from array of pointers to arrays of character IDs,
// it can be index 0,1,2,3
OVR_230.characterSelectIconLayout = numPlyr - 1;
// Loop through all characters,
// If a character is unlocked that covers
// the top row (Joe, Penta, Fake Crash)
// Then dont draw "Select character"
for (i = 0; i < 0xf; i++) {
unlocked = OVR_230.csm_1P2P[i].characterID; // 800B4E8A
if ((sdata->gameProgress->unlocks[unlocked >> 5] >> unlocked & 1) != 0) {
// enough characters are unlocked for expanded menu
// menu is expanded, stop drawing "select character"
OVR_230.isRosterExpanded = expand;
}
}
if (
// if there are less than 3 players
(numPlyr < 3) &&
// if very few characters are unlocked
(!expand)
) {
// get new pointer to array of character IDs with less icons
OVR_230.characterSelectIconLayout = numPlyr + 3;
}
// set final index to array of pointers of character IDs
iVar3 = OVR_230.characterSelectIconLayout;
// get driver posY from array
*(int*)0x800b5362 = ((int*)0x800b4db4)[iVar3];
// get driver posZ from array
*(int*)0x800b5364 = ((int*)0x800b4da8)[iVar3];
// get window height from array
*(int*)0x800b59dc = ((int*)0x800b4d9c)[iVar3];
// pointer to array of driver window positions,
// this can be used to dynamically erase any driver window
// of any player in any menu, for Oxide in menus
*(int*)0x800b5a0c = OVR_230.ptrSelectWindowPos[iVar3];
// set pointer to array of driver icons
// If you ever want to make new driver arrays for oxide,
// change the pointers at 800b509c to do it
*(int*)0x800b5a18 = OVR_230.ptr_csm_1P[iVar3];
// get window width from array
*(int*)0x800b5a30 = ((int*)0x800b4d90)[iVar3];
// Get position of text relative to window position
*(int*)0x800b5a38 = ((int*)0x800b4dc0)[iVar3];
*(int*)0x800b5a3c = OVR_230.ptr_transitionMeta_csm[numPlyr - 1];
return;
}

View File

@ -1,61 +0,0 @@
#include <common.h>
int DECOMP_MM_TransitionInOut(u_short *param_1,int param_2,short numFrames)
{
char bVar1;
short uVar2;
int iVar3;
short *puVar4;
int iVar5;
short sVar6;
bVar1 = 1;
sVar6 = 0;
uVar2 = param_1[2];
if (-1 < (short)param_1[2]) {
iVar5 = (int)numFrames;
puVar4 = param_1 + 2;
do {
if ((int)((param_2 - (u_int)uVar2) == 4) && (sVar6 == 0))
{
// Play "swoosh" sound for menu transition
OtherFX_Play(0x65,0);
}
iVar3 = (int)(param_2 - (u_int)uVar2);
if (iVar3 < 1) {
bVar1 = 0;
puVar4[1] = 0;
puVar4[2] = 0;
}
else {
if (iVar3 < iVar5) {
if (iVar5 == 0) {
trap(0x1c00);
}
if ((iVar5 == -1) && (iVar3 * (short)*param_1 == -0x80000000)) {
trap(0x1800);
}
if (iVar5 == 0) {
trap(0x1c00);
}
if ((iVar5 == -1) && (iVar3 * (short)puVar4[-1] == -0x80000000)) {
trap(0x1800);
}
uVar2 = (u_short)((iVar3 * (short)puVar4[-1]) / iVar5);
bVar1 = 0;
puVar4[1] = (u_short)((iVar3 * (short)*param_1) / iVar5);
}
else {
uVar2 = puVar4[-1];
puVar4[1] = *param_1;
}
puVar4[2] = uVar2;
}
puVar4 = puVar4 + 5;
param_1 = param_1 + 5;
uVar2 = *puVar4;
sVar6 = sVar6 + 1;
} while (-1 < (short)*puVar4);
}
return bVar1;
}

View File

@ -520,7 +520,7 @@ void MM_Characters_MenuBox()
// if character is unlocked
// from 4-byte variable that handles all rewards
// also the variable written by cheats
(((u_int)(&sdata->gameProgress.unlocks[0])[iVar8] >> (psVar18[4] & 0x1fU) & 1) != 0)
((sdata->gameProgress.unlocks[iVar8] >> psVar18[4] & 1) != 0)
)
{
iconColor = &OVR_230.characterSelect_NeutralColor;

View File

@ -0,0 +1,121 @@
#include <common.h>
void DECOMP_BOTS_Driver_Convert(struct Driver *d) {
struct GameTracker *gGT = sdata->gGT;
char validPath;
short numPoints;
int i, pathIndex;
unsigned int navFrame;
unsigned int actionFlag;
// if this racer is not an AI (player)
if ((d->actionFlagsSet & 0x100000) == 0) {
UI_RaceEnd_GetDriverClock(d);
// nav path index of this driver
pathIndex = sdata->driver_pathIndexIDs[d->driverID];
validPath = 0;
// number of nav points on this path
numPoints = sdata->NavPath_ptrHeader[pathIndex]->numPoints);
// ============
// same as BOTS_Driver_Init
// check if nav path data exists
// ============
// if invalid path
if (numPoints == 0) {
// check all paths
for (i = 0; i < 3; i++) {
// quit loop when found
if (sdata->NavPath_ptrHeader[i]->numPoints != 0) {
// valid path data was found
validPath = 1;
break;
}
}
}
LAB_800173e4:
// if valid path data was found
if (validPath) {
// 0x94 chunk in driver struct?
memset(*(int *)(d + 0x598), 0, 0x94);
// path index
pathIndex = i * 4;
*(int *)(d + 0x5d0) = d->ySpeed;
// nav path index
*(short *)(d + 0x5b8) = pathIndex;
// AI speed
*(int *)(d + 0x5d4) = d->speedApprox;
// pointer to first navFrame on path
navFrame = sdata->NavPath_ptrNavFrameArray[pathIndex];
*(int *)(d + 0x5a8) = 0;
d->unknownDimension2Curr = 0;
d->multiDrift = 0;
d->ampTurnState = 0;
d->set_0xF0_OnWallRub = 0;
// current navFrame
*(int *)(d + 0x5a4) = navFrame;
// driver -> instance -> thread -> funcThTick =
d->instSelf->thread->funcThTick = BOTS_ThTick_Drive;
// if you are in battle mode
if ((gGT->gameMode1 & 0x20) != 0) {
// pointer to each AI Path Header
piVar8 = &sdata->NavPath_ptrHeader[iVar10];
// set the X, Y, and Z positions
d->posCurr[0] = (int)piVar8->frame->pos[0] << 8;
d->posCurr[1] = (int)piVar8->frame->pos[1] << 8;
d->posCurr[2] = (int)piVar8->frame->pos[2] << 8;
}
// (free or taken?)
LIST_AddFront(&DAT_8008daf8[pathIndex], *(int *)(d + 0x598));
BOTS_SetRotation(d, 0);
GAMEPAD_Vib_2(d, 0, 0);
actionFlag = d->actionFlagsSet;
// player becomes AI, drop bits for button holding
d->actionFlagsSet &= 0xfffffff3 | 0x100000;
// if previous value of actions flag set had 26th flag on (means racer
// finished the race)
if ((actionFlag & 0x2000000) != 0) {
CAM_EndOfRace(gGT->cameraDC[d->driverID], d);
}
// Kart state:
switch (d->kartState) {
// if racer is spinning
case 3:
navFrame = 1;
// if racer is blasted
case 6:
navFrame = 2;
break;
default:
return;
}
BOTS_ChangeState(d, navFrame, 0, 0);
}
}
}

View File

@ -1,67 +0,0 @@
#include <common.h>
void DECOMP_DebugFont_DrawNumbers(int number, u_int posX, int posY)
{
POLY_FT4* p;
u_long* ot;
u_int uVar4;
u_int uVar5;
u_int uVar6;
uVar6 = posX + 7 & 0xffff;
uVar4 = (posY + 7) * 0x10000;
// backBuffer->primMem.curr
p = (POLY_FT4*)sdata->gGT->backBuffer->primMem.curr;
// pointer to OT memory
ot = sdata->gGT->tileView_UI.ptrOT;
// backBuffer->primMem.curr
sdata->gGT->backBuffer->primMem.curr = p + 1;
*(int*)&p->r0 = 0x2e000000;
p->x0 = posX & 0xffff | posY << 0x10;
p->x1 = uVar6 | posY << 0x10;
p->x2 = posX & 0xffff | uVar4;
p->x3 = uVar6 | uVar4;
// each character is 7 pixels wide
// and 7 pixels tall
// '0' is 6th character in 2nd row,
// Get X value of pixel
// This is the bottom of two bytes
uVar4 = sdata->debugFont.pixelX + (number + 5) * 7;
// Get Y value for top of the quad
// bit shift to top byte
uVar6 = (sdata->debugFont.pixelY + 7) * 0x100;
// Get Y value for bottom of the quad1
// bit shift to top byte
uVar5 = (uVar6 + 7) * 0x100;
// Top Left corner
p->u0 = uVar4 | uVar6;
// Top Right corner
p->u1 = uVar4 + 7 | uVar6;
// Bottom Left corner
p->u2 = uVar4 | uVar5;
// Bottom Right corner
p->u3 = uVar4 + 7 | uVar5;
// color palette
p->clut = sdata->debugFont.clut;
// texture page
p->tpage = sdata->debugFont.tpage;
*(int*)p = *ot | 0x9000000;
*ot = (u_int)p & 0xffffff;
return;
}

View File

@ -0,0 +1,53 @@
// called "EffectSfx" for no good reason,
// but is related to rain sounds, no proof of name
// this func handle rain on tiger temple and cortex castle
void EffectSfxRain_MakeSound(struct GameTracker *gGT) {
int i, lev;
unsigned int rained;
rained = 0;
lev = gGT->levelID;
// if you are not in
if (
// Tiger Temple
(lev != 4)
// Cortex Castle
&& (lev != 10)) {
return;
}
// if numPlyrCurrGame is not zero
if (gGT->numPlyrCurrGame) {
for (i = 0; i < gGT->numPlyrCurrGame; i++) {
rained |= gGT->rainBuffer[i];
}
} else {
return;
}
// if at least one is rained on
if (rained) {
// if there is no rain
if (gGT->rainVariable == 0) {
// now there is rain
gGT->rainVariable = OtherFX_Play(0x82, 0);
}
}
// if nobody is rained on
else {
// if it's raining
if (gGT->rainVariable != 0) {
OtherFX_Stop1();
// no more rain
gGT->rainVariable = 0;
}
}
return;
}
void EffectSfxRain_Reset(struct gameTracker *gGT) {
gGT->rainVariable = 0;
return;
}

View File

@ -0,0 +1,11 @@
#include <common.h>
int DECOMP_CountSounds(void)
{
// watch it increase when scrolling in main menu
sdata->countSounds += 1;
if (sdata->countSounds < 1) {
sdata->countSounds = 1;
}
return sdata->countSounds;
}

View File

@ -0,0 +1,22 @@
#include <common.h>
void Cutscene_VolumeBackup(void)
{
// enter critical section
Smart_EnterCriticalSection();
// make a copy of FX volume
sdata->currentVolume = howl_VolumeGet(0);
// make another copy volume of FX and clamp to 0x100
sdata->storedVolume = sdata->currentVolume;
sdata->currentVolume &= 0xff;
// copy exists
sdata->boolStoringVolume = 1;
// exit critical section
Smart_ExitCriticalSection();
return;
}

View File

@ -0,0 +1,18 @@
#include <common.h>
void Cutscene_VolumeRestore(void)
{
// enter critical section
Smart_EnterCriticalSection();
// copy does not exist
sdata->boolStoringVolume = 0;
// Set volume of FX
howl_VolumeSet(0,sdata->storedVolume);
// exit critical section
Smart_ExitCriticalSection();
return;
}

View File

@ -0,0 +1,25 @@
#include <common.h>
void Smart_EnterCriticalSection(void)
{
char alreadyEntered;
int iVar2;
// Add 1 to the number of times you've
// tried to enter a critical section
iVar2 = sdata->criticalSectionCount + 1;
// Check if you're already in a critical section
alreadyEntered = (sdata->criticalSectionCount == 0);
// Set the number of times you've
// tried to enter a critical section
sdata->criticalSectionCount = iVar2;
// if you are not already in critical section
if (alreadyEntered)
{
// enter the critical section
Smart_EnterCriticalSection();
}
return;
}

View File

@ -0,0 +1,19 @@
#include <common.h>
void Smart_ExitCriticalSection(void)
{
if (
// if you're already in a critical section
(sdata->criticalSectionCount != 0) &&
// reduce the number of times you've tried to exit, by 1
(sdata->criticalSectionCount += -1,
// if you have no more active needs to be in a critical section
sdata->criticalSectionCount == 0))
{
// You are no longer in a critical section
Smart_ExitCriticalSection();
}
return;
}

View File

@ -0,0 +1,37 @@
#include <common.h>
// Only used for drawing player comments
void DECOMP_MenuBox_DrawQuip(char* comment,short posX,int posY,u_int sizeX,short fontType,
int flags,short param_7)
{
int lineWidth;
short posX;
u_int posY;
u_int sizeX;
u_int sizeY;
if ((sizeX & 0xffff) == 0)
{
lineWidth = DecalFont_GetLineWidth(comment,(int)fontType);
sizeX = lineWidth + 0xc;
}
// if text is not centered
if ((flags & 0x8000U) != 0)
{
// posX with text un-centered
posX = posX - (short)(((int)(sizeX << 0x10) >> 0x10) - ((int)(sizeX << 0x10) >> 0x1f) >> 1);
}
sizeY = (u_int)data.PlayerCommentBoxParams[0][fontType];
// Draw string
DecalFont_DrawLine(comment,
posX,(data.PlayerCommentBoxParams[1][lineWidth] + posY),
fontType, flags);
// Draw 2D Menu rectangle background
MenuBox_DrawFullRect(&posX,(int)param_7, sdata->gGT->backBuffer->otMem.startPlusFour);
return;
}

View File

@ -0,0 +1,17 @@
#include <common.h>
int DECOMP_MixRNG_Scramble()
{
// random algorithm for seemingly-random numbers
sdata->randomNumber = sdata->randomNumber * 0x6255 + 0x3619 & 0xffff;
return sdata->randomNumber;
}
int DECOMP_MixRNG_Particles(int numParticle)
{
return (int)((RngDeadCoed(sdata->gGT->deadcoed_struct.unk1 & 0xffff) * numParticle) >> 0x10);
}
u_int DECOMP_MixRNG_GetValue(int val)
{
return val * 0x6255 + 0x3619U & 0xffff;
}

View File

@ -0,0 +1,55 @@
#include <common.h>
// param1 is thread checked for collision
// param2 is WeaponSearchData
// param3 is person who used weapon
void DECOMP_THREAD_CollideHitboxWithBucket(struct Thread* collThread,struct WeaponSearchData* param_2,int param_3)
{
struct Instance* inst;
int distX, distY, distZ;
// if thread is valid
if (collThread != NULL) return;
do
{
// if child thread exists
if (collThread->childThread != NULL)
{
// recursively check all children
THREAD_CollideHitboxWithBucket(collThread->childThread,param_2,param_3);
}
if (
// make sure you dont hit your own weapon???
(collThread->next != param_3) &&
// if collision is not disabled for this thread,
// and if this thread is not dead
((collThread->flags & 0x1800) == 0)
)
{
// get instance
inst = collThread->inst;
// get distance of X, Y, Z
distX = (int)param_2->pos[0] - inst->matrix.t[0];
distY = (int)param_2->pos[1] - inst->matrix.t[1];
distZ = (int)param_2->pos[2] - inst->matrix.t[2];
// if all the dist values are small
if ((distX * distX < 0x10000000) &&
(distY * distY < 0x10000000) &&
(distZ * distZ < 0x10000000) &&
// if abs distance is less than collision radius
(distX * distX + distY * distY + distZ * distZ < param_2->hitRadiusSquared)
)
{
// save distancdistX param_2->pos[8] = (short)iVardistX param_2->pos[9] = (short)iVardistX param_2->pos[10] = (short)iVar1;
// some collision funcPtr???
(**(code **)param_2->funcCallback)(param_2,collThread);
}
}
// thread = thread->sibling;
collThread = collThread->siblingThread;
} while (collThread != NULL);
}

View File

@ -0,0 +1,43 @@
#include <common.h>
void THREAD_PerVisData_CheckInstances(struct VisData* param_1, struct WeaponSearchData* param_2)
{
int distX, distY, distZ;
struct VisData* piVar4;
struct InstDef* piVar5;
piVar4 = param_1->data.leaf.ptrVisDataArray_InstHitboxes;
if (piVar4 != NULL) return;
// loop through all hitboxes
//+(8 * 0x4) = +0x20 bytes, size of VisData
for (piVar5 = param_1->data.hitbox.instDef; piVar4->flag != 0; piVar4 += 8, piVar5 += 8)
{
if (
((piVar4->flag & 0x80) != 0)
&&
((piVar5->name == NULL || (piVar5->ptrInstance->flags & 0xf) != 0))
) {
distX = (int)param_2->pos[0] - (int)*(short *)(piVar4 + -1);
distY = (int)param_2->pos[1] - (int)*(short *)((int)piVar4 + -2);
distZ = (int)param_2->pos[2] - (int)*(short *)piVar4;
// if all the dist values are small
if ((distX * distX < 0x10000000) &&
(distY * distY < 0x10000000) &&
(distZ * distZ < 0x10000000) &&
// if abs distance is less than collision radius
(distX * distX + distY * distY + distX * distX < param_2->hitRadiusSquared)) {
// distX param_2->pos[10] = (short)iVardistX param_2->pos[9] = (short)iVardistX param_2->pos[8] = (short)iVar3;
// short+0x14 = byte+0x28,
// callback on collision
// either for colliding with lev object or nonLev
**(code **)(param_2->funcCallback)(param_2,piVar5);
}
}
}
}

View File

@ -0,0 +1,30 @@
#include <common.h>
void THREAD_PerVisData_CheckInstances();
void DECOMP_THREAD_StartSearch_Self(struct WeaponSearchData* param)
{
struct GameTracker* gGT = sdata->gGT;
short sVar1;
// box half-length
sVar1 = param->hitRadius;
// position of object hitting
// tiger temple teeth
// param[0] = posX,
// param[1] = posY,
// param[2] = posZ,
// Make hitbox, min and max x,y,z
param->min[0] = param->pos[0] - sVar1;
param->min[1] = param->pos[1] - sVar1;
param->min[2] = param->pos[2] - sVar1;
param->max[0] = param->pos[0] + sVar1;
param->max[1] = param->pos[1] + sVar1;
param->max[2] = param->pos[2] + sVar1;
COLL_SearchTree_FindX(&gGT->level1->ptrModelsPtrArray,param->funcCallback,THREAD_PerVisData_CheckInstances);
return;
}

View File

@ -663,20 +663,20 @@ void DECOMP_UI_CupStandings_UpdateCupRanks(void)
puVar16 = ((int) & local_50 + difficulty * 2);
// add cupID to bit
uVar6 = (int) puVar16 + gGT->cup.cupID;
uVar6 = (int)puVar16[gGT->cup.cupID];
// byte index
byteIndex = (int) uVar6 >> 5;
// Save record that this cup, on this difficulty, was won
sdata->gameProgress.unlocks[byteIndex] = sdata->gameProgress.unlocks[byteIndex] | 1 << (uVar6 & 0x1f);
sdata->gameProgress.unlocks[byteIndex] |= 1 << uVar6;
// bit index of cup completion on this difficulty (prior to now)
uVar6 = (int)((int) & local_48 + difficulty * 2) + gGT->cup.cupID;
// If this cup was not previuosly beaten on this difficulty,
// and this is the first time the cup was won
if (((u_int) sdata->gameProgress.unlocks[(int) uVar6 >> 5] >> (uVar6 & 0x1f) & 1) == 0) {
if ((sdata->gameProgress.unlocks[byteIndex] >> uVar6 & 1) == 0) {
// gGT->0x8 | 0x1000,
// lets 233 know to prompt the Save Game box
@ -692,7 +692,7 @@ void DECOMP_UI_CupStandings_UpdateCupRanks(void)
for (i = 0; i < 4; i++) {
// if any of four cups on this difficulty was not won
if (((u_int) sdata->gameProgress.unlocks[(int) uVar6 >> 5] >> (uVar6 & 0x1f) & 1) == 0) {
if ((sdata->gameProgress.unlocks[uVar6 >> 5] >> uVar6 & 1) == 0) {
// you dont deserve to unlock a battle map
wonCup = false;
break;

View File

@ -1,119 +0,0 @@
#include <common.h>
void Turbo_Increment(int param_1, int param_2, u_int param_3, int param_4);
void Voiceline_RequestPlay(u_int param_1, u_int param_2, u_int param_3);
void DECOMP_UI_JumpMeter_Update(struct Driver* driver)
{
short jumpMeter;
int jumpMeterMinus32ms;
//if player is not in the air
if ((driver->actionsFlagSet & 0x80000) == 0)
{
//if, in previous frame? player was not in the air either
if ((driver->actionsFlagSetPrevFrame & 0x80000) == 0)
{
//if Jump meter Timer is done
if (driver->jumpMeterTimer == 0)
{
//reset Jump meter
driver->jumpMeter = 0;
}
//if Jump meter Timer is not done
else
{
jumpMeterMinus32ms = (u_int)driver->jumpMeterTimer - (u_int)*(u_short *)sdata->gGT->elapsedTimeMS;
//reduce Jump meter Timer by ~32ms
driver->jumpMeterTimer = (short)jumpMeterMinus32ms;
//if Jump meter Timer goes negative
if (jumpMeterMinus32ms * 0x10000 < 0)
{
//prevent Jump meter Timer from going negative
driver->jumpMeterTimer = 0;
}
}
}
//if, in previous frame? player was in the air
else
{
//jumpMeterMinus32ms = Jump meter
jumpMeterMinus32ms = (int)driver->jumpMeter;
// if jump is high enough to be significant
if (jumpMeterMinus32ms > 336)
{
// keep track of all jumps
driver->timeSpentJumping += jumpMeterMinus32ms;
jumpMeterMinus32ms = (int)driver->jumpMeter;
}
// if highest jump is less than current jump
if (*(short *)driver->highestJump < jumpMeterMinus32ms)
{
// save highest jump
*(u_short *)driver->highestJump = driver->jumpMeter;
}
jumpMeter = driver->jumpMeter;
if (jumpMeter < 1440)
{
if (jumpMeter < 960)
{
//if Jump meter > 639
if (jumpMeter > 639)
{
// add one second reserves
Turbo_Increment(driver, 960, 2, 0);
}
}
//if Jump meter >= 960
else
{
// Turbo_Increment
// add one second reserves, plus speed
Turbo_Increment(driver, 960, 2, 0x80);
}
}
//if Jump meter >= 1440
else
{
// add one second reserves, plus speed
Turbo_Increment(driver, 960, 2, 0x100);
}
}
}
//if player is in the air
else
{
if ((driver->jump_LandingBoost > 1152) && (driver->jumpMeter < 1153))
{
//Jump meter related operation
// Make driver talk
Voiceline_RequestPlay(7, (int)data.characterIDs[driver->driverID], 0x10);
}
driver->jumpMeter = driver->jump_LandingBoost;
//if Jump meter > 2400
if (driver->jump_LandingBoost > 2400)
{
//prevent Jump meter from going over 2400
driver->jumpMeter = 2400;
}
//keep Jump meter Timer at 1440.
driver->jumpMeterTimer = 1440;
}
return;
}

View File

@ -1,124 +1,22 @@
// MATH_Sin(angle)
int FUN_8003d184(uint param_1)
#include <common.h>
{
int iVar1;
// approximate trigonometry
iVar1 = *(int *)(&DAT_800845a0 + (param_1 & 0x3ff) * 4);
// if (0 < angle < 90) or (180 < angle < 270)
if ((param_1 & 0x400) == 0)
{
// shift bottom 2-byte to become top 2-byte
iVar1 = iVar1 << 0x10;
}
// move top 2-byte to bottom 2-byte,
// and make top 2-byte zero
iVar1 = iVar1 >> 0x10;
// if (angle > 180)
if ((param_1 & 0x800) != 0)
{
// make negative
iVar1 = -iVar1;
}
return iVar1;
}
// MATH_Cos(angle)
int FUN_8003d1c0(uint param_1)
{
int iVar1;
// if (0 < angle < 90) or (180 < angle < 270)
if ((param_1 & 0x400) == 0)
{
// approximate trigonometry, then shift top bytes to bottom
iVar1 = *(int *)(&DAT_800845a0 + (param_1 & 0x3ff) * 4) >> 0x10;
// if (180 < angle < 270)
if ((param_1 & 0x800) != 0)
{
// convert negativeY into positiveX
iVar1 = -iVar1;
}
}
// if (90 < angle < 180) or (270 < angle < 360)
else
{
// approximate trigonometry, use bottom bytes
iVar1 = (int)(short)*(int *)(&DAT_800845a0 + (param_1 & 0x3ff) * 4);
// if (90 < angle < 180)
if ((param_1 & 0x800) == 0)
{
// convert negativeX into positiveX
iVar1 = -iVar1;
}
}
return iVar1;
}
// prediction
// f(i,j) = f(i,0) * f(1,j)
// f(i,0) = approx square root
// f(1,j) = 2^(j/2)
int FUN_8003d214(uint param_1,int param_2)
{
bool bVar1;
uint uVar2;
int iVar3;
uint uVar4;
int iVar5;
int iVar6;
uVar2 = 0;
iVar3 = (param_2 >> 1) + 0xf;
iVar5 = 0;
do {
uVar2 = uVar2 << 2 | param_1 >> 0x1e;
iVar6 = iVar5 * 2;
uVar4 = iVar5 * 4 + 1;
param_1 = param_1 << 2;
if (uVar4 <= uVar2) {
uVar2 = uVar2 - uVar4;
iVar6 = iVar6 + 1;
}
bVar1 = iVar3 != 0;
iVar3 = iVar3 + -1;
iVar5 = iVar6;
} while (bVar1);
return iVar6;
}
// param_1 matrix output
// param_2 matrix input
// only used by flamejet and PapuPyramidPlant for hitbox collision,
// also used by missile, probably hitbox again
// MATH_HitboxMatrix
undefined8 FUN_8003d264(uint *param_1,uint *param_2)
MATRIX* MATH_HitboxMatrix(MATRIX* output, MATRIX* input)
{
short sVar1;
uint uVar2;
uint uVar3;
uint uVar4;
uint uVar5;
unsigned int uVar2;
unsigned int uVar3;
unsigned int uVar4;
unsigned int uVar5;
// transpose matrix
uVar5 = *param_2 & 0xffff | param_2[1] & 0xffff0000;
uVar4 = param_2[3] & 0xffff | *param_2 & 0xffff0000;
uVar2 = param_2[2] & 0xffff | param_2[3] & 0xffff0000;
uVar3 = param_2[1] & 0xffff | param_2[2] & 0xffff0000;
sVar1 = *(short *)(param_2 + 4);
uVar5 = input->m[0][0] & 0xffff | input->m[0][1] & 0xffff0000;
uVar4 = input->m[1][0] & 0xffff | input->m[0][0] & 0xffff0000;
uVar2 = input->m[0][2] & 0xffff | input->m[1][0] & 0xffff0000;
uVar3 = input->m[0][1] & 0xffff | input->m[0][2] & 0xffff0000;
sVar1 = input->m[1][1];
// store matrix into GTE
gte_ldR11R12(uVar5);
@ -127,95 +25,65 @@ undefined8 FUN_8003d264(uint *param_1,uint *param_2)
gte_ldR31R32(uVar3);
gte_ldR33((int)sVar1);
gte_ldVXY0(-param_2[5] & 0xffff | param_2[6] * -0x10000);
gte_ldVZ0(-param_2[7]);
gte_ldVXY0(-(input->m[1][2]) & 0xffff |input->m[2][0] * -0x10000);
gte_ldVZ0(-(input->m[2][1]));
gte_rtv0();
*param_1 = uVar5;
param_1[1] = uVar4;
param_1[2] = uVar2;
param_1[3] = uVar3;
output->m[0][0] = uVar5;
output->m[0][1] = uVar4;
output->m[0][2] = uVar2;
output->m[1][0] = uVar3;
*(short *)(param_1 + 4) = sVar1;
gte_stlvnl((VECTOR *)(param_1 + 5));
output->m[1][1]= sVar1;
gte_stlvnl((VECTOR *)output->m[1][2]);
return;
}
// MATH_VectorLength
void FUN_8003d328(undefined4 *param_1)
void MATH_VectorLength(VECTOR* input)
{
undefined4 uVar1;
unsigned int uVar1;
gte_ldR11R12(*param_1);
gte_ldR13R21((int)*(short *)(param_1 + 1));
gte_ldVXY0(*param_1);
gte_ldVZ0((int)*(short *)(param_1 + 1));
gte_ldR11R12(input->vx);
gte_ldR13R21(input->vy);
gte_ldVXY0(input->vx);
gte_ldVZ0(input->vy);
gte_mvmva(0,0,0,3,0);
uVar1 = gte_stMAC1();
SquareRoot0(uVar1);
return;
}
// MATH_VectorNormalize
int FUN_8003d378(short *param_1)
int MATH_VectorNormalize(VECTOR* input)
{
int iVar1;
int length;
// MATH_VectorLength
iVar1 = FUN_8003d328();
length = MATH_VectorLength();
if (iVar1 != 0) {
if (iVar1 == 0) {
if (length != 0) {
if (length == 0) {
trap(0x1c00);
}
if ((iVar1 == -1) && ((int)*param_1 << 0xc == -0x80000000)) {
if ((length == -1) && (input->vx | input->vy | input->vz) == 0x8000) {
trap(0x1800);
}
if (iVar1 == 0) {
trap(0x1c00);
}
if ((iVar1 == -1) && ((int)param_1[1] << 0xc == -0x80000000)) {
trap(0x1800);
}
if (iVar1 == 0) {
trap(0x1c00);
}
if ((iVar1 == -1) && ((int)param_1[2] << 0xc == -0x80000000)) {
trap(0x1800);
}
*param_1 = (short)(((int)*param_1 << 0xc) / iVar1);
param_1[1] = (short)(((int)param_1[1] << 0xc) / iVar1);
param_1[2] = (short)(((int)param_1[2] << 0xc) / iVar1);
input->vx = (short)((input->vx << 0xc) / length);
input->vy = (short)((input->vy << 0xc) / length);
input->vz = (short)((input->vz << 0xc) / length);
}
return iVar1;
return length;
}
// MATH_MatrixMul
// Inspired by Spyro 2 USA demo, with 94426 variable names
void FUN_8003d460(int param_1,MATRIX *param_2,int param_3)
void MATH_MatrixMul(MATRIX* output, MATRIX* input,VECTOR* rotate)
{
// param_3 - input
// param_1 - output
// MatrixRotate (param_1 = param_2 matrix rotated by param_3 matrix)
FUN_8006c3b0(param_1, param_2, param_3);
// FUN_8006c6f0
// param_2 - matrix input
// param_3+14 - vector input
// param_1+14 - vector output
ApplyMatrixLV(param_2,(VECTOR *)(param_3 + 0x14),(VECTOR *)(param_1 + 0x14));
MatrixRotate(output, input, rotate);
ApplyMatrixLV(input,rotate->vx,(VECTOR *)(output->t[0]));
// Add Matrix2's position to Matrix1's position
*(int *)(param_1 + 0x14) = *(int *)(param_1 + 0x14) + param_2->t[0];
*(int *)(param_1 + 0x18) = *(int *)(param_1 + 0x18) + param_2->t[1];
*(int *)(param_1 + 0x1c) = *(int *)(param_1 + 0x1c) + param_2->t[2];
output->t[0] += param_2->t[0];
output->t[1] += param_2->t[1];
output->t[2] += param_2->t[2];
return;
}