CTR-ModSDK/ghidra/MEMCARD.c
2024-07-04 16:08:59 -04:00

1283 lines
24 KiB
C

// MEMCARD_SetIcon
void FUN_8003d4e4(short param_1)
{
undefined4 *puVar1;
undefined4 *puVar2;
undefined4 *puVar3;
undefined4 uVar4;
undefined4 uVar5;
undefined4 uVar6;
// copy destination
// overwrite psyq hand
puVar2 = (undefined4 *)&DAT_800857a0;
// pick a copy source
if (param_1 == 0)
{
// ghost
puVar1 = &DAT_800856a0;
}
else
{
// crash head
puVar1 = &DAT_800855a0;
}
// last byte of copy (0x100)
puVar3 = puVar1 + 0x40;
// copy
do {
uVar4 = puVar1[1];
uVar5 = puVar1[2];
uVar6 = puVar1[3];
*puVar2 = *puVar1;
puVar2[1] = uVar4;
puVar2[2] = uVar5;
puVar2[3] = uVar6;
puVar1 = puVar1 + 4;
puVar2 = puVar2 + 4;
} while (puVar1 != puVar3);
return;
}
//calculates crc16 with polynomial p = x^16+x^12+x^5+x^0 (0x11021)
//this is a part of save game checksum calculation
//https://github.com/ShendoXT/memcardrex-plugins/blob/master/CTREdit/CTREdit/Additional/Crash Team Racing save.txt
// MEMCARD_CRC16
//param_1 - crc
//param_2 - data
uint FUN_8003d540(uint param_1,int param_2)
{
uint uVar1;
uint uVar2;
//iterator i
uVar1 = 7;
//for (i = 7; i >= 0; i--)
do {
uVar2 = param_1 << 1;
param_1 = uVar2 | param_2 >> (uVar1 & 0x1f) & 1U;
if ((uVar2 & 0x10000) != 0) {
param_1 = param_1 ^ 0x11021;
}
//i--
uVar1 = uVar1 - 1;
} while (-1 < (int)uVar1);
return param_1;
}
// MEMCARD_ChecksumSave
// calculates memcard data stream checksum
// param_1 - pointer to data
// param_2 - data length (0x3e00, or 0x1680)
void FUN_8003d584(byte *param_1,int param_2)
{
undefined2 uVar1;
byte *pbVar2;
undefined4 uVar3;
int iVar4;
//keep in mind checksum bytes are added in the end of stream
//crc
uVar3 = 0;
//iterator i
iVar4 = 0;
//pointer to data
pbVar2 = param_1;
//if data length > 0
if (0 < param_2 + -2) {
//for each entry in data
do {
//i++
iVar4 = iVar4 + 1;
//crc = MEMCARD_CRC16
uVar3 = FUN_8003d540(uVar3,(uint)*pbVar2);
//set next data entry
pbVar2 = param_1 + iVar4;
} while (iVar4 < param_2 + -2);
}
// waste, dont need to save checkpoint
DAT_8008d8d0 = uVar3;
// finalize checksum
// MEMCARD_CRC16 twice
uVar3 = FUN_8003d540(uVar3,0);
uVar1 = FUN_8003d540(uVar3,0);
// write checksum to data (last 2 bytes),
// swap endians to throw off hackers,
// which didn't really throw anyone off at all
param_1[iVar4] = (byte)((ushort)uVar1 >> 8);
param_1[iVar4 + 1] = (byte)uVar1;
return;
}
// MEMCARD_ChecksumLoad
// assumed validates memcard data checksum,
// check full memcard, all 0x1680 bytes
uint FUN_8003d618(int param_1,int param_2)
{
bool bVar1;
undefined4 uVar2;
int iVar3;
uint uVar4;
int iVar5;
// previous crc
uVar2 = DAT_8008d8d0;
// CRC start byte
iVar3 = DAT_8008d8b0;
// if not the last frame of crc16
if ((DAT_8008d8cc & 8) == 0)
{
// CRC end byte (start + 0x200)
iVar5 = DAT_8008d8b0 + 0x200;
bVar1 = false;
// if checksum is not over
if (iVar5 < param_2 + -2) goto LAB_8003d688;
}
// checksum is over, go to finalize
bVar1 = true;
// CRC end byte (last two bytes of data)
iVar5 = param_2 + -2;
LAB_8003d688:
// from start to end
while (iVar3 < iVar5)
{
// MEMCARD_CRC16
uVar2 = FUN_8003d540(uVar2,(uint)*(byte *)(param_1 + iVar3));
iVar3 = iVar3 + 1;
}
// save last byte, as the next checksum's start byte
DAT_8008d8b0 = iVar3;
// new crc
DAT_8008d8d0 = uVar2;
// if last frame of crc16
if (bVar1)
{
// finalize checksum
// MEMCARD_CRC16 twice
uVar2 = FUN_8003d540(uVar2,(uint)*(byte *)(param_1 + iVar3));
iVar3 = FUN_8003d540(uVar2,(uint)*(byte *)(param_1 + iVar3 + 1));
// return if it worked or not
uVar4 = (uint)(iVar3 != 0);
}
// if not last frame of crc16
else
{
// return 7, which means repeat step
uVar4 = 7;
}
return uVar4;
}
// MEMCARD_StringInit
// param1 - slotIndex
uint * FUN_8003d6e8(uint param_1,uint *param_2)
{
// if no paramter given
if (param_2 == (uint *)0x0)
{
// "bu00:\0"
param_2 = &DAT_8008d414;
}
// set "buXX"
// where XX depends on param_1
*param_2 = (((int)param_1 >> 4 & 1U) + 0x30) * 0x10000 |
((param_1 & 3) + 0x30) * 0x1000000 | 0x7562;
// set bytes [4,5] with a short,
// which sets ':' and '\0'
*(undefined2 *)(param_2 + 1) = 0x3a;
return param_2;
}
// MEMCARD_StringSet
// param2 slotIndex
void FUN_8003d730(char *param_1,undefined4 param_2,char *param_3)
{
char cVar1;
int iVar2;
int iVar3;
// MEMCARD_StringInit
FUN_8003d6e8(param_2,param_1);
// index
iVar3 = 0;
// destination string
if (*param_1 != '\0') {
iVar2 = 1;
do
{
// loop counter
iVar3 = iVar2;
iVar2 = iVar3 + 1;
// loop to end of string
} while (param_1[iVar3] != '\0');
}
// source string
cVar1 = *param_3;
// copy string from param_3 to param_1
while ((cVar1 != '\0' && (iVar3 < 0x3f))) {
cVar1 = *param_3;
param_3 = param_3 + 1;
param_1[iVar3] = cVar1;
cVar1 = *param_3;
iVar3 = iVar3 + 1;
}
param_1[iVar3] = '\0';
return;
}
//8003d7d8 - initializes memcard stuff - MEMCARD_Init
//- creates 8 events (4 per card?)
//- calls InitCARD and StartCARD
void FUN_8003d7d8(void)
{
// This section was copy/pasted by Naughty Dog,
// psx\sample\memcard\CARD\CARD.C lines 84 to 101
// -------------------------------------------
EnterCriticalSection();
DAT_8008d8d4 = OpenEvent(SwCARD,EvSpIOE, EvMdNOINTR, NULL);
DAT_8008d8c4 = OpenEvent(SwCARD,EvSpERROR, EvMdNOINTR, NULL);
DAT_8008d8e0 = OpenEvent(SwCARD,EvSpTIMOUT, EvMdNOINTR, NULL);
DAT_8008d8c0 = OpenEvent(SwCARD,EvSpNEW, EvMdNOINTR, NULL);
DAT_8008d8c8 = OpenEvent(HwCARD,EvSpIOE, EvMdNOINTR, NULL);
DAT_8008d8b4 = OpenEvent(HwCARD,EvSpERROR, EvMdNOINTR, NULL);
DAT_8008d8dc = OpenEvent(HwCARD,EvSpTIMOUT, EvMdNOINTR, NULL);
DAT_8008d8bc = OpenEvent(HwCARD,EvSpNEW, EvMdNOINTR, NULL);
EnableEvent(DAT_8008d8d4);
EnableEvent(DAT_8008d8c4);
EnableEvent(DAT_8008d8e0);
EnableEvent(DAT_8008d8c0);
EnableEvent(DAT_8008d8c8);
EnableEvent(DAT_8008d8b4);
EnableEvent(DAT_8008d8dc);
EnableEvent(DAT_8008d8bc);
ExitCriticalSection();
// -------------------------------------------
InitCARD(0);
StartCARD();
_bu_init();
// This tells us a memory card exists,
// If it is set to 0 with Cheat Engine,
// the game will think the card is unformatted
DAT_8008d8cc = 1;
return;
}
//8003d95c - closes memcard stuff - MEMCARD_Close
void FUN_8003d95c(void)
{
// This function was copy/pasted by Naughty Dog,
// psx\sample\memcard\CARD\CARD.C lines 355 to 365
StopCARD();
EnterCriticalSection();
CloseEvent(DAT_8008d8d4);
CloseEvent(DAT_8008d8c4);
CloseEvent(DAT_8008d8e0);
CloseEvent(DAT_8008d8c0);
CloseEvent(DAT_8008d8c8);
CloseEvent(DAT_8008d8b4);
CloseEvent(DAT_8008d8dc);
CloseEvent(DAT_8008d8bc);
ExitCriticalSection();
return;
}
//8003d9ec - tests for 1st slot events - MEMCARD_GetNextSwEvent
//- basically gets index of first triggered event or returns 7, which is no event i guess. 7 is 3 bits.
undefined4 FUN_8003d9ec(void)
{
long lVar1;
undefined4 uVar2;
// SwIOE (processing done)
lVar1 = TestEvent(DAT_8008d8d4);
uVar2 = 0;
if (lVar1 != 1)
{
// SwERROR (bad card)
lVar1 = TestEvent(DAT_8008d8c4);
uVar2 = 1;
if (lVar1 != 1)
{
// SwTIMEOUT (no card)
lVar1 = TestEvent(DAT_8008d8e0);
if (lVar1 == 1) {
uVar2 = 2;
}
else
{
// SwNEWCARD
lVar1 = TestEvent(DAT_8008d8c0);
uVar2 = 3;
if (lVar1 != 1) {
uVar2 = 7;
}
}
}
}
return uVar2;
}
//8003da68 - tests for 2nd slot events - MEMCARD_GetNextHwEvent
//- same as above but for other 4 events
undefined4 FUN_8003da68(void)
{
long lVar1;
undefined4 uVar2;
// HwIOE (processing done)
lVar1 = TestEvent(DAT_8008d8c8);
uVar2 = 0;
if (lVar1 != 1)
{
// HwERROR (bad card)
lVar1 = TestEvent(DAT_8008d8b4);
uVar2 = 1;
if (lVar1 != 1)
{
// HwTIMEOUT (no card)
lVar1 = TestEvent(DAT_8008d8dc);
if (lVar1 == 1) {
uVar2 = 2;
}
else
{
// HwNEWCARD
lVar1 = TestEvent(DAT_8008d8bc);
uVar2 = 3;
if (lVar1 != 1) {
uVar2 = 7;
}
}
}
}
return uVar2;
}
//8003dae4 - waits for event on slot1 to happen and returns index - MEMCARD_WaitForHwEvent
//- loops while there is not a single true for mc1 events
//- only called once, wonder how that doesn't halt the exection. or maybe it does, are there hangs when save/load happens?
undefined4 FUN_8003dae4(void)
{
long lVar1;
do
{
// HwIOE (processing done)
lVar1 = TestEvent(DAT_8008d8c8);
if (lVar1 == 1) {
return 0;
}
// HwERROR (bad card)
lVar1 = TestEvent(DAT_8008d8b4);
if (lVar1 == 1) {
return 1;
}
// HwTIMEOUT (no card)
lVar1 = TestEvent(DAT_8008d8dc);
if (lVar1 == 1) {
return 2;
}
// HwNEWCARD
lVar1 = TestEvent(DAT_8008d8bc);
} while (lVar1 != 1);
return 3;
}
//8003db54 - tests all events until no events left for both cards - MEMCARD_SkipEvents
//maybe it's a kind of clearing function?
undefined4 FUN_8003db54(void)
{
int iVar1;
do
{
// MEMCARD_GetNextSwEvent
iVar1 = FUN_8003d9ec();
} while (iVar1 != 7);
do
{
// MEMCARD_GetNextHwEvent
iVar1 = FUN_8003da68();
} while (iVar1 != 7);
return 7;
}
// MEMCARD_NewTask
// param1 slotIndex
// param2 name
// param3 pointer to profile
// param4 memcard size
undefined4 FUN_8003db98(undefined4 param_1,undefined4 param_2,undefined4 param_3,undefined4 param_4)
{
// card slot
DAT_8008d8b8 = param_1;
// MEMCARD_StringSet
FUN_8003d730(&DAT_800990a4,param_1,param_2);
// pointer to profile
// either Save Source, or Load Destination
DAT_8008d408 = param_3;
// reset to 8 attempts before quitting
DAT_8008d410 = 8;
// memcard size (0x1680)
DAT_8008d8a8 = param_4;
return 0;
}
// close memcard file
void FUN_8003dbf8(void)
{
// if file is open
if (DAT_8008d40c != -1)
{
// close the file
close(DAT_8008d40c);
// no file is open
DAT_8008d40c = -1;
}
DAT_8008d404 = 0;
return;
}
// MEMCARD_ReadFile
// parameters are start and end offsets
undefined4 FUN_8003dc30(long param_1,long param_2)
{
long lVar1;
// seek to start offset
lVar1 = lseek(DAT_8008d40c,param_1,0);
// read to memcard buffer in RAM, param_2 size
if ((lVar1 != -1) && (lVar1 = read(DAT_8008d40c,DAT_8008d408,param_2), lVar1 != -1))
{
// MC_RETURN_SUCCESS
return 7;
}
// close memcard file
FUN_8003dbf8();
// MC_RETURN TIMEOUT
return 1;
}
// MEMCARD_WriteFile
// start offset, pointer to data, end offset
undefined4 FUN_8003dc9c(long param_1,void *param_2,long param_3)
{
long lVar1;
// seek to start offset
lVar1 = lseek(DAT_8008d40c,param_1,0);
// write to memcard buffer in RAM, param_3 size
if ((lVar1 != -1) && (lVar1 = write(DAT_8008d40c,param_2,param_3), lVar1 != -1))
{
// MC_RETURN_SUCCESS
return 7;
}
// close memcard file
FUN_8003dbf8();
// MC_RETURN TIMEOUT
return 1;
}
// MEMCARD_GetFreeBytes
// param1 slotIndex
void FUN_8003dd10(undefined4 param_1)
{
DIRENTRY *pDVar1;
DIRENTRY *pDVar2;
int iVar3;
DIRENTRY DStack56;
// MEMCARD_StringSet
FUN_8003d730(&DAT_800990a4,param_1,&DAT_8008d41c);
// bytes used on memory card
iVar3 = 0;
// 800990a4
// string for directory and file of save that is in use
pDVar1 = firstfile(&DAT_800990a4,&DStack56);
pDVar2 = &DStack56;
while (pDVar1 == pDVar2)
{
// add to number of bytes used
iVar3 = iVar3 + (DStack56.size + 0x1fffU & 0xffffe000);
pDVar2 = nextfile(&DStack56);
}
// bytes left on memcard = 128kb - used size
DAT_8008d8ac = 0x1e000 - iVar3;
return;
}
int FUN_8003ddac(void)
{
long lVar1;
undefined4 uVar2;
int iVar3;
int iVar4;
undefined *puVar5;
switch(DAT_8008d404) {
case 1:
// MEMCARD_GetNextSwEvent
iVar3 = FUN_8003d9ec();
if (iVar3 == 0)
{
// If this is the first frame of the main game loop,
// after all initialization is done
if ((DAT_8008d8cc & 1) != 0)
{
// allow the "switch" statement to go to stage 2
DAT_8008d404 = 2;
// MEMCARD_SkipEvents do something wtih both memcards if they're present,
FUN_8003db54();
// ??
// spam read until it works?
do {
lVar1 = _card_load(DAT_8008d8b8);
} while (lVar1 != 1);
// MC_RETURN_SUCCESS
return 7;
}
if ((DAT_8008d8cc & 2) == 0)
{
// zero free bytes on memcard
DAT_8008d8ac = 0;
// MC_RETURN_UNFORMATTED
iVar3 = 5;
}
}
else {
if (iVar3 != 3) {
if (iVar3 != 7) {
DAT_8008d404 = 0;
// zero free bytes on memcard
DAT_8008d8ac = 0;
return iVar3;
}
// MC_RETURN_SUCCESS
return 7;
}
FUN_8003db54();
do {
lVar1 = _card_clear(DAT_8008d8b8);
} while (lVar1 != 1);
iVar3 = FUN_8003dae4();
if (iVar3 == 0) {
DAT_8008d404 = 2;
FUN_8003db54();
do {
lVar1 = _card_load(DAT_8008d8b8);
} while (lVar1 != 1);
// MC_RETURN_SUCCESS
return 7;
}
}
goto LAB_8003df38;
case 2:
// MEMCARD_GetNextSwEvent
iVar3 = FUN_8003d9ec();
if (iVar3 == 0) {
DAT_8008d404 = 0;
DAT_8008d8cc = DAT_8008d8cc & 0xfffffffe | 2;
// MEMCARD_GetFreeBytes
FUN_8003dd10(DAT_8008d8b8);
// MC_RETURN_NEWCARD
return 3;
}
if (iVar3 == 3)
{
DAT_8008d404 = 0;
DAT_8008d8cc = DAT_8008d8cc & 0xfffffffc;
// MC_RETURN_UNFORMATTED
return 5;
}
if (iVar3 == 7)
{
// MC_RETURN_SUCCESS
return 7;
}
LAB_8003df38:
DAT_8008d404 = 0;
break;
case 3:
// MEMCARD_GetNextSwEvent
iVar3 = FUN_8003d9ec();
if (iVar3 == 0)
{
// allow "switch" statement to go to stage 4
DAT_8008d404 = 4;
DAT_8008d8d8 = (((uint)(byte)DAT_8008d408[2] & 0xf) + 1) * 0x80;
// Read memory card
uVar2 = FUN_8003dc30(DAT_8008d8d8,DAT_8008d8a8);
if ((DAT_8008d8d8 + DAT_8008d8a8 + 0x1fff >> 0xd < (int)(uint)(byte)DAT_8008d408[3]) &&
(1 < DAT_8008d8d8 + DAT_8008d8a8 * 2 + 0x1fff >> 0xd)) {
DAT_8008d8cc = DAT_8008d8cc & 0xfffffffb;
return uVar2;
}
DAT_8008d8cc = DAT_8008d8cc | 4;
return uVar2;
}
if (iVar3 == 7) {
return 7;
}
if (0 < DAT_8008d410) {
iVar4 = 0;
iVar3 = 0x80;
// reduce remaining attempts
DAT_8008d410 = DAT_8008d410 + -1;
// go to read card
goto LAB_8003e010;
}
// go to close file
goto LAB_8003e1fc;
case 4:
case 6:
// MEMCARD_GetNextSwEvent
iVar3 = FUN_8003d9ec();
if (iVar3 == 0) {
DAT_8008d8b0 = 0;
DAT_8008d8d0 = 0;
DAT_8008d404 = DAT_8008d404 + 1;
if ((DAT_8008d8cc & 8) == 0) {
DAT_8008d8b0 = 0;
DAT_8008d8d0 = 0;
// MC_RETURN_SUCCESS
return 7;
}
goto switchD_8003dde0_caseD_5;
}
if (iVar3 == 7)
{
// MC_RETURN_SUCCESS
return 7;
}
if (0 < DAT_8008d410) {
iVar4 = DAT_8008d8d8 + (DAT_8008d404 + -4) * DAT_8008d8a8;
iVar3 = DAT_8008d8a8;
// reduce remaining attempts
DAT_8008d410 = DAT_8008d410 + -1;
// go to read card
goto LAB_8003e010;
}
// go to close file
goto LAB_8003e1fc;
case 5:
case 7:
switchD_8003dde0_caseD_5:
// MEMCARD_ChecksumLoad
// pointer to memory card, and size
iVar3 = FUN_8003d618(DAT_8008d408,DAT_8008d8a8);
if (iVar3 != 0)
{
// if checksumLoad returned 7, then the checksum
// is not finished processing, it will continue next frame
if (iVar3 == 7)
{
// MC_RETURN_SUCCESS
return 7;
}
// at this point, assume checksum succeeded (return 1)
if (((DAT_8008d8cc & 4) == 0) && (iVar4 = DAT_8008d404 + -3, DAT_8008d404 < 7))
{
// Make "switch" statement go to "next" stage
DAT_8008d404 = DAT_8008d404 + 1;
iVar4 = DAT_8008d8d8 + iVar4 * DAT_8008d8a8;
iVar3 = DAT_8008d8a8;
LAB_8003e010:
// Read memory card
uVar2 = FUN_8003dc30(iVar4,iVar3);
return uVar2;
}
}
LAB_8003e1fc:
// close memcard file
FUN_8003dbf8();
break;
default:
iVar3 = 1;
break;
case 9:
case 10:
case 0xb:
// MEMCARD_GetNextSwEvent
iVar3 = FUN_8003d9ec();
if (iVar3 == 0)
{
if ((DAT_8008d404 != 9) && ((10 < DAT_8008d404 || ((DAT_8008d8cc & 4) != 0))))
{
// close memcard file
FUN_8003dbf8();
// MEMCARD_GetFreeBytes
FUN_8003dd10(DAT_8008d8b8);
// MC_RETURN_IOE
return 0;
}
iVar3 = DAT_8008d404 + -9;
DAT_8008d404 = DAT_8008d404 + 1;
LAB_8003e1e4:
iVar4 = DAT_8008d8d8 + iVar3 * DAT_8008d8a8;
// pointer to memory card bytes
puVar5 = DAT_8008d408;
// size, 0x1680 bytes
iVar3 = DAT_8008d8a8;
}
else
{
if (iVar3 == 7)
{
// MC_RETURN_SUCCESS
return 7;
}
// reduce remaining number of attempts
iVar4 = DAT_8008d410 + -1;
// if out of attempts, go to close file
if (DAT_8008d410 < 1) goto LAB_8003e1fc;
iVar3 = DAT_8008d404 + -10;
DAT_8008d410 = iVar4;
if (DAT_8008d404 != 9) goto LAB_8003e1e4;
iVar4 = 0;
// pointer to memory card icon
// psyq hand
puVar5 = &DAT_800857a0;
// 256 bytes, 0x100
iVar3 = DAT_8008d8d8;
}
// MEMCARD_WriteFile
iVar3 = FUN_8003dc9c(iVar4,puVar5,iVar3);
break;
case 0xd:
DAT_8008d404 = 0;
iVar3 = 1;
break;
case 0xe:
DAT_8008d404 = 0;
iVar3 = 0;
}
return iVar3;
}
// MEMCARD_GetInfo
undefined4 FUN_8003e238(long param_1)
{
undefined4 uVar1;
long lVar2;
if (DAT_8008d404 == 0) {
FUN_8003db54();
DAT_8008d404 = 1;
DAT_8008d8b8 = param_1;
// loop until check is "submitted",
// result is not "returned", result
// is found in SwCARD descriptor/event (see libref)
do
{
// check if card is connected
lVar2 = _card_info(param_1);
} while (lVar2 != 1);
DAT_8008d410 = 8;
// MC_RETURN_SUCCESS
uVar1 = 7;
}
else
{
// MC_RETURN TIMEOUT
uVar1 = 1;
}
return uVar1;
}
// MEMCARD_Load
// ghidra couldn't detect parameters,
// because they were passed directly from this func to another
undefined4 FUN_8003e29c(param1, param2, param3, param4, param5)
{
int iVar1;
undefined4 uVar2;
uint param_5;
if (
(DAT_8008d404 == 0) &&
(
// MEMCARD_NewTask
iVar1 = FUN_8003db98(param1, param2, param3, param4, param5),
// this will always be true
iVar1 == 0
)
)
{
// 800990a4
// string for directory and file of save that is in use
// 0x8001, in sys/fcntl.h
// 0x8000 = FASYNC, for asynchronous I/O
// 0x0001 = FREAD, for reading
DAT_8008d40c = open(&DAT_800990a4,0x8001);
// if open failed
if (DAT_8008d40c == -1)
{
// close memcard file
FUN_8003dbf8();
// MC_RETURN_NODATA
uVar2 = 6;
}
else {
if ((param_5 & 2) == 0)
{
// dont process crc16 to the end of memory,
// just the next 0x200 bytes (async)
DAT_8008d8cc = DAT_8008d8cc & 0xfffffff7;
}
else
{
// process crc16 to the end of memory
DAT_8008d8cc = DAT_8008d8cc | 8;
}
DAT_8008d404 = 3;
// Read memory card
uVar2 = FUN_8003dc30(0,0x80);
}
}
else
{
// MC_RETURN TIMEOUT
uVar2 = 1;
}
return uVar2;
}
// MEMCARD_Save
undefined4 FUN_8003e344(undefined4 param_1,undefined4 param_2,
char *param_3,undefined4 param_4,int param_5,
uint param_6)
{
char cVar1;
int iVar2;
undefined4 uVar3;
int iVar4;
if (DAT_8008d404 == 0)
{
DAT_8008d8d8 = 0x100;
// MEMCARD_NewTask
iVar2 = FUN_8003db98(param_1,param_2,param_4,param_5);
// this will always be true
if (iVar2 == 0)
{
if (((param_6 & 1) == 0) && (1 < DAT_8008d8d8 + param_5 * 2 + 0x1fff >> 0xd)) {
DAT_800857a3 = (byte)(DAT_8008d8d8 + param_5 + 0x1fff >> 0xd);
DAT_8008d8cc = DAT_8008d8cc | 4;
}
else {
DAT_8008d8cc = DAT_8008d8cc & 0xfffffffb;
DAT_800857a3 = (byte)(DAT_8008d8d8 + param_5 * 2 + 0x1fff >> 0xd);
}
// clear icon
iVar2 = 0;
do {
iVar4 = iVar2 + 2;
(&DAT_800857a4)[iVar2] = 0x81;
(&DAT_800857a5)[iVar2] = 0x40;
iVar2 = iVar4;
} while (iVar4 < 0x40);
// file icon
cVar1 = *param_3;
iVar2 = 0;
while ((cVar1 != '\0' && (iVar2 < 0x40))) {
cVar1 = *param_3;
param_3 = param_3 + 1;
(&DAT_800857a4)[iVar2] = cVar1;
cVar1 = *param_3;
iVar2 = iVar2 + 1;
}
// MEMCARD_ChecksumSave
// ptrData, size of data
// (8009aa50 and 8009aa54)
FUN_8003d584(param_4,param_5);
// 800990a4
// string for directory and file of save that is in use
// In sys/fcntl.h
// 0x200 is FCREAT, create if it does not exist,
// DAT_800857a3 handles read or write
DAT_8008d40c = open(&DAT_800990a4,(uint)DAT_800857a3 << 0x10 | 0x200);
if (DAT_8008d40c != -1) {
close(DAT_8008d40c);
DAT_8008d40c = -1;
}
// 800990a4
// string for directory and file of save that is in use
// 0x8002, in sys/fcntl.h
// 0x8000 = FASYNC, for asynchronous I/O
// 0x0001 = FWRITE, for writing
DAT_8008d40c = open(&DAT_800990a4,0x8002);
if (DAT_8008d40c != -1) {
DAT_8008d404 = 9;
// MEMCARD_WriteFile
// and the size of the icon, psyq hand
uVar3 = FUN_8003dc9c(0,&DAT_800857a0,DAT_8008d8d8);
return uVar3;
}
// close memcard file
FUN_8003dbf8(0);
// MC_RETURN_FULL
return 4;
}
}
// MC_RETURN TIMEOUT
return 1;
}
// MEMCARD_Format
// param1 slotIndex
undefined4 FUN_8003e51c(long param_1)
{
char *pcVar1;
long lVar2;
undefined4 uVar3;
if (DAT_8008d404 == 0)
{
// MEMCARD_StringInit
pcVar1 = (char *)FUN_8003d6e8(param_1,0);
lVar2 = format(pcVar1);
uVar3 = 1;
if (lVar2 == 1) {
DAT_8008d404 = 2;
// slotIndex
DAT_8008d8b8 = param_1;
// MEMCARD_SkipEvents
FUN_8003db54();
do {
lVar2 = _card_load(DAT_8008d8b8);
} while (lVar2 != 1);
DAT_8008d410 = 8;
// MC_RETURN_SUCCESS
uVar3 = 7;
}
}
else
{
// MC_RETURN TIMEOUT
uVar3 = 1;
}
return uVar3;
}
// MEMCARD_IsFile
// param1 slotIndex
// param2 saveName
undefined4 FUN_8003e59c(undefined4 param_1,undefined4 param_2)
{
undefined4 uVar1;
char acStack72 [64];
// MEMCARD_StringSet
FUN_8003d730(acStack72,param_1,param_2);
// 0x8002, in sys/fcntl.h
// 0x8000 = FASYNC, for asynchronous I/O
// 0x0001 = FWRITE, for writing
DAT_8008d40c = open(acStack72,0x8002);
if (DAT_8008d40c == -1)
{
// MC_RETURN_NODATA
uVar1 = 6;
}
else
{
close(DAT_8008d40c);
DAT_8008d40c = -1;
// MC_RETURN_IOE
uVar1 = 0;
}
return uVar1;
}
// MEMCARD_FindFirstGhost
undefined * FUN_8003e600(undefined4 param_1,undefined4 param_2)
{
DIRENTRY *pDVar1;
DIRENTRY DStack48;
// param2 = BASCUS-94426G*
if (DAT_8008d404 == 0)
{
// MEMCARD_StringSet
FUN_8003d730(&DAT_800990a4,param_1,param_2);
// 800990a4
// string for directory and file of save that is in use
pDVar1 = firstfile(&DAT_800990a4,&DStack48);
if (pDVar1 == &DStack48) {
DAT_8008d404 = 0xf;
strcpy();
return &DAT_800990c4;
}
}
return (undefined *)0;
}
// MEMCARD_FindNextGhost
undefined * FUN_8003e678(void)
{
DIRENTRY *pDVar1;
DIRENTRY DStack48;
if (DAT_8008d404 == 0xf) {
pDVar1 = nextfile(&DStack48);
if (pDVar1 == &DStack48) {
strcpy();
return &DAT_800990c4;
}
DAT_8008d404 = 0;
}
return (undefined *)0;
}
// MEMCARD_EraseFile (unused)
// param1 slotIndex
undefined4 FUN_8003e6d4(undefined4 param_1,undefined4 param_2)
{
undefined4 uVar1;
long lVar2;
char acStack72 [64];
if (DAT_8008d404 == 0)
{
// MEMCARD_StringSet
FUN_8003d730(acStack72,param_1,param_2);
DAT_8008d404 = 0xe;
lVar2 = erase(acStack72);
if (lVar2 != 1) {
DAT_8008d404 = 0xd;
}
// MEMCARD_GetFreeBytes
FUN_8003dd10(param_1);
uVar1 = 7;
}
else {
uVar1 = 1;
}
return uVar1;
}