* Enabled nand extract features for full nand and game saves

* Made nand emulation kind of noob prove
* Wiiflow will search for a valid FAT32 partition if nand emu is enabled, but no partition is selected
* Wiiflow will now offer to extract the nand if nand emu is enabled, and no nand for nand emulation is available
* Wiiflow will now offer to extract a game save if nand emulation is enabled, a save is found on real nand and no save is found on emu nand.cpp
* Illegal chars for FAT are now escaped the 'd2x' way in the nand file extractor

TODO:

* Add nand extract functions to game config menu's
* Add feature to flash a save back to real nand
This commit is contained in:
overjoy.psm 2012-05-02 23:08:11 +00:00
parent afc24fa9c5
commit 1cb8a493d9
10 changed files with 948 additions and 212 deletions

View File

@ -51,6 +51,8 @@ config_header *cfg_hdr;
bool tbdec = false; bool tbdec = false;
bool configloaded = false; bool configloaded = false;
static const int d2xfatrepl_len = 7;
static NandDevice NandDeviceList[] = static NandDevice NandDeviceList[] =
{ {
{ "Disable", 0, 0x00, 0x00 }, { "Disable", 0, 0x00, 0x00 },
@ -412,53 +414,43 @@ bool Nand::__FileExists(const char *path, ...)
return false; return false;
} }
u32 Nand::__TestNandPath(const char *path) void Nand::__FATify(char *ptr, const char *str)
{ {
if(!strncmp(path, "/import", 7)) return 0; char ctr;
if(!strncmp(path, "/meta", 5)) return 0; while ((ctr = *(str++)) != '\0')
if(!strncmp(path, "/shared", 7) && !n_dumpwsc && !n_dumpwvc) return 1;
if(!strncmp(path, "/sys", 4)) return 0;
if(!strncmp(path, "/ticket/00000001/", 17))
{ {
const char *tmp = path + 17; const char *esc;
if(!strncmp(tmp, "00000002.tik", 8) && !n_dumpmen) return 1; // Menu switch (ctr)
if(strncmp(tmp, "00000002.tik", 8) && !n_dumpios) return 1; // IOSs {
return 0; case '"':
esc = "&qt;";
break;
case '*':
esc = "&st;";
break;
case ':':
esc = "&cl;";
break;
case '<':
esc = "&lt;";
break;
case '>':
esc = "&gt;";
break;
case '?':
esc = "&qm;";
break;
case '|':
esc = "&vb;";
break;
default:
*(ptr++) = ctr;
continue;
} }
if(!strncmp(path, "/ticket/00010001/", 17)) strcpy(ptr, esc);
{ ptr += 4;
const char *tmp = path + 17;
if(!strncmp(tmp, "48XXXXXX.tik", 2) && n_dumpwsc) return 0; // SC
if(strncmp(tmp, "48XXXXXX.tik", 2) && n_dumpwvc) return 0; // WW&VC
return 1;
} }
if(!strncmp(path, "/ticket/00010002/", 17) && !n_dumpwsc) return 1; // SC *ptr = '\0';
if(!strncmp(path, "/ticket/00010005/", 17) && !n_dumpwgs) return 1; // DLC?
if(!strncmp(path, "/ticket/00010008/", 17) && !n_dumpwsc) return 1; // Hidden SC
if(!strncmp(path, "/title/00000001/", 16))
{
const char *tmp = path + 16;
if(!strncmp(tmp, "00000002", 8) && n_dumpmen) return 0; // Menu
if(strncmp(tmp, "00000002", 8) && n_dumpios) return 0; // IOSs
return 1;
}
if(!strncmp(path, "/title/00010000/", 16) && !n_dumpwgs) return 1; // Saves
if(!strncmp(path, "/title/00010001/", 16))
{
const char *tmp = path + 16;
if(!strncmp(tmp, "48XXXXXX", 2) && n_dumpwsc) return 0; // SC
if(strncmp(tmp, "48XXXXXX", 2) && n_dumpwvc) return 0; // WW&VC
return 1;
}
if(!strncmp(path, "/title/00010002/", 16) && !n_dumpwsc) return 1; // SC
if(!strncmp(path, "/title/00010004/", 16) && !n_dumpwgs) return 1; // Saves
if(!strncmp(path, "/title/00010005/", 16) && !n_dumpwgs) return 1; // DLC
if(!strncmp(path, "/title/00010008/", 16) && !n_dumpwsc) return 1; // Hidden SC
if(!strncmp(path, "/tmp", 4)) return 0;
return 0;
} }
s32 Nand::__FlashNandFile(const char *source, const char *dest) s32 Nand::__FlashNandFile(const char *source, const char *dest)
@ -526,9 +518,7 @@ s32 Nand::__FlashNandFile(const char *source, const char *dest)
s32 Nand::__DumpNandFile(const char *source, const char *dest) s32 Nand::__DumpNandFile(const char *source, const char *dest)
{ {
if(__TestNandPath(source)) FileDone = 0;
return 0;
s32 fd = ISFS_Open(source, ISFS_OPEN_READ); s32 fd = ISFS_Open(source, ISFS_OPEN_READ);
if (fd < 0) if (fd < 0)
{ {
@ -536,6 +526,27 @@ s32 Nand::__DumpNandFile(const char *source, const char *dest)
return fd; return fd;
} }
fstats *status = (fstats *)MEM2_alloc(sizeof(fstats));
s32 ret = ISFS_GetFileStats(fd, status);
if (ret < 0)
{
gprintf("Error: ISFS_GetFileStats(%d) %d\n", fd, ret);
ISFS_Close(fd);
MEM2_free(status);
return ret;
}
if(fake)
{
NandSize += status->file_length;
if(showprogress)
dumper(NandSize, 0x1f400000, 0x1f400000, NandSize, FilesDone, FoldersDone, (char *)"", data);
ISFS_Close(fd);
MEM2_free(status);
return 0;
}
if(__FileExists(dest)) if(__FileExists(dest))
remove(dest); remove(dest);
@ -547,18 +558,7 @@ s32 Nand::__DumpNandFile(const char *source, const char *dest)
return 0; return 0;
} }
fstats *status = (fstats *)MEM2_alloc(sizeof(fstats)); gprintf("Dumping: %s (%ukb)...", source, (status->file_length / 0x400)+1);
s32 ret = ISFS_GetFileStats(fd, status);
if (ret < 0)
{
gprintf("Error: ISFS_GetFileStats(%d) %d\n", fd, ret);
ISFS_Close(fd);
SAFE_CLOSE(file);
MEM2_free(status);
return ret;
}
gprintf("Dumping: %s (%uKB)...", source, (status->file_length / 0x400)+1);
u8 *buffer = (u8 *)MEM2_alloc(BLOCK); u8 *buffer = (u8 *)MEM2_alloc(BLOCK);
u32 toread = status->file_length; u32 toread = status->file_length;
@ -590,13 +590,28 @@ s32 Nand::__DumpNandFile(const char *source, const char *dest)
return ret; return ret;
} }
toread -= size; toread -= size;
NandDone += size;
FileDone += size;
if(showprogress)
{
const char *file = strrchr(source, '/')+1;
dumper(NandDone, NandSize, status->file_length, FileDone, FilesDone, FoldersDone, (char *)file, data);
}
}
FilesDone++;
if(showprogress)
{
const char *file = strrchr(source, '/')+1;
dumper(NandDone, NandSize, status->file_length, FileDone, FilesDone, FoldersDone, (char *)file, data);
} }
gprintf(" done!\n"); gprintf(" done!\n");
ISFS_Close(fd);
SAFE_CLOSE(file); SAFE_CLOSE(file);
ISFS_Close(fd);
MEM2_free(status); MEM2_free(status);
MEM2_free(buffer); MEM2_free(buffer);
return 1;
return 0;
} }
s32 Nand::__DumpNandFolder(const char *source, const char *dest) s32 Nand::__DumpNandFolder(const char *source, const char *dest)
@ -605,6 +620,7 @@ s32 Nand::__DumpNandFolder(const char *source, const char *dest)
int cnt, i; int cnt, i;
char nsource[ISFS_MAXPATH]; char nsource[ISFS_MAXPATH];
char ndest[MAX_FAT_PATH]; char ndest[MAX_FAT_PATH];
char tdest[MAX_FAT_PATH];
__GetNameList(source, &names, &cnt); __GetNameList(source, &names, &cnt);
@ -617,20 +633,22 @@ s32 Nand::__DumpNandFolder(const char *source, const char *dest)
if(!names[i].type) if(!names[i].type)
{ {
Asciify2(nsource); __FATify(tdest, nsource);
snprintf(ndest, sizeof(ndest), "%s%s", dest, nsource); snprintf(ndest, sizeof(ndest), "%s%s", dest, tdest);
__DumpNandFile(nsource, ndest); __DumpNandFile(nsource, ndest);
} }
else else
{ {
if(!__TestNandPath(nsource)) if(!fake)
{ {
CreatePath("%s%s", dest, nsource); __FATify(tdest, nsource);
CreatePath("%s%s", dest, tdest);
FoldersDone++;
}
__DumpNandFolder(nsource, dest); __DumpNandFolder(nsource, dest);
} }
} }
}
SAFE_FREE(names); SAFE_FREE(names);
return 0; return 0;
} }
@ -645,8 +663,6 @@ void Nand::CreatePath(const char *path, ...)
if(folder[strlen(folder)-1] == '/') if(folder[strlen(folder)-1] == '/')
folder[strlen(folder)-1] = 0; folder[strlen(folder)-1] = 0;
Asciify2(folder);
DIR *d; DIR *d;
d = opendir(folder); d = opendir(folder);
@ -665,16 +681,14 @@ void Nand::CreatePath(const char *path, ...)
SAFE_FREE(folder); SAFE_FREE(folder);
} }
s32 Nand::DoNandDump(const char *source, const char *dest, bool dumpios, bool dumpwgs, bool dumpwsc, bool dumpwvc, bool dumpmen) s32 Nand::DoNandDump(const char *source, const char *dest, bool dumpwgs, dump_callback_t i_dumper, void *i_data)
{ {
n_dumpios = dumpios; data = i_data;
dumper = i_dumper;
n_dumpwgs = dumpwgs; n_dumpwgs = dumpwgs;
n_dumpwsc = dumpwsc; fake = false;
n_dumpwvc = dumpwvc; showprogress = true;
n_dumpmen = dumpmen;
u32 temp = 0; u32 temp = 0;
s32 ret = ISFS_ReadDir(source, NULL, &temp); s32 ret = ISFS_ReadDir(source, NULL, &temp);
if(ret < 0) if(ret < 0)
{ {
@ -688,10 +702,36 @@ s32 Nand::DoNandDump(const char *source, const char *dest, bool dumpios, bool du
{ {
__DumpNandFolder(source, dest); __DumpNandFolder(source, dest);
} }
return 0; return 0;
} }
s32 Nand::CalcDumpSpace(const char *source, bool dumpwgs, dump_callback_t i_dumper, void *i_data)
{
data = i_data;
dumper = i_dumper;
n_dumpwgs = dumpwgs;
fake = true;
showprogress = true;
u32 temp = 0;
s32 ret = ISFS_ReadDir(source, NULL, &temp);
if(ret < 0)
__DumpNandFile(source, "");
else
__DumpNandFolder(source, "");
return NandSize;
}
void Nand::ResetCounters(void)
{
NandSize = 0;
FilesDone = 0;
FoldersDone = 0;
NandDone = 0;
}
s32 Nand::CreateConfig(const char *path) s32 Nand::CreateConfig(const char *path)
{ {
CreatePath(path); CreatePath(path);
@ -702,6 +742,9 @@ s32 Nand::CreateConfig(const char *path)
CreatePath("%s/title/00000001/00000002", path); CreatePath("%s/title/00000001/00000002", path);
CreatePath("%s/title/00000001/00000002/data", path); CreatePath("%s/title/00000001/00000002/data", path);
fake = false;
showprogress = false;
bzero(cfgpath, MAX_FAT_PATH+1); bzero(cfgpath, MAX_FAT_PATH+1);
bzero(settxtpath, MAX_FAT_PATH+1); bzero(settxtpath, MAX_FAT_PATH+1);

View File

@ -23,6 +23,8 @@
#define BLOCK 2048 #define BLOCK 2048
typedef void (*dump_callback_t)(int dumpstat, int dumpprog, int filestat, int fileprog, int files, int folders, char *tmess, void *user_data);
/* 'NAND Device' structure */ /* 'NAND Device' structure */
typedef struct nandDevice typedef struct nandDevice
{ {
@ -70,7 +72,9 @@ class Nand
s32 CreateConfig(const char *path); s32 CreateConfig(const char *path);
s32 Do_Region_Change(string id); s32 Do_Region_Change(string id);
s32 DoNandDump(const char *source, const char *dest, bool dumpios, bool dumpwgs, bool dumpwsc, bool dumpwvc, bool dumpmen); 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);
void ResetCounters(void);
private: private:
Nand() : MountedDevice(0), EmuDevice(REAL_NAND), Disabled(true), Partition(0), FullMode(0x100), NandPath() {} Nand() : MountedDevice(0), EmuDevice(REAL_NAND), Disabled(true), Partition(0), FullMode(0x100), NandPath() {}
@ -90,20 +94,26 @@ class Nand
u32 __configsetbigarray(const char *item, void *val, u32 size); u32 __configsetbigarray(const char *item, void *val, u32 size);
u32 __configsetsetting(const char *item, const char *val); u32 __configsetsetting(const char *item, const char *val);
bool __FileExists(const char *path, ...); bool __FileExists(const char *path, ...);
u32 __TestNandPath(const char *path); void __FATify(char *dst, const char *src);
s32 __Unescaped2x(const char *path);
s32 __FlashNandFile(const char *source, const char *dest); s32 __FlashNandFile(const char *source, const char *dest);
s32 __DumpNandFile(const char *source, const char *dest); s32 __DumpNandFile(const char *source, const char *dest);
s32 __DumpNandFolder(const char *source, const char *dest); s32 __DumpNandFolder(const char *source, const char *dest);
u32 MountedDevice; u32 MountedDevice;
u32 EmuDevice; u32 EmuDevice;
u32 NandSize;
u32 NandDone;
u32 FileDone;
u32 FilesDone;
u32 FoldersDone;
bool Disabled; bool Disabled;
bool n_dumpios;
bool n_dumpwgs; bool n_dumpwgs;
bool n_dumpwsc; bool fake;
bool n_dumpwvc; bool showprogress;
bool n_dumpmen;
void *data;
dump_callback_t dumper;
u32 Partition ATTRIBUTE_ALIGN(32); u32 Partition ATTRIBUTE_ALIGN(32);
u32 FullMode ATTRIBUTE_ALIGN(32); u32 FullMode ATTRIBUTE_ALIGN(32);
char NandPath[32] ATTRIBUTE_ALIGN(32); char NandPath[32] ATTRIBUTE_ALIGN(32);

View File

@ -4,7 +4,7 @@
#define APPDATA_DIR "wiiflow" #define APPDATA_DIR "wiiflow"
#define APPDATA_DIR2 "apps/wiiflow" #define APPDATA_DIR2 "apps/wiiflow"
#define STDEMU_DIR "/wiiflow/nandemu" #define STDEMU_DIR "/wiiflow/nandemu/"
#define GAMES_DIR "%s:/wbfs" #define GAMES_DIR "%s:/wbfs"
#define HOMEBREW_DIR "%s:/apps" #define HOMEBREW_DIR "%s:/apps"
#define DML_DIR "%s:/games" #define DML_DIR "%s:/games"

View File

@ -1026,6 +1026,7 @@ void CMenu::_buildMenus(void)
_initCategorySettingsMenu(theme); _initCategorySettingsMenu(theme);
_initSystemMenu(theme); _initSystemMenu(theme);
_initGameInfoMenu(theme); _initGameInfoMenu(theme);
_initNandEmuMenu(theme);
_loadCFCfg(theme); _loadCFCfg(theme);
} }

View File

@ -192,10 +192,8 @@ private:
u32 m_configLblPartition; u32 m_configLblPartition;
u32 m_configBtnPartitionP; u32 m_configBtnPartitionP;
u32 m_configBtnPartitionM; u32 m_configBtnPartitionM;
u32 m_configLblEmulationVal; u32 m_configLblNandEmu;
u32 m_configLblEmulation; u32 m_configBtnNandEmu;
u32 m_configBtnEmulationM;
u32 m_configBtnEmulationP;
u32 m_configLblUser[4]; u32 m_configLblUser[4];
u32 m_configAdvLblTheme; u32 m_configAdvLblTheme;
u32 m_configAdvLblCurTheme; u32 m_configAdvLblCurTheme;
@ -554,6 +552,37 @@ private:
u32 m_categoryBtnCats[21]; u32 m_categoryBtnCats[21];
u32 m_categoryLblUser[4]; u32 m_categoryLblUser[4];
u8 m_max_categories; u8 m_max_categories;
// NandEmulation menu
std::string m_saveExtGameId;
bool m_nandext;
bool m_fulldump;
bool m_sgdump;
bool m_saveall;
bool m_forceext;
//int m_saveExtMode;
u32 m_nandemuLblTitle;
u32 m_nandemuBtnBack;
u32 m_nandemuLblEmulationVal;
u32 m_nandemuLblEmulation;
u32 m_nandemuBtnEmulationM;
u32 m_nandemuBtnEmulationP;
u32 m_nandemuLblSaveDump;
u32 m_nandemuBtnAll;
u32 m_nandemuBtnMissing;
u32 m_nandemuLblNandDump;
u32 m_nandemuBtnNandDump;
u32 m_nandfileLblMessage;
u32 m_nandemuLblMessage;
u32 m_nandfileLblDialog;
u32 m_nandfinLblDialog;
u32 m_nandemuLblDialog;
u32 m_nandfilePBar;
u32 m_nandemuPBar;
u32 m_nandemuBtnExtract;
u32 m_nandemuBtnDisable;
u32 m_nandemuLblInit;
u32 m_nandemuLblUser[4];
STexture m_nandemuBg;
// Zones // Zones
SZone m_mainPrevZone; SZone m_mainPrevZone;
SZone m_mainNextZone; SZone m_mainNextZone;
@ -651,6 +680,7 @@ private:
mutex_t m_mutex; mutex_t m_mutex;
wstringEx m_thrdMessage; wstringEx m_thrdMessage;
volatile float m_thrdProgress; volatile float m_thrdProgress;
volatile float m_fileProgress;
volatile bool m_thrdMessageAdded; volatile bool m_thrdMessageAdded;
volatile bool m_gameSelected; volatile bool m_gameSelected;
GuiSound m_gameSound; GuiSound m_gameSound;
@ -802,6 +832,7 @@ private:
void _initCategorySettingsMenu(SThemeData &theme); void _initCategorySettingsMenu(SThemeData &theme);
void _initSystemMenu(SThemeData &theme); void _initSystemMenu(SThemeData &theme);
void _initGameInfoMenu(SThemeData &theme); void _initGameInfoMenu(SThemeData &theme);
void _initNandEmuMenu(CMenu::SThemeData &theme);
// //
void _textCategorySettings(void); void _textCategorySettings(void);
void _textCheatSettings(void); void _textCheatSettings(void);
@ -822,6 +853,7 @@ private:
void _textWBFS(void); void _textWBFS(void);
void _textGameSettings(void); void _textGameSettings(void);
void _textGameInfo(void); void _textGameInfo(void);
void _textNandEmu(void);
// //
void _hideCheatSettings(bool instant = false); void _hideCheatSettings(bool instant = false);
void _hideError(bool instant = false); void _hideError(bool instant = false);
@ -844,6 +876,7 @@ private:
void _hideSystem(bool instant = false); void _hideSystem(bool instant = false);
void _hideGameInfo(bool instant = false); void _hideGameInfo(bool instant = false);
void _hideCheatDownload(bool instant = false); void _hideCheatDownload(bool instant = false);
void _hideNandEmu(bool instant = false);
// //
void _showError(void); void _showError(void);
void _showMain(void); void _showMain(void);
@ -872,6 +905,7 @@ private:
void _updateBg(void); void _updateBg(void);
void _drawBg(void); void _drawBg(void);
void _updateText(void); void _updateText(void);
void _showNandEmu(void);
// //
void _config(int page); void _config(int page);
int _config1(void); int _config1(void);
@ -880,6 +914,9 @@ private:
int _config4(void); int _config4(void);
int _configAdv(void); int _configAdv(void);
int _configSnd(void); int _configSnd(void);
int _NandEmuCfg(void);
int _AutoCreateNand(void);
int _AutoExtractSave(string gameId);
void _game(bool launch = false); void _game(bool launch = false);
void _download(std::string gameId = std::string()); void _download(std::string gameId = std::string());
bool _code(char code[4], bool erase = false); bool _code(char code[4], bool erase = false);
@ -950,6 +987,7 @@ private:
wstringEx _getNoticeTranslation(int sorting, wstringEx curLetter); wstringEx _getNoticeTranslation(int sorting, wstringEx curLetter);
// //
void _setThrdMsg(const wstringEx &msg, float progress); void _setThrdMsg(const wstringEx &msg, float progress);
void _setDumpMsg(const wstringEx &msg, float progress, float fileprog);
int _coverDownloader(bool missingOnly); int _coverDownloader(bool missingOnly);
static int _coverDownloaderAll(CMenu *m); static int _coverDownloaderAll(CMenu *m);
static int _coverDownloaderMissing(CMenu *m); static int _coverDownloaderMissing(CMenu *m);
@ -967,12 +1005,21 @@ private:
void _getGrabStatus(void); void _getGrabStatus(void);
static void _addDiscProgress(int status, int total, void *user_data); static void _addDiscProgress(int status, int total, void *user_data);
static void _Messenger(int message, int info, char *cinfo, void *user_data); static void _Messenger(int message, int info, char *cinfo, void *user_data);
static void _ShowProgress(int dumpstat, int dumpprog, int filestat, int fileprog, int files, int folders, char *tmess, void *user_data);
static int _gameInstaller(void *obj); static int _gameInstaller(void *obj);
static int _GCgameInstaller(void *obj); static int _GCgameInstaller(void *obj);
static int _GCcopyGame(void *obj); static int _GCcopyGame(void *obj);
float m_progress; float m_progress;
float m_fprogress;
int m_fileprog;
int m_filesize;
int m_dumpsize;
int m_filesdone;
int m_foldersdone;
int m_nandexentry;
wstringEx _optBoolToString(int b); wstringEx _optBoolToString(int b);
void _stopSounds(void); void _stopSounds(void);
static int _NandDumper(void *obj);
static u32 _downloadCheatFileAsync(void *obj); static u32 _downloadCheatFileAsync(void *obj);
@ -1002,6 +1049,7 @@ private:
static const SOption _vidModePatch[4]; static const SOption _vidModePatch[4];
static const SOption _hooktype[8]; static const SOption _hooktype[8];
static const SOption _exitTo[6]; static const SOption _exitTo[6];
static const SOption _DumpMode[4];
static std::map<u8, u8> _installed_cios; static std::map<u8, u8> _installed_cios;
typedef std::map<u8, u8>::iterator CIOSItr; typedef std::map<u8, u8>::iterator CIOSItr;
static int _version[9]; static int _version[9];

View File

@ -6,54 +6,11 @@
#include "loader/alt_ios.h" #include "loader/alt_ios.h"
#include "gecko/gecko.h" #include "gecko/gecko.h"
using namespace std; using namespace std;
static inline int loopNum(int i, int s)
{
return i < 0 ? (s - (-i % s)) % s : i % s;
}
const int CMenu::_nbCfgPages = 6; const int CMenu::_nbCfgPages = 6;
static const int g_curPage = 1; static const int g_curPage = 1;
void CMenu::_enableNandEmu(bool fromconfig)
{
bool disable = true;
int i = m_current_view == COVERFLOW_CHANNEL && min(max(0, m_cfg.getInt("NAND", "emulation", 0)), (int)ARRAY_SIZE(CMenu::_NandEmu) - 1);
gprintf("i: %i\n",i);
if (i>0 || m_current_view != COVERFLOW_CHANNEL)
disable = false;
if(!disable)
{
Nand::Instance()->Disable_Emu();
bool isD2XnewerThanV6 = false;
iosinfo_t * iosInfo = cIOSInfo::GetInfo(mainIOS);
if (iosInfo->version > 6)
isD2XnewerThanV6 = true;
if(m_current_view == COVERFLOW_CHANNEL && m_cfg.getInt("NAND", "emulation", 0) > 0)
Nand::Instance()->Enable_Emu();
u8 limiter = 0;
s8 direction = m_btnMgr.selected(m_configBtnPartitionP) ? 1 : -1;
if (!fromconfig)
direction = 0;
currentPartition = loopNum(currentPartition + direction, (int)USB8);
while(!DeviceHandler::Instance()->IsInserted(currentPartition) ||
((m_current_view == COVERFLOW_CHANNEL || m_current_view == COVERFLOW_EMU) && (DeviceHandler::Instance()->GetFSType(currentPartition) != PART_FS_FAT ||
(!isD2XnewerThanV6 && DeviceHandler::Instance()->PathToDriveType(m_appDir.c_str()) == currentPartition) ||
(!isD2XnewerThanV6 && DeviceHandler::Instance()->PathToDriveType(m_dataDir.c_str()) == currentPartition))) ||
((m_current_view == COVERFLOW_HOMEBREW || m_current_view == COVERFLOW_DML) && DeviceHandler::Instance()->GetFSType(currentPartition) == PART_FS_WBFS))
{
currentPartition = loopNum(currentPartition + direction, (int)USB8);
if (limiter > 10) break;
limiter++;
}
gprintf("Next item: %s\n", DeviceName[currentPartition]);
m_cfg.setInt(_domainFromView(), "partition", currentPartition);
}
}
void CMenu::_hideConfig(bool instant) void CMenu::_hideConfig(bool instant)
{ {
m_btnMgr.hide(m_configLblTitle, instant); m_btnMgr.hide(m_configLblTitle, instant);
@ -71,10 +28,8 @@ void CMenu::_hideConfig(bool instant)
m_btnMgr.hide(m_configLblParental, instant); m_btnMgr.hide(m_configLblParental, instant);
m_btnMgr.hide(m_configBtnUnlock, instant); m_btnMgr.hide(m_configBtnUnlock, instant);
m_btnMgr.hide(m_configBtnSetCode, instant); m_btnMgr.hide(m_configBtnSetCode, instant);
m_btnMgr.hide(m_configLblEmulationVal, instant); m_btnMgr.hide(m_configLblNandEmu, instant);
m_btnMgr.hide(m_configLblEmulation, instant); m_btnMgr.hide(m_configBtnNandEmu, instant);
m_btnMgr.hide(m_configBtnEmulationP, instant);
m_btnMgr.hide(m_configBtnEmulationM, instant);
for (u32 i = 0; i < ARRAY_SIZE(m_configLblUser); ++i) for (u32 i = 0; i < ARRAY_SIZE(m_configLblUser); ++i)
if (m_configLblUser[i] != -1u) if (m_configLblUser[i] != -1u)
m_btnMgr.hide(m_configLblUser[i], instant); m_btnMgr.hide(m_configLblUser[i], instant);
@ -118,25 +73,8 @@ void CMenu::_showConfig(void)
m_btnMgr.setText(m_configLblPage, wfmt(L"%i / %i", g_curPage, m_locked ? g_curPage + 1 : CMenu::_nbCfgPages)); m_btnMgr.setText(m_configLblPage, wfmt(L"%i / %i", g_curPage, m_locked ? g_curPage + 1 : CMenu::_nbCfgPages));
if ((m_current_view == COVERFLOW_CHANNEL || m_current_view == COVERFLOW_USB) && !m_locked) m_btnMgr.show(m_configLblNandEmu);
{ m_btnMgr.show(m_configBtnNandEmu);
m_btnMgr.show(m_configLblEmulation);
m_btnMgr.show(m_configLblEmulationVal);
m_btnMgr.show(m_configBtnEmulationP);
m_btnMgr.show(m_configBtnEmulationM);
if (m_current_view == COVERFLOW_CHANNEL)
{
m_btnMgr.setText(m_configLblEmulation, _t("cfg12", L"NAND Emulation"));
i = min(max(0, m_cfg.getInt("NAND", "emulation", 0)), (int)ARRAY_SIZE(CMenu::_NandEmu) - 1);
m_btnMgr.setText(m_configLblEmulationVal, _t(CMenu::_NandEmu[i].id, CMenu::_NandEmu[i].text));
}
else if (m_current_view == COVERFLOW_USB)
{
m_btnMgr.setText(m_configLblEmulation, _t("cfgg24", L"Savegame Emulation"));
i = min(max(0, m_cfg.getInt("GAMES", "save_emulation", 0)), (int)ARRAY_SIZE(CMenu::_GlobalSaveEmu) - 1);
m_btnMgr.setText(m_configLblEmulationVal, _t(CMenu::_GlobalSaveEmu[i].id, CMenu::_GlobalSaveEmu[i].text));
}
}
} }
void CMenu::_config(int page) void CMenu::_config(int page)
@ -245,14 +183,13 @@ int CMenu::_config1(void)
_enableNandEmu(true); _enableNandEmu(true);
_showConfig(); _showConfig();
} }
else if (!m_locked && (m_btnMgr.selected(m_configBtnEmulationP) || m_btnMgr.selected(m_configBtnEmulationM))) else if (!m_locked && m_btnMgr.selected(m_configBtnNandEmu))
{ {
s8 direction = m_btnMgr.selected(m_configBtnEmulationP) ? 1 : -1; m_cf.stopCoverLoader(true);
if (m_current_view == COVERFLOW_CHANNEL) _hideConfig();
m_cfg.setInt("NAND", "emulation", (int)loopNum((u32)m_cfg.getInt("NAND", "emulation", 0) + direction, ARRAY_SIZE(CMenu::_NandEmu))); _NandEmuCfg();
else if (m_current_view == COVERFLOW_USB)
m_cfg.setInt("GAMES", "save_emulation", (int)loopNum((u32)m_cfg.getInt("GAMES", "save_emulation", 0) + direction, ARRAY_SIZE(CMenu::_GlobalSaveEmu)));
_showConfig(); _showConfig();
m_cf.startCoverLoader();
} }
} }
} }
@ -295,11 +232,8 @@ void CMenu::_initConfigMenu(CMenu::SThemeData &theme)
m_configLblPartition = _addLabel(theme, "CONFIG/PARTITION_BTN", theme.btnFont, L"", 456, 250, 88, 56, theme.btnFontColor, FTGX_JUSTIFY_CENTER | FTGX_ALIGN_MIDDLE, theme.btnTexC); m_configLblPartition = _addLabel(theme, "CONFIG/PARTITION_BTN", theme.btnFont, L"", 456, 250, 88, 56, theme.btnFontColor, FTGX_JUSTIFY_CENTER | FTGX_ALIGN_MIDDLE, theme.btnTexC);
m_configBtnPartitionM = _addPicButton(theme, "CONFIG/PARTITION_MINUS", theme.btnTexMinus, theme.btnTexMinusS, 400, 250, 56, 56); m_configBtnPartitionM = _addPicButton(theme, "CONFIG/PARTITION_MINUS", theme.btnTexMinus, theme.btnTexMinusS, 400, 250, 56, 56);
m_configBtnPartitionP = _addPicButton(theme, "CONFIG/PARTITION_PLUS", theme.btnTexPlus, theme.btnTexPlusS, 544, 250, 56, 56); m_configBtnPartitionP = _addPicButton(theme, "CONFIG/PARTITION_PLUS", theme.btnTexPlus, theme.btnTexPlusS, 544, 250, 56, 56);
m_configLblEmulation = _addLabel(theme, "CONFIG/EMU_SAVE", theme.lblFont, L"", 40, 310, 340, 56, theme.lblFontColor, FTGX_JUSTIFY_LEFT | FTGX_ALIGN_MIDDLE); m_configLblNandEmu = _addLabel(theme, "CONFIG/NANDEMU", theme.lblFont, L"", 40, 310, 340, 56, theme.lblFontColor, FTGX_JUSTIFY_LEFT | FTGX_ALIGN_MIDDLE);
m_configLblEmulationVal = _addLabel(theme, "CONFIG/EMU_SAVE_BTN_GLOBAL", theme.btnFont, L"", 456, 310, 88, 56, theme.btnFontColor, FTGX_JUSTIFY_CENTER | FTGX_ALIGN_MIDDLE, theme.btnTexC); m_configBtnNandEmu = _addButton(theme, "CONFIG/NANDEMU_BTN", theme.btnFont, L"", 400, 310, 200, 56, theme.btnFontColor);m_configLblPage = _addLabel(theme, "CONFIG/PAGE_BTN", theme.btnFont, L"", 76, 400, 80, 56, theme.btnFontColor, FTGX_JUSTIFY_CENTER | FTGX_ALIGN_MIDDLE, theme.btnTexC);
m_configBtnEmulationM = _addPicButton(theme, "CONFIG/EMU_SAVE_MINUS", theme.btnTexMinus, theme.btnTexMinusS, 400, 310, 56, 56);
m_configBtnEmulationP = _addPicButton(theme, "CONFIG/EMU_SAVE_PLUS", theme.btnTexPlus, theme.btnTexPlusS, 544, 310, 56, 56);
m_configLblPage = _addLabel(theme, "CONFIG/PAGE_BTN", theme.btnFont, L"", 76, 400, 80, 56, theme.btnFontColor, FTGX_JUSTIFY_CENTER | FTGX_ALIGN_MIDDLE, theme.btnTexC);
m_configBtnPageM = _addPicButton(theme, "CONFIG/PAGE_MINUS", theme.btnTexMinus, theme.btnTexMinusS, 20, 400, 56, 56); m_configBtnPageM = _addPicButton(theme, "CONFIG/PAGE_MINUS", theme.btnTexMinus, theme.btnTexMinusS, 20, 400, 56, 56);
m_configBtnPageP = _addPicButton(theme, "CONFIG/PAGE_PLUS", theme.btnTexPlus, theme.btnTexPlusS, 156, 400, 56, 56); m_configBtnPageP = _addPicButton(theme, "CONFIG/PAGE_PLUS", theme.btnTexPlus, theme.btnTexPlusS, 156, 400, 56, 56);
m_configBtnBack = _addButton(theme, "CONFIG/BACK_BTN", theme.btnFont, L"", 420, 400, 200, 56, theme.btnFontColor); m_configBtnBack = _addButton(theme, "CONFIG/BACK_BTN", theme.btnFont, L"", 420, 400, 200, 56, theme.btnFontColor);
@ -315,10 +249,8 @@ void CMenu::_initConfigMenu(CMenu::SThemeData &theme)
_setHideAnim(m_configLblPartition, "CONFIG/PARTITION_BTN", 0, 0, 1.f, -1.f); _setHideAnim(m_configLblPartition, "CONFIG/PARTITION_BTN", 0, 0, 1.f, -1.f);
_setHideAnim(m_configBtnPartitionM, "CONFIG/PARTITION_MINUS", 0, 0, 1.f, -1.f); _setHideAnim(m_configBtnPartitionM, "CONFIG/PARTITION_MINUS", 0, 0, 1.f, -1.f);
_setHideAnim(m_configBtnPartitionP, "CONFIG/PARTITION_PLUS", 0, 0, 1.f, -1.f); _setHideAnim(m_configBtnPartitionP, "CONFIG/PARTITION_PLUS", 0, 0, 1.f, -1.f);
_setHideAnim(m_configLblEmulation, "CONFIG/EMU_SAVE", 100, 0, -2.f, 0.f); _setHideAnim(m_configLblNandEmu, "CONFIG/NANDEMU", 100, 0, -2.f, 0.f);
_setHideAnim(m_configLblEmulationVal, "CONFIG/EMU_SAVE_BTN_GLOBAL", 0, 0, 1.f, -1.f); _setHideAnim(m_configBtnNandEmu, "CONFIG/NANDEMU_BTN", 0, 0, 1.f, -1.f);
_setHideAnim(m_configBtnEmulationM, "CONFIG/EMU_SAVE_MINUS", 0, 0, 1.f, -1.f);
_setHideAnim(m_configBtnEmulationP, "CONFIG/EMU_SAVE_PLUS", 0, 0, 1.f, -1.f);
_setHideAnim(m_configBtnBack, "CONFIG/BACK_BTN", 0, 0, -2.f, 0.f); _setHideAnim(m_configBtnBack, "CONFIG/BACK_BTN", 0, 0, -2.f, 0.f);
_setHideAnim(m_configLblPage, "CONFIG/PAGE_BTN", 0, 0, 1.f, -1.f); _setHideAnim(m_configLblPage, "CONFIG/PAGE_BTN", 0, 0, 1.f, -1.f);
_setHideAnim(m_configBtnPageM, "CONFIG/PAGE_MINUS", 0, 0, 1.f, -1.f); _setHideAnim(m_configBtnPageM, "CONFIG/PAGE_MINUS", 0, 0, 1.f, -1.f);
@ -335,7 +267,8 @@ void CMenu::_textConfig(void)
m_btnMgr.setText(m_configLblParental, _t("cfg5", L"Parental control")); m_btnMgr.setText(m_configLblParental, _t("cfg5", L"Parental control"));
m_btnMgr.setText(m_configBtnUnlock, _t("cfg6", L"Unlock")); m_btnMgr.setText(m_configBtnUnlock, _t("cfg6", L"Unlock"));
m_btnMgr.setText(m_configBtnSetCode, _t("cfg7", L"Set code")); m_btnMgr.setText(m_configBtnSetCode, _t("cfg7", L"Set code"));
m_btnMgr.setText(m_configLblPartitionName, _t("cfgp1", L"Game Partition")); m_btnMgr.setText(m_configLblPartitionName, _t("cfgp1", L"Game Partition"));
m_btnMgr.setText(m_configBtnBack, _t("cfg10", L"Back")); m_btnMgr.setText(m_configBtnBack, _t("cfg10", L"Back"));
m_btnMgr.setText(m_configLblNandEmu, _t("cfg13", L"Nand emulation settings"));
m_btnMgr.setText(m_configBtnNandEmu, _t("cfg14", L"Set"));
} }

View File

@ -204,6 +204,7 @@ const CMenu::SOption CMenu::_hooktype[8] = {
{ "hooktype6", L"OSSleepThread" }, { "hooktype6", L"OSSleepThread" },
{ "hooktype7", L"AXNextFrame" }, { "hooktype7", L"AXNextFrame" },
}; };
/* /*
0 No Hook 0 No Hook
1 VBI 1 VBI
@ -215,6 +216,13 @@ const CMenu::SOption CMenu::_hooktype[8] = {
7 AXNextFrame Hook 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" },
};
std::map<u8, u8> CMenu::_installed_cios; std::map<u8, u8> CMenu::_installed_cios;
u8 banner_title[84]; u8 banner_title[84];
@ -1071,6 +1079,27 @@ void CMenu::_launchGame(dir_discHdr *hdr, bool dvd)
if(!dvd && emuSave) if(!dvd && emuSave)
{ {
bool emuPartIsValid = false;
for(u8 i = emuPartition; i <= USB8; ++i)
{
if(!DeviceHandler::Instance()->IsInserted(emuPartition) || DeviceHandler::Instance()->GetFSType(emuPartition) != PART_FS_FAT)
{
emuPartition++;
continue;
}
else
{
emuPartIsValid = true;
break;
}
}
if(!emuPartIsValid)
{
error(sfmt("No valid FAT partition found for nandemulation!"));
return;
}
bool createnand = false; bool createnand = false;
char basepath[64]; char basepath[64];
if(emuPath.size() == 0) if(emuPath.size() == 0)
@ -1105,18 +1134,20 @@ void CMenu::_launchGame(dir_discHdr *hdr, bool dvd)
if(createnand) if(createnand)
{ {
#ifdef ENABLEDUMPER _hideWaitMessage();
bool dumpios = m_cfg.getBool("NAND", "nanddumpios", false); _AutoCreateNand();
bool dumpgs = m_cfg.getBool("NAND", "nanddumpgamesaves", false); _showWaitMessage();
bool dumpsc = m_cfg.getBool("NAND", "nanddumpsyschannels", false);
bool dumpwvc = m_cfg.getBool("NAND", "nanddumpwwchannels", true);
bool dumpmen = m_cfg.getBool("NAND", "nanddumpsysmenu", false);
Nand::Instance()->DoNandDump("/", basepath, dumpios, dumpgs, dumpsc, dumpwvc, dumpmen);
#endif
} }
if(emuSave == 2 || emuSave > 3) if(emuSave == 2 || emuSave > 3)
{ {
if(emuSave == 2)
{
m_forceext = false;
_hideWaitMessage();
_AutoExtractSave(id);
_showWaitMessage();
}
CreateSavePath(basepath, hdr); CreateSavePath(basepath, hdr);
} }
if(emuSave > 2) if(emuSave > 2)

View File

@ -143,9 +143,39 @@ void CMenu::_showMain(void)
if (m_gameList.empty()) if (m_gameList.empty())
{ {
switch(m_current_view)
{
case COVERFLOW_USB:
case COVERFLOW_DML:
m_btnMgr.setText(m_mainLblInit, _t("main2", L"Welcome to WiiFlow. I have not found any games. Click Install to install games, or Select partition to select your partition type."), true);
m_btnMgr.show(m_mainBtnInit); m_btnMgr.show(m_mainBtnInit);
m_btnMgr.show(m_mainBtnInit2); m_btnMgr.show(m_mainBtnInit2);
m_btnMgr.show(m_mainLblInit); m_btnMgr.show(m_mainLblInit);
break;
case COVERFLOW_CHANNEL:
if(!m_cfg.getBool("NAND", "disable", true))
{
Nand::Instance()->Disable_Emu();
_hideMain();
if(!_AutoCreateNand())
m_cfg.setBool("NAND", "disable", true);
_loadList();
_showMain();
_initCF();
}
break;
case COVERFLOW_HOMEBREW:
m_btnMgr.setText(m_mainLblInit, _t("main4", L"Welcome to WiiFlow. I have not found any homebrew apps. Select partition to select your partition type."), true);
m_btnMgr.show(m_mainBtnInit2);
m_btnMgr.show(m_mainLblInit);
break;
case COVERFLOW_EMU:
m_btnMgr.setText(m_mainLblInit, _t("main5", L"Welcome to WiiFlow. I have not found any emulator plugins or games. Select partition to select your partition type."), true);
m_btnMgr.show(m_mainBtnInit2);
m_btnMgr.show(m_mainLblInit);
break;
}
} }
} }
@ -913,7 +943,7 @@ void CMenu::_textMain(void)
{ {
m_btnMgr.setText(m_mainBtnInit, _t("main1", L"Install Game")); m_btnMgr.setText(m_mainBtnInit, _t("main1", L"Install Game"));
m_btnMgr.setText(m_mainBtnInit2, _t("main3", L"Select Partition")); m_btnMgr.setText(m_mainBtnInit2, _t("main3", L"Select Partition"));
m_btnMgr.setText(m_mainLblInit, _t("main2", L"Welcome to WiiFlow. I have not found any games. Click Install to install games, or Select partition to select your partition type."), true); //m_btnMgr.setText(m_mainLblInit, _t("main2", L"Welcome to WiiFlow. I have not found any games. Click Install to install games, or Select partition to select your partition type."), true);
} }
wstringEx CMenu::_getNoticeTranslation(int sorting, wstringEx curLetter) wstringEx CMenu::_getNoticeTranslation(int sorting, wstringEx curLetter)

View File

@ -0,0 +1,640 @@
#include "menu.hpp"
#include "nand.hpp"
#include "sys.h"
#include "loader/cios.hpp"
#include "loader/alt_ios.h"
#include "lockMutex.hpp"
#include "gecko/gecko.h"
#include "defines.h"
using namespace std;
static inline int loopNum(int i, int s)
{
return i < 0 ? (s - (-i % s)) % s : i % s;
}
static bool _saveExcists(const char *path)
{
DIR *d;
d = opendir(path);
if(!d)
{
return false;
}
else
{
closedir(d);
return true;
}
}
static bool _nandSaveExcists(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)
{
bool disable = true;
int i = m_current_view == COVERFLOW_CHANNEL && min(max(0, m_cfg.getInt("NAND", "emulation", 0)), (int)ARRAY_SIZE(CMenu::_NandEmu) - 1);
gprintf("i: %i\n",i);
if (i>0 || m_current_view != COVERFLOW_CHANNEL)
disable = false;
if(!disable)
{
Nand::Instance()->Disable_Emu();
bool isD2XnewerThanV6 = false;
iosinfo_t * iosInfo = cIOSInfo::GetInfo(mainIOS);
if (iosInfo->version > 6)
isD2XnewerThanV6 = true;
if(m_current_view == COVERFLOW_CHANNEL && m_cfg.getInt("NAND", "emulation", 0) > 0)
Nand::Instance()->Enable_Emu();
u8 limiter = 0;
s8 direction = m_btnMgr.selected(m_configBtnPartitionP) ? 1 : -1;
if (!fromconfig)
direction = 0;
currentPartition = loopNum(currentPartition + direction, (int)USB8);
while(!DeviceHandler::Instance()->IsInserted(currentPartition) ||
(m_current_view == COVERFLOW_CHANNEL && (DeviceHandler::Instance()->GetFSType(currentPartition) != PART_FS_FAT ||
(!isD2XnewerThanV6 && DeviceHandler::Instance()->PathToDriveType(m_appDir.c_str()) == currentPartition) ||
(!isD2XnewerThanV6 && DeviceHandler::Instance()->PathToDriveType(m_dataDir.c_str()) == currentPartition))) ||
((m_current_view == COVERFLOW_HOMEBREW || m_current_view == COVERFLOW_DML) && DeviceHandler::Instance()->GetFSType(currentPartition) == PART_FS_WBFS))
{
currentPartition = loopNum(currentPartition + direction, (int)USB8);
if (limiter > 10) break;
limiter++;
}
gprintf("Next item: %s\n", DeviceName[currentPartition]);
m_cfg.setInt(_domainFromView(), "partition", currentPartition);
}
}
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, 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.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_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_nandemuBtnExtract, instant);
m_btnMgr.hide(m_nandemuBtnDisable, instant);
m_btnMgr.hide(m_nandemuLblInit, 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);
int i;
if((m_current_view == COVERFLOW_CHANNEL || m_current_view == COVERFLOW_USB) && !m_locked)
{
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("NAND", "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_USB)
{
i = min(max(0, m_cfg.getInt("GAMES", "save_emulation", 0)), (int)ARRAY_SIZE(CMenu::_GlobalSaveEmu) - 1);
m_btnMgr.setText(m_nandemuLblEmulationVal, _t(CMenu::_GlobalSaveEmu[i].id, CMenu::_GlobalSaveEmu[i].text));
}
}
}
int CMenu::_NandEmuCfg(void)
{
lwp_t thread = 0;
SetupInput();
_showNandEmu();
m_thrdStop = false;
m_thrdMessageAdded = false;
m_nandext = false;
while(true)
{
_mainLoopCommon(false, m_thrdWorking);
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("NAND", "emulation", (int)loopNum((u32)m_cfg.getInt("NAND", "emulation", 0) + direction, ARRAY_SIZE(CMenu::_NandEmu)));
else if(m_current_view == COVERFLOW_USB)
m_cfg.setInt("GAMES", "save_emulation", (int)loopNum((u32)m_cfg.getInt("GAMES", "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.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_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();
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];
string npath = sfmt("/title/00010000/%x", savePath);
string path = sfmt("%s:%s/title/00010000/%x", DeviceName[emuPartition], m_cfg.getString("GAMES", "savepath", m_cfg.getString("NAND", "path", "")).c_str(), savePath);
if(!_nandSaveExcists(npath.c_str()) || (!m_forceext && _saveExcists(path.c_str())))
return 0;
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 excisting safe file from real nand or create new file for nandemulation?"));
m_btnMgr.show(m_nandemuBtnExtract);
m_btnMgr.show(m_nandemuBtnDisable);
m_btnMgr.show(m_nandemuLblInit);
}
m_saveExtGameId = gameId;
while(true)
{
_mainLoopCommon(false, m_thrdWorking);
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);
}
if(BTN_A_PRESSED && (m_btnMgr.selected(m_nandemuBtnDisable)))
{
_hideNandEmu();
return 0;
}
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));
_hideNandEmu();
return 1;
}
}
}
_hideNandEmu();
return 0;
}
int CMenu::_AutoCreateNand(void)
{
lwp_t thread = 0;
SetupInput();
m_thrdStop = false;
m_thrdMessageAdded = false;
m_nandext = false;
m_btnMgr.setText(m_nandemuBtnExtract, _t("cfgne5", L"Extract nand"));
m_btnMgr.setText(m_nandemuBtnDisable, _t("cfgne22", L"Disable nandemulation"));
m_btnMgr.setText(m_nandemuLblInit, _t("cfgne23", L"Welcome to WiiFlow. I have not found a valid nand for nand emulation. Click Extract to extract your nand, or click disable to disable nand emulation."));
m_btnMgr.show(m_nandemuBtnExtract);
m_btnMgr.show(m_nandemuBtnDisable);
m_btnMgr.show(m_nandemuLblInit);
while(true)
{
_mainLoopCommon(false, m_thrdWorking);
if(BTN_A_PRESSED && (m_btnMgr.selected(m_nandemuBtnExtract)))
{
m_fulldump = true;
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("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);
}
if(BTN_A_PRESSED && (m_btnMgr.selected(m_nandemuBtnDisable)))
{
_hideNandEmu();
return 0;
}
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));
_hideNandEmu();
return 1;
}
}
}
_hideNandEmu();
return 0;
}
int CMenu::_NandDumper(void *obj)
{
CMenu &m = *(CMenu *)obj;
string emuPath;
int emuPartition = -1;
bool emuPartIsValid = false;
m.m_nandext = false;
m.m_sgdump = false;
m.m_dumpsize = 0;
m.m_filesdone = 0;
m.m_foldersdone = 0;
Nand::Instance()->ResetCounters();
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", ""));
}
for(u8 i = emuPartition; i <= USB8; ++i)
{
if(!DeviceHandler::Instance()->IsInserted(emuPartition) || DeviceHandler::Instance()->GetFSType(emuPartition) != PART_FS_FAT)
{
emuPartition++;
continue;
}
else
{
emuPartIsValid = true;
if(m.m_current_view == COVERFLOW_CHANNEL)
m.m_cfg.setInt("NAND", "partition", emuPartition);
else if(m.m_current_view == COVERFLOW_USB)
m.m_cfg.setInt("GAMES", "savepartition", emuPartition);
break;
}
}
if(!emuPartIsValid)
{
m.error(sfmt("No valid FAT partition found for nandemulation!"));
m.m_thrdWorking = false;
m.m_btnMgr.hide(m.m_nandfilePBar);
m.m_btnMgr.hide(m.m_nandfileLblMessage);
LWP_MutexLock(m.m_mutex);
m._setDumpMsg(m._t("cfgne20", L"Extraction failed!"), 1.f, 1.f);
LWP_MutexUnlock(m.m_mutex);
m._hideNandEmu();
return 0;
}
if(emuPath.size() == 0)
{
Nand::Instance()->CreatePath("%s:/wiiflow", DeviceName[emuPartition]);
Nand::Instance()->CreatePath("%s:/wiiflow/nandemu", DeviceName[emuPartition]);
if(m.m_current_view == COVERFLOW_CHANNEL)
{
m.m_cfg.setString("NAND", "path", STDEMU_DIR);
emuPath = m.m_cfg.getString("NAND", "path", STDEMU_DIR);
}
else if(m.m_current_view == COVERFLOW_USB)
{
m.m_cfg.setString("GAMES", "savepath", STDEMU_DIR);
emuPath = m.m_cfg.getString("GAMES", "savepath", STDEMU_DIR);
}
}
m.m_cfg.save();
char basepath[64];
snprintf(basepath, 64, "%s:%s", DeviceName[emuPartition], emuPath.c_str());
LWP_MutexLock(m.m_mutex);
m._setDumpMsg(L"Calculating space needed for extraction...", 0.f, 0.f);
LWP_MutexUnlock(m.m_mutex);
if(m.m_fulldump)
{
m.m_dumpsize = Nand::Instance()->CalcDumpSpace("/", true, CMenu::_ShowProgress, obj);
m.m_nandext = true;
Nand::Instance()->DoNandDump("/", basepath, true, CMenu::_ShowProgress, obj);
}
else
{
bool missingOnly = !m.m_saveall;
string path, npath;
safe_vector<string> saveList;
m.m_sgdump = true;
if(m.m_saveExtGameId.empty())
{
m.m_nandexentry = 0;
saveList.reserve(m.m_gameList.size());
for(u32 i = 0; i < m.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.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];
path = sfmt("%s/title/00010000/%x", basepath, savePath);
npath = sfmt("/title/00010000/%x", savePath);
if(!missingOnly || !_saveExcists(path.c_str()))
{
if(_nandSaveExcists(npath.c_str()))
{
m.m_nandexentry++;
saveList.push_back(id);
}
}
}
}
else
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/%x", savePath);
m.m_dumpsize = Nand::Instance()->CalcDumpSpace(source, false, 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/%x", savePath);
m.m_nandext = true;
Nand::Instance()->DoNandDump(source, basepath, false, 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("cfgne19", L"Extraction finished!"), 1.f, 1.f);
LWP_MutexUnlock(m.m_mutex);
return 0;
}
void CMenu::_initNandEmuMenu(CMenu::SThemeData &theme)
{
_addUserLabels(theme, m_nandemuLblUser, ARRAY_SIZE(m_nandemuLblUser), "NANDEMU");
m_nandemuBg = _texture(theme.texSet, "NANDEMU/BG", "texture", theme.bg);
m_nandemuLblTitle = _addTitle(theme, "NANDEMU/TITLE", theme.titleFont, L"", 20, 30, 600, 60, theme.titleFontColor, FTGX_JUSTIFY_CENTER | FTGX_ALIGN_MIDDLE);
m_nandfileLblMessage = _addLabel(theme, "NANDEMU/FMESSAGE", theme.lblFont, L"", 40, 230, 560, 100, theme.lblFontColor, FTGX_JUSTIFY_CENTER | FTGX_ALIGN_TOP);
m_nandemuLblMessage = _addLabel(theme, "NANDEMU/MESSAGE", theme.lblFont, L"", 40, 350, 560, 100, theme.lblFontColor, FTGX_JUSTIFY_CENTER | FTGX_ALIGN_TOP);
m_nandfileLblDialog = _addLabel(theme, "NANDEMU/FDIALOG", theme.lblFont, L"", 40, 60, 560, 200, theme.lblFontColor, FTGX_JUSTIFY_LEFT | FTGX_ALIGN_MIDDLE);
m_nandfinLblDialog = _addLabel(theme, "NANDEMU/FINDIALOG", theme.lblFont, L"", 40, 120, 560, 200, theme.lblFontColor, FTGX_JUSTIFY_LEFT | FTGX_ALIGN_MIDDLE);
m_nandemuLblDialog = _addLabel(theme, "NANDEMU/DIALOG", theme.lblFont, L"", 40, 180, 560, 200, theme.lblFontColor, FTGX_JUSTIFY_LEFT | FTGX_ALIGN_MIDDLE);
m_nandfilePBar = _addProgressBar(theme, "NANDEMU/FILEPROGRESS_BAR", 40, 200, 560, 20);
m_nandemuPBar = _addProgressBar(theme, "NANDEMU/PROGRESS_BAR", 40, 320, 560, 20);
m_nandemuLblEmulation = _addLabel(theme, "NANDEMU/EMU_SAVE", theme.lblFont, L"", 40, 130, 340, 56, theme.lblFontColor, FTGX_JUSTIFY_LEFT | FTGX_ALIGN_MIDDLE);
m_nandemuLblEmulationVal = _addLabel(theme, "NANDEMU/EMU_SAVE_BTN_GLOBAL", theme.btnFont, L"", 400, 130, 144, 56, theme.btnFontColor, FTGX_JUSTIFY_CENTER | FTGX_ALIGN_MIDDLE, theme.btnTexC);
m_nandemuBtnEmulationM = _addPicButton(theme, "NANDEMU/EMU_SAVE_MINUS", theme.btnTexMinus, theme.btnTexMinusS, 344, 130, 56, 56);
m_nandemuBtnEmulationP = _addPicButton(theme, "NANDEMU/EMU_SAVE_PLUS", theme.btnTexPlus, theme.btnTexPlusS, 544, 130, 56, 56);
m_nandemuLblSaveDump = _addLabel(theme, "NANDEMU/SAVE_DUMP", theme.lblFont, L"", 40, 190, 340, 56, theme.lblFontColor, FTGX_JUSTIFY_LEFT | FTGX_ALIGN_MIDDLE);
m_nandemuBtnAll = _addButton(theme, "NANDEMU/ALL_BTN", theme.btnFont, L"", 350, 190, 250, 56, theme.btnFontColor);
m_nandemuBtnMissing = _addButton(theme, "NANDEMU/MISSING_BTN", theme.btnFont, L"", 350, 250, 250, 56, theme.btnFontColor);
m_nandemuLblNandDump = _addLabel(theme, "NANDEMU/NAND_DUMP", theme.lblFont, L"", 40, 310, 340, 56, theme.lblFontColor, FTGX_JUSTIFY_LEFT | FTGX_ALIGN_MIDDLE);
m_nandemuBtnNandDump = _addButton(theme, "NANDEMU/NAND_DUMP_BTN", theme.btnFont, L"", 350, 310, 250, 56, theme.btnFontColor);
m_nandemuBtnBack = _addButton(theme, "NANDEMU/BACK_BTN", theme.btnFont, L"", 420, 400, 200, 56, theme.btnFontColor);
m_nandemuBtnExtract = _addButton(theme, "NANDEMU/EXTRACT", theme.titleFont, L"", 72, 180, 496, 56, theme.titleFontColor);
m_nandemuBtnDisable = _addButton(theme, "NANDEMU/DISABLE", theme.titleFont, L"", 72, 290, 496, 56, theme.titleFontColor);
m_nandemuLblInit = _addLabel(theme, "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", 100, 0, -2.f, 0.f);
_setHideAnim(m_nandemuLblEmulationVal, "NANDEMU/EMU_SAVE_BTN_GLOBAL", 0, 0, 1.f, -1.f);
_setHideAnim(m_nandemuBtnEmulationM, "NANDEMU/EMU_SAVE_MINUS", 0, 0, 1.f, -1.f);
_setHideAnim(m_nandemuBtnEmulationP, "NANDEMU/EMU_SAVE_PLUS", 0, 0, 1.f, -1.f);
_setHideAnim(m_nandemuLblSaveDump, "NANDEMU/SAVE_DUMP", 100, 0, -2.f, 0.f);
_setHideAnim(m_nandemuBtnAll, "NANDEMU/ALL_BTN", 0, 0, -2.f, 0.f);
_setHideAnim(m_nandemuBtnMissing, "NANDEMU/MISSING_BTN", 0, 0, -2.f, 0.f);
_setHideAnim(m_nandemuLblNandDump, "NANDEMU/NAND_DUMP", 100, 0, -2.f, 0.f);
_setHideAnim(m_nandemuBtnNandDump, "NANDEMU/NAND_DUMP_BTN", 0, 0, -2.f, 0.f);
_setHideAnim(m_nandemuBtnBack, "NANDEMU/BACK_BTN", 0, 0, -2.f, 0.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", 100, 0, -2.f, 0.f);
_hideNandEmu(true);
_textNandEmu();
}
void CMenu::_textNandEmu(void)
{
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"));
}

View File

@ -87,17 +87,17 @@ void WavDecoder::OpenFile()
SWaveChunk DataChunk; SWaveChunk DataChunk;
file_fd->read((u8 *) &DataChunk, sizeof(SWaveChunk)); file_fd->read((u8 *) &DataChunk, sizeof(SWaveChunk));
if(DataChunk.magicDATA == 'fact') while(DataChunk.magicDATA != 'data')
{ {
DataOffset += 8+le32(DataChunk.size); DataOffset += 8+le32(DataChunk.size);
file_fd->seek(DataOffset, SEEK_SET); file_fd->seek(DataOffset, SEEK_SET);
file_fd->read((u8 *) &DataChunk, sizeof(SWaveChunk)); int ret = file_fd->read((u8 *) &DataChunk, sizeof(SWaveChunk));
} if(ret <= 0)
if(DataChunk.magicDATA != 'data')
{ {
CloseFile(); CloseFile();
return; return;
} }
}
DataOffset += 8; DataOffset += 8;
DataSize = le32(DataChunk.size); DataSize = le32(DataChunk.size);