diff --git a/Test/menu.c b/Test/menu.c deleted file mode 100644 index aa50a82..0000000 --- a/Test/menu.c +++ /dev/null @@ -1,1416 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include - -#include "sys.h" -#include "fat.h" -#include "nand.h" -#include "restart.h" -#include "title.h" -#include "usbstorage.h" -#include "utils.h" -#include "video.h" -#include "wad.h" -#include "wpad.h" -#include -#include "globals.h" -#include "iospatch.h" -#include "appboot.h" - -/* FAT device list */ -//static fatDevice fdevList[] = { -fatDevice fdevList[] = { - { "sd", "Wii SD Slot", &__io_wiisd }, - { "usb", "USB Mass Storage Device", &__io_usbstorage }, - { "usb2", "USB 2.0 Mass Storage Device", &__io_wiiums }, - { "gcsda", "SD Gecko (Slot A)", &__io_gcsda }, - { "gcsdb", "SD Gecko (Slot B)", &__io_gcsdb }, - //{ "smb", "SMB share", NULL }, -}; - -/* NAND device list */ -//static nandDevice ndevList[] = { -nandDevice ndevList[] = { - { "Disable", 0, 0x00, 0x00 }, - { "SD/SDHC Card", 1, 0xF0, 0xF1 }, - { "USB 2.0 Mass Storage Device", 2, 0xF2, 0xF3 }, -}; - -/* FAT device */ -static fatDevice *fdev = NULL; -static nandDevice *ndev = NULL; - -// wiiNinja: Define a buffer holding the previous path names as user -// traverses the directory tree. Max of 10 levels is define at this point -static u8 gDirLevel = 0; -static char gDirList [MAX_DIR_LEVELS][MAX_FILE_PATH_LEN]; -static s32 gSeleted[MAX_DIR_LEVELS]; -static s32 gStart[MAX_DIR_LEVELS]; - -/* Macros */ -#define NB_FAT_DEVICES (sizeof(fdevList) / sizeof(fatDevice)) -#define NB_NAND_DEVICES (sizeof(ndevList) / sizeof(nandDevice)) - -// Local prototypes: wiiNinja -void WaitPrompt (char *prompt); -int PushCurrentDir(char *dirStr, int Selected, int Start); -char *PopCurrentDir(int *Selected, int *Start); -bool IsListFull (void); -char *PeekCurrentDir (void); -u32 WaitButtons(void); -u32 Pad_GetButtons(void); -void WiiLightControl (int state); - -int __Menu_IsGreater(const void *p1, const void *p2) -{ - u32 n1 = *(u32 *)p1; - u32 n2 = *(u32 *)p2; - - /* Equal */ - if (n1 == n2) - return 0; - - return (n1 > n2) ? 1 : -1; -} - - -int __Menu_EntryCmp(const void *p1, const void *p2) -{ - fatFile *f1 = (fatFile *)p1; - fatFile *f2 = (fatFile *)p2; - - /* Compare entries */ // wiiNinja: Include directory - if ((f1->isdir) && !(f2->isdir)) - return (-1); - else if (!(f1->isdir) && (f2->isdir)) - return (1); - else - return strcasecmp(f1->filename, f2->filename); -} - -static bool __FolderExists(const char *path) -{ - DIR *dir; - dir = opendir(path); - if(dir) - { - closedir(dir); - return true; - } - return false; -} - -static size_t __GetFileSizeBytes(const char *path) -{ - FILE *f; - size_t size = 0; - - f = fopen(path, "rb"); - if(!f) return 0; - - //Get file size - fseek(f, 0, SEEK_END); - size = ftell(f); - fclose(f); - - return size; -} - -char gFileName[MAX_FILE_PATH_LEN]; -s32 __Menu_RetrieveList(char *inPath, fatFile **outbuf, u32 *outlen) -{ - fatFile *buffer = NULL; - DIR *dir = NULL; - struct dirent *ent = NULL; - - //char dirpath[256], filename[768]; - u32 cnt; - - /* Generate dirpath */ - //sprintf(dirpath, "%s:" WAD_DIRECTORY, fdev->mount); - - /* Open directory */ - dir = opendir(inPath); - if (!dir) - return -1; - - /* Count entries */ - for (cnt = 0; ((ent = readdir(dir)) != NULL);) { - cnt++; - } - - if (cnt > 0) { - /* Allocate memory */ - buffer = malloc(sizeof(fatFile) * cnt); - if (!buffer) { - closedir(dir); - return -2; - } - - /* Reset directory */ - rewinddir(dir); - - /* Get entries */ - for (cnt = 0; ((ent = readdir(dir)) != NULL);) - { - bool addFlag = false; - bool isdir = false; - size_t fsize = 0; - - snprintf(gFileName, MAX_FILE_PATH_LEN, "%s/%s", inPath, ent->d_name); - if (__FolderExists(gFileName)) // wiiNinja - { - isdir = true; - // Add only the item ".." which is the previous directory - // AND if we're not at the root directory - if ((strcmp (ent->d_name, "..") == 0) && (gDirLevel > 1)) - addFlag = true; - else if (strcmp (ent->d_name, ".") != 0) - addFlag = true; - } - else - { - if(strlen(ent->d_name)>4) - { - if(!strcasecmp(ent->d_name+strlen(ent->d_name)-4, ".wad")) - { - fsize = __GetFileSizeBytes(gFileName); - addFlag = true; - } - } - } - - if (addFlag == true) - { - fatFile *file = &buffer[cnt++]; - - /* File name */ - strcpy(file->filename, ent->d_name); - - /* File stats */ - file->isdir = isdir; - file->fsize = fsize; - - } - } - - /* Sort list */ - qsort(buffer, cnt, sizeof(fatFile), __Menu_EntryCmp); - } - - /* Close directory */ - closedir(dir); - - /* Set values */ - *outbuf = buffer; - *outlen = cnt; - - return 0; -} - - -void Menu_SelectIOS(void) -{ - u8 *iosVersion = NULL; - u32 iosCnt; - u8 tmpVersion; - - u32 cnt; - s32 ret, selected = 0; - bool found = false; - - /* Get IOS versions */ - ret = Title_GetIOSVersions(&iosVersion, &iosCnt); - if (ret < 0) - return; - - /* Sort list */ - qsort(iosVersion, iosCnt, sizeof(u8), __Menu_IsGreater); - - if (gConfig.cIOSVersion < 0) - tmpVersion = CIOS_VERSION; - else - { - tmpVersion = (u8)gConfig.cIOSVersion; - // For debugging only - //printf ("User pre-selected cIOS: %i\n", tmpVersion); - //WaitButtons(); - } - - /* Set default version */ - for (cnt = 0; cnt < iosCnt; cnt++) { - u8 version = iosVersion[cnt]; - - /* Custom IOS available */ - //if (version == CIOS_VERSION) - if (version == tmpVersion) - { - selected = cnt; - found = true; - break; - } - - /* Current IOS */ - if (version == IOS_GetVersion()) - selected = cnt; - } - - /* Ask user for IOS version */ - if ((gConfig.cIOSVersion < 0) || (found == false)) - { - for (;;) - { - /* Clear console */ - Con_Clear(); - - printf("\t>> Select IOS version to use: < IOS%d >\n\n", iosVersion[selected]); - - printf("\t Press LEFT/RIGHT to change IOS version.\n\n"); - - printf("\t Press A button to continue.\n"); - printf("\t Press HOME button to restart.\n\n"); - - u32 buttons = WaitButtons(); - - /* LEFT/RIGHT buttons */ - if (buttons & WPAD_BUTTON_LEFT) { - if ((--selected) <= -1) - selected = (iosCnt - 1); - } - if (buttons & WPAD_BUTTON_RIGHT) { - if ((++selected) >= iosCnt) - selected = 0; - } - - /* HOME button */ - if (buttons & WPAD_BUTTON_HOME) - Restart(); - - /* A button */ - if (buttons & WPAD_BUTTON_A) - break; - } - } - - - u8 version = iosVersion[selected]; - - if (IOS_GetVersion() != version) { - /* Shutdown subsystems */ - Wpad_Disconnect(); - //mload_close(); - - /* Load IOS */ - - if(!loadIOS(version)) Wpad_Init(), Menu_SelectIOS(); - - /* Initialize subsystems */ - Wpad_Init(); - } -} - -void Menu_FatDevice(void) -{ - int ret, selected = 0; - - /* Unmount FAT device */ - //if (fdev) - //Fat_Unmount(fdev); - //if (((fdevList[selected].mount[0] == 's') && (ndev->name[0] == 'S'))) - //selected++; - static const u16 konamiCode[] = { - WPAD_BUTTON_UP, WPAD_BUTTON_UP, WPAD_BUTTON_DOWN, WPAD_BUTTON_DOWN, WPAD_BUTTON_LEFT, - WPAD_BUTTON_RIGHT, WPAD_BUTTON_LEFT, WPAD_BUTTON_RIGHT, WPAD_BUTTON_B, WPAD_BUTTON_A - }; - - int codePosition = 0; - - /* Select source device */ - if (gConfig.fatDeviceIndex < 0) - { - for (;;) { - /* Clear console */ - Con_Clear(); - - /* Selected device */ - fdev = &fdevList[selected]; - - printf("\t>> Select source device: < %s >\n\n", fdev->name); - - printf("\t Press LEFT/RIGHT to change the selected device.\n\n"); - - printf("\t Press A button to continue.\n"); - printf("\t Press HOME button to restart.\n\n"); - - u32 buttons = WaitButtons(); - - if (buttons & (WPAD_BUTTON_UP | WPAD_BUTTON_DOWN | WPAD_BUTTON_RIGHT | WPAD_BUTTON_LEFT | WPAD_BUTTON_A | WPAD_BUTTON_B)) { - if (buttons & konamiCode[codePosition]) - ++codePosition; - else - codePosition = 0; - } - - /* LEFT/RIGHT buttons */ - if (buttons & WPAD_BUTTON_LEFT) { - if ((--selected) <= -1) - selected = (NB_FAT_DEVICES - 1); - if ((fdevList[selected].mount[0] == 's') && (ndev->name[0] == 'S')) - selected--; - if ((fdevList[selected].mount[0] == 'u' && fdevList[selected].mount[3] == '2') && (ndev->name[0] == 'U')) - selected--; - if ((selected) <= -1) - selected = (NB_FAT_DEVICES - 1); - } - if (buttons & WPAD_BUTTON_RIGHT) { - if ((++selected) >= NB_FAT_DEVICES) - selected = 0; - if ((fdevList[selected].mount[0] == 's') && (ndev->name[0] == 'S')) - selected++; - if ((fdevList[selected].mount[0] == 'u' && fdevList[selected].mount[3] == '2') && (ndev->name[0] == 'U')) - selected++; - } - - /* HOME button */ - if (buttons & WPAD_BUTTON_HOME) - Restart(); - - /* A button */ - if (buttons & WPAD_BUTTON_A) { - if (codePosition == sizeof(konamiCode) / sizeof(konamiCode[0])) { - extern bool skipRegionSafetyCheck; - skipRegionSafetyCheck = true; - printf("[+] Disabled SM region checks\n"); - sleep(2); - } - break; - } - } - } - else - { - sleep(5); - fdev = &fdevList[gConfig.fatDeviceIndex]; - } - - printf("[+] Mounting %s, please wait...", fdev->name ); - fflush(stdout); - - /* Mount FAT device */ - - ret = Fat_Mount(fdev); - if (ret < 0) { - printf(" ERROR! (ret = %d)\n", ret); - goto err; - } else - printf(" OK!\n"); - - return; - -err: - - if(gConfig.fatDeviceIndex >= 0) gConfig.fatDeviceIndex = -1; - WiiLightControl (WII_LIGHT_OFF); - printf("\n"); - printf(" Press any button to continue...\n"); - - WaitButtons(); - - /* Prompt menu again */ - Menu_FatDevice(); -} - -void Menu_NandDevice(void) -{ - int ret, selected = 0; - - /* Disable NAND emulator */ - if (ndev) { - Nand_Unmount(ndev); - Nand_Disable(); - } - - /* Select source device */ - if (gConfig.nandDeviceIndex < 0) - { - for (;;) { - /* Clear console */ - Con_Clear(); - - /* Selected device */ - ndev = &ndevList[selected]; - - printf("\t>> Select NAND emulator device: < %s >\n\n", ndev->name); - - printf("\t Press LEFT/RIGHT to change the selected device.\n\n"); - - printf("\t Press A button to continue.\n"); - printf("\t Press HOME button to restart.\n\n"); - - u32 buttons = WaitButtons(); - - /* LEFT/RIGHT buttons */ - if (buttons & WPAD_BUTTON_LEFT) { - if ((--selected) <= -1) - selected = (NB_NAND_DEVICES - 1); - } - if (buttons & WPAD_BUTTON_RIGHT) { - if ((++selected) >= NB_NAND_DEVICES) - selected = 0; - } - - /* HOME button */ - if (buttons & WPAD_BUTTON_HOME) - Restart(); - - /* A button */ - if (buttons & WPAD_BUTTON_A) - break; - } - } - else - { - ndev = &ndevList[gConfig.nandDeviceIndex]; - } - - /* No NAND device */ - if (!ndev->mode) - return; - - printf("[+] Enabling NAND emulator..."); - fflush(stdout); - - /* Mount NAND device */ - ret = Nand_Mount(ndev); - if (ret < 0) { - printf(" ERROR! (ret = %d)\n", ret); - goto err; - } - - /* Enable NAND emulator */ - ret = Nand_Enable(ndev); - if (ret < 0) { - printf(" ERROR! (ret = %d)\n", ret); - goto err; - } else - printf(" OK!\n"); - - return; - -err: - printf("\n"); - printf(" Press any button to continue...\n"); - - WaitButtons(); - - /* Prompt menu again */ - Menu_NandDevice(); -} - -char gTmpFilePath[MAX_FILE_PATH_LEN]; -/* Install and/or Uninstall multiple WADs - Leathl */ -int Menu_BatchProcessWads(fatFile *files, int fileCount, char *inFilePath, int installCnt, int uninstallCnt) -{ - int count; - - for (;;) - { - Con_Clear(); - - if ((installCnt > 0) & (uninstallCnt == 0)) { - printf("[+] %d file%s marked for installation.\n", installCnt, (installCnt == 1) ? "" : "s"); - printf(" Do you want to proceed?\n"); - } - else if ((installCnt == 0) & (uninstallCnt > 0)) { - printf("[+] %d file%s marked for uninstallation.\n", uninstallCnt, (uninstallCnt == 1) ? "" : "s"); - printf(" Do you want to proceed?\n"); - } - else { - printf("[+] %d file%s marked for installation and %d file%s for uninstallation.\n", installCnt, (installCnt == 1) ? "" : "s", uninstallCnt, (uninstallCnt == 1) ? "" : "s"); - printf(" Do you want to proceed?\n"); - } - - printf("\n\n Press A to continue.\n"); - printf(" Press B to go back to the menu.\n\n"); - - u32 buttons = WaitButtons(); - - if (buttons & WPAD_BUTTON_A) - break; - - if (buttons & WPAD_BUTTON_B) - return 0; - } - - WiiLightControl (WII_LIGHT_ON); - int errors = 0; - int success = 0; - s32 ret; - - for (count = 0; count < fileCount; count++) - { - fatFile *thisFile = &files[count]; - - if ((thisFile->install == 1) | (thisFile->install == 2)) { - int mode = thisFile->install; - Con_Clear(); - printf("[+] Opening \"%s\", please wait...\n\n", thisFile->filename); - - sprintf(gTmpFilePath, "%s/%s", inFilePath, thisFile->filename); - - FILE *fp = fopen(gTmpFilePath, "rb"); - if (!fp) { - printf(" ERROR!\n"); - errors += 1; - continue; - } - - printf("[+] %s WAD, please wait...\n", (mode == 2) ? "Uninstalling" : "Installing"); - if (mode == 2) { - ret = Wad_Uninstall(fp); - } - else { - ret = Wad_Install(fp); - } - - if (ret < 0) errors += 1; - else success += 1; - - thisFile->installstate = ret; - - if (fp) - fclose(fp); - } - } - - WiiLightControl (WII_LIGHT_OFF); - - printf("\n"); - printf(" %d titles succeeded and %d failed...\n", success, errors); - - if (errors > 0) - { - printf("\n Some operations failed"); - printf("\n Press A to list.\n"); - printf(" Press B skip.\n"); - - u32 buttons = WaitButtons(); - - if ((buttons & WPAD_BUTTON_A)) - { - Con_Clear(); - - int i=0; - for (count = 0; count < fileCount; count++) - { - fatFile *thisFile = &files[count]; - - if (thisFile->installstate <0) - { - char str[41]; - strncpy(str, thisFile->filename, 40); //Only 40 chars to fit the screen - str[40]=0; - i++; - if(thisFile->installstate == -999) printf(" %s BRICK BLOCKED\n", str); - else if(thisFile->installstate == -998) printf(" %s Skipped\n", str); - else if(thisFile->installstate == -106) printf(" %s Not installed?\n", str); - else if(thisFile->installstate == -1036 ) printf(" %s Needed IOS missing\n", str); - else if(thisFile->installstate == -4100 ) printf(" %s No trucha bug?\n", str); - else printf(" %s error %d\n", str, thisFile->installstate); - if( i == 17 ) - { - printf("\n Press any button to continue\n"); - WaitButtons(); - i = 0; - } - } - } - } - } - printf("\n Press any button to continue...\n"); - WaitButtons(); - - return 1; -} - -/* File Operations - Leathl */ -int Menu_FileOperations(fatFile *file, char *inFilePath) -{ - f32 filesize = (file->fsize / MB_SIZE); - - for (;;) - { - Con_Clear(); - - printf("[+] WAD Filename : %s\n", file->filename); - printf(" WAD Filesize : %.2f MB\n\n\n", filesize); - - - printf("[+] Select action: < %s WAD >\n\n", "Delete"); //There's yet nothing else than delete - - printf(" Press LEFT/RIGHT to change selected action.\n\n"); - - printf(" Press A to continue.\n"); - printf(" Press B to go back to the menu.\n\n"); - - u32 buttons = WaitButtons(); - - /* A button */ - if (buttons & WPAD_BUTTON_A) - break; - - /* B button */ - if (buttons & WPAD_BUTTON_B) - return 0; - } - - Con_Clear(); - - printf("[+] Deleting \"%s\", please wait...\n", file->filename); - - sprintf(gTmpFilePath, "%s/%s", inFilePath, file->filename); - int error = remove(gTmpFilePath); - if (error != 0) - printf(" ERROR!"); - else - printf(" Successfully deleted!"); - - printf("\n"); - printf(" Press any button to continue...\n"); - - WaitButtons(); - - return !error; -} - -void Menu_WadManage(fatFile *file, char *inFilePath) -{ - FILE *fp = NULL; - - //char filepath[128]; - f32 filesize; - - u32 mode = 0; - - /* File size in megabytes */ - filesize = (file->fsize / MB_SIZE); - - for (;;) { - /* Clear console */ - Con_Clear(); - - printf("[+] WAD Filename : %s\n", file->filename); - printf(" WAD Filesize : %.2f MB\n\n\n", filesize); - - - printf("[+] Select action: < %s WAD >\n\n", (!mode) ? "Install" : "Uninstall"); - - printf(" Press LEFT/RIGHT to change selected action.\n\n"); - - printf(" Press A to continue.\n"); - printf(" Press B to go back to the menu.\n\n"); - - u32 buttons = WaitButtons(); - - /* LEFT/RIGHT buttons */ - if (buttons & (WPAD_BUTTON_LEFT | WPAD_BUTTON_RIGHT)) - mode ^= 1; - - /* A button */ - if (buttons & WPAD_BUTTON_A) - break; - - /* B button */ - if (buttons & WPAD_BUTTON_B) - return; - } - - /* Clear console */ - Con_Clear(); - - printf("[+] Opening \"%s\", please wait...", file->filename); - fflush(stdout); - - /* Generate filepath */ - // sprintf(filepath, "%s:" WAD_DIRECTORY "/%s", fdev->mount, file->filename); - sprintf(gTmpFilePath, "%s/%s", inFilePath, file->filename); // wiiNinja - - /* Open WAD */ - fp = fopen(gTmpFilePath, "rb"); - if (!fp) { - printf(" ERROR!\n"); - goto out; - } else - printf(" OK!\n\n"); - - printf("[+] %s WAD, please wait...\n", (!mode) ? "Installing" : "Uninstalling"); - - /* Do install/uninstall */ - WiiLightControl (WII_LIGHT_ON); - if (!mode) - Wad_Install(fp); - else - Wad_Uninstall(fp); - WiiLightControl (WII_LIGHT_OFF); - -out: - /* Close file */ - if (fp) - fclose(fp); - - printf("\n"); - printf(" Press any button to continue...\n"); - - /* Wait for button */ - WaitButtons(); -} - -void Menu_WadList(void) -{ - char str [100]; - fatFile *fileList = NULL; - u32 fileCnt; - int ret, selected = 0, start = 0; - char *tmpPath = malloc (MAX_FILE_PATH_LEN); - int installCnt = 0; - int uninstallCnt = 0; - - //fatFile *installFiles = malloc(sizeof(fatFile) * 50); - //int installCount = 0; - - // wiiNinja: check for malloc error - if (tmpPath == NULL) - { - ret = -997; // What am I gonna use here? - printf(" ERROR! Out of memory (ret = %d)\n", ret); - return; - } - - printf("[+] Retrieving file list..."); - fflush(stdout); - - gDirLevel = 0; - - // push root dir as base folder - sprintf(tmpPath, "%s:%s", fdev->mount, WAD_DIRECTORY); - PushCurrentDir(tmpPath,0,0); - // if user provides startup directory, try it out first - if (strcmp (WAD_DIRECTORY, gConfig.startupPath) != 0) - { - // replace root dir with provided startup directory - sprintf(tmpPath, "%s:%s", fdev->mount, gConfig.startupPath); - // If the directory can be successfully opened, it must exists - DIR *tmpDirPtr = opendir(tmpPath); - if (tmpDirPtr) - { - closedir (tmpDirPtr); - PushCurrentDir(tmpPath,0,0); - } - else // unable to open provided dir, stick with root dir - sprintf(tmpPath, "%s:%s", fdev->mount, WAD_DIRECTORY); - } - - /* Retrieve filelist */ -getList: - free (fileList); - fileList = NULL; - - ret = __Menu_RetrieveList(tmpPath, &fileList, &fileCnt); - if (ret < 0) { - printf(" ERROR! (ret = %d)\n", ret); - goto err; - } - - /* No files */ - if (!fileCnt) { - printf(" No files found!\n"); - goto err; - } - - /* Set install-values to 0 - Leathl */ - int counter; - for (counter = 0; counter < fileCnt; counter++) { - fatFile *file = &fileList[counter]; - file->install = 0; - } - - for (;;) - { - u32 cnt; - s32 index; - - /* Clear console */ - Con_Clear(); - - /** Print entries **/ - cnt = strlen(tmpPath); - if(cnt>30) - index = cnt-30; - else - index = 0; - - printf("[+] WAD files on [%s]:\n\n", tmpPath+index); - - /* Print entries */ - for (cnt = start; cnt < fileCnt; cnt++) - { - fatFile *file = &fileList[cnt]; - f32 filesize = file->fsize / MB_SIZE; - - /* Entries per page limit */ - if ((cnt - start) >= ENTRIES_PER_PAGE) - break; - - strncpy(str, file->filename, 40); //Only 40 chars to fit the screen - str[40]=0; - - /* Print filename */ - //printf("\t%2s %s (%.2f MB)\n", (cnt == selected) ? ">>" : " ", file->filename, filesize); - if (file->isdir) // wiiNinja - printf("\t%2s [%s]\n", (cnt == selected) ? ">>" : " ", str); - else - printf("\t%2s%s%s (%.2f MB)\n", (cnt == selected) ? ">>" : " ", (file->install == 1) ? "+" : ((file->install == 2) ? "-" : " "), str, filesize); - - } - - printf("\n"); - - printf("[+] Press A to (un)install."); - if(gDirLevel>1) - printf(" Press B to go up-level DIR.\n"); - else - printf(" Press B to select a device.\n"); - printf(" Use +/X and -/Y to (un)mark. Press 1/Z/ZR for delete menu.\n"); - - printf(" Press 2 to launch app.\n"); - - /** Controls **/ - u32 buttons = WaitButtons(); - - if (buttons & WPAD_BUTTON_2) - { - if (!LoadApp(tmpPath)) - { - printf(" Failed to load app.\n"); - goto err; - } - - Fat_Unmount(fdev); - //SetIos(36); - - LaunchApp(); - } - - /* DPAD buttons */ - if (buttons & WPAD_BUTTON_UP) { - selected--; - - if (selected <= -1) - selected = (fileCnt - 1); - } - if (buttons & WPAD_BUTTON_LEFT) { - selected = selected + ENTRIES_PER_PAGE; - - if (selected >= fileCnt) - selected = 0; - } - if (buttons & WPAD_BUTTON_DOWN) { - selected ++; - - if (selected >= fileCnt) - selected = 0; - } - if (buttons & WPAD_BUTTON_RIGHT) { - selected = selected - ENTRIES_PER_PAGE; - - if (selected <= -1) - selected = (fileCnt - 1); - } - - /* HOME button */ - if (buttons & WPAD_BUTTON_HOME) - Restart(); - - /* Plus Button - Leathl */ - if (buttons & WPAD_BUTTON_PLUS) - { - if(Wpad_TimeButton()) - { - installCnt = 0; - int i = 0; - while( i < fileCnt) - { - fatFile *file = &fileList[i]; - if (((file->isdir) == false) & (file->install == 0)) { - file->install = 1; - - installCnt += 1; - } - else if (((file->isdir) == false) & (file->install == 1)) { - file->install = 0; - - installCnt -= 1; - } - else if (((file->isdir) == false) & (file->install == 2)) { - file->install = 1; - - installCnt += 1; - uninstallCnt -= 1; - } - i++; - } - - } - else - { - fatFile *file = &fileList[selected]; - if (((file->isdir) == false) & (file->install == 0)) { - file->install = 1; - - installCnt += 1; - } - else if (((file->isdir) == false) & (file->install == 1)) { - file->install = 0; - - installCnt -= 1; - } - else if (((file->isdir) == false) & (file->install == 2)) { - file->install = 1; - - installCnt += 1; - uninstallCnt -= 1; - } - selected++; - - if (selected >= fileCnt) - selected = 0; - } - } - - /* Minus Button - Leathl */ - if (buttons & WPAD_BUTTON_MINUS) - { - if(Wpad_TimeButton()) - { - installCnt = 0; - int i = 0; - while( i < fileCnt) - { - fatFile *file = &fileList[i]; - if (((file->isdir) == false) & (file->install == 0)) { - file->install = 2; - - uninstallCnt += 1; - } - else if (((file->isdir) == false) & (file->install == 1)) { - file->install = 2; - - uninstallCnt += 1; - installCnt -= 1; - } - else if (((file->isdir) == false) & (file->install == 2)) { - file->install = 0; - - uninstallCnt -= 1; - } - i++; - } - - } - else - { - fatFile *file = &fileList[selected]; - if (((file->isdir) == false) & (file->install == 0)) { - file->install = 2; - - uninstallCnt += 1; - } - else if (((file->isdir) == false) & (file->install == 1)) { - file->install = 2; - - uninstallCnt += 1; - installCnt -= 1; - } - else if (((file->isdir) == false) & (file->install == 2)) { - file->install = 0; - - uninstallCnt -= 1; - } - selected++; - - if (selected >= fileCnt) - selected = 0; - } - } - - /* 1 Button - Leathl */ - if (buttons & WPAD_BUTTON_1) - { - fatFile *tmpFile = &fileList[selected]; - char *tmpCurPath = PeekCurrentDir (); - if (tmpCurPath != NULL) { - int res = Menu_FileOperations(tmpFile, tmpCurPath); - if (res != 0) - goto getList; - } - } - - - /* A button */ - if (buttons & WPAD_BUTTON_A) - { - fatFile *tmpFile = &fileList[selected]; - char *tmpCurPath; - if (tmpFile->isdir) // wiiNinja - { - if (strcmp (tmpFile->filename, "..") == 0) - { - selected = 0; - start = 0; - - // Previous dir - tmpCurPath = PopCurrentDir(&selected, &start); - if (tmpCurPath != NULL) - sprintf(tmpPath, "%s", tmpCurPath); - - installCnt = 0; - uninstallCnt = 0; - - goto getList; - } - else if (IsListFull () == true) - { - WaitPrompt ("Maximum number of directory levels is reached.\n"); - } - else - { - tmpCurPath = PeekCurrentDir (); - if (tmpCurPath != NULL) - { - if(gDirLevel>1) - sprintf(tmpPath, "%s/%s", tmpCurPath, tmpFile->filename); - else - sprintf(tmpPath, "%s%s", tmpCurPath, tmpFile->filename); - } - // wiiNinja: Need to PopCurrentDir - PushCurrentDir (tmpPath, selected, start); - selected = 0; - start = 0; - - installCnt = 0; - uninstallCnt = 0; - - goto getList; - } - } - else - { - //If at least one WAD is marked, goto batch screen - Leathl - if ((installCnt > 0) | (uninstallCnt > 0)) { - char *thisCurPath = PeekCurrentDir (); - if (thisCurPath != NULL) { - int res = Menu_BatchProcessWads(fileList, fileCnt, thisCurPath, installCnt, uninstallCnt); - - if (res == 1) { - int counter; - for (counter = 0; counter < fileCnt; counter++) { - fatFile *temp = &fileList[counter]; - temp->install = 0; - } - - installCnt = 0; - uninstallCnt = 0; - } - } - } - //else use standard wadmanage menu - Leathl - else { - tmpCurPath = PeekCurrentDir (); - if (tmpCurPath != NULL) - Menu_WadManage(tmpFile, tmpCurPath); - } - } - } - - /* B button */ - if (buttons & WPAD_BUTTON_B) - { - if(gDirLevel<=1) - { - return; - } - - char *tmpCurPath; - selected = 0; - start = 0; - // Previous dir - tmpCurPath = PopCurrentDir(&selected, &start); - if (tmpCurPath != NULL) - sprintf(tmpPath, "%s", tmpCurPath); - goto getList; - //return; - } - - /** Scrolling **/ - /* List scrolling */ - index = (selected - start); - - if (index >= ENTRIES_PER_PAGE) - start += index - (ENTRIES_PER_PAGE - 1); - if (index <= -1) - start += index; - } - -err: - printf("\n"); - printf(" Press any button to continue...\n"); - - free (tmpPath); - - /* Wait for button */ - WaitButtons(); -} - - -void Menu_Loop(void) -{ - u8 iosVersion; - if(AHBPROT_DISABLED) - IOSPATCH_Apply(); - else - { - /* Select IOS menu */ - Menu_SelectIOS(); - } - - /* Retrieve IOS version */ - iosVersion = IOS_GetVersion(); - - ndev = &ndevList[0]; - - /* NAND device menu */ - if ((iosVersion == CIOS_VERSION || iosVersion == 250) && IOS_GetRevision() >13) - { - Menu_NandDevice(); - } - for (;;) { - /* FAT device menu */ - Menu_FatDevice(); - - /* WAD list menu */ - Menu_WadList(); - } -} - -// Start of wiiNinja's added routines - -int PushCurrentDir (char *dirStr, int Selected, int Start) -{ - int retval = 0; - - // Store dirStr into the list and increment the gDirLevel - // WARNING: Make sure dirStr is no larger than MAX_FILE_PATH_LEN - if (gDirLevel < MAX_DIR_LEVELS) - { - strcpy (gDirList [gDirLevel], dirStr); - gSeleted[gDirLevel]=Selected; - gStart[gDirLevel]=Start; - gDirLevel++; - //if (gDirLevel >= MAX_DIR_LEVELS) - // gDirLevel = 0; - } - else - retval = -1; - - return (retval); -} - -char *PopCurrentDir(int *Selected, int *Start) -{ - if (gDirLevel > 1) - gDirLevel--; - else { - gDirLevel = 0; - } - *Selected = gSeleted[gDirLevel]; - *Start = gStart[gDirLevel]; - return PeekCurrentDir(); -} - -bool IsListFull (void) -{ - if (gDirLevel < MAX_DIR_LEVELS) - return (false); - else - return (true); -} - -char *PeekCurrentDir (void) -{ - // Return the current path - if (gDirLevel > 0) - return (gDirList [gDirLevel-1]); - else - return (NULL); -} - -void WaitPrompt (char *prompt) -{ - printf("\n%s", prompt); - printf(" Press any button to continue...\n"); - - /* Wait for button */ - WaitButtons(); -} - -u32 Pad_GetButtons(void) -{ - u32 buttons = 0, cnt; - - /* Scan pads */ - PAD_ScanPads(); - - /* Get pressed buttons */ - //for (cnt = 0; cnt < MAX_WIIMOTES; cnt++) - for (cnt = 0; cnt < 4; cnt++) - buttons |= PAD_ButtonsDown(cnt); - - return buttons; -} - -u32 WiiDRC_GetButtons(void) -{ - if(!WiiDRC_Inited() || !WiiDRC_Connected()) - return 0; - - /* Scan pads */ - WiiDRC_ScanPads(); - - /* Get pressed buttons */ - return WiiDRC_ButtonsDown(); -} - -// Routine to wait for a button from either the Wiimote or a gamecube -// controller. The return value will mimic the WPAD buttons to minimize -// the amount of changes to the original code, that is expecting only -// Wiimote button presses. Note that the "HOME" button on the Wiimote -// is mapped to the "SELECT" button on the Gamecube Ctrl. (wiiNinja 5/15/2009) -u32 WaitButtons(void) -{ - u32 buttons = 0; - u32 buttonsGC = 0; - u32 buttonsDRC = 0; - - /* Wait for button pressing */ - while (!buttons && !buttonsGC && !buttonsDRC) - { - // Wii buttons - buttons = Wpad_GetButtons(); - - // GC buttons - buttonsGC = Pad_GetButtons(); - - // DRC buttons - buttonsDRC = WiiDRC_GetButtons(); - - VIDEO_WaitVSync(); - } - - if(buttons & WPAD_CLASSIC_BUTTON_A) - buttons |= WPAD_BUTTON_A; - else if(buttons & WPAD_CLASSIC_BUTTON_B) - buttons |= WPAD_BUTTON_B; - else if(buttons & WPAD_CLASSIC_BUTTON_LEFT) - buttons |= WPAD_BUTTON_LEFT; - else if(buttons & WPAD_CLASSIC_BUTTON_RIGHT) - buttons |= WPAD_BUTTON_RIGHT; - else if(buttons & WPAD_CLASSIC_BUTTON_DOWN) - buttons |= WPAD_BUTTON_DOWN; - else if(buttons & WPAD_CLASSIC_BUTTON_UP) - buttons |= WPAD_BUTTON_UP; - else if(buttons & WPAD_CLASSIC_BUTTON_HOME) - buttons |= WPAD_BUTTON_HOME; - else if(buttons & (WPAD_CLASSIC_BUTTON_X | WPAD_CLASSIC_BUTTON_PLUS)) - buttons |= WPAD_BUTTON_PLUS; - else if(buttons & (WPAD_CLASSIC_BUTTON_Y | WPAD_CLASSIC_BUTTON_MINUS)) - buttons |= WPAD_BUTTON_MINUS; - else if(buttons & WPAD_CLASSIC_BUTTON_ZR) - buttons |= WPAD_BUTTON_1; - - if (buttonsGC) - { - if(buttonsGC & PAD_BUTTON_A) - buttons |= WPAD_BUTTON_A; - else if(buttonsGC & PAD_BUTTON_B) - buttons |= WPAD_BUTTON_B; - else if(buttonsGC & PAD_BUTTON_LEFT) - buttons |= WPAD_BUTTON_LEFT; - else if(buttonsGC & PAD_BUTTON_RIGHT) - buttons |= WPAD_BUTTON_RIGHT; - else if(buttonsGC & PAD_BUTTON_DOWN) - buttons |= WPAD_BUTTON_DOWN; - else if(buttonsGC & PAD_BUTTON_UP) - buttons |= WPAD_BUTTON_UP; - else if(buttonsGC & PAD_BUTTON_START) - buttons |= WPAD_BUTTON_HOME; - else if(buttonsGC & PAD_BUTTON_X) - buttons |= WPAD_BUTTON_PLUS; - else if(buttonsGC & PAD_BUTTON_Y) - buttons |= WPAD_BUTTON_MINUS; - else if(buttonsGC & PAD_TRIGGER_Z) - buttons |= WPAD_BUTTON_1; - } - - if (buttonsDRC) - { - if(buttonsDRC & WIIDRC_BUTTON_A) - buttons |= WPAD_BUTTON_A; - else if(buttonsDRC & WIIDRC_BUTTON_B) - buttons |= WPAD_BUTTON_B; - else if(buttonsDRC & WIIDRC_BUTTON_LEFT) - buttons |= WPAD_BUTTON_LEFT; - else if(buttonsDRC & WIIDRC_BUTTON_RIGHT) - buttons |= WPAD_BUTTON_RIGHT; - else if(buttonsDRC & WIIDRC_BUTTON_DOWN) - buttons |= WPAD_BUTTON_DOWN; - else if(buttonsDRC & WIIDRC_BUTTON_UP) - buttons |= WPAD_BUTTON_UP; - else if(buttonsDRC & WIIDRC_BUTTON_HOME) - buttons |= WPAD_BUTTON_HOME; - else if(buttonsDRC & (WIIDRC_BUTTON_X | WIIDRC_BUTTON_PLUS)) - buttons |= WPAD_BUTTON_PLUS; - else if(buttonsDRC & (WIIDRC_BUTTON_Y | WIIDRC_BUTTON_MINUS)) - buttons |= WPAD_BUTTON_MINUS; - else if(buttonsDRC & WIIDRC_BUTTON_ZR) - buttons |= WPAD_BUTTON_1; - } - - return buttons; -} // WaitButtons - - -void WiiLightControl (int state) -{ - switch (state) - { - case WII_LIGHT_ON: - /* Turn on Wii Light */ - WIILIGHT_SetLevel(255); - WIILIGHT_TurnOn(); - break; - - case WII_LIGHT_OFF: - default: - /* Turn off Wii Light */ - WIILIGHT_SetLevel(0); - WIILIGHT_TurnOn(); - WIILIGHT_Toggle(); - break; - } -} // WiiLightControl - diff --git a/data/appboot.bin b/data/appboot.bin index 5adac45..08ab355 100644 Binary files a/data/appboot.bin and b/data/appboot.bin differ diff --git a/source/fat.c b/source/fat.c index 5c8081b..b20cecf 100644 --- a/source/fat.c +++ b/source/fat.c @@ -1,58 +1,104 @@ #include #include #include +#include +#include +#include +#include + //#include #include "fat.h" +#include "usbstorage.h" - -s32 Fat_Mount(fatDevice *dev) +typedef struct { - s32 ret; + /* Device prefix */ + char* prefix; - /* Initialize interface */ - ret = dev->interface->startup(); - if (!ret) - return -1; + /* Device name */ + char* name; - /* Mount device */ - ret = fatMountSimple(dev->mount, dev->interface); - if (!ret) - return -1; + /* Device available */ + bool isMounted; - return 0; + /* Device interface */ + const DISC_INTERFACE* interface; +} FatDevice; + +static FatDevice DeviceList[] = +{ + { "sd", "Wii SD Slot", false, &__io_wiisd }, + { "usb", "USB Mass Storage Device", false, &__io_usbstorage }, + { "usb2", "USB 2.0 Mass Storage Device", false, &__io_wiiums }, + { "gcsda", "SD Gecko (Slot A)", false, &__io_gcsda }, + { "gcsdb", "SD Gecko (Slot B)", false, &__io_gcsdb }, +}; + +static u32 gNumDevices = 0; +FatDevice* gDevices[(sizeof(DeviceList) / sizeof(FatDevice))]; + +void FatMount() +{ + FatUnmount(); + + s32 i; + for (i = 0; i < (sizeof(DeviceList) / sizeof(FatDevice)); i++) + { + gDevices[gNumDevices] = &DeviceList[i]; + + s32 ret = gDevices[gNumDevices]->interface->startup(); + + if (!ret) + continue; + + ret = fatMountSimple(gDevices[gNumDevices]->prefix, gDevices[gNumDevices]->interface); + + if (!ret) + continue; + + gDevices[gNumDevices]->isMounted = true; + gNumDevices++; + } } -void Fat_Unmount(fatDevice *dev) +void FatUnmount() { - /* Unmount device */ - fatUnmount(dev->mount); - - /* Shutdown interface */ - dev->interface->shutdown(); -} - -char *Fat_ToFilename(const char *filename) -{ - static char buffer[128]; - - u32 cnt, idx, len; - - /* Clear buffer */ - memset(buffer, 0, sizeof(buffer)); - - /* Get filename length */ - len = strlen(filename); - - for (cnt = idx = 0; idx < len; idx++) { - char c = filename[idx]; - - /* Valid characters */ - if ( (c >= '#' && c <= ')') || (c >= '-' && c <= '.') || - (c >= '0' && c <= '9') || (c >= 'A' && c <= 'z') || - (c >= 'a' && c <= 'z') || (c == '!') ) - buffer[cnt++] = c; + s32 i; + for (i = 0; i < FatGetDeviceCount(); i++) + { + fatUnmount(gDevices[i]->prefix); + gDevices[i]->interface->shutdown(); + gDevices[i]->isMounted = false; } - return buffer; + gNumDevices = 0; +} + +char* FatGetDeviceName(u8 index) +{ + if (index >= FatGetDeviceCount()) + return NULL; + + if (gDevices[index]->isMounted) + return gDevices[index]->name; + + return NULL; +} + + +char* FatGetDevicePrefix(u8 index) +{ + if (index >= FatGetDeviceCount()) + return NULL; + + if (gDevices[index]->isMounted) + return gDevices[index]->prefix; + + return NULL; +} + +s32 FatGetDeviceCount() +{ + return gNumDevices; } diff --git a/source/fat.h b/source/fat.h index bf869df..26538f2 100644 --- a/source/fat.h +++ b/source/fat.h @@ -1,27 +1,6 @@ #ifndef _FAT_H_ #define _FAT_H_ -/* libfat header */ -#include -#include - -/* SD headers */ -#include -#include - - -/* 'FAT Device' structure */ -typedef struct { - /* Device mount point */ - char *mount; - - /* Device name */ - char *name; - - /* Device interface */ - const DISC_INTERFACE *interface; -} fatDevice; - /* 'FAT File' structure */ typedef struct { /* Filename */ @@ -41,9 +20,11 @@ typedef struct { /* Prototypes */ -s32 Fat_Mount(fatDevice *); -void Fat_Unmount(fatDevice *); -char *Fat_ToFilename(const char *); + +void FatMount(); +void FatUnmount(); +char* FatGetDeviceName(u8 index); +char* FatGetDevicePrefix(u8 index); +s32 FatGetDeviceCount(); #endif - diff --git a/source/fileops.c b/source/fileops.c new file mode 100644 index 0000000..5b52bd7 --- /dev/null +++ b/source/fileops.c @@ -0,0 +1,80 @@ +#include +#include + +#include "fileops.h" + + +bool FSOPFileExists(const char* file) +{ + FILE* f; + f = fopen(file, "rb"); + if (f) + { + fclose(f); + return true; + } + return false; +} + +bool FSOPFolderExists(const char* path) +{ + DIR* dir; + dir = opendir(path); + if (dir) + { + closedir(dir); + return true; + } + return false; +} + +size_t FSOPGetFileSizeBytes(const char* path) +{ + FILE* f; + size_t size = 0; + + f = fopen(path, "rb"); + if (!f) + return 0; + + fseek(f, 0, SEEK_END); + size = ftell(f); + fclose(f); + + return size; +} + +void FSOPDeleteFile(const char* file) +{ + if (!FSOPFileExists(file)) + return; + + remove(file); +} + +void FSOPMakeFolder(const char* path) +{ + if (FSOPFolderExists(path)) + return; + + mkdir(path, S_IREAD | S_IWRITE); +} + +s32 FSOPReadOpenFile(FILE* fp, void* buffer, u32 offset, u32 length) +{ + fseek(fp, offset, SEEK_SET); + return fread(buffer, length, 1, fp); +} + +s32 FSOPReadOpenFileA(FILE* fp, void** buffer, u32 offset, u32 length) +{ + *buffer = memalign(32, length); + if (!*buffer) + return -1; + + s32 ret = FSOPReadOpenFile(fp, *buffer, offset, length); + if (ret < 0) + free(*buffer); + + return ret; +} diff --git a/source/fileops.h b/source/fileops.h new file mode 100644 index 0000000..b912721 --- /dev/null +++ b/source/fileops.h @@ -0,0 +1,17 @@ +#ifndef __FILEOPS_H__ +#define __FILEOPS_H__ + +#include +#include + +bool FSOPFileExists(const char* file); +bool FSOPFolderExists(const char* path); +size_t FSOPGetFileSizeBytes(const char* path); + +void FSOPDeleteFile(const char* file); +void FSOPMakeFolder(const char* path); + +s32 FSOPReadOpenFile(FILE* fp, void* buffer, u32 offset, u32 length); +s32 FSOPReadOpenFileA(FILE* fp, void** buffer, u32 offset, u32 length); + +#endif \ No newline at end of file diff --git a/source/globals.h b/source/globals.h index 1db1364..5172e99 100644 --- a/source/globals.h +++ b/source/globals.h @@ -3,7 +3,7 @@ // Constants #define CIOS_VERSION 249 -#define ENTRIES_PER_PAGE 14 +#define ENTRIES_PER_PAGE 12 #define MAX_FILE_PATH_LEN 1024 #define MAX_DIR_LEVELS 10 #define WAD_DIRECTORY "/" @@ -16,20 +16,8 @@ #define WM_CONFIG_FILE_PATH ":/wad/wm_config.txt" #define WM_BACKGROUND_PATH ":/wad/background.png" -// These are indices into the fatDevice fdevList -#define FAT_DEVICE_INDEX_WII_SD 0 -#define FAT_DEVICE_INDXE_USB 1 -#define FAT_DEVICE_INDEX_USB2 2 -#define FAT_DEVICE_INDEX_GC_SDA 3 -#define FAT_DEVICE_INDEX_GC_SDB 4 #define FAT_DEVICE_INDEX_INVALID -1 - -// These are the indices into the nandDevice ndevList -#define NAND_DEVICE_INDEX_DISABLE 0 -#define NAND_DEVICE_INDEX_SD 1 -#define NAND_DEVICE_INDEX_USB 2 #define NAND_DEVICE_INDEX_INVALID -1 - #define CIOS_VERSION_INVALID -1 // For the WiiLight @@ -52,7 +40,7 @@ typedef struct extern CONFIG gConfig; extern nandDevice ndevList[]; -extern fatDevice fdevList[]; +//extern fatDevice fdevList[]; #endif diff --git a/source/gui.c b/source/gui.c index 2305e9a..dffad46 100644 --- a/source/gui.c +++ b/source/gui.c @@ -7,6 +7,7 @@ #include "menu.h" #include "nand.h" #include "globals.h" +#include "fileops.h" /* Constants */ #define CONSOLE_XCOORD 70 @@ -14,36 +15,25 @@ #define CONSOLE_WIDTH 502 #define CONSOLE_HEIGHT 300 -bool file_exists(const char * filename) -{ - FILE * file; - if ((file = fopen(filename, "r"))) - { - fclose(file); - return true; - } - return false; -} - - s32 __Gui_DrawPng(void *img, u32 x, u32 y) { IMGCTX ctx = NULL; PNGUPROP imgProp; + char path[1024]; + s32 ret = -1; + s32 i; - s32 ret; - - fatDevice *fdev = &fdevList[0]; - ret = Fat_Mount(fdev); - if (file_exists("sd:/wad/background.png")) ctx = PNGU_SelectImageFromDevice ("sd:/wad/background.png"); - - if (ret < 0) + for (i = 0; i < FatGetDeviceCount(); i++) { - fdev = &fdevList[2]; - Fat_Mount(fdev); - if (file_exists("usb2:/wad/background.png")) ctx = PNGU_SelectImageFromDevice ("usb2:/wad/background.png"); + snprintf(path, sizeof(path), "%s:/wad/background.png", FatGetDevicePrefix(i)); + if (FSOPFileExists(path)) + { + ctx = PNGU_SelectImageFromDevice(path); + break; + } + } - + if(!ctx) { /* Select PNG data */ @@ -53,6 +43,7 @@ s32 __Gui_DrawPng(void *img, u32 x, u32 y) goto out; } } + /* Get image properties */ ret = PNGU_GetImageProperties(ctx, &imgProp); if (ret != PNGU_OK) { diff --git a/source/iospatch.c b/source/iospatch.c index 50d97e5..4895266 100644 --- a/source/iospatch.c +++ b/source/iospatch.c @@ -74,6 +74,8 @@ const u8 ES_TitleVersionCheck_old[] = { 0xD2, 0x01, 0x4E, 0x56 }; const u8 ES_TitleVersionCheck_patch[] = { 0xE0, 0x01, 0x4E, 0x56 }; const u8 ES_TitleDeleteCheck_old[] = { 0xD8, 0x00, 0x4A, 0x04 }; const u8 ES_TitleDeleteCheck_patch[] = { 0xE0, 0x00, 0x4A, 0x04 }; +const u8 isfs_permissions_old[] = { 0x9B, 0x05, 0x40, 0x03, 0x99, 0x05, 0x42, 0x8B, }; +const u8 isfs_permissions_patch[] = { 0x9B, 0x05, 0x40, 0x03, 0x1C, 0x0B, 0x42, 0x8B, }; //Following patches made my damysteryman for use with Wii U's vWii const u8 Kill_AntiSysTitleInstallv3_pt1_old[] = { 0x68, 0x1A, 0x2A, 0x01, 0xD0, 0x05 }; // Make sure that the pt1 @@ -97,7 +99,7 @@ u32 IOSPATCH_Apply() { if (AHBPROT_DISABLED) { disable_memory_protection(); //count += apply_patch("di_readlimit", di_readlimit_old, sizeof(di_readlimit_old), di_readlimit_patch, sizeof(di_readlimit_patch), 12); - //count += apply_patch("isfs_permissions", isfs_permissions_old, sizeof(isfs_permissions_old), isfs_permissions_patch, sizeof(isfs_permissions_patch), 0); + count += apply_patch("isfs_permissions", isfs_permissions_old, sizeof(isfs_permissions_old), isfs_permissions_patch, sizeof(isfs_permissions_patch), 0); //count += apply_patch("es_setuid", setuid_old, sizeof(setuid_old), setuid_patch, sizeof(setuid_patch), 0); //count += apply_patch("es_identify", es_identify_old, sizeof(es_identify_old), es_identify_patch, sizeof(es_identify_patch), 2); count += apply_patch("hash_check", hash_old, sizeof(hash_old), hash_patch, sizeof(hash_patch), 1); diff --git a/source/menu.c b/source/menu.c index 0ed273d..de46ab2 100644 --- a/source/menu.c +++ b/source/menu.c @@ -12,7 +12,6 @@ #include "nand.h" #include "restart.h" #include "title.h" -#include "usbstorage.h" #include "utils.h" #include "video.h" #include "wad.h" @@ -21,27 +20,16 @@ #include "globals.h" #include "iospatch.h" #include "appboot.h" - -/* FAT device list */ -//static fatDevice fdevList[] = { -fatDevice fdevList[] = { - { "sd", "Wii SD Slot", &__io_wiisd }, - { "usb", "USB Mass Storage Device", &__io_usbstorage }, - { "usb2", "USB 2.0 Mass Storage Device", &__io_wiiums }, - { "gcsda", "SD Gecko (Slot A)", &__io_gcsda }, - { "gcsdb", "SD Gecko (Slot B)", &__io_gcsdb }, -}; +#include "fileops.h" /* NAND device list */ -//static nandDevice ndevList[] = { -nandDevice ndevList[] = { +nandDevice ndevList[] = +{ { "Disable", 0, 0x00, 0x00 }, { "SD/SDHC Card", 1, 0xF0, 0xF1 }, { "USB 2.0 Mass Storage Device", 2, 0xF2, 0xF3 }, }; -/* FAT device */ -static fatDevice *fdev = NULL; static nandDevice *ndev = NULL; // wiiNinja: Define a buffer holding the previous path names as user @@ -50,9 +38,12 @@ static u8 gDirLevel = 0; static char gDirList [MAX_DIR_LEVELS][MAX_FILE_PATH_LEN]; static s32 gSeleted[MAX_DIR_LEVELS]; static s32 gStart[MAX_DIR_LEVELS]; +static char gMenuRegion = '\0'; +static u16 gMenuVersion = 0; +static u8 gSelected = 0; /* Macros */ -#define NB_FAT_DEVICES (sizeof(fdevList) / sizeof(fatDevice)) +//#define NB_FAT_DEVICES (sizeof(fdevList) / sizeof(fatDevice)) #define NB_NAND_DEVICES (sizeof(ndevList) / sizeof(nandDevice)) // Local prototypes: wiiNinja @@ -92,34 +83,6 @@ int __Menu_EntryCmp(const void *p1, const void *p2) return strcasecmp(f1->filename, f2->filename); } -static bool __FolderExists(const char *path) -{ - DIR *dir; - dir = opendir(path); - if(dir) - { - closedir(dir); - return true; - } - return false; -} - -static size_t __GetFileSizeBytes(const char *path) -{ - FILE *f; - size_t size = 0; - - f = fopen(path, "rb"); - if(!f) return 0; - - //Get file size - fseek(f, 0, SEEK_END); - size = ftell(f); - fclose(f); - - return size; -} - char gFileName[MAX_FILE_PATH_LEN]; s32 __Menu_RetrieveList(char *inPath, fatFile **outbuf, u32 *outlen) { @@ -165,7 +128,7 @@ s32 __Menu_RetrieveList(char *inPath, fatFile **outbuf, u32 *outlen) size_t fsize = 0; snprintf(gFileName, MAX_FILE_PATH_LEN, "%s/%s", inPath, ent->d_name); - if (__FolderExists(gFileName)) // wiiNinja + if (FSOPFolderExists(gFileName)) // wiiNinja { isdir = true; // Add only the item ".." which is the previous directory @@ -181,19 +144,19 @@ s32 __Menu_RetrieveList(char *inPath, fatFile **outbuf, u32 *outlen) { if(!strcasecmp(ent->d_name+strlen(ent->d_name)-4, ".wad")) { - fsize = __GetFileSizeBytes(gFileName); + fsize = FSOPGetFileSizeBytes(gFileName); addFlag = true; iswad = true; } if(!strcasecmp(ent->d_name+strlen(ent->d_name)-4, ".dol")) { - fsize = __GetFileSizeBytes(gFileName); + fsize = FSOPGetFileSizeBytes(gFileName); addFlag = true; isdol = true; } if(!strcasecmp(ent->d_name+strlen(ent->d_name)-4, ".elf")) { - fsize = __GetFileSizeBytes(gFileName); + fsize = FSOPGetFileSizeBytes(gFileName); addFlag = true; iself = true; } @@ -333,74 +296,94 @@ void Menu_SelectIOS(void) void Menu_FatDevice(void) { - int ret, selected = 0; + FatMount(); - /* Unmount FAT device */ - //if (fdev) - //Fat_Unmount(fdev); - //if (((fdevList[selected].mount[0] == 's') && (ndev->name[0] == 'S'))) - //selected++; - static const u16 konamiCode[] = { + const u16 konamiCode[] = + { WPAD_BUTTON_UP, WPAD_BUTTON_UP, WPAD_BUTTON_DOWN, WPAD_BUTTON_DOWN, WPAD_BUTTON_LEFT, WPAD_BUTTON_RIGHT, WPAD_BUTTON_LEFT, WPAD_BUTTON_RIGHT, WPAD_BUTTON_B, WPAD_BUTTON_A }; int codePosition = 0; + extern bool skipRegionSafetyCheck; /* Select source device */ if (gConfig.fatDeviceIndex < 0) { - for (;;) { + for (;;) + { /* Clear console */ Con_Clear(); + if (!FatGetDeviceCount()) + { + printf("\t[+] No source device: < %s >\n\n", FatGetDeviceName(gSelected)); + } + /* Selected device */ - fdev = &fdevList[selected]; - - printf("\t>> Select source device: < %s >\n\n", fdev->name); - + //printf("\tWii menu version: %d, region: %s\n\n", gMenuVersion, GetSysMenuRegionString(&gMenuRegion)); + printf("\t>> Select source device: < %s >\n\n", FatGetDeviceName(gSelected)); printf("\t Press LEFT/RIGHT to change the selected device.\n\n"); - printf("\t Press A button to continue.\n"); + printf("\t Press B button to remount source devices.\n"); printf("\t Press HOME button to restart.\n\n"); + if (skipRegionSafetyCheck) + { + printf("[+] WARNING: SM Region checks disabled!\n\n"); + printf("\t Press 1 button to reset.\n"); + } + + u32 buttons = WaitButtons(); - if (buttons & (WPAD_BUTTON_UP | WPAD_BUTTON_DOWN | WPAD_BUTTON_RIGHT | WPAD_BUTTON_LEFT | WPAD_BUTTON_A | WPAD_BUTTON_B)) { - if (buttons & konamiCode[codePosition]) - ++codePosition; - else - codePosition = 0; + if (buttons & (WPAD_BUTTON_UP | WPAD_BUTTON_DOWN | WPAD_BUTTON_RIGHT | WPAD_BUTTON_LEFT | WPAD_BUTTON_A | WPAD_BUTTON_B)) + { + if (!skipRegionSafetyCheck) + { + if (buttons & konamiCode[codePosition]) + ++codePosition; + else + codePosition = 0; + } } - - /* LEFT/RIGHT buttons */ - if (buttons & WPAD_BUTTON_LEFT) { - if ((--selected) <= -1) - selected = (NB_FAT_DEVICES - 1); - if ((fdevList[selected].mount[0] == 's') && (ndev->name[0] == 'S')) - selected--; - if ((fdevList[selected].mount[0] == 'u' && fdevList[selected].mount[3] == '2') && (ndev->name[0] == 'U')) - selected--; - if ((selected) <= -1) - selected = (NB_FAT_DEVICES - 1); + if (buttons & WPAD_BUTTON_LEFT) + { + if ((s8)(--gSelected) < 0) + gSelected = FatGetDeviceCount() - 1; } - if (buttons & WPAD_BUTTON_RIGHT) { - if ((++selected) >= NB_FAT_DEVICES) - selected = 0; - if ((fdevList[selected].mount[0] == 's') && (ndev->name[0] == 'S')) - selected++; - if ((fdevList[selected].mount[0] == 'u' && fdevList[selected].mount[3] == '2') && (ndev->name[0] == 'U')) - selected++; + else if (buttons & WPAD_BUTTON_1 && skipRegionSafetyCheck) + { + skipRegionSafetyCheck = false; } - - /* HOME button */ - if (buttons & WPAD_BUTTON_HOME) + else if (buttons & WPAD_BUTTON_RIGHT) + { + if ((++gSelected) >= FatGetDeviceCount()) + gSelected = 0; + } + else if (buttons & WPAD_BUTTON_HOME) + { Restart(); - - /* A button */ - if (buttons & WPAD_BUTTON_A) { - if (codePosition == sizeof(konamiCode) / sizeof(konamiCode[0])) { - extern bool skipRegionSafetyCheck; + } + else if (buttons & WPAD_BUTTON_B && !codePosition) + { + printf("\t\t[-] Mounting devices."); + usleep(500000); + printf("\r\t\t[\\]"); + usleep(500000); + printf("\r\t\t[|]"); + usleep(500000); + printf("\r\t\t[/]"); + usleep(500000); + printf("\r\t\t[-]"); + FatMount(); + gSelected = 0; + usleep(500000); + } + else if (buttons & WPAD_BUTTON_A) + { + if (codePosition == sizeof(konamiCode) / sizeof(konamiCode[0])) + { skipRegionSafetyCheck = true; printf("[+] Disabled SM region checks\n"); sleep(3); @@ -412,34 +395,12 @@ void Menu_FatDevice(void) else { sleep(5); - fdev = &fdevList[gConfig.fatDeviceIndex]; + if (gConfig.fatDeviceIndex < FatGetDeviceCount()) + gSelected = gConfig.fatDeviceIndex; } - printf("[+] Mounting %s, please wait...", fdev->name ); - fflush(stdout); - - /* Mount FAT device */ - - ret = Fat_Mount(fdev); - if (ret < 0) { - printf(" ERROR! (ret = %d)\n", ret); - goto err; - } else - printf(" OK!\n"); + printf("[+] Selected source device: %s.", FatGetDeviceName(gSelected)); sleep(2); - return; - -err: - - if(gConfig.fatDeviceIndex >= 0) gConfig.fatDeviceIndex = -1; - WiiLightControl (WII_LIGHT_OFF); - printf("\n"); - printf(" Press any button to continue...\n"); - - WaitButtons(); - - /* Prompt menu again */ - Menu_FatDevice(); } void Menu_NandDevice(void) @@ -845,45 +806,58 @@ void Menu_WadList(void) gDirLevel = 0; - // push root dir as base folder - sprintf(tmpPath, "%s:%s", fdev->mount, WAD_DIRECTORY); + // push root dir as base folderGetDevice() + //sprintf(tmpPath, "%s:%s", fdev->mount, WAD_DIRECTORY); + sprintf(tmpPath, "%s:%s", FatGetDevicePrefix(gSelected), WAD_DIRECTORY); PushCurrentDir(tmpPath,0,0); // if user provides startup directory, try it out first if (strcmp (WAD_DIRECTORY, gConfig.startupPath) != 0) { // replace root dir with provided startup directory - sprintf(tmpPath, "%s:%s", fdev->mount, gConfig.startupPath); - // If the directory can be successfully opened, it must exists - DIR *tmpDirPtr = opendir(tmpPath); - if (tmpDirPtr) - { - closedir (tmpDirPtr); - PushCurrentDir(tmpPath,0,0); - } - else // unable to open provided dir, stick with root dir - sprintf(tmpPath, "%s:%s", fdev->mount, WAD_DIRECTORY); + sprintf(tmpPath, "%s:%s", FatGetDevicePrefix(gSelected), gConfig.startupPath); + + if (FSOPFolderExists(tmpPath)) + PushCurrentDir(tmpPath, 0, 0); + else + sprintf(tmpPath, "%s:%s", FatGetDevicePrefix(gSelected), WAD_DIRECTORY); + + // If the directory can be successfully opened, it must exists + // DIR *tmpDirPtr = opendir(tmpPath); + // if (tmpDirPtr) + // { + // closedir (tmpDirPtr); + // PushCurrentDir(tmpPath,0,0); + // } + //else // unable to open provided dir, stick with root dir + //{ + // sprintf(tmpPath, "%s:%s", FatGetDevicePrefix(gSelected), WAD_DIRECTORY); + //} + } /* Retrieve filelist */ getList: - free (fileList); + free(fileList); fileList = NULL; ret = __Menu_RetrieveList(tmpPath, &fileList, &fileCnt); - if (ret < 0) { + if (ret < 0) + { printf(" ERROR! (ret = %d)\n", ret); goto err; } /* No files */ - if (!fileCnt) { + if (!fileCnt) + { printf(" No files found!\n"); goto err; } /* Set install-values to 0 - Leathl */ int counter; - for (counter = 0; counter < fileCnt; counter++) { + for (counter = 0; counter < fileCnt; counter++) + { fatFile *file = &fileList[counter]; file->install = 0; } @@ -898,8 +872,8 @@ getList: /** Print entries **/ cnt = strlen(tmpPath); - if(cnt>30) - index = cnt-30; + if(cnt > 30) + index = cnt - 30; else index = 0; @@ -916,13 +890,16 @@ getList: break; strncpy(str, file->filename, 40); //Only 40 chars to fit the screen - str[40]=0; + str[40] = 0; /* Print filename */ //printf("\t%2s %s (%.2f MB)\n", (cnt == selected) ? ">>" : " ", file->filename, filesize); if (file->isdir) // wiiNinja + { printf("\t%2s [%s]\n", (cnt == selected) ? ">>" : " ", str); - else { + } + else + { if(file->iswad) printf("\t%2s%s%s (%.2f MB)\n", (cnt == selected) ? ">>" : " ", (file->install == 1) ? "+" : ((file->install == 2) ? "-" : " "), str, filesize); else @@ -932,270 +909,285 @@ getList: printf("\n"); fatFile *file = &fileList[selected]; - if(file->iswad) - printf("[+] Press A to (un)install."); - else if(file->isdol || file->iself) - printf("[+] Press A to launch dol/elf."); - else if(file->isdir) - printf("[+] Press A to Enter directory."); - if(gDirLevel>1) + + if (file->iswad) + printf("[+] Press A to (un)install."); + else if (file->isdol || file->iself) + printf("[+] Press A to launch dol/elf."); + else if (file->isdir) + printf("[+] Press A to Enter directory."); + + if (gDirLevel > 1) printf(" Press B to go up-level DIR.\n"); else printf(" Press B to select a device.\n"); - if(file->iswad) printf(" Use +/X and -/Y to (un)mark. Press 1/Z/ZR for delete menu."); + + if (file->iswad) + printf(" Use +/X and -/Y to (un)mark. Press 1/Z/ZR for delete menu."); /** Controls **/ u32 buttons = WaitButtons(); /* DPAD buttons */ - if (buttons & WPAD_BUTTON_UP) { - selected--; - - if (selected <= -1) + if (buttons & WPAD_BUTTON_UP) + { + if (--selected < 0) selected = (fileCnt - 1); } - if (buttons & WPAD_BUTTON_LEFT) { - selected = selected + ENTRIES_PER_PAGE; + else if (buttons & WPAD_BUTTON_LEFT) + { + selected += ENTRIES_PER_PAGE; if (selected >= fileCnt) selected = 0; } - if (buttons & WPAD_BUTTON_DOWN) { - selected ++; - - if (selected >= fileCnt) + else if (buttons & WPAD_BUTTON_DOWN) + { + if (++selected >= fileCnt) selected = 0; } - if (buttons & WPAD_BUTTON_RIGHT) { - selected = selected - ENTRIES_PER_PAGE; + else if (buttons & WPAD_BUTTON_RIGHT) + { + selected -= ENTRIES_PER_PAGE; - if (selected <= -1) + if (selected < 0) selected = (fileCnt - 1); } - - /* HOME button */ - if (buttons & WPAD_BUTTON_HOME) + else if (buttons & WPAD_BUTTON_HOME) + { Restart(); - if(file->iswad) { - /* Plus Button - Leathl */ - if (buttons & WPAD_BUTTON_PLUS) + } + + if (file->iswad) { - if(Wpad_TimeButton()) + /* Plus Button - Leathl */ + if (buttons & WPAD_BUTTON_PLUS) { - installCnt = 0; - int i = 0; - while( i < fileCnt) - { - fatFile *file = &fileList[i]; - if (((file->isdir) == false) & (file->install == 0)) { - file->install = 1; + if(Wpad_TimeButton()) + { + installCnt = 0; + int i = 0; + while( i < fileCnt) + { + fatFile *file = &fileList[i]; + if (((file->isdir) == false) && (file->install == 0)) + { + file->install = 1; + installCnt += 1; + } + else if (((file->isdir) == false) && (file->install == 1)) + { + file->install = 0; + installCnt--; + } + else if (((file->isdir) == false) && (file->install == 2)) + { + file->install = 1; - installCnt += 1; - } - else if (((file->isdir) == false) & (file->install == 1)) { - file->install = 0; + installCnt++; + uninstallCnt--; + } - installCnt -= 1; - } - else if (((file->isdir) == false) & (file->install == 2)) { - file->install = 1; - - installCnt += 1; - uninstallCnt -= 1; - } - i++; - } + i++; + } + } + else + { + fatFile *file = &fileList[selected]; + if (((file->isdir) == false) && (file->install == 0)) + { + file->install = 1; + installCnt++; + } + else if (((file->isdir) == false) & (file->install == 1)) + { + file->install = 0; + installCnt--; + } + else if (((file->isdir) == false) & (file->install == 2)) + { + file->install = 1; + installCnt++; + uninstallCnt--; + } + + selected++; + if (selected >= fileCnt) + selected = 0; + } } - else + + /* Minus Button - Leathl */ + else if (buttons & WPAD_BUTTON_MINUS) { - fatFile *file = &fileList[selected]; - if (((file->isdir) == false) & (file->install == 0)) { - file->install = 1; + if(Wpad_TimeButton()) + { + installCnt = 0; + int i = 0; + + while( i < fileCnt) + { + fatFile *file = &fileList[i]; + if (((file->isdir) == false) && (file->install == 0)) + { + file->install = 2; + uninstallCnt++; + } + else if (((file->isdir) == false) && (file->install == 1)) + { + file->install = 2; + uninstallCnt++; + installCnt--; + } + else if (((file->isdir) == false) & (file->install == 2)) + { + file->install = 0; + uninstallCnt--; + } - installCnt += 1; - } - else if (((file->isdir) == false) & (file->install == 1)) { - file->install = 0; - - installCnt -= 1; - } - else if (((file->isdir) == false) & (file->install == 2)) { - file->install = 1; - - installCnt += 1; - uninstallCnt -= 1; - } - selected++; - - if (selected >= fileCnt) - selected = 0; + i++; + } + } + else + { + fatFile *file = &fileList[selected]; + if (((file->isdir) == false) && (file->install == 0)) + { + file->install = 2; + uninstallCnt++; + } + else if (((file->isdir) == false) && (file->install == 1)) + { + file->install = 2; + uninstallCnt++; + installCnt--; + } + else if (((file->isdir) == false) && (file->install == 2)) + { + file->install = 0; + uninstallCnt -= 1; + } + + selected++; + if (selected >= fileCnt) + selected = 0; + } } - } - - /* Minus Button - Leathl */ - if (buttons & WPAD_BUTTON_MINUS) - { - if(Wpad_TimeButton()) - { - installCnt = 0; - int i = 0; - while( i < fileCnt) - { - fatFile *file = &fileList[i]; - if (((file->isdir) == false) & (file->install == 0)) { - file->install = 2; - - uninstallCnt += 1; - } - else if (((file->isdir) == false) & (file->install == 1)) { - file->install = 2; - - uninstallCnt += 1; - installCnt -= 1; - } - else if (((file->isdir) == false) & (file->install == 2)) { - file->install = 0; - - uninstallCnt -= 1; - } - i++; - } - - } - else - { - fatFile *file = &fileList[selected]; - if (((file->isdir) == false) & (file->install == 0)) { - file->install = 2; - - uninstallCnt += 1; - } - else if (((file->isdir) == false) & (file->install == 1)) { - file->install = 2; - - uninstallCnt += 1; - installCnt -= 1; - } - else if (((file->isdir) == false) & (file->install == 2)) { - file->install = 0; - - uninstallCnt -= 1; - } - selected++; - - if (selected >= fileCnt) - selected = 0; - } - } } + /* 1 Button - Leathl */ if (buttons & WPAD_BUTTON_1) { fatFile *tmpFile = &fileList[selected]; - char *tmpCurPath = PeekCurrentDir (); - if (tmpCurPath != NULL) { + char *tmpCurPath = PeekCurrentDir(); + if (tmpCurPath != NULL) + { int res = Menu_FileOperations(tmpFile, tmpCurPath); if (res != 0) goto getList; } } - /* A button */ - if (buttons & WPAD_BUTTON_A) + else if (buttons & WPAD_BUTTON_A) { - fatFile *tmpFile = &fileList[selected]; - char *tmpCurPath; - if (tmpFile->isdir) // wiiNinja + fatFile *tmpFile = &fileList[selected]; + char *tmpCurPath; + if (tmpFile->isdir) // wiiNinja + { + if (strcmp (tmpFile->filename, "..") == 0) { - if (strcmp (tmpFile->filename, "..") == 0) - { - selected = 0; - start = 0; + selected = 0; + start = 0; - // Previous dir - tmpCurPath = PopCurrentDir(&selected, &start); - if (tmpCurPath != NULL) - sprintf(tmpPath, "%s", tmpCurPath); + // Previous dir + tmpCurPath = PopCurrentDir(&selected, &start); + if (tmpCurPath != NULL) + sprintf(tmpPath, "%s", tmpCurPath); - installCnt = 0; - uninstallCnt = 0; + installCnt = 0; + uninstallCnt = 0; - goto getList; - } - else if (IsListFull () == true) - { - WaitPrompt ("Maximum number of directory levels is reached.\n"); - } - else - { - tmpCurPath = PeekCurrentDir (); - if (tmpCurPath != NULL) - { - if(gDirLevel>1) - sprintf(tmpPath, "%s/%s", tmpCurPath, tmpFile->filename); - else - sprintf(tmpPath, "%s%s", tmpCurPath, tmpFile->filename); - } - // wiiNinja: Need to PopCurrentDir - PushCurrentDir (tmpPath, selected, start); - selected = 0; - start = 0; - - installCnt = 0; - uninstallCnt = 0; - - goto getList; - } + goto getList; + } + else if (IsListFull() == true) + { + WaitPrompt ("Maximum number of directory levels is reached.\n"); } else { - //If at least one WAD is marked, goto batch screen - Leathl - if ((installCnt > 0) | (uninstallCnt > 0)) { - char *thisCurPath = PeekCurrentDir (); - if (thisCurPath != NULL) { - int res = Menu_BatchProcessWads(fileList, fileCnt, thisCurPath, installCnt, uninstallCnt); + tmpCurPath = PeekCurrentDir (); + if (tmpCurPath != NULL) + { + if(gDirLevel > 1) + sprintf(tmpPath, "%s/%s", tmpCurPath, tmpFile->filename); + else + sprintf(tmpPath, "%s%s", tmpCurPath, tmpFile->filename); + } + + // wiiNinja: Need to PopCurrentDir + PushCurrentDir (tmpPath, selected, start); + selected = 0; + start = 0; - if (res == 1) { - int counter; - for (counter = 0; counter < fileCnt; counter++) { - fatFile *temp = &fileList[counter]; - temp->install = 0; - } + installCnt = 0; + uninstallCnt = 0; - installCnt = 0; - uninstallCnt = 0; + goto getList; + } + } + else + { + //If at least one WAD is marked, goto batch screen - Leathl + if ((installCnt > 0) || (uninstallCnt > 0)) + { + char *thisCurPath = PeekCurrentDir (); + if (thisCurPath != NULL) + { + int res = Menu_BatchProcessWads(fileList, fileCnt, thisCurPath, installCnt, uninstallCnt); + + if (res == 1) + { + int counter; + for (counter = 0; counter < fileCnt; counter++) + { + fatFile *temp = &fileList[counter]; + temp->install = 0; } + + installCnt = 0; + uninstallCnt = 0; } } - //else use standard wadmanage menu - Leathl - else { - tmpCurPath = PeekCurrentDir (); - if (tmpCurPath != NULL) - Menu_WadManage(tmpFile, tmpCurPath); - } } + //else use standard wadmanage menu - Leathl + else + { + tmpCurPath = PeekCurrentDir (); + if (tmpCurPath != NULL) + Menu_WadManage(tmpFile, tmpCurPath); + } + } } /* B button */ - if (buttons & WPAD_BUTTON_B) + else if (buttons & WPAD_BUTTON_B) { - if(gDirLevel<=1) - { + if (gDirLevel <= 1) return; - } char *tmpCurPath; selected = 0; start = 0; + // Previous dir tmpCurPath = PopCurrentDir(&selected, &start); if (tmpCurPath != NULL) sprintf(tmpPath, "%s", tmpCurPath); + goto getList; - //return; } /** Scrolling **/ @@ -1204,7 +1196,7 @@ getList: if (index >= ENTRIES_PER_PAGE) start += index - (ENTRIES_PER_PAGE - 1); - if (index <= -1) + else if (index < 0) start += index; } @@ -1212,7 +1204,7 @@ err: printf("\n"); printf(" Press any button to continue...\n"); - free (tmpPath); + free(tmpPath); /* Wait for button */ WaitButtons(); @@ -1220,8 +1212,10 @@ err: void Menu_Loop(void) { u8 iosVersion; - if(AHBPROT_DISABLED) + if (AHBPROT_DISABLED) + { IOSPATCH_Apply(); + } else { /* Select IOS menu */ @@ -1230,6 +1224,7 @@ void Menu_Loop(void) /* Retrieve IOS version */ iosVersion = IOS_GetVersion(); + GetSysMenuRegion(&gMenuVersion, &gMenuRegion); ndev = &ndevList[0]; diff --git a/source/nand.c b/source/nand.c index a5c99be..a7447dc 100644 --- a/source/nand.c +++ b/source/nand.c @@ -1,10 +1,58 @@ #include +#include #include +#include +#include #include "nand.h" +#include "fileops.h" + +#define BLOCK 2048 /* Buffer */ static u32 inbuf[8] ATTRIBUTE_ALIGN(32); +static bool gNandInitialized = false; + +#if 0 +static void NANDFATify(char* ptr, const char* str) +{ + char ctr; + while ((ctr = *(str++)) != '\0') + { + const char* esc; + switch (ctr) + { + case '"': + esc = "&qt;"; + break; + case '*': + esc = "&st;"; + break; + case ':': + esc = "&cl;"; + break; + case '<': + esc = "<"; + break; + case '>': + esc = ">"; + break; + case '?': + esc = "&qm;"; + break; + case '|': + esc = "&vb;"; + break; + default: + *(ptr++) = ctr; + continue; + } + strcpy(ptr, esc); + ptr += 4; + } + *ptr = '\0'; +} +#endif s32 Nand_Mount(nandDevice *dev) @@ -83,4 +131,337 @@ s32 Nand_Disable(void) IOS_Close(fd); return ret; -} +} + +bool NANDInitialize() +{ + if(!gNandInitialized) + { + if (ISFS_Initialize() == ISFS_OK) + gNandInitialized = true; + } + + return gNandInitialized; +} + +u8* NANDReadFromFile(const char* path, u32 offset, u32 length, u32* size) +{ + *size = ISFS_EINVAL; + + if (NANDInitialize()) + { + s32 fd = IOS_Open(path, 1); + + if (fd < 0) + { + *size = fd; + return NULL; + } + + if (!length) + length = IOS_Seek(fd, 0, SEEK_END); + + u8* data = (u8*)memalign(0x40, length); + if (!data) + { + *size = 0; + IOS_Close(fd); + return NULL; + } + + *size = IOS_Seek(fd, offset, SEEK_SET); + if (*size < 0) + { + IOS_Close(fd); + free(data); + return NULL; + } + + *size = IOS_Read(fd, data, length); + IOS_Close(fd); + if (*size != length) + { + free(data); + return NULL; + } + + return data; + } + + return NULL; +} + +u8* NANDLoadFile(const char* path, u32* size) +{ + return NANDReadFromFile(path, 0, 0, size); +} + +s32 NANDWriteFileSafe(const char* path, u8* data, u32 size) +{ + NANDInitialize(); + + char* tmpPath = (char*)memalign(0x40, ISFS_MAXPATH); + u32 i; + + for (i = strlen(path); i > 0; --i) + { + if (path[i] == '/') + break; + } + + sprintf(tmpPath, "/tmp%s", path + i); + + s32 ret = ISFS_CreateFile(tmpPath, 0, 3, 3, 3); + if (ret == -105) + { + ISFS_Delete(tmpPath); + ret = ISFS_CreateFile(tmpPath, 0, 3, 3, 3); + + if (ret < 0) + { + free(tmpPath); + return ret; + } + } + else + { + if (ret < 0) + { + free(tmpPath); + return ret; + } + } + + s32 fd = IOS_Open(tmpPath, 2); + if (fd < 0) + { + free(tmpPath); + return fd; + } + + ret = IOS_Write(fd, data, size); + + + IOS_Close(fd); + if (ret != size) + { + free(tmpPath); + return ret - 3; + } + + if (strcmp(tmpPath, path)) + ret = ISFS_Rename(tmpPath, path); + else + ret = 0; + + free(tmpPath); + return ret; +} + +s32 NANDBackUpFile(const char* src, const char* dst, u32* size) +{ + NANDInitialize(); + u8* buffer = NANDLoadFile(src, size); + if (!buffer) + return *size; + + s32 ret = NANDWriteFileSafe(dst, buffer, *size); + + free(buffer); + return ret; +} + +s32 NANDGetFileSize(const char* path, u32* size) +{ + NANDInitialize(); + s32 fd = IOS_Open(path, 1); + + if (fd < 0) + { + *size = 0; + return fd; + } + + *size = IOS_Seek(fd, 0, SEEK_END); + return IOS_Close(fd); +} + +s32 NANDDeleteFile(const char* path) +{ + NANDInitialize(); + return ISFS_Delete(path); +} + +#if 0 +s32 NANDGetNameList(const char* src, NameList** entries, s32* count) +{ + *count = 0; + u32 numEntries = 0; + char currentEntry[ISFS_MAXPATH]; + char entryPath[ISFS_MAXPATH + 1]; + + s32 ret = ISFS_ReadDir(src, NULL, &numEntries); + + if (ret < 0) + return ret; + + char* names = (char*)memalign(0x40, ISFS_MAXPATH * numEntries); + + if (!names) + return ISFS_ENOMEM; + + ret = ISFS_ReadDir(src, names, &numEntries); + if (ret < 0) + { + free(names); + return ret; + } + + *count = numEntries; + + free(*entries); + *entries = (NameList*)memalign(0x20, sizeof(NameList) * numEntries); + if (!*entries) + { + free(names); + return ISFS_ENOMEM; + } + + s32 i, j, k; + u32 dummy; + for (i = 0, k = 0; i < numEntries; i++) + { + for (j = 0; names[k] != 0; j++, k++) + currentEntry[j] = names[k]; + + currentEntry[j] = 0; + k++; + + strcpy((*entries)[i].name, currentEntry); + + if (src[strlen(src) - 1] == '/') + snprintf(entryPath, sizeof(entryPath), "%s%s", src, currentEntry); + else + snprintf(entryPath, sizeof(entryPath), "%s/%s", src, currentEntry); + + ret = ISFS_ReadDir(entryPath, NULL, &dummy); + (*entries)[i].type = ret < 0 ? 0 : 1; + } + + free(names); + return 0; +} + +s32 NANDDumpFile(const char* src, const char* dst) +{ + s32 fd = ISFS_Open(src, ISFS_OPEN_READ); + if (fd < 0) + return fd; + + fstats* status = (fstats*)memalign(32, sizeof(fstats)); + if (status == NULL) + return ISFS_ENOMEM; + + s32 ret = ISFS_GetFileStats(fd, status); + if (ret < 0) + { + ISFS_Close(fd); + free(status); + return ret; + } + + FSOPDeleteFile(dst); + + FILE* file = fopen(dst, "wb"); + + if (!file) + { + ISFS_Close(fd); + free(status); + return ISFS_EINVAL; + } + + u8* buffer = (u8*)memalign(32, BLOCK); + if (!buffer) + { + ISFS_Close(fd); + free(status); + return ISFS_ENOMEM; + } + + u32 toRead = status->file_length; + while (toRead > 0) + { + u32 size = toRead < BLOCK ? toRead : BLOCK; + + ret = ISFS_Read(fd, buffer, size); + if (ret < 0) + { + ISFS_Close(fd); + fclose(file); + free(status); + free(buffer); + return ret; + } + + ret = fwrite(buffer, 1, size, file); + if (ret < 0) + { + ISFS_Close(fd); + fclose(file); + free(status); + free(buffer); + return ret; + } + + toRead -= size; + } + + fclose(file); + ISFS_Close(fd); + free(status); + free(buffer); + + return ISFS_OK; +} + +s32 NANDDumpFolder(const char* src, const char* dst) +{ + NameList* names = NULL; + s32 count = 0; + s32 i; + + char nSrc[ISFS_MAXPATH + 1]; + char nDst[1024]; + char tDst[1024]; + + NANDGetNameList(src, &names, &count); + FSOPMakeFolder(dst); + + for (i = 0; i < count; i++) + { + + if (src[strlen(src) - 1] == '/') + snprintf(nSrc, sizeof(nSrc), "%s%s", src, names[i].name); + else + snprintf(nSrc, sizeof(nSrc), "%s/%s", src, names[i].name); + + if (!names[i].type) + { + NANDFATify(tDst, nSrc); + snprintf(nDst, sizeof(nDst), "%s%s", dst, tDst); + NANDDumpFile(nSrc, nDst); + } + else + { + NANDFATify(tDst, nSrc); + snprintf(nDst, sizeof(nDst), "%s%s", dst, tDst); + FSOPMakeFolder(nDst); + NANDDumpFolder(nSrc, dst); + } + } + + free(names); + return 0; +} +#endif diff --git a/source/nand.h b/source/nand.h index 0b769d8..fb9af97 100644 --- a/source/nand.h +++ b/source/nand.h @@ -12,7 +12,13 @@ typedef struct { /* Un/mount command */ u32 mountCmd; u32 umountCmd; -} nandDevice; +} nandDevice; + +typedef struct +{ + char name[ISFS_MAXPATH]; + int type; +} NameList; /* Prototypes */ @@ -20,5 +26,18 @@ s32 Nand_Mount(nandDevice *); s32 Nand_Unmount(nandDevice *); s32 Nand_Enable(nandDevice *); s32 Nand_Disable(void); +bool NANDInitialize(); +u8* NANDReadFromFile(const char* path, u32 offset, u32 length, u32* size); +u8* NANDLoadFile(const char* path, u32* size); +s32 NANDWriteFileSafe(const char* path, u8* data, u32 size); +s32 NANDBackUpFile(const char* src, const char* dst, u32* size); +s32 NANDGetFileSize(const char* path, u32* size); +s32 NANDDeleteFile(const char* path); + +#if 0 +s32 NANDGetNameList(const char* src, NameList** entries, s32* count); +s32 NANDDumpFile(const char* src, const char* dst); +s32 NANDDumpFolder(const char* src, const char* dst); +#endif #endif diff --git a/source/sha1.c b/source/sha1.c index 7ce9e6d..41ebaa6 100644 --- a/source/sha1.c +++ b/source/sha1.c @@ -175,3 +175,17 @@ void SHA1(unsigned char *ptr, unsigned int size, unsigned char *outbuf) { SHA1Update(&ctx, ptr, size); SHA1Final(outbuf, &ctx); } + +int CompareHash(unsigned char* first, unsigned int firstSize, unsigned char* second, unsigned int secondSize) +{ + unsigned int HashA[5] = { 0, 0, 0, 0, 0, }; + unsigned int HashB[5] = { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, }; + + SHA1(first, firstSize, (unsigned char*)HashA); + SHA1(second, secondSize, (unsigned char*)HashB); + + //printf("Hash 1: %.8X, %.8X, %.8X, %.8X, %.8X", HashA[0], HashA[1], HashA[2], HashA[3], HashA[4]); + //printf("Hash 2: %.8X, %.8X, %.8X, %.8X, %.8X", HashB[0], HashB[1], HashB[2], HashB[3], HashB[4]); + + return memcmp(HashA, HashB, sizeof(HashA)); +} diff --git a/source/sha1.h b/source/sha1.h index 35b3388..333571c 100644 --- a/source/sha1.h +++ b/source/sha1.h @@ -2,5 +2,6 @@ #define _SHA1_H_ void SHA1(unsigned char *, unsigned int, unsigned char *); +int CompareHash(unsigned char* first, unsigned int firstSize, unsigned char* second, unsigned int secondSize); #endif diff --git a/source/wad-manager.c b/source/wad-manager.c index 2ab749f..be5ef1b 100644 --- a/source/wad-manager.c +++ b/source/wad-manager.c @@ -166,6 +166,8 @@ int main(int argc, char **argv) /* Set video mode */ Video_SetMode(); + FatMount(); + /* Initialize console */ Gui_InitConsole(); @@ -193,6 +195,8 @@ int main(int argc, char **argv) /* Menu loop */ Menu_Loop(); + FatUnmount(); + /* Restart Wii */ Restart_Wait(); @@ -200,30 +204,27 @@ int main(int argc, char **argv) } -int ReadConfigFile (char *configFilePath) +int ReadConfigFile(char* configFilePath) { - int retval = 0; - FILE *fptr; - char *tmpStr = malloc (MAX_FILE_PATH_LEN); - char tmpOutStr [40], path[128]; - int i; + int retval = 0; + FILE* fptr; + char* tmpStr = malloc(MAX_FILE_PATH_LEN); + char tmpOutStr[40], path[128]; + s32 i; + s32 ret = -1; + bool found = false; if (tmpStr == NULL) return (-1); - fatDevice *fdev = &fdevList[0]; - int ret = Fat_Mount(fdev); - snprintf(path, sizeof(path), "%s%s", fdev->mount, configFilePath); - - if (ret < 0) + // Just check if at least one device is available + for (i = 0; i < FatGetDeviceCount(); i++) { - fdev = &fdevList[2]; - ret = Fat_Mount(fdev); - snprintf(path, sizeof(path), "%s%s", fdev->mount, configFilePath); - //snprintf(path, sizeof(path), "%s%s", fdev->mount, configFilePath); + snprintf(path, sizeof(path), "%s%s", FatGetDevicePrefix(i), configFilePath); + found = true; } - if (ret < 0) + if (!found) { printf(" ERROR! (ret = %d)\n", ret); // goto err; @@ -281,7 +282,8 @@ int ReadConfigFile (char *configFilePath) GetStringParam (tmpOutStr, tmpStr, MAX_FAT_DEVICE_LENGTH); for (i = 0; i < 5; i++) { - if (strncmp (fdevList[i].mount, tmpOutStr, 4) == 0) + //if (strncmp (fdevList[i].mount, tmpOutStr, 4) == 0) + if (strncmp(FatGetDevicePrefix(i), tmpOutStr, 4) == 0) { gConfig.fatDeviceIndex = i; } @@ -313,11 +315,11 @@ int ReadConfigFile (char *configFilePath) //printf ("Config file is not found\n"); // This is for testing only //WaitButtons(); } - Fat_Unmount(fdev); + //Fat_Unmount(fdev); } // Free memory - free (tmpStr); + free(tmpStr); return (retval); } // ReadConfig diff --git a/source/wad.c b/source/wad.c index ddd186b..942f55e 100644 --- a/source/wad.c +++ b/source/wad.c @@ -3,6 +3,7 @@ #include #include #include +#include #include "sys.h" #include "title.h" @@ -10,6 +11,9 @@ #include "video.h" #include "wad.h" #include "wpad.h" +#include "nand.h" +#include "fileops.h" +#include "sha1.h" // Turn upper and lower into a full title ID #define TITLE_ID(x,y) (((u64)(x) << 32) | (y)) @@ -18,32 +22,34 @@ // Turn upper and lower into a full title ID #define TITLE_LOWER(x) ((u32)(x)) -typedef struct { - int version; - int region; - -} SMRegion; - -SMRegion regionlist[] = { - {33, 'X'}, - {128, 'J'}, {97, 'E'}, {130, 'P'}, - {162, 'P'}, - {192, 'J'}, {193, 'E'}, {194, 'P'}, - {224, 'J'}, {225, 'E'}, {226, 'P'}, - {256, 'J'}, {257, 'E'}, {258, 'P'}, - {288, 'J'}, {289, 'E'}, {290, 'P'}, - {352, 'J'}, {353, 'E'}, {354, 'P'}, {326, 'K'}, - {384, 'J'}, {385, 'E'}, {386, 'P'}, - {390, 'K'}, - {416, 'J'}, {417, 'E'}, {418, 'P'}, - {448, 'J'}, {449, 'E'}, {450, 'P'}, {454, 'K'}, - {480, 'J'}, {481, 'E'}, {482, 'P'}, {486, 'K'}, - {512, 'E'}, {513, 'E'}, {514, 'P'}, {518, 'K'}, +const char RegionLookupList[16] = +{ + 'J', 'E', 'P', 0, 0, 0, 'K', 0, 0, 0, 0, 0, 0, 0, 0, 0, }; -#define NB_SM (sizeof(regionlist) / sizeof(SMRegion)) +const u16 versionList[] = +{ +// J E P K + + 64, 33, 66, // 1.0 + 128, 97, 130, // 2.0 + 162, // 2.1 + 192, 193, 194, // 2.2 + 224, 225, 226, // 3.0 + 256, 257, 258, // 3.1 + 288, 289, 290, // 3.2 + 352, 353, 354, 326, // 3.3 + 384, 385, 386, // 3.4 + 390, // 3.5 + 416, 417, 418, // 4.0 + 448, 449, 450, 454, // 4.1 + 480, 481, 482, 486, // 4.2 + 512, 513, 514, 518, // 4.3 +}; u32 WaitButtons(void); +static u32 gPriiloaderSize = 0; +static bool gForcedInstall = false; u32 be32(const u8 *p) { @@ -125,33 +131,280 @@ u64 get_title_ios(u64 title) { return 0; } -int get_sm_region_basic() +s32 GetSysMenuRegion(u16* version, char* region) { - u32 tmd_size; - - u64 title = TITLE_ID(1, 2); - static u8 tmd_buf[MAX_SIGNED_TMD_SIZE] ATTRIBUTE_ALIGN(32); - - int ret = ES_GetStoredTMDSize(title, &tmd_size); - - // Some of this code adapted from bushing's title_lister.c - signed_blob *s_tmd = (signed_blob *)tmd_buf; - ret = ES_GetStoredTMD(title, s_tmd, tmd_size); - if (ret < 0){ - //printf("Error! ES_GetStoredTMD: %d\n", ret); - return -1; - } - tmd *t = SIGNATURE_PAYLOAD(s_tmd); - ret = t->title_version; - int i = 0; - while( i <= NB_SM) - { - if( regionlist[i].version == ret) return regionlist[i].region; - i++; - } + u16 v = 0; + s32 ret = Title_GetVersion(0x100000002LL, &v); + + if (ret < 0) + return ret; + + if (version) + *version = v; + + if (region) + *region = RegionLookupList[(v & 0x0F)]; + return 0; } +const char* GetSysMenuRegionString(const char* region) +{ + switch (*region) + { + case 'J': return "Japan (NTSC-J)"; + case 'E': return "USA (NTSC-U/C)"; + case 'P': return "Europe (PAL)"; + case 'K': return "Korea (NTSC-K)"; + } + + return "Unknown"; +} + +static char* GetTitleExec(u64 tId, bool tweaked) +{ + u32 size; + const u8 buffer[MAX_SIGNED_TMD_SIZE] ATTRIBUTE_ALIGN(32); + + s32 ret = ES_GetStoredTMDSize(0x100000002, &size); + signed_blob* tmdRaw = (signed_blob*)buffer; + + ret = ES_GetStoredTMD(0x100000002, tmdRaw, size); + if (ret < 0) + { + printf("Error! ES_GetStoredTMDSize: Failed! (Error: %d)\n", ret); + return NULL; + } + + tmd* smTMD = SIGNATURE_PAYLOAD(tmdRaw); + + char* path = (char*)memalign(0x40, ISFS_MAXPATH); + if (!path) + return NULL; + + if(tweaked) + sprintf(path, "/title/%08x/%08x/content/1%.7x.app", TITLE_UPPER(tId), TITLE_LOWER(tId), smTMD->contents[smTMD->boot_index].cid); + else + sprintf(path, "/title/%08x/%08x/content/%.8x.app", TITLE_UPPER(tId), TITLE_LOWER(tId), smTMD->contents[smTMD->boot_index].cid); + + return path; +} + +static inline bool IsPriiloaderInstalled() +{ + char* path = GetTitleExec(0x100000002LL, true); + if (!path) + return false; + + + u32 size = 0; + NANDGetFileSize(path, &size); + free(path); + + if (size > 0) + return true; + else + return false; +} + +static bool BackUpPriiloader() +{ + char* path = GetTitleExec(0x100000002LL, false); + if (!path) + return false; + + u32 size = 0; + s32 ret = NANDBackUpFile(path, "/tmp/priiload.app", &size); + free(path); + + if (ret < 0) + { + printf("Error! NANDBackUpFile: Failed! (Error: %d)\n", ret); + return false; + } + + ret = NANDGetFileSize("/tmp/priiload.app", &gPriiloaderSize); + + return (gPriiloaderSize == size); +} + +static bool MoveMenu(bool restore) +{ + char* srcPath = GetTitleExec(0x100000002LL, restore); + if (!srcPath) + return false; + + char* dstPath = GetTitleExec(0x100000002LL, !restore); + if (!dstPath) + { + free(srcPath); + return false; + } + + u32 size = 0; + s32 ret = NANDBackUpFile(srcPath, dstPath, &size); + if (ret < 0) + { + free(srcPath); + free(dstPath); + printf("Error! NANDBackUpFile: Failed! (Error: %d)\n", ret); + return false; + } + + u32 checkSize = 0; + ret = NANDGetFileSize(dstPath, &checkSize); + + free(srcPath); + free(dstPath); + + return (checkSize == size); +} + +static bool RestorePriiloader() +{ + char* dstPath = GetTitleExec(0x100000002LL, false); + if (!dstPath) + return false; + + u32 size = 0; + s32 ret = NANDBackUpFile("/tmp/priiload.app", dstPath, &size); + if (ret < 0) + { + free(dstPath); + printf("Error! NANDBackUpFile: Failed! (Error: %d)\n", ret); + return false; + } + + u32 checkSize = 0; + ret = NANDGetFileSize(dstPath, &checkSize); + + free(dstPath); + + return (checkSize == size && checkSize == gPriiloaderSize); +} + +static void PrintCleanupResult(s32 result) +{ + + if (result < 0) + { + switch (result) + { + case -102: + { + printf(" Acces denied.\n"); + } break; + case -106: + { + printf(" Not found.\n"); + } break; + default: + { + printf(" Error: %d\n", result); + } break; + } + } + else + { + printf(" OK!\n"); + } + + sleep(1); +} + +static void CleanupPriiloaderLeftOvers(bool retain) +{ + if (!retain) + { + printf("\n\t\tCleanup Priiloader leftover files...\n"); + printf("\r\t\t>> Password file..."); + PrintCleanupResult(NANDDeleteFile("/title/00000001/00000002/data/password.txt")); + printf("\r\t\t>> Settings file..."); + PrintCleanupResult(NANDDeleteFile("/title/00000001/00000002/data/loader.ini")); + printf("\r\t\t>> Ticket..."); + PrintCleanupResult(NANDDeleteFile("/title/00000001/00000002/data/ticket")); + printf("\r\t\t>> File: main.nfo..."); + PrintCleanupResult(NANDDeleteFile("/title/00000001/00000002/data/main.nfo")); + printf("\r\t\t>> File: main.bin..."); + PrintCleanupResult(NANDDeleteFile("/title/00000001/00000002/data/main.bin")); + } + + printf("\n\t\tRemoving Priiloader hacks...\n"); + + printf("\r\t\t>> File: hacks_s.ini..."); + PrintCleanupResult(NANDDeleteFile("/title/00000001/00000002/data/hacks_s.ini")); + printf("\r\t\t>> File: hacks.ini..."); + PrintCleanupResult(NANDDeleteFile("/title/00000001/00000002/data/hacks.ini")); + printf("\r\t\t>> File: hacksh_s.ini..."); + PrintCleanupResult(NANDDeleteFile("/title/00000001/00000002/data/hacksh_s.ini")); + printf("\r\t\t>> File: hackshas.ini..."); + PrintCleanupResult(NANDDeleteFile("/title/00000001/00000002/data/hackshas.ini")); + + if (retain) + { + printf("\n\t\tPriiloader hacks will be reset!\n"); + printf("\t\tRemember to set them again.\n"); + } +} + +static bool CompareHashes(bool priiloader) +{ + char* dstPath = NULL; + char* srcPath = GetTitleExec(0x100000002LL, false); + + if (!srcPath) + return false; + + if (priiloader) + { + dstPath = (char*)memalign(0x40, ISFS_MAXPATH); + if (!dstPath) + { + free(srcPath); + return false; + } + + strcpy(dstPath, "/tmp/priiload.app"); + } + else + { + dstPath = GetTitleExec(0x100000002LL, true); + if (!dstPath) + { + free(srcPath); + return false; + } + } + + u32 sizeA = 0; + u32 sizeB = 0; + u8* dataA = NANDLoadFile(srcPath, &sizeA); + if (!dataA) + { + free(srcPath); + free(dstPath); + return false; + } + + u8* dataB = NANDLoadFile(dstPath, &sizeB); + if (!dataA) + { + free(srcPath); + free(dstPath); + free(dataA); + return false; + } + + bool ret = !CompareHash(dataA, sizeA, dataB, sizeB); + + free(srcPath); + free(dstPath); + free(dataA); + free(dataB); + + return ret; +} + /* 'WAD Header' structure */ typedef struct { /* Header length */ @@ -174,45 +427,6 @@ typedef struct { /* Variables */ static u8 wadBuffer[BLOCK_SIZE] ATTRIBUTE_ALIGN(32); - -s32 __Wad_ReadFile(FILE *fp, void *outbuf, u32 offset, u32 len) -{ - s32 ret; - - /* Seek to offset */ - fseek(fp, offset, SEEK_SET); - - /* Read data */ - ret = fread(outbuf, len, 1, fp); - if (ret < 0) - return ret; - - return 0; -} - -s32 __Wad_ReadAlloc(FILE *fp, void **outbuf, u32 offset, u32 len) -{ - void *buffer = NULL; - s32 ret; - - /* Allocate memory */ - buffer = memalign(32, len); - if (!buffer) - return -1; - - /* Read file */ - ret = __Wad_ReadFile(fp, buffer, offset, len); - if (ret < 0) { - free(buffer); - return ret; - } - - /* Set pointer */ - *outbuf = buffer; - - return 0; -} - s32 __Wad_GetTitleID(FILE *fp, wadHeader *header, u64 *tid) { signed_blob *p_tik = NULL; @@ -227,8 +441,8 @@ s32 __Wad_GetTitleID(FILE *fp, wadHeader *header, u64 *tid) offset += round_up(header->crl_len, 64); /* Read ticket */ - ret = __Wad_ReadAlloc(fp, (void *)&p_tik, offset, header->tik_len); - if (ret < 0) + ret = FSOPReadOpenFileA(fp, (void*)&p_tik, offset, header->tik_len); + if (ret != 1) goto out; /* Ticket data */ @@ -273,15 +487,17 @@ s32 Wad_Install(FILE *fp) u32 cnt, offset = 0; int ret; u64 tid; + bool retainPriiloader = false; + bool cleanupPriiloader = false; printf("\t\t>> Reading WAD data..."); fflush(stdout); - ret = __Wad_ReadAlloc(fp, (void *)&header, offset, sizeof(wadHeader)); - if (ret >= 0) - offset += round_up(header->header_len, 64); + ret = FSOPReadOpenFileA(fp, (void*)&header, offset, sizeof(wadHeader)); + if (ret != 1) + goto err; else - goto err; + offset += round_up(header->header_len, 64); //Don't try to install boot2 __Wad_GetTitleID(fp, header, &tid); @@ -294,31 +510,31 @@ s32 Wad_Install(FILE *fp) } /* WAD certificates */ - ret = __Wad_ReadAlloc(fp, (void *)&p_certs, offset, header->certs_len); - if (ret >= 0) - offset += round_up(header->certs_len, 64); + ret = FSOPReadOpenFileA(fp, (void*)&p_certs, offset, header->certs_len); + if (ret != 1) + goto err; else - goto err; - + offset += round_up(header->certs_len, 64); + /* WAD crl */ if (header->crl_len) { - ret = __Wad_ReadAlloc(fp, (void *)&p_crl, offset, header->crl_len); - if (ret < 0) + ret = FSOPReadOpenFileA(fp, (void*)&p_crl, offset, header->crl_len); + if (ret != 1) goto err; else offset += round_up(header->crl_len, 64); } /* WAD ticket */ - ret = __Wad_ReadAlloc(fp, (void *)&p_tik, offset, header->tik_len); - if (ret < 0) + ret = FSOPReadOpenFileA(fp, (void*)&p_tik, offset, header->tik_len); + if (ret != 1) goto err; else offset += round_up(header->tik_len, 64); /* WAD TMD */ - ret = __Wad_ReadAlloc(fp, (void *)&p_tmd, offset, header->tmd_len); - if (ret < 0) + ret = FSOPReadOpenFileA(fp, (void*)&p_tmd, offset, header->tmd_len); + if (ret != 1) goto err; else offset += round_up(header->tmd_len, 64); @@ -338,7 +554,7 @@ s32 Wad_Install(FILE *fp) if(get_title_ios(TITLE_ID(1, 2)) == tid) { - if ( ( tmd_data->num_contents == 3) && (tmd_data->contents[0].type == 1 && tmd_data->contents[1].type == 0x8001 && tmd_data->contents[2].type == 0x8001) ) + if (( tmd_data->num_contents == 3) && (tmd_data->contents[0].type == 1 && tmd_data->contents[1].type == 0x8001 && tmd_data->contents[2].type == 0x8001)) { printf("\n I won't install a stub System Menu IOS\n"); ret = -999; @@ -348,7 +564,7 @@ s32 Wad_Install(FILE *fp) if(tid == get_title_ios(TITLE_ID(0x10008, 0x48414B00 | 'E')) || tid == get_title_ios(TITLE_ID(0x10008, 0x48414B00 | 'P')) || tid == get_title_ios(TITLE_ID(0x10008, 0x48414B00 | 'J')) || tid == get_title_ios(TITLE_ID(0x10008, 0x48414B00 | 'K'))) { - if ( ( tmd_data->num_contents == 3) && (tmd_data->contents[0].type == 1 && tmd_data->contents[1].type == 0x8001 && tmd_data->contents[2].type == 0x8001) ) + if ((tmd_data->num_contents == 3) && (tmd_data->contents[0].type == 1 && tmd_data->contents[1].type == 0x8001 && tmd_data->contents[2].type == 0x8001)) { printf("\n I won't install a stub EULA IOS\n"); ret = -999; @@ -358,7 +574,7 @@ s32 Wad_Install(FILE *fp) if(tid == get_title_ios(TITLE_ID(0x10008, 0x48414C00 | 'E')) || tid == get_title_ios(TITLE_ID(0x10008, 0x48414C00 | 'P')) || tid == get_title_ios(TITLE_ID(0x10008, 0x48414C00 | 'J')) || tid == get_title_ios(TITLE_ID(0x10008, 0x48414C00 | 'K'))) { - if ( ( tmd_data->num_contents == 3) && (tmd_data->contents[0].type == 1 && tmd_data->contents[1].type == 0x8001 && tmd_data->contents[2].type == 0x8001) ) + if ((tmd_data->num_contents == 3) && (tmd_data->contents[0].type == 1 && tmd_data->contents[1].type == 0x8001 && tmd_data->contents[2].type == 0x8001)) { printf("\n I won't install a stub rgsel IOS\n"); ret = -999; @@ -385,30 +601,36 @@ s32 Wad_Install(FILE *fp) if (tid == TITLE_ID(1, 2)) { - if (skipRegionSafetyCheck) goto skipChecks; + char region = 0; + u16 version = 0; - if(get_sm_region_basic() == 0) + if (skipRegionSafetyCheck || gForcedInstall) + goto skipChecks; + + GetSysMenuRegion(&version, ®ion); + if(region == 0) { - printf("\n Can't get the SM region\n Please check the site for updates\n"); + printf("\n Unkown SM region\n Please check the site for updates\n"); ret = -999; goto err; } + int i, ret = -1; - for(i = 0; i <= NB_SM; i++) + for(i = 0; i < sizeof(versionList); i++) { - if( regionlist[i].version == tmd_data->title_version) + if(versionList[i] == tmd_data->title_version) { ret = 1; break; } } - if(ret -1) + if(ret != 1) { - printf("\n Can't get the SM region\n Please check the site for updates\n"); + printf("\n Unknown SM region\n Please check the site for updates\n"); ret = -999; goto err; } - if(get_sm_region_basic() != regionlist[i].region) + if(region != RegionLookupList[(tmd_data->title_version & 0x0F)]) { printf("\n I won't install the wrong regions SM\n"); ret = -999; @@ -424,8 +646,57 @@ skipChecks: goto err; } } + + if (!gForcedInstall && IsPriiloaderInstalled()) + { + cleanupPriiloader = true; + printf("\n Priiloader is installed next to the system menu.\n\n"); + printf(" Press A to retain Priiloader or B to remove."); + + u32 buttons = WaitButtons(); + + if ((buttons & WPAD_BUTTON_A)) + { + retainPriiloader = (BackUpPriiloader() && CompareHashes(true)); + if (retainPriiloader) + { + Con_ClearLine(); + printf("\r[+] Priiloader will be retained.\n"); + fflush(stdout); + } + else + { + Con_ClearLine(); + printf("\r Couldn't backup Priiloader.\n"); + fflush(stdout); + + printf("\n Press A to continue or B to skip"); + + u32 buttons = WaitButtons(); + + if (!(buttons & WPAD_BUTTON_A)) + { + ret = -990; + goto err; + } + } + } + + if (!retainPriiloader) + { + Con_ClearLine(); + printf("\r[+] Priiloader will be removed.\n"); + fflush(stdout); + } + } } + if (gForcedInstall) + { + gForcedInstall = false; + cleanupPriiloader = true; + } + /* Fix ticket */ __Wad_FixTicket(p_tik); @@ -479,8 +750,8 @@ skipChecks: size = BLOCK_SIZE; /* Read data */ - ret = __Wad_ReadFile(fp, &wadBuffer, offset, size); - if (ret < 0) + ret = FSOPReadOpenFile(fp, &wadBuffer, offset, size); + if (ret != 1) goto err; /* Install data */ @@ -506,13 +777,106 @@ skipChecks: /* Finish title install */ ret = ES_AddTitleFinish(); - if (ret >= 0) { + if (ret >= 0) + { printf(" OK!\n"); + + if (retainPriiloader) + { + printf("\r\t\t>> Moving System Menu..."); + if (MoveMenu(false)) + { + printf(" OK!\n"); + + printf("\r\t\t>> Check System Menu executable hashes..."); + + s32 restoreMenu = 0; + + if (CompareHashes(false)) + { + printf(" OK!\n"); + } + else + { + printf(" Failed!\n"); + restoreMenu = 1; + } + + printf("\r\t\t>> Restore Priiloader..."); + if (!restoreMenu && RestorePriiloader()) + { + printf(" OK!\n"); + printf("\r\t\t>> Check Priiloader executable hashes..."); + if (CompareHashes(true)) + { + printf(" OK!\n"); + } + else + { + printf(" Failed!\n"); + restoreMenu = 2; + } + } + else + { + printf(" Failed!\n"); + restoreMenu = 2; + } + + if (restoreMenu) + { + printf("\r\t\t>> Restore System Menu..."); + bool restored = true; + switch (restoreMenu) + { + case 2: + { + restored = (MoveMenu(true) && CompareHashes(false)); + } + case 1: + { + if (restored) + { + char* path = GetTitleExec(0x100000002LL, true); + NANDDeleteFile(path); + free(path); + } + } + } + + if (restored) + { + printf(" OK!\n"); + } + else + { + printf(" Failed!\n"); + printf("\n\t\t>> Reinstalling System Menu...\n\n"); + sleep(3); + printf("\t\t>> Priiloader will be removed!\n\n"); + + gForcedInstall = true; + cleanupPriiloader = false; + } + } + } + else + { + printf(" Failed!\n"); + printf("\n\t\t>> Priiloader will be removed!\n\n"); + } + } + + if (cleanupPriiloader) + { + CleanupPriiloaderLeftOvers(retainPriiloader); + } + goto out; } err: - printf(" ERROR! (ret = %d)\n", ret); + printf("\n ERROR! (ret = %d)\n", ret); /* Cancel install */ ES_AddTitleCancel(); @@ -525,6 +889,9 @@ out: free(p_tik); free(p_tmd); + if (gForcedInstall) + return Wad_Install(fp); + return ret; } @@ -541,8 +908,9 @@ s32 Wad_Uninstall(FILE *fp) fflush(stdout); /* WAD header */ - ret = __Wad_ReadAlloc(fp, (void *)&header, 0, sizeof(wadHeader)); - if (ret < 0) { + ret = FSOPReadOpenFileA(fp, (void*)&header, 0, sizeof(wadHeader)); + if (ret != 1) + { printf(" ERROR! (ret = %d)\n", ret); goto out; } @@ -592,32 +960,36 @@ s32 Wad_Uninstall(FILE *fp) goto out; } } + + char region = 0; + GetSysMenuRegion(NULL, ®ion); + if((tid == TITLE_ID(0x10008, 0x48414B00 | 'E') || tid == TITLE_ID(0x10008, 0x48414B00 | 'P') || tid == TITLE_ID(0x10008, 0x48414B00 | 'J') || tid == TITLE_ID(0x10008, 0x48414B00 | 'K') - || (tid == TITLE_ID(0x10008, 0x48414C00 | 'E') || tid == TITLE_ID(0x10008, 0x48414C00 | 'P') || tid == TITLE_ID(0x10008, 0x48414C00 | 'J') || tid == TITLE_ID(0x10008, 0x48414C00 | 'K'))) && get_sm_region_basic() == 0) + || (tid == TITLE_ID(0x10008, 0x48414C00 | 'E') || tid == TITLE_ID(0x10008, 0x48414C00 | 'P') || tid == TITLE_ID(0x10008, 0x48414C00 | 'J') || tid == TITLE_ID(0x10008, 0x48414C00 | 'K'))) && region == 0) { - printf("\n Can't get the SM region\n Please check the site for updates\n"); + printf("\n Unkown SM region\n Please check the site for updates\n"); ret = -999; goto out; } - if(tid == TITLE_ID(0x10008, 0x48414B00 | get_sm_region_basic())) + if(tid == TITLE_ID(0x10008, 0x48414B00 | region)) { printf("\n I won't uninstall the EULA\n"); ret = -999; goto out; } - if(tid == TITLE_ID(0x10008, 0x48414C00 | get_sm_region_basic())) + if(tid == TITLE_ID(0x10008, 0x48414C00 | region)) { printf("\n I won't uninstall rgsel\n"); ret = -999; goto out; } - if(tid == get_title_ios(TITLE_ID(0x10008, 0x48414B00 | get_sm_region_basic()))) + if(tid == get_title_ios(TITLE_ID(0x10008, 0x48414B00 | region))) { printf("\n I won't uninstall the EULAs IOS\n"); ret = -999; goto out; } - if(tid == get_title_ios(TITLE_ID(0x10008, 0x48414C00 | get_sm_region_basic()))) + if(tid == get_title_ios(TITLE_ID(0x10008, 0x48414C00 | region))) { printf("\n I won't uninstall the rgsel IOS\n"); ret = -999; diff --git a/source/wad.h b/source/wad.h index f5b2586..106f33f 100644 --- a/source/wad.h +++ b/source/wad.h @@ -2,7 +2,9 @@ #define _WAD_H_ /* Prototypes */ -s32 Wad_Install(FILE *); -s32 Wad_Uninstall(FILE *); +s32 Wad_Install(FILE* fp); +s32 Wad_Uninstall(FILE* fp); +s32 GetSysMenuRegion(u16* version, char* region); +const char* GetSysMenuRegionString(const char* region); #endif