mirror of
https://github.com/modmii/YAWM-ModMii-Edition.git
synced 2024-11-21 23:59:18 +01:00
- 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:
parent
2d2592a890
commit
31d2402d59
1416
Test/menu.c
1416
Test/menu.c
File diff suppressed because it is too large
Load Diff
BIN
data/appboot.bin
BIN
data/appboot.bin
Binary file not shown.
Before Width: | Height: | Size: 178 KiB After Width: | Height: | Size: 178 KiB |
128
source/fat.c
128
source/fat.c
@ -1,58 +1,104 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <ogcsys.h>
|
#include <ogcsys.h>
|
||||||
|
#include <fat.h>
|
||||||
|
#include <sys/dir.h>
|
||||||
|
#include <sdcard/gcsd.h>
|
||||||
|
#include <sdcard/wiisd_io.h>
|
||||||
|
|
||||||
//#include <smb.h>
|
//#include <smb.h>
|
||||||
|
|
||||||
#include "fat.h"
|
#include "fat.h"
|
||||||
|
#include "usbstorage.h"
|
||||||
|
|
||||||
|
typedef struct
|
||||||
s32 Fat_Mount(fatDevice *dev)
|
|
||||||
{
|
{
|
||||||
s32 ret;
|
/* Device prefix */
|
||||||
|
char* prefix;
|
||||||
|
|
||||||
/* Initialize interface */
|
/* Device name */
|
||||||
ret = dev->interface->startup();
|
char* name;
|
||||||
if (!ret)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
/* Mount device */
|
/* Device available */
|
||||||
ret = fatMountSimple(dev->mount, dev->interface);
|
bool isMounted;
|
||||||
if (!ret)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
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 */
|
s32 i;
|
||||||
fatUnmount(dev->mount);
|
for (i = 0; i < FatGetDeviceCount(); i++)
|
||||||
|
{
|
||||||
/* Shutdown interface */
|
fatUnmount(gDevices[i]->prefix);
|
||||||
dev->interface->shutdown();
|
gDevices[i]->interface->shutdown();
|
||||||
}
|
gDevices[i]->isMounted = false;
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
31
source/fat.h
31
source/fat.h
@ -1,27 +1,6 @@
|
|||||||
#ifndef _FAT_H_
|
#ifndef _FAT_H_
|
||||||
#define _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 */
|
/* 'FAT File' structure */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
/* Filename */
|
/* Filename */
|
||||||
@ -41,9 +20,11 @@ typedef struct {
|
|||||||
|
|
||||||
|
|
||||||
/* Prototypes */
|
/* Prototypes */
|
||||||
s32 Fat_Mount(fatDevice *);
|
|
||||||
void Fat_Unmount(fatDevice *);
|
void FatMount();
|
||||||
char *Fat_ToFilename(const char *);
|
void FatUnmount();
|
||||||
|
char* FatGetDeviceName(u8 index);
|
||||||
|
char* FatGetDevicePrefix(u8 index);
|
||||||
|
s32 FatGetDeviceCount();
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
80
source/fileops.c
Normal file
80
source/fileops.c
Normal 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
17
source/fileops.h
Normal 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
|
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
// Constants
|
// Constants
|
||||||
#define CIOS_VERSION 249
|
#define CIOS_VERSION 249
|
||||||
#define ENTRIES_PER_PAGE 14
|
#define ENTRIES_PER_PAGE 12
|
||||||
#define MAX_FILE_PATH_LEN 1024
|
#define MAX_FILE_PATH_LEN 1024
|
||||||
#define MAX_DIR_LEVELS 10
|
#define MAX_DIR_LEVELS 10
|
||||||
#define WAD_DIRECTORY "/"
|
#define WAD_DIRECTORY "/"
|
||||||
@ -16,20 +16,8 @@
|
|||||||
#define WM_CONFIG_FILE_PATH ":/wad/wm_config.txt"
|
#define WM_CONFIG_FILE_PATH ":/wad/wm_config.txt"
|
||||||
#define WM_BACKGROUND_PATH ":/wad/background.png"
|
#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
|
#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 NAND_DEVICE_INDEX_INVALID -1
|
||||||
|
|
||||||
#define CIOS_VERSION_INVALID -1
|
#define CIOS_VERSION_INVALID -1
|
||||||
|
|
||||||
// For the WiiLight
|
// For the WiiLight
|
||||||
@ -52,7 +40,7 @@ typedef struct
|
|||||||
|
|
||||||
extern CONFIG gConfig;
|
extern CONFIG gConfig;
|
||||||
extern nandDevice ndevList[];
|
extern nandDevice ndevList[];
|
||||||
extern fatDevice fdevList[];
|
//extern fatDevice fdevList[];
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
35
source/gui.c
35
source/gui.c
@ -7,6 +7,7 @@
|
|||||||
#include "menu.h"
|
#include "menu.h"
|
||||||
#include "nand.h"
|
#include "nand.h"
|
||||||
#include "globals.h"
|
#include "globals.h"
|
||||||
|
#include "fileops.h"
|
||||||
|
|
||||||
/* Constants */
|
/* Constants */
|
||||||
#define CONSOLE_XCOORD 70
|
#define CONSOLE_XCOORD 70
|
||||||
@ -14,34 +15,23 @@
|
|||||||
#define CONSOLE_WIDTH 502
|
#define CONSOLE_WIDTH 502
|
||||||
#define CONSOLE_HEIGHT 300
|
#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)
|
s32 __Gui_DrawPng(void *img, u32 x, u32 y)
|
||||||
{
|
{
|
||||||
IMGCTX ctx = NULL;
|
IMGCTX ctx = NULL;
|
||||||
PNGUPROP imgProp;
|
PNGUPROP imgProp;
|
||||||
|
char path[1024];
|
||||||
|
s32 ret = -1;
|
||||||
|
s32 i;
|
||||||
|
|
||||||
s32 ret;
|
for (i = 0; i < FatGetDeviceCount(); i++)
|
||||||
|
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
fdev = &fdevList[2];
|
snprintf(path, sizeof(path), "%s:/wad/background.png", FatGetDevicePrefix(i));
|
||||||
Fat_Mount(fdev);
|
if (FSOPFileExists(path))
|
||||||
if (file_exists("usb2:/wad/background.png")) ctx = PNGU_SelectImageFromDevice ("usb2:/wad/background.png");
|
{
|
||||||
|
ctx = PNGU_SelectImageFromDevice(path);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!ctx)
|
if(!ctx)
|
||||||
@ -53,6 +43,7 @@ s32 __Gui_DrawPng(void *img, u32 x, u32 y)
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get image properties */
|
/* Get image properties */
|
||||||
ret = PNGU_GetImageProperties(ctx, &imgProp);
|
ret = PNGU_GetImageProperties(ctx, &imgProp);
|
||||||
if (ret != PNGU_OK) {
|
if (ret != PNGU_OK) {
|
||||||
|
@ -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_TitleVersionCheck_patch[] = { 0xE0, 0x01, 0x4E, 0x56 };
|
||||||
const u8 ES_TitleDeleteCheck_old[] = { 0xD8, 0x00, 0x4A, 0x04 };
|
const u8 ES_TitleDeleteCheck_old[] = { 0xD8, 0x00, 0x4A, 0x04 };
|
||||||
const u8 ES_TitleDeleteCheck_patch[] = { 0xE0, 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
|
//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
|
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) {
|
if (AHBPROT_DISABLED) {
|
||||||
disable_memory_protection();
|
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("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_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("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);
|
count += apply_patch("hash_check", hash_old, sizeof(hash_old), hash_patch, sizeof(hash_patch), 1);
|
||||||
|
657
source/menu.c
657
source/menu.c
@ -12,7 +12,6 @@
|
|||||||
#include "nand.h"
|
#include "nand.h"
|
||||||
#include "restart.h"
|
#include "restart.h"
|
||||||
#include "title.h"
|
#include "title.h"
|
||||||
#include "usbstorage.h"
|
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "video.h"
|
#include "video.h"
|
||||||
#include "wad.h"
|
#include "wad.h"
|
||||||
@ -21,27 +20,16 @@
|
|||||||
#include "globals.h"
|
#include "globals.h"
|
||||||
#include "iospatch.h"
|
#include "iospatch.h"
|
||||||
#include "appboot.h"
|
#include "appboot.h"
|
||||||
|
#include "fileops.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 },
|
|
||||||
};
|
|
||||||
|
|
||||||
/* NAND device list */
|
/* NAND device list */
|
||||||
//static nandDevice ndevList[] = {
|
nandDevice ndevList[] =
|
||||||
nandDevice ndevList[] = {
|
{
|
||||||
{ "Disable", 0, 0x00, 0x00 },
|
{ "Disable", 0, 0x00, 0x00 },
|
||||||
{ "SD/SDHC Card", 1, 0xF0, 0xF1 },
|
{ "SD/SDHC Card", 1, 0xF0, 0xF1 },
|
||||||
{ "USB 2.0 Mass Storage Device", 2, 0xF2, 0xF3 },
|
{ "USB 2.0 Mass Storage Device", 2, 0xF2, 0xF3 },
|
||||||
};
|
};
|
||||||
|
|
||||||
/* FAT device */
|
|
||||||
static fatDevice *fdev = NULL;
|
|
||||||
static nandDevice *ndev = NULL;
|
static nandDevice *ndev = NULL;
|
||||||
|
|
||||||
// wiiNinja: Define a buffer holding the previous path names as user
|
// 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 char gDirList [MAX_DIR_LEVELS][MAX_FILE_PATH_LEN];
|
||||||
static s32 gSeleted[MAX_DIR_LEVELS];
|
static s32 gSeleted[MAX_DIR_LEVELS];
|
||||||
static s32 gStart[MAX_DIR_LEVELS];
|
static s32 gStart[MAX_DIR_LEVELS];
|
||||||
|
static char gMenuRegion = '\0';
|
||||||
|
static u16 gMenuVersion = 0;
|
||||||
|
static u8 gSelected = 0;
|
||||||
|
|
||||||
/* Macros */
|
/* 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))
|
#define NB_NAND_DEVICES (sizeof(ndevList) / sizeof(nandDevice))
|
||||||
|
|
||||||
// Local prototypes: wiiNinja
|
// Local prototypes: wiiNinja
|
||||||
@ -92,34 +83,6 @@ int __Menu_EntryCmp(const void *p1, const void *p2)
|
|||||||
return strcasecmp(f1->filename, f2->filename);
|
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];
|
char gFileName[MAX_FILE_PATH_LEN];
|
||||||
s32 __Menu_RetrieveList(char *inPath, fatFile **outbuf, u32 *outlen)
|
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;
|
size_t fsize = 0;
|
||||||
|
|
||||||
snprintf(gFileName, MAX_FILE_PATH_LEN, "%s/%s", inPath, ent->d_name);
|
snprintf(gFileName, MAX_FILE_PATH_LEN, "%s/%s", inPath, ent->d_name);
|
||||||
if (__FolderExists(gFileName)) // wiiNinja
|
if (FSOPFolderExists(gFileName)) // wiiNinja
|
||||||
{
|
{
|
||||||
isdir = true;
|
isdir = true;
|
||||||
// Add only the item ".." which is the previous directory
|
// 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"))
|
if(!strcasecmp(ent->d_name+strlen(ent->d_name)-4, ".wad"))
|
||||||
{
|
{
|
||||||
fsize = __GetFileSizeBytes(gFileName);
|
fsize = FSOPGetFileSizeBytes(gFileName);
|
||||||
addFlag = true;
|
addFlag = true;
|
||||||
iswad = true;
|
iswad = true;
|
||||||
}
|
}
|
||||||
if(!strcasecmp(ent->d_name+strlen(ent->d_name)-4, ".dol"))
|
if(!strcasecmp(ent->d_name+strlen(ent->d_name)-4, ".dol"))
|
||||||
{
|
{
|
||||||
fsize = __GetFileSizeBytes(gFileName);
|
fsize = FSOPGetFileSizeBytes(gFileName);
|
||||||
addFlag = true;
|
addFlag = true;
|
||||||
isdol = true;
|
isdol = true;
|
||||||
}
|
}
|
||||||
if(!strcasecmp(ent->d_name+strlen(ent->d_name)-4, ".elf"))
|
if(!strcasecmp(ent->d_name+strlen(ent->d_name)-4, ".elf"))
|
||||||
{
|
{
|
||||||
fsize = __GetFileSizeBytes(gFileName);
|
fsize = FSOPGetFileSizeBytes(gFileName);
|
||||||
addFlag = true;
|
addFlag = true;
|
||||||
iself = true;
|
iself = true;
|
||||||
}
|
}
|
||||||
@ -333,74 +296,94 @@ void Menu_SelectIOS(void)
|
|||||||
|
|
||||||
void Menu_FatDevice(void)
|
void Menu_FatDevice(void)
|
||||||
{
|
{
|
||||||
int ret, selected = 0;
|
FatMount();
|
||||||
|
|
||||||
/* Unmount FAT device */
|
const u16 konamiCode[] =
|
||||||
//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_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
|
WPAD_BUTTON_RIGHT, WPAD_BUTTON_LEFT, WPAD_BUTTON_RIGHT, WPAD_BUTTON_B, WPAD_BUTTON_A
|
||||||
};
|
};
|
||||||
|
|
||||||
int codePosition = 0;
|
int codePosition = 0;
|
||||||
|
extern bool skipRegionSafetyCheck;
|
||||||
|
|
||||||
/* Select source device */
|
/* Select source device */
|
||||||
if (gConfig.fatDeviceIndex < 0)
|
if (gConfig.fatDeviceIndex < 0)
|
||||||
{
|
{
|
||||||
for (;;) {
|
for (;;)
|
||||||
|
{
|
||||||
/* Clear console */
|
/* Clear console */
|
||||||
Con_Clear();
|
Con_Clear();
|
||||||
|
|
||||||
|
if (!FatGetDeviceCount())
|
||||||
|
{
|
||||||
|
printf("\t[+] No source device: < %s >\n\n", FatGetDeviceName(gSelected));
|
||||||
|
}
|
||||||
|
|
||||||
/* Selected device */
|
/* Selected device */
|
||||||
fdev = &fdevList[selected];
|
//printf("\tWii menu version: %d, region: %s\n\n", gMenuVersion, GetSysMenuRegionString(&gMenuRegion));
|
||||||
|
printf("\t>> Select source device: < %s >\n\n", FatGetDeviceName(gSelected));
|
||||||
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 LEFT/RIGHT to change the selected device.\n\n");
|
||||||
|
|
||||||
printf("\t Press A button to continue.\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");
|
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();
|
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 (buttons & konamiCode[codePosition])
|
{
|
||||||
++codePosition;
|
if (!skipRegionSafetyCheck)
|
||||||
else
|
{
|
||||||
codePosition = 0;
|
if (buttons & konamiCode[codePosition])
|
||||||
|
++codePosition;
|
||||||
|
else
|
||||||
|
codePosition = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
if (buttons & WPAD_BUTTON_LEFT)
|
||||||
/* LEFT/RIGHT buttons */
|
{
|
||||||
if (buttons & WPAD_BUTTON_LEFT) {
|
if ((s8)(--gSelected) < 0)
|
||||||
if ((--selected) <= -1)
|
gSelected = FatGetDeviceCount() - 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) {
|
else if (buttons & WPAD_BUTTON_1 && skipRegionSafetyCheck)
|
||||||
if ((++selected) >= NB_FAT_DEVICES)
|
{
|
||||||
selected = 0;
|
skipRegionSafetyCheck = false;
|
||||||
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_RIGHT)
|
||||||
/* HOME button */
|
{
|
||||||
if (buttons & WPAD_BUTTON_HOME)
|
if ((++gSelected) >= FatGetDeviceCount())
|
||||||
|
gSelected = 0;
|
||||||
|
}
|
||||||
|
else if (buttons & WPAD_BUTTON_HOME)
|
||||||
|
{
|
||||||
Restart();
|
Restart();
|
||||||
|
}
|
||||||
/* A button */
|
else if (buttons & WPAD_BUTTON_B && !codePosition)
|
||||||
if (buttons & WPAD_BUTTON_A) {
|
{
|
||||||
if (codePosition == sizeof(konamiCode) / sizeof(konamiCode[0])) {
|
printf("\t\t[-] Mounting devices.");
|
||||||
extern bool skipRegionSafetyCheck;
|
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;
|
skipRegionSafetyCheck = true;
|
||||||
printf("[+] Disabled SM region checks\n");
|
printf("[+] Disabled SM region checks\n");
|
||||||
sleep(3);
|
sleep(3);
|
||||||
@ -412,34 +395,12 @@ void Menu_FatDevice(void)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
sleep(5);
|
sleep(5);
|
||||||
fdev = &fdevList[gConfig.fatDeviceIndex];
|
if (gConfig.fatDeviceIndex < FatGetDeviceCount())
|
||||||
|
gSelected = gConfig.fatDeviceIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("[+] Mounting %s, please wait...", fdev->name );
|
printf("[+] Selected source device: %s.", FatGetDeviceName(gSelected));
|
||||||
fflush(stdout);
|
|
||||||
|
|
||||||
/* Mount FAT device */
|
|
||||||
|
|
||||||
ret = Fat_Mount(fdev);
|
|
||||||
if (ret < 0) {
|
|
||||||
printf(" ERROR! (ret = %d)\n", ret);
|
|
||||||
goto err;
|
|
||||||
} else
|
|
||||||
printf(" OK!\n");
|
|
||||||
sleep(2);
|
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)
|
void Menu_NandDevice(void)
|
||||||
@ -845,45 +806,58 @@ void Menu_WadList(void)
|
|||||||
|
|
||||||
gDirLevel = 0;
|
gDirLevel = 0;
|
||||||
|
|
||||||
// push root dir as base folder
|
// push root dir as base folderGetDevice()
|
||||||
sprintf(tmpPath, "%s:%s", fdev->mount, WAD_DIRECTORY);
|
//sprintf(tmpPath, "%s:%s", fdev->mount, WAD_DIRECTORY);
|
||||||
|
sprintf(tmpPath, "%s:%s", FatGetDevicePrefix(gSelected), WAD_DIRECTORY);
|
||||||
PushCurrentDir(tmpPath,0,0);
|
PushCurrentDir(tmpPath,0,0);
|
||||||
// if user provides startup directory, try it out first
|
// if user provides startup directory, try it out first
|
||||||
if (strcmp (WAD_DIRECTORY, gConfig.startupPath) != 0)
|
if (strcmp (WAD_DIRECTORY, gConfig.startupPath) != 0)
|
||||||
{
|
{
|
||||||
// replace root dir with provided startup directory
|
// replace root dir with provided startup directory
|
||||||
sprintf(tmpPath, "%s:%s", fdev->mount, gConfig.startupPath);
|
sprintf(tmpPath, "%s:%s", FatGetDevicePrefix(gSelected), gConfig.startupPath);
|
||||||
// If the directory can be successfully opened, it must exists
|
|
||||||
DIR *tmpDirPtr = opendir(tmpPath);
|
if (FSOPFolderExists(tmpPath))
|
||||||
if (tmpDirPtr)
|
PushCurrentDir(tmpPath, 0, 0);
|
||||||
{
|
else
|
||||||
closedir (tmpDirPtr);
|
sprintf(tmpPath, "%s:%s", FatGetDevicePrefix(gSelected), WAD_DIRECTORY);
|
||||||
PushCurrentDir(tmpPath,0,0);
|
|
||||||
}
|
// If the directory can be successfully opened, it must exists
|
||||||
else // unable to open provided dir, stick with root dir
|
// DIR *tmpDirPtr = opendir(tmpPath);
|
||||||
sprintf(tmpPath, "%s:%s", fdev->mount, WAD_DIRECTORY);
|
// 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 */
|
/* Retrieve filelist */
|
||||||
getList:
|
getList:
|
||||||
free (fileList);
|
free(fileList);
|
||||||
fileList = NULL;
|
fileList = NULL;
|
||||||
|
|
||||||
ret = __Menu_RetrieveList(tmpPath, &fileList, &fileCnt);
|
ret = __Menu_RetrieveList(tmpPath, &fileList, &fileCnt);
|
||||||
if (ret < 0) {
|
if (ret < 0)
|
||||||
|
{
|
||||||
printf(" ERROR! (ret = %d)\n", ret);
|
printf(" ERROR! (ret = %d)\n", ret);
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* No files */
|
/* No files */
|
||||||
if (!fileCnt) {
|
if (!fileCnt)
|
||||||
|
{
|
||||||
printf(" No files found!\n");
|
printf(" No files found!\n");
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set install-values to 0 - Leathl */
|
/* Set install-values to 0 - Leathl */
|
||||||
int counter;
|
int counter;
|
||||||
for (counter = 0; counter < fileCnt; counter++) {
|
for (counter = 0; counter < fileCnt; counter++)
|
||||||
|
{
|
||||||
fatFile *file = &fileList[counter];
|
fatFile *file = &fileList[counter];
|
||||||
file->install = 0;
|
file->install = 0;
|
||||||
}
|
}
|
||||||
@ -898,8 +872,8 @@ getList:
|
|||||||
|
|
||||||
/** Print entries **/
|
/** Print entries **/
|
||||||
cnt = strlen(tmpPath);
|
cnt = strlen(tmpPath);
|
||||||
if(cnt>30)
|
if(cnt > 30)
|
||||||
index = cnt-30;
|
index = cnt - 30;
|
||||||
else
|
else
|
||||||
index = 0;
|
index = 0;
|
||||||
|
|
||||||
@ -916,13 +890,16 @@ getList:
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
strncpy(str, file->filename, 40); //Only 40 chars to fit the screen
|
strncpy(str, file->filename, 40); //Only 40 chars to fit the screen
|
||||||
str[40]=0;
|
str[40] = 0;
|
||||||
|
|
||||||
/* Print filename */
|
/* Print filename */
|
||||||
//printf("\t%2s %s (%.2f MB)\n", (cnt == selected) ? ">>" : " ", file->filename, filesize);
|
//printf("\t%2s %s (%.2f MB)\n", (cnt == selected) ? ">>" : " ", file->filename, filesize);
|
||||||
if (file->isdir) // wiiNinja
|
if (file->isdir) // wiiNinja
|
||||||
|
{
|
||||||
printf("\t%2s [%s]\n", (cnt == selected) ? ">>" : " ", str);
|
printf("\t%2s [%s]\n", (cnt == selected) ? ">>" : " ", str);
|
||||||
else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
if(file->iswad)
|
if(file->iswad)
|
||||||
printf("\t%2s%s%s (%.2f MB)\n", (cnt == selected) ? ">>" : " ", (file->install == 1) ? "+" : ((file->install == 2) ? "-" : " "), str, filesize);
|
printf("\t%2s%s%s (%.2f MB)\n", (cnt == selected) ? ">>" : " ", (file->install == 1) ? "+" : ((file->install == 2) ? "-" : " "), str, filesize);
|
||||||
else
|
else
|
||||||
@ -932,270 +909,285 @@ getList:
|
|||||||
|
|
||||||
printf("\n");
|
printf("\n");
|
||||||
fatFile *file = &fileList[selected];
|
fatFile *file = &fileList[selected];
|
||||||
if(file->iswad)
|
|
||||||
printf("[+] Press A to (un)install.");
|
if (file->iswad)
|
||||||
else if(file->isdol || file->iself)
|
printf("[+] Press A to (un)install.");
|
||||||
printf("[+] Press A to launch dol/elf.");
|
else if (file->isdol || file->iself)
|
||||||
else if(file->isdir)
|
printf("[+] Press A to launch dol/elf.");
|
||||||
printf("[+] Press A to Enter directory.");
|
else if (file->isdir)
|
||||||
if(gDirLevel>1)
|
printf("[+] Press A to Enter directory.");
|
||||||
|
|
||||||
|
if (gDirLevel > 1)
|
||||||
printf(" Press B to go up-level DIR.\n");
|
printf(" Press B to go up-level DIR.\n");
|
||||||
else
|
else
|
||||||
printf(" Press B to select a device.\n");
|
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 **/
|
/** Controls **/
|
||||||
u32 buttons = WaitButtons();
|
u32 buttons = WaitButtons();
|
||||||
|
|
||||||
/* DPAD buttons */
|
/* DPAD buttons */
|
||||||
if (buttons & WPAD_BUTTON_UP) {
|
if (buttons & WPAD_BUTTON_UP)
|
||||||
selected--;
|
{
|
||||||
|
if (--selected < 0)
|
||||||
if (selected <= -1)
|
|
||||||
selected = (fileCnt - 1);
|
selected = (fileCnt - 1);
|
||||||
}
|
}
|
||||||
if (buttons & WPAD_BUTTON_LEFT) {
|
else if (buttons & WPAD_BUTTON_LEFT)
|
||||||
selected = selected + ENTRIES_PER_PAGE;
|
{
|
||||||
|
selected += ENTRIES_PER_PAGE;
|
||||||
|
|
||||||
if (selected >= fileCnt)
|
if (selected >= fileCnt)
|
||||||
selected = 0;
|
selected = 0;
|
||||||
}
|
}
|
||||||
if (buttons & WPAD_BUTTON_DOWN) {
|
else if (buttons & WPAD_BUTTON_DOWN)
|
||||||
selected ++;
|
{
|
||||||
|
if (++selected >= fileCnt)
|
||||||
if (selected >= fileCnt)
|
|
||||||
selected = 0;
|
selected = 0;
|
||||||
}
|
}
|
||||||
if (buttons & WPAD_BUTTON_RIGHT) {
|
else if (buttons & WPAD_BUTTON_RIGHT)
|
||||||
selected = selected - ENTRIES_PER_PAGE;
|
{
|
||||||
|
selected -= ENTRIES_PER_PAGE;
|
||||||
|
|
||||||
if (selected <= -1)
|
if (selected < 0)
|
||||||
selected = (fileCnt - 1);
|
selected = (fileCnt - 1);
|
||||||
}
|
}
|
||||||
|
else if (buttons & WPAD_BUTTON_HOME)
|
||||||
/* HOME button */
|
{
|
||||||
if (buttons & WPAD_BUTTON_HOME)
|
|
||||||
Restart();
|
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;
|
if(Wpad_TimeButton())
|
||||||
int i = 0;
|
{
|
||||||
while( i < fileCnt)
|
installCnt = 0;
|
||||||
{
|
int i = 0;
|
||||||
fatFile *file = &fileList[i];
|
while( i < fileCnt)
|
||||||
if (((file->isdir) == false) & (file->install == 0)) {
|
{
|
||||||
file->install = 1;
|
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;
|
installCnt++;
|
||||||
}
|
uninstallCnt--;
|
||||||
else if (((file->isdir) == false) & (file->install == 1)) {
|
}
|
||||||
file->install = 0;
|
|
||||||
|
|
||||||
installCnt -= 1;
|
i++;
|
||||||
}
|
}
|
||||||
else if (((file->isdir) == false) & (file->install == 2)) {
|
}
|
||||||
file->install = 1;
|
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 += 1;
|
installCnt++;
|
||||||
uninstallCnt -= 1;
|
uninstallCnt--;
|
||||||
}
|
}
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
selected++;
|
||||||
|
if (selected >= fileCnt)
|
||||||
|
selected = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
/* Minus Button - Leathl */
|
||||||
|
else if (buttons & WPAD_BUTTON_MINUS)
|
||||||
{
|
{
|
||||||
fatFile *file = &fileList[selected];
|
if(Wpad_TimeButton())
|
||||||
if (((file->isdir) == false) & (file->install == 0)) {
|
{
|
||||||
file->install = 1;
|
installCnt = 0;
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
installCnt += 1;
|
while( i < fileCnt)
|
||||||
}
|
{
|
||||||
else if (((file->isdir) == false) & (file->install == 1)) {
|
fatFile *file = &fileList[i];
|
||||||
file->install = 0;
|
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;
|
i++;
|
||||||
}
|
}
|
||||||
else if (((file->isdir) == false) & (file->install == 2)) {
|
}
|
||||||
file->install = 1;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
installCnt += 1;
|
selected++;
|
||||||
uninstallCnt -= 1;
|
if (selected >= fileCnt)
|
||||||
}
|
selected = 0;
|
||||||
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 */
|
/* 1 Button - Leathl */
|
||||||
if (buttons & WPAD_BUTTON_1)
|
if (buttons & WPAD_BUTTON_1)
|
||||||
{
|
{
|
||||||
fatFile *tmpFile = &fileList[selected];
|
fatFile *tmpFile = &fileList[selected];
|
||||||
char *tmpCurPath = PeekCurrentDir ();
|
char *tmpCurPath = PeekCurrentDir();
|
||||||
if (tmpCurPath != NULL) {
|
if (tmpCurPath != NULL)
|
||||||
|
{
|
||||||
int res = Menu_FileOperations(tmpFile, tmpCurPath);
|
int res = Menu_FileOperations(tmpFile, tmpCurPath);
|
||||||
if (res != 0)
|
if (res != 0)
|
||||||
goto getList;
|
goto getList;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* A button */
|
/* A button */
|
||||||
if (buttons & WPAD_BUTTON_A)
|
else if (buttons & WPAD_BUTTON_A)
|
||||||
{
|
{
|
||||||
fatFile *tmpFile = &fileList[selected];
|
fatFile *tmpFile = &fileList[selected];
|
||||||
char *tmpCurPath;
|
char *tmpCurPath;
|
||||||
if (tmpFile->isdir) // wiiNinja
|
if (tmpFile->isdir) // wiiNinja
|
||||||
|
{
|
||||||
|
if (strcmp (tmpFile->filename, "..") == 0)
|
||||||
{
|
{
|
||||||
if (strcmp (tmpFile->filename, "..") == 0)
|
selected = 0;
|
||||||
{
|
start = 0;
|
||||||
selected = 0;
|
|
||||||
start = 0;
|
|
||||||
|
|
||||||
// Previous dir
|
// Previous dir
|
||||||
tmpCurPath = PopCurrentDir(&selected, &start);
|
tmpCurPath = PopCurrentDir(&selected, &start);
|
||||||
if (tmpCurPath != NULL)
|
if (tmpCurPath != NULL)
|
||||||
sprintf(tmpPath, "%s", tmpCurPath);
|
sprintf(tmpPath, "%s", tmpCurPath);
|
||||||
|
|
||||||
installCnt = 0;
|
installCnt = 0;
|
||||||
uninstallCnt = 0;
|
uninstallCnt = 0;
|
||||||
|
|
||||||
goto getList;
|
goto getList;
|
||||||
}
|
}
|
||||||
else if (IsListFull () == true)
|
else if (IsListFull() == true)
|
||||||
{
|
{
|
||||||
WaitPrompt ("Maximum number of directory levels is reached.\n");
|
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
|
else
|
||||||
{
|
{
|
||||||
//If at least one WAD is marked, goto batch screen - Leathl
|
tmpCurPath = PeekCurrentDir ();
|
||||||
if ((installCnt > 0) | (uninstallCnt > 0)) {
|
if (tmpCurPath != NULL)
|
||||||
char *thisCurPath = PeekCurrentDir ();
|
{
|
||||||
if (thisCurPath != NULL) {
|
if(gDirLevel > 1)
|
||||||
int res = Menu_BatchProcessWads(fileList, fileCnt, thisCurPath, installCnt, uninstallCnt);
|
sprintf(tmpPath, "%s/%s", tmpCurPath, tmpFile->filename);
|
||||||
|
else
|
||||||
|
sprintf(tmpPath, "%s%s", tmpCurPath, tmpFile->filename);
|
||||||
|
}
|
||||||
|
|
||||||
if (res == 1) {
|
// wiiNinja: Need to PopCurrentDir
|
||||||
int counter;
|
PushCurrentDir (tmpPath, selected, start);
|
||||||
for (counter = 0; counter < fileCnt; counter++) {
|
selected = 0;
|
||||||
fatFile *temp = &fileList[counter];
|
start = 0;
|
||||||
temp->install = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
installCnt = 0;
|
installCnt = 0;
|
||||||
uninstallCnt = 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 */
|
/* B button */
|
||||||
if (buttons & WPAD_BUTTON_B)
|
else if (buttons & WPAD_BUTTON_B)
|
||||||
{
|
{
|
||||||
if(gDirLevel<=1)
|
if (gDirLevel <= 1)
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
char *tmpCurPath;
|
char *tmpCurPath;
|
||||||
selected = 0;
|
selected = 0;
|
||||||
start = 0;
|
start = 0;
|
||||||
|
|
||||||
// Previous dir
|
// Previous dir
|
||||||
tmpCurPath = PopCurrentDir(&selected, &start);
|
tmpCurPath = PopCurrentDir(&selected, &start);
|
||||||
if (tmpCurPath != NULL)
|
if (tmpCurPath != NULL)
|
||||||
sprintf(tmpPath, "%s", tmpCurPath);
|
sprintf(tmpPath, "%s", tmpCurPath);
|
||||||
|
|
||||||
goto getList;
|
goto getList;
|
||||||
//return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Scrolling **/
|
/** Scrolling **/
|
||||||
@ -1204,7 +1196,7 @@ getList:
|
|||||||
|
|
||||||
if (index >= ENTRIES_PER_PAGE)
|
if (index >= ENTRIES_PER_PAGE)
|
||||||
start += index - (ENTRIES_PER_PAGE - 1);
|
start += index - (ENTRIES_PER_PAGE - 1);
|
||||||
if (index <= -1)
|
else if (index < 0)
|
||||||
start += index;
|
start += index;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1212,7 +1204,7 @@ err:
|
|||||||
printf("\n");
|
printf("\n");
|
||||||
printf(" Press any button to continue...\n");
|
printf(" Press any button to continue...\n");
|
||||||
|
|
||||||
free (tmpPath);
|
free(tmpPath);
|
||||||
|
|
||||||
/* Wait for button */
|
/* Wait for button */
|
||||||
WaitButtons();
|
WaitButtons();
|
||||||
@ -1220,8 +1212,10 @@ err:
|
|||||||
void Menu_Loop(void)
|
void Menu_Loop(void)
|
||||||
{
|
{
|
||||||
u8 iosVersion;
|
u8 iosVersion;
|
||||||
if(AHBPROT_DISABLED)
|
if (AHBPROT_DISABLED)
|
||||||
|
{
|
||||||
IOSPATCH_Apply();
|
IOSPATCH_Apply();
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Select IOS menu */
|
/* Select IOS menu */
|
||||||
@ -1230,6 +1224,7 @@ void Menu_Loop(void)
|
|||||||
|
|
||||||
/* Retrieve IOS version */
|
/* Retrieve IOS version */
|
||||||
iosVersion = IOS_GetVersion();
|
iosVersion = IOS_GetVersion();
|
||||||
|
GetSysMenuRegion(&gMenuVersion, &gMenuRegion);
|
||||||
|
|
||||||
ndev = &ndevList[0];
|
ndev = &ndevList[0];
|
||||||
|
|
||||||
|
381
source/nand.c
381
source/nand.c
@ -1,10 +1,58 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <stdarg.h>
|
||||||
#include <ogcsys.h>
|
#include <ogcsys.h>
|
||||||
|
#include <malloc.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#include "nand.h"
|
#include "nand.h"
|
||||||
|
#include "fileops.h"
|
||||||
|
|
||||||
|
#define BLOCK 2048
|
||||||
|
|
||||||
/* Buffer */
|
/* Buffer */
|
||||||
static u32 inbuf[8] ATTRIBUTE_ALIGN(32);
|
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)
|
s32 Nand_Mount(nandDevice *dev)
|
||||||
@ -84,3 +132,336 @@ s32 Nand_Disable(void)
|
|||||||
|
|
||||||
return ret;
|
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
|
||||||
|
@ -14,11 +14,30 @@ typedef struct {
|
|||||||
u32 umountCmd;
|
u32 umountCmd;
|
||||||
} nandDevice;
|
} nandDevice;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
char name[ISFS_MAXPATH];
|
||||||
|
int type;
|
||||||
|
} NameList;
|
||||||
|
|
||||||
|
|
||||||
/* Prototypes */
|
/* Prototypes */
|
||||||
s32 Nand_Mount(nandDevice *);
|
s32 Nand_Mount(nandDevice *);
|
||||||
s32 Nand_Unmount(nandDevice *);
|
s32 Nand_Unmount(nandDevice *);
|
||||||
s32 Nand_Enable(nandDevice *);
|
s32 Nand_Enable(nandDevice *);
|
||||||
s32 Nand_Disable(void);
|
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
|
#endif
|
||||||
|
@ -175,3 +175,17 @@ void SHA1(unsigned char *ptr, unsigned int size, unsigned char *outbuf) {
|
|||||||
SHA1Update(&ctx, ptr, size);
|
SHA1Update(&ctx, ptr, size);
|
||||||
SHA1Final(outbuf, &ctx);
|
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));
|
||||||
|
}
|
||||||
|
@ -2,5 +2,6 @@
|
|||||||
#define _SHA1_H_
|
#define _SHA1_H_
|
||||||
|
|
||||||
void SHA1(unsigned char *, unsigned int, unsigned char *);
|
void SHA1(unsigned char *, unsigned int, unsigned char *);
|
||||||
|
int CompareHash(unsigned char* first, unsigned int firstSize, unsigned char* second, unsigned int secondSize);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -166,6 +166,8 @@ int main(int argc, char **argv)
|
|||||||
/* Set video mode */
|
/* Set video mode */
|
||||||
Video_SetMode();
|
Video_SetMode();
|
||||||
|
|
||||||
|
FatMount();
|
||||||
|
|
||||||
/* Initialize console */
|
/* Initialize console */
|
||||||
Gui_InitConsole();
|
Gui_InitConsole();
|
||||||
|
|
||||||
@ -193,6 +195,8 @@ int main(int argc, char **argv)
|
|||||||
/* Menu loop */
|
/* Menu loop */
|
||||||
Menu_Loop();
|
Menu_Loop();
|
||||||
|
|
||||||
|
FatUnmount();
|
||||||
|
|
||||||
/* Restart Wii */
|
/* Restart Wii */
|
||||||
Restart_Wait();
|
Restart_Wait();
|
||||||
|
|
||||||
@ -200,30 +204,27 @@ int main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int ReadConfigFile (char *configFilePath)
|
int ReadConfigFile(char* configFilePath)
|
||||||
{
|
{
|
||||||
int retval = 0;
|
int retval = 0;
|
||||||
FILE *fptr;
|
FILE* fptr;
|
||||||
char *tmpStr = malloc (MAX_FILE_PATH_LEN);
|
char* tmpStr = malloc(MAX_FILE_PATH_LEN);
|
||||||
char tmpOutStr [40], path[128];
|
char tmpOutStr[40], path[128];
|
||||||
int i;
|
s32 i;
|
||||||
|
s32 ret = -1;
|
||||||
|
bool found = false;
|
||||||
|
|
||||||
if (tmpStr == NULL)
|
if (tmpStr == NULL)
|
||||||
return (-1);
|
return (-1);
|
||||||
|
|
||||||
fatDevice *fdev = &fdevList[0];
|
// Just check if at least one device is available
|
||||||
int ret = Fat_Mount(fdev);
|
for (i = 0; i < FatGetDeviceCount(); i++)
|
||||||
snprintf(path, sizeof(path), "%s%s", fdev->mount, configFilePath);
|
|
||||||
|
|
||||||
if (ret < 0)
|
|
||||||
{
|
{
|
||||||
fdev = &fdevList[2];
|
snprintf(path, sizeof(path), "%s%s", FatGetDevicePrefix(i), configFilePath);
|
||||||
ret = Fat_Mount(fdev);
|
found = true;
|
||||||
snprintf(path, sizeof(path), "%s%s", fdev->mount, configFilePath);
|
|
||||||
//snprintf(path, sizeof(path), "%s%s", fdev->mount, configFilePath);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret < 0)
|
if (!found)
|
||||||
{
|
{
|
||||||
printf(" ERROR! (ret = %d)\n", ret);
|
printf(" ERROR! (ret = %d)\n", ret);
|
||||||
// goto err;
|
// goto err;
|
||||||
@ -281,7 +282,8 @@ int ReadConfigFile (char *configFilePath)
|
|||||||
GetStringParam (tmpOutStr, tmpStr, MAX_FAT_DEVICE_LENGTH);
|
GetStringParam (tmpOutStr, tmpStr, MAX_FAT_DEVICE_LENGTH);
|
||||||
for (i = 0; i < 5; i++)
|
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;
|
gConfig.fatDeviceIndex = i;
|
||||||
}
|
}
|
||||||
@ -313,11 +315,11 @@ int ReadConfigFile (char *configFilePath)
|
|||||||
//printf ("Config file is not found\n"); // This is for testing only
|
//printf ("Config file is not found\n"); // This is for testing only
|
||||||
//WaitButtons();
|
//WaitButtons();
|
||||||
}
|
}
|
||||||
Fat_Unmount(fdev);
|
//Fat_Unmount(fdev);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Free memory
|
// Free memory
|
||||||
free (tmpStr);
|
free(tmpStr);
|
||||||
|
|
||||||
return (retval);
|
return (retval);
|
||||||
} // ReadConfig
|
} // ReadConfig
|
||||||
|
612
source/wad.c
612
source/wad.c
@ -3,6 +3,7 @@
|
|||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
#include <ogcsys.h>
|
#include <ogcsys.h>
|
||||||
#include <ogc/pad.h>
|
#include <ogc/pad.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "sys.h"
|
#include "sys.h"
|
||||||
#include "title.h"
|
#include "title.h"
|
||||||
@ -10,6 +11,9 @@
|
|||||||
#include "video.h"
|
#include "video.h"
|
||||||
#include "wad.h"
|
#include "wad.h"
|
||||||
#include "wpad.h"
|
#include "wpad.h"
|
||||||
|
#include "nand.h"
|
||||||
|
#include "fileops.h"
|
||||||
|
#include "sha1.h"
|
||||||
|
|
||||||
// Turn upper and lower into a full title ID
|
// Turn upper and lower into a full title ID
|
||||||
#define TITLE_ID(x,y) (((u64)(x) << 32) | (y))
|
#define TITLE_ID(x,y) (((u64)(x) << 32) | (y))
|
||||||
@ -18,32 +22,34 @@
|
|||||||
// Turn upper and lower into a full title ID
|
// Turn upper and lower into a full title ID
|
||||||
#define TITLE_LOWER(x) ((u32)(x))
|
#define TITLE_LOWER(x) ((u32)(x))
|
||||||
|
|
||||||
typedef struct {
|
const char RegionLookupList[16] =
|
||||||
int version;
|
{
|
||||||
int region;
|
'J', 'E', 'P', 0, 0, 0, 'K', 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
|
||||||
} 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'},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#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);
|
u32 WaitButtons(void);
|
||||||
|
static u32 gPriiloaderSize = 0;
|
||||||
|
static bool gForcedInstall = false;
|
||||||
|
|
||||||
u32 be32(const u8 *p)
|
u32 be32(const u8 *p)
|
||||||
{
|
{
|
||||||
@ -125,33 +131,280 @@ u64 get_title_ios(u64 title) {
|
|||||||
return 0;
|
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);
|
if (ret < 0)
|
||||||
static u8 tmd_buf[MAX_SIGNED_TMD_SIZE] ATTRIBUTE_ALIGN(32);
|
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;
|
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 */
|
/* 'WAD Header' structure */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
/* Header length */
|
/* Header length */
|
||||||
@ -174,45 +427,6 @@ typedef struct {
|
|||||||
/* Variables */
|
/* Variables */
|
||||||
static u8 wadBuffer[BLOCK_SIZE] ATTRIBUTE_ALIGN(32);
|
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)
|
s32 __Wad_GetTitleID(FILE *fp, wadHeader *header, u64 *tid)
|
||||||
{
|
{
|
||||||
signed_blob *p_tik = NULL;
|
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);
|
offset += round_up(header->crl_len, 64);
|
||||||
|
|
||||||
/* Read ticket */
|
/* Read ticket */
|
||||||
ret = __Wad_ReadAlloc(fp, (void *)&p_tik, offset, header->tik_len);
|
ret = FSOPReadOpenFileA(fp, (void*)&p_tik, offset, header->tik_len);
|
||||||
if (ret < 0)
|
if (ret != 1)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
/* Ticket data */
|
/* Ticket data */
|
||||||
@ -273,15 +487,17 @@ s32 Wad_Install(FILE *fp)
|
|||||||
u32 cnt, offset = 0;
|
u32 cnt, offset = 0;
|
||||||
int ret;
|
int ret;
|
||||||
u64 tid;
|
u64 tid;
|
||||||
|
bool retainPriiloader = false;
|
||||||
|
bool cleanupPriiloader = false;
|
||||||
|
|
||||||
printf("\t\t>> Reading WAD data...");
|
printf("\t\t>> Reading WAD data...");
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
|
|
||||||
ret = __Wad_ReadAlloc(fp, (void *)&header, offset, sizeof(wadHeader));
|
ret = FSOPReadOpenFileA(fp, (void*)&header, offset, sizeof(wadHeader));
|
||||||
if (ret >= 0)
|
if (ret != 1)
|
||||||
offset += round_up(header->header_len, 64);
|
goto err;
|
||||||
else
|
else
|
||||||
goto err;
|
offset += round_up(header->header_len, 64);
|
||||||
|
|
||||||
//Don't try to install boot2
|
//Don't try to install boot2
|
||||||
__Wad_GetTitleID(fp, header, &tid);
|
__Wad_GetTitleID(fp, header, &tid);
|
||||||
@ -294,31 +510,31 @@ s32 Wad_Install(FILE *fp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* WAD certificates */
|
/* WAD certificates */
|
||||||
ret = __Wad_ReadAlloc(fp, (void *)&p_certs, offset, header->certs_len);
|
ret = FSOPReadOpenFileA(fp, (void*)&p_certs, offset, header->certs_len);
|
||||||
if (ret >= 0)
|
if (ret != 1)
|
||||||
offset += round_up(header->certs_len, 64);
|
goto err;
|
||||||
else
|
else
|
||||||
goto err;
|
offset += round_up(header->certs_len, 64);
|
||||||
|
|
||||||
/* WAD crl */
|
/* WAD crl */
|
||||||
if (header->crl_len) {
|
if (header->crl_len) {
|
||||||
ret = __Wad_ReadAlloc(fp, (void *)&p_crl, offset, header->crl_len);
|
ret = FSOPReadOpenFileA(fp, (void*)&p_crl, offset, header->crl_len);
|
||||||
if (ret < 0)
|
if (ret != 1)
|
||||||
goto err;
|
goto err;
|
||||||
else
|
else
|
||||||
offset += round_up(header->crl_len, 64);
|
offset += round_up(header->crl_len, 64);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* WAD ticket */
|
/* WAD ticket */
|
||||||
ret = __Wad_ReadAlloc(fp, (void *)&p_tik, offset, header->tik_len);
|
ret = FSOPReadOpenFileA(fp, (void*)&p_tik, offset, header->tik_len);
|
||||||
if (ret < 0)
|
if (ret != 1)
|
||||||
goto err;
|
goto err;
|
||||||
else
|
else
|
||||||
offset += round_up(header->tik_len, 64);
|
offset += round_up(header->tik_len, 64);
|
||||||
|
|
||||||
/* WAD TMD */
|
/* WAD TMD */
|
||||||
ret = __Wad_ReadAlloc(fp, (void *)&p_tmd, offset, header->tmd_len);
|
ret = FSOPReadOpenFileA(fp, (void*)&p_tmd, offset, header->tmd_len);
|
||||||
if (ret < 0)
|
if (ret != 1)
|
||||||
goto err;
|
goto err;
|
||||||
else
|
else
|
||||||
offset += round_up(header->tmd_len, 64);
|
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(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");
|
printf("\n I won't install a stub System Menu IOS\n");
|
||||||
ret = -999;
|
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(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");
|
printf("\n I won't install a stub EULA IOS\n");
|
||||||
ret = -999;
|
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(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");
|
printf("\n I won't install a stub rgsel IOS\n");
|
||||||
ret = -999;
|
ret = -999;
|
||||||
@ -385,30 +601,36 @@ s32 Wad_Install(FILE *fp)
|
|||||||
|
|
||||||
if (tid == TITLE_ID(1, 2))
|
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;
|
ret = -999;
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
int i, ret = -1;
|
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;
|
ret = 1;
|
||||||
break;
|
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;
|
ret = -999;
|
||||||
goto err;
|
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");
|
printf("\n I won't install the wrong regions SM\n");
|
||||||
ret = -999;
|
ret = -999;
|
||||||
@ -424,6 +646,55 @@ skipChecks:
|
|||||||
goto err;
|
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 */
|
/* Fix ticket */
|
||||||
@ -479,8 +750,8 @@ skipChecks:
|
|||||||
size = BLOCK_SIZE;
|
size = BLOCK_SIZE;
|
||||||
|
|
||||||
/* Read data */
|
/* Read data */
|
||||||
ret = __Wad_ReadFile(fp, &wadBuffer, offset, size);
|
ret = FSOPReadOpenFile(fp, &wadBuffer, offset, size);
|
||||||
if (ret < 0)
|
if (ret != 1)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
/* Install data */
|
/* Install data */
|
||||||
@ -506,13 +777,106 @@ skipChecks:
|
|||||||
|
|
||||||
/* Finish title install */
|
/* Finish title install */
|
||||||
ret = ES_AddTitleFinish();
|
ret = ES_AddTitleFinish();
|
||||||
if (ret >= 0) {
|
if (ret >= 0)
|
||||||
|
{
|
||||||
printf(" OK!\n");
|
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;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
err:
|
err:
|
||||||
printf(" ERROR! (ret = %d)\n", ret);
|
printf("\n ERROR! (ret = %d)\n", ret);
|
||||||
|
|
||||||
/* Cancel install */
|
/* Cancel install */
|
||||||
ES_AddTitleCancel();
|
ES_AddTitleCancel();
|
||||||
@ -525,6 +889,9 @@ out:
|
|||||||
free(p_tik);
|
free(p_tik);
|
||||||
free(p_tmd);
|
free(p_tmd);
|
||||||
|
|
||||||
|
if (gForcedInstall)
|
||||||
|
return Wad_Install(fp);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -541,8 +908,9 @@ s32 Wad_Uninstall(FILE *fp)
|
|||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
|
|
||||||
/* WAD header */
|
/* WAD header */
|
||||||
ret = __Wad_ReadAlloc(fp, (void *)&header, 0, sizeof(wadHeader));
|
ret = FSOPReadOpenFileA(fp, (void*)&header, 0, sizeof(wadHeader));
|
||||||
if (ret < 0) {
|
if (ret != 1)
|
||||||
|
{
|
||||||
printf(" ERROR! (ret = %d)\n", ret);
|
printf(" ERROR! (ret = %d)\n", ret);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@ -592,32 +960,36 @@ s32 Wad_Uninstall(FILE *fp)
|
|||||||
goto out;
|
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')
|
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;
|
ret = -999;
|
||||||
goto out;
|
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");
|
printf("\n I won't uninstall the EULA\n");
|
||||||
ret = -999;
|
ret = -999;
|
||||||
goto out;
|
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");
|
printf("\n I won't uninstall rgsel\n");
|
||||||
ret = -999;
|
ret = -999;
|
||||||
goto out;
|
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");
|
printf("\n I won't uninstall the EULAs IOS\n");
|
||||||
ret = -999;
|
ret = -999;
|
||||||
goto out;
|
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");
|
printf("\n I won't uninstall the rgsel IOS\n");
|
||||||
ret = -999;
|
ret = -999;
|
||||||
|
@ -2,7 +2,9 @@
|
|||||||
#define _WAD_H_
|
#define _WAD_H_
|
||||||
|
|
||||||
/* Prototypes */
|
/* Prototypes */
|
||||||
s32 Wad_Install(FILE *);
|
s32 Wad_Install(FILE* fp);
|
||||||
s32 Wad_Uninstall(FILE *);
|
s32 Wad_Uninstall(FILE* fp);
|
||||||
|
s32 GetSysMenuRegion(u16* version, char* region);
|
||||||
|
const char* GetSysMenuRegionString(const char* region);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user