WiiFlow_Lite/source/menu/menu_nandemu.cpp
Fledge68 6f6b3ec2d8 external_booter.bin fixes that i missed when i changed the booter in v5.5.0 beta 12 commit 9f7da43
- added missing *BI2 = 0x817E5480; to  Disc_SetLowMem() for wii games.
- added missing memcpy((void*)0x80001800, (void*)Disc_ID, 8); needed for debugger and ocarina cheats engine.

- fixed default setting for savegame emulation back to OFF (0). v5.5.0 and v5.5.1 new clean install's would set it to FULL (2) which caused wii games to crash on boot up. if you have this issue you can simply go to main settings>nand emulation settings and set it to OFF.
- changes to STexture::fromPNG() to hopefully clear up the out of mem issue when downloading and converting the cover png to a wfc cache file.
- v5.5.2
2022-02-07 07:19:27 -06:00

1158 lines
45 KiB
C++

#include <dirent.h>
#include <unistd.h>
#include <algorithm>
#include <sys/stat.h>
#include "menu.hpp"
#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_nandemuLblNandSelect;
s16 m_nandemuLblNandSelectVal;
s16 m_nandemuBtnNandSelectM;
s16 m_nandemuBtnNandSelectP;
s16 m_nandemuLblEmulation;
s16 m_nandemuLblEmulationVal;
s16 m_nandemuBtnEmulationM;
s16 m_nandemuBtnEmulationP;
s16 m_nandemuLblSaveNandSelect;
s16 m_nandemuLblSaveNandSelectVal;
s16 m_nandemuBtnSaveNandSelectM;
s16 m_nandemuBtnSaveNandSelectP;
s16 m_nandemuLblSaveEmulation;
s16 m_nandemuLblSaveEmulationVal;
s16 m_nandemuBtnSaveEmulationM;
s16 m_nandemuBtnSaveEmulationP;
s16 m_nandemuLblSaveDump;
s16 m_nandemuBtnAll;
s16 m_nandemuBtnMissing;
s16 m_nandemuLblNandDump;
s16 m_nandemuBtnNandDump;
s16 m_nandemuLblSavePartition;
s16 m_nandemuLblSavePartitionVal;
s16 m_nandemuBtnSavePartitionM;
s16 m_nandemuBtnSavePartitionP;
s16 m_nandemuLblInstallWad;
s16 m_nandemuBtnInstallWad;
s16 m_nandemuLblRealConfig;
s16 m_nandemuBtnRealConfig;
s16 m_nandemuLblRealMiis;
s16 m_nandemuBtnRealMiis;
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_nandemuLblInit;
s16 m_nandemuLblUser[4];
TexData m_nandemuBg;
int nandemuPage = 1;
int curEmuNand = 0;
int curSavesNand = 0;
vector<string> emuNands;
vector<string> savesNands;
bool m_nandext;
bool m_nanddump;
bool m_sgdump;
bool m_saveall;
static inline int loopNum(int i, int s)
{
return (i + s) % s;
}
void CMenu::_listEmuNands(const char *path, vector<string> &nands)
{
DIR *d;
struct dirent *dir;
nands.clear();
bool add_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)
{
nands.push_back(dir->d_name);
if(strlen(dir->d_name) == 7 && strcasecmp(dir->d_name, "default") == 0)
add_def = false;
}
}
closedir(d);
}
else
return;
if(add_def)
nands.push_back("default");
sort(nands.begin(), nands.end());
}
void CMenu::_getEmuNands(void)
{
u8 i;
string emuNand = m_cfg.getString(CHANNEL_DOMAIN, "current_emunand", "default");
int emuPart = m_cfg.getInt(CHANNEL_DOMAIN, "partition", -1);
string savesNand = m_cfg.getString(WII_DOMAIN, "current_save_emunand", "default");
int savesPart = m_cfg.getInt(WII_DOMAIN, "savepartition", -1);
/* emu Nands */
_listEmuNands(fmt("%s:/%s", DeviceName[emuPart], emu_nands_dir), emuNands);
if(emuNands.empty())// in case device has been temporarily disconnected
emuNands.push_back(emuNand);
curEmuNand = 0;
for(i = 0; i < emuNands.size(); ++i)// find current emunand folder
{
if(emuNands[i] == emuNand)
{
curEmuNand = i;
break;
}
}
if(i == emuNands.size())// didn't find emunand folder so set to default
{
for(i = 0; i < emuNands.size(); ++i)
{
if(emuNands[i] == "default")
{
curEmuNand = i;
break;
}
}
}
/* saves Nands */
_listEmuNands(fmt("%s:/%s", DeviceName[savesPart], emu_nands_dir), savesNands);
if(savesNands.empty())
savesNands.push_back(savesNand);
curSavesNand = 0;
for(i = 0; i < savesNands.size(); ++i)// find current savesnand folder
{
if(savesNands[i] == savesNand)
{
curSavesNand = i;
break;
}
}
if(i == savesNands.size())// didn't find savesnand folder set to default
{
for(i = 0; i < savesNands.size(); ++i)
{
if(savesNands[i] == "default")
{
curSavesNand = i;
break;
}
}
}
}
/* This checks if nand emulation is set to Full */
/* if is then it copies SYSCONF, setting.txt, and RFL_DB.dat only if they don't already exist */
/* this is helpful if you use a modmii created nand, wiiflow dumped nand will already have these files */
/* if you wish to overwrite these files then use the real nand mii's and config options */
void CMenu::_FullNandCheck(void)
{
for(u8 i = 0; i < 2; i++)
{
int emulate_mode;
if(i == EMU_NAND)
emulate_mode = m_cfg.getInt(CHANNEL_DOMAIN, "emulation");// partial by default
else
emulate_mode = m_cfg.getInt(WII_DOMAIN, "save_emulation");// off by default
if((i == EMU_NAND && emulate_mode == 1) || (i == SAVES_NAND && emulate_mode == 2))//full
{
int emuPart = _FindEmuPart(i, false);
if(emuPart < 0)
continue;
bool need_config = false;
bool need_miis = false;
const char *emuPath = NandHandle.Get_NandPath();
char basepath[MAX_FAT_PATH];
snprintf(basepath, sizeof(basepath), "%s:%s", DeviceName[emuPart], emuPath);
char testpath[MAX_FAT_PATH + 42];
//check config file - time and date, video settings, etc...
snprintf(testpath, sizeof(testpath), "%s/shared2/sys/SYSCONF", basepath);
if(!fsop_FileExist(testpath))
need_config = true;
// system info like model and serial numbers, not real important. modmii creates this file.
snprintf(testpath, sizeof(testpath), "%s/title/00000001/00000002/data/setting.txt", basepath);
if(!fsop_FileExist(testpath))
need_config = true;
// Check Mii's
snprintf(testpath, sizeof(testpath), "%s/shared2/menu/FaceLib/RFL_DB.dat", basepath);
if(!fsop_FileExist(testpath))
need_miis = true;
NandHandle.PreNandCfg(need_miis, need_config);//copy to emunand if needed
}
}
}
int CMenu::_FindEmuPart(bool savesnand, bool skipchecks)
{
int emuPart;
char tmpPath[32];
tmpPath[31] = '\0';
if(savesnand)
{
emuPart = m_cfg.getInt(WII_DOMAIN, "savepartition");
strncpy(tmpPath, fmt("/%s/%s", emu_nands_dir, m_cfg.getString(WII_DOMAIN, "current_save_emunand").c_str()), sizeof(tmpPath) - 1);
}
else
{
emuPart = m_cfg.getInt(CHANNEL_DOMAIN, "partition");
strncpy(tmpPath, fmt("/%s/%s", emu_nands_dir, m_cfg.getString(CHANNEL_DOMAIN, "current_emunand").c_str()), sizeof(tmpPath) - 1);
}
if(!DeviceHandle.PartitionUsableForNandEmu(emuPart))//check if device is mounted and partition is FAT
return -1;
else if((skipchecks || _TestEmuNand(emuPart, tmpPath, false)))//check if emunand folder exist
{
NandHandle.SetNANDEmu(emuPart);
NandHandle.SetPaths(tmpPath, DeviceName[emuPart]);
return emuPart;
}
return -2;
}
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;
}
static bool _saveExists(const char *path)
{
DIR *d = opendir(path);
if(!d)
return false;
else
{
closedir(d);
return true;
}
}
bool CMenu::_checkSave(string id, int nand_type)
{
int savePath = id.c_str()[0] << 24 | id.c_str()[1] << 16 | id.c_str()[2] << 8 | id.c_str()[3];
if(nand_type == REAL_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 // SAVES_NAND
{
int emuPartition = m_cfg.getInt(WII_DOMAIN, "savepartition");
const char *emuPath = fmt("/%s/%s", emu_nands_dir, m_cfg.getString(WII_DOMAIN, "current_save_emunand").c_str());
if(emuPartition < 0 || emuPath == NULL)
return false;
struct stat fstat;
if((stat(fmt("%s:%s/title/00010000/%08x", DeviceName[emuPartition], emuPath, savePath), &fstat) != 0)
&& (stat(fmt("%s:%s/title/00010004/%08x", DeviceName[emuPartition], emuPath, 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_nandemuLblNandSelect, instant);
m_btnMgr.hide(m_nandemuLblNandSelectVal, instant);
m_btnMgr.hide(m_nandemuBtnNandSelectP, instant);
m_btnMgr.hide(m_nandemuBtnNandSelectM, instant);
m_btnMgr.hide(m_nandemuLblEmulation, instant);
m_btnMgr.hide(m_nandemuLblEmulationVal, instant);
m_btnMgr.hide(m_nandemuBtnEmulationP, instant);
m_btnMgr.hide(m_nandemuBtnEmulationM, instant);
m_btnMgr.hide(m_nandemuLblSaveNandSelect, instant);
m_btnMgr.hide(m_nandemuLblSaveNandSelectVal, instant);
m_btnMgr.hide(m_nandemuBtnSaveNandSelectP, instant);
m_btnMgr.hide(m_nandemuBtnSaveNandSelectM, instant);
m_btnMgr.hide(m_nandemuLblSaveEmulation, instant);
m_btnMgr.hide(m_nandemuLblSaveEmulationVal, instant);
m_btnMgr.hide(m_nandemuBtnSaveEmulationP, instant);
m_btnMgr.hide(m_nandemuBtnSaveEmulationM, 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_nandemuLblSavePartition, instant);
m_btnMgr.hide(m_nandemuLblSavePartitionVal, instant);
m_btnMgr.hide(m_nandemuBtnSavePartitionP, instant);
m_btnMgr.hide(m_nandemuBtnSavePartitionM, instant);
m_btnMgr.hide(m_nandemuLblInstallWad, instant);
m_btnMgr.hide(m_nandemuBtnInstallWad, instant);
m_btnMgr.hide(m_nandemuLblRealConfig, instant);
m_btnMgr.hide(m_nandemuBtnRealConfig, instant);
m_btnMgr.hide(m_nandemuLblRealMiis, instant);
m_btnMgr.hide(m_nandemuBtnRealMiis, instant);
m_btnMgr.hide(m_nandemuBtnExtract, 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::_hideNandEmuPg(void)
{
//Does not hide title, page, back, or user labels
if(nandemuPage == 1)
{
m_btnMgr.hide(m_nandemuLblNandSelect);
m_btnMgr.hide(m_nandemuLblNandSelectVal);
m_btnMgr.hide(m_nandemuBtnNandSelectP);
m_btnMgr.hide(m_nandemuBtnNandSelectM);
m_btnMgr.hide(m_nandemuLblEmulationVal);
m_btnMgr.hide(m_nandemuLblEmulation);
m_btnMgr.hide(m_nandemuBtnEmulationP);
m_btnMgr.hide(m_nandemuBtnEmulationM);
m_btnMgr.hide(m_nandemuLblSaveNandSelect);
m_btnMgr.hide(m_nandemuLblSaveNandSelectVal);
m_btnMgr.hide(m_nandemuBtnSaveNandSelectP);
m_btnMgr.hide(m_nandemuBtnSaveNandSelectM);
m_btnMgr.hide(m_nandemuLblSaveEmulationVal);
m_btnMgr.hide(m_nandemuLblSaveEmulation);
m_btnMgr.hide(m_nandemuBtnSaveEmulationP);
m_btnMgr.hide(m_nandemuBtnSaveEmulationM);
}
else if(nandemuPage == 2)
{
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_nandemuLblInstallWad);
m_btnMgr.hide(m_nandemuBtnInstallWad);
}
else
{
m_btnMgr.hide(m_nandemuLblSavePartition);
m_btnMgr.hide(m_nandemuLblSavePartitionVal);
m_btnMgr.hide(m_nandemuBtnSavePartitionP);
m_btnMgr.hide(m_nandemuBtnSavePartitionM);
m_btnMgr.hide(m_nandemuLblRealConfig);
m_btnMgr.hide(m_nandemuBtnRealConfig);
m_btnMgr.hide(m_nandemuLblRealMiis);
m_btnMgr.hide(m_nandemuBtnRealMiis);
}
}
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 / 3", nandemuPage));
m_btnMgr.show(m_nandemuLblPage);
m_btnMgr.show(m_nandemuBtnPageM);
m_btnMgr.show(m_nandemuBtnPageP);
if(nandemuPage == 1)
{
int 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));
i = min(max(0, m_cfg.getInt(WII_DOMAIN, "save_emulation", 0)), (int)ARRAY_SIZE(CMenu::_GlobalSaveEmu) - 1);
m_btnMgr.setText(m_nandemuLblSaveEmulationVal, _t(CMenu::_GlobalSaveEmu[i].id, CMenu::_GlobalSaveEmu[i].text));
m_btnMgr.setText(m_nandemuLblNandSelectVal, m_cfg.getString(CHANNEL_DOMAIN, "current_emunand"));
m_btnMgr.setText(m_nandemuLblSaveNandSelectVal, m_cfg.getString(WII_DOMAIN, "current_save_emunand"));
m_btnMgr.show(m_nandemuLblNandSelect);
m_btnMgr.show(m_nandemuLblNandSelectVal);
m_btnMgr.show(m_nandemuBtnNandSelectP);
m_btnMgr.show(m_nandemuBtnNandSelectM);
m_btnMgr.show(m_nandemuLblEmulation);
m_btnMgr.show(m_nandemuLblEmulationVal);
m_btnMgr.show(m_nandemuBtnEmulationP);
m_btnMgr.show(m_nandemuBtnEmulationM);
m_btnMgr.show(m_nandemuLblSaveNandSelect);
m_btnMgr.show(m_nandemuLblSaveNandSelectVal);
m_btnMgr.show(m_nandemuBtnSaveNandSelectP);
m_btnMgr.show(m_nandemuBtnSaveNandSelectM);
m_btnMgr.show(m_nandemuLblSaveEmulation);
m_btnMgr.show(m_nandemuLblSaveEmulationVal);
m_btnMgr.show(m_nandemuBtnSaveEmulationP);
m_btnMgr.show(m_nandemuBtnSaveEmulationM);
}
else if(nandemuPage == 2)
{
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);
m_btnMgr.show(m_nandemuLblInstallWad);
m_btnMgr.show(m_nandemuBtnInstallWad);
}
else
{
const char *partitionname = DeviceName[m_cfg.getInt(WII_DOMAIN, "savepartition")];
m_btnMgr.setText(m_nandemuLblSavePartitionVal, upperCase(partitionname));
m_btnMgr.setText(m_nandemuBtnRealConfig, m_cfg.getBool(CHANNEL_DOMAIN, "real_nand_config", false) ? _t("on", L"On") : _t("off", L"Off"));
m_btnMgr.setText(m_nandemuBtnRealMiis, m_cfg.getBool(CHANNEL_DOMAIN, "real_nand_miis", false) ? _t("on", L"On") : _t("off", L"Off"));
m_btnMgr.show(m_nandemuLblSavePartition);
m_btnMgr.show(m_nandemuLblSavePartitionVal);
m_btnMgr.show(m_nandemuBtnSavePartitionP);
m_btnMgr.show(m_nandemuBtnSavePartitionM);
m_btnMgr.show(m_nandemuLblRealConfig);
m_btnMgr.show(m_nandemuBtnRealConfig);
m_btnMgr.show(m_nandemuLblRealMiis);
m_btnMgr.show(m_nandemuBtnRealMiis);
}
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)
{
if(isWiiVC)
{
error(_t("errboot7", L"Access denied in Wii VC mode."));
return 0;
}
nandemuPage = 1;
string ExtNand = "";
string emuNand = m_cfg.getString(CHANNEL_DOMAIN, "current_emunand");
lwp_t thread = 0;
SetupInput();
_getEmuNands();
_showNandEmu();
m_thrdStop = false;
m_thrdMessageAdded = false;
m_nandext = false;
while(!m_exit)
{
_mainLoopCommon();
if((BTN_MINUS_PRESSED || BTN_LEFT_PRESSED) || (BTN_A_PRESSED && m_btnMgr.selected(m_nandemuBtnPageM)))
{
_hideNandEmuPg();
if(nandemuPage == 1)
nandemuPage = 3;
else --nandemuPage;
if(BTN_LEFT_PRESSED || BTN_MINUS_PRESSED)
m_btnMgr.click(m_nandemuBtnPageM);
_showNandEmu();
}
else if((BTN_PLUS_PRESSED || BTN_RIGHT_PRESSED) || (BTN_A_PRESSED && m_btnMgr.selected(m_nandemuBtnPageP)))
{
_hideNandEmuPg();
if(nandemuPage == 3)
nandemuPage = 1;
else
++nandemuPage;
if(BTN_RIGHT_PRESSED || BTN_PLUS_PRESSED)
m_btnMgr.click(m_nandemuBtnPageP);
_showNandEmu();
}
else if((BTN_HOME_PRESSED || BTN_B_PRESSED) && !m_thrdWorking)
break;
else if(BTN_UP_PRESSED && !m_thrdWorking)
m_btnMgr.up();
else if(BTN_DOWN_PRESSED && !m_thrdWorking)
m_btnMgr.down();
else if(BTN_A_PRESSED)
{
if(m_btnMgr.selected(m_nandemuBtnEmulationP) || m_btnMgr.selected(m_nandemuBtnEmulationM))
{
s8 direction = m_btnMgr.selected(m_nandemuBtnEmulationP) ? 1 : -1;
m_cfg.setInt(CHANNEL_DOMAIN, "emulation", loopNum(m_cfg.getInt(CHANNEL_DOMAIN, "emulation", 0) + direction, ARRAY_SIZE(CMenu::_NandEmu)));
_showNandEmu();
}
else if(m_btnMgr.selected(m_nandemuBtnSaveEmulationP) || m_btnMgr.selected(m_nandemuBtnSaveEmulationM))
{
s8 direction = m_btnMgr.selected(m_nandemuBtnSaveEmulationP) ? 1 : -1;
m_cfg.setInt(WII_DOMAIN, "save_emulation", loopNum(m_cfg.getInt(WII_DOMAIN, "save_emulation", 0) + direction, ARRAY_SIZE(CMenu::_GlobalSaveEmu)));
_showNandEmu();
}
else if(m_btnMgr.selected(m_nandemuBtnSavePartitionP) || m_btnMgr.selected(m_nandemuBtnSavePartitionM))
{
s8 direction = m_btnMgr.selected(m_nandemuBtnSavePartitionP) ? 1 : -1;
currentPartition = m_cfg.getInt(WII_DOMAIN, "savepartition");
m_emuSaveNand = true;
_setPartition(direction);
m_emuSaveNand = false;
_getEmuNands();// refresh emunands in case the partition was changed
_showNandEmu();
}
else if(m_btnMgr.selected(m_nandemuBtnNandDump) || m_btnMgr.selected(m_nandemuBtnAll) || m_btnMgr.selected(m_nandemuBtnMissing))
{
m_nanddump = m_btnMgr.selected(m_nandemuBtnNandDump) ? true : false;
m_saveall = m_btnMgr.selected(m_nandemuBtnAll) ? true : false;
m_btnMgr.hide(m_nandemuBtnBack);
_hideNandEmu(true);
int emuPart = _FindEmuPart(!m_nanddump, true);
if(emuPart < 0)
{
error(_t("cfgne8", L"No valid FAT partition found for NAND Emulation!"));
_showNandEmu();
}
else
{
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:"));
if(m_nanddump)
{
ExtNand = emuNands[curEmuNand];// set for later to refresh game list
m_btnMgr.setText(m_nandemuLblTitle, _t("cfgne12", L"NAND Extractor"));
}
else // saves dump
{
//ExtNand = savesNands[curSavesNand];
m_btnMgr.setText(m_nandemuLblTitle, _t("cfgne13", L"Game Save Extractor"));
}
m_thrdStop = false;
m_thrdProgress = 0.f;
m_thrdWorking = true;
LWP_CreateThread(&thread, _NandDumper, this, 0, 32768, 40);
}
}
else if(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());
m_cfg.setString(CHANNEL_DOMAIN, "current_emunand", emuNands[curEmuNand]);
_showNandEmu();
}
else if(m_btnMgr.selected(m_nandemuBtnSaveNandSelectP) || m_btnMgr.selected(m_nandemuBtnSaveNandSelectM))
{
s8 direction = m_btnMgr.selected(m_nandemuBtnSaveNandSelectP) ? 1 : -1;
curSavesNand = loopNum(curSavesNand + direction, savesNands.size());
m_cfg.setString(WII_DOMAIN, "current_save_emunand", savesNands[curSavesNand]);
_showNandEmu();
}
else if(m_btnMgr.selected(m_nandemuBtnInstallWad))
{
_hideNandEmu();
_wadExplorer();
nandemuPage = 1;
_showNandEmu();
}
else if(m_btnMgr.selected(m_nandemuBtnRealConfig))
{
m_cfg.setBool(CHANNEL_DOMAIN, "real_nand_config", !m_cfg.getBool(CHANNEL_DOMAIN, "real_nand_config"));
_showNandEmu();
}
else if(m_btnMgr.selected(m_nandemuBtnRealMiis))
{
m_cfg.setBool(CHANNEL_DOMAIN, "real_nand_miis", !m_cfg.getBool(CHANNEL_DOMAIN, "real_nand_miis"));
_showNandEmu();
}
else if(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);
while(!m_exit)
{
_mainLoopCommon();
if(BTN_HOME_PRESSED || BTN_B_PRESSED || (BTN_A_PRESSED && m_btnMgr.selected(m_nandemuBtnBack)))
{
_hideNandEmu();
nandemuPage = 1;
_showNandEmu();
break;
}
}
}
}
}
_hideNandEmu();
_FullNandCheck();
/* if changed emunand choice or emunand is the new one extracted */
if(emuNand != m_cfg.getString(CHANNEL_DOMAIN, "current_emunand") || emuNand == ExtNand)
{
m_cfg.setBool(CHANNEL_DOMAIN, "update_cache", true);
if(m_current_view & COVERFLOW_CHANNEL)
m_refreshGameList = true;
}
return 0;
}
int CMenu::_FlashSave(string gameId)
{
if(_FindEmuPart(SAVES_NAND, false) < 0)// if savesnand folder not found
return 0;
if(!_checkSave(gameId, SAVES_NAND))// if save not on saves emunand
return 0;
lwp_t thread = 0;
m_thrdStop = false;
m_thrdMessageAdded = false;
m_nandext = false;
m_saveExtGameId = gameId;
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_thrdProgress = 0.f;
m_thrdWorking = true;
LWP_CreateThread(&thread, _NandFlasher, this, 0, 32768, 40);
SetupInput();
while(!m_exit)
{
_mainLoopCommon();
if(!m_thrdWorking && (BTN_HOME_PRESSED || BTN_B_PRESSED || (BTN_A_PRESSED && m_btnMgr.selected(m_nandemuBtnBack))))
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)
{
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 1;
}
int CMenu::_AutoExtractSave(string gameId)// called from game settings menu to extract a gamesave from real nand to savesnand
{
if(!_checkSave(gameId, REAL_NAND))//if save not on real nand
return 0;
int emuPart = _FindEmuPart(SAVES_NAND, false);
if(emuPart == -1)// if savesnand partition unusable
return 0;
else if(emuPart == -2)// emunand folder not found so make it
{
emuPart = _FindEmuPart(SAVES_NAND, true);
const char *emuPath = NandHandle.Get_NandPath();
char basepath[MAX_FAT_PATH];
snprintf(basepath, sizeof(basepath), "%s:%s", DeviceName[emuPart], emuPath);
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);
}
lwp_t thread = 0;
m_thrdStop = false;
m_thrdMessageAdded = false;
m_nandext = false;
m_saveExtGameId = gameId;
bool finished = false;
m_nanddump = false;
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_thrdProgress = 0.f;
m_thrdWorking = true;
LWP_CreateThread(&thread, _NandDumper, this, 0, 32768, 40);
SetupInput();
while(!m_exit)
{
_mainLoopCommon();
if(finished && (BTN_HOME_PRESSED || BTN_B_PRESSED || (BTN_A_PRESSED && m_btnMgr.selected(m_nandemuBtnBack))))
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)
{
finished = true;
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 1;
}
void * CMenu::_NandFlasher(void *obj)
{
CMenu &m = *(CMenu *)obj;
char source[MAX_FAT_PATH];
char dest[ISFS_MAXPATH];
int emuPartition = m._FindEmuPart(SAVES_NAND, true);
const char *emuPath = NandHandle.Get_NandPath();
const char *SaveGameID = m.m_saveExtGameId.c_str();
int flashID = SaveGameID[0] << 24 | SaveGameID[1] << 16 | SaveGameID[2] << 8 | SaveGameID[3];
/* we know it exist on emunand just need to figure out which folder */
if(_saveExists(fmt("%s:%s/title/00010000/%08x", DeviceName[emuPartition], emuPath, flashID)))
{
snprintf(source, sizeof(source), "%s:%s/title/00010000/%08x", DeviceName[emuPartition], emuPath, flashID);
snprintf(dest, sizeof(dest), "/title/00010000/%08x", flashID);
}
else //if(_saveExists(fmt("%s:%s/title/00010004/%08x", DeviceName[emuPartition], emuPath, flashID)))
{
snprintf(source, sizeof(source), "%s:%s/title/00010004/%08x", DeviceName[emuPartition], emuPath, 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);
LWP_MutexLock(m.m_mutex);
m_btnMgr.hide(m_nandfilePBar);
m_btnMgr.hide(m_nandfileLblMessage);
m_btnMgr.hide(m_nandemuPBar);
m_btnMgr.hide(m_nandemuLblMessage);
m._setDumpMsg(m._t("cfgne30", L"Flashing save files finished!"), 1.f, 1.f);
LWP_MutexUnlock(m.m_mutex);
m.m_thrdWorking = false;
return 0;
}
void * CMenu::_NandDumper(void *obj)
{
CMenu &m = *(CMenu *)obj;
m_nandext = false;
m_sgdump = false;
m.m_dumpsize = 0;
m.m_filesdone = 0;
m.m_foldersdone = 0;
NandHandle.ResetCounters();
int emuPartition = m._FindEmuPart(!m_nanddump, true);
const char *emuPath = NandHandle.Get_NandPath();
char basepath[64];
snprintf(basepath, sizeof(basepath), "%s:%s", DeviceName[emuPartition], emuPath);
/* create basepath in case it doesn't exist */
NandHandle.CreatePath("%s", basepath);
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_nanddump)/* full nand dump */
{
m.m_dumpsize = NandHandle.CalcDumpSpace("/", CMenu::_ShowProgress, obj);
m_nandext = true;
NandHandle.DoNandDump("/", basepath, CMenu::_ShowProgress, obj);
}
else /* gamesave(s) dump */
{
bool missingOnly = !m_saveall;
vector<string> saveList;
m_sgdump = true;
if(m.m_saveExtGameId.empty())// if not a specified gamesave from game config menu or launching wii game
{
/* extract all or missing gamesaves - main emunand settings menu */
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);
m.m_nandexentry = 0;
saveList.reserve(m.m_gameList.size());
for(u32 i = 0; i < m.m_gameList.size() && !m.m_thrdStop; ++i)
{
if(m.m_gameList[i].type == TYPE_WII_GAME)
{
string id((const char *)m.m_gameList[i].id, 4);
if(!missingOnly || !m._checkSave(id, SAVES_NAND))// if all or the gamesave is not already on saves emunand
{
if(m._checkSave(id, REAL_NAND))// if save on real nand
{
m.m_nandexentry++;
saveList.push_back(id);
}
}
}
}
}
else /*one gamesave extract from game config menu or launching wii game */
{
m.m_nandexentry = 1;
saveList.push_back(m.m_saveExtGameId);
}
/* for loop to calculate SD or HDD space NanHandle will need for the actual savegame(s) dump */
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], REAL_NAND))
snprintf(source, sizeof(source), "/title/00010004/%08x", savePath);
m.m_dumpsize = NandHandle.CalcDumpSpace(source, CMenu::_ShowProgress, obj);
}
/* for loop to do the actual savegame(s) dump */
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], REAL_NAND))
snprintf(source, sizeof(source), "/title/00010004/%08x", savePath);
m_nandext = true;
NandHandle.DoNandDump(source, basepath, CMenu::_ShowProgress, obj);
}
}
LWP_MutexLock(m.m_mutex);
m_btnMgr.hide(m_nandfilePBar);
m_btnMgr.hide(m_nandfileLblMessage);
m_btnMgr.hide(m_nandemuPBar);
m_btnMgr.hide(m_nandemuLblMessage);
m._setDumpMsg(m._t("cfgne19", L"Extraction finished!"), 1.f, 1.f);
LWP_MutexUnlock(m.m_mutex);
m.m_thrdWorking = false;
return 0;
}
void CMenu::_initNandEmuMenu()
{
_addUserLabels(m_nandemuLblUser, ARRAY_SIZE(m_nandemuLblUser), "NANDEMU");
m_nandemuBg = _texture("NANDEMU/BG", "texture", theme.bg, false);
m_nandemuLblTitle = _addLabel("NANDEMU/TITLE", theme.titleFont, L"", 0, 10, 640, 60, theme.titleFontColor, FTGX_JUSTIFY_CENTER | FTGX_ALIGN_MIDDLE);
m_nandfilePBar = _addProgressBar("NANDEMU/FILEPROGRESS_BAR", 40, 80, 560, 20);
m_nandfileLblMessage = _addLabel("NANDEMU/FMESSAGE", theme.lblFont, L"", 40, 110, 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_nandemuPBar = _addProgressBar("NANDEMU/PROGRESS_BAR", 40, 220, 560, 20);
m_nandemuLblMessage = _addLabel("NANDEMU/MESSAGE", theme.lblFont, L"", 40, 280, 560, 100, theme.lblFontColor, FTGX_JUSTIFY_CENTER | FTGX_ALIGN_TOP);
m_nandemuLblDialog = _addLabel("NANDEMU/DIALOG", theme.lblFont, L"", 40, 190, 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_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_nandemuLblEmulation = _addLabel("NANDEMU/NAND_EMU", theme.lblFont, L"", 20, 185, 385, 56, theme.lblFontColor, FTGX_JUSTIFY_LEFT | FTGX_ALIGN_MIDDLE);
m_nandemuLblEmulationVal = _addLabel("NANDEMU/NAND_EMU_BTN", theme.btnFont, L"", 468, 190, 104, 48, theme.btnFontColor, FTGX_JUSTIFY_CENTER | FTGX_ALIGN_MIDDLE, theme.btnTexC);
m_nandemuBtnEmulationM = _addPicButton("NANDEMU/NAND_EMU_MINUS", theme.btnTexMinus, theme.btnTexMinusS, 420, 190, 48, 48);
m_nandemuBtnEmulationP = _addPicButton("NANDEMU/NAND_EMU_PLUS", theme.btnTexPlus, theme.btnTexPlusS, 572, 190, 48, 48);
m_nandemuLblSaveNandSelect = _addLabel("NANDEMU/SAVE_NAND_SELECT", theme.lblFont, L"", 20, 245, 385, 56, theme.lblFontColor, FTGX_JUSTIFY_LEFT | FTGX_ALIGN_MIDDLE);
m_nandemuLblSaveNandSelectVal = _addLabel("NANDEMU/SAVE_NAND_SELECT_BTN", theme.btnFont, L"", 468, 250, 104, 48, theme.btnFontColor, FTGX_JUSTIFY_CENTER | FTGX_ALIGN_MIDDLE, theme.btnTexC);
m_nandemuBtnSaveNandSelectM = _addPicButton("NANDEMU/SAVE_NAND_SELECT_MINUS", theme.btnTexMinus, theme.btnTexMinusS, 420, 250, 48, 48);
m_nandemuBtnSaveNandSelectP = _addPicButton("NANDEMU/SAVE_NAND_SELECT_PLUS", theme.btnTexPlus, theme.btnTexPlusS, 572, 250, 48, 48);
m_nandemuLblSaveEmulation = _addLabel("NANDEMU/SAVE_EMU", theme.lblFont, L"", 20, 305, 385, 56, theme.lblFontColor, FTGX_JUSTIFY_LEFT | FTGX_ALIGN_MIDDLE);
m_nandemuLblSaveEmulationVal = _addLabel("NANDEMU/SAVE_EMU_BTN", theme.btnFont, L"", 468, 310, 104, 48, theme.btnFontColor, FTGX_JUSTIFY_CENTER | FTGX_ALIGN_MIDDLE, theme.btnTexC);
m_nandemuBtnSaveEmulationM = _addPicButton("NANDEMU/SAVE_EMU_MINUS", theme.btnTexMinus, theme.btnTexMinusS, 420, 310, 48, 48);
m_nandemuBtnSaveEmulationP = _addPicButton("NANDEMU/SAVE_EMU_PLUS", theme.btnTexPlus, theme.btnTexPlusS, 572, 310, 48, 48);
m_nandemuLblSaveDump = _addLabel("NANDEMU/SAVE_DUMP", theme.lblFont, L"", 20, 125, 385, 56, theme.lblFontColor, FTGX_JUSTIFY_LEFT | FTGX_ALIGN_MIDDLE);
m_nandemuBtnAll = _addButton("NANDEMU/ALL_BTN", theme.btnFont, L"", 420, 130, 200, 48, theme.btnFontColor);
m_nandemuBtnMissing = _addButton("NANDEMU/MISSING_BTN", theme.btnFont, L"", 420, 190, 200, 48, theme.btnFontColor);
m_nandemuLblNandDump = _addLabel("NANDEMU/NAND_DUMP", theme.lblFont, L"", 20, 245, 385, 56, theme.lblFontColor, FTGX_JUSTIFY_LEFT | FTGX_ALIGN_MIDDLE);
m_nandemuBtnNandDump = _addButton("NANDEMU/NAND_DUMP_BTN", theme.btnFont, L"", 420, 250, 200, 48, theme.btnFontColor);
m_nandemuLblInstallWad = _addLabel("NANDEMU/INSTALL_WAD", theme.lblFont, L"", 20, 305, 385, 56, theme.lblFontColor, FTGX_JUSTIFY_LEFT | FTGX_ALIGN_MIDDLE);
m_nandemuBtnInstallWad = _addButton("NANDEMU/INSTALL_WAD_BTN", theme.btnFont, L"", 420, 310, 200, 48, theme.btnFontColor);
m_nandemuLblSavePartition = _addLabel("NANDEMU/SAVE_PART", theme.lblFont, L"", 20, 125, 385, 56, theme.lblFontColor, FTGX_JUSTIFY_LEFT | FTGX_ALIGN_MIDDLE);
m_nandemuLblSavePartitionVal = _addLabel("NANDEMU/SAVE_PART_BTN", theme.btnFont, L"", 468,130, 104, 48, theme.btnFontColor, FTGX_JUSTIFY_CENTER | FTGX_ALIGN_MIDDLE, theme.btnTexC);
m_nandemuBtnSavePartitionM = _addPicButton("NANDEMU/SAVE_PART_MINUS", theme.btnTexMinus, theme.btnTexMinusS, 420, 130, 48, 48);
m_nandemuBtnSavePartitionP = _addPicButton("NANDEMU/SAVE_PART_PLUS", theme.btnTexPlus, theme.btnTexPlusS, 572, 130, 48, 48);
m_nandemuLblRealConfig = _addLabel("NANDEMU/REAL_CONFIG", theme.lblFont, L"", 20, 185, 385, 56, theme.lblFontColor, FTGX_JUSTIFY_LEFT | FTGX_ALIGN_MIDDLE);
m_nandemuBtnRealConfig = _addButton("NANDEMU/REAL_CONFIG_BTN", theme.btnFont, L"", 420, 190, 200, 48, theme.btnFontColor);
m_nandemuLblRealMiis = _addLabel("NANDEMU/REAL_MIIS", theme.lblFont, L"", 20, 245, 385, 56, theme.lblFontColor, FTGX_JUSTIFY_LEFT | FTGX_ALIGN_MIDDLE);
m_nandemuBtnRealMiis = _addButton("NANDEMU/REAL_MIIS_BTN", theme.btnFont, L"", 420, 250, 200, 48, theme.btnFontColor);
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_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_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_nandemuLblEmulation, "NANDEMU/NAND_EMU", 50, 0, -2.f, 0.f);
_setHideAnim(m_nandemuLblEmulationVal, "NANDEMU/NAND_EMU_BTN", -50, 0, 1.f, 0.f);
_setHideAnim(m_nandemuBtnEmulationM, "NANDEMU/NAND_EMU_MINUS", -50, 0, 1.f, 0.f);
_setHideAnim(m_nandemuBtnEmulationP, "NANDEMU/NAND_EMU_PLUS", -50, 0, 1.f, 0.f);
_setHideAnim(m_nandemuLblSaveNandSelect, "NANDEMU/SAVE_NAND_SELECT", 50, 0, -2.f, 0.f);
_setHideAnim(m_nandemuLblSaveNandSelectVal, "NANDEMU/SAVE_NAND_SELECT_BTN", -50, 0, 1.f, 0.f);
_setHideAnim(m_nandemuBtnSaveNandSelectM, "NANDEMU/SAVE_NAND_SELECT_MINUS", -50, 0, 1.f, 0.f);
_setHideAnim(m_nandemuBtnSaveNandSelectP, "NANDEMU/SAVE_NAND_SELECT_PLUS", -50, 0, 1.f, 0.f);
_setHideAnim(m_nandemuLblSaveEmulation, "NANDEMU/SAVE_EMU", 50, 0, -2.f, 0.f);
_setHideAnim(m_nandemuLblSaveEmulationVal, "NANDEMU/SAVE_EMU_BTN", -50, 0, 1.f, 0.f);
_setHideAnim(m_nandemuBtnSaveEmulationM, "NANDEMU/SAVE_EMU_MINUS", -50, 0, 1.f, 0.f);
_setHideAnim(m_nandemuBtnSaveEmulationP, "NANDEMU/SAVE_EMU_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_nandemuLblSavePartition, "NANDEMU/SAVE_PART", 50, 0, -2.f, 0.f);
_setHideAnim(m_nandemuLblSavePartitionVal, "NANDEMU/SAVE_PART_BTN", -50, 0, 1.f, 0.f);
_setHideAnim(m_nandemuBtnSavePartitionM, "NANDEMU/SAVE_PART_MINUS", -50, 0, 1.f, 0.f);
_setHideAnim(m_nandemuBtnSavePartitionP, "NANDEMU/SAVE_PART_PLUS", -50, 0, 1.f, 0.f);
_setHideAnim(m_nandemuLblInstallWad, "NANDEMU/INSTALL_WAD", 50, 0, -2.f, 0.f);
_setHideAnim(m_nandemuBtnInstallWad, "NANDEMU/INSTALL_WAD_BTN", -50, 0, 1.f, 0.f);
_setHideAnim(m_nandemuLblRealConfig, "NANDEMU/REAL_CONFIG", 50, 0, -2.f, 0.f);
_setHideAnim(m_nandemuBtnRealConfig, "NANDEMU/REAL_CONFIG_BTN", -50, 0, 1.f, 0.f);
_setHideAnim(m_nandemuLblRealMiis, "NANDEMU/REAL_MIIS", 50, 0, -2.f, 0.f);
_setHideAnim(m_nandemuBtnRealMiis, "NANDEMU/REAL_MIIS_BTN", -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_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_nandemuLblSaveNandSelect, _t("cfgne32", L"Select Saves NAND"));
m_btnMgr.setText(m_nandemuLblSaveEmulation, _t("cfgne33", L"Saves NAND Emulation"));
m_btnMgr.setText(m_nandemuLblSavePartition, _t("cfgne38", L"Saves NAND Partition"));
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_nandemuLblInstallWad, _t("cfgne98", L"Install Wad"));
m_btnMgr.setText(m_nandemuBtnInstallWad, _t("cfgne99", L"Go"));
m_btnMgr.setText(m_nandemuLblRealConfig, _t("cfgne40", L"Use Real NAND Config"));
m_btnMgr.setText(m_nandemuLblRealMiis, _t("cfgne41", L"Use Real NAND Miis"));
m_btnMgr.setText(m_nandemuBtnBack, _t("cfgne7", L"Back"));
}