diff options
Diffstat (limited to 'src/m_Do')
| -rw-r--r-- | src/m_Do/m_Do_MemCard.cpp | 405 | ||||
| -rw-r--r-- | src/m_Do/m_Do_MemCardRWmng.cpp | 160 |
2 files changed, 552 insertions, 13 deletions
diff --git a/src/m_Do/m_Do_MemCard.cpp b/src/m_Do/m_Do_MemCard.cpp index 29248e5b69..47c29af4a1 100644 --- a/src/m_Do/m_Do_MemCard.cpp +++ b/src/m_Do/m_Do_MemCard.cpp @@ -10,6 +10,11 @@ #include "m_Do/m_Do_MemCardRWmng.h" #include "m_Do/m_Do_Reset.h" +#if PLATFORM_WII || PLATFORM_SHIELD +#include <revolution/nand.h> +#include <revolution/sc.h> +#endif + #define SLOT_A 0 #define CHECKSPACE_RESULT_READY 0 @@ -17,14 +22,60 @@ #define CHECKSPACE_RESULT_NOENT 2 #define CHECKSPACE_RESULT_ERROR 3 +#if PLATFORM_WII +s32 my_CARDOpen(s32 chan, const char* fileName, CARDFileInfo* fileInfo) { + CARDStat stat; + DVDDiskID* diskID = DVDGetCurrentDiskID(); + + for (int i = 0; i < CARD_MAX_FILE; i++) { + s32 ret = CARDGetStatus(chan, i, &stat); + if (ret == CARD_RESULT_READY) { + if (memcmp(stat.gameName, "GZ2E", 4) == 0 && + memcmp(stat.company, diskID->company, 2) == 0 && + strncmp(stat.fileName, fileName, 32) == 0) + { + return CARDFastOpen(chan, i, fileInfo); + } + } else if (ret != CARD_RESULT_NOFILE) { + return ret; + } + } + + return CARD_RESULT_NOFILE; +} +#endif + +#if PLATFORM_WII +#define CARD_OPEN my_CARDOpen +#else +#define CARD_OPEN CARDOpen +#endif + +#if PLATFORM_WII +#define NAND_OPEN NANDSafeOpen +#define NAND_CLOSE NANDSafeClose +#elif PLATFORM_SHIELD +#define NAND_OPEN NANDSimpleSafeOpen +#define NAND_CLOSE NANDSimpleSafeClose +#endif + mDoMemCd_Ctrl_c::mDoMemCd_Ctrl_c() {} -static u8 MemCardStack[0x1000]; +#if PLATFORM_GCN +#define STACK_SIZE 0x1000 +#else +#define STACK_SIZE 0x2000 +#endif + +static u8 MemCardStack[STACK_SIZE]; static OSThread MemCardThread; void mDoMemCd_Ctrl_c::ThdInit() { + #if !PLATFORM_SHIELD CARDInit(); + #endif + mCopyToPos = 0; mProbeStat = 2; mCardState = CARD_STATE_NO_CARD_e; @@ -33,10 +84,8 @@ void mDoMemCd_Ctrl_c::ThdInit() { OSInitMutex(&mMutex); OSInitCond(&mCond); - - int priority = OSGetThreadPriority(OSGetCurrentThread()); OSCreateThread(&MemCardThread, (void*(*)(void*))mDoMemCd_main, NULL, MemCardStack + sizeof(MemCardStack), - sizeof(MemCardStack), priority + 1, 1); + sizeof(MemCardStack), OSGetThreadPriority(OSGetCurrentThread()) + 1, 1); OSResumeThread(&MemCardThread); // "Memory Card Thread Init\n" @@ -52,6 +101,7 @@ void mDoMemCd_Ctrl_c::main() { OSUnlockMutex(&mMutex); switch (mCardCommand) { + #if PLATFORM_GCN || PLATFORM_WII case COMM_RESTORE_e: restore(); break; @@ -67,6 +117,26 @@ void mDoMemCd_Ctrl_c::main() { case COMM_DETACH_e: detach(); break; + #elif PLATFORM_SHIELD + case COMM_RESTORE_e: + case COMM_STORE_e: + case COMM_FORMAT_e: + case COMM_ATTACH_e: + case COMM_DETACH_e: + break; + #endif + + #if PLATFORM_WII || PLATFORM_SHIELD + case COMM_RESTORE_NAND_e: + restoreNAND(); + break; + case COMM_STORE_NAND_e: + storeNAND(); + break; + case COMM_STORE_SETUP_NAND_e: + storeSetUpNAND(); + break; + #endif } OSLockMutex(&mMutex); @@ -83,6 +153,7 @@ void mDoMemCd_Ctrl_c::update() { OSUnlockMutex(&mMutex); OSSignalCond(&mCond); } else if (getStatus(0) != 14) { + #if PLATFORM_GCN || PLATFORM_WII if (CARDProbe(SLOT_A) && getStatus(0) == 0) { OSLockMutex(&mMutex); mProbeStat = 0; @@ -98,6 +169,7 @@ void mDoMemCd_Ctrl_c::update() { OSUnlockMutex(&mMutex); OSSignalCond(&mCond); } + #endif } } @@ -110,11 +182,12 @@ void mDoMemCd_Ctrl_c::load() { } } +#if !PLATFORM_SHIELD void mDoMemCd_Ctrl_c::restore() { CARDFileInfo file; field_0x1fc8 = 0; - s32 ret = CARDOpen(mChannel, "gczelda2", &file); + s32 ret = CARD_OPEN(mChannel, "gczelda2", &file); OS_REPORT("\x1b[43;30mCret=%d\n\x1b[m", ret); if (ret == CARD_RESULT_READY) { s32 ret2 = mDoMemCdRWm_Restore(&file, this, sizeof(mData)); @@ -131,6 +204,7 @@ void mDoMemCd_Ctrl_c::restore() { field_0x1fc8 = 1; } +#endif s32 mDoMemCd_Ctrl_c::LoadSync(void* i_buffer, u32 i_size, u32 i_position) { int ret = 0; @@ -164,13 +238,18 @@ void mDoMemCd_Ctrl_c::save(void* i_buffer, u32 i_size, u32 i_position) { } } +#if !PLATFORM_SHIELD void mDoMemCd_Ctrl_c::store() { CARDFileInfo file; s32 ret; field_0x1fc8 = 0; if (mCardState == CARD_STATE_NO_FILE_e) { - ret = CARDCreate(mChannel, "gczelda2", SAVEDATA_FILE_SIZE, &file); + #if PLATFORM_GCN + ret = CARDCreate(mChannel, "gczelda2", CARD_FILE_SIZE, &file); + #else + ret = CARDCreate(mChannel, "zeldaTp.dat", CARD_FILE_SIZE, &file); + #endif if (ret == CARD_RESULT_READY || ret == CARD_RESULT_EXIST) { mCardState = CARD_STATE_READY_e; } else { @@ -179,7 +258,7 @@ void mDoMemCd_Ctrl_c::store() { } if (mCardState == CARD_STATE_READY_e) { - ret = CARDOpen(mChannel, "gczelda2", &file); + ret = CARD_OPEN(mChannel, "gczelda2", &file); if (ret == CARD_RESULT_READY) { ret = mDoMemCdRWm_Store(&file, this, sizeof(mData)); if (ret != CARD_RESULT_READY) { @@ -199,6 +278,7 @@ void mDoMemCd_Ctrl_c::store() { field_0x1fc8 = 1; } +#endif s32 mDoMemCd_Ctrl_c::SaveSync() { int ret = 0; @@ -217,7 +297,6 @@ s32 mDoMemCd_Ctrl_c::SaveSync() { ret = 2; } - OS_REPORT("CARD Save Sync ret:%d stat:%d\n", ret, mCardState); OSUnlockMutex(&mMutex); } @@ -287,6 +366,7 @@ void mDoMemCd_Ctrl_c::command_format() { } } +#if !PLATFORM_SHIELD void mDoMemCd_Ctrl_c::format() { field_0x1fc8 = 0; @@ -302,6 +382,7 @@ void mDoMemCd_Ctrl_c::format() { OSUnlockMutex(&mMutex); } } +#endif s32 mDoMemCd_Ctrl_c::FormatSync() { int ret = 0; @@ -325,6 +406,7 @@ s32 mDoMemCd_Ctrl_c::FormatSync() { return ret; } +#if !PLATFORM_SHIELD void mDoMemCd_Ctrl_c::attach() { s32 mem_size; s32 sector_size; @@ -418,7 +500,7 @@ s32 mDoMemCd_Ctrl_c::mount() { s32 mDoMemCd_Ctrl_c::loadfile() { CARDFileInfo file; - s32 ret = CARDOpen(mChannel, "gczelda2", &file); + s32 ret = CARD_OPEN(mChannel, "gczelda2", &file); if (ret == CARD_RESULT_READY) { CARDClose(&file); return TRUE; @@ -428,7 +510,6 @@ s32 mDoMemCd_Ctrl_c::loadfile() { } } -// s32 mDoMemCd_Ctrl_c::checkspace() { s32 bytesNotUsed, filesNotUsed; s32 result = CARDFreeBlocks(mChannel, &bytesNotUsed, &filesNotUsed); @@ -438,7 +519,7 @@ s32 mDoMemCd_Ctrl_c::checkspace() { return CHECKSPACE_RESULT_ERROR; } - if (bytesNotUsed < SAVEDATA_FILE_SIZE) { + if (bytesNotUsed < CARD_FILE_SIZE) { return CHECKSPACE_RESULT_INSSPACE; } @@ -472,13 +553,313 @@ void mDoMemCd_Ctrl_c::setCardState(s32 i_result) { break; } } +#endif + +#if PLATFORM_WII || PLATFORM_SHIELD +void mDoMemCd_Ctrl_c::loadNAND() { + if (OSTryLockMutex(&mMutex)) { + field_0x1fc8 = 0; + mCardCommand = COMM_RESTORE_NAND_e; + OSUnlockMutex(&mMutex); + OSSignalCond(&mCond); + } +} + +void mDoMemCd_Ctrl_c::restoreNAND() { + NANDFileInfo file; + s32 ret, ret2; + + field_0x1fc8 = 0; + + ret = NANDOpen("zeldaTp.dat", &file, NAND_ACCESS_RW); + OS_REPORT("\x1b[43;30mCret=%d\n\x1b[m", ret); + if (ret == NAND_RESULT_OK) { + ret2 = mDoMemCdRWm_RestoreNAND(&file, this, sizeof(mData)); + OS_REPORT("\x1b[43;30mret2=%d\n\x1b[m", ret2); + if (ret2 == NAND_RESULT_OK) { + mNandState = NAND_STATE_READ_e; + } else { + setNandState(ret); + } + NANDClose(&file); + } else { + setNandState(ret); + } + + field_0x1fc8 = 1; +} + +s32 mDoMemCd_Ctrl_c::LoadSyncNAND(void* i_buffer, u32 i_size, u32 i_position) { + int ret = 0; + + if (field_0x1fc8 == 0) { + return 0; + } + + if (OSTryLockMutex(&mMutex)) { + if (mNandState == NAND_STATE_READ_e) { + memcpy(i_buffer, &mData[i_position], i_size); + mNandState = NAND_STATE_READY_e; + ret = 1; + } else { + ret = 2; + } + OSUnlockMutex(&mMutex); + } + + return ret; +} + +void mDoMemCd_Ctrl_c::saveNAND(void* i_buffer, u32 i_size, u32 i_position) { + if (OSTryLockMutex(&mMutex)) { + memcpy(&mData[i_position], i_buffer, i_size); + field_0x1fc8 = 0; + mCardCommand = COMM_STORE_NAND_e; + OSUnlockMutex(&mMutex); + OSSignalCond(&mCond); + } +} + +static u8 l_safeCopyBuf[0x4000]; + +void mDoMemCd_Ctrl_c::storeNAND() { + NANDFileInfo file; + s32 ret; + field_0x1fc8 = 0; + + if (mNandState == NAND_STATE_NO_FILE_e) { + ret = NANDCreate("zeldaTp.dat", NAND_PERM_RUSR | NAND_PERM_WUSR | NAND_PERM_RGRP, 0); + if (ret == NAND_RESULT_OK) { + mNandState = NAND_STATE_READY_e; + } else { + setNandState(ret); + } + } + + if (mNandState == NAND_STATE_READY_e) { + u8 sp8 = 1; + ret = NANDCreate("banner.bin", NAND_PERM_RUSR | NAND_PERM_WUSR | NAND_PERM_RGRP, 0); + printf("NAND bannerFile Create ret:%d\n", ret); + if (ret == NAND_RESULT_OK || ret == NAND_RESULT_EXISTS) { + ret = NAND_OPEN("banner.bin", &file, NAND_ACCESS_RW, l_safeCopyBuf, sizeof(l_safeCopyBuf)); + if (ret == NAND_RESULT_OK) { + ret = mDoMemCdRWm_StoreBannerNAND(&file); + if (ret == NAND_RESULT_OK) { + printf("NAND bannerFile Write OK ret:%d\n", ret); + } else { + setNandState(ret); + printf("NAND bannerFile Write ERR ret:%d\n", ret); + } + NAND_CLOSE(&file); + } else { + setNandState(ret); + } + } else { + setNandState(ret); + } + + if (ret == NAND_RESULT_OK) { + ret = NAND_OPEN("zeldaTp.dat", &file, NAND_ACCESS_RW, l_safeCopyBuf, sizeof(l_safeCopyBuf)); + if (ret == NAND_RESULT_OK) { + ret = mDoMemCdRWm_StoreNAND(&file, this, sizeof(mData)); + if (ret == NAND_RESULT_OK) { + mNandState = NAND_STATE_WRITE_e; + printf("NAND Write OK ret:%d stat:%d\n", ret, mNandState); + } else { + setNandState(ret); + printf("NAND Write ERR ret:%d\n", ret); + } + NAND_CLOSE(&file); + } else { + setNandState(ret); + } + } + } else { + setNandState(ret); + } + + field_0x1fc8 = 1; +} + +s32 mDoMemCd_Ctrl_c::SaveSyncNAND() { + int ret = 0; + + if (field_0x1fc8 == 0) { + return 0; + } + + if (OSTryLockMutex(&mMutex)) { + if (mNandState == NAND_STATE_WRITE_e) { + mNandState = NAND_STATE_READY_e; + ret = 1; + } else { + ret = 2; + } + + printf("NAND Save Sync ret:%d stat:%d\n", ret, mNandState); + OSUnlockMutex(&mMutex); + } + + return ret; +} + +void mDoMemCd_Ctrl_c::storeSetUpNAND() { + field_0x1fc8 = 0; + + while ((int)SCCheckStatus() != 0) {} + + #if PLATFORM_WII + if (!SCFlush()) { + mNandState = NAND_STATE_WRITE_e; + printf("== 本体設定Write OK ==\n"); + } else { + mNandState = NAND_STATE_FATAL_ERROR_e; + printf("== 本体設定Write ERR ==\n"); + } + #else + mNandState = NAND_STATE_WRITE_e; + #endif + + field_0x1fc8 = 1; +} + +void m_Do_MemCard_cpp__dummyString() { + DEAD_STRING("本体設定 Save Sync ret:%d stat:%d\n"); +} + +void mDoMemCd_Ctrl_c::setNandState(s32 i_result) { + switch (i_result) { + case NAND_RESULT_CORRUPT: + mNandState = NAND_STATE_BROKEN_e; + break; + case NAND_RESULT_MAXBLOCKS: + mNandState = NAND_STATE_INSSPACE_e; + break; + case NAND_RESULT_MAXFILES: + case NAND_RESULT_MAXFD: + mNandState = NAND_STATE_NOENT_e; + break; + case NAND_RESULT_ECC_CRIT: + case NAND_RESULT_AUTHENTICATION: + mNandState = NAND_STATE_AUTHENTICATION_e; + break; + case NAND_RESULT_NOEXISTS: + mNandState = NAND_STATE_NO_FILE_e; + break; + case NAND_RESULT_UNKNOWN: + case NAND_RESULT_FATAL_ERROR: + mNandState = NAND_STATE_FATAL_ERROR_e; + break; + case -7: + case NAND_RESULT_BUSY: + case NAND_RESULT_ALLOC_FAILED: + case NAND_RESULT_ACCESS: + break; + } +} + +u32 mDoMemCd_Ctrl_c::getStatusNAND() { + u32 status; + if (OSTryLockMutex(&mMutex)) { + switch (mNandState) { + case NAND_STATE_READY_e: + status = 1; + break; + case NAND_STATE_NO_FILE_e: + status = 0; + break; + case NAND_STATE_READ_e: + status = 2; + break; + case NAND_STATE_WRITE_e: + status = 3; + break; + case NAND_STATE_FORMAT_e: + status = 6; + break; + case NAND_STATE_AUTHENTICATION_e: + status = 4; + break; + case NAND_STATE_BROKEN_e: + status = 5; + break; + case NAND_STATE_INSSPACE_e: + status = 7; + break; + case NAND_STATE_NOENT_e: + status = 8; + break; + case NAND_STATE_FATAL_ERROR_e: + status = 9; + break; + case NAND_STATE_10_e: + status = 10; + break; + } + + OSUnlockMutex(&mMutex); + return status; + } + + return 10; +} + +s32 mDoMemCd_Ctrl_c::chekNANDFile() { + NANDFileInfo file; + + s32 ret = NANDOpen("zeldaTp.dat", &file, NAND_ACCESS_RW); + if (ret == NAND_RESULT_OK) { + mNandState = NAND_STATE_READY_e; + NANDClose(&file); + return 1; + } + + switch (checkspaceNAND()) { + case CHECKSPACE_RESULT_READY: + mNandState = NAND_STATE_NO_FILE_e; + break; + case CHECKSPACE_RESULT_INSSPACE: + mNandState = NAND_STATE_INSSPACE_e; + break; + case CHECKSPACE_RESULT_NOENT: + mNandState = NAND_STATE_NOENT_e; + break; + case CHECKSPACE_RESULT_ERROR: + setNandState(ret); + break; + } + + return 0; +} + +s32 mDoMemCd_Ctrl_c::checkspaceNAND() { + u32 answer = -1; + s32 ret; + + s32 result = NANDCheck(3, 2, &answer); + if (result != NAND_RESULT_OK) { + setNandState(result); + return CHECKSPACE_RESULT_ERROR; + } + + if (answer == 0) { + ret = 0; + } else if (answer & 5) { + ret = 1; + } else if (answer & 10) { + ret = 2; + } + + return ret; +} +#endif mDoMemCd_Ctrl_c g_mDoMemCd_control; static int mDoMemCd_main(void*) { { JKRThread thread(OSGetCurrentThread(), 0); } - mDoExt_getAssertHeap()->becomeCurrentHeap(); + JKRSetCurrentHeap(mDoExt_getAssertHeap()); g_mDoMemCd_control.main(); return 0; diff --git a/src/m_Do/m_Do_MemCardRWmng.cpp b/src/m_Do/m_Do_MemCardRWmng.cpp index 5c2c33e693..010b986c00 100644 --- a/src/m_Do/m_Do_MemCardRWmng.cpp +++ b/src/m_Do/m_Do_MemCardRWmng.cpp @@ -13,6 +13,9 @@ #if VERSION == VERSION_GCN_JPN #define HEADER_TITLE "ゼルダの伝説 トワイライトプリンセス" #define HEADER_COMMENT "%d月%d日のセーブデータです" +#elif PLATFORM_WII +#define HEADER_TITLE "The Legend of Zelda: TP" +#define HEADER_COMMENT "%d/%d Save Data" #else #define HEADER_TITLE "Zelda: Twilight Princess" #define HEADER_COMMENT "%d/%d Save Data" @@ -21,12 +24,13 @@ struct data_s { int unk_0x0; int data_version; - u8 data[(SAVEDATA_SIZE * 3) + 0x38]; // unsure what the extra 0x38 is + u8 data[(SAVEFILE_SIZE) + 0x38]; // unsure what the extra 0x38 is u32 checksum; }; static u8 sTmpBuf[SECTOR_SIZE * 2]; +#if !PLATFORM_SHIELD s32 mDoMemCdRWm_Store(CARDFileInfo* file, void* data, u32 length) { mDoMemCdRWm_BuildHeader((mDoMemCdRWm_HeaderData*)sTmpBuf); @@ -152,6 +156,160 @@ s32 mDoMemCdRWm_Restore(CARDFileInfo* file, void* data, u32 length) { return CARD_RESULT_READY; } +#endif + +#if PLATFORM_WII || PLATFORM_SHIELD +s32 mDoMemCdRWm_StoreNAND(NANDFileInfo* file, void* data, u32 length) { + s32 ret; + + memset(sTmpBuf, 0, sizeof(sTmpBuf)); + + data_s* tmp_data = (data_s*)sTmpBuf; + tmp_data->unk_0x0 = 0; + tmp_data->data_version = SAVEDATA_VERSION; + memcpy(tmp_data->data, data, length); + + u32 checksum = tmp_data->checksum = mDoMemCdRWm_CalcCheckSum(tmp_data, sizeof(data_s) - 4); + + ret = NANDWrite(file, sTmpBuf, 0x2000); + if (ret != 0x2000) { + return ret; + } + + NANDSeek(file, 0, 0); + + ret = NANDRead(file, sTmpBuf, 0x2000); + if (ret != 0x2000) { + return ret; + } + + if (checksum != mDoMemCdRWm_CalcCheckSum(sTmpBuf, sizeof(data_s) - 4)) { + return ret; + } + + NANDSeek(file, 0x2000, 0); + + ret = NANDWrite(file, sTmpBuf, 0x2000); + if (ret != 0x2000) { + return ret; + } + + NANDSeek(file, 0x2000, 0); + + ret = NANDRead(file, sTmpBuf, 0x2000); + if (ret != 0x2000) { + return ret; + } + + if (checksum != mDoMemCdRWm_CalcCheckSum(sTmpBuf, sizeof(data_s) - 4)) { + return ret; + } + + return NAND_RESULT_OK; +} + +s32 mDoMemCdRWm_RestoreNAND(NANDFileInfo* file, void* data, u32 length) { + BOOL rewrite = FALSE; + + data_s* saves = (data_s*)sTmpBuf; + data_s* backup_saves = (data_s*)(sTmpBuf + SECTOR_SIZE); + + NANDSeek(file, 0, 0); + s32 ret = NANDRead(file, saves, 0x2000); + if (ret != 0x2000) { + return ret; + } + + BOOL save1_valid = mDoMemCdRWm_TestCheckSumGameData(&saves->data[SAVEDATA_SIZE * 0]); + BOOL save2_valid = mDoMemCdRWm_TestCheckSumGameData(&saves->data[SAVEDATA_SIZE * 1]); + BOOL save3_valid = mDoMemCdRWm_TestCheckSumGameData(&saves->data[SAVEDATA_SIZE * 2]); + + NANDSeek(file, 0x2000, 0); + ret = NANDRead(file, backup_saves, 0x2000); + if (ret != 0x2000) { + return ret; + } + + BOOL backup1_valid = mDoMemCdRWm_TestCheckSumGameData(&backup_saves->data[SAVEDATA_SIZE * 0]); + BOOL backup2_valid = mDoMemCdRWm_TestCheckSumGameData(&backup_saves->data[SAVEDATA_SIZE * 1]); + BOOL backup3_valid = mDoMemCdRWm_TestCheckSumGameData(&backup_saves->data[SAVEDATA_SIZE * 2]); + + if (!save1_valid && backup1_valid) { + memcpy(&saves->data[SAVEDATA_SIZE * 0], &backup_saves->data[SAVEDATA_SIZE * 0], SAVEDATA_SIZE); + rewrite = TRUE; + } + + if (!save2_valid && backup2_valid) { + memcpy(&saves->data[SAVEDATA_SIZE * 1], &backup_saves->data[SAVEDATA_SIZE * 1], SAVEDATA_SIZE); + rewrite = TRUE; + } + + if (!save3_valid && backup3_valid) { + memcpy(&saves->data[SAVEDATA_SIZE * 2], &backup_saves->data[SAVEDATA_SIZE * 2], SAVEDATA_SIZE); + rewrite = TRUE; + } + + BOOL sp10 = FALSE; + if (!save1_valid && !backup1_valid && + !save2_valid && !backup2_valid && + !save3_valid && !backup3_valid) + { + sp10 = TRUE; + } + + if (rewrite) { + NANDSeek(file, 0, 0); + ret = NANDWrite(file, saves, 0x2000); + if (ret != 0x2000) { + return ret; + } + + NANDSeek(file, 0x2000, 0); + ret = NANDWrite(file, saves, 0x2000); + if (ret != 0x2000) { + return ret; + } + } + + memcpy(data, saves->data, length); + mDoMemCd_setDataVersion(saves->data_version); + + return NAND_RESULT_OK; +} +#endif + +#if PLATFORM_WII || PLATFORM_SHIELD +s32 mDoMemCdRWm_StoreBannerNAND(NANDFileInfo* file) { + static NANDBanner info; + static wchar_t titleTxt[] = L"The Legend of Zelda:"; + static wchar_t commentTxt[] = L"Twilight Princess"; + u32 size; + s32 ret; + + NANDInitBanner(&info, 0, (u16*)titleTxt, (u16*)commentTxt); + + ResTIMG* banner_data = (ResTIMG*)dComIfGp_getCardIconResArchive()->getResource("zelda2_wii_banner.bti"); + ResTIMG* icon_data = (ResTIMG*)dComIfGp_getCardIconResArchive()->getResource("zelda2_wii_icon.bti"); + + u8* banner_base_ptr = (u8*)banner_data; + u8* icon_base_ptr = (u8*)icon_data; + + memcpy(info.bannerTexture, banner_base_ptr + banner_data->imageOffset, sizeof(info.bannerTexture)); + memcpy(info.iconTexture, icon_base_ptr + icon_data->imageOffset, 0x1200); + dComIfGp_getCardIconResArchive()->removeResourceAll(); + + NANDSetIconSpeed(info, 0, NAND_STAT_SPEED_MIDDLE); + NANDSetIconSpeed(info, 1, NAND_STAT_SPEED_END); + + size = 0x72A0; + ret = NANDWrite(file, &info, size); + if (ret != size) { + return ret; + } + + return NAND_RESULT_OK; +} +#endif static void mDoMemCdRWm_BuildHeader(mDoMemCdRWm_HeaderData* header) { snprintf(header->mTitle, sizeof(header->mTitle), HEADER_TITLE); |
