mirror of
https://github.com/wiidev/usbloadergx.git
synced 2024-11-25 12:46: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">
|
<app version="1">
|
||||||
<name> USB Loader GX</name>
|
<name> USB Loader GX</name>
|
||||||
<coder>USB Loader GX Team</coder>
|
<coder>USB Loader GX Team</coder>
|
||||||
<version>1.0 r949</version>
|
<version>1.0 r950</version>
|
||||||
<release_date>201009180855</release_date>
|
<release_date>201009182245</release_date>
|
||||||
<short_description>Loads games from USB-devices</short_description>
|
<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.
|
<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.
|
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)))
|
||||||
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.S)))
|
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.S)))
|
||||||
ELFFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.elf)))
|
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)))
|
TTFFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.ttf)))
|
||||||
PNGFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.png)))
|
PNGFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.png)))
|
||||||
OGGFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.ogg)))
|
OGGFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.ogg)))
|
||||||
@ -112,7 +112,7 @@ export OFILES := $(addsuffix .o,$(BINFILES)) \
|
|||||||
$(sFILES:.s=.o) $(SFILES:.S=.o) \
|
$(sFILES:.s=.o) $(SFILES:.S=.o) \
|
||||||
$(TTFFILES:.ttf=.ttf.o) $(PNGFILES:.png=.png.o) $(addsuffix .o,$(DOLFILES))\
|
$(TTFFILES:.ttf=.ttf.o) $(PNGFILES:.png=.png.o) $(addsuffix .o,$(DOLFILES))\
|
||||||
$(OGGFILES:.ogg=.ogg.o) $(PCMFILES:.pcm=.pcm.o) $(MP3FILES:.mp3=.mp3.o) \
|
$(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
|
# build a list of include paths
|
||||||
|
@ -33,12 +33,13 @@ bool InitGecko()
|
|||||||
if (geckoattached)
|
if (geckoattached)
|
||||||
{
|
{
|
||||||
usb_flush(EXI_CHANNEL_1);
|
usb_flush(EXI_CHANNEL_1);
|
||||||
|
CON_EnableGecko( 1, true );
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else return false;
|
else return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static char ascii(char s)
|
char ascii(char s)
|
||||||
{
|
{
|
||||||
if(s < 0x20)
|
if(s < 0x20)
|
||||||
return '.';
|
return '.';
|
||||||
|
@ -7,6 +7,8 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
char ascii(char s);
|
||||||
|
|
||||||
#ifndef NO_DEBUG
|
#ifndef NO_DEBUG
|
||||||
//use this just like printf();
|
//use this just like printf();
|
||||||
void gprintf(const char *str, ...);
|
void gprintf(const char *str, ...);
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
#if 0
|
||||||
#include <gccore.h>
|
#include <gccore.h>
|
||||||
#include <ogcsys.h>
|
#include <ogcsys.h>
|
||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
@ -102,6 +103,10 @@ int BootHomebrew()
|
|||||||
if (!entry)
|
if (!entry)
|
||||||
Sys_BackToLoader();
|
Sys_BackToLoader();
|
||||||
|
|
||||||
|
VIDEO_SetBlack(true);
|
||||||
|
VIDEO_Flush();
|
||||||
|
VIDEO_WaitVSync();
|
||||||
|
|
||||||
SYS_ResetSystem(SYS_SHUTDOWN, 0, 0);
|
SYS_ResetSystem(SYS_SHUTDOWN, 0, 0);
|
||||||
_CPU_ISR_Disable (cpu_isr);
|
_CPU_ISR_Disable (cpu_isr);
|
||||||
__exception_closeall();
|
__exception_closeall();
|
||||||
@ -129,3 +134,218 @@ int BootHomebrew(const char * filepath)
|
|||||||
|
|
||||||
return BootHomebrew();
|
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_
|
#ifndef _BOOTHOMEBREW_H_
|
||||||
#define _BOOTHOMEBREW_H_
|
#define _BOOTHOMEBREW_H_
|
||||||
|
|
||||||
int BootHomebrew();
|
//int BootHomebrew();
|
||||||
int BootHomebrew(const char * filepath);
|
int BootHomebrewFromMem();
|
||||||
|
int BootHomebrew( char * filepath);
|
||||||
int CopyHomebrewMemory(u8 *temp, u32 pos, u32 len);
|
int CopyHomebrewMemory(u8 *temp, u32 pos, u32 len);
|
||||||
void AddBootArgument(const char * arg);
|
void AddBootArgument(const char * arg);
|
||||||
void FreeHomebrewBuffer();
|
void FreeHomebrewBuffer();
|
||||||
int LoadHomebrew(const char * filepath);
|
int LoadHomebrew(const char * filepath);
|
||||||
|
int AllocHomebrewMemory( u32 filesize );
|
||||||
|
extern void *innetbuffer;
|
||||||
|
extern u32 homebrewsize;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -793,8 +793,14 @@ int MenuHomebrewBrowse() {
|
|||||||
|
|
||||||
int choice = WindowPrompt(filesizetxt, temp, tr("OK"), tr("Cancel"));
|
int choice = WindowPrompt(filesizetxt, temp, tr("OK"), tr("Cancel"));
|
||||||
|
|
||||||
if (choice == 1)
|
if (choice == 1) {
|
||||||
{
|
|
||||||
|
int res = AllocHomebrewMemory(infilesize);
|
||||||
|
|
||||||
|
if (res < 0) {
|
||||||
|
CloseConnection();
|
||||||
|
WindowPrompt(tr("Not enough free memory."), 0, tr("OK"));
|
||||||
|
} else {
|
||||||
u32 read = 0;
|
u32 read = 0;
|
||||||
u8 *temp = NULL;
|
u8 *temp = NULL;
|
||||||
int len = NETWORKBLOCKSIZE;
|
int len = NETWORKBLOCKSIZE;
|
||||||
@ -872,7 +878,7 @@ int MenuHomebrewBrowse() {
|
|||||||
uLongf f = uncfilesize;
|
uLongf f = uncfilesize;
|
||||||
error = uncompress(unc, &f, temp, infilesize) != Z_OK;
|
error = uncompress(unc, &f, temp, infilesize) != Z_OK;
|
||||||
uncfilesize = f;
|
uncfilesize = f;
|
||||||
infilesize = f;
|
homebrewsize = uncfilesize;
|
||||||
|
|
||||||
free(temp);
|
free(temp);
|
||||||
temp = unc;
|
temp = unc;
|
||||||
@ -880,8 +886,8 @@ int MenuHomebrewBrowse() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!error && strstr(filename,".zip") == NULL) {
|
if (!error && strstr(filename,".zip") == NULL) {
|
||||||
CopyHomebrewMemory(temp, 0, infilesize);
|
innetbuffer = temp;
|
||||||
free(temp);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -892,8 +898,7 @@ int MenuHomebrewBrowse() {
|
|||||||
FreeHomebrewBuffer();
|
FreeHomebrewBuffer();
|
||||||
} else {
|
} else {
|
||||||
if (strstr(filename,".dol") || strstr(filename,".DOL")
|
if (strstr(filename,".dol") || strstr(filename,".DOL")
|
||||||
|| strstr(filename,".elf") || strstr(filename,".ELF"))
|
|| strstr(filename,".elf") || strstr(filename,".ELF")) {
|
||||||
{
|
|
||||||
boothomebrew = 2;
|
boothomebrew = 2;
|
||||||
AddBootArgument( filename );
|
AddBootArgument( filename );
|
||||||
menu = MENU_EXIT;
|
menu = MENU_EXIT;
|
||||||
@ -908,6 +913,7 @@ int MenuHomebrewBrowse() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
CloseConnection();
|
CloseConnection();
|
||||||
ResumeNetworkWait();
|
ResumeNetworkWait();
|
||||||
}
|
}
|
||||||
@ -915,8 +921,7 @@ int MenuHomebrewBrowse() {
|
|||||||
else if (channelBtn.GetState() == STATE_CLICKED) {
|
else if (channelBtn.GetState() == STATE_CLICKED) {
|
||||||
w.SetState(STATE_DISABLED);
|
w.SetState(STATE_DISABLED);
|
||||||
//10001 are the channels that are installed as channels, not including shop channel/mii channel etc
|
//10001 are the channels that are installed as channels, not including shop channel/mii channel etc
|
||||||
u32 num = 0x00010001;
|
TitleBrowser();
|
||||||
TitleBrowser(num);
|
|
||||||
//if they didn't boot a channel reset this window
|
//if they didn't boot a channel reset this window
|
||||||
w.SetState(STATE_DEFAULT);
|
w.SetState(STATE_DEFAULT);
|
||||||
channelBtn.ResetState();
|
channelBtn.ResetState();
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
#include "gui.h"
|
#include "gui.h"
|
||||||
#include "../wpad.h"
|
#include "../wpad.h"
|
||||||
#include "../main.h"
|
#include "../main.h"
|
||||||
|
#include "../gecko.h"
|
||||||
#include "../settings/cfg.h"
|
#include "../settings/cfg.h"
|
||||||
#include "gui_customoptionbrowser.h"
|
#include "gui_customoptionbrowser.h"
|
||||||
|
|
||||||
@ -95,6 +96,7 @@ void customOptionList::SetName(int i, const char *format, ...)
|
|||||||
va_end(va);
|
va_end(va);
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
|
//gprintf("customOptionList::SetName( %d, %s )\n", i, name[i] );
|
||||||
}
|
}
|
||||||
void customOptionList::SetValue(int i, const char *format, ...)
|
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*/)
|
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_
|
#ifndef _LSTUB_H_
|
||||||
#define _LSTUB_H_
|
#define _LSTUB_H_
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//to set the "return to" stub for a certain ID
|
//to set the "return to" stub for a certain ID
|
||||||
//!reqID is the Requested ID to return to
|
//!reqID is the Requested ID to return to
|
||||||
//!returns WII_EINTERNAL if it cant get the list of installed titles with ES functions
|
//!returns WII_EINTERNAL if it cant get the list of installed titles with ES functions
|
||||||
@ -31,8 +27,4 @@ u64 getStubDest();
|
|||||||
u8 hbcStubAvailable();
|
u8 hbcStubAvailable();
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -47,17 +47,19 @@ extern "C"
|
|||||||
#include "fat.h"
|
#include "fat.h"
|
||||||
#include "gecko.h"
|
#include "gecko.h"
|
||||||
#include "svnrev.h"
|
#include "svnrev.h"
|
||||||
#include "wad/title.h"
|
|
||||||
#include "usbloader/partition_usbloader.h"
|
#include "usbloader/partition_usbloader.h"
|
||||||
#include "usbloader/usbstorage2.h"
|
#include "usbloader/usbstorage2.h"
|
||||||
#include "memory/mem2.h"
|
#include "memory/mem2.h"
|
||||||
#include "lstub.h"
|
#include "lstub.h"
|
||||||
#include "usbloader/usbstorage2.h"
|
#include "usbloader/usbstorage2.h"
|
||||||
|
#include "wad/nandtitle.h"
|
||||||
|
|
||||||
extern bool geckoinit;
|
extern bool geckoinit;
|
||||||
extern bool textVideoInit;
|
extern bool textVideoInit;
|
||||||
extern char headlessID[8];
|
extern char headlessID[8];
|
||||||
|
|
||||||
|
NandTitle titles;
|
||||||
|
|
||||||
/* Constants */
|
/* Constants */
|
||||||
#define CONSOLE_XCOORD 260
|
#define CONSOLE_XCOORD 260
|
||||||
#define CONSOLE_YCOORD 115
|
#define CONSOLE_YCOORD 115
|
||||||
@ -75,7 +77,9 @@ int main(int argc, char *argv[])
|
|||||||
geckoinit = InitGecko();
|
geckoinit = InitGecko();
|
||||||
__exception_setreload(20);
|
__exception_setreload(20);
|
||||||
|
|
||||||
printf("\n\tStarting up");
|
printf("\tStarting up\n");
|
||||||
|
titles.Get();
|
||||||
|
titles.Exists( 0x100014e414c45ULL );
|
||||||
|
|
||||||
bool bootDevice_found=false;
|
bool bootDevice_found=false;
|
||||||
if (argc >= 1)
|
if (argc >= 1)
|
||||||
@ -89,14 +93,14 @@ int main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Let's use libogc sd/usb for config loading
|
//Let's use libogc sd/usb for config loading
|
||||||
printf("\n\tInitialize sd card");
|
printf("\tInitialize sd card\n");
|
||||||
SDCard_Init();
|
SDCard_Init();
|
||||||
printf("\n\tInitialize usb device");
|
printf("\tInitialize usb device\n");
|
||||||
USBDevice_Init();
|
USBDevice_Init();
|
||||||
|
|
||||||
if (!bootDevice_found)
|
if (!bootDevice_found)
|
||||||
{
|
{
|
||||||
printf("\n\tSearch for configuration file");
|
printf("\tSearch for configuration file\n");
|
||||||
//try USB
|
//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
|
//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"))
|
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"))
|
|| checkfile((char*) "USB:/apps/usbloader_gx/boot.dol"))
|
||||||
strcpy(bootDevice, "USB:");
|
strcpy(bootDevice, "USB:");
|
||||||
|
|
||||||
printf("\n\tConfiguration file is on %s", bootDevice);
|
printf("\tConfiguration file is on %s\n", bootDevice);
|
||||||
}
|
}
|
||||||
|
|
||||||
gettextCleanUp();
|
gettextCleanUp();
|
||||||
printf("\n\tLoading configuration...");
|
printf("\tLoading configuration...");
|
||||||
CFG_Load();
|
CFG_Load();
|
||||||
printf("done");
|
printf("done\n");
|
||||||
|
|
||||||
SDCard_deInit();// unmount SD for reloading IOS
|
SDCard_deInit();// unmount SD for reloading IOS
|
||||||
USBDevice_deInit();// unmount USB 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
|
// This part is added, because we need a identify patched ios
|
||||||
//! pune please replace this with your magic patch functions - Dimok
|
//! pune please replace this with your magic patch functions - Dimok
|
||||||
if (IOS_ReloadIOSsafe(236) < 0)
|
//if (IOS_ReloadIOSsafe(236) < 0)
|
||||||
IOS_ReloadIOSsafe(36);
|
// IOS_ReloadIOSsafe(36);
|
||||||
|
|
||||||
printf("\n\tCheck for an existing cIOS");
|
printf("\tCheck for an existing cIOS\n");
|
||||||
CheckForCIOS();
|
CheckForCIOS();
|
||||||
|
|
||||||
// Let's load the cIOS now
|
// Let's load the cIOS now
|
||||||
|
@ -23,7 +23,6 @@
|
|||||||
#include "themes/Theme_Downloader.h"
|
#include "themes/Theme_Downloader.h"
|
||||||
#include "usbloader/disc.h"
|
#include "usbloader/disc.h"
|
||||||
#include "usbloader/GameList.h"
|
#include "usbloader/GameList.h"
|
||||||
#include "wad/title.h"
|
|
||||||
#include "xml/xml.h"
|
#include "xml/xml.h"
|
||||||
#include "audio.h"
|
#include "audio.h"
|
||||||
#include "gecko.h"
|
#include "gecko.h"
|
||||||
@ -34,6 +33,7 @@
|
|||||||
#include "patches/fst.h"
|
#include "patches/fst.h"
|
||||||
#include "usbloader/frag.h"
|
#include "usbloader/frag.h"
|
||||||
#include "usbloader/wbfs.h"
|
#include "usbloader/wbfs.h"
|
||||||
|
#include "wad/nandtitle.h"
|
||||||
|
|
||||||
/*** Variables that are also used extern ***/
|
/*** Variables that are also used extern ***/
|
||||||
GuiWindow * mainWindow = NULL;
|
GuiWindow * mainWindow = NULL;
|
||||||
@ -322,7 +322,7 @@ int MainMenu(int menu) {
|
|||||||
|
|
||||||
|
|
||||||
// MemInfoPrompt();
|
// MemInfoPrompt();
|
||||||
gprintf("\nExiting main GUI. mountMethod = %d",mountMethod);
|
gprintf("Exiting main GUI. mountMethod = %d\n",mountMethod);
|
||||||
|
|
||||||
CloseXMLDatabase();
|
CloseXMLDatabase();
|
||||||
NewTitles::DestroyInstance();
|
NewTitles::DestroyInstance();
|
||||||
@ -375,15 +375,16 @@ int MainMenu(int menu) {
|
|||||||
}
|
}
|
||||||
else if (boothomebrew == 2) {
|
else if (boothomebrew == 2) {
|
||||||
gprintf("\nBootHomebrew from Menu");
|
gprintf("\nBootHomebrew from Menu");
|
||||||
BootHomebrew();
|
//BootHomebrew();
|
||||||
|
BootHomebrewFromMem();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
gprintf("\n\tSettings.partition:%d",Settings.partition);
|
gprintf("\tSettings.partition: %d\n",Settings.partition);
|
||||||
struct discHdr *header = NULL;
|
struct discHdr *header = NULL;
|
||||||
//if the GUI was "skipped" to boot a game from main(argv[1])
|
//if the GUI was "skipped" to boot a game from main(argv[1])
|
||||||
if (strcmp(headlessID,"")!=0)
|
if (strcmp(headlessID,"")!=0)
|
||||||
{
|
{
|
||||||
gprintf("\n\tHeadless mode (%s)",headlessID);
|
gprintf("\tHeadless mode (%s)\n",headlessID);
|
||||||
gameList.LoadUnfiltered();
|
gameList.LoadUnfiltered();
|
||||||
if (!gameList.size())
|
if (!gameList.size())
|
||||||
{
|
{
|
||||||
@ -399,13 +400,13 @@ int MainMenu(int menu) {
|
|||||||
if (strcmp(tmp,headlessID)==0)
|
if (strcmp(tmp,headlessID)==0)
|
||||||
{
|
{
|
||||||
gameSelected = i;
|
gameSelected = i;
|
||||||
gprintf(" found (%d)",i);
|
gprintf(" found (%d)\n",i);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
//if the game was not found
|
//if the game was not found
|
||||||
if (i==gameList.GameCount()-1)
|
if (i==gameList.GameCount()-1)
|
||||||
{
|
{
|
||||||
gprintf(" not found (%d IDs checked)",i);
|
gprintf(" not found (%d IDs checked)\n",i);
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -483,20 +484,20 @@ int MainMenu(int menu) {
|
|||||||
}
|
}
|
||||||
if (!mountMethod)
|
if (!mountMethod)
|
||||||
{
|
{
|
||||||
gprintf("\nLoading fragment list...");
|
gprintf("Loading fragment list...");
|
||||||
ret = get_frag_list(header->id);
|
ret = get_frag_list(header->id);
|
||||||
gprintf("%d\n", ret);
|
gprintf("%d\n", ret);
|
||||||
|
|
||||||
gprintf("\nSetting fragment list...");
|
gprintf("Setting fragment list...");
|
||||||
ret = set_frag_list(header->id);
|
ret = set_frag_list(header->id);
|
||||||
gprintf("%d\n", ret);
|
gprintf("%d\n", ret);
|
||||||
|
|
||||||
ret = Disc_SetUSB(header->id);
|
ret = Disc_SetUSB(header->id);
|
||||||
if (ret < 0) Sys_BackToLoader();
|
if (ret < 0) Sys_BackToLoader();
|
||||||
gprintf("\n\tUSB set to game");
|
gprintf("\tUSB set to game\n");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
gprintf("\n\tUSB not set, loading DVD");
|
gprintf("\tUSB not set, loading DVD\n");
|
||||||
}
|
}
|
||||||
ret = Disc_Open();
|
ret = Disc_Open();
|
||||||
|
|
||||||
@ -505,7 +506,7 @@ int MainMenu(int menu) {
|
|||||||
if(dvdheader)
|
if(dvdheader)
|
||||||
delete dvdheader;
|
delete dvdheader;
|
||||||
|
|
||||||
gprintf("\nLoading BCA data...");
|
gprintf("Loading BCA data...");
|
||||||
ret = do_bca_code(header->id);
|
ret = do_bca_code(header->id);
|
||||||
gprintf("%d\n", ret);
|
gprintf("%d\n", ret);
|
||||||
|
|
||||||
@ -640,13 +641,14 @@ int MainMenu(int menu) {
|
|||||||
vipatch = 0;
|
vipatch = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
gprintf("\n\tDisc_wiiBoot");
|
gprintf("\tDisc_wiiBoot\n");
|
||||||
|
|
||||||
ret = Disc_WiiBoot(videoselected, cheat, vipatch, countrystrings, errorfixer002, alternatedol, alternatedoloffset);
|
ret = Disc_WiiBoot(videoselected, cheat, vipatch, countrystrings, errorfixer002, alternatedol, alternatedoloffset);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
Sys_LoadMenu();
|
Sys_LoadMenu();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//should never get here
|
||||||
printf("Returning entry point: 0x%0x\n", ret);
|
printf("Returning entry point: 0x%0x\n", ret);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -17,7 +17,6 @@
|
|||||||
#include "sys.h"
|
#include "sys.h"
|
||||||
#include "settings/cfg.h"
|
#include "settings/cfg.h"
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
#include "../wad/title.h"
|
|
||||||
#include "../gecko.h"
|
#include "../gecko.h"
|
||||||
#include "../patches/dvd_broadway.h"
|
#include "../patches/dvd_broadway.h"
|
||||||
|
|
||||||
|
@ -34,7 +34,6 @@
|
|||||||
#include "svnrev.h"
|
#include "svnrev.h"
|
||||||
#include "audio.h"
|
#include "audio.h"
|
||||||
#include "xml/xml.h"
|
#include "xml/xml.h"
|
||||||
#include "wad/title.h"
|
|
||||||
#include "language/UpdateLanguage.h"
|
#include "language/UpdateLanguage.h"
|
||||||
#include "gecko.h"
|
#include "gecko.h"
|
||||||
#include "lstub.h"
|
#include "lstub.h"
|
||||||
|
@ -23,14 +23,10 @@
|
|||||||
#include "audio.h"
|
#include "audio.h"
|
||||||
#include "wad/wad.h"
|
#include "wad/wad.h"
|
||||||
#include "xml/xml.h"
|
#include "xml/xml.h"
|
||||||
#include "wad/title.h"
|
#include "wad/nandtitle.h"
|
||||||
#include "usbloader/utils.h"
|
#include "../usbloader/utils.h"
|
||||||
#include "gecko.h"
|
#include "../gecko.h"
|
||||||
|
|
||||||
#define typei 0x00010001
|
|
||||||
|
|
||||||
struct discHdr * titleList=NULL;
|
|
||||||
//discHdr ** titleList;
|
|
||||||
u32 titleCnt;
|
u32 titleCnt;
|
||||||
extern u32 infilesize;
|
extern u32 infilesize;
|
||||||
extern u32 uncfilesize;
|
extern u32 uncfilesize;
|
||||||
@ -40,8 +36,6 @@ extern char wiiloadVersion[2];
|
|||||||
#include "unzip/unzip.h"
|
#include "unzip/unzip.h"
|
||||||
#include "unzip/miniunz.h"
|
#include "unzip/miniunz.h"
|
||||||
|
|
||||||
extern struct discHdr * gameList;
|
|
||||||
extern u32 gameCnt;
|
|
||||||
|
|
||||||
/*** Extern functions ***/
|
/*** Extern functions ***/
|
||||||
extern void ResumeGui();
|
extern void ResumeGui();
|
||||||
@ -59,181 +53,134 @@ extern wchar_t *gameFilter;
|
|||||||
* TitleBrowser- opens a browser with a list of installed Titles
|
* TitleBrowser- opens a browser with a list of installed Titles
|
||||||
* relies on code from any title deleter.
|
* relies on code from any title deleter.
|
||||||
*********************************************************************************/
|
*********************************************************************************/
|
||||||
int TitleBrowser(u32 type) {
|
int TitleBrowser()
|
||||||
|
{
|
||||||
|
|
||||||
u32 num_titles;
|
u32 num_titles;
|
||||||
u32 titles[100] ATTRIBUTE_ALIGN(32);
|
|
||||||
u32 num_sys_titles;
|
u32 num_sys_titles;
|
||||||
u32 sys_titles[10] ATTRIBUTE_ALIGN(32);
|
|
||||||
s32 ret = -1;
|
s32 ret = -1;
|
||||||
int numtitle;//to get rid of a stupid compile wrning
|
u64 *titleList = NULL;
|
||||||
//open the database file
|
|
||||||
FILE *f;
|
|
||||||
char path[100];
|
|
||||||
|
|
||||||
ISFS_Initialize();
|
ISFS_Initialize();//initialize for "titles.Exists()"
|
||||||
|
|
||||||
sprintf(path,"%s/config/database.txt",bootDevice);
|
// Get count of titles of the good titles
|
||||||
f = fopen(path, "r");
|
num_titles = titles.SetType( 0x10001 );
|
||||||
|
u32 n = num_titles;
|
||||||
// Get count of titles of our requested type
|
for( u32 i = 0; i < n; i++ )
|
||||||
ret = getTitles_TypeCount(type, &num_titles);
|
{
|
||||||
if (ret < 0) {
|
u64 tid = titles.Next();
|
||||||
//printf("\tError! Can't get count of titles! (ret = %d)\n", ret);
|
if( !tid )
|
||||||
//exit(1);
|
{
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get titles of our requested type
|
//remove ones not actually installed on the nand
|
||||||
ret = getTitles_Type(type, titles, num_titles);
|
if( !titles.Exists( tid ) )
|
||||||
if (ret < 0) {
|
{
|
||||||
//printf("\tError! Can't get list of titles! (ret = %d)\n", ret);
|
num_titles--;
|
||||||
//exit(1);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get count of system titles
|
// Get count of system titles
|
||||||
ret = getTitles_TypeCount(0x00010002, &num_sys_titles);
|
num_sys_titles = titles.SetType( 0x10002 );
|
||||||
if (ret < 0) {
|
n = num_sys_titles;
|
||||||
//printf("\tError! Can't get count of titles! (ret = %d)\n", ret);
|
for( u32 i = 0; i < n; i++ )
|
||||||
//exit(1);
|
{
|
||||||
}
|
u64 tid = titles.Next();
|
||||||
|
if( !tid )
|
||||||
// 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//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);
|
|
||||||
//write the titles on the option browser
|
|
||||||
u32 i = 0;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//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]));
|
|
||||||
|
|
||||||
//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++)
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
if (!found) {
|
|
||||||
if (getNameBN(name[i], TITLE_ID(type, titles[i]))>=0)
|
|
||||||
found=3;
|
|
||||||
|
|
||||||
if (!found)
|
|
||||||
snprintf(name[i],sizeof(name[i]),"Unknown Title (%08x)",titles[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++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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;
|
break;
|
||||||
}
|
}
|
||||||
|
//these can't be booted anyways
|
||||||
|
if( TITLE_LOWER( tid ) == 0x48414741 || TITLE_LOWER( tid ) == 0x48414141 || TITLE_LOWER( tid ) == 0x48414641 )
|
||||||
|
{
|
||||||
|
num_sys_titles--;
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if (!found) {
|
|
||||||
if (getName00(name[i], TITLE_ID(0x00010002, sys_titles[i-num_titles]))>=0)
|
|
||||||
found=2;
|
|
||||||
|
|
||||||
if (!found) {
|
//these aren't installed on the nand
|
||||||
if (getNameBN(name[i], TITLE_ID(0x00010002, sys_titles[i-num_titles]))>=0)
|
if( !titles.Exists( tid ) )
|
||||||
found=3;
|
{
|
||||||
|
num_sys_titles--;
|
||||||
if (!found)
|
|
||||||
snprintf(name[i],sizeof(name[i]),"Unknown Title (%08x)",sys_titles[i-num_titles]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//set the text to the option browser
|
//make a list of just the tids we are adding to the titlebrowser
|
||||||
options3.SetName(i, "%s",text);
|
titleList = (u64*)memalign( 32, ( num_titles + num_sys_titles ) * sizeof( u64 ) );
|
||||||
options3.SetValue(i, "%s",name[i]);
|
if( !titleList )
|
||||||
//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
|
gprintf("TitleBrowser(): out of memory!\n");
|
||||||
|
return -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 )
|
||||||
|
{
|
||||||
|
u64 tid = titles.Next();
|
||||||
|
if( !tid )
|
||||||
|
{
|
||||||
|
gprintf("shit happened3\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
//gprintf("[ %u] tid: %016llx\t%s\n", i, tid, titles.NameOf( tid ) );
|
||||||
|
|
||||||
|
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++;
|
i++;
|
||||||
}
|
}
|
||||||
if (i == num_titles+num_sys_titles) {
|
|
||||||
|
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.SetName( i, " " );
|
||||||
options3.SetValue( i, "%s",tr("Wii Settings") );
|
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;
|
bool exit = false;
|
||||||
|
int total = num_titles + num_sys_titles;
|
||||||
|
|
||||||
if( IsNetworkInit() )
|
if( IsNetworkInit() )
|
||||||
ResumeNetworkWait();
|
ResumeNetworkWait();
|
||||||
@ -281,10 +228,10 @@ int TitleBrowser(u32 type) {
|
|||||||
cancelBtn.SetTrigger(&trigB);
|
cancelBtn.SetTrigger(&trigB);
|
||||||
|
|
||||||
u8 scrollbaron = 0;
|
u8 scrollbaron = 0;
|
||||||
if (num_titles > 9)
|
if (total + 1 > 9)
|
||||||
scrollbaron = 1;
|
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.SetPosition(0, 90);
|
||||||
optionBrowser3.SetAlignment(ALIGN_CENTRE, ALIGN_TOP);
|
optionBrowser3.SetAlignment(ALIGN_CENTRE, ALIGN_TOP);
|
||||||
|
|
||||||
@ -316,108 +263,76 @@ int TitleBrowser(u32 type) {
|
|||||||
w.Append(&cancelBtn);
|
w.Append(&cancelBtn);
|
||||||
w.Append(&wifiBtn);
|
w.Append(&wifiBtn);
|
||||||
w.Append(&optionBrowser3);
|
w.Append(&optionBrowser3);
|
||||||
|
|
||||||
mainWindow->Append(&w);
|
mainWindow->Append(&w);
|
||||||
|
|
||||||
|
|
||||||
int tmp=num_titles+num_sys_titles;
|
|
||||||
ResumeGui();
|
ResumeGui();
|
||||||
numtitle=num_titles;
|
|
||||||
while (!exit) {
|
while (!exit)
|
||||||
|
{
|
||||||
VIDEO_WaitVSync();
|
VIDEO_WaitVSync();
|
||||||
|
|
||||||
if (shutdown == 1)
|
if( shutdown == 1 ) Sys_Shutdown();
|
||||||
Sys_Shutdown();
|
if( reset == 1 ) Sys_Reboot();
|
||||||
if (reset == 1)
|
|
||||||
Sys_Reboot();
|
|
||||||
|
|
||||||
else if (wifiBtn.GetState() == STATE_CLICKED) {
|
|
||||||
|
|
||||||
|
else if( wifiBtn.GetState() == STATE_CLICKED )
|
||||||
|
{
|
||||||
ResumeNetworkWait();
|
ResumeNetworkWait();
|
||||||
wifiBtn.ResetState();
|
wifiBtn.ResetState();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsNetworkInit()) {
|
if( IsNetworkInit() )
|
||||||
|
{
|
||||||
wifiBtn.SetAlpha(255);
|
wifiBtn.SetAlpha(255);
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = optionBrowser3.GetClickedOption();
|
ret = optionBrowser3.GetClickedOption();
|
||||||
|
|
||||||
if (ret > -1) {//if a click happened
|
if( ret > -1 )
|
||||||
|
{ //if a click happened
|
||||||
|
|
||||||
//char name[50];
|
if ( ret < total )
|
||||||
char text[15];
|
{
|
||||||
if (f)rewind(f);
|
|
||||||
//strcpy(name,"");//make sure name is empty
|
|
||||||
|
|
||||||
if (ret<numtitle) {
|
|
||||||
//set the title's name, number, ID to text
|
//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 );
|
||||||
|
|
||||||
|
snprintf( text, sizeof( text ), "%s : %s", id, titles.NameOf( titleList[ ret ] ) );
|
||||||
|
|
||||||
char temp[100];
|
|
||||||
//prompt to boot selected title
|
//prompt to boot selected title
|
||||||
snprintf(temp, sizeof(temp), "%s : %s",text,name[ret]);
|
if( WindowPrompt( tr( "Boot?" ), text, tr( "OK" ), tr( "Cancel" ) ) )
|
||||||
int choice = WindowPrompt(tr("Boot?"), temp, tr("OK"), tr("Cancel"));
|
{ //if they say yes
|
||||||
if (choice) {//if they say yes
|
|
||||||
|
|
||||||
|
|
||||||
//stop all this stuff before starting the channel
|
|
||||||
|
|
||||||
CloseXMLDatabase();
|
CloseXMLDatabase();
|
||||||
ExitGUIThreads();
|
ExitGUIThreads();
|
||||||
ShutdownAudio();
|
ShutdownAudio();
|
||||||
StopGX();
|
StopGX();
|
||||||
WII_Initialize();
|
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
|
//this really shouldn't be needed because the title will be booted
|
||||||
exit = true;
|
exit = true;
|
||||||
break;
|
break;
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
//if they said no to booting the title
|
//if they said no to booting the title
|
||||||
ret = -1;
|
ret = -1;
|
||||||
optionBrowser3.ResetState();
|
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();
|
CloseXMLDatabase();
|
||||||
ExitGUIThreads();
|
ExitGUIThreads();
|
||||||
ShutdownAudio();
|
ShutdownAudio();
|
||||||
StopGX();
|
StopGX();
|
||||||
WII_Initialize();
|
WII_Initialize();
|
||||||
WII_ReturnToSettings();
|
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();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
#if 0
|
||||||
}
|
|
||||||
|
|
||||||
if(infilesize > 0) {
|
if(infilesize > 0) {
|
||||||
|
|
||||||
char filesizetxt[50];
|
char filesizetxt[50];
|
||||||
@ -585,7 +500,7 @@ int TitleBrowser(u32 type) {
|
|||||||
CloseConnection();
|
CloseConnection();
|
||||||
ResumeNetworkWait();
|
ResumeNetworkWait();
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
if (cancelBtn.GetState() == STATE_CLICKED) {
|
if (cancelBtn.GetState() == STATE_CLICKED) {
|
||||||
//break the loop and end the function
|
//break the loop and end the function
|
||||||
exit = true;
|
exit = true;
|
||||||
@ -603,9 +518,9 @@ int TitleBrowser(u32 type) {
|
|||||||
if (IsNetworkInit())
|
if (IsNetworkInit())
|
||||||
HaltNetworkThread();
|
HaltNetworkThread();
|
||||||
|
|
||||||
fclose(f);
|
|
||||||
HaltGui();
|
HaltGui();
|
||||||
mainWindow->Remove(&w);
|
mainWindow->Remove(&w);
|
||||||
|
free( titleList );
|
||||||
ResumeGui();
|
ResumeGui();
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -8,10 +8,6 @@
|
|||||||
#ifndef _TITLEBROWSER_H_
|
#ifndef _TITLEBROWSER_H_
|
||||||
#define _TITLEBROWSER_H_
|
#define _TITLEBROWSER_H_
|
||||||
|
|
||||||
///opens a window with a custom option browser in it populated with
|
int TitleBrowser();
|
||||||
//! 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);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
#include "usbloader/partition_usbloader.h"
|
#include "usbloader/partition_usbloader.h"
|
||||||
#include "usbloader/utils.h"
|
#include "usbloader/utils.h"
|
||||||
#include "xml/xml.h"
|
#include "xml/xml.h"
|
||||||
|
#include "wad/nandtitle.h"
|
||||||
|
|
||||||
#define MAXOPTIONS 13
|
#define MAXOPTIONS 13
|
||||||
|
|
||||||
@ -1001,7 +1002,7 @@ int MenuSettings()
|
|||||||
if (++Settings.cios >= settings_cios_max) {
|
if (++Settings.cios >= settings_cios_max) {
|
||||||
Settings.cios = 0;
|
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"));
|
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 "sys.h"
|
||||||
#include "wpad.h"
|
#include "wpad.h"
|
||||||
#include "lstub.h"
|
#include "lstub.h"
|
||||||
|
#include "wad/nandtitle.h"
|
||||||
|
|
||||||
extern char game_partition[6];
|
extern char game_partition[6];
|
||||||
extern u8 load_from_fs;
|
extern u8 load_from_fs;
|
||||||
@ -221,47 +222,44 @@ void ShowMemInfo() {
|
|||||||
WindowPrompt("Mem info", (char *) &buf, "OK");
|
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)
|
s32 IOS_ReloadIOSsafe(int ios)
|
||||||
{
|
{
|
||||||
if( ios == 222 )
|
if( ios == 222 )
|
||||||
{
|
{
|
||||||
if (ios222rev == -69)
|
s32 ios222rev = titles.VersionOf( 0x1000000deULL );
|
||||||
ios222rev = getIOSrev(0x00000001000000dell);
|
if( !ios222rev )
|
||||||
|
return -2;
|
||||||
if (ios222rev > 0 && (ios222rev != 4 && ios222rev != 5))return -2;
|
if( ios222rev != 4 && ios222rev != 5 && ios222rev != 65535 )
|
||||||
|
return -2;
|
||||||
}
|
}
|
||||||
else if (ios==223)
|
else if (ios==223)
|
||||||
{
|
{
|
||||||
if (ios223rev == -69)
|
s32 ios223rev = titles.VersionOf( 0x1000000dfULL );
|
||||||
ios223rev = getIOSrev(0x00000001000000dfll);
|
if( !ios223rev )
|
||||||
|
return -2;
|
||||||
if (ios223rev > 0 && (ios223rev != 4 && ios223rev != 5))return -2;
|
if( ios223rev != 4 && ios223rev != 5 && ios223rev != 65535 )
|
||||||
|
return -2;
|
||||||
}
|
}
|
||||||
else if (ios==249)
|
else if (ios==249)
|
||||||
{
|
{
|
||||||
if (ios249rev == -69)
|
s32 ios249rev = titles.VersionOf( 0x1000000f9ULL );
|
||||||
ios249rev = getIOSrev(0x00000001000000f9ll);
|
if( !ios249rev )
|
||||||
|
return -2;
|
||||||
if (ios249rev >= 0 && !(ios249rev>=9 && ios249rev<65280))return -2;
|
if( ios249rev < 9 || ios249rev == 65280 )
|
||||||
|
return -2;
|
||||||
}
|
}
|
||||||
else if (ios==250)
|
else if (ios==250)
|
||||||
{
|
{
|
||||||
if (ios250rev == -69)
|
s32 ios250rev = titles.VersionOf( 0x1000000faULL );
|
||||||
ios250rev = getIOSrev(0x00000001000000fall);
|
if( !ios250rev )
|
||||||
|
return -2;
|
||||||
if (ios250rev >= 0 && !(ios250rev>=9 && ios250rev<65280))return -2;
|
if( ios250rev < 9 || ios250rev == 65280 )
|
||||||
|
return -2;
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 r = IOS_ReloadIOS(ios);
|
s32 r = IOS_ReloadIOS(ios);
|
||||||
if (r >= 0) {
|
if( r >= 0 )
|
||||||
|
{
|
||||||
WII_Initialize();
|
WII_Initialize();
|
||||||
}
|
}
|
||||||
return r;
|
return r;
|
||||||
@ -269,13 +267,20 @@ s32 IOS_ReloadIOSsafe(int ios)
|
|||||||
|
|
||||||
s32 CheckForCIOS()
|
s32 CheckForCIOS()
|
||||||
{
|
{
|
||||||
gprintf("\n\tChecking for stub IOS");
|
gprintf("\tChecking for stub IOS\n");
|
||||||
s32 ret = 1;
|
s32 ret = 1;
|
||||||
ios222rev = getIOSrev(0x00000001000000dell);
|
s32 ios222rev = titles.VersionOf( 0x00000001000000deULL );
|
||||||
ios249rev = getIOSrev(0x00000001000000f9ll);
|
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 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");
|
printf("\x1b[2J");
|
||||||
if ((ios222rev < 0 && ios222rev != WII_EINSTALL) && (ios249rev < 0 && ios249rev != WII_EINSTALL)) {
|
if ((ios222rev < 0 && ios222rev != WII_EINSTALL) && (ios249rev < 0 && ios249rev != WII_EINSTALL)) {
|
||||||
|
@ -24,5 +24,6 @@ extern s32 ios223rev;
|
|||||||
extern s32 ios249rev;
|
extern s32 ios249rev;
|
||||||
extern s32 ios250rev;
|
extern s32 ios250rev;
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#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);
|
appldr_entry(&appldr_init, &appldr_main, &appldr_final);
|
||||||
|
|
||||||
/* Initialize apploader */
|
/* Initialize apploader */
|
||||||
appldr_init(__noprint);
|
appldr_init( gprintf );
|
||||||
|
|
||||||
if (error002fix!=0)
|
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 <ogcsys.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "title.h"
|
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "video.h"
|
#include "video.h"
|
||||||
#include "wad.h"
|
#include "wad.h"
|
||||||
|
|
||||||
|
#include "nandtitle.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#include "prompts/PromptWindows.h"
|
#include "prompts/PromptWindows.h"
|
||||||
@ -569,7 +570,7 @@ s32 Wad_Uninstall(FILE *fp)
|
|||||||
msg2Txt.SetText(tr(">> Deleting tickets..."));
|
msg2Txt.SetText(tr(">> Deleting tickets..."));
|
||||||
|
|
||||||
// Get ticket views
|
// Get ticket views
|
||||||
ret = Title_GetTicketViews(tid, &viewData, &viewCnt);
|
ret = titles.GetTicketViews(tid, &viewData, &viewCnt);
|
||||||
if (ret < 0){
|
if (ret < 0){
|
||||||
char errTxt[50];
|
char errTxt[50];
|
||||||
sprintf(errTxt,"%sret = %d",tr(">> Deleting tickets...ERROR! "),ret);
|
sprintf(errTxt,"%sret = %d",tr(">> Deleting tickets...ERROR! "),ret);
|
||||||
|
@ -2,6 +2,9 @@
|
|||||||
#define _WAD_H_
|
#define _WAD_H_
|
||||||
|
|
||||||
/* Prototypes */
|
/* Prototypes */
|
||||||
|
|
||||||
|
#define BLOCK_SIZE 1024
|
||||||
|
|
||||||
s32 Wad_Install(FILE *);
|
s32 Wad_Install(FILE *);
|
||||||
s32 Wad_Uninstall(FILE *);
|
s32 Wad_Uninstall(FILE *);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user