diff options
author | mrb0nk500 <b0nk@b0nk.xyz> | 2023-02-01 18:45:02 -0400 |
---|---|---|
committer | mrb0nk500 <b0nk@b0nk.xyz> | 2023-02-01 18:50:25 -0400 |
commit | 9fa0a7f1da1b70bee995f53c6c96c43189018772 (patch) | |
tree | 114548896790eaff23cdca84a025281de86bbb51 /src/Dolphin/card/CARDRead.c | |
parent | 2ba3289286bbfcf9fcc13fd135d976058d8b6c2e (diff) |
global: Import Dolphin SDK
This version comes from the Metroid Prime decompilation project.
https://github.com/PrimeDecomp/prime
Diffstat (limited to 'src/Dolphin/card/CARDRead.c')
-rw-r--r-- | src/Dolphin/card/CARDRead.c | 141 |
1 files changed, 141 insertions, 0 deletions
diff --git a/src/Dolphin/card/CARDRead.c b/src/Dolphin/card/CARDRead.c new file mode 100644 index 0000000..ffffc5f --- /dev/null +++ b/src/Dolphin/card/CARDRead.c @@ -0,0 +1,141 @@ +#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; +} |