mirror of https://github.com/zeldaret/tp.git
264 lines
6.8 KiB
C
264 lines
6.8 KiB
C
//
|
|
// Generated By: dol2asm
|
|
// Translation Unit: CARDCheck
|
|
//
|
|
|
|
#include "dolphin/card/CARDCheck.h"
|
|
#include "MSL_C/MSL_Common/Src/string.h"
|
|
#include "dol2asm.h"
|
|
#include "dolphin/card/card.h"
|
|
#include "dolphin/dsp/dsp.h"
|
|
#include "dolphin/dvd/dvd.h"
|
|
|
|
#include "dolphin/card/CARDPriv.h"
|
|
|
|
//
|
|
// Forward References:
|
|
//
|
|
|
|
static s32 VerifyID(CARDControl* card);
|
|
static s32 VerifyDir(CARDControl* card, int* outCurrent);
|
|
static s32 VerifyFAT(CARDControl* card, int* outCurrent);
|
|
|
|
//
|
|
// External References:
|
|
//
|
|
|
|
void __shr2i();
|
|
|
|
//
|
|
// Declarations:
|
|
//
|
|
|
|
/* 803559E0-80355B90 350320 01B0+00 0/0 3/3 0/0 .text __CARDCheckSum */
|
|
void __CARDCheckSum(void* ptr, int length, u16* checksum, u16* checksumInv) {
|
|
u16* p;
|
|
int i;
|
|
|
|
length /= sizeof(u16);
|
|
*checksum = *checksumInv = 0;
|
|
|
|
for (i = 0, p = ptr; i < length; i++, p++) {
|
|
*checksum += *p;
|
|
*checksumInv += ~*p;
|
|
}
|
|
|
|
if (*checksum == 0xFFFF) {
|
|
*checksum = 0;
|
|
}
|
|
|
|
if (*checksumInv == 0xFFFF) {
|
|
*checksumInv = 0;
|
|
}
|
|
}
|
|
|
|
/* 80355B90-80355E14 3504D0 0284+00 2/2 0/0 0/0 .text VerifyID */
|
|
#pragma push
|
|
#pragma optimization_level 0
|
|
#pragma optimizewithasm off
|
|
static asm s32 VerifyID(CARDControl* card) {
|
|
nofralloc
|
|
#include "asm/dolphin/card/CARDCheck/VerifyID.s"
|
|
}
|
|
#pragma pop
|
|
|
|
/* 80355E14-80356054 350754 0240+00 2/2 0/0 0/0 .text VerifyDir */
|
|
#pragma push
|
|
#pragma optimization_level 0
|
|
#pragma optimizewithasm off
|
|
static asm s32 VerifyDir(CARDControl* card, int* outCurrent) {
|
|
nofralloc
|
|
#include "asm/dolphin/card/CARDCheck/VerifyDir.s"
|
|
}
|
|
#pragma pop
|
|
|
|
/* 80356054-803562D8 350994 0284+00 2/2 0/0 0/0 .text VerifyFAT */
|
|
#pragma push
|
|
#pragma optimization_level 0
|
|
#pragma optimizewithasm off
|
|
static asm s32 VerifyFAT(CARDControl* card, int* outCurrent) {
|
|
nofralloc
|
|
#include "asm/dolphin/card/CARDCheck/VerifyFAT.s"
|
|
}
|
|
#pragma pop
|
|
|
|
/* 803562D8-80356364 350C18 008C+00 0/0 1/1 0/0 .text __CARDVerify */
|
|
s32 __CARDVerify(CARDControl* card) {
|
|
s32 result;
|
|
int errors;
|
|
|
|
result = VerifyID(card);
|
|
if (result < 0) {
|
|
return result;
|
|
}
|
|
|
|
errors = VerifyDir(card, NULL);
|
|
errors += VerifyFAT(card, NULL);
|
|
switch (errors) {
|
|
case 0:
|
|
return CARD_RESULT_READY;
|
|
case 1:
|
|
return CARD_RESULT_BROKEN;
|
|
default:
|
|
return CARD_RESULT_BROKEN;
|
|
}
|
|
}
|
|
|
|
/* 80356364-803568F4 350CA4 0590+00 1/1 0/0 0/0 .text CARDCheckExAsync */
|
|
#ifdef NONMATCHING
|
|
s32 CARDCheckExAsync(s32 chan, s32* xferBytes, CARDCallback callback) {
|
|
CARDControl* card;
|
|
CARDDir* dir[2];
|
|
u16* fat[2];
|
|
u16* map;
|
|
s32 result;
|
|
int errors;
|
|
int currentFat;
|
|
int currentDir;
|
|
s32 fileNo;
|
|
u16 iBlock;
|
|
u16 cBlock;
|
|
u16 cFree;
|
|
BOOL updateFat = FALSE;
|
|
BOOL updateDir = FALSE;
|
|
BOOL updateOrphan = FALSE;
|
|
|
|
if (xferBytes) {
|
|
*xferBytes = 0;
|
|
}
|
|
|
|
result = __CARDGetControlBlock(chan, &card);
|
|
if (result < 0) {
|
|
return result;
|
|
}
|
|
|
|
result = VerifyID(card);
|
|
if (result < 0) {
|
|
return __CARDPutControlBlock(card, result);
|
|
}
|
|
|
|
errors = VerifyDir(card, ¤tDir);
|
|
errors += VerifyFAT(card, ¤tFat);
|
|
if (1 < errors) {
|
|
return __CARDPutControlBlock(card, CARD_RESULT_BROKEN);
|
|
}
|
|
|
|
dir[0] = (CARDDir*)((u8*)card->workArea + (1 + 0) * CARD_SYSTEM_BLOCK_SIZE);
|
|
dir[1] = (CARDDir*)((u8*)card->workArea + (1 + 1) * CARD_SYSTEM_BLOCK_SIZE);
|
|
fat[0] = (u16*)((u8*)card->workArea + (3 + 0) * CARD_SYSTEM_BLOCK_SIZE);
|
|
fat[1] = (u16*)((u8*)card->workArea + (3 + 1) * CARD_SYSTEM_BLOCK_SIZE);
|
|
|
|
switch (errors) {
|
|
case 0:
|
|
break;
|
|
case 1:
|
|
if (!card->currentDir) {
|
|
card->currentDir = dir[currentDir];
|
|
memcpy(dir[currentDir], dir[currentDir ^ 1], CARD_SYSTEM_BLOCK_SIZE);
|
|
updateDir = TRUE;
|
|
} else {
|
|
card->currentFat = fat[currentFat];
|
|
memcpy(fat[currentFat], fat[currentFat ^ 1], CARD_SYSTEM_BLOCK_SIZE);
|
|
updateFat = TRUE;
|
|
}
|
|
break;
|
|
}
|
|
|
|
map = fat[currentFat ^ 1];
|
|
memset(map, 0, CARD_SYSTEM_BLOCK_SIZE);
|
|
|
|
for (fileNo = 0; fileNo < CARD_MAX_FILE; fileNo++) {
|
|
CARDDir* ent;
|
|
|
|
ent = &card->currentDir[fileNo];
|
|
if (ent->gameName[0] == 0xff) {
|
|
continue;
|
|
}
|
|
|
|
for (iBlock = ent->startBlock, cBlock = 0; iBlock != 0xFFFF && cBlock < ent->length;
|
|
iBlock = card->currentFat[iBlock], ++cBlock) {
|
|
if (!CARDIsValidBlockNo(card, iBlock) || 1 < ++map[iBlock]) {
|
|
return __CARDPutControlBlock(card, CARD_RESULT_BROKEN);
|
|
}
|
|
}
|
|
if (cBlock != ent->length || iBlock != 0xFFFF) {
|
|
return __CARDPutControlBlock(card, CARD_RESULT_BROKEN);
|
|
}
|
|
}
|
|
|
|
cFree = 0;
|
|
for (iBlock = CARD_NUM_SYSTEM_BLOCK; iBlock < card->cBlock; iBlock++) {
|
|
u16 nextBlock;
|
|
|
|
nextBlock = card->currentFat[iBlock];
|
|
if (map[iBlock] == 0) {
|
|
if (nextBlock != CARD_FAT_AVAIL) {
|
|
card->currentFat[iBlock] = CARD_FAT_AVAIL;
|
|
updateOrphan = TRUE;
|
|
}
|
|
cFree++;
|
|
} else if (!CARDIsValidBlockNo(card, nextBlock) && nextBlock != 0xFFFF) {
|
|
return __CARDPutControlBlock(card, CARD_RESULT_BROKEN);
|
|
}
|
|
}
|
|
if (cFree != card->currentFat[CARD_FAT_FREEBLOCKS]) {
|
|
card->currentFat[CARD_FAT_FREEBLOCKS] = cFree;
|
|
updateOrphan = TRUE;
|
|
}
|
|
if (updateOrphan) {
|
|
__CARDCheckSum(&card->currentFat[CARD_FAT_CHECKCODE], CARD_SYSTEM_BLOCK_SIZE - sizeof(u32),
|
|
&card->currentFat[CARD_FAT_CHECKSUM],
|
|
&card->currentFat[CARD_FAT_CHECKSUMINV]);
|
|
}
|
|
|
|
memcpy(fat[currentFat ^ 1], fat[currentFat], CARD_SYSTEM_BLOCK_SIZE);
|
|
|
|
if (updateDir) {
|
|
if (xferBytes) {
|
|
*xferBytes = CARD_SYSTEM_BLOCK_SIZE;
|
|
}
|
|
return __CARDUpdateDir(chan, callback);
|
|
}
|
|
|
|
if (updateFat | updateOrphan) {
|
|
if (xferBytes) {
|
|
*xferBytes = CARD_SYSTEM_BLOCK_SIZE;
|
|
}
|
|
return __CARDUpdateFatBlock(chan, card->currentFat, callback);
|
|
}
|
|
|
|
__CARDPutControlBlock(card, CARD_RESULT_READY);
|
|
if (callback) {
|
|
BOOL enabled = OSDisableInterrupts();
|
|
callback(chan, CARD_RESULT_READY);
|
|
OSRestoreInterrupts(enabled);
|
|
}
|
|
return CARD_RESULT_READY;
|
|
}
|
|
#else
|
|
#pragma push
|
|
#pragma optimization_level 0
|
|
#pragma optimizewithasm off
|
|
static asm s32 CARDCheckExAsync(s32 chan, s32* xferBytes, CARDCallback callback) {
|
|
nofralloc
|
|
#include "asm/dolphin/card/CARDCheck/CARDCheckExAsync.s"
|
|
}
|
|
#pragma pop
|
|
#endif
|
|
|
|
/* 803568F4-80356948 351234 0054+00 0/0 2/2 0/0 .text CARDCheck */
|
|
s32 CARDCheck(s32 chan) {
|
|
s32 xferBytes;
|
|
|
|
s32 result = CARDCheckExAsync(chan, &xferBytes, __CARDSyncCallback);
|
|
if (result >= 0) {
|
|
if (&xferBytes == NULL) {
|
|
return result;
|
|
}
|
|
|
|
return __CARDSync(chan);
|
|
}
|
|
|
|
return result;
|
|
}
|