- FAT stuff:

- Refactored almost everything
  - Will mount available devices at start and unmount at exit app
  - Device select screen will now only show avialable devices
  - Added option to remount devices in the select screen
  - Will now warn if region checks are disabled in select screen
  - Added option to reenable region checks in select screen
  - Probably even more changes

- SM wad installation:
  - Changed the region check functions (WIP)
  - While you install a SM you'll now be able to retain Priiloader

- Bug fixes
- Refactoring
- Even more bug fixes
This commit is contained in:
0verjoY 2023-02-19 20:47:31 +01:00
parent 2d2592a890
commit 31d2402d59
17 changed files with 1476 additions and 2001 deletions

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 178 KiB

After

Width:  |  Height:  |  Size: 178 KiB

View File

@ -1,58 +1,104 @@
#include <stdio.h>
#include <string.h>
#include <ogcsys.h>
#include <fat.h>
#include <sys/dir.h>
#include <sdcard/gcsd.h>
#include <sdcard/wiisd_io.h>
//#include <smb.h>
#include "fat.h"
#include "usbstorage.h"
s32 Fat_Mount(fatDevice *dev)
typedef struct
{
s32 ret;
/* Device prefix */
char* prefix;
/* Device name */
char* name;
/* Device available */
bool isMounted;
/* 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();
/* Initialize interface */
ret = dev->interface->startup();
if (!ret)
return -1;
continue;
ret = fatMountSimple(gDevices[gNumDevices]->prefix, gDevices[gNumDevices]->interface);
/* Mount device */
ret = fatMountSimple(dev->mount, dev->interface);
if (!ret)
return -1;
continue;
return 0;
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)
s32 i;
for (i = 0; i < FatGetDeviceCount(); i++)
{
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;
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;
}

View File

@ -1,27 +1,6 @@
#ifndef _FAT_H_
#define _FAT_H_
/* libfat header */
#include <fat.h>
#include <sys/dir.h>
/* SD headers */
#include <sdcard/gcsd.h>
#include <sdcard/wiisd_io.h>
/* '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

80
source/fileops.c Normal file
View File

@ -0,0 +1,80 @@
#include <stdio.h>
#include <malloc.h>
#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;
}

17
source/fileops.h Normal file
View File

@ -0,0 +1,17 @@
#ifndef __FILEOPS_H__
#define __FILEOPS_H__
#include <dirent.h>
#include <ogcsys.h>
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

View File

@ -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

View File

@ -7,6 +7,7 @@
#include "menu.h"
#include "nand.h"
#include "globals.h"
#include "fileops.h"
/* Constants */
#define CONSOLE_XCOORD 70
@ -14,34 +15,23 @@
#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)
@ -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) {

View File

@ -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);

View File

@ -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 & (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_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++;
if (buttons & WPAD_BUTTON_LEFT)
{
if ((s8)(--gSelected) < 0)
gSelected = FatGetDeviceCount() - 1;
}
/* HOME button */
if (buttons & WPAD_BUTTON_HOME)
else if (buttons & WPAD_BUTTON_1 && skipRegionSafetyCheck)
{
skipRegionSafetyCheck = false;
}
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,23 +806,33 @@ 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);
sprintf(tmpPath, "%s:%s", FatGetDevicePrefix(gSelected), gConfig.startupPath);
if (FSOPFolderExists(tmpPath))
PushCurrentDir(tmpPath, 0, 0);
}
else // unable to open provided dir, stick with root dir
sprintf(tmpPath, "%s:%s", fdev->mount, WAD_DIRECTORY);
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 */
@ -870,20 +841,23 @@ getList:
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;
}
@ -921,8 +895,11 @@ getList:
/* 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,51 +909,57 @@ 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)
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) {
}
if (file->iswad)
{
/* Plus Button - Leathl */
if (buttons & WPAD_BUTTON_PLUS)
{
@ -987,124 +970,128 @@ getList:
while( i < fileCnt)
{
fatFile *file = &fileList[i];
if (((file->isdir) == false) & (file->install == 0)) {
if (((file->isdir) == false) && (file->install == 0))
{
file->install = 1;
installCnt += 1;
}
else if (((file->isdir) == false) & (file->install == 1)) {
else if (((file->isdir) == false) && (file->install == 1))
{
file->install = 0;
installCnt -= 1;
installCnt--;
}
else if (((file->isdir) == false) & (file->install == 2)) {
else if (((file->isdir) == false) && (file->install == 2))
{
file->install = 1;
installCnt += 1;
uninstallCnt -= 1;
installCnt++;
uninstallCnt--;
}
i++;
}
}
else
{
fatFile *file = &fileList[selected];
if (((file->isdir) == false) & (file->install == 0)) {
if (((file->isdir) == false) && (file->install == 0))
{
file->install = 1;
installCnt += 1;
installCnt++;
}
else if (((file->isdir) == false) & (file->install == 1)) {
else if (((file->isdir) == false) & (file->install == 1))
{
file->install = 0;
installCnt -= 1;
installCnt--;
}
else if (((file->isdir) == false) & (file->install == 2)) {
else if (((file->isdir) == false) & (file->install == 2))
{
file->install = 1;
installCnt += 1;
uninstallCnt -= 1;
installCnt++;
uninstallCnt--;
}
selected++;
selected++;
if (selected >= fileCnt)
selected = 0;
}
}
/* Minus Button - Leathl */
if (buttons & WPAD_BUTTON_MINUS)
else 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)) {
if (((file->isdir) == false) && (file->install == 0))
{
file->install = 2;
uninstallCnt += 1;
uninstallCnt++;
}
else if (((file->isdir) == false) & (file->install == 1)) {
else if (((file->isdir) == false) && (file->install == 1))
{
file->install = 2;
uninstallCnt += 1;
installCnt -= 1;
uninstallCnt++;
installCnt--;
}
else if (((file->isdir) == false) & (file->install == 2)) {
else if (((file->isdir) == false) & (file->install == 2))
{
file->install = 0;
uninstallCnt -= 1;
uninstallCnt--;
}
i++;
}
}
else
{
fatFile *file = &fileList[selected];
if (((file->isdir) == false) & (file->install == 0)) {
if (((file->isdir) == false) && (file->install == 0))
{
file->install = 2;
uninstallCnt += 1;
uninstallCnt++;
}
else if (((file->isdir) == false) & (file->install == 1)) {
else if (((file->isdir) == false) && (file->install == 1))
{
file->install = 2;
uninstallCnt += 1;
installCnt -= 1;
uninstallCnt++;
installCnt--;
}
else if (((file->isdir) == false) & (file->install == 2)) {
else if (((file->isdir) == false) && (file->install == 2))
{
file->install = 0;
uninstallCnt -= 1;
}
selected++;
selected++;
if (selected >= fileCnt)
selected = 0;
}
}
}
/* 1 Button - Leathl */
if (buttons & WPAD_BUTTON_1)
{
fatFile *tmpFile = &fileList[selected];
char *tmpCurPath = PeekCurrentDir();
if (tmpCurPath != NULL) {
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;
@ -1139,6 +1126,7 @@ getList:
else
sprintf(tmpPath, "%s%s", tmpCurPath, tmpFile->filename);
}
// wiiNinja: Need to PopCurrentDir
PushCurrentDir (tmpPath, selected, start);
selected = 0;
@ -1153,14 +1141,18 @@ getList:
else
{
//If at least one WAD is marked, goto batch screen - Leathl
if ((installCnt > 0) | (uninstallCnt > 0)) {
if ((installCnt > 0) || (uninstallCnt > 0))
{
char *thisCurPath = PeekCurrentDir ();
if (thisCurPath != NULL) {
if (thisCurPath != NULL)
{
int res = Menu_BatchProcessWads(fileList, fileCnt, thisCurPath, installCnt, uninstallCnt);
if (res == 1) {
if (res == 1)
{
int counter;
for (counter = 0; counter < fileCnt; counter++) {
for (counter = 0; counter < fileCnt; counter++)
{
fatFile *temp = &fileList[counter];
temp->install = 0;
}
@ -1171,7 +1163,8 @@ getList:
}
}
//else use standard wadmanage menu - Leathl
else {
else
{
tmpCurPath = PeekCurrentDir ();
if (tmpCurPath != NULL)
Menu_WadManage(tmpFile, tmpCurPath);
@ -1180,22 +1173,21 @@ getList:
}
/* B button */
if (buttons & WPAD_BUTTON_B)
else 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 **/
@ -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;
}
@ -1221,7 +1213,9 @@ void Menu_Loop(void)
{
u8 iosVersion;
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];

View File

@ -1,10 +1,58 @@
#include <stdio.h>
#include <stdarg.h>
#include <ogcsys.h>
#include <malloc.h>
#include <string.h>
#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 = "&lt;";
break;
case '>':
esc = "&gt;";
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)
@ -84,3 +132,336 @@ s32 Nand_Disable(void)
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

View File

@ -14,11 +14,30 @@ typedef struct {
u32 umountCmd;
} nandDevice;
typedef struct
{
char name[ISFS_MAXPATH];
int type;
} NameList;
/* Prototypes */
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

View File

@ -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));
}

View File

@ -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

View File

@ -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();
@ -206,24 +210,21 @@ int ReadConfigFile (char *configFilePath)
FILE* fptr;
char* tmpStr = malloc(MAX_FILE_PATH_LEN);
char tmpOutStr[40], path[128];
int i;
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,7 +315,7 @@ 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

View File

@ -3,6 +3,7 @@
#include <malloc.h>
#include <ogcsys.h>
#include <ogc/pad.h>
#include <unistd.h>
#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;
u16 v = 0;
s32 ret = Title_GetVersion(0x100000002LL, &v);
u64 title = TITLE_ID(1, 2);
static u8 tmd_buf[MAX_SIGNED_TMD_SIZE] ATTRIBUTE_ALIGN(32);
if (ret < 0)
return ret;
int ret = ES_GetStoredTMDSize(title, &tmd_size);
if (version)
*version = v;
if (region)
*region = RegionLookupList[(v & 0x0F)];
// 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++;
}
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);
else
ret = FSOPReadOpenFileA(fp, (void*)&header, offset, sizeof(wadHeader));
if (ret != 1)
goto err;
else
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);
else
ret = FSOPReadOpenFileA(fp, (void*)&p_certs, offset, header->certs_len);
if (ret != 1)
goto err;
else
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);
@ -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, &region);
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,6 +646,55 @@ 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 */
@ -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, &region);
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;

View File

@ -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