mirror of https://github.com/PrimeDecomp/prime.git
parent
8b689adc97
commit
f9cecfd4b1
|
@ -5,12 +5,12 @@
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define CARD_FAT_AVAIL 0x0000u
|
#define CARD_FAT_AVAIL 0x0000u
|
||||||
#define CARD_FAT_CHECKSUM 0x0000u
|
#define CARD_FAT_CHECKSUM 0x0000u
|
||||||
#define CARD_FAT_CHECKSUMINV 0x0001u
|
#define CARD_FAT_CHECKSUMINV 0x0001u
|
||||||
#define CARD_FAT_CHECKCODE 0x0002u
|
#define CARD_FAT_CHECKCODE 0x0002u
|
||||||
#define CARD_FAT_FREEBLOCKS 0x0003u
|
#define CARD_FAT_FREEBLOCKS 0x0003u
|
||||||
#define CARD_FAT_LASTSLOT 0x0004u
|
#define CARD_FAT_LASTSLOT 0x0004u
|
||||||
|
|
||||||
#define CARD_PAGE_SIZE 128u
|
#define CARD_PAGE_SIZE 128u
|
||||||
#define CARD_SEG_SIZE 512u
|
#define CARD_SEG_SIZE 512u
|
||||||
|
@ -20,28 +20,35 @@ extern "C" {
|
||||||
|
|
||||||
#define CARD_MAX_MOUNT_STEP (CARD_NUM_SYSTEM_BLOCK + 2)
|
#define CARD_MAX_MOUNT_STEP (CARD_NUM_SYSTEM_BLOCK + 2)
|
||||||
|
|
||||||
typedef struct CARDDir
|
typedef struct CARDDir {
|
||||||
{
|
u8 gameName[4];
|
||||||
u8 gameName[4];
|
u8 company[2];
|
||||||
u8 company[2];
|
u8 _padding0;
|
||||||
u8 _padding0;
|
u8 bannerFormat;
|
||||||
u8 bannerFormat;
|
u8 fileName[CARD_FILENAME_MAX];
|
||||||
u8 fileName[CARD_FILENAME_MAX];
|
u32 time; // seconds since 01/01/2000 midnight
|
||||||
u32 time; // seconds since 01/01/2000 midnight
|
|
||||||
|
|
||||||
u32 iconAddr; // 0xffffffff if not used
|
u32 iconAddr; // 0xffffffff if not used
|
||||||
u16 iconFormat;
|
u16 iconFormat;
|
||||||
u16 iconSpeed;
|
u16 iconSpeed;
|
||||||
|
|
||||||
u8 permission;
|
u8 permission;
|
||||||
u8 copyTimes;
|
u8 copyTimes;
|
||||||
u16 startBlock;
|
u16 startBlock;
|
||||||
u16 length;
|
u16 length;
|
||||||
u8 _padding1[2];
|
u8 _padding1[2];
|
||||||
|
|
||||||
u32 commentAddr; // 0xffffffff if not used
|
u32 commentAddr; // 0xffffffff if not used
|
||||||
} CARDDir;
|
} CARDDir;
|
||||||
|
|
||||||
|
typedef struct CARDDirCheck {
|
||||||
|
u8 padding0[64 - 2 * 4];
|
||||||
|
u16 padding1;
|
||||||
|
s16 checkCode;
|
||||||
|
u16 checkSum;
|
||||||
|
u16 checkSumInv;
|
||||||
|
} CARDDirCheck;
|
||||||
|
|
||||||
typedef struct CARDControl {
|
typedef struct CARDControl {
|
||||||
BOOL attached;
|
BOOL attached;
|
||||||
s32 result;
|
s32 result;
|
||||||
|
@ -57,7 +64,7 @@ typedef struct CARDControl {
|
||||||
u32 scramble;
|
u32 scramble;
|
||||||
DSPTaskInfo task;
|
DSPTaskInfo task;
|
||||||
void* workArea;
|
void* workArea;
|
||||||
CARDDir* dir;
|
CARDDir* currentDir;
|
||||||
u16* currentFat;
|
u16* currentFat;
|
||||||
OSThreadQueue threadQueue;
|
OSThreadQueue threadQueue;
|
||||||
u8 cmd[9];
|
u8 cmd[9];
|
||||||
|
@ -95,15 +102,17 @@ typedef struct CARDID {
|
||||||
u16 checkSumInv;
|
u16 checkSumInv;
|
||||||
} CARDID;
|
} CARDID;
|
||||||
|
|
||||||
#define CARDIsValidBlockNo(card, iBlock) (CARD_NUM_SYSTEM_BLOCK <= (iBlock) && (iBlock) < (card)->cBlock)
|
#define CARDIsValidBlockNo(card, iBlock) (CARD_NUM_SYSTEM_BLOCK <= (iBlock) && (iBlock) < (card)->cBlock)
|
||||||
|
#define __CARDGetDirCheck(dir) ((CARDDirCheck*) &(dir)[CARD_MAX_FILE])
|
||||||
|
|
||||||
CARDDir* __CARDGetDirBlock( CARDControl* card );
|
CARDDir* __CARDGetDirBlock(CARDControl* card);
|
||||||
u16* __CARDGetFatBlock ( CARDControl* card );
|
u16* __CARDGetFatBlock(CARDControl* card);
|
||||||
s32 __CARDUpdateFatBlock(s32 chan, u16* fat, CARDCallback callback);
|
s32 __CARDUpdateFatBlock(s32 chan, u16* fat, CARDCallback callback);
|
||||||
|
void __CARDCheckSum(void* ptr, int length, u16* checkSum, u16* checkSumInv);
|
||||||
|
u16 __CARDGetFontEncode();
|
||||||
|
|
||||||
extern CARDControl __CARDBlock[2];
|
extern CARDControl __CARDBlock[2];
|
||||||
extern DVDDiskID __CARDDiskNone;
|
extern DVDDiskID __CARDDiskNone;
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
#ifndef __OSRTCPRIV_H__
|
||||||
|
#define __OSRTCPRIV_H__
|
||||||
|
|
||||||
|
#include <types.h>
|
||||||
|
|
||||||
|
typedef struct OSSram {
|
||||||
|
u16 checkSum;
|
||||||
|
u16 checkSumInv;
|
||||||
|
u32 ead0;
|
||||||
|
u32 ead1;
|
||||||
|
u32 counterBias;
|
||||||
|
s8 displayOffsetH;
|
||||||
|
u8 ntd;
|
||||||
|
u8 language;
|
||||||
|
|
||||||
|
u8 flags;
|
||||||
|
} OSSram;
|
||||||
|
|
||||||
|
typedef struct OSSramEx {
|
||||||
|
u8 flashID[2][12];
|
||||||
|
u32 wirelessKeyboardID;
|
||||||
|
u16 wirelessPadID[4];
|
||||||
|
u8 dvdErrorCode;
|
||||||
|
u8 _padding0;
|
||||||
|
u8 flashIDCheckSum[2];
|
||||||
|
u16 gbs;
|
||||||
|
u8 _padding1[2];
|
||||||
|
} OSSramEx;
|
||||||
|
|
||||||
|
OSSramEx* __OSLockSramEx();
|
||||||
|
#endif
|
|
@ -819,7 +819,7 @@ CARD_FILES :=\
|
||||||
$(BUILD_DIR)/src/Dolphin/card/CARDUnlock.ep.o\
|
$(BUILD_DIR)/src/Dolphin/card/CARDUnlock.ep.o\
|
||||||
$(BUILD_DIR)/src/Dolphin/card/CARDRdwr.ep.o\
|
$(BUILD_DIR)/src/Dolphin/card/CARDRdwr.ep.o\
|
||||||
$(BUILD_DIR)/src/Dolphin/card/CARDBlock.ep.o\
|
$(BUILD_DIR)/src/Dolphin/card/CARDBlock.ep.o\
|
||||||
$(BUILD_DIR)/asm/Dolphin/card/CARDDir.o\
|
$(BUILD_DIR)/src/Dolphin/card/CARDDir.ep.o\
|
||||||
$(BUILD_DIR)/asm/Dolphin/card/CARDCheck.o\
|
$(BUILD_DIR)/asm/Dolphin/card/CARDCheck.o\
|
||||||
$(BUILD_DIR)/asm/Dolphin/card/CARDMount.o\
|
$(BUILD_DIR)/asm/Dolphin/card/CARDMount.o\
|
||||||
$(BUILD_DIR)/asm/Dolphin/card/CARDFormat.o\
|
$(BUILD_DIR)/asm/Dolphin/card/CARDFormat.o\
|
||||||
|
|
|
@ -447,7 +447,7 @@ void CARDInit(void) {
|
||||||
OSRegisterResetFunction(&ResetFunctionInfo);
|
OSRegisterResetFunction(&ResetFunctionInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
u16 __CARDGetFontEncode(s32 chan) { return __CARDEncode; }
|
u16 __CARDGetFontEncode() { return __CARDEncode; }
|
||||||
|
|
||||||
void __CARDSetDiskID(const DVDDiskID* id) {
|
void __CARDSetDiskID(const DVDDiskID* id) {
|
||||||
__CARDBlock[0].diskID = id ? id : &__CARDDiskNone;
|
__CARDBlock[0].diskID = id ? id : &__CARDDiskNone;
|
||||||
|
|
|
@ -0,0 +1,318 @@
|
||||||
|
#include <dolphin/card.h>
|
||||||
|
#include <dolphin/dsp.h>
|
||||||
|
#include <dolphin/dvd.h>
|
||||||
|
#include <dolphin/os.h>
|
||||||
|
|
||||||
|
#include <dolphin/CARDPriv.h>
|
||||||
|
#include <dolphin/OSRtcPriv.h>
|
||||||
|
|
||||||
|
#define __CARDGetDirCheck(dir) ((CARDDirCheck*)&(dir)[CARD_MAX_FILE])
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static s32 VerifyID(CARDControl* card) {
|
||||||
|
CARDID* id;
|
||||||
|
u16 checksum;
|
||||||
|
u16 checksumInv;
|
||||||
|
OSSramEx* sramEx;
|
||||||
|
OSTime rand;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
id = card->workArea;
|
||||||
|
|
||||||
|
if (id->deviceID != 0 || id->size != card->size) {
|
||||||
|
return CARD_RESULT_BROKEN;
|
||||||
|
}
|
||||||
|
|
||||||
|
__CARDCheckSum(id, sizeof(CARDID) - sizeof(u32), &checksum, &checksumInv);
|
||||||
|
if (id->checkSum != checksum || id->checkSumInv != checksumInv) {
|
||||||
|
return CARD_RESULT_BROKEN;
|
||||||
|
}
|
||||||
|
|
||||||
|
rand = *(OSTime*)&id->serial[12];
|
||||||
|
sramEx = __OSLockSramEx();
|
||||||
|
|
||||||
|
for (i = 0; i < 12; i++) {
|
||||||
|
rand = (rand * 1103515245 + 12345) >> 16;
|
||||||
|
if (id->serial[i] != (u8)(sramEx->flashID[card - __CARDBlock][i] + rand)) {
|
||||||
|
__OSUnlockSramEx(FALSE);
|
||||||
|
return CARD_RESULT_BROKEN;
|
||||||
|
}
|
||||||
|
rand = ((rand * 1103515245 + 12345) >> 16) & 0x7FFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
__OSUnlockSramEx(FALSE);
|
||||||
|
if (id->encode != __CARDGetFontEncode()) {
|
||||||
|
return CARD_RESULT_ENCODING;
|
||||||
|
}
|
||||||
|
|
||||||
|
return CARD_RESULT_READY;
|
||||||
|
}
|
||||||
|
|
||||||
|
static s32 VerifyDir(CARDControl* card, int* outCurrent) {
|
||||||
|
CARDDir* dir[2];
|
||||||
|
CARDDirCheck* check[2];
|
||||||
|
u16 checkSum;
|
||||||
|
u16 checkSumInv;
|
||||||
|
int i;
|
||||||
|
int errors;
|
||||||
|
int current;
|
||||||
|
|
||||||
|
current = errors = 0;
|
||||||
|
for (i = 0; i < 2; i++) {
|
||||||
|
dir[i] = (CARDDir*)((u8*)card->workArea + (1 + i) * CARD_SYSTEM_BLOCK_SIZE);
|
||||||
|
check[i] = __CARDGetDirCheck(dir[i]);
|
||||||
|
__CARDCheckSum(dir[i], CARD_SYSTEM_BLOCK_SIZE - sizeof(u32), &checkSum, &checkSumInv);
|
||||||
|
if (check[i]->checkSum != checkSum || check[i]->checkSumInv != checkSumInv) {
|
||||||
|
++errors;
|
||||||
|
current = i;
|
||||||
|
card->currentDir = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0 == errors) {
|
||||||
|
if (card->currentDir == 0) {
|
||||||
|
if ((check[0]->checkCode - check[1]->checkCode) < 0) {
|
||||||
|
current = 0;
|
||||||
|
} else {
|
||||||
|
current = 1;
|
||||||
|
}
|
||||||
|
card->currentDir = dir[current];
|
||||||
|
memcpy(dir[current], dir[current ^ 1], CARD_SYSTEM_BLOCK_SIZE);
|
||||||
|
} else {
|
||||||
|
current = (card->currentDir == dir[0]) ? 0 : 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (outCurrent) {
|
||||||
|
*outCurrent = current;
|
||||||
|
}
|
||||||
|
return errors;
|
||||||
|
}
|
||||||
|
|
||||||
|
static s32 VerifyFAT(CARDControl* card, int* outCurrent) {
|
||||||
|
u16* fat[2];
|
||||||
|
u16* fatp;
|
||||||
|
u16 nBlock;
|
||||||
|
u16 cFree;
|
||||||
|
int i;
|
||||||
|
u16 checkSum;
|
||||||
|
u16 checkSumInv;
|
||||||
|
int errors;
|
||||||
|
int current;
|
||||||
|
|
||||||
|
current = errors = 0;
|
||||||
|
for (i = 0; i < 2; i++) {
|
||||||
|
fatp = fat[i] = (u16*)((u8*)card->workArea + (3 + i) * CARD_SYSTEM_BLOCK_SIZE);
|
||||||
|
|
||||||
|
__CARDCheckSum(&fatp[CARD_FAT_CHECKCODE], CARD_SYSTEM_BLOCK_SIZE - sizeof(u32), &checkSum, &checkSumInv);
|
||||||
|
if (fatp[CARD_FAT_CHECKSUM] != checkSum || fatp[CARD_FAT_CHECKSUMINV] != checkSumInv) {
|
||||||
|
++errors;
|
||||||
|
current = i;
|
||||||
|
card->currentFat = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
cFree = 0;
|
||||||
|
for (nBlock = CARD_NUM_SYSTEM_BLOCK; nBlock < card->cBlock; nBlock++) {
|
||||||
|
if (fatp[nBlock] == CARD_FAT_AVAIL) {
|
||||||
|
cFree++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (cFree != fatp[CARD_FAT_FREEBLOCKS]) {
|
||||||
|
++errors;
|
||||||
|
current = i;
|
||||||
|
card->currentFat = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0 == errors) {
|
||||||
|
if (card->currentFat == 0) {
|
||||||
|
if (((s16)fat[0][CARD_FAT_CHECKCODE] - (s16)fat[1][CARD_FAT_CHECKCODE]) < 0) {
|
||||||
|
current = 0;
|
||||||
|
} else {
|
||||||
|
current = 1;
|
||||||
|
}
|
||||||
|
card->currentFat = fat[current];
|
||||||
|
memcpy(fat[current], fat[current ^ 1], CARD_SYSTEM_BLOCK_SIZE);
|
||||||
|
} else {
|
||||||
|
current = (card->currentFat == fat[0]) ? 0 : 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (outCurrent) {
|
||||||
|
*outCurrent = current;
|
||||||
|
}
|
||||||
|
return errors;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 CARDCheckAsync(s32 chan, CARDCallback callback) {
|
||||||
|
s32 xferBytes;
|
||||||
|
|
||||||
|
return CARDCheckExAsync(chan, &xferBytes, callback);
|
||||||
|
}
|
|
@ -0,0 +1,92 @@
|
||||||
|
#include <dolphin/card.h>
|
||||||
|
#include <dolphin/dsp.h>
|
||||||
|
#include <dolphin/dvd.h>
|
||||||
|
#include <dolphin/os.h>
|
||||||
|
|
||||||
|
#include <dolphin/CARDPriv.h>
|
||||||
|
|
||||||
|
CARDDir* __CARDGetDirBlock(CARDControl* card) { return card->currentDir; }
|
||||||
|
|
||||||
|
static void WriteCallback(s32 chan, s32 result) {
|
||||||
|
CARDControl* card;
|
||||||
|
CARDCallback callback;
|
||||||
|
|
||||||
|
card = &__CARDBlock[chan];
|
||||||
|
if (0 <= result) {
|
||||||
|
CARDDir* dir0 = (CARDDir*)((u8*)card->workArea + 0x2000);
|
||||||
|
CARDDir* dir1 = (CARDDir*)((u8*)card->workArea + 0x4000);
|
||||||
|
|
||||||
|
if (card->currentDir == dir0) {
|
||||||
|
card->currentDir = dir1;
|
||||||
|
memcpy(dir1, dir0, 0x2000);
|
||||||
|
} else {
|
||||||
|
card->currentDir = dir0;
|
||||||
|
memcpy(dir0, dir1, 0x2000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
error:
|
||||||
|
if (card->apiCallback == 0) {
|
||||||
|
__CARDPutControlBlock(card, result);
|
||||||
|
}
|
||||||
|
callback = card->eraseCallback;
|
||||||
|
if (callback) {
|
||||||
|
card->eraseCallback = 0;
|
||||||
|
callback(chan, result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void EraseCallback(s32 chan, s32 result) {
|
||||||
|
CARDControl* card;
|
||||||
|
CARDCallback callback;
|
||||||
|
CARDDir* dir;
|
||||||
|
u32 tmp[2];
|
||||||
|
u32 addr;
|
||||||
|
|
||||||
|
card = &__CARDBlock[chan];
|
||||||
|
if (result < 0) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
dir = __CARDGetDirBlock(card);
|
||||||
|
addr = ((u32)dir - (u32)card->workArea) / 0x2000 * card->sectorSize;
|
||||||
|
result = __CARDWrite(chan, addr, 0x2000, dir, WriteCallback);
|
||||||
|
if (result < 0) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
|
error:
|
||||||
|
if (card->apiCallback == 0) {
|
||||||
|
__CARDPutControlBlock(card, result);
|
||||||
|
}
|
||||||
|
callback = card->eraseCallback;
|
||||||
|
if (callback) {
|
||||||
|
card->eraseCallback = 0;
|
||||||
|
callback(chan, result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 __CARDUpdateDir(s32 chan, CARDCallback callback) {
|
||||||
|
CARDControl* card;
|
||||||
|
CARDDirCheck* check;
|
||||||
|
u32 tmp[2];
|
||||||
|
u32 addr;
|
||||||
|
CARDDir* dir;
|
||||||
|
|
||||||
|
card = &__CARDBlock[chan];
|
||||||
|
if (!card->attached) {
|
||||||
|
return CARD_RESULT_NOCARD;
|
||||||
|
}
|
||||||
|
|
||||||
|
dir = __CARDGetDirBlock(card);
|
||||||
|
check = __CARDGetDirCheck(dir);
|
||||||
|
++check->checkCode;
|
||||||
|
__CARDCheckSum(dir, 0x2000 - sizeof(u32), &check->checkSum, &check->checkSumInv);
|
||||||
|
DCStoreRange(dir, 0x2000);
|
||||||
|
|
||||||
|
card->eraseCallback = callback;
|
||||||
|
addr = ((u32)dir - (u32)card->workArea) / 0x2000 * card->sectorSize;
|
||||||
|
return __CARDEraseSector(chan, addr, EraseCallback);
|
||||||
|
}
|
Loading…
Reference in New Issue