CTR-ModSDK/ghidra/RefreshCard.c
2024-07-25 23:06:56 -04:00

1344 lines
28 KiB
C

// RefreshCard_BoolGhostForLEV
int FUN_800469f0(short param_1)
{
short sVar1;
int iVar2;
short sVar3;
sVar3 = 0;
iVar2 = 0;
sVar1 = 0;
// if ghost profiles are present
if (0 < DAT_8009aa5c)
{
// loop through ghost profiles
do {
sVar3 = sVar1;
sVar1 = (short)iVar2;
iVar2 = iVar2 + 1;
// Check trackID of each profile
if ((&DAT_8009aa88)[sVar1 * 0x1a] == param_1) {
sVar3 = sVar3 + 1;
}
sVar1 = sVar3;
} while (iVar2 * 0x10000 >> 0x10 < (int)DAT_8009aa5c);
}
return (int)sVar3;
}
void FUN_80046a74(void)
{
DAT_8009aa30 = DAT_8009aa30 & 0xfffffff7 | 6;
return;
}
// RefreshCard_GetResult
uint FUN_80046a90(short param_1)
{
uint uVar1;
if ((param_1 == 8) && ((DAT_8009aa30 & 6) != 0)) {
return 1;
}
uVar1 = 0;
if (
((DAT_8009aa30 & 6) == 0) &&
// if frame3 == frame4
(DAT_8009aa3e == DAT_8009aa42) &&
(DAT_8009aa40 == DAT_8009aa44)
)
{
// is desired_memcardResult == WhatYouLookFor?
uVar1 = (uint)(DAT_8009aa34 == param_1);
}
return uVar1;
}
// param1 - memcardSlot
// param2 - action
// param3 - filename
// param4 - memcard icon header
// param5 - ghostHeader
// param6 - size
void FUN_80046b1c(undefined2 param_1,undefined2 param_2,undefined4 param_3,undefined4 param_4,
undefined4 param_5,undefined2 param_6)
{
DAT_8009aa30 = DAT_8009aa30 & 0xfffffff7;
// frame2_memcardAction
// frame2_memcardSlot
DAT_8009aa3a = param_2;
DAT_8009aa3c = param_1;
// frame4_memcardAction
// frame4_memcardSlot
DAT_8009aa42 = param_2;
DAT_8009aa44 = param_1;
// Save filename (BASCUS...)
DAT_8009aa48 = param_3;
// Save icon (crash/ghost/psyqhand)
DAT_8009aa4c = param_4;
// pointer to ghostHeader (not memcard)
DAT_8009aa50 = param_5;
// size (3E00)
DAT_8009aa54 = param_6;
return;
}
// RefreshCard_GhostEncodeByte
uint FUN_80046b60(int param_1)
{
// only called from RefreshCard_GhostEncodeProfile
uint uVar1;
short sVar2;
sVar2 = (short)param_1;
if (sVar2 < 10) {
return param_1 + 0x30U & 0xff;
}
if (sVar2 < 0x24) {
return param_1 + 0x37U & 0xff;
}
if (sVar2 < 0x3e) {
uVar1 = param_1 + 0x3dU & 0xff;
}
else {
uVar1 = 0x2d;
if (sVar2 != 0x3e) {
return 0x5f;
}
}
return uVar1;
}
// RefreshCard_GhostDecodeByte
int FUN_80046bc0(byte param_1)
{
// only called from RefreshCard_GhostDecodeProfile
if (param_1 == 0x2d) {
return 0x3e;
}
if (param_1 == 0x5f) {
return 0x3f;
}
if (param_1 < 0x3a) {
return (uint)param_1 - 0x30;
}
if (0x5a < param_1) {
return (int)(((uint)param_1 + 0xffc3) * 0x10000) >> 0x10;
}
return (int)(((uint)param_1 + 0xffc9) * 0x10000) >> 0x10;
}
// WARNING: Removing unreachable block (ram,0x80046e88)
// WARNING: Removing unreachable block (ram,0x80046ed4)
// WARNING: Globals starting with '_' overlap smaller symbols at the same address
// RefreshCard_GhostEncodeProfile
void FUN_80046c30(
uint param_1, // index to save (or load) to
ushort param_2, // character ID array
ushort param_3, // Level ID Array
int param_4, // amount of time
undefined4 *param_5) // string typed from OSK
{
bool bVar1;
undefined4 *puVar2;
undefined uVar3;
byte bVar4;
int iVar5;
char *pcVar6;
undefined4 *puVar7;
undefined4 uVar8;
undefined4 uVar9;
undefined4 uVar10;
uint uVar11;
uint uVar12;
uint uVar13;
int iVar14;
undefined4 *puVar15;
undefined4 *puVar16;
char local_138 [128];
undefined4 local_b8 [32];
ushort local_38;
uint local_30;
local_30 = SEXT24((short)param_2);
local_38 = param_2;
do {
bVar1 = true;
// if time is more than 9:59:99
if (0x8c9ff < param_4)
{
// set time to 9:59:99
param_4 = 0x8c9ff;
}
uVar11 = local_30 | (int)((uint)param_3 << 0x10) >> 0xc;
uVar12 = uVar11 | param_4 << 9;
uVar13 = uVar12 | param_1 << 0x1d;
// RefreshCard_GhostEncodeByte
uVar3 = FUN_80046b60(uVar11 & 0x3f);
_DAT_80085a3c = CONCAT11(uVar3,DAT_80085a3c);
_DAT_80085a3c = _DAT_80085a3c & 0xffff0000 | (uint)_DAT_80085a3c;
// RefreshCard_GhostEncodeByte
uVar3 = FUN_80046b60((uVar12 & 0xfc0) >> 6);
_DAT_80085a3c = CONCAT12(uVar3,_DAT_80085a3c);
_DAT_80085a3c = _DAT_80085a3c & 0xff000000 | (uint)_DAT_80085a3c;
// RefreshCard_GhostEncodeByte
bVar4 = FUN_80046b60((uVar12 & 0x3f000) >> 0xc);
_DAT_80085a3c = _DAT_80085a3c & 0xffffff | (uint)bVar4 << 0x18;
bVar4 = FUN_80046b60((uVar12 & 0xfc0000) >> 0x12);
_DAT_80085a40 = _DAT_80085a40 & 0xffffff00 | (uint)bVar4;
// RefreshCard_GhostEncodeByte
uVar3 = FUN_80046b60(uVar13 >> 0x18 & 0x3f);
_DAT_80085a40 = CONCAT11(uVar3,DAT_80085a40);
_DAT_80085a40 = _DAT_80085a40 & 0xffff0000 | (uint)_DAT_80085a40;
// RefreshCard_GhostEncodeByte
uVar3 = FUN_80046b60(uVar13 >> 0x1e);
// loop counter
iVar14 = 0;
_DAT_80085a40 = (uint)CONCAT12(uVar3,_DAT_80085a40);
// If there is ghost data to load
if (0 < DAT_8009aa5c)
{
// for iVar14 = 0; iVar14 < numGhosts; iVar14++
do {
iVar5 = strcmp();
// increment loop counter
iVar14 = iVar14 + 1;
if (iVar5 == 0) {
bVar1 = false;
break;
}
} while (iVar14 * 0x10000 >> 0x10 < (int)DAT_8009aa5c);
}
param_1 = param_1 + 1 & 7;
if (bVar1)
{
local_138[0] = '\0';
// length of string
iVar14 = strlen();
// param_3 = levelID
strcat(
// append end of string
local_138 + iVar14,
// lngStrings[MetaDataLEV[id].name_LNG]
*(char **)((int)*(short *)(&DAT_80083a88 + (int)(short)param_3 * 0x18) * 4 +
DAT_8008d878)
);
// ":"
strcat(local_138,&DAT_8008d46c);
// length of string
iVar14 = strlen();
// local_38 = 80086E84
strcat(
// append end of string
local_138 + iVar14,
// lngStrings[MetaDataCharacters[id].name_LNG_long]
*(char **)((int)*(short *)(&DAT_80086d8a + ((int)((uint)local_38 << 0x10) >> 0xc)) * 4
+ DAT_8008d878)
);
// ":"
strcat(local_138,&DAT_8008d46c);
// make a string with amount of time
// param_4 is the number of milliseconds in the race (or lap)
pcVar6 = (char *)FUN_80044ff8(param_4);
// append end of string
strcat(local_138,pcVar6);
// CTR_ScrambleGhostString (why?)
FUN_80022234(local_b8,local_138);
puVar2 = &DAT_800992a4;
puVar16 = local_b8;
do {
puVar15 = puVar16;
puVar7 = puVar2;
uVar9 = puVar15[1];
uVar8 = puVar15[2];
uVar10 = puVar15[3];
*puVar7 = *puVar15;
puVar7[1] = uVar9;
puVar7[2] = uVar8;
puVar7[3] = uVar10;
puVar16 = puVar15 + 4;
puVar2 = puVar7 + 4;
} while (puVar16 != local_b8 + 0xc);
uVar10 = puVar15[5];
uVar8 = puVar15[6];
uVar3 = *(undefined *)(puVar15 + 7);
puVar7[4] = *puVar16;
puVar7[5] = uVar10;
puVar7[6] = uVar8;
*(undefined *)(puVar7 + 7) = uVar3;
*(undefined *)((int)puVar7 + 0x1d) = *(undefined *)((int)puVar15 + 0x1d);
// WARNING: Read-only address (ram,0x8009abe5) is written
// WARNING: Read-only address (ram,0x8009abe9) is written
// copy string into ghostProfile_current
DAT_8009abcc = DAT_80085a30;
DAT_8009abd0 = DAT_80085a34;
DAT_8009abd4 = DAT_80085a38;
DAT_8009abd8 = _DAT_80085a3c;
DAT_8009abdc = _DAT_80085a40;
// 80085a44
// BASCUS-94426G*
DAT_8009abe0._0_1_ = s_BASCUS_94426G__80085a44[0];
// OSK name
ram0x8009abe1 = *param_5;
ram0x8009abe5 = param_5[1];
ram0x8009abe9 = param_5[2];
DAT_8009abed = param_5[3];
DAT_8009abf1 = *(undefined *)(param_5 + 4);
DAT_8009abf2 = 1;
// trackID
DAT_8009abf4 = param_3;
// characterID
DAT_8009abf6 = local_38;
DAT_8009abf8 = (short)param_1;
DAT_8009abfc = param_4;
return;
}
} while( true );
}
// RefreshCard_GhostDecodeProfile
void FUN_80047034(undefined4 *param_1,undefined4 *param_2)
{
undefined uVar1;
ushort uVar2;
int iVar3;
int iVar4;
int iVar5;
int iVar6;
int iVar7;
undefined4 uVar8;
undefined4 uVar9;
undefined4 uVar10;
uint uVar11;
uint uVar12;
// RefreshCard_GhostDecodeByte
uVar2 = FUN_80046bc0((uint)*(byte *)((int)param_2 + 0xd));
iVar3 = FUN_80046bc0((uint)*(byte *)((int)param_2 + 0xe));
iVar4 = FUN_80046bc0((uint)*(byte *)((int)param_2 + 0xf));
iVar5 = FUN_80046bc0((uint)*(byte *)((int)param_2 + 0x10));
iVar6 = FUN_80046bc0((uint)*(byte *)((int)param_2 + 0x11));
iVar7 = FUN_80046bc0((uint)*(byte *)((int)param_2 + 0x12));
uVar11 = (int)(short)uVar2 | (iVar3 << 0x10) >> 10;
uVar12 = uVar11 | (iVar4 << 0x10) >> 4 | iVar5 << 0x12 | iVar6 << 0x18;
*(ushort *)((int)param_1 + 0x2a) = uVar2 & 0xf;
*(short *)(param_1 + 10) = (short)((uVar11 & 0x1f0) >> 4);
param_1[0xc] = (uVar12 & 0x1ffffe00) >> 9;
*(ushort *)(param_1 + 0xb) =
((ushort)(uVar12 >> 0x10) | (ushort)((uint)(iVar7 << 0x1e) >> 0x10)) >> 0xd;
*(undefined *)((int)param_1 + 0x26) = 0;
uVar8 = param_2[1];
uVar9 = param_2[2];
uVar10 = param_2[3];
*param_1 = *param_2;
param_1[1] = uVar8;
param_1[2] = uVar9;
param_1[3] = uVar10;
uVar1 = *(undefined *)(param_2 + 5);
param_1[4] = param_2[4];
*(undefined *)(param_1 + 5) = uVar1;
*(undefined *)((int)param_1 + 0x29) = 0;
return;
}
// RefreshCard_StartMemcardAction
// MC_START_xxx enum from regionsEXE.h
void FUN_80047198(undefined2 param_1)
{
DAT_8008d478 = param_1;
DAT_8008d964 = 0;
// boolError
DAT_8008d984 = 0;
return;
}
// RefreshCard_StopMemcardAction
void FUN_800471ac(void)
{
// memcard action = null
DAT_8008d478 = 2;
DAT_8008d964 = 1;
return;
}
// RefreshCard_SetScreenText
void FUN_800471c4(undefined2 param_1)
{
DAT_8008d47a = param_1;
FUN_80046a74();
return;
}
void FUN_800471e8(void)
{
// boolAdvProfilesChecked
if (DAT_8008d968 == 0)
{
// GAMEPROG_InitFullMemcard
// 8008d474 is ptr to memcard data,
// reset and reload with new memcard
FUN_80026c24(PTR_DAT_8008d474);
// boolAdvProfilesChecked
DAT_8008d968 = 1;
}
DAT_8008d928 = 0;
DAT_8008d95c = 1;
return;
}
// RefreshCard_GetNumGhostsTotal
void FUN_80047224(void)
{
// By default, there are zero ghosts available to load
DAT_8009aa5c = 0;
return;
}
// RefreshCard_GameProgressAndOptions
void FUN_80047230(void)
{
undefined4 *puVar1;
undefined4 *puVar2;
undefined4 *puVar3;
undefined4 *puVar4;
undefined4 uVar5;
undefined4 uVar6;
undefined4 uVar7;
undefined4 *puVar8;
DAT_8008d95c = 1;
DAT_8008d928 = 1;
DAT_8008d96c = 0xffff;
// GAMEPROG_SyncGameAndCard
// params are: memcardPtr, ram ptr
// not "save", more like "sync" memcard and ram
FUN_80026d7c(PTR_DAT_8008d474 + 0x144,&DAT_8008e6e8);
// pointer to memcard GameProgress and partially GameOptions
puVar2 = (undefined4 *)(PTR_DAT_8008d474 + 0x15f4);
puVar4 = (undefined4 *)(PTR_DAT_8008d474 + 0x144);
// GameProgress struct
puVar1 = &DAT_8008e6e8;
// Copy to memory card
do {
puVar8 = puVar1;
puVar3 = puVar4;
uVar5 = puVar3[1];
uVar6 = puVar3[2];
uVar7 = puVar3[3];
*puVar8 = *puVar3;
puVar8[1] = uVar5;
puVar8[2] = uVar6;
puVar8[3] = uVar7;
puVar4 = puVar3 + 4;
puVar1 = puVar8 + 4;
} while (puVar4 != puVar2);
uVar5 = puVar3[5];
uVar6 = puVar3[6];
puVar8[4] = *puVar4;
puVar8[5] = uVar5;
puVar8[6] = uVar6;
// RaceConfig_LoadGameOptions
FUN_80043c10();
return;
}
void FUN_800472d0(void)
{
bool bVar1;
int iVar2;
int iVar3;
undefined4 local_1c;
undefined4 *puVar4;
undefined4 uVar5;
char *pcVar6;
undefined4 *puVar7;
undefined4 uVar8;
undefined *local_20;
bVar1 = false;
switch(DAT_8008d47a)
{
// MC_SCREEN_WARNING_NOCARD
case 0:
bVar1 = true;
// memcard action = null
DAT_8008d478 = 2;
// boolError
DAT_8008d984 = 1;
break;
// MC_SCREEN_WARNING_UNFORMATTED
case 1:
// If not MC_START_LOAD_MAIN
if (DAT_8008d478 != 7)
{
// memcard action = null
DAT_8008d478 = 2;
goto LAB_800475b4;
}
// From here on...
// MC_START_LOAD_MAIN
// memcard action = null
DAT_8008d478 = 2;
// RefreshCard_SetScreenText
FUN_800471c4();
// MC_ACTION_Format
uVar5 = 4;
// 800859e4
// BASCUS-94426-SLOTS
pcVar6 = s_BASCUS_94426_SLOTS_800859e4;
puVar7 = (undefined4 *)0x0;
local_20 = (undefined *)0x0;
local_1c = 0;
LAB_80047544:
FUN_80046b1c(0,uVar5,pcVar6,puVar7,local_20,local_1c);
// boolError
DAT_8008d984 = 0;
break;
// MC_SCREEN_CHECKING
// MC_SCREEN_ERROR_FULL
case 5:
case 6:
bVar1 = true;
break;
// MC_SCREEN_ERROR_TIMEOUT
// MC_SCREEN_NULL
// MC_SCREEN_ERROR_NODATA
case 7:
case 8:
case 9:
// MC_START_LOAD_GHOST
if (DAT_8008d478 == 5)
{
// RefreshCard_SetScreenText(MC_SCREEN_LOADING)
FUN_800471c4(4);
// 3 = MC_ACTION_Load
FUN_80046b1c(0,3,&DAT_8009aa60 + (int)DAT_8009aa5a * 0x34,0,DAT_8008d754,0x3e00);
}
else
{
// < 6
if (DAT_8008d478 < 6)
{
// MC_START_SAVE_MAIN
if (DAT_8008d478 == 3)
{
// memcard action = null
DAT_8008d478 = 2;
// RefreshCard_SetScreenText(MC_SCREEN_SAVING)
FUN_800471c4(3);
// 800859e4
// BASCUS-94426-SLOTS
pcVar6 = s_BASCUS_94426_SLOTS_800859e4;
// memcardIcon_HeaderSLOTS
puVar7 = (undefined4 *)&DAT_800859f8;
// size of memory card buffer
local_1c = 0x1680;
// 8008d470 -> 800992E4, holds all memory card bytes
local_20 = PTR_DAT_8008d470;
LAB_8004753c:
// MC_ACTION_Save
uVar5 = 2;
goto LAB_80047544;
}
}
// >= 6
else {
// MC_START_SAVE_GHOST
if (DAT_8008d478 == 6)
{
// First Frame of Overwriting Old Save
if (-1 < (int)DAT_8009aa56)
{
// Get offset in array based on index,
// the string of each profile is 0x34 bytes apart
iVar2 = (int)DAT_8009aa56 * 0x34;
// This happens as soon as you start saving ghost,
// and "Saving..." appears on the screen
// Generate 0x14-character string for profile name
// BASCUS-94426GT xxxxx
DAT_80099284 = *(undefined4 *)(&DAT_8009aa60 + iVar2);
DAT_80099288 = *(undefined4 *)(&DAT_8009aa64 + iVar2);
DAT_8009928c = *(undefined4 *)(&DAT_8009aa68 + iVar2);
DAT_80099290 = *(undefined4 *)(&DAT_8009aa6c + iVar2);
DAT_80099294 = *(undefined4 *)(&DAT_8009aa70 + iVar2);
DAT_80099298 = (&DAT_8009aa74)[iVar2];
// RefreshCard_SetScreenText(MC_SCREEN_SAVING)
FUN_800471c4(3);
// Erase old profile to make
// room for new profile being saved?
// 5 = MC_ACTION_Erase
FUN_80046b1c(0,5,&DAT_80099284,0,0,0);
// boolError
DAT_8008d984 = 0;
iVar2 = ((int)DAT_8009aa5c + -1) - (int)DAT_8009aa56;
if (iVar2 != 0)
{
// Get byte index, given array index
iVar3 = (int)DAT_8009aa56 * 0x34;
// copy the string
memmove(&DAT_8009aa60 + iVar3,&DAT_8009aa94 + iVar3,iVar2 * 0x34);
}
// decrease number of ghost profiles
DAT_8009aa5c = DAT_8009aa5c + -1;
break;
}
// RefreshCard_SetScreenText(MC_SCREEN_SAVING)
FUN_800471c4(3);
// BASCUS-94426G name
pcVar6 = (char *)&DAT_80085a30;
// memcardIcon_HeaderGHOST
puVar7 = &DAT_800992a4;
// size of two memcard slots
local_1c = 0x3e00;
// address of ghost recording buffer
local_20 = DAT_8008fbf4;
goto LAB_8004753c;
}
// if 7 or more?
}
}
LAB_800475b4:
bVar1 = true;
// boolError
DAT_8008d984 = 1;
}
// RefreshCard_GetResult(MC_RESULT_NEWCARD)
iVar2 = FUN_80046a90(3);
// if new card
if (iVar2 != 0)
{
FUN_800471e8();
// RefreshCard_GetNumGhostsTotal
FUN_80047224();
goto LAB_80047a08;
}
// RefreshCard_GetResult(MC_RESULT_ERROR_NOCARD)
iVar2 = FUN_80046a90(0);
// if memory card is present
if (iVar2 == 0)
{
// RefreshCard_GetResult(MC_RESULT_FULL)
iVar2 = FUN_80046a90(1);
// MC_SCREEN_ERROR_FULL
local_1c = 6;
if (iVar2 == 0) {
// RefreshCard_GetResult(MC_RESULT_ERROR_TIMEOUT)
iVar2 = FUN_80046a90(2);
// no TIMEOUT
if (iVar2 == 0)
{
// RefreshCard_GetResult(MC_RESULT_ERROR_NODATA)
iVar2 = FUN_80046a90(5);
// if data found on memcard
if (iVar2 == 0)
{
// RefreshCard_GetResult(READY_LOAD)
iVar2 = FUN_80046a90(4);
if (iVar2 != 0)
{
LAB_800479bc:
// wrapper for resetting GameProg
FUN_800471e8();
DAT_8008d95c = 0;
// boolAdvProfilesChecked
// reload with new memory card
DAT_8008d968 = 0;
// RefreshCard_SetScreenText(MC_SCREEN_LOADING)
FUN_800471c4(4);
// MC_ACTION_Load
uVar5 = 3;
// 800859e4
// BASCUS-94426-SLOTS
pcVar6 = s_BASCUS_94426_SLOTS_800859e4;
puVar7 = (undefined4 *)0x0;
// size of memory card buffer
local_1c = 0x1680;
// 8008d470 -> 800992E4, holds all memory card bytes
local_20 = PTR_DAT_8008d470;
LAB_800479f4:
bVar1 = false;
// action is save/load/format/erase
FUN_80046b1c(0,uVar5,pcVar6,puVar7,local_20,local_1c);
// boolError
DAT_8008d984 = 0;
goto LAB_80047a08;
}
// RefreshCard_GetResult(ERROR_UNFORMATTED)
iVar2 = FUN_80046a90(6);
// if unformatted
if (iVar2 != 0)
{
// RefreshCard_GetNumGhostsTotal
FUN_80047224();
FUN_800471e8();
// MC_SCREEN_WARNING_UNFORMATTED
local_1c = 1;
goto LAB_800476b4;
}
// RefreshCard_GetResult(READY_SAVE)
iVar2 = FUN_80046a90(7);
if (iVar2 == 0) goto LAB_80047a08;
// boolError
DAT_8008d984 = 1;
// MC_SCREEN_SAVING
if (DAT_8008d47a == 3)
{
// MC_START_SAVE_GHOST
if (DAT_8008d478 == 6)
{
if (-1 < DAT_8009aa56) {
DAT_8009aa56 = -1;
// RefreshCard_SetScreenText(MC_SCREEN_SAVING)
FUN_800471c4(3);
uVar5 = 2;
pcVar6 = (char *)&DAT_80085a30;
puVar7 = &DAT_800992a4;
// max size of ghost recording buffer
local_1c = 0x3e00;
// address of ghost recording buffer
local_20 = DAT_8008fbf4;
goto LAB_800479f4;
}
iVar2 = ((int)DAT_8009aa5c + -1) - (int)DAT_8009aa58;
if (iVar2 != 0)
{
// get ghost profile
iVar3 = (int)DAT_8009aa58 * 0x34;
// copy from profile array to current profile
memmove(&DAT_8009aa94 + iVar3,&DAT_8009aa60 + iVar3,iVar2 * 0x34);
}
puVar4 = &DAT_8009abcc;
puVar7 = (undefined4 *)(&DAT_8009aa60 + (int)DAT_8009aa58 * 0x34);
// increment number of ghost profiles
DAT_8009aa5c = DAT_8009aa5c + 1;
do {
local_1c = puVar4[1];
uVar5 = puVar4[2];
uVar8 = puVar4[3];
*puVar7 = *puVar4;
puVar7[1] = local_1c;
puVar7[2] = uVar5;
puVar7[3] = uVar8;
puVar4 = puVar4 + 4;
puVar7 = puVar7 + 4;
} while (puVar4 != &DAT_8009abfc);
*puVar7 = DAT_8009abfc;
}
DAT_8008d964 = 1;
// MC_SCREEN_NULL
local_1c = 8;
// memcard action = null
DAT_8008d478 = 2;
goto LAB_80047984;
}
if (DAT_8008d47a < 4)
{
// MC_SCREEN_FORMATTING
if (DAT_8008d47a == 2)
{
// RefreshCard_GetNumGhostsTotal
FUN_80047224();
FUN_800471e8();
DAT_8008d928 = 1;
if (-1 < DAT_8008d978)
{
// if chose load or save (0 or 1)
if (DAT_8008d978 < 2)
{
// 8008d474 is ptr to memcard data
// GAMEPROG_InitFullMemcard
FUN_80026c24(PTR_DAT_8008d474);
// RefreshCard_SetScreenText(MC_SCREEN_NULL)
FUN_800471c4(8);
// 1 = MC_ACTION_GetInfo
FUN_80046b1c(0,1,s_BASCUS_94426_SLOTS_800859e4,0,0,0);
bVar1 = false;
}
else {
// if you are deleting data
if (DAT_8008d978 == 2)
{
// boolError
DAT_8008d984 = 1;
}
}
}
}
goto LAB_80047a08;
}
// if not MC_SCREEN_LOADING
if (DAT_8008d47a != 4)
{
// if not MC_SCREEN_CHECKING
if (DAT_8008d47a != 5) goto LAB_80047a08;
// if MC_SCREEN_CHECKING
// RefreshCard_GetNumGhostsTotal
FUN_80047224();
goto LAB_800479bc;
}
// === if MC_SCREEN_LOADING ===
// MC_START_LOAD_GHOST
if (DAT_8008d478 == 5)
{
// you want to show a ghost during a race
DAT_8008d958 = 1;
DAT_8008d964 = 1;
// MC_SCREEN_NULL
local_1c = 8;
}
else
{
// If memory card save has correct version number
if (*(int *)PTR_DAT_8008d474 == 0x1600ffee)
{
// the save is not outdated
DAT_8008d944 = 0;
// RefreshCard_GameProgressAndOptions
FUN_80047230();
// MC_SCREEN_NULL
local_1c = 8;
}
else
{
// the save is outdated
DAT_8008d944 = 1;
FUN_800471e8();
// MC_SCREEN_ERROR_NODATA
local_1c = 9;
}
}
// RefreshCard_SetScreenText
FUN_800471c4(local_1c);
// memcard action = null
DAT_8008d478 = 2;
}
// if no data is found
else
{
// the save is not outdated
DAT_8008d944 = 0;
FUN_800471e8();
// boolError
DAT_8008d984 = 1;
// MC_SCREEN_ERROR_NODATA
local_1c = 9;
if (
(DAT_8008d978 != 0) &&
(
(
DAT_8008d978 < 0 ||
(
// MC_SCREEN_NULL
local_1c = 8,
2 < DAT_8008d978
)
)
)
)
{
goto LAB_80047a08;
}
LAB_80047984:
// boolError
DAT_8008d984 = 1;
// RefreshCard_SetScreenText
FUN_800471c4(local_1c);
}
// 1 = MC_ACTION_GetInfo
FUN_80046b1c(0,1,s_BASCUS_94426_SLOTS_800859e4,0,0,0);
bVar1 = false;
goto LAB_80047a08;
}
// TIMEOUT (no card)
FUN_800471e8();
// MC_SCREEN_ERROR_TIMEOUT
local_1c = 7;
}
}
// if no memory card
else {
FUN_800471e8();
// RefreshCard_GetNumGhostsTotal
FUN_80047224();
// MC_SCREEN_WARNING_NOCARD
local_1c = 0;
}
LAB_800476b4:
// RefreshCard_SetScreenText
FUN_800471c4(local_1c);
// 1 = MC_ACTION_GetInfo
FUN_80046b1c(0,1,s_BASCUS_94426_SLOTS_800859e4,0,0,0);
// boolError
DAT_8008d984 = 1;
bVar1 = false;
LAB_80047a08:
if ((bVar1) && (iVar2 = FUN_80046a90(8), iVar2 == 0))
{
// 1 = MC_ACTION_GetInfo
FUN_80046b1c(0,1,s_BASCUS_94426_SLOTS_800859e4,0,0,0);
}
return;
}
void FUN_80047a58(void)
{
uint uVar1;
int iVar2;
int iVar3;
int iVar4;
iVar4 = -1;
if ((DAT_8009aa30 & 1) == 0)
{
// frame1_memcardAction
if (DAT_8009aa36 != 0)
{
iVar4 = FUN_8003ddac();
// frame3 = frame1
DAT_8009aa3e = DAT_8009aa36;
DAT_8009aa40 = DAT_8009aa38;
}
}
else
{
// frame3 = frame1
DAT_8009aa3e = DAT_8009aa36;
DAT_8009aa40 = DAT_8009aa38;
uVar1 = DAT_8009aa30 & 0xfffffffe;
if ((DAT_8009aa30 & 2) == 0) {
uVar1 = DAT_8009aa30 & 0xfffffffa;
}
DAT_8009aa30 = uVar1;
// frame1_memcardAction
switch(DAT_8009aa36)
{
case 1:
// MEMCARD_GetInfo
iVar4 = FUN_8003e238((int)DAT_8009aa38);
break;
case 2:
// MEMCARD_Save
iVar4 = FUN_8003e344((int)DAT_8009aa38,DAT_8009aa48,DAT_8009aa4c,DAT_8009aa50,
(int)DAT_8009aa54,0);
break;
case 3:
// MEMCARD_Load
iVar4 = FUN_8003e29c((int)DAT_8009aa38,DAT_8009aa48,DAT_8009aa50,(int)DAT_8009aa54,0);
break;
case 4:
// MEMCARD_Format
iVar4 = FUN_8003e51c((int)DAT_8009aa38);
break;
case 5:
// MEMCARD_EraseFile
iVar4 = FUN_8003e6d4((int)DAT_8009aa38,DAT_8009aa48);
}
}
iVar2 = iVar4 << 0x10;
if (
(DAT_8009aa36 == 1) &&
(
iVar3 = iVar2 >> 0x10,
iVar2 = iVar4 << 0x10,
iVar3 == 3
)
)
{
iVar4 = 0;
// Set number of ghost profiles to zero
DAT_8009aa5c = 0;
// 80085a44
// BASCUS-94426G*
// MEMCARD_FindFirstGhost
iVar3 = FUN_8003e600((int)DAT_8009aa38,s_BASCUS_94426G__80085a44);
iVar2 = 0;
// loop until you have gone through all memory card saves
while (iVar3 != 0)
{
// If there are less than 7 ghosts loaded
if (iVar2 >> 0x10 < 7)
{
// RefreshCard_GhostDecodeProfile
FUN_80047034(&DAT_8009aa60 + (iVar2 >> 0x10) * 0x34);
// increment ghost counter
DAT_8009aa5c = DAT_8009aa5c + 1;
}
// increment number of ghosts loaded
iVar4 = iVar4 + 1;
// MEMCARD_FindNextGhost
iVar3 = FUN_8003e678();
// bitshifted version of numGhosts
iVar2 = iVar4 * 0x10000;
}
// slotIndex, and saveName
FUN_8003e59c((int)DAT_8009aa38,DAT_8009aa48);
DAT_8009aa30 = DAT_8009aa30 | 8;
// slotIndex, and saveName
iVar2 = FUN_8003e59c((int)DAT_8009aa38,DAT_8009aa48);
iVar2 = iVar2 << 0x10;
}
switch(iVar2 >> 0x10) {
// MC_RETURN_IOE (processing done)
case 0:
// MC_RESULT_READY_SAVE
DAT_8009aa34 = 7;
if (
(DAT_8009aa36 == 1) &&
(
// MC_RESULT_READY_LOAD
DAT_8009aa34 = 4,
(DAT_8009aa30 & 8) == 0
)
)
{
// MC_RESULT_READY_SAVE
DAT_8009aa34 = 7;
}
break;
// MC_RETURN TIMEOUT
case 1:
// MC_RESULT_ERROR_TIMEOUT
DAT_8009aa34 = 2;
break;
// MC_RETURN_NOCARD
case 2:
// MC_RESULT_ERROR_NOCARD
DAT_8009aa34 = 0;
DAT_8009aa36 = 0;
goto switchD_80047c84_caseD_8;
// MC_RETURN_NEWCARD
case 3:
// MC_RESULT_NEWCARD
DAT_8009aa34 = 3;
if (DAT_8009aa36 == 4)
{
// MC_RESULT_READY_SAVE
DAT_8009aa34 = 7;
}
break;
// MC_RETURN_FULL
case 4:
// MC_RESULT_FULL
DAT_8009aa34 = 1;
break;
// from FUN_8003ddac
// MC_RETURN_UNFORMATTED
case 5:
// MC_RESULT_ERROR_UNFORMATTED
DAT_8009aa34 = 6;
break;
// MC_RETURN_NODATA
case 6:
// MC_RESULT_ERROR_NODATA
DAT_8009aa34 = 5;
break;
// MC_RETURN_SUCCESS
case 7:
// MC_RESULT_FINISHED
DAT_8009aa34 = 8;
default:
goto switchD_80047c84_caseD_8;
}
// frame1_memcardAction NULL
DAT_8009aa36 = 0;
switchD_80047c84_caseD_8:
if (
// frame1_memcardAction == NULL
(DAT_8009aa36 == 0) &&
// frame2_memcardAction != NULL
(DAT_8009aa3a != 0)
)
{
// set frame1, erase frame2
DAT_8009aa36 = DAT_8009aa3a;
DAT_8009aa3a = 0;
// set frame1, leave frame2
DAT_8009aa38 = DAT_8009aa3c;
DAT_8009aa30 = DAT_8009aa30 & 0xfffffffd | 1;
}
return;
}
// spammed in main menu, adv arena, and end-of-race
// supposedly triggers memcard routines. if noped, game hangs at CHECKING... screen
// the 2 functions are only called here.
void FUN_80047d64(void)
{
// if PauseAllThreads is diabled
if ((*(uint *)PTR_DAT_8008d2ac & 0x10) == 0)
{
FUN_80047a58();
// Handles BASCUS-94426-SLOTS file for
// Adventure saves and time trial scores
FUN_800472d0();
}
return;
}