mirror of
https://gitlab.com/Nanolx/homebrewfilter.git
synced 2024-11-24 18:16:56 +01:00
652 lines
16 KiB
C
652 lines
16 KiB
C
/*-------------------------------------------------------------
|
|
|
|
uneek_fs.c -- USB mass storage support, using a modified uneek fs-usb
|
|
|
|
rev. 1.00 first draft
|
|
|
|
rev. 1.01 second draft
|
|
added detection and support for SDHC access in SNEEK
|
|
added check_uneek_fs_type function to see if it's sneek or uneek
|
|
|
|
rev. 1.02 third draft
|
|
added the UNEEK_FS_BOTH option to the init_uneek_fs function.
|
|
when the parameter is set, both sd and usb access are rerouted to the sd card.
|
|
it can only be used with sneek and could serve programs like Joyflow on a sd only
|
|
setup.
|
|
the exit_uneek_fs function needs to be called when that setup is used.
|
|
since I can't disable usb, not knowing if sd access is still needed, and
|
|
I can't disable sd if usb access if sd is still needed.
|
|
It's probably exceptional that one will be shutdown and the other still used,
|
|
but it's better to stay on the safe area.
|
|
|
|
rev. 1.04 fourth draft.
|
|
shutdown function is now a stub as some programs call it before they end to force a remount
|
|
exit_uneek_fs added to properly shutdown the uneek_usb_fs file system.
|
|
max_write_sectors increased to speedup things. Transfer speed from wiixplorer gone up
|
|
from 20KB/s to 265KB/s.
|
|
|
|
rev. 1.05 fifth draft
|
|
added "is_uneek" function
|
|
|
|
rev. 1.06 sixth draft
|
|
added "is_neek2" and "is_neek3" functions
|
|
Crediar changed the boot2 version back from 5 to 4.
|
|
The is_uneek function will not detect those neek versions anymore.
|
|
Stfour created the is_neek2 method to detect if neek is running.
|
|
JoostinOnline and GiantPune created the is_neek3 which is a little less code.
|
|
So, you should use either is_neek2 or is_neek3
|
|
|
|
rev. 1.07 seventh draft
|
|
added "is_neek4" function
|
|
Dj_Skual created the is_neek4 method to detect if neek is running.
|
|
|
|
added WII_launch_Channel. It's not really uneek_fs related, but it could be handy
|
|
|
|
|
|
Copyright (C) 2011 Obcd
|
|
|
|
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:
|
|
|
|
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.
|
|
|
|
3. This notice may not be removed or altered from any source
|
|
distribution.
|
|
|
|
-------------------------------------------------------------*/
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <ogcsys.h>
|
|
#include <locale.h>
|
|
#include <malloc.h>
|
|
#include <ogc/isfs.h>
|
|
//#include <sdcard/wiisd_io.h>
|
|
//#include <gctypes.h>
|
|
//#include <ogc/disc_io.h>
|
|
|
|
|
|
//#define SHOW_GECKO_DEBUG 1
|
|
|
|
#ifdef SHOW_GECKO_DEBUG
|
|
#include "gecko.h"
|
|
#endif
|
|
|
|
#define MAX_READ_SECTORS 16 //yet to be determined how much is allowed?
|
|
#define MAX_WRITE_SECTORS 16 //yet to be determined how much is allowed?
|
|
#define CACHE_SECTOR_LOCATION 1 //not sure if it will improve speed much...
|
|
|
|
#define UNEEK_FS_NONE 0
|
|
#define UNEEK_FS_USB 1
|
|
#define UNEEK_FS_SD 2
|
|
#define UNEEK_FS_BOTH 4
|
|
|
|
#define ISFS_OPEN_ALL 64
|
|
|
|
#define DEVICE_TYPE_WII_SD (('W'<<24)|('I'<<16)|('S'<<8)|'D')
|
|
|
|
|
|
//Not yet implemented as most disk io buffers don't seem have proper alignment
|
|
//It would require a more serious modification in the code (aligning those buffers)
|
|
//#define USE_ORIGINAL_ALIGNED_BUF 0 //if the buffer is aligned already...why not?
|
|
|
|
|
|
|
|
//This one triggers the unique functions in the uneek fs
|
|
//Don't try to change it.
|
|
//If you really need to access that file with ISFS, access it in read/write mode
|
|
//As only read mode will trigger uneek fs
|
|
|
|
static char _dev_obcd[] ATTRIBUTE_ALIGN(32) = "/sneek/obcd.txt";
|
|
|
|
static s32 fu = -1;
|
|
// static bool uneek_fs_ok = false;
|
|
static s32 uneek_fs_type = UNEEK_FS_NONE;
|
|
|
|
s32 confirm_neek1 = 5;
|
|
s32 confirm_neek2 = 5;
|
|
s32 confirm_neek3 = 5;
|
|
s32 confirm_neek4 = 5;
|
|
|
|
|
|
#ifdef CACHE_SECTOR_LOCATION
|
|
static u32 seek_cache;
|
|
#endif
|
|
|
|
// DISC_INTERFACE __io_usbstorage;
|
|
DISC_INTERFACE __io_wiisd;
|
|
extern DISC_INTERFACE __io_usbstorage;
|
|
//extern DISC_INTERFACE __io_usb2storage;
|
|
|
|
// DISC_INTERFACE methods
|
|
|
|
static bool __io_uns_IsInserted(void)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
static bool __io_uns_Startup(void)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
int usb_verbose = 0;
|
|
|
|
bool __io_uns_ReadSectors(u32 sector, u32 count, void *buffer)
|
|
{
|
|
|
|
u8* buf;
|
|
s32 whence;
|
|
u32 done;
|
|
u32 sec;
|
|
u32 amount;
|
|
u8* resultbuf;
|
|
|
|
done = 0;
|
|
sec = sector;
|
|
if (count <= MAX_READ_SECTORS)
|
|
{
|
|
amount = count;
|
|
}
|
|
else
|
|
{
|
|
amount = MAX_READ_SECTORS;
|
|
}
|
|
// buf = (u8 *)memalign(32, 512 * amount);
|
|
// sdhc aligns it's buffers on 64 byte boundaries
|
|
buf = (u8 *)memalign(64, 512 * amount);
|
|
|
|
while(done < count)
|
|
{
|
|
whence = 0;
|
|
if ((sec & 0x80000000)!= 0)
|
|
{
|
|
sec &= 0x7fffffff;
|
|
whence = 1;
|
|
}
|
|
#ifdef CACHE_SECTOR_LOCATION
|
|
if ((sector + done) != seek_cache)
|
|
{
|
|
#endif
|
|
ISFS_Seek(fu,sec,whence);
|
|
#ifdef CACHE_SECTOR_LOCATION
|
|
seek_cache = sector + done;
|
|
}
|
|
#endif
|
|
s32 ret = ISFS_Read(fu,buf,512*amount);
|
|
if (ret == (s32)(512*amount))
|
|
{
|
|
resultbuf = (u8*)buffer + (done * 512);
|
|
memcpy(resultbuf,buf,512*amount);
|
|
done+=amount;
|
|
sec = sector + done;
|
|
#ifdef CACHE_SECTOR_LOCATION
|
|
seek_cache = sector + done;
|
|
#endif
|
|
if((count-done)<=MAX_READ_SECTORS)
|
|
{
|
|
amount = count - done;
|
|
}
|
|
else
|
|
{
|
|
amount = MAX_READ_SECTORS;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
#ifdef CACHE_SECTOR_LOCATION
|
|
seek_cache = 0xfffffff8;
|
|
#endif
|
|
return false;
|
|
}
|
|
}
|
|
free(buf);
|
|
if (usb_verbose) {
|
|
printf("usb-r: %x [%d]\n", sector, count);
|
|
//sleep(1);
|
|
}
|
|
//printf("ret = %x\n",ret);
|
|
return true;
|
|
}
|
|
|
|
bool __io_uns_WriteSectors(u32 sector, u32 count, void *buffer)
|
|
{
|
|
|
|
u8* buf;
|
|
s32 whence;
|
|
u32 done;
|
|
u32 sec;
|
|
u32 amount;
|
|
u8* resultbuf;
|
|
|
|
done = 0;
|
|
sec = sector;
|
|
if (count <= MAX_WRITE_SECTORS)
|
|
{
|
|
amount = count;
|
|
}
|
|
else
|
|
{
|
|
amount = MAX_WRITE_SECTORS;
|
|
}
|
|
// buf = (u8 *)memalign(32, 512 * amount);
|
|
// sdhc aligns it's buffers on 64 byte boundaries
|
|
buf = (u8 *)memalign(64, 512 * amount);
|
|
|
|
while(done < count)
|
|
{
|
|
whence = 0;
|
|
if ((sec & 0x80000000)!= 0)
|
|
{
|
|
sec &= 0x7fffffff;
|
|
whence = 1;
|
|
}
|
|
#ifdef CACHE_SECTOR_LOCATION
|
|
if ((sector + done) != seek_cache)
|
|
{
|
|
#endif
|
|
ISFS_Seek(fu,sec,whence);
|
|
#ifdef CACHE_SECTOR_LOCATION
|
|
seek_cache = sector + done;
|
|
}
|
|
#endif
|
|
resultbuf = (u8*)buffer + (done * 512);
|
|
memcpy(buf,resultbuf,512*amount);
|
|
s32 ret = ISFS_Write(fu,buf,512*amount);
|
|
if (ret == (s32)(512*amount))
|
|
{
|
|
done+=amount;
|
|
sec = sector + done;
|
|
#ifdef CACHE_SECTOR_LOCATION
|
|
seek_cache = sector + done;
|
|
#endif
|
|
if((count-done)<=MAX_WRITE_SECTORS)
|
|
{
|
|
amount = count - done;
|
|
}
|
|
else
|
|
{
|
|
amount = MAX_WRITE_SECTORS;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
#ifdef CACHE_SECTOR_LOCATION
|
|
seek_cache = 0xfffffff8;
|
|
#endif
|
|
return false;
|
|
}
|
|
}
|
|
|
|
free(buf);
|
|
if (usb_verbose) {
|
|
printf("usb-r: %x [%d]\n", sector, count);
|
|
//sleep(1);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static bool __io_uns_ClearStatus(void)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
static bool __io_uns_Shutdown(void)
|
|
{
|
|
|
|
return true;
|
|
/*
|
|
if ((uneek_fs_type != UNEEK_FS_NONE)&&(uneek_fs_type != UNEEK_FS_BOTH))
|
|
{
|
|
ISFS_Close(fu);
|
|
ISFS_Deinitialize();
|
|
uneek_fs_type = UNEEK_FS_NONE;
|
|
}
|
|
// do nothing
|
|
return true;
|
|
*/
|
|
}
|
|
|
|
static bool __io_uns_NOP(void)
|
|
{
|
|
// do nothing
|
|
return true;
|
|
}
|
|
|
|
|
|
|
|
bool init_uneek_fs(u32 mode)
|
|
{
|
|
|
|
u8* buf = NULL;
|
|
struct _fstats* pstat = NULL;
|
|
//struct _fstats stat;
|
|
|
|
if (uneek_fs_type == UNEEK_FS_NONE){
|
|
ISFS_Initialize();
|
|
fu = ISFS_Open(_dev_obcd, ISFS_OPEN_READ);
|
|
buf = (u8*)memalign(32, sizeof(struct _fstats));
|
|
pstat = (struct _fstats*)buf;
|
|
pstat->file_length = 0;
|
|
pstat->file_pos = 0;
|
|
if(fu >= 0)
|
|
{
|
|
ISFS_GetFileStats(fu,pstat);
|
|
//printf("Filestat length returned %x\n",pstat->file_length);
|
|
//printf("Filestat pos returned %x\n",pstat->file_pos);
|
|
}
|
|
if ((pstat->file_length == 0xfffffff0)&&(pstat->file_pos == 0xfffffff8)&&(fu>=0))
|
|
{
|
|
#ifdef CACHE_SECTOR_LOCATION
|
|
seek_cache = 0xfffffff8;
|
|
#endif
|
|
if (mode & ISFS_OPEN_WRITE)
|
|
{
|
|
__io_usbstorage.ioType = DEVICE_TYPE_WII_USB;
|
|
__io_usbstorage.features = FEATURE_MEDIUM_CANREAD | FEATURE_MEDIUM_CANWRITE | FEATURE_WII_USB;
|
|
__io_usbstorage.startup = (FN_MEDIUM_STARTUP)&__io_uns_Startup;
|
|
__io_usbstorage.isInserted = (FN_MEDIUM_ISINSERTED)&__io_uns_IsInserted;
|
|
__io_usbstorage.readSectors = (FN_MEDIUM_READSECTORS)&__io_uns_ReadSectors;
|
|
__io_usbstorage.writeSectors = (FN_MEDIUM_WRITESECTORS)&__io_uns_WriteSectors;
|
|
__io_usbstorage.clearStatus = (FN_MEDIUM_CLEARSTATUS)&__io_uns_ClearStatus;
|
|
__io_usbstorage.shutdown = (FN_MEDIUM_SHUTDOWN)&__io_uns_Shutdown;
|
|
}
|
|
else
|
|
{
|
|
__io_usbstorage.ioType = DEVICE_TYPE_WII_USB;
|
|
__io_usbstorage.features = FEATURE_MEDIUM_CANREAD | FEATURE_WII_USB;
|
|
__io_usbstorage.startup = (FN_MEDIUM_STARTUP)&__io_uns_Startup;
|
|
__io_usbstorage.isInserted = (FN_MEDIUM_ISINSERTED)&__io_uns_IsInserted;
|
|
__io_usbstorage.readSectors = (FN_MEDIUM_READSECTORS)&__io_uns_ReadSectors;
|
|
__io_usbstorage.writeSectors = (FN_MEDIUM_WRITESECTORS)&__io_uns_NOP; //&__io_uns_WriteSectors
|
|
__io_usbstorage.clearStatus = (FN_MEDIUM_CLEARSTATUS)&__io_uns_ClearStatus;
|
|
__io_usbstorage.shutdown = (FN_MEDIUM_SHUTDOWN)&__io_uns_Shutdown;
|
|
}
|
|
|
|
uneek_fs_type = UNEEK_FS_USB;
|
|
free (buf);
|
|
return true;
|
|
}
|
|
//sneek
|
|
else if ((pstat->file_length == 0xfffffff1)&&(pstat->file_pos == 0xfffffff8)&&(fu>=0))
|
|
{
|
|
#ifdef CACHE_SECTOR_LOCATION
|
|
seek_cache = 0xfffffff8;
|
|
#endif
|
|
uneek_fs_type = UNEEK_FS_SD;
|
|
if (mode & ISFS_OPEN_WRITE)
|
|
{
|
|
__io_wiisd.ioType = DEVICE_TYPE_WII_SD;
|
|
__io_wiisd.features = FEATURE_MEDIUM_CANREAD | FEATURE_MEDIUM_CANWRITE | FEATURE_WII_SD;
|
|
__io_wiisd.startup = (FN_MEDIUM_STARTUP)&__io_uns_Startup;
|
|
__io_wiisd.isInserted = (FN_MEDIUM_ISINSERTED)&__io_uns_IsInserted;
|
|
__io_wiisd.readSectors = (FN_MEDIUM_READSECTORS)&__io_uns_ReadSectors;
|
|
__io_wiisd.writeSectors = (FN_MEDIUM_WRITESECTORS)&__io_uns_WriteSectors;
|
|
__io_wiisd.clearStatus = (FN_MEDIUM_CLEARSTATUS)&__io_uns_ClearStatus;
|
|
__io_wiisd.shutdown = (FN_MEDIUM_SHUTDOWN)&__io_uns_Shutdown;
|
|
|
|
//usb and sd will be treated equally
|
|
//needed for joyflow with the sd only setup
|
|
|
|
if (mode & ISFS_OPEN_ALL)
|
|
{
|
|
__io_usbstorage.ioType = DEVICE_TYPE_WII_USB;
|
|
__io_usbstorage.features = FEATURE_MEDIUM_CANREAD | FEATURE_MEDIUM_CANWRITE | FEATURE_WII_USB;
|
|
__io_usbstorage.startup = (FN_MEDIUM_STARTUP)&__io_uns_Startup;
|
|
__io_usbstorage.isInserted = (FN_MEDIUM_ISINSERTED)&__io_uns_IsInserted;
|
|
__io_usbstorage.readSectors = (FN_MEDIUM_READSECTORS)&__io_uns_ReadSectors;
|
|
__io_usbstorage.writeSectors = (FN_MEDIUM_WRITESECTORS)&__io_uns_WriteSectors;
|
|
__io_usbstorage.clearStatus = (FN_MEDIUM_CLEARSTATUS)&__io_uns_ClearStatus;
|
|
__io_usbstorage.shutdown = (FN_MEDIUM_SHUTDOWN)&__io_uns_Shutdown;
|
|
uneek_fs_type = UNEEK_FS_BOTH;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
__io_wiisd.ioType = DEVICE_TYPE_WII_SD;
|
|
__io_wiisd.features = FEATURE_MEDIUM_CANREAD | FEATURE_WII_SD;
|
|
__io_wiisd.startup = (FN_MEDIUM_STARTUP)&__io_uns_Startup;
|
|
__io_wiisd.isInserted = (FN_MEDIUM_ISINSERTED)&__io_uns_IsInserted;
|
|
__io_wiisd.readSectors = (FN_MEDIUM_READSECTORS)&__io_uns_ReadSectors;
|
|
__io_wiisd.writeSectors = (FN_MEDIUM_WRITESECTORS)&__io_uns_NOP; //&__io_uns_WriteSectors
|
|
__io_wiisd.clearStatus = (FN_MEDIUM_CLEARSTATUS)&__io_uns_ClearStatus;
|
|
__io_wiisd.shutdown = (FN_MEDIUM_SHUTDOWN)&__io_uns_Shutdown;
|
|
if(mode & ISFS_OPEN_ALL)
|
|
{
|
|
__io_usbstorage.ioType = DEVICE_TYPE_WII_USB;
|
|
__io_usbstorage.features = FEATURE_MEDIUM_CANREAD | FEATURE_WII_USB;
|
|
__io_usbstorage.startup = (FN_MEDIUM_STARTUP)&__io_uns_Startup;
|
|
__io_usbstorage.isInserted = (FN_MEDIUM_ISINSERTED)&__io_uns_IsInserted;
|
|
__io_usbstorage.readSectors = (FN_MEDIUM_READSECTORS)&__io_uns_ReadSectors;
|
|
__io_usbstorage.writeSectors = (FN_MEDIUM_WRITESECTORS)&__io_uns_NOP; //&__io_uns_WriteSectors
|
|
__io_usbstorage.clearStatus = (FN_MEDIUM_CLEARSTATUS)&__io_uns_ClearStatus;
|
|
__io_usbstorage.shutdown = (FN_MEDIUM_SHUTDOWN)&__io_uns_Shutdown;
|
|
uneek_fs_type = UNEEK_FS_BOTH;
|
|
}
|
|
}
|
|
free (buf);
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
/* these should be initialised right in the ogc library */
|
|
/* so we will ignore those for the moment */
|
|
/*
|
|
__io_usbstorage.ioType = DEVICE_TYPE_WII_USB;
|
|
__io_usbstorage.features = FEATURE_MEDIUM_CANREAD | FEATURE_MEDIUM_CANWRITE | FEATURE_WII_USB;
|
|
__io_usbstorage.startup = (FN_MEDIUM_STARTUP)&__io_usb_Startup;
|
|
__io_usbstorage.isInserted = (FN_MEDIUM_ISINSERTED)&__io_usb_IsInserted;
|
|
__io_usbstorage.readSectors = (FN_MEDIUM_READSECTORS)&__io_usb_ReadSectors;
|
|
__io_usbstorage.writeSectors = (FN_MEDIUM_WRITESECTORS)&__io_usb_WriteSectors;
|
|
__io_usbstorage.clearStatus = (FN_MEDIUM_CLEARSTATUS)&__io_usb_ClearStatus;
|
|
__io_usbstorage.shutdown = (FN_MEDIUM_SHUTDOWN)&__io_usb_Shutdown;
|
|
*/
|
|
|
|
uneek_fs_type = UNEEK_FS_NONE;
|
|
free(buf);
|
|
ISFS_Close(fu);
|
|
ISFS_Deinitialize();
|
|
return false;
|
|
}
|
|
}
|
|
else //was already initialised
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
|
|
/* stay compatible with previous versions */
|
|
bool check_uneek_fs(void)
|
|
{
|
|
if(uneek_fs_type != UNEEK_FS_NONE)
|
|
{
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
s32 check_uneek_fs_type(void)
|
|
{
|
|
return uneek_fs_type;
|
|
}
|
|
|
|
bool exit_uneek_fs(void)
|
|
{
|
|
if (uneek_fs_type != UNEEK_FS_NONE)
|
|
{
|
|
ISFS_Close(fu);
|
|
ISFS_Deinitialize();
|
|
uneek_fs_type = UNEEK_FS_NONE;
|
|
}
|
|
// do nothing
|
|
return true;
|
|
}
|
|
|
|
|
|
bool SenseSneek (bool isfsinit)
|
|
{
|
|
bool ret = true;
|
|
char path[ISFS_MAXPATH] ATTRIBUTE_ALIGN(32);
|
|
|
|
strcpy (path, "/SNEEK/kernel.bin");
|
|
|
|
if (isfsinit) ISFS_Initialize ();
|
|
|
|
s32 fd = ISFS_Open(path, ISFS_OPEN_READ);
|
|
if (fd < 0)
|
|
ret = false;
|
|
else
|
|
ISFS_Close (fd);
|
|
|
|
if (isfsinit) ISFS_Deinitialize();
|
|
return ret;
|
|
}
|
|
|
|
|
|
|
|
bool is_neek(void)
|
|
{
|
|
u32 boot2version;
|
|
|
|
if(confirm_neek1 == 5)
|
|
{
|
|
ES_GetBoot2Version(&boot2version);
|
|
if(boot2version < 5)
|
|
confirm_neek1 = false;
|
|
else
|
|
confirm_neek1 = true;
|
|
}
|
|
return confirm_neek1;
|
|
}
|
|
|
|
|
|
bool is_neek2 (bool isfsinit)
|
|
{
|
|
|
|
char path[ISFS_MAXPATH] ATTRIBUTE_ALIGN(32);
|
|
|
|
if(confirm_neek2 == 5)
|
|
{
|
|
confirm_neek2 = true;
|
|
strcpy (path, "/SNEEK/kernel.bin");
|
|
|
|
if (isfsinit) ISFS_Initialize ();
|
|
|
|
s32 fd = ISFS_Open(path, ISFS_OPEN_READ);
|
|
if (fd < 0)
|
|
confirm_neek2 = false;
|
|
else
|
|
ISFS_Close (fd);
|
|
|
|
if (isfsinit) ISFS_Deinitialize ();
|
|
}
|
|
return confirm_neek2;
|
|
}
|
|
|
|
//! New method for determining if this is a real or emu nand.
|
|
//! Works with new versions of classic Crediar NEEK
|
|
bool is_neek3(bool isfsinit)
|
|
{
|
|
u32 num = 0;
|
|
|
|
//! Thanks goes to the almighty giantpune for this
|
|
if(confirm_neek3 == 5)
|
|
{
|
|
if (isfsinit) ISFS_Initialize ();
|
|
if(ISFS_ReadDir("/Sneek", NULL, &num)==0)
|
|
confirm_neek3 = true;
|
|
else
|
|
confirm_neek3 = false;
|
|
if (isfsinit) ISFS_Deinitialize ();
|
|
}
|
|
return confirm_neek3;
|
|
}
|
|
|
|
bool is_neek4(bool isfsinit)
|
|
{
|
|
|
|
u32 ownerID;
|
|
u16 groupID;
|
|
u8 attributes;
|
|
u8 ownerperm;
|
|
u8 groupperm;
|
|
u8 otherperm;
|
|
|
|
if(confirm_neek4 == 5)
|
|
{
|
|
confirm_neek4 = false;
|
|
if(isfsinit) ISFS_Initialize();
|
|
ISFS_GetAttr("/shared1/00000000.app", &ownerID, &groupID, &attributes, &ownerperm, &groupperm, &otherperm);
|
|
if(otherperm)
|
|
confirm_neek4 = true;
|
|
|
|
if(isfsinit) ISFS_Deinitialize();
|
|
}
|
|
return confirm_neek4;
|
|
}
|
|
|
|
bool WII_Launch_Channel(char* which)
|
|
{
|
|
#ifdef HW_RVL
|
|
size_t wlen;
|
|
u64 title_id;
|
|
int titlemsb, titlelsb;
|
|
char stitlexsb[16];
|
|
union lsbstufftype
|
|
{
|
|
char titlename[4];
|
|
u32 title_lsb;
|
|
}lsbstuff;
|
|
|
|
|
|
wlen = strlen(which);
|
|
if ((wlen != 4) && (wlen != 16))
|
|
{
|
|
#ifdef SHOW_GECKO_DEBUG
|
|
gprintf("Title %s has an invalid length\n",which);
|
|
#endif
|
|
return false;
|
|
}
|
|
if (wlen == 4)
|
|
{
|
|
titlemsb = 0x00010001;
|
|
strncpy(lsbstuff.titlename,which,4);
|
|
titlelsb = lsbstuff.title_lsb;
|
|
}
|
|
else
|
|
{
|
|
strncpy(stitlexsb,which,8);
|
|
stitlexsb[8]=0;
|
|
sscanf(stitlexsb,"%x",&titlemsb);
|
|
strncpy(stitlexsb,which+8,8);
|
|
stitlexsb[8]=0;
|
|
sscanf(stitlexsb,"%x",&titlelsb);
|
|
}
|
|
title_id = (u64)(titlemsb) << 32;
|
|
title_id = title_id + (u64)(titlelsb);
|
|
#ifdef SHOW_GECKO_DEBUG
|
|
gprintf( "titleid = %08x %08x\r\n", (u32)((title_id)>>32), (u32)(title_id) );
|
|
s32 lret = WII_LaunchTitle(title_id);
|
|
gprintf("WII_LaunchTitle returned %d\r\n",lret);
|
|
#else
|
|
WII_LaunchTitle(title_id);
|
|
#endif
|
|
// basically, it shouldn't get here I assume
|
|
#endif //HW_RVL
|
|
return false;
|
|
} |