WiiFlow_Lite/source/menu/menu_nandemu.cpp

1056 lines
40 KiB
C++
Raw Normal View History

#include <dirent.h>
#include <unistd.h>
#include <algorithm>
#include "menu.hpp"
#include "defines.h"
#include "lockMutex.hpp"
#include "channel/nand.hpp"
#include "loader/cios.h"
#include "loader/nk.h"
// NandEmulation menu
s16 m_nandemuLblTitle;
s16 m_nandemuBtnBack;
s16 m_nandemuLblPage;
s16 m_nandemuBtnPageM;
s16 m_nandemuBtnPageP;
s16 m_nandemuLblEmulationVal;
s16 m_nandemuLblEmulation;
s16 m_nandemuBtnEmulationM;
s16 m_nandemuBtnEmulationP;
s16 m_nandemuLblSaveDump;
s16 m_nandemuBtnAll;
s16 m_nandemuBtnMissing;
s16 m_nandemuLblNandDump;
s16 m_nandemuBtnNandDump;
s16 m_nandemuLblNandSelect;
s16 m_nandemuLblNandSelectVal;
s16 m_nandemuBtnNandSelectM;
s16 m_nandemuBtnNandSelectP;
s16 m_nandfileLblMessage;
s16 m_nandemuLblMessage;
s16 m_nandfileLblDialog;
s16 m_nandfinLblDialog;
s16 m_nandemuLblDialog;
s16 m_nandfilePBar;
s16 m_nandemuPBar;
s16 m_nandemuBtnExtract;
s16 m_nandemuBtnDisable;
s16 m_nandemuBtnPartition;
s16 m_nandemuLblInit;
s16 m_nandemuLblUser[4];
TexData m_nandemuBg;
int nandemuPage = 1;
bool m_nandext;
bool m_fulldump;
bool m_sgdump;
bool m_saveall;
static inline int loopNum(int i, int s)
{
return (i + s) % s;
}
static void listEmuNands(const char * path, vector<string> &emuNands)
{
DIR *d;
struct dirent *dir;
emuNands.clear();
bool def = true;
d = opendir(path);
if(d != 0)
{
while((dir = readdir(d)) != 0)
{
if(dir->d_name[0] == '.')
continue;
if(dir->d_type == DT_DIR)
{
emuNands.push_back(dir->d_name);
string filename = dir->d_name;
if(filename == "default")
def = false;
}
}
closedir(d);
}
if(def)
emuNands.push_back("default");
sort(emuNands.begin(), emuNands.end());
}
void CMenu::_validateEmuNand(void)
{
string emuNand;
int emuPart;
if(m_current_view == COVERFLOW_CHANNEL)
{
emuNand = m_cfg.getString(CHANNEL_DOMAIN, "current_emunand", "default");
emuPart = m_cfg.getInt(CHANNEL_DOMAIN, "partition", 0);
}
else
{
emuNand = m_cfg.getString(WII_DOMAIN, "current_save_emunand", m_cfg.getString(CHANNEL_DOMAIN, "current_emunand", "default"));
emuPart = m_cfg.getInt(WII_DOMAIN, "savepartition", m_cfg.getInt(CHANNEL_DOMAIN, "partition", 0));
}
if(!DeviceHandle.PartitionUsableForNandEmu(emuPart))
{
for(emuPart = SD; emuPart <= USB8; emuPart++)
{
if(DeviceHandle.PartitionUsableForNandEmu(emuPart))
{
if(m_current_view == COVERFLOW_CHANNEL)
m_cfg.setInt(CHANNEL_DOMAIN, "partition", emuPart);
else
m_cfg.setInt(WII_DOMAIN, "savepartition", emuPart);
break;
}
}
}
const char *tmpPath = fmt("/%s/%s", EMU_NANDS_DIR, emuNand.c_str());
if(!_TestEmuNand(emuPart, tmpPath, false))
{
if(m_current_view == COVERFLOW_CHANNEL)
m_cfg.setString(CHANNEL_DOMAIN, "current_emunand", "default");
else
m_cfg.setString(WII_DOMAIN, "current_save_emunand", "default");
}
}
static bool _saveExists(const char *path)
{
DIR *d = opendir(path);
if(!d)
return false;
else
{
closedir(d);
return true;
}
}
bool CMenu::_TestEmuNand(int epart, const char *path, bool indept)
{
char basepath[64];
char testpath[MAX_FAT_PATH];
snprintf(basepath, sizeof(basepath), "%s:%s", DeviceName[epart], path);
DIR *d = opendir(basepath);
if(!d)
return false;
else
closedir(d);
if(indept)
{
// Check Wiimotes && Region
snprintf(testpath, sizeof(testpath), "%s/shared2/sys/SYSCONF", basepath);
if(!fsop_FileExist(testpath))
return false;
snprintf(testpath, sizeof(testpath), "%s/title/00000001/00000002/data/setting.txt", basepath);
if(!fsop_FileExist(testpath))
return false;
// Check Mii's
snprintf(testpath, sizeof(testpath), "%s/shared2/menu/FaceLib/RFL_DB.dat", basepath);
if(!fsop_FileExist(testpath))
return false;
}
return true;
}
2012-12-22 23:37:11 +01:00
int CMenu::_FindEmuPart(string &emuPath, bool skipchecks)
{
int emuPart = -1;
const char *tmpPath = NULL;
if(m_current_view == COVERFLOW_CHANNEL)
{
emuPart = m_cfg.getInt(CHANNEL_DOMAIN, "partition", 0);
tmpPath = fmt("/%s/%s", EMU_NANDS_DIR, m_cfg.getString(CHANNEL_DOMAIN, "current_emunand", "default").c_str());
}
else if(m_current_view == COVERFLOW_WII)
{
emuPart = m_cfg.getInt(WII_DOMAIN, "savepartition", m_cfg.getInt(CHANNEL_DOMAIN, "partition", 0));
tmpPath = fmt("/%s/%s", EMU_NANDS_DIR, m_cfg.getString(WII_DOMAIN, "current_save_emunand", m_cfg.getString(CHANNEL_DOMAIN, "current_emunand", "default")).c_str());
}
if(!DeviceHandle.PartitionUsableForNandEmu(emuPart))
return -1;
else if((skipchecks || _TestEmuNand(emuPart, tmpPath, true)))
{
NandHandle.SetNANDEmu(emuPart);
NandHandle.SetPaths(tmpPath, DeviceName[emuPart]);
emuPath = tmpPath;
return emuPart;
}
return -2;
}
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(fmt("/title/00010000/%08x", savePath), NULL, &temp) < 0)
if(ISFS_ReadDir(fmt("/title/00010004/%08x", savePath), NULL, &temp) < 0)
return false;
}
else
{
int emuPartition = m_cfg.getInt(WII_DOMAIN, "savepartition", m_cfg.getInt(CHANNEL_DOMAIN, "partition", 0));
string emuPath = m_cfg.getString(WII_DOMAIN, "savepath", "");
if(emuPartition < 0 || emuPath.size() == 0)
return false;
struct stat fstat;
if((stat(fmt("%s:%s/title/00010000/%08x", DeviceName[emuPartition], emuPath.c_str(), savePath), &fstat) != 0 )
&& (stat(fmt("%s:%s/title/00010004/%08x", DeviceName[emuPartition], emuPath.c_str(), savePath), &fstat) != 0))
return false;
}
return true;
}
void CMenu::_setDumpMsg(const wstringEx &msg, float totprog, float fileprog)
{
if(m_thrdStop) return;
if(msg != L"...") m_thrdMessage = msg;
m_thrdMessageAdded = true;
m_thrdProgress = totprog;
m_fileProgress = fileprog;
}
void CMenu::_ShowProgress(int dumpstat, int dumpprog, int filesize, int fileprog, int files, int folders, const char *tmess, void *user_data)
{
CMenu &m = *(CMenu *)user_data;
m.m_progress = dumpprog == 0 ? 0.f : (float)dumpstat / (float)dumpprog;
m.m_fprogress = filesize == 0 ? 0.f : (float)fileprog / (float)filesize;
m.m_fileprog = fileprog;
m.m_filesize = filesize;
m.m_filesdone = files;
m.m_foldersdone = folders;
LWP_MutexLock(m.m_mutex);
if(m_nandext)
m._setDumpMsg(wfmt(m._fmt("cfgne9", L"Current file: %s"), tmess), m.m_progress, m.m_fprogress);
else
m._setDumpMsg(L"...", m.m_progress, m.m_fprogress);
LWP_MutexUnlock(m.m_mutex);
}
void CMenu::_hideNandEmu(bool instant)
{
m_btnMgr.hide(m_nandemuLblTitle, instant);
m_btnMgr.hide(m_nandemuBtnBack, instant);
m_btnMgr.hide(m_nandemuLblPage, instant);
m_btnMgr.hide(m_nandemuBtnPageM, instant);
m_btnMgr.hide(m_nandemuBtnPageP, instant);
m_btnMgr.hide(m_nandfilePBar, instant);
m_btnMgr.hide(m_nandemuPBar, instant);
m_btnMgr.hide(m_nandfileLblMessage, instant);
m_btnMgr.hide(m_nandemuLblMessage, instant);
m_btnMgr.hide(m_nandfileLblDialog, instant);
m_btnMgr.hide(m_nandemuLblDialog, instant);
m_btnMgr.hide(m_nandfinLblDialog, instant);
m_btnMgr.hide(m_nandemuLblEmulationVal, instant);
m_btnMgr.hide(m_nandemuLblEmulation, instant);
m_btnMgr.hide(m_nandemuBtnEmulationP, instant);
m_btnMgr.hide(m_nandemuBtnEmulationM, instant);
m_btnMgr.hide(m_nandemuLblSaveDump, instant);
m_btnMgr.hide(m_nandemuBtnAll, instant);
m_btnMgr.hide(m_nandemuBtnMissing, instant);
m_btnMgr.hide(m_nandemuLblNandDump, instant);
m_btnMgr.hide(m_nandemuBtnNandDump, instant);
m_btnMgr.hide(m_nandemuLblNandSelect, instant);
m_btnMgr.hide(m_nandemuLblNandSelectVal, instant);
m_btnMgr.hide(m_nandemuBtnNandSelectP, instant);
m_btnMgr.hide(m_nandemuBtnNandSelectM, instant);
m_btnMgr.hide(m_nandemuBtnExtract, instant);
m_btnMgr.hide(m_nandemuBtnPartition, instant);
m_btnMgr.hide(m_nandemuBtnDisable, instant);
m_btnMgr.hide(m_nandemuLblInit, instant);
for(u8 i = 0; i < ARRAY_SIZE(m_nandemuLblUser); ++i)
if(m_nandemuLblUser[i] != -1)
m_btnMgr.hide(m_nandemuLblUser[i], instant);
}
void CMenu::_showNandEmu(void)
{
_setBg(m_nandemuBg, m_nandemuBg);
m_btnMgr.setText(m_nandemuLblTitle, _t("cfgne10", L"NAND Emulation Settings"));
m_btnMgr.show(m_nandemuLblTitle);
m_btnMgr.show(m_nandemuBtnBack);
m_btnMgr.setText(m_nandemuLblPage, wfmt(L"%i / 2", nandemuPage));
m_btnMgr.show(m_nandemuLblPage);
m_btnMgr.show(m_nandemuBtnPageM);
m_btnMgr.show(m_nandemuBtnPageP);
if(nandemuPage == 1)
{
int i;
if(((m_current_view == COVERFLOW_CHANNEL && m_cfg.getBool(CHANNEL_DOMAIN, "emu_nand", false)) || m_current_view == COVERFLOW_WII))
{
m_btnMgr.show(m_nandemuLblEmulation);
m_btnMgr.show(m_nandemuLblEmulationVal);
m_btnMgr.show(m_nandemuBtnEmulationP);
m_btnMgr.show(m_nandemuBtnEmulationM);
}
m_btnMgr.show(m_nandemuLblSaveDump);
m_btnMgr.show(m_nandemuBtnAll);
m_btnMgr.show(m_nandemuBtnMissing);
m_btnMgr.show(m_nandemuLblNandDump);
m_btnMgr.show(m_nandemuBtnNandDump);
if(m_current_view == COVERFLOW_CHANNEL)
{
i = min(max(0, m_cfg.getInt(CHANNEL_DOMAIN, "emulation", 0)), (int)ARRAY_SIZE(CMenu::_NandEmu) - 1);
m_btnMgr.setText(m_nandemuLblEmulationVal, _t(CMenu::_NandEmu[i].id, CMenu::_NandEmu[i].text));
}
else if(m_current_view == COVERFLOW_WII)
{
i = min(max(0, m_cfg.getInt(WII_DOMAIN, "save_emulation", 0)), (int)ARRAY_SIZE(CMenu::_GlobalSaveEmu) - 1);
m_btnMgr.setText(m_nandemuLblEmulationVal, _t(CMenu::_GlobalSaveEmu[i].id, CMenu::_GlobalSaveEmu[i].text));
}
}
else //page 2
{
m_btnMgr.show(m_nandemuLblNandSelect);
m_btnMgr.show(m_nandemuLblNandSelectVal);
m_btnMgr.show(m_nandemuBtnNandSelectP);
m_btnMgr.show(m_nandemuBtnNandSelectM);
if(m_current_view == COVERFLOW_CHANNEL)
m_btnMgr.setText(m_nandemuLblNandSelectVal, m_cfg.getString(CHANNEL_DOMAIN, "current_emunand"));
else if(m_current_view == COVERFLOW_WII)
m_btnMgr.setText(m_nandemuLblNandSelectVal, m_cfg.getString(WII_DOMAIN, "current_save_emunand"));
}
for(u8 i = 0; i < ARRAY_SIZE(m_nandemuLblUser); ++i)
if(m_nandemuLblUser[i] != -1)
m_btnMgr.show(m_nandemuLblUser[i]);
}
int CMenu::_NandEmuCfg(void)
{
nandemuPage = 1;
vector<string> emuNands;
string prevEmuNand;
int emuPart;
if(m_current_view == COVERFLOW_CHANNEL)
{
prevEmuNand = m_cfg.getString(CHANNEL_DOMAIN, "current_emunand");
emuPart = m_cfg.getInt(CHANNEL_DOMAIN, "partition");
}
else
{
prevEmuNand = m_cfg.getString(WII_DOMAIN, "current_save_emunand");
emuPart = m_cfg.getInt(WII_DOMAIN, "savepartition");
}
listEmuNands(fmt("%s:/%s", DeviceName[emuPart], EMU_NANDS_DIR), emuNands);
int curEmuNand = 0;
for(u8 i = 0; i < emuNands.size(); ++i)
{
if(emuNands[i] == prevEmuNand)
{
curEmuNand = i;
break;
}
}
lwp_t thread = 0;
SetupInput();
_showNandEmu();
m_thrdStop = false;
m_thrdMessageAdded = false;
m_nandext = false;
2012-09-09 20:35:15 +02:00
while(!m_exit)
{
2012-09-09 20:35:15 +02:00
_mainLoopCommon();
if((BTN_MINUS_PRESSED || BTN_LEFT_PRESSED) || (BTN_A_PRESSED && m_btnMgr.selected(m_nandemuBtnPageM)))
{
m_btnMgr.hide(m_nandemuLblEmulationVal, true);
m_btnMgr.hide(m_nandemuLblEmulation, true);
m_btnMgr.hide(m_nandemuBtnEmulationP, true);
m_btnMgr.hide(m_nandemuBtnEmulationM, true);
m_btnMgr.hide(m_nandemuLblSaveDump, true);
m_btnMgr.hide(m_nandemuBtnAll, true);
m_btnMgr.hide(m_nandemuBtnMissing, true);
m_btnMgr.hide(m_nandemuLblNandDump, true);
m_btnMgr.hide(m_nandemuBtnNandDump, true);
m_btnMgr.hide(m_nandemuLblNandSelect, true);
m_btnMgr.hide(m_nandemuLblNandSelectVal, true);
m_btnMgr.hide(m_nandemuBtnNandSelectP, true);
m_btnMgr.hide(m_nandemuBtnNandSelectM, true);
nandemuPage = nandemuPage == 1 ? 2 : 1;
_showNandEmu();
}
else if((BTN_PLUS_PRESSED || BTN_RIGHT_PRESSED) || (BTN_A_PRESSED && m_btnMgr.selected(m_nandemuBtnPageP)))
{
m_btnMgr.hide(m_nandemuLblEmulationVal, true);
m_btnMgr.hide(m_nandemuLblEmulation, true);
m_btnMgr.hide(m_nandemuBtnEmulationP, true);
m_btnMgr.hide(m_nandemuBtnEmulationM, true);
m_btnMgr.hide(m_nandemuLblSaveDump, true);
m_btnMgr.hide(m_nandemuBtnAll, true);
m_btnMgr.hide(m_nandemuBtnMissing, true);
m_btnMgr.hide(m_nandemuLblNandDump, true);
m_btnMgr.hide(m_nandemuBtnNandDump, true);
m_btnMgr.hide(m_nandemuLblNandSelect, true);
m_btnMgr.hide(m_nandemuLblNandSelectVal, true);
m_btnMgr.hide(m_nandemuBtnNandSelectP, true);
m_btnMgr.hide(m_nandemuBtnNandSelectM, true);
nandemuPage = nandemuPage == 1 ? 2 : 1;
_showNandEmu();
}
else if((BTN_HOME_PRESSED || BTN_B_PRESSED) && !m_thrdWorking)
break;
else if(BTN_UP_PRESSED)
m_btnMgr.up();
else if(BTN_DOWN_PRESSED)
m_btnMgr.down();
else if (BTN_A_PRESSED && (m_btnMgr.selected(m_nandemuBtnEmulationP) || m_btnMgr.selected(m_nandemuBtnEmulationM)))
{
s8 direction = m_btnMgr.selected(m_nandemuBtnEmulationP) ? 1 : -1;
if(m_current_view == COVERFLOW_CHANNEL)
m_cfg.setInt(CHANNEL_DOMAIN, "emulation", (int)loopNum((u32)m_cfg.getInt(CHANNEL_DOMAIN, "emulation", 0) + direction, ARRAY_SIZE(CMenu::_NandEmu)));
else if(m_current_view == COVERFLOW_WII)
m_cfg.setInt(WII_DOMAIN, "save_emulation", (int)loopNum((u32)m_cfg.getInt(WII_DOMAIN, "save_emulation", 0) + direction, ARRAY_SIZE(CMenu::_GlobalSaveEmu)));
_showNandEmu();
}
else if(BTN_A_PRESSED && (m_btnMgr.selected(m_nandemuBtnNandDump) || m_btnMgr.selected(m_nandemuBtnAll) || m_btnMgr.selected(m_nandemuBtnMissing)))
{
m_fulldump = m_btnMgr.selected(m_nandemuBtnNandDump) ? true : false;
m_saveall = m_btnMgr.selected(m_nandemuBtnAll) ? true : false;
m_btnMgr.hide(m_nandemuBtnBack);
m_btnMgr.hide(m_nandemuLblEmulationVal);
m_btnMgr.hide(m_nandemuLblEmulation);
m_btnMgr.hide(m_nandemuBtnEmulationP);
m_btnMgr.hide(m_nandemuBtnEmulationM);
m_btnMgr.hide(m_nandemuLblSaveDump);
m_btnMgr.hide(m_nandemuBtnAll);
m_btnMgr.hide(m_nandemuBtnMissing);
m_btnMgr.hide(m_nandemuLblNandDump);
m_btnMgr.hide(m_nandemuBtnNandDump);
m_btnMgr.hide(m_nandemuLblPage);
m_btnMgr.hide(m_nandemuBtnPageM);
m_btnMgr.hide(m_nandemuBtnPageP);
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:"));
if(m_fulldump)
m_btnMgr.setText(m_nandemuLblTitle, _t("cfgne12", L"NAND Extractor"));
else
m_btnMgr.setText(m_nandemuLblTitle, _t("cfgne13", L"Game Save Extractor"));
m_thrdStop = false;
m_thrdProgress = 0.f;
m_thrdWorking = true;
LWP_CreateThread(&thread, (void *(*)(void *))CMenu::_NandDumper, (void *)this, 0, 32768, 40);
}
else if(BTN_A_PRESSED && (m_btnMgr.selected(m_nandemuBtnNandSelectP) || m_btnMgr.selected(m_nandemuBtnNandSelectM)))
{
s8 direction = m_btnMgr.selected(m_nandemuBtnNandSelectP) ? 1 : -1;
curEmuNand = loopNum(curEmuNand + direction, emuNands.size());
if(m_current_view == COVERFLOW_CHANNEL)
m_cfg.setString(CHANNEL_DOMAIN, "current_emunand", emuNands[curEmuNand]);
else
m_cfg.setString(WII_DOMAIN, "current_save_emunand", emuNands[curEmuNand]);
_showNandEmu();
}
else if(BTN_A_PRESSED && (m_btnMgr.selected(m_nandemuBtnBack)))
{
m_cfg.save();
break;
}
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)
{
if(m_sgdump)
m_btnMgr.setText(m_nandfinLblDialog, wfmt(_fmt("cfgne14", L"Extracted: %d saves / %d files / %d folders"), m_nandexentry, m_filesdone, m_foldersdone));
else
m_btnMgr.setText(m_nandfinLblDialog, wfmt(_fmt("cfgne15", L"Extracted: %d files / %d folders"), 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();
if(prevEmuNand != m_cfg.getString(CHANNEL_DOMAIN, "current_emunand") && m_current_view == COVERFLOW_CHANNEL)
{
m_cfg.setBool(CHANNEL_DOMAIN, "update_cache", true);
m_load_view = true;
}
return 0;
}
int CMenu::_FlashSave(string gameId)
{
int emuPartition = m_cfg.getInt(WII_DOMAIN, "savepartition", m_cfg.getInt(CHANNEL_DOMAIN, "partition", 0));
char basepath[MAX_FAT_PATH];
snprintf(basepath, sizeof(basepath), "%s:/%s/%s", DeviceName[emuPartition], EMU_NANDS_DIR, m_cfg.getString(WII_DOMAIN, "current_save_emunand", m_cfg.getString(CHANNEL_DOMAIN, "current_emunand", "default")).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;
2012-09-09 20:35:15 +02:00
while(!m_exit)
{
2012-09-09 20:35:15 +02:00
_mainLoopCommon();
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)
{
string emuPath;
2012-12-22 23:37:11 +01:00
int emuPartition = _FindEmuPart(emuPath, false);
if(emuPartition < 0)
2012-12-22 23:37:11 +01:00
emuPartition = _FindEmuPart(emuPath, true);
if(!_checkSave(gameId, true))//if save not on real nand
return 1;
if(!m_forceext && _checkSave(gameId, false))//if not force extract and save is already on emunand
return 1;
lwp_t thread = 0;
SetupInput();
m_thrdStop = false;
m_thrdMessageAdded = false;
m_nandext = false;
if(!m_forceext)
{
m_btnMgr.setText(m_nandemuBtnExtract, _t("cfgne24", L"Extract save"));
m_btnMgr.setText(m_nandemuBtnDisable, _t("cfgne25", L"Create new save"));
m_btnMgr.setText(m_nandemuLblInit, _t("cfgne26", L"A save file for this game was created on real NAND. Extract existing save file from real NAND or create new file for NAND Emulation?"));
m_btnMgr.show(m_nandemuBtnExtract);
m_btnMgr.show(m_nandemuBtnDisable);
m_btnMgr.show(m_nandemuLblInit);
}
m_saveExtGameId = gameId;
2012-09-09 20:35:15 +02:00
while(!m_exit)
{
2012-09-09 20:35:15 +02:00
_mainLoopCommon();
if((BTN_A_PRESSED && (m_btnMgr.selected(m_nandemuBtnExtract))) || m_forceext)
{
m_forceext = false;
m_fulldump = false;
m_btnMgr.hide(m_nandemuBtnExtract);
m_btnMgr.hide(m_nandemuBtnDisable);
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("cfgne13", L"Game Save Extractor"));
m_thrdStop = false;
m_thrdProgress = 0.f;
m_thrdWorking = true;
LWP_CreateThread(&thread, (void *(*)(void *))CMenu::_NandDumper, (void *)this, 0, 32768, 40);
}
else if(BTN_A_PRESSED && (m_btnMgr.selected(m_nandemuBtnDisable)))//create new save
{
char basepath[MAX_FAT_PATH];
snprintf(basepath, sizeof(basepath), "%s:%s", DeviceName[emuPartition], emuPath.c_str());
NandHandle.CreatePath("%s/import", basepath);
NandHandle.CreatePath("%s/meta", basepath);
NandHandle.CreatePath("%s/shared1", basepath);
NandHandle.CreatePath("%s/shared2", basepath);
NandHandle.CreatePath("%s/sys", basepath);
NandHandle.CreatePath("%s/title", basepath);
NandHandle.CreatePath("%s/ticket", basepath);
NandHandle.CreatePath("%s/tmp", basepath);
_hideNandEmu();
return 0;
}
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("cfgne14", L"Extracted: %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::_AutoCreateNand(void)
{
lwp_t thread = 0;
SetupInput();
m_thrdStop = false;
m_thrdMessageAdded = false;
m_nandext = false;
m_emuSaveNand = false;
bool changePart = false;
bool lock_part_change = false;
m_btnMgr.setText(m_nandemuBtnExtract, _t("cfgne5", L"Extract NAND"));
m_btnMgr.setText(m_nandemuBtnDisable, _t("cfgne22", L"Disable NAND Emulation"));
m_btnMgr.setText(m_nandemuBtnPartition, _t("cfgne31", L"Select Partition"));
//might add change nand button
//m_btnMgr.setText(m_nandemuLblInit, _t("cfgne23", L"Emu NAND not found. Try changing the partition to select the correct device/partition, click Extract to extract your NAND, or click disable to disable NAND Emulation."));
m_btnMgr.setText(m_nandemuLblInit, _t("cfgne23", L"Emu NAND not found. Try one of these options to fix the problem."));
m_btnMgr.show(m_nandemuBtnExtract);
m_btnMgr.show(m_nandemuBtnDisable);
m_btnMgr.show(m_nandemuBtnPartition);
m_btnMgr.show(m_nandemuLblInit);
2012-09-09 20:35:15 +02:00
while(!m_exit)
{
2012-09-09 20:35:15 +02:00
_mainLoopCommon();
if(BTN_A_PRESSED)
{
if(m_btnMgr.selected(m_nandemuBtnExtract))
{
lock_part_change = true;
m_fulldump = true;
m_btnMgr.hide(m_nandemuBtnExtract);
m_btnMgr.hide(m_nandemuBtnDisable);
m_btnMgr.hide(m_nandemuBtnPartition);
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("cfgne12", L"NAND Extractor"));
m_thrdStop = false;
m_thrdProgress = 0.f;
m_thrdWorking = true;
LWP_CreateThread(&thread, (void *(*)(void *))CMenu::_NandDumper, (void *)this, 0, 32768, 40);
}
else if(m_btnMgr.selected(m_nandemuBtnDisable))
{
_hideNandEmu();
return 0;
}
else if(m_btnMgr.selected(m_nandemuBtnPartition))
{
m_btnMgr.hide(m_nandemuBtnExtract);
m_btnMgr.hide(m_nandemuBtnDisable);
m_btnMgr.hide(m_nandemuBtnPartition);
m_btnMgr.hide(m_nandemuLblInit);
m_btnMgr.show(m_configLblPartitionName);
m_btnMgr.show(m_configLblPartition);
m_btnMgr.show(m_configBtnPartitionP);
m_btnMgr.show(m_configBtnPartitionM);
m_btnMgr.show(m_nandemuBtnBack);
changePart = true;
}
else if(m_btnMgr.selected(m_configBtnPartitionP) || m_btnMgr.selected(m_configBtnPartitionM))
{
s8 direction = m_btnMgr.selected(m_configBtnPartitionP) ? 1 : -1;
u8 limiter = 0;
do
{
currentPartition = loopNum(currentPartition + direction, 9);
limiter++;
}
while(limiter < 9 && !DeviceHandle.PartitionUsableForNandEmu(currentPartition));
//if limiter = 9 error
m_btnMgr.setText(m_configLblPartition, upperCase(DeviceName[currentPartition]));
}
else if(m_btnMgr.selected(m_nandemuBtnBack))
{
if(changePart)
{
m_btnMgr.hide(m_configLblPartitionName);
m_btnMgr.hide(m_configLblPartition);
m_btnMgr.hide(m_configBtnPartitionP);
m_btnMgr.hide(m_configBtnPartitionM);
m_btnMgr.hide(m_nandemuBtnBack);
if(m_current_view == COVERFLOW_WII)
m_cfg.setInt(WII_DOMAIN, "savepartition", currentPartition);
else
m_cfg.setInt(CHANNEL_DOMAIN, "partition", currentPartition);
return 1;
}
else
{
m_cfg.save();//why save?
_hideNandEmu();
return 1;
}
}
}
else if(BTN_B_HELD && BTN_MINUS_PRESSED && !lock_part_change)
{
_setPartition(1);
_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("cfgne15", L"Extracted: %d files / %d folders"), 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::_NandFlasher(void *obj)
{
CMenu &m = *(CMenu *)obj;
string emuPath;
char source[MAX_FAT_PATH];
char dest[ISFS_MAXPATH];
const char *SaveGameID = m.m_saveExtGameId.c_str();
2012-12-22 23:37:11 +01:00
int emuPartition = m._FindEmuPart(emuPath, false);
int flashID = SaveGameID[0] << 24 | SaveGameID[1] << 16 | SaveGameID[2] << 8 | SaveGameID[3];
if(_saveExists(fmt("%s:%s/title/00010000/%08x", DeviceName[emuPartition], emuPath.c_str(), flashID)))
{
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(fmt("%s:%s/title/00010004/%08x", DeviceName[emuPartition], emuPath.c_str(), flashID)))
{
snprintf(source, sizeof(source), "%s:%s/title/00010004/%08x", DeviceName[emuPartition], emuPath.c_str(), flashID);
snprintf(dest, sizeof(dest), "/title/00010004/%08x", flashID);
}
NandHandle.ResetCounters();
m.m_nandexentry = 1;
m.m_dumpsize = NandHandle.CalcFlashSize(source, _ShowProgress, obj);
m_nandext = true;
NandHandle.FlashToNAND(source, dest, _ShowProgress, obj);
m.m_thrdWorking = false;
LWP_MutexLock(m.m_mutex);
m_btnMgr.hide(m_nandfilePBar);
m_btnMgr.hide(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;
string emuPath;
int emuPartition = -1;
m_nandext = false;
m_sgdump = false;
m.m_dumpsize = 0;
m.m_filesdone = 0;
m.m_foldersdone = 0;
NandHandle.ResetCounters();
2012-12-22 23:37:11 +01:00
emuPartition = m._FindEmuPart(emuPath, true);
if(emuPartition < 0)
{
m.error(m._t("cfgne8", L"No valid FAT partition found for NAND Emulation!"));
//probably should set m.m_thrdWorking = false;
//and set bool error to true and then main thread will handle it
return 0;
}
char basepath[64];
snprintf(basepath, sizeof(basepath), "%s:%s", DeviceName[emuPartition], emuPath.c_str());
LWP_MutexLock(m.m_mutex);
m._setDumpMsg(m._t("cfgne27", L"Calculating space needed for extraction..."), 0.f, 0.f);
LWP_MutexUnlock(m.m_mutex);
if(m_fulldump)
{
m.m_dumpsize = NandHandle.CalcDumpSpace("/", CMenu::_ShowProgress, obj);
m_nandext = true;
NandHandle.DoNandDump("/", basepath, CMenu::_ShowProgress, obj);
}
else
{
bool missingOnly = !m_saveall;
vector<string> saveList;
m_sgdump = true;
if(m.m_saveExtGameId.empty())
{
m.m_nandexentry = 0;
saveList.reserve(m_gameList.size());
for(u32 i = 0; i < m_gameList.size() && !m.m_thrdStop; ++i)
{
LWP_MutexLock(m.m_mutex);
m._setDumpMsg(m._t("cfgne18", L"Listing game saves to extract..."), 0.f, 0.f);
LWP_MutexUnlock(m.m_mutex);
string id((const char *)m_gameList[i].id, 4);
if(!missingOnly || !m._checkSave(id, false))
{
if(m._checkSave(id, true))
{
m.m_nandexentry++;
saveList.push_back(id);
}
}
}
}
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(!m._checkSave(saveList[i], true))
snprintf(source, sizeof(source), "/title/00010004/%08x", savePath);
m.m_dumpsize = NandHandle.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(!m._checkSave(saveList[i], true))
snprintf(source, sizeof(source), "/title/00010004/%08x", savePath);
m_nandext = true;
NandHandle.DoNandDump(source, basepath, CMenu::_ShowProgress, obj);
}
}
m.m_thrdWorking = false;
LWP_MutexLock(m.m_mutex);
m_btnMgr.hide(m_nandfilePBar);
m_btnMgr.hide(m_nandfileLblMessage);
m._setDumpMsg(m._t("cfgne19", L"Extraction finished!"), 1.f, 1.f);
LWP_MutexUnlock(m.m_mutex);
return 0;
}
void CMenu::_initNandEmuMenu()
{
_addUserLabels(m_nandemuLblUser, ARRAY_SIZE(m_nandemuLblUser), "NANDEMU");
m_nandemuBg = _texture("NANDEMU/BG", "texture", theme.bg, false);
m_nandemuLblTitle = _addTitle("NANDEMU/TITLE", theme.titleFont, L"", 0, 10, 640, 60, theme.titleFontColor, FTGX_JUSTIFY_CENTER | FTGX_ALIGN_MIDDLE);
m_nandfileLblMessage = _addLabel("NANDEMU/FMESSAGE", theme.lblFont, L"", 40, 230, 560, 100, theme.lblFontColor, FTGX_JUSTIFY_CENTER | FTGX_ALIGN_TOP);
m_nandemuLblMessage = _addLabel("NANDEMU/MESSAGE", theme.lblFont, L"", 40, 350, 560, 100, theme.lblFontColor, FTGX_JUSTIFY_CENTER | FTGX_ALIGN_TOP);
m_nandfileLblDialog = _addLabel("NANDEMU/FDIALOG", theme.lblFont, L"", 40, 60, 560, 200, theme.lblFontColor, FTGX_JUSTIFY_LEFT | FTGX_ALIGN_MIDDLE);
m_nandfinLblDialog = _addLabel("NANDEMU/FINDIALOG", theme.lblFont, L"", 40, 120, 560, 200, theme.lblFontColor, FTGX_JUSTIFY_LEFT | FTGX_ALIGN_MIDDLE);
m_nandemuLblDialog = _addLabel("NANDEMU/DIALOG", theme.lblFont, L"", 40, 180, 560, 200, theme.lblFontColor, FTGX_JUSTIFY_LEFT | FTGX_ALIGN_MIDDLE);
m_nandfilePBar = _addProgressBar("NANDEMU/FILEPROGRESS_BAR", 40, 200, 560, 20);
m_nandemuPBar = _addProgressBar("NANDEMU/PROGRESS_BAR", 40, 200, 560, 20);
m_nandemuLblEmulation = _addLabel("NANDEMU/EMU_SAVE", theme.lblFont, L"", 20, 125, 385, 56, theme.lblFontColor, FTGX_JUSTIFY_LEFT | FTGX_ALIGN_MIDDLE);
m_nandemuLblEmulationVal = _addLabel("NANDEMU/EMU_SAVE_BTN_GLOBAL", theme.btnFont, L"", 468, 130, 104, 48, theme.btnFontColor, FTGX_JUSTIFY_CENTER | FTGX_ALIGN_MIDDLE, theme.btnTexC);
m_nandemuBtnEmulationM = _addPicButton("NANDEMU/EMU_SAVE_MINUS", theme.btnTexMinus, theme.btnTexMinusS, 420, 130, 48, 48);
m_nandemuBtnEmulationP = _addPicButton("NANDEMU/EMU_SAVE_PLUS", theme.btnTexPlus, theme.btnTexPlusS, 572, 130, 48, 48);
m_nandemuLblSaveDump = _addLabel("NANDEMU/SAVE_DUMP", theme.lblFont, L"", 20, 185, 385, 56, theme.lblFontColor, FTGX_JUSTIFY_LEFT | FTGX_ALIGN_MIDDLE);
m_nandemuBtnAll = _addButton("NANDEMU/ALL_BTN", theme.btnFont, L"", 420, 190, 200, 48, theme.btnFontColor);
m_nandemuBtnMissing = _addButton("NANDEMU/MISSING_BTN", theme.btnFont, L"", 420, 250, 200, 48, theme.btnFontColor);
m_nandemuLblNandDump = _addLabel("NANDEMU/NAND_DUMP", theme.lblFont, L"", 20, 305, 385, 56, theme.lblFontColor, FTGX_JUSTIFY_LEFT | FTGX_ALIGN_MIDDLE);
m_nandemuBtnNandDump = _addButton("NANDEMU/NAND_DUMP_BTN", theme.btnFont, L"", 420, 310, 200, 48, theme.btnFontColor);
m_nandemuLblNandSelect = _addLabel("NANDEMU/NAND_SELECT", theme.lblFont, L"", 20, 125, 385, 56, theme.lblFontColor, FTGX_JUSTIFY_LEFT | FTGX_ALIGN_MIDDLE);
m_nandemuLblNandSelectVal = _addLabel("NANDEMU/NAND_SELECT_BTN", theme.btnFont, L"", 468, 130, 104, 48, theme.btnFontColor, FTGX_JUSTIFY_CENTER | FTGX_ALIGN_MIDDLE, theme.btnTexC);
m_nandemuBtnNandSelectM = _addPicButton("NANDEMU/NAND_SELECT_MINUS", theme.btnTexMinus, theme.btnTexMinusS, 420, 130, 48, 48);
m_nandemuBtnNandSelectP = _addPicButton("NANDEMU/NAND_SELECT_PLUS", theme.btnTexPlus, theme.btnTexPlusS, 572, 130, 48, 48);
m_nandemuBtnBack = _addButton("NANDEMU/BACK_BTN", theme.btnFont, L"", 420, 400, 200, 48, theme.btnFontColor);
m_nandemuLblPage = _addLabel("NANDEMU/PAGE_BTN", theme.btnFont, L"", 68, 400, 104, 48, theme.btnFontColor, FTGX_JUSTIFY_CENTER | FTGX_ALIGN_MIDDLE, theme.btnTexC);
m_nandemuBtnPageM = _addPicButton("NANDEMU/PAGE_MINUS", theme.btnTexMinus, theme.btnTexMinusS, 20, 400, 48, 48);
m_nandemuBtnPageP = _addPicButton("NANDEMU/PAGE_PLUS", theme.btnTexPlus, theme.btnTexPlusS, 172, 400, 48, 48);
m_nandemuBtnExtract = _addButton("NANDEMU/EXTRACT", theme.titleFont, L"", 72, 180, 496, 48, theme.titleFontColor);
m_nandemuBtnDisable = _addButton("NANDEMU/DISABLE", theme.titleFont, L"", 72, 270, 496, 48, theme.titleFontColor);
m_nandemuBtnPartition = _addButton("NANDEMU/PARTITION", theme.titleFont, L"", 72, 360, 496, 48, theme.titleFontColor);
m_nandemuLblInit = _addLabel("NANDEMU/INIT", theme.lblFont, L"", 40, 40, 560, 140, theme.lblFontColor, FTGX_JUSTIFY_LEFT | FTGX_ALIGN_MIDDLE);
_setHideAnim(m_nandemuLblTitle, "NANDEMU/TITLE", 0, 0, -2.f, 0.f);
_setHideAnim(m_nandfileLblMessage, "NANDEMU/FMESSAGE", 0, 0, -2.f, 0.f);
_setHideAnim(m_nandemuLblMessage, "NANDEMU/MESSAGE", 0, 0, -2.f, 0.f);
_setHideAnim(m_nandfileLblDialog, "NANDEMU/FDIALOG", 0, 0, -2.f, 0.f);
_setHideAnim(m_nandfinLblDialog, "NANDEMU/FINDIALOG", 0, 0, -2.f, 0.f);
_setHideAnim(m_nandemuLblDialog, "NANDEMU/DIALOG", 0, 0, -2.f, 0.f);
_setHideAnim(m_nandfilePBar, "NANDEMU/FILEPROGRESS_BAR", 0, 0, -2.f, 0.f);
_setHideAnim(m_nandemuPBar, "NANDEMU/PROGRESS_BAR", 0, 0, -2.f, 0.f);
_setHideAnim(m_nandemuLblEmulation, "NANDEMU/EMU_SAVE", 50, 0, -2.f, 0.f);
_setHideAnim(m_nandemuLblEmulationVal, "NANDEMU/EMU_SAVE_BTN_GLOBAL", -50, 0, 1.f, 0.f);
_setHideAnim(m_nandemuBtnEmulationM, "NANDEMU/EMU_SAVE_MINUS", -50, 0, 1.f, 0.f);
_setHideAnim(m_nandemuBtnEmulationP, "NANDEMU/EMU_SAVE_PLUS", -50, 0, 1.f, 0.f);
_setHideAnim(m_nandemuLblSaveDump, "NANDEMU/SAVE_DUMP", 50, 0, -2.f, 0.f);
_setHideAnim(m_nandemuBtnAll, "NANDEMU/ALL_BTN", -50, 0, 1.f, 0.f);
_setHideAnim(m_nandemuBtnMissing, "NANDEMU/MISSING_BTN", -50, 0, 1.f, 0.f);
_setHideAnim(m_nandemuLblNandDump, "NANDEMU/NAND_DUMP", 50, 0, -2.f, 0.f);
_setHideAnim(m_nandemuBtnNandDump, "NANDEMU/NAND_DUMP_BTN", -50, 0, 1.f, 0.f);
_setHideAnim(m_nandemuLblNandSelect, "NANDEMU/NAND_SELECT", 50, 0, -2.f, 0.f);
_setHideAnim(m_nandemuLblNandSelectVal, "NANDEMU/NAND_SELECT_BTN", -50, 0, 1.f, 0.f);
_setHideAnim(m_nandemuBtnNandSelectM, "NANDEMU/NAND_SELECT_MINUS", -50, 0, 1.f, 0.f);
_setHideAnim(m_nandemuBtnNandSelectP, "NANDEMU/NAND_SELECT_PLUS", -50, 0, 1.f, 0.f);
_setHideAnim(m_nandemuBtnBack, "NANDEMU/BACK_BTN", 0, 0, 1.f, -1.f);
_setHideAnim(m_nandemuLblPage, "NANDEMU/PAGE_BTN", 0, 0, 1.f, -1.f);
_setHideAnim(m_nandemuBtnPageM, "NANDEMU/PAGE_MINUS", 0, 0, 1.f, -1.f);
_setHideAnim(m_nandemuBtnPageP, "NANDEMU/PAGE_PLUS", 0, 0, 1.f, -1.f);
_setHideAnim(m_nandemuBtnExtract, "NANDEMU/EXTRACT", 0, 0, -2.f, 0.f);
_setHideAnim(m_nandemuBtnPartition, "NANDEMU/PARTITION", 0, 0, -2.f, 0.f);
_setHideAnim(m_nandemuBtnDisable, "NANDEMU/DISABLE", 0, 0, -2.f, 0.f);
_setHideAnim(m_nandemuLblInit, "NANDEMU/INIT", 0, 0, -2.f, 0.f);
_hideNandEmu(true);
_textNandEmu();
}
void CMenu::_textNandEmu(void)
{
m_btnMgr.setText(m_nandemuLblNandSelect, _t("cfgne37", L"Select Nand"));
m_btnMgr.setText(m_nandemuLblEmulation, _t("cfgne1", L"NAND Emulation"));
m_btnMgr.setText(m_nandemuLblSaveDump, _t("cfgne2", L"Extract Game Saves"));
m_btnMgr.setText(m_nandemuBtnAll, _t("cfgne3", L"All"));
m_btnMgr.setText(m_nandemuBtnMissing, _t("cfgne4", L"Missing"));
m_btnMgr.setText(m_nandemuLblNandDump, _t("cfgne5", L"Extract NAND"));
m_btnMgr.setText(m_nandemuBtnNandDump, _t("cfgne6", L"Start"));
m_btnMgr.setText(m_nandemuBtnBack, _t("cfgne7", L"Back"));
}