mirror of
https://github.com/ACreTeam/ac-decomp
synced 2026-06-10 20:28:20 -04:00
4718 lines
149 KiB
C
4718 lines
149 KiB
C
#include "m_card.h"
|
|
|
|
#include "card/__card.h"
|
|
#include "libultra/libultra.h"
|
|
#include "m_malloc.h"
|
|
#include "libc64/sleep.h"
|
|
#include "m_common_data.h"
|
|
#include "m_font.h"
|
|
#include "jsyswrap.h"
|
|
#include "zurumode.h"
|
|
#include "m_house.h"
|
|
#include "m_cockroach.h"
|
|
|
|
typedef struct card_bg_info {
|
|
CARDFileInfo fileInfo;
|
|
s32 fileNo;
|
|
int space_proc;
|
|
int tries;
|
|
void* data;
|
|
s32 offset;
|
|
s32 length;
|
|
} mCD_bg_info_c;
|
|
|
|
enum {
|
|
mCD_WBC_CHECK_SLOT,
|
|
mCD_WBC_INIT,
|
|
mCD_WBC_CHECK_FILESYSTEM,
|
|
mCD_WBC_OPEN_FILE,
|
|
mCD_WBC_READ,
|
|
mCD_WBC_WRITE,
|
|
|
|
mCD_WBC_FINISHED,
|
|
mCD_WBC_NUM = mCD_WBC_FINISHED
|
|
};
|
|
|
|
enum {
|
|
mCD_SAVEHOME_BG_PROC_GET_AREA,
|
|
mCD_SAVEHOME_BG_PROC_ERASE_DUMMY,
|
|
mCD_SAVEHOME_BG_PROC_CHECK_SLOT,
|
|
mCD_SAVEHOME_BG_PROC_READ_SEND_PRESENT,
|
|
mCD_SAVEHOME_BG_PROC_WRITE_PRESENT,
|
|
mCD_SAVEHOME_BG_PROC_GET_SLOT,
|
|
mCD_SAVEHOME_BG_PROC_CREATE_FILE,
|
|
mCD_SAVEHOME_BG_PROC_CHECK_REPAIR_LAND,
|
|
mCD_SAVEHOME_BG_PROC_REPAIR_LAND,
|
|
mCD_SAVEHOME_BG_PROC_SET_FILE_PERMISSION,
|
|
mCD_SAVEHOME_BG_PROC_SET_DATA,
|
|
mCD_SAVEHOME_BG_PROC_WRITE_MAIN_2,
|
|
mCD_SAVEHOME_BG_PROC_WRITE_BK,
|
|
mCD_SAVEHOME_BG_PROC_SET_OTHERS,
|
|
mCD_SAVEHOME_BG_PROC_WRITE_OTHERS,
|
|
mCD_SAVEHOME_BG_PROC_GET_STATUS_2,
|
|
mCD_SAVEHOME_BG_PROC_SET_STATUS_2,
|
|
mCD_SAVEHOME_BG_PROC_RENAME,
|
|
|
|
mCD_SAVEHOME_BG_PROC_NUM
|
|
};
|
|
|
|
static char mCD_file_name[32] = "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(u32 req_sector_size, int chan) {
|
|
s32 mem_size = 0;
|
|
s32 sector_size = 0;
|
|
int ms = 0;
|
|
s32 result = CARD_RESULT_BUSY;
|
|
int res = mCD_RESULT_ERROR;
|
|
|
|
while (result == CARD_RESULT_BUSY && ms < 500) {
|
|
result = CARDProbeEx((s32)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_com(int 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, int chan) {
|
|
int num = 0;
|
|
s32 result;
|
|
|
|
if (workArea != NULL && mCD_check_card(&result, mCD_MEMCARD_SECTORSIZE, chan) == mCD_RESULT_SUCCESS) {
|
|
result = CARDMount((s32)chan, workArea, NULL);
|
|
|
|
if (result == CARD_RESULT_READY || result == CARD_RESULT_BROKEN) {
|
|
result = CARDCheck((s32)chan);
|
|
num = mCD_get_file_num_com(chan);
|
|
CARDUnmount((s32)chan);
|
|
} else if (result == CARD_RESULT_ENCODING) {
|
|
CARDUnmount((s32)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, (s32)chan);
|
|
if (res == mCD_RESULT_SUCCESS && workArea != NULL) {
|
|
*freeBlocks = 0;
|
|
*result = CARDMountAsync((s32)chan, workArea, NULL, NULL);
|
|
|
|
if (*result == CARD_RESULT_ENCODING) {
|
|
CARDUnmount((s32)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((s32)chan);
|
|
if (*result == CARD_RESULT_READY || *result == CARD_RESULT_BROKEN) {
|
|
*result = CARDCheck((s32)chan);
|
|
|
|
if (*result == CARD_RESULT_READY) {
|
|
s32 freeFiles;
|
|
|
|
*result = CARDFreeBlocks((s32)chan, freeBlocks, &freeFiles);
|
|
if (*result == CARD_RESULT_READY) {
|
|
res = mCD_RESULT_SUCCESS;
|
|
} else {
|
|
res = mCD_RESULT_ERROR;
|
|
}
|
|
} else {
|
|
res = mCD_RESULT_ERROR;
|
|
}
|
|
|
|
CARDUnmount((s32)chan);
|
|
} else if (*result != CARD_RESULT_BUSY) {
|
|
if (*result == CARD_RESULT_ENCODING) {
|
|
CARDUnmount((s32)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, void* data, const char* filename, s32 data_len,
|
|
u32 length, s32 offset, void** workArea_p, void** read_p, CARDStat* stat) {
|
|
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((s32)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((s32)chan, NULL);
|
|
|
|
if (*result == CARD_RESULT_READY) {
|
|
bg_info->space_proc = 3;
|
|
res = mCD_RESULT_SUCCESS;
|
|
} else {
|
|
if (*result == CARD_RESULT_BROKEN || *result == CARD_RESULT_ENCODING) {
|
|
CARDUnmount((s32)chan);
|
|
}
|
|
|
|
res = mCD_RESULT_ERROR;
|
|
}
|
|
} else {
|
|
if (*result == CARD_RESULT_ENCODING) {
|
|
CARDUnmount((s32)chan);
|
|
}
|
|
|
|
res = mCD_RESULT_ERROR;
|
|
}
|
|
} else {
|
|
res = mCD_RESULT_ERROR;
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
static int mCD_bg_init(mCD_bg_info_c* bg_info, s32 chan, s32* result, void* data, const char* filename, s32 data_len,
|
|
u32 length, s32 offset, void** workArea_p, void** read_p, CARDStat* stat) {
|
|
return mCD_bg_init_com(bg_info, chan, result, workArea_p, read_p, FALSE);
|
|
}
|
|
|
|
static int mCD_bg_check_filesystem(mCD_bg_info_c* bg_info, s32 chan, s32* result, void* data, const char* filename,
|
|
s32 data_len, u32 length, s32 offset, void** workArea_p, void** read_p,
|
|
CARDStat* stat) {
|
|
int res = mCD_RESULT_BUSY;
|
|
|
|
*result = CARDGetResultCode((s32)chan);
|
|
if (*result == CARD_RESULT_READY) {
|
|
*result = CARDCheckAsync((s32)chan, NULL);
|
|
if (*result == CARD_RESULT_READY) {
|
|
bg_info->space_proc++;
|
|
res = mCD_RESULT_SUCCESS;
|
|
} else {
|
|
CARDUnmount((s32)chan);
|
|
res = mCD_RESULT_ERROR;
|
|
}
|
|
} else if (*result != CARD_RESULT_BUSY) {
|
|
res = mCD_RESULT_ERROR;
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
static int mCD_write_bg_open_file(mCD_bg_info_c* bg_info, s32 chan, s32* result, void* data, const char* filename,
|
|
s32 data_len, u32 length, s32 offset, void** workArea_p, void** read_p,
|
|
CARDStat* stat) {
|
|
int res = mCD_RESULT_BUSY;
|
|
|
|
*result = CARDGetResultCode((s32)chan);
|
|
if (*result == CARD_RESULT_READY) {
|
|
*result = CARDOpen((s32)chan, filename, &bg_info->fileInfo);
|
|
if (*result == CARD_RESULT_READY) {
|
|
CARDStat stat;
|
|
|
|
bg_info->fileNo = bg_info->fileInfo.fileNo;
|
|
*result = CARDGetStatus((s32)chan, bg_info->fileNo, &stat);
|
|
if (*result == CARD_RESULT_READY && stat.length == length) {
|
|
*result = CARDWriteAsync(&bg_info->fileInfo, data, data_len, offset, NULL);
|
|
if (*result == CARD_RESULT_READY) {
|
|
bg_info->space_proc++;
|
|
res = mCD_RESULT_SUCCESS;
|
|
} else {
|
|
mCD_close_and_unmount(&bg_info->fileInfo, (s32)chan);
|
|
res = mCD_RESULT_ERROR;
|
|
}
|
|
} else {
|
|
mCD_close_and_unmount(&bg_info->fileInfo, (s32)chan);
|
|
res = mCD_RESULT_ERROR;
|
|
}
|
|
} else {
|
|
CARDUnmount((s32)chan);
|
|
res = mCD_RESULT_ERROR;
|
|
}
|
|
} else if (*result != CARD_RESULT_BUSY) {
|
|
res = mCD_RESULT_ERROR;
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
static int mCD_write_bg_write(mCD_bg_info_c* bg_info, s32 chan, s32* result, void* data, const char* filename,
|
|
s32 data_len, u32 length, s32 offset, void** workArea_p, void** read_p, CARDStat* stat) {
|
|
int res = mCD_RESULT_BUSY;
|
|
|
|
*result = CARDGetResultCode(chan);
|
|
if (*result == CARD_RESULT_READY) {
|
|
*result = CARDWriteAsync(&bg_info->fileInfo, data, data_len, offset, NULL);
|
|
if (*result == CARD_RESULT_READY) {
|
|
bg_info->space_proc++;
|
|
res = mCD_RESULT_SUCCESS;
|
|
} else {
|
|
res = mCD_RESULT_ERROR;
|
|
}
|
|
} else if (*result != CARD_RESULT_BUSY) {
|
|
mCD_close_and_unmount(&bg_info->fileInfo, chan);
|
|
res = mCD_RESULT_ERROR;
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
static int mCD_write_bg_cleanup(mCD_bg_info_c* bg_info, s32 chan, s32* result, void* data, const char* filename,
|
|
s32 data_len, u32 length, s32 offset, void** workArea_p, void** read_p,
|
|
CARDStat* stat) {
|
|
int res = mCD_RESULT_BUSY;
|
|
|
|
*result = CARDGetResultCode(chan);
|
|
if (*result != CARD_RESULT_BUSY) {
|
|
mCD_close_and_unmount(&bg_info->fileInfo, chan);
|
|
bg_info->space_proc++;
|
|
res = mCD_RESULT_SUCCESS;
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
typedef int (*mCD_BG_PROC)(mCD_bg_info_c*, s32, s32*, void*, const char*, s32, u32, s32, void**, void**, CARDStat*);
|
|
|
|
/* @unused static int mCD_write_bg(void* data, const char* filename, s32 data_len, u32 length, s32 offset, s32 chan,
|
|
* s32* result) */
|
|
static int mCD_write_bg(void* data, const char* filename, s32 data_len, u32 length, s32 offset,
|
|
s32 chan, s32* result) {
|
|
static void* work_p = NULL;
|
|
// clang-format off
|
|
static mCD_BG_PROC wbg_proc[] = {
|
|
&mCD_bg_check_slot,
|
|
&mCD_bg_init,
|
|
&mCD_bg_check_filesystem,
|
|
&mCD_write_bg_open_file,
|
|
&mCD_write_bg_write,
|
|
&mCD_write_bg_cleanup,
|
|
};
|
|
// clang-format on
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int mCD_bg_init_write_comp(mCD_bg_info_c* bg_info, s32 chan, s32* result, void* data, const char* filename,
|
|
s32 data_len, u32 length, s32 offset, void** workArea_p, void** read_p,
|
|
CARDStat* stat) {
|
|
int res = mCD_bg_init_com(bg_info, chan, result, workArea_p, read_p, TRUE);
|
|
|
|
if (res == mCD_RESULT_SUCCESS) {
|
|
bg_info->data = data;
|
|
bg_info->offset = offset;
|
|
if (data_len < mCD_MEMCARD_SECTORSIZE) {
|
|
bg_info->length = data_len;
|
|
} else {
|
|
bg_info->length = mCD_MEMCARD_SECTORSIZE;
|
|
}
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
static int mCD_write_comp_bg_open_file(mCD_bg_info_c* bg_info, s32 chan, s32* result, void* data, const char* filename,
|
|
s32 data_len, u32 length, s32 offset, void** workArea_p, void** read_p,
|
|
CARDStat* stat) {
|
|
int res = mCD_RESULT_BUSY;
|
|
|
|
*result = CARDGetResultCode((s32)chan);
|
|
if (*result == CARD_RESULT_READY) {
|
|
*result = CARDOpen((s32)chan, filename, &bg_info->fileInfo);
|
|
if (*result == CARD_RESULT_READY) {
|
|
CARDStat stat;
|
|
|
|
bg_info->fileNo = bg_info->fileInfo.fileNo;
|
|
*result = CARDGetStatus((s32)chan, bg_info->fileNo, &stat);
|
|
if (*result == CARD_RESULT_READY && stat.length == length) {
|
|
bzero(*read_p, mCD_MEMCARD_SECTORSIZE);
|
|
*result = CARDReadAsync(&bg_info->fileInfo, *read_p, bg_info->length, bg_info->offset, NULL);
|
|
if (*result == CARD_RESULT_READY) {
|
|
bg_info->space_proc++;
|
|
res = mCD_RESULT_SUCCESS;
|
|
} else {
|
|
res = mCD_RESULT_ERROR;
|
|
mCD_close_and_unmount(&bg_info->fileInfo, chan);
|
|
}
|
|
} else {
|
|
mCD_close_and_unmount(&bg_info->fileInfo, chan);
|
|
res = mCD_RESULT_ERROR;
|
|
}
|
|
} else {
|
|
CARDUnmount((s32)chan);
|
|
res = mCD_RESULT_ERROR;
|
|
}
|
|
} else if (*result != CARD_RESULT_BUSY) {
|
|
res = mCD_RESULT_ERROR;
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
static int mCD_write_comp_bg_read(mCD_bg_info_c* bg_info, s32 chan, s32* result, void* data, const char* filename,
|
|
s32 data_len, u32 length, s32 offset, void** workArea_p, void** read_p,
|
|
CARDStat* stat) {
|
|
int res = mCD_RESULT_BUSY;
|
|
|
|
*result = CARDGetResultCode(chan);
|
|
if (*result == CARD_RESULT_READY) {
|
|
if (mem_cmp((u8*)*read_p, (u8*)bg_info->data, bg_info->length) == 0) {
|
|
*result = CARDWriteAsync(&bg_info->fileInfo, bg_info->data, bg_info->length, bg_info->offset, NULL);
|
|
if (*result == CARD_RESULT_READY) {
|
|
bg_info->space_proc++;
|
|
res = mCD_RESULT_SUCCESS;
|
|
} else {
|
|
mCD_close_and_unmount(&bg_info->fileInfo, chan);
|
|
res = mCD_RESULT_ERROR;
|
|
}
|
|
} else {
|
|
int ofs;
|
|
|
|
bg_info->offset += mCD_MEMCARD_SECTORSIZE;
|
|
ofs = bg_info->offset - offset;
|
|
|
|
if (ofs >= data_len) {
|
|
mCD_close_and_unmount(&bg_info->fileInfo, chan);
|
|
bg_info->space_proc = mCD_WBC_FINISHED;
|
|
res = mCD_RESULT_SUCCESS;
|
|
} else {
|
|
if (data_len - ofs < mCD_MEMCARD_SECTORSIZE) {
|
|
bg_info->length = data_len - ofs; /* Remaining size less than memcard sector size */
|
|
} else {
|
|
bg_info->length = mCD_MEMCARD_SECTORSIZE;
|
|
}
|
|
|
|
bg_info->data = (void*)((u32)data + ofs);
|
|
bzero(*read_p, mCD_MEMCARD_SECTORSIZE);
|
|
*result = CARDReadAsync(&bg_info->fileInfo, *read_p, bg_info->length, bg_info->offset, NULL);
|
|
if (*result == CARD_RESULT_READY) {
|
|
bg_info->space_proc = mCD_WBC_READ;
|
|
res = mCD_RESULT_SUCCESS;
|
|
} else {
|
|
mCD_close_and_unmount(&bg_info->fileInfo, chan);
|
|
res = mCD_RESULT_ERROR;
|
|
}
|
|
}
|
|
}
|
|
} else if (*result != CARD_RESULT_BUSY) {
|
|
mCD_close_and_unmount(&bg_info->fileInfo, chan);
|
|
res = mCD_RESULT_ERROR;
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
static int mCD_write_comp_bg_write(mCD_bg_info_c* bg_info, s32 chan, s32* result, void* data, const char* filename,
|
|
s32 data_len, u32 length, s32 offset, void** workArea_p, void** read_p,
|
|
CARDStat* stat) {
|
|
int res = mCD_RESULT_BUSY;
|
|
int ofs;
|
|
|
|
*result = CARDGetResultCode((s32)chan);
|
|
if (*result == CARD_RESULT_READY) {
|
|
bg_info->offset += mCD_MEMCARD_SECTORSIZE;
|
|
ofs = bg_info->offset - offset;
|
|
|
|
if (ofs >= data_len) {
|
|
mCD_close_and_unmount(&bg_info->fileInfo, chan);
|
|
bg_info->space_proc = mCD_WBC_FINISHED;
|
|
res = mCD_RESULT_SUCCESS;
|
|
} else {
|
|
if (data_len - ofs < mCD_MEMCARD_SECTORSIZE) {
|
|
bg_info->length = data_len - ofs; /* Remaining size less than memcard sector size */
|
|
} else {
|
|
bg_info->length = mCD_MEMCARD_SECTORSIZE;
|
|
}
|
|
bg_info->data = (void*)((u32)data + ofs);
|
|
bzero(*read_p, mCD_MEMCARD_SECTORSIZE);
|
|
|
|
*result = CARDReadAsync(&bg_info->fileInfo, *read_p, bg_info->length, bg_info->offset, NULL);
|
|
if (*result == CARD_RESULT_READY) {
|
|
bg_info->space_proc = mCD_WBC_READ;
|
|
res = mCD_RESULT_SUCCESS;
|
|
} else {
|
|
mCD_close_and_unmount(&bg_info->fileInfo, chan);
|
|
res = mCD_RESULT_ERROR;
|
|
}
|
|
}
|
|
} else if (*result != CARD_RESULT_BUSY) {
|
|
mCD_close_and_unmount(&bg_info->fileInfo, chan);
|
|
res = mCD_RESULT_ERROR;
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
static int mCD_write_comp_bg(void* data, const char* filename, s32 data_len, u32 length, s32 offset, s32 chan,
|
|
s32* result) {
|
|
static void* work_p = NULL;
|
|
static void* read_p = NULL;
|
|
// clang-format off
|
|
static mCD_BG_PROC wcbg_proc[] = {
|
|
&mCD_bg_check_slot,
|
|
&mCD_bg_init_write_comp,
|
|
&mCD_bg_check_filesystem,
|
|
&mCD_write_comp_bg_open_file,
|
|
&mCD_write_comp_bg_read,
|
|
&mCD_write_comp_bg_write,
|
|
};
|
|
// clang-format on
|
|
|
|
int res = mCD_RESULT_BUSY;
|
|
mCD_bg_info_c* bg_info = &l_mcd_bg_info;
|
|
int proc = bg_info->space_proc;
|
|
|
|
if (proc >= 0 && proc < mCD_WBC_NUM) {
|
|
int success = (*wcbg_proc[proc])(bg_info, chan, result, data, filename, data_len, length, offset,
|
|
&work_p, &read_p, NULL);
|
|
|
|
if (success == mCD_RESULT_SUCCESS && bg_info->space_proc == mCD_WBC_FINISHED) {
|
|
mCD_ClearCardBgInfo(bg_info);
|
|
res = mCD_RESULT_SUCCESS;
|
|
} else if (success == mCD_RESULT_ERROR) {
|
|
mCD_ClearCardBgInfo(bg_info);
|
|
res = mCD_RESULT_ERROR;
|
|
}
|
|
|
|
if (res != mCD_RESULT_BUSY) {
|
|
if (work_p != NULL) {
|
|
zelda_free(work_p);
|
|
work_p = NULL;
|
|
}
|
|
|
|
if (read_p != NULL) {
|
|
zelda_free(read_p);
|
|
read_p = NULL;
|
|
}
|
|
}
|
|
} else {
|
|
if (work_p != NULL) {
|
|
zelda_free(work_p);
|
|
work_p = NULL;
|
|
}
|
|
|
|
if (read_p != NULL) {
|
|
zelda_free(read_p);
|
|
read_p = NULL;
|
|
}
|
|
|
|
mCD_ClearCardBgInfo(bg_info);
|
|
work_p = NULL; // extra set
|
|
res = mCD_RESULT_ERROR;
|
|
}
|
|
|
|
/* Debug display for error state */
|
|
if (ZURUMODE2_ENABLED()) {
|
|
if (res == mCD_RESULT_ERROR) {
|
|
mCD_OnErrInfo(mCD_ERROR_WRITE);
|
|
mCD_SetErrResult(*result);
|
|
} else if (res == mCD_RESULT_SUCCESS) {
|
|
mCD_OffErrInfo(mCD_ERROR_WRITE);
|
|
mCD_SetErrResult(*result);
|
|
}
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
static int mCD_read_bg_open_file(mCD_bg_info_c* bg_info, s32 chan, s32* result, void* data, const char* filename,
|
|
s32 data_len, u32 length, s32 offset, void** workArea_p, void** read_p,
|
|
CARDStat* stat) {
|
|
int res = mCD_RESULT_BUSY;
|
|
|
|
*result = CARDGetResultCode((s32)chan);
|
|
if (*result == CARD_RESULT_READY) {
|
|
*result = CARDOpen((s32)chan, filename, &bg_info->fileInfo);
|
|
if (*result == CARD_RESULT_READY) {
|
|
*result = CARDReadAsync(&bg_info->fileInfo, data, data_len, offset, NULL);
|
|
|
|
if (*result == CARD_RESULT_READY) {
|
|
bg_info->space_proc = 4;
|
|
res = mCD_RESULT_SUCCESS;
|
|
} else {
|
|
mCD_close_and_unmount(&bg_info->fileInfo, chan);
|
|
res = mCD_RESULT_ERROR;
|
|
}
|
|
} else {
|
|
CARDUnmount((s32)chan);
|
|
res = mCD_RESULT_ERROR;
|
|
}
|
|
} else if (*result != CARD_RESULT_BUSY) {
|
|
if (*result == CARD_RESULT_BROKEN || *result == CARD_RESULT_ENCODING) {
|
|
CARDUnmount((s32)chan);
|
|
}
|
|
|
|
res = mCD_RESULT_ERROR;
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
static int mCD_read_bg_cleanup(mCD_bg_info_c* bg_info, s32 chan, s32* result, void* data, const char* filename,
|
|
s32 data_len, u32 length, s32 offset, void** workArea_p, void** read_p, CARDStat* stat) {
|
|
int res = mCD_RESULT_BUSY;
|
|
|
|
*result = CARDGetResultCode(chan);
|
|
if (*result != CARD_RESULT_BUSY) {
|
|
mCD_close_and_unmount(&bg_info->fileInfo, chan);
|
|
bg_info->space_proc++;
|
|
res = mCD_RESULT_SUCCESS;
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
/* @unused */
|
|
static int mCD_read_bg(void* data, const char* filename, s32 data_len, u32 length, s32 offset, s32 chan, s32* result) {
|
|
static void* work_p = NULL;
|
|
// clang-format off
|
|
static mCD_BG_PROC rbg_proc[] = {
|
|
&mCD_bg_check_slot,
|
|
&mCD_bg_init,
|
|
&mCD_bg_check_filesystem,
|
|
&mCD_read_bg_open_file,
|
|
&mCD_read_bg_cleanup,
|
|
};
|
|
// clang-format on
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int mCD_read_fg(void* buf, const char* filename, s32 length, s32 offset, s32 chan, s32* result) {
|
|
void* workArea;
|
|
int res = mCD_RESULT_ERROR;
|
|
|
|
if (buf != NULL && IS_ALIGNED((u32)buf, 32)) {
|
|
int card_res = mCD_check_card(result, mCD_MEMCARD_SECTORSIZE, chan);
|
|
|
|
if (card_res == mCD_RESULT_SUCCESS) {
|
|
workArea = mCD_malloc_32(CARD_WORKAREA_SIZE);
|
|
|
|
if (workArea != NULL) {
|
|
*result = CARDMount((s32)chan, workArea, NULL);
|
|
if (*result == CARD_RESULT_READY || *result == CARD_RESULT_BROKEN) {
|
|
*result = CARDCheck((s32)chan);
|
|
if (*result == CARD_RESULT_READY) {
|
|
CARDFileInfo fileInfo;
|
|
|
|
*result = CARDOpen((s32)chan, filename, &fileInfo);
|
|
if (*result == CARD_RESULT_READY) {
|
|
*result = CARDRead(&fileInfo, buf, length, offset);
|
|
if (*result == CARD_RESULT_READY) {
|
|
res = mCD_RESULT_SUCCESS;
|
|
}
|
|
|
|
mCD_close_and_unmount(&fileInfo, chan);
|
|
} else {
|
|
CARDUnmount((s32)chan);
|
|
}
|
|
} else {
|
|
CARDUnmount((s32)chan);
|
|
}
|
|
} else if (*result == CARD_RESULT_ENCODING) {
|
|
CARDUnmount((s32)chan);
|
|
}
|
|
|
|
if (workArea != NULL) {
|
|
zelda_free(workArea);
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
*result = CARD_RESULT_FATAL_ERROR;
|
|
res = mCD_RESULT_ERROR;
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
static int mCD_find_fg(const char* filename, void* workArea, s32 chan, s32* result) {
|
|
int res = FALSE;
|
|
|
|
if (mCD_check_card(result, mCD_MEMCARD_SECTORSIZE, chan) == mCD_RESULT_SUCCESS && workArea != NULL) {
|
|
*result = CARDMount((s32)chan, workArea, NULL);
|
|
if (*result == CARD_RESULT_READY || *result == CARD_RESULT_BROKEN) {
|
|
*result = CARDCheck((s32)chan);
|
|
if (*result == CARD_RESULT_READY) {
|
|
CARDFileInfo fileInfo;
|
|
|
|
*result = CARDOpen((s32)chan, filename, &fileInfo);
|
|
if (*result == CARD_RESULT_READY) {
|
|
mCD_close_and_unmount(&fileInfo, chan);
|
|
res = TRUE;
|
|
} else {
|
|
CARDUnmount((s32)chan);
|
|
}
|
|
} else {
|
|
CARDUnmount((s32)chan);
|
|
}
|
|
} else if (*result == CARD_RESULT_ENCODING) {
|
|
CARDUnmount((s32)chan);
|
|
}
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
static int mCD_format_bg_mount(mCD_bg_info_c* bg_info, s32 chan, s32* result, void* data, const char* filename,
|
|
s32 data_len, u32 length, s32 offset, void** workArea_p, void** read_p, CARDStat* stat) {
|
|
*workArea_p = mCD_malloc_32(CARD_WORKAREA_SIZE);
|
|
if (*workArea_p != NULL) {
|
|
*result = CARDMountAsync(chan, *workArea_p, NULL, NULL);
|
|
if (*result == CARD_RESULT_READY || *result == CARD_RESULT_BROKEN || *result == CARD_RESULT_ENCODING) {
|
|
bg_info->space_proc++;
|
|
return mCD_RESULT_SUCCESS;
|
|
} else {
|
|
return mCD_RESULT_ERROR;
|
|
}
|
|
} else {
|
|
return mCD_RESULT_ERROR;
|
|
}
|
|
}
|
|
|
|
static int mCD_format_bg_open_file(mCD_bg_info_c* bg_info, s32 chan, s32* result, void* data, const char* filename,
|
|
s32 data_len, u32 length, s32 offset, void** workArea_p, void** read_p,
|
|
CARDStat* stat) {
|
|
int res = mCD_RESULT_BUSY;
|
|
|
|
*result = CARDGetResultCode((s32)chan);
|
|
if (*result == CARD_RESULT_READY || *result == CARD_RESULT_ENCODING || *result == CARD_RESULT_BROKEN) {
|
|
*result = CARDFormatAsync((s32)chan, NULL);
|
|
if (*result == CARD_RESULT_READY) {
|
|
bg_info->space_proc++;
|
|
res = mCD_RESULT_SUCCESS;
|
|
} else {
|
|
CARDUnmount((s32)chan);
|
|
res = mCD_RESULT_ERROR;
|
|
}
|
|
} else if (*result != CARD_RESULT_BUSY) {
|
|
res = mCD_RESULT_ERROR;
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
static int mCD_format_bg_cleanup(mCD_bg_info_c* bg_info, s32 chan, s32* result, void* data, const char* filename,
|
|
s32 data_len, u32 length, s32 offset, void** workArea_p, void** read_p,
|
|
CARDStat* stat) {
|
|
int res = mCD_RESULT_BUSY;
|
|
|
|
*result = CARDGetResultCode((s32)chan);
|
|
if (*result != CARD_RESULT_BUSY) {
|
|
res = *result == CARD_RESULT_READY ? mCD_RESULT_SUCCESS : mCD_RESULT_ERROR;
|
|
CARDUnmount((s32)chan);
|
|
bg_info->space_proc++;
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
static int mCD_format_bg(s32 chan, s32* result) {
|
|
static void* work_p = NULL;
|
|
// clang-format off
|
|
static mCD_BG_PROC fbg_proc[] = {
|
|
&mCD_bg_check_slot,
|
|
&mCD_format_bg_mount,
|
|
&mCD_format_bg_open_file,
|
|
&mCD_format_bg_cleanup,
|
|
};
|
|
// clang-format on
|
|
|
|
int res = mCD_RESULT_BUSY;
|
|
mCD_bg_info_c* const bg_info = &l_mcd_bg_info;
|
|
|
|
if (bg_info->space_proc >= 0 && bg_info->space_proc < 4) {
|
|
int success = (*fbg_proc[bg_info->space_proc])(&l_mcd_bg_info, chan, result, NULL, NULL, 0, 0, 0, &work_p, NULL, NULL);
|
|
|
|
if (success == mCD_RESULT_SUCCESS && bg_info->space_proc == 4) {
|
|
mCD_ClearCardBgInfo(bg_info);
|
|
res = mCD_RESULT_SUCCESS;
|
|
} else if (success == mCD_RESULT_ERROR) {
|
|
mCD_ClearCardBgInfo(bg_info);
|
|
res = mCD_RESULT_ERROR;
|
|
}
|
|
|
|
if (res != mCD_RESULT_BUSY) {
|
|
if (work_p != NULL) {
|
|
zelda_free(work_p);
|
|
work_p = NULL;
|
|
}
|
|
}
|
|
} else {
|
|
if (work_p != NULL) {
|
|
zelda_free(work_p);
|
|
work_p = NULL;
|
|
}
|
|
|
|
res = mCD_RESULT_ERROR;
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
static int mCD_set_file_status_bg_open_file(mCD_bg_info_c* bg_info, s32 chan, s32* result, void* data,
|
|
const char* filename, s32 data_len, u32 length, s32 offset,
|
|
void** workArea_p, void** read_p, CARDStat* stat) {
|
|
int res = mCD_RESULT_BUSY;
|
|
|
|
*result = CARDGetResultCode((s32)chan);
|
|
if (*result == CARD_RESULT_READY) {
|
|
*result = CARDOpen((s32)chan, filename, &bg_info->fileInfo);
|
|
if (*result == CARD_RESULT_READY) {
|
|
bg_info->fileNo = bg_info->fileInfo.fileNo;
|
|
*result = CARDSetStatusAsync((s32)chan, bg_info->fileNo, stat, NULL);
|
|
if (*result == CARD_RESULT_READY) {
|
|
bg_info->space_proc++;
|
|
res = mCD_RESULT_SUCCESS;
|
|
} else {
|
|
mCD_close_and_unmount(&bg_info->fileInfo, chan);
|
|
res = mCD_RESULT_ERROR;
|
|
}
|
|
} else {
|
|
CARDUnmount((s32)chan);
|
|
res = mCD_RESULT_ERROR;
|
|
}
|
|
} else if (*result != CARD_RESULT_BUSY) {
|
|
res = mCD_RESULT_ERROR;
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
static int mCD_set_file_status_bg_cleanup(mCD_bg_info_c* bg_info, s32 chan, s32* result, void* data,
|
|
const char* filename, s32 data_len, u32 length, s32 offset, void** workArea_p,
|
|
void** read_p, CARDStat* stat) {
|
|
int res = mCD_RESULT_BUSY;
|
|
|
|
*result = CARDGetResultCode(chan);
|
|
if (*result != CARD_RESULT_BUSY) {
|
|
res = *result == CARD_RESULT_READY ? mCD_RESULT_SUCCESS : mCD_RESULT_ERROR;
|
|
mCD_close_and_unmount(&bg_info->fileInfo, chan);
|
|
bg_info->space_proc++;
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
static int mCD_set_file_status_bg(CARDStat* stat, const char* filename, s32 chan, s32* result) {
|
|
static void* work_p = NULL;
|
|
// clang-format off
|
|
static mCD_BG_PROC ssbg_proc[] = {
|
|
&mCD_bg_check_slot,
|
|
&mCD_bg_init,
|
|
&mCD_bg_check_filesystem,
|
|
&mCD_set_file_status_bg_open_file,
|
|
&mCD_set_file_status_bg_cleanup,
|
|
};
|
|
// clang-format on
|
|
|
|
int res = mCD_RESULT_BUSY;
|
|
mCD_bg_info_c* const bg_info = &l_mcd_bg_info;
|
|
|
|
if (bg_info->space_proc >= 0 && bg_info->space_proc < 5) {
|
|
int success =
|
|
(*ssbg_proc[bg_info->space_proc])(bg_info, chan, result, NULL, filename, 0, 0, 0, &work_p, NULL, stat);
|
|
|
|
if (success == mCD_RESULT_SUCCESS && bg_info->space_proc == 5) {
|
|
mCD_ClearCardBgInfo(bg_info);
|
|
res = mCD_RESULT_SUCCESS;
|
|
} else if (success == mCD_RESULT_ERROR) {
|
|
mCD_ClearCardBgInfo(bg_info);
|
|
res = mCD_RESULT_ERROR;
|
|
}
|
|
|
|
if (res != mCD_RESULT_BUSY) {
|
|
if (work_p != NULL) {
|
|
zelda_free(work_p);
|
|
work_p = NULL;
|
|
}
|
|
}
|
|
} else {
|
|
if (work_p != NULL) {
|
|
zelda_free(work_p);
|
|
work_p = NULL;
|
|
}
|
|
|
|
res = mCD_RESULT_ERROR;
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
static int mCD_get_file_status_bg_open_file(mCD_bg_info_c* bg_info, s32 chan, s32* result, void* data,
|
|
const char* filename, s32 data_len, u32 length, s32 offset,
|
|
void** workArea_p, void** read_p, CARDStat* stat) {
|
|
int res = mCD_RESULT_BUSY;
|
|
|
|
*result = CARDGetResultCode((s32)chan);
|
|
if (*result == CARD_RESULT_READY) {
|
|
*result = CARDOpen((s32)chan, filename, &bg_info->fileInfo);
|
|
if (*result == CARD_RESULT_READY) {
|
|
bg_info->fileNo = bg_info->fileInfo.fileNo;
|
|
*result = CARDGetStatus((s32)chan, bg_info->fileNo, stat);
|
|
if (*result == CARD_RESULT_READY) {
|
|
bg_info->space_proc++;
|
|
res = mCD_RESULT_SUCCESS;
|
|
} else {
|
|
res = mCD_RESULT_ERROR;
|
|
}
|
|
|
|
mCD_close_and_unmount(&bg_info->fileInfo, chan);
|
|
} else {
|
|
CARDUnmount((s32)chan);
|
|
res = mCD_RESULT_ERROR;
|
|
}
|
|
} else if (*result != CARD_RESULT_BUSY) {
|
|
res = mCD_RESULT_ERROR;
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
static int mCD_get_file_status_bg(CARDStat* stat, const char* filename, s32 chan, s32* result) {
|
|
static void* work_p = NULL;
|
|
// clang-format off
|
|
static mCD_BG_PROC gsbg_proc[] = {
|
|
&mCD_bg_check_slot,
|
|
&mCD_bg_init,
|
|
&mCD_bg_check_filesystem,
|
|
&mCD_get_file_status_bg_open_file,
|
|
};
|
|
// clang-format on
|
|
|
|
int res = mCD_RESULT_BUSY;
|
|
mCD_bg_info_c* const bg_info = &l_mcd_bg_info;
|
|
|
|
if (bg_info->space_proc >= 0 && bg_info->space_proc < 4) {
|
|
int success =
|
|
(*gsbg_proc[bg_info->space_proc])(bg_info, chan, result, NULL, filename, 0, 0, 0, &work_p, NULL, stat);
|
|
|
|
if (success == mCD_RESULT_SUCCESS && bg_info->space_proc == 4) {
|
|
mCD_ClearCardBgInfo(bg_info);
|
|
res = mCD_RESULT_SUCCESS;
|
|
} else if (success == mCD_RESULT_ERROR) {
|
|
mCD_ClearCardBgInfo(bg_info);
|
|
res = mCD_RESULT_ERROR;
|
|
}
|
|
|
|
if (res != mCD_RESULT_BUSY) {
|
|
if (work_p != NULL) {
|
|
zelda_free(work_p);
|
|
work_p = NULL;
|
|
}
|
|
}
|
|
} else {
|
|
if (work_p != NULL) {
|
|
zelda_free(work_p);
|
|
work_p = NULL;
|
|
}
|
|
|
|
res = mCD_RESULT_ERROR;
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
static int mCD_create_file_bg_create(mCD_bg_info_c* bg_info, s32 chan, s32* result, void* data, const char* filename,
|
|
s32 data_len, u32 length, s32 offset, void** workArea_p, void** read_p,
|
|
CARDStat* stat) {
|
|
int res = mCD_RESULT_BUSY;
|
|
|
|
*result = CARDGetResultCode((s32)chan);
|
|
if (*result == CARD_RESULT_READY) {
|
|
*result = CARDCreateAsync((s32)chan, filename, length, &bg_info->fileInfo, NULL);
|
|
if (*result == CARD_RESULT_READY) {
|
|
bg_info->space_proc++;
|
|
res = mCD_RESULT_SUCCESS;
|
|
} else {
|
|
CARDUnmount((s32)chan);
|
|
res = mCD_RESULT_ERROR;
|
|
}
|
|
} else if (*result != CARD_RESULT_BUSY) {
|
|
res = mCD_RESULT_ERROR;
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
static int mCD_create_file_bg_set_not_copy(mCD_bg_info_c* bg_info, s32 chan, s32* result, void* data,
|
|
const char* filename, s32 data_len, u32 length, s32 offset,
|
|
void** workArea_p, void** read_p, CARDStat* stat) {
|
|
int res = mCD_RESULT_BUSY;
|
|
|
|
*result = CARDGetResultCode((s32)chan);
|
|
if (*result == CARD_RESULT_READY) {
|
|
CARDDir dir;
|
|
|
|
bg_info->fileNo = bg_info->fileInfo.fileNo;
|
|
*result = __CARDGetStatusEx((s32)chan, bg_info->fileNo, &dir);
|
|
if (*result == CARD_RESULT_READY) {
|
|
dir.permission |= data_len;
|
|
|
|
/* @bug - missing *result = ? */
|
|
__CARDSetStatusEx((s32)chan, bg_info->fileNo, &dir);
|
|
if (*result == CARD_RESULT_READY) {
|
|
bg_info->space_proc++;
|
|
res = mCD_RESULT_SUCCESS;
|
|
} else {
|
|
res = mCD_RESULT_ERROR;
|
|
}
|
|
} else {
|
|
res = mCD_RESULT_ERROR;
|
|
}
|
|
|
|
mCD_close_and_unmount(&bg_info->fileInfo, chan);
|
|
} else if (*result != CARD_RESULT_BUSY) {
|
|
CARDUnmount((s32)chan);
|
|
res = mCD_RESULT_ERROR;
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
static int mCD_create_file_bg(const char* filename, s32 perms, u32 length, s32 chan, s32* result, s32* fileNo) {
|
|
static void* work_p = NULL;
|
|
// clang-format off
|
|
static mCD_BG_PROC cbg_proc[] = {
|
|
&mCD_bg_check_slot,
|
|
&mCD_bg_init,
|
|
&mCD_bg_check_filesystem,
|
|
&mCD_create_file_bg_create,
|
|
&mCD_create_file_bg_set_not_copy,
|
|
};
|
|
// clang-format on
|
|
|
|
int res;
|
|
mCD_bg_info_c* bg_info;
|
|
int proc;
|
|
|
|
res = mCD_RESULT_BUSY;
|
|
bg_info = &l_mcd_bg_info;
|
|
proc = bg_info->space_proc;
|
|
*fileNo = 0;
|
|
if (proc >= 0 && proc < 5) {
|
|
int success = (*cbg_proc[proc])(bg_info, chan, result, NULL, filename, perms, length, 0, &work_p,
|
|
NULL, NULL);
|
|
|
|
if (success == mCD_RESULT_SUCCESS && bg_info->space_proc == 5) {
|
|
*fileNo = bg_info->fileNo;
|
|
mCD_ClearCardBgInfo(bg_info);
|
|
res = mCD_RESULT_SUCCESS;
|
|
} else if (success == mCD_RESULT_ERROR) {
|
|
mCD_ClearCardBgInfo(bg_info);
|
|
res = mCD_RESULT_ERROR;
|
|
}
|
|
|
|
if (res != mCD_RESULT_BUSY) {
|
|
if (work_p != NULL) {
|
|
zelda_free(work_p);
|
|
work_p = NULL;
|
|
}
|
|
}
|
|
} else {
|
|
if (work_p != NULL) {
|
|
zelda_free(work_p);
|
|
work_p = NULL;
|
|
}
|
|
|
|
res = mCD_RESULT_ERROR;
|
|
}
|
|
|
|
/* Debug display for error state */
|
|
if (ZURUMODE2_ENABLED()) {
|
|
if (res == mCD_RESULT_ERROR) {
|
|
mCD_OnErrInfo(mCD_ERROR_CREATE);
|
|
mCD_SetErrResult(*result);
|
|
} else if (res == mCD_RESULT_SUCCESS) {
|
|
mCD_OffErrInfo(mCD_ERROR_CREATE);
|
|
mCD_SetErrResult(*result);
|
|
}
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
static int mCD_set_file_permission_bg_set(mCD_bg_info_c* bg_info, s32 chan, s32* result, void* data,
|
|
const char* filename, s32 data_len, u32 length, s32 offset, void** workArea_p,
|
|
void** read_p, CARDStat* stat) {
|
|
int res = mCD_RESULT_BUSY;
|
|
|
|
*result = CARDGetResultCode((s32)chan);
|
|
if (*result == CARD_RESULT_READY) {
|
|
*result = CARDOpen((s32)chan, filename, &bg_info->fileInfo);
|
|
if (*result == CARD_RESULT_READY) {
|
|
CARDDir dir;
|
|
|
|
bg_info->fileNo = bg_info->fileInfo.fileNo;
|
|
*result = __CARDGetStatusEx((s32)chan, bg_info->fileNo, &dir);
|
|
if (*result == CARD_RESULT_READY) {
|
|
dir.permission |= data_len;
|
|
|
|
/* @bug - missing *result = ? */
|
|
__CARDSetStatusEx((s32)chan, bg_info->fileNo, &dir);
|
|
if (*result == CARD_RESULT_READY) {
|
|
bg_info->space_proc++;
|
|
res = mCD_RESULT_SUCCESS;
|
|
} else {
|
|
res = mCD_RESULT_ERROR;
|
|
}
|
|
} else {
|
|
res = mCD_RESULT_ERROR;
|
|
}
|
|
|
|
mCD_close_and_unmount(&bg_info->fileInfo, chan);
|
|
} else {
|
|
CARDUnmount((s32)chan);
|
|
res = mCD_RESULT_ERROR;
|
|
}
|
|
} else if (*result != CARD_RESULT_BUSY) {
|
|
CARDUnmount((s32)chan);
|
|
res = mCD_RESULT_ERROR;
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
static int mCD_set_file_permission_bg(const char* filename, s32 perms, s32 chan, s32* result, s32* fileNo) {
|
|
static void* work_p = NULL;
|
|
// clang-format off
|
|
static mCD_BG_PROC sp_proc[] = {
|
|
&mCD_bg_check_slot,
|
|
&mCD_bg_init,
|
|
&mCD_bg_check_filesystem,
|
|
&mCD_set_file_permission_bg_set,
|
|
};
|
|
// clang-format on
|
|
|
|
int res = mCD_RESULT_BUSY;
|
|
mCD_bg_info_c* bg_info = &l_mcd_bg_info;
|
|
int proc = bg_info->space_proc;
|
|
|
|
if (fileNo != NULL) {
|
|
*fileNo = 0;
|
|
}
|
|
|
|
if (proc >= 0 && proc < 4) {
|
|
int success = (*sp_proc[proc])(bg_info, chan, result, NULL, filename, perms, 0, 0, &work_p, NULL, NULL);
|
|
|
|
if (success == mCD_RESULT_SUCCESS && bg_info->space_proc == 4) {
|
|
if (fileNo != NULL) {
|
|
*fileNo = bg_info->fileNo;
|
|
}
|
|
mCD_ClearCardBgInfo(bg_info);
|
|
res = mCD_RESULT_SUCCESS;
|
|
} else if (success == mCD_RESULT_ERROR) {
|
|
mCD_ClearCardBgInfo(bg_info);
|
|
res = mCD_RESULT_ERROR;
|
|
}
|
|
|
|
if (res != mCD_RESULT_BUSY) {
|
|
if (work_p != NULL) {
|
|
zelda_free(work_p);
|
|
work_p = NULL;
|
|
}
|
|
}
|
|
} else {
|
|
if (work_p != NULL) {
|
|
zelda_free(work_p);
|
|
work_p = NULL;
|
|
}
|
|
|
|
res = mCD_RESULT_ERROR;
|
|
}
|
|
|
|
/* Debug display for error state */
|
|
if (ZURUMODE2_ENABLED()) {
|
|
if (res == mCD_RESULT_ERROR) {
|
|
mCD_OnErrInfo(mCD_ERROR_CREATE);
|
|
mCD_SetErrResult(*result);
|
|
} else if (res == mCD_RESULT_SUCCESS) {
|
|
mCD_OffErrInfo(mCD_ERROR_CREATE);
|
|
mCD_SetErrResult(*result);
|
|
}
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
static int mCD_erase_file_bg_erase(mCD_bg_info_c* bg_info, s32 chan, s32* result, void* data, const char* filename,
|
|
s32 data_len, u32 length, s32 offset, void** workArea_p, void** read_p,
|
|
CARDStat* stat) {
|
|
int res = mCD_RESULT_BUSY;
|
|
|
|
*result = CARDGetResultCode((s32)chan);
|
|
if (*result == CARD_RESULT_READY) {
|
|
*result = CARDDeleteAsync((s32)chan, filename, NULL);
|
|
if (*result == CARD_RESULT_READY) {
|
|
bg_info->space_proc++;
|
|
res = mCD_RESULT_SUCCESS;
|
|
} else {
|
|
CARDUnmount((s32)chan);
|
|
res = mCD_RESULT_ERROR;
|
|
}
|
|
} else if (*result != CARD_RESULT_BUSY) {
|
|
res = mCD_RESULT_ERROR;
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
static int mCD_erase_file_bg(const char* filename, s32 chan, s32* result) {
|
|
static void* work_p = NULL;
|
|
// clang-format off
|
|
static mCD_BG_PROC ebg_proc[] = {
|
|
&mCD_bg_check_slot,
|
|
&mCD_bg_init,
|
|
&mCD_bg_check_filesystem,
|
|
&mCD_erase_file_bg_erase,
|
|
&mCD_format_bg_cleanup,
|
|
};
|
|
// clang-format on
|
|
|
|
int res = mCD_RESULT_BUSY;
|
|
mCD_bg_info_c* bg_info = &l_mcd_bg_info;
|
|
int proc = bg_info->space_proc;
|
|
|
|
if (proc >= 0 && proc < 5) {
|
|
int success = (*ebg_proc[proc])(bg_info, chan, result, NULL, filename, 0, 0, 0, &work_p, NULL, NULL);
|
|
|
|
if (success == mCD_RESULT_SUCCESS && bg_info->space_proc == 5) {
|
|
mCD_ClearCardBgInfo(bg_info);
|
|
res = mCD_RESULT_SUCCESS;
|
|
} else if (success == mCD_RESULT_ERROR) {
|
|
mCD_ClearCardBgInfo(bg_info);
|
|
res = mCD_RESULT_ERROR;
|
|
}
|
|
|
|
if (res != mCD_RESULT_BUSY) {
|
|
if (work_p != NULL) {
|
|
zelda_free(work_p);
|
|
work_p = NULL;
|
|
}
|
|
}
|
|
} else {
|
|
if (work_p != NULL) {
|
|
zelda_free(work_p);
|
|
work_p = NULL;
|
|
}
|
|
|
|
res = mCD_RESULT_ERROR;
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
static int mCD_erase_file_fg(const char* filename, s32 chan, s32* result, void* workArea) {
|
|
int res = FALSE;
|
|
|
|
if (chan != -1 && workArea != NULL && mCD_check_card(result, mCD_MEMCARD_SECTORSIZE, chan) == mCD_RESULT_SUCCESS) {
|
|
*result = CARDMount((s32)chan, workArea, NULL);
|
|
if (*result == CARD_RESULT_READY || *result == CARD_RESULT_BUSY) {
|
|
*result = CARDCheck((s32)chan);
|
|
if (*result == CARD_RESULT_READY) {
|
|
*result = CARDDelete((s32)chan, filename);
|
|
if (*result == CARD_RESULT_READY) {
|
|
res = TRUE;
|
|
}
|
|
}
|
|
|
|
CARDUnmount((s32)chan);
|
|
} else if (*result == CARD_RESULT_ENCODING) {
|
|
CARDUnmount((s32)chan);
|
|
}
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
static int mCD_rename_file_fg(const char* new_filename, const char* filename, s32 chan, s32* result, void* workArea) {
|
|
int res = FALSE;
|
|
|
|
if (chan != -1 && workArea != NULL && mCD_check_card(result, mCD_MEMCARD_SECTORSIZE, (s32)chan) == mCD_RESULT_SUCCESS) {
|
|
*result = CARDMount((s32)chan, workArea, NULL);
|
|
if (*result == CARD_RESULT_READY || *result == CARD_RESULT_BUSY) {
|
|
*result = CARDCheck((s32)chan);
|
|
if (*result == CARD_RESULT_READY) {
|
|
*result = CARDRename((s32)chan, filename, new_filename);
|
|
if (*result == CARD_RESULT_READY) {
|
|
res = TRUE;
|
|
}
|
|
}
|
|
|
|
CARDUnmount((s32)chan);
|
|
} else if (*result == CARD_RESULT_ENCODING) {
|
|
CARDUnmount((s32)chan);
|
|
}
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
static u16 l_mcd_copy_protect = 0xFFFF;
|
|
|
|
// clang-format off
|
|
static u8 l_mcd_font_1[256] ATTRIBUTE_ALIGN(4) = {
|
|
0xa1, 0xbf, 0xc4, 0xc0, 0xc1, 0xc2, 0xc3, 0xc5, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce,
|
|
0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdf, 0xde, 0xe0,
|
|
0xa0, 0x21, 0x94, 0xe1, 0xe2, 0x25, 0x26, 0xb4, 0x28, 0x29, 0x7e, 0x97, 0x82, 0x2d, 0x2e, 0x97,
|
|
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x97, 0x3c, 0x3d, 0x3e, 0x3f,
|
|
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
|
|
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0xe3, 0x97, 0xe4, 0xe5, 0x5f,
|
|
0xe7, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
|
|
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0xe8, 0xe9, 0xea, 0xeb, 0x97,
|
|
0x97, 0xec, 0xed, 0xee, 0xef, 0x95, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf8, 0xf9, 0xfa,
|
|
0x96, 0xfb, 0xfc, 0xfd, 0xff, 0xfe, 0xdd, 0x7c, 0xa7, 0x97, 0x97, 0xb6, 0xb5, 0xb3, 0xb2, 0xb9,
|
|
0xaf, 0xac, 0xc6, 0xe6, 0x84, 0xbb, 0xab, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x2f, 0x97,
|
|
0x97, 0x97, 0x97, 0x97, 0x2b, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97,
|
|
0x97, 0xf7, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97,
|
|
0x3b, 0x23, 0xa0, 0xa0, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97,
|
|
0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97,
|
|
0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97
|
|
};
|
|
// clang-format on
|
|
|
|
static char l_comment_0_str[32] ATTRIBUTE_ALIGN(4) = "Animal Crossing";
|
|
static char l_comment_1_str[32] ATTRIBUTE_ALIGN(4) = " Town Data";
|
|
static char l_comment_erase_land[32] ATTRIBUTE_ALIGN(4) = "Letters and Designs Data";
|
|
static char l_comment_player_0_str[32] ATTRIBUTE_ALIGN(4) = "Animal Crossing";
|
|
static char l_comment_player_1_str[32] ATTRIBUTE_ALIGN(4) = " is traveling";
|
|
static char l_comment_present_0_str[32] ATTRIBUTE_ALIGN(4) = "Animal Crossing";
|
|
static char l_comment_present_1_str[32] ATTRIBUTE_ALIGN(4) = "Bonus Letters:";
|
|
static char l_comment_gift_1_str[32] ATTRIBUTE_ALIGN(4) = "Gift Letters:";
|
|
|
|
static char l_mCD_land_file_name[32] ATTRIBUTE_ALIGN(4) = "DobutsunomoriP_MURA";
|
|
static char l_mCD_land_file_name_dummy[32] ATTRIBUTE_ALIGN(4) = "DobutsunomoriP_MURA_d";
|
|
static char l_mCD_player_file_name[32] ATTRIBUTE_ALIGN(4) = "DobutsunomoriP_PL_";
|
|
static char l_mCD_present_file_name[32] ATTRIBUTE_ALIGN(4) = "DobutsunomoriP_Omake_";
|
|
|
|
typedef struct {
|
|
const char* filename; /* filename */
|
|
int filesize; /* size of the entire file */
|
|
int entrysize; /* size of the sub-entry */
|
|
} mCD_file_entry_c;
|
|
|
|
static mCD_file_entry_c l_mcd_file_table[] = {
|
|
{ l_mCD_land_file_name, mCD_LAND_SAVE_SIZE, sizeof(Save) },
|
|
{ l_mCD_land_file_name, mCD_LAND_SAVE_SIZE, sizeof(Save) },
|
|
{ l_mCD_land_file_name, mCD_LAND_SAVE_SIZE, sizeof(Save) },
|
|
{ l_mCD_land_file_name, mCD_LAND_SAVE_SIZE, mCD_MAIL_SAVE_SIZE },
|
|
{ l_mCD_land_file_name, mCD_LAND_SAVE_SIZE, mCD_ORIGINAL_SAVE_SIZE },
|
|
{ l_mCD_land_file_name, mCD_LAND_SAVE_SIZE, mCD_DIARY_SAVE_SIZE },
|
|
{ l_mCD_present_file_name, mCD_PRESENT_SAVE_SIZE, mCD_PRESENT_SAVE_SIZE },
|
|
{ l_mCD_player_file_name, mCD_PLAYER_SAVE_SIZE, mCD_PLAYER_SAVE_SIZE },
|
|
};
|
|
|
|
static int l_keepSave_set;
|
|
static int l_mcd_keep_startCond = 0;
|
|
static int l_aram_access_bit = 0;
|
|
|
|
static void mCD_clear_aram_access_bit(void) {
|
|
l_aram_access_bit = 0;
|
|
}
|
|
|
|
static u32 l_aram_alloc_size_table[mCD_ARAM_DATA_NUM] = {
|
|
ALIGN_NEXT(sizeof(mCD_keep_original_c), 32),
|
|
ALIGN_NEXT(sizeof(mCD_keep_mail_c), 32),
|
|
ALIGN_NEXT(sizeof(mCD_keep_diary_c), 32),
|
|
};
|
|
static u32 l_aram_real_size_32_table[mCD_ARAM_DATA_NUM] = {
|
|
ALIGN_NEXT(sizeof(mCD_keep_original_c), 32),
|
|
ALIGN_NEXT(sizeof(mCD_keep_mail_c), 32),
|
|
ALIGN_NEXT(sizeof(mCD_keep_diary_c), 32),
|
|
};
|
|
static void* l_aram_block_p_table[mCD_ARAM_DATA_NUM];
|
|
|
|
extern void mCD_save_data_aram_malloc(void) {
|
|
int i;
|
|
|
|
for (i = 0; i < mCD_ARAM_DATA_NUM; i++) {
|
|
l_aram_block_p_table[i] = JC__JKRAllocFromAram(l_aram_alloc_size_table[i]);
|
|
}
|
|
}
|
|
|
|
extern int mCD_save_data_aram_to_main(void* dst, u32 size, u32 idx) {
|
|
int res = FALSE;
|
|
void* aram_block;
|
|
|
|
if (idx >= mCD_ARAM_DATA_NUM) {
|
|
idx = 0;
|
|
}
|
|
|
|
aram_block = l_aram_block_p_table[idx];
|
|
if (aram_block != NULL) {
|
|
JC__JKRAramToMainRam_block(aram_block, dst, size);
|
|
DCFlushRange(dst, size);
|
|
res = TRUE;
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
extern int mCD_save_data_main_to_aram(void* src, u32 size, u32 idx) {
|
|
int res = FALSE;
|
|
void* aram_block;
|
|
|
|
if (idx >= mCD_ARAM_DATA_NUM) {
|
|
idx = 0;
|
|
}
|
|
|
|
aram_block = l_aram_block_p_table[idx];
|
|
if (aram_block != NULL) {
|
|
DCFlushRange(src, size);
|
|
JC__JKRMainRamToAram_block(src, aram_block, size);
|
|
res = TRUE;
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
static u32 mCD_get_aram_save_data_max_size(void) {
|
|
u32 size = 0;
|
|
int i;
|
|
|
|
for (i = 0; i < mCD_ARAM_DATA_NUM; i++) {
|
|
if (l_aram_alloc_size_table[i] > size) {
|
|
size = l_aram_alloc_size_table[i];
|
|
}
|
|
}
|
|
|
|
return size;
|
|
}
|
|
|
|
static void mCD_set_init_mail_data(u8* buf) {
|
|
mCD_keep_mail_c* keep_mail = (mCD_keep_mail_c*)buf;
|
|
Mail_c* mail = (Mail_c*)keep_mail->mail;
|
|
int i;
|
|
int j;
|
|
|
|
for (i = 0; i < mCD_KEEP_MAIL_PAGE_COUNT; i++) {
|
|
mem_clear(keep_mail->folder_names[i], sizeof(keep_mail->folder_names[i]), CHAR_SPACE);
|
|
for (j = 0; j < mCD_KEEP_MAIL_COUNT; j++) {
|
|
mMl_clear_mail(mail);
|
|
mail++;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void mCD_set_init_original_data(u8* buf) {
|
|
mCD_keep_original_c* keep_original = (mCD_keep_original_c*)buf;
|
|
int i;
|
|
int j;
|
|
|
|
for (i = 0; i < mCD_KEEP_ORIGINAL_PAGE_COUNT; i++) {
|
|
mem_clear(keep_original->folder_names[i], sizeof(keep_original->folder_names[i]), CHAR_SPACE);
|
|
for (j = 0; j < mCD_KEEP_ORIGINAL_COUNT; j++) {
|
|
mNW_InitOriginalData(&keep_original->original[i][j]);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void mCD_set_init_diary_data(u8* buf) {
|
|
mCD_keep_diary_c* keep_diary = (mCD_keep_diary_c*)buf;
|
|
mDi_entry_c* entry_p;
|
|
int i;
|
|
int j;
|
|
|
|
for (i = 0; i < mCD_KEEP_DIARY_COUNT; i++) {
|
|
entry_p = keep_diary->entries[i];
|
|
for (j = 0; j < mCD_KEEP_DIARY_ENTRY_COUNT; j++) {
|
|
mDi_init_diary(entry_p);
|
|
entry_p++;
|
|
}
|
|
}
|
|
}
|
|
|
|
typedef void (*mCD_DATA_INIT_PROC)(u8*);
|
|
|
|
extern void mCD_set_aram_save_data(void) {
|
|
static mCD_DATA_INIT_PROC init_proc[] = {
|
|
&mCD_set_init_original_data,
|
|
&mCD_set_init_mail_data,
|
|
&mCD_set_init_diary_data,
|
|
};
|
|
u32 max_size = mCD_get_aram_save_data_max_size();
|
|
u8* buf = (u8*)mCD_malloc_32(max_size);
|
|
|
|
if (buf != NULL) {
|
|
int i;
|
|
|
|
for (i = 0; i < mCD_ARAM_DATA_NUM; i++) {
|
|
if (l_aram_block_p_table[i] != NULL) {
|
|
bzero(buf, max_size);
|
|
(*init_proc[i])(buf);
|
|
mCD_save_data_main_to_aram(buf, l_aram_real_size_32_table[i], i);
|
|
}
|
|
}
|
|
|
|
zelda_free(buf);
|
|
mCD_clear_aram_access_bit();
|
|
}
|
|
}
|
|
|
|
static int mCD_TransErrorCode(s32 result_code) {
|
|
switch (result_code) {
|
|
case CARD_RESULT_READY:
|
|
return mCD_TRANS_ERR_NONE;
|
|
case CARD_RESULT_NOCARD:
|
|
case CARD_RESULT_WRONGDEVICE:
|
|
return mCD_TRANS_ERR_NOCARD;
|
|
case CARD_RESULT_IOERROR:
|
|
return mCD_TRANS_ERR_IOERROR;
|
|
case CARD_RESULT_BROKEN:
|
|
case CARD_RESULT_ENCODING:
|
|
return mCD_TRANS_ERR_BROKEN_WRONGENCODING;
|
|
case CARD_RESULT_NOENT:
|
|
case CARD_RESULT_INSSPACE:
|
|
return mCD_TRANS_ERR_NO_SPACE;
|
|
case CARD_RESULT_EXIST:
|
|
case CARD_RESULT_CANCELED:
|
|
case CARD_RESULT_FATAL_ERROR:
|
|
case CARD_RESULT_NAMETOOLONG:
|
|
case CARD_RESULT_LIMIT:
|
|
case CARD_RESULT_NOPERM:
|
|
case CARD_RESULT_NOFILE:
|
|
return mCD_TRANS_ERR_GENERIC;
|
|
case CARD_RESULT_BUSY:
|
|
return mCD_TRANS_ERR_BUSY;
|
|
default:
|
|
return mCD_TRANS_ERR_GENERIC;
|
|
}
|
|
}
|
|
|
|
static int mCD_TransErrorCode_nes(s32 result_code) {
|
|
switch (result_code) {
|
|
case CARD_RESULT_READY:
|
|
return mCD_TRANS_ERR_NONE;
|
|
case CARD_RESULT_WRONGDEVICE:
|
|
return mCD_TRANS_ERR_WRONGDEVICE;
|
|
case CARD_RESULT_NOCARD:
|
|
return mCD_TRANS_ERR_NOCARD;
|
|
case CARD_RESULT_IOERROR:
|
|
return mCD_TRANS_ERR_IOERROR;
|
|
case CARD_RESULT_BROKEN:
|
|
case CARD_RESULT_ENCODING:
|
|
return mCD_TRANS_ERR_BROKEN_WRONGENCODING;
|
|
case CARD_RESULT_NOENT:
|
|
case CARD_RESULT_INSSPACE:
|
|
return mCD_TRANS_ERR_NO_SPACE;
|
|
case CARD_RESULT_EXIST:
|
|
case CARD_RESULT_CANCELED:
|
|
case CARD_RESULT_FATAL_ERROR:
|
|
case CARD_RESULT_NAMETOOLONG:
|
|
case CARD_RESULT_LIMIT:
|
|
case CARD_RESULT_NOPERM:
|
|
case CARD_RESULT_NOFILE:
|
|
return mCD_TRANS_ERR_GENERIC;
|
|
case CARD_RESULT_BUSY:
|
|
return mCD_TRANS_ERR_BUSY;
|
|
default:
|
|
return mCD_TRANS_ERR_GENERIC;
|
|
}
|
|
}
|
|
|
|
static int mCD_get_offset(int idx) {
|
|
mCD_file_entry_c* entry = l_mcd_file_table;
|
|
int ofs = 0;
|
|
int i;
|
|
|
|
if (idx >= mCD_FILE_SAVE_MAIN && idx <= mCD_FILE_SAVE_DIARY) {
|
|
for (i = idx - 1; i >= 0; i--) {
|
|
ofs += entry->entrysize;
|
|
entry++;
|
|
}
|
|
}
|
|
|
|
return ofs;
|
|
}
|
|
|
|
static int mCD_get_size(int idx) {
|
|
int size = 0;
|
|
|
|
if (idx >= 0 && idx < mCD_FILE_NUM) {
|
|
size = l_mcd_file_table[idx].entrysize;
|
|
}
|
|
|
|
return size;
|
|
}
|
|
|
|
static Save l_keepSave;
|
|
static mCD_memMgr_c l_memMgr;
|
|
|
|
static void mCD_ClearMemMgr_com(mCD_memMgr_c* mgr) {
|
|
bzero(mgr, sizeof(mCD_memMgr_c));
|
|
mgr->chan = -1;
|
|
mgr->land_saved = -1;
|
|
mgr->copy_protect = -1;
|
|
mgr->broken_file_idx = -1;
|
|
}
|
|
|
|
static void mCD_ClearMemMgr_com2(mCD_memMgr_c* mgr) {
|
|
if (mgr->workArea != NULL) {
|
|
zelda_free(mgr->workArea);
|
|
}
|
|
|
|
if (mgr->cards[0].workArea != NULL) {
|
|
zelda_free(mgr->cards[0].workArea);
|
|
}
|
|
|
|
if (mgr->cards[1].workArea != NULL) {
|
|
zelda_free(mgr->cards[1].workArea);
|
|
}
|
|
|
|
mCD_ClearMemMgr_com(mgr);
|
|
}
|
|
|
|
static void mCD_ClearKeepLand(void) {
|
|
bzero(&l_keepSave, sizeof(l_keepSave));
|
|
l_keepSave_set = FALSE;
|
|
}
|
|
|
|
static void mCD_ClearMemMgr(void) {
|
|
mCD_ClearMemMgr_com(&l_memMgr);
|
|
}
|
|
|
|
typedef struct {
|
|
PersonalID_c pid;
|
|
char filename[32];
|
|
} mCD_cardPrivate_c;
|
|
|
|
static mCD_cardPrivate_c l_mcd_card_private_table[19];
|
|
static mCD_cardPrivate_c l_mcd_card_private;
|
|
|
|
static void mCD_ClearCardPrivateTable_com(mCD_cardPrivate_c* priv, int count) {
|
|
for (count; count != 0; count--) {
|
|
mPr_ClearPersonalID(&priv->pid);
|
|
mem_clear((u8*)priv->filename, sizeof(priv->filename), 0);
|
|
priv++;
|
|
}
|
|
}
|
|
|
|
static void mCD_ClearCardPrivateTable(void) {
|
|
mCD_ClearCardPrivateTable_com(l_mcd_card_private_table, ARRAY_COUNT(l_mcd_card_private_table));
|
|
}
|
|
|
|
static void mCD_SetCardPrivateTable(mCD_cardPrivate_c* priv, PersonalID_c* pid, char* filename) {
|
|
mPr_CopyPersonalID(&priv->pid, pid);
|
|
bcopy(filename, priv->filename, sizeof(priv->filename));
|
|
}
|
|
|
|
typedef struct {
|
|
u16 checksum;
|
|
Private_c priv;
|
|
Animal_c remove_animal;
|
|
u16 copy_protect;
|
|
u8 _2DEA[54];
|
|
} mCD_foreigner_c;
|
|
|
|
typedef union {
|
|
struct {
|
|
char comment[CARD_COMMENT_SIZE];
|
|
u8 banner[0xC00 + 0x200];
|
|
u8 icon[0x400 * 8 + 0x200];
|
|
mCD_foreigner_c file;
|
|
};
|
|
u8 sector_align[mCD_ALIGN_SECTORSIZE(sizeof(MemcardHeader_c) + sizeof(mCD_foreigner_c))];
|
|
} ForeignerFile_c;
|
|
|
|
static union {
|
|
mCD_foreigner_c file;
|
|
u8 sector_align[mCD_ALIGN_SECTORSIZE(sizeof(mCD_foreigner_c))];
|
|
} l_mcd_foreigner_file;
|
|
|
|
static void mCD_ClearForeignerFile(mCD_foreigner_c* foreigner) {
|
|
bzero(foreigner, sizeof(l_mcd_foreigner_file));
|
|
foreigner->checksum = 0;
|
|
mPr_ClearPrivateInfo(&foreigner->priv);
|
|
mNpc_ClearAnimalInfo(&foreigner->remove_animal);
|
|
foreigner->copy_protect = 0xFFFF;
|
|
}
|
|
|
|
typedef struct {
|
|
u16 code[4];
|
|
} mCD_LandProtectCode_c;
|
|
|
|
static mCD_LandProtectCode_c l_keep_noLandCode;
|
|
|
|
static void mCD_ClearNoLandProtectCode(mCD_LandProtectCode_c* protect_code) {
|
|
bzero(protect_code, sizeof(mCD_LandProtectCode_c));
|
|
}
|
|
|
|
static int mCD_CheckInitProtectCode(mCD_LandProtectCode_c* protect_code) {
|
|
u16* code_p = protect_code->code;
|
|
int res = FALSE;
|
|
int i;
|
|
|
|
for (i = 0; i < 4; i++) {
|
|
if (*code_p != 0) {
|
|
break;
|
|
}
|
|
|
|
code_p++;
|
|
}
|
|
|
|
if (i == 4) {
|
|
res = TRUE;
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
static int mCD_CheckProtectCode(u16* protect_code) {
|
|
int res = FALSE;
|
|
int i;
|
|
|
|
if (*protect_code == 0x3C1C) {
|
|
protect_code++;
|
|
for (i = 0; i < 3; i++) {
|
|
if (*protect_code == 0) {
|
|
break;
|
|
}
|
|
|
|
protect_code++;
|
|
}
|
|
|
|
if (i == 3) {
|
|
res = TRUE;
|
|
}
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
static void mCD_MakeProtectCode(mCD_LandProtectCode_c* protect_code) {
|
|
int i;
|
|
u16* code_p = protect_code->code;
|
|
|
|
*code_p = mCD_LAND_PROTECT_CODE_MAGIC0;
|
|
code_p++;
|
|
for (i = 0; i < 3; i++) {
|
|
*code_p = RANDOM(0xFFFE);
|
|
*code_p = *code_p + 1;
|
|
code_p++;
|
|
}
|
|
}
|
|
|
|
static int mCD_CompNoLandCode(u16* code0, u16* code1) {
|
|
int res = FALSE;
|
|
|
|
if (mCD_CheckProtectCode(code0) == TRUE) {
|
|
int i;
|
|
|
|
for (i = 0; i < 4; i++) {
|
|
if (*code0 != *code1) {
|
|
break;
|
|
}
|
|
|
|
code0++;
|
|
code1++;
|
|
}
|
|
|
|
if (i == 4) {
|
|
res = TRUE;
|
|
}
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
static void mCD_SetForeignerFile(mCD_foreigner_c* foreigner, Private_c* priv, Animal_c* animal) {
|
|
mPr_CopyPrivateInfo(&foreigner->priv, priv);
|
|
bcopy(animal, &foreigner->remove_animal, sizeof(Animal_c));
|
|
foreigner->checksum = mFRm_GetFlatCheckSum((u16*)foreigner, sizeof(mCD_foreigner_c), foreigner->checksum);
|
|
}
|
|
|
|
static void mCD_clear_all_control(void);
|
|
|
|
extern void mCD_InitAll(void) {
|
|
mCD_StartSetCardBgInfo();
|
|
mCD_ClearMemMgr();
|
|
mCD_ClearKeepLand();
|
|
mCD_ClearCardPrivateTable();
|
|
mCD_ClearCardPrivateTable_com(&l_mcd_card_private, 1);
|
|
mCD_clear_all_control();
|
|
l_mcd_copy_protect = 0xFFFF;
|
|
mCD_ClearForeignerFile(&l_mcd_foreigner_file.file);
|
|
mCD_ClearNoLandProtectCode(&l_keep_noLandCode);
|
|
mCD_ClearErrInfo();
|
|
}
|
|
|
|
static int mCD_save_file(void* data, int file_idx, s32 chan, s32* result) {
|
|
int res = mCD_RESULT_ERROR;
|
|
|
|
if (data != NULL && file_idx >= 0 && file_idx < mCD_FILE_NUM) {
|
|
mCD_file_entry_c* file = &l_mcd_file_table[file_idx];
|
|
int ofs = mCD_get_offset(file_idx);
|
|
|
|
res = mCD_write_comp_bg(data, file->filename, file->entrysize, file->filesize, ofs, chan, result);
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
static int mCD_load_file(void* buf, int file_idx, s32 chan, s32* result) {
|
|
int res = mCD_RESULT_ERROR;
|
|
|
|
if (buf != NULL && file_idx >= 0 && file_idx < mCD_FILE_NUM) {
|
|
mCD_file_entry_c* file = &l_mcd_file_table[file_idx];
|
|
int ofs = mCD_get_offset(file_idx);
|
|
|
|
res = mCD_read_fg(buf, file->filename, file->entrysize, ofs, chan, result);
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
/* This struct seems to be stubbed */
|
|
typedef struct {
|
|
int _00;
|
|
int _04;
|
|
int _08;
|
|
int _0C;
|
|
int _10;
|
|
mCD_LandProtectCode_c protect_code; // assumed?
|
|
int _1C;
|
|
int _20;
|
|
int _24;
|
|
int _28;
|
|
int _2C;
|
|
int _30;
|
|
} mCD_wctrl_c;
|
|
|
|
static mCD_wctrl_c l_mCD_wctrl;
|
|
|
|
static void mCD_clear_write_control_common(mCD_wctrl_c* write_control) {
|
|
write_control->_00 = 0;
|
|
write_control->_04 = 0;
|
|
write_control->_08 = 0;
|
|
write_control->_0C = 0;
|
|
bzero(&write_control->protect_code, sizeof(mCD_LandProtectCode_c));
|
|
write_control->_1C = 0;
|
|
write_control->_20 = 0;
|
|
write_control->_24 = 0;
|
|
write_control->_28 = 0;
|
|
write_control->_30 = 0;
|
|
}
|
|
|
|
static void mCD_clear_all_control(void) {
|
|
mCD_clear_write_control_common(&l_mCD_wctrl);
|
|
}
|
|
|
|
static int mCD_GetHighPriority_common(mCD_memMgr_c* mgr, int prio0, int prio1) {
|
|
mgr->chan = 0;
|
|
if (prio1 < prio0) {
|
|
mgr->chan = 1;
|
|
prio0 = prio1;
|
|
}
|
|
|
|
return prio0;
|
|
}
|
|
|
|
static int mCD_check_Land_exist_com(s32 chan) {
|
|
int res = FALSE;
|
|
|
|
if (chan == 0 || chan == 1) {
|
|
CARDFileInfo fileInfo;
|
|
|
|
if (CARDOpen(chan, l_mCD_land_file_name, &fileInfo) == CARD_RESULT_READY) {
|
|
res = TRUE;
|
|
}
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
static int mCD_check_Land_exist(s32 chan, void* workArea) {
|
|
int res = FALSE;
|
|
|
|
if ((chan == 0 || chan == 1) && workArea != NULL) {
|
|
s32 result;
|
|
|
|
if (mCD_check_card(&result, mCD_MEMCARD_SECTORSIZE, chan) == mCD_RESULT_SUCCESS) {
|
|
result = CARDMount((s32)chan, workArea, NULL);
|
|
if (result == CARD_RESULT_READY || result == CARD_RESULT_BROKEN) {
|
|
result = CARDCheck((s32)chan);
|
|
if (result == CARD_RESULT_READY) {
|
|
res = mCD_check_Land_exist_com(chan);
|
|
}
|
|
|
|
CARDUnmount((s32)chan);
|
|
} else if (result == CARD_RESULT_ENCODING) {
|
|
CARDUnmount((s32)chan);
|
|
}
|
|
}
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
static int mCD_CheckFilename(const char* name0, const char* name1, int len) {
|
|
int i = 0;
|
|
int j = 0;
|
|
int res = FALSE;
|
|
|
|
while (name0 != NULL && j < len && *name0 != '\0') {
|
|
if (*name0 != *name1) {
|
|
break;
|
|
}
|
|
|
|
i++;
|
|
name0++;
|
|
name1++;
|
|
j++;
|
|
}
|
|
|
|
if (i == len) {
|
|
res = TRUE;
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
static int mCD_CheckPresentFilename(CARDStat* stat) {
|
|
return mCD_CheckFilename(stat->fileName, l_mCD_present_file_name, 21);
|
|
}
|
|
|
|
static int mCD_CheckPresentFileStatus(CARDStat* stat) {
|
|
int res = FALSE;
|
|
|
|
if (stat->company[0] == '0' && stat->company[1] == '1') {
|
|
res = mCD_CheckPresentFilename(stat);
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
static int mCD_CheckPassportFilename(CARDStat* stat) {
|
|
return mCD_CheckFilename(stat->fileName, l_mCD_player_file_name, 18);
|
|
}
|
|
|
|
static int mCD_CheckPassportFileStatus(CARDStat* stat) {
|
|
int res = FALSE;
|
|
|
|
if (stat->company[0] == '0' && stat->company[1] == '1') {
|
|
res = mCD_CheckPassportFilename(stat);
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
static int mCD_set_to_num(char* c) {
|
|
int n = 0;
|
|
int num = 0;
|
|
int i = 0;
|
|
|
|
if (c != NULL) {
|
|
for (i; i < 3; i++) {
|
|
if (c[i] == '\0') {
|
|
break;
|
|
}
|
|
|
|
if (num != 0) {
|
|
num *= 10;
|
|
} else {
|
|
num = 1;
|
|
}
|
|
}
|
|
|
|
for (i; i != 0; i--) {
|
|
n += (*c - '0') * num;
|
|
num /= 10;
|
|
c++;
|
|
}
|
|
}
|
|
|
|
return n;
|
|
}
|
|
|
|
static int mCD_GetPassportFileIdx(char* filename) {
|
|
return mCD_set_to_num(&filename[18]);
|
|
}
|
|
|
|
static int mCD_CheckPassportFile_slot(s32 chan, void* workArea) {
|
|
int i;
|
|
int res = FALSE;
|
|
|
|
if ((chan == 0 || chan == 1) && workArea != NULL) {
|
|
s32 result;
|
|
|
|
if (mCD_check_card(&result, mCD_MEMCARD_SECTORSIZE, chan) == mCD_RESULT_SUCCESS) {
|
|
result = CARDMount((s32)chan, workArea, NULL);
|
|
if (result == CARD_RESULT_READY || result == CARD_RESULT_BROKEN) {
|
|
result = CARDCheck((s32)chan);
|
|
if (result == CARD_RESULT_READY) {
|
|
/* Check all files on the memcard */
|
|
CARDStat stat;
|
|
|
|
for (i = 0; i < CARD_MAX_FILE; i++) {
|
|
result = CARDGetStatus((s32)chan, i, &stat);
|
|
if (result == CARD_RESULT_READY) {
|
|
if (mCD_CheckPassportFileStatus(&stat) == TRUE) {
|
|
res = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
CARDUnmount((s32)chan);
|
|
} else if (result == CARD_RESULT_ENCODING) {
|
|
CARDUnmount((s32)chan);
|
|
}
|
|
}
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
static int mCD_GetSpaceSlot_bg2(mCD_memMgr_c* mgr, int size) {
|
|
mCD_memMgr_card_info_c* card_info;
|
|
int chan;
|
|
int res;
|
|
u8 _0010;
|
|
|
|
chan = 0;
|
|
res = mCD_RESULT_BUSY;
|
|
_0010 = mgr->_0010;
|
|
if ((_0010 & 1) == 1) {
|
|
chan = 1;
|
|
}
|
|
card_info = &mgr->cards[chan];
|
|
|
|
if (card_info->workArea != NULL) {
|
|
int space_res = mCD_get_space_bg(&card_info->freeBlocks, chan, &card_info->result, card_info->workArea);
|
|
if (space_res == mCD_RESULT_SUCCESS) {
|
|
if (card_info->freeBlocks >= size) {
|
|
if (mCD_check_Land_exist(chan, card_info->workArea) == TRUE) {
|
|
card_info->game_result = mCD_TRANS_ERR_LAND_EXIST;
|
|
} else if (mCD_CheckPassportFile_slot(chan, card_info->workArea) == TRUE) {
|
|
card_info->game_result = mCD_TRANS_ERR_PASSPORT_EXIST;
|
|
} else if (mCD_get_file_num(card_info->workArea, chan) >= CARD_MAX_FILE) {
|
|
card_info->game_result = mCD_TRANS_ERR_NO_FILES;
|
|
} else {
|
|
mgr->chan = chan;
|
|
res = mCD_RESULT_SUCCESS;
|
|
}
|
|
} else {
|
|
card_info->result = CARD_RESULT_INSSPACE;
|
|
}
|
|
|
|
mgr->_0010 |= 1 << chan;
|
|
} else if (space_res != mCD_RESULT_BUSY) {
|
|
if (mCD_check_sector_size(mCD_MEMCARD_SECTORSIZE, chan) == FALSE) {
|
|
card_info->game_result = mCD_TRANS_ERR_NOT_MEMCARD;
|
|
}
|
|
|
|
mgr->_0010 |= 1 << chan;
|
|
}
|
|
} else {
|
|
_0010 |= 1 << chan;
|
|
mgr->_0010 = _0010;
|
|
res = mCD_RESULT_ERROR;
|
|
}
|
|
|
|
if (card_info->game_result != mCD_TRANS_ERR_LAND_EXIST && card_info->game_result != mCD_TRANS_ERR_PASSPORT_EXIST &&
|
|
card_info->game_result != mCD_TRANS_ERR_NOT_MEMCARD && card_info->game_result != mCD_TRANS_ERR_NO_FILES) {
|
|
card_info->game_result = mCD_TransErrorCode_nes(card_info->result);
|
|
}
|
|
|
|
/* If no memcard was chosen */
|
|
if (mgr->_0010 == 0b11 && res == mCD_RESULT_BUSY) {
|
|
mCD_GetHighPriority_common(mgr, mgr->cards[0].game_result, mgr->cards[1].game_result);
|
|
|
|
if (mgr->chan == -1 || mgr->cards[mgr->chan].game_result != mCD_TRANS_ERR_NONE) {
|
|
res = mCD_RESULT_ERROR;
|
|
} else {
|
|
res = mCD_RESULT_SUCCESS;
|
|
}
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
static int mCD_check_noLand_file(mCD_LandProtectCode_c* protect_code, u8* data, s32 chan) {
|
|
int res = FALSE;
|
|
|
|
if (data != NULL) {
|
|
s32 result;
|
|
|
|
if (mCD_load_file(data, mCD_FILE_SAVE_MISC, chan, &result) == mCD_RESULT_SUCCESS) {
|
|
if (mCD_CheckProtectCode((u16*)(data + mCD_SAVE_DATA_OFS)) == TRUE) {
|
|
if (protect_code != NULL) {
|
|
bcopy((mCD_LandProtectCode_c*)(data + mCD_SAVE_DATA_OFS), protect_code,
|
|
sizeof(mCD_LandProtectCode_c));
|
|
}
|
|
|
|
res = TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
static int mCD_GetNoLandSlot_bg(mCD_memMgr_c* mgr) {
|
|
s32 chan = 0;
|
|
mCD_memMgr_card_info_c* card_info;
|
|
int res = mCD_RESULT_BUSY;
|
|
u8 _0010 = mgr->_0010;
|
|
|
|
if ((_0010 & 1) == 1) {
|
|
chan = 1;
|
|
}
|
|
|
|
card_info = &mgr->cards[chan];
|
|
|
|
if (card_info->workArea != NULL) {
|
|
static mCD_LandProtectCode_c noLand_code;
|
|
|
|
if (mCD_check_noLand_file(&noLand_code, mgr->workArea, chan) == TRUE &&
|
|
mCD_CompNoLandCode(noLand_code.code, l_keep_noLandCode.code) == TRUE) {
|
|
mgr->chan = chan;
|
|
res = mCD_RESULT_SUCCESS;
|
|
} else {
|
|
mgr->_0010 |= 1 << chan;
|
|
card_info->game_result = mCD_TRANS_ERR_INVALID_NOLAND_CODE;
|
|
}
|
|
} else {
|
|
_0010 |= 1 << chan;
|
|
mgr->_0010 = _0010;
|
|
res = mCD_RESULT_ERROR;
|
|
}
|
|
|
|
if (card_info->game_result != mCD_TRANS_ERR_INVALID_NOLAND_CODE) {
|
|
card_info->game_result = mCD_TransErrorCode(card_info->result);
|
|
}
|
|
|
|
if (mgr->_0010 == 0b11 && res == mCD_RESULT_BUSY) {
|
|
mCD_GetHighPriority_common(mgr, mgr->cards[0].game_result, mgr->cards[1].game_result);
|
|
res = mCD_RESULT_ERROR;
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
static int mCD_CheckThisLandSlot(s32* result, s32* game_result, s32 chan, Save_t* buf_save) {
|
|
int res = mCD_RESULT_ERROR;
|
|
|
|
if (buf_save != NULL) {
|
|
int i;
|
|
|
|
for (i = 0; i < 2; i++) {
|
|
int read_res;
|
|
|
|
*result = CARD_RESULT_NOCARD;
|
|
read_res = mCD_read_fg(buf_save, l_mCD_land_file_name, CARD_WORKAREA_SIZE,
|
|
mCD_get_offset(mCD_FILE_SAVE_MAIN + i), chan, result);
|
|
if (read_res == mCD_RESULT_SUCCESS) {
|
|
if (mFRm_CheckSaveData_common(&buf_save->save_check, buf_save->land_info.id) == TRUE) {
|
|
if (mLd_CheckThisLand(buf_save->land_info.name, buf_save->land_info.id) == TRUE) {
|
|
*game_result = mCD_TRANS_ERR_NONE;
|
|
res = mCD_RESULT_SUCCESS;
|
|
break;
|
|
} else if (mLd_CheckId(buf_save->land_info.id) == TRUE) {
|
|
*game_result = mCD_TRANS_ERR_OTHER_TOWN;
|
|
res = mCD_RESULT_BUSY;
|
|
break;
|
|
} else {
|
|
*game_result = mCD_TRANS_ERR_TOWN_INVALID;
|
|
res = mCD_RESULT_BUSY;
|
|
}
|
|
} else {
|
|
*game_result = mCD_TRANS_ERR_TOWN_INVALID;
|
|
res = mCD_RESULT_BUSY;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
static void mCD_set_1byte(char* c, int idx) {
|
|
*c = l_mcd_font_1[idx];
|
|
}
|
|
|
|
static void mCD_set_number_str(char* str, u8 num) {
|
|
int n = num;
|
|
int f = FALSE;
|
|
int fig_table[3];
|
|
int i;
|
|
|
|
bzero(fig_table, sizeof(fig_table));
|
|
for (i = 0; i < 3; i++) {
|
|
fig_table[i] = n % 10;
|
|
n /= 10;
|
|
}
|
|
|
|
for (i = 2; i > 0; i--) {
|
|
if (fig_table[i] > 0 || f == TRUE) {
|
|
*str++ = fig_table[i] + '0';
|
|
f = TRUE;
|
|
}
|
|
}
|
|
|
|
*str = fig_table[0] + '0';
|
|
}
|
|
|
|
static void mCD_get_land_comment1(char* comment1, u8* town_name) {
|
|
int n;
|
|
int i;
|
|
int spaces = 0;
|
|
u8* town_name_p;
|
|
char* comment_p;
|
|
|
|
town_name_p = town_name;
|
|
mem_clear((u8*)comment1, 32, 0);
|
|
for (i = LAND_NAME_SIZE; i != 0; i--) {
|
|
u8 c = *town_name++;
|
|
|
|
if (c != CHAR_SPACE) {
|
|
spaces = 0;
|
|
} else {
|
|
spaces++;
|
|
}
|
|
}
|
|
|
|
town_name = town_name_p;
|
|
n = LAND_NAME_SIZE - spaces;
|
|
for (i = 0; i < n; i++) {
|
|
mCD_set_1byte(comment1, *town_name);
|
|
comment1++;
|
|
town_name++;
|
|
}
|
|
|
|
comment_p = l_comment_1_str;
|
|
for (i = 0; i < 32; i++) {
|
|
*comment1 = *comment_p;
|
|
if (*comment_p == '\0') {
|
|
break;
|
|
}
|
|
|
|
comment1++;
|
|
comment_p++;
|
|
}
|
|
}
|
|
|
|
static void mCD_get_passport_comment1(char* comment1, u8* player_name) {
|
|
int i;
|
|
int n;
|
|
int spaces = 0;
|
|
u8* player_name_p;
|
|
char* comment_p;
|
|
|
|
player_name_p = player_name;
|
|
mem_clear((u8*)comment1, 32, 0);
|
|
for (i = LAND_NAME_SIZE; i != 0; i--) {
|
|
u8 c = *player_name++;
|
|
|
|
if (c != CHAR_SPACE) {
|
|
spaces = 0;
|
|
} else {
|
|
spaces++;
|
|
}
|
|
}
|
|
|
|
player_name = player_name_p;
|
|
n = PLAYER_NAME_LEN - spaces;
|
|
for (i = 0; i < n; i++) {
|
|
mCD_set_1byte(comment1, *player_name);
|
|
comment1++;
|
|
player_name++;
|
|
}
|
|
|
|
comment_p = l_comment_player_1_str;
|
|
for (i = 0; i < 32; i++) {
|
|
*comment1 = *comment_p;
|
|
if (*comment_p == '\0') {
|
|
break;
|
|
}
|
|
|
|
comment1++;
|
|
comment_p++;
|
|
}
|
|
}
|
|
|
|
static void mCD_get_present_comment1(char* comment1, int num, const char* src_comment, int src_len) {
|
|
int i;
|
|
|
|
mem_clear((u8*)comment1, 32, 0);
|
|
for (i = 0; i < src_len; i++) {
|
|
*comment1++ = *src_comment++;
|
|
}
|
|
|
|
if (num >= 0) {
|
|
num %= 10;
|
|
mCD_set_1byte(comment1, '0' + num);
|
|
}
|
|
}
|
|
|
|
extern int mCD_card_format_bg(s32 chan) {
|
|
s32 result;
|
|
|
|
return mCD_format_bg(chan, &result);
|
|
}
|
|
|
|
static int mCD_get_this_land_slot_no(mCD_memMgr_c* mgr) {
|
|
mCD_memMgr_card_info_c* card_info = mgr->cards;
|
|
Save_t* buf_save = (Save_t*)mgr->workArea;
|
|
int i;
|
|
int res = mCD_RESULT_ERROR;
|
|
|
|
for (i = 0; i < CARD_NUM_CHANS; i++) {
|
|
card_info[i].result = CARD_RESULT_NOCARD;
|
|
card_info[i].game_result = mCD_TRANS_ERR_NOCARD;
|
|
}
|
|
|
|
if (buf_save != NULL) {
|
|
for (i = 0; i < CARD_NUM_CHANS; i++) {
|
|
int t_res = mCD_CheckThisLandSlot(&card_info->result, &card_info->game_result, i, buf_save);
|
|
|
|
if (t_res == mCD_RESULT_SUCCESS) {
|
|
mgr->chan = i;
|
|
card_info->game_result = mCD_TRANS_ERR_NONE;
|
|
res = mCD_RESULT_SUCCESS;
|
|
break;
|
|
}
|
|
|
|
if (card_info->game_result == mCD_TRANS_ERR_NOCARD || t_res == mCD_RESULT_ERROR) {
|
|
card_info->game_result = mCD_TransErrorCode(card_info->result);
|
|
}
|
|
|
|
card_info++;
|
|
}
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
static int mCD_get_this_land_slot_no_game_start(mCD_memMgr_c* mgr) {
|
|
mCD_memMgr_card_info_c* card_info = mgr->cards;
|
|
Save_t* buf_save = (Save_t*)mgr->workArea;
|
|
int i;
|
|
int res = mCD_RESULT_ERROR;
|
|
|
|
for (i = 0; i < CARD_NUM_CHANS; i++) {
|
|
card_info[i].result = CARD_RESULT_NOCARD;
|
|
card_info[i].game_result = mCD_TRANS_ERR_NOCARD;
|
|
}
|
|
|
|
if (buf_save != NULL) {
|
|
for (i = 0; i < CARD_NUM_CHANS; i++) {
|
|
int t_res = mCD_CheckThisLandSlot(&card_info->result, &card_info->game_result, i, buf_save);
|
|
|
|
if (t_res == mCD_RESULT_SUCCESS) {
|
|
mgr->chan = i;
|
|
res = mCD_RESULT_SUCCESS;
|
|
break;
|
|
}
|
|
|
|
if (card_info->game_result == mCD_TRANS_ERR_NOCARD || t_res == mCD_RESULT_ERROR) {
|
|
card_info->game_result = mCD_TransErrorCode(card_info->result);
|
|
} else {
|
|
card_info->game_result = mCD_TRANS_ERR_WRONG_LAND;
|
|
mgr->chan = i;
|
|
}
|
|
|
|
card_info++;
|
|
}
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
static int mCD_get_this_land_slot_no_nes(mCD_memMgr_c* mgr) {
|
|
mCD_memMgr_card_info_c* card_info = mgr->cards;
|
|
Save_t* buf_save = (Save_t*)mgr->workArea;
|
|
int i;
|
|
int res = mCD_RESULT_ERROR;
|
|
|
|
for (i = 0; i < CARD_NUM_CHANS; i++) {
|
|
card_info[i].result = CARD_RESULT_NOCARD;
|
|
card_info[i].game_result = mCD_TRANS_ERR_NOCARD;
|
|
}
|
|
|
|
if (buf_save != NULL) {
|
|
for (i = 0; i < CARD_NUM_CHANS; i++) {
|
|
int t_res = mCD_CheckThisLandSlot(&card_info->result, &card_info->game_result, i, buf_save);
|
|
|
|
if (t_res == mCD_RESULT_SUCCESS) {
|
|
mgr->chan = i;
|
|
res = mCD_RESULT_SUCCESS;
|
|
break;
|
|
}
|
|
|
|
if (mCD_check_sector_size(mCD_MEMCARD_SECTORSIZE, i) == FALSE) {
|
|
card_info->game_result = mCD_TRANS_ERR_NOT_MEMCARD;
|
|
mgr->chan = i;
|
|
} else if (card_info->game_result == mCD_TRANS_ERR_NOCARD || t_res == mCD_RESULT_ERROR) {
|
|
card_info->game_result = mCD_TransErrorCode(card_info->result);
|
|
}
|
|
|
|
card_info++;
|
|
}
|
|
}
|
|
|
|
if (res == mCD_RESULT_ERROR) {
|
|
mCD_GetHighPriority_common(mgr, mgr->cards[0].game_result, mgr->cards[1].game_result);
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
static int mCD_check_copyProtect(Save_t* buf_save, s32 chan) {
|
|
int i;
|
|
int res = FALSE;
|
|
|
|
if (chan != -1 && buf_save != NULL) {
|
|
for (i = 0; i < 2; i++) {
|
|
s32 result;
|
|
int t_res = mCD_read_fg(buf_save, l_mCD_land_file_name, 0x200, mCD_get_offset(mCD_FILE_SAVE_MAIN + i), chan,
|
|
&result);
|
|
|
|
if (t_res == mCD_RESULT_SUCCESS && buf_save->copy_protect == Common_Get(copy_protect)) {
|
|
res = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
static int mCD_bg_get_area_common(mCD_memMgr_c* mgr, mCD_memMgr_fileInfo_c* fileInfo, int file_idx, int sound_idx) {
|
|
static u8 sound_table[mCD_HOME_SFX_NUM] = { NA_SE_47, NA_SE_53 };
|
|
mCD_memMgr_card_info_c* card_info = mgr->cards;
|
|
int stages_compl = 0;
|
|
int res = mCD_RESULT_BUSY;
|
|
|
|
/* Start playing sound effect if necessary */
|
|
if (mgr->_017C == 0 && sound_idx >= 0 && sound_idx < mCD_HOME_SFX_NUM) {
|
|
sAdo_SysLevStart(sound_table[sound_idx]);
|
|
}
|
|
|
|
if (mgr->_017C < 100) {
|
|
int i;
|
|
|
|
for (i = 0; i < CARD_NUM_CHANS; i++) {
|
|
if (card_info->workArea == NULL) {
|
|
card_info->workArea = mCD_malloc_32(CARD_WORKAREA_SIZE);
|
|
}
|
|
|
|
if (card_info->workArea != NULL) {
|
|
stages_compl++;
|
|
}
|
|
|
|
card_info++;
|
|
}
|
|
|
|
if (mgr->workArea == NULL) {
|
|
mgr->workArea_size = mCD_get_size(file_idx);
|
|
mgr->workArea = mCD_malloc_32(mgr->workArea_size);
|
|
}
|
|
|
|
if (mgr->workArea != NULL) {
|
|
stages_compl++;
|
|
}
|
|
|
|
if (stages_compl == 3) {
|
|
fileInfo->proc++;
|
|
res = mCD_RESULT_SUCCESS;
|
|
} else {
|
|
mgr->_017C++;
|
|
}
|
|
} else {
|
|
/* Unable to allocate work area buffers */
|
|
mCD_OnErrInfo(mCD_ERROR_AREA);
|
|
res = mCD_RESULT_ERROR;
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
static int mCD_SaveHome_bg_get_area(mCD_memMgr_c* mgr, mCD_memMgr_fileInfo_c* fileInfo) {
|
|
SoftResetEnable = FALSE;
|
|
return mCD_bg_get_area_common(mgr, fileInfo, mCD_FILE_SAVE_MAIN, mCD_HOME_SFX_NORMAL);
|
|
}
|
|
|
|
static int mCD_SaveHome_bg_erase_dummy(mCD_memMgr_c* mgr, mCD_memMgr_fileInfo_c* fileInfo) {
|
|
mCD_memMgr_card_info_c* card_info = mgr->cards;
|
|
int i;
|
|
|
|
for (i = 0; i < CARD_NUM_CHANS; i++) {
|
|
s32 result;
|
|
|
|
mCD_erase_file_fg(l_mCD_land_file_name_dummy, i, &result, card_info->workArea);
|
|
card_info++;
|
|
}
|
|
|
|
fileInfo->proc++;
|
|
return mCD_RESULT_SUCCESS;
|
|
}
|
|
|
|
static int mCD_send_present(PresentSaveFile_c* present_file, int length) {
|
|
Mail_c* letter = present_file->save.letters;
|
|
int res = FALSE;
|
|
u32 player_no = Common_Get(player_no);
|
|
u16 checksum = mFRm_ReturnCheckSum((u16*)present_file, length);
|
|
|
|
if (checksum == 0 && present_file->save.present_count <= mCD_PRESENT_MAX) {
|
|
int i;
|
|
|
|
for (i = 0; i < mCD_PRESENT_MAX; i++, letter++) {
|
|
if (mPr_NullCheckPersonalID(&letter->header.recipient.personalID) == TRUE) {
|
|
Private_c* priv;
|
|
mHm_hs_c* house;
|
|
int free_idx;
|
|
|
|
if (player_no >= PLAYER_NUM) {
|
|
break;
|
|
}
|
|
|
|
priv = Now_Private;
|
|
if (priv == NULL) {
|
|
break;
|
|
}
|
|
|
|
house = &Save_Get(homes[mHS_get_arrange_idx(player_no)]);
|
|
if (mPr_CheckCmpPersonalID(&priv->player_ID, &house->ownerID) != TRUE) {
|
|
break;
|
|
}
|
|
|
|
free_idx = mMl_chk_mail_free_space(house->mailbox, HOME_MAILBOX_SIZE);
|
|
if (free_idx == -1) {
|
|
break;
|
|
}
|
|
|
|
letter->content.font = mMl_FONT_RECV;
|
|
mPr_CopyPersonalID(&letter->header.recipient.personalID, &priv->player_ID);
|
|
letter->header.recipient.type = mMl_NAME_TYPE_PLAYER;
|
|
mMl_copy_mail(&house->mailbox[free_idx], letter);
|
|
|
|
res = TRUE;
|
|
present_file->save.present_count--;
|
|
if (present_file->save.present_count <= 0) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
static int mCD_SaveHome_bg_check_slot(mCD_memMgr_c* mgr, mCD_memMgr_fileInfo_c* fileInfo) {
|
|
int res = mCD_RESULT_BUSY;
|
|
|
|
if (mgr->cards[0].workArea != NULL && mgr->cards[1].workArea != NULL && mgr->workArea != NULL) {
|
|
if (Save_Get(save_exist) == FALSE) {
|
|
if (mCD_CheckInitProtectCode(&l_keep_noLandCode) == FALSE &&
|
|
mCD_CheckProtectCode(l_keep_noLandCode.code) == TRUE) {
|
|
int slot_res = mCD_GetNoLandSlot_bg(mgr);
|
|
|
|
if (slot_res == mCD_RESULT_SUCCESS) {
|
|
mgr->land_saved = Save_Get(save_exist);
|
|
mgr->copy_protect = Common_Get(copy_protect);
|
|
mgr->_0010 = 0b00;
|
|
fileInfo->proc++;
|
|
res = mCD_RESULT_SUCCESS;
|
|
} else if (slot_res != mCD_RESULT_BUSY) {
|
|
res = mCD_RESULT_ERROR;
|
|
}
|
|
} else {
|
|
int space_res = mCD_GetSpaceSlot_bg2(mgr, mCD_LAND_SAVE_SIZE);
|
|
|
|
if (space_res == TRUE) {
|
|
if (mgr->chan != -1) {
|
|
fileInfo->proc++;
|
|
mgr->land_saved = Save_Get(save_exist);
|
|
mgr->copy_protect = Common_Get(copy_protect);
|
|
mgr->_0010 = 0b00;
|
|
res = mCD_RESULT_SUCCESS;
|
|
} else {
|
|
res = mCD_RESULT_ERROR;
|
|
}
|
|
} else if (space_res != mCD_RESULT_BUSY) {
|
|
mgr->_0010 = 0b00;
|
|
res = mCD_RESULT_ERROR;
|
|
}
|
|
}
|
|
} else {
|
|
int land_slot_res = mCD_get_this_land_slot_no_nes(mgr);
|
|
|
|
if (land_slot_res == mCD_RESULT_SUCCESS) {
|
|
int chan = mgr->chan;
|
|
|
|
if (chan != -1) {
|
|
if (mCD_check_copyProtect((Save_t*)mgr->workArea, chan) == TRUE) {
|
|
fileInfo->proc++;
|
|
mgr->land_saved = Save_Get(save_exist);
|
|
mgr->copy_protect = Common_Get(copy_protect);
|
|
res = mCD_RESULT_SUCCESS;
|
|
} else {
|
|
mgr->cards[chan].game_result = mCD_TRANS_ERR_WRONG_LAND;
|
|
mgr->land_saved = Save_Get(save_exist);
|
|
mgr->copy_protect = Common_Get(copy_protect);
|
|
res = mCD_RESULT_ERROR;
|
|
}
|
|
} else {
|
|
res = mCD_RESULT_ERROR;
|
|
}
|
|
} else if (land_slot_res != mCD_RESULT_BUSY) {
|
|
res = mCD_RESULT_ERROR;
|
|
}
|
|
}
|
|
} else {
|
|
res = mCD_RESULT_ERROR;
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
static int mCD_CheckPresentFile(char* filename, s32* fileNo, s32 chan, s32* result, void* workArea) {
|
|
CARDStat stat;
|
|
int file;
|
|
int res = FALSE;
|
|
|
|
if (mCD_check_card(result, mCD_MEMCARD_SECTORSIZE, (s32)chan) == mCD_RESULT_SUCCESS) {
|
|
*result = CARDMount((s32)chan, workArea, NULL);
|
|
if (*result == CARD_RESULT_READY || *result == CARD_RESULT_BROKEN) {
|
|
*result = CARDCheck((s32)chan);
|
|
if (*result == CARD_RESULT_READY) {
|
|
for (file = *fileNo; file < 32; file++) {
|
|
*result = CARDGetStatus((s32)chan, file, &stat);
|
|
if (*result == CARD_RESULT_READY && mCD_CheckPresentFileStatus(&stat) == TRUE) {
|
|
bcopy(stat.fileName, filename, CARD_FILENAME_MAX);
|
|
res = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* @BUG - if CARDCheck fails, file will be undefined */
|
|
*fileNo = file;
|
|
CARDUnmount((s32)chan);
|
|
} else {
|
|
if (*result == CARD_RESULT_ENCODING) {
|
|
CARDUnmount((s32)chan);
|
|
}
|
|
|
|
*fileNo = 32;
|
|
}
|
|
} else {
|
|
*fileNo = 32;
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
#include "../src/game/m_card_bti.c_inc"
|
|
|
|
static int mCD_SaveHome_bg_read_send_present(mCD_memMgr_c* mgr, mCD_memMgr_fileInfo_c* fileInfo) {
|
|
static int icon_fileNo[mCD_PRESENT_TYPE_NUM] = { RESOURCE_TEGAMI, RESOURCE_TEGAMI2 };
|
|
static const char* comment_p_table[mCD_PRESENT_TYPE_NUM] = { l_comment_present_1_str, l_comment_gift_1_str };
|
|
static int comment_len_table[mCD_PRESENT_TYPE_NUM] = { 14, 13 };
|
|
void* workArea = mgr->workArea;
|
|
mCD_file_entry_c* present_entry;
|
|
mCD_memMgr_card_info_c* card_info;
|
|
int type;
|
|
PresentSaveFile_c* present_buf;
|
|
int icon;
|
|
|
|
icon = 0;
|
|
type = mCD_PRESENT_TYPE_BONUS;
|
|
present_entry = &l_mcd_file_table[mCD_FILE_PRESENT];
|
|
if (mgr->cards[0].workArea != NULL && mgr->cards[1].workArea != NULL && workArea != NULL) {
|
|
mgr->chan = -1;
|
|
card_info = &mgr->cards[fileInfo->chan];
|
|
|
|
/* Get info about the present save file */
|
|
if (mCD_CheckPresentFile(mgr->filename, &fileInfo->fileNo, fileInfo->chan, &card_info->result,
|
|
card_info->workArea) == TRUE) {
|
|
if (mCD_read_fg(workArea, mgr->filename, present_entry->entrysize,
|
|
mCD_get_offset(mCD_FILE_PRESENT), fileInfo->chan,
|
|
&card_info->result) == mCD_RESULT_SUCCESS) {
|
|
present_buf = (PresentSaveFile_c*)workArea;
|
|
|
|
/* Determine if this is a bonus gift file or a 'gift' present file */
|
|
if (mCD_CheckFilename(present_buf->header.comment + 32, l_comment_gift_1_str, 13) == TRUE) {
|
|
type = mCD_PRESENT_TYPE_GIFT;
|
|
}
|
|
|
|
/* Try sending the presents */
|
|
if (mCD_send_present(present_buf, present_entry->entrysize) == TRUE) {
|
|
mgr->loaded_file_type = mCD_FILE_PRESENT;
|
|
mgr->workArea_size = mCD_get_size(mgr->loaded_file_type);
|
|
mgr->chan = fileInfo->chan;
|
|
mCD_get_present_comment1(present_buf->header.comment + 32, present_buf->save.present_count,
|
|
comment_p_table[type], comment_len_table[type]);
|
|
if (present_buf->save.present_count == 0) {
|
|
icon = 1;
|
|
}
|
|
mCD_set_bti_data(present_buf->header.icon, icon_fileNo[icon], 0x400, 1, 0x200);
|
|
present_buf->save.checksum =
|
|
mFRm_GetFlatCheckSum((u16*)workArea, mgr->workArea_size, present_buf->save.checksum);
|
|
fileInfo->proc++;
|
|
} else if (present_buf->save.present_count != 0) {
|
|
mgr->chan = -1;
|
|
fileInfo->chan = CARD_NUM_CHANS;
|
|
} else {
|
|
fileInfo->fileNo++;
|
|
mgr->chan = fileInfo->chan;
|
|
}
|
|
} else if (card_info->result == CARD_RESULT_WRONGDEVICE || card_info->result == CARD_RESULT_NOCARD ||
|
|
card_info->result == CARD_RESULT_IOERROR || card_info->result == CARD_RESULT_BROKEN ||
|
|
card_info->result == CARD_RESULT_FATAL_ERROR || card_info->result == CARD_RESULT_LIMIT ||
|
|
card_info->result == CARD_RESULT_ENCODING) {
|
|
fileInfo->fileNo = 32;
|
|
}
|
|
}
|
|
|
|
if (mgr->chan == -1 || fileInfo->fileNo >= 32) {
|
|
fileInfo->proc = mCD_SAVEHOME_BG_PROC_READ_SEND_PRESENT;
|
|
fileInfo->fileNo = 0;
|
|
fileInfo->chan++;
|
|
}
|
|
|
|
if (fileInfo->chan >= CARD_NUM_CHANS) {
|
|
fileInfo->proc = mCD_SAVEHOME_BG_PROC_GET_SLOT;
|
|
mgr->chan = -1;
|
|
}
|
|
|
|
return mCD_RESULT_SUCCESS;
|
|
} else {
|
|
return mCD_RESULT_ERROR;
|
|
}
|
|
}
|
|
|
|
static int mCD_write_common(mCD_memMgr_c* mgr) {
|
|
int chan = mgr->chan;
|
|
mCD_memMgr_card_info_c* card_info;
|
|
int res;
|
|
|
|
if (mgr->workArea != NULL && chan != -1) {
|
|
card_info = &mgr->cards[chan];
|
|
res = mCD_save_file(mgr->workArea, mgr->loaded_file_type, mgr->chan, &card_info->result);
|
|
card_info->game_result = mCD_TransErrorCode(card_info->result);
|
|
} else {
|
|
res = mCD_RESULT_ERROR;
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
static int mCD_SaveHome_bg_write_present(mCD_memMgr_c* mgr, mCD_memMgr_fileInfo_c* fileInfo) {
|
|
mCD_file_entry_c* file_entry;
|
|
int chan = mgr->chan;
|
|
mCD_memMgr_card_info_c* card_info;
|
|
int ofs;
|
|
int ret;
|
|
int write_res;
|
|
|
|
if (chan != -1) {
|
|
file_entry = &l_mcd_file_table[mgr->loaded_file_type];
|
|
ofs = mCD_get_offset(mgr->loaded_file_type);
|
|
card_info = &mgr->cards[chan];
|
|
write_res = mCD_write_comp_bg(mgr->workArea, mgr->filename, mgr->workArea_size, file_entry->filesize, ofs,
|
|
chan, &card_info->result);
|
|
|
|
card_info->game_result = mCD_TransErrorCode(card_info->result);
|
|
if (write_res != mCD_RESULT_BUSY) {
|
|
if (card_info->result == CARD_RESULT_WRONGDEVICE || card_info->result == CARD_RESULT_NOCARD ||
|
|
card_info->result == CARD_RESULT_IOERROR || card_info->result == CARD_RESULT_BROKEN ||
|
|
card_info->result == CARD_RESULT_FATAL_ERROR || card_info->result == CARD_RESULT_LIMIT ||
|
|
card_info->result == CARD_RESULT_ENCODING) {
|
|
fileInfo->chan++;
|
|
fileInfo->fileNo = 0;
|
|
} else {
|
|
fileInfo->fileNo++;
|
|
}
|
|
|
|
if (fileInfo->fileNo >= 32) {
|
|
fileInfo->chan++;
|
|
}
|
|
|
|
if (fileInfo->chan >= CARD_NUM_CHANS) {
|
|
fileInfo->proc++;
|
|
mgr->loaded_file_type = mCD_FILE_SAVE_MAIN;
|
|
mgr->chan = -1;
|
|
} else {
|
|
fileInfo->proc = mCD_SAVEHOME_BG_PROC_READ_SEND_PRESENT;
|
|
}
|
|
}
|
|
|
|
card_info->game_result = mCD_TransErrorCode(card_info->result);
|
|
return mCD_RESULT_SUCCESS;
|
|
} else {
|
|
return mCD_RESULT_ERROR;
|
|
}
|
|
}
|
|
|
|
static int mCD_SaveHome_bg_get_slot(mCD_memMgr_c* mgr, mCD_memMgr_fileInfo_c* fileInfo) {
|
|
int res = mCD_RESULT_BUSY;
|
|
|
|
if (mgr->cards[0].workArea != NULL && mgr->cards[1].workArea != NULL && mgr->workArea != NULL) {
|
|
if (Save_Get(save_exist) == FALSE) {
|
|
if (mCD_CheckInitProtectCode(&l_keep_noLandCode) == FALSE &&
|
|
mCD_CheckProtectCode(l_keep_noLandCode.code) == TRUE) {
|
|
int slot_res = mCD_GetNoLandSlot_bg(mgr);
|
|
|
|
if (slot_res == mCD_RESULT_SUCCESS) {
|
|
mgr->land_saved = Save_Get(save_exist);
|
|
mgr->copy_protect = Common_Get(copy_protect);
|
|
mgr->_0010 = 0b00;
|
|
fileInfo->proc = mCD_SAVEHOME_BG_PROC_SET_FILE_PERMISSION;
|
|
res = mCD_RESULT_SUCCESS;
|
|
} else if (slot_res != mCD_RESULT_BUSY) {
|
|
res = mCD_RESULT_ERROR;
|
|
}
|
|
} else {
|
|
int space_res = mCD_GetSpaceSlot_bg2(mgr, mCD_LAND_SAVE_SIZE);
|
|
|
|
if (space_res == TRUE) {
|
|
if (mgr->chan != -1) {
|
|
fileInfo->proc++;
|
|
mgr->land_saved = Save_Get(save_exist);
|
|
mgr->copy_protect = Common_Get(copy_protect);
|
|
mgr->_0010 = 0b00;
|
|
res = mCD_RESULT_SUCCESS;
|
|
} else {
|
|
res = mCD_RESULT_ERROR;
|
|
}
|
|
} else if (space_res != mCD_RESULT_BUSY) {
|
|
res = mCD_RESULT_ERROR;
|
|
}
|
|
}
|
|
} else {
|
|
int land_slot_res = mCD_get_this_land_slot_no_nes(mgr);
|
|
|
|
if (land_slot_res == mCD_RESULT_SUCCESS) {
|
|
int chan = mgr->chan;
|
|
|
|
if (chan != -1) {
|
|
if (mCD_check_copyProtect((Save_t*)mgr->workArea, chan) == TRUE) {
|
|
fileInfo->proc = mCD_SAVEHOME_BG_PROC_CHECK_REPAIR_LAND;
|
|
mgr->land_saved = Save_Get(save_exist);
|
|
mgr->copy_protect = Common_Get(copy_protect);
|
|
res = mCD_RESULT_SUCCESS;
|
|
} else {
|
|
mgr->cards[chan].game_result = mCD_TRANS_ERR_WRONG_LAND;
|
|
mgr->land_saved = Save_Get(save_exist);
|
|
mgr->copy_protect = Common_Get(copy_protect);
|
|
res = mCD_RESULT_ERROR;
|
|
}
|
|
} else {
|
|
res = mCD_RESULT_ERROR;
|
|
}
|
|
} else if (land_slot_res != mCD_RESULT_BUSY) {
|
|
res = mCD_RESULT_ERROR;
|
|
}
|
|
}
|
|
} else {
|
|
res = mCD_RESULT_ERROR;
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
static int mCD_SaveHome_bg_create_file(mCD_memMgr_c* mgr, mCD_memMgr_fileInfo_c* fileInfo) {
|
|
int chan = mgr->chan;
|
|
mCD_memMgr_card_info_c* card_info;
|
|
mCD_file_entry_c* entry = &l_mcd_file_table[mCD_FILE_SAVE_MISC];
|
|
int res;
|
|
|
|
if (chan != -1) {
|
|
card_info = &mgr->cards[chan];
|
|
mgr->_019C = 1;
|
|
res = mCD_create_file_bg(l_mCD_land_file_name_dummy, CARD_ATTR_NO_MOVE | CARD_ATTR_NO_COPY,
|
|
entry->filesize, chan, &card_info->result, &card_info->fileNo);
|
|
card_info->game_result = mCD_TransErrorCode(card_info->result);
|
|
if (res == mCD_RESULT_SUCCESS) {
|
|
fileInfo->proc = mCD_SAVEHOME_BG_PROC_SET_FILE_PERMISSION;
|
|
}
|
|
} else {
|
|
res = mCD_RESULT_ERROR;
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
static int mCD_check_broken_land(mCD_memMgr_c* mgr) {
|
|
s32 chan = mgr->chan;
|
|
Save_t* save = (Save_t*)mgr->workArea;
|
|
int ok_save_idx = -1;
|
|
int size;
|
|
int res = FALSE;
|
|
|
|
if (chan != -1 && save != NULL) {
|
|
int i;
|
|
|
|
size = mCD_get_size(mCD_FILE_SAVE_MAIN);
|
|
for (i = 0; i < 2; i++) {
|
|
s32 result;
|
|
|
|
if (mCD_load_file(save, mCD_FILE_SAVE_MAIN + i, chan, &result) != mCD_RESULT_SUCCESS) {
|
|
break;
|
|
}
|
|
|
|
if (mFRm_ReturnCheckSum((u16*)save, size) == 0 &&
|
|
mFRm_CheckSaveData_common(&save->save_check, save->land_info.id)) {
|
|
ok_save_idx = i;
|
|
} else {
|
|
mgr->broken_file_idx = i;
|
|
}
|
|
}
|
|
|
|
if (ok_save_idx != -1 && mgr->broken_file_idx != -1 && ok_save_idx != mgr->broken_file_idx) {
|
|
res = TRUE;
|
|
}
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
static int mCD_repair_load_land(mCD_memMgr_c* mgr) {
|
|
s32 chan = mgr->chan;
|
|
Save_t* save = (Save_t*)mgr->workArea;
|
|
int res = FALSE;
|
|
|
|
if (chan != -1 && save != NULL && mgr->broken_file_idx != -1) {
|
|
s32 result;
|
|
|
|
if (mCD_load_file(save, mCD_FILE_SAVE_MAIN + ((~mgr->broken_file_idx) & 1), chan, &result) ==
|
|
mCD_RESULT_SUCCESS) {
|
|
int size = mCD_get_size(mCD_FILE_SAVE_MAIN);
|
|
|
|
if (mFRm_ReturnCheckSum((u16*)save, size) == 0 &&
|
|
mFRm_CheckSaveData_common(&save->save_check, save->land_info.id)) {
|
|
res = TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
static int mCD_repair_land(mCD_memMgr_c* mgr) {
|
|
int chan = mgr->chan;
|
|
Save_t* save = (Save_t*)mgr->workArea;
|
|
int broken_file_idx = mgr->broken_file_idx;
|
|
|
|
if (chan != -1 && save != NULL && broken_file_idx != -1) {
|
|
s32 result;
|
|
|
|
/* The loaded file is the 'good' version of the save so we just write it back to the broken save */
|
|
return mCD_save_file(save, mCD_FILE_SAVE_MAIN + broken_file_idx, chan, &result);
|
|
} else {
|
|
return mCD_RESULT_ERROR;
|
|
}
|
|
}
|
|
|
|
static int mCD_SaveHome_bg_check_repair_land(mCD_memMgr_c* mgr, mCD_memMgr_fileInfo_c* fileInfo) {
|
|
if (mCD_check_broken_land(mgr) == TRUE) {
|
|
if (mCD_repair_load_land(mgr) == TRUE) {
|
|
fileInfo->proc++;
|
|
} else {
|
|
fileInfo->proc = mCD_SAVEHOME_BG_PROC_SET_FILE_PERMISSION;
|
|
}
|
|
} else {
|
|
fileInfo->proc = mCD_SAVEHOME_BG_PROC_SET_FILE_PERMISSION;
|
|
}
|
|
|
|
return mCD_RESULT_SUCCESS;
|
|
}
|
|
|
|
static int mCD_SaveHome_bg_repair_land(mCD_memMgr_c* mgr, mCD_memMgr_fileInfo_c* fileInfo) {
|
|
int res = mCD_RESULT_BUSY;
|
|
|
|
if (mCD_repair_land(mgr)) {
|
|
fileInfo->proc++;
|
|
res = mCD_RESULT_SUCCESS;
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
// @unused mCD_SaveHome_bg_set_icon_data(mCD_memMgr_c* mgr, mCD_memMgr_fileInfo_c* fileInfo)
|
|
static int mCD_SaveHome_bg_set_icon_data(mCD_memMgr_c* mgr, mCD_memMgr_fileInfo_c* fileInfo) {
|
|
// clang-format off
|
|
static int icon_fileNo[] = {
|
|
RESOURCE_EKI1, RESOURCE_EKI1_2, RESOURCE_EKI1_3, RESOURCE_EKI1_4, RESOURCE_EKI1_5,
|
|
RESOURCE_EKI2, RESOURCE_EKI2_2, RESOURCE_EKI2_3, RESOURCE_EKI2_4, RESOURCE_EKI2_5,
|
|
RESOURCE_EKI3, RESOURCE_EKI3_2, RESOURCE_EKI3_3, RESOURCE_EKI3_4, RESOURCE_EKI3_5,
|
|
};
|
|
|
|
static int banner_fileNo[] = { RESOURCE_MURA_SPRING, RESOURCE_MURA_SUMMER, RESOURCE_MURA_FALL, RESOURCE_MURA_WINTER };
|
|
// clang-format on
|
|
|
|
u8* buf = (u8*)mgr->workArea;
|
|
|
|
if (buf != NULL) {
|
|
mgr->loaded_file_type = mCD_FILE_SAVE_MISC;
|
|
mgr->workArea_size = mCD_get_size(mgr->loaded_file_type);
|
|
bzero(buf, mgr->workArea_size);
|
|
bcopy(l_comment_0_str, buf, sizeof(l_comment_0_str));
|
|
mCD_get_land_comment1((char*)buf + sizeof(l_comment_0_str), Save_Get(land_info).name);
|
|
buf = mCD_set_bti_data(buf, icon_fileNo[Save_Get(station_type)], 0xC00, 1, 0x200);
|
|
buf = mCD_set_bti_data(buf, banner_fileNo[Common_Get(time.season)], 0x400, 1, 0x200);
|
|
fileInfo->proc++;
|
|
return mCD_RESULT_SUCCESS;
|
|
}
|
|
|
|
return mCD_RESULT_ERROR;
|
|
}
|
|
|
|
static int mCD_get_status_common(mCD_memMgr_c* mgr, mCD_memMgr_fileInfo_c* fileInfo, const char* filename,
|
|
u32 comment_addr, u32 icon_addr, int icon_fmt, int icon_speed, int icon_frames,
|
|
int banner_fmt) {
|
|
mCD_memMgr_card_info_c* card_info;
|
|
s32 chan = mgr->chan;
|
|
int res;
|
|
|
|
if (chan != -1) {
|
|
card_info = &mgr->cards[chan];
|
|
res = mCD_get_file_status_bg(&card_info->stat, filename, chan, &card_info->result);
|
|
card_info->game_result = mCD_TransErrorCode(card_info->result);
|
|
|
|
if (res == mCD_RESULT_SUCCESS) {
|
|
int i;
|
|
|
|
card_info->stat.commentAddr = comment_addr;
|
|
card_info->stat.iconAddr = icon_addr;
|
|
for (i = 0; i < icon_frames; i++) {
|
|
card_info->stat.iconFormat =
|
|
(card_info->stat.iconFormat & ~(CARD_STAT_ICON_MASK << (i * 2))) | (icon_fmt << (i * 2));
|
|
card_info->stat.iconSpeed =
|
|
(card_info->stat.iconSpeed & ~(CARD_STAT_SPEED_MASK << (i * 2))) | (icon_speed << (i * 2));
|
|
}
|
|
|
|
card_info->stat.bannerFormat = (card_info->stat.bannerFormat & ~CARD_STAT_BANNER_MASK) | banner_fmt;
|
|
fileInfo->proc++;
|
|
}
|
|
} else {
|
|
res = mCD_RESULT_ERROR;
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
static int mCD_SaveHome_bg_set_file_permission(mCD_memMgr_c* mgr, mCD_memMgr_fileInfo_c* fileInfo) {
|
|
s32 chan = mgr->chan;
|
|
mCD_file_entry_c* entry = &l_mcd_file_table[mCD_FILE_SAVE_MISC];
|
|
const char* filename = entry->filename;
|
|
mCD_memMgr_card_info_c* card_info;
|
|
int res = mCD_RESULT_BUSY;
|
|
|
|
|
|
if (chan != -1) {
|
|
if (mgr->_019C == 1) {
|
|
filename = l_mCD_land_file_name_dummy;
|
|
}
|
|
card_info = &mgr->cards[chan];
|
|
res = mCD_set_file_permission_bg(filename, CARD_ATTR_NO_MOVE | CARD_ATTR_NO_COPY, chan, &card_info->result,
|
|
&card_info->fileNo);
|
|
card_info->game_result = mCD_TransErrorCode(card_info->result);
|
|
|
|
if (res == mCD_RESULT_SUCCESS) {
|
|
fileInfo->proc++;
|
|
}
|
|
} else {
|
|
res = mCD_RESULT_ERROR;
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
static void mCD_ClearResetCode(void) {
|
|
bzero(&Now_Private->reset_code, sizeof(Now_Private->reset_code));
|
|
}
|
|
|
|
static int mCD_CheckResetCode(Private_c* priv) {
|
|
int res = TRUE;
|
|
|
|
if ((priv->state_flags & mPr_FLAG_BIRTHDAY_ACTIVE) != 0) {
|
|
priv->reset_code = 0;
|
|
}
|
|
|
|
if (priv->reset_code != 0) {
|
|
res = FALSE;
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
static void mCD_SetResetCode(Private_c* priv) {
|
|
priv->reset_code = (u32)RANDOM_F(USHT_MAX_S);
|
|
priv->reset_code++;
|
|
}
|
|
|
|
static void mCD_SetResetInfo(Private_c* priv) {
|
|
Common_Set(reset_flag, FALSE);
|
|
if (mCD_CheckResetCode(priv) == FALSE) {
|
|
|
|
/* No reset penalty if zurumode 2 is enabled */
|
|
if (!ZURUMODE2_ENABLED()) {
|
|
Common_Set(reset_flag, TRUE);
|
|
}
|
|
|
|
priv->reset_count++;
|
|
}
|
|
}
|
|
|
|
static int mCD_get_land_copyProtect(void) {
|
|
return 1 + (u16)RANDOM(0xFFF0);
|
|
}
|
|
|
|
static int mCD_SaveHome_bg_set_data(mCD_memMgr_c* mgr, mCD_memMgr_fileInfo_c* fileInfo) {
|
|
Save_t* save = (Save_t*)mgr->workArea;
|
|
Private_c* priv;
|
|
int _04 = fileInfo->_04;
|
|
int copy_protect;
|
|
mActor_name_t* pockets_p;
|
|
int i;
|
|
|
|
if (save != NULL) {
|
|
bzero(save, mgr->workArea_size);
|
|
priv = Now_Private;
|
|
mCkRh_SavePlayTime(Common_Get(player_no));
|
|
|
|
if (_04 == 0) {
|
|
mCD_ClearResetCode();
|
|
mAGrw_ClearMoneyStoneShineGround();
|
|
} else if (mCD_CheckResetCode(priv) == TRUE) {
|
|
mCD_SetResetCode(priv);
|
|
}
|
|
|
|
if (_04 == 0 && priv != NULL) {
|
|
pockets_p = priv->inventory.pockets;
|
|
|
|
/* Clear all Wisp spirits in the player's inventory */
|
|
for (i = 0; i < mPr_POCKETS_SLOT_COUNT; i++) {
|
|
if (ITEM_IS_WISP(*pockets_p)) {
|
|
mPr_SetPossessionItem(priv, i, EMPTY_NO, mPr_ITEM_COND_NORMAL);
|
|
}
|
|
|
|
pockets_p++;
|
|
}
|
|
}
|
|
|
|
Save_Set(save_exist, TRUE);
|
|
copy_protect = mCD_get_land_copyProtect();
|
|
Common_Set(copy_protect, copy_protect);
|
|
Save_Set(copy_protect, copy_protect);
|
|
Save_Set(travel_hard_time, lbRTC_HardTime());
|
|
bcopy(&Common_Get(save).save, save, sizeof(Save_t));
|
|
save->save_check.version = mFRm_VERSION;
|
|
mFRm_SetSaveCheckData(&save->save_check);
|
|
save->save_check.checksum = mFRm_GetFlatCheckSum((u16*)save, sizeof(Save), save->save_check.checksum);
|
|
mgr->loaded_file_type = mCD_FILE_SAVE_MAIN;
|
|
mgr->workArea_size = mCD_get_size(mgr->loaded_file_type);
|
|
fileInfo->proc++;
|
|
return mCD_RESULT_SUCCESS;
|
|
} else {
|
|
return mCD_RESULT_ERROR;
|
|
}
|
|
}
|
|
|
|
static int mCD_SaveHome_bg_write_main_2(mCD_memMgr_c* mgr, mCD_memMgr_fileInfo_c* fileInfo) {
|
|
void* workArea = mgr->workArea;
|
|
mCD_file_entry_c* file_entry = &l_mcd_file_table[mCD_FILE_SAVE_MAIN];
|
|
const char* filename = file_entry->filename;
|
|
int chan = mgr->chan;
|
|
int res;
|
|
Save_t* save = (Save_t*)workArea;
|
|
|
|
if (mgr->_019C == 1) {
|
|
filename = l_mCD_land_file_name_dummy;
|
|
}
|
|
|
|
if (workArea != NULL && chan != -1) {
|
|
mCD_memMgr_card_info_c* card_info;
|
|
int ofs;
|
|
|
|
mgr->loaded_file_type = mCD_FILE_SAVE_MAIN;
|
|
ofs = mCD_get_offset(mgr->loaded_file_type);
|
|
card_info = &mgr->cards[chan];
|
|
res = mCD_write_comp_bg(save, filename, mgr->workArea_size, file_entry->filesize, ofs, chan,
|
|
&card_info->result);
|
|
card_info->game_result = mCD_TransErrorCode(card_info->result);
|
|
|
|
if (res == mCD_RESULT_SUCCESS) {
|
|
mgr->loaded_file_type = mCD_FILE_SAVE_MAIN_BAK;
|
|
fileInfo->proc++;
|
|
} else if (res != mCD_RESULT_BUSY) {
|
|
res = mCD_RESULT_ERROR;
|
|
}
|
|
} else {
|
|
res = mCD_RESULT_ERROR;
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
static int mCD_SaveHome_bg_write_bk(mCD_memMgr_c* mgr, mCD_memMgr_fileInfo_c* fileInfo) {
|
|
void* workArea = mgr->workArea;
|
|
mCD_file_entry_c* file_entry = &l_mcd_file_table[mCD_FILE_SAVE_MAIN_BAK];
|
|
const char* filename = file_entry->filename;
|
|
s32 chan = mgr->chan;
|
|
mCD_memMgr_card_info_c* card_info;
|
|
Private_c* priv = Now_Private;
|
|
int res;
|
|
Save_t* save = (Save_t*)workArea;
|
|
int ofs;
|
|
|
|
if (mgr->_019C == 1) {
|
|
filename = l_mCD_land_file_name_dummy;
|
|
}
|
|
|
|
if (workArea != NULL && chan != -1) {
|
|
mgr->loaded_file_type = mCD_FILE_SAVE_MAIN_BAK;
|
|
ofs = mCD_get_offset(mgr->loaded_file_type);
|
|
card_info = &mgr->cards[chan];
|
|
res = mCD_write_comp_bg(save, filename, mgr->workArea_size, file_entry->filesize, ofs, chan,
|
|
&card_info->result);
|
|
card_info->game_result = mCD_TransErrorCode(card_info->result);
|
|
|
|
if (res == mCD_RESULT_SUCCESS) {
|
|
if (fileInfo->_04 == 1) {
|
|
if (Common_Get(player_decoy_flag) == TRUE && priv != NULL) {
|
|
priv->exists = TRUE;
|
|
}
|
|
} else {
|
|
Common_Set(player_decoy_flag, FALSE);
|
|
}
|
|
|
|
mgr->loaded_file_type = mCD_FILE_SAVE_MAIN_BAK;
|
|
fileInfo->proc++;
|
|
} else if (res != mCD_RESULT_BUSY) {
|
|
res = mCD_RESULT_ERROR;
|
|
}
|
|
} else {
|
|
res = mCD_RESULT_ERROR;
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
static int mCD_SaveHome_bg_set_others(mCD_memMgr_c* mgr, mCD_memMgr_fileInfo_c* fileInfo) {
|
|
// clang-format off
|
|
static int icon_fileNo[] = {
|
|
RESOURCE_EKI1, RESOURCE_EKI1_2, RESOURCE_EKI1_3, RESOURCE_EKI1_4, RESOURCE_EKI1_5,
|
|
RESOURCE_EKI2, RESOURCE_EKI2_2, RESOURCE_EKI2_3, RESOURCE_EKI2_4, RESOURCE_EKI2_5,
|
|
RESOURCE_EKI3, RESOURCE_EKI3_2, RESOURCE_EKI3_3, RESOURCE_EKI3_4, RESOURCE_EKI3_5,
|
|
};
|
|
|
|
static int banner_fileNo[] = { RESOURCE_MURA_SPRING, RESOURCE_MURA_SUMMER, RESOURCE_MURA_FALL, RESOURCE_MURA_WINTER };
|
|
|
|
|
|
// clang-format on
|
|
|
|
u8* data_p = (u8*)mgr->workArea;
|
|
size_t data_size;
|
|
|
|
if (data_p != NULL) {
|
|
bzero(data_p, OTHERS_SIZE);
|
|
bcopy(l_comment_0_str, data_p, sizeof(l_comment_0_str));
|
|
mCD_get_land_comment1((char*)data_p + sizeof(l_comment_0_str), Save_Get(land_info).name);
|
|
data_p = mCD_set_bti_data(data_p + CARD_COMMENT_SIZE, banner_fileNo[Common_Get(time.season)], 0xC00, 1, 0x200);
|
|
data_p = mCD_set_bti_data(data_p, icon_fileNo[Save_Get(station_type)], 0x400, 1, 0x200) + 32;
|
|
|
|
{
|
|
mCD_keep_mail_c* mail = (mCD_keep_mail_c*)data_p;
|
|
|
|
mCD_save_data_aram_to_main(mail, l_aram_real_size_32_table[mCD_ARAM_DATA_MAIL], mCD_ARAM_DATA_MAIL);
|
|
mail->landid = Save_Get(land_info).id;
|
|
mail->checksum = mFRm_GetFlatCheckSum((u16*)mail, l_aram_real_size_32_table[mCD_ARAM_DATA_MAIL], mail->checksum);
|
|
data_p += l_aram_real_size_32_table[mCD_ARAM_DATA_MAIL];
|
|
data_size = (sizeof(MemcardHeader_c) + 32) + l_aram_real_size_32_table[mCD_ARAM_DATA_MAIL];
|
|
}
|
|
|
|
{
|
|
mCD_keep_original_c* original = (mCD_keep_original_c*)data_p;
|
|
|
|
mCD_save_data_aram_to_main(original, l_aram_real_size_32_table[mCD_ARAM_DATA_ORIGINAL], mCD_ARAM_DATA_ORIGINAL);
|
|
original->landid = Save_Get(land_info).id;
|
|
original->checksum = mFRm_GetFlatCheckSum((u16*)original, l_aram_real_size_32_table[mCD_ARAM_DATA_ORIGINAL],
|
|
original->checksum);
|
|
data_p += l_aram_real_size_32_table[mCD_ARAM_DATA_ORIGINAL];
|
|
data_size += l_aram_real_size_32_table[mCD_ARAM_DATA_ORIGINAL];
|
|
}
|
|
|
|
{
|
|
mCD_keep_diary_c* diary = (mCD_keep_diary_c*)data_p;
|
|
|
|
mCD_save_data_aram_to_main(diary, l_aram_real_size_32_table[mCD_ARAM_DATA_DIARY], mCD_ARAM_DATA_DIARY);
|
|
diary->checksum = mFRm_GetFlatCheckSum((u16*)diary, l_aram_real_size_32_table[mCD_ARAM_DATA_DIARY],
|
|
diary->checksum);
|
|
data_size += l_aram_real_size_32_table[mCD_ARAM_DATA_DIARY];
|
|
}
|
|
|
|
data_size = mCD_ALIGN_SECTORSIZE(data_size);
|
|
mgr->workArea_size = data_size;
|
|
fileInfo->proc++;
|
|
return mCD_RESULT_SUCCESS;
|
|
}
|
|
|
|
return mCD_RESULT_ERROR;
|
|
}
|
|
|
|
static int mCD_SaveHome_bg_write_others(mCD_memMgr_c* mgr, mCD_memMgr_fileInfo_c* fileInfo) {
|
|
mCD_memMgr_card_info_c* card_info;
|
|
int ret;
|
|
void* workArea = mgr->workArea;
|
|
mCD_file_entry_c* entry = &l_mcd_file_table[mCD_FILE_SAVE_MAIN];
|
|
const char* filename = entry->filename;
|
|
int chan = mgr->chan;
|
|
|
|
if (mgr->_019C == 1) {
|
|
filename = l_mCD_land_file_name_dummy;
|
|
}
|
|
|
|
if (mgr->workArea != NULL && chan != -1) {
|
|
card_info = &mgr->cards[chan];
|
|
ret = mCD_write_comp_bg(workArea, filename, mgr->workArea_size, OTHERS_SIZE + sizeof(Save) * 2, 0, chan,
|
|
&card_info->result);
|
|
card_info->game_result = mCD_TransErrorCode(card_info->result);
|
|
|
|
if (ret == mCD_RESULT_SUCCESS) {
|
|
fileInfo->proc++;
|
|
} else if (ret != mCD_RESULT_BUSY) {
|
|
ret = mCD_RESULT_ERROR;
|
|
}
|
|
} else {
|
|
ret = mCD_RESULT_ERROR;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
static int mCD_SaveHome_bg_get_status_2(mCD_memMgr_c* mgr, mCD_memMgr_fileInfo_c* fileInfo) {
|
|
mCD_file_entry_c* entry = &l_mcd_file_table[mCD_FILE_SAVE_MAIN];
|
|
const char* filename = entry->filename;
|
|
|
|
if (mgr->_019C == 1) {
|
|
filename = l_mCD_land_file_name_dummy;
|
|
}
|
|
|
|
return mCD_get_status_common(mgr, fileInfo, filename, 0, CARD_COMMENT_SIZE, CARD_STAT_ICON_C8, CARD_STAT_SPEED_SLOW, 1, CARD_STAT_BANNER_C8);
|
|
}
|
|
|
|
static int mCD_SaveHome_bg_set_status_2(mCD_memMgr_c* mgr, mCD_memMgr_fileInfo_c* fileInfo) {
|
|
mCD_memMgr_card_info_c* card_info;
|
|
int ret;
|
|
mCD_file_entry_c* entry = &l_mcd_file_table[mCD_FILE_SAVE_MAIN];
|
|
const char* filename = entry->filename;
|
|
int chan = mgr->chan;
|
|
|
|
if (mgr->_019C == 1) {
|
|
filename = l_mCD_land_file_name_dummy;
|
|
}
|
|
|
|
if (chan != -1) {
|
|
card_info = &mgr->cards[chan];
|
|
ret = mCD_set_file_status_bg(&card_info->stat, filename, chan, &card_info->result);
|
|
if (ret == mCD_RESULT_SUCCESS) {
|
|
fileInfo->proc++;
|
|
}
|
|
} else {
|
|
ret = mCD_RESULT_ERROR;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
static int mCD_SaveHome_bg_rename(mCD_memMgr_c* mgr, mCD_memMgr_fileInfo_c* fileInfo) {
|
|
mCD_memMgr_card_info_c* card_info;
|
|
int ret = mCD_RESULT_ERROR;
|
|
int chan = mgr->chan;
|
|
|
|
if (mgr->_019C == 1) {
|
|
if (chan != -1) {
|
|
card_info = &mgr->cards[chan];
|
|
|
|
if (card_info->workArea != NULL) {
|
|
if (mCD_rename_file_fg(l_mCD_land_file_name, l_mCD_land_file_name_dummy, chan, &card_info->result, card_info->workArea) == TRUE) {
|
|
fileInfo->proc++;
|
|
ret = mCD_RESULT_SUCCESS;
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
fileInfo->proc++;
|
|
ret = mCD_RESULT_SUCCESS;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
static int mCD_SaveHome_ChangeErrCode(int err_code) {
|
|
switch (err_code) {
|
|
default:
|
|
break;
|
|
case mCD_TRANS_ERR_TOWN_INVALID:
|
|
case mCD_TRANS_ERR_16:
|
|
case mCD_TRANS_ERR_GENERIC:
|
|
err_code = mCD_TRANS_ERR_NONE;
|
|
break;
|
|
case mCD_TRANS_ERR_OTHER_TOWN:
|
|
err_code = mCD_TRANS_ERR_NOCARD;
|
|
break;
|
|
}
|
|
|
|
return err_code;
|
|
}
|
|
|
|
static void mCD_create_famicom_file(int chan) {
|
|
if (mLd_PlayerManKindCheck() == FALSE) {
|
|
famicom_internal_data_save();
|
|
}
|
|
}
|
|
|
|
static void mCD_load_famicom_file(void) {
|
|
if (mLd_PlayerManKindCheck() == FALSE) {
|
|
famicom_internal_data_load();
|
|
}
|
|
}
|
|
|
|
typedef int (*mCD_SAVEHOME_PROC)(mCD_memMgr_c*, mCD_memMgr_fileInfo_c*);
|
|
|
|
extern int mCD_SaveHome_bg(int param_1, int* chan) {
|
|
// clang-format off
|
|
static mCD_SAVEHOME_PROC save_proc[] = {
|
|
mCD_SaveHome_bg_get_area,
|
|
mCD_SaveHome_bg_check_slot,
|
|
mCD_SaveHome_bg_read_send_present,
|
|
mCD_SaveHome_bg_write_present,
|
|
mCD_SaveHome_bg_get_slot,
|
|
mCD_SaveHome_bg_create_file,
|
|
mCD_SaveHome_bg_check_repair_land,
|
|
mCD_SaveHome_bg_repair_land,
|
|
mCD_SaveHome_bg_set_file_permission,
|
|
mCD_SaveHome_bg_set_data,
|
|
mCD_SaveHome_bg_write_main_2,
|
|
mCD_SaveHome_bg_write_bk,
|
|
mCD_SaveHome_bg_set_others,
|
|
mCD_SaveHome_bg_write_others,
|
|
mCD_SaveHome_bg_get_status_2,
|
|
mCD_SaveHome_bg_set_status_2,
|
|
mCD_SaveHome_bg_rename,
|
|
};
|
|
// clang-format on
|
|
|
|
mCD_memMgr_card_info_c* cardInfo;
|
|
mCD_memMgr_c* mgr = &l_memMgr;
|
|
mCD_memMgr_fileInfo_c* fileInfo = &mgr->save_home_info;
|
|
int ret = mCD_TRANS_ERR_BUSY;
|
|
u8 proc = (u8)fileInfo->proc;
|
|
|
|
mgr->_0188++;
|
|
if (mgr->_018C == 0) {
|
|
if (proc < 18) {
|
|
int res;
|
|
|
|
fileInfo->_04 = param_1;
|
|
res = (*save_proc[proc])(mgr, fileInfo);
|
|
if (res == mCD_RESULT_SUCCESS) {
|
|
if (fileInfo->proc == 18) {
|
|
*chan = mgr->chan;
|
|
ret = mCD_TRANS_ERR_NONE;
|
|
mCD_ClearNoLandProtectCode(&l_keep_noLandCode);
|
|
}
|
|
} else if (res != mCD_RESULT_BUSY) {
|
|
int cur_chan = mgr->chan;
|
|
|
|
if (cur_chan == 0 || cur_chan == 1) {
|
|
*chan = cur_chan;
|
|
cardInfo = &mgr->cards[mgr->chan];
|
|
ret = cardInfo->game_result;
|
|
} else {
|
|
ret = mCD_TRANS_ERR_NOCARD;
|
|
}
|
|
|
|
if (mgr->land_saved != -1) {
|
|
Save_Set(save_exist, mgr->land_saved);
|
|
}
|
|
|
|
if (mgr->copy_protect != -1 && fileInfo->proc < 12) {
|
|
Common_Set(copy_protect, mgr->copy_protect);
|
|
}
|
|
}
|
|
|
|
if (res == mCD_RESULT_ERROR || (res == mCD_RESULT_SUCCESS && fileInfo->proc == 18)) {
|
|
if (mgr->_0188 >= 112) {
|
|
if (res == mCD_RESULT_SUCCESS) {
|
|
mCD_create_famicom_file(mgr->chan);
|
|
}
|
|
|
|
sAdo_SysLevStop(NA_SE_47);
|
|
mCD_ClearMemMgr_com2(mgr);
|
|
} else {
|
|
|
|
mgr->_018C = 1;
|
|
mgr->_0190 = ret;
|
|
mgr->_0194 = *chan;
|
|
ret = mCD_TRANS_ERR_BUSY;
|
|
if (mgr->_0190 == mCD_TRANS_ERR_BUSY) {
|
|
mgr->_0190 = mCD_TRANS_ERR_NOCARD;
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
ret = mCD_TRANS_ERR_NONE;
|
|
mCD_ClearMemMgr_com2(mgr);
|
|
}
|
|
} else {
|
|
if (mgr->_0188 >= 112) {
|
|
ret = mgr->_0190;
|
|
*chan = mgr->_0194;
|
|
mCD_ClearMemMgr_com2(mgr);
|
|
if (ret == mCD_TRANS_ERR_NONE) {
|
|
mCD_create_famicom_file(*chan);
|
|
}
|
|
sAdo_SysLevStop(NA_SE_47);
|
|
}
|
|
}
|
|
|
|
ret = mCD_SaveHome_ChangeErrCode(ret);
|
|
if (ret != mCD_TRANS_ERR_BUSY) {
|
|
SoftResetEnable = TRUE;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
static int mCD_TransErrCodeToCond(int err_code) {
|
|
switch (err_code) {
|
|
case mCD_TRANS_ERR_IOERROR:
|
|
return 4;
|
|
case mCD_TRANS_ERR_NOT_MEMCARD:
|
|
return 6;
|
|
case mCD_TRANS_ERR_BROKEN_WRONGENCODING:
|
|
case mCD_TRANS_ERR_REPAIR:
|
|
return 5;
|
|
case mCD_TRANS_ERR_16:
|
|
return 2;
|
|
case mCD_TRANS_ERR_NO_SPACE:
|
|
case mCD_TRANS_ERR_GENERIC:
|
|
return 7;
|
|
case mCD_TRANS_ERR_WRONGDEVICE:
|
|
return 8;
|
|
default:
|
|
return 9;
|
|
}
|
|
}
|
|
|
|
static void mCD_load_set_others_common(mCD_memMgr_c* mgr, mCD_memMgr_card_info_c* card_info, int chan, int diary_flag) {
|
|
u8* data_p = (u8*)mgr->workArea;
|
|
mCD_file_entry_c* entry;
|
|
|
|
bzero(data_p, OTHERS_SIZE);
|
|
|
|
entry = &l_mcd_file_table[mCD_FILE_SAVE_MISC];
|
|
if (mCD_read_fg(data_p, entry->filename, entry->entrysize, 0, chan, &card_info->result) == mCD_RESULT_SUCCESS) {
|
|
data_p += sizeof(MemcardHeader_c) + 32;
|
|
|
|
{
|
|
mCD_keep_mail_c* mail = (mCD_keep_mail_c*)data_p;
|
|
|
|
if (mFRm_ReturnCheckSum((u16*)mail, l_aram_real_size_32_table[mCD_ARAM_DATA_MAIL]) == 0) {
|
|
mCD_save_data_main_to_aram(mail, l_aram_real_size_32_table[mCD_ARAM_DATA_MAIL], mCD_ARAM_DATA_MAIL);
|
|
}
|
|
|
|
data_p += l_aram_real_size_32_table[mCD_ARAM_DATA_MAIL];
|
|
}
|
|
|
|
{
|
|
mCD_keep_original_c* original = (mCD_keep_original_c*)data_p;
|
|
|
|
if (mFRm_ReturnCheckSum((u16*)original, l_aram_real_size_32_table[mCD_ARAM_DATA_ORIGINAL]) == 0) {
|
|
mCD_save_data_main_to_aram(original, l_aram_real_size_32_table[mCD_ARAM_DATA_ORIGINAL], mCD_ARAM_DATA_ORIGINAL);
|
|
}
|
|
|
|
data_p += l_aram_real_size_32_table[mCD_ARAM_DATA_ORIGINAL];
|
|
}
|
|
|
|
if (diary_flag) {
|
|
mCD_keep_diary_c* diary = (mCD_keep_diary_c*)data_p;
|
|
|
|
if (mFRm_ReturnCheckSum((u16*)diary, l_aram_real_size_32_table[mCD_ARAM_DATA_DIARY]) == 0) {
|
|
mCD_save_data_main_to_aram(diary, l_aram_real_size_32_table[mCD_ARAM_DATA_DIARY], mCD_ARAM_DATA_DIARY);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
extern void mCD_LoadLand(void) {
|
|
static u16 noLand_code[2][8];
|
|
mCD_memMgr_c* mgr = &l_memMgr;
|
|
mCD_memMgr_card_info_c* card_info = mgr->cards;
|
|
Save_t* save;
|
|
int noLand_info[2];
|
|
u8 cond[2];
|
|
int flashrom_cond = 9;
|
|
int save_found = FALSE;
|
|
mCD_memMgr_fileInfo_c* save_home_info = &mgr->save_home_info;
|
|
int bad_save_chan;
|
|
int save_chan = -1;
|
|
int type;
|
|
s32 chan;
|
|
int res;
|
|
|
|
res = mCD_bg_get_area_common(mgr, save_home_info, mCD_FILE_SAVE_MAIN, 2);
|
|
save = (Save_t*)mgr->workArea;
|
|
|
|
if (res == mCD_RESULT_SUCCESS) {
|
|
for (chan = 0; chan < 2; chan++) {
|
|
noLand_info[chan] = 0;
|
|
cond[chan] = 9;
|
|
bad_save_chan = 0;
|
|
|
|
for (type = 0; type < 2; type++) {
|
|
mgr->loaded_file_type = mCD_FILE_SAVE_MAIN + type; // main -> main backup
|
|
mgr->workArea_size = mCD_get_size(mgr->loaded_file_type);
|
|
bzero(save, mgr->workArea_size);
|
|
|
|
if (mCD_load_file(save, mgr->loaded_file_type, chan, &card_info->result) == mCD_RESULT_SUCCESS) {
|
|
if (mFRm_CheckSaveData_common(&save->save_check, save->land_info.id)) {
|
|
if (mFRm_ReturnCheckSum((u16*)save, mgr->workArea_size) == 0 && (save->save_check.version == 6 || save->save_check.version == 5)) {
|
|
bcopy(save, Common_GetPointer(save), sizeof(Save));
|
|
save_found = TRUE;
|
|
Common_Set(copy_protect, Save_Get(copy_protect));
|
|
cond[chan] = 0;
|
|
save_chan = chan;
|
|
if (type == 1) {
|
|
mCD_OnErrInfo(mCD_ERROR_OUTDATED); // loaded backup
|
|
} else {
|
|
mCD_OffErrInfo(mCD_ERROR_OUTDATED); // loaded main
|
|
}
|
|
|
|
break;
|
|
} else {
|
|
cond[chan] = 2;
|
|
}
|
|
} else if (cond[chan] == 9) {
|
|
cond[chan] = 0;
|
|
bad_save_chan++;
|
|
}
|
|
} else {
|
|
if (card_info->result == CARD_RESULT_NOFILE) {
|
|
if (mCD_find_fg(l_mCD_land_file_name_dummy, card_info->workArea, chan, &card_info->result) == TRUE) {
|
|
cond[chan] = 0;
|
|
} else {
|
|
int res = mCD_RESULT_BUSY;
|
|
|
|
while (res == mCD_RESULT_BUSY) {
|
|
res = mCD_get_space_bg(&card_info->freeBlocks, chan, &card_info->result, card_info->workArea);
|
|
}
|
|
|
|
if (res == mCD_RESULT_SUCCESS) {
|
|
if (card_info->freeBlocks >= mCD_LAND_SAVE_SIZE) {
|
|
if (mCD_CheckPassportFile_slot(chan, card_info->workArea) == TRUE) {
|
|
cond[chan] = 1;
|
|
} else if (mCD_get_file_num(card_info->workArea, chan) >= CARD_MAX_FILE) {
|
|
cond[chan] = 3;
|
|
} else {
|
|
cond[chan] = 0;
|
|
}
|
|
} else {
|
|
cond[chan] = 7;
|
|
}
|
|
} else {
|
|
cond[chan] = mCD_TransErrCodeToCond(mCD_TransErrorCode(card_info->result));
|
|
}
|
|
}
|
|
} else if (mCD_check_sector_size(mCD_MEMCARD_SECTORSIZE, chan) == FALSE) {
|
|
cond[chan] = 6;
|
|
} else {
|
|
cond[chan] = mCD_TransErrCodeToCond(mCD_TransErrorCode_nes(card_info->result));
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (save_found == TRUE) {
|
|
break;
|
|
}
|
|
|
|
if (bad_save_chan == 1 && save_chan == -1) {
|
|
noLand_info[chan] = mCD_check_noLand_file((mCD_LandProtectCode_c*)noLand_code[chan], (u8*)mgr->workArea, chan);
|
|
save_chan = chan;
|
|
}
|
|
|
|
card_info++;
|
|
}
|
|
|
|
if (save_found == FALSE) {
|
|
if (save_chan != -1) {
|
|
if (noLand_info[save_chan] == TRUE) {
|
|
bcopy(noLand_code[save_chan], &l_keep_noLandCode, sizeof(l_keep_noLandCode));
|
|
flashrom_cond = 0;
|
|
mCD_load_set_others_common(mgr, &mgr->cards[save_chan], save_chan, FALSE);
|
|
} else {
|
|
flashrom_cond = 2;
|
|
}
|
|
} else {
|
|
if (cond[0] > cond[1]) {
|
|
flashrom_cond = cond[1];
|
|
save_chan = 1;
|
|
} else {
|
|
flashrom_cond = cond[0];
|
|
save_chan = 0;
|
|
}
|
|
}
|
|
} else {
|
|
flashrom_cond = cond[save_chan];
|
|
mCD_load_set_others_common(mgr, &mgr->cards[save_chan], save_chan, TRUE);
|
|
}
|
|
}
|
|
|
|
Common_Set(save_error_type, flashrom_cond);
|
|
|
|
if (save_chan != -1) {
|
|
Common_Set(memcard_slot, save_chan);
|
|
} else {
|
|
Common_Set(memcard_slot, 0);
|
|
}
|
|
|
|
mCD_ClearMemMgr_com2(mgr);
|
|
|
|
if (mFRm_CheckSaveData_common(Save_GetPointer(save_check), Save_Get(land_info).id) && Save_Get(save_check).version == 5) {
|
|
bcopy(&Save_Get(save_check).time, Save_GetPointer(saved_auto_nwrite_time), sizeof(lbRTC_time_c));
|
|
}
|
|
}
|
|
|
|
extern void mCD_ReCheckLoadLand(GAME_PLAY* play) {
|
|
int scene = Save_Get(scene_no);
|
|
int bad;
|
|
|
|
mCD_LoadLand();
|
|
Save_Set(scene_no, scene);
|
|
|
|
switch (Common_Get(save_error_type)) {
|
|
case 0:
|
|
bad = TRUE;
|
|
break;
|
|
default:
|
|
bad = FALSE;
|
|
break;
|
|
}
|
|
|
|
if (bad == FALSE) {
|
|
scene = SCENE_PLAYERSELECT_3;
|
|
Common_Set(house_owner_name, RSV_NO);
|
|
Common_Set(last_field_id, RSV_NO);
|
|
} else {
|
|
int res = mFRm_CheckSaveData();
|
|
|
|
if (res == FALSE) {
|
|
scene = SCENE_PLAYERSELECT;
|
|
Common_Set(house_owner_name, RSV_NO);
|
|
Common_Set(last_field_id, RSV_NO);
|
|
} else {
|
|
int rtc_on = Common_Get(time.rtc_enabled);
|
|
Common_Set(time.rtc_enabled, TRUE);
|
|
mTM_rtcTime_limit_check();
|
|
scene = SCENE_PLAYERSELECT_2;
|
|
Common_Set(time.rtc_enabled, rtc_on);
|
|
mEv_ClearEventInfo();
|
|
}
|
|
}
|
|
|
|
|
|
play->next_scene_no = scene;
|
|
}
|
|
|
|
static int mCD_EraseLand_ChangeErrCode(int err_code) {
|
|
switch (err_code) {
|
|
case mCD_TRANS_ERR_BROKEN_WRONGENCODING:
|
|
case mCD_TRANS_ERR_REPAIR:
|
|
case mCD_TRANS_ERR_TOWN_INVALID:
|
|
case mCD_TRANS_ERR_16:
|
|
case mCD_TRANS_ERR_GENERIC:
|
|
err_code = mCD_TRANS_ERR_IOERROR;
|
|
break;
|
|
case mCD_TRANS_ERR_NO_SPACE:
|
|
case mCD_TRANS_ERR_OTHER_TOWN:
|
|
err_code = mCD_TRANS_ERR_NOCARD;
|
|
break;
|
|
}
|
|
|
|
return err_code;
|
|
}
|
|
|
|
static int mCD_EraseLand_bg_get_area(mCD_memMgr_c* mgr, mCD_memMgr_fileInfo_c* fileInfo) {
|
|
return mCD_bg_get_area_common(mgr, fileInfo, mCD_FILE_SAVE_MAIN, 1);
|
|
}
|
|
|
|
static int mCD_EraseLand_bg_get_slot(mCD_memMgr_c* mgr, mCD_memMgr_fileInfo_c* fileInfo) {
|
|
mCD_memMgr_card_info_c* card_info = mgr->cards;
|
|
int res = mCD_RESULT_BUSY;
|
|
|
|
if (mgr->cards[0].workArea != NULL && mgr->cards[1].workArea != NULL && mgr->workArea != NULL) {
|
|
if (Save_Get(save_exist) == FALSE) {
|
|
res = mCD_RESULT_ERROR;
|
|
} else {
|
|
int slot = mCD_get_this_land_slot_no(mgr);
|
|
|
|
if (slot == mCD_SLOT_B) {
|
|
if (mgr->chan != -1) {
|
|
res = mCD_RESULT_SUCCESS;
|
|
fileInfo->proc++;
|
|
} else {
|
|
res = mCD_RESULT_ERROR;
|
|
}
|
|
} else if (slot != mCD_SLOT_A) {
|
|
res = mCD_RESULT_ERROR;
|
|
}
|
|
}
|
|
} else {
|
|
res = mCD_RESULT_ERROR;
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
static int mCD_EraseLand_bg_set_data(mCD_memMgr_c* mgr, mCD_memMgr_fileInfo_c* fileInfo) {
|
|
mCD_memMgr_card_info_c* card_info;
|
|
u8* data_p = (u8*)mgr->workArea;
|
|
int res;
|
|
|
|
if (data_p != NULL && mgr->chan != -1) {
|
|
bzero(data_p, CARD_WORKAREA_SIZE);
|
|
bcopy(Common_GetPointer(save), data_p, CARD_WORKAREA_SIZE);
|
|
mFRm_ClearSaveCheckData((mFRm_chk_t*)data_p);
|
|
mgr->loaded_file_type = mCD_FILE_SAVE_MAIN;
|
|
mgr->workArea_size = mCD_get_size(mCD_FILE_SAVE_MAIN);
|
|
card_info = &mgr->cards[mgr->chan];
|
|
card_info->game_result = mCD_TRANS_ERR_NOCARD;
|
|
fileInfo->proc++;
|
|
res = mCD_RESULT_SUCCESS;
|
|
} else {
|
|
res = mCD_RESULT_ERROR;
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
static int mCD_EraseLand_bg_write_main(mCD_memMgr_c* mgr, mCD_memMgr_fileInfo_c* fileInfo) {
|
|
mCD_file_entry_c* entry;
|
|
mCD_memMgr_card_info_c* card_info;
|
|
int res;
|
|
int chan = mgr->chan;
|
|
int ofs;
|
|
|
|
if (chan != -1) {
|
|
entry = &l_mcd_file_table[mgr->loaded_file_type];
|
|
ofs = mCD_get_offset(mgr->loaded_file_type);
|
|
card_info = &mgr->cards[chan];
|
|
res = mCD_write_comp_bg(mgr->workArea, entry->filename, mgr->workArea_size, entry->filesize, ofs, chan, &card_info->result);
|
|
card_info->game_result = mCD_TransErrorCode(card_info->result);
|
|
|
|
if (res == mCD_RESULT_SUCCESS) {
|
|
fileInfo->proc++;
|
|
mgr->loaded_file_type = mCD_FILE_SAVE_MAIN_BAK;
|
|
}
|
|
} else {
|
|
res = mCD_RESULT_ERROR;
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
|
|
static int mCD_EraseLand_bg_write_bk(mCD_memMgr_c* mgr, mCD_memMgr_fileInfo_c* fileInfo) {
|
|
mCD_file_entry_c* entry;
|
|
mCD_memMgr_card_info_c* card_info;
|
|
int res;
|
|
int chan = mgr->chan;
|
|
int ofs;
|
|
|
|
if (chan != -1) {
|
|
entry = &l_mcd_file_table[mgr->loaded_file_type];
|
|
ofs = mCD_get_offset(mgr->loaded_file_type);
|
|
card_info = &mgr->cards[chan];
|
|
res = mCD_write_comp_bg(mgr->workArea, entry->filename, mgr->workArea_size, entry->filesize, ofs, chan, &card_info->result);
|
|
card_info->game_result = mCD_TransErrorCode(card_info->result);
|
|
|
|
if (res == mCD_RESULT_SUCCESS) {
|
|
fileInfo->proc++;
|
|
bzero(mgr->workArea, mgr->workArea_size);
|
|
mgr->loaded_file_type = mCD_FILE_SAVE_MISC;
|
|
mgr->workArea_size = mCD_get_size(mgr->loaded_file_type);
|
|
}
|
|
} else {
|
|
res = mCD_RESULT_ERROR;
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
static int mCD_EraseLand_bg_load_icon(mCD_memMgr_c* mgr, mCD_memMgr_fileInfo_c* fileInfo) {
|
|
mCD_memMgr_card_info_c* card_info;
|
|
int res;
|
|
int chan = mgr->chan;
|
|
|
|
if (chan != -1) {
|
|
card_info = &mgr->cards[chan];
|
|
res = mCD_load_file(mgr->workArea, mgr->loaded_file_type, chan, &card_info->result);
|
|
|
|
if (res == mCD_RESULT_SUCCESS) {
|
|
fileInfo->proc++;
|
|
bcopy(l_comment_erase_land, (u8*)mgr->workArea + sizeof(l_comment_0_str), sizeof(l_comment_erase_land));
|
|
mCD_MakeProtectCode((mCD_LandProtectCode_c*)((u8*)mgr->workArea + sizeof(MemcardHeader_c)));
|
|
}
|
|
} else {
|
|
res = mCD_RESULT_ERROR;
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
static int mCD_EraseLand_bg_write_icon(mCD_memMgr_c* mgr, mCD_memMgr_fileInfo_c* fileInfo) {
|
|
int res;
|
|
|
|
res = mCD_write_common(mgr);
|
|
|
|
if (res == mCD_RESULT_SUCCESS) {
|
|
fileInfo->proc++;
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
extern int mCD_EraseLand_bg(int* slot) {
|
|
// clang-format off
|
|
static mCD_SAVEHOME_PROC erase_proc[] = {
|
|
mCD_EraseLand_bg_get_area,
|
|
mCD_EraseLand_bg_get_slot,
|
|
mCD_EraseLand_bg_set_data,
|
|
mCD_EraseLand_bg_write_main,
|
|
mCD_EraseLand_bg_write_bk,
|
|
mCD_EraseLand_bg_load_icon,
|
|
mCD_EraseLand_bg_write_icon,
|
|
};
|
|
// clang-format on
|
|
|
|
mCD_memMgr_c* mgr = &l_memMgr;
|
|
mCD_memMgr_fileInfo_c* fileInfo = &mgr->save_home_info;
|
|
mCD_memMgr_card_info_c* card_info;
|
|
int res;
|
|
u8 proc = (u8)fileInfo->proc;
|
|
int ret = mCD_TRANS_ERR_BUSY;
|
|
|
|
mgr->_0188++;
|
|
if (mgr->_018C == 0) {
|
|
if (proc < 7) {
|
|
res = (*erase_proc[proc])(mgr, fileInfo);
|
|
if (res == mCD_RESULT_SUCCESS) {
|
|
if (fileInfo->proc == 7) {
|
|
*slot = mgr->chan;
|
|
ret = mCD_TRANS_ERR_NONE;
|
|
}
|
|
} else if (res != mCD_RESULT_BUSY) {
|
|
int cur_chan = mgr->chan;
|
|
|
|
if (cur_chan == 0 || cur_chan == 1) {
|
|
*slot = cur_chan;
|
|
card_info = &mgr->cards[mgr->chan];
|
|
ret = card_info->game_result;
|
|
} else {
|
|
ret = mCD_TRANS_ERR_NOCARD;
|
|
}
|
|
}
|
|
|
|
if (res == mCD_RESULT_ERROR || (res == mCD_RESULT_SUCCESS && fileInfo->proc == 7)) {
|
|
if (mgr->_0188 >= 170) {
|
|
sAdo_SysLevStop(NA_SE_53);
|
|
mCD_ClearMemMgr_com2(mgr);
|
|
} else {
|
|
mgr->_018C = 1;
|
|
mgr->_0190 = ret;
|
|
mgr->_0194 = *slot;
|
|
ret = mCD_TRANS_ERR_BUSY;
|
|
|
|
if (mgr->_0190 == mCD_TRANS_ERR_BUSY) {
|
|
mgr->_0190 = mCD_TRANS_ERR_NOCARD;
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
ret = mCD_TRANS_ERR_NONE;
|
|
mCD_ClearMemMgr_com2(mgr);
|
|
}
|
|
} else if (mgr->_0188 >= 170) {
|
|
ret = mgr->_0190;
|
|
*slot = mgr->_0194;
|
|
mCD_ClearMemMgr_com2(mgr);
|
|
sAdo_SysLevStop(NA_SE_53);
|
|
}
|
|
|
|
return mCD_EraseLand_ChangeErrCode(ret);
|
|
}
|
|
|
|
static int mCD_EraseBrokenLand_bg_get_slot(mCD_memMgr_c* mgr, mCD_memMgr_fileInfo_c* fileInfo) {
|
|
mCD_memMgr_card_info_c* card_info;
|
|
Save_t* save;
|
|
int sel_chan;
|
|
int i;
|
|
s32 chan;
|
|
int type;
|
|
int ret;
|
|
|
|
save = (Save_t*)mgr->workArea;
|
|
card_info = mgr->cards;
|
|
sel_chan = -1;
|
|
if (mgr->cards[mCD_SLOT_A].workArea != NULL && mgr->cards[mCD_SLOT_B].workArea != NULL && mgr->workArea != NULL) {
|
|
for (chan = 0; chan < 2; chan++) {
|
|
card_info->game_result = mCD_TRANS_ERR_NOCARD;
|
|
|
|
for (i = 0, type = 0; type < 2; type++) {
|
|
int size;
|
|
|
|
mgr->loaded_file_type = mCD_FILE_SAVE_MAIN + type;
|
|
mgr->workArea_size = mCD_get_size(mgr->loaded_file_type);
|
|
bzero(save, mgr->workArea_size);
|
|
|
|
if (mCD_load_file(save, mgr->loaded_file_type, chan, &card_info->result) == mCD_RESULT_SUCCESS) {
|
|
if (mFRm_CheckSaveData_common(&save->save_check, save->land_info.id)) {
|
|
if (mFRm_ReturnCheckSum((u16*)save, mgr->workArea_size) == 0 && (save->save_check.version == 6 || save->save_check.version == 5)) {
|
|
card_info->game_result = mCD_TRANS_ERR_15;
|
|
sel_chan = chan;
|
|
break;
|
|
} else {
|
|
i++;
|
|
}
|
|
} else {
|
|
i++;
|
|
}
|
|
} else {
|
|
card_info->game_result = mCD_TransErrorCode(card_info->result);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (i == 2) {
|
|
mgr->chan = chan;
|
|
break;
|
|
}
|
|
|
|
card_info++;
|
|
}
|
|
|
|
if (mgr->chan != -1) {
|
|
fileInfo->proc++;
|
|
ret = mCD_RESULT_SUCCESS;
|
|
} else {
|
|
if (sel_chan != -1) {
|
|
mgr->chan = sel_chan;
|
|
} else {
|
|
mCD_GetHighPriority_common(mgr, mgr->cards[mCD_SLOT_A].game_result, mgr->cards[mCD_SLOT_B].game_result);
|
|
}
|
|
ret = mCD_RESULT_ERROR;
|
|
}
|
|
} else {
|
|
ret = mCD_RESULT_ERROR;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
extern int mCD_EraseBrokenLand_bg(int* slot) {
|
|
// clang-format off
|
|
static mCD_SAVEHOME_PROC erase_proc[] = {
|
|
mCD_EraseLand_bg_get_area,
|
|
mCD_EraseBrokenLand_bg_get_slot,
|
|
mCD_EraseLand_bg_set_data,
|
|
mCD_EraseLand_bg_write_main,
|
|
mCD_EraseLand_bg_write_bk,
|
|
mCD_EraseLand_bg_load_icon,
|
|
mCD_EraseLand_bg_write_icon,
|
|
};
|
|
// clang-format on
|
|
|
|
mCD_memMgr_c* mgr = &l_memMgr;
|
|
mCD_memMgr_fileInfo_c* fileInfo = &mgr->save_home_info;
|
|
mCD_memMgr_card_info_c* card_info;
|
|
int res;
|
|
u8 proc = (u8)fileInfo->proc;
|
|
int ret = mCD_TRANS_ERR_BUSY;
|
|
|
|
mgr->_0188++;
|
|
if (mgr->_018C == 0) {
|
|
if (proc < 7) {
|
|
res = (*erase_proc[proc])(mgr, fileInfo);
|
|
if (res == mCD_RESULT_SUCCESS) {
|
|
if (fileInfo->proc == 7) {
|
|
*slot = mgr->chan;
|
|
ret = mCD_TRANS_ERR_NONE;
|
|
}
|
|
} else if (res != mCD_RESULT_BUSY) {
|
|
int cur_chan = mgr->chan;
|
|
|
|
if (cur_chan == 0 || cur_chan == 1) {
|
|
*slot = cur_chan;
|
|
card_info = &mgr->cards[mgr->chan];
|
|
ret = card_info->game_result;
|
|
} else {
|
|
ret = mCD_TRANS_ERR_NOCARD;
|
|
}
|
|
}
|
|
|
|
if (res == mCD_RESULT_ERROR || (res == mCD_RESULT_SUCCESS && fileInfo->proc == 7)) {
|
|
if (mgr->_0188 >= 170) {
|
|
sAdo_SysLevStop(NA_SE_53);
|
|
mCD_ClearMemMgr_com2(mgr);
|
|
} else {
|
|
mgr->_018C = 1;
|
|
mgr->_0190 = ret;
|
|
mgr->_0194 = *slot;
|
|
ret = mCD_TRANS_ERR_BUSY;
|
|
|
|
if (mgr->_0190 == mCD_TRANS_ERR_BUSY) {
|
|
mgr->_0190 = mCD_TRANS_ERR_NOCARD;
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
ret = mCD_TRANS_ERR_NONE;
|
|
mCD_ClearMemMgr_com2(mgr);
|
|
}
|
|
} else if (mgr->_0188 >= 170) {
|
|
ret = mgr->_0190;
|
|
*slot = mgr->_0194;
|
|
mCD_ClearMemMgr_com2(mgr);
|
|
sAdo_SysLevStop(NA_SE_53);
|
|
}
|
|
|
|
return mCD_EraseLand_ChangeErrCode(ret);
|
|
}
|
|
|
|
extern int mCD_CheckPassportFile(void) {
|
|
void* workArea;
|
|
int ret;
|
|
|
|
ret = -1;
|
|
workArea = mCD_malloc_32(CARD_WORKAREA_SIZE);
|
|
|
|
if (workArea != NULL) {
|
|
int i;
|
|
|
|
for (i = 0; i < 2; i++) {
|
|
if (mCD_CheckPassportFile_slot(i, workArea) == TRUE) {
|
|
ret = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (workArea != NULL) {
|
|
zelda_free(workArea);
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
extern int mCD_CheckBrokenPassportFile(int slot) {
|
|
ForeignerFile_c* foreigner_file;
|
|
void* workArea;
|
|
int i;
|
|
int ret;
|
|
s32 result;
|
|
CARDStat stat;
|
|
CARDFileInfo file_info;
|
|
|
|
ret = FALSE;
|
|
workArea = mCD_malloc_32(CARD_WORKAREA_SIZE);
|
|
foreigner_file = (ForeignerFile_c*)mCD_malloc_32(mCD_PLAYER_SAVE_SIZE);
|
|
if ((slot == mCD_SLOT_A || slot == mCD_SLOT_B) && workArea != NULL && foreigner_file != NULL && mCD_check_card(&result, mCD_MEMCARD_SECTORSIZE, slot) == TRUE) {
|
|
result = CARDMount((s32)slot, workArea, NULL);
|
|
if (result == CARD_RESULT_READY || result == CARD_RESULT_BROKEN) {
|
|
result = CARDCheck((s32)slot);
|
|
if (result == CARD_RESULT_READY) {
|
|
|
|
for (i = 0; i < CARD_MAX_FILE; i++) {
|
|
result = CARDGetStatus((s32)slot, i, &stat);
|
|
|
|
if (result == CARD_RESULT_READY && mCD_CheckPassportFileStatus(&stat) == TRUE) {
|
|
result = CARDOpen((s32)slot, stat.fileName, &file_info);
|
|
|
|
if (result == CARD_RESULT_READY) {
|
|
result = CARDRead(&file_info, foreigner_file, mCD_PLAYER_SAVE_SIZE, 0);
|
|
|
|
if (result == CARD_RESULT_READY && (mFRm_ReturnCheckSum((u16*)&foreigner_file->file, sizeof(mCD_foreigner_c)) != 0 || mPr_NullCheckPersonalID(&foreigner_file->file.priv.player_ID) == TRUE)) {
|
|
CARDClose(&file_info);
|
|
ret = TRUE;
|
|
break;
|
|
}
|
|
|
|
CARDClose(&file_info);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
CARDUnmount((s32)slot);
|
|
} else if (result == CARD_RESULT_ENCODING) {
|
|
CARDUnmount((s32)slot);
|
|
}
|
|
|
|
if (workArea != NULL) {
|
|
zelda_free(workArea);
|
|
}
|
|
|
|
if (foreigner_file != NULL) {
|
|
zelda_free(foreigner_file);
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
static int mCD_ErasePassport_bg_get_area(mCD_memMgr_c* mgr, mCD_memMgr_fileInfo_c* fileInfo) {
|
|
return mCD_bg_get_area_common(mgr, fileInfo, mCD_FILE_PLAYER, 1);
|
|
}
|
|
|
|
static int mCD_ErasePassport_bg_mount_card(mCD_memMgr_c* mgr, mCD_memMgr_fileInfo_c* fileInfo) {
|
|
mCD_memMgr_card_info_c* card_info;
|
|
int res;
|
|
int chan = mgr->chan;
|
|
|
|
if (chan != -1) {
|
|
card_info = &mgr->cards[chan];
|
|
if (card_info->workArea != NULL && mCD_check_card(&card_info->result, mCD_MEMCARD_SECTORSIZE, chan) == TRUE) {
|
|
card_info->result = CARDMount((s32)chan, card_info->workArea, NULL);
|
|
if (card_info->result == CARD_RESULT_READY || card_info->result == CARD_RESULT_BROKEN) {
|
|
card_info->result = CARDCheck((s32)chan);
|
|
if (card_info->result == CARD_RESULT_READY) {
|
|
res = mCD_RESULT_SUCCESS;
|
|
fileInfo->proc++;
|
|
} else {
|
|
CARDUnmount((s32)chan);
|
|
res = mCD_RESULT_ERROR;
|
|
}
|
|
} else {
|
|
if (card_info->result == CARD_RESULT_ENCODING) {
|
|
CARDUnmount((s32)chan);
|
|
}
|
|
|
|
res = mCD_RESULT_ERROR;
|
|
}
|
|
} else {
|
|
res = mCD_RESULT_ERROR;
|
|
}
|
|
} else {
|
|
res = mCD_RESULT_ERROR;
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
static int mCD_ErasePassportFile_bg_get_broken_Passport(mCD_memMgr_c* mgr, mCD_memMgr_fileInfo_c* fileInfo) {
|
|
mCD_memMgr_card_info_c* card_info;
|
|
ForeignerFile_c* foreigner_file;
|
|
int ret;
|
|
int i;
|
|
CARDFileInfo file_info;
|
|
int chan;
|
|
int fileNo;
|
|
CARDStat* stat;
|
|
|
|
foreigner_file = (ForeignerFile_c*)mgr->workArea;
|
|
chan = mgr->chan;
|
|
fileNo = fileInfo->_04;
|
|
ret = mCD_RESULT_BUSY;
|
|
|
|
if (chan != -1 && foreigner_file != NULL) {
|
|
card_info = &mgr->cards[chan];
|
|
stat = &card_info->stat;
|
|
for (i = fileNo; i < CARD_MAX_FILE; i++) {
|
|
card_info->result = CARDGetStatus((s32)chan, i, stat);
|
|
|
|
if (card_info->result == CARD_RESULT_READY && mCD_CheckPassportFileStatus(stat) == TRUE) {
|
|
card_info->result = CARDOpen((s32)chan, stat->fileName, &file_info);
|
|
|
|
if (card_info->result == CARD_RESULT_READY) {
|
|
card_info->result = CARDRead(&file_info, foreigner_file, mCD_PLAYER_SAVE_SIZE, 0);
|
|
|
|
if (card_info->result == CARD_RESULT_READY && (mFRm_ReturnCheckSum((u16*)&foreigner_file->file, sizeof(mCD_foreigner_c)) != 0 || mPr_NullCheckPersonalID(&foreigner_file->file.priv.player_ID) == TRUE)) {
|
|
fileInfo->_04 = i;
|
|
CARDClose(&file_info);
|
|
card_info->result = CARDDeleteAsync((s32)chan, stat->fileName, NULL);
|
|
if (card_info->result == CARD_RESULT_READY) {
|
|
ret = mCD_RESULT_SUCCESS;
|
|
fileInfo->proc++;
|
|
} else {
|
|
ret = mCD_RESULT_ERROR;
|
|
}
|
|
break;
|
|
}
|
|
|
|
CARDClose(&file_info);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (i == CARD_MAX_FILE) {
|
|
CARDUnmount((s32)chan);
|
|
ret = mCD_RESULT_SUCCESS;
|
|
fileInfo->proc = 4;
|
|
} else {
|
|
if (ret == mCD_RESULT_ERROR) {
|
|
CARDUnmount((s32)chan);
|
|
}
|
|
}
|
|
} else {
|
|
if (chan != -1) {
|
|
CARDUnmount((s32)chan);
|
|
}
|
|
|
|
ret = mCD_RESULT_ERROR;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
static int mCD_ErasePassportFile_bg_erase(mCD_memMgr_c* mgr, mCD_memMgr_fileInfo_c* fileInfo) {
|
|
mCD_memMgr_card_info_c* info;
|
|
int chan = mgr->chan;
|
|
int _04 = fileInfo->_04;
|
|
int ret = mCD_RESULT_BUSY;
|
|
|
|
if (chan != -1 && _04 >= 0 && _04 < 127) {
|
|
info = &mgr->cards[chan];
|
|
info->result = CARDGetResultCode(chan);
|
|
if (info->result == CARD_RESULT_READY) {
|
|
fileInfo->_04++;
|
|
|
|
if (fileInfo->_04 >= 127) {
|
|
CARDUnmount(chan);
|
|
fileInfo->proc = 4;
|
|
} else {
|
|
fileInfo->proc = 2;
|
|
}
|
|
|
|
ret = mCD_RESULT_SUCCESS;
|
|
} else if (info->result != CARD_RESULT_BUSY) {
|
|
CARDUnmount(chan);
|
|
ret = mCD_RESULT_ERROR;
|
|
}
|
|
} else {
|
|
if (chan != -1) {
|
|
CARDUnmount(chan);
|
|
}
|
|
|
|
ret = mCD_RESULT_ERROR;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
extern int mCD_ErasePassportFile_bg(int slot) {
|
|
// clang-format off
|
|
static mCD_SAVEHOME_PROC erase_proc[] = {
|
|
mCD_ErasePassport_bg_get_area,
|
|
mCD_ErasePassport_bg_mount_card,
|
|
mCD_ErasePassportFile_bg_get_broken_Passport,
|
|
mCD_ErasePassportFile_bg_erase,
|
|
};
|
|
// clang-format on
|
|
|
|
mCD_memMgr_c* mgr = &l_memMgr;
|
|
mCD_memMgr_fileInfo_c* fileInfo = &mgr->save_home_info;
|
|
mCD_memMgr_card_info_c* card_info;
|
|
int res;
|
|
u8 proc = (u8)fileInfo->proc;
|
|
int ret = mCD_RESULT_BUSY;
|
|
|
|
mgr->_0188++;
|
|
mgr->chan = slot;
|
|
if (mgr->_018C == 0) {
|
|
if (proc < 4) {
|
|
res = (*erase_proc[proc])(mgr, fileInfo);
|
|
if (res == mCD_RESULT_SUCCESS) {
|
|
if (fileInfo->proc == 4) {
|
|
ret = mCD_RESULT_SUCCESS;
|
|
}
|
|
} else if (res != mCD_RESULT_BUSY) {
|
|
ret = mCD_RESULT_ERROR;
|
|
}
|
|
|
|
if (res == mCD_RESULT_ERROR || (res == mCD_RESULT_SUCCESS && fileInfo->proc == 4)) {
|
|
if (mgr->_0188 >= 170) {
|
|
sAdo_SysLevStop(NA_SE_53);
|
|
mCD_ClearMemMgr_com2(mgr);
|
|
} else {
|
|
mgr->_018C = 1;
|
|
mgr->_0190 = ret;
|
|
ret = mCD_RESULT_BUSY;
|
|
}
|
|
}
|
|
} else {
|
|
ret = mCD_RESULT_ERROR;
|
|
mCD_ClearMemMgr_com2(mgr);
|
|
}
|
|
} else if (mgr->_0188 >= 170) {
|
|
ret = l_memMgr._0190;
|
|
mCD_ClearMemMgr_com2(mgr);
|
|
sAdo_SysLevStop(NA_SE_53);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
static int mCD_GameStart_ChangeErrCode(int err_code) {
|
|
switch (err_code) {
|
|
case mCD_TRANS_ERR_BROKEN_WRONGENCODING:
|
|
case mCD_TRANS_ERR_REPAIR:
|
|
case mCD_TRANS_ERR_TOWN_INVALID:
|
|
case mCD_TRANS_ERR_16:
|
|
case mCD_TRANS_ERR_GENERIC:
|
|
err_code = mCD_TRANS_ERR_IOERROR;
|
|
break;
|
|
|
|
case mCD_TRANS_ERR_NO_SPACE:
|
|
case mCD_TRANS_ERR_OTHER_TOWN:
|
|
err_code = mCD_TRANS_ERR_NOCARD;
|
|
break;
|
|
}
|
|
|
|
return err_code;
|
|
}
|
|
|
|
static void mCD_SetCopyProtect(mCD_foreigner_c* passport) {
|
|
f32 random = fqrand();
|
|
u16 code = (u16)(random * 0xFFFE);
|
|
|
|
l_mcd_copy_protect = code;
|
|
passport->copy_protect = code;
|
|
passport->checksum = mFRm_GetFlatCheckSum((u16*)passport, sizeof(mCD_foreigner_c), passport->checksum);
|
|
}
|
|
|
|
static Private_c* mCD_GetSaveFilePrivateP(void) {
|
|
return &l_mcd_foreigner_file.file.priv;
|
|
}
|
|
|
|
static int mCD_InitGameStart_bg_get_area(mCD_memMgr_c* mgr, mCD_memMgr_fileInfo_c* fileInfo) {
|
|
static int sound_mode[] = { 2, 0, 0, 0, 0 };
|
|
|
|
int soundm = 2;
|
|
|
|
if (fileInfo->chan >= 0 && fileInfo->chan < 5) {
|
|
soundm = sound_mode[fileInfo->chan];
|
|
}
|
|
|
|
fileInfo->_10 = soundm;
|
|
SoftResetEnable = FALSE;
|
|
return mCD_bg_get_area_common(mgr, fileInfo, mCD_FILE_SAVE_MAIN, soundm);
|
|
}
|
|
|
|
static int mCD_InitGameStart_bg_get_slot(mCD_memMgr_c* mgr, mCD_memMgr_fileInfo_c* fileInfo) {
|
|
int _0C = fileInfo->chan;
|
|
int res = mCD_RESULT_BUSY;
|
|
|
|
if (mgr->cards[0].workArea != NULL && mgr->cards[1].workArea != NULL && mgr->workArea != NULL) {
|
|
if (_0C == 0 || _0C == 2) {
|
|
res = mCD_RESULT_SUCCESS;
|
|
fileInfo->proc = 4;
|
|
} else {
|
|
int slot = mCD_get_this_land_slot_no_game_start(mgr);
|
|
|
|
if (slot == mCD_SLOT_B) {
|
|
int chan = mgr->chan;
|
|
|
|
if (chan != -1) {
|
|
if (mCD_check_copyProtect((Save_t*)mgr->workArea, chan) == TRUE) {
|
|
res = mCD_RESULT_SUCCESS;
|
|
fileInfo->proc++;
|
|
} else {
|
|
mCD_memMgr_card_info_c* card_info = mgr->cards;
|
|
|
|
res = mCD_RESULT_ERROR;
|
|
card_info[chan].game_result = mCD_TRANS_ERR_WRONG_LAND;
|
|
}
|
|
} else {
|
|
res = mCD_RESULT_ERROR;
|
|
}
|
|
} else if (slot != mCD_SLOT_A) {
|
|
res = mCD_RESULT_ERROR;
|
|
}
|
|
}
|
|
} else {
|
|
res = mCD_RESULT_ERROR;
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
static int mCD_InitGameStart_bg_check_repair_land(mCD_memMgr_c* mgr, mCD_memMgr_fileInfo_c* fileInfo) {
|
|
if (mCD_check_broken_land(mgr) == TRUE) {
|
|
if (mCD_repair_land(mgr) == TRUE) {
|
|
fileInfo->proc++;
|
|
} else {
|
|
fileInfo->proc = 4;
|
|
}
|
|
} else {
|
|
fileInfo->proc = 4;
|
|
}
|
|
|
|
return mCD_RESULT_SUCCESS;
|
|
}
|
|
|
|
static int mCD_LoadPrivate_idx(mCD_memMgr_c* mgr, Private_c* priv, Animal_c* animal, int idx) {
|
|
ForeignerFile_c* file;
|
|
mCD_foreigner_c* foreigner;
|
|
void* workArea = mgr->workArea;
|
|
mCD_cardPrivate_c* card_priv;
|
|
int ret = FALSE;
|
|
|
|
if (workArea != NULL && idx >= 0 && idx < ARRAY_SIZE(l_mcd_card_private_table, mCD_cardPrivate_c)) {
|
|
card_priv = &l_mcd_card_private_table[idx];
|
|
|
|
if (!mPr_NullCheckPersonalID(&card_priv->pid)) {
|
|
s32 result;
|
|
int i;
|
|
|
|
for (i = 0; i < mCD_SLOT_NUM; i++) {
|
|
file = (ForeignerFile_c*)workArea;
|
|
foreigner = &file->file;
|
|
|
|
bzero(workArea, sizeof(ForeignerFile_c));
|
|
|
|
if (mCD_read_fg(file, card_priv->filename, sizeof(ForeignerFile_c), 0, i, &result) == mCD_RESULT_SUCCESS) {
|
|
if (mFRm_ReturnCheckSum((u16*)foreigner, sizeof(mCD_foreigner_c)) == 0 &&
|
|
mPr_CheckCmpPersonalID(&foreigner->priv.player_ID, &card_priv->pid) == TRUE
|
|
) {
|
|
mPr_CopyPrivateInfo(priv, &foreigner->priv);
|
|
if (animal != NULL) {
|
|
bcopy(&foreigner->remove_animal, animal, sizeof(Animal_c));
|
|
}
|
|
|
|
bcopy(foreigner, &l_mcd_foreigner_file.file, sizeof(l_mcd_foreigner_file));
|
|
ret = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|