*Fixed crash when changing NAND emu path to USB

*Creating the missing NAND folders when needed (Allows the "Partial" Nand Emulation to work with no NAND at all on the drive)
This commit is contained in:
dimok321 2011-07-26 08:57:12 +00:00
parent 973d8b2005
commit 372717aaa0
12 changed files with 147 additions and 159 deletions

View File

@ -2,8 +2,8 @@
<app version="1">
<name> USB Loader GX</name>
<coder>USB Loader GX Team</coder>
<version>2.2 r1105</version>
<release_date>201107252212</release_date>
<version>2.2 r1106</version>
<release_date>201107260730</release_date>
<!-- // remove this line to enable arguments
<arguments>
<arg>--ios=250</arg>

View File

@ -287,7 +287,7 @@ int DeviceHandler::PathToDriveType(const char * path)
for(int i = SD; i < MAXDEVICES; i++)
{
if(strncmp(path, DeviceName[i], strlen(DeviceName[i])) == 0)
if(strncasecmp(path, DeviceName[i], strlen(DeviceName[i])) == 0)
return i;
}
@ -309,21 +309,21 @@ const char * DeviceHandler::GetFSName(int dev)
if(DeviceHandler::instance->usb1)
partCount1 += DeviceHandler::instance->usb1->GetPartitionCount();
if(dev-USB1 > partCount0 && DeviceHandler::instance->usb0)
if(dev-USB1 < partCount0 && DeviceHandler::instance->usb0)
return DeviceHandler::instance->usb0->GetFSName(dev-USB1);
else if(DeviceHandler::instance->usb1)
return DeviceHandler::instance->usb1->GetFSName(dev-USB1-partCount0);
}
return NULL;
return "";
}
int DeviceHandler::GetUSBFilesystemType(int partition)
int DeviceHandler::GetFilesystemType(int dev)
{
if(!instance)
return -1;
const char *FSName = GetUSBFSName(partition);
const char *FSName = GetFSName(dev);
if(!FSName) return -1;
if(strncmp(FSName, "WBFS", 4) == 0)
@ -384,20 +384,6 @@ int DeviceHandler::PartitionToPortPartition(int part)
return part;
}
const char *DeviceHandler::GetUSBFSName(int partition)
{
if(!instance)
return NULL;
const char * FSName = NULL;
PartitionHandle *handle = instance->GetUSBHandleFromPartition(partition);
if(handle)
FSName = handle->GetFSName(PartitionToPortPartition(partition));
return FSName;
}
PartitionHandle *DeviceHandler::GetUSBHandleFromPartition(int part) const
{
if(PartitionToUSBPort(part) == 0)

View File

@ -84,14 +84,13 @@ class DeviceHandler
PartitionHandle * GetUSBHandleFromPartition(int part) const;
static const DISC_INTERFACE *GetUSB0Interface() { return &__io_usbstorage2_port0; }
static const DISC_INTERFACE *GetUSB1Interface() { return &__io_usbstorage2_port1; }
static int GetUSBFilesystemType(int part);
static int PathToDriveType(const char * path);
static int GetFilesystemType(int dev);
static const char * GetFSName(int dev);
static int PathToDriveType(const char * path);
static const char * PathToFSName(const char * path) { return GetFSName(PathToDriveType(path)); };
static int PartitionToUSBPort(int part);
static u16 GetUSBPartitionCount();
static int PartitionToPortPartition(int part);
static const char *GetUSBFSName(int partition);
private:
DeviceHandler() : sd(0), gca(0), gcb(0), usb0(0), usb1(0) { };
~DeviceHandler();

View File

@ -30,6 +30,7 @@
#include "language/gettext.h"
#include "prompts/filebrowser.h"
#include "themes/CTheme.h"
#include "gecko.h"
CustomPathsSM::CustomPathsSM()
: SettingsMenu(tr("Custom Paths"), &GuiOptions, MENU_NONE)
@ -236,10 +237,16 @@ int CustomPathsSM::GetMenuInternal()
//! Settings: Nand Emu Path
else if (ret == ++Idx)
{
char oldPath[sizeof(Settings.NandEmuPath)];
snprintf(oldPath, sizeof(oldPath), Settings.NandEmuPath);
titleTxt->SetText(tr( "Nand Emu Path" ));
ChangePath(Settings.NandEmuPath, sizeof(Settings.NandEmuPath));
if(strncasecmp(DeviceHandler::PathToFSName(Settings.NandEmuPath), "FAT", 3) != 0)
WindowPrompt(tr("Warning:"), tr("Nand Emulation only works on FAT/FAT32 partitions!"), tr("OK"));
{
snprintf(Settings.NandEmuPath, sizeof(Settings.NandEmuPath), oldPath);
WindowPrompt(tr("Error:"), tr("Nand Emulation only works on FAT/FAT32 partitions!"), tr("OK"));
}
}
//! Global set back of the titleTxt after a change

View File

@ -174,7 +174,7 @@ int HardDriveSM::GetMenuInternal()
do
{
Settings.partition = (Settings.partition + 1) % DeviceHandler::GetUSBPartitionCount();
fs_type = DeviceHandler::GetUSBFilesystemType(Settings.partition);
fs_type = DeviceHandler::GetFilesystemType(USB1+Settings.partition);
}
while (!IsValidPartition(fs_type, ios) && --retries > 0);
@ -213,7 +213,7 @@ int HardDriveSM::GetMenuInternal()
{
if (++Settings.GameSplit >= GAMESPLIT_MAX)
{
if(DeviceHandler::GetUSBFilesystemType(Settings.partition) == PART_FS_FAT)
if(DeviceHandler::GetFilesystemType(USB1+Settings.partition) == PART_FS_FAT)
Settings.GameSplit = GAMESPLIT_2GB;
else
Settings.GameSplit = GAMESPLIT_NONE;
@ -249,7 +249,7 @@ int HardDriveSM::GetMenuInternal()
for(int i = 0; i < partCount; ++i)
{
ShowProgress(i, partCount);
if(DeviceHandler::GetUSBFilesystemType(i) == PART_FS_FAT)
if(DeviceHandler::GetFilesystemType(USB1+i) == PART_FS_FAT)
{
PartitionHandle *usb = DeviceHandler::Instance()->GetUSBHandleFromPartition(i);
if(!usb) continue;

View File

@ -26,7 +26,7 @@
#include "menu/menus.h"
#include "memory/memory.h"
#include "GameBooter.hpp"
#include "nand.h"
#include "NandEmu.h"
#include "SavePath.h"
#include "sys.h"

View File

@ -32,7 +32,7 @@ class GameList
int operator--(int i) { return operator--(); }
struct discHdr * GetCurrentSelected() const { return operator[](selectedGame); }
int GetPartitionNumber(const u8 *gameid) const;
int GetGameFS(const u8 *gameID) const { return DeviceHandler::Instance()->GetUSBFilesystemType(GetPartitionNumber(gameID)); }
int GetGameFS(const u8 *gameID) const { return DeviceHandler::Instance()->GetFilesystemType(USB1+GetPartitionNumber(gameID)); }
void RemovePartition(int part_num);
protected:
int InternalReadList(int part);

View File

@ -19,7 +19,7 @@ static int FindGamePartition()
// Loop through all WBFS partitions first to check them in case IOS249 Rev < 18
for(int i = 0; i < partCount; ++i)
{
if(DeviceHandler::GetUSBFilesystemType(i) != PART_FS_WBFS)
if(DeviceHandler::GetFilesystemType(USB1+i) != PART_FS_WBFS)
continue;
if (WBFS_OpenPart(i) == 0)
@ -36,9 +36,9 @@ static int FindGamePartition()
// Loop through FAT/NTFS/EXT partitions, and find the first partition with games on it (if there is one)
for(int i = 0; i < partCount; ++i)
{
if(DeviceHandler::GetUSBFilesystemType(i) != PART_FS_NTFS &&
DeviceHandler::GetUSBFilesystemType(i) != PART_FS_FAT &&
DeviceHandler::GetUSBFilesystemType(i) != PART_FS_EXT)
if(DeviceHandler::GetFilesystemType(USB1+i) != PART_FS_NTFS &&
DeviceHandler::GetFilesystemType(USB1+i) != PART_FS_FAT &&
DeviceHandler::GetFilesystemType(USB1+i) != PART_FS_EXT)
{
continue;
}
@ -79,9 +79,9 @@ static int PartitionChoice()
if(part_num >= 0)
{
if(IosLoader::IsWaninkokoIOS() && NandTitles.VersionOf(TITLE_ID(1, IOS_GetVersion())) < 18 &&
(DeviceHandler::GetUSBFilesystemType(part_num) == PART_FS_NTFS ||
DeviceHandler::GetUSBFilesystemType(part_num) == PART_FS_FAT ||
DeviceHandler::GetUSBFilesystemType(part_num) == PART_FS_EXT))
(DeviceHandler::GetFilesystemType(USB1+part_num) == PART_FS_NTFS ||
DeviceHandler::GetFilesystemType(USB1+part_num) == PART_FS_FAT ||
DeviceHandler::GetFilesystemType(USB1+part_num) == PART_FS_EXT))
{
WindowPrompt(tr("Warning:"), tr("You are trying to select a FAT32/NTFS/EXT partition with cIOS 249 Rev < 18. This is not supported. Continue on your own risk."), tr("OK"));
}

View File

@ -1,19 +1,29 @@
/*****************************************
* This code is from Mighty Channel 11
* which is based on the TriiForce source.
* Modifications by Dimok.
*****************************************/
#include <stdio.h>
#include <ogcsys.h>
#include <malloc.h>
#include <string.h>
#include "system/IosLoader.h"
#include "gecko.h"
#include "nand.h"
#include "NandEmu.h"
/* Buffer */
static const char fs[] ATTRIBUTE_ALIGN(32) = "/dev/fs";
static const char fat[] ATTRIBUTE_ALIGN(32) = "fat";
static u32 inbuf[8] ATTRIBUTE_ALIGN(32);
/* 'NAND Device' structure */
typedef struct {
/* Device name */
const char *name;
/* Mode value */
u32 mode;
/* Un/mount command */
u32 mountCmd;
u32 umountCmd;
} nandDevice;
static nandDevice ndevList[] =
{
@ -22,44 +32,43 @@ static nandDevice ndevList[] =
{ "USB 2.0 Mass Storage Device", 2, 0xF2, 0xF3 },
};
/* Buffer */
static u32 inbuf[8] ATTRIBUTE_ALIGN(32);
static const char fs[] ATTRIBUTE_ALIGN(32) = "/dev/fs";
static const char fat[] ATTRIBUTE_ALIGN(32) = "fat";
static int mounted = 0;
static int partition = 0;
static int fullmode = 0;
static char path[32] = "\0";
s32 Nand_Mount(nandDevice *dev)
static s32 Nand_Mount(nandDevice *dev)
{
s32 fd, ret;
u32 inlen = 0;
ioctlv *vector = NULL;
u32 *buffer = NULL;
int rev = IOS_GetRevision();
/* Open FAT module */
fd = IOS_Open(fat, 0);
if (fd < 0)
return fd;
/* Prepare vector */
if(rev >= 21 && rev < 30000)
{
// NOTE:
// The official cIOSX rev21 by Waninkoko ignores the partition argument
// and the nand is always expected to be on the 1st partition.
// However this way earlier d2x betas having revision 21 take in
// consideration the partition argument.
inlen = 1;
// NOTE:
// The official cIOSX rev21 by Waninkoko ignores the partition argument
// and the nand is always expected to be on the 1st partition.
// However this way earlier d2x betas having revision 21 take in
// consideration the partition argument.
inlen = 1;
/* Allocate memory */
buffer = (u32 *)memalign(32, sizeof(u32)*3);
/* Allocate memory */
buffer = (u32 *)memalign(32, sizeof(u32)*3);
/* Set vector pointer */
vector = (ioctlv *)buffer;
/* Set vector pointer */
vector = (ioctlv *)buffer;
buffer[0] = (u32)(buffer + 2);
buffer[1] = sizeof(u32);
buffer[2] = (u32)partition;
}
buffer[0] = (u32)(buffer + 2);
buffer[1] = sizeof(u32);
buffer[2] = (u32)partition;
/* Mount device */
ret = IOS_Ioctlv(fd, dev->mountCmd, inlen, 0, vector);
@ -75,8 +84,11 @@ s32 Nand_Mount(nandDevice *dev)
return ret;
}
s32 Nand_Unmount(nandDevice *dev)
static s32 Nand_Unmount(nandDevice *dev)
{
if(!IosLoader::IsD2X())
return -1;
s32 fd, ret;
// Open FAT module
@ -93,55 +105,37 @@ s32 Nand_Unmount(nandDevice *dev)
return ret;
}
s32 Nand_Enable(nandDevice *dev)
static s32 Nand_Enable(nandDevice *dev)
{
s32 fd, ret;
u32 *buffer = NULL;
int rev;
// Open /dev/fs
fd = IOS_Open(fs, 0);
if (fd < 0)
return fd;
rev = IOS_GetRevision();
// Set input buffer
if(rev >= 21 && rev < 30000 && dev->mode != 0)
{
//FULL NAND emulation since rev18
//needed for reading images on triiforce mrc folder using ISFS commands
inbuf[0] = dev->mode | fullmode;
}
else
{
inbuf[0] = dev->mode; //old method
}
//FULL NAND emulation since rev18
//needed for reading images on triiforce mrc folder using ISFS commands
inbuf[0] = dev->mode | fullmode;
// Enable NAND emulator
if(rev >= 21 && rev < 30000)
{
// NOTE:
// The official cIOSX rev21 by Waninkoko provides an undocumented feature
// to set nand path when mounting the device.
// This feature has been discovered during d2x development.
int pathlen = strlen(path)+1;
// NOTE:
// The official cIOSX rev21 by Waninkoko provides an undocumented feature
// to set nand path when mounting the device.
// This feature has been discovered during d2x development.
int pathlen = strlen(path)+1;
/* Allocate memory */
buffer = (u32 *)memalign(32, (sizeof(u32)*5)+pathlen);
/* Allocate memory */
buffer = (u32 *)memalign(32, (sizeof(u32)*5)+pathlen);
buffer[0] = (u32)(buffer + 4);
buffer[1] = sizeof(u32); // actually not used by cios
buffer[2] = (u32)(buffer + 5);
buffer[3] = pathlen; // actually not used by cios
buffer[4] = inbuf[0];
strcpy((char*)(buffer+5), path);
buffer[0] = (u32)(buffer + 4);
buffer[1] = sizeof(u32); // actually not used by cios
buffer[2] = (u32)(buffer + 5);
buffer[3] = pathlen; // actually not used by cios
buffer[4] = inbuf[0];
strcpy((char*)(buffer+5), path);
ret = IOS_Ioctlv(fd, 100, 2, 0, (ioctlv *)buffer);
}
else
{
ret = IOS_Ioctl(fd, 100, inbuf, sizeof(inbuf), NULL, 0);
}
ret = IOS_Ioctlv(fd, 100, 2, 0, (ioctlv *)buffer);
/* Free memory */
if(buffer != NULL)
@ -153,7 +147,7 @@ s32 Nand_Enable(nandDevice *dev)
return ret;
}
s32 Nand_Disable(void)
static s32 Nand_Disable(void)
{
s32 fd, ret;
@ -174,9 +168,11 @@ s32 Nand_Disable(void)
return ret;
}
s32 Enable_Emu(int selection)
{
if(!IosLoader::IsD2X())
return -1;
if(mounted != 0)
return -1;
@ -204,6 +200,9 @@ s32 Enable_Emu(int selection)
s32 Disable_Emu()
{
if(!IosLoader::IsD2X())
return -1;
if(mounted==0)
return 0;

View File

@ -0,0 +1,16 @@
#ifndef _NAND_EMU_H_
#define _NAND_EMU_H_
#define REAL_NAND 0
#define EMU_SD 1
#define EMU_USB 2
/* Prototypes */
s32 Enable_Emu(int selection);
s32 Disable_Emu();
void Set_Partition(int);
void Set_Path(const char*);
void Set_FullMode(int);
const char* Get_Path(void);
#endif

View File

@ -30,7 +30,6 @@
#include "FileOperations/fileops.h"
#include "gecko.h"
void CreateTitleTMD(const char *path, const struct discHdr *hdr)
{
wbfs_disc_t *disc = WBFS_OpenDisc((u8 *) hdr->id);
@ -64,22 +63,47 @@ void CreateTitleTMD(const char *path, const struct discHdr *hdr)
free(titleTMD);
}
void CreateSavePath(const struct discHdr *hdr)
static void CreateNandPath(const char *path)
{
char contentPath[512];
char dataPath[512];
snprintf(contentPath, sizeof(contentPath), "%s/title/00010000/%02x%02x%02x%02x/content", Settings.NandEmuPath, hdr->id[0], hdr->id[1], hdr->id[2], hdr->id[3]);
snprintf(dataPath, sizeof(dataPath), "%s/title/00010000/%02x%02x%02x%02x/data", Settings.NandEmuPath, hdr->id[0], hdr->id[1], hdr->id[2], hdr->id[3]);
if(CheckFile(contentPath) && CheckFile(dataPath))
if(CheckFile(path))
return;
gprintf("Creating Save Path: %s\n", contentPath);
gprintf("Creating Save Path: %s\n", dataPath);
CreateSubfolder(contentPath);
CreateSubfolder(dataPath);
strcat(contentPath, "/title.tmd");
CreateTitleTMD(contentPath, hdr);
gprintf("Creating Nand Path: %s\n", path);
CreateSubfolder(path);
}
void CreateSavePath(const struct discHdr *hdr)
{
char nandPath[512];
snprintf(nandPath, sizeof(nandPath), "%s/import", Settings.NandEmuPath);
CreateNandPath(nandPath);
snprintf(nandPath, sizeof(nandPath), "%s/meta", Settings.NandEmuPath);
CreateNandPath(nandPath);
snprintf(nandPath, sizeof(nandPath), "%s/shared1", Settings.NandEmuPath);
CreateNandPath(nandPath);
snprintf(nandPath, sizeof(nandPath), "%s/shared2", Settings.NandEmuPath);
CreateNandPath(nandPath);
snprintf(nandPath, sizeof(nandPath), "%s/sys", Settings.NandEmuPath);
CreateNandPath(nandPath);
snprintf(nandPath, sizeof(nandPath), "%s/ticket", Settings.NandEmuPath);
CreateNandPath(nandPath);
snprintf(nandPath, sizeof(nandPath), "%s/tmp", Settings.NandEmuPath);
CreateNandPath(nandPath);
snprintf(nandPath, sizeof(nandPath), "%s/title/00010000/%02x%02x%02x%02x/data", Settings.NandEmuPath, hdr->id[0], hdr->id[1], hdr->id[2], hdr->id[3]);
CreateNandPath(nandPath);
snprintf(nandPath, sizeof(nandPath), "%s/title/00010000/%02x%02x%02x%02x/content", Settings.NandEmuPath, hdr->id[0], hdr->id[1], hdr->id[2], hdr->id[3]);
CreateNandPath(nandPath);
strcat(nandPath, "/title.tmd");
if(!CheckFile(nandPath))
CreateTitleTMD(nandPath, hdr);
}

View File

@ -1,43 +0,0 @@
#ifndef _NAND_H_
#define _NAND_H_
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/* 'NAND Device' structure */
typedef struct {
/* Device name */
char *name;
/* Mode value */
u32 mode;
/* Un/mount command */
u32 mountCmd;
u32 umountCmd;
} nandDevice;
#define REAL_NAND 0
#define EMU_SD 1
#define EMU_USB 2
/* Prototypes */
s32 Nand_Mount(nandDevice *);
s32 Nand_Unmount(nandDevice *);
s32 Nand_Enable(nandDevice *);
s32 Nand_Disable(void);
s32 Enable_Emu(int selection);
s32 Disable_Emu();
void Set_Partition(int);
void Set_Path(const char*);
void Set_FullMode(int);
const char* Get_Path(void);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif