mirror of
https://github.com/Fledge68/WiiFlow_Lite.git
synced 2024-12-25 03:11:58 +01:00
-lets use the old gui_sound.cpp, because we shouldnt force set
the memory we use for them, not that we get problems -added debug prints about how much mem left before and after cleanup -updated devicehandler, partition handler and usb code to the latest usb loader gx one, should give more compatility and port 1 support (not enabled yet)
This commit is contained in:
parent
71e0d1e425
commit
5640028b17
@ -23,7 +23,7 @@
|
|||||||
*
|
*
|
||||||
* for WiiXplorer 2010
|
* for WiiXplorer 2010
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
#include <malloc.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <ogc/mutex.h>
|
#include <ogc/mutex.h>
|
||||||
@ -42,7 +42,6 @@ extern const DISC_INTERFACE __io_sdhc;
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
DeviceHandler * DeviceHandler::instance = NULL;
|
DeviceHandler * DeviceHandler::instance = NULL;
|
||||||
unsigned int DeviceHandler::watchdog_timeout = 10;
|
|
||||||
|
|
||||||
DeviceHandler::~DeviceHandler()
|
DeviceHandler::~DeviceHandler()
|
||||||
{
|
{
|
||||||
@ -52,14 +51,18 @@ DeviceHandler::~DeviceHandler()
|
|||||||
DeviceHandler * DeviceHandler::Instance()
|
DeviceHandler * DeviceHandler::Instance()
|
||||||
{
|
{
|
||||||
if (instance == NULL)
|
if (instance == NULL)
|
||||||
|
{
|
||||||
instance = new DeviceHandler();
|
instance = new DeviceHandler();
|
||||||
|
}
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DeviceHandler::DestroyInstance()
|
void DeviceHandler::DestroyInstance()
|
||||||
{
|
{
|
||||||
if(instance) delete instance;
|
if(instance)
|
||||||
|
{
|
||||||
|
delete instance;
|
||||||
|
}
|
||||||
instance = NULL;
|
instance = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -67,38 +70,39 @@ bool DeviceHandler::MountAll()
|
|||||||
{
|
{
|
||||||
bool result = false;
|
bool result = false;
|
||||||
|
|
||||||
for(u32 i = SD; i <= USB8; i++)
|
for(u32 i = SD; i < MAXDEVICES; i++)
|
||||||
if(Mount(i)) result = true;
|
{
|
||||||
|
if(Mount(i))
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DeviceHandler::UnMountAll()
|
void DeviceHandler::UnMountAll()
|
||||||
{
|
{
|
||||||
for(u32 i = SD; i <= GCSDB; i++)
|
for(u32 i = SD; i < MAXDEVICES; i++)
|
||||||
UnMount(i);
|
UnMount(i);
|
||||||
|
|
||||||
if(sd) delete sd;
|
if(sd)
|
||||||
if(usb) delete usb;
|
delete sd;
|
||||||
if(gca) delete gca;
|
if(usb0)
|
||||||
if(gcb) delete gca;
|
delete usb0;
|
||||||
|
if(usb1)
|
||||||
|
delete usb1;
|
||||||
|
|
||||||
sd = NULL;
|
sd = NULL;
|
||||||
usb = NULL;
|
usb0 = NULL;
|
||||||
gca = NULL;
|
usb1 = NULL;
|
||||||
gcb = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DeviceHandler::Mount(int dev)
|
bool DeviceHandler::Mount(int dev)
|
||||||
{
|
{
|
||||||
if(dev == SD)
|
if(dev == SD)
|
||||||
return MountSD();
|
return MountSD();
|
||||||
|
|
||||||
else if(dev >= USB1 && dev <= USB8)
|
else if(dev >= USB1 && dev <= USB8)
|
||||||
return MountUSB(dev-USB1);
|
return MountUSB(dev-USB1);
|
||||||
else if(dev == GCSDA)
|
|
||||||
return MountGCA();
|
|
||||||
else if(dev == GCSDB)
|
|
||||||
return MountGCB();
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -107,12 +111,14 @@ bool DeviceHandler::IsInserted(int dev)
|
|||||||
{
|
{
|
||||||
if(dev == SD)
|
if(dev == SD)
|
||||||
return SD_Inserted() && sd->IsMounted(0);
|
return SD_Inserted() && sd->IsMounted(0);
|
||||||
|
|
||||||
else if(dev >= USB1 && dev <= USB8)
|
else if(dev >= USB1 && dev <= USB8)
|
||||||
return USB_Inserted() && usb->IsMounted(dev-USB1);
|
{
|
||||||
else if(dev == GCSDA)
|
int portPart = PartitionToPortPartition(dev-USB1);
|
||||||
return GCA_Inserted() && gca->IsMounted(0);
|
PartitionHandle *usb = instance->GetUSBHandleFromPartition(dev-USB1);
|
||||||
else if(dev == GCSDB)
|
if(usb)
|
||||||
return GCB_Inserted() && gcb->IsMounted(0);
|
return usb->IsMounted(portPart);
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -121,12 +127,9 @@ void DeviceHandler::UnMount(int dev)
|
|||||||
{
|
{
|
||||||
if(dev == SD)
|
if(dev == SD)
|
||||||
UnMountSD();
|
UnMountSD();
|
||||||
|
|
||||||
else if(dev >= USB1 && dev <= USB8)
|
else if(dev >= USB1 && dev <= USB8)
|
||||||
UnMountUSB(dev-USB1);
|
UnMountUSB(dev-USB1);
|
||||||
else if(dev == GCSDA)
|
|
||||||
UnMountGCA();
|
|
||||||
else if(dev == GCSDB)
|
|
||||||
UnMountGCB();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DeviceHandler::MountSD()
|
bool DeviceHandler::MountSD()
|
||||||
@ -146,114 +149,121 @@ bool DeviceHandler::MountSD()
|
|||||||
}
|
}
|
||||||
|
|
||||||
//! Mount only one SD Partition
|
//! Mount only one SD Partition
|
||||||
return sd->Mount(0, DeviceName[SD]);
|
return sd->Mount(0, DeviceName[SD], true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool DeviceHandler::MountUSB(int pos)
|
bool DeviceHandler::MountUSB(int pos)
|
||||||
{
|
{
|
||||||
if(!usb) usb = new PartitionHandle(&__io_usbstorage);
|
if(!usb0 && !usb1)
|
||||||
|
|
||||||
if(usb->GetPartitionCount() < 1)
|
|
||||||
{
|
|
||||||
delete usb;
|
|
||||||
usb = NULL;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set the watchdog
|
|
||||||
InternalSetWatchdog(watchdog_timeout);
|
|
||||||
|
|
||||||
if(pos >= usb->GetPartitionCount())
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return usb->Mount(pos, DeviceName[USB1+pos]);
|
if(pos >= GetUSBPartitionCount())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
int portPart = PartitionToPortPartition(pos);
|
||||||
|
|
||||||
|
if(PartitionToUSBPort(pos) == 0 && usb0)
|
||||||
|
return usb0->Mount(portPart, DeviceName[USB1+pos]);
|
||||||
|
else if(usb1)
|
||||||
|
return usb1->Mount(portPart, DeviceName[USB1+pos]);
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DeviceHandler::MountAllUSB()
|
bool DeviceHandler::MountAllUSB()
|
||||||
{
|
{
|
||||||
if(!usb) usb = new PartitionHandle(&__io_usbstorage);
|
if(!usb0)
|
||||||
|
usb0 = new PartitionHandle(GetUSB0Interface());
|
||||||
|
//if(!usb1 && (Settings.USBPort == 1 || Settings.USBPort == 2))
|
||||||
|
//usb1 = new PartitionHandle(GetUSB1Interface());
|
||||||
|
|
||||||
|
if(usb0 && usb0->GetPartitionCount() < 1)
|
||||||
|
{
|
||||||
|
delete usb0;
|
||||||
|
usb0 = NULL;
|
||||||
|
}
|
||||||
|
if(usb1 && usb1->GetPartitionCount() < 1)
|
||||||
|
{
|
||||||
|
delete usb1;
|
||||||
|
usb1 = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
bool result = false;
|
bool result = false;
|
||||||
|
int partCount = GetUSBPartitionCount();
|
||||||
|
|
||||||
for(int i = 0; i < usb->GetPartitionCount(); i++)
|
for(int i = 0; i < partCount; i++)
|
||||||
|
{
|
||||||
if(MountUSB(i))
|
if(MountUSB(i))
|
||||||
result = true;
|
result = true;
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DeviceHandler::MountGCA()
|
bool DeviceHandler::MountUSBPort1()
|
||||||
{
|
{
|
||||||
if(!gca) gca = new PartitionHandle(&__io_gcsda);
|
if(!usb1)// && (Settings.USBPort == 1 || Settings.USBPort == 2))
|
||||||
|
usb1 = new PartitionHandle(GetUSB1Interface());
|
||||||
|
|
||||||
if(gca->GetPartitionCount() < 1)
|
if(usb1 && usb1->GetPartitionCount() < 1)
|
||||||
{
|
{
|
||||||
delete gca;
|
delete usb1;
|
||||||
gca = NULL;
|
usb1 = NULL;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Mount only one Partition
|
bool result = false;
|
||||||
return gca->Mount(0, DeviceName[GCSDA]);
|
int partCount = GetUSBPartitionCount();
|
||||||
|
int partCount0 = 0;
|
||||||
|
if(usb0)
|
||||||
|
partCount0 = usb0->GetPartitionCount();
|
||||||
|
|
||||||
|
for(int i = partCount0; i < partCount; i++)
|
||||||
|
{
|
||||||
|
if(MountUSB(i))
|
||||||
|
result = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DeviceHandler::MountGCB()
|
return result;
|
||||||
{
|
|
||||||
if(!gcb) gcb = new PartitionHandle(&__io_gcsdb);
|
|
||||||
|
|
||||||
if(gcb->GetPartitionCount() < 1)
|
|
||||||
{
|
|
||||||
delete gcb;
|
|
||||||
gcb = NULL;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! Mount only one Partition
|
|
||||||
return gcb->Mount(0, DeviceName[GCSDB]);;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DeviceHandler::UnMountUSB(int pos)
|
void DeviceHandler::UnMountUSB(int pos)
|
||||||
{
|
{
|
||||||
if(!usb) return;
|
if(pos >= GetUSBPartitionCount())
|
||||||
|
|
||||||
if(pos >= usb->GetPartitionCount())
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
usb->UnMount(pos);
|
int portPart = PartitionToPortPartition(pos);
|
||||||
|
|
||||||
|
if(PartitionToUSBPort(pos) == 0 && usb0)
|
||||||
|
return usb0->UnMount(portPart);
|
||||||
|
else if(usb1)
|
||||||
|
return usb1->UnMount(portPart);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DeviceHandler::UnMountAllUSB()
|
void DeviceHandler::UnMountAllUSB()
|
||||||
{
|
{
|
||||||
if(!usb) return;
|
int partCount = GetUSBPartitionCount();
|
||||||
|
|
||||||
for(int i = 0; i < usb->GetPartitionCount(); i++)
|
for(int i = 0; i < partCount; i++)
|
||||||
usb->UnMount(i);
|
UnMountUSB(i);
|
||||||
|
|
||||||
delete usb;
|
delete usb0;
|
||||||
usb = NULL;
|
usb0 = NULL;
|
||||||
}
|
delete usb1;
|
||||||
|
usb1 = NULL;
|
||||||
bool DeviceHandler::InternalSetWatchdog(unsigned int timeout)
|
|
||||||
{
|
|
||||||
if (Instance()->USB_Inserted())
|
|
||||||
return USBStorage_SetWatchdog(timeout) == 0;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DeviceHandler::SetWatchdog(unsigned int timeout)
|
|
||||||
{
|
|
||||||
watchdog_timeout = timeout;
|
|
||||||
return InternalSetWatchdog(timeout);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int DeviceHandler::PathToDriveType(const char * path)
|
int DeviceHandler::PathToDriveType(const char * path)
|
||||||
{
|
{
|
||||||
if(!path) return -1;
|
if(!path)
|
||||||
|
return -1;
|
||||||
|
|
||||||
for(int i = SD; i <= GCSDB; i++)
|
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;
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -261,61 +271,71 @@ int DeviceHandler::PathToDriveType(const char * path)
|
|||||||
const char * DeviceHandler::GetFSName(int dev)
|
const char * DeviceHandler::GetFSName(int dev)
|
||||||
{
|
{
|
||||||
if(dev == SD && DeviceHandler::instance->sd)
|
if(dev == SD && DeviceHandler::instance->sd)
|
||||||
|
{
|
||||||
return DeviceHandler::instance->sd->GetFSName(0);
|
return DeviceHandler::instance->sd->GetFSName(0);
|
||||||
else if(dev >= USB1 && dev <= USB8 && DeviceHandler::instance->usb)
|
}
|
||||||
return DeviceHandler::instance->usb->GetFSName(dev-USB1);
|
else if(dev >= USB1 && dev <= USB8)
|
||||||
else if(dev == GCSDA && DeviceHandler::instance->gca)
|
{
|
||||||
return DeviceHandler::instance->gca->GetFSName(0);
|
int partCount0 = 0;
|
||||||
else if(dev == GCSDB && DeviceHandler::instance->gcb)
|
int partCount1 = 0;
|
||||||
return DeviceHandler::instance->gcb->GetFSName(0);
|
if(DeviceHandler::instance->usb0)
|
||||||
|
partCount0 += DeviceHandler::instance->usb0->GetPartitionCount();
|
||||||
|
if(DeviceHandler::instance->usb1)
|
||||||
|
partCount1 += DeviceHandler::instance->usb1->GetPartitionCount();
|
||||||
|
|
||||||
return NULL;
|
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 "";
|
||||||
}
|
}
|
||||||
|
|
||||||
int DeviceHandler::GetFSType(int dev)
|
int DeviceHandler::GetFSType(int dev)
|
||||||
{
|
{
|
||||||
const char *name = GetFSName(dev);
|
if(!instance)
|
||||||
if(!name) return -1;
|
return -1;
|
||||||
|
|
||||||
if (strncasecmp(name, "WBFS", 4) == 0)
|
const char *FSName = GetFSName(dev);
|
||||||
|
if(!FSName) return -1;
|
||||||
|
|
||||||
|
if(strncmp(FSName, "WBFS", 4) == 0)
|
||||||
return PART_FS_WBFS;
|
return PART_FS_WBFS;
|
||||||
else if (strncasecmp(name, "FAT", 3) == 0)
|
else if(strncmp(FSName, "FAT", 3) == 0)
|
||||||
return PART_FS_FAT;
|
return PART_FS_FAT;
|
||||||
else if (strncasecmp(name, "NTFS", 4) == 0)
|
else if(strncmp(FSName, "NTFS", 4) == 0)
|
||||||
return PART_FS_NTFS;
|
return PART_FS_NTFS;
|
||||||
else if (strncasecmp(name, "LINUX", 5) == 0)
|
else if(strncmp(FSName, "LINUX", 4) == 0)
|
||||||
return PART_FS_EXT;
|
return PART_FS_EXT;
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
s16 DeviceHandler::GetMountedCount(int dev)
|
|
||||||
{
|
|
||||||
if(dev == SD && DeviceHandler::instance->sd && IsInserted(SD))
|
|
||||||
return 1;
|
|
||||||
else if(dev >= USB1 && dev <= USB8 && DeviceHandler::instance->usb)
|
|
||||||
for(int i = 0; i < usb->GetPartitionCount(); i++)
|
|
||||||
{
|
|
||||||
if(!IsInserted(i)) return i;
|
|
||||||
}
|
|
||||||
else if(dev == GCSDA && DeviceHandler::instance->gca && IsInserted(GCSDA))
|
|
||||||
return 1;
|
|
||||||
else if(dev == GCSDB && DeviceHandler::instance->gcb && IsInserted(GCSDB))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
return -1;
|
u16 DeviceHandler::GetUSBPartitionCount()
|
||||||
|
{
|
||||||
|
if(!instance)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
u16 partCount0 = 0;
|
||||||
|
u16 partCount1 = 0;
|
||||||
|
if(instance->usb0)
|
||||||
|
partCount0 = instance->usb0->GetPartitionCount();
|
||||||
|
if(instance->usb1)
|
||||||
|
partCount1 = instance->usb1->GetPartitionCount();
|
||||||
|
|
||||||
|
return partCount0+partCount1;
|
||||||
}
|
}
|
||||||
|
|
||||||
wbfs_t * DeviceHandler::GetWbfsHandle(int dev)
|
wbfs_t * DeviceHandler::GetWbfsHandle(int dev)
|
||||||
{
|
{
|
||||||
if(dev == SD && DeviceHandler::instance->sd)
|
if(dev == SD && DeviceHandler::instance->sd)
|
||||||
return DeviceHandler::instance->sd->GetWbfsHandle(0);
|
return DeviceHandler::instance->sd->GetWbfsHandle(0);
|
||||||
else if(dev >= USB1 && dev <= USB8 && DeviceHandler::instance->usb)
|
else if(dev >= USB1 && dev <= USB8 && DeviceHandler::instance->usb0)
|
||||||
return DeviceHandler::instance->usb->GetWbfsHandle(dev-USB1);
|
return DeviceHandler::instance->usb0->GetWbfsHandle(dev-USB1);
|
||||||
else if(dev == GCSDA && DeviceHandler::instance->gca)
|
else if(dev >= USB1 && dev <= USB8 && DeviceHandler::instance->usb1)
|
||||||
return DeviceHandler::instance->gca->GetWbfsHandle(0);
|
return DeviceHandler::instance->usb1->GetWbfsHandle(dev-USB1);
|
||||||
else if(dev == GCSDB && DeviceHandler::instance->gcb)
|
|
||||||
return DeviceHandler::instance->gcb->GetWbfsHandle(0);
|
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -331,13 +351,48 @@ s32 DeviceHandler::Open_WBFS(int dev)
|
|||||||
else if(dev >= USB1 && dev <= USB8 && IsInserted(dev))
|
else if(dev >= USB1 && dev <= USB8 && IsInserted(dev))
|
||||||
{
|
{
|
||||||
part_idx = dev;
|
part_idx = dev;
|
||||||
part_lba = Instance()->usb->GetLBAStart(dev - USB1);
|
part_lba = Instance()->usb0->GetLBAStart(dev - USB1);
|
||||||
}
|
}
|
||||||
else if(dev == GCSDA && IsInserted(dev))
|
else
|
||||||
part_lba = Instance()->gca->GetLBAStart(dev);
|
return -1;
|
||||||
else if(dev == GCSDB && IsInserted(dev))
|
|
||||||
part_lba = Instance()->gcb->GetLBAStart(dev);
|
|
||||||
else return -1;
|
|
||||||
|
|
||||||
return WBFS_Init(GetWbfsHandle(dev), part_fs, part_idx, part_lba, partition, dev);
|
return WBFS_Init(GetWbfsHandle(dev), part_fs, part_idx, part_lba, partition, dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int DeviceHandler::PartitionToUSBPort(int part)
|
||||||
|
{
|
||||||
|
if(!DeviceHandler::instance)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
u16 partCount0 = 0;
|
||||||
|
if(DeviceHandler::instance->usb0)
|
||||||
|
partCount0 = instance->usb0->GetPartitionCount();
|
||||||
|
|
||||||
|
if(!instance->usb0 || part >= partCount0)
|
||||||
|
return 1;
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int DeviceHandler::PartitionToPortPartition(int part)
|
||||||
|
{
|
||||||
|
if(!DeviceHandler::instance)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
u16 partCount0 = 0;
|
||||||
|
if(instance->usb0)
|
||||||
|
partCount0 = instance->usb0->GetPartitionCount();
|
||||||
|
|
||||||
|
if(!instance->usb0 || part >= partCount0)
|
||||||
|
return part-partCount0;
|
||||||
|
else
|
||||||
|
return part;
|
||||||
|
}
|
||||||
|
|
||||||
|
PartitionHandle *DeviceHandler::GetUSBHandleFromPartition(int part) const
|
||||||
|
{
|
||||||
|
if(PartitionToUSBPort(part) == 0)
|
||||||
|
return usb0;
|
||||||
|
else
|
||||||
|
return usb1;
|
||||||
|
}
|
||||||
|
@ -27,7 +27,12 @@
|
|||||||
#define DEVICE_HANDLER_HPP_
|
#define DEVICE_HANDLER_HPP_
|
||||||
|
|
||||||
#include "PartitionHandle.h"
|
#include "PartitionHandle.h"
|
||||||
|
#include "usbstorage.h"
|
||||||
|
#include "libwbfs/libwbfs.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* libogc device names.
|
||||||
|
*/
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
SD = 0,
|
SD = 0,
|
||||||
@ -39,12 +44,13 @@ enum
|
|||||||
USB6,
|
USB6,
|
||||||
USB7,
|
USB7,
|
||||||
USB8,
|
USB8,
|
||||||
GCSDA,
|
|
||||||
GCSDB,
|
|
||||||
MAXDEVICES
|
MAXDEVICES
|
||||||
};
|
};
|
||||||
|
|
||||||
const char DeviceName[MAXDEVICES][6] =
|
/**
|
||||||
|
* libogc device names.
|
||||||
|
*/
|
||||||
|
const char DeviceName[MAXDEVICES][8] =
|
||||||
{
|
{
|
||||||
"sd",
|
"sd",
|
||||||
"usb1",
|
"usb1",
|
||||||
@ -55,8 +61,6 @@ const char DeviceName[MAXDEVICES][6] =
|
|||||||
"usb6",
|
"usb6",
|
||||||
"usb7",
|
"usb7",
|
||||||
"usb8",
|
"usb8",
|
||||||
"gca",
|
|
||||||
"gcb",
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class DeviceHandler
|
class DeviceHandler
|
||||||
@ -73,49 +77,46 @@ class DeviceHandler
|
|||||||
|
|
||||||
//! Individual Mounts/UnMounts...
|
//! Individual Mounts/UnMounts...
|
||||||
bool MountSD();
|
bool MountSD();
|
||||||
bool MountUSB(int part);
|
|
||||||
bool MountAllUSB();
|
bool MountAllUSB();
|
||||||
bool MountGCA();
|
bool MountUSBPort1();
|
||||||
bool MountGCB();
|
|
||||||
|
|
||||||
bool SD_Inserted() { if(sd) return sd->IsInserted(); return false; };
|
bool SD_Inserted() { if(sd) return sd->IsInserted(); return false; }
|
||||||
bool USB_Inserted() { if(usb) return usb->IsInserted(); return false; };
|
bool USB0_Inserted() { if(usb0) return usb0->IsInserted(); return false; }
|
||||||
bool GCA_Inserted() { if(gca) return gca->IsInserted(); return false; };
|
bool USB1_Inserted() { if(usb1) return usb1->IsInserted(); return false; }
|
||||||
bool GCB_Inserted() { if(gcb) return gcb->IsInserted(); return false; };
|
|
||||||
|
|
||||||
void UnMountSD() { if(sd) delete sd; sd = NULL; };
|
void UnMountSD() { if(sd) delete sd; sd = NULL; }
|
||||||
void UnMountUSB(int pos);
|
void UnMountUSB(int pos);
|
||||||
void UnMountAllUSB();
|
void UnMountAllUSB();
|
||||||
void UnMountGCA() { if(gca) delete gca; gca = NULL; };
|
|
||||||
void UnMountGCB() { if(gcb) delete gcb; gcb = NULL; };
|
|
||||||
|
|
||||||
const PartitionHandle * GetSDHandle() { return sd; };
|
PartitionHandle * GetSDHandle() const { return sd; }
|
||||||
const PartitionHandle * GetUSBHandle() { return usb; };
|
PartitionHandle * GetUSB0Handle() const { return usb0; }
|
||||||
const PartitionHandle * GetGCAHandle() { return gca; };
|
PartitionHandle * GetUSB1Handle() const { return usb1; }
|
||||||
const PartitionHandle * GetGCBHandle() { return gcb; };
|
|
||||||
|
PartitionHandle * GetUSBHandleFromPartition(int part) const;
|
||||||
|
static const DISC_INTERFACE *GetUSB0Interface() { return &__io_usbstorage2_port0; }
|
||||||
|
static const DISC_INTERFACE *GetUSB1Interface() { return &__io_usbstorage2_port1; }
|
||||||
|
|
||||||
static bool SetWatchdog(unsigned int timeout);
|
|
||||||
static int PathToDriveType(const char * path);
|
static int PathToDriveType(const char * path);
|
||||||
static const char * GetFSName(int dev);
|
static const char * GetFSName(int dev);
|
||||||
static int GetFSType(int dev);
|
static int GetFSType(int dev);
|
||||||
s16 GetMountedCount(int dev);
|
static u16 GetUSBPartitionCount();
|
||||||
static const char * PathToFSName(const char * path) { return GetFSName(PathToDriveType(path)); };
|
static const char * PathToFSName(const char * path) { return GetFSName(PathToDriveType(path)); }
|
||||||
static wbfs_t *GetWbfsHandle(int dev);
|
static wbfs_t *GetWbfsHandle(int dev);
|
||||||
//static u32 GetLBAStart(int dev);
|
|
||||||
s32 Open_WBFS(int dev);
|
s32 Open_WBFS(int dev);
|
||||||
|
static int PartitionToUSBPort(int part);
|
||||||
|
static int PartitionToPortPartition(int part);
|
||||||
private:
|
private:
|
||||||
DeviceHandler() : sd(0), usb(0), gca(0), gcb(0) { };
|
DeviceHandler() : sd(0), gca(0), gcb(0), usb0(0), usb1(0) { }
|
||||||
~DeviceHandler();
|
~DeviceHandler();
|
||||||
static bool InternalSetWatchdog(unsigned int timeout);
|
bool MountUSB(int part);
|
||||||
|
|
||||||
static DeviceHandler *instance;
|
static DeviceHandler *instance;
|
||||||
static unsigned int watchdog_timeout;
|
|
||||||
|
|
||||||
PartitionHandle * sd;
|
PartitionHandle * sd;
|
||||||
PartitionHandle * usb;
|
|
||||||
PartitionHandle * gca;
|
PartitionHandle * gca;
|
||||||
PartitionHandle * gcb;
|
PartitionHandle * gcb;
|
||||||
|
PartitionHandle * usb0;
|
||||||
|
PartitionHandle * usb1;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Copyright (C) 2010
|
* Copyright (C) 2010
|
||||||
* by Dimok
|
* by Dimok
|
||||||
* modified for Debugging, GPT, WBFS, and EXT by Miigotu
|
|
||||||
*
|
*
|
||||||
* This software is provided 'as-is', without any express or implied
|
* This software is provided 'as-is', without any express or implied
|
||||||
* warranty. In no event will the authors be held liable for any
|
* warranty. In no event will the authors be held liable for any
|
||||||
@ -22,8 +21,7 @@
|
|||||||
* 3. This notice may not be removed or altered from any source
|
* 3. This notice may not be removed or altered from any source
|
||||||
* distribution.
|
* distribution.
|
||||||
*
|
*
|
||||||
* By Dimok for WiiXplorer 2010
|
* for WiiXplorer 2010
|
||||||
* By Miigotu for WiiFlow 2010
|
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
#include <gccore.h>
|
#include <gccore.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@ -47,18 +45,21 @@ extern const DISC_INTERFACE __io_sdhc;
|
|||||||
|
|
||||||
#define PARTITION_TYPE_DOS33_EXTENDED 0x05 /* DOS 3.3+ extended partition */
|
#define PARTITION_TYPE_DOS33_EXTENDED 0x05 /* DOS 3.3+ extended partition */
|
||||||
#define PARTITION_TYPE_WIN95_EXTENDED 0x0F /* Windows 95 extended partition */
|
#define PARTITION_TYPE_WIN95_EXTENDED 0x0F /* Windows 95 extended partition */
|
||||||
#define PARTITION_TYPE_GPT_TABLE 0xEE /* New Standard */
|
|
||||||
|
//! libfat stuff
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
sec_t FindFirstValidPartition(const DISC_INTERFACE* disc);
|
||||||
|
}
|
||||||
|
|
||||||
#define CACHE 32
|
#define CACHE 32
|
||||||
#define SECTORS 64
|
#define SECTORS 64
|
||||||
|
|
||||||
extern u32 sector_size;
|
|
||||||
|
|
||||||
static inline const char * PartFromType(int type)
|
static inline const char * PartFromType(int type)
|
||||||
{
|
{
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case 0x00: return "Unused"; //Or WBFS
|
case 0x00: return "Unused";
|
||||||
case 0x01: return "FAT12";
|
case 0x01: return "FAT12";
|
||||||
case 0x04: return "FAT16";
|
case 0x04: return "FAT16";
|
||||||
case 0x05: return "Extended";
|
case 0x05: return "Extended";
|
||||||
@ -74,22 +75,25 @@ static inline const char * PartFromType(int type)
|
|||||||
case 0xa8: return "OSX";
|
case 0xa8: return "OSX";
|
||||||
case 0xab: return "OSXBT";
|
case 0xab: return "OSXBT";
|
||||||
case 0xaf: return "OSXHF";
|
case 0xaf: return "OSXHF";
|
||||||
|
case 0xbf: return "WBFS";
|
||||||
case 0xe8: return "LUKS";
|
case 0xe8: return "LUKS";
|
||||||
case 0xee: return "GPT";
|
|
||||||
default: return "Unknown";
|
default: return "Unknown";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PartitionHandle::PartitionHandle(const DISC_INTERFACE *discio)
|
PartitionHandle::PartitionHandle(const DISC_INTERFACE *discio)
|
||||||
|
: interface(discio)
|
||||||
{
|
{
|
||||||
interface = discio;
|
|
||||||
|
|
||||||
// Sanity check
|
// Sanity check
|
||||||
if(!interface) return;
|
if (!interface)
|
||||||
|
return;
|
||||||
|
|
||||||
// Start the device and check that it is inserted
|
// Start the device and check that it is inserted
|
||||||
if(!interface->startup()) return;
|
if (!interface->startup())
|
||||||
if(!interface->isInserted()) return;
|
return;
|
||||||
|
|
||||||
|
if (!interface->isInserted())
|
||||||
|
return;
|
||||||
|
|
||||||
FindPartitions();
|
FindPartitions();
|
||||||
}
|
}
|
||||||
@ -114,42 +118,71 @@ bool PartitionHandle::IsMounted(int pos)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PartitionHandle::Mount(int pos, const char * name)
|
bool PartitionHandle::Mount(int pos, const char * name, bool forceFAT)
|
||||||
{
|
{
|
||||||
if(!valid(pos)) return false;
|
if(!valid(pos))
|
||||||
if(!name) return false;
|
return false;
|
||||||
|
|
||||||
|
if(!name)
|
||||||
|
return false;
|
||||||
|
|
||||||
UnMount(pos);
|
UnMount(pos);
|
||||||
|
|
||||||
if(pos >= (int) MountNameList.size())
|
if(pos >= (int) MountNameList.size())
|
||||||
MountNameList.resize(GetPartitionCount());
|
MountNameList.resize(pos+1);
|
||||||
|
|
||||||
MountNameList[pos] = name;
|
MountNameList[pos] = name;
|
||||||
SetWbfsHandle(pos, NULL);
|
SetWbfsHandle(pos, NULL);
|
||||||
|
|
||||||
if(strncmp(GetFSName(pos), "FAT", 3) == 0)
|
//! Some stupid partition manager think they don't need to edit the freaken MBR.
|
||||||
|
//! So we need to check the first 64 sectors and see if some partition is there.
|
||||||
|
//! libfat does that by default so let's use it.
|
||||||
|
//! We do that only on sd not on usb.
|
||||||
|
if(forceFAT && (!GetFSName(pos) || strcmp(GetFSName(pos), "Unknown") == 0))
|
||||||
|
{
|
||||||
|
if (fatMount(MountNameList[pos].c_str(), interface, 0, CACHE, SECTORS))
|
||||||
|
{
|
||||||
|
sec_t FAT_startSector = FindFirstValidPartition(interface);
|
||||||
|
AddPartition("FAT", FAT_startSector, 0xdeadbeaf, true, 0x0c, 0);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(strncmp(GetFSName(pos), "FAT", 3) == 0 || strcmp(GetFSName(pos), "GUID-Entry") == 0)
|
||||||
{
|
{
|
||||||
if (fatMount(MountNameList[pos].c_str(), interface, GetLBAStart(pos), CACHE, SECTORS))
|
if (fatMount(MountNameList[pos].c_str(), interface, GetLBAStart(pos), CACHE, SECTORS))
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else if(strncmp(GetFSName(pos), "NTFS", 4) == 0)
|
|
||||||
{
|
{
|
||||||
if(ntfsMount(MountNameList[pos].c_str(), interface, GetLBAStart(pos), CACHE, SECTORS, NTFS_SU | NTFS_RECOVER))
|
if(strcmp(GetFSName(pos), "GUID-Entry") == 0)
|
||||||
|
PartitionList[pos].FSName = "FAT";
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if(strncmp(GetFSName(pos), "LINUX", 5) == 0)
|
}
|
||||||
|
|
||||||
|
if(strncmp(GetFSName(pos), "NTFS", 4) == 0 || strcmp(GetFSName(pos), "GUID-Entry") == 0)
|
||||||
|
{
|
||||||
|
if(ntfsMount(MountNameList[pos].c_str(), interface, GetLBAStart(pos), CACHE, SECTORS, NTFS_SHOW_HIDDEN_FILES | NTFS_RECOVER))
|
||||||
|
{
|
||||||
|
PartitionList[pos].FSName = "NTFS";
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(strncmp(GetFSName(pos), "LINUX", 5) == 0 || strcmp(GetFSName(pos), "GUID-Entry") == 0)
|
||||||
{
|
{
|
||||||
if(ext2Mount(MountNameList[pos].c_str(), interface, GetLBAStart(pos), CACHE, SECTORS, EXT2_FLAG_DEFAULT))
|
if(ext2Mount(MountNameList[pos].c_str(), interface, GetLBAStart(pos), CACHE, SECTORS, EXT2_FLAG_DEFAULT))
|
||||||
|
{
|
||||||
|
PartitionList[pos].FSName = "LINUX";
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else if(strncmp(GetFSName(pos), "WBFS", 4) == 0)
|
else if(strncmp(GetFSName(pos), "WBFS", 4) == 0)
|
||||||
{
|
{
|
||||||
if(interface == &__io_usbstorage)
|
if(interface == &__io_usbstorage2_port0 || interface == &__io_usbstorage2_port1)
|
||||||
SetWbfsHandle(pos, wbfs_open_partition(__WBFS_ReadUSB, __WBFS_WriteUSB, NULL, sector_size, GetSecCount(pos), GetLBAStart(pos), 0));
|
SetWbfsHandle(pos, wbfs_open_partition(__WBFS_ReadUSB, __WBFS_WriteUSB, NULL, USBStorage2_GetSectorSize(), GetSecCount(pos), GetLBAStart(pos), 0));
|
||||||
else if((neek2o() && interface == &__io_wiisd) || (!neek2o() && interface == &__io_sdhc))
|
else if((neek2o() && interface == &__io_wiisd) || (!neek2o() && interface == &__io_sdhc))
|
||||||
SetWbfsHandle(pos, wbfs_open_partition(__WBFS_ReadSDHC, __WBFS_WriteSDHC, NULL, sector_size, GetSecCount(pos), GetLBAStart(pos), 0));
|
SetWbfsHandle(pos, wbfs_open_partition(__WBFS_ReadSDHC, __WBFS_WriteSDHC, NULL, 512, GetSecCount(pos), GetLBAStart(pos), 0));
|
||||||
|
if(GetWbfsHandle(pos))
|
||||||
if(GetWbfsHandle(pos)) return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
MountNameList[pos].clear();
|
MountNameList[pos].clear();
|
||||||
@ -159,105 +192,97 @@ bool PartitionHandle::Mount(int pos, const char * name)
|
|||||||
|
|
||||||
void PartitionHandle::UnMount(int pos)
|
void PartitionHandle::UnMount(int pos)
|
||||||
{
|
{
|
||||||
if(!interface) return;
|
if(!interface)
|
||||||
|
return;
|
||||||
|
|
||||||
if(pos >= (int) MountNameList.size()) return;
|
if(pos >= (int) MountNameList.size())
|
||||||
|
return;
|
||||||
|
|
||||||
if(MountNameList[pos].size() == 0) return;
|
if(MountNameList[pos].size() == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
char DeviceName[20];
|
char DeviceSyn[20];
|
||||||
snprintf(DeviceName, sizeof(DeviceName), "%s:", MountNameList[pos].c_str());
|
snprintf(DeviceSyn, sizeof(DeviceSyn), "%s:", MountNameList[pos].c_str());
|
||||||
|
|
||||||
wbfs_t* wbfshandle = GetWbfsHandle(pos);
|
wbfs_t* wbfshandle = GetWbfsHandle(pos);
|
||||||
if(wbfshandle) wbfs_close(wbfshandle);
|
if(wbfshandle) wbfs_close(wbfshandle);
|
||||||
SetWbfsHandle(pos, NULL);
|
SetWbfsHandle(pos, NULL);
|
||||||
WBFS_Close();
|
WBFS_Close();
|
||||||
|
|
||||||
fatUnmount(DeviceName);
|
//closing all open Files write back the cache
|
||||||
ntfsUnmount(DeviceName, true);
|
fatUnmount(DeviceSyn);
|
||||||
ext2Unmount(DeviceName);
|
//closing all open Files write back the cache
|
||||||
|
ntfsUnmount(DeviceSyn, true);
|
||||||
//Remove mount name from the list
|
//closing all open Files write back the cache
|
||||||
|
ext2Unmount(DeviceSyn);
|
||||||
|
//Remove name from list
|
||||||
MountNameList[pos].clear();
|
MountNameList[pos].clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool PartitionHandle::IsExisting(u64 lba)
|
||||||
|
{
|
||||||
|
for(u32 i = 0; i < PartitionList.size(); ++i)
|
||||||
|
{
|
||||||
|
if(PartitionList[i].LBA_Start == lba)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
int PartitionHandle::FindPartitions()
|
int PartitionHandle::FindPartitions()
|
||||||
{
|
{
|
||||||
MASTER_BOOT_RECORD *mbr = (MASTER_BOOT_RECORD *)MEM2_alloc(MAX_BYTES_PER_SECTOR);
|
MASTER_BOOT_RECORD *mbr = (MASTER_BOOT_RECORD *) malloc(MAX_BYTES_PER_SECTOR);
|
||||||
if(mbr == NULL)
|
if(!mbr) return -1;
|
||||||
return -1;
|
|
||||||
|
|
||||||
// Read the first sector on the device
|
// Read the first sector on the device
|
||||||
if (!interface->readSectors(0, 1, mbr))
|
if (!interface->readSectors(0, 1, mbr))
|
||||||
{
|
{
|
||||||
MEM2_free(mbr);
|
free(mbr);
|
||||||
return 0;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if it's a RAW disc, without a partition table
|
// If this is the devices master boot record
|
||||||
if(CheckRAW((VOLUME_BOOT_RECORD *)mbr))
|
|
||||||
{
|
|
||||||
MEM2_free(mbr);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
// Verify this is the device's master boot record
|
|
||||||
if (mbr->signature != MBR_SIGNATURE)
|
if (mbr->signature != MBR_SIGNATURE)
|
||||||
{
|
{
|
||||||
MEM2_free(mbr);
|
free(mbr);
|
||||||
return 0;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < 4; i++)
|
for (int i = 0; i < 4; i++)
|
||||||
{
|
{
|
||||||
PARTITION_RECORD * partition = (PARTITION_RECORD *) &mbr->partitions[i];
|
PARTITION_RECORD * partition = (PARTITION_RECORD *) &mbr->partitions[i];
|
||||||
VOLUME_BOOT_RECORD *vbr = (VOLUME_BOOT_RECORD *)MEM2_alloc(MAX_BYTES_PER_SECTOR);
|
|
||||||
if(!vbr)
|
if(partition->type == PARTITION_TYPE_GPT)
|
||||||
{
|
{
|
||||||
MEM2_free(mbr);
|
int ret = CheckGPT(i);
|
||||||
return -1;
|
if(ret == 0) // if it's a GPT we don't need to go on looking through the mbr anymore
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (le32(partition->lba_start) == 0) continue; // Invalid partition
|
if(partition->type == PARTITION_TYPE_DOS33_EXTENDED || partition->type == PARTITION_TYPE_WIN95_EXTENDED)
|
||||||
|
|
||||||
if(!interface->readSectors(le32(partition->lba_start), 1, vbr)) continue;
|
|
||||||
|
|
||||||
// Check if the partition is WBFS
|
|
||||||
bool isWBFS = memcmp((u8 *)vbr, WBFS_SIGNATURE, sizeof(WBFS_SIGNATURE)) == 0;
|
|
||||||
|
|
||||||
if(!isWBFS && i == 0 && partition->type == PARTITION_TYPE_GPT_TABLE)
|
|
||||||
return CheckGPT() ? PartitionList.size() : 0;
|
|
||||||
|
|
||||||
if(!isWBFS && vbr->Signature != VBR_SIGNATURE && partition->type != 0x83) continue;
|
|
||||||
|
|
||||||
if(!isWBFS && (partition->type == PARTITION_TYPE_DOS33_EXTENDED || partition->type == PARTITION_TYPE_WIN95_EXTENDED))
|
|
||||||
{
|
{
|
||||||
CheckEBR(i, le32(partition->lba_start));
|
CheckEBR(i, le32(partition->lba_start));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if(isWBFS || le32(partition->block_count) > 0)
|
|
||||||
{
|
|
||||||
PartitionFS PartitionEntry = {"0",0,0,0,0,0,0,0};
|
|
||||||
PartitionEntry.FSName = isWBFS ? "WBFS" : PartFromType(partition->type);
|
|
||||||
PartitionEntry.LBA_Start = le32(partition->lba_start);
|
|
||||||
PartitionEntry.SecCount = isWBFS ? ((wbfs_head_t *)vbr)->n_hd_sec : le32(partition->block_count);
|
|
||||||
PartitionEntry.Bootable = (partition->status == PARTITION_BOOTABLE);
|
|
||||||
PartitionEntry.PartitionType = partition->type;
|
|
||||||
PartitionEntry.PartitionNum = i;
|
|
||||||
PartitionEntry.EBR_Sector = 0;
|
|
||||||
|
|
||||||
PartitionList.push_back(PartitionEntry);
|
if(le32(partition->block_count) > 0 && !IsExisting(le32(partition->lba_start)))
|
||||||
|
{
|
||||||
|
AddPartition(PartFromType(partition->type), le32(partition->lba_start),
|
||||||
|
le32(partition->block_count), (partition->status == PARTITION_BOOTABLE),
|
||||||
|
partition->type, i);
|
||||||
}
|
}
|
||||||
MEM2_free(vbr);
|
|
||||||
}
|
}
|
||||||
MEM2_free(mbr);
|
|
||||||
return PartitionList.size();
|
free(mbr);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PartitionHandle::CheckEBR(u8 PartNum, sec_t ebr_lba)
|
void PartitionHandle::CheckEBR(u8 PartNum, sec_t ebr_lba)
|
||||||
{
|
{
|
||||||
EXTENDED_BOOT_RECORD *ebr = (EXTENDED_BOOT_RECORD *)MEM2_alloc(MAX_BYTES_PER_SECTOR);
|
EXTENDED_BOOT_RECORD *ebr = (EXTENDED_BOOT_RECORD *) malloc(MAX_BYTES_PER_SECTOR);
|
||||||
if(ebr == NULL)
|
if(!ebr) return;
|
||||||
return;
|
|
||||||
sec_t next_erb_lba = 0;
|
sec_t next_erb_lba = 0;
|
||||||
|
|
||||||
do
|
do
|
||||||
@ -265,176 +290,136 @@ void PartitionHandle::CheckEBR(u8 PartNum, sec_t ebr_lba)
|
|||||||
// Read and validate the extended boot record
|
// Read and validate the extended boot record
|
||||||
if (!interface->readSectors(ebr_lba + next_erb_lba, 1, ebr))
|
if (!interface->readSectors(ebr_lba + next_erb_lba, 1, ebr))
|
||||||
{
|
{
|
||||||
MEM2_free(ebr);
|
free(ebr);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if the partition is WBFS
|
if (ebr->signature != EBR_SIGNATURE)
|
||||||
bool isWBFS = memcmp((u8 *)ebr, WBFS_SIGNATURE, sizeof(WBFS_SIGNATURE)) == 0;
|
|
||||||
|
|
||||||
if(!isWBFS && ebr->signature != EBR_SIGNATURE)
|
|
||||||
{
|
{
|
||||||
MEM2_free(ebr);
|
free(ebr);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(isWBFS || le32(ebr->partition.block_count) > 0)
|
if(le32(ebr->partition.block_count) > 0 && !IsExisting(ebr_lba + next_erb_lba + le32(ebr->partition.lba_start)))
|
||||||
{
|
{
|
||||||
PartitionFS PartitionEntry = {"0",0,0,0,0,0,0,0};
|
AddPartition(PartFromType(ebr->partition.type), ebr_lba + next_erb_lba + le32(ebr->partition.lba_start),
|
||||||
PartitionEntry.FSName = isWBFS ? "WBFS" : PartFromType(ebr->partition.type);
|
le32(ebr->partition.block_count), (ebr->partition.status == PARTITION_BOOTABLE),
|
||||||
PartitionEntry.LBA_Start = ebr_lba + next_erb_lba + le32(ebr->partition.lba_start);
|
ebr->partition.type, PartNum);
|
||||||
PartitionEntry.SecCount = isWBFS ? ((wbfs_head_t *)&ebr)->n_hd_sec : le32(ebr->partition.block_count);
|
|
||||||
PartitionEntry.Bootable = (ebr->partition.status == PARTITION_BOOTABLE);
|
|
||||||
PartitionEntry.PartitionType = ebr->partition.type;
|
|
||||||
PartitionEntry.PartitionNum = PartNum;
|
|
||||||
PartitionEntry.EBR_Sector = ebr_lba + next_erb_lba;
|
|
||||||
|
|
||||||
PartitionList.push_back(PartitionEntry);
|
|
||||||
}
|
}
|
||||||
// Get the start sector of the current partition
|
// Get the start sector of the current partition
|
||||||
// and the next extended boot record in the chain
|
// and the next extended boot record in the chain
|
||||||
next_erb_lba = le32(ebr->next_ebr.lba_start);
|
next_erb_lba = le32(ebr->next_ebr.lba_start);
|
||||||
}
|
}
|
||||||
while(next_erb_lba > 0);
|
while(next_erb_lba > 0);
|
||||||
MEM2_free(ebr);
|
|
||||||
|
free(ebr);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PartitionHandle::CheckGPT(void)
|
static const u8 TYPE_UNUSED[16] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 };
|
||||||
{
|
static const u8 TYPE_BIOS[16] = { 0x48,0x61,0x68,0x21,0x49,0x64,0x6F,0x6E,0x74,0x4E,0x65,0x65,0x64,0x45,0x46,0x49 };
|
||||||
GPT_PARTITION_TABLE *gpt = (GPT_PARTITION_TABLE *)MEM2_alloc(MAX_BYTES_PER_SECTOR);
|
static const u8 TYPE_LINUX_MS_BASIC_DATA[16] = { 0xA2,0xA0,0xD0,0xEB,0xE5,0xB9,0x33,0x44,0x87,0xC0,0x68,0xB6,0xB7,0x26,0x99,0xC7 };
|
||||||
if(gpt == NULL)
|
|
||||||
return false;
|
|
||||||
bool success = false; // To return false unless at least 1 partition is verified
|
|
||||||
|
|
||||||
if(!interface->readSectors(1, 33, gpt))
|
int PartitionHandle::CheckGPT(u8 PartNum)
|
||||||
{
|
{
|
||||||
MEM2_free(gpt);
|
GPT_HEADER *gpt_header = (GPT_HEADER *) malloc(MAX_BYTES_PER_SECTOR);
|
||||||
return false; // To read all 128 possible partitions
|
if(!gpt_header) return -1;
|
||||||
|
|
||||||
|
// Read and validate the extended boot record
|
||||||
|
if (!interface->readSectors(1, 1, gpt_header))
|
||||||
|
{
|
||||||
|
free(gpt_header);
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify this is the Primary GPT entry
|
if(strncmp(gpt_header->magic, "EFI PART", 8) != 0)
|
||||||
if((strncmp(gpt->magic, GPT_SIGNATURE, 8) != 0)
|
|
||||||
|| (le32(gpt->Entry_Size) != 128)
|
|
||||||
|| (le64(gpt->Table_LBA) != 2)
|
|
||||||
|| (le64(gpt->Header_LBA) != 1)
|
|
||||||
|| (le64(gpt->First_Usable_LBA) != 34)
|
|
||||||
|| (gpt->Reserved != 0))
|
|
||||||
{
|
{
|
||||||
MEM2_free(gpt);
|
free(gpt_header);
|
||||||
return false;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
for(u8 i = 0; i < le32(gpt->Num_Entries) && PartitionList.size() <= 8; i++)
|
gpt_header->part_table_lba = le64(gpt_header->part_table_lba);
|
||||||
|
gpt_header->part_entries = le32(gpt_header->part_entries);
|
||||||
|
gpt_header->part_entry_size = le32(gpt_header->part_entry_size);
|
||||||
|
gpt_header->part_entry_checksum = le32(gpt_header->part_entry_checksum);
|
||||||
|
|
||||||
|
u8 * sector_buf = new u8[MAX_BYTES_PER_SECTOR];
|
||||||
|
|
||||||
|
u64 next_lba = gpt_header->part_table_lba;
|
||||||
|
|
||||||
|
for(u32 i = 0; i < gpt_header->part_entries; ++i)
|
||||||
{
|
{
|
||||||
GUID_PARTITION_ENTRY *entry = (GUID_PARTITION_ENTRY *) &gpt->partitions[i];
|
if (!interface->readSectors(next_lba, 1, sector_buf))
|
||||||
VOLUME_BOOT_RECORD *vbr = (VOLUME_BOOT_RECORD*)MEM2_alloc(MAX_BYTES_PER_SECTOR);
|
break;
|
||||||
if(vbr == NULL)
|
|
||||||
|
for(u32 n = 0; n < BYTES_PER_SECTOR/gpt_header->part_entry_size; ++n, ++i)
|
||||||
{
|
{
|
||||||
MEM2_free(gpt);
|
GUID_PART_ENTRY * part_entry = (GUID_PART_ENTRY *) (sector_buf+gpt_header->part_entry_size*n);
|
||||||
return false;
|
|
||||||
|
if(memcmp(part_entry->part_type_guid, TYPE_UNUSED, 16) == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if(IsExisting(le64(part_entry->part_first_lba)))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
bool bootable = (memcmp(part_entry->part_type_guid, TYPE_BIOS, 16) == 0);
|
||||||
|
|
||||||
|
AddPartition("GUID-Entry", le64(part_entry->part_first_lba), le64(part_entry->part_last_lba), bootable, PARTITION_TYPE_GPT, PartNum);
|
||||||
}
|
}
|
||||||
|
|
||||||
int Start = le64(entry->First_LBA);
|
next_lba++;
|
||||||
int End = le64(entry->Last_LBA);
|
|
||||||
int Size = End - Start;
|
|
||||||
|
|
||||||
if(!interface->readSectors(Start, 1, vbr)) continue;
|
|
||||||
|
|
||||||
PartitionFS PartitionEntry = {"0",0,0,0,0,0,0,0};
|
|
||||||
if(memcmp((u8 *)vbr + BPB_NTFS_ADDR, NTFS_SIGNATURE, sizeof(NTFS_SIGNATURE)) == 0)
|
|
||||||
{
|
|
||||||
PartitionEntry.FSName = "NTFS";
|
|
||||||
PartitionEntry.PartitionType = 0x07;
|
|
||||||
PartitionEntry.SecCount = le64(vbr->Number_of_Sectors);
|
|
||||||
}
|
|
||||||
else if(memcmp((u8 *)vbr + BPB_FAT32_ADDR, FAT_SIGNATURE, sizeof(FAT_SIGNATURE)) == 0)
|
|
||||||
{
|
|
||||||
PartitionEntry.FSName = "FAT32";
|
|
||||||
PartitionEntry.PartitionType = 0x0c;
|
|
||||||
PartitionEntry.SecCount = le16(vbr->bpb.FatSectors);
|
|
||||||
if (PartitionEntry.SecCount == 0)
|
|
||||||
PartitionEntry.SecCount = le32(vbr->bpb.Large_Sectors);
|
|
||||||
}
|
|
||||||
else if(memcmp((u8 *)vbr + BPB_FAT16_ADDR, FAT_SIGNATURE, sizeof(FAT_SIGNATURE)) == 0)
|
|
||||||
{
|
|
||||||
PartitionEntry.FSName = "FAT16";
|
|
||||||
PartitionEntry.PartitionType = 0x0e;
|
|
||||||
|
|
||||||
PartitionEntry.SecCount = le16(vbr->bpb.FatSectors);
|
|
||||||
if (PartitionEntry.SecCount == 0)
|
|
||||||
PartitionEntry.SecCount = le32(vbr->bpb.Large_Sectors);
|
|
||||||
}
|
|
||||||
else if(memcmp((u8 *)vbr, WBFS_SIGNATURE, sizeof(WBFS_SIGNATURE)) == 0)
|
|
||||||
{
|
|
||||||
PartitionEntry.FSName = "WBFS";
|
|
||||||
PartitionEntry.SecCount = ((wbfs_head_t *)vbr)->n_hd_sec;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
bzero(&PartitionEntry, sizeof(PartitionFS));
|
|
||||||
if(interface->readSectors(Start + 1, 1, vbr))
|
|
||||||
{
|
|
||||||
if(memcmp((u8 *)vbr + BPB_EXT2_ADDR, EXT_SIGNATURE, sizeof(EXT_SIGNATURE)) == 0)
|
|
||||||
{
|
|
||||||
PartitionEntry.FSName = "LINUX";
|
|
||||||
PartitionEntry.PartitionType = 0x83;
|
|
||||||
PartitionEntry.SecCount = Size;
|
|
||||||
}
|
|
||||||
else continue;
|
|
||||||
}
|
|
||||||
else continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(PartitionEntry.SecCount != 0 && PartitionEntry.FSName[0] != '0')
|
delete [] sector_buf;
|
||||||
{
|
free(gpt_header);
|
||||||
PartitionEntry.LBA_Start = Start;
|
|
||||||
PartitionEntry.PartitionNum = i;
|
|
||||||
|
|
||||||
success = true;
|
return 0;
|
||||||
PartitionList.push_back(PartitionEntry);
|
|
||||||
}
|
|
||||||
MEM2_free(vbr);
|
|
||||||
}
|
|
||||||
MEM2_free(gpt);
|
|
||||||
|
|
||||||
return success;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PartitionHandle::CheckRAW(VOLUME_BOOT_RECORD * vbr)
|
void PartitionHandle::AddPartition(const char * name, u64 lba_start, u64 sec_count, bool bootable, u8 part_type, u8 part_num)
|
||||||
{
|
{
|
||||||
PartitionFS PartitionEntry = {"0",0,0,0,0,0,0,0};
|
char *buffer = (char *) malloc(MAX_BYTES_PER_SECTOR);
|
||||||
if(memcmp((u8 *)vbr + BPB_NTFS_ADDR, NTFS_SIGNATURE, sizeof(NTFS_SIGNATURE)) == 0)
|
|
||||||
|
if (!interface->readSectors(lba_start, 1, buffer))
|
||||||
{
|
{
|
||||||
PartitionEntry.FSName = "NTFS";
|
free(buffer);
|
||||||
PartitionEntry.PartitionType = 0x07;
|
return;
|
||||||
PartitionEntry.SecCount = le64(vbr->Number_of_Sectors);
|
|
||||||
}
|
|
||||||
else if(memcmp((u8 *)vbr + BPB_FAT32_ADDR, FAT_SIGNATURE, sizeof(FAT_SIGNATURE)) == 0)
|
|
||||||
{
|
|
||||||
PartitionEntry.FSName = "FAT32";
|
|
||||||
PartitionEntry.PartitionType = 0x0c;
|
|
||||||
PartitionEntry.SecCount = le16(vbr->bpb.FatSectors);
|
|
||||||
if (PartitionEntry.SecCount == 0)
|
|
||||||
PartitionEntry.SecCount = le32(vbr->bpb.Large_Sectors);
|
|
||||||
}
|
|
||||||
else if(memcmp((u8 *)vbr + BPB_FAT16_ADDR, FAT_SIGNATURE, sizeof(FAT_SIGNATURE)) == 0)
|
|
||||||
{
|
|
||||||
PartitionEntry.FSName = "FAT16";
|
|
||||||
PartitionEntry.PartitionType = 0x0e;
|
|
||||||
PartitionEntry.SecCount = le16(vbr->bpb.FatSectors);
|
|
||||||
if (PartitionEntry.SecCount == 0)
|
|
||||||
PartitionEntry.SecCount = le32(vbr->bpb.Large_Sectors);
|
|
||||||
}
|
|
||||||
else if(memcmp((u8 *)vbr, WBFS_SIGNATURE, sizeof(WBFS_SIGNATURE)) == 0)
|
|
||||||
{
|
|
||||||
PartitionEntry.FSName = "WBFS";
|
|
||||||
PartitionEntry.SecCount = ((wbfs_head_t *)vbr)->n_hd_sec;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(PartitionEntry.FSName[0] != '0')
|
wbfs_head_t *head = (wbfs_head_t *) buffer;
|
||||||
|
|
||||||
|
if (head->magic == wbfs_htonl(WBFS_MAGIC))
|
||||||
{
|
{
|
||||||
PartitionList.push_back(PartitionEntry);
|
name = "WBFS";
|
||||||
return true;
|
part_type = 0xBF; //Override partition type on WBFS
|
||||||
|
//! correct sector size in physical sectors (512 bytes per sector)
|
||||||
|
sec_count = (u64) head->n_hd_sec * (u64) (1 << head->hd_sec_sz_s) / (u64) BYTES_PER_SECTOR;
|
||||||
|
|
||||||
}
|
}
|
||||||
return false;
|
else if(*((u16 *) (buffer + 0x1FE)) == 0x55AA)
|
||||||
|
{
|
||||||
|
//! Partition typ can be missleading the correct partition format. Stupid lazy ass Partition Editors.
|
||||||
|
if((memcmp(buffer + 0x36, "FAT", 3) == 0 || memcmp(buffer + 0x52, "FAT", 3) == 0) &&
|
||||||
|
strncmp(PartFromType(part_type), "FAT", 3) != 0)
|
||||||
|
{
|
||||||
|
name = "FAT32";
|
||||||
|
part_type = 0x0c;
|
||||||
|
}
|
||||||
|
if (memcmp(buffer + 0x03, "NTFS", 4) == 0)
|
||||||
|
{
|
||||||
|
name = "NTFS";
|
||||||
|
part_type = 0x07;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PartitionFS PartitionEntrie;
|
||||||
|
PartitionEntrie.FSName = name;
|
||||||
|
PartitionEntrie.LBA_Start = lba_start;
|
||||||
|
PartitionEntrie.SecCount = sec_count;
|
||||||
|
PartitionEntrie.Bootable = bootable;
|
||||||
|
PartitionEntrie.PartitionType = part_type;
|
||||||
|
PartitionEntrie.PartitionNum = part_num;
|
||||||
|
|
||||||
|
PartitionList.push_back(PartitionEntrie);
|
||||||
|
|
||||||
|
free(buffer);
|
||||||
}
|
}
|
||||||
|
@ -28,6 +28,7 @@
|
|||||||
|
|
||||||
#include <gccore.h>
|
#include <gccore.h>
|
||||||
#include "libwbfs/libwbfs.h"
|
#include "libwbfs/libwbfs.h"
|
||||||
|
#include "usbstorage.h"
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
@ -39,27 +40,19 @@ using namespace std;
|
|||||||
|
|
||||||
#define MBR_SIGNATURE 0x55AA
|
#define MBR_SIGNATURE 0x55AA
|
||||||
#define EBR_SIGNATURE MBR_SIGNATURE
|
#define EBR_SIGNATURE MBR_SIGNATURE
|
||||||
#define VBR_SIGNATURE MBR_SIGNATURE
|
|
||||||
#define GPT_SIGNATURE "EFI PART"
|
|
||||||
|
|
||||||
#define PARTITION_BOOTABLE 0x80 /* Bootable (active) */
|
#define PARTITION_BOOTABLE 0x80 /* Bootable (active) */
|
||||||
#define PARTITION_NONBOOTABLE 0x00 /* Non-bootable */
|
#define PARTITION_NONBOOTABLE 0x00 /* Non-bootable */
|
||||||
|
#define PARTITION_TYPE_GPT 0xEE /* Indicates that a GPT header is available */
|
||||||
|
|
||||||
|
#define GUID_SYSTEM_PARTITION 0x0000000000000001LL /* System partition (disk partitioning utilities must reserve the partition as is) */
|
||||||
|
#define GUID_READ_ONLY_PARTITION 0x0800000000000000LL /* Read-only partition */
|
||||||
|
#define GUID_HIDDEN_PARTITION 0x2000000000000000LL /* Hidden partition */
|
||||||
|
#define GUID_NO_AUTOMOUNT_PARTITION 0x4000000000000000LL /* Do not automount (e.g., do not assign drive letter) */
|
||||||
|
|
||||||
#define BYTES_PER_SECTOR 512 /* Default in libogc */
|
#define BYTES_PER_SECTOR 512 /* Default in libogc */
|
||||||
#define MAX_BYTES_PER_SECTOR 4096 /* Max bytes per sector */
|
#define MAX_BYTES_PER_SECTOR 4096 /* Max bytes per sector */
|
||||||
|
|
||||||
enum SIG_OFFSETS {
|
|
||||||
BPB_NTFS_ADDR = 0x3,
|
|
||||||
BPB_FAT16_ADDR = 0x36,
|
|
||||||
BPB_EXT2_ADDR = 0x38,
|
|
||||||
BPB_FAT32_ADDR = 0x52,
|
|
||||||
};
|
|
||||||
|
|
||||||
static const char FAT_SIGNATURE[3] = {'F', 'A', 'T'};
|
|
||||||
static const char NTFS_SIGNATURE[4] = {'N', 'T', 'F', 'S'};
|
|
||||||
static const char WBFS_SIGNATURE[4] = {'W', 'B', 'F', 'S'};
|
|
||||||
static const char EXT_SIGNATURE[2] = {0x53, 0xEF};
|
|
||||||
|
|
||||||
typedef struct _PARTITION_RECORD {
|
typedef struct _PARTITION_RECORD {
|
||||||
u8 status; /* Partition status; see above */
|
u8 status; /* Partition status; see above */
|
||||||
u8 chs_start[3]; /* Cylinder-head-sector address to first block of partition */
|
u8 chs_start[3]; /* Cylinder-head-sector address to first block of partition */
|
||||||
@ -69,10 +62,9 @@ typedef struct _PARTITION_RECORD {
|
|||||||
u32 block_count; /* Number of blocks in partition */
|
u32 block_count; /* Number of blocks in partition */
|
||||||
} __attribute__((__packed__)) PARTITION_RECORD;
|
} __attribute__((__packed__)) PARTITION_RECORD;
|
||||||
|
|
||||||
|
|
||||||
typedef struct _MASTER_BOOT_RECORD {
|
typedef struct _MASTER_BOOT_RECORD {
|
||||||
u8 code_area[440]; /* Code area; normally empty */
|
u8 code_area[446]; /* Code area; normally empty */
|
||||||
u8 disk_guid[4]; /* Disk signature (optional) */
|
|
||||||
u8 reserved[2]; /* Usually zeroed */
|
|
||||||
PARTITION_RECORD partitions[4]; /* 4 primary partitions */
|
PARTITION_RECORD partitions[4]; /* 4 primary partitions */
|
||||||
u16 signature; /* MBR signature; 0xAA55 */
|
u16 signature; /* MBR signature; 0xAA55 */
|
||||||
} __attribute__((__packed__)) MASTER_BOOT_RECORD;
|
} __attribute__((__packed__)) MASTER_BOOT_RECORD;
|
||||||
@ -85,81 +77,45 @@ typedef struct _EXTENDED_BOOT_RECORD {
|
|||||||
u16 signature; /* EBR signature; 0xAA55 */
|
u16 signature; /* EBR signature; 0xAA55 */
|
||||||
} __attribute__((__packed__)) EXTENDED_BOOT_RECORD;
|
} __attribute__((__packed__)) EXTENDED_BOOT_RECORD;
|
||||||
|
|
||||||
typedef struct _GUID_PARTITION_ENTRY
|
typedef struct _GUID_PART_ENTRY
|
||||||
{
|
{
|
||||||
u8 Type_GUID[16]; /* Partition type GUID */
|
u8 part_type_guid[16]; /* Partition type GUID */
|
||||||
u8 Unique_GUID[16]; /* Unique partition GUID */
|
u8 uniq_part_guid[16]; /* Unique partition GUID */
|
||||||
u64 First_LBA; /* First LBA (little-endian) */
|
u64 part_first_lba; /* First LBA (little-endian) */
|
||||||
u64 Last_LBA; /* Last LBA (inclusive, usually odd) */
|
u64 part_last_lba; /* Last LBA (inclusive, usually odd) */
|
||||||
u64 Attributes; /* GUID Attribute flags (e.g. bit 60 denotes read-only) */
|
u64 attribute_flags; /* GUID Attribute flags (e.g. bit 60 denotes read-only) */
|
||||||
char Name[72]; /* Partition name (36 UTF-16LE code units) */
|
char partition_name[72]; /* Partition name (36 UTF-16LE code units) */
|
||||||
} __attribute__((__packed__)) GUID_PARTITION_ENTRY;
|
} __attribute__((__packed__)) GUID_PART_ENTRY;
|
||||||
|
|
||||||
typedef struct _GPT_PARTITION_TABLE {
|
typedef struct _GPT_HEADER
|
||||||
|
{
|
||||||
char magic[8]; /* "EFI PART" */
|
char magic[8]; /* "EFI PART" */
|
||||||
u32 Revision;
|
u32 revision; /* For version 1.0 */
|
||||||
u32 Header_Size; /* Size of this header */
|
u32 header_size; /* Header size in bytes */
|
||||||
u32 CheckSum;
|
u32 checksum; /* CRC32 of header (0 to header size), with this field zeroed during calculation */
|
||||||
u32 Reserved; /* Must be 0 */
|
u32 reserved; /* must be 0 */
|
||||||
u64 Header_LBA; /* Location of this header, always 1 in primary copy */
|
u64 header_lba; /* Current LBA (location of this header copy) */
|
||||||
u64 Backup_Header_LBA; /* Location of backup header, always max lba - 1 */
|
u64 backup_lba; /* Backup LBA (location of the other header copy) */
|
||||||
u64 First_Usable_LBA; /* Primary GPT partition table's last LBA + 1 */
|
u64 first_part_lba; /* First usable LBA for partitions (primary partition table last LBA + 1) */
|
||||||
u64 Last_Usable_LBA; /* Secondary GPT partition table's first LBA - 1 */
|
u64 last_part_lba; /* Last usable LBA (secondary partition table first LBA - 1) */
|
||||||
u8 GUID[16]; /* Disk GUID (also referred as UUID on UNIXes) */
|
u8 disk_guid[16]; /* Disk GUID (also referred as UUID on UNIXes) */
|
||||||
u64 Table_LBA; /* Always 2 in primary copy, or Header_LBA + 1. Secondary copy is Backup_Header_LBA - 1 */
|
u64 part_table_lba; /* Partition entries starting LBA (always 2 in primary copy) */
|
||||||
u32 Num_Entries; /* Number of entries in the partition info array */
|
u32 part_entries; /* Number of partition entries */
|
||||||
u32 Entry_Size; /* Size of each array entry, usually 128 */
|
u32 part_entry_size; /* Size of a partition entry (usually 128) */
|
||||||
u32 Entries_CheckSum; /* CRC32 of partition array */
|
u32 part_entry_checksum; /* CRC32 of partition array */
|
||||||
u8 Zeroes[420]; /* Pad to a total 512 byte LBA or sizeof 1 LBA */
|
u8 zeros[420];
|
||||||
GUID_PARTITION_ENTRY partitions[128]; /* Max 128 Partition Entries */
|
} __attribute__((__packed__)) GPT_HEADER;
|
||||||
} __attribute__((__packed__)) GPT_PARTITION_TABLE;
|
|
||||||
|
|
||||||
typedef struct _PartitionFS {
|
typedef struct _PartitionFS {
|
||||||
const char * FSName;
|
const char * FSName;
|
||||||
u32 LBA_Start;
|
u64 LBA_Start;
|
||||||
u32 SecCount;
|
u64 SecCount;
|
||||||
bool Bootable;
|
bool Bootable;
|
||||||
u8 PartitionType;
|
u8 PartitionType;
|
||||||
u8 PartitionNum;
|
u8 PartitionNum;
|
||||||
u32 EBR_Sector;
|
|
||||||
wbfs_t *wbfshandle;
|
wbfs_t *wbfshandle;
|
||||||
} PartitionFS;
|
} __attribute__((__packed__)) PartitionFS;
|
||||||
|
|
||||||
typedef struct _BIOS_PARAMETER_BLOCK {
|
|
||||||
u16 Bytes_Per_Sector; /* Size of a sector in bytes. */
|
|
||||||
u8 Sectors_Per_Cluster; /* Size of a cluster in sectors. */
|
|
||||||
u16 ReservedSsectors; /* zero on ntfs */
|
|
||||||
u8 Fats; /* zero on ntfs */
|
|
||||||
u16 Root_Entries; /* zero on ntfs */
|
|
||||||
u16 FatSectors; /* Number of sectors in volume. (FAT) Zero on ntfs */
|
|
||||||
u8 Media_Type; /* 0xf8 = hard disk */
|
|
||||||
u16 Sectors_Per_Fat; /* zero on ntfs*/
|
|
||||||
u16 Sectors_Per_Track; /* Required to boot Windows. (0x0d) */
|
|
||||||
u16 Heads; /* Required to boot Windows. (0x0f) */
|
|
||||||
u32 Hidden_Sectors; /* Offset to the start of the partition (0x11) in sectors. */
|
|
||||||
u32 Large_Sectors; /* Number of sectors in volume if Sectors is 0 (FAT) Zero on ntfs (0x15) */
|
|
||||||
} __attribute__((__packed__)) BIOS_PARAMETER_BLOCK; /* 25 (0x19) bytes */
|
|
||||||
|
|
||||||
typedef struct _VOLUME_BOOT_RECORD {
|
|
||||||
u8 Jump[3]; /* Irrelevant (jump to boot up code).*/
|
|
||||||
char Name[8]; /* Magic "NTFS ". */
|
|
||||||
BIOS_PARAMETER_BLOCK bpb; /* See BIOS_PARAMETER_BLOCK. (0x0b) */
|
|
||||||
u8 Drive_Type; /* 0x00 floppy, 0x80 hard disk */
|
|
||||||
u8 Current_Head; /* zero on ntfs */
|
|
||||||
u8 Extended_Boot_Signature; /* 0x80 on ntfs (Doesnt show this in M$ docs)*/
|
|
||||||
u8 Reserved0; /* zero on ntfs */
|
|
||||||
s64 Number_of_Sectors; /* Number of sectors in volume. (NTFS)(0x28)*/
|
|
||||||
s64 MFT; /* Cluster location of mft data. */
|
|
||||||
s64 MFT_Mirror; /* Cluster location of copy of mft. */
|
|
||||||
s8 Clusters_Per_MFT; /* Mft record size in clusters. */
|
|
||||||
u8 Reserved1[3]; /* zero */
|
|
||||||
s8 Clusters_Per_Index; /* Index block size in clusters. */
|
|
||||||
u8 Reserved2[3]; /* zero */
|
|
||||||
u64 Volume_Serial_Number; /* Irrelevant (serial number). */
|
|
||||||
u8 Checksum[4]; /* Boot sector checksum. */
|
|
||||||
u8 Bootstrap[426]; /* Irrelevant (boot up code). (0x54) */
|
|
||||||
u16 Signature; /* End of bootsector magic. LE 0xaa55 */
|
|
||||||
} __attribute__((__packed__)) VOLUME_BOOT_RECORD; /* 512 (0x200) bytes */
|
|
||||||
|
|
||||||
class PartitionHandle
|
class PartitionHandle
|
||||||
{
|
{
|
||||||
@ -173,7 +129,7 @@ class PartitionHandle
|
|||||||
//! Is the partition Mounted
|
//! Is the partition Mounted
|
||||||
bool IsMounted(int pos);
|
bool IsMounted(int pos);
|
||||||
//! Mount a specific Partition
|
//! Mount a specific Partition
|
||||||
bool Mount(int pos, const char * name);
|
bool Mount(int pos, const char * name, bool forceFAT = false);
|
||||||
//! UnMount a specific Partition
|
//! UnMount a specific Partition
|
||||||
void UnMount(int pos);
|
void UnMount(int pos);
|
||||||
//! UnMount all Partition
|
//! UnMount all Partition
|
||||||
@ -192,30 +148,29 @@ class PartitionHandle
|
|||||||
int GetPartitionType(int pos) { if(valid(pos)) return PartitionList[pos].PartitionType; else return -1; };
|
int GetPartitionType(int pos) { if(valid(pos)) return PartitionList[pos].PartitionType; else return -1; };
|
||||||
//! Get the entrie number in MBR of this partition
|
//! Get the entrie number in MBR of this partition
|
||||||
int GetPartitionNum(int pos) { if(valid(pos)) return PartitionList[pos].PartitionNum; else return -1; };
|
int GetPartitionNum(int pos) { if(valid(pos)) return PartitionList[pos].PartitionNum; else return -1; };
|
||||||
//! Get the EBR sector where this partition is described
|
|
||||||
int GetEBRSector(int pos) { if(valid(pos)) return PartitionList[pos].EBR_Sector; else return 0; };
|
|
||||||
//! Get the count of found partitions
|
//! Get the count of found partitions
|
||||||
int GetPartitionCount() { return PartitionList.size(); };
|
int GetPartitionCount() const { return PartitionList.size(); };
|
||||||
//! Get the partition size in bytes
|
//! Get the partition size in bytes
|
||||||
u64 GetSize(int pos) { if(valid(pos)) return (u64) PartitionList[pos].SecCount*BYTES_PER_SECTOR; else return 0; };
|
u64 GetSize(int pos) { if(valid(pos)) return (u64) PartitionList[pos].SecCount*BYTES_PER_SECTOR; else return 0; };
|
||||||
//! Get the wbfs mount handle
|
|
||||||
wbfs_t * GetWbfsHandle(int pos) { if(valid(pos)) return PartitionList[pos].wbfshandle; else return 0; };
|
|
||||||
//! Set the wbfs mount handle
|
|
||||||
bool SetWbfsHandle(int pos, wbfs_t * wbfshandle) { if(valid(pos)) {PartitionList[pos].wbfshandle = wbfshandle; return true;} else return false; };
|
|
||||||
//! Get the whole partition record struct
|
//! Get the whole partition record struct
|
||||||
PartitionFS * GetPartitionRecord(int pos) { if(valid(pos)) return &PartitionList[pos]; else return NULL; };
|
PartitionFS * GetPartitionRecord(int pos) { if(valid(pos)) return &PartitionList[pos]; else return NULL; };
|
||||||
//! Get the disc interface of this handle
|
//! Get the disc interface of this handle
|
||||||
const DISC_INTERFACE * GetDiscInterface() { return interface; };
|
const DISC_INTERFACE * GetDiscInterface() { return interface; };
|
||||||
|
//! Get the wbfs mount handle
|
||||||
|
wbfs_t *GetWbfsHandle(int pos) { if(valid(pos)) return PartitionList[pos].wbfshandle; else return 0; };
|
||||||
|
//! Set the wbfs mount handle
|
||||||
|
bool SetWbfsHandle(int pos, wbfs_t * wbfshandle) { if(valid(pos)) {PartitionList[pos].wbfshandle = wbfshandle; return true;} else return false; };
|
||||||
protected:
|
protected:
|
||||||
bool valid(int pos) { return (pos >= 0 && pos < (int) PartitionList.size()); }
|
bool valid(int pos) { return (pos >= 0 && pos < (int) PartitionList.size()); }
|
||||||
bool CheckRAW(VOLUME_BOOT_RECORD * vbr);
|
void AddPartition(const char * name, u64 lba_start, u64 sec_count, bool bootable, u8 part_type, u8 part_num);
|
||||||
|
bool IsExisting(u64 lba);
|
||||||
int FindPartitions();
|
int FindPartitions();
|
||||||
void CheckEBR(u8 PartNum, sec_t ebr_lba);
|
void CheckEBR(u8 PartNum, sec_t ebr_lba);
|
||||||
bool CheckGPT(void);
|
int CheckGPT(u8 PartNum);
|
||||||
|
|
||||||
const DISC_INTERFACE *interface;
|
const DISC_INTERFACE *interface;
|
||||||
vector<PartitionFS> PartitionList;
|
vector<PartitionFS> PartitionList;
|
||||||
vector<std::string> MountNameList;
|
vector<string> MountNameList;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
/*-------------------------------------------------------------
|
/*-------------------------------------------------------------
|
||||||
|
|
||||||
usbstorage_starlet.c -- USB mass storage support, inside starlet
|
usbstorage_starlet.c -- USB mass storage support, inside starlet
|
||||||
|
Copyright (C) 2011 Dimok
|
||||||
|
Copyright (C) 2011 Rodries
|
||||||
Copyright (C) 2009 Kwiirk
|
Copyright (C) 2009 Kwiirk
|
||||||
|
|
||||||
If this driver is linked before libogc, this will replace the original
|
If this driver is linked before libogc, this will replace the original
|
||||||
@ -30,9 +32,11 @@ distribution.
|
|||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include "usbstorage.h"
|
||||||
|
#include "memory/mem2.hpp"
|
||||||
#include "gecko.h"
|
#include "gecko.h"
|
||||||
|
|
||||||
|
|
||||||
/* IOCTL commands */
|
/* IOCTL commands */
|
||||||
#define UMS_BASE (('U'<<24)|('M'<<16)|('S'<<8))
|
#define UMS_BASE (('U'<<24)|('M'<<16)|('S'<<8))
|
||||||
#define USB_IOCTL_UMS_INIT (UMS_BASE+0x1)
|
#define USB_IOCTL_UMS_INIT (UMS_BASE+0x1)
|
||||||
@ -41,259 +45,292 @@ distribution.
|
|||||||
#define USB_IOCTL_UMS_WRITE_SECTORS (UMS_BASE+0x4)
|
#define USB_IOCTL_UMS_WRITE_SECTORS (UMS_BASE+0x4)
|
||||||
#define USB_IOCTL_UMS_READ_STRESS (UMS_BASE+0x5)
|
#define USB_IOCTL_UMS_READ_STRESS (UMS_BASE+0x5)
|
||||||
#define USB_IOCTL_UMS_SET_VERBOSE (UMS_BASE+0x6)
|
#define USB_IOCTL_UMS_SET_VERBOSE (UMS_BASE+0x6)
|
||||||
|
#define USB_IOCTL_UMS_UMOUNT (UMS_BASE+0x10)
|
||||||
#define USB_IOCTL_UMS_WATCHDOG (UMS_BASE+0x80)
|
#define USB_IOCTL_UMS_WATCHDOG (UMS_BASE+0x80)
|
||||||
|
|
||||||
#define UMS_HEAPSIZE 0x8000
|
#define USB_IOCTL_UMS_TESTMODE (UMS_BASE+0x81)
|
||||||
#define USB_MEM2_SIZE 0x10000
|
#define USB_IOCTL_SET_PORT (UMS_BASE+0x83)
|
||||||
|
|
||||||
|
#define WBFS_BASE (('W'<<24)|('F'<<16)|('S'<<8))
|
||||||
|
#define USB_IOCTL_WBFS_OPEN_DISC (WBFS_BASE+0x1)
|
||||||
|
#define USB_IOCTL_WBFS_READ_DISC (WBFS_BASE+0x2)
|
||||||
|
#define USB_IOCTL_WBFS_SET_DEVICE (WBFS_BASE+0x50)
|
||||||
|
#define USB_IOCTL_WBFS_SET_FRAGLIST (WBFS_BASE+0x51)
|
||||||
|
|
||||||
|
#define isMEM2Buffer(p) (((u32) p & 0x10000000) != 0)
|
||||||
|
|
||||||
|
#define MAX_SECTOR_SIZE 4096
|
||||||
|
#define MAX_BUFFER_SECTORS 128
|
||||||
|
#define UMS_HEAPSIZE 2*1024
|
||||||
|
|
||||||
/* Variables */
|
/* Variables */
|
||||||
static char fs[] ATTRIBUTE_ALIGN(32) = "/dev/usb2";
|
static char fs[] ATTRIBUTE_ALIGN(32) = "/dev/usb2";
|
||||||
static char fs2[] ATTRIBUTE_ALIGN(32) = "/dev/usb123";
|
static char fs2[] ATTRIBUTE_ALIGN(32) = "/dev/usb123";
|
||||||
static char fs3[] ATTRIBUTE_ALIGN(32) = "/dev/usb/ehc";
|
static char fs3[] ATTRIBUTE_ALIGN(32) = "/dev/usb/ehc";
|
||||||
|
|
||||||
|
static u8 * mem2_ptr = NULL;
|
||||||
static s32 hid = -1, fd = -1;
|
static s32 hid = -1, fd = -1;
|
||||||
u32 sector_size;
|
static u32 usb2_port = -1; //current USB port
|
||||||
static void *usb_buf2;
|
bool hddInUse[2] = { false, false };
|
||||||
|
u32 hdd_sector_size[2] = { 512, 512 };
|
||||||
|
|
||||||
extern void* SYS_AllocArena2MemLo(u32 size,u32 align);
|
s32 USBStorage2_Init(u32 port)
|
||||||
|
|
||||||
inline s32 __USBStorage_isMEM2Buffer(const void *buffer)
|
|
||||||
{
|
{
|
||||||
u32 high_addr = ((u32)buffer) >> 24;
|
if(hddInUse[port])
|
||||||
|
|
||||||
return (high_addr == 0x90) || (high_addr == 0xD0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
u32 USBStorage_GetCapacity(u32 *_sector_size)
|
|
||||||
{
|
|
||||||
if (fd >= 0)
|
|
||||||
{
|
|
||||||
u32 ret;
|
|
||||||
|
|
||||||
ret = IOS_IoctlvFormat(hid, fd, USB_IOCTL_UMS_GET_CAPACITY, ":i", §or_size);
|
|
||||||
|
|
||||||
static bool first = true;
|
|
||||||
if (first)
|
|
||||||
{
|
|
||||||
gprintf("\nSECTORS: %lu\n", ret);
|
|
||||||
gprintf("SEC SIZE: %lu\n", sector_size);
|
|
||||||
u32 size = ((((ret / 1024U) * sector_size) / 1024U) / 1024U);
|
|
||||||
if(size >= 1000U)
|
|
||||||
{
|
|
||||||
gprintf("HDD SIZE: %lu.%lu TB [%u]\n", size / 1024U, (size * 100U) % 1024U, sector_size);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
gprintf("HDD SIZE: %lu GB [%u]\n", size, sector_size);
|
|
||||||
}
|
|
||||||
first = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ret && _sector_size)
|
|
||||||
*_sector_size = sector_size;
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
|
|
||||||
s32 USBStorage_OpenDev()
|
|
||||||
{
|
|
||||||
/* Already open */
|
|
||||||
if (fd >= 0) return fd;
|
|
||||||
|
|
||||||
/* Create heap */
|
/* Create heap */
|
||||||
if (hid < 0)
|
if (hid < 0)
|
||||||
{
|
{
|
||||||
hid = iosCreateHeap(UMS_HEAPSIZE);
|
hid = iosCreateHeap(UMS_HEAPSIZE);
|
||||||
if (hid < 0) return IPC_ENOMEM; // = -22
|
if (hid < 0) return IPC_ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
// allocate buf2
|
|
||||||
if (usb_buf2 == NULL) usb_buf2 = SYS_AllocArena2MemLo(USB_MEM2_SIZE, 32);
|
|
||||||
|
|
||||||
/* Open USB device */
|
/* Open USB device */
|
||||||
fd = IOS_Open(fs, 0);
|
if (fd < 0) fd = IOS_Open(fs, 0);
|
||||||
if (fd < 0) fd = IOS_Open(fs2, 0);
|
if (fd < 0) fd = IOS_Open(fs2, 0);
|
||||||
if (fd < 0) fd = IOS_Open(fs3, 0);
|
if (fd < 0) fd = IOS_Open(fs3, 0);
|
||||||
return fd;
|
|
||||||
}
|
|
||||||
|
|
||||||
s32 USBStorage_SetWatchdog(u32 seconds)
|
|
||||||
{
|
|
||||||
if (fd < 0) return fd;
|
if (fd < 0) return fd;
|
||||||
|
|
||||||
static ioctlv vector[1] ATTRIBUTE_ALIGN(32);
|
USBStorage2_SetPort(port);
|
||||||
static u32 secs[8] ATTRIBUTE_ALIGN(32);
|
|
||||||
|
|
||||||
secs[0] = seconds;
|
|
||||||
vector[0].data = secs;
|
|
||||||
vector[0].len = 4;
|
|
||||||
|
|
||||||
return IOS_Ioctlv(fd, USB_IOCTL_UMS_WATCHDOG, 1, 0, vector);
|
|
||||||
}
|
|
||||||
|
|
||||||
s32 USBStorage_Init(void)
|
|
||||||
{
|
|
||||||
s32 ret;
|
|
||||||
USBStorage_OpenDev();
|
|
||||||
if (fd < 0) return fd;
|
|
||||||
|
|
||||||
/* Initialize USB storage */
|
/* Initialize USB storage */
|
||||||
ret = IOS_IoctlvFormat(hid, fd, USB_IOCTL_UMS_INIT, ":");
|
IOS_IoctlvFormat(hid, fd, USB_IOCTL_UMS_INIT, ":");
|
||||||
|
|
||||||
/* Get device capacity */
|
/* Get device capacity */
|
||||||
ret = USBStorage_GetCapacity(NULL);
|
if (USBStorage2_GetCapacity(port, &hdd_sector_size[port]) == 0)
|
||||||
if (!ret) goto err;
|
return IPC_ENOENT;
|
||||||
|
|
||||||
|
hddInUse[port] = true;
|
||||||
|
|
||||||
|
return 0; // 0->HDD, 1->DVD
|
||||||
|
}
|
||||||
|
|
||||||
|
void USBStorage2_Deinit()
|
||||||
|
{
|
||||||
|
/* Close USB device */
|
||||||
|
if (fd >= 0)
|
||||||
|
{
|
||||||
|
IOS_Close(fd); // not sure to close the fd is needed
|
||||||
|
fd = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 USBStorage2_SetPort(u32 port)
|
||||||
|
{
|
||||||
|
//! Port = 2 is handle in the loader, no need to handle it in cIOS
|
||||||
|
if(port > 1)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if(port == usb2_port)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err:
|
s32 ret = -1;
|
||||||
/* Close USB device */
|
usb2_port = port;
|
||||||
|
|
||||||
|
gprintf("Changing USB port to port %i....\n", port);
|
||||||
|
//must be called before USBStorage2_Init (default port 0)
|
||||||
if (fd >= 0)
|
if (fd >= 0)
|
||||||
{
|
ret = IOS_IoctlvFormat(hid, fd, USB_IOCTL_SET_PORT, "i:", usb2_port);
|
||||||
IOS_Close(fd);
|
|
||||||
fd = -1;
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
if (hid > 0) {
|
|
||||||
iosDestroyHeap(hid);
|
|
||||||
hid = -1;
|
|
||||||
} */
|
|
||||||
//USB_Deinitialize(); //Screwing up inputs even worse if i do this here..grr
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void USBStorage_Deinit(void)
|
|
||||||
{
|
|
||||||
/* Close USB device */
|
|
||||||
if (fd >= 0)
|
|
||||||
{
|
|
||||||
IOS_Close(fd);
|
|
||||||
fd = -1;
|
|
||||||
}
|
|
||||||
/* if (hid > 0) {
|
|
||||||
iosDestroyHeap(hid);
|
|
||||||
hid = -1;
|
|
||||||
} */
|
|
||||||
USB_Deinitialize();
|
|
||||||
}
|
|
||||||
|
|
||||||
s32 USBStorage_ReadSectors(u32 sector, u32 numSectors, void *buffer)
|
|
||||||
{
|
|
||||||
void *buf = (void *)buffer;
|
|
||||||
u32 len = (sector_size * numSectors);
|
|
||||||
s32 ret;
|
|
||||||
|
|
||||||
/* Device not opened */
|
|
||||||
if (fd < 0)
|
|
||||||
return fd;
|
|
||||||
|
|
||||||
/* MEM1 buffer */
|
|
||||||
if (!__USBStorage_isMEM2Buffer(buffer))
|
|
||||||
{
|
|
||||||
/* Allocate memory */
|
|
||||||
//buf = iosAlloc(hid, len);
|
|
||||||
buf = usb_buf2;
|
|
||||||
if (!buf) return IPC_ENOMEM;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Read data */
|
|
||||||
ret = IOS_IoctlvFormat(hid, fd, USB_IOCTL_UMS_READ_SECTORS, "ii:d", sector, numSectors, buf, len);
|
|
||||||
|
|
||||||
/* Copy data */
|
|
||||||
if (buf != buffer)
|
|
||||||
{
|
|
||||||
memcpy(buffer, buf, len);
|
|
||||||
//iosFree(hid, buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 USBStorage_WriteSectors(u32 sector, u32 numSectors, const void *buffer)
|
s32 USBStorage2_GetPort()
|
||||||
|
{
|
||||||
|
return usb2_port;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 USBStorage2_GetCapacity(u32 port, u32 *_sector_size)
|
||||||
|
{
|
||||||
|
if (fd >= 0)
|
||||||
{
|
{
|
||||||
void *buf = (void *)buffer;
|
|
||||||
u32 len = (sector_size * numSectors);
|
|
||||||
s32 ret;
|
s32 ret;
|
||||||
|
u32 sector_size = 0;
|
||||||
|
USBStorage2_SetPort(port);
|
||||||
|
|
||||||
|
ret = IOS_IoctlvFormat(hid, fd, USB_IOCTL_UMS_GET_CAPACITY, ":i", §or_size);
|
||||||
|
|
||||||
|
if (ret && _sector_size) *_sector_size = sector_size;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return IPC_ENOENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 USBStorage2_ReadSectors(u32 port, u32 sector, u32 numSectors, void *buffer)
|
||||||
|
{
|
||||||
|
u8 *buf = (u8 *) buffer;
|
||||||
|
s32 ret = -1;
|
||||||
|
|
||||||
/* Device not opened */
|
/* Device not opened */
|
||||||
if (fd < 0) return fd;
|
if (fd < 0) return fd;
|
||||||
|
|
||||||
/* MEM1 buffer */
|
if (!mem2_ptr)
|
||||||
if (!__USBStorage_isMEM2Buffer(buffer))
|
mem2_ptr = (u8 *) MEM2_alloc(MAX_SECTOR_SIZE * MAX_BUFFER_SECTORS);
|
||||||
{
|
|
||||||
/* Allocate memory */
|
|
||||||
//buf = iosAlloc(hid, len);
|
|
||||||
buf = usb_buf2;
|
|
||||||
if (!buf) return IPC_ENOMEM;
|
|
||||||
|
|
||||||
/* Copy data */
|
USBStorage2_SetPort(port);
|
||||||
memcpy(buf, buffer, len);
|
|
||||||
|
s32 read_secs, read_size;
|
||||||
|
|
||||||
|
while(numSectors > 0)
|
||||||
|
{
|
||||||
|
read_secs = numSectors > MAX_BUFFER_SECTORS ? MAX_BUFFER_SECTORS : numSectors;
|
||||||
|
read_size = read_secs*hdd_sector_size[port];
|
||||||
|
|
||||||
|
// Do not read more than MAX_BUFFER_SECTORS sectors at once and create a mem overflow!
|
||||||
|
if (!isMEM2Buffer(buffer))
|
||||||
|
{
|
||||||
|
ret = IOS_IoctlvFormat(hid, fd, USB_IOCTL_UMS_READ_SECTORS, "ii:d", sector, read_secs, mem2_ptr, read_size);
|
||||||
|
if(ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
memcpy(buf, mem2_ptr, read_size);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Read data */
|
||||||
|
ret = IOS_IoctlvFormat(hid, fd, USB_IOCTL_UMS_READ_SECTORS, "ii:d", sector, read_secs, buf, read_size);
|
||||||
|
if(ret < 0)
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Write data */
|
sector += read_secs;
|
||||||
ret = IOS_IoctlvFormat(hid, fd, USB_IOCTL_UMS_WRITE_SECTORS, "ii:d", sector, numSectors, buf, len);
|
numSectors -= read_secs;
|
||||||
|
buf += read_size;
|
||||||
/* Free memory */
|
}
|
||||||
//if (buf != buffer)
|
|
||||||
// iosFree(hid, buf);
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
// DISC_INTERFACE methods
|
s32 USBStorage2_WriteSectors(u32 port, u32 sector, u32 numSectors, const void *buffer)
|
||||||
|
|
||||||
static bool __io_usb_IsInserted(void)
|
|
||||||
{
|
{
|
||||||
s32 ret;
|
u8 *buf = (u8 *) buffer;
|
||||||
u32 sec_size;
|
s32 ret = -1;
|
||||||
if (fd < 0)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
ret = USBStorage_GetCapacity(&sec_size);
|
/* Device not opened */
|
||||||
if (ret == 0)
|
if (fd < 0) return fd;
|
||||||
return false;
|
|
||||||
return true;
|
/* Device not opened */
|
||||||
|
if (!mem2_ptr)
|
||||||
|
mem2_ptr = (u8 *) MEM2_alloc(MAX_SECTOR_SIZE * MAX_BUFFER_SECTORS);
|
||||||
|
|
||||||
|
USBStorage2_SetPort(port);
|
||||||
|
|
||||||
|
s32 write_size, write_secs;
|
||||||
|
|
||||||
|
while(numSectors > 0)
|
||||||
|
{
|
||||||
|
write_secs = numSectors > MAX_BUFFER_SECTORS ? MAX_BUFFER_SECTORS : numSectors;
|
||||||
|
write_size = write_secs*hdd_sector_size[port];
|
||||||
|
|
||||||
|
/* MEM1 buffer */
|
||||||
|
if (!isMEM2Buffer(buffer))
|
||||||
|
{
|
||||||
|
// Do not read more than MAX_BUFFER_SECTORS sectors at once and create a mem overflow!
|
||||||
|
memcpy(mem2_ptr, buf, write_size);
|
||||||
|
|
||||||
|
ret = IOS_IoctlvFormat(hid, fd, USB_IOCTL_UMS_WRITE_SECTORS, "ii:d", sector, write_secs, mem2_ptr, write_size);
|
||||||
|
if(ret < 0)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Write data */
|
||||||
|
ret = IOS_IoctlvFormat(hid, fd, USB_IOCTL_UMS_WRITE_SECTORS, "ii:d", sector, write_secs, buf, write_size);
|
||||||
|
if(ret < 0)
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool __io_usb_Startup(void)
|
sector += write_secs;
|
||||||
{
|
numSectors -= write_secs;
|
||||||
if (USBStorage_Init() < 0) return false;
|
buf += write_size;
|
||||||
return __io_usb_IsInserted();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool __io_usb_ReadSectors(u32 sector, u32 count, void *buffer)
|
return ret;
|
||||||
{
|
|
||||||
return USBStorage_ReadSectors(sector, count, buffer) >= 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool __io_usb_WriteSectors(u32 sector, u32 count, void *buffer)
|
s32 USBStorage2_GetSectorSize()
|
||||||
{
|
{
|
||||||
return USBStorage_WriteSectors(sector, count, buffer) >= 0;
|
return hdd_sector_size[usb2_port];
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool __io_usb_ClearStatus(void)
|
static bool __usbstorage_Startup(void)
|
||||||
|
{
|
||||||
|
return USBStorage2_Init(0) >= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool __usbstorage_IsInserted(void)
|
||||||
|
{
|
||||||
|
return (USBStorage2_GetCapacity(0, NULL) != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool __usbstorage_ReadSectors(u32 sector, u32 numSectors, void *buffer)
|
||||||
|
{
|
||||||
|
return (USBStorage2_ReadSectors(0, sector, numSectors, buffer) >= 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool __usbstorage_WriteSectors(u32 sector, u32 numSectors, const void *buffer)
|
||||||
|
{
|
||||||
|
return (USBStorage2_WriteSectors(0, sector, numSectors, buffer) >= 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool __usbstorage_ClearStatus(void)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool __io_usb_Shutdown(void)
|
static bool __usbstorage_Shutdown(void)
|
||||||
{
|
{
|
||||||
// do nothing
|
hddInUse[0] = false;
|
||||||
|
hdd_sector_size[0] = 512;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
DISC_INTERFACE __io_usbstorage = {
|
const DISC_INTERFACE __io_usbstorage2_port0 = {
|
||||||
DEVICE_TYPE_WII_USB,
|
DEVICE_TYPE_WII_UMS, FEATURE_MEDIUM_CANREAD | FEATURE_MEDIUM_CANWRITE | FEATURE_WII_USB,
|
||||||
FEATURE_MEDIUM_CANREAD | FEATURE_MEDIUM_CANWRITE | FEATURE_WII_USB,
|
(FN_MEDIUM_STARTUP) &__usbstorage_Startup,
|
||||||
(FN_MEDIUM_STARTUP) &__io_usb_Startup,
|
(FN_MEDIUM_ISINSERTED) &__usbstorage_IsInserted,
|
||||||
(FN_MEDIUM_ISINSERTED) &__io_usb_IsInserted,
|
(FN_MEDIUM_READSECTORS) &__usbstorage_ReadSectors,
|
||||||
(FN_MEDIUM_READSECTORS) &__io_usb_ReadSectors,
|
(FN_MEDIUM_WRITESECTORS) &__usbstorage_WriteSectors,
|
||||||
(FN_MEDIUM_WRITESECTORS) &__io_usb_WriteSectors,
|
(FN_MEDIUM_CLEARSTATUS) &__usbstorage_ClearStatus,
|
||||||
(FN_MEDIUM_CLEARSTATUS) &__io_usb_ClearStatus,
|
(FN_MEDIUM_SHUTDOWN) &__usbstorage_Shutdown
|
||||||
(FN_MEDIUM_SHUTDOWN) &__io_usb_Shutdown
|
};
|
||||||
|
|
||||||
|
static bool __usbstorage_Startup2(void)
|
||||||
|
{
|
||||||
|
return USBStorage2_Init(1) >= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool __usbstorage_IsInserted2(void)
|
||||||
|
{
|
||||||
|
return (USBStorage2_GetCapacity(1, NULL) != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool __usbstorage_ReadSectors2(u32 sector, u32 numSectors, void *buffer)
|
||||||
|
{
|
||||||
|
return (USBStorage2_ReadSectors(1, sector, numSectors, buffer) >= 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool __usbstorage_WriteSectors2(u32 sector, u32 numSectors, const void *buffer)
|
||||||
|
{
|
||||||
|
return (USBStorage2_WriteSectors(1, sector, numSectors, buffer) >= 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool __usbstorage_Shutdown2(void)
|
||||||
|
{
|
||||||
|
hddInUse[1] = false;
|
||||||
|
hdd_sector_size[1] = 512;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const DISC_INTERFACE __io_usbstorage2_port1 = {
|
||||||
|
DEVICE_TYPE_WII_UMS, FEATURE_MEDIUM_CANREAD | FEATURE_MEDIUM_CANWRITE | FEATURE_WII_USB,
|
||||||
|
(FN_MEDIUM_STARTUP) &__usbstorage_Startup2,
|
||||||
|
(FN_MEDIUM_ISINSERTED) &__usbstorage_IsInserted2,
|
||||||
|
(FN_MEDIUM_READSECTORS) &__usbstorage_ReadSectors2,
|
||||||
|
(FN_MEDIUM_WRITESECTORS) &__usbstorage_WriteSectors2,
|
||||||
|
(FN_MEDIUM_CLEARSTATUS) &__usbstorage_ClearStatus,
|
||||||
|
(FN_MEDIUM_SHUTDOWN) &__usbstorage_Shutdown2
|
||||||
};
|
};
|
@ -1,22 +1,32 @@
|
|||||||
#ifndef _USBSTORAGE_H_
|
#ifndef _USBSTORAGE2_H_
|
||||||
#define _USBSTORAGE_H_
|
#define _USBSTORAGE2_H_
|
||||||
|
|
||||||
#include <ogcsys.h>
|
#include "ogc/disc_io.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C"
|
||||||
#endif /* __cplusplus */
|
{
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Prototypes */
|
/* Prototypes */
|
||||||
s32 USBStorage_GetCapacity(u32 *);
|
s32 USBStorage2_Init(u32 port);
|
||||||
s32 USBStorage_SetWatchdog(u32);
|
void USBStorage2_Deinit();
|
||||||
s32 USBStorage_Init(void);
|
s32 USBStorage2_GetCapacity(u32 port, u32 *size);
|
||||||
void USBStorage_Deinit(void);
|
|
||||||
s32 USBStorage_ReadSectors(u32, u32, void *);
|
s32 USBStorage2_ReadSectors(u32 port, u32 sector, u32 numSectors, void *buffer);
|
||||||
s32 USBStorage_WriteSectors(u32, u32, void *);
|
s32 USBStorage2_WriteSectors(u32 port, u32 sector, u32 numSectors, const void *buffer);
|
||||||
|
s32 USBStorage2_GetSectorSize();
|
||||||
|
|
||||||
|
s32 USBStorage2_SetPort(u32 port);
|
||||||
|
s32 USBStorage2_GetPort();
|
||||||
|
|
||||||
|
#define DEVICE_TYPE_WII_UMS (('W'<<24)|('U'<<16)|('M'<<8)|'S')
|
||||||
|
|
||||||
|
extern const DISC_INTERFACE __io_usbstorage2_port0;
|
||||||
|
extern const DISC_INTERFACE __io_usbstorage2_port1;
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif /* __cplusplus */
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -87,7 +87,7 @@ bool loadIOS(int ios, bool launch_game)
|
|||||||
DeviceHandler::Instance()->UnMountAll();
|
DeviceHandler::Instance()->UnMountAll();
|
||||||
|
|
||||||
WDVD_Close();
|
WDVD_Close();
|
||||||
USBStorage_Deinit();
|
USBStorage2_Deinit();
|
||||||
mload_close();
|
mload_close();
|
||||||
|
|
||||||
bool iosOK = IOS_ReloadIOS(ios) == 0;
|
bool iosOK = IOS_ReloadIOS(ios) == 0;
|
||||||
|
@ -29,8 +29,6 @@
|
|||||||
/* WBFS device */
|
/* WBFS device */
|
||||||
s32 wbfsDev = WBFS_MIN_DEVICE;
|
s32 wbfsDev = WBFS_MIN_DEVICE;
|
||||||
|
|
||||||
extern u32 sector_size;
|
|
||||||
|
|
||||||
// partition
|
// partition
|
||||||
int wbfs_part_fs = PART_FS_WBFS;
|
int wbfs_part_fs = PART_FS_WBFS;
|
||||||
u32 wbfs_part_idx = 0;
|
u32 wbfs_part_idx = 0;
|
||||||
@ -99,7 +97,7 @@ s32 __WBFS_ReadUSB(void* fp, u32 lba, u32 count, void *iobuf)
|
|||||||
/* Do reads */
|
/* Do reads */
|
||||||
while (cnt < count)
|
while (cnt < count)
|
||||||
{
|
{
|
||||||
fp = ((u8 *)iobuf) + (cnt * sector_size);
|
fp = ((u8 *)iobuf) + (cnt * USBStorage2_GetSectorSize());
|
||||||
u32 sectors = (count - cnt);
|
u32 sectors = (count - cnt);
|
||||||
|
|
||||||
/* Read sectors is too big */
|
/* Read sectors is too big */
|
||||||
@ -107,7 +105,7 @@ s32 __WBFS_ReadUSB(void* fp, u32 lba, u32 count, void *iobuf)
|
|||||||
sectors = MAX_NB_SECTORS;
|
sectors = MAX_NB_SECTORS;
|
||||||
|
|
||||||
/* USB read */
|
/* USB read */
|
||||||
s32 ret = USBStorage_ReadSectors(lba + cnt, sectors, fp);
|
s32 ret = USBStorage2_ReadSectors(USBStorage2_GetPort(), lba + cnt, sectors, fp);
|
||||||
if (ret < 0) return ret;
|
if (ret < 0) return ret;
|
||||||
|
|
||||||
/* Increment counter */
|
/* Increment counter */
|
||||||
@ -124,7 +122,7 @@ s32 __WBFS_WriteUSB(void* fp, u32 lba, u32 count, void *iobuf)
|
|||||||
/* Do writes */
|
/* Do writes */
|
||||||
while (cnt < count)
|
while (cnt < count)
|
||||||
{
|
{
|
||||||
fp = ((u8 *)iobuf) + (cnt * sector_size);
|
fp = ((u8 *)iobuf) + (cnt * USBStorage2_GetSectorSize());
|
||||||
u32 sectors = (count - cnt);
|
u32 sectors = (count - cnt);
|
||||||
|
|
||||||
/* Write sectors is too big */
|
/* Write sectors is too big */
|
||||||
@ -132,7 +130,7 @@ s32 __WBFS_WriteUSB(void* fp, u32 lba, u32 count, void *iobuf)
|
|||||||
sectors = MAX_NB_SECTORS;
|
sectors = MAX_NB_SECTORS;
|
||||||
|
|
||||||
/* USB write */
|
/* USB write */
|
||||||
s32 ret = USBStorage_WriteSectors(lba + cnt, sectors, fp);
|
s32 ret = USBStorage2_WriteSectors(USBStorage2_GetPort(), lba + cnt, sectors, fp);
|
||||||
if (ret < 0) return ret;
|
if (ret < 0) return ret;
|
||||||
|
|
||||||
/* Increment counter */
|
/* Increment counter */
|
||||||
@ -149,7 +147,7 @@ s32 __WBFS_ReadSDHC(void* fp, u32 lba, u32 count, void *iobuf)
|
|||||||
/* Do reads */
|
/* Do reads */
|
||||||
while (cnt < count)
|
while (cnt < count)
|
||||||
{
|
{
|
||||||
fp = ((u8 *)iobuf) + (cnt * sector_size);
|
fp = ((u8 *)iobuf) + (cnt * 512);
|
||||||
u32 sectors = (count - cnt);
|
u32 sectors = (count - cnt);
|
||||||
|
|
||||||
/* Read sectors is too big */
|
/* Read sectors is too big */
|
||||||
@ -175,7 +173,7 @@ s32 __WBFS_WriteSDHC(void* fp, u32 lba, u32 count, void *iobuf)
|
|||||||
/* Do writes */
|
/* Do writes */
|
||||||
while (cnt < count)
|
while (cnt < count)
|
||||||
{
|
{
|
||||||
fp = ((u8 *)iobuf) + (cnt * sector_size);
|
fp = ((u8 *)iobuf) + (cnt * 512);
|
||||||
u32 sectors = (count - cnt);
|
u32 sectors = (count - cnt);
|
||||||
|
|
||||||
/* Write sectors is too big */
|
/* Write sectors is too big */
|
||||||
@ -231,6 +229,7 @@ s32 WBFS_Init(wbfs_t * handle, u32 part_fs, u32 part_idx, u32 part_lba, char *pa
|
|||||||
|
|
||||||
s32 WBFS_Format(u32 lba, u32 size)
|
s32 WBFS_Format(u32 lba, u32 size)
|
||||||
{
|
{
|
||||||
|
u32 sector_size = (currentPartition == 0) ? 512 : USBStorage2_GetSectorSize();
|
||||||
u32 wbfs_sector_size = sector_size;
|
u32 wbfs_sector_size = sector_size;
|
||||||
u32 partition_num_sec = size;
|
u32 partition_num_sec = size;
|
||||||
|
|
||||||
@ -310,7 +309,7 @@ s32 WBFS_GameSize(u8 *discid, char *path, f32 *size)
|
|||||||
|
|
||||||
s32 WBFS_DVD_Size(u64 *comp_size, u64 *real_size)
|
s32 WBFS_DVD_Size(u64 *comp_size, u64 *real_size)
|
||||||
{
|
{
|
||||||
if (wbfs_part_fs) return WBFS_Ext_DVD_Size(comp_size, real_size);
|
if (wbfs_part_fs) return WBFS_Ext_DVD_Size(comp_size, real_size, (currentPartition == 0));
|
||||||
|
|
||||||
u32 comp_sec = 0, last_sec = 0;
|
u32 comp_sec = 0, last_sec = 0;
|
||||||
|
|
||||||
|
@ -26,8 +26,6 @@
|
|||||||
#define MAX_FAT_PATH 1024
|
#define MAX_FAT_PATH 1024
|
||||||
#define TITLE_LEN 64
|
#define TITLE_LEN 64
|
||||||
|
|
||||||
extern u32 sector_size;
|
|
||||||
|
|
||||||
char wbfs_fs_drive[16];
|
char wbfs_fs_drive[16];
|
||||||
char wbfs_ext_dir[16] = "/wbfs";
|
char wbfs_ext_dir[16] = "/wbfs";
|
||||||
char invalid_path[] = "/\\:|<>?*\"'";
|
char invalid_path[] = "/\\:|<>?*\"'";
|
||||||
@ -46,6 +44,7 @@ char* strcopy(char *dest, const char *src, int size)
|
|||||||
|
|
||||||
wbfs_disc_t* WBFS_Ext_OpenDisc(u8 *discid, char *fname)
|
wbfs_disc_t* WBFS_Ext_OpenDisc(u8 *discid, char *fname)
|
||||||
{
|
{
|
||||||
|
bool sd = strstr(fname, "sd") != NULL;
|
||||||
if (strcasecmp(strrchr(fname,'.'), ".iso") == 0)
|
if (strcasecmp(strrchr(fname,'.'), ".iso") == 0)
|
||||||
{
|
{
|
||||||
// .iso file
|
// .iso file
|
||||||
@ -58,7 +57,7 @@ wbfs_disc_t* WBFS_Ext_OpenDisc(u8 *discid, char *fname)
|
|||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
// mark with a special wbfs_part
|
// mark with a special wbfs_part
|
||||||
wbfs_iso_file.wbfs_sec_sz = sector_size;
|
wbfs_iso_file.wbfs_sec_sz = sd ? 512 : USBStorage2_GetSectorSize();
|
||||||
iso_file->p = &wbfs_iso_file;
|
iso_file->p = &wbfs_iso_file;
|
||||||
iso_file->header = (void*)fd;
|
iso_file->header = (void*)fd;
|
||||||
return iso_file;
|
return iso_file;
|
||||||
@ -116,12 +115,13 @@ s32 WBFS_Ext_DiskSpace(f32 *used, f32 *free)
|
|||||||
|
|
||||||
wbfs_t* WBFS_Ext_OpenPart(char *fname)
|
wbfs_t* WBFS_Ext_OpenPart(char *fname)
|
||||||
{
|
{
|
||||||
|
bool sd = strstr(fname, "sd") != NULL;
|
||||||
if(split_open(&split, fname) < 0)
|
if(split_open(&split, fname) < 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
wbfs_set_force_mode(1);
|
wbfs_set_force_mode(1);
|
||||||
wbfs_t *part = wbfs_open_partition(split_read_sector, 0, //readonly //split_write_sector,
|
wbfs_t *part = wbfs_open_partition(split_read_sector, 0, //readonly //split_write_sector,
|
||||||
&split, sector_size, split.total_sec, 0, 0);
|
&split, sd ? 512 : USBStorage2_GetSectorSize(), split.total_sec, 0, 0);
|
||||||
wbfs_set_force_mode(0);
|
wbfs_set_force_mode(0);
|
||||||
|
|
||||||
if (!part)
|
if (!part)
|
||||||
@ -223,17 +223,16 @@ s32 WBFS_Ext_AddGame(progress_callback_t spinner, void *spinner_data)
|
|||||||
return ret < 0 ? ret : 0;
|
return ret < 0 ? ret : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 WBFS_Ext_DVD_Size(u64 *comp_size, u64 *real_size)
|
s32 WBFS_Ext_DVD_Size(u64 *comp_size, u64 *real_size, bool sd)
|
||||||
{
|
{
|
||||||
u64 size = (u64)143432*2*0x8000ULL;
|
u64 size = (u64)143432*2*0x8000ULL;
|
||||||
u32 n_sector = size / 512;
|
u32 n_sector = size / 512;
|
||||||
|
|
||||||
// init a temporary dummy part
|
// init a temporary dummy part
|
||||||
// as a placeholder for wbfs_size_disc
|
// as a placeholder for wbfs_size_disc
|
||||||
wbfs_t *part = wbfs_open_partition(
|
wbfs_t *part = wbfs_open_partition(0, 0, NULL, sd ? 512 : USBStorage2_GetSectorSize(), n_sector, 0, 1);
|
||||||
0, 0,
|
if (!part)
|
||||||
NULL, sector_size, n_sector, 0, 1);
|
return -1;
|
||||||
if (!part) return -1;
|
|
||||||
|
|
||||||
u32 comp_sec = 0, last_sec = 0;
|
u32 comp_sec = 0, last_sec = 0;
|
||||||
s32 ret = wbfs_size_disc(part, __WBFS_ReadDVD, NULL, ONLY_GAME_PARTITION, &comp_sec, &last_sec);
|
s32 ret = wbfs_size_disc(part, __WBFS_ReadDVD, NULL, ONLY_GAME_PARTITION, &comp_sec, &last_sec);
|
||||||
|
@ -16,7 +16,7 @@ void WBFS_Ext_CloseDisc(wbfs_disc_t* disc);
|
|||||||
s32 WBFS_Ext_DiskSpace(f32 *used, f32 *free);
|
s32 WBFS_Ext_DiskSpace(f32 *used, f32 *free);
|
||||||
s32 WBFS_Ext_RemoveGame(u8 *discid, char *path);
|
s32 WBFS_Ext_RemoveGame(u8 *discid, char *path);
|
||||||
s32 WBFS_Ext_AddGame(progress_callback_t spinner, void *spinner_data);
|
s32 WBFS_Ext_AddGame(progress_callback_t spinner, void *spinner_data);
|
||||||
s32 WBFS_Ext_DVD_Size(u64 *comp_size, u64 *real_size);
|
s32 WBFS_Ext_DVD_Size(u64 *comp_size, u64 *real_size, bool sd);
|
||||||
int WBFS_Ext_find_fname(u8 *id, char *path, char *fname, int len);
|
int WBFS_Ext_find_fname(u8 *id, char *path, char *fname, int len);
|
||||||
|
|
||||||
char* strcopy(char *dest, const char *src, int size);
|
char* strcopy(char *dest, const char *src, int size);
|
||||||
|
@ -88,19 +88,18 @@ int main(int argc, char **argv)
|
|||||||
{
|
{
|
||||||
Open_Inputs(); //(re)init wiimote
|
Open_Inputs(); //(re)init wiimote
|
||||||
#ifndef DOLPHIN
|
#ifndef DOLPHIN
|
||||||
|
const DISC_INTERFACE *handle = DeviceHandler::GetUSB0Interface();
|
||||||
bool deviceAvailable = false;
|
bool deviceAvailable = false;
|
||||||
u8 timeout = 0;
|
u8 timeout = 0;
|
||||||
|
DeviceHandler::Instance()->MountSD();
|
||||||
while(!deviceAvailable && timeout++ != 20)
|
while(!deviceAvailable && timeout++ != 20)
|
||||||
{
|
{
|
||||||
DeviceHandler::Instance()->MountAll();
|
deviceAvailable = (handle->startup() && handle->isInserted());
|
||||||
sleep(1);
|
if(deviceAvailable)
|
||||||
|
break;
|
||||||
for(u8 device = USB1; device <= USB8; device++)
|
usleep(50000);
|
||||||
{
|
|
||||||
if(DeviceHandler::Instance()->IsInserted(device))
|
|
||||||
deviceAvailable = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
DeviceHandler::Instance()->MountAllUSB();
|
||||||
if(DeviceHandler::Instance()->IsInserted(SD))
|
if(DeviceHandler::Instance()->IsInserted(SD))
|
||||||
deviceAvailable = true;
|
deviceAvailable = true;
|
||||||
#else
|
#else
|
||||||
|
@ -309,7 +309,7 @@ void CMenu::init(void)
|
|||||||
m_screenshotDir = m_cfg.getString("GENERAL", "dir_screenshot", sfmt("%s/screenshots", m_dataDir.c_str()));
|
m_screenshotDir = m_cfg.getString("GENERAL", "dir_screenshot", sfmt("%s/screenshots", m_dataDir.c_str()));
|
||||||
m_helpDir = m_cfg.getString("GENERAL", "dir_help", sfmt("%s/help", m_dataDir.c_str()));
|
m_helpDir = m_cfg.getString("GENERAL", "dir_help", sfmt("%s/help", m_dataDir.c_str()));
|
||||||
|
|
||||||
DeviceHandler::SetWatchdog(m_cfg.getUInt("GENERAL", "watchdog_timeout", 10));
|
//DeviceHandler::SetWatchdog(m_cfg.getUInt("GENERAL", "watchdog_timeout", 10));
|
||||||
|
|
||||||
const char *domain = _domainFromView();
|
const char *domain = _domainFromView();
|
||||||
const char *checkDir = m_current_view == COVERFLOW_HOMEBREW ? HOMEBREW_DIR : GAMES_DIR;
|
const char *checkDir = m_current_view == COVERFLOW_HOMEBREW ? HOMEBREW_DIR : GAMES_DIR;
|
||||||
@ -491,7 +491,7 @@ void CMenu::cleanup()
|
|||||||
{
|
{
|
||||||
if(cleaned_up)
|
if(cleaned_up)
|
||||||
return;
|
return;
|
||||||
|
gprintf("MEM1_freesize(): %i\nMEM2_freesize(): %i\n", MEM1_freesize(), MEM2_freesize());
|
||||||
m_cf.stopCoverLoader();
|
m_cf.stopCoverLoader();
|
||||||
_cleanupDefaultFont();
|
_cleanupDefaultFont();
|
||||||
m_cf.clear();
|
m_cf.clear();
|
||||||
@ -542,6 +542,7 @@ void CMenu::cleanup()
|
|||||||
|
|
||||||
cleaned_up = true;
|
cleaned_up = true;
|
||||||
gprintf(" \nMemory cleaned up\n");
|
gprintf(" \nMemory cleaned up\n");
|
||||||
|
gprintf("MEM1_freesize(): %i\nMEM2_freesize(): %i\n", MEM1_freesize(), MEM2_freesize());
|
||||||
}
|
}
|
||||||
|
|
||||||
void CMenu::_reload_wifi_gecko(void)
|
void CMenu::_reload_wifi_gecko(void)
|
||||||
|
@ -61,7 +61,6 @@ extern const u8 blank_png[];
|
|||||||
extern const u8 gc_ogg[];
|
extern const u8 gc_ogg[];
|
||||||
extern const u32 gc_ogg_size;
|
extern const u32 gc_ogg_size;
|
||||||
|
|
||||||
extern u32 sector_size;
|
|
||||||
extern u32 boot2version;
|
extern u32 boot2version;
|
||||||
extern int mainIOS;
|
extern int mainIOS;
|
||||||
static u64 sm_title_id[8] ATTRIBUTE_ALIGN(32);
|
static u64 sm_title_id[8] ATTRIBUTE_ALIGN(32);
|
||||||
@ -871,7 +870,7 @@ void CMenu::_launchGC(dir_discHdr *hdr, bool disc)
|
|||||||
cleanup();
|
cleanup();
|
||||||
#ifndef DOLPHIN
|
#ifndef DOLPHIN
|
||||||
ISFS_Deinitialize();
|
ISFS_Deinitialize();
|
||||||
USBStorage_Deinit();
|
USBStorage2_Deinit();
|
||||||
SDHC_Init();
|
SDHC_Init();
|
||||||
#endif
|
#endif
|
||||||
GC_SetVideoMode(videoMode, videoSetting);
|
GC_SetVideoMode(videoMode, videoSetting);
|
||||||
@ -910,7 +909,7 @@ void CMenu::_launchHomebrew(const char *filepath, vector<string> arguments)
|
|||||||
AddBootArgument(arguments[i].c_str());
|
AddBootArgument(arguments[i].c_str());
|
||||||
#ifndef DOLPHIN
|
#ifndef DOLPHIN
|
||||||
ISFS_Deinitialize();
|
ISFS_Deinitialize();
|
||||||
USBStorage_Deinit();
|
USBStorage2_Deinit();
|
||||||
#endif
|
#endif
|
||||||
//MEM2_clear();
|
//MEM2_clear();
|
||||||
BootHomebrew(title);
|
BootHomebrew(title);
|
||||||
@ -1285,8 +1284,7 @@ void CMenu::_launchGame(dir_discHdr *hdr, bool dvd)
|
|||||||
Nand::Instance()->Do_Region_Change(id);
|
Nand::Instance()->Do_Region_Change(id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if(!dvd && get_frag_list((u8 *)id.c_str(), (char*)path.c_str(), currentPartition == 0 ? 0x200 : USBStorage2_GetSectorSize()) < 0)
|
||||||
if(!dvd && get_frag_list((u8 *)id.c_str(), (char*)path.c_str(), currentPartition == 0 ? 0x200 : sector_size) < 0)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
u8 patchVidMode = min((u32)m_gcfg2.getInt(id, "patch_video_modes", 0), ARRAY_SIZE(CMenu::_vidModePatch) - 1u);
|
u8 patchVidMode = min((u32)m_gcfg2.getInt(id, "patch_video_modes", 0), ARRAY_SIZE(CMenu::_vidModePatch) - 1u);
|
||||||
@ -1406,7 +1404,7 @@ void CMenu::_launchGame(dir_discHdr *hdr, bool dvd)
|
|||||||
}
|
}
|
||||||
#ifndef DOLPHIN
|
#ifndef DOLPHIN
|
||||||
ISFS_Deinitialize();
|
ISFS_Deinitialize();
|
||||||
USBStorage_Deinit();
|
USBStorage2_Deinit();
|
||||||
if(currentPartition == 0)
|
if(currentPartition == 0)
|
||||||
SDHC_Init();
|
SDHC_Init();
|
||||||
#endif
|
#endif
|
||||||
|
@ -56,8 +56,7 @@ static inline int GetFirstUnusedVoice()
|
|||||||
extern "C" void SoundCallback(s32 voice)
|
extern "C" void SoundCallback(s32 voice)
|
||||||
{
|
{
|
||||||
SoundDecoder * decoder = SoundHandler::Instance()->Decoder(voice);
|
SoundDecoder * decoder = SoundHandler::Instance()->Decoder(voice);
|
||||||
if(!decoder)
|
if(!decoder) return;
|
||||||
return;
|
|
||||||
|
|
||||||
if(decoder->IsBufferReady())
|
if(decoder->IsBufferReady())
|
||||||
{
|
{
|
||||||
@ -99,13 +98,12 @@ GuiSound::GuiSound(GuiSound *g)
|
|||||||
voice = -1;
|
voice = -1;
|
||||||
|
|
||||||
Init();
|
Init();
|
||||||
if (g == NULL)
|
if (g == NULL) return;
|
||||||
return;
|
|
||||||
|
|
||||||
if (g->sound != NULL)
|
if (g->sound != NULL)
|
||||||
{
|
{
|
||||||
u8 *snd = (u8 *)MEM1_alloc(g->length);
|
u8 * snd = (u8 *) malloc(g->length);
|
||||||
memcpy(snd, g->sound, length);
|
memcpy(snd, g->sound, g->length);
|
||||||
Load(snd, g->length, true);
|
Load(snd, g->length, true);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -144,9 +142,11 @@ void GuiSound::FreeMemory()
|
|||||||
|
|
||||||
if(allocated)
|
if(allocated)
|
||||||
{
|
{
|
||||||
MEM1_free(sound);
|
free(sound);
|
||||||
allocated = false;
|
allocated = false;
|
||||||
}
|
}
|
||||||
|
sound = NULL;
|
||||||
|
length = 0;
|
||||||
filepath = "";
|
filepath = "";
|
||||||
|
|
||||||
SoundEffectLength = 0;
|
SoundEffectLength = 0;
|
||||||
@ -161,8 +161,7 @@ bool GuiSound::Load(const char * filepath)
|
|||||||
|
|
||||||
FILE * f = fopen(filepath, "rb");
|
FILE * f = fopen(filepath, "rb");
|
||||||
if(!f)
|
if(!f)
|
||||||
{
|
{ gprintf("Failed to load file %s!!\n", filepath);
|
||||||
gprintf("Failed to load file %s!!\n", filepath);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -174,14 +173,12 @@ bool GuiSound::Load(const char * filepath)
|
|||||||
gprintf("Loading %s using voice %d\n", filepath, voice);
|
gprintf("Loading %s using voice %d\n", filepath, voice);
|
||||||
SoundDecoder * decoder = SoundHandler::Instance()->Decoder(voice);
|
SoundDecoder * decoder = SoundHandler::Instance()->Decoder(voice);
|
||||||
if(!decoder)
|
if(!decoder)
|
||||||
{
|
{ gprintf("No Decoder!!!\n");
|
||||||
gprintf("No Decoder!!!\n");
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!decoder->IsBufferReady())
|
if(!decoder->IsBufferReady())
|
||||||
{
|
{ gprintf("Buffer not ready!!n");
|
||||||
gprintf("Buffer not ready!!\n");
|
|
||||||
SoundHandler::Instance()->RemoveDecoder(voice);
|
SoundHandler::Instance()->RemoveDecoder(voice);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -197,14 +194,15 @@ bool GuiSound::Load(const u8 * snd, u32 len, bool isallocated)
|
|||||||
FreeMemory();
|
FreeMemory();
|
||||||
this->voice = voice;
|
this->voice = voice;
|
||||||
|
|
||||||
if(!snd)
|
if(!snd) return false;
|
||||||
return false;
|
|
||||||
|
|
||||||
if(!isallocated && *((u32 *) snd) == 'RIFF')
|
if(!isallocated && *((u32 *) snd) == 'RIFF')
|
||||||
return LoadSoundEffect(snd, len);
|
return LoadSoundEffect(snd, len);
|
||||||
|
|
||||||
if(*((u32 *) snd) == 'IMD5')
|
if(*((u32 *) snd) == 'IMD5')
|
||||||
|
{
|
||||||
UncompressSoundbin(snd, len, isallocated);
|
UncompressSoundbin(snd, len, isallocated);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
sound = (u8 *) snd;
|
sound = (u8 *) snd;
|
||||||
@ -216,7 +214,9 @@ bool GuiSound::Load(const u8 * snd, u32 len, bool isallocated)
|
|||||||
|
|
||||||
SoundDecoder * decoder = SoundHandler::Instance()->Decoder(voice);
|
SoundDecoder * decoder = SoundHandler::Instance()->Decoder(voice);
|
||||||
if(!decoder)
|
if(!decoder)
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if(!decoder->IsBufferReady())
|
if(!decoder->IsBufferReady())
|
||||||
{
|
{
|
||||||
@ -237,15 +237,15 @@ bool GuiSound::LoadSoundEffect(const u8 * snd, u32 len)
|
|||||||
decoder.Rewind();
|
decoder.Rewind();
|
||||||
|
|
||||||
u32 done = 0;
|
u32 done = 0;
|
||||||
sound = (u8 *)MEM1_alloc(4096);
|
sound = (u8 *)malloc(4096);
|
||||||
memset(sound, 0, 4096);
|
memset(sound, 0, 4096);
|
||||||
|
|
||||||
while(1)
|
while(1)
|
||||||
{
|
{
|
||||||
u8 * tmpsnd = (u8 *)MEM1_realloc(sound, done+4096);
|
u8 * tmpsnd = (u8 *)realloc(sound, done+4096);
|
||||||
if(!tmpsnd)
|
if(!tmpsnd)
|
||||||
{
|
{
|
||||||
MEM1_free(sound);
|
free(sound);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -258,7 +258,7 @@ bool GuiSound::LoadSoundEffect(const u8 * snd, u32 len)
|
|||||||
done += read;
|
done += read;
|
||||||
}
|
}
|
||||||
|
|
||||||
sound = (u8 *)MEM1_realloc(sound, done);
|
sound = (u8 *)realloc(sound, done);
|
||||||
SoundEffectLength = done;
|
SoundEffectLength = done;
|
||||||
allocated = true;
|
allocated = true;
|
||||||
|
|
||||||
@ -274,15 +274,10 @@ void GuiSound::Play(int vol, bool restart)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(IsPlaying() && !restart)
|
if((IsPlaying() && !restart) || voice < 0 || voice >= 16) return;
|
||||||
return;
|
|
||||||
|
|
||||||
if(voice < 0 || voice >= 16)
|
|
||||||
return;
|
|
||||||
|
|
||||||
SoundDecoder * decoder = SoundHandler::Instance()->Decoder(voice);
|
SoundDecoder * decoder = SoundHandler::Instance()->Decoder(voice);
|
||||||
if(!decoder)
|
if(!decoder) return;
|
||||||
return;
|
|
||||||
|
|
||||||
ASND_StopVoice(voice);
|
ASND_StopVoice(voice);
|
||||||
if(decoder->IsEOF())
|
if(decoder->IsEOF())
|
||||||
@ -307,16 +302,14 @@ void GuiSound::Play()
|
|||||||
|
|
||||||
void GuiSound::Stop()
|
void GuiSound::Stop()
|
||||||
{
|
{
|
||||||
if (!IsPlaying()) return;
|
volume = 0;
|
||||||
|
if (!IsPlaying() || voice < 0 || voice >= 16)
|
||||||
if(voice < 0 || voice >= 16)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ASND_StopVoice(voice);
|
ASND_StopVoice(voice);
|
||||||
|
|
||||||
SoundDecoder * decoder = SoundHandler::Instance()->Decoder(voice);
|
SoundDecoder * decoder = SoundHandler::Instance()->Decoder(voice);
|
||||||
if(!decoder)
|
if(!decoder) return;
|
||||||
return;
|
|
||||||
|
|
||||||
decoder->ClearBuffer();
|
decoder->ClearBuffer();
|
||||||
Rewind();
|
Rewind();
|
||||||
@ -357,10 +350,7 @@ int GuiSound::GetVolume()
|
|||||||
|
|
||||||
void GuiSound::SetVolume(int vol)
|
void GuiSound::SetVolume(int vol)
|
||||||
{
|
{
|
||||||
if(voice < 0 || voice >= 16)
|
if(voice < 0 || voice >= 16 || vol < 0)
|
||||||
return;
|
|
||||||
|
|
||||||
if(vol < 0)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
volume = vol;
|
volume = vol;
|
||||||
@ -372,8 +362,7 @@ void GuiSound::SetLoop(u8 l)
|
|||||||
loop = l;
|
loop = l;
|
||||||
|
|
||||||
SoundDecoder * decoder = SoundHandler::Instance()->Decoder(voice);
|
SoundDecoder * decoder = SoundHandler::Instance()->Decoder(voice);
|
||||||
if(!decoder)
|
if(!decoder) return;
|
||||||
return;
|
|
||||||
|
|
||||||
decoder->SetLoop(l == 1);
|
decoder->SetLoop(l == 1);
|
||||||
}
|
}
|
||||||
@ -381,8 +370,7 @@ void GuiSound::SetLoop(u8 l)
|
|||||||
void GuiSound::Rewind()
|
void GuiSound::Rewind()
|
||||||
{
|
{
|
||||||
SoundDecoder * decoder = SoundHandler::Instance()->Decoder(voice);
|
SoundDecoder * decoder = SoundHandler::Instance()->Decoder(voice);
|
||||||
if(!decoder)
|
if(!decoder) return;
|
||||||
return;
|
|
||||||
|
|
||||||
decoder->Rewind();
|
decoder->Rewind();
|
||||||
}
|
}
|
||||||
@ -407,10 +395,9 @@ u8 * uncompressLZ77(const u8 *inBuf, u32 inLength, u32 * size)
|
|||||||
const u8 *inBufEnd = inBuf + inLength;
|
const u8 *inBufEnd = inBuf + inLength;
|
||||||
inBuf += 8;
|
inBuf += 8;
|
||||||
|
|
||||||
buffer = (u8 *)MEM1_alloc(uncSize);
|
buffer = (u8 *)malloc(uncSize);
|
||||||
|
|
||||||
if (!buffer)
|
if (!buffer) return buffer;
|
||||||
return buffer;
|
|
||||||
|
|
||||||
u8 *bufCur = buffer;
|
u8 *bufCur = buffer;
|
||||||
u8 *bufEnd = buffer + uncSize;
|
u8 *bufEnd = buffer + uncSize;
|
||||||
@ -452,8 +439,7 @@ void GuiSound::UncompressSoundbin(const u8 * snd, u32 len, bool isallocated)
|
|||||||
const u8 * file = snd+32;
|
const u8 * file = snd+32;
|
||||||
|
|
||||||
length = len-32;
|
length = len-32;
|
||||||
if (length <= 0)
|
if (length <= 0) return;
|
||||||
return;
|
|
||||||
|
|
||||||
if(*((u32 *) file) == 'LZ77')
|
if(*((u32 *) file) == 'LZ77')
|
||||||
{
|
{
|
||||||
@ -468,7 +454,7 @@ void GuiSound::UncompressSoundbin(const u8 * snd, u32 len, bool isallocated)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
sound = (u8 *)MEM1_alloc(length);
|
sound = (u8 *)malloc(length);
|
||||||
if (!sound)
|
if (!sound)
|
||||||
{
|
{
|
||||||
length = 0;
|
length = 0;
|
||||||
|
Loading…
Reference in New Issue
Block a user