diff --git a/source/channel/nand.cpp b/source/channel/nand.cpp index c8b88456..1ab59975 100644 --- a/source/channel/nand.cpp +++ b/source/channel/nand.cpp @@ -37,9 +37,9 @@ #include "nand.hpp" #include "utils.h" -#include "gecko.h" #include "mem2.hpp" -#include "text.hpp" +#include "wbfs.h" +#include "gecko.h" u8 *confbuffer ATTRIBUTE_ALIGN(32); u8 CCode[0x1008]; @@ -465,7 +465,17 @@ s32 Nand::__FlashNandFile(const char *source, const char *dest) u32 fsize = ftell(file); fseek(file, 0, SEEK_SET); - gprintf("Flashing: %s (%uKB) to nand...", source, (fsize / 0x400)+1); + if(fake) + { + NandSize += fsize; + if(showprogress) + dumper(NandSize, 0x1f400000, 0x1f400000, NandSize, FilesDone, FoldersDone, (char *)"", data); + + SAFE_CLOSE(file); + return 0; + } + + gprintf("Flashing: %s (%uKB) to nand...", dest, (fsize / 0x400)+1); ISFS_Delete(dest); ISFS_CreateFile(dest, 0, 3, 3, 3); @@ -505,12 +515,25 @@ s32 Nand::__FlashNandFile(const char *source, const char *dest) return ret; } toread -= size; + NandDone += size; + FileDone += size; + + if(showprogress) + { + const char *file = strrchr(dest, '/')+1; + dumper(NandDone, NandSize, fsize, FileDone, FilesDone, FoldersDone, (char *)file, data); + } + } + gprintf(" done!\n"); + FilesDone++; + if(showprogress) + { + const char *file = strrchr(dest, '/')+1; + dumper(NandDone, NandSize, fsize, FileDone, FilesDone, FoldersDone, (char *)file, data); } - - gprintf(" done!\n"); ISFS_Close(fd); - SAFE_CLOSE(file); MEM2_free(buffer); + SAFE_CLOSE(file); return 1; } @@ -612,6 +635,56 @@ s32 Nand::__DumpNandFile(const char *source, const char *dest) return 0; } + +s32 Nand::__FlashNandFolder(const char *source, const char *dest) +{ + char nsource[MAX_FAT_PATH]; + char ndest[ISFS_MAXPATH]; + char tdest[ISFS_MAXPATH]; + + DIR *dir_iter; + struct dirent *ent; + + dir_iter = opendir(source); + if (!dir_iter) + return 1; + + while((ent = readdir(dir_iter)) != NULL) + { + if(ent->d_name[0] == '.') + continue; + + if(dest[strlen(dest)-1] == '/') + snprintf(ndest, sizeof(ndest), "%s%s", dest, ent->d_name); + else + snprintf(ndest, sizeof(ndest), "%s/%s", dest, ent->d_name); + + if(source[strlen(source)-1] == '/') + snprintf(nsource, sizeof(nsource), "%s%s", source, ent->d_name); + else + snprintf(nsource, sizeof(nsource), "%s/%s", source, ent->d_name); + + if(ent->d_type == DT_DIR) + { + //__FATify(tdest, ndest); + if(!fake) + { + //ISFS_CreateDir(tdest, 0, 3, 3, 3); + ISFS_CreateDir(ndest, 0, 3, 3, 3); + FoldersDone++; + } + __FlashNandFolder(nsource, ndest); + } + else + { + //__FATify(tdest, ndest); + //__FlashNandFile(nsource, tdest); + __FlashNandFile(nsource, ndest); + } + } + return 0; +} + s32 Nand::__DumpNandFolder(const char *source, const char *dest) { namelist *names = NULL; @@ -679,11 +752,65 @@ void Nand::CreatePath(const char *path, ...) SAFE_FREE(folder); } -s32 Nand::DoNandDump(const char *source, const char *dest, bool dumpwgs, dump_callback_t i_dumper, void *i_data) +void Nand::CreateTitleTMD(const char *path, dir_discHdr *hdr) +{ + wbfs_disc_t *disc = WBFS_OpenDisc((u8 *) &hdr->hdr.id, (char *)hdr->path); + if(!disc) + return; + + u8 *titleTMD = NULL; + u32 tmd_size = wbfs_extract_file(disc, (char *) "TMD", (void **)&titleTMD); + WBFS_CloseDisc(disc); + + if(!titleTMD) + return; + + u32 highTID = *(u32*)(titleTMD+0x18c); + u32 lowTID = *(u32*)(titleTMD+0x190); + + CreatePath("%s/title/%08x/%08x/data", path, highTID, lowTID); + CreatePath("%s/title/%08x/%08x/content", path, highTID, lowTID); + + char nandpath[MAX_FAT_PATH]; + snprintf(nandpath, sizeof(nandpath), "%s/title/%08x/%08x/content/title.tmd", path, highTID, lowTID); + + struct stat filestat; + if (stat(nandpath, &filestat) == 0) + { + SAFE_FREE(titleTMD); + gprintf("%s Exists!\n", nandpath); + return; + } + gprintf("Creating title TMD: %s\n", nandpath); + + FILE *file = fopen(nandpath, "wb"); + if(file) + { + fwrite(titleTMD, 1, tmd_size, file); + gprintf("Title TMD written to: %s\n", nandpath); + fclose(file); + } + else + gprintf("Creating title TMD: %s failed (%i)\n", nandpath, file); + + SAFE_FREE(titleTMD); +} + +s32 Nand::FlashToNAND(const char *source, const char *dest, dump_callback_t i_dumper, void *i_data) +{ + ISFS_CreateDir(dest, 0, 3, 3, 3); + data = i_data; + dumper = i_dumper; + fake = false; + showprogress = true; + __FlashNandFolder(source, dest); + return 0; +} + +s32 Nand::DoNandDump(const char *source, const char *dest, dump_callback_t i_dumper, void *i_data) { data = i_data; dumper = i_dumper; - n_dumpwgs = dumpwgs; fake = false; showprogress = true; u32 temp = 0; @@ -703,11 +830,20 @@ s32 Nand::DoNandDump(const char *source, const char *dest, bool dumpwgs, dump_ca return 0; } -s32 Nand::CalcDumpSpace(const char *source, bool dumpwgs, dump_callback_t i_dumper, void *i_data) +s32 Nand::CalcFlashSize(const char *source, dump_callback_t i_dumper, void *i_data) +{ + data = i_data; + dumper = i_dumper; + fake = true; + showprogress = true; + __FlashNandFolder(source, ""); + return NandSize; +} + +s32 Nand::CalcDumpSpace(const char *source, dump_callback_t i_dumper, void *i_data) { data = i_data; dumper = i_dumper; - n_dumpwgs = dumpwgs; fake = true; showprogress = true; diff --git a/source/channel/nand.hpp b/source/channel/nand.hpp index 04e8d5ca..f1696e11 100644 --- a/source/channel/nand.hpp +++ b/source/channel/nand.hpp @@ -9,6 +9,8 @@ #include #include +#include "loader/disc.h" + #define REAL_NAND 0 #define EMU_SD 1 #define EMU_USB 2 @@ -70,10 +72,13 @@ class Nand void Set_NandPath(string path); void CreatePath(const char *path, ...); + void CreateTitleTMD(const char *path, dir_discHdr *hdr); s32 CreateConfig(const char *path); s32 Do_Region_Change(string id); - s32 DoNandDump(const char *source, const char *dest, bool dumpwgs, dump_callback_t i_dumper, void *i_data); - s32 CalcDumpSpace(const char *source, bool dumpwgs, dump_callback_t i_dumper, void *i_data); + s32 FlashToNAND(const char *source, const char *dest, dump_callback_t i_dumper, void *i_data); + s32 DoNandDump(const char *source, const char *dest, dump_callback_t i_dumper, void *i_data); + s32 CalcFlashSize(const char *source, dump_callback_t i_dumper, void *i_data); + s32 CalcDumpSpace(const char *source, dump_callback_t i_dumper, void *i_data); void ResetCounters(void); private: @@ -97,6 +102,7 @@ class Nand void __FATify(char *dst, const char *src); s32 __Unescaped2x(const char *path); s32 __FlashNandFile(const char *source, const char *dest); + s32 __FlashNandFolder(const char *source, const char *dest); s32 __DumpNandFile(const char *source, const char *dest); s32 __DumpNandFolder(const char *source, const char *dest); @@ -108,7 +114,6 @@ class Nand u32 FilesDone; u32 FoldersDone; bool Disabled; - bool n_dumpwgs; bool fake; bool showprogress; diff --git a/source/loader/savefile.c b/source/loader/savefile.c deleted file mode 100644 index ff30d032..00000000 --- a/source/loader/savefile.c +++ /dev/null @@ -1,92 +0,0 @@ -/**************************************************************************** - * Copyright (C) 2011 - * by Dimok - * heavily modified by Miigotu - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event will the authors be held liable for any - * damages arising from the use of this software. - * - * Permission is granted to anyone to use this software for any - * purpose, including commercial applications, and to alter it and - * redistribute it freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented; you - * must not claim that you wrote the original software. If you use - * this software in a product, an acknowledgment in the product - * documentation would be appreciated but is not required. - * - * 2. Altered source versions must be plainly marked as such, and - * must not be misrepresented as being the original software. - * - * 3. This notice may not be removed or altered from any source - * distribution. - ***************************************************************************/ - -#include -#include -#include -#include -#include - -#include "wbfs.h" -#include "utils.h" -#include "gecko.h" -#include "savefile.h" - -static void CreateNandPath(const char *path, ...) -{ - char *tmp = NULL; - va_list va; - va_start(va, path); - if((vasprintf(&tmp, path, va) >= 0) && tmp) - { - gprintf("Creating Nand Path: %s\n", tmp); - makedir(tmp); - } - va_end(va); - SAFE_FREE(tmp); -} - -void CreateTitleTMD(const char *path, struct dir_discHdr *hdr) -{ - wbfs_disc_t *disc = WBFS_OpenDisc((u8 *) &hdr->hdr.id, (char *)hdr->path); - if(!disc) - return; - - u8 *titleTMD = NULL; - u32 tmd_size = wbfs_extract_file(disc, (char *) "TMD", (void **)&titleTMD); - WBFS_CloseDisc(disc); - - if(!titleTMD) - return; - - u32 highTID = *(u32*)(titleTMD+0x18c); - u32 lowTID = *(u32*)(titleTMD+0x190); - - CreateNandPath("%s/title/%08x/%08x/data", path, highTID, lowTID); - CreateNandPath("%s/title/%08x/%08x/content", path, highTID, lowTID); - - char nandpath[ISFS_MAXPATH]; - snprintf(nandpath, sizeof(nandpath), "%s/title/%08x/%08x/content/title.tmd", path, highTID, lowTID); - - struct stat filestat; - if (stat(nandpath, &filestat) == 0) - { - SAFE_FREE(titleTMD); - gprintf("%s Exists!\n", nandpath); - return; - } - gprintf("Creating Game TMD: %s\n", nandpath); - - FILE *file = fopen(nandpath, "wb"); - if(file) - { - fwrite(titleTMD, 1, tmd_size, file); - gprintf("Written Game TMD to: %s\n", nandpath); - fclose(file); - } - else gprintf("Openning %s failed returning %i\n", nandpath, file); - - SAFE_FREE(titleTMD); -} \ No newline at end of file diff --git a/source/loader/savefile.h b/source/loader/savefile.h deleted file mode 100644 index 9f9bb9d6..00000000 --- a/source/loader/savefile.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef SAVEPATH_H_ -#define SAVEPATH_H_ - -#include "disc.h" - -#ifdef __cplusplus - extern "C" { -#endif /* __cplusplus */ - -void CreateTitleTMD(const char *path, struct dir_discHdr *hdr); - -#ifdef __cplusplus - } -#endif /* __cplusplus */ - -#endif \ No newline at end of file diff --git a/source/menu/menu.hpp b/source/menu/menu.hpp index d6a4c658..00a1b902 100644 --- a/source/menu/menu.hpp +++ b/source/menu/menu.hpp @@ -504,6 +504,10 @@ private: u32 m_gameSettingsLblIOS; u32 m_gameSettingsBtnIOSP; u32 m_gameSettingsBtnIOSM; + u32 m_gameSettingsLblExtractSave; + u32 m_gameSettingsBtnExtractSave; + u32 m_gameSettingsLblFlashSave; + u32 m_gameSettingsBtnFlashSave; // System Menu u32 m_systemBtnBack; u32 m_systemLblTitle; @@ -956,6 +960,7 @@ private: int _NandEmuCfg(void); int _AutoCreateNand(void); int _AutoExtractSave(string gameId); + int _FlashSave(string gameId); enum configPageChanges { CONFIG_PAGE_DEC = -1, @@ -1069,6 +1074,8 @@ private: wstringEx _optBoolToString(int b); void _stopSounds(void); static int _NandDumper(void *obj); + static int _NandFlasher(void *obj); + bool _checkSave(string id, bool nand); static u32 _downloadCheatFileAsync(void *obj); @@ -1098,7 +1105,6 @@ private: static const SOption _vidModePatch[4]; static const SOption _hooktype[8]; static const SOption _exitTo[6]; - static const SOption _DumpMode[4]; static map _installed_cios; typedef map::iterator CIOSItr; static int _version[9]; diff --git a/source/menu/menu_config_game.cpp b/source/menu/menu_config_game.cpp index 058aa27f..b2353598 100644 --- a/source/menu/menu_config_game.cpp +++ b/source/menu/menu_config_game.cpp @@ -12,7 +12,7 @@ static inline int loopNum(int i, int s) return i < 0 ? (s - (-i % s)) % s : i % s; } -u32 g_numGCfPages = 4; +u32 g_numGCfPages = 5; void CMenu::_hideGameSettings(bool instant) { @@ -85,6 +85,10 @@ void CMenu::_hideGameSettings(bool instant) m_btnMgr.hide(m_gameSettingsLblIOS, instant); m_btnMgr.hide(m_gameSettingsBtnIOSP, instant); m_btnMgr.hide(m_gameSettingsBtnIOSM, instant); + m_btnMgr.hide(m_gameSettingsLblExtractSave, instant); + m_btnMgr.hide(m_gameSettingsBtnExtractSave, instant); + m_btnMgr.hide(m_gameSettingsLblFlashSave, instant); + m_btnMgr.hide(m_gameSettingsBtnFlashSave, instant); for (u32 i = 0; i < ARRAY_SIZE(m_gameSettingsLblUser); ++i) if (m_gameSettingsLblUser[i] != -1u) @@ -118,7 +122,12 @@ void CMenu::_showGameSettings(void) m_btnMgr.show(m_gameSettingsBtnBack); m_btnMgr.show(m_gameSettingsLblTitle); if(m_cf.getHdr()->hdr.gc_magic != 0xc2339f3d) - g_numGCfPages = 4; + { + if(m_current_view == COVERFLOW_USB && _checkSave(string((const char *)m_cf.getHdr()->hdr.id), false)) + g_numGCfPages = 5; + else + g_numGCfPages = 4; + } else { if(m_new_dml) @@ -247,14 +256,14 @@ void CMenu::_showGameSettings(void) m_btnMgr.show(m_gameSettingsBtnVipatch); m_btnMgr.show(m_gameSettingsLblCountryPatch); - m_btnMgr.show(m_gameSettingsBtnCountryPatch); - - if(m_current_view == COVERFLOW_USB) + m_btnMgr.show(m_gameSettingsBtnCountryPatch); + + if (m_current_view != COVERFLOW_HOMEBREW) { - m_btnMgr.show(m_gameSettingsLblEmulationVal); - m_btnMgr.show(m_gameSettingsLblEmulation); - m_btnMgr.show(m_gameSettingsBtnEmulationP); - m_btnMgr.show(m_gameSettingsBtnEmulationM); + m_btnMgr.show(m_gameSettingsLblAspectRatio); + m_btnMgr.show(m_gameSettingsLblAspectRatioVal); + m_btnMgr.show(m_gameSettingsBtnAspectRatioP); + m_btnMgr.show(m_gameSettingsBtnAspectRatioM); } } else @@ -284,11 +293,11 @@ void CMenu::_showGameSettings(void) m_btnMgr.hide(m_gameSettingsLblCountryPatch); m_btnMgr.hide(m_gameSettingsBtnCountryPatch); - - m_btnMgr.hide(m_gameSettingsLblEmulationVal); - m_btnMgr.hide(m_gameSettingsLblEmulation); - m_btnMgr.hide(m_gameSettingsBtnEmulationP); - m_btnMgr.hide(m_gameSettingsBtnEmulationM); + + m_btnMgr.hide(m_gameSettingsLblAspectRatio); + m_btnMgr.hide(m_gameSettingsLblAspectRatioVal); + m_btnMgr.hide(m_gameSettingsBtnAspectRatioP); + m_btnMgr.hide(m_gameSettingsBtnAspectRatioM); } else { @@ -305,6 +314,19 @@ void CMenu::_showGameSettings(void) } if (m_gameSettingsPage == 4) { + if (m_current_view == COVERFLOW_CHANNEL) + { + m_btnMgr.show(m_gameSettingsLblCustom); + m_btnMgr.show(m_gameSettingsBtnCustom); + } + + if(m_current_view == COVERFLOW_USB) + { + m_btnMgr.show(m_gameSettingsLblEmulationVal); + m_btnMgr.show(m_gameSettingsLblEmulation); + m_btnMgr.show(m_gameSettingsBtnEmulationP); + m_btnMgr.show(m_gameSettingsBtnEmulationM); + } m_btnMgr.show(m_gameSettingsLblGameIOS); m_btnMgr.show(m_gameSettingsLblIOS); m_btnMgr.show(m_gameSettingsBtnIOSP); @@ -314,36 +336,46 @@ void CMenu::_showGameSettings(void) { m_btnMgr.show(m_gameSettingsLblIOSreloadBlock); m_btnMgr.show(m_gameSettingsBtnIOSreloadBlock); - - m_btnMgr.show(m_gameSettingsLblAspectRatio); - m_btnMgr.show(m_gameSettingsLblAspectRatioVal); - m_btnMgr.show(m_gameSettingsBtnAspectRatioP); - m_btnMgr.show(m_gameSettingsBtnAspectRatioM); } - if (m_current_view == COVERFLOW_CHANNEL) + + if(m_current_view == COVERFLOW_USB && _checkSave(string((const char *)m_cf.getHdr()->hdr.id), true)) { - m_btnMgr.show(m_gameSettingsLblCustom); - m_btnMgr.show(m_gameSettingsBtnCustom); + m_btnMgr.show(m_gameSettingsLblExtractSave); + m_btnMgr.show(m_gameSettingsBtnExtractSave); } } else { + m_btnMgr.hide(m_gameSettingsLblCustom); + m_btnMgr.hide(m_gameSettingsBtnCustom); + + m_btnMgr.hide(m_gameSettingsLblEmulationVal); + m_btnMgr.hide(m_gameSettingsLblEmulation); + m_btnMgr.hide(m_gameSettingsBtnEmulationP); + m_btnMgr.hide(m_gameSettingsBtnEmulationM); + m_btnMgr.hide(m_gameSettingsLblGameIOS); m_btnMgr.hide(m_gameSettingsLblIOS); m_btnMgr.hide(m_gameSettingsBtnIOSP); m_btnMgr.hide(m_gameSettingsBtnIOSM); m_btnMgr.hide(m_gameSettingsLblIOSreloadBlock); - m_btnMgr.hide(m_gameSettingsBtnIOSreloadBlock); - - m_btnMgr.hide(m_gameSettingsLblAspectRatio); - m_btnMgr.hide(m_gameSettingsLblAspectRatioVal); - m_btnMgr.hide(m_gameSettingsBtnAspectRatioP); - m_btnMgr.hide(m_gameSettingsBtnAspectRatioM); + m_btnMgr.hide(m_gameSettingsBtnIOSreloadBlock); - m_btnMgr.hide(m_gameSettingsLblCustom); - m_btnMgr.hide(m_gameSettingsBtnCustom); + m_btnMgr.hide(m_gameSettingsLblExtractSave); + m_btnMgr.hide(m_gameSettingsBtnExtractSave); } + if (m_gameSettingsPage == 5) + { + m_btnMgr.show(m_gameSettingsLblFlashSave); + m_btnMgr.show(m_gameSettingsBtnFlashSave); + } + else + { + m_btnMgr.hide(m_gameSettingsLblFlashSave); + m_btnMgr.hide(m_gameSettingsBtnFlashSave); + } + u32 i = 0; for (i = 0; i < ARRAY_SIZE(m_gameSettingsLblUser); ++i) if (m_gameSettingsLblUser[i] != -1u) @@ -604,6 +636,20 @@ void CMenu::_gameSettings(void) _CategorySettings(true); _showGameSettings(); } + else if (m_btnMgr.selected(m_gameSettingsBtnExtractSave)) + { + _hideGameSettings(); + m_forceext = true; + _AutoExtractSave(id); + _showGameSettings(); + } + else if (m_btnMgr.selected(m_gameSettingsBtnFlashSave)) + { + _hideGameSettings(); + m_forceext = true; + _FlashSave(id); + _showGameSettings(); + } } else if ((WBTN_2_HELD && WBTN_1_PRESSED) || (WBTN_1_HELD && WBTN_2_PRESSED)) { @@ -673,22 +719,22 @@ void CMenu::_initGameSettingsMenu(CMenu::SThemeData &theme) m_gameSettingsBtnCheat = _addButton(theme, "GAME_SETTINGS/CHEAT_BTN", theme.btnFont, L"", 330, 310, 270, 56, theme.btnFontColor); // Page 3 - m_gameSettingsLblCountryPatch = _addLabel(theme, "GAME_SETTINGS/COUNTRY_PATCH", theme.lblFont, L"", 40, 130, 340, 56, theme.lblFontColor, FTGX_JUSTIFY_LEFT | FTGX_ALIGN_MIDDLE); - m_gameSettingsBtnCountryPatch = _addButton(theme, "GAME_SETTINGS/COUNTRY_PATCH_BTN", theme.btnFont, L"", 380, 130, 220, 56, theme.btnFontColor); + m_gameSettingsLblCountryPatch = _addLabel(theme, "GAME_SETTINGS/COUNTRY_PATCH", theme.lblFont, L"", 40, 130, 290, 56, theme.lblFontColor, FTGX_JUSTIFY_LEFT | FTGX_ALIGN_MIDDLE); + m_gameSettingsBtnCountryPatch = _addButton(theme, "GAME_SETTINGS/COUNTRY_PATCH_BTN", theme.btnFont, L"", 330, 130, 270, 56, theme.btnFontColor); - m_gameSettingsLblVipatch = _addLabel(theme, "GAME_SETTINGS/VIPATCH", theme.lblFont, L"", 40, 190, 340, 56, theme.lblFontColor, FTGX_JUSTIFY_LEFT | FTGX_ALIGN_MIDDLE); - m_gameSettingsBtnVipatch = _addButton(theme, "GAME_SETTINGS/VIPATCH_BTN", theme.btnFont, L"", 380, 190, 220, 56, theme.btnFontColor); + m_gameSettingsLblVipatch = _addLabel(theme, "GAME_SETTINGS/VIPATCH", theme.lblFont, L"", 40, 190, 290, 56, theme.lblFontColor, FTGX_JUSTIFY_LEFT | FTGX_ALIGN_MIDDLE); + m_gameSettingsBtnVipatch = _addButton(theme, "GAME_SETTINGS/VIPATCH_BTN", theme.btnFont, L"", 330, 190, 270, 56, theme.btnFontColor); m_gameSettingsLblPatchVidModes = _addLabel(theme, "GAME_SETTINGS/PATCH_VIDEO_MODE", theme.lblFont, L"", 40, 250, 290, 56, theme.lblFontColor, FTGX_JUSTIFY_LEFT | FTGX_ALIGN_MIDDLE); - m_gameSettingsLblPatchVidModesVal = _addLabel(theme, "GAME_SETTINGS/PATCH_VIDEO_MODE_BTN", theme.btnFont, L"", 436, 250, 108, 56, theme.btnFontColor, FTGX_JUSTIFY_CENTER | FTGX_ALIGN_MIDDLE, theme.btnTexC); - m_gameSettingsBtnPatchVidModesM = _addPicButton(theme, "GAME_SETTINGS/PATCH_VIDEO_MODE_MINUS", theme.btnTexMinus, theme.btnTexMinusS, 380, 250, 56, 56); + m_gameSettingsLblPatchVidModesVal = _addLabel(theme, "GAME_SETTINGS/PATCH_VIDEO_MODE_BTN", theme.btnFont, L"", 386, 250, 158, 56, theme.btnFontColor, FTGX_JUSTIFY_CENTER | FTGX_ALIGN_MIDDLE, theme.btnTexC); + m_gameSettingsBtnPatchVidModesM = _addPicButton(theme, "GAME_SETTINGS/PATCH_VIDEO_MODE_MINUS", theme.btnTexMinus, theme.btnTexMinusS, 330, 250, 56, 56); m_gameSettingsBtnPatchVidModesP = _addPicButton(theme, "GAME_SETTINGS/PATCH_VIDEO_MODE_PLUS", theme.btnTexPlus, theme.btnTexPlusS, 544, 250, 56, 56); - m_gameSettingsLblEmulation = _addLabel(theme, "GAME_SETTINGS/EMU_SAVE", theme.lblFont, L"", 40, 310, 290, 56, theme.lblFontColor, FTGX_JUSTIFY_LEFT | FTGX_ALIGN_MIDDLE); - m_gameSettingsLblEmulationVal = _addLabel(theme, "GAME_SETTINGS/EMU_SAVE_BTN", theme.btnFont, L"", 436, 310, 108, 56, theme.btnFontColor, FTGX_JUSTIFY_CENTER | FTGX_ALIGN_MIDDLE, theme.btnTexC); - m_gameSettingsBtnEmulationM = _addPicButton(theme, "GAME_SETTINGS/EMU_SAVE_MINUS", theme.btnTexMinus, theme.btnTexMinusS, 380, 310, 56, 56); - m_gameSettingsBtnEmulationP = _addPicButton(theme, "GAME_SETTINGS/EMU_SAVE_PLUS", theme.btnTexPlus, theme.btnTexPlusS, 544, 310, 56, 56); - + m_gameSettingsLblAspectRatio = _addLabel(theme, "GAME_SETTINGS/ASPECT_RATIO", theme.lblFont, L"", 40, 310, 290, 56, theme.lblFontColor, FTGX_JUSTIFY_LEFT | FTGX_ALIGN_MIDDLE); + m_gameSettingsLblAspectRatioVal = _addLabel(theme, "GAME_SETTINGS/ASPECT_RATIO_BTN", theme.btnFont, L"", 386, 310, 158, 56, theme.btnFontColor, FTGX_JUSTIFY_CENTER | FTGX_ALIGN_MIDDLE, theme.btnTexC); + m_gameSettingsBtnAspectRatioM = _addPicButton(theme, "GAME_SETTINGS/ASPECT_RATIO_MINUS", theme.btnTexMinus, theme.btnTexMinusS, 330, 310, 56, 56); + m_gameSettingsBtnAspectRatioP = _addPicButton(theme, "GAME_SETTINGS/ASPECT_RATIO_PLUS", theme.btnTexPlus, theme.btnTexPlusS, 544, 310, 56, 56); + //DML Page 3 m_gameSettingsLblNMM = _addLabel(theme, "GAME_SETTINGS/DML_NMM", theme.lblFont, L"", 40, 130, 290, 56, theme.lblFontColor, FTGX_JUSTIFY_LEFT | FTGX_ALIGN_MIDDLE); m_gameSettingsLblNMM_Val = _addLabel(theme, "GAME_SETTINGS/DML_NMM_BTN", theme.btnFont, L"", 386, 130, 158, 56, theme.btnFontColor, FTGX_JUSTIFY_CENTER | FTGX_ALIGN_MIDDLE, theme.btnTexC); @@ -701,22 +747,30 @@ void CMenu::_initGameSettingsMenu(CMenu::SThemeData &theme) m_gameSettingsBtnNoDVD_P = _addPicButton(theme, "GAME_SETTINGS/NO_DVD_PATCH_PLUS", theme.btnTexPlus, theme.btnTexPlusS, 544, 190, 56, 56); //Page 4 - m_gameSettingsLblGameIOS = _addLabel(theme, "GAME_SETTINGS/IOS", theme.lblFont, L"", 40, 130, 340, 56, theme.lblFontColor, FTGX_JUSTIFY_LEFT | FTGX_ALIGN_MIDDLE); - m_gameSettingsLblIOS = _addLabel(theme, "GAME_SETTINGS/IOS_BTN", theme.btnFont, L"", 406, 130, 138, 56, theme.btnFontColor, FTGX_JUSTIFY_CENTER | FTGX_ALIGN_MIDDLE, theme.btnTexC); - m_gameSettingsBtnIOSM = _addPicButton(theme, "GAME_SETTINGS/IOS_MINUS", theme.btnTexMinus, theme.btnTexMinusS, 350, 130, 56, 56); - m_gameSettingsBtnIOSP = _addPicButton(theme, "GAME_SETTINGS/IOS_PLUS", theme.btnTexPlus, theme.btnTexPlusS, 544, 130, 56, 56); - - m_gameSettingsLblIOSreloadBlock = _addLabel(theme, "GAME_SETTINGS/IOS_RELOAD_BLOCK", theme.lblFont, L"", 40, 190, 290, 56, theme.lblFontColor, FTGX_JUSTIFY_LEFT | FTGX_ALIGN_MIDDLE); - m_gameSettingsBtnIOSreloadBlock = _addButton(theme, "GAME_SETTINGS/IOS_RELOAD_BLOCK_BTN", theme.btnFont, L"", 330, 190, 270, 56, theme.btnFontColor); - - m_gameSettingsLblAspectRatio = _addLabel(theme, "GAME_SETTINGS/ASPECT_RATIO", theme.lblFont, L"", 40, 250, 290, 56, theme.lblFontColor, FTGX_JUSTIFY_LEFT | FTGX_ALIGN_MIDDLE); - m_gameSettingsLblAspectRatioVal = _addLabel(theme, "GAME_SETTINGS/ASPECT_RATIO_BTN", theme.btnFont, L"", 402, 250, 146, 56, theme.btnFontColor, FTGX_JUSTIFY_CENTER | FTGX_ALIGN_MIDDLE, theme.btnTexC); - m_gameSettingsBtnAspectRatioP = _addPicButton(theme, "GAME_SETTINGS/ASPECT_RATIO_PLUS", theme.btnTexPlus, theme.btnTexPlusS, 548, 250, 52, 56); - m_gameSettingsBtnAspectRatioM = _addPicButton(theme, "GAME_SETTINGS/ASPECT_RATIO_MINUS", theme.btnTexMinus, theme.btnTexMinusS, 350, 250, 52, 56); + m_gameSettingsLblCustom = _addLabel(theme, "GAME_SETTINGS/CUSTOM", theme.lblFont, L"", 40, 130, 340, 56, theme.lblFontColor, FTGX_JUSTIFY_LEFT | FTGX_ALIGN_MIDDLE); + m_gameSettingsBtnCustom = _addButton(theme, "GAME_SETTINGS/CUSTOM_BTN", theme.btnFont, L"", 330, 130, 240, 56, theme.btnFontColor); - m_gameSettingsLblCustom = _addLabel(theme, "GAME_SETTINGS/CUSTOM", theme.lblFont, L"", 40, 310, 340, 56, theme.lblFontColor, FTGX_JUSTIFY_LEFT | FTGX_ALIGN_MIDDLE); - m_gameSettingsBtnCustom = _addButton(theme, "GAME_SETTINGS/CUSTOM_BTN", theme.btnFont, L"", 350, 310, 240, 56, theme.btnFontColor); + m_gameSettingsLblEmulation = _addLabel(theme, "GAME_SETTINGS/EMU_SAVE", theme.lblFont, L"", 40, 130, 290, 56, theme.lblFontColor, FTGX_JUSTIFY_LEFT | FTGX_ALIGN_MIDDLE); + m_gameSettingsLblEmulationVal = _addLabel(theme, "GAME_SETTINGS/EMU_SAVE_BTN", theme.btnFont, L"", 386, 130, 158, 56, theme.btnFontColor, FTGX_JUSTIFY_CENTER | FTGX_ALIGN_MIDDLE, theme.btnTexC); + m_gameSettingsBtnEmulationM = _addPicButton(theme, "GAME_SETTINGS/EMU_SAVE_MINUS", theme.btnTexMinus, theme.btnTexMinusS, 330, 130, 56, 56); + m_gameSettingsBtnEmulationP = _addPicButton(theme, "GAME_SETTINGS/EMU_SAVE_PLUS", theme.btnTexPlus, theme.btnTexPlusS, 544, 130, 56, 56); + + m_gameSettingsLblGameIOS = _addLabel(theme, "GAME_SETTINGS/IOS", theme.lblFont, L"", 40, 190, 340, 56, theme.lblFontColor, FTGX_JUSTIFY_LEFT | FTGX_ALIGN_MIDDLE); + m_gameSettingsLblIOS = _addLabel(theme, "GAME_SETTINGS/IOS_BTN", theme.btnFont, L"", 386, 190, 158, 56, theme.btnFontColor, FTGX_JUSTIFY_CENTER | FTGX_ALIGN_MIDDLE, theme.btnTexC); + m_gameSettingsBtnIOSM = _addPicButton(theme, "GAME_SETTINGS/IOS_MINUS", theme.btnTexMinus, theme.btnTexMinusS, 330, 190, 56, 56); + m_gameSettingsBtnIOSP = _addPicButton(theme, "GAME_SETTINGS/IOS_PLUS", theme.btnTexPlus, theme.btnTexPlusS, 544, 190, 56, 56); + m_gameSettingsLblIOSreloadBlock = _addLabel(theme, "GAME_SETTINGS/IOS_RELOAD_BLOCK", theme.lblFont, L"", 40, 250, 290, 56, theme.lblFontColor, FTGX_JUSTIFY_LEFT | FTGX_ALIGN_MIDDLE); + m_gameSettingsBtnIOSreloadBlock = _addButton(theme, "GAME_SETTINGS/IOS_RELOAD_BLOCK_BTN", theme.btnFont, L"", 330, 250, 270, 56, theme.btnFontColor); + + m_gameSettingsLblExtractSave = _addLabel(theme, "GAME_SETTINGS/EXTRACT_SAVE", theme.lblFont, L"", 40, 310, 290, 56, theme.lblFontColor, FTGX_JUSTIFY_LEFT | FTGX_ALIGN_MIDDLE); + m_gameSettingsBtnExtractSave = _addButton(theme, "GAME_SETTINGS/EXTRACT_SAVE_BTN", theme.btnFont, L"", 330, 310, 270, 56, theme.btnFontColor); + + //Page 5 + m_gameSettingsLblFlashSave = _addLabel(theme, "GAME_SETTINGS/FLASH_SAVE", theme.lblFont, L"", 40, 130, 290, 56, theme.lblFontColor, FTGX_JUSTIFY_LEFT | FTGX_ALIGN_MIDDLE); + m_gameSettingsBtnFlashSave = _addButton(theme, "GAME_SETTINGS/FLASH_SAVE_BTN", theme.btnFont, L"", 330, 130, 270, 56, theme.btnFontColor); + + //Footer m_gameSettingsLblPage = _addLabel(theme, "GAME_SETTINGS/PAGE_BTN", theme.btnFont, L"", 76, 400, 80, 56, theme.btnFontColor, FTGX_JUSTIFY_CENTER | FTGX_ALIGN_MIDDLE, theme.btnTexC); m_gameSettingsBtnPageM = _addPicButton(theme, "GAME_SETTINGS/PAGE_MINUS", theme.btnTexMinus, theme.btnTexMinusS, 20, 400, 56, 56); m_gameSettingsBtnPageP = _addPicButton(theme, "GAME_SETTINGS/PAGE_PLUS", theme.btnTexPlus, theme.btnTexPlusS, 156, 400, 56, 56); @@ -789,6 +843,10 @@ void CMenu::_initGameSettingsMenu(CMenu::SThemeData &theme) _setHideAnim(m_gameSettingsLblDebuggerV, "GAME_SETTINGS/GAME_DEBUGGER_BTN", 200, 0, 1.f, 0.f); _setHideAnim(m_gameSettingsBtnDebuggerM, "GAME_SETTINGS/GAME_DEBUGGER_MINUS", 200, 0, 1.f, 0.f); _setHideAnim(m_gameSettingsBtnDebuggerP, "GAME_SETTINGS/GAME_DEBUGGER_PLUS", 200, 0, 1.f, 0.f); + _setHideAnim(m_gameSettingsLblExtractSave, "GAME_SETTINGS/EXTRACT_SAVE", -200, 0, 1.f, 0.f); + _setHideAnim(m_gameSettingsBtnExtractSave, "GAME_SETTINGS/EXTRACT_SAVE_BTN", 200, 0, 1.f, 0.f); + _setHideAnim(m_gameSettingsLblFlashSave, "GAME_SETTINGS/FLASH_SAVE", -200, 0, 1.f, 0.f); + _setHideAnim(m_gameSettingsBtnFlashSave, "GAME_SETTINGS/FLASH_SAVE_BTN", 200, 0, 1.f, 0.f); //Categories _setHideAnim(m_gameSettingsBtnCategoryMain, "GAME_SETTINGS/CAT_MAIN_BTN", 200, 0, 1.f, 0.f); _setHideAnim(m_gameSettingsLblCategoryMain, "GAME_SETTINGS/CAT_MAIN", -200, 0, 1.f, 0.f); @@ -824,4 +882,8 @@ void CMenu::_textGameSettings(void) m_btnMgr.setText(m_gameSettingsLblNMM, _t("cfgg28", L"NMM")); m_btnMgr.setText(m_gameSettingsLblNoDVD, _t("cfgg29", L"No DVD Patch")); m_btnMgr.setText(m_gameSettingsLblCustom, _t("custom", L"Custom")); + m_btnMgr.setText(m_gameSettingsLblExtractSave, _t("cfgg30", L"Extract Save from NAND")); + m_btnMgr.setText(m_gameSettingsBtnExtractSave, _t("cfgg31", L"Extract")); + m_btnMgr.setText(m_gameSettingsLblFlashSave, _t("cfgg32", L"Flash Save to NAND")); + m_btnMgr.setText(m_gameSettingsBtnFlashSave, _t("cfgg33", L"Flash")); } diff --git a/source/menu/menu_game.cpp b/source/menu/menu_game.cpp index 8a0d2c99..04d839a4 100644 --- a/source/menu/menu_game.cpp +++ b/source/menu/menu_game.cpp @@ -14,7 +14,6 @@ #include "network/gcard.h" #include "DeviceHandler.hpp" #include "loader/wbfs.h" -#include "savefile.h" #include "wip.h" #include "channel_launcher.h" #include "devicemounter/sdhc.h" @@ -213,13 +212,6 @@ const CMenu::SOption CMenu::_hooktype[8] = { 7 AXNextFrame Hook */ -const CMenu::SOption CMenu::_DumpMode[4] = { - { "DumpNAll", L"Nand All" }, - { "DumpNMss", L"Nand Missing" }, - { "DumpLAll", L"List All" }, - { "DumpLMss", L"List Missing" }, -}; - map CMenu::_installed_cios; u8 banner_title[84]; @@ -1151,7 +1143,7 @@ void CMenu::_launchGame(dir_discHdr *hdr, bool dvd) m_forceext = false; _hideWaitMessage(); if(!_AutoExtractSave(id)) - CreateTitleTMD(basepath, hdr); + Nand::Instance()->CreateTitleTMD(basepath, hdr); _showWaitMessage(); } } diff --git a/source/menu/menu_nandemu.cpp b/source/menu/menu_nandemu.cpp index a1fe02f9..748edca3 100644 --- a/source/menu/menu_nandemu.cpp +++ b/source/menu/menu_nandemu.cpp @@ -13,12 +13,38 @@ static inline int loopNum(int i, int s) return i < 0 ? (s - (-i % s)) % s : i % s; } + +bool CMenu::_checkSave(string id, bool nand) +{ + int savePath = id.c_str()[0] << 24 | id.c_str()[1] << 16 | id.c_str()[2] << 8 | id.c_str()[3]; + if(nand) + { + u32 temp = 0; + if(ISFS_ReadDir(sfmt("/title/00010000/%08x", savePath).c_str(), NULL, &temp) < 0) + if(ISFS_ReadDir(sfmt("/title/00010004/%08x", savePath).c_str(), NULL, &temp) < 0) + return false; + } + else + { + int emuPartition = m_cfg.getInt("GAMES", "savepartition", -1); + string emuPath = m_cfg.getString("GAMES", "savepath", ""); + if(emuPartition < 0 || emuPath.size() == 0) + return false; + + struct stat fstat; + if((stat(sfmt("%s:%s/title/00010000/%08x", DeviceName[emuPartition], emuPath.c_str(), savePath).c_str(), &fstat) != 0 ) + && (stat(sfmt("%s:%s/title/00010004/%08x", DeviceName[emuPartition], emuPath.c_str(), savePath).c_str(), &fstat) != 0)) + return false; + } + return true; +} + static bool _saveExists(const char *path) { DIR *d; d = opendir(path); if(!d) - { + { return false; } else @@ -28,17 +54,6 @@ static bool _saveExists(const char *path) } } -static bool _nandSaveExists(const char *npath) -{ - u32 temp = 0; - - s32 ret = ISFS_ReadDir(npath, NULL, &temp); - if(ret < 0) - return false; - - return true; -} - void CMenu::_enableNandEmu(bool fromconfig) { _cfNeedsUpdate(); @@ -255,10 +270,84 @@ int CMenu::_NandEmuCfg(void) return 0; } +int CMenu::_FlashSave(string gameId) +{ + int emuPartition = m_cfg.getInt("GAMES", "savepartition", m_cfg.getInt("NAND", "partition", 0)); + char basepath[MAX_FAT_PATH]; + snprintf(basepath, sizeof(basepath), "%s:%s", DeviceName[emuPartition], m_cfg.getString("GAMES", "savepath", m_cfg.getString("NAND", "path", "")).c_str()); + + if(!_checkSave(gameId, false)) + return 0; + + lwp_t thread = 0; + SetupInput(); + m_thrdStop = false; + m_thrdMessageAdded = false; + m_nandext = false; + + m_saveExtGameId = gameId; + + while(true) + { + _mainLoopCommon(false, m_thrdWorking); + if(m_forceext) + { + m_forceext = false; + m_btnMgr.hide(m_nandemuLblInit); + m_btnMgr.show(m_nandemuLblTitle); + m_btnMgr.show(m_nandfilePBar); + m_btnMgr.show(m_nandemuPBar); + m_btnMgr.show(m_nandfileLblMessage); + m_btnMgr.show(m_nandemuLblMessage); + m_btnMgr.show(m_nandfileLblDialog); + m_btnMgr.show(m_nandemuLblDialog); + m_btnMgr.setText(m_nandemuLblMessage, L""); + m_btnMgr.setText(m_nandfileLblMessage, L""); + m_btnMgr.setText(m_nandemuLblDialog, _t("cfgne11", L"Overall Progress:")); + m_btnMgr.setText(m_nandemuLblTitle, _t("cfgne28", L"Game Save Flasher")); + m_thrdStop = false; + m_thrdProgress = 0.f; + m_thrdWorking = true; + LWP_CreateThread(&thread, (void *(*)(void *))CMenu::_NandFlasher, (void *)this, 0, 32768, 40); + } + else if(BTN_A_PRESSED && (m_btnMgr.selected(m_nandemuBtnBack))) + { + m_cfg.save(); + _hideNandEmu(); + return 1; + } + + if(m_thrdMessageAdded) + { + LockMutex lock(m_mutex); + m_thrdMessageAdded = false; + if (!m_thrdMessage.empty()) + m_btnMgr.setText(m_nandfileLblDialog, m_thrdMessage); + m_btnMgr.setProgress(m_nandfilePBar, m_fileProgress); + m_btnMgr.setProgress(m_nandemuPBar, m_thrdProgress); + m_btnMgr.setText(m_nandfileLblMessage, wfmt(_fmt("fileprogress", L"%d / %dKB"), m_fileprog/0x400, m_filesize/0x400)); + m_btnMgr.setText(m_nandemuLblMessage, wfmt(_fmt("dumpprogress", L"%i%%"), (int)(m_thrdProgress*100.f))); + + if (!m_thrdWorking) + { + m_btnMgr.setText(m_nandfinLblDialog, wfmt(_fmt("cfgne29", L"Flashed: %d saves / %d files / %d folders"), m_nandexentry, m_filesdone, m_foldersdone)); + if(m_dumpsize/0x400 > 0x270f) + m_btnMgr.setText(m_nandemuLblDialog, wfmt(_fmt("cfgne16", L"Total size: %uMB (%d blocks)"), (m_dumpsize/0x100000), (m_dumpsize/0x8000)>>2)); + else + m_btnMgr.setText(m_nandemuLblDialog, wfmt(_fmt("cfgne17", L"Total size: %uKB (%d blocks)"), (m_dumpsize/0x400), (m_dumpsize/0x8000)>>2)); + + m_btnMgr.show(m_nandemuBtnBack); + m_btnMgr.show(m_nandfinLblDialog); + } + } + } + _hideNandEmu(); + return 0; +} + int CMenu::_AutoExtractSave(string gameId) { int emuPartition = m_cfg.getInt("GAMES", "savepartition", m_cfg.getInt("NAND", "partition", 0)); - int savePath = gameId.c_str()[0] << 24 | gameId.c_str()[1] << 16 | gameId.c_str()[2] << 8 | gameId.c_str()[3]; char basepath[MAX_FAT_PATH]; snprintf(basepath, sizeof(basepath), "%s:%s", DeviceName[emuPartition], m_cfg.getString("GAMES", "savepath", m_cfg.getString("NAND", "path", "")).c_str()); @@ -271,13 +360,10 @@ int CMenu::_AutoExtractSave(string gameId) Nand::Instance()->CreatePath("%s/ticket", basepath); Nand::Instance()->CreatePath("%s/tmp", basepath); - string npath = sfmt("/title/00010000/%08x", savePath); - string path = sfmt("%s/title/00010000/%08x", basepath, savePath); - - if(!_nandSaveExists(sfmt("/title/00010000/%08x", savePath).c_str()) && !_nandSaveExists(sfmt("/title/00010004/%08x", savePath).c_str())) - return 0; - - if(!m_forceext && (_saveExists(sfmt("%s/title/00010000/%08x", basepath, savePath).c_str()) || _saveExists(sfmt("%s/title/00010004/%08x", basepath, savePath).c_str()))) + if(!_checkSave(gameId, true)) + return 1; + + if(!m_forceext && _checkSave(gameId, false)) return 1; lwp_t thread = 0; @@ -324,11 +410,17 @@ int CMenu::_AutoExtractSave(string gameId) m_thrdWorking = true; LWP_CreateThread(&thread, (void *(*)(void *))CMenu::_NandDumper, (void *)this, 0, 32768, 40); } - if(BTN_A_PRESSED && (m_btnMgr.selected(m_nandemuBtnDisable))) + else if(BTN_A_PRESSED && (m_btnMgr.selected(m_nandemuBtnDisable))) { _hideNandEmu(); return 0; } + else if(BTN_A_PRESSED && (m_btnMgr.selected(m_nandemuBtnBack))) + { + m_cfg.save(); + _hideNandEmu(); + return 1; + } if(m_thrdMessageAdded) { @@ -349,8 +441,8 @@ int CMenu::_AutoExtractSave(string gameId) else m_btnMgr.setText(m_nandemuLblDialog, wfmt(_fmt("cfgne17", L"Total size: %uKB (%d blocks)"), (m_dumpsize/0x400), (m_dumpsize/0x8000)>>2)); - _hideNandEmu(); - return 1; + m_btnMgr.show(m_nandemuBtnBack); + m_btnMgr.show(m_nandfinLblDialog); } } } @@ -398,11 +490,17 @@ int CMenu::_AutoCreateNand(void) m_thrdWorking = true; LWP_CreateThread(&thread, (void *(*)(void *))CMenu::_NandDumper, (void *)this, 0, 32768, 40); } - if(BTN_A_PRESSED && (m_btnMgr.selected(m_nandemuBtnDisable))) + else if(BTN_A_PRESSED && (m_btnMgr.selected(m_nandemuBtnDisable))) { _hideNandEmu(); return 0; } + else if(BTN_A_PRESSED && (m_btnMgr.selected(m_nandemuBtnBack))) + { + m_cfg.save(); + _hideNandEmu(); + return 1; + } if(m_thrdMessageAdded) { @@ -423,8 +521,8 @@ int CMenu::_AutoCreateNand(void) else m_btnMgr.setText(m_nandemuLblDialog, wfmt(_fmt("cfgne17", L"Total size: %uKB (%d blocks)"), (m_dumpsize/0x400), (m_dumpsize/0x8000)>>2)); - _hideNandEmu(); - return 1; + m_btnMgr.show(m_nandemuBtnBack); + m_btnMgr.show(m_nandfinLblDialog); } } } @@ -432,6 +530,54 @@ int CMenu::_AutoCreateNand(void) return 0; } +int CMenu::_NandFlasher(void *obj) +{ + CMenu &m = *(CMenu *)obj; + string emuPath; + int emuPartition = -1; + char source[MAX_FAT_PATH]; + char dest[ISFS_MAXPATH]; + + if(m.m_current_view == COVERFLOW_CHANNEL) + { + emuPartition = m.m_cfg.getInt("NAND", "partition", 0); + emuPath = m.m_cfg.getString("NAND", "path", ""); + } + else if(m.m_current_view == COVERFLOW_USB) + { + emuPartition = m.m_cfg.getInt("GAMES", "savepartition", -1); + if(emuPartition == -1) + emuPartition = m.m_cfg.getInt("NAND", "partition", 0); + emuPath = m.m_cfg.getString("GAMES", "savepath", m.m_cfg.getString("NAND", "path", "")); + } + + int flashID = m.m_saveExtGameId.c_str()[0] << 24 | m.m_saveExtGameId.c_str()[1] << 16 | m.m_saveExtGameId.c_str()[2] << 8 | m.m_saveExtGameId.c_str()[3]; + + if(_saveExists(sfmt("%s:%s/title/00010000/%08x", DeviceName[emuPartition], emuPath.c_str(), flashID).c_str())) + { + snprintf(source, sizeof(source), "%s:%s/title/00010000/%08x", DeviceName[emuPartition], emuPath.c_str(), flashID); + snprintf(dest, sizeof(dest), "/title/00010000/%08x", flashID); + } + else if(_saveExists(sfmt("%s:%s/title/00010004/%08x", DeviceName[emuPartition], emuPath.c_str(), flashID).c_str())) + { + snprintf(source, sizeof(source), "%s:%s/title/00010004/%08x", DeviceName[emuPartition], emuPath.c_str(), flashID); + snprintf(dest, sizeof(dest), "/title/00010004/%08x", flashID); + } + Nand::Instance()->ResetCounters(); + m.m_nandexentry = 1; + m.m_dumpsize = Nand::Instance()->CalcFlashSize(source, CMenu::_ShowProgress, obj); + m.m_nandext = true; + Nand::Instance()->FlashToNAND(source, dest, CMenu::_ShowProgress, obj); + + m.m_thrdWorking = false; + LWP_MutexLock(m.m_mutex); + m.m_btnMgr.hide(m.m_nandfilePBar); + m.m_btnMgr.hide(m.m_nandfileLblMessage); + m._setDumpMsg(m._t("cfgne30", L"Flashing save files finished!"), 1.f, 1.f); + LWP_MutexUnlock(m.m_mutex); + return 0; +} + int CMenu::_NandDumper(void *obj) { CMenu &m = *(CMenu *)obj; @@ -517,9 +663,9 @@ int CMenu::_NandDumper(void *obj) if(m.m_fulldump) { - m.m_dumpsize = Nand::Instance()->CalcDumpSpace("/", true, CMenu::_ShowProgress, obj); + m.m_dumpsize = Nand::Instance()->CalcDumpSpace("/", CMenu::_ShowProgress, obj); m.m_nandext = true; - Nand::Instance()->DoNandDump("/", basepath, true, CMenu::_ShowProgress, obj); + Nand::Instance()->DoNandDump("/", basepath, CMenu::_ShowProgress, obj); } else { @@ -539,11 +685,9 @@ int CMenu::_NandDumper(void *obj) string id((const char *)m.m_gameList[i].hdr.id, 4); - int savePath = id.c_str()[0] << 24 | id.c_str()[1] << 16 | id.c_str()[2] << 8 | id.c_str()[3]; - - if(!missingOnly || (!_saveExists(sfmt("%s/title/00010000/%08x", basepath, savePath).c_str()) && !_saveExists(sfmt("%s/title/00010004/%08x", basepath, savePath).c_str()))) + if(!missingOnly || !m._checkSave(id, false)) { - if(_nandSaveExists(sfmt("/title/00010000/%08x", savePath).c_str()) || _nandSaveExists(sfmt("/title/00010004/%08x", savePath).c_str())) + if(m._checkSave(id, true)) { m.m_nandexentry++; saveList.push_back(id); @@ -552,28 +696,31 @@ int CMenu::_NandDumper(void *obj) } } else + { + m.m_nandexentry = 1; saveList.push_back(m.m_saveExtGameId); + } for(u32 i = 0; i < saveList.size() && !m.m_thrdStop; ++i) { char source[ISFS_MAXPATH]; int savePath = saveList[i].c_str()[0] << 24 | saveList[i].c_str()[1] << 16 | saveList[i].c_str()[2] << 8 | saveList[i].c_str()[3]; - snprintf(source, sizeof(source), "/title/00010000/%08x", savePath); - if(!_nandSaveExists(source)) - snprintf(source, sizeof(source), "/title/00010004/%08x", savePath); + snprintf(source, sizeof(source), "/title/00010000/%08x", savePath); + if(!m._checkSave(saveList[i], true)) + snprintf(source, sizeof(source), "/title/00010004/%08x", savePath); - m.m_dumpsize = Nand::Instance()->CalcDumpSpace(source, false, CMenu::_ShowProgress, obj); + m.m_dumpsize = Nand::Instance()->CalcDumpSpace(source, CMenu::_ShowProgress, obj); } for(u32 i = 0; i < saveList.size() && !m.m_thrdStop; ++i) { char source[ISFS_MAXPATH]; int savePath = saveList[i].c_str()[0] << 24 | saveList[i].c_str()[1] << 16 | saveList[i].c_str()[2] << 8 | saveList[i].c_str()[3]; snprintf(source, sizeof(source), "/title/00010000/%08x", savePath); - if(!_nandSaveExists(source)) + if(!m._checkSave(saveList[i], true)) snprintf(source, sizeof(source), "/title/00010004/%08x", savePath); m.m_nandext = true; - Nand::Instance()->DoNandDump(source, basepath, false, CMenu::_ShowProgress, obj); + Nand::Instance()->DoNandDump(source, basepath, CMenu::_ShowProgress, obj); } } diff --git a/wiiflow.pnproj b/wiiflow.pnproj index 0757ee64..c81f9f01 100644 --- a/wiiflow.pnproj +++ b/wiiflow.pnproj @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/wiiflow.pnps b/wiiflow.pnps index eba498cf..9780e385 100644 --- a/wiiflow.pnps +++ b/wiiflow.pnps @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file