Link nearly all of CARD

This commit is contained in:
Phillip Stephens 2022-09-10 21:54:54 -07:00
parent 28a4b75d39
commit e3de3f9e5d
13 changed files with 1203 additions and 9 deletions

View File

@ -102,6 +102,8 @@ typedef struct CARDID {
u16 checkSumInv;
} CARDID;
void __CARDDefaultApiCallback(s32 chan, s32 result);
#define CARDIsValidBlockNo(card, iBlock) (CARD_NUM_SYSTEM_BLOCK <= (iBlock) && (iBlock) < (card)->cBlock)
#define __CARDGetDirCheck(dir) ((CARDDirCheck*) &(dir)[CARD_MAX_FILE])
@ -110,9 +112,18 @@ u16* __CARDGetFatBlock(CARDControl* card);
s32 __CARDUpdateFatBlock(s32 chan, u16* fat, CARDCallback callback);
void __CARDCheckSum(void* ptr, int length, u16* checkSum, u16* checkSumInv);
u16 __CARDGetFontEncode();
void __CARDExiHandler(s32 chan, OSContext* context);
void __CARDExtHandler(s32 chan, OSContext* context);
void __CARDUnlockedHandler(s32 chan, OSContext* context);
s32 __CARDAccess(CARDControl* card, CARDDir* ent);
BOOL __CARDIsWritable(CARDDir* ent);
#define TRUNC(n, a) (((u32) (n)) & ~((a) - 1))
#define OFFSET(n, a) (((u32) (n)) & ((a) - 1))
extern CARDControl __CARDBlock[2];
extern DVDDiskID __CARDDiskNone;
extern u16 __CARDVendorID;
#ifdef __cplusplus
}

View File

@ -27,5 +27,6 @@ typedef struct OSSramEx {
u8 _padding1[2];
} OSSramEx;
OSSram* __OSLockSram();
OSSramEx* __OSLockSramEx();
#endif

View File

@ -22,6 +22,8 @@ void VISetWindowFullscreen(bool fullscreen);
bool VIGetWindowFullscreen();
#endif
vu16 __VIRegs[59] : 0xCC002000;
#ifdef __cplusplus
}
#endif

View File

@ -821,16 +821,16 @@ CARD_FILES :=\
$(BUILD_DIR)/src/Dolphin/card/CARDBlock.ep.o\
$(BUILD_DIR)/src/Dolphin/card/CARDDir.ep.o\
$(BUILD_DIR)/asm/Dolphin/card/CARDCheck.o\
$(BUILD_DIR)/asm/Dolphin/card/CARDMount.o\
$(BUILD_DIR)/asm/Dolphin/card/CARDFormat.o\
$(BUILD_DIR)/src/Dolphin/card/CARDMount.ep.o\
$(BUILD_DIR)/src/Dolphin/card/CARDFormat.ep.o\
$(BUILD_DIR)/src/Dolphin/card/CARDOpen.ep.o\
$(BUILD_DIR)/asm/Dolphin/card/CARDCreate.o\
$(BUILD_DIR)/asm/Dolphin/card/CARDRead.o\
$(BUILD_DIR)/asm/Dolphin/card/CARDWrite.o\
$(BUILD_DIR)/asm/Dolphin/card/CARDDelete.o\
$(BUILD_DIR)/asm/Dolphin/card/CARDStat.o\
$(BUILD_DIR)/asm/Dolphin/card/CARDRename.o\
$(BUILD_DIR)/asm/Dolphin/card/CARDNet.o
$(BUILD_DIR)/src/Dolphin/card/CARDCreate.ep.o\
$(BUILD_DIR)/src/Dolphin/card/CARDRead.ep.o\
$(BUILD_DIR)/src/Dolphin/card/CARDWrite.ep.o\
$(BUILD_DIR)/src/Dolphin/card/CARDDelete.ep.o\
$(BUILD_DIR)/src/Dolphin/card/CARDStat.ep.o\
$(BUILD_DIR)/src/Dolphin/card/CARDRename.ep.o\
$(BUILD_DIR)/src/Dolphin/card/CARDNet.ep.o
SI_FILES :=\
$(BUILD_DIR)/asm/Dolphin/si/SIBios.o\

View File

@ -0,0 +1,113 @@
#include <dolphin/card.h>
#include <dolphin/dsp.h>
#include <dolphin/dvd.h>
#include <dolphin/os.h>
#include <dolphin/CARDPriv.h>
static void CreateCallbackFat(s32 chan, s32 result) {
CARDControl* card;
CARDDir* dir;
CARDDir* ent;
CARDCallback callback;
card = &__CARDBlock[chan];
callback = card->apiCallback;
card->apiCallback = 0;
if (result < 0) {
goto error;
}
dir = __CARDGetDirBlock(card);
ent = &dir[card->freeNo];
memcpy(ent->gameName, card->diskID->gameName, sizeof(ent->gameName));
memcpy(ent->company, card->diskID->company, sizeof(ent->company));
ent->permission = CARD_ATTR_PUBLIC;
ent->copyTimes = 0;
ent->startBlock = card->startBlock;
ent->bannerFormat = 0;
ent->iconAddr = 0xffffffff;
ent->iconFormat = 0;
ent->iconSpeed = 0;
ent->commentAddr = 0xffffffff;
CARDSetIconSpeed(ent, 0, CARD_STAT_SPEED_FAST);
card->fileInfo->offset = 0;
card->fileInfo->iBlock = ent->startBlock;
ent->time = (u32)OSTicksToSeconds(OSGetTime());
result = __CARDUpdateDir(chan, callback);
if (result < 0) {
goto error;
}
return;
error:
__CARDPutControlBlock(card, result);
if (callback) {
callback(chan, result);
}
}
s32 CARDCreateAsync(s32 chan, const char* fileName, u32 size, CARDFileInfo* fileInfo, CARDCallback callback) {
CARDControl* card;
CARDDir* dir;
CARDDir* ent;
s32 result;
u16 fileNo;
u16 freeNo;
u16* fat;
if (strlen(fileName) > (u32)CARD_FILENAME_MAX) {
return CARD_RESULT_NAMETOOLONG;
}
result = __CARDGetControlBlock(chan, &card);
if (result < 0) {
return result;
}
if (size <= 0 || (size % card->sectorSize) != 0) {
return CARD_RESULT_FATAL_ERROR;
}
freeNo = (u16)-1;
dir = __CARDGetDirBlock(card);
for (fileNo = 0; fileNo < CARD_MAX_FILE; fileNo++) {
ent = &dir[fileNo];
if (ent->gameName[0] == 0xff) {
if (freeNo == (u16)-1) {
freeNo = fileNo;
}
} else if (memcmp(ent->gameName, card->diskID->gameName, sizeof(ent->gameName)) == 0 &&
memcmp(ent->company, card->diskID->company, sizeof(ent->company)) == 0 && __CARDCompareFileName(ent, fileName)) {
return __CARDPutControlBlock(card, CARD_RESULT_EXIST);
}
}
if (freeNo == (u16)-1) {
return __CARDPutControlBlock(card, CARD_RESULT_NOENT);
}
fat = __CARDGetFatBlock(card);
if (card->sectorSize * fat[CARD_FAT_FREEBLOCKS] < size) {
return __CARDPutControlBlock(card, CARD_RESULT_INSSPACE);
}
card->apiCallback = callback ? callback : __CARDDefaultApiCallback;
card->freeNo = freeNo;
ent = &dir[freeNo];
ent->length = (u16)(size / card->sectorSize);
strncpy(ent->fileName, fileName, CARD_FILENAME_MAX);
card->fileInfo = fileInfo;
fileInfo->chan = chan;
fileInfo->fileNo = freeNo;
result = __CARDAllocBlock(chan, size / card->sectorSize, CreateCallbackFat);
if (result < 0) {
return __CARDPutControlBlock(card, result);
}
return result;
}

View File

@ -0,0 +1,97 @@
#include <dolphin/card.h>
#include <dolphin/dsp.h>
#include <dolphin/dvd.h>
#include <dolphin/os.h>
#include <dolphin/CARDPriv.h>
static void DeleteCallback(s32 chan, s32 result) {
CARDControl* card;
CARDCallback callback;
card = &__CARDBlock[chan];
callback = card->apiCallback;
card->apiCallback = 0;
if (result < 0) {
goto error;
}
result = __CARDFreeBlock(chan, card->startBlock, callback);
if (result < 0) {
goto error;
}
return;
error:
__CARDPutControlBlock(card, result);
if (callback) {
callback(chan, result);
}
}
s32 CARDFastDeleteAsync(s32 chan, s32 fileNo, CARDCallback callback) {
CARDControl* card;
CARDDir* dir;
CARDDir* ent;
s32 result;
if (fileNo < 0 || CARD_MAX_FILE <= fileNo) {
return CARD_RESULT_FATAL_ERROR;
}
result = __CARDGetControlBlock(chan, &card);
if (result < 0) {
return result;
}
dir = __CARDGetDirBlock(card);
ent = &dir[fileNo];
result = __CARDAccess(card, ent);
if (result < 0) {
return __CARDPutControlBlock(card, result);
}
if (__CARDIsOpened(card, fileNo)) {
return __CARDPutControlBlock(card, CARD_RESULT_BUSY);
}
card->startBlock = ent->startBlock;
memset(ent, 0xff, sizeof(CARDDir));
card->apiCallback = callback ? callback : __CARDDefaultApiCallback;
result = __CARDUpdateDir(chan, DeleteCallback);
if (result < 0) {
__CARDPutControlBlock(card, result);
}
return result;
}
s32 CARDDeleteAsync(s32 chan, const char* fileName, CARDCallback callback) {
CARDControl* card;
s32 fileNo;
s32 result;
CARDDir* dir;
CARDDir* ent;
result = __CARDGetControlBlock(chan, &card);
if (result < 0) {
return result;
}
result = __CARDGetFileNo(card, fileName, &fileNo);
if (result < 0) {
return __CARDPutControlBlock(card, result);
}
if (__CARDIsOpened(card, fileNo)) {
return __CARDPutControlBlock(card, CARD_RESULT_BUSY);
}
dir = __CARDGetDirBlock(card);
ent = &dir[fileNo];
card->startBlock = ent->startBlock;
memset(ent, 0xff, sizeof(CARDDir));
card->apiCallback = callback ? callback : __CARDDefaultApiCallback;
result = __CARDUpdateDir(chan, DeleteCallback);
if (result < 0) {
__CARDPutControlBlock(card, result);
}
return result;
}

View File

@ -0,0 +1,121 @@
#include <dolphin/card.h>
#include <dolphin/dsp.h>
#include <dolphin/dvd.h>
#include <dolphin/os.h>
#include <dolphin/CARDPriv.h>
#include <dolphin/OSRtcPriv.h>
#include <dolphin/vi.h>
static void FormatCallback(s32 chan, s32 result) {
CARDControl* card;
CARDCallback callback;
card = &__CARDBlock[chan];
if (result < 0) {
goto error;
}
++card->formatStep;
if (card->formatStep < CARD_NUM_SYSTEM_BLOCK) {
result = __CARDEraseSector(chan, (u32)card->sectorSize * card->formatStep, FormatCallback);
if (0 <= result) {
return;
}
} else if (card->formatStep < 2 * CARD_NUM_SYSTEM_BLOCK) {
int step = card->formatStep - CARD_NUM_SYSTEM_BLOCK;
result = __CARDWrite(chan, (u32)card->sectorSize * step, CARD_SYSTEM_BLOCK_SIZE, (u8*)card->workArea + (CARD_SYSTEM_BLOCK_SIZE * step),
FormatCallback);
if (result >= 0) {
return;
}
} else {
card->currentDir = (CARDDir*)((u8*)card->workArea + (1 + 0) * CARD_SYSTEM_BLOCK_SIZE);
memcpy(card->currentDir, (u8*)card->workArea + (1 + 1) * CARD_SYSTEM_BLOCK_SIZE, CARD_SYSTEM_BLOCK_SIZE);
card->currentFat = (u16*)((u8*)card->workArea + (3 + 0) * CARD_SYSTEM_BLOCK_SIZE);
memcpy(card->currentFat, (u8*)card->workArea + (3 + 1) * CARD_SYSTEM_BLOCK_SIZE, CARD_SYSTEM_BLOCK_SIZE);
}
error:
callback = card->apiCallback;
card->apiCallback = 0;
__CARDPutControlBlock(card, result);
callback(chan, result);
}
s32 __CARDFormatRegionAsync(s32 chan, u16 encode, CARDCallback callback) {
CARDControl* card;
CARDID* id;
CARDDir* dir;
u16* fat;
s16 i;
s32 result;
OSSram* sram;
OSSramEx* sramEx;
u16 viDTVStatus;
OSTime time;
OSTime rand;
result = __CARDGetControlBlock(chan, &card);
if (result < 0) {
return result;
}
id = (CARDID*)card->workArea;
memset(id, 0xff, CARD_SYSTEM_BLOCK_SIZE);
viDTVStatus = __VIRegs[55];
id->encode = encode;
sram = __OSLockSram();
*(u32*)&id->serial[20] = sram->counterBias;
*(u32*)&id->serial[24] = sram->language;
__OSUnlockSram(FALSE);
rand = time = OSGetTime();
sramEx = __OSLockSramEx();
for (i = 0; i < 12; i++) {
rand = (rand * 1103515245 + 12345) >> 16;
id->serial[i] = (u8)(sramEx->flashID[chan][i] + rand);
rand = ((rand * 1103515245 + 12345) >> 16) & 0x7FFF;
}
__OSUnlockSramEx(FALSE);
*(u32*)&id->serial[28] = viDTVStatus;
*(OSTime*)&id->serial[12] = time;
id->deviceID = 0;
id->size = card->size;
__CARDCheckSum(id, sizeof(CARDID) - sizeof(u32), &id->checkSum, &id->checkSumInv);
for (i = 0; i < 2; i++) {
CARDDirCheck* check;
dir = (CARDDir*)((u8*)card->workArea + (1 + i) * CARD_SYSTEM_BLOCK_SIZE);
memset(dir, 0xff, CARD_SYSTEM_BLOCK_SIZE);
check = __CARDGetDirCheck(dir);
check->checkCode = i;
__CARDCheckSum(dir, CARD_SYSTEM_BLOCK_SIZE - sizeof(u32), &check->checkSum, &check->checkSumInv);
}
for (i = 0; i < 2; i++) {
fat = (u16*)((u8*)card->workArea + (3 + i) * CARD_SYSTEM_BLOCK_SIZE);
memset(fat, 0x00, CARD_SYSTEM_BLOCK_SIZE);
fat[CARD_FAT_CHECKCODE] = (u16)i;
fat[CARD_FAT_FREEBLOCKS] = (u16)(card->cBlock - CARD_NUM_SYSTEM_BLOCK);
fat[CARD_FAT_LASTSLOT] = CARD_NUM_SYSTEM_BLOCK - 1;
__CARDCheckSum(&fat[CARD_FAT_CHECKCODE], CARD_SYSTEM_BLOCK_SIZE - sizeof(u32), &fat[CARD_FAT_CHECKSUM], &fat[CARD_FAT_CHECKSUMINV]);
}
card->apiCallback = callback ? callback : __CARDDefaultApiCallback;
DCStoreRange(card->workArea, CARD_WORKAREA_SIZE);
card->formatStep = 0;
result = __CARDEraseSector(chan, (u32)card->sectorSize * card->formatStep, FormatCallback);
if (result < 0) {
__CARDPutControlBlock(card, result);
}
return result;
}
s32 CARDFormatAsync(s32 chan, CARDCallback callback) { return __CARDFormatRegionAsync(chan, __CARDGetFontEncode(), callback); }

View File

@ -0,0 +1,353 @@
#include <dolphin/card.h>
#include <dolphin/dsp.h>
#include <dolphin/dvd.h>
#include <dolphin/os.h>
#include <dolphin/CARDPriv.h>
#include <dolphin/OSRtcPriv.h>
u8 GameChoice : (OS_BASE_CACHED | 0x000030E3);
static u32 SectorSizeTable[8] = {
8 * 1024, 16 * 1024, 32 * 1024, 64 * 1024, 128 * 1024, 256 * 1024, 0, 0,
};
static u32 LatencyTable[8] = {
4, 8, 16, 32, 64, 128, 256, 512,
};
void __CARDMountCallback(s32 chan, s32 result);
static void DoUnmount(s32 chan, s32 result);
static BOOL IsCard(u32 id) {
u32 size;
s32 sectorSize;
if (id & (0xFFFF0000) && (id != 0x80000004 || __CARDVendorID == 0xFFFF)) {
return FALSE;
}
if ((id & 3) != 0) {
return FALSE;
}
size = id & 0xfc;
switch (size) {
case 4:
case 8:
case 16:
case 32:
case 64:
case 128:
break;
default:
return FALSE;
break;
}
sectorSize = SectorSizeTable[(id & 0x00003800) >> 11];
if (sectorSize == 0) {
return FALSE;
}
if ((size * 1024 * 1024 / 8) / sectorSize < 8) {
return FALSE;
}
return TRUE;
}
s32 CARDProbeEx(s32 chan, s32* memSize, s32* sectorSize) {
u32 id;
CARDControl* card;
BOOL enabled;
s32 result;
int probe;
if (chan < 0 || 2 <= chan) {
return CARD_RESULT_FATAL_ERROR;
}
if (GameChoice & 0x80) {
return CARD_RESULT_NOCARD;
}
card = &__CARDBlock[chan];
enabled = OSDisableInterrupts();
probe = EXIProbeEx(chan);
if (probe == -1) {
result = CARD_RESULT_NOCARD;
} else if (probe == 0) {
result = CARD_RESULT_BUSY;
} else if (card->attached) {
if (card->mountStep < 1) {
result = CARD_RESULT_BUSY;
} else {
if (memSize) {
*memSize = card->size;
}
if (sectorSize) {
*sectorSize = card->sectorSize;
}
result = CARD_RESULT_READY;
}
} else if ((EXIGetState(chan) & 8)) {
result = CARD_RESULT_WRONGDEVICE;
} else if (!EXIGetID(chan, 0, &id)) {
result = CARD_RESULT_BUSY;
} else if (IsCard(id)) {
if (memSize) {
*memSize = (s32)(id & 0xfc);
}
if (sectorSize) {
*sectorSize = SectorSizeTable[(id & 0x00003800) >> 11];
}
result = CARD_RESULT_READY;
} else {
result = CARD_RESULT_WRONGDEVICE;
}
OSRestoreInterrupts(enabled);
return result;
}
static s32 DoMount(s32 chan) {
CARDControl* card;
u32 id;
u8 status;
s32 result;
OSSramEx* sram;
int i;
u8 checkSum;
int step;
card = &__CARDBlock[chan];
if (card->mountStep == 0) {
if (EXIGetID(chan, 0, &id) == 0) {
result = CARD_RESULT_NOCARD;
} else if (IsCard(id)) {
result = CARD_RESULT_READY;
} else {
result = CARD_RESULT_WRONGDEVICE;
}
if (result < 0) {
goto error;
}
card->cid = id;
card->size = (u16)(id & 0xFC);
card->sectorSize = SectorSizeTable[(id & 0x00003800) >> 11];
card->cBlock = (u16)((card->size * 1024 * 1024 / 8) / card->sectorSize);
card->latency = LatencyTable[(id & 0x00000700) >> 8];
result = __CARDClearStatus(chan);
if (result < 0) {
goto error;
}
result = __CARDReadStatus(chan, &status);
if (result < 0) {
goto error;
}
if (!EXIProbe(chan)) {
result = CARD_RESULT_NOCARD;
goto error;
}
if (!(status & 0x40)) {
result = __CARDUnlock(chan, card->id);
if (result < 0) {
goto error;
}
checkSum = 0;
sram = __OSLockSramEx();
for (i = 0; i < 12; i++) {
sram->flashID[chan][i] = card->id[i];
checkSum += card->id[i];
}
sram->flashIDCheckSum[chan] = (u8)~checkSum;
__OSUnlockSramEx(TRUE);
return result;
} else {
card->mountStep = 1;
checkSum = 0;
sram = __OSLockSramEx();
for (i = 0; i < 12; i++) {
checkSum += sram->flashID[chan][i];
}
__OSUnlockSramEx(FALSE);
if (sram->flashIDCheckSum[chan] != (u8)~checkSum) {
result = CARD_RESULT_IOERROR;
goto error;
}
}
}
if (card->mountStep == 1) {
if (card->cid == 0x80000004) {
u16 vendorID;
sram = __OSLockSramEx();
vendorID = *(u16*)sram->flashID[chan];
__OSUnlockSramEx(FALSE);
if (__CARDVendorID == 0xffff || vendorID != __CARDVendorID) {
result = CARD_RESULT_WRONGDEVICE;
goto error;
}
}
card->mountStep = 2;
result = __CARDEnableInterrupt(chan, TRUE);
if (result < 0) {
goto error;
}
EXISetExiCallback(chan, __CARDExiHandler);
EXIUnlock(chan);
DCInvalidateRange(card->workArea, CARD_WORKAREA_SIZE);
}
step = card->mountStep - 2;
result = __CARDRead(chan, (u32)card->sectorSize * step, CARD_SYSTEM_BLOCK_SIZE, (u8*)card->workArea + (CARD_SYSTEM_BLOCK_SIZE * step),
__CARDMountCallback);
if (result < 0) {
__CARDPutControlBlock(card, result);
}
return result;
error:
EXIUnlock(chan);
DoUnmount(chan, result);
return result;
}
void __CARDMountCallback(s32 chan, s32 result) {
CARDControl* card;
CARDCallback callback;
card = &__CARDBlock[chan];
switch (result) {
case CARD_RESULT_READY:
if (++card->mountStep < CARD_MAX_MOUNT_STEP) {
result = DoMount(chan);
if (0 <= result) {
return;
}
} else {
result = __CARDVerify(card);
}
break;
case CARD_RESULT_UNLOCKED:
card->unlockCallback = __CARDMountCallback;
if (!EXILock(chan, 0, __CARDUnlockedHandler)) {
return;
}
card->unlockCallback = 0;
result = DoMount(chan);
if (0 <= result) {
return;
}
break;
case CARD_RESULT_IOERROR:
case CARD_RESULT_NOCARD:
DoUnmount(chan, result);
break;
}
callback = card->apiCallback;
card->apiCallback = 0;
__CARDPutControlBlock(card, result);
callback(chan, result);
}
s32 CARDMountAsync(s32 chan, void* workArea, CARDCallback detachCallback, CARDCallback attachCallback) {
CARDControl* card;
BOOL enabled;
if (chan < 0 || 2 <= chan) {
return CARD_RESULT_FATAL_ERROR;
}
if (GameChoice & 0x80) {
return CARD_RESULT_NOCARD;
}
card = &__CARDBlock[chan];
enabled = OSDisableInterrupts();
if (card->result == CARD_RESULT_BUSY) {
OSRestoreInterrupts(enabled);
return CARD_RESULT_BUSY;
}
if (!card->attached && (EXIGetState(chan) & 0x08)) {
OSRestoreInterrupts(enabled);
return CARD_RESULT_WRONGDEVICE;
}
card->result = CARD_RESULT_BUSY;
card->workArea = workArea;
card->extCallback = detachCallback;
card->apiCallback = attachCallback ? attachCallback : __CARDDefaultApiCallback;
card->exiCallback = 0;
if (!card->attached && !EXIAttach(chan, __CARDExtHandler)) {
card->result = CARD_RESULT_NOCARD;
OSRestoreInterrupts(enabled);
return CARD_RESULT_NOCARD;
}
card->mountStep = 0;
card->attached = TRUE;
EXISetExiCallback(chan, 0);
OSCancelAlarm(&card->alarm);
card->currentDir = 0;
card->currentFat = 0;
OSRestoreInterrupts(enabled);
card->unlockCallback = __CARDMountCallback;
if (!EXILock(chan, 0, __CARDUnlockedHandler)) {
return CARD_RESULT_READY;
}
card->unlockCallback = 0;
return DoMount(chan);
}
static void DoUnmount(s32 chan, s32 result) {
CARDControl* card;
BOOL enabled;
card = &__CARDBlock[chan];
enabled = OSDisableInterrupts();
if (card->attached) {
EXISetExiCallback(chan, 0);
EXIDetach(chan);
OSCancelAlarm(&card->alarm);
card->attached = FALSE;
card->result = result;
card->mountStep = 0;
}
OSRestoreInterrupts(enabled);
}
s32 CARDUnmount(s32 chan) {
CARDControl* card;
s32 result;
result = __CARDGetControlBlock(chan, &card);
if (result < 0) {
return result;
}
DoUnmount(chan, CARD_RESULT_NOCARD);
return CARD_RESULT_READY;
}

View File

@ -0,0 +1,34 @@
#include <dolphin/card.h>
#include <dolphin/dsp.h>
#include <dolphin/dvd.h>
#include <dolphin/os.h>
#include <dolphin/CARDPriv.h>
u16 __CARDVendorID = 0xffff;
s32 CARDGetSerialNo(s32 chan, u64* serialNo) {
CARDControl* card;
CARDID* id;
int i;
u64 code;
s32 result;
if (!(0 <= chan && chan < 2)) {
return CARD_RESULT_FATAL_ERROR;
}
result = __CARDGetControlBlock(chan, &card);
if (result < 0) {
return result;
}
id = (CARDID*)card->workArea;
for (code = 0, i = 0; i < sizeof(id->serial) / sizeof(u64); ++i) {
code ^= *(u64*)&id->serial[sizeof(u64) * i];
}
*serialNo = code;
return __CARDPutControlBlock(card, CARD_RESULT_READY);
}

136
src/Dolphin/card/CARDRead.c Normal file
View File

@ -0,0 +1,136 @@
#include <dolphin/card.h>
#include <dolphin/dsp.h>
#include <dolphin/dvd.h>
#include <dolphin/os.h>
#include <dolphin/CARDPriv.h>
s32 __CARDSeek(CARDFileInfo* fileInfo, s32 length, s32 offset, CARDControl** pcard) {
CARDControl* card;
CARDDir* dir;
CARDDir* ent;
s32 result;
u16* fat;
result = __CARDGetControlBlock(fileInfo->chan, &card);
if (result < 0) {
return result;
}
if (!CARDIsValidBlockNo(card, fileInfo->iBlock) || card->cBlock * card->sectorSize <= fileInfo->offset) {
return __CARDPutControlBlock(card, CARD_RESULT_FATAL_ERROR);
}
dir = __CARDGetDirBlock(card);
ent = &dir[fileInfo->fileNo];
if (ent->length * card->sectorSize <= offset || ent->length * card->sectorSize < offset + length) {
return __CARDPutControlBlock(card, CARD_RESULT_LIMIT);
}
card->fileInfo = fileInfo;
fileInfo->length = length;
if (offset < fileInfo->offset) {
fileInfo->offset = 0;
fileInfo->iBlock = ent->startBlock;
if (!CARDIsValidBlockNo(card, fileInfo->iBlock)) {
return __CARDPutControlBlock(card, CARD_RESULT_BROKEN);
}
}
fat = __CARDGetFatBlock(card);
while (fileInfo->offset < TRUNC(offset, card->sectorSize)) {
fileInfo->offset += card->sectorSize;
fileInfo->iBlock = fat[fileInfo->iBlock];
if (!CARDIsValidBlockNo(card, fileInfo->iBlock)) {
return __CARDPutControlBlock(card, CARD_RESULT_BROKEN);
}
}
fileInfo->offset = offset;
*pcard = card;
return CARD_RESULT_READY;
}
static void ReadCallback(s32 chan, s32 result) {
CARDControl* card;
CARDCallback callback;
u16* fat;
CARDFileInfo* fileInfo;
s32 length;
card = &__CARDBlock[chan];
if (result < 0) {
goto error;
}
fileInfo = card->fileInfo;
if (fileInfo->length < 0) {
result = CARD_RESULT_CANCELED;
goto error;
}
length = (s32)TRUNC(fileInfo->offset + card->sectorSize, card->sectorSize) - fileInfo->offset;
fileInfo->length -= length;
if (fileInfo->length <= 0) {
goto error;
}
fat = __CARDGetFatBlock(card);
fileInfo->offset += length;
fileInfo->iBlock = fat[fileInfo->iBlock];
if (!CARDIsValidBlockNo(card, fileInfo->iBlock)) {
result = CARD_RESULT_BROKEN;
goto error;
}
result = __CARDRead(chan, card->sectorSize * (u32)fileInfo->iBlock,
(fileInfo->length < card->sectorSize) ? fileInfo->length : card->sectorSize, card->buffer, ReadCallback);
if (result < 0) {
goto error;
}
return;
error:
callback = card->apiCallback;
card->apiCallback = 0;
__CARDPutControlBlock(card, result);
callback(chan, result);
}
s32 CARDReadAsync(CARDFileInfo* fileInfo, void* buf, s32 length, s32 offset, CARDCallback callback) {
CARDControl* card;
s32 result;
CARDDir* dir;
CARDDir* ent;
if (OFFSET(offset, CARD_SEG_SIZE) != 0 || OFFSET(length, CARD_SEG_SIZE) != 0) {
return CARD_RESULT_FATAL_ERROR;
}
result = __CARDSeek(fileInfo, length, offset, &card);
if (result < 0) {
return result;
}
dir = __CARDGetDirBlock(card);
ent = &dir[fileInfo->fileNo];
result = __CARDAccess(card, ent);
if (result == CARD_RESULT_NOPERM) {
result = __CARDIsWritable(ent);
}
if (result < 0) {
return __CARDPutControlBlock(card, result);
}
DCInvalidateRange(buf, (u32)length);
card->apiCallback = callback ? callback : __CARDDefaultApiCallback;
offset = (s32)OFFSET(fileInfo->offset, card->sectorSize);
length = (length < card->sectorSize - offset) ? length : card->sectorSize - offset;
result = __CARDRead(fileInfo->chan, card->sectorSize * (u32)fileInfo->iBlock + offset, length, buf, ReadCallback);
if (result < 0) {
__CARDPutControlBlock(card, result);
}
return result;
}

View File

@ -0,0 +1,70 @@
#include <dolphin/card.h>
#include <dolphin/dsp.h>
#include <dolphin/dvd.h>
#include <dolphin/os.h>
#include <dolphin/CARDPriv.h>
s32 CARDRenameAsync(s32 chan, const char* old, const char* new, CARDCallback callback) {
CARDControl* card;
CARDDir* dir;
CARDDir* ent;
s32 result;
int fileNo;
int newNo;
int oldNo;
if (*old == 0xff || *new == 0xff || *old == 0x00 || *new == 0x00) {
return CARD_RESULT_FATAL_ERROR;
}
if (CARD_FILENAME_MAX < (u32)strlen(old) || CARD_FILENAME_MAX < (u32)strlen(new)) {
return CARD_RESULT_NAMETOOLONG;
}
result = __CARDGetControlBlock(chan, &card);
if (result < 0) {
return result;
}
newNo = oldNo = -1;
dir = __CARDGetDirBlock(card);
for (fileNo = 0; fileNo < CARD_MAX_FILE; fileNo++) {
ent = &dir[fileNo];
if (ent->gameName[0] == 0xff) {
continue;
}
if (memcmp(ent->gameName, card->diskID->gameName, sizeof(ent->gameName)) != 0 ||
memcmp(ent->company, card->diskID->company, sizeof(ent->company)) != 0) {
continue;
}
if (__CARDCompareFileName(ent, old)) {
oldNo = fileNo;
}
if (__CARDCompareFileName(ent, new)) {
newNo = fileNo;
}
}
if (oldNo == -1) {
return __CARDPutControlBlock(card, CARD_RESULT_NOFILE);
}
if (newNo != -1) {
return __CARDPutControlBlock(card, CARD_RESULT_EXIST);
}
ent = &dir[oldNo];
result = __CARDAccess(card, ent);
if (result < 0) {
return __CARDPutControlBlock(card, result);
}
strncpy((char*)ent->fileName, new, CARD_FILENAME_MAX);
ent->time = (u32)OSTicksToSeconds(OSGetTime());
result = __CARDUpdateDir(chan, callback);
if (result < 0) {
__CARDPutControlBlock(card, result);
}
return result;
}

142
src/Dolphin/card/CARDStat.c Normal file
View File

@ -0,0 +1,142 @@
#include <dolphin/card.h>
#include <dolphin/dsp.h>
#include <dolphin/dvd.h>
#include <dolphin/os.h>
#include <dolphin/CARDPriv.h>
static void UpdateIconOffsets(CARDDir* ent, CARDStat* stat) {
u32 offset;
BOOL iconTlut;
int i;
offset = ent->iconAddr;
if (offset == 0xffffffff) {
stat->bannerFormat = 0;
stat->iconFormat = 0;
stat->iconSpeed = 0;
offset = 0;
}
iconTlut = FALSE;
switch (CARDGetBannerFormat(ent)) {
case CARD_STAT_BANNER_C8:
stat->offsetBanner = offset;
offset += CARD_BANNER_WIDTH * CARD_BANNER_HEIGHT;
stat->offsetBannerTlut = offset;
offset += 2 * 256;
break;
case CARD_STAT_BANNER_RGB5A3:
stat->offsetBanner = offset;
offset += 2 * CARD_BANNER_WIDTH * CARD_BANNER_HEIGHT;
stat->offsetBannerTlut = 0xffffffff;
break;
default:
stat->offsetBanner = 0xffffffff;
stat->offsetBannerTlut = 0xffffffff;
break;
}
for (i = 0; i < CARD_ICON_MAX; ++i) {
switch (CARDGetIconFormat(ent, i)) {
case CARD_STAT_ICON_C8:
stat->offsetIcon[i] = offset;
offset += CARD_ICON_WIDTH * CARD_ICON_HEIGHT;
iconTlut = TRUE;
break;
case CARD_STAT_ICON_RGB5A3:
stat->offsetIcon[i] = offset;
offset += 2 * CARD_ICON_WIDTH * CARD_ICON_HEIGHT;
break;
default:
stat->offsetIcon[i] = 0xffffffff;
break;
}
}
if (iconTlut) {
stat->offsetIconTlut = offset;
offset += 2 * 256;
} else {
stat->offsetIconTlut = 0xffffffff;
}
stat->offsetData = offset;
}
s32 CARDGetStatus(s32 chan, s32 fileNo, CARDStat* stat) {
CARDControl* card;
CARDDir* dir;
CARDDir* ent;
s32 result;
if (fileNo < 0 || CARD_MAX_FILE <= fileNo) {
return CARD_RESULT_FATAL_ERROR;
}
result = __CARDGetControlBlock(chan, &card);
if (result < 0) {
return result;
}
dir = __CARDGetDirBlock(card);
ent = &dir[fileNo];
result = __CARDAccess(card, ent);
if (result == CARD_RESULT_NOPERM) {
result = __CARDIsWritable(ent);
}
if (result >= 0) {
memcpy(stat->gameName, ent->gameName, sizeof(stat->gameName));
memcpy(stat->company, ent->company, sizeof(stat->company));
stat->length = (u32)ent->length * card->sectorSize;
memcpy(stat->fileName, ent->fileName, CARD_FILENAME_MAX);
stat->time = ent->time;
stat->bannerFormat = ent->bannerFormat;
stat->iconAddr = ent->iconAddr;
stat->iconFormat = ent->iconFormat;
stat->iconSpeed = ent->iconSpeed;
stat->commentAddr = ent->commentAddr;
UpdateIconOffsets(ent, stat);
}
return __CARDPutControlBlock(card, result);
}
s32 CARDSetStatusAsync(s32 chan, s32 fileNo, CARDStat* stat, CARDCallback callback) {
CARDControl* card;
CARDDir* dir;
CARDDir* ent;
s32 result;
if (fileNo < 0 || CARD_MAX_FILE <= fileNo || (stat->iconAddr != 0xffffffff && CARD_READ_SIZE <= stat->iconAddr) ||
(stat->commentAddr != 0xffffffff && CARD_SYSTEM_BLOCK_SIZE - CARD_COMMENT_SIZE < stat->commentAddr % CARD_SYSTEM_BLOCK_SIZE)) {
return CARD_RESULT_FATAL_ERROR;
}
result = __CARDGetControlBlock(chan, &card);
if (result < 0) {
return result;
}
dir = __CARDGetDirBlock(card);
ent = &dir[fileNo];
result = __CARDAccess(card, ent);
if (result < 0) {
return __CARDPutControlBlock(card, result);
}
ent->bannerFormat = stat->bannerFormat;
ent->iconAddr = stat->iconAddr;
ent->iconFormat = stat->iconFormat;
ent->iconSpeed = stat->iconSpeed;
ent->commentAddr = stat->commentAddr;
UpdateIconOffsets(ent, stat);
if (ent->iconAddr == 0xffffffff) {
CARDSetIconSpeed(ent, 0, CARD_STAT_SPEED_FAST);
}
ent->time = (u32)OSTicksToSeconds(OSGetTime());
result = __CARDUpdateDir(chan, callback);
if (result < 0) {
__CARDPutControlBlock(card, result);
}
return result;
}

View File

@ -0,0 +1,114 @@
#include <dolphin/card.h>
#include <dolphin/dsp.h>
#include <dolphin/dvd.h>
#include <dolphin/os.h>
#include <dolphin/CARDPriv.h>
static void EraseCallback(s32 chan, s32 result);
static void WriteCallback(s32 chan, s32 result) {
CARDControl* card;
CARDCallback callback;
u16* fat;
CARDDir* dir;
CARDDir* ent;
CARDFileInfo* fileInfo;
card = &__CARDBlock[chan];
if (result < 0) {
goto error;
}
fileInfo = card->fileInfo;
if (fileInfo->length < 0) {
result = CARD_RESULT_CANCELED;
goto error;
}
fileInfo->length -= card->sectorSize;
if (fileInfo->length <= 0) {
dir = __CARDGetDirBlock(card);
ent = &dir[fileInfo->fileNo];
ent->time = (u32)OSTicksToSeconds(OSGetTime());
callback = card->apiCallback;
card->apiCallback = 0;
result = __CARDUpdateDir(chan, callback);
} else {
fat = __CARDGetFatBlock(card);
fileInfo->offset += card->sectorSize;
fileInfo->iBlock = fat[fileInfo->iBlock];
if (!CARDIsValidBlockNo(card, fileInfo->iBlock)) {
result = CARD_RESULT_BROKEN;
goto error;
}
result = __CARDEraseSector(chan, card->sectorSize * (u32)fileInfo->iBlock, EraseCallback);
}
if (result < 0) {
goto error;
}
return;
error:
callback = card->apiCallback;
card->apiCallback = 0;
__CARDPutControlBlock(card, result);
callback(chan, result);
}
static void EraseCallback(s32 chan, s32 result) {
CARDControl* card;
CARDCallback callback;
CARDFileInfo* fileInfo;
card = &__CARDBlock[chan];
if (result < 0) {
goto error;
}
fileInfo = card->fileInfo;
result = __CARDWrite(chan, card->sectorSize * (u32)fileInfo->iBlock, card->sectorSize, card->buffer, WriteCallback);
if (result < 0) {
goto error;
}
return;
error:
callback = card->apiCallback;
card->apiCallback = 0;
__CARDPutControlBlock(card, result);
callback(chan, result);
}
s32 CARDWriteAsync(CARDFileInfo* fileInfo, const void* buf, s32 length, s32 offset, CARDCallback callback) {
CARDControl* card;
s32 result;
CARDDir* dir;
CARDDir* ent;
result = __CARDSeek(fileInfo, length, offset, &card);
if (result < 0) {
return result;
}
if (OFFSET(offset, card->sectorSize) != 0 || OFFSET(length, card->sectorSize) != 0) {
return __CARDPutControlBlock(card, CARD_RESULT_FATAL_ERROR);
}
dir = __CARDGetDirBlock(card);
ent = &dir[fileInfo->fileNo];
result = __CARDAccess(card, ent);
if (result < 0) {
return __CARDPutControlBlock(card, result);
}
DCStoreRange((void*)buf, (u32)length);
card->apiCallback = callback ? callback : __CARDDefaultApiCallback;
card->buffer = (void*)buf;
result = __CARDEraseSector(fileInfo->chan, card->sectorSize * (u32)fileInfo->iBlock, EraseCallback);
if (result < 0) {
__CARDPutControlBlock(card, result);
}
return result;
}