-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:
fix94.1 2012-07-18 14:09:28 +00:00
parent 71e0d1e425
commit 5640028b17
14 changed files with 953 additions and 928 deletions

View File

@ -23,7 +23,7 @@
*
* for WiiXplorer 2010
***************************************************************************/
#include <malloc.h>
#include <unistd.h>
#include <string.h>
#include <ogc/mutex.h>
@ -42,91 +42,94 @@ extern const DISC_INTERFACE __io_sdhc;
#endif
DeviceHandler * DeviceHandler::instance = NULL;
unsigned int DeviceHandler::watchdog_timeout = 10;
DeviceHandler::~DeviceHandler()
{
UnMountAll();
UnMountAll();
}
DeviceHandler * DeviceHandler::Instance()
{
if (instance == NULL)
{
instance = new DeviceHandler();
}
return instance;
}
void DeviceHandler::DestroyInstance()
{
if(instance) delete instance;
instance = NULL;
if(instance)
{
delete instance;
}
instance = NULL;
}
bool DeviceHandler::MountAll()
{
bool result = false;
bool result = false;
for(u32 i = SD; i <= USB8; i++)
if(Mount(i)) result = true;
for(u32 i = SD; i < MAXDEVICES; i++)
{
if(Mount(i))
result = true;
}
return result;
return result;
}
void DeviceHandler::UnMountAll()
{
for(u32 i = SD; i <= GCSDB; i++)
UnMount(i);
for(u32 i = SD; i < MAXDEVICES; i++)
UnMount(i);
if(sd) delete sd;
if(usb) delete usb;
if(gca) delete gca;
if(gcb) delete gca;
if(sd)
delete sd;
if(usb0)
delete usb0;
if(usb1)
delete usb1;
sd = NULL;
usb = NULL;
gca = NULL;
gcb = NULL;
sd = NULL;
usb0 = NULL;
usb1 = NULL;
}
bool DeviceHandler::Mount(int dev)
{
if(dev == SD)
if(dev == SD)
return MountSD();
else if(dev >= USB1 && dev <= USB8)
return MountUSB(dev-USB1);
else if(dev == GCSDA)
return MountGCA();
else if(dev == GCSDB)
return MountGCB();
return false;
return false;
}
bool DeviceHandler::IsInserted(int dev)
{
if(dev == SD)
if(dev == SD)
return SD_Inserted() && sd->IsMounted(0);
else if(dev >= USB1 && dev <= USB8)
return USB_Inserted() && usb->IsMounted(dev-USB1);
else if(dev == GCSDA)
return GCA_Inserted() && gca->IsMounted(0);
else if(dev == GCSDB)
return GCB_Inserted() && gcb->IsMounted(0);
return false;
else if(dev >= USB1 && dev <= USB8)
{
int portPart = PartitionToPortPartition(dev-USB1);
PartitionHandle *usb = instance->GetUSBHandleFromPartition(dev-USB1);
if(usb)
return usb->IsMounted(portPart);
}
return false;
}
void DeviceHandler::UnMount(int dev)
{
if(dev == SD)
if(dev == SD)
UnMountSD();
else if(dev >= USB1 && dev <= USB8)
else if(dev >= USB1 && dev <= USB8)
UnMountUSB(dev-USB1);
else if(dev == GCSDA)
UnMountGCA();
else if(dev == GCSDB)
UnMountGCB();
}
bool DeviceHandler::MountSD()
@ -145,177 +148,194 @@ bool DeviceHandler::MountSD()
}
}
//! Mount only one SD Partition
return sd->Mount(0, DeviceName[SD]);
//! Mount only one SD Partition
return sd->Mount(0, DeviceName[SD], true);
}
bool DeviceHandler::MountUSB(int pos)
{
if(!usb) usb = new PartitionHandle(&__io_usbstorage);
if(!usb0 && !usb1)
return false;
if(usb->GetPartitionCount() < 1)
{
delete usb;
usb = NULL;
return false;
}
// Set the watchdog
InternalSetWatchdog(watchdog_timeout);
if(pos >= GetUSBPartitionCount())
return false;
if(pos >= usb->GetPartitionCount())
return false;
int portPart = PartitionToPortPartition(pos);
return usb->Mount(pos, DeviceName[USB1+pos]);
}
bool DeviceHandler::MountAllUSB()
{
if(!usb) usb = new PartitionHandle(&__io_usbstorage);
bool result = false;
for(int i = 0; i < usb->GetPartitionCount(); i++)
if(MountUSB(i))
result = true;
return result;
}
bool DeviceHandler::MountGCA()
{
if(!gca) gca = new PartitionHandle(&__io_gcsda);
if(gca->GetPartitionCount() < 1)
{
delete gca;
gca = NULL;
return false;
}
//! Mount only one Partition
return gca->Mount(0, DeviceName[GCSDA]);
}
bool DeviceHandler::MountGCB()
{
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)
{
if(!usb) return;
if(pos >= usb->GetPartitionCount())
return;
usb->UnMount(pos);
}
void DeviceHandler::UnMountAllUSB()
{
if(!usb) return;
for(int i = 0; i < usb->GetPartitionCount(); i++)
usb->UnMount(i);
delete usb;
usb = NULL;
}
bool DeviceHandler::InternalSetWatchdog(unsigned int timeout)
{
if (Instance()->USB_Inserted())
return USBStorage_SetWatchdog(timeout) == 0;
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::SetWatchdog(unsigned int timeout)
bool DeviceHandler::MountAllUSB()
{
watchdog_timeout = timeout;
return InternalSetWatchdog(timeout);
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;
int partCount = GetUSBPartitionCount();
for(int i = 0; i < partCount; i++)
{
if(MountUSB(i))
result = true;
}
return result;
}
bool DeviceHandler::MountUSBPort1()
{
if(!usb1)// && (Settings.USBPort == 1 || Settings.USBPort == 2))
usb1 = new PartitionHandle(GetUSB1Interface());
if(usb1 && usb1->GetPartitionCount() < 1)
{
delete usb1;
usb1 = NULL;
return false;
}
bool result = false;
int partCount = GetUSBPartitionCount();
int partCount0 = 0;
if(usb0)
partCount0 = usb0->GetPartitionCount();
for(int i = partCount0; i < partCount; i++)
{
if(MountUSB(i))
result = true;
}
return result;
}
void DeviceHandler::UnMountUSB(int pos)
{
if(pos >= GetUSBPartitionCount())
return;
int portPart = PartitionToPortPartition(pos);
if(PartitionToUSBPort(pos) == 0 && usb0)
return usb0->UnMount(portPart);
else if(usb1)
return usb1->UnMount(portPart);
}
void DeviceHandler::UnMountAllUSB()
{
int partCount = GetUSBPartitionCount();
for(int i = 0; i < partCount; i++)
UnMountUSB(i);
delete usb0;
usb0 = NULL;
delete usb1;
usb1 = NULL;
}
int DeviceHandler::PathToDriveType(const char * path)
{
if(!path) return -1;
if(!path)
return -1;
for(int i = SD; i <= GCSDB; i++)
if(strncmp(path, DeviceName[i], strlen(DeviceName[i])) == 0)
return i;
for(int i = SD; i < MAXDEVICES; i++)
{
if(strncasecmp(path, DeviceName[i], strlen(DeviceName[i])) == 0)
return i;
}
return -1;
return -1;
}
const char * DeviceHandler::GetFSName(int dev)
{
if(dev == SD && DeviceHandler::instance->sd)
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 == GCSDA && DeviceHandler::instance->gca)
return DeviceHandler::instance->gca->GetFSName(0);
else if(dev == GCSDB && DeviceHandler::instance->gcb)
return DeviceHandler::instance->gcb->GetFSName(0);
if(dev == SD && DeviceHandler::instance->sd)
{
return DeviceHandler::instance->sd->GetFSName(0);
}
else if(dev >= USB1 && dev <= USB8)
{
int partCount0 = 0;
int partCount1 = 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)
{
const char *name = GetFSName(dev);
if(!name) return -1;
if(!instance)
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;
else if (strncasecmp(name, "FAT", 3) == 0)
else if(strncmp(FSName, "FAT", 3) == 0)
return PART_FS_FAT;
else if (strncasecmp(name, "NTFS", 4) == 0)
else if(strncmp(FSName, "NTFS", 4) == 0)
return PART_FS_NTFS;
else if (strncasecmp(name, "LINUX", 5) == 0)
else if(strncmp(FSName, "LINUX", 4) == 0)
return PART_FS_EXT;
return -1;
}
s16 DeviceHandler::GetMountedCount(int dev)
u16 DeviceHandler::GetUSBPartitionCount()
{
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;
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)
{
if(dev == SD && DeviceHandler::instance->sd)
return DeviceHandler::instance->sd->GetWbfsHandle(0);
else if(dev >= USB1 && dev <= USB8 && DeviceHandler::instance->usb)
return DeviceHandler::instance->usb->GetWbfsHandle(dev-USB1);
else if(dev == GCSDA && DeviceHandler::instance->gca)
return DeviceHandler::instance->gca->GetWbfsHandle(0);
else if(dev == GCSDB && DeviceHandler::instance->gcb)
return DeviceHandler::instance->gcb->GetWbfsHandle(0);
else if(dev >= USB1 && dev <= USB8 && DeviceHandler::instance->usb0)
return DeviceHandler::instance->usb0->GetWbfsHandle(dev-USB1);
else if(dev >= USB1 && dev <= USB8 && DeviceHandler::instance->usb1)
return DeviceHandler::instance->usb1->GetWbfsHandle(dev-USB1);
return NULL;
}
@ -331,13 +351,48 @@ s32 DeviceHandler::Open_WBFS(int dev)
else if(dev >= USB1 && dev <= USB8 && IsInserted(dev))
{
part_idx = dev;
part_lba = Instance()->usb->GetLBAStart(dev - USB1);
part_lba = Instance()->usb0->GetLBAStart(dev - USB1);
}
else if(dev == GCSDA && IsInserted(dev))
part_lba = Instance()->gca->GetLBAStart(dev);
else if(dev == GCSDB && IsInserted(dev))
part_lba = Instance()->gcb->GetLBAStart(dev);
else return -1;
else
return -1;
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;
}

View File

@ -27,95 +27,96 @@
#define DEVICE_HANDLER_HPP_
#include "PartitionHandle.h"
#include "usbstorage.h"
#include "libwbfs/libwbfs.h"
/**
* libogc device names.
*/
enum
{
SD = 0,
USB1,
USB2,
USB3,
USB4,
USB5,
USB6,
USB7,
USB8,
GCSDA,
GCSDB,
MAXDEVICES
SD = 0,
USB1,
USB2,
USB3,
USB4,
USB5,
USB6,
USB7,
USB8,
MAXDEVICES
};
const char DeviceName[MAXDEVICES][6] =
/**
* libogc device names.
*/
const char DeviceName[MAXDEVICES][8] =
{
"sd",
"usb1",
"usb2",
"usb3",
"usb4",
"usb5",
"usb6",
"usb7",
"usb8",
"gca",
"gcb",
"sd",
"usb1",
"usb2",
"usb3",
"usb4",
"usb5",
"usb6",
"usb7",
"usb8",
};
class DeviceHandler
{
public:
public:
static DeviceHandler * Instance();
static void DestroyInstance();
bool MountAll();
void UnMountAll();
bool Mount(int dev);
bool IsInserted(int dev);
void UnMount(int dev);
bool MountAll();
void UnMountAll();
bool Mount(int dev);
bool IsInserted(int dev);
void UnMount(int dev);
//! Individual Mounts/UnMounts...
//! Individual Mounts/UnMounts...
bool MountSD();
bool MountUSB(int part);
bool MountAllUSB();
bool MountGCA();
bool MountGCB();
bool MountUSBPort1();
bool SD_Inserted() { if(sd) return sd->IsInserted(); return false; };
bool USB_Inserted() { if(usb) return usb->IsInserted(); return false; };
bool GCA_Inserted() { if(gca) return gca->IsInserted(); return false; };
bool GCB_Inserted() { if(gcb) return gcb->IsInserted(); return false; };
bool SD_Inserted() { if(sd) return sd->IsInserted(); return false; }
bool USB0_Inserted() { if(usb0) return usb0->IsInserted(); return false; }
bool USB1_Inserted() { if(usb1) return usb1->IsInserted(); return false; }
void UnMountSD() { if(sd) delete sd; sd = NULL; };
void UnMountSD() { if(sd) delete sd; sd = NULL; }
void UnMountUSB(int pos);
void UnMountAllUSB();
void UnMountGCA() { if(gca) delete gca; gca = NULL; };
void UnMountGCB() { if(gcb) delete gcb; gcb = NULL; };
const PartitionHandle * GetSDHandle() { return sd; };
const PartitionHandle * GetUSBHandle() { return usb; };
const PartitionHandle * GetGCAHandle() { return gca; };
const PartitionHandle * GetGCBHandle() { return gcb; };
PartitionHandle * GetSDHandle() const { return sd; }
PartitionHandle * GetUSB0Handle() const { return usb0; }
PartitionHandle * GetUSB1Handle() const { return usb1; }
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 const char * GetFSName(int dev);
static const char * GetFSName(int dev);
static int GetFSType(int dev);
s16 GetMountedCount(int dev);
static const char * PathToFSName(const char * path) { return GetFSName(PathToDriveType(path)); };
static wbfs_t * GetWbfsHandle(int dev);
//static u32 GetLBAStart(int dev);
static u16 GetUSBPartitionCount();
static const char * PathToFSName(const char * path) { return GetFSName(PathToDriveType(path)); }
static wbfs_t *GetWbfsHandle(int dev);
s32 Open_WBFS(int dev);
static int PartitionToUSBPort(int part);
static int PartitionToPortPartition(int part);
private:
DeviceHandler() : sd(0), gca(0), gcb(0), usb0(0), usb1(0) { }
~DeviceHandler();
bool MountUSB(int part);
private:
DeviceHandler() : sd(0), usb(0), gca(0), gcb(0) { };
~DeviceHandler();
static bool InternalSetWatchdog(unsigned int timeout);
static DeviceHandler *instance;
static DeviceHandler * instance;
static unsigned int watchdog_timeout;
PartitionHandle * sd;
PartitionHandle * usb;
PartitionHandle * gca;
PartitionHandle * gcb;
PartitionHandle * sd;
PartitionHandle * gca;
PartitionHandle * gcb;
PartitionHandle * usb0;
PartitionHandle * usb1;
};
#endif

View File

@ -1,7 +1,6 @@
/****************************************************************************
* Copyright (C) 2010
* by Dimok
* modified for Debugging, GPT, WBFS, and EXT by Miigotu
*
* This software is provided 'as-is', without any express or implied
* 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
* distribution.
*
* By Dimok for WiiXplorer 2010
* By Miigotu for WiiFlow 2010
* for WiiXplorer 2010
***************************************************************************/
#include <gccore.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_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 SECTORS 64
extern u32 sector_size;
static inline const char * PartFromType(int type)
{
switch (type)
{
case 0x00: return "Unused"; //Or WBFS
case 0x00: return "Unused";
case 0x01: return "FAT12";
case 0x04: return "FAT16";
case 0x05: return "Extended";
@ -74,29 +75,32 @@ static inline const char * PartFromType(int type)
case 0xa8: return "OSX";
case 0xab: return "OSXBT";
case 0xaf: return "OSXHF";
case 0xbf: return "WBFS";
case 0xe8: return "LUKS";
case 0xee: return "GPT";
default: return "Unknown";
}
}
PartitionHandle::PartitionHandle(const DISC_INTERFACE *discio)
: interface(discio)
{
interface = discio;
// Sanity check
if(!interface) return;
if (!interface)
return;
// Start the device and check that it is inserted
if(!interface->startup()) return;
if(!interface->isInserted()) return;
if (!interface->startup())
return;
if (!interface->isInserted())
return;
FindPartitions();
}
PartitionHandle::~PartitionHandle()
{
UnMountAll();
UnMountAll();
//shutdown device
if(!neek2o())
@ -114,42 +118,71 @@ bool PartitionHandle::IsMounted(int pos)
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(!name) return false;
if(!valid(pos))
return false;
if(!name)
return false;
UnMount(pos);
if(pos >= (int) MountNameList.size())
MountNameList.resize(GetPartitionCount());
MountNameList.resize(pos+1);
MountNameList[pos] = name;
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, GetLBAStart(pos), CACHE, SECTORS))
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;
}
}
else if(strncmp(GetFSName(pos), "NTFS", 4) == 0)
if(strncmp(GetFSName(pos), "FAT", 3) == 0 || strcmp(GetFSName(pos), "GUID-Entry") == 0)
{
if(ntfsMount(MountNameList[pos].c_str(), interface, GetLBAStart(pos), CACHE, SECTORS, NTFS_SU | NTFS_RECOVER))
if (fatMount(MountNameList[pos].c_str(), interface, GetLBAStart(pos), CACHE, SECTORS))
{
if(strcmp(GetFSName(pos), "GUID-Entry") == 0)
PartitionList[pos].FSName = "FAT";
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))
{
PartitionList[pos].FSName = "LINUX";
return true;
}
}
else if(strncmp(GetFSName(pos), "WBFS", 4) == 0)
{
if(interface == &__io_usbstorage)
SetWbfsHandle(pos, wbfs_open_partition(__WBFS_ReadUSB, __WBFS_WriteUSB, NULL, sector_size, GetSecCount(pos), GetLBAStart(pos), 0));
if(interface == &__io_usbstorage2_port0 || interface == &__io_usbstorage2_port1)
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))
SetWbfsHandle(pos, wbfs_open_partition(__WBFS_ReadSDHC, __WBFS_WriteSDHC, NULL, sector_size, GetSecCount(pos), GetLBAStart(pos), 0));
if(GetWbfsHandle(pos)) return true;
SetWbfsHandle(pos, wbfs_open_partition(__WBFS_ReadSDHC, __WBFS_WriteSDHC, NULL, 512, GetSecCount(pos), GetLBAStart(pos), 0));
if(GetWbfsHandle(pos))
return true;
}
MountNameList[pos].clear();
@ -159,282 +192,234 @@ bool PartitionHandle::Mount(int pos, const char * name)
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];
snprintf(DeviceName, sizeof(DeviceName), "%s:", MountNameList[pos].c_str());
char DeviceSyn[20];
snprintf(DeviceSyn, sizeof(DeviceSyn), "%s:", MountNameList[pos].c_str());
wbfs_t* wbfshandle = GetWbfsHandle(pos);
if(wbfshandle) wbfs_close(wbfshandle);
SetWbfsHandle(pos, NULL);
WBFS_Close();
fatUnmount(DeviceName);
ntfsUnmount(DeviceName, true);
ext2Unmount(DeviceName);
//Remove mount name from the list
//closing all open Files write back the cache
fatUnmount(DeviceSyn);
//closing all open Files write back the cache
ntfsUnmount(DeviceSyn, true);
//closing all open Files write back the cache
ext2Unmount(DeviceSyn);
//Remove name from list
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()
{
MASTER_BOOT_RECORD *mbr = (MASTER_BOOT_RECORD *)MEM2_alloc(MAX_BYTES_PER_SECTOR);
if(mbr == NULL)
return -1;
MASTER_BOOT_RECORD *mbr = (MASTER_BOOT_RECORD *) malloc(MAX_BYTES_PER_SECTOR);
if(!mbr) return -1;
// Read the first sector on the device
if(!interface->readSectors(0, 1, mbr))
if (!interface->readSectors(0, 1, mbr))
{
MEM2_free(mbr);
return 0;
free(mbr);
return -1;
}
// Check if it's a RAW disc, without a partition table
if(CheckRAW((VOLUME_BOOT_RECORD *)mbr))
// If this is the devices master boot record
if (mbr->signature != MBR_SIGNATURE)
{
MEM2_free(mbr);
return 1;
}
// Verify this is the device's master boot record
if(mbr->signature != MBR_SIGNATURE)
{
MEM2_free(mbr);
return 0;
free(mbr);
return -1;
}
for (int i = 0; i < 4; i++)
{
PARTITION_RECORD * partition = (PARTITION_RECORD *)&mbr->partitions[i];
VOLUME_BOOT_RECORD *vbr = (VOLUME_BOOT_RECORD *)MEM2_alloc(MAX_BYTES_PER_SECTOR);
if(!vbr)
PARTITION_RECORD * partition = (PARTITION_RECORD *) &mbr->partitions[i];
if(partition->type == PARTITION_TYPE_GPT)
{
MEM2_free(mbr);
return -1;
int ret = CheckGPT(i);
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(!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))
if(partition->type == PARTITION_TYPE_DOS33_EXTENDED || partition->type == PARTITION_TYPE_WIN95_EXTENDED)
{
CheckEBR(i, le32(partition->lba_start));
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)
{
EXTENDED_BOOT_RECORD *ebr = (EXTENDED_BOOT_RECORD *)MEM2_alloc(MAX_BYTES_PER_SECTOR);
if(ebr == NULL)
return;
EXTENDED_BOOT_RECORD *ebr = (EXTENDED_BOOT_RECORD *) malloc(MAX_BYTES_PER_SECTOR);
if(!ebr) return;
sec_t next_erb_lba = 0;
do
{
// 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;
}
// Check if the partition is WBFS
bool isWBFS = memcmp((u8 *)ebr, WBFS_SIGNATURE, sizeof(WBFS_SIGNATURE)) == 0;
if(!isWBFS && ebr->signature != EBR_SIGNATURE)
if (ebr->signature != EBR_SIGNATURE)
{
MEM2_free(ebr);
free(ebr);
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};
PartitionEntry.FSName = isWBFS ? "WBFS" : PartFromType(ebr->partition.type);
PartitionEntry.LBA_Start = ebr_lba + next_erb_lba + le32(ebr->partition.lba_start);
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);
AddPartition(PartFromType(ebr->partition.type), ebr_lba + next_erb_lba + le32(ebr->partition.lba_start),
le32(ebr->partition.block_count), (ebr->partition.status == PARTITION_BOOTABLE),
ebr->partition.type, PartNum);
}
// Get the start sector of the current partition
// and the next extended boot record in the chain
next_erb_lba = le32(ebr->next_ebr.lba_start);
}
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 };
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 };
int PartitionHandle::CheckGPT(u8 PartNum)
{
GPT_PARTITION_TABLE *gpt = (GPT_PARTITION_TABLE *)MEM2_alloc(MAX_BYTES_PER_SECTOR);
if(gpt == NULL)
return false;
bool success = false; // To return false unless at least 1 partition is verified
GPT_HEADER *gpt_header = (GPT_HEADER *) malloc(MAX_BYTES_PER_SECTOR);
if(!gpt_header) return -1;
if(!interface->readSectors(1, 33, gpt))
// Read and validate the extended boot record
if (!interface->readSectors(1, 1, gpt_header))
{
MEM2_free(gpt);
return false; // To read all 128 possible partitions
free(gpt_header);
return -1;
}
// Verify this is the Primary GPT entry
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))
if(strncmp(gpt_header->magic, "EFI PART", 8) != 0)
{
MEM2_free(gpt);
return false;
free(gpt_header);
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];
VOLUME_BOOT_RECORD *vbr = (VOLUME_BOOT_RECORD*)MEM2_alloc(MAX_BYTES_PER_SECTOR);
if(vbr == NULL)
if (!interface->readSectors(next_lba, 1, sector_buf))
break;
for(u32 n = 0; n < BYTES_PER_SECTOR/gpt_header->part_entry_size; ++n, ++i)
{
MEM2_free(gpt);
return false;
GUID_PART_ENTRY * part_entry = (GUID_PART_ENTRY *) (sector_buf+gpt_header->part_entry_size*n);
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);
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')
{
PartitionEntry.LBA_Start = Start;
PartitionEntry.PartitionNum = i;
success = true;
PartitionList.push_back(PartitionEntry);
}
MEM2_free(vbr);
next_lba++;
}
MEM2_free(gpt);
return success;
delete [] sector_buf;
free(gpt_header);
return 0;
}
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};
if(memcmp((u8 *)vbr + BPB_NTFS_ADDR, NTFS_SIGNATURE, sizeof(NTFS_SIGNATURE)) == 0)
char *buffer = (char *) malloc(MAX_BYTES_PER_SECTOR);
if (!interface->readSectors(lba_start, 1, buffer))
{
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;
free(buffer);
return;
}
if(PartitionEntry.FSName[0] != '0')
wbfs_head_t *head = (wbfs_head_t *) buffer;
if (head->magic == wbfs_htonl(WBFS_MAGIC))
{
PartitionList.push_back(PartitionEntry);
return true;
name = "WBFS";
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);
}

View File

@ -28,194 +28,149 @@
#include <gccore.h>
#include "libwbfs/libwbfs.h"
#include "usbstorage.h"
#include <string>
#include <vector>
using namespace std;
#define MAX_PARTITIONS 32 /* Maximum number of partitions that can be found */
#define MAX_MOUNTS 10 /* Maximum number of mounts available at one time */
#define MAX_SYMLINK_DEPTH 10 /* Maximum search depth when resolving symbolic links */
#define MAX_PARTITIONS 32 /* Maximum number of partitions that can be found */
#define MAX_MOUNTS 10 /* Maximum number of mounts available at one time */
#define MAX_SYMLINK_DEPTH 10 /* Maximum search depth when resolving symbolic links */
#define MBR_SIGNATURE 0x55AA
#define EBR_SIGNATURE MBR_SIGNATURE
#define VBR_SIGNATURE MBR_SIGNATURE
#define GPT_SIGNATURE "EFI PART"
#define MBR_SIGNATURE 0x55AA
#define EBR_SIGNATURE MBR_SIGNATURE
#define PARTITION_BOOTABLE 0x80 /* Bootable (active) */
#define PARTITION_BOOTABLE 0x80 /* Bootable (active) */
#define PARTITION_NONBOOTABLE 0x00 /* Non-bootable */
#define PARTITION_TYPE_GPT 0xEE /* Indicates that a GPT header is available */
#define BYTES_PER_SECTOR 512 /* Default in libogc */
#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 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 {
u8 status; /* Partition status; see above */
u8 chs_start[3]; /* Cylinder-head-sector address to first block of partition */
u8 type; /* Partition type; see above */
u8 chs_end[3]; /* Cylinder-head-sector address to last block of partition */
u32 lba_start; /* Local block address to first sector of partition */
u32 block_count; /* Number of blocks in partition */
u8 status; /* Partition status; see above */
u8 chs_start[3]; /* Cylinder-head-sector address to first block of partition */
u8 type; /* Partition type; see above */
u8 chs_end[3]; /* Cylinder-head-sector address to last block of partition */
u32 lba_start; /* Local block address to first sector of partition */
u32 block_count; /* Number of blocks in partition */
} __attribute__((__packed__)) PARTITION_RECORD;
typedef struct _MASTER_BOOT_RECORD {
u8 code_area[440]; /* Code area; normally empty */
u8 disk_guid[4]; /* Disk signature (optional) */
u8 reserved[2]; /* Usually zeroed */
PARTITION_RECORD partitions[4]; /* 4 primary partitions */
u16 signature; /* MBR signature; 0xAA55 */
u8 code_area[446]; /* Code area; normally empty */
PARTITION_RECORD partitions[4]; /* 4 primary partitions */
u16 signature; /* MBR signature; 0xAA55 */
} __attribute__((__packed__)) MASTER_BOOT_RECORD;
typedef struct _EXTENDED_BOOT_RECORD {
u8 code_area[446]; /* Code area; normally empty */
PARTITION_RECORD partition; /* Primary partition */
PARTITION_RECORD next_ebr; /* Next extended boot record in the chain */
u8 reserved[32]; /* Normally empty */
u16 signature; /* EBR signature; 0xAA55 */
u8 code_area[446]; /* Code area; normally empty */
PARTITION_RECORD partition; /* Primary partition */
PARTITION_RECORD next_ebr; /* Next extended boot record in the chain */
u8 reserved[32]; /* Normally empty */
u16 signature; /* EBR signature; 0xAA55 */
} __attribute__((__packed__)) EXTENDED_BOOT_RECORD;
typedef struct _GUID_PARTITION_ENTRY
typedef struct _GUID_PART_ENTRY
{
u8 Type_GUID[16]; /* Partition type GUID */
u8 Unique_GUID[16]; /* Unique partition GUID */
u64 First_LBA; /* First LBA (little-endian) */
u64 Last_LBA; /* Last LBA (inclusive, usually odd) */
u64 Attributes; /* GUID Attribute flags (e.g. bit 60 denotes read-only) */
char Name[72]; /* Partition name (36 UTF-16LE code units) */
} __attribute__((__packed__)) GUID_PARTITION_ENTRY;
u8 part_type_guid[16]; /* Partition type GUID */
u8 uniq_part_guid[16]; /* Unique partition GUID */
u64 part_first_lba; /* First LBA (little-endian) */
u64 part_last_lba; /* Last LBA (inclusive, usually odd) */
u64 attribute_flags; /* GUID Attribute flags (e.g. bit 60 denotes read-only) */
char partition_name[72]; /* Partition name (36 UTF-16LE code units) */
} __attribute__((__packed__)) GUID_PART_ENTRY;
typedef struct _GPT_PARTITION_TABLE {
char magic[8]; /* "EFI PART" */
u32 Revision;
u32 Header_Size; /* Size of this header */
u32 CheckSum;
u32 Reserved; /* Must be 0 */
u64 Header_LBA; /* Location of this header, always 1 in primary copy */
u64 Backup_Header_LBA; /* Location of backup header, always max lba - 1 */
u64 First_Usable_LBA; /* Primary GPT partition table's last LBA + 1 */
u64 Last_Usable_LBA; /* Secondary GPT partition table's first LBA - 1 */
u8 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 */
u32 Num_Entries; /* Number of entries in the partition info array */
u32 Entry_Size; /* Size of each array entry, usually 128 */
u32 Entries_CheckSum; /* CRC32 of partition array */
u8 Zeroes[420]; /* Pad to a total 512 byte LBA or sizeof 1 LBA */
GUID_PARTITION_ENTRY partitions[128]; /* Max 128 Partition Entries */
} __attribute__((__packed__)) GPT_PARTITION_TABLE;
typedef struct _GPT_HEADER
{
char magic[8]; /* "EFI PART" */
u32 revision; /* For version 1.0 */
u32 header_size; /* Header size in bytes */
u32 checksum; /* CRC32 of header (0 to header size), with this field zeroed during calculation */
u32 reserved; /* must be 0 */
u64 header_lba; /* Current LBA (location of this header copy) */
u64 backup_lba; /* Backup LBA (location of the other header copy) */
u64 first_part_lba; /* First usable LBA for partitions (primary partition table last LBA + 1) */
u64 last_part_lba; /* Last usable LBA (secondary partition table first LBA - 1) */
u8 disk_guid[16]; /* Disk GUID (also referred as UUID on UNIXes) */
u64 part_table_lba; /* Partition entries starting LBA (always 2 in primary copy) */
u32 part_entries; /* Number of partition entries */
u32 part_entry_size; /* Size of a partition entry (usually 128) */
u32 part_entry_checksum; /* CRC32 of partition array */
u8 zeros[420];
} __attribute__((__packed__)) GPT_HEADER;
typedef struct _PartitionFS {
const char * FSName;
u32 LBA_Start;
u32 SecCount;
bool Bootable;
u8 PartitionType;
u8 PartitionNum;
u32 EBR_Sector;
const char * FSName;
u64 LBA_Start;
u64 SecCount;
bool Bootable;
u8 PartitionType;
u8 PartitionNum;
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
{
public:
//! Constructor reads the MBR and all EBRs and lists up the Partitions
PartitionHandle(const DISC_INTERFACE *discio);
//! Destructor unmounts drives
~PartitionHandle();
//! Is Drive inserted
bool IsInserted() { if(!interface) return false; else return interface->isInserted(); };
//! Is the partition Mounted
bool IsMounted(int pos);
//! Mount a specific Partition
bool Mount(int pos, const char * name);
//! UnMount a specific Partition
void UnMount(int pos);
//! UnMount all Partition
void UnMountAll() { for(u32 i = 0; i < PartitionList.size(); ++i) UnMount(i); };
//! Get the Mountname
const char * MountName(int pos) { if(pos < 0 || pos >= (int) MountNameList.size() || !MountNameList[pos].size()) return ""; else return MountNameList[pos].c_str(); };
//! Get the Name of the FileSystem e.g. "FAT32"
const char * GetFSName(int pos) { if(valid(pos)) return PartitionList[pos].FSName; else return ""; };
//! Get the LBA where the partition is located
u32 GetLBAStart(int pos) { if(valid(pos)) return PartitionList[pos].LBA_Start; else return 0; };
//! Get the partition size in sectors of this partition
u32 GetSecCount(int pos) { if(valid(pos)) return PartitionList[pos].SecCount; else return 0; };
//! Check if the partition is Active or NonBootable
bool IsActive(int pos) { if(valid(pos)) return PartitionList[pos].Bootable; else return false; };
//! Get the partition type
int GetPartitionType(int pos) { if(valid(pos)) return PartitionList[pos].PartitionType; else return -1; };
//! Get the entrie number in MBR of this partition
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
int GetPartitionCount() { return PartitionList.size(); };
//! Get the partition size in bytes
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
PartitionFS * GetPartitionRecord(int pos) { if(valid(pos)) return &PartitionList[pos]; else return NULL; };
//! Get the disc interface of this handle
const DISC_INTERFACE * GetDiscInterface() { return interface; };
protected:
bool valid(int pos) { return (pos >= 0 && pos < (int) PartitionList.size()); }
bool CheckRAW(VOLUME_BOOT_RECORD * vbr);
int FindPartitions();
void CheckEBR(u8 PartNum, sec_t ebr_lba);
bool CheckGPT(void);
public:
//! Constructor reads the MBR and all EBRs and lists up the Partitions
PartitionHandle(const DISC_INTERFACE *discio);
//! Destructor unmounts drives
~PartitionHandle();
//! Is Drive inserted
bool IsInserted() { if(!interface) return false; else return interface->isInserted(); };
//! Is the partition Mounted
bool IsMounted(int pos);
//! Mount a specific Partition
bool Mount(int pos, const char * name, bool forceFAT = false);
//! UnMount a specific Partition
void UnMount(int pos);
//! UnMount all Partition
void UnMountAll() { for(u32 i = 0; i < PartitionList.size(); ++i) UnMount(i); };
//! Get the Mountname
const char * MountName(int pos) { if(pos < 0 || pos >= (int) MountNameList.size() || !MountNameList[pos].size()) return ""; else return MountNameList[pos].c_str(); };
//! Get the Name of the FileSystem e.g. "FAT32"
const char * GetFSName(int pos) { if(valid(pos)) return PartitionList[pos].FSName; else return ""; };
//! Get the LBA where the partition is located
u32 GetLBAStart(int pos) { if(valid(pos)) return PartitionList[pos].LBA_Start; else return 0; };
//! Get the partition size in sectors of this partition
u32 GetSecCount(int pos) { if(valid(pos)) return PartitionList[pos].SecCount; else return 0; };
//! Check if the partition is Active or NonBootable
bool IsActive(int pos) { if(valid(pos)) return PartitionList[pos].Bootable; else return false; };
//! Get the partition type
int GetPartitionType(int pos) { if(valid(pos)) return PartitionList[pos].PartitionType; else return -1; };
//! Get the entrie number in MBR of this partition
int GetPartitionNum(int pos) { if(valid(pos)) return PartitionList[pos].PartitionNum; else return -1; };
//! Get the count of found partitions
int GetPartitionCount() const { return PartitionList.size(); };
//! Get the partition size in bytes
u64 GetSize(int pos) { if(valid(pos)) return (u64) PartitionList[pos].SecCount*BYTES_PER_SECTOR; else return 0; };
//! Get the whole partition record struct
PartitionFS * GetPartitionRecord(int pos) { if(valid(pos)) return &PartitionList[pos]; else return NULL; };
//! Get the disc interface of this handle
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:
bool valid(int pos) { return (pos >= 0 && pos < (int) PartitionList.size()); }
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();
void CheckEBR(u8 PartNum, sec_t ebr_lba);
int CheckGPT(u8 PartNum);
const DISC_INTERFACE *interface;
vector<PartitionFS> PartitionList;
vector<std::string> MountNameList;
const DISC_INTERFACE *interface;
vector<PartitionFS> PartitionList;
vector<string> MountNameList;
};
#endif

View File

@ -1,299 +1,336 @@
/*-------------------------------------------------------------
usbstorage_starlet.c -- USB mass storage support, inside starlet
Copyright (C) 2009 Kwiirk
usbstorage_starlet.c -- USB mass storage support, inside starlet
Copyright (C) 2011 Dimok
Copyright (C) 2011 Rodries
Copyright (C) 2009 Kwiirk
If this driver is linked before libogc, this will replace the original
usbstorage driver by svpe from libogc
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any
damages arising from the use of this software.
If this driver is linked before libogc, this will replace the original
usbstorage driver by svpe from libogc
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any
damages arising from the use of this software.
Permission is granted to anyone to use this software for any
purpose, including commercial applications, and to alter it and
redistribute it freely, subject to the following restrictions:
Permission is granted to anyone to use this software for any
purpose, including commercial applications, and to alter it and
redistribute it freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you
must not claim that you wrote the original software. If you use
this software in a product, an acknowledgment in the product
documentation would be appreciated but is not required.
1. The origin of this software must not be misrepresented; you
must not claim that you wrote the original software. If you use
this software in a product, an acknowledgment in the product
documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and
must not be misrepresented as being the original software.
2. Altered source versions must be plainly marked as such, and
must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
3. This notice may not be removed or altered from any source
distribution.
-------------------------------------------------------------*/
-------------------------------------------------------------*/
#include <gccore.h>
#include <malloc.h>
#include <stdio.h>
#include <string.h>
#include "usbstorage.h"
#include "memory/mem2.hpp"
#include "gecko.h"
/* IOCTL commands */
#define UMS_BASE (('U'<<24)|('M'<<16)|('S'<<8))
#define USB_IOCTL_UMS_INIT (UMS_BASE+0x1)
#define USB_IOCTL_UMS_GET_CAPACITY (UMS_BASE+0x2)
#define USB_IOCTL_UMS_READ_SECTORS (UMS_BASE+0x3)
#define USB_IOCTL_UMS_WRITE_SECTORS (UMS_BASE+0x4)
#define USB_IOCTL_UMS_READ_STRESS (UMS_BASE+0x5)
#define USB_IOCTL_UMS_SET_VERBOSE (UMS_BASE+0x6)
#define USB_IOCTL_UMS_INIT (UMS_BASE+0x1)
#define USB_IOCTL_UMS_GET_CAPACITY (UMS_BASE+0x2)
#define USB_IOCTL_UMS_READ_SECTORS (UMS_BASE+0x3)
#define USB_IOCTL_UMS_WRITE_SECTORS (UMS_BASE+0x4)
#define USB_IOCTL_UMS_READ_STRESS (UMS_BASE+0x5)
#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 USB_IOCTL_UMS_TESTMODE (UMS_BASE+0x81)
#define USB_IOCTL_SET_PORT (UMS_BASE+0x83)
#define UMS_HEAPSIZE 0x8000
#define USB_MEM2_SIZE 0x10000
#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 */
static char fs[] ATTRIBUTE_ALIGN(32) = "/dev/usb2";
static char fs2[] ATTRIBUTE_ALIGN(32) = "/dev/usb123";
static char fs3[] ATTRIBUTE_ALIGN(32) = "/dev/usb/ehc";
static u8 * mem2_ptr = NULL;
static s32 hid = -1, fd = -1;
u32 sector_size;
static void *usb_buf2;
static u32 usb2_port = -1; //current USB port
bool hddInUse[2] = { false, false };
u32 hdd_sector_size[2] = { 512, 512 };
extern void* SYS_AllocArena2MemLo(u32 size,u32 align);
inline s32 __USBStorage_isMEM2Buffer(const void *buffer)
s32 USBStorage2_Init(u32 port)
{
u32 high_addr = ((u32)buffer) >> 24;
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", &sector_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;
}
s32 USBStorage_OpenDev()
{
/* Already open */
if (fd >= 0) return fd;
if(hddInUse[port])
return 0;
/* Create heap */
if (hid < 0)
{
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 */
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(fs3, 0);
return fd;
}
s32 USBStorage_SetWatchdog(u32 seconds)
{
if (fd < 0) return fd;
static ioctlv vector[1] ATTRIBUTE_ALIGN(32);
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;
USBStorage2_SetPort(port);
/* Initialize USB storage */
ret = IOS_IoctlvFormat(hid, fd, USB_IOCTL_UMS_INIT, ":");
IOS_IoctlvFormat(hid, fd, USB_IOCTL_UMS_INIT, ":");
/* Get device capacity */
ret = USBStorage_GetCapacity(NULL);
if (!ret) goto err;
if (USBStorage2_GetCapacity(port, &hdd_sector_size[port]) == 0)
return IPC_ENOENT;
return 0;
hddInUse[port] = true;
err:
/* Close USB device */
if (fd >= 0)
{
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;
return 0; // 0->HDD, 1->DVD
}
void USBStorage_Deinit(void)
void USBStorage2_Deinit()
{
/* Close USB device */
if (fd >= 0)
{
IOS_Close(fd);
IOS_Close(fd); // not sure to close the fd is needed
fd = -1;
}
/* if (hid > 0) {
iosDestroyHeap(hid);
hid = -1;
} */
USB_Deinitialize();
}
s32 USBStorage_ReadSectors(u32 sector, u32 numSectors, void *buffer)
s32 USBStorage2_SetPort(u32 port)
{
void *buf = (void *)buffer;
u32 len = (sector_size * numSectors);
s32 ret;
//! Port = 2 is handle in the loader, no need to handle it in cIOS
if(port > 1)
return -1;
/* Device not opened */
if (fd < 0)
return fd;
if(port == usb2_port)
return 0;
/* MEM1 buffer */
if (!__USBStorage_isMEM2Buffer(buffer))
{
/* Allocate memory */
//buf = iosAlloc(hid, len);
buf = usb_buf2;
if (!buf) return IPC_ENOMEM;
}
s32 ret = -1;
usb2_port = port;
/* 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);
}
gprintf("Changing USB port to port %i....\n", port);
//must be called before USBStorage2_Init (default port 0)
if (fd >= 0)
ret = IOS_IoctlvFormat(hid, fd, USB_IOCTL_SET_PORT, "i:", usb2_port);
return ret;
}
s32 USBStorage_WriteSectors(u32 sector, u32 numSectors, const void *buffer)
s32 USBStorage2_GetPort()
{
void *buf = (void *)buffer;
u32 len = (sector_size * numSectors);
s32 ret;
return usb2_port;
}
s32 USBStorage2_GetCapacity(u32 port, u32 *_sector_size)
{
if (fd >= 0)
{
s32 ret;
u32 sector_size = 0;
USBStorage2_SetPort(port);
ret = IOS_IoctlvFormat(hid, fd, USB_IOCTL_UMS_GET_CAPACITY, ":i", &sector_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 */
if (fd < 0) return fd;
/* MEM1 buffer */
if (!__USBStorage_isMEM2Buffer(buffer))
if (!mem2_ptr)
mem2_ptr = (u8 *) MEM2_alloc(MAX_SECTOR_SIZE * MAX_BUFFER_SECTORS);
USBStorage2_SetPort(port);
s32 read_secs, read_size;
while(numSectors > 0)
{
/* Allocate memory */
//buf = iosAlloc(hid, len);
buf = usb_buf2;
if (!buf) return IPC_ENOMEM;
read_secs = numSectors > MAX_BUFFER_SECTORS ? MAX_BUFFER_SECTORS : numSectors;
read_size = read_secs*hdd_sector_size[port];
/* Copy data */
memcpy(buf, buffer, len);
// 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;
}
sector += read_secs;
numSectors -= read_secs;
buf += read_size;
}
/* Write data */
ret = IOS_IoctlvFormat(hid, fd, USB_IOCTL_UMS_WRITE_SECTORS, "ii:d", sector, numSectors, buf, len);
/* Free memory */
//if (buf != buffer)
// iosFree(hid, buf);
return ret;
}
// DISC_INTERFACE methods
static bool __io_usb_IsInserted(void)
s32 USBStorage2_WriteSectors(u32 port, u32 sector, u32 numSectors, const void *buffer)
{
s32 ret;
u32 sec_size;
if (fd < 0)
return false;
u8 *buf = (u8 *) buffer;
s32 ret = -1;
ret = USBStorage_GetCapacity(&sec_size);
if (ret == 0)
return false;
return true;
/* Device not opened */
if (fd < 0) return fd;
/* 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;
}
sector += write_secs;
numSectors -= write_secs;
buf += write_size;
}
return ret;
}
static bool __io_usb_Startup(void)
s32 USBStorage2_GetSectorSize()
{
if (USBStorage_Init() < 0) return false;
return __io_usb_IsInserted();
return hdd_sector_size[usb2_port];
}
bool __io_usb_ReadSectors(u32 sector, u32 count, void *buffer)
static bool __usbstorage_Startup(void)
{
return USBStorage_ReadSectors(sector, count, buffer) >= 0;
return USBStorage2_Init(0) >= 0;
}
bool __io_usb_WriteSectors(u32 sector, u32 count, void *buffer)
static bool __usbstorage_IsInserted(void)
{
return USBStorage_WriteSectors(sector, count, buffer) >= 0;
return (USBStorage2_GetCapacity(0, NULL) != 0);
}
static bool __io_usb_ClearStatus(void)
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;
}
static bool __io_usb_Shutdown(void)
static bool __usbstorage_Shutdown(void)
{
// do nothing
hddInUse[0] = false;
hdd_sector_size[0] = 512;
return true;
}
DISC_INTERFACE __io_usbstorage = {
DEVICE_TYPE_WII_USB,
FEATURE_MEDIUM_CANREAD | FEATURE_MEDIUM_CANWRITE | FEATURE_WII_USB,
(FN_MEDIUM_STARTUP) &__io_usb_Startup,
(FN_MEDIUM_ISINSERTED) &__io_usb_IsInserted,
(FN_MEDIUM_READSECTORS) &__io_usb_ReadSectors,
(FN_MEDIUM_WRITESECTORS) &__io_usb_WriteSectors,
(FN_MEDIUM_CLEARSTATUS) &__io_usb_ClearStatus,
(FN_MEDIUM_SHUTDOWN) &__io_usb_Shutdown
};
const DISC_INTERFACE __io_usbstorage2_port0 = {
DEVICE_TYPE_WII_UMS, FEATURE_MEDIUM_CANREAD | FEATURE_MEDIUM_CANWRITE | FEATURE_WII_USB,
(FN_MEDIUM_STARTUP) &__usbstorage_Startup,
(FN_MEDIUM_ISINSERTED) &__usbstorage_IsInserted,
(FN_MEDIUM_READSECTORS) &__usbstorage_ReadSectors,
(FN_MEDIUM_WRITESECTORS) &__usbstorage_WriteSectors,
(FN_MEDIUM_CLEARSTATUS) &__usbstorage_ClearStatus,
(FN_MEDIUM_SHUTDOWN) &__usbstorage_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
};

View File

@ -1,22 +1,32 @@
#ifndef _USBSTORAGE_H_
#define _USBSTORAGE_H_
#ifndef _USBSTORAGE2_H_
#define _USBSTORAGE2_H_
#include <ogcsys.h>
#include "ogc/disc_io.h"
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
extern "C"
{
#endif
/* Prototypes */
s32 USBStorage_GetCapacity(u32 *);
s32 USBStorage_SetWatchdog(u32);
s32 USBStorage_Init(void);
void USBStorage_Deinit(void);
s32 USBStorage_ReadSectors(u32, u32, void *);
s32 USBStorage_WriteSectors(u32, u32, void *);
/* Prototypes */
s32 USBStorage2_Init(u32 port);
void USBStorage2_Deinit();
s32 USBStorage2_GetCapacity(u32 port, u32 *size);
s32 USBStorage2_ReadSectors(u32 port, u32 sector, u32 numSectors, void *buffer);
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
}
#endif /* __cplusplus */
#endif
#endif

View File

@ -87,7 +87,7 @@ bool loadIOS(int ios, bool launch_game)
DeviceHandler::Instance()->UnMountAll();
WDVD_Close();
USBStorage_Deinit();
USBStorage2_Deinit();
mload_close();
bool iosOK = IOS_ReloadIOS(ios) == 0;

View File

@ -29,8 +29,6 @@
/* WBFS device */
s32 wbfsDev = WBFS_MIN_DEVICE;
extern u32 sector_size;
// partition
int wbfs_part_fs = PART_FS_WBFS;
u32 wbfs_part_idx = 0;
@ -99,7 +97,7 @@ s32 __WBFS_ReadUSB(void* fp, u32 lba, u32 count, void *iobuf)
/* Do reads */
while (cnt < count)
{
fp = ((u8 *)iobuf) + (cnt * sector_size);
fp = ((u8 *)iobuf) + (cnt * USBStorage2_GetSectorSize());
u32 sectors = (count - cnt);
/* Read sectors is too big */
@ -107,7 +105,7 @@ s32 __WBFS_ReadUSB(void* fp, u32 lba, u32 count, void *iobuf)
sectors = MAX_NB_SECTORS;
/* 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;
/* Increment counter */
@ -124,7 +122,7 @@ s32 __WBFS_WriteUSB(void* fp, u32 lba, u32 count, void *iobuf)
/* Do writes */
while (cnt < count)
{
fp = ((u8 *)iobuf) + (cnt * sector_size);
fp = ((u8 *)iobuf) + (cnt * USBStorage2_GetSectorSize());
u32 sectors = (count - cnt);
/* Write sectors is too big */
@ -132,7 +130,7 @@ s32 __WBFS_WriteUSB(void* fp, u32 lba, u32 count, void *iobuf)
sectors = MAX_NB_SECTORS;
/* 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;
/* Increment counter */
@ -149,7 +147,7 @@ s32 __WBFS_ReadSDHC(void* fp, u32 lba, u32 count, void *iobuf)
/* Do reads */
while (cnt < count)
{
fp = ((u8 *)iobuf) + (cnt * sector_size);
fp = ((u8 *)iobuf) + (cnt * 512);
u32 sectors = (count - cnt);
/* Read sectors is too big */
@ -175,7 +173,7 @@ s32 __WBFS_WriteSDHC(void* fp, u32 lba, u32 count, void *iobuf)
/* Do writes */
while (cnt < count)
{
fp = ((u8 *)iobuf) + (cnt * sector_size);
fp = ((u8 *)iobuf) + (cnt * 512);
u32 sectors = (count - cnt);
/* 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)
{
u32 sector_size = (currentPartition == 0) ? 512 : USBStorage2_GetSectorSize();
u32 wbfs_sector_size = sector_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)
{
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;

View File

@ -26,8 +26,6 @@
#define MAX_FAT_PATH 1024
#define TITLE_LEN 64
extern u32 sector_size;
char wbfs_fs_drive[16];
char wbfs_ext_dir[16] = "/wbfs";
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)
{
bool sd = strstr(fname, "sd") != NULL;
if (strcasecmp(strrchr(fname,'.'), ".iso") == 0)
{
// .iso file
@ -58,7 +57,7 @@ wbfs_disc_t* WBFS_Ext_OpenDisc(u8 *discid, char *fname)
return NULL;
// 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->header = (void*)fd;
return iso_file;
@ -116,12 +115,13 @@ s32 WBFS_Ext_DiskSpace(f32 *used, f32 *free)
wbfs_t* WBFS_Ext_OpenPart(char *fname)
{
bool sd = strstr(fname, "sd") != NULL;
if(split_open(&split, fname) < 0)
return NULL;
wbfs_set_force_mode(1);
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);
if (!part)
@ -223,17 +223,16 @@ s32 WBFS_Ext_AddGame(progress_callback_t spinner, void *spinner_data)
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;
u32 n_sector = size / 512;
// init a temporary dummy part
// as a placeholder for wbfs_size_disc
wbfs_t *part = wbfs_open_partition(
0, 0,
NULL, sector_size, n_sector, 0, 1);
if (!part) return -1;
wbfs_t *part = wbfs_open_partition(0, 0, NULL, sd ? 512 : USBStorage2_GetSectorSize(), n_sector, 0, 1);
if (!part)
return -1;
u32 comp_sec = 0, last_sec = 0;
s32 ret = wbfs_size_disc(part, __WBFS_ReadDVD, NULL, ONLY_GAME_PARTITION, &comp_sec, &last_sec);

View File

@ -16,7 +16,7 @@ void WBFS_Ext_CloseDisc(wbfs_disc_t* disc);
s32 WBFS_Ext_DiskSpace(f32 *used, f32 *free);
s32 WBFS_Ext_RemoveGame(u8 *discid, char *path);
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);
char* strcopy(char *dest, const char *src, int size);

View File

@ -88,19 +88,18 @@ int main(int argc, char **argv)
{
Open_Inputs(); //(re)init wiimote
#ifndef DOLPHIN
const DISC_INTERFACE *handle = DeviceHandler::GetUSB0Interface();
bool deviceAvailable = false;
u8 timeout = 0;
DeviceHandler::Instance()->MountSD();
while(!deviceAvailable && timeout++ != 20)
{
DeviceHandler::Instance()->MountAll();
sleep(1);
for(u8 device = USB1; device <= USB8; device++)
{
if(DeviceHandler::Instance()->IsInserted(device))
deviceAvailable = true;
}
}
deviceAvailable = (handle->startup() && handle->isInserted());
if(deviceAvailable)
break;
usleep(50000);
}
DeviceHandler::Instance()->MountAllUSB();
if(DeviceHandler::Instance()->IsInserted(SD))
deviceAvailable = true;
#else

View File

@ -309,7 +309,7 @@ void CMenu::init(void)
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()));
DeviceHandler::SetWatchdog(m_cfg.getUInt("GENERAL", "watchdog_timeout", 10));
//DeviceHandler::SetWatchdog(m_cfg.getUInt("GENERAL", "watchdog_timeout", 10));
const char *domain = _domainFromView();
const char *checkDir = m_current_view == COVERFLOW_HOMEBREW ? HOMEBREW_DIR : GAMES_DIR;
@ -491,7 +491,7 @@ void CMenu::cleanup()
{
if(cleaned_up)
return;
gprintf("MEM1_freesize(): %i\nMEM2_freesize(): %i\n", MEM1_freesize(), MEM2_freesize());
m_cf.stopCoverLoader();
_cleanupDefaultFont();
m_cf.clear();
@ -542,6 +542,7 @@ void CMenu::cleanup()
cleaned_up = true;
gprintf(" \nMemory cleaned up\n");
gprintf("MEM1_freesize(): %i\nMEM2_freesize(): %i\n", MEM1_freesize(), MEM2_freesize());
}
void CMenu::_reload_wifi_gecko(void)

View File

@ -61,7 +61,6 @@ extern const u8 blank_png[];
extern const u8 gc_ogg[];
extern const u32 gc_ogg_size;
extern u32 sector_size;
extern u32 boot2version;
extern int mainIOS;
static u64 sm_title_id[8] ATTRIBUTE_ALIGN(32);
@ -871,7 +870,7 @@ void CMenu::_launchGC(dir_discHdr *hdr, bool disc)
cleanup();
#ifndef DOLPHIN
ISFS_Deinitialize();
USBStorage_Deinit();
USBStorage2_Deinit();
SDHC_Init();
#endif
GC_SetVideoMode(videoMode, videoSetting);
@ -910,7 +909,7 @@ void CMenu::_launchHomebrew(const char *filepath, vector<string> arguments)
AddBootArgument(arguments[i].c_str());
#ifndef DOLPHIN
ISFS_Deinitialize();
USBStorage_Deinit();
USBStorage2_Deinit();
#endif
//MEM2_clear();
BootHomebrew(title);
@ -1285,8 +1284,7 @@ void CMenu::_launchGame(dir_discHdr *hdr, bool dvd)
Nand::Instance()->Do_Region_Change(id);
}
}
if(!dvd && get_frag_list((u8 *)id.c_str(), (char*)path.c_str(), currentPartition == 0 ? 0x200 : sector_size) < 0)
if(!dvd && get_frag_list((u8 *)id.c_str(), (char*)path.c_str(), currentPartition == 0 ? 0x200 : USBStorage2_GetSectorSize()) < 0)
return;
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
ISFS_Deinitialize();
USBStorage_Deinit();
USBStorage2_Deinit();
if(currentPartition == 0)
SDHC_Init();
#endif

View File

@ -31,7 +31,7 @@
#include "WavDecoder.hpp"
#include "loader/sys.h"
#define MAX_SND_VOICES 16
#define MAX_SND_VOICES 16
using namespace std;
@ -56,8 +56,7 @@ static inline int GetFirstUnusedVoice()
extern "C" void SoundCallback(s32 voice)
{
SoundDecoder * decoder = SoundHandler::Instance()->Decoder(voice);
if(!decoder)
return;
if(!decoder) return;
if(decoder->IsBufferReady())
{
@ -70,7 +69,7 @@ extern "C" void SoundCallback(s32 voice)
else if(decoder->IsEOF())
ASND_StopVoice(voice);
else
SoundHandler::Instance()->ThreadSignal();
SoundHandler::Instance()->ThreadSignal();
}
GuiSound::GuiSound()
@ -99,13 +98,12 @@ GuiSound::GuiSound(GuiSound *g)
voice = -1;
Init();
if (g == NULL)
return;
if (g == NULL) return;
if (g->sound != NULL)
{
u8 *snd = (u8 *)MEM1_alloc(g->length);
memcpy(snd, g->sound, length);
u8 * snd = (u8 *) malloc(g->length);
memcpy(snd, g->sound, g->length);
Load(snd, g->length, true);
}
else
@ -127,7 +125,7 @@ void GuiSound::Init()
voice = GetFirstUnusedVoice();
if(voice > 0)
VoiceUsed[voice] = true;
volume = 255;
SoundEffectLength = 0;
loop = false;
@ -144,9 +142,11 @@ void GuiSound::FreeMemory()
if(allocated)
{
MEM1_free(sound);
free(sound);
allocated = false;
}
sound = NULL;
length = 0;
filepath = "";
SoundEffectLength = 0;
@ -161,8 +161,7 @@ bool GuiSound::Load(const char * filepath)
FILE * f = fopen(filepath, "rb");
if(!f)
{
gprintf("Failed to load file %s!!\n", filepath);
{ gprintf("Failed to load file %s!!\n", filepath);
return false;
}
@ -174,14 +173,12 @@ bool GuiSound::Load(const char * filepath)
gprintf("Loading %s using voice %d\n", filepath, voice);
SoundDecoder * decoder = SoundHandler::Instance()->Decoder(voice);
if(!decoder)
{
gprintf("No Decoder!!!\n");
{ gprintf("No Decoder!!!\n");
return false;
}
if(!decoder->IsBufferReady())
{
gprintf("Buffer not ready!!\n");
{ gprintf("Buffer not ready!!n");
SoundHandler::Instance()->RemoveDecoder(voice);
return false;
}
@ -197,26 +194,29 @@ bool GuiSound::Load(const u8 * snd, u32 len, bool isallocated)
FreeMemory();
this->voice = voice;
if(!snd)
return false;
if(!snd) return false;
if(!isallocated && *((u32 *) snd) == 'RIFF')
return LoadSoundEffect(snd, len);
if(*((u32 *) snd) == 'IMD5')
{
UncompressSoundbin(snd, len, isallocated);
}
else
{
sound = (u8 *) snd;
length = len;
allocated = isallocated;
}
SoundHandler::Instance()->AddDecoder(this->voice, sound, length);
SoundDecoder * decoder = SoundHandler::Instance()->Decoder(voice);
if(!decoder)
{
return false;
}
if(!decoder->IsBufferReady())
{
@ -237,15 +237,15 @@ bool GuiSound::LoadSoundEffect(const u8 * snd, u32 len)
decoder.Rewind();
u32 done = 0;
sound = (u8 *)MEM1_alloc(4096);
sound = (u8 *)malloc(4096);
memset(sound, 0, 4096);
while(1)
{
u8 * tmpsnd = (u8 *)MEM1_realloc(sound, done+4096);
u8 * tmpsnd = (u8 *)realloc(sound, done+4096);
if(!tmpsnd)
{
MEM1_free(sound);
free(sound);
return false;
}
@ -253,12 +253,12 @@ bool GuiSound::LoadSoundEffect(const u8 * snd, u32 len)
int read = decoder.Read(sound+done, 4096, done);
if(read <= 0)
break;
break;
done += read;
}
sound = (u8 *)MEM1_realloc(sound, done);
sound = (u8 *)realloc(sound, done);
SoundEffectLength = done;
allocated = true;
@ -274,15 +274,10 @@ void GuiSound::Play(int vol, bool restart)
return;
}
if(IsPlaying() && !restart)
return;
if(voice < 0 || voice >= 16)
return;
if((IsPlaying() && !restart) || voice < 0 || voice >= 16) return;
SoundDecoder * decoder = SoundHandler::Instance()->Decoder(voice);
if(!decoder)
return;
if(!decoder) return;
ASND_StopVoice(voice);
if(decoder->IsEOF())
@ -307,20 +302,18 @@ void GuiSound::Play()
void GuiSound::Stop()
{
if (!IsPlaying()) return;
if(voice < 0 || voice >= 16)
volume = 0;
if (!IsPlaying() || voice < 0 || voice >= 16)
return;
ASND_StopVoice(voice);
SoundDecoder * decoder = SoundHandler::Instance()->Decoder(voice);
if(!decoder)
return;
if(!decoder) return;
decoder->ClearBuffer();
Rewind();
SoundHandler::Instance()->ThreadSignal();
}
@ -357,10 +350,7 @@ int GuiSound::GetVolume()
void GuiSound::SetVolume(int vol)
{
if(voice < 0 || voice >= 16)
return;
if(vol < 0)
if(voice < 0 || voice >= 16 || vol < 0)
return;
volume = vol;
@ -372,8 +362,7 @@ void GuiSound::SetLoop(u8 l)
loop = l;
SoundDecoder * decoder = SoundHandler::Instance()->Decoder(voice);
if(!decoder)
return;
if(!decoder) return;
decoder->SetLoop(l == 1);
}
@ -381,16 +370,15 @@ void GuiSound::SetLoop(u8 l)
void GuiSound::Rewind()
{
SoundDecoder * decoder = SoundHandler::Instance()->Decoder(voice);
if(!decoder)
return;
if(!decoder) return;
decoder->Rewind();
}
struct _LZ77Info
{
u16 length : 4;
u16 offset : 12;
u16 length : 4;
u16 offset : 12;
} __attribute__((packed));
typedef struct _LZ77Info LZ77Info;
@ -407,10 +395,9 @@ u8 * uncompressLZ77(const u8 *inBuf, u32 inLength, u32 * size)
const u8 *inBufEnd = inBuf + inLength;
inBuf += 8;
buffer = (u8 *)MEM1_alloc(uncSize);
buffer = (u8 *)malloc(uncSize);
if (!buffer)
return buffer;
if (!buffer) return buffer;
u8 *bufCur = buffer;
u8 *bufEnd = buffer + uncSize;
@ -428,7 +415,7 @@ u8 * uncompressLZ77(const u8 *inBuf, u32 inLength, u32 * size)
inBuf += sizeof (LZ77Info);
int length = info->length + 3;
if (bufCur - info->offset - 1 < buffer || bufCur + length > bufEnd)
return buffer;
return buffer;
memcpy(bufCur, bufCur - info->offset - 1, length);
bufCur += length;
}
@ -452,8 +439,7 @@ void GuiSound::UncompressSoundbin(const u8 * snd, u32 len, bool isallocated)
const u8 * file = snd+32;
length = len-32;
if (length <= 0)
return;
if (length <= 0) return;
if(*((u32 *) file) == 'LZ77')
{
@ -468,7 +454,7 @@ void GuiSound::UncompressSoundbin(const u8 * snd, u32 len, bool isallocated)
}
else
{
sound = (u8 *)MEM1_alloc(length);
sound = (u8 *)malloc(length);
if (!sound)
{
length = 0;