mirror of
https://github.com/ACreTeam/ac-decomp
synced 2026-06-04 18:28:49 -04:00
355 lines
9.3 KiB
C
355 lines
9.3 KiB
C
#include "m_card.h"
|
|
|
|
#include "dolphin/private/card.h"
|
|
#include "libultra/libultra.h"
|
|
#include "m_malloc.h"
|
|
#include "libc64/sleep.h"
|
|
|
|
typedef struct card_bg_info {
|
|
int _00;
|
|
int _04;
|
|
int _08;
|
|
int _0C;
|
|
int _10;
|
|
int _14;
|
|
int space_proc;
|
|
int tries;
|
|
int _20;
|
|
int _24;
|
|
int _28;
|
|
} mCD_bg_info_c;
|
|
|
|
static char mCD_file_name[] = "DobutsunomoriP_MURA";
|
|
static int l_mcd_err_debug[mCD_ERROR_NUM] = { FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE };
|
|
static s32 l_mcd_err_result = CARD_RESULT_READY;
|
|
static mCD_bg_info_c l_mcd_bg_info;
|
|
|
|
static void mCD_ClearErrInfo(void) {
|
|
bzero(l_mcd_err_debug, sizeof(l_mcd_err_debug));
|
|
l_mcd_err_result = 0;
|
|
}
|
|
|
|
static void mCD_OnErrInfo(int err) {
|
|
if (err >= 0 && err < mCD_ERROR_NUM) {
|
|
l_mcd_err_debug[err] = TRUE;
|
|
}
|
|
}
|
|
|
|
static void mCD_OffErrInfo(int err) {
|
|
if (err >= 0 && err < mCD_ERROR_NUM) {
|
|
l_mcd_err_debug[err] = FALSE;
|
|
}
|
|
}
|
|
|
|
static void mCD_SetErrResult(s32 result) {
|
|
l_mcd_err_result = result;
|
|
}
|
|
|
|
extern void mCD_PrintErrInfo(gfxprint_t* gfxprint) {
|
|
gfxprint_color(gfxprint, 250, 100, 250, 255);
|
|
gfxprint_locate8x8(gfxprint, 22, 3);
|
|
|
|
if (l_mcd_err_debug[mCD_ERROR_NOT_ENABLED]) {
|
|
gfxprint_printf(gfxprint, "N");
|
|
}
|
|
|
|
if (l_mcd_err_debug[mCD_ERROR_AREA]) {
|
|
gfxprint_printf(gfxprint, "A");
|
|
}
|
|
|
|
if (l_mcd_err_debug[mCD_ERROR_WRITE]) {
|
|
gfxprint_printf(gfxprint, "W");
|
|
}
|
|
|
|
if (l_mcd_err_debug[mCD_ERROR_READ]) {
|
|
gfxprint_printf(gfxprint, "R");
|
|
}
|
|
|
|
if (l_mcd_err_debug[mCD_ERROR_CHECKSUM]) {
|
|
gfxprint_printf(gfxprint, "C");
|
|
}
|
|
|
|
if (l_mcd_err_debug[mCD_ERROR_OUTDATED]) {
|
|
gfxprint_printf(gfxprint, "O");
|
|
}
|
|
|
|
if (l_mcd_err_debug[mCD_ERROR_CREATE]) {
|
|
gfxprint_printf(gfxprint, "c");
|
|
}
|
|
|
|
if (l_mcd_err_result != CARD_RESULT_READY) {
|
|
gfxprint_printf(gfxprint, "%d", l_mcd_err_result);
|
|
}
|
|
}
|
|
|
|
static void* mCD_malloc_32(u32 size) {
|
|
return zelda_malloc_align(size, 32);
|
|
}
|
|
|
|
static int mCD_check_card_common(s32* result, s32 req_sector_size, s32 chan) {
|
|
s32 mem_size = 0;
|
|
s32 sector_size = 0;
|
|
int res = mCD_RESULT_BUSY;
|
|
|
|
*result = CARDProbeEx(chan, &mem_size, §or_size);
|
|
|
|
if (*result == CARD_RESULT_READY && sector_size == req_sector_size) {
|
|
res = mCD_RESULT_SUCCESS;
|
|
} else if (*result != CARD_RESULT_BUSY) {
|
|
res = mCD_RESULT_ERROR;
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
static int mCD_check_card(s32* result, s32 req_sector_size, s32 chan) {
|
|
int ms = 0;
|
|
int check_common_res = mCD_RESULT_BUSY;
|
|
int res = mCD_RESULT_ERROR;
|
|
|
|
while (check_common_res == mCD_RESULT_BUSY && ms < 500) {
|
|
check_common_res = mCD_check_card_common(result, req_sector_size, chan);
|
|
|
|
if (check_common_res == mCD_RESULT_BUSY) {
|
|
msleep(1);
|
|
ms++;
|
|
}
|
|
}
|
|
|
|
if (check_common_res == mCD_RESULT_SUCCESS) {
|
|
res = mCD_RESULT_SUCCESS;
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
static int mCD_check_sector_size(s32 req_sector_size, s32 chan) {
|
|
s32 mem_size = 0;
|
|
s32 sector_size = 0;
|
|
s32 result = CARD_RESULT_BUSY;
|
|
int ms = 0;
|
|
int res = mCD_RESULT_BUSY;
|
|
|
|
while (result == CARD_RESULT_BUSY && ms < 500) {
|
|
result = CARDProbeEx(chan, &mem_size, §or_size);
|
|
|
|
if (result == CARD_RESULT_BUSY) {
|
|
msleep(1);
|
|
ms++;
|
|
}
|
|
}
|
|
|
|
if (result == CARD_RESULT_READY) {
|
|
if (req_sector_size == sector_size) {
|
|
res = mCD_RESULT_SUCCESS;
|
|
} else {
|
|
res = mCD_RESULT_BUSY;
|
|
}
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
static int mCD_get_file_num_common(s32 chan) {
|
|
CARDFileInfo fileInfo;
|
|
s32 num = 0;
|
|
s32 file_no;
|
|
|
|
for (file_no = 0; file_no < CARD_MAX_FILE; file_no++) {
|
|
s32 result = CARDFastOpen(chan, file_no, &fileInfo);
|
|
|
|
if (result == CARD_RESULT_READY) {
|
|
num++;
|
|
CARDClose(&fileInfo);
|
|
}
|
|
}
|
|
|
|
return num;
|
|
}
|
|
|
|
static int mCD_get_file_num(void* workArea, s32 chan) {
|
|
int num = 0;
|
|
s32 result;
|
|
|
|
if (workArea != NULL && mCD_check_card(&result, mCD_MEMCARD_SECTORSIZE, chan) == mCD_RESULT_SUCCESS) {
|
|
result = CARDMount(chan, workArea, NULL);
|
|
|
|
if (result == CARD_RESULT_READY || result == CARD_RESULT_BROKEN) {
|
|
result = CARDCheck(chan);
|
|
num = mCD_get_file_num_common(chan);
|
|
CARDUnmount(chan);
|
|
} else if (result == CARD_RESULT_ENCODING) {
|
|
CARDUnmount(chan);
|
|
}
|
|
}
|
|
|
|
return num;
|
|
}
|
|
|
|
extern void mCD_init_card(void) {
|
|
CARDInit();
|
|
}
|
|
|
|
static void mCD_ClearCardBgInfo(mCD_bg_info_c* bg_info) {
|
|
bzero(bg_info, sizeof(mCD_bg_info_c));
|
|
}
|
|
|
|
static void mCD_StartSetCardBgInfo(void) {
|
|
mCD_ClearCardBgInfo(&l_mcd_bg_info);
|
|
}
|
|
|
|
static int mCD_get_space_bg_get_slot(s32* freeBlocks, mCD_bg_info_c* bg_info, s32 chan, s32* result, void* workArea) {
|
|
int res;
|
|
|
|
bg_info->tries++;
|
|
res = mCD_check_card_common(result, mCD_MEMCARD_SECTORSIZE, chan);
|
|
if (res == mCD_RESULT_SUCCESS && workArea != NULL) {
|
|
*freeBlocks = 0;
|
|
*result = CARDMountAsync(chan, workArea, NULL, NULL);
|
|
|
|
if (*result == CARD_RESULT_ENCODING) {
|
|
CARDUnmount(chan);
|
|
res = mCD_RESULT_ERROR;
|
|
} else if (*result != CARD_RESULT_READY && *result != CARD_RESULT_BROKEN) {
|
|
res = mCD_RESULT_ERROR;
|
|
}
|
|
|
|
bg_info->tries = 0;
|
|
} else if (res != mCD_RESULT_BUSY) {
|
|
*freeBlocks = 0;
|
|
res = mCD_RESULT_ERROR;
|
|
bg_info->tries = 0;
|
|
} else if (bg_info->tries >= 100) {
|
|
*freeBlocks = 0;
|
|
res = mCD_RESULT_ERROR;
|
|
bg_info->tries = 0;
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
static int mCD_get_space_bg_main(s32* freeBlocks, mCD_bg_info_c* bg_info, s32 chan, s32* result, void* workArea) {
|
|
int res = mCD_RESULT_BUSY;
|
|
|
|
*result = CARDGetResultCode(chan);
|
|
if (*result == CARD_RESULT_READY || *result == CARD_RESULT_BROKEN) {
|
|
*result = CARDCheck(chan);
|
|
|
|
if (*result == CARD_RESULT_READY) {
|
|
s32 freeFiles;
|
|
|
|
*result = CARDFreeBlocks(chan, freeBlocks, &freeFiles);
|
|
if (*result == CARD_RESULT_READY) {
|
|
res = mCD_RESULT_SUCCESS;
|
|
} else {
|
|
res = mCD_RESULT_ERROR;
|
|
}
|
|
} else {
|
|
res = mCD_RESULT_ERROR;
|
|
}
|
|
|
|
CARDUnmount(chan);
|
|
} else if (*result != CARD_RESULT_BUSY) {
|
|
if (*result == CARD_RESULT_ENCODING) {
|
|
CARDUnmount(chan);
|
|
}
|
|
|
|
res = mCD_RESULT_ERROR;
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
typedef int (*mCD_GET_SPACE_BG_PROC)(s32*, mCD_bg_info_c*, s32, s32*, void*);
|
|
static int mCD_get_space_bg(s32* freeBlocks, s32 chan, s32* result, void* workArea) {
|
|
static mCD_GET_SPACE_BG_PROC get_proc[mCD_SPACE_BG_NUM] = { &mCD_get_space_bg_get_slot, &mCD_get_space_bg_main };
|
|
mCD_bg_info_c* bg_info = &l_mcd_bg_info;
|
|
u8 proc_type = bg_info->space_proc;
|
|
int res = mCD_RESULT_BUSY;
|
|
|
|
*freeBlocks = 0;
|
|
if (proc_type < mCD_SPACE_BG_NUM) {
|
|
int proc_res = (*get_proc[proc_type])(freeBlocks, bg_info, chan, result, workArea);
|
|
|
|
if (proc_res == mCD_RESULT_SUCCESS) {
|
|
bg_info->space_proc++;
|
|
|
|
if (bg_info->space_proc >= mCD_SPACE_BG_NUM) {
|
|
res = mCD_RESULT_SUCCESS;
|
|
mCD_ClearCardBgInfo(bg_info);
|
|
}
|
|
} else if (proc_res != mCD_RESULT_BUSY) {
|
|
res = mCD_RESULT_ERROR;
|
|
mCD_ClearCardBgInfo(bg_info);
|
|
}
|
|
} else {
|
|
res = mCD_RESULT_ERROR;
|
|
mCD_ClearCardBgInfo(bg_info);
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
static void mCD_close_and_unmount(CARDFileInfo* fileInfo, s32 chan) {
|
|
CARDClose(fileInfo);
|
|
CARDUnmount(chan);
|
|
}
|
|
|
|
static int mCD_bg_check_slot(mCD_bg_info_c* bg_info, s32 chan, s32* result) {
|
|
int res = mCD_RESULT_BUSY;
|
|
int common_res = mCD_check_card_common(result, mCD_MEMCARD_SECTORSIZE, chan);
|
|
|
|
bg_info->tries++;
|
|
if (common_res == mCD_RESULT_SUCCESS) {
|
|
bg_info->space_proc++;
|
|
bg_info->tries = 0;
|
|
res = mCD_RESULT_SUCCESS;
|
|
} else if (common_res != mCD_RESULT_BUSY || bg_info->tries >= 100) {
|
|
bg_info->tries = 0;
|
|
res = mCD_RESULT_ERROR;
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
static int mCD_bg_init_com(mCD_bg_info_c* bg_info, s32 chan, s32* result, void** workArea_p, void** read_p, int read) {
|
|
int res;
|
|
|
|
*workArea_p = mCD_malloc_32(CARD_WORKAREA_SIZE);
|
|
if (read == TRUE) {
|
|
*read_p = mCD_malloc_32(mCD_MEMCARD_SECTORSIZE);
|
|
}
|
|
|
|
if (*workArea_p != NULL && (read == FALSE || (read == TRUE && *read_p != NULL))) {
|
|
*result = CARDMountAsync(chan, *workArea_p, NULL, NULL);
|
|
|
|
if (*result == CARD_RESULT_READY) {
|
|
bg_info->space_proc++;
|
|
res = mCD_RESULT_SUCCESS;
|
|
} else if (*result == CARD_RESULT_BROKEN) {
|
|
*result = CARDCheckAsync(chan, NULL);
|
|
|
|
if (*result == CARD_RESULT_READY) {
|
|
bg_info->space_proc++;
|
|
res = mCD_RESULT_SUCCESS;
|
|
} else {
|
|
if (*result == CARD_RESULT_BROKEN || *result == CARD_RESULT_ENCODING) {
|
|
CARDUnmount(chan);
|
|
}
|
|
|
|
res = mCD_RESULT_ERROR;
|
|
}
|
|
} else {
|
|
if (*result == CARD_RESULT_ENCODING) {
|
|
CARDUnmount(chan);
|
|
}
|
|
|
|
res = mCD_RESULT_ERROR;
|
|
}
|
|
} else {
|
|
res = mCD_RESULT_ERROR;
|
|
}
|
|
|
|
return res;
|
|
}
|