mirror of
https://github.com/wiidev/usbloadergx.git
synced 2024-12-25 19:21:53 +01:00
* move title stuff into a class
* only get the list of shit installed on the wii 1 time and use that list globally for stuff like checking if something is installed, getting channel names, getting title versions * remove unused files * probably fuckup svn merge
This commit is contained in:
parent
1902318e4e
commit
e1a36e8988
@ -2,8 +2,8 @@
|
||||
<app version="1">
|
||||
<name> USB Loader GX</name>
|
||||
<coder>USB Loader GX Team</coder>
|
||||
<version>1.0 r949</version>
|
||||
<release_date>201009180855</release_date>
|
||||
<version>1.0 r950</version>
|
||||
<release_date>201009182245</release_date>
|
||||
<short_description>Loads games from USB-devices</short_description>
|
||||
<long_description>USB Loader GX is a libwiigui based USB iso loader with a wii-like GUI. You can install games to your HDDs and boot them with shorter loading times.
|
||||
The interactive GUI is completely controllable with WiiMote, Classic Controller or GC Controller.
|
||||
|
4
Makefile
4
Makefile
@ -90,7 +90,7 @@ export CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
|
||||
sFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
|
||||
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.S)))
|
||||
ELFFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.elf)))
|
||||
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
|
||||
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.bin)))
|
||||
TTFFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.ttf)))
|
||||
PNGFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.png)))
|
||||
OGGFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.ogg)))
|
||||
@ -112,7 +112,7 @@ export OFILES := $(addsuffix .o,$(BINFILES)) \
|
||||
$(sFILES:.s=.o) $(SFILES:.S=.o) \
|
||||
$(TTFFILES:.ttf=.ttf.o) $(PNGFILES:.png=.png.o) $(addsuffix .o,$(DOLFILES))\
|
||||
$(OGGFILES:.ogg=.ogg.o) $(PCMFILES:.pcm=.pcm.o) $(MP3FILES:.mp3=.mp3.o) \
|
||||
$(addsuffix .o,$(ELFFILES))
|
||||
$(addsuffix .o,$(ELFFILES)) $(CURDIR)/data/magic_patcher.o
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# build a list of include paths
|
||||
|
@ -33,12 +33,13 @@ bool InitGecko()
|
||||
if (geckoattached)
|
||||
{
|
||||
usb_flush(EXI_CHANNEL_1);
|
||||
CON_EnableGecko( 1, true );
|
||||
return true;
|
||||
}
|
||||
else return false;
|
||||
}
|
||||
|
||||
static char ascii(char s)
|
||||
char ascii(char s)
|
||||
{
|
||||
if(s < 0x20)
|
||||
return '.';
|
||||
|
@ -7,6 +7,8 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
char ascii(char s);
|
||||
|
||||
#ifndef NO_DEBUG
|
||||
//use this just like printf();
|
||||
void gprintf(const char *str, ...);
|
||||
|
@ -1,3 +1,4 @@
|
||||
#if 0
|
||||
#include <gccore.h>
|
||||
#include <ogcsys.h>
|
||||
#include <malloc.h>
|
||||
@ -102,6 +103,10 @@ int BootHomebrew()
|
||||
if (!entry)
|
||||
Sys_BackToLoader();
|
||||
|
||||
VIDEO_SetBlack(true);
|
||||
VIDEO_Flush();
|
||||
VIDEO_WaitVSync();
|
||||
|
||||
SYS_ResetSystem(SYS_SHUTDOWN, 0, 0);
|
||||
_CPU_ISR_Disable (cpu_isr);
|
||||
__exception_closeall();
|
||||
@ -129,3 +134,218 @@ int BootHomebrew(const char * filepath)
|
||||
|
||||
return BootHomebrew();
|
||||
}
|
||||
#endif
|
||||
|
||||
#include <gccore.h>
|
||||
#include <ogcsys.h>
|
||||
#include <malloc.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <ogc/machine/processor.h>
|
||||
#include <wiiuse/wpad.h>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include "../lstub.h"
|
||||
#include "../sys.h"
|
||||
#include "../gecko.h"
|
||||
|
||||
#include "fatmounter.h"
|
||||
#include "dolloader.h"
|
||||
|
||||
|
||||
void *innetbuffer = NULL;
|
||||
static u8 *homebrewbuffer =( u8 * )0x92000000;
|
||||
u32 homebrewsize = 0;
|
||||
static std::vector<std::string> Arguments;
|
||||
|
||||
extern const u8 app_booter_dol[];
|
||||
|
||||
int AllocHomebrewMemory( u32 filesize )
|
||||
{
|
||||
|
||||
innetbuffer = malloc( filesize );
|
||||
|
||||
if ( !innetbuffer )
|
||||
return -1;
|
||||
|
||||
homebrewsize = filesize;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void AddBootArgument( const char * argv )
|
||||
{
|
||||
std::string arg( argv );
|
||||
Arguments.push_back( arg );
|
||||
}
|
||||
|
||||
int CopyHomebrewMemory( u8 *temp, u32 pos, u32 len )
|
||||
{
|
||||
homebrewsize += len;
|
||||
memcpy(( homebrewbuffer ) + pos, temp, len );
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void FreeHomebrewBuffer()
|
||||
{
|
||||
homebrewbuffer = ( u8 * ) 0x92000000;
|
||||
homebrewsize = 0;
|
||||
|
||||
if ( innetbuffer )
|
||||
{
|
||||
free( innetbuffer );
|
||||
innetbuffer = NULL;
|
||||
}
|
||||
|
||||
Arguments.clear();
|
||||
}
|
||||
|
||||
static int SetupARGV( struct __argv * args )
|
||||
{
|
||||
if ( !args )
|
||||
return -1;
|
||||
|
||||
bzero( args, sizeof( struct __argv ) );
|
||||
args->argvMagic = ARGV_MAGIC;
|
||||
|
||||
u32 stringlength = 1;
|
||||
|
||||
/** Append Arguments **/
|
||||
for ( u32 i = 0; i < Arguments.size(); i++ )
|
||||
{
|
||||
stringlength += Arguments[i].size() + 1;
|
||||
}
|
||||
|
||||
args->length = stringlength;
|
||||
args->commandLine = ( char* ) malloc( args->length );
|
||||
|
||||
if ( !args->commandLine )
|
||||
return -1;
|
||||
|
||||
u32 argc = 0;
|
||||
u32 position = 0;
|
||||
|
||||
/** Append Arguments **/
|
||||
for ( u32 i = 0; i < Arguments.size(); i++ )
|
||||
{
|
||||
strcpy( &args->commandLine[position], Arguments[i].c_str() );
|
||||
position += Arguments[i].size() + 1;
|
||||
argc++;
|
||||
}
|
||||
|
||||
args->argc = argc;
|
||||
|
||||
args->commandLine[args->length - 1] = '\0';
|
||||
args->argv = &args->commandLine;
|
||||
args->endARGV = args->argv + 1;
|
||||
|
||||
Arguments.clear();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int RunAppbooter()
|
||||
{
|
||||
if ( homebrewsize == 0 )
|
||||
return -1;
|
||||
|
||||
struct __argv args;
|
||||
SetupARGV( &args );
|
||||
|
||||
u32 cpu_isr;
|
||||
|
||||
entrypoint entry = ( entrypoint ) load_dol(( void* ) app_booter_dol, &args );
|
||||
|
||||
if ( !entry )
|
||||
{
|
||||
FreeHomebrewBuffer();
|
||||
return -1;
|
||||
}
|
||||
|
||||
u64 currentStub = getStubDest();
|
||||
loadStub();
|
||||
|
||||
if ( Set_Stub_Split( 0x00010001, "UNEO" ) < 0 )
|
||||
{
|
||||
if ( Set_Stub_Split( 0x00010001, "ULNR" ) < 0 )
|
||||
{
|
||||
if ( !currentStub )
|
||||
currentStub = 0x100000002ULL;
|
||||
|
||||
Set_Stub( currentStub );
|
||||
}
|
||||
}
|
||||
|
||||
SDCard_deInit();
|
||||
USBDevice_deInit();
|
||||
|
||||
WPAD_Flush( 0 );
|
||||
WPAD_Disconnect( 0 );
|
||||
WPAD_Shutdown();
|
||||
|
||||
SYS_ResetSystem( SYS_SHUTDOWN, 0, 0 );
|
||||
_CPU_ISR_Disable( cpu_isr );
|
||||
__exception_closeall();
|
||||
entry();
|
||||
_CPU_ISR_Restore( cpu_isr );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int BootHomebrew( char * filepath )
|
||||
{
|
||||
void *buffer = NULL;
|
||||
u32 filesize = 0;
|
||||
|
||||
FILE *file = fopen( filepath, "rb" );
|
||||
|
||||
if ( !file )
|
||||
Sys_BackToLoader();
|
||||
|
||||
fseek( file, 0, SEEK_END );
|
||||
filesize = ftell( file );
|
||||
rewind( file );
|
||||
|
||||
buffer = malloc( filesize );
|
||||
|
||||
if ( fread( buffer, 1, filesize, file ) != filesize )
|
||||
{
|
||||
fclose( file );
|
||||
free( buffer );
|
||||
SDCard_deInit();
|
||||
USBDevice_deInit();
|
||||
Sys_BackToLoader();
|
||||
}
|
||||
|
||||
fclose( file );
|
||||
|
||||
CopyHomebrewMemory(( u8* ) buffer, 0, filesize );
|
||||
|
||||
if ( buffer )
|
||||
{
|
||||
free( buffer );
|
||||
buffer = NULL;
|
||||
}
|
||||
|
||||
AddBootArgument( filepath );
|
||||
return RunAppbooter();
|
||||
}
|
||||
|
||||
int BootHomebrewFromMem()
|
||||
{
|
||||
gprintf( "BootHomebrewFromMem()\n %p, %08x\n", innetbuffer, homebrewsize );
|
||||
|
||||
if ( !innetbuffer )
|
||||
{
|
||||
gprintf( "!innetbuffer\n" );
|
||||
SDCard_deInit();
|
||||
USBDevice_deInit();
|
||||
Sys_BackToLoader();
|
||||
}
|
||||
|
||||
CopyHomebrewMemory(( u8* ) innetbuffer, 0, homebrewsize );
|
||||
free( innetbuffer );
|
||||
|
||||
return RunAppbooter();
|
||||
}
|
||||
|
@ -1,11 +1,15 @@
|
||||
#ifndef _BOOTHOMEBREW_H_
|
||||
#define _BOOTHOMEBREW_H_
|
||||
|
||||
int BootHomebrew();
|
||||
int BootHomebrew(const char * filepath);
|
||||
//int BootHomebrew();
|
||||
int BootHomebrewFromMem();
|
||||
int BootHomebrew( char * filepath);
|
||||
int CopyHomebrewMemory(u8 *temp, u32 pos, u32 len);
|
||||
void AddBootArgument(const char * arg);
|
||||
void FreeHomebrewBuffer();
|
||||
int LoadHomebrew(const char * filepath);
|
||||
int AllocHomebrewMemory( u32 filesize );
|
||||
extern void *innetbuffer;
|
||||
extern u32 homebrewsize;
|
||||
|
||||
#endif
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -9,6 +9,7 @@
|
||||
#include "gui.h"
|
||||
#include "../wpad.h"
|
||||
#include "../main.h"
|
||||
#include "../gecko.h"
|
||||
#include "../settings/cfg.h"
|
||||
#include "gui_customoptionbrowser.h"
|
||||
|
||||
@ -83,7 +84,7 @@ void customOptionList::SetSize(int Size) //set number of lines
|
||||
}
|
||||
void customOptionList::SetName(int i, const char *format, ...)
|
||||
{
|
||||
if(i >= length) SetLength(i+1);
|
||||
if(i >= length) SetLength(i+1);
|
||||
|
||||
if(i >= 0 && i < length)
|
||||
{
|
||||
@ -95,6 +96,7 @@ void customOptionList::SetName(int i, const char *format, ...)
|
||||
va_end(va);
|
||||
changed = true;
|
||||
}
|
||||
//gprintf("customOptionList::SetName( %d, %s )\n", i, name[i] );
|
||||
}
|
||||
void customOptionList::SetValue(int i, const char *format, ...)
|
||||
{
|
||||
@ -120,6 +122,7 @@ void customOptionList::SetValue(int i, const char *format, ...)
|
||||
}
|
||||
}
|
||||
}
|
||||
//gprintf("customOptionList::SetValue( %d, %s )\n", i, value[i] );
|
||||
}
|
||||
void customOptionList::Clear(bool OnlyValue/*=false*/)
|
||||
{
|
||||
|
114
source/lstub.cpp
Normal file
114
source/lstub.cpp
Normal file
@ -0,0 +1,114 @@
|
||||
//functions for manipulating the HBC stub by giantpune
|
||||
|
||||
#include <string.h>
|
||||
#include <ogcsys.h>
|
||||
#include <malloc.h>
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
#include "lstub.h"
|
||||
#include "stub_bin.h"
|
||||
#include "gecko.h"
|
||||
|
||||
#include "wad/nandtitle.h"
|
||||
|
||||
static char* determineStubTIDLocation()
|
||||
{
|
||||
u32 *stubID = (u32*)0x80001818;
|
||||
|
||||
//HBC stub 1.0.6 and lower, and stub.bin
|
||||
if( stubID[ 0 ] == 0x480004c1 && stubID[ 1 ] == 0x480004f5 )
|
||||
return (char *)0x800024C6;
|
||||
|
||||
//HBC stub changed @ version 1.0.7. this file was last updated for HBC 1.0.8
|
||||
else if ( stubID[ 0 ] == 0x48000859 && stubID[ 1 ] == 0x4800088d )
|
||||
return (char *)0x8000286A;
|
||||
|
||||
//hexdump( stubID, 0x20 );
|
||||
return NULL;
|
||||
|
||||
}
|
||||
|
||||
s32 Set_Stub(u64 reqID)
|
||||
{
|
||||
if( titles.IndexOf( reqID ) < 0 )
|
||||
return WII_EINSTALL;
|
||||
|
||||
char *stub = determineStubTIDLocation();
|
||||
if( !stub )
|
||||
return -68;
|
||||
|
||||
stub[0] = TITLE_7(reqID);
|
||||
stub[1] = TITLE_6(reqID);
|
||||
stub[8] = TITLE_5(reqID);
|
||||
stub[9] = TITLE_4(reqID);
|
||||
stub[4] = TITLE_3(reqID);
|
||||
stub[5] = TITLE_2(reqID);
|
||||
stub[12] = TITLE_1(reqID);
|
||||
stub[13] = ((u8)(reqID));
|
||||
|
||||
DCFlushRange( stub, 0x10 );
|
||||
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
s32 Set_Stub_Split(u32 type, const char* reqID)
|
||||
{
|
||||
char tmp[4];
|
||||
u32 lower;
|
||||
sprintf(tmp,"%c%c%c%c",reqID[0],reqID[1],reqID[2],reqID[3]);
|
||||
memcpy(&lower, tmp, 4);
|
||||
u64 reqID64 = TITLE_ID(type, lower);
|
||||
return Set_Stub(reqID64);
|
||||
|
||||
}
|
||||
|
||||
void loadStub()
|
||||
{
|
||||
char *stubLoc = (char *)0x80001800;
|
||||
memcpy(stubLoc, stub_bin, stub_bin_size);
|
||||
DCFlushRange( stubLoc, stub_bin_size );
|
||||
}
|
||||
|
||||
u64 getStubDest()
|
||||
{
|
||||
if (!hbcStubAvailable())
|
||||
return 0;
|
||||
|
||||
char ret[ 8 ];
|
||||
u64 retu = 0;
|
||||
|
||||
char *stub = determineStubTIDLocation();
|
||||
if( !stub )
|
||||
return 0;
|
||||
|
||||
|
||||
ret[0] = stub[0];
|
||||
ret[1] = stub[1];
|
||||
ret[2] = stub[8];
|
||||
ret[3] = stub[9];
|
||||
ret[4] = stub[4];
|
||||
ret[5] = stub[5];
|
||||
ret[6] = stub[12];
|
||||
ret[7] = stub[13];
|
||||
|
||||
memcpy(&retu, ret, 8);
|
||||
|
||||
return retu;
|
||||
}
|
||||
|
||||
u8 hbcStubAvailable()
|
||||
{
|
||||
char * sig = (char *)0x80001804;
|
||||
return (
|
||||
sig[0] == 'S' &&
|
||||
sig[1] == 'T' &&
|
||||
sig[2] == 'U' &&
|
||||
sig[3] == 'B' &&
|
||||
sig[4] == 'H' &&
|
||||
sig[5] == 'A' &&
|
||||
sig[6] == 'X' &&
|
||||
sig[7] == 'X') ? 1 : 0;
|
||||
}
|
||||
|
@ -4,10 +4,6 @@
|
||||
#ifndef _LSTUB_H_
|
||||
#define _LSTUB_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
//to set the "return to" stub for a certain ID
|
||||
//!reqID is the Requested ID to return to
|
||||
//!returns WII_EINTERNAL if it cant get the list of installed titles with ES functions
|
||||
@ -31,8 +27,4 @@ u64 getStubDest();
|
||||
u8 hbcStubAvailable();
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -47,17 +47,19 @@ extern "C"
|
||||
#include "fat.h"
|
||||
#include "gecko.h"
|
||||
#include "svnrev.h"
|
||||
#include "wad/title.h"
|
||||
#include "usbloader/partition_usbloader.h"
|
||||
#include "usbloader/usbstorage2.h"
|
||||
#include "memory/mem2.h"
|
||||
#include "lstub.h"
|
||||
#include "usbloader/usbstorage2.h"
|
||||
#include "wad/nandtitle.h"
|
||||
|
||||
extern bool geckoinit;
|
||||
extern bool textVideoInit;
|
||||
extern char headlessID[8];
|
||||
|
||||
NandTitle titles;
|
||||
|
||||
/* Constants */
|
||||
#define CONSOLE_XCOORD 260
|
||||
#define CONSOLE_YCOORD 115
|
||||
@ -75,7 +77,9 @@ int main(int argc, char *argv[])
|
||||
geckoinit = InitGecko();
|
||||
__exception_setreload(20);
|
||||
|
||||
printf("\n\tStarting up");
|
||||
printf("\tStarting up\n");
|
||||
titles.Get();
|
||||
titles.Exists( 0x100014e414c45ULL );
|
||||
|
||||
bool bootDevice_found=false;
|
||||
if (argc >= 1)
|
||||
@ -89,14 +93,14 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
//Let's use libogc sd/usb for config loading
|
||||
printf("\n\tInitialize sd card");
|
||||
printf("\tInitialize sd card\n");
|
||||
SDCard_Init();
|
||||
printf("\n\tInitialize usb device");
|
||||
printf("\tInitialize usb device\n");
|
||||
USBDevice_Init();
|
||||
|
||||
if (!bootDevice_found)
|
||||
{
|
||||
printf("\n\tSearch for configuration file");
|
||||
printf("\tSearch for configuration file\n");
|
||||
//try USB
|
||||
//left in all the dol and elf files in this check in case this is the first time running the app and they dont have the config
|
||||
if (checkfile((char*) "USB:/config/GXglobal.cfg") || (checkfile((char*) "USB:/apps/usbloader_gx/boot.elf"))
|
||||
@ -104,13 +108,13 @@ int main(int argc, char *argv[])
|
||||
|| checkfile((char*) "USB:/apps/usbloader_gx/boot.dol"))
|
||||
strcpy(bootDevice, "USB:");
|
||||
|
||||
printf("\n\tConfiguration file is on %s", bootDevice);
|
||||
printf("\tConfiguration file is on %s\n", bootDevice);
|
||||
}
|
||||
|
||||
gettextCleanUp();
|
||||
printf("\n\tLoading configuration...");
|
||||
printf("\tLoading configuration...");
|
||||
CFG_Load();
|
||||
printf("done");
|
||||
printf("done\n");
|
||||
|
||||
SDCard_deInit();// unmount SD for reloading IOS
|
||||
USBDevice_deInit();// unmount USB for reloading IOS
|
||||
@ -118,10 +122,10 @@ int main(int argc, char *argv[])
|
||||
|
||||
// This part is added, because we need a identify patched ios
|
||||
//! pune please replace this with your magic patch functions - Dimok
|
||||
if (IOS_ReloadIOSsafe(236) < 0)
|
||||
IOS_ReloadIOSsafe(36);
|
||||
//if (IOS_ReloadIOSsafe(236) < 0)
|
||||
// IOS_ReloadIOSsafe(36);
|
||||
|
||||
printf("\n\tCheck for an existing cIOS");
|
||||
printf("\tCheck for an existing cIOS\n");
|
||||
CheckForCIOS();
|
||||
|
||||
// Let's load the cIOS now
|
||||
|
@ -23,7 +23,6 @@
|
||||
#include "themes/Theme_Downloader.h"
|
||||
#include "usbloader/disc.h"
|
||||
#include "usbloader/GameList.h"
|
||||
#include "wad/title.h"
|
||||
#include "xml/xml.h"
|
||||
#include "audio.h"
|
||||
#include "gecko.h"
|
||||
@ -34,6 +33,7 @@
|
||||
#include "patches/fst.h"
|
||||
#include "usbloader/frag.h"
|
||||
#include "usbloader/wbfs.h"
|
||||
#include "wad/nandtitle.h"
|
||||
|
||||
/*** Variables that are also used extern ***/
|
||||
GuiWindow * mainWindow = NULL;
|
||||
@ -322,7 +322,7 @@ int MainMenu(int menu) {
|
||||
|
||||
|
||||
// MemInfoPrompt();
|
||||
gprintf("\nExiting main GUI. mountMethod = %d",mountMethod);
|
||||
gprintf("Exiting main GUI. mountMethod = %d\n",mountMethod);
|
||||
|
||||
CloseXMLDatabase();
|
||||
NewTitles::DestroyInstance();
|
||||
@ -375,15 +375,16 @@ int MainMenu(int menu) {
|
||||
}
|
||||
else if (boothomebrew == 2) {
|
||||
gprintf("\nBootHomebrew from Menu");
|
||||
BootHomebrew();
|
||||
//BootHomebrew();
|
||||
BootHomebrewFromMem();
|
||||
}
|
||||
else {
|
||||
gprintf("\n\tSettings.partition:%d",Settings.partition);
|
||||
gprintf("\tSettings.partition: %d\n",Settings.partition);
|
||||
struct discHdr *header = NULL;
|
||||
//if the GUI was "skipped" to boot a game from main(argv[1])
|
||||
if (strcmp(headlessID,"")!=0)
|
||||
{
|
||||
gprintf("\n\tHeadless mode (%s)",headlessID);
|
||||
gprintf("\tHeadless mode (%s)\n",headlessID);
|
||||
gameList.LoadUnfiltered();
|
||||
if (!gameList.size())
|
||||
{
|
||||
@ -399,13 +400,13 @@ int MainMenu(int menu) {
|
||||
if (strcmp(tmp,headlessID)==0)
|
||||
{
|
||||
gameSelected = i;
|
||||
gprintf(" found (%d)",i);
|
||||
gprintf(" found (%d)\n",i);
|
||||
break;
|
||||
}
|
||||
//if the game was not found
|
||||
if (i==gameList.GameCount()-1)
|
||||
{
|
||||
gprintf(" not found (%d IDs checked)",i);
|
||||
gprintf(" not found (%d IDs checked)\n",i);
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
@ -483,20 +484,20 @@ int MainMenu(int menu) {
|
||||
}
|
||||
if (!mountMethod)
|
||||
{
|
||||
gprintf("\nLoading fragment list...");
|
||||
gprintf("Loading fragment list...");
|
||||
ret = get_frag_list(header->id);
|
||||
gprintf("%d\n", ret);
|
||||
|
||||
gprintf("\nSetting fragment list...");
|
||||
gprintf("Setting fragment list...");
|
||||
ret = set_frag_list(header->id);
|
||||
gprintf("%d\n", ret);
|
||||
|
||||
ret = Disc_SetUSB(header->id);
|
||||
if (ret < 0) Sys_BackToLoader();
|
||||
gprintf("\n\tUSB set to game");
|
||||
gprintf("\tUSB set to game\n");
|
||||
}
|
||||
else {
|
||||
gprintf("\n\tUSB not set, loading DVD");
|
||||
gprintf("\tUSB not set, loading DVD\n");
|
||||
}
|
||||
ret = Disc_Open();
|
||||
|
||||
@ -505,7 +506,7 @@ int MainMenu(int menu) {
|
||||
if(dvdheader)
|
||||
delete dvdheader;
|
||||
|
||||
gprintf("\nLoading BCA data...");
|
||||
gprintf("Loading BCA data...");
|
||||
ret = do_bca_code(header->id);
|
||||
gprintf("%d\n", ret);
|
||||
|
||||
@ -640,13 +641,14 @@ int MainMenu(int menu) {
|
||||
vipatch = 0;
|
||||
break;
|
||||
}
|
||||
gprintf("\n\tDisc_wiiBoot");
|
||||
gprintf("\tDisc_wiiBoot\n");
|
||||
|
||||
ret = Disc_WiiBoot(videoselected, cheat, vipatch, countrystrings, errorfixer002, alternatedol, alternatedoloffset);
|
||||
if (ret < 0) {
|
||||
Sys_LoadMenu();
|
||||
}
|
||||
|
||||
//should never get here
|
||||
printf("Returning entry point: 0x%0x\n", ret);
|
||||
}
|
||||
return 0;
|
||||
|
@ -17,7 +17,6 @@
|
||||
#include "sys.h"
|
||||
#include "settings/cfg.h"
|
||||
#include "memory.h"
|
||||
#include "../wad/title.h"
|
||||
#include "../gecko.h"
|
||||
#include "../patches/dvd_broadway.h"
|
||||
|
||||
|
@ -34,7 +34,6 @@
|
||||
#include "svnrev.h"
|
||||
#include "audio.h"
|
||||
#include "xml/xml.h"
|
||||
#include "wad/title.h"
|
||||
#include "language/UpdateLanguage.h"
|
||||
#include "gecko.h"
|
||||
#include "lstub.h"
|
||||
|
@ -23,14 +23,10 @@
|
||||
#include "audio.h"
|
||||
#include "wad/wad.h"
|
||||
#include "xml/xml.h"
|
||||
#include "wad/title.h"
|
||||
#include "usbloader/utils.h"
|
||||
#include "gecko.h"
|
||||
#include "wad/nandtitle.h"
|
||||
#include "../usbloader/utils.h"
|
||||
#include "../gecko.h"
|
||||
|
||||
#define typei 0x00010001
|
||||
|
||||
struct discHdr * titleList=NULL;
|
||||
//discHdr ** titleList;
|
||||
u32 titleCnt;
|
||||
extern u32 infilesize;
|
||||
extern u32 uncfilesize;
|
||||
@ -40,8 +36,6 @@ extern char wiiloadVersion[2];
|
||||
#include "unzip/unzip.h"
|
||||
#include "unzip/miniunz.h"
|
||||
|
||||
extern struct discHdr * gameList;
|
||||
extern u32 gameCnt;
|
||||
|
||||
/*** Extern functions ***/
|
||||
extern void ResumeGui();
|
||||
@ -59,183 +53,136 @@ extern wchar_t *gameFilter;
|
||||
* TitleBrowser- opens a browser with a list of installed Titles
|
||||
* relies on code from any title deleter.
|
||||
*********************************************************************************/
|
||||
int TitleBrowser(u32 type) {
|
||||
int TitleBrowser()
|
||||
{
|
||||
|
||||
u32 num_titles;
|
||||
u32 titles[100] ATTRIBUTE_ALIGN(32);
|
||||
u32 num_sys_titles;
|
||||
u32 sys_titles[10] ATTRIBUTE_ALIGN(32);
|
||||
s32 ret = -1;
|
||||
int numtitle;//to get rid of a stupid compile wrning
|
||||
//open the database file
|
||||
FILE *f;
|
||||
char path[100];
|
||||
u64 *titleList = NULL;
|
||||
|
||||
ISFS_Initialize();
|
||||
ISFS_Initialize();//initialize for "titles.Exists()"
|
||||
|
||||
sprintf(path,"%s/config/database.txt",bootDevice);
|
||||
f = fopen(path, "r");
|
||||
// Get count of titles of the good titles
|
||||
num_titles = titles.SetType( 0x10001 );
|
||||
u32 n = num_titles;
|
||||
for( u32 i = 0; i < n; i++ )
|
||||
{
|
||||
u64 tid = titles.Next();
|
||||
if( !tid )
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// Get count of titles of our requested type
|
||||
ret = getTitles_TypeCount(type, &num_titles);
|
||||
if (ret < 0) {
|
||||
//printf("\tError! Can't get count of titles! (ret = %d)\n", ret);
|
||||
//exit(1);
|
||||
}
|
||||
|
||||
// Get titles of our requested type
|
||||
ret = getTitles_Type(type, titles, num_titles);
|
||||
if (ret < 0) {
|
||||
//printf("\tError! Can't get list of titles! (ret = %d)\n", ret);
|
||||
//exit(1);
|
||||
//remove ones not actually installed on the nand
|
||||
if( !titles.Exists( tid ) )
|
||||
{
|
||||
num_titles--;
|
||||
}
|
||||
}
|
||||
|
||||
// Get count of system titles
|
||||
ret = getTitles_TypeCount(0x00010002, &num_sys_titles);
|
||||
if (ret < 0) {
|
||||
//printf("\tError! Can't get count of titles! (ret = %d)\n", ret);
|
||||
//exit(1);
|
||||
num_sys_titles = titles.SetType( 0x10002 );
|
||||
n = num_sys_titles;
|
||||
for( u32 i = 0; i < n; i++ )
|
||||
{
|
||||
u64 tid = titles.Next();
|
||||
if( !tid )
|
||||
{
|
||||
break;
|
||||
}
|
||||
//these can't be booted anyways
|
||||
if( TITLE_LOWER( tid ) == 0x48414741 || TITLE_LOWER( tid ) == 0x48414141 || TITLE_LOWER( tid ) == 0x48414641 )
|
||||
{
|
||||
num_sys_titles--;
|
||||
continue;
|
||||
}
|
||||
|
||||
//these aren't installed on the nand
|
||||
if( !titles.Exists( tid ) )
|
||||
{
|
||||
num_sys_titles--;
|
||||
}
|
||||
}
|
||||
|
||||
// Get system titles
|
||||
ret = getTitles_Type(0x00010002, sys_titles, num_sys_titles);
|
||||
if (ret < 0) {
|
||||
//printf("\tError! Can't get list of titles! (ret = %d)\n", ret);
|
||||
//exit(1);
|
||||
//make a list of just the tids we are adding to the titlebrowser
|
||||
titleList = (u64*)memalign( 32, ( num_titles + num_sys_titles ) * sizeof( u64 ) );
|
||||
if( !titleList )
|
||||
{
|
||||
gprintf("TitleBrowser(): out of memory!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
//this array will hold all the names for the titles so we only have to get them one time
|
||||
char name[num_titles+num_sys_titles][50];
|
||||
|
||||
customOptionList options3(num_titles+num_sys_titles+1);
|
||||
customOptionList options3( num_titles + num_sys_titles + 1 );
|
||||
//write the titles on the option browser
|
||||
|
||||
u32 i = 0;
|
||||
|
||||
|
||||
|
||||
titles.SetType( 0x10001 );
|
||||
//first add the good stuff
|
||||
while (i < num_titles) {
|
||||
//start from the beginning of the file each loop
|
||||
if (f)rewind(f);
|
||||
//char name[50];
|
||||
char text[15];
|
||||
strcpy(name[i],"");//make sure name is empty
|
||||
u8 found=0;
|
||||
//set the title's name, number, ID to text
|
||||
sprintf(text, "%s", titleText(type, titles[i]));
|
||||
while( i < num_titles )
|
||||
{
|
||||
u64 tid = titles.Next();
|
||||
if( !tid )
|
||||
{
|
||||
gprintf("shit happened3\n");
|
||||
break;
|
||||
}
|
||||
//gprintf("[ %u] tid: %016llx\t%s\n", i, tid, titles.NameOf( tid ) );
|
||||
|
||||
//get name from database cause i dont like the ADT function
|
||||
char line[200];
|
||||
char tmp[50];
|
||||
snprintf(tmp,50," ");
|
||||
|
||||
//check if the content.bin is on the SD card for that game
|
||||
//if there is content.bin,then the game is on the SDmenu and not the wii
|
||||
sprintf(line,"SD:/private/wii/title/%s/content.bin",text);
|
||||
if (!checkfile(line))
|
||||
{
|
||||
if (f) {
|
||||
while (fgets(line, sizeof(line), f)) {
|
||||
if (line[0]== text[0]&&
|
||||
line[1]== text[1]&&
|
||||
line[2]== text[2]) {
|
||||
int j=0;
|
||||
found=1;
|
||||
for (j=0;(line[j+4]!='\0' || j<51);j++)
|
||||
if( !titles.Exists( tid ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
tmp[j]=line[j+4];
|
||||
snprintf(name[i],sizeof(name[i]),"%s",tmp);
|
||||
//break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
if (getName00(name[i], TITLE_ID(type, titles[i]),CONF_GetLanguage()*2)>=0)
|
||||
found=2;
|
||||
char id[ 5 ];
|
||||
titles.AsciiTID( tid, (char*)&id );
|
||||
|
||||
if (!found) {
|
||||
if (getNameBN(name[i], TITLE_ID(type, titles[i]))>=0)
|
||||
found=3;
|
||||
char* name = titles.NameOf( tid );
|
||||
|
||||
if (!found)
|
||||
snprintf(name[i],sizeof(name[i]),"Unknown Title (%08x)",titles[i]);
|
||||
}
|
||||
}
|
||||
options3.SetName( i, "%s", id );
|
||||
options3.SetValue( i, "%s", name ? titles.NameOf( tid ): "Unknown" );
|
||||
titleList[ i ] = tid;
|
||||
i++;
|
||||
}
|
||||
|
||||
//set the text to the option browser
|
||||
options3.SetName(i, "%s",text);
|
||||
options3.SetValue(i, "%s",name[i]);
|
||||
//options3.SetValue(i, " (%08x) %s",titles[i],name[i]);//use this line to show the number to call to launch the channel
|
||||
//move on to the next title
|
||||
}
|
||||
i++;
|
||||
titles.SetType( 0x10002 );
|
||||
while( i < num_sys_titles + num_titles )
|
||||
{
|
||||
u64 tid = titles.Next();
|
||||
if( !tid )
|
||||
{
|
||||
break;
|
||||
}
|
||||
if( TITLE_LOWER( tid ) == 0x48414741 || TITLE_LOWER( tid ) == 0x48414141 || TITLE_LOWER( tid ) == 0x48414641 )
|
||||
continue;
|
||||
|
||||
if( !titles.Exists( tid ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
char id[ 5 ];
|
||||
titles.AsciiTID( tid, (char*)&id );
|
||||
char* name = titles.NameOf( tid );
|
||||
|
||||
options3.SetName( i, "%s", id );
|
||||
options3.SetValue( i, "%s", name ? titles.NameOf( tid ): "Unknown" );
|
||||
titleList[ i ] = tid;
|
||||
i++;
|
||||
}
|
||||
|
||||
ISFS_Deinitialize();
|
||||
|
||||
|
||||
if( i == num_titles+num_sys_titles )
|
||||
{
|
||||
options3.SetName( i, " " );
|
||||
options3.SetValue( i, "%s",tr("Wii Settings") );
|
||||
}
|
||||
|
||||
// now add the crappy system titles
|
||||
while (i < num_titles+num_sys_titles) {
|
||||
//start from the beginning of the file each loop
|
||||
if (f)rewind(f);
|
||||
//char name[50];
|
||||
char text[15];
|
||||
strcpy(name[i],"");//make sure name is empty
|
||||
u8 found=0;
|
||||
//set the title's name, number, ID to text
|
||||
sprintf(text, "%s", titleText(0x00010002, sys_titles[i-num_titles]));
|
||||
|
||||
//get name from database cause i dont like the ADT function
|
||||
char line[200];
|
||||
char tmp[50];
|
||||
snprintf(tmp,50," ");
|
||||
//snprintf(name[i],sizeof(name[i]),"Unknown Title");
|
||||
if (f) {
|
||||
while (fgets(line, sizeof(line), f)) {
|
||||
if (line[0]== text[0]&&
|
||||
line[1]== text[1]&&
|
||||
line[2]== text[2]) {
|
||||
int j=0;
|
||||
found=1;
|
||||
for (j=0;(line[j+4]!='\0' || j<51);j++)
|
||||
|
||||
tmp[j]=line[j+4];
|
||||
snprintf(name[i],sizeof(name[i]),"%s",tmp);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
if (getName00(name[i], TITLE_ID(0x00010002, sys_titles[i-num_titles]))>=0)
|
||||
found=2;
|
||||
|
||||
if (!found) {
|
||||
if (getNameBN(name[i], TITLE_ID(0x00010002, sys_titles[i-num_titles]))>=0)
|
||||
found=3;
|
||||
|
||||
if (!found)
|
||||
snprintf(name[i],sizeof(name[i]),"Unknown Title (%08x)",sys_titles[i-num_titles]);
|
||||
}
|
||||
}
|
||||
|
||||
//set the text to the option browser
|
||||
options3.SetName(i, "%s",text);
|
||||
options3.SetValue(i, "%s",name[i]);
|
||||
//options3.SetValue(i, " (%08x) %s",titles[i],name[i]);//use this line to show the number to call to launch the channel
|
||||
//move on to the next title
|
||||
i++;
|
||||
}
|
||||
if (i == num_titles+num_sys_titles) {
|
||||
options3.SetName(i, " ");
|
||||
options3.SetValue(i, "%s",tr("Wii Settings"));
|
||||
}
|
||||
//we have all the titles we need so close the database and stop poking around in the wii
|
||||
fclose(f);
|
||||
|
||||
//get rid of our footprints in there
|
||||
Uninstall_FromTitle(TITLE_ID(1, 0));
|
||||
ISFS_Deinitialize();
|
||||
bool exit = false;
|
||||
int total = num_titles + num_sys_titles;
|
||||
|
||||
if (IsNetworkInit())
|
||||
if( IsNetworkInit() )
|
||||
ResumeNetworkWait();
|
||||
|
||||
GuiSound btnSoundOver(button_over_pcm, button_over_pcm_size, Settings.sfxvolume);
|
||||
@ -281,10 +228,10 @@ int TitleBrowser(u32 type) {
|
||||
cancelBtn.SetTrigger(&trigB);
|
||||
|
||||
u8 scrollbaron = 0;
|
||||
if (num_titles > 9)
|
||||
scrollbaron = 1;
|
||||
if (total + 1 > 9)
|
||||
scrollbaron = 1;
|
||||
|
||||
GuiCustomOptionBrowser optionBrowser3(396, 280, &options3, CFG.theme_path, "bg_options_gamesettings.png", bg_options_settings_png, num_titles+num_sys_titles>9?1:0, 200);
|
||||
GuiCustomOptionBrowser optionBrowser3(396, 280, &options3, CFG.theme_path, "bg_options_gamesettings.png", bg_options_settings_png, scrollbaron, 200);
|
||||
optionBrowser3.SetPosition(0, 90);
|
||||
optionBrowser3.SetAlignment(ALIGN_CENTRE, ALIGN_TOP);
|
||||
|
||||
@ -308,7 +255,7 @@ int TitleBrowser(u32 type) {
|
||||
screenShotBtn.SetPosition(0,0);
|
||||
screenShotBtn.SetTrigger(&trigZ);
|
||||
|
||||
HaltGui();
|
||||
HaltGui();
|
||||
GuiWindow w(screenwidth, screenheight);
|
||||
w.Append(&screenShotBtn);
|
||||
w.Append(&settingsbackgroundbtn);
|
||||
@ -316,108 +263,76 @@ int TitleBrowser(u32 type) {
|
||||
w.Append(&cancelBtn);
|
||||
w.Append(&wifiBtn);
|
||||
w.Append(&optionBrowser3);
|
||||
|
||||
mainWindow->Append(&w);
|
||||
|
||||
|
||||
int tmp=num_titles+num_sys_titles;
|
||||
|
||||
ResumeGui();
|
||||
numtitle=num_titles;
|
||||
while (!exit) {
|
||||
|
||||
while (!exit)
|
||||
{
|
||||
VIDEO_WaitVSync();
|
||||
|
||||
if (shutdown == 1)
|
||||
Sys_Shutdown();
|
||||
if (reset == 1)
|
||||
Sys_Reboot();
|
||||
|
||||
else if (wifiBtn.GetState() == STATE_CLICKED) {
|
||||
if( shutdown == 1 ) Sys_Shutdown();
|
||||
if( reset == 1 ) Sys_Reboot();
|
||||
|
||||
else if( wifiBtn.GetState() == STATE_CLICKED )
|
||||
{
|
||||
ResumeNetworkWait();
|
||||
wifiBtn.ResetState();
|
||||
}
|
||||
|
||||
if (IsNetworkInit()) {
|
||||
if( IsNetworkInit() )
|
||||
{
|
||||
wifiBtn.SetAlpha(255);
|
||||
}
|
||||
|
||||
ret = optionBrowser3.GetClickedOption();
|
||||
|
||||
if (ret > -1) {//if a click happened
|
||||
if( ret > -1 )
|
||||
{ //if a click happened
|
||||
|
||||
//char name[50];
|
||||
char text[15];
|
||||
if (f)rewind(f);
|
||||
//strcpy(name,"");//make sure name is empty
|
||||
|
||||
if (ret<numtitle) {
|
||||
if ( ret < total )
|
||||
{
|
||||
//set the title's name, number, ID to text
|
||||
sprintf(text, "%s", titleText(type, titles[ret]));
|
||||
char text[ 0x100 ];
|
||||
char id[ 5 ];
|
||||
titles.AsciiTID( titleList[ ret ], (char*)&id );
|
||||
|
||||
char temp[100];
|
||||
//prompt to boot selected title
|
||||
snprintf(temp, sizeof(temp), "%s : %s",text,name[ret]);
|
||||
int choice = WindowPrompt(tr("Boot?"), temp, tr("OK"), tr("Cancel"));
|
||||
if (choice) {//if they say yes
|
||||
snprintf( text, sizeof( text ), "%s : %s", id, titles.NameOf( titleList[ ret ] ) );
|
||||
|
||||
|
||||
//stop all this stuff before starting the channel
|
||||
|
||||
CloseXMLDatabase();
|
||||
//prompt to boot selected title
|
||||
if( WindowPrompt( tr( "Boot?" ), text, tr( "OK" ), tr( "Cancel" ) ) )
|
||||
{ //if they say yes
|
||||
CloseXMLDatabase();
|
||||
ExitGUIThreads();
|
||||
ShutdownAudio();
|
||||
StopGX();
|
||||
WII_Initialize();
|
||||
WII_LaunchTitle(TITLE_ID(type,titles[ret]));
|
||||
WII_LaunchTitle( titleList[ ret ] );
|
||||
//this really shouldn't be needed because the title will be booted
|
||||
exit = true;
|
||||
break;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
//if they said no to booting the title
|
||||
ret = -1;
|
||||
optionBrowser3.ResetState();
|
||||
}
|
||||
|
||||
} else { //if they clicked a system title
|
||||
if (ret == tmp) {
|
||||
}
|
||||
else if( ret == total )
|
||||
{ //if they clicked to go to the wii settings
|
||||
CloseXMLDatabase();
|
||||
ExitGUIThreads();
|
||||
ShutdownAudio();
|
||||
StopGX();
|
||||
WII_Initialize();
|
||||
WII_ReturnToSettings();
|
||||
|
||||
} else {
|
||||
//set the title's name, number, ID to text
|
||||
sprintf(text, "%s", titleText(0x00010002, sys_titles[ret-num_titles]));
|
||||
|
||||
char temp[112];
|
||||
//prompt to boot selected title
|
||||
snprintf(temp, sizeof(temp), tr("%s : %s May not boot correctly if your System Menu is not up to date."),text,name[ret]);
|
||||
int choice = WindowPrompt(tr("Boot?"), temp, tr("OK"), tr("Cancel"));
|
||||
if (choice) {//if they say yes
|
||||
|
||||
|
||||
//stop all this stuff before starting the channel
|
||||
|
||||
CloseXMLDatabase();
|
||||
ExitGUIThreads();
|
||||
ShutdownAudio();
|
||||
StopGX();
|
||||
WII_Initialize();
|
||||
WII_LaunchTitle(TITLE_ID(0x00010002,sys_titles[ret-num_titles]));
|
||||
//this really shouldn't be needed because the title will be booted
|
||||
exit = true;
|
||||
break;
|
||||
} else {
|
||||
//if they said no to booting the title
|
||||
ret = -1;
|
||||
optionBrowser3.ResetState();
|
||||
}
|
||||
}
|
||||
WII_ReturnToSettings();
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
if(infilesize > 0) {
|
||||
|
||||
char filesizetxt[50];
|
||||
@ -585,7 +500,7 @@ int TitleBrowser(u32 type) {
|
||||
CloseConnection();
|
||||
ResumeNetworkWait();
|
||||
}
|
||||
|
||||
#endif
|
||||
if (cancelBtn.GetState() == STATE_CLICKED) {
|
||||
//break the loop and end the function
|
||||
exit = true;
|
||||
@ -603,9 +518,9 @@ int TitleBrowser(u32 type) {
|
||||
if (IsNetworkInit())
|
||||
HaltNetworkThread();
|
||||
|
||||
fclose(f);
|
||||
HaltGui();
|
||||
mainWindow->Remove(&w);
|
||||
free( titleList );
|
||||
ResumeGui();
|
||||
|
||||
return ret;
|
||||
|
@ -8,10 +8,6 @@
|
||||
#ifndef _TITLEBROWSER_H_
|
||||
#define _TITLEBROWSER_H_
|
||||
|
||||
///opens a window with a custom option browser in it populated with
|
||||
//! type is the type of chnnel to put in the list
|
||||
int TitleBrowser(u32 type);
|
||||
|
||||
//int buildTitleList(int t=0, const wchar_t* Filter=NULL);
|
||||
int TitleBrowser();
|
||||
|
||||
#endif
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include "usbloader/partition_usbloader.h"
|
||||
#include "usbloader/utils.h"
|
||||
#include "xml/xml.h"
|
||||
#include "wad/nandtitle.h"
|
||||
|
||||
#define MAXOPTIONS 13
|
||||
|
||||
@ -1001,7 +1002,7 @@ int MenuSettings()
|
||||
if (++Settings.cios >= settings_cios_max) {
|
||||
Settings.cios = 0;
|
||||
}
|
||||
if ((Settings.cios == 1 && ios222rev!=4) || (Settings.cios == 2 && ios223rev != 4)) {
|
||||
if ((Settings.cios == 1 && titles.VersionOf( 0x1000000deULL ) != 4 ) || (Settings.cios == 2 && titles.VersionOf( 0x1000000dfULL ) != 4)) {
|
||||
WindowPrompt(tr("Hermes CIOS"),tr("USB Loader GX will only run with Hermes CIOS rev 4! Please make sure you have revision 4 installed!"),tr("OK"));
|
||||
}
|
||||
}
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "sys.h"
|
||||
#include "wpad.h"
|
||||
#include "lstub.h"
|
||||
#include "wad/nandtitle.h"
|
||||
|
||||
extern char game_partition[6];
|
||||
extern u8 load_from_fs;
|
||||
@ -221,61 +222,65 @@ void ShowMemInfo() {
|
||||
WindowPrompt("Mem info", (char *) &buf, "OK");
|
||||
}
|
||||
|
||||
|
||||
#include "wad/title.h"
|
||||
|
||||
s32 ios222rev = -69;
|
||||
s32 ios223rev = -69;
|
||||
s32 ios249rev = -69;
|
||||
s32 ios250rev = -69;
|
||||
|
||||
s32 IOS_ReloadIOSsafe(int ios)
|
||||
{
|
||||
if (ios==222)
|
||||
if( ios == 222 )
|
||||
{
|
||||
if (ios222rev == -69)
|
||||
ios222rev = getIOSrev(0x00000001000000dell);
|
||||
|
||||
if (ios222rev > 0 && (ios222rev != 4 && ios222rev != 5))return -2;
|
||||
s32 ios222rev = titles.VersionOf( 0x1000000deULL );
|
||||
if( !ios222rev )
|
||||
return -2;
|
||||
if( ios222rev != 4 && ios222rev != 5 && ios222rev != 65535 )
|
||||
return -2;
|
||||
}
|
||||
else if (ios==223)
|
||||
{
|
||||
if (ios223rev == -69)
|
||||
ios223rev = getIOSrev(0x00000001000000dfll);
|
||||
|
||||
if (ios223rev > 0 && (ios223rev != 4 && ios223rev != 5))return -2;
|
||||
s32 ios223rev = titles.VersionOf( 0x1000000dfULL );
|
||||
if( !ios223rev )
|
||||
return -2;
|
||||
if( ios223rev != 4 && ios223rev != 5 && ios223rev != 65535 )
|
||||
return -2;
|
||||
}
|
||||
else if (ios==249)
|
||||
{
|
||||
if (ios249rev == -69)
|
||||
ios249rev = getIOSrev(0x00000001000000f9ll);
|
||||
|
||||
if (ios249rev >= 0 && !(ios249rev>=9 && ios249rev<65280))return -2;
|
||||
s32 ios249rev = titles.VersionOf( 0x1000000f9ULL );
|
||||
if( !ios249rev )
|
||||
return -2;
|
||||
if( ios249rev < 9 || ios249rev == 65280 )
|
||||
return -2;
|
||||
}
|
||||
else if (ios==250)
|
||||
{
|
||||
if (ios250rev == -69)
|
||||
ios250rev = getIOSrev(0x00000001000000fall);
|
||||
|
||||
if (ios250rev >= 0 && !(ios250rev>=9 && ios250rev<65280))return -2;
|
||||
s32 ios250rev = titles.VersionOf( 0x1000000faULL );
|
||||
if( !ios250rev )
|
||||
return -2;
|
||||
if( ios250rev < 9 || ios250rev == 65280 )
|
||||
return -2;
|
||||
}
|
||||
|
||||
s32 r = IOS_ReloadIOS(ios);
|
||||
if (r >= 0) {
|
||||
WII_Initialize();
|
||||
if( r >= 0 )
|
||||
{
|
||||
WII_Initialize();
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
s32 CheckForCIOS()
|
||||
{
|
||||
gprintf("\n\tChecking for stub IOS");
|
||||
gprintf("\tChecking for stub IOS\n");
|
||||
s32 ret = 1;
|
||||
ios222rev = getIOSrev(0x00000001000000dell);
|
||||
ios249rev = getIOSrev(0x00000001000000f9ll);
|
||||
s32 ios222rev = titles.VersionOf( 0x00000001000000deULL );
|
||||
s32 ios249rev = titles.VersionOf( 0x00000001000000f9ULL );
|
||||
|
||||
u8 ios222OK = !( ios222rev < 4 || ios222rev == 65280 );
|
||||
u8 ios249OK = !( ios249rev < 9 || ios249rev == 65280 );
|
||||
|
||||
gprintf("222ok: %u\t 249ok: %u\n", ios222OK, ios249OK );
|
||||
return 1;
|
||||
|
||||
//if we don't like either of the cIOS then scram
|
||||
if (!((ios222rev >= 4 && ios222rev < 65280) || (ios249rev >=9 && ios249rev < 65280)))
|
||||
//if( !((ios222rev >= 4 && ios222rev < 65280) || (ios249rev >=9 && ios249rev < 65280)))
|
||||
if( ios222rev < 4 || ios222rev == 65280 || ios249rev < 9 || ios249rev == 65280 )
|
||||
{
|
||||
printf("\x1b[2J");
|
||||
if ((ios222rev < 0 && ios222rev != WII_EINSTALL) && (ios249rev < 0 && ios249rev != WII_EINSTALL)) {
|
||||
|
@ -24,5 +24,6 @@ extern s32 ios223rev;
|
||||
extern s32 ios249rev;
|
||||
extern s32 ios250rev;
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -95,7 +95,7 @@ s32 Apploader_Run(entry_point *entry, u8 cheat, u8 videoSelected, u8 vipatch, u8
|
||||
appldr_entry(&appldr_init, &appldr_main, &appldr_final);
|
||||
|
||||
/* Initialize apploader */
|
||||
appldr_init(__noprint);
|
||||
appldr_init( gprintf );
|
||||
|
||||
if (error002fix!=0)
|
||||
{
|
||||
|
203
source/wad/id.c
203
source/wad/id.c
@ -1,203 +0,0 @@
|
||||
/*-------------------------------------------------------------
|
||||
|
||||
id.c -- ES Identification code
|
||||
|
||||
Copyright (C) 2008 tona
|
||||
Unless other credit specified
|
||||
|
||||
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 <gccore.h>
|
||||
|
||||
#include "id.h"
|
||||
#include "patchmii_core.h"
|
||||
|
||||
#include "certs_dat.h"
|
||||
|
||||
|
||||
// Turn upper and lower into a full title ID
|
||||
#define TITLE_ID(x,y) (((u64)(x) << 32) | (y))
|
||||
// Get upper or lower half of a title ID
|
||||
#define TITLE_UPPER(x) ((u32)((x) >> 32))
|
||||
// Turn upper and lower into a full title ID
|
||||
#define TITLE_LOWER(x) ((u32)(x))
|
||||
|
||||
|
||||
/* Debug functions adapted from libogc's es.c */
|
||||
//#define DEBUG_ES
|
||||
//#define DEBUG_IDENT
|
||||
#define ISALIGNED(x) ((((u32)x)&0x1F)==0)
|
||||
|
||||
static u8 su_tmd[0x208] ATTRIBUTE_ALIGN(32);
|
||||
static u8 su_tik[STD_SIGNED_TIK_SIZE] ATTRIBUTE_ALIGN(32);
|
||||
int su_id_filled = 0;
|
||||
|
||||
|
||||
/* Reads a file from ISFS to an array in memory */
|
||||
s32 ISFS_ReadFileToArray (const char *filepath, u8 *filearray, u32 max_size, u32 *file_size) {
|
||||
s32 ret, fd;
|
||||
static fstats filestats ATTRIBUTE_ALIGN(32);
|
||||
|
||||
*file_size = 0;
|
||||
ret = ISFS_Open(filepath, ISFS_OPEN_READ);
|
||||
if (ret <= 0) {
|
||||
//printf("Error! ISFS_Open (ret = %d)\n", ret);
|
||||
return -1;
|
||||
}
|
||||
|
||||
fd = ret;
|
||||
|
||||
ret = ISFS_GetFileStats(fd, &filestats);
|
||||
if (ret < 0) {
|
||||
//printf("Error! ISFS_GetFileStats (ret = %d)\n", ret);
|
||||
return -1;
|
||||
}
|
||||
|
||||
*file_size = filestats.file_length;
|
||||
|
||||
if (*file_size > max_size) {
|
||||
//printf("File is too large! Size: %u Max: %u", *file_size, max_size);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = ISFS_Read(fd, filearray, *file_size);
|
||||
*file_size = ret;
|
||||
if (ret < 0) {
|
||||
//printf("Error! ISFS_Read (ret = %d)\n", ret);
|
||||
return -1;
|
||||
} else if (ret != filestats.file_length) {
|
||||
//printf("Error! ISFS_Read Only read: %d\n", ret);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = ISFS_Close(fd);
|
||||
if (ret < 0) {
|
||||
//printf("Error! ISFS_Close (ret = %d)\n", ret);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Make_SUID(void) {
|
||||
signed_blob *s_tmd, *s_tik;
|
||||
tmd *p_tmd;
|
||||
tik *p_tik;
|
||||
|
||||
memset(su_tmd, 0, sizeof su_tmd);
|
||||
memset(su_tik, 0, sizeof su_tik);
|
||||
s_tmd = (signed_blob*)&su_tmd[0];
|
||||
s_tik = (signed_blob*)&su_tik[0];
|
||||
*s_tmd = *s_tik = 0x10001;
|
||||
p_tmd = (tmd*)SIGNATURE_PAYLOAD(s_tmd);
|
||||
p_tik = (tik*)SIGNATURE_PAYLOAD(s_tik);
|
||||
|
||||
|
||||
strcpy(p_tmd->issuer, "Root-CA00000001-CP00000004");
|
||||
p_tmd->title_id = TITLE_ID(1,2);
|
||||
|
||||
p_tmd->num_contents = 1;
|
||||
|
||||
forge_tmd(s_tmd);
|
||||
|
||||
strcpy(p_tik->issuer, "Root-CA00000001-XS00000003");
|
||||
p_tik->ticketid = 0x000038A45236EE5FLL;
|
||||
p_tik->titleid = TITLE_ID(1,2);
|
||||
|
||||
memset(p_tik->cidx_mask, 0xFF, 0x20);
|
||||
forge_tik(s_tik);
|
||||
|
||||
su_id_filled = 1;
|
||||
|
||||
}
|
||||
|
||||
s32 Identify(const u8 *certs, u32 certs_size, const u8 *idtmd, u32 idtmd_size, const u8 *idticket, u32 idticket_size) {
|
||||
s32 ret;
|
||||
u32 keyid = 0;
|
||||
ret = ES_Identify((signed_blob*)certs, certs_size, (signed_blob*)idtmd, idtmd_size, (signed_blob*)idticket, idticket_size, &keyid);
|
||||
/*if (ret < 0){
|
||||
switch(ret){
|
||||
case ES_EINVAL:
|
||||
printf("Error! ES_Identify (ret = %d;) Data invalid!\n", ret);
|
||||
break;
|
||||
case ES_EALIGN:
|
||||
printf("Error! ES_Identify (ret = %d;) Data not aligned!\n", ret);
|
||||
break;
|
||||
case ES_ENOTINIT:
|
||||
printf("Error! ES_Identify (ret = %d;) ES not initialized!\n", ret);
|
||||
break;
|
||||
case ES_ENOMEM:
|
||||
printf("Error! ES_Identify (ret = %d;) No memory!\n", ret);
|
||||
break;
|
||||
default:
|
||||
printf("Error! ES_Identify (ret = %d)\n", ret);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
printf("OK!\n");*/
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
s32 Identify_SU(void) {
|
||||
if (!su_id_filled)
|
||||
Make_SUID();
|
||||
|
||||
//printf("\nIdentifying as SU...");
|
||||
//fflush(stdout);
|
||||
return Identify(certs_dat, certs_dat_size, su_tmd, sizeof su_tmd, su_tik, sizeof su_tik);
|
||||
}
|
||||
|
||||
s32 Identify_SysMenu(void) {
|
||||
s32 ret;
|
||||
u32 sysmenu_tmd_size, sysmenu_ticket_size;
|
||||
//static u8 certs[0xA00] ATTRIBUTE_ALIGN(32);
|
||||
static u8 sysmenu_tmd[MAX_SIGNED_TMD_SIZE] ATTRIBUTE_ALIGN(32);
|
||||
static u8 sysmenu_ticket[STD_SIGNED_TIK_SIZE] ATTRIBUTE_ALIGN(32);
|
||||
|
||||
/*printf("\nPulling Certs...");
|
||||
ret = ISFS_ReadFileToArray ("/sys/certs.sys", certs, 0xA00, &certs_size);
|
||||
if (ret < 0) {
|
||||
printf("\tReading Certs failed!\n");
|
||||
return -1;
|
||||
}*/
|
||||
|
||||
//printf("\nPulling Sysmenu TMD...");
|
||||
ret = ISFS_ReadFileToArray ("/title/00000001/00000002/content/title.tmd", sysmenu_tmd, MAX_SIGNED_TMD_SIZE, &sysmenu_tmd_size);
|
||||
if (ret < 0) {
|
||||
//printf("\tReading TMD failed!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
//printf("\nPulling Sysmenu Ticket...");
|
||||
ret = ISFS_ReadFileToArray ("/ticket/00000001/00000002.tik", sysmenu_ticket, STD_SIGNED_TIK_SIZE, &sysmenu_ticket_size);
|
||||
if (ret < 0) {
|
||||
//printf("\tReading TMD failed!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
//printf("\nIdentifying as SysMenu...");
|
||||
//fflush(stdout);
|
||||
return Identify(certs_dat, certs_dat_size, sysmenu_tmd, sysmenu_tmd_size, sysmenu_ticket, sysmenu_ticket_size);
|
||||
}
|
@ -1,38 +0,0 @@
|
||||
/*-------------------------------------------------------------
|
||||
|
||||
id.h -- ES Identification code
|
||||
|
||||
Copyright (C) 2008 tona
|
||||
Unless other credit specified
|
||||
|
||||
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.
|
||||
|
||||
-------------------------------------------------------------*/
|
||||
|
||||
#ifndef _ID_H_
|
||||
#define _ID_H_
|
||||
|
||||
// Identify as the "super user"
|
||||
s32 Identify_SU(void);
|
||||
|
||||
// Identify as the system menu
|
||||
s32 Identify_SysMenu(void);
|
||||
|
||||
#endif
|
@ -1,494 +0,0 @@
|
||||
/*
|
||||
|
||||
libisfs -- a NAND filesystem devoptab library for the Wii
|
||||
|
||||
Copyright (C) 2008 Joseph Jordan <joe.ftpii@psychlaw.com.au>
|
||||
Copyright (C) 2009 Waninkoko <waninkoko@gmail.com>
|
||||
|
||||
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 <errno.h>
|
||||
#include <ogc/isfs.h>
|
||||
#include <ogc/lwp_watchdog.h>
|
||||
#include <ogcsys.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/dir.h>
|
||||
#include <sys/iosupport.h>
|
||||
|
||||
#include "isfs.h"
|
||||
|
||||
#define DEVICE_NAME "isfs"
|
||||
|
||||
#define FLAG_DIR 1
|
||||
#define DIR_SEPARATOR '/'
|
||||
#define SECTOR_SIZE 0x800
|
||||
#define BUFFER_SIZE 0x8000
|
||||
|
||||
typedef struct DIR_ENTRY_STRUCT {
|
||||
char *name;
|
||||
char *abspath;
|
||||
u32 size;
|
||||
u8 flags;
|
||||
u32 fileCount;
|
||||
struct DIR_ENTRY_STRUCT *children;
|
||||
} DIR_ENTRY;
|
||||
|
||||
typedef struct {
|
||||
DIR_ENTRY *entry;
|
||||
s32 isfs_fd;
|
||||
bool inUse;
|
||||
} FILE_STRUCT;
|
||||
|
||||
typedef struct {
|
||||
DIR_ENTRY *entry;
|
||||
u32 index;
|
||||
bool inUse;
|
||||
} DIR_STATE_STRUCT;
|
||||
|
||||
static char rw_buffer[BUFFER_SIZE] __attribute__((aligned(32)));
|
||||
|
||||
static DIR_ENTRY *root = NULL;
|
||||
static DIR_ENTRY *current = NULL;
|
||||
static s32 dotab_device = -1;
|
||||
|
||||
static bool is_dir(DIR_ENTRY *entry) {
|
||||
return entry->flags & FLAG_DIR;
|
||||
}
|
||||
|
||||
static bool invalid_drive_specifier(const char *path) {
|
||||
if (strchr(path, ':') == NULL) return false;
|
||||
int namelen = strlen(DEVICE_NAME);
|
||||
if (!strncmp(DEVICE_NAME, path, namelen) && path[namelen] == ':') return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static DIR_ENTRY *entry_from_path(const char *path) {
|
||||
if (invalid_drive_specifier(path)) return NULL;
|
||||
if (strchr(path, ':') != NULL) path = strchr(path, ':') + 1;
|
||||
DIR_ENTRY *entry;
|
||||
bool found = false;
|
||||
bool notFound = false;
|
||||
const char *pathPosition = path;
|
||||
const char *pathEnd = strchr(path, '\0');
|
||||
if (pathPosition[0] == DIR_SEPARATOR) {
|
||||
entry = root;
|
||||
while (pathPosition[0] == DIR_SEPARATOR) pathPosition++;
|
||||
if (pathPosition >= pathEnd) found = true;
|
||||
} else {
|
||||
entry = current;
|
||||
}
|
||||
if (entry == root && !strcmp(".", pathPosition)) found = true;
|
||||
DIR_ENTRY *dir = entry;
|
||||
while (!found && !notFound) {
|
||||
const char *nextPathPosition = strchr(pathPosition, DIR_SEPARATOR);
|
||||
size_t dirnameLength;
|
||||
if (nextPathPosition != NULL) dirnameLength = nextPathPosition - pathPosition;
|
||||
else dirnameLength = strlen(pathPosition);
|
||||
if (dirnameLength >= ISFS_MAXPATHLEN) return NULL;
|
||||
|
||||
u32 fileIndex = 0;
|
||||
while (fileIndex < dir->fileCount && !found && !notFound) {
|
||||
entry = &dir->children[fileIndex];
|
||||
if (dirnameLength == strnlen(entry->name, ISFS_MAXPATHLEN - 1) && !strncasecmp(pathPosition, entry->name, dirnameLength)) found = true;
|
||||
if (found && !is_dir(entry) && nextPathPosition) found = false;
|
||||
if (!found) fileIndex++;
|
||||
}
|
||||
|
||||
if (fileIndex >= dir->fileCount) {
|
||||
notFound = true;
|
||||
found = false;
|
||||
} else if (!nextPathPosition || nextPathPosition >= pathEnd) {
|
||||
found = true;
|
||||
} else if (is_dir(entry)) {
|
||||
dir = entry;
|
||||
pathPosition = nextPathPosition;
|
||||
while (pathPosition[0] == DIR_SEPARATOR) pathPosition++;
|
||||
if (pathPosition >= pathEnd) found = true;
|
||||
else found = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (found && !notFound) return entry;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int _ISFS_open_r(struct _reent *r, void *fileStruct, const char *path, int flags, int mode) {
|
||||
FILE_STRUCT *file = (FILE_STRUCT *)fileStruct;
|
||||
DIR_ENTRY *entry = entry_from_path(path);
|
||||
if (!entry) {
|
||||
r->_errno = ENOENT;
|
||||
return -1;
|
||||
} else if (is_dir(entry)) {
|
||||
r->_errno = EISDIR;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int omode = 0;
|
||||
|
||||
if (mode & O_RDONLY)
|
||||
omode |= ISFS_OPEN_READ;
|
||||
if (mode & O_WRONLY)
|
||||
omode |= ISFS_OPEN_WRITE;
|
||||
if (mode & O_RDWR)
|
||||
omode |= ISFS_OPEN_RW;
|
||||
|
||||
if (mode & O_CREAT) {
|
||||
int user = 0;
|
||||
int group = 0;
|
||||
int other = 0;
|
||||
|
||||
if (flags & S_IRUSR)
|
||||
user |= ISFS_OPEN_READ;
|
||||
if (flags & S_IWUSR)
|
||||
user |= ISFS_OPEN_WRITE;
|
||||
if (flags & S_IRGRP)
|
||||
group |= ISFS_OPEN_READ;
|
||||
if (flags & S_IWGRP)
|
||||
group |= ISFS_OPEN_WRITE;
|
||||
if (flags & S_IROTH)
|
||||
other |= ISFS_OPEN_READ;
|
||||
if (flags & S_IWOTH)
|
||||
other |= ISFS_OPEN_WRITE;
|
||||
|
||||
ISFS_CreateFile(entry->abspath, 0, user, group, other);
|
||||
}
|
||||
|
||||
file->entry = entry;
|
||||
file->inUse = true;
|
||||
file->isfs_fd = ISFS_Open(entry->abspath, omode);
|
||||
if (file->isfs_fd < 0) {
|
||||
r->_errno = -file->isfs_fd;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return (int)file;
|
||||
}
|
||||
|
||||
static int _ISFS_close_r(struct _reent *r, int fd) {
|
||||
FILE_STRUCT *file = (FILE_STRUCT *)fd;
|
||||
if (!file->inUse) {
|
||||
r->_errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
file->inUse = false;
|
||||
|
||||
s32 ret = ISFS_Close(file->isfs_fd);
|
||||
if (ret < 0) {
|
||||
r->_errno = -ret;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _ISFS_write_r(struct _reent *r, int fd, const char *ptr, size_t len) {
|
||||
FILE_STRUCT *file = (FILE_STRUCT *)fd;
|
||||
if (!file->inUse) {
|
||||
r->_errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
if (len <= 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(rw_buffer, ptr, len);
|
||||
|
||||
s32 ret = ISFS_Write(file->isfs_fd, rw_buffer, len);
|
||||
if (ret < 0) {
|
||||
r->_errno = -ret;
|
||||
return -1;
|
||||
} else if (ret < len) {
|
||||
r->_errno = EOVERFLOW;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int _ISFS_read_r(struct _reent *r, int fd, char *ptr, size_t len) {
|
||||
FILE_STRUCT *file = (FILE_STRUCT *)fd;
|
||||
if (!file->inUse) {
|
||||
r->_errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
if (len <= 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
s32 ret = ISFS_Read(file->isfs_fd, rw_buffer, len);
|
||||
if (ret < 0) {
|
||||
r->_errno = -ret;
|
||||
return -1;
|
||||
} else if (ret < len) {
|
||||
r->_errno = EOVERFLOW;
|
||||
}
|
||||
|
||||
memcpy(ptr, rw_buffer, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static off_t _ISFS_seek_r(struct _reent *r, int fd, off_t pos, int dir) {
|
||||
FILE_STRUCT *file = (FILE_STRUCT *)fd;
|
||||
if (!file->inUse) {
|
||||
r->_errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
|
||||
s32 ret = ISFS_Seek(file->isfs_fd, pos, dir);
|
||||
if (ret < 0) {
|
||||
r->_errno = -ret;
|
||||
return -1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void stat_entry(DIR_ENTRY *entry, struct stat *st) {
|
||||
st->st_dev = 0x4957;
|
||||
st->st_ino = 0;
|
||||
st->st_mode = ((is_dir(entry)) ? S_IFDIR : S_IFREG) | (S_IRUSR | S_IRGRP | S_IROTH);
|
||||
st->st_nlink = 1;
|
||||
st->st_uid = 1;
|
||||
st->st_gid = 2;
|
||||
st->st_rdev = st->st_dev;
|
||||
st->st_size = entry->size;
|
||||
st->st_atime = 0;
|
||||
st->st_spare1 = 0;
|
||||
st->st_mtime = 0;
|
||||
st->st_spare2 = 0;
|
||||
st->st_ctime = 0;
|
||||
st->st_spare3 = 0;
|
||||
st->st_blksize = SECTOR_SIZE;
|
||||
st->st_blocks = (entry->size + SECTOR_SIZE - 1) / SECTOR_SIZE;
|
||||
st->st_spare4[0] = 0;
|
||||
st->st_spare4[1] = 0;
|
||||
}
|
||||
|
||||
static int _ISFS_fstat_r(struct _reent *r, int fd, struct stat *st) {
|
||||
FILE_STRUCT *file = (FILE_STRUCT *)fd;
|
||||
if (!file->inUse) {
|
||||
r->_errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
stat_entry(file->entry, st);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _ISFS_stat_r(struct _reent *r, const char *path, struct stat *st) {
|
||||
DIR_ENTRY *entry = entry_from_path(path);
|
||||
if (!entry) {
|
||||
r->_errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
stat_entry(entry, st);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _ISFS_chdir_r(struct _reent *r, const char *path) {
|
||||
DIR_ENTRY *entry = entry_from_path(path);
|
||||
if (!entry) {
|
||||
r->_errno = ENOENT;
|
||||
return -1;
|
||||
} else if (!is_dir(entry)) {
|
||||
r->_errno = ENOTDIR;
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _ISFS_mkdir_r(struct _reent *r, const char *path, int mode) {
|
||||
DIR_ENTRY *entry = entry_from_path(path);
|
||||
if (entry) {
|
||||
r->_errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int other = (mode % 10);
|
||||
int group = (mode / 10) % 10;
|
||||
int user = (mode / 100) % 10;
|
||||
|
||||
s32 ret = ISFS_CreateDir(path, 0, user >> 1, group >> 1, other >> 1);
|
||||
if (ret < 0) {
|
||||
r->_errno = -ret;
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static DIR_ITER *_ISFS_diropen_r(struct _reent *r, DIR_ITER *dirState, const char *path) {
|
||||
DIR_STATE_STRUCT *state = (DIR_STATE_STRUCT *)(dirState->dirStruct);
|
||||
state->entry = entry_from_path(path);
|
||||
if (!state->entry) {
|
||||
r->_errno = ENOENT;
|
||||
return NULL;
|
||||
} else if (!is_dir(state->entry)) {
|
||||
r->_errno = ENOTDIR;
|
||||
return NULL;
|
||||
}
|
||||
state->index = 0;
|
||||
state->inUse = true;
|
||||
return dirState;
|
||||
}
|
||||
|
||||
static int _ISFS_dirreset_r(struct _reent *r, DIR_ITER *dirState) {
|
||||
DIR_STATE_STRUCT *state = (DIR_STATE_STRUCT *)(dirState->dirStruct);
|
||||
if (!state->inUse) {
|
||||
r->_errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
state->index = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _ISFS_dirnext_r(struct _reent *r, DIR_ITER *dirState, char *filename, struct stat *st) {
|
||||
DIR_STATE_STRUCT *state = (DIR_STATE_STRUCT *)(dirState->dirStruct);
|
||||
if (!state->inUse) {
|
||||
r->_errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
if (state->index >= state->entry->fileCount) {
|
||||
r->_errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
DIR_ENTRY *entry = &state->entry->children[state->index++];
|
||||
strlcpy(filename, entry->name, ISFS_MAXPATHLEN);
|
||||
stat_entry(entry, st);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _ISFS_dirclose_r(struct _reent *r, DIR_ITER *dirState) {
|
||||
DIR_STATE_STRUCT *state = (DIR_STATE_STRUCT *)(dirState->dirStruct);
|
||||
if (!state->inUse) {
|
||||
r->_errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
state->inUse = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const devoptab_t dotab_isfs = {
|
||||
DEVICE_NAME,
|
||||
sizeof(FILE_STRUCT),
|
||||
_ISFS_open_r,
|
||||
_ISFS_close_r,
|
||||
_ISFS_write_r,
|
||||
_ISFS_read_r,
|
||||
_ISFS_seek_r,
|
||||
_ISFS_fstat_r,
|
||||
_ISFS_stat_r,
|
||||
NULL,
|
||||
NULL,
|
||||
_ISFS_chdir_r,
|
||||
NULL,
|
||||
_ISFS_mkdir_r,
|
||||
sizeof(DIR_STATE_STRUCT),
|
||||
_ISFS_diropen_r,
|
||||
_ISFS_dirreset_r,
|
||||
_ISFS_dirnext_r,
|
||||
_ISFS_dirclose_r,
|
||||
NULL
|
||||
};
|
||||
|
||||
static DIR_ENTRY *add_child_entry(DIR_ENTRY *dir, const char *name) {
|
||||
DIR_ENTRY *newChildren = realloc(dir->children, (dir->fileCount + 1) * sizeof(DIR_ENTRY));
|
||||
if (!newChildren) return NULL;
|
||||
bzero(newChildren + dir->fileCount, sizeof(DIR_ENTRY));
|
||||
dir->children = newChildren;
|
||||
DIR_ENTRY *child = &dir->children[dir->fileCount++];
|
||||
child->name = strdup(name);
|
||||
if (!child->name) return NULL;
|
||||
child->abspath = malloc(strlen(dir->abspath) + (dir != root) + strlen(name) + 1);
|
||||
if (!child->abspath) return NULL;
|
||||
sprintf(child->abspath, "%s/%s", dir == root ? "" : dir->abspath, name);
|
||||
return child;
|
||||
}
|
||||
|
||||
static bool read_recursive(DIR_ENTRY *parent) {
|
||||
u32 fileCount;
|
||||
s32 ret = ISFS_ReadDir(parent->abspath, NULL, &fileCount);
|
||||
if (ret != ISFS_OK) {
|
||||
s32 fd = ISFS_Open(parent->abspath, ISFS_OPEN_READ);
|
||||
if (fd >= 0) {
|
||||
static fstats st __attribute__((aligned(32)));
|
||||
if (ISFS_GetFileStats(fd, &st) == ISFS_OK) parent->size = st.file_length;
|
||||
ISFS_Close(fd);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
parent->flags = FLAG_DIR;
|
||||
if (fileCount > 0) {
|
||||
if ((ISFS_MAXPATHLEN * fileCount) > BUFFER_SIZE) return false;
|
||||
ret = ISFS_ReadDir(parent->abspath, rw_buffer, &fileCount);
|
||||
if (ret != ISFS_OK) return false;
|
||||
u32 fileNum;
|
||||
char *name = rw_buffer;
|
||||
for (fileNum = 0; fileNum < fileCount; fileNum++) {
|
||||
DIR_ENTRY *child = add_child_entry(parent, name);
|
||||
if (!child) return false;
|
||||
name += strlen(name) + 1;
|
||||
}
|
||||
for (fileNum = 0; fileNum < fileCount; fileNum++)
|
||||
if (!read_recursive(parent->children + fileNum))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool read_isfs() {
|
||||
root = malloc(sizeof(DIR_ENTRY));
|
||||
if (!root) return false;
|
||||
bzero(root, sizeof(DIR_ENTRY));
|
||||
current = root;
|
||||
root->name = strdup("/");
|
||||
if (!root->name) return false;
|
||||
root->abspath = strdup("/");
|
||||
if (!root->abspath) return false;
|
||||
return read_recursive(root);
|
||||
}
|
||||
|
||||
static void cleanup_recursive(DIR_ENTRY *entry) {
|
||||
u32 i;
|
||||
for (i = 0; i < entry->fileCount; i++) cleanup_recursive(&entry->children[i]);
|
||||
if (entry->children) free(entry->children);
|
||||
if (entry->name) free(entry->name);
|
||||
if (entry->abspath) free(entry->abspath);
|
||||
}
|
||||
|
||||
bool ISFS_Mount() {
|
||||
ISFS_Unmount();
|
||||
bool success = read_isfs() && (dotab_device = AddDevice(&dotab_isfs)) >= 0;
|
||||
if (!success) ISFS_Unmount();
|
||||
return success;
|
||||
}
|
||||
|
||||
bool ISFS_Unmount() {
|
||||
if (root) {
|
||||
cleanup_recursive(root);
|
||||
free(root);
|
||||
root = NULL;
|
||||
}
|
||||
current = root;
|
||||
if (dotab_device >= 0) {
|
||||
dotab_device = -1;
|
||||
return !RemoveDevice(DEVICE_NAME ":");
|
||||
}
|
||||
return true;
|
||||
}
|
@ -1,37 +0,0 @@
|
||||
/*
|
||||
|
||||
libisfs -- a NAND filesystem devoptab library for the Wii
|
||||
|
||||
Copyright (C) 2008 Joseph Jordan <joe.ftpii@psychlaw.com.au>
|
||||
|
||||
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.
|
||||
|
||||
*/
|
||||
#ifndef _LIBISFS_H
|
||||
#define _LIBISFS_H
|
||||
|
||||
#include <ogc/isfs.h>
|
||||
|
||||
#define ISFS_MAXPATHLEN (ISFS_MAXPATH + 1)
|
||||
|
||||
bool ISFS_Mount();
|
||||
bool ISFS_Unmount();
|
||||
|
||||
#endif /* _LIBISFS_H_ */
|
||||
|
446
source/wad/nandtitle.cpp
Normal file
446
source/wad/nandtitle.cpp
Normal file
@ -0,0 +1,446 @@
|
||||
#include "nandtitle.h"
|
||||
#include "gecko.h"
|
||||
|
||||
extern "C"
|
||||
{
|
||||
extern s32 MagicPatches(s32);
|
||||
}
|
||||
|
||||
static u8 tmd_buf[ MAX_SIGNED_TMD_SIZE ] ATTRIBUTE_ALIGN( 32 );
|
||||
|
||||
NandTitle::NandTitle()
|
||||
{
|
||||
numTitles = 0;
|
||||
currentIndex = 0;
|
||||
currentType = 0;
|
||||
list = NULL;
|
||||
nameList = NULL;
|
||||
}
|
||||
|
||||
NandTitle::~NandTitle()
|
||||
{
|
||||
if( list )
|
||||
{
|
||||
free( list );
|
||||
list = NULL;
|
||||
}
|
||||
|
||||
if( nameList )
|
||||
{
|
||||
free( nameList );
|
||||
nameList = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
s32 NandTitle::Get()
|
||||
{
|
||||
s32 ret;
|
||||
|
||||
if( list )
|
||||
{
|
||||
free( list );
|
||||
list = NULL;
|
||||
}
|
||||
|
||||
if( nameList )
|
||||
{
|
||||
free( nameList );
|
||||
nameList = NULL;
|
||||
}
|
||||
|
||||
ret = ES_GetNumTitles( &numTitles );
|
||||
if(ret < 0)
|
||||
return WII_EINTERNAL;
|
||||
|
||||
list = (u64*)memalign( 32, numTitles * sizeof( u64 ) );
|
||||
if( !list )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = ES_GetTitles( list, numTitles );
|
||||
if( ret < 0 )
|
||||
{
|
||||
free( list );
|
||||
return WII_EINTERNAL;
|
||||
}
|
||||
|
||||
nameList = (char*)malloc( IMET_MAX_NAME_LEN * numTitles );
|
||||
if( !nameList )
|
||||
{
|
||||
free( nameList );
|
||||
return -2;
|
||||
}
|
||||
memset( nameList, 0, IMET_MAX_NAME_LEN * numTitles );
|
||||
|
||||
MagicPatches( 1 );
|
||||
int language = CONF_GetLanguage();
|
||||
ISFS_Initialize();
|
||||
|
||||
wchar_t name[ IMET_MAX_NAME_LEN ];
|
||||
|
||||
for( u32 i = 0; i < numTitles; i++)
|
||||
{
|
||||
bool r = GetName( list[ i ], language, name );
|
||||
if( r )
|
||||
{
|
||||
wString *wsname = new wString( name );
|
||||
memcpy( nameList + ( IMET_MAX_NAME_LEN * i ), (wsname->toUTF8()).c_str(), strlen( (wsname->toUTF8()).c_str() ) );
|
||||
//gprintf("adding: %s\n", (wsname->toUTF8()).c_str() );
|
||||
delete wsname;
|
||||
}
|
||||
}
|
||||
|
||||
ISFS_Deinitialize();
|
||||
MagicPatches( 0 );
|
||||
return 1;
|
||||
}
|
||||
|
||||
tmd* NandTitle::GetTMD( u64 tid )
|
||||
{
|
||||
//gprintf("GetTMD( %016llx ): ", tid );
|
||||
signed_blob *s_tmd = (signed_blob *)tmd_buf;
|
||||
u32 tmd_size;
|
||||
|
||||
if( ES_GetStoredTMDSize( tid, &tmd_size ) < 0 )
|
||||
{
|
||||
//gprintf("!size\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
s32 ret = ES_GetStoredTMD( tid, s_tmd, tmd_size );
|
||||
if( ret < 0 )
|
||||
{
|
||||
//gprintf("!tmd - %04x\n", ret );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
tmd *t = (tmd*)SIGNATURE_PAYLOAD(s_tmd);
|
||||
//gprintf("ok\n");
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
bool NandTitle::GetName( u64 tid, int language, wchar_t* name )
|
||||
{
|
||||
if( TITLE_UPPER( tid ) != 0x10001 && TITLE_UPPER( tid ) != 0x10002 && TITLE_UPPER( tid ) != 0x10004 )
|
||||
return false;
|
||||
//gprintf("GetName( %016llx ): ", tid );
|
||||
char app[ ISFS_MAXPATH ];
|
||||
IMET *imet = (IMET*)memalign( 32, sizeof( IMET ) );
|
||||
|
||||
tmd* titleTmd = GetTMD( tid );
|
||||
if( !titleTmd )
|
||||
{
|
||||
//gprintf("no TMD\n");
|
||||
free( imet );
|
||||
return false;
|
||||
}
|
||||
|
||||
u16 i;
|
||||
bool ok = false;
|
||||
for( i = 0; i < titleTmd->num_contents; i++ )
|
||||
{
|
||||
if( !titleTmd->contents[ i ].index )
|
||||
{
|
||||
ok = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( !ok )
|
||||
{
|
||||
free( imet );
|
||||
return false;
|
||||
}
|
||||
|
||||
snprintf( app, sizeof( app ), "/title/%08x/%08x/content/%08x.app", TITLE_UPPER( tid ), TITLE_LOWER( tid ), titleTmd->contents[ i ].cid );
|
||||
//gprintf("%s\n", app );
|
||||
|
||||
if( language > CONF_LANG_KOREAN )
|
||||
language = CONF_LANG_ENGLISH;
|
||||
|
||||
s32 fd = ISFS_Open( app, ISFS_OPEN_READ );
|
||||
if( fd < 0 )
|
||||
{
|
||||
//gprintf("fd: %d\n", fd );
|
||||
free( imet );
|
||||
return false;
|
||||
}
|
||||
|
||||
if( ISFS_Seek( fd, IMET_OFFSET, SEEK_SET ) != IMET_OFFSET )
|
||||
{
|
||||
ISFS_Close( fd );
|
||||
free( imet );
|
||||
return false;
|
||||
}
|
||||
|
||||
if( ISFS_Read( fd, imet, sizeof( IMET ) ) != sizeof( IMET ) )
|
||||
{
|
||||
ISFS_Close( fd );
|
||||
free( imet );
|
||||
return false;
|
||||
}
|
||||
|
||||
ISFS_Close( fd );
|
||||
|
||||
if( imet->sig != IMET_SIGNATURE )
|
||||
{
|
||||
free( imet );
|
||||
return false;
|
||||
}
|
||||
|
||||
if( imet->name_japanese[ language * IMET_MAX_NAME_LEN ] == 0 )
|
||||
{
|
||||
// channel name is not available in system language
|
||||
if( imet->name_english[ 0 ] != 0 )
|
||||
{
|
||||
language = CONF_LANG_ENGLISH;
|
||||
}
|
||||
else
|
||||
{
|
||||
// channel name is also not available on english, get ascii name
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
name[ i ] = ( TITLE_LOWER( tid ) >> ( 24 - i * 8 ) ) & 0xFF;
|
||||
}
|
||||
name[ 4 ] = 0;
|
||||
free( imet );
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// retrieve channel name in system language or on english
|
||||
for( int i = 0; i < IMET_MAX_NAME_LEN; i++ )
|
||||
{
|
||||
name[ i ] = imet->name_japanese[ i + ( language * IMET_MAX_NAME_LEN ) ];
|
||||
}
|
||||
|
||||
free( imet );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NandTitle::Exists( u64 tid )
|
||||
{
|
||||
char app[ ISFS_MAXPATH ];
|
||||
tmd* titleTmd = GetTMD( tid );
|
||||
if( !titleTmd )
|
||||
return false;
|
||||
|
||||
u16 i;
|
||||
bool ok = false;
|
||||
for( i = 0; i < titleTmd->num_contents; i++ )
|
||||
{
|
||||
if( !titleTmd->contents[ i ].index )
|
||||
{
|
||||
ok = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( !ok )
|
||||
return false;
|
||||
|
||||
|
||||
snprintf( app, sizeof( app ), "/title/%08x/%08x/content/%08x.app", TITLE_UPPER( tid ), TITLE_LOWER( tid ), titleTmd->contents[ i ].cid );
|
||||
s32 fd = ISFS_Open( app, ISFS_OPEN_READ );
|
||||
if( fd >= 0 )
|
||||
ISFS_Close( fd );
|
||||
|
||||
//gprintf(" fd: %d\n", fd );
|
||||
return fd >= 0 || fd == -102; //102 means it exists, but we dont have permission to open it
|
||||
|
||||
}
|
||||
|
||||
bool NandTitle::ExistsFromIndex( u32 i )
|
||||
{
|
||||
if( i > numTitles || i < 0 )
|
||||
return false;
|
||||
|
||||
return Exists( list[ i ] );
|
||||
}
|
||||
|
||||
u64 NandTitle::At( u32 i )
|
||||
{
|
||||
if( i > numTitles || i < 0 )
|
||||
return 0;
|
||||
|
||||
return list[ i ];
|
||||
}
|
||||
|
||||
int NandTitle::IndexOf( u64 tid )
|
||||
{
|
||||
for( u32 i = 0; i < numTitles; i++ )
|
||||
{
|
||||
if( list[ i ] == tid )
|
||||
return i;
|
||||
}
|
||||
|
||||
return WII_EINSTALL;
|
||||
}
|
||||
|
||||
char* NandTitle::NameOf( u64 tid )
|
||||
{
|
||||
for( u32 i = 0; i < numTitles; i++ )
|
||||
{
|
||||
if( list[ i ] == tid )
|
||||
{
|
||||
if( !nameList[ IMET_MAX_NAME_LEN * i ] )
|
||||
return NULL;
|
||||
|
||||
return nameList + ( IMET_MAX_NAME_LEN * i );
|
||||
}
|
||||
|
||||
}
|
||||
return NULL;
|
||||
|
||||
}
|
||||
|
||||
char* NandTitle::NameFromIndex( u32 i )
|
||||
{
|
||||
if( i > numTitles || i < 0 )
|
||||
return NULL;
|
||||
|
||||
if( !nameList[ IMET_MAX_NAME_LEN * i ] )
|
||||
return NULL;
|
||||
|
||||
return nameList + ( IMET_MAX_NAME_LEN * i );
|
||||
}
|
||||
|
||||
u16 NandTitle::VersionOf( u64 tid )
|
||||
{
|
||||
for( u32 i = 0; i < numTitles; i++ )
|
||||
{
|
||||
if( list[ i ] == tid )
|
||||
{
|
||||
tmd* Tmd = GetTMD( tid );
|
||||
if( !Tmd )
|
||||
break;
|
||||
|
||||
return Tmd->title_version;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
u16 NandTitle::VersionFromIndex( u32 i )
|
||||
{
|
||||
if( i > numTitles || i < 0 )
|
||||
return 0;
|
||||
|
||||
tmd* Tmd = GetTMD( list[ i ] );
|
||||
if( !Tmd )
|
||||
return 0;
|
||||
|
||||
return Tmd->title_version;
|
||||
}
|
||||
|
||||
u32 NandTitle::CountType( u32 type )
|
||||
{
|
||||
u32 ret = 0;
|
||||
for( u32 i = 0; i < numTitles; i++ )
|
||||
{
|
||||
if( TITLE_UPPER( list[ i ] ) == type )
|
||||
{
|
||||
ret++;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
u32 NandTitle::SetType( u32 upper )
|
||||
{
|
||||
currentType = upper;
|
||||
currentIndex = 0;
|
||||
|
||||
return CountType( upper );
|
||||
}
|
||||
|
||||
u64 NandTitle::Next()
|
||||
{
|
||||
u64 ret = 0;
|
||||
//gprintf("Next( %08x, %u )\n", currentType, currentIndex );
|
||||
u32 i;
|
||||
for( i = currentIndex; i < numTitles; i++ )
|
||||
{
|
||||
if( currentType )
|
||||
{
|
||||
if( currentType == TITLE_UPPER( list[ i ] ) )
|
||||
{
|
||||
ret = list[ i ];
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = list[ i ];
|
||||
break;
|
||||
}
|
||||
}
|
||||
currentIndex = i + 1;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void NandTitle::ResetCounter()
|
||||
{
|
||||
currentIndex = 0;
|
||||
}
|
||||
|
||||
void NandTitle::AsciiTID( u64 tid, char* out )
|
||||
{
|
||||
//gprintf("AsciiTID( %016llx ): ");
|
||||
out[ 0 ] = ascii( TITLE_3( tid ) );
|
||||
out[ 1 ] = ascii( TITLE_2( tid ) );
|
||||
out[ 2 ] = ascii( TITLE_1( tid ) );
|
||||
out[ 3 ] = ascii( (u8)( tid ) );
|
||||
out[ 4 ] = 0;
|
||||
//gprintf("%s\n", out );
|
||||
}
|
||||
|
||||
void NandTitle::AsciiFromIndex( u32 i, char* out )
|
||||
{
|
||||
if( i > numTitles || i < 0 )
|
||||
{
|
||||
out[ 0 ] = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
AsciiTID( list[ i ], out );
|
||||
}
|
||||
|
||||
s32 NandTitle::GetTicketViews( u64 tid, tikview **outbuf, u32 *outlen )
|
||||
{
|
||||
tikview *views = NULL;
|
||||
|
||||
u32 nb_views;
|
||||
s32 ret;
|
||||
|
||||
/* Get number of ticket views */
|
||||
ret = ES_GetNumTicketViews(tid, &nb_views);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* Allocate memory */
|
||||
views = (tikview *)memalign(32, sizeof(tikview) * nb_views);
|
||||
if (!views)
|
||||
return -1;
|
||||
|
||||
/* Get ticket views */
|
||||
ret = ES_GetTicketViews(tid, views, nb_views);
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
|
||||
/* Set values */
|
||||
*outbuf = views;
|
||||
*outlen = nb_views;
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
/* Free memory */
|
||||
if (views)
|
||||
free(views);
|
||||
|
||||
return ret;
|
||||
}
|
107
source/wad/nandtitle.h
Normal file
107
source/wad/nandtitle.h
Normal file
@ -0,0 +1,107 @@
|
||||
#ifndef NANDTITLE_H
|
||||
#define NANDTITLE_H
|
||||
|
||||
#include <gccore.h>
|
||||
#include <ogcsys.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <malloc.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "wstring.hpp"
|
||||
|
||||
#define TITLE_ID(x,y) (((u64)(x) << 32) | (y))
|
||||
#define TITLE_UPPER(x) ((u32)((x) >> 32))
|
||||
#define TITLE_LOWER(x) ((u32)(x))
|
||||
|
||||
#define TITLE_1(x) ((u8)((x) >> 8))
|
||||
#define TITLE_2(x) ((u8)((x) >> 16))
|
||||
#define TITLE_3(x) ((u8)((x) >> 24))
|
||||
#define TITLE_4(x) ((u8)((x) >> 32))
|
||||
#define TITLE_5(x) ((u8)((x) >> 40))
|
||||
#define TITLE_6(x) ((u8)((x) >> 48))
|
||||
#define TITLE_7(x) ((u8)((x) >> 56))
|
||||
|
||||
#define IMET_MAX_NAME_LEN 0x2a
|
||||
|
||||
#define IMET_OFFSET 0x40
|
||||
#define IMET_SIGNATURE 0x494d4554
|
||||
#define DOWNLOADED_CHANNELS 0x00010001
|
||||
#define SYSTEM_CHANNELS 0x00010002
|
||||
#define RF_NEWS_CHANNEL 0x48414741
|
||||
#define RF_FORECAST_CHANNEL 0x48414641
|
||||
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u8 zeroes1[0x40];
|
||||
u32 sig; // "IMET"
|
||||
u32 unk1;
|
||||
u32 unk2;
|
||||
u32 filesizes[3];
|
||||
u32 unk3;
|
||||
u16 name_japanese[IMET_MAX_NAME_LEN];
|
||||
u16 name_english[IMET_MAX_NAME_LEN];
|
||||
u16 name_german[IMET_MAX_NAME_LEN];
|
||||
u16 name_french[IMET_MAX_NAME_LEN];
|
||||
u16 name_spanish[IMET_MAX_NAME_LEN];
|
||||
u16 name_italian[IMET_MAX_NAME_LEN];
|
||||
u16 name_dutch[IMET_MAX_NAME_LEN];
|
||||
u16 name_simp_chinese[IMET_MAX_NAME_LEN];
|
||||
u16 name_trad_chinese[IMET_MAX_NAME_LEN];
|
||||
u16 name_korean[IMET_MAX_NAME_LEN];
|
||||
u8 zeroes2[0x24c];
|
||||
u8 md5[0x10];
|
||||
} IMET;
|
||||
|
||||
|
||||
class NandTitle
|
||||
{
|
||||
public:
|
||||
NandTitle();
|
||||
~NandTitle();
|
||||
|
||||
s32 Get();
|
||||
u64 At( u32 i );
|
||||
int IndexOf( u64 tid );
|
||||
u32 Count(){ return numTitles; }
|
||||
|
||||
char* NameOf( u64 tid );
|
||||
char* NameFromIndex( u32 i );
|
||||
|
||||
u16 VersionOf( u64 tid );
|
||||
u16 VersionFromIndex( u32 i );
|
||||
|
||||
u32 CountType( u32 type );
|
||||
|
||||
|
||||
u32 SetType( u32 upper );
|
||||
u64 Next();
|
||||
void ResetCounter();
|
||||
|
||||
void AsciiTID( u64 tid, char* out );
|
||||
void AsciiFromIndex( u32 i, char* out );
|
||||
|
||||
bool Exists( u64 tid );
|
||||
bool ExistsFromIndex( u32 i );
|
||||
|
||||
s32 GetTicketViews( u64 tid, tikview **outbuf, u32 *outlen );
|
||||
|
||||
u64 operator[]( u32 i ) { return At( i ); }
|
||||
|
||||
private:
|
||||
u64* list;
|
||||
char* nameList;
|
||||
u32 numTitles;
|
||||
bool GetName( u64 tid, int language, wchar_t* name );
|
||||
tmd* GetTMD( u64 tid );
|
||||
|
||||
|
||||
u32 currentIndex;
|
||||
u32 currentType;
|
||||
};
|
||||
|
||||
extern NandTitle titles;
|
||||
#endif // NANDTITLE_H
|
||||
|
@ -1,94 +0,0 @@
|
||||
/* patchmii_core -- low-level functions to handle the downloading, patching
|
||||
and installation of updates on the Wii
|
||||
|
||||
Copyright (C) 2008 bushing / hackmii.com
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, version 2.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <malloc.h>
|
||||
#include <ogcsys.h>
|
||||
#include <gccore.h>
|
||||
#include <stdarg.h>
|
||||
#include <ctype.h>
|
||||
#include <unistd.h>
|
||||
#include <network.h>
|
||||
#include <sys/errno.h>
|
||||
|
||||
#include "patchmii_core.h"
|
||||
#include "sha1.h"
|
||||
|
||||
#define ALIGN(a,b) ((((a)+(b)-1)/(b))*(b))
|
||||
|
||||
int http_status = 0;
|
||||
int tmd_dirty = 0, tik_dirty = 0, temp_ios_slot = 0;
|
||||
|
||||
// yeah, yeah, I know.
|
||||
signed_blob *s_tmd = NULL, *s_tik = NULL, *s_certs = NULL;
|
||||
//static u8 tmdbuf[MAX_SIGNED_TMD_SIZE] ATTRIBUTE_ALIGN(0x20);
|
||||
//static u8 tikbuf[STD_SIGNED_TIK_SIZE] ATTRIBUTE_ALIGN(0x20);
|
||||
|
||||
|
||||
void zero_sig(signed_blob *sig) {
|
||||
u8 *sig_ptr = (u8 *)sig;
|
||||
memset(sig_ptr + 4, 0, SIGNATURE_SIZE(sig)-4);
|
||||
}
|
||||
|
||||
void brute_tmd(tmd *p_tmd) {
|
||||
u16 fill;
|
||||
for (fill=0; fill<65535; fill++) {
|
||||
p_tmd->fill3=fill;
|
||||
sha1 hash;
|
||||
// debug_printf("SHA1(%p, %x, %p)\n", p_tmd, TMD_SIZE(p_tmd), hash);
|
||||
SHA1((u8 *)p_tmd, TMD_SIZE(p_tmd), hash);;
|
||||
|
||||
if (hash[0]==0) {
|
||||
// debug_printf("setting fill3 to %04hx\n", fill);
|
||||
return;
|
||||
}
|
||||
}
|
||||
printf("Unable to fix tmd :(\n");
|
||||
exit(4);
|
||||
}
|
||||
|
||||
void brute_tik(tik *p_tik) {
|
||||
u16 fill;
|
||||
for (fill=0; fill<65535; fill++) {
|
||||
p_tik->padding=fill;
|
||||
sha1 hash;
|
||||
// debug_printf("SHA1(%p, %x, %p)\n", p_tmd, TMD_SIZE(p_tmd), hash);
|
||||
SHA1((u8 *)p_tik, sizeof(tik), hash);
|
||||
|
||||
if (hash[0]==0) return;
|
||||
}
|
||||
printf("Unable to fix tik :(\n");
|
||||
exit(5);
|
||||
}
|
||||
|
||||
void forge_tmd(signed_blob *s_tmd) {
|
||||
// debug_printf("forging tmd sig");
|
||||
zero_sig(s_tmd);
|
||||
brute_tmd(SIGNATURE_PAYLOAD(s_tmd));
|
||||
}
|
||||
|
||||
void forge_tik(signed_blob *s_tik) {
|
||||
// debug_printf("forging tik sig");
|
||||
zero_sig(s_tik);
|
||||
brute_tik(SIGNATURE_PAYLOAD(s_tik));
|
||||
}
|
||||
|
||||
|
@ -1,60 +0,0 @@
|
||||
#ifndef _PATCHMII_CORE_
|
||||
#define _PATCHMII_CORE_
|
||||
|
||||
|
||||
//Patchmii functions
|
||||
void patchmii_network_init(void);
|
||||
// Call with version = 0 to get the latest version
|
||||
// Set "patch" if you want to try to patch title contents
|
||||
s32 patchmii_install(u32 in_title_h, u32 in_title_l, u32 in_version, u32 out_title_h, u32 out_title_l, u32 out_version, bool patch);
|
||||
s32 install_temporary_ios(u32 base_ios, u32 base_ver);
|
||||
s32 load_temporary_ios(void);
|
||||
s32 cleanup_temporary_ios(void);
|
||||
|
||||
//Tools
|
||||
void forge_tmd(signed_blob *s_tmd);
|
||||
void forge_tik(signed_blob *s_tik);
|
||||
|
||||
void spinner(void);
|
||||
|
||||
#define TEMP_IOS
|
||||
|
||||
// Basic I/O.
|
||||
|
||||
static inline u32 read32(u32 addr) {
|
||||
u32 x;
|
||||
asm volatile("lwz %0,0(%1) ; sync" : "=r"(x) : "b"(0xc0000000 | addr));
|
||||
return x;
|
||||
}
|
||||
|
||||
static inline void write32(u32 addr, u32 x) {
|
||||
asm("stw %0,0(%1) ; eieio" : : "r"(x), "b"(0xc0000000 | addr));
|
||||
}
|
||||
|
||||
// USB Gecko.
|
||||
|
||||
void usb_flush(int chn);
|
||||
int usb_sendbuffer(int chn,const void *buffer,int size);
|
||||
|
||||
// Version string.
|
||||
|
||||
extern const char version[];
|
||||
|
||||
// Debug: blink the tray led.
|
||||
|
||||
static inline void blink(void) {
|
||||
write32(0x0d8000c0, read32(0x0d8000c0) ^ 0x20);
|
||||
}
|
||||
|
||||
void debug_printf(const char *fmt, ...);
|
||||
void hexdump(FILE *fp, void *d, int len);
|
||||
void aes_set_key(u8 *key);
|
||||
void aes_decrypt(u8 *iv, u8 *inbuf, u8 *outbuf, unsigned long long len);
|
||||
void aes_encrypt(u8 *iv, u8 *inbuf, u8 *outbuf, unsigned long long len);
|
||||
|
||||
#define TRACE(x) debug_printf("%s / %d: %d\n", __FUNCTION__, __LINE__, (x))
|
||||
|
||||
#define ISFS_ACCESS_READ 1
|
||||
#define ISFS_ACCESS_WRITE 2
|
||||
|
||||
#endif
|
@ -1,227 +0,0 @@
|
||||
/*
|
||||
SHA-1 in C
|
||||
By Steve Reid <steve@edmweb.com>
|
||||
100% Public Domain
|
||||
|
||||
Test Vectors (from FIPS PUB 180-1)
|
||||
"abc"
|
||||
A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
|
||||
"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
|
||||
84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
|
||||
A million repetitions of "a"
|
||||
34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
|
||||
*/
|
||||
|
||||
/* #define LITTLE_ENDIAN * This should be #define'd if true. */
|
||||
#define SHA1HANDSOFF
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "sha1.h"
|
||||
|
||||
#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
|
||||
|
||||
/* blk0() and blk() perform the initial expand. */
|
||||
/* I got the idea of expanding during the round function from SSLeay */
|
||||
#ifdef LITTLE_ENDIAN
|
||||
#define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \
|
||||
|(rol(block->l[i],8)&0x00FF00FF))
|
||||
#else
|
||||
#define blk0(i) block->l[i]
|
||||
#endif
|
||||
#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \
|
||||
^block->l[(i+2)&15]^block->l[i&15],1))
|
||||
|
||||
/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
|
||||
#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30);
|
||||
#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30);
|
||||
#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
|
||||
#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);
|
||||
#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);
|
||||
|
||||
|
||||
/* Hash a single 512-bit block. This is the core of the algorithm. */
|
||||
|
||||
void SHA1Transform(unsigned long state[5], unsigned char buffer[64]) {
|
||||
unsigned long a, b, c, d, e;
|
||||
typedef union {
|
||||
unsigned char c[64];
|
||||
unsigned long l[16];
|
||||
} CHAR64LONG16;
|
||||
CHAR64LONG16* block;
|
||||
#ifdef SHA1HANDSOFF
|
||||
static unsigned char workspace[64];
|
||||
block = (CHAR64LONG16*)workspace;
|
||||
memcpy(block, buffer, 64);
|
||||
#else
|
||||
block = (CHAR64LONG16*)buffer;
|
||||
#endif
|
||||
/* Copy context->state[] to working vars */
|
||||
a = state[0];
|
||||
b = state[1];
|
||||
c = state[2];
|
||||
d = state[3];
|
||||
e = state[4];
|
||||
/* 4 rounds of 20 operations each. Loop unrolled. */
|
||||
R0(a,b,c,d,e, 0);
|
||||
R0(e,a,b,c,d, 1);
|
||||
R0(d,e,a,b,c, 2);
|
||||
R0(c,d,e,a,b, 3);
|
||||
R0(b,c,d,e,a, 4);
|
||||
R0(a,b,c,d,e, 5);
|
||||
R0(e,a,b,c,d, 6);
|
||||
R0(d,e,a,b,c, 7);
|
||||
R0(c,d,e,a,b, 8);
|
||||
R0(b,c,d,e,a, 9);
|
||||
R0(a,b,c,d,e,10);
|
||||
R0(e,a,b,c,d,11);
|
||||
R0(d,e,a,b,c,12);
|
||||
R0(c,d,e,a,b,13);
|
||||
R0(b,c,d,e,a,14);
|
||||
R0(a,b,c,d,e,15);
|
||||
R1(e,a,b,c,d,16);
|
||||
R1(d,e,a,b,c,17);
|
||||
R1(c,d,e,a,b,18);
|
||||
R1(b,c,d,e,a,19);
|
||||
R2(a,b,c,d,e,20);
|
||||
R2(e,a,b,c,d,21);
|
||||
R2(d,e,a,b,c,22);
|
||||
R2(c,d,e,a,b,23);
|
||||
R2(b,c,d,e,a,24);
|
||||
R2(a,b,c,d,e,25);
|
||||
R2(e,a,b,c,d,26);
|
||||
R2(d,e,a,b,c,27);
|
||||
R2(c,d,e,a,b,28);
|
||||
R2(b,c,d,e,a,29);
|
||||
R2(a,b,c,d,e,30);
|
||||
R2(e,a,b,c,d,31);
|
||||
R2(d,e,a,b,c,32);
|
||||
R2(c,d,e,a,b,33);
|
||||
R2(b,c,d,e,a,34);
|
||||
R2(a,b,c,d,e,35);
|
||||
R2(e,a,b,c,d,36);
|
||||
R2(d,e,a,b,c,37);
|
||||
R2(c,d,e,a,b,38);
|
||||
R2(b,c,d,e,a,39);
|
||||
R3(a,b,c,d,e,40);
|
||||
R3(e,a,b,c,d,41);
|
||||
R3(d,e,a,b,c,42);
|
||||
R3(c,d,e,a,b,43);
|
||||
R3(b,c,d,e,a,44);
|
||||
R3(a,b,c,d,e,45);
|
||||
R3(e,a,b,c,d,46);
|
||||
R3(d,e,a,b,c,47);
|
||||
R3(c,d,e,a,b,48);
|
||||
R3(b,c,d,e,a,49);
|
||||
R3(a,b,c,d,e,50);
|
||||
R3(e,a,b,c,d,51);
|
||||
R3(d,e,a,b,c,52);
|
||||
R3(c,d,e,a,b,53);
|
||||
R3(b,c,d,e,a,54);
|
||||
R3(a,b,c,d,e,55);
|
||||
R3(e,a,b,c,d,56);
|
||||
R3(d,e,a,b,c,57);
|
||||
R3(c,d,e,a,b,58);
|
||||
R3(b,c,d,e,a,59);
|
||||
R4(a,b,c,d,e,60);
|
||||
R4(e,a,b,c,d,61);
|
||||
R4(d,e,a,b,c,62);
|
||||
R4(c,d,e,a,b,63);
|
||||
R4(b,c,d,e,a,64);
|
||||
R4(a,b,c,d,e,65);
|
||||
R4(e,a,b,c,d,66);
|
||||
R4(d,e,a,b,c,67);
|
||||
R4(c,d,e,a,b,68);
|
||||
R4(b,c,d,e,a,69);
|
||||
R4(a,b,c,d,e,70);
|
||||
R4(e,a,b,c,d,71);
|
||||
R4(d,e,a,b,c,72);
|
||||
R4(c,d,e,a,b,73);
|
||||
R4(b,c,d,e,a,74);
|
||||
R4(a,b,c,d,e,75);
|
||||
R4(e,a,b,c,d,76);
|
||||
R4(d,e,a,b,c,77);
|
||||
R4(c,d,e,a,b,78);
|
||||
R4(b,c,d,e,a,79);
|
||||
/* Add the working vars back into context.state[] */
|
||||
state[0] += a;
|
||||
state[1] += b;
|
||||
state[2] += c;
|
||||
state[3] += d;
|
||||
state[4] += e;
|
||||
/* Wipe variables */
|
||||
a = b = c = d = e = 0;
|
||||
}
|
||||
|
||||
|
||||
/* SHA1Init - Initialize new context */
|
||||
|
||||
void SHA1Init(SHA1_CTX* context) {
|
||||
/* SHA1 initialization constants */
|
||||
context->state[0] = 0x67452301;
|
||||
context->state[1] = 0xEFCDAB89;
|
||||
context->state[2] = 0x98BADCFE;
|
||||
context->state[3] = 0x10325476;
|
||||
context->state[4] = 0xC3D2E1F0;
|
||||
context->count[0] = context->count[1] = 0;
|
||||
}
|
||||
|
||||
|
||||
/* Run your data through this. */
|
||||
|
||||
void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned int len) {
|
||||
unsigned int i, j;
|
||||
|
||||
j = (context->count[0] >> 3) & 63;
|
||||
if ((context->count[0] += len << 3) < (len << 3)) context->count[1]++;
|
||||
context->count[1] += (len >> 29);
|
||||
if ((j + len) > 63) {
|
||||
memcpy(&context->buffer[j], data, (i = 64-j));
|
||||
SHA1Transform(context->state, context->buffer);
|
||||
for ( ; i + 63 < len; i += 64) {
|
||||
SHA1Transform(context->state, &data[i]);
|
||||
}
|
||||
j = 0;
|
||||
} else i = 0;
|
||||
memcpy(&context->buffer[j], &data[i], len - i);
|
||||
}
|
||||
|
||||
|
||||
/* Add padding and return the message digest. */
|
||||
|
||||
void SHA1Final(unsigned char digest[20], SHA1_CTX* context) {
|
||||
unsigned long i, j;
|
||||
unsigned char finalcount[8];
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)]
|
||||
>> ((3-(i & 3)) * 8) ) & 255); /* Endian independent */
|
||||
}
|
||||
SHA1Update(context, (unsigned char *)"\200", 1);
|
||||
while ((context->count[0] & 504) != 448) {
|
||||
SHA1Update(context, (unsigned char *)"\0", 1);
|
||||
}
|
||||
SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform() */
|
||||
for (i = 0; i < 20; i++) {
|
||||
digest[i] = (unsigned char)
|
||||
((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
|
||||
}
|
||||
/* Wipe variables */
|
||||
i = j = 0;
|
||||
memset(context->buffer, 0, 64);
|
||||
memset(context->state, 0, 20);
|
||||
memset(context->count, 0, 8);
|
||||
memset(&finalcount, 0, 8);
|
||||
#ifdef SHA1HANDSOFF /* make SHA1Transform overwrite it's own static vars */
|
||||
SHA1Transform(context->state, context->buffer);
|
||||
#endif
|
||||
}
|
||||
|
||||
void SHA1(unsigned char *ptr, unsigned int size, unsigned char *outbuf) {
|
||||
SHA1_CTX ctx;
|
||||
|
||||
SHA1Init(&ctx);
|
||||
SHA1Update(&ctx, ptr, size);
|
||||
SHA1Final(outbuf, &ctx);
|
||||
}
|
||||
|
@ -1,12 +0,0 @@
|
||||
typedef struct {
|
||||
unsigned long state[5];
|
||||
unsigned long count[2];
|
||||
unsigned char buffer[64];
|
||||
} SHA1_CTX;
|
||||
|
||||
void SHA1Transform(unsigned long state[5], unsigned char buffer[64]);
|
||||
void SHA1Init(SHA1_CTX* context);
|
||||
void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned int len);
|
||||
void SHA1Final(unsigned char digest[20], SHA1_CTX* context);
|
||||
|
||||
void SHA1(unsigned char *ptr, unsigned int size, unsigned char *outbuf);
|
@ -1,949 +0,0 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <malloc.h>
|
||||
#include <gccore.h>
|
||||
#include <ogcsys.h>
|
||||
|
||||
#include "utils.h"
|
||||
#include "../settings/cfg.h"
|
||||
#include "fatmounter.h"
|
||||
#include "id.h"
|
||||
#include "isfs.h"
|
||||
#include "../gecko.h"
|
||||
|
||||
|
||||
#define MAX_TITLES 256
|
||||
|
||||
|
||||
s32 Title_GetList(u64 **outbuf, u32 *outlen) {
|
||||
u64 *titles = NULL;
|
||||
|
||||
u32 len, nb_titles;
|
||||
s32 ret;
|
||||
|
||||
/* Get number of titles */
|
||||
ret = ES_GetNumTitles(&nb_titles);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* Calculate buffer lenght */
|
||||
len = round_up(sizeof(u64) * nb_titles, 32);
|
||||
|
||||
/* Allocate memory */
|
||||
titles = memalign(32, len);
|
||||
if (!titles)
|
||||
return -1;
|
||||
|
||||
/* Get titles */
|
||||
ret = ES_GetTitles(titles, nb_titles);
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
|
||||
/* Set values */
|
||||
*outbuf = titles;
|
||||
*outlen = nb_titles;
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
/* Free memory */
|
||||
if (titles)
|
||||
free(titles);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
s32 Title_GetTicketViews(u64 tid, tikview **outbuf, u32 *outlen) {
|
||||
tikview *views = NULL;
|
||||
|
||||
u32 nb_views;
|
||||
s32 ret;
|
||||
|
||||
/* Get number of ticket views */
|
||||
ret = ES_GetNumTicketViews(tid, &nb_views);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* Allocate memory */
|
||||
views = (tikview *)memalign(32, sizeof(tikview) * nb_views);
|
||||
if (!views)
|
||||
return -1;
|
||||
|
||||
/* Get ticket views */
|
||||
ret = ES_GetTicketViews(tid, views, nb_views);
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
|
||||
/* Set values */
|
||||
*outbuf = views;
|
||||
*outlen = nb_views;
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
/* Free memory */
|
||||
if (views)
|
||||
free(views);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
s32 Title_GetTMD(u64 tid, signed_blob **outbuf, u32 *outlen) {
|
||||
void *p_tmd = NULL;
|
||||
|
||||
u32 len;
|
||||
s32 ret;
|
||||
|
||||
/* Get TMD size */
|
||||
ret = ES_GetStoredTMDSize(tid, &len);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* Allocate memory */
|
||||
p_tmd = memalign(32, round_up(len, 32));
|
||||
if (!p_tmd)
|
||||
return -1;
|
||||
|
||||
/* Read TMD */
|
||||
ret = ES_GetStoredTMD(tid, p_tmd, len);
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
|
||||
/* Set values */
|
||||
*outbuf = p_tmd;
|
||||
*outlen = len;
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
/* Free memory */
|
||||
if (p_tmd)
|
||||
free(p_tmd);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
s32 Title_GetVersion(u64 tid, u16 *outbuf) {
|
||||
signed_blob *p_tmd = NULL;
|
||||
tmd *tmd_data = NULL;
|
||||
|
||||
u32 len;
|
||||
s32 ret;
|
||||
|
||||
/* Get title TMD */
|
||||
ret = Title_GetTMD(tid, &p_tmd, &len);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* Retrieve TMD info */
|
||||
tmd_data = (tmd *)SIGNATURE_PAYLOAD(p_tmd);
|
||||
|
||||
/* Set values */
|
||||
*outbuf = tmd_data->title_version;
|
||||
|
||||
/* Free memory */
|
||||
free(p_tmd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
s32 Title_GetSysVersion(u64 tid, u64 *outbuf) {
|
||||
signed_blob *p_tmd = NULL;
|
||||
tmd *tmd_data = NULL;
|
||||
|
||||
u32 len;
|
||||
s32 ret;
|
||||
|
||||
/* Get title TMD */
|
||||
ret = Title_GetTMD(tid, &p_tmd, &len);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* Retrieve TMD info */
|
||||
tmd_data = (tmd *)SIGNATURE_PAYLOAD(p_tmd);
|
||||
|
||||
/* Set values */
|
||||
*outbuf = tmd_data->sys_version;
|
||||
|
||||
/* Free memory */
|
||||
free(p_tmd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
s32 Title_GetSize(u64 tid, u32 *outbuf) {
|
||||
signed_blob *p_tmd = NULL;
|
||||
tmd *tmd_data = NULL;
|
||||
|
||||
u32 cnt, len, size = 0;
|
||||
s32 ret;
|
||||
|
||||
/* Get title TMD */
|
||||
ret = Title_GetTMD(tid, &p_tmd, &len);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* Retrieve TMD info */
|
||||
tmd_data = (tmd *)SIGNATURE_PAYLOAD(p_tmd);
|
||||
|
||||
/* Calculate title size */
|
||||
for (cnt = 0; cnt < tmd_data->num_contents; cnt++) {
|
||||
tmd_content *content = &tmd_data->contents[cnt];
|
||||
|
||||
/* Add content size */
|
||||
size += content->size;
|
||||
}
|
||||
|
||||
/* Set values */
|
||||
*outbuf = size;
|
||||
|
||||
/* Free memory */
|
||||
free(p_tmd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
s32 Title_GetIOSVersions(u8 **outbuf, u32 *outlen) {
|
||||
u8 *buffer = NULL;
|
||||
u64 *list = NULL;
|
||||
|
||||
u32 count, cnt, idx;
|
||||
s32 ret;
|
||||
|
||||
/* Get title list */
|
||||
ret = Title_GetList(&list, &count);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* Count IOS */
|
||||
for (cnt = idx = 0; idx < count; idx++) {
|
||||
u32 tidh = (list[idx] >> 32);
|
||||
u32 tidl = (list[idx] & 0xFFFFFFFF);
|
||||
|
||||
/* Title is IOS */
|
||||
if ((tidh == 0x1) && (tidl >= 3) && (tidl <= 255))
|
||||
cnt++;
|
||||
}
|
||||
|
||||
/* Allocate memory */
|
||||
buffer = (u8 *)memalign(32, cnt);
|
||||
if (!buffer) {
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Copy IOS */
|
||||
for (cnt = idx = 0; idx < count; idx++) {
|
||||
u32 tidh = (list[idx] >> 32);
|
||||
u32 tidl = (list[idx] & 0xFFFFFFFF);
|
||||
|
||||
/* Title is IOS */
|
||||
if ((tidh == 0x1) && (tidl >= 3) && (tidl <= 255))
|
||||
buffer[cnt++] = (u8)(tidl & 0xFF);
|
||||
}
|
||||
|
||||
/* Set values */
|
||||
*outbuf = buffer;
|
||||
*outlen = cnt;
|
||||
|
||||
goto out;
|
||||
|
||||
out:
|
||||
/* Free memory */
|
||||
if (list)
|
||||
free(list);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
s32 Uninstall_RemoveTicket(u64 tid) {
|
||||
static tikview viewdata[0x10] ATTRIBUTE_ALIGN(32);
|
||||
|
||||
u32 cnt, views;
|
||||
s32 ret;
|
||||
|
||||
/* Get number of ticket views */
|
||||
ret = ES_GetNumTicketViews(tid, &views);
|
||||
if (ret < 0) {
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!views) {
|
||||
//printf(" No tickets found!\n");
|
||||
return 1;
|
||||
} else if (views > 16) {
|
||||
//printf(" Too many ticket views! (views = %d)\n", views);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Get ticket views */
|
||||
ret = ES_GetTicketViews(tid, viewdata, views);
|
||||
if (ret < 0) {
|
||||
//printf(" \n\tError! ES_GetTicketViews (ret = %d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Remove tickets */
|
||||
for (cnt = 0; cnt < views; cnt++) {
|
||||
ret = ES_DeleteTicket(&viewdata[cnt]);
|
||||
if (ret < 0) {
|
||||
//printf(" Error! (view = %d, ret = %d)\n", cnt, ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
//printf(" OK!\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
s32 Uninstall_DeleteTitle(u32 title_u, u32 title_l) {
|
||||
s32 ret;
|
||||
char filepath[256];
|
||||
sprintf(filepath, "/title/%08x/%08x", title_u, title_l);
|
||||
|
||||
/* Remove title */
|
||||
ret = ISFS_Delete(filepath);
|
||||
return ret;
|
||||
}
|
||||
|
||||
s32 Uninstall_DeleteTicket(u32 title_u, u32 title_l) {
|
||||
s32 ret;
|
||||
|
||||
char filepath[256];
|
||||
sprintf(filepath, "/ticket/%08x/%08x.tik", title_u, title_l);
|
||||
|
||||
/* Delete ticket */
|
||||
ret = ISFS_Delete(filepath);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
//////savegame shit, from waninkoko. modified for use in this project
|
||||
/* Savegame structure */
|
||||
struct savegame {
|
||||
/* Title name */
|
||||
char name[65];
|
||||
|
||||
/* Title ID */
|
||||
u64 tid;
|
||||
};
|
||||
|
||||
s32 Savegame_CheckTitle(const char *path)
|
||||
{
|
||||
FILE *fp = NULL;
|
||||
|
||||
char filepath[128];
|
||||
|
||||
/* Generate filepath */
|
||||
sprintf(filepath, "%s/banner.bin", path);
|
||||
|
||||
/* Try to open banner */
|
||||
fp = fopen(filepath, "rb");
|
||||
if (!fp)
|
||||
return -1;
|
||||
|
||||
/* Close file */
|
||||
fclose(fp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
s32 Savegame_GetNandPath(u64 tid, char *outbuf)
|
||||
{
|
||||
s32 ret;
|
||||
char buffer[1024] ATTRIBUTE_ALIGN(32);
|
||||
|
||||
/* Get data directory */
|
||||
ret = ES_GetDataDir(tid, buffer);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* Generate NAND directory */
|
||||
sprintf(outbuf, "isfs:%s", buffer);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
s32 __Menu_GetNandSaves(struct savegame **outbuf, u32 *outlen)
|
||||
{
|
||||
struct savegame *buffer = NULL;
|
||||
|
||||
u64 *titleList = NULL;
|
||||
u32 titleCnt;
|
||||
|
||||
u32 cnt, idx;
|
||||
s32 ret;
|
||||
|
||||
/* Get title list */
|
||||
ret = Title_GetList(&titleList, &titleCnt);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* Allocate memory */
|
||||
buffer = malloc(sizeof(struct savegame) * titleCnt);
|
||||
if (!buffer) {
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Copy titles */
|
||||
for (cnt = idx = 0; idx < titleCnt; idx++) {
|
||||
u64 tid = titleList[idx];
|
||||
char savepath[128];
|
||||
|
||||
/* Generate dirpath */
|
||||
Savegame_GetNandPath(tid, savepath);
|
||||
|
||||
/* Check for title savegame */
|
||||
ret = Savegame_CheckTitle(savepath);
|
||||
if (!ret) {
|
||||
struct savegame *save = &buffer[cnt++];
|
||||
|
||||
/* Set title ID */
|
||||
save->tid = tid;
|
||||
}
|
||||
}
|
||||
|
||||
/* Set values */
|
||||
*outbuf = buffer;
|
||||
*outlen = cnt;
|
||||
|
||||
/* Success */
|
||||
ret = 0;
|
||||
|
||||
out:
|
||||
/* Free memory */
|
||||
if (titleList)
|
||||
free(titleList);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
s32 __Menu_EntryCmp(const void *p1, const void *p2)
|
||||
{
|
||||
struct savegame *s1 = (struct savegame *)p1;
|
||||
struct savegame *s2 = (struct savegame *)p2;
|
||||
|
||||
/* Compare entries */
|
||||
return strcmp(s1->name, s2->name);
|
||||
}
|
||||
|
||||
s32 __Menu_RetrieveList(struct savegame **outbuf, u32 *outlen)
|
||||
{
|
||||
s32 ret;
|
||||
ret = __Menu_GetNandSaves(outbuf, outlen);
|
||||
if (ret >= 0)
|
||||
qsort(*outbuf, *outlen, sizeof(struct savegame), __Menu_EntryCmp);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
//carefull when using this function
|
||||
//it will force remove stuff even if something fails
|
||||
s32 Uninstall_FromTitle(const u64 tid) {
|
||||
s32 contents_ret, tik_ret, title_ret, ret;
|
||||
u32 id = tid & 0xFFFFFFFF, kind = tid >> 32;
|
||||
contents_ret = tik_ret = title_ret = ret = 0;
|
||||
|
||||
if (kind == 1) {
|
||||
// Delete title and ticket at FS level.
|
||||
tik_ret = Uninstall_DeleteTicket(kind, id);
|
||||
title_ret = Uninstall_DeleteTitle(kind, id);
|
||||
contents_ret = title_ret;
|
||||
} else {
|
||||
// Remove title (contents and ticket)
|
||||
tik_ret = Uninstall_RemoveTicket(tid);
|
||||
contents_ret = ES_DeleteTitleContent(tid);
|
||||
title_ret = ES_DeleteTitle(tid);
|
||||
|
||||
|
||||
// Attempt forced uninstall if something fails
|
||||
if (tik_ret < 0 || contents_ret < 0 || title_ret < 0) {
|
||||
tik_ret = Uninstall_DeleteTicket(kind, id);
|
||||
title_ret = Uninstall_DeleteTitle(kind, id);
|
||||
contents_ret = title_ret;
|
||||
|
||||
}
|
||||
}
|
||||
if (tik_ret < 0 && contents_ret < 0 && title_ret < 0)
|
||||
ret = -1;
|
||||
else if (tik_ret < 0 || contents_ret < 0 || title_ret < 0)
|
||||
ret = 1;
|
||||
else
|
||||
ret = 0;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------------------
|
||||
taken from anytitledeleter
|
||||
name.c -- functions for determining the name of a title
|
||||
|
||||
Copyright (C) 2009 MrClick
|
||||
|
||||
-------------------------------------------------------------*/
|
||||
|
||||
s32 __convertWiiString(char *str, u8 *data, u32 cnt) {
|
||||
u32 i = 0;
|
||||
for (; i < cnt; data += 2) {
|
||||
u16 *chr = (u16*)data;
|
||||
if (*chr == 0)
|
||||
break;
|
||||
// ignores all but ASCII characters
|
||||
else if (*chr >= 0x20 && *chr <= 0x7E)
|
||||
str[i] = *chr;
|
||||
else
|
||||
str[i] = '.';
|
||||
i++;
|
||||
}
|
||||
str[i] = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
s32 getNameBN(char* name, u64 id) {
|
||||
// Terminate the name string just in case the function exits prematurely
|
||||
name[0] = 0;
|
||||
|
||||
// Create a string containing the absolute filename
|
||||
char file[256] __attribute__ ((aligned (32)));
|
||||
sprintf(file, "/title/%08x/%08x/data/banner.bin", (u32)(id >> 32), (u32)id);
|
||||
|
||||
// Bring the Wii into the title's userspace
|
||||
if (ES_SetUID(id) < 0) {
|
||||
// Should that fail repeat after setting permissions to system menu mode
|
||||
Identify_SysMenu();
|
||||
if (ES_SetUID(id) < 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Try to open file
|
||||
s32 fh = ISFS_Open(file, ISFS_OPEN_READ);
|
||||
|
||||
// If a title does not have a banner.bin bail out
|
||||
if (fh == -106)
|
||||
return -2;
|
||||
|
||||
// If it fails try to open again after identifying as SU
|
||||
if (fh == -102) {
|
||||
Identify_SU();
|
||||
fh = ISFS_Open(file, ISFS_OPEN_READ);
|
||||
}
|
||||
// If the file won't open
|
||||
else if (fh < 0)
|
||||
return fh;
|
||||
|
||||
// Seek to 0x20 where the name is stored
|
||||
ISFS_Seek(fh, 0x20, 0);
|
||||
|
||||
// Read a chunk of 256 bytes from the banner.bin
|
||||
u8 *data = memalign(32, 0x100);
|
||||
if (ISFS_Read(fh, data, 0x100) < 0) {
|
||||
ISFS_Close(fh);
|
||||
free(data);
|
||||
return -3;
|
||||
}
|
||||
|
||||
|
||||
// Prepare the strings that will contain the name of the title
|
||||
char name1[0x41] __attribute__ ((aligned (32)));
|
||||
char name2[0x41] __attribute__ ((aligned (32)));
|
||||
name1[0x40] = 0;
|
||||
name2[0x40] = 0;
|
||||
|
||||
__convertWiiString(name1, data + 0x00, 0x40);
|
||||
__convertWiiString(name2, data + 0x40, 0x40);
|
||||
free(data);
|
||||
|
||||
// Assemble name
|
||||
sprintf(name, "%s", name1);
|
||||
if (strlen(name2) > 1)
|
||||
sprintf(name, "%s (%s)", name, name2);
|
||||
|
||||
// Close the banner.bin
|
||||
ISFS_Close(fh);
|
||||
|
||||
// Job well done
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
s32 getName00(char* name, u64 id, int lang) {
|
||||
/*
|
||||
languages
|
||||
0jap
|
||||
2eng
|
||||
4german
|
||||
6french
|
||||
8spanish
|
||||
10italian
|
||||
12dutch
|
||||
*/
|
||||
// Create a string containing the absolute filename
|
||||
char file[256] __attribute__ ((aligned (32)));
|
||||
sprintf(file, "/title/%08x/%08x/content/00000000.app", (u32)(id >> 32), (u32)id);
|
||||
Identify_SU();
|
||||
s32 fh = ISFS_Open(file, ISFS_OPEN_READ);
|
||||
|
||||
|
||||
|
||||
// If the title does not have 00000000.app bail out
|
||||
if (fh == -106)
|
||||
return fh;
|
||||
|
||||
// In case there is some problem with the permission
|
||||
if (fh == -102) {
|
||||
// Identify as super user
|
||||
Identify_SU();
|
||||
fh = ISFS_Open(file, ISFS_OPEN_READ);
|
||||
} else if (fh < 0)
|
||||
return fh;
|
||||
|
||||
// Jump to start of the name entries
|
||||
ISFS_Seek(fh, 0x9C, 0);
|
||||
|
||||
// Read a chunk of 0x22 * 0x2B bytes from 00000000.app
|
||||
u8 *data = memalign(32, 2048);
|
||||
s32 r = ISFS_Read(fh, data, 0x22 * 0x2B);
|
||||
//printf("%s %d\n", file, r);wait_anyKey();
|
||||
if (r < 0) {
|
||||
ISFS_Close(fh);
|
||||
free(data);
|
||||
return -4;
|
||||
}
|
||||
|
||||
// Take the entries apart
|
||||
char str[0x22][0x2B];
|
||||
u8 i = 0;
|
||||
// Convert the entries to ASCII strings
|
||||
for (; i < 0x22; i++)
|
||||
__convertWiiString(str[i], data + (i * 0x2A), 0x2A);
|
||||
|
||||
// Clean up
|
||||
ISFS_Close(fh);
|
||||
free(data);
|
||||
|
||||
// Assemble name
|
||||
if (strlen(str[lang]) > 1) {
|
||||
sprintf(name, "%s", str[lang]);
|
||||
if (strlen(str[lang+1]) > 1)
|
||||
sprintf(name, "%s (%s)", name, str[lang+1]);
|
||||
} else {
|
||||
sprintf(name, "%s", str[2]);
|
||||
if (strlen(str[3]) > 1)
|
||||
sprintf(name, "%s (%s)", name, str[3]);
|
||||
}
|
||||
// Job well done
|
||||
return 2;
|
||||
}
|
||||
|
||||
|
||||
s32 printContent(u64 tid) {
|
||||
char dir[256] __attribute__ ((aligned (32)));
|
||||
sprintf(dir, "/title/%08x/%08x/content", (u32)(tid >> 32), (u32)tid);
|
||||
|
||||
u32 num = 64;
|
||||
|
||||
static char list[8000] __attribute__((aligned(32)));
|
||||
|
||||
ISFS_ReadDir(dir, list, &num);
|
||||
|
||||
char *ptr = list;
|
||||
u8 br = 0;
|
||||
for (; strlen(ptr) > 0; ptr += strlen(ptr) + 1) {
|
||||
printf(" %-12.12s", ptr);
|
||||
br++;
|
||||
if (br == 4) {
|
||||
br = 0;
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
if (br != 0)
|
||||
printf("\n");
|
||||
|
||||
return num;
|
||||
}
|
||||
|
||||
|
||||
char *titleText(u32 kind, u32 title) {
|
||||
static char text[10];
|
||||
|
||||
if (kind == 1) {
|
||||
// If we're dealing with System Titles, use custom names
|
||||
switch (title) {
|
||||
case 1:
|
||||
strcpy(text, "BOOT2");
|
||||
break;
|
||||
case 2:
|
||||
strcpy(text, "SYSMENU");
|
||||
break;
|
||||
case 0x100:
|
||||
strcpy(text, "BC");
|
||||
break;
|
||||
case 0x101:
|
||||
strcpy(text, "MIOS");
|
||||
break;
|
||||
default:
|
||||
sprintf(text, "IOS%u", title);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
// Otherwise, just convert the title to ASCII
|
||||
int i =32, j = 0;
|
||||
do {
|
||||
u8 temp;
|
||||
i -= 8;
|
||||
temp = (title >> i) & 0x000000FF;
|
||||
if (temp < 32 || temp > 126)
|
||||
text[j] = '.';
|
||||
else
|
||||
text[j] = temp;
|
||||
j++;
|
||||
} while (i > 0);
|
||||
text[4] = 0;
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
//giantpune's magic function to check for game saves
|
||||
//give a ID4 of a game and returns 1 if the game has save data, 0 if not, or <0 for errors
|
||||
int CheckForSave(const char *gameID)
|
||||
{
|
||||
|
||||
if (ISFS_Initialize()<0)
|
||||
return -1;
|
||||
|
||||
if (!ISFS_Mount())
|
||||
return -2;
|
||||
|
||||
struct savegame *saveList = NULL;
|
||||
u32 saveCnt;
|
||||
u32 cnt;
|
||||
|
||||
|
||||
if (__Menu_RetrieveList(&saveList, &saveCnt)<0)
|
||||
return -3;
|
||||
|
||||
for (cnt=0;cnt<saveCnt;cnt++)
|
||||
{
|
||||
struct savegame *save = &saveList[cnt];
|
||||
if (strcmp(gameID,titleText((u32)(save->tid >> 32),(u32)(save->tid & 0xFFFFFFFF)))==0) {
|
||||
free(saveList);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
free(saveList);
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------------------
|
||||
from any title deleter
|
||||
titles.c -- functions for grabbing all titles of a certain type
|
||||
|
||||
Copyright (C) 2008 tona
|
||||
-------------------------------------------------------------*/
|
||||
|
||||
u32 __titles_init = 0;
|
||||
u32 __num_titles;
|
||||
static u64 __title_list[MAX_TITLES] ATTRIBUTE_ALIGN(32);
|
||||
|
||||
s32 __getTitles() {
|
||||
s32 ret;
|
||||
ret = ES_GetNumTitles(&__num_titles);
|
||||
if (ret <0)
|
||||
return ret;
|
||||
if (__num_titles > MAX_TITLES)
|
||||
return -1;
|
||||
ret = ES_GetTitles(__title_list, __num_titles);
|
||||
if (ret <0)
|
||||
return ret;
|
||||
__titles_init = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
s32 getTitles_TypeCount(u32 type, u32 *count) {
|
||||
s32 ret = 0;
|
||||
u32 type_count;
|
||||
if (!__titles_init)
|
||||
ret = __getTitles();
|
||||
if (ret <0)
|
||||
return ret;
|
||||
int i;
|
||||
type_count = 0;
|
||||
for (i=0; i < __num_titles; i++) {
|
||||
u32 upper, lower;
|
||||
upper = __title_list[i] >> 32;
|
||||
lower = __title_list[i] & 0xFFFFFFFF;
|
||||
if ((upper == type)&&
|
||||
((lower !=0x48414741)&&//this filters out haga,haaa, hafa. dupe factory channels that don't load
|
||||
(lower !=0x48414141)&&//since we dont care about apps that dont load for what we are doing
|
||||
(lower !=0x48414641)))
|
||||
type_count++;
|
||||
}
|
||||
*count = type_count;
|
||||
return ret;
|
||||
}
|
||||
|
||||
s32 getTitles_Type(u32 type, u32 *titles, u32 count) {
|
||||
s32 ret = 0;
|
||||
u32 type_count;
|
||||
if (!__titles_init)
|
||||
ret = __getTitles();
|
||||
if (ret <0)
|
||||
return ret;
|
||||
int i;
|
||||
type_count = 0;
|
||||
for (i=0; type_count < count && i < __num_titles; i++) {
|
||||
u32 upper, lower;
|
||||
upper = __title_list[i] >> 32;
|
||||
lower = __title_list[i] & 0xFFFFFFFF;
|
||||
if ((upper == type)&&
|
||||
((lower !=0x48414741)&&
|
||||
(lower !=0x48414141)&&
|
||||
(lower !=0x48414641))) {
|
||||
titles[type_count]=lower;
|
||||
type_count++;
|
||||
}
|
||||
}
|
||||
if (type_count < count)
|
||||
return -2;
|
||||
__titles_init = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//this function expects initialize be called before it is called
|
||||
// if not, it will fail miserably and catch the wii on fire and kick you in the nuts
|
||||
#define TITLE_ID(x,y) (((u64)(x) << 32) | (y))
|
||||
s32 WII_BootHBC()
|
||||
{
|
||||
u32 tmdsize;
|
||||
u64 tid = 0;
|
||||
u64 *list;
|
||||
u32 titlecount;
|
||||
s32 ret;
|
||||
u32 i;
|
||||
|
||||
ret = ES_GetNumTitles(&titlecount);
|
||||
if(ret < 0)
|
||||
return WII_EINTERNAL;
|
||||
|
||||
list = memalign(32, titlecount * sizeof(u64) + 32);
|
||||
|
||||
ret = ES_GetTitles(list, titlecount);
|
||||
if(ret < 0) {
|
||||
free(list);
|
||||
return WII_EINTERNAL;
|
||||
}
|
||||
|
||||
for(i=0; i<titlecount; i++) {
|
||||
if (list[i]==TITLE_ID(0x00010001,0x4A4F4449)
|
||||
|| list[i]==TITLE_ID(0x00010001,0x48415858))
|
||||
{
|
||||
tid = list[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
free(list);
|
||||
|
||||
if(!tid)
|
||||
return WII_EINSTALL;
|
||||
|
||||
if(ES_GetStoredTMDSize(tid, &tmdsize) < 0)
|
||||
return WII_EINSTALL;
|
||||
|
||||
return WII_LaunchTitle(tid);
|
||||
}
|
||||
|
||||
tmd* getTMD(u64 tid){
|
||||
static char filepath[256] ATTRIBUTE_ALIGN(32);
|
||||
static u8 tmd_buf[MAX_SIGNED_TMD_SIZE] ATTRIBUTE_ALIGN(32);
|
||||
signed_blob *s_tmd = (signed_blob *)tmd_buf;
|
||||
u32 tmd_size;
|
||||
|
||||
if (ES_GetDataDir(tid, filepath) < 0 )
|
||||
return NULL;
|
||||
|
||||
if (ES_GetStoredTMDSize(tid, &tmd_size) < 0)
|
||||
return NULL;
|
||||
|
||||
|
||||
if (ES_GetStoredTMD(tid, s_tmd, tmd_size) < 0)
|
||||
return NULL;
|
||||
|
||||
tmd *t = SIGNATURE_PAYLOAD(s_tmd);
|
||||
|
||||
return t;
|
||||
|
||||
}
|
||||
|
||||
//some pune magic to make sure we don't try to load a stubbed IOS for those idiots that don't know what theyre doing
|
||||
s32 getIOSrev(u64 req)
|
||||
{
|
||||
gprintf("\n\tgetIOSrev(%016llx)",req);
|
||||
u32 tmdsize;
|
||||
u64 tid = 0;
|
||||
u64 *list;
|
||||
u32 titlecount;
|
||||
s32 ret;
|
||||
u32 i;
|
||||
|
||||
ret = ES_GetNumTitles(&titlecount);
|
||||
if(ret < 0)
|
||||
{
|
||||
ret = WII_EINTERNAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
list = memalign(32, titlecount * sizeof(u64) + 32);
|
||||
|
||||
ret = ES_GetTitles(list, titlecount);
|
||||
if(ret < 0) {
|
||||
free(list);
|
||||
ret = WII_EINTERNAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
for(i=0; i<titlecount; i++) {
|
||||
if (list[i]==req)
|
||||
{
|
||||
tid = list[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
free(list);
|
||||
|
||||
if(!tid)
|
||||
{
|
||||
ret = WII_EINSTALL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if(ES_GetStoredTMDSize(tid, &tmdsize) < 0)
|
||||
{
|
||||
ret = WII_EINSTALL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
tmd *tmd = getTMD(tid);
|
||||
|
||||
if(tmd->title_version<255)
|
||||
{
|
||||
ret = tmd->title_version;
|
||||
}
|
||||
|
||||
out:
|
||||
gprintf(" = %d",ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -1,77 +0,0 @@
|
||||
/*-------------------------------------------------------------
|
||||
from any title deleter and wad manager 1.4
|
||||
title.h --
|
||||
|
||||
Copyright (C) 2008 tona and/or waninkoko
|
||||
-------------------------------------------------------------*/
|
||||
#include <gccore.h>
|
||||
#include <ogcsys.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <malloc.h>
|
||||
#include "libfat/fat.h"
|
||||
|
||||
// Turn upper and lower into a full title ID
|
||||
#define TITLE_ID(x,y) (((u64)(x) << 32) | (y))
|
||||
// Get upper or lower half of a title ID
|
||||
#define TITLE_UPPER(x) ((u32)((x) >> 32))
|
||||
// Turn upper and lower into a full title ID
|
||||
#define TITLE_LOWER(x) ((u32)(x))
|
||||
|
||||
#define MAX_TITLES 100
|
||||
|
||||
#ifndef _TITLE_H_
|
||||
#define _TITLE_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
/* Constants */
|
||||
#define BLOCK_SIZE 1024
|
||||
|
||||
/* Prototypes */
|
||||
s32 Title_GetList(u64 **, u32 *);
|
||||
s32 Title_GetTicketViews(u64, tikview **, u32 *);
|
||||
s32 Title_GetTMD(u64, signed_blob **, u32 *);
|
||||
s32 Title_GetVersion(u64, u16 *);
|
||||
s32 Title_GetSysVersion(u64, u64 *);
|
||||
s32 Title_GetSize(u64, u32 *);
|
||||
s32 Title_GetIOSVersions(u8 **, u32 *);
|
||||
|
||||
// Get the name of a title from its banner.bin in NAND
|
||||
s32 getNameBN(char *name, u64 id);
|
||||
|
||||
// Get the name of a title from its 00000000.app in NAND
|
||||
s32 getName00(char *name, u64 id, int lang = 2);
|
||||
|
||||
// Get string representation of lower title id
|
||||
char *titleText(u32 kind, u32 title);
|
||||
|
||||
// Converts a 16 bit Wii string to a printable 8 bit string
|
||||
s32 __convertWiiString(char *str, u8 *data, u32 cnt);
|
||||
|
||||
// Get the number of titles on the Wii of a given type
|
||||
s32 getTitles_TypeCount(u32 type, u32 *count);
|
||||
|
||||
// Get the list of titles of this type
|
||||
s32 getTitles_Type(u32 type, u32 *titles, u32 count);
|
||||
|
||||
//returns a name for a title
|
||||
char *__getTitleName(u64 titleid, int language);
|
||||
|
||||
s32 Uninstall_FromTitle(const u64 tid);
|
||||
|
||||
//check for a game save present on nand based on game ID
|
||||
int CheckForSave(const char *gameID);
|
||||
|
||||
//boot HBC in either HAXX or JODI locations
|
||||
s32 WII_BootHBC();
|
||||
|
||||
//get the rev of a ISO and such without having to load it
|
||||
s32 getIOSrev(u64 req);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
@ -4,11 +4,12 @@
|
||||
#include <ogcsys.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "title.h"
|
||||
#include "utils.h"
|
||||
#include "video.h"
|
||||
#include "wad.h"
|
||||
|
||||
#include "nandtitle.h"
|
||||
|
||||
|
||||
|
||||
#include "prompts/PromptWindows.h"
|
||||
@ -347,9 +348,9 @@ s32 Wad_Install(FILE *fp)
|
||||
snprintf(imgPath, sizeof(imgPath), "%s%d...",tr(">> Installing content #"),content->cid);
|
||||
msg4Txt.SetText(imgPath);
|
||||
// Install content data
|
||||
while (idx < len) {
|
||||
|
||||
//VIDEO_WaitVSync ();
|
||||
while (idx < len) {
|
||||
|
||||
//VIDEO_WaitVSync ();
|
||||
|
||||
u32 size;
|
||||
|
||||
@ -569,7 +570,7 @@ s32 Wad_Uninstall(FILE *fp)
|
||||
msg2Txt.SetText(tr(">> Deleting tickets..."));
|
||||
|
||||
// Get ticket views
|
||||
ret = Title_GetTicketViews(tid, &viewData, &viewCnt);
|
||||
ret = titles.GetTicketViews(tid, &viewData, &viewCnt);
|
||||
if (ret < 0){
|
||||
char errTxt[50];
|
||||
sprintf(errTxt,"%sret = %d",tr(">> Deleting tickets...ERROR! "),ret);
|
||||
|
@ -2,6 +2,9 @@
|
||||
#define _WAD_H_
|
||||
|
||||
/* Prototypes */
|
||||
|
||||
#define BLOCK_SIZE 1024
|
||||
|
||||
s32 Wad_Install(FILE *);
|
||||
s32 Wad_Uninstall(FILE *);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user