diff --git a/source/channel/nand.cpp b/source/channel/nand.cpp index 807f0509..dff9ce0e 100644 --- a/source/channel/nand.cpp +++ b/source/channel/nand.cpp @@ -1,6 +1,6 @@ /*************************************************************************** - * Copyright (C) 2011 by Miigotu for wiiflow 2011 - * (C) 2012 by OverjoY for Wiiflow-mod + * Copyright (C) 2011 by Miigotu + * (C) 2012 by OverjoY * * Rewritten code from Mighty Channels and Triiforce * @@ -23,7 +23,7 @@ * 3. This notice may not be removed or altered from any source * distribution. * - * Nand/Emulation Handling Class + * Nand/Emulation Handling Class for Wiiflow * ***************************************************************************/ @@ -39,7 +39,7 @@ #include "utils.h" #include "gecko.h" #include "mem2.hpp" -#include "smartptr.hpp" +#include "text.hpp" u8 *confbuffer ATTRIBUTE_ALIGN(32); u8 CCode[0x1008]; @@ -51,7 +51,8 @@ config_header *cfg_hdr; bool tbdec = false; bool configloaded = false; -static NandDevice NandDeviceList[] = { +static NandDevice NandDeviceList[] = +{ { "Disable", 0, 0x00, 0x00 }, { "SD/SDHC Card", 1, 0xF0, 0xF1 }, { "USB 2.0 Mass Storage Device", 2, 0xF2, 0xF3 }, @@ -228,6 +229,45 @@ void Nand::__configshifttxt(char *str) *ctr = '\0'; } +void Nand::__GetNameList(const char *source, namelist **entries, int *count) +{ + u32 i, j, k, l; + u32 numentries = 0; + char *names; + char curentry[ISFS_MAXPATH]; + char entrypath[ISFS_MAXPATH]; + + s32 ret = ISFS_ReadDir(source, NULL, &numentries); + names = (char *)MEM2_alloc((ISFS_MAXPATH) * numentries); + ret = ISFS_ReadDir(source, names, &numentries); + *count = numentries; + + if(*entries) + MEM2_free(*entries); + + *entries = (namelist *)MEM2_alloc(sizeof(namelist)*numentries); + + for(i = 0, k = 0; i < numentries; i++) + { + for(j = 0; names[k] != 0; j++, k++) + curentry[j] = names[k]; + + curentry[j] = 0; + k++; + + strcpy((*entries)[i].name, curentry); + + if(source[strlen(source)-1] == '/') + snprintf(entrypath, sizeof(entrypath), "%s%s", source, curentry); + else + snprintf(entrypath, sizeof(entrypath), "%s/%s", source, curentry); + + ret = ISFS_ReadDir(entrypath, NULL, &l); + (*entries)[i].type = ret < 0 ? 0 : 1; + } + MEM2_free(names); +} + s32 Nand::__configread(void) { confbuffer = (u8 *)MEM2_alloc(0x4000); @@ -360,6 +400,67 @@ u32 Nand::__configsetsetting(const char *item, const char *val) return 0; } +bool Nand::__FileExists(const char *path, ...) +{ + FILE *f = fopen(path, "rb"); + if (f != 0) + { + gprintf("File \"%s\" exists\n", path); + SAFE_CLOSE(f); + return true; + } + return false; +} + +u32 Nand::__TestNandPath(const char *path) +{ + if(!strncmp(path, "/import", 7)) return 0; + if(!strncmp(path, "/meta", 5)) return 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; + if(!strncmp(tmp, "00000002.tik", 8) && !n_dumpmen) return 1; // Menu + if(strncmp(tmp, "00000002.tik", 8) && !n_dumpios) return 1; // IOSs + return 0; + } + if(!strncmp(path, "/ticket/00010001/", 17)) + { + 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 + 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 ret; @@ -374,7 +475,7 @@ s32 Nand::__FlashNandFile(const char *source, const char *dest) u32 fsize = ftell(file); fseek(file, 0, SEEK_SET); - gprintf("Flashing: %s (%uKB) to nand: %s...", source, (fsize / 0x400)+1, dest); + gprintf("Flashing: %s (%uKB) to nand...", source, (fsize / 0x400)+1); ISFS_Delete(dest); ISFS_CreateFile(dest, 0, 3, 3, 3); @@ -425,13 +526,19 @@ s32 Nand::__FlashNandFile(const char *source, const char *dest) s32 Nand::__DumpNandFile(const char *source, const char *dest) { + if(__TestNandPath(source)) + return 0; + s32 fd = ISFS_Open(source, ISFS_OPEN_READ); if (fd < 0) { gprintf("Error: IOS_OPEN(%s, %d) %d\n", source, ISFS_OPEN_READ, fd); return fd; } - + + if(__FileExists(dest)) + remove(dest); + FILE *file = fopen(dest, "wb"); if (!file) { @@ -451,7 +558,7 @@ s32 Nand::__DumpNandFile(const char *source, const char *dest) return ret; } - gprintf("Dumping: %s (%uKB) from nand to %s...", source, (status->file_length / 0x400)+1, dest); + gprintf("Dumping: %s (%uKB)...", source, (status->file_length / 0x400)+1); u8 *buffer = (u8 *)MEM2_alloc(BLOCK); u32 toread = status->file_length; @@ -492,18 +599,59 @@ s32 Nand::__DumpNandFile(const char *source, const char *dest) return 1; } -void Nand::__CreatePath(const char *path, ...) +s32 Nand::__DumpNandFolder(const char *source, const char *dest) { + namelist *names = NULL; + int cnt, i; + char nsource[ISFS_MAXPATH]; + char ndest[MAX_FAT_PATH]; + + __GetNameList(source, &names, &cnt); + + for(i = 0; i < cnt; i++) + { + if(source[strlen(source)-1] == '/') + snprintf(nsource, sizeof(nsource), "%s%s", source, names[i].name); + else + snprintf(nsource, sizeof(nsource), "%s/%s", source, names[i].name); + + if(!names[i].type) + { + Asciify2(nsource); + snprintf(ndest, sizeof(ndest), "%s%s", dest, nsource); + __DumpNandFile(nsource, ndest); + } + else + { + if(!__TestNandPath(nsource)) + { + CreatePath("%s%s", dest, nsource); + __DumpNandFolder(nsource, dest); + } + } + } + + SAFE_FREE(names); + return 0; +} + +void Nand::CreatePath(const char *path, ...) +{ char *folder = NULL; va_list args; va_start(args, path); if((vasprintf(&folder, path, args) >= 0) && folder) { + if(folder[strlen(folder)-1] == '/') + folder[strlen(folder)-1] = 0; + + Asciify2(folder); + DIR *d; - d = opendir(folder); + if(!d) - { + { gprintf("Creating folder: \"%s\"\n", folder); makedir(folder); } @@ -516,19 +664,46 @@ void Nand::__CreatePath(const char *path, ...) va_end(args); SAFE_FREE(folder); } + +s32 Nand::DoNandDump(const char *source, const char *dest, bool dumpios, bool dumpwgs, bool dumpwsc, bool dumpwvc, bool dumpmen) +{ + n_dumpios = dumpios; + n_dumpwgs = dumpwgs; + n_dumpwsc = dumpwsc; + n_dumpwvc = dumpwvc; + n_dumpmen = dumpmen; + + u32 temp = 0; + + s32 ret = ISFS_ReadDir(source, NULL, &temp); + if(ret < 0) + { + char ndest[MAX_FAT_PATH]; + snprintf(ndest, sizeof(ndest), "%s%s", dest, source); + CreatePath(dest); + + __DumpNandFile(source, ndest); + } + else + { + __DumpNandFolder(source, dest); + } + + return 0; +} s32 Nand::CreateConfig(const char *path) { - __CreatePath(path); - __CreatePath("%s/shared2", path); - __CreatePath("%s/shared2/sys", path); - __CreatePath("%s/title", path); - __CreatePath("%s/title/00000001", path); - __CreatePath("%s/title/00000001/00000002", path); - __CreatePath("%s/title/00000001/00000002/data", path); + CreatePath(path); + CreatePath("%s/shared2", path); + CreatePath("%s/shared2/sys", path); + CreatePath("%s/title", path); + CreatePath("%s/title/00000001", path); + CreatePath("%s/title/00000001/00000002", path); + CreatePath("%s/title/00000001/00000002/data", path); - bzero(cfgpath, MAX_FAT_PATH); - bzero(settxtpath, MAX_FAT_PATH); + bzero(cfgpath, MAX_FAT_PATH+1); + bzero(settxtpath, MAX_FAT_PATH+1); snprintf(cfgpath, sizeof(cfgpath), "%s%s", path, SYSCONFPATH); snprintf(settxtpath, sizeof(settxtpath), "%s%s", path, TXTPATH); @@ -602,5 +777,4 @@ s32 Nand::Do_Region_Change(string id) } __configwrite(); return 1; -} - \ No newline at end of file +} \ No newline at end of file diff --git a/source/channel/nand.hpp b/source/channel/nand.hpp index 58897f28..25480d0e 100644 --- a/source/channel/nand.hpp +++ b/source/channel/nand.hpp @@ -21,7 +21,7 @@ #define SYSCONFPATH "/shared2/sys/SYSCONF" #define TXTPATH "/title/00000001/00000002/data/setting.txt" -#define BLOCK 0x4000 +#define BLOCK 2048 /* 'NAND Device' structure */ typedef struct nandDevice @@ -39,6 +39,12 @@ typedef struct _config_header u16 noff[]; } config_header; +typedef struct _namelist +{ + char name[ISFS_MAXPATH]; + int type; +} namelist; + using namespace std; class Nand @@ -60,10 +66,12 @@ class Nand u32 Get_Partition(void) { return Partition; }; void Set_NandPath(string path); + void CreatePath(const char *path, ...); s32 CreateConfig(const char *path); s32 Do_Region_Change(string id); - + s32 DoNandDump(const char *source, const char *dest, bool dumpios, bool dumpwgs, bool dumpwsc, bool dumpwvc, bool dumpmen); + private: Nand() : MountedDevice(0), EmuDevice(REAL_NAND), Disabled(true), Partition(0), FullMode(0x100), NandPath() {} ~Nand(void){} @@ -75,20 +83,27 @@ class Nand s32 Nand_Disable(void); void __Dec_Enc_TB(void); void __configshifttxt(char *str); + void __GetNameList(const char *source, namelist **entries, int *count); s32 __configread(void); s32 __configwrite(void); u32 __configsetbyte(const char *item, u8 val); u32 __configsetbigarray(const char *item, void *val, u32 size); u32 __configsetsetting(const char *item, const char *val); + bool __FileExists(const char *path, ...); + u32 __TestNandPath(const char *path); s32 __FlashNandFile(const char *source, const char *dest); s32 __DumpNandFile(const char *source, const char *dest); - void __CreatePath(const char *path, ...); - + s32 __DumpNandFolder(const char *source, const char *dest); u32 MountedDevice; u32 EmuDevice; bool Disabled; - + bool n_dumpios; + bool n_dumpwgs; + bool n_dumpwsc; + bool n_dumpwvc; + bool n_dumpmen; + u32 Partition ATTRIBUTE_ALIGN(32); u32 FullMode ATTRIBUTE_ALIGN(32); char NandPath[32] ATTRIBUTE_ALIGN(32); diff --git a/source/defines.h b/source/defines.h index c9644246..5acf690c 100644 --- a/source/defines.h +++ b/source/defines.h @@ -1,9 +1,10 @@ #define APP_NAME "WiiFlow" -#define APP_VERSION "Mod 3.0" +#define APP_VERSION "Mod 3.1" #define APPDATA_DIR "wiiflow" #define APPDATA_DIR2 "apps/wiiflow" +#define STDEMU_DIR "/wiiflow/nandemu" #define GAMES_DIR "%s:/wbfs" #define HOMEBREW_DIR "%s:/apps" #define DML_DIR "%s:/games" @@ -13,8 +14,8 @@ #define TITLES_FILENAME "titles.ini" #define CTITLES_FILENAME "custom_titles.ini" -#define DEVELOPERS "r-win, Miigotu, OverjoY, FIX94" -#define PAST_DEVELOPERS "Hibernatus, Narolez, Hulk" +#define DEVELOPERS "r-win, OverjoY, FIX94" +#define PAST_DEVELOPERS "Hibernatus, Narolez, Hulk, Miigotu" #define LOADER_AUTHOR "Kwiirk, Waninkoko, Hermes" #define GUI_AUTHOR "Hibernatus" diff --git a/source/devicemounter/libwbfs/libwbfs.c b/source/devicemounter/libwbfs/libwbfs.c index 04c3a7ff..f51c4efc 100644 --- a/source/devicemounter/libwbfs/libwbfs.c +++ b/source/devicemounter/libwbfs/libwbfs.c @@ -497,7 +497,6 @@ u32 wbfs_add_disc(wbfs_t *p, read_wiidisc_callback_t read_src_wii_disc, void *ca } if (ret) break; info->wlba_table[i] = wbfs_htons(bl); - wbfs_sync(p); } // write disc info int disc_info_sz_lba = p->disc_info_sz>>p->hd_sec_sz_s; diff --git a/source/gui/text.cpp b/source/gui/text.cpp index 9fafeb85..f3ab8c0c 100644 --- a/source/gui/text.cpp +++ b/source/gui/text.cpp @@ -493,7 +493,6 @@ void Asciify2( char *str ) { case '*': case '\"': - case ':': case '|': case '<': case '>': diff --git a/source/list/cachedlist.cpp b/source/list/cachedlist.cpp index 70c862e4..777eeadb 100644 --- a/source/list/cachedlist.cpp +++ b/source/list/cachedlist.cpp @@ -40,13 +40,31 @@ void CachedList::Load(string path, string containing, string m_lastLanguage) bool noDB = stat(m_database.c_str(), &cache) == -1; bool mtimes = filestat.st_mtime > cache.st_mtime; if(strcasestr(m_discinf.c_str(), "wbfs") != NULL && stat(m_discinf.c_str(), &discinfo) != -1) - ditimes = discinfo.st_mtime > cache.st_mtime; + ditimes = discinfo.st_mtime > cache.st_mtime; m_update = update_lang || noDB || mtimes || ditimes; if(m_update) gprintf("Cache of %s is being updated because ", path.c_str()); if(update_lang) gprintf("languages are different!\nOld language string: %s\nNew language string: %s\n", m_lastLanguage.c_str(), m_curLanguage.c_str()); if(noDB) gprintf("a database was not found!\n"); if(mtimes || ditimes) gprintf("the WBFS folder was modified!\n"); + + if(m_extcheck && !m_update) + { + bool m_chupdate = false; + + DIR *dir = opendir(path.c_str()); + struct dirent *entry; + while((entry = readdir(dir)) != NULL) + { + m_discinf = sfmt("%s/%s", path.c_str(), entry->d_name); + if(stat(m_discinf.c_str(), &discinfo) != -1) + m_chupdate = discinfo.st_mtime > cache.st_mtime; + + if(m_chupdate) + break; + } + m_update = m_chupdate; + } } if(update_games) force_update[COVERFLOW_USB] = false; diff --git a/source/list/cachedlist.hpp b/source/list/cachedlist.hpp index a41d78c2..d1f422f8 100644 --- a/source/list/cachedlist.hpp +++ b/source/list/cachedlist.hpp @@ -20,7 +20,7 @@ template class CachedList : public safe_vector { public: - void Init(string cachedir, string settingsDir, string curLanguage, string DMLgameDir) /* Initialize Private Variables */ + void Init(string cachedir, string settingsDir, string curLanguage, string DMLgameDir, bool extcheck) /* Initialize Private Variables */ { m_cacheDir = cachedir; m_settingsDir = settingsDir; @@ -28,6 +28,7 @@ class CachedList : public safe_vector m_loaded = false; m_database = ""; m_update = false; + m_extcheck = extcheck; m_DMLgameDir = DMLgameDir; for(u32 i = 0; i < COVERFLOW_MAX; i++) force_update[i] = false; @@ -67,6 +68,7 @@ class CachedList : public safe_vector bool m_loaded; bool m_update; bool m_wbfsFS; + bool m_extcheck; u8 force_update[COVERFLOW_MAX]; CList list; string m_database; diff --git a/source/main.cpp b/source/main.cpp index 73f3471a..d2799436 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -52,14 +52,14 @@ int main(int argc, char **argv) gameid = NULL; } } - gprintf("Loading cIOS: %d\n", mainIOS); - - ISFS_Initialize(); + gprintf("Loading cIOS: %d\n", mainIOS); // Load Custom IOS bool iosOK = loadIOS(mainIOS, false); MEM2_init(52); + ISFS_Initialize(); + u8 mainIOSBase = 0; iosOK = iosOK && cIOSInfo::D2X(mainIOS, &mainIOSBase); gprintf("Loaded cIOS: %u has base %u\n", mainIOS, mainIOSBase); diff --git a/source/menu/menu.cpp b/source/menu/menu.cpp index 8ef3e9b6..af598ab3 100644 --- a/source/menu/menu.cpp +++ b/source/menu/menu.cpp @@ -375,7 +375,9 @@ void CMenu::init(void) m_loc.load(sfmt("%s/%s.ini", m_languagesDir.c_str(), m_curLanguage.c_str()).c_str()); } - m_gameList.Init(m_listCacheDir, m_settingsDir, m_loc.getString(m_curLanguage, "gametdb_code", "EN"), m_DMLgameDir); + bool extcheck = m_cfg.getBool("GENERAL", "extended_list_check", true); + + m_gameList.Init(m_listCacheDir, m_settingsDir, m_loc.getString(m_curLanguage, "gametdb_code", "EN"), m_DMLgameDir, extcheck); m_aa = 3; diff --git a/source/menu/menu_game.cpp b/source/menu/menu_game.cpp index 6e26f7d0..85ecb520 100644 --- a/source/menu/menu_game.cpp +++ b/source/menu/menu_game.cpp @@ -1,4 +1,6 @@ +//#define ENABLEDUMPER + #include "menu.hpp" #include "loader/patchcode.h" @@ -1008,7 +1010,7 @@ void CMenu::_launchGame(dir_discHdr *hdr, bool dvd) emuPartition = m_cfg.getInt("NAND", "partition", 0); string emuPath = m_cfg.getString("GAMES", "savepath", m_cfg.getString("NAND", "path", "")); - + u8 emuSave = min((u32)m_gcfg2.getInt(id, "emulate_save", 0), ARRAY_SIZE(CMenu::_SaveEmu) - 1u); if (emuSave == 0) @@ -1018,15 +1020,54 @@ void CMenu::_launchGame(dir_discHdr *hdr, bool dvd) emuSave++; } else if (emuSave == 1) - emuSave = 0; - - if (!dvd && get_frag_list((u8 *) hdr->hdr.id, (char *) hdr->path, currentPartition == 0 ? 0x200 : sector_size) < 0) - return; + emuSave = 0; if(!dvd && emuSave) - { + { + bool createnand = false; char basepath[64]; - snprintf(basepath, 64, "%s:%s", DeviceName[emuPartition], emuPath.c_str()); + if(emuPath.size() == 0) + { + Nand::Instance()->CreatePath("%s:/wiiflow", DeviceName[emuPartition]); + Nand::Instance()->CreatePath("%s:/wiiflow/nandemu", DeviceName[emuPartition]); + m_cfg.setString("GAMES", "savepath", STDEMU_DIR); + emuPath = m_cfg.getString("GAMES", "savepath", STDEMU_DIR); + snprintf(basepath, 64, "%s:%s", DeviceName[emuPartition], emuPath.c_str()); + if(emuSave == 4) + createnand = true; + } + else + { + snprintf(basepath, 64, "%s:%s", DeviceName[emuPartition], emuPath.c_str()); + if(emuSave == 4) + { + DIR *d; + d = opendir(basepath); + if(!d) + { + Nand::Instance()->CreatePath("%s:/wiiflow", DeviceName[emuPartition]); + Nand::Instance()->CreatePath("%s:/wiiflow/nandemu", DeviceName[emuPartition]); + createnand = true; + } + else + { + closedir(d); + } + } + } + + if(createnand) + { +#ifdef ENABLEDUMPER + bool dumpios = m_cfg.getBool("NAND", "nanddumpios", false); + bool dumpgs = m_cfg.getBool("NAND", "nanddumpgamesaves", false); + 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) { CreateSavePath(basepath, hdr); @@ -1037,6 +1078,9 @@ void CMenu::_launchGame(dir_discHdr *hdr, bool dvd) Nand::Instance()->Do_Region_Change(id); } } + + if (!dvd && get_frag_list((u8 *) hdr->hdr.id, (char *) hdr->path, currentPartition == 0 ? 0x200 : sector_size) < 0) + return; int gameIOS = 0; int userIOS = 0; diff --git a/source/music/musicplayer.cpp b/source/music/musicplayer.cpp index d679c3d9..3cdb7821 100644 --- a/source/music/musicplayer.cpp +++ b/source/music/musicplayer.cpp @@ -31,7 +31,7 @@ void MusicPlayer::Init(Config &cfg, string musicDir, string themeMusicDir) SetVolume(0); // Fades in with tick() MusicDirectory dir = (MusicDirectory) cfg.getInt("GENERAL", "music_directories", NORMAL_MUSIC | THEME_MUSIC); - m_music_files.Init(cfg.getString("GENERAL", "dir_list_cache"), std::string(), std::string(), std::string()); + m_music_files.Init(cfg.getString("GENERAL", "dir_list_cache"), std::string(), std::string(), std::string(), false); if (dir & THEME_MUSIC) m_music_files.Load(themeMusicDir, ".ogg|.mp3", "EN"); //|.mod|.xm|.s3m|.wav|.aiff");