* 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:
giantpune 2010-09-18 23:04:39 +00:00
parent 1902318e4e
commit e1a36e8988
34 changed files with 1759 additions and 3130 deletions

View File

@ -2,8 +2,8 @@
<app version="1">
<name> USB Loader GX</name>
<coder>USB Loader GX Team</coder>
<version>1.0 r949</version>
<release_date>201009180855</release_date>
<version>1.0 r950</version>
<release_date>201009182245</release_date>
<short_description>Loads games from USB-devices</short_description>
<long_description>USB Loader GX is a libwiigui based USB iso loader with a wii-like GUI. You can install games to your HDDs and boot them with shorter loading times.
The interactive GUI is completely controllable with WiiMote, Classic Controller or GC Controller.

View File

@ -90,7 +90,7 @@ export CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
sFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.S)))
ELFFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.elf)))
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.bin)))
TTFFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.ttf)))
PNGFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.png)))
OGGFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.ogg)))
@ -112,7 +112,7 @@ export OFILES := $(addsuffix .o,$(BINFILES)) \
$(sFILES:.s=.o) $(SFILES:.S=.o) \
$(TTFFILES:.ttf=.ttf.o) $(PNGFILES:.png=.png.o) $(addsuffix .o,$(DOLFILES))\
$(OGGFILES:.ogg=.ogg.o) $(PCMFILES:.pcm=.pcm.o) $(MP3FILES:.mp3=.mp3.o) \
$(addsuffix .o,$(ELFFILES))
$(addsuffix .o,$(ELFFILES)) $(CURDIR)/data/magic_patcher.o
#---------------------------------------------------------------------------------
# build a list of include paths

View File

@ -33,12 +33,13 @@ bool InitGecko()
if (geckoattached)
{
usb_flush(EXI_CHANNEL_1);
CON_EnableGecko( 1, true );
return true;
}
else return false;
}
static char ascii(char s)
char ascii(char s)
{
if(s < 0x20)
return '.';

View File

@ -7,6 +7,8 @@
extern "C" {
#endif
char ascii(char s);
#ifndef NO_DEBUG
//use this just like printf();
void gprintf(const char *str, ...);

View File

@ -1,3 +1,4 @@
#if 0
#include <gccore.h>
#include <ogcsys.h>
#include <malloc.h>
@ -102,6 +103,10 @@ int BootHomebrew()
if (!entry)
Sys_BackToLoader();
VIDEO_SetBlack(true);
VIDEO_Flush();
VIDEO_WaitVSync();
SYS_ResetSystem(SYS_SHUTDOWN, 0, 0);
_CPU_ISR_Disable (cpu_isr);
__exception_closeall();
@ -129,3 +134,218 @@ int BootHomebrew(const char * filepath)
return BootHomebrew();
}
#endif
#include <gccore.h>
#include <ogcsys.h>
#include <malloc.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <ogc/machine/processor.h>
#include <wiiuse/wpad.h>
#include <vector>
#include <string>
#include "../lstub.h"
#include "../sys.h"
#include "../gecko.h"
#include "fatmounter.h"
#include "dolloader.h"
void *innetbuffer = NULL;
static u8 *homebrewbuffer =( u8 * )0x92000000;
u32 homebrewsize = 0;
static std::vector<std::string> Arguments;
extern const u8 app_booter_dol[];
int AllocHomebrewMemory( u32 filesize )
{
innetbuffer = malloc( filesize );
if ( !innetbuffer )
return -1;
homebrewsize = filesize;
return 1;
}
void AddBootArgument( const char * argv )
{
std::string arg( argv );
Arguments.push_back( arg );
}
int CopyHomebrewMemory( u8 *temp, u32 pos, u32 len )
{
homebrewsize += len;
memcpy(( homebrewbuffer ) + pos, temp, len );
return 1;
}
void FreeHomebrewBuffer()
{
homebrewbuffer = ( u8 * ) 0x92000000;
homebrewsize = 0;
if ( innetbuffer )
{
free( innetbuffer );
innetbuffer = NULL;
}
Arguments.clear();
}
static int SetupARGV( struct __argv * args )
{
if ( !args )
return -1;
bzero( args, sizeof( struct __argv ) );
args->argvMagic = ARGV_MAGIC;
u32 stringlength = 1;
/** Append Arguments **/
for ( u32 i = 0; i < Arguments.size(); i++ )
{
stringlength += Arguments[i].size() + 1;
}
args->length = stringlength;
args->commandLine = ( char* ) malloc( args->length );
if ( !args->commandLine )
return -1;
u32 argc = 0;
u32 position = 0;
/** Append Arguments **/
for ( u32 i = 0; i < Arguments.size(); i++ )
{
strcpy( &args->commandLine[position], Arguments[i].c_str() );
position += Arguments[i].size() + 1;
argc++;
}
args->argc = argc;
args->commandLine[args->length - 1] = '\0';
args->argv = &args->commandLine;
args->endARGV = args->argv + 1;
Arguments.clear();
return 0;
}
static int RunAppbooter()
{
if ( homebrewsize == 0 )
return -1;
struct __argv args;
SetupARGV( &args );
u32 cpu_isr;
entrypoint entry = ( entrypoint ) load_dol(( void* ) app_booter_dol, &args );
if ( !entry )
{
FreeHomebrewBuffer();
return -1;
}
u64 currentStub = getStubDest();
loadStub();
if ( Set_Stub_Split( 0x00010001, "UNEO" ) < 0 )
{
if ( Set_Stub_Split( 0x00010001, "ULNR" ) < 0 )
{
if ( !currentStub )
currentStub = 0x100000002ULL;
Set_Stub( currentStub );
}
}
SDCard_deInit();
USBDevice_deInit();
WPAD_Flush( 0 );
WPAD_Disconnect( 0 );
WPAD_Shutdown();
SYS_ResetSystem( SYS_SHUTDOWN, 0, 0 );
_CPU_ISR_Disable( cpu_isr );
__exception_closeall();
entry();
_CPU_ISR_Restore( cpu_isr );
return 0;
}
int BootHomebrew( char * filepath )
{
void *buffer = NULL;
u32 filesize = 0;
FILE *file = fopen( filepath, "rb" );
if ( !file )
Sys_BackToLoader();
fseek( file, 0, SEEK_END );
filesize = ftell( file );
rewind( file );
buffer = malloc( filesize );
if ( fread( buffer, 1, filesize, file ) != filesize )
{
fclose( file );
free( buffer );
SDCard_deInit();
USBDevice_deInit();
Sys_BackToLoader();
}
fclose( file );
CopyHomebrewMemory(( u8* ) buffer, 0, filesize );
if ( buffer )
{
free( buffer );
buffer = NULL;
}
AddBootArgument( filepath );
return RunAppbooter();
}
int BootHomebrewFromMem()
{
gprintf( "BootHomebrewFromMem()\n %p, %08x\n", innetbuffer, homebrewsize );
if ( !innetbuffer )
{
gprintf( "!innetbuffer\n" );
SDCard_deInit();
USBDevice_deInit();
Sys_BackToLoader();
}
CopyHomebrewMemory(( u8* ) innetbuffer, 0, homebrewsize );
free( innetbuffer );
return RunAppbooter();
}

View File

@ -1,11 +1,15 @@
#ifndef _BOOTHOMEBREW_H_
#define _BOOTHOMEBREW_H_
int BootHomebrew();
int BootHomebrew(const char * filepath);
//int BootHomebrew();
int BootHomebrewFromMem();
int BootHomebrew( char * filepath);
int CopyHomebrewMemory(u8 *temp, u32 pos, u32 len);
void AddBootArgument(const char * arg);
void FreeHomebrewBuffer();
int LoadHomebrew(const char * filepath);
int AllocHomebrewMemory( u32 filesize );
extern void *innetbuffer;
extern u32 homebrewsize;
#endif

File diff suppressed because it is too large Load Diff

View File

@ -9,6 +9,7 @@
#include "gui.h"
#include "../wpad.h"
#include "../main.h"
#include "../gecko.h"
#include "../settings/cfg.h"
#include "gui_customoptionbrowser.h"
@ -83,7 +84,7 @@ void customOptionList::SetSize(int Size) //set number of lines
}
void customOptionList::SetName(int i, const char *format, ...)
{
if(i >= length) SetLength(i+1);
if(i >= length) SetLength(i+1);
if(i >= 0 && i < length)
{
@ -95,6 +96,7 @@ void customOptionList::SetName(int i, const char *format, ...)
va_end(va);
changed = true;
}
//gprintf("customOptionList::SetName( %d, %s )\n", i, name[i] );
}
void customOptionList::SetValue(int i, const char *format, ...)
{
@ -120,6 +122,7 @@ void customOptionList::SetValue(int i, const char *format, ...)
}
}
}
//gprintf("customOptionList::SetValue( %d, %s )\n", i, value[i] );
}
void customOptionList::Clear(bool OnlyValue/*=false*/)
{

114
source/lstub.cpp Normal file
View 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;
}

View File

@ -4,10 +4,6 @@
#ifndef _LSTUB_H_
#define _LSTUB_H_
#ifdef __cplusplus
extern "C" {
#endif
//to set the "return to" stub for a certain ID
//!reqID is the Requested ID to return to
//!returns WII_EINTERNAL if it cant get the list of installed titles with ES functions
@ -31,8 +27,4 @@ u64 getStubDest();
u8 hbcStubAvailable();
#ifdef __cplusplus
}
#endif
#endif

View File

@ -47,17 +47,19 @@ extern "C"
#include "fat.h"
#include "gecko.h"
#include "svnrev.h"
#include "wad/title.h"
#include "usbloader/partition_usbloader.h"
#include "usbloader/usbstorage2.h"
#include "memory/mem2.h"
#include "lstub.h"
#include "usbloader/usbstorage2.h"
#include "wad/nandtitle.h"
extern bool geckoinit;
extern bool textVideoInit;
extern char headlessID[8];
NandTitle titles;
/* Constants */
#define CONSOLE_XCOORD 260
#define CONSOLE_YCOORD 115
@ -75,7 +77,9 @@ int main(int argc, char *argv[])
geckoinit = InitGecko();
__exception_setreload(20);
printf("\n\tStarting up");
printf("\tStarting up\n");
titles.Get();
titles.Exists( 0x100014e414c45ULL );
bool bootDevice_found=false;
if (argc >= 1)
@ -89,14 +93,14 @@ int main(int argc, char *argv[])
}
//Let's use libogc sd/usb for config loading
printf("\n\tInitialize sd card");
printf("\tInitialize sd card\n");
SDCard_Init();
printf("\n\tInitialize usb device");
printf("\tInitialize usb device\n");
USBDevice_Init();
if (!bootDevice_found)
{
printf("\n\tSearch for configuration file");
printf("\tSearch for configuration file\n");
//try USB
//left in all the dol and elf files in this check in case this is the first time running the app and they dont have the config
if (checkfile((char*) "USB:/config/GXglobal.cfg") || (checkfile((char*) "USB:/apps/usbloader_gx/boot.elf"))
@ -104,13 +108,13 @@ int main(int argc, char *argv[])
|| checkfile((char*) "USB:/apps/usbloader_gx/boot.dol"))
strcpy(bootDevice, "USB:");
printf("\n\tConfiguration file is on %s", bootDevice);
printf("\tConfiguration file is on %s\n", bootDevice);
}
gettextCleanUp();
printf("\n\tLoading configuration...");
printf("\tLoading configuration...");
CFG_Load();
printf("done");
printf("done\n");
SDCard_deInit();// unmount SD for reloading IOS
USBDevice_deInit();// unmount USB for reloading IOS
@ -118,10 +122,10 @@ int main(int argc, char *argv[])
// This part is added, because we need a identify patched ios
//! pune please replace this with your magic patch functions - Dimok
if (IOS_ReloadIOSsafe(236) < 0)
IOS_ReloadIOSsafe(36);
//if (IOS_ReloadIOSsafe(236) < 0)
// IOS_ReloadIOSsafe(36);
printf("\n\tCheck for an existing cIOS");
printf("\tCheck for an existing cIOS\n");
CheckForCIOS();
// Let's load the cIOS now

View File

@ -23,7 +23,6 @@
#include "themes/Theme_Downloader.h"
#include "usbloader/disc.h"
#include "usbloader/GameList.h"
#include "wad/title.h"
#include "xml/xml.h"
#include "audio.h"
#include "gecko.h"
@ -34,6 +33,7 @@
#include "patches/fst.h"
#include "usbloader/frag.h"
#include "usbloader/wbfs.h"
#include "wad/nandtitle.h"
/*** Variables that are also used extern ***/
GuiWindow * mainWindow = NULL;
@ -322,7 +322,7 @@ int MainMenu(int menu) {
// MemInfoPrompt();
gprintf("\nExiting main GUI. mountMethod = %d",mountMethod);
gprintf("Exiting main GUI. mountMethod = %d\n",mountMethod);
CloseXMLDatabase();
NewTitles::DestroyInstance();
@ -375,15 +375,16 @@ int MainMenu(int menu) {
}
else if (boothomebrew == 2) {
gprintf("\nBootHomebrew from Menu");
BootHomebrew();
//BootHomebrew();
BootHomebrewFromMem();
}
else {
gprintf("\n\tSettings.partition:%d",Settings.partition);
gprintf("\tSettings.partition: %d\n",Settings.partition);
struct discHdr *header = NULL;
//if the GUI was "skipped" to boot a game from main(argv[1])
if (strcmp(headlessID,"")!=0)
{
gprintf("\n\tHeadless mode (%s)",headlessID);
gprintf("\tHeadless mode (%s)\n",headlessID);
gameList.LoadUnfiltered();
if (!gameList.size())
{
@ -399,13 +400,13 @@ int MainMenu(int menu) {
if (strcmp(tmp,headlessID)==0)
{
gameSelected = i;
gprintf(" found (%d)",i);
gprintf(" found (%d)\n",i);
break;
}
//if the game was not found
if (i==gameList.GameCount()-1)
{
gprintf(" not found (%d IDs checked)",i);
gprintf(" not found (%d IDs checked)\n",i);
exit(0);
}
}
@ -483,20 +484,20 @@ int MainMenu(int menu) {
}
if (!mountMethod)
{
gprintf("\nLoading fragment list...");
gprintf("Loading fragment list...");
ret = get_frag_list(header->id);
gprintf("%d\n", ret);
gprintf("\nSetting fragment list...");
gprintf("Setting fragment list...");
ret = set_frag_list(header->id);
gprintf("%d\n", ret);
ret = Disc_SetUSB(header->id);
if (ret < 0) Sys_BackToLoader();
gprintf("\n\tUSB set to game");
gprintf("\tUSB set to game\n");
}
else {
gprintf("\n\tUSB not set, loading DVD");
gprintf("\tUSB not set, loading DVD\n");
}
ret = Disc_Open();
@ -505,7 +506,7 @@ int MainMenu(int menu) {
if(dvdheader)
delete dvdheader;
gprintf("\nLoading BCA data...");
gprintf("Loading BCA data...");
ret = do_bca_code(header->id);
gprintf("%d\n", ret);
@ -640,13 +641,14 @@ int MainMenu(int menu) {
vipatch = 0;
break;
}
gprintf("\n\tDisc_wiiBoot");
gprintf("\tDisc_wiiBoot\n");
ret = Disc_WiiBoot(videoselected, cheat, vipatch, countrystrings, errorfixer002, alternatedol, alternatedoloffset);
if (ret < 0) {
Sys_LoadMenu();
}
//should never get here
printf("Returning entry point: 0x%0x\n", ret);
}
return 0;

View File

@ -17,7 +17,6 @@
#include "sys.h"
#include "settings/cfg.h"
#include "memory.h"
#include "../wad/title.h"
#include "../gecko.h"
#include "../patches/dvd_broadway.h"

View File

@ -34,7 +34,6 @@
#include "svnrev.h"
#include "audio.h"
#include "xml/xml.h"
#include "wad/title.h"
#include "language/UpdateLanguage.h"
#include "gecko.h"
#include "lstub.h"

View File

@ -23,14 +23,10 @@
#include "audio.h"
#include "wad/wad.h"
#include "xml/xml.h"
#include "wad/title.h"
#include "usbloader/utils.h"
#include "gecko.h"
#include "wad/nandtitle.h"
#include "../usbloader/utils.h"
#include "../gecko.h"
#define typei 0x00010001
struct discHdr * titleList=NULL;
//discHdr ** titleList;
u32 titleCnt;
extern u32 infilesize;
extern u32 uncfilesize;
@ -40,8 +36,6 @@ extern char wiiloadVersion[2];
#include "unzip/unzip.h"
#include "unzip/miniunz.h"
extern struct discHdr * gameList;
extern u32 gameCnt;
/*** Extern functions ***/
extern void ResumeGui();
@ -59,183 +53,136 @@ extern wchar_t *gameFilter;
* TitleBrowser- opens a browser with a list of installed Titles
* relies on code from any title deleter.
*********************************************************************************/
int TitleBrowser(u32 type) {
int TitleBrowser()
{
u32 num_titles;
u32 titles[100] ATTRIBUTE_ALIGN(32);
u32 num_sys_titles;
u32 sys_titles[10] ATTRIBUTE_ALIGN(32);
s32 ret = -1;
int numtitle;//to get rid of a stupid compile wrning
//open the database file
FILE *f;
char path[100];
u64 *titleList = NULL;
ISFS_Initialize();
ISFS_Initialize();//initialize for "titles.Exists()"
sprintf(path,"%s/config/database.txt",bootDevice);
f = fopen(path, "r");
// Get count of titles of the good titles
num_titles = titles.SetType( 0x10001 );
u32 n = num_titles;
for( u32 i = 0; i < n; i++ )
{
u64 tid = titles.Next();
if( !tid )
{
break;
}
// Get count of titles of our requested type
ret = getTitles_TypeCount(type, &num_titles);
if (ret < 0) {
//printf("\tError! Can't get count of titles! (ret = %d)\n", ret);
//exit(1);
}
// Get titles of our requested type
ret = getTitles_Type(type, titles, num_titles);
if (ret < 0) {
//printf("\tError! Can't get list of titles! (ret = %d)\n", ret);
//exit(1);
//remove ones not actually installed on the nand
if( !titles.Exists( tid ) )
{
num_titles--;
}
}
// Get count of system titles
ret = getTitles_TypeCount(0x00010002, &num_sys_titles);
if (ret < 0) {
//printf("\tError! Can't get count of titles! (ret = %d)\n", ret);
//exit(1);
num_sys_titles = titles.SetType( 0x10002 );
n = num_sys_titles;
for( u32 i = 0; i < n; i++ )
{
u64 tid = titles.Next();
if( !tid )
{
break;
}
//these can't be booted anyways
if( TITLE_LOWER( tid ) == 0x48414741 || TITLE_LOWER( tid ) == 0x48414141 || TITLE_LOWER( tid ) == 0x48414641 )
{
num_sys_titles--;
continue;
}
//these aren't installed on the nand
if( !titles.Exists( tid ) )
{
num_sys_titles--;
}
}
// Get system titles
ret = getTitles_Type(0x00010002, sys_titles, num_sys_titles);
if (ret < 0) {
//printf("\tError! Can't get list of titles! (ret = %d)\n", ret);
//exit(1);
//make a list of just the tids we are adding to the titlebrowser
titleList = (u64*)memalign( 32, ( num_titles + num_sys_titles ) * sizeof( u64 ) );
if( !titleList )
{
gprintf("TitleBrowser(): out of memory!\n");
return -1;
}
//this array will hold all the names for the titles so we only have to get them one time
char name[num_titles+num_sys_titles][50];
customOptionList options3(num_titles+num_sys_titles+1);
customOptionList options3( num_titles + num_sys_titles + 1 );
//write the titles on the option browser
u32 i = 0;
titles.SetType( 0x10001 );
//first add the good stuff
while (i < num_titles) {
//start from the beginning of the file each loop
if (f)rewind(f);
//char name[50];
char text[15];
strcpy(name[i],"");//make sure name is empty
u8 found=0;
//set the title's name, number, ID to text
sprintf(text, "%s", titleText(type, titles[i]));
while( i < num_titles )
{
u64 tid = titles.Next();
if( !tid )
{
gprintf("shit happened3\n");
break;
}
//gprintf("[ %u] tid: %016llx\t%s\n", i, tid, titles.NameOf( tid ) );
//get name from database cause i dont like the ADT function
char line[200];
char tmp[50];
snprintf(tmp,50," ");
//check if the content.bin is on the SD card for that game
//if there is content.bin,then the game is on the SDmenu and not the wii
sprintf(line,"SD:/private/wii/title/%s/content.bin",text);
if (!checkfile(line))
{
if (f) {
while (fgets(line, sizeof(line), f)) {
if (line[0]== text[0]&&
line[1]== text[1]&&
line[2]== text[2]) {
int j=0;
found=1;
for (j=0;(line[j+4]!='\0' || j<51);j++)
if( !titles.Exists( tid ) )
{
continue;
}
tmp[j]=line[j+4];
snprintf(name[i],sizeof(name[i]),"%s",tmp);
//break;
}
}
}
if (!found) {
if (getName00(name[i], TITLE_ID(type, titles[i]),CONF_GetLanguage()*2)>=0)
found=2;
char id[ 5 ];
titles.AsciiTID( tid, (char*)&id );
if (!found) {
if (getNameBN(name[i], TITLE_ID(type, titles[i]))>=0)
found=3;
char* name = titles.NameOf( tid );
if (!found)
snprintf(name[i],sizeof(name[i]),"Unknown Title (%08x)",titles[i]);
}
}
options3.SetName( i, "%s", id );
options3.SetValue( i, "%s", name ? titles.NameOf( tid ): "Unknown" );
titleList[ i ] = tid;
i++;
}
//set the text to the option browser
options3.SetName(i, "%s",text);
options3.SetValue(i, "%s",name[i]);
//options3.SetValue(i, " (%08x) %s",titles[i],name[i]);//use this line to show the number to call to launch the channel
//move on to the next title
}
i++;
titles.SetType( 0x10002 );
while( i < num_sys_titles + num_titles )
{
u64 tid = titles.Next();
if( !tid )
{
break;
}
if( TITLE_LOWER( tid ) == 0x48414741 || TITLE_LOWER( tid ) == 0x48414141 || TITLE_LOWER( tid ) == 0x48414641 )
continue;
if( !titles.Exists( tid ) )
{
continue;
}
char id[ 5 ];
titles.AsciiTID( tid, (char*)&id );
char* name = titles.NameOf( tid );
options3.SetName( i, "%s", id );
options3.SetValue( i, "%s", name ? titles.NameOf( tid ): "Unknown" );
titleList[ i ] = tid;
i++;
}
ISFS_Deinitialize();
if( i == num_titles+num_sys_titles )
{
options3.SetName( i, " " );
options3.SetValue( i, "%s",tr("Wii Settings") );
}
// now add the crappy system titles
while (i < num_titles+num_sys_titles) {
//start from the beginning of the file each loop
if (f)rewind(f);
//char name[50];
char text[15];
strcpy(name[i],"");//make sure name is empty
u8 found=0;
//set the title's name, number, ID to text
sprintf(text, "%s", titleText(0x00010002, sys_titles[i-num_titles]));
//get name from database cause i dont like the ADT function
char line[200];
char tmp[50];
snprintf(tmp,50," ");
//snprintf(name[i],sizeof(name[i]),"Unknown Title");
if (f) {
while (fgets(line, sizeof(line), f)) {
if (line[0]== text[0]&&
line[1]== text[1]&&
line[2]== text[2]) {
int j=0;
found=1;
for (j=0;(line[j+4]!='\0' || j<51);j++)
tmp[j]=line[j+4];
snprintf(name[i],sizeof(name[i]),"%s",tmp);
break;
}
}
}
if (!found) {
if (getName00(name[i], TITLE_ID(0x00010002, sys_titles[i-num_titles]))>=0)
found=2;
if (!found) {
if (getNameBN(name[i], TITLE_ID(0x00010002, sys_titles[i-num_titles]))>=0)
found=3;
if (!found)
snprintf(name[i],sizeof(name[i]),"Unknown Title (%08x)",sys_titles[i-num_titles]);
}
}
//set the text to the option browser
options3.SetName(i, "%s",text);
options3.SetValue(i, "%s",name[i]);
//options3.SetValue(i, " (%08x) %s",titles[i],name[i]);//use this line to show the number to call to launch the channel
//move on to the next title
i++;
}
if (i == num_titles+num_sys_titles) {
options3.SetName(i, " ");
options3.SetValue(i, "%s",tr("Wii Settings"));
}
//we have all the titles we need so close the database and stop poking around in the wii
fclose(f);
//get rid of our footprints in there
Uninstall_FromTitle(TITLE_ID(1, 0));
ISFS_Deinitialize();
bool exit = false;
int total = num_titles + num_sys_titles;
if (IsNetworkInit())
if( IsNetworkInit() )
ResumeNetworkWait();
GuiSound btnSoundOver(button_over_pcm, button_over_pcm_size, Settings.sfxvolume);
@ -281,10 +228,10 @@ int TitleBrowser(u32 type) {
cancelBtn.SetTrigger(&trigB);
u8 scrollbaron = 0;
if (num_titles > 9)
scrollbaron = 1;
if (total + 1 > 9)
scrollbaron = 1;
GuiCustomOptionBrowser optionBrowser3(396, 280, &options3, CFG.theme_path, "bg_options_gamesettings.png", bg_options_settings_png, num_titles+num_sys_titles>9?1:0, 200);
GuiCustomOptionBrowser optionBrowser3(396, 280, &options3, CFG.theme_path, "bg_options_gamesettings.png", bg_options_settings_png, scrollbaron, 200);
optionBrowser3.SetPosition(0, 90);
optionBrowser3.SetAlignment(ALIGN_CENTRE, ALIGN_TOP);
@ -308,7 +255,7 @@ int TitleBrowser(u32 type) {
screenShotBtn.SetPosition(0,0);
screenShotBtn.SetTrigger(&trigZ);
HaltGui();
HaltGui();
GuiWindow w(screenwidth, screenheight);
w.Append(&screenShotBtn);
w.Append(&settingsbackgroundbtn);
@ -316,108 +263,76 @@ int TitleBrowser(u32 type) {
w.Append(&cancelBtn);
w.Append(&wifiBtn);
w.Append(&optionBrowser3);
mainWindow->Append(&w);
int tmp=num_titles+num_sys_titles;
ResumeGui();
numtitle=num_titles;
while (!exit) {
while (!exit)
{
VIDEO_WaitVSync();
if (shutdown == 1)
Sys_Shutdown();
if (reset == 1)
Sys_Reboot();
else if (wifiBtn.GetState() == STATE_CLICKED) {
if( shutdown == 1 ) Sys_Shutdown();
if( reset == 1 ) Sys_Reboot();
else if( wifiBtn.GetState() == STATE_CLICKED )
{
ResumeNetworkWait();
wifiBtn.ResetState();
}
if (IsNetworkInit()) {
if( IsNetworkInit() )
{
wifiBtn.SetAlpha(255);
}
ret = optionBrowser3.GetClickedOption();
if (ret > -1) {//if a click happened
if( ret > -1 )
{ //if a click happened
//char name[50];
char text[15];
if (f)rewind(f);
//strcpy(name,"");//make sure name is empty
if (ret<numtitle) {
if ( ret < total )
{
//set the title's name, number, ID to text
sprintf(text, "%s", titleText(type, titles[ret]));
char text[ 0x100 ];
char id[ 5 ];
titles.AsciiTID( titleList[ ret ], (char*)&id );
char temp[100];
//prompt to boot selected title
snprintf(temp, sizeof(temp), "%s : %s",text,name[ret]);
int choice = WindowPrompt(tr("Boot?"), temp, tr("OK"), tr("Cancel"));
if (choice) {//if they say yes
snprintf( text, sizeof( text ), "%s : %s", id, titles.NameOf( titleList[ ret ] ) );
//stop all this stuff before starting the channel
CloseXMLDatabase();
//prompt to boot selected title
if( WindowPrompt( tr( "Boot?" ), text, tr( "OK" ), tr( "Cancel" ) ) )
{ //if they say yes
CloseXMLDatabase();
ExitGUIThreads();
ShutdownAudio();
StopGX();
WII_Initialize();
WII_LaunchTitle(TITLE_ID(type,titles[ret]));
WII_LaunchTitle( titleList[ ret ] );
//this really shouldn't be needed because the title will be booted
exit = true;
break;
} else {
}
else
{
//if they said no to booting the title
ret = -1;
optionBrowser3.ResetState();
}
} else { //if they clicked a system title
if (ret == tmp) {
}
else if( ret == total )
{ //if they clicked to go to the wii settings
CloseXMLDatabase();
ExitGUIThreads();
ShutdownAudio();
StopGX();
WII_Initialize();
WII_ReturnToSettings();
} else {
//set the title's name, number, ID to text
sprintf(text, "%s", titleText(0x00010002, sys_titles[ret-num_titles]));
char temp[112];
//prompt to boot selected title
snprintf(temp, sizeof(temp), tr("%s : %s May not boot correctly if your System Menu is not up to date."),text,name[ret]);
int choice = WindowPrompt(tr("Boot?"), temp, tr("OK"), tr("Cancel"));
if (choice) {//if they say yes
//stop all this stuff before starting the channel
CloseXMLDatabase();
ExitGUIThreads();
ShutdownAudio();
StopGX();
WII_Initialize();
WII_LaunchTitle(TITLE_ID(0x00010002,sys_titles[ret-num_titles]));
//this really shouldn't be needed because the title will be booted
exit = true;
break;
} else {
//if they said no to booting the title
ret = -1;
optionBrowser3.ResetState();
}
}
WII_ReturnToSettings();
}
}
#if 0
if(infilesize > 0) {
char filesizetxt[50];
@ -585,7 +500,7 @@ int TitleBrowser(u32 type) {
CloseConnection();
ResumeNetworkWait();
}
#endif
if (cancelBtn.GetState() == STATE_CLICKED) {
//break the loop and end the function
exit = true;
@ -603,9 +518,9 @@ int TitleBrowser(u32 type) {
if (IsNetworkInit())
HaltNetworkThread();
fclose(f);
HaltGui();
mainWindow->Remove(&w);
free( titleList );
ResumeGui();
return ret;

View File

@ -8,10 +8,6 @@
#ifndef _TITLEBROWSER_H_
#define _TITLEBROWSER_H_
///opens a window with a custom option browser in it populated with
//! type is the type of chnnel to put in the list
int TitleBrowser(u32 type);
//int buildTitleList(int t=0, const wchar_t* Filter=NULL);
int TitleBrowser();
#endif

View File

@ -20,6 +20,7 @@
#include "usbloader/partition_usbloader.h"
#include "usbloader/utils.h"
#include "xml/xml.h"
#include "wad/nandtitle.h"
#define MAXOPTIONS 13
@ -1001,7 +1002,7 @@ int MenuSettings()
if (++Settings.cios >= settings_cios_max) {
Settings.cios = 0;
}
if ((Settings.cios == 1 && ios222rev!=4) || (Settings.cios == 2 && ios223rev != 4)) {
if ((Settings.cios == 1 && titles.VersionOf( 0x1000000deULL ) != 4 ) || (Settings.cios == 2 && titles.VersionOf( 0x1000000dfULL ) != 4)) {
WindowPrompt(tr("Hermes CIOS"),tr("USB Loader GX will only run with Hermes CIOS rev 4! Please make sure you have revision 4 installed!"),tr("OK"));
}
}

View File

@ -16,6 +16,7 @@
#include "sys.h"
#include "wpad.h"
#include "lstub.h"
#include "wad/nandtitle.h"
extern char game_partition[6];
extern u8 load_from_fs;
@ -221,61 +222,65 @@ void ShowMemInfo() {
WindowPrompt("Mem info", (char *) &buf, "OK");
}
#include "wad/title.h"
s32 ios222rev = -69;
s32 ios223rev = -69;
s32 ios249rev = -69;
s32 ios250rev = -69;
s32 IOS_ReloadIOSsafe(int ios)
{
if (ios==222)
if( ios == 222 )
{
if (ios222rev == -69)
ios222rev = getIOSrev(0x00000001000000dell);
if (ios222rev > 0 && (ios222rev != 4 && ios222rev != 5))return -2;
s32 ios222rev = titles.VersionOf( 0x1000000deULL );
if( !ios222rev )
return -2;
if( ios222rev != 4 && ios222rev != 5 && ios222rev != 65535 )
return -2;
}
else if (ios==223)
{
if (ios223rev == -69)
ios223rev = getIOSrev(0x00000001000000dfll);
if (ios223rev > 0 && (ios223rev != 4 && ios223rev != 5))return -2;
s32 ios223rev = titles.VersionOf( 0x1000000dfULL );
if( !ios223rev )
return -2;
if( ios223rev != 4 && ios223rev != 5 && ios223rev != 65535 )
return -2;
}
else if (ios==249)
{
if (ios249rev == -69)
ios249rev = getIOSrev(0x00000001000000f9ll);
if (ios249rev >= 0 && !(ios249rev>=9 && ios249rev<65280))return -2;
s32 ios249rev = titles.VersionOf( 0x1000000f9ULL );
if( !ios249rev )
return -2;
if( ios249rev < 9 || ios249rev == 65280 )
return -2;
}
else if (ios==250)
{
if (ios250rev == -69)
ios250rev = getIOSrev(0x00000001000000fall);
if (ios250rev >= 0 && !(ios250rev>=9 && ios250rev<65280))return -2;
s32 ios250rev = titles.VersionOf( 0x1000000faULL );
if( !ios250rev )
return -2;
if( ios250rev < 9 || ios250rev == 65280 )
return -2;
}
s32 r = IOS_ReloadIOS(ios);
if (r >= 0) {
WII_Initialize();
if( r >= 0 )
{
WII_Initialize();
}
return r;
}
s32 CheckForCIOS()
{
gprintf("\n\tChecking for stub IOS");
gprintf("\tChecking for stub IOS\n");
s32 ret = 1;
ios222rev = getIOSrev(0x00000001000000dell);
ios249rev = getIOSrev(0x00000001000000f9ll);
s32 ios222rev = titles.VersionOf( 0x00000001000000deULL );
s32 ios249rev = titles.VersionOf( 0x00000001000000f9ULL );
u8 ios222OK = !( ios222rev < 4 || ios222rev == 65280 );
u8 ios249OK = !( ios249rev < 9 || ios249rev == 65280 );
gprintf("222ok: %u\t 249ok: %u\n", ios222OK, ios249OK );
return 1;
//if we don't like either of the cIOS then scram
if (!((ios222rev >= 4 && ios222rev < 65280) || (ios249rev >=9 && ios249rev < 65280)))
//if( !((ios222rev >= 4 && ios222rev < 65280) || (ios249rev >=9 && ios249rev < 65280)))
if( ios222rev < 4 || ios222rev == 65280 || ios249rev < 9 || ios249rev == 65280 )
{
printf("\x1b[2J");
if ((ios222rev < 0 && ios222rev != WII_EINSTALL) && (ios249rev < 0 && ios249rev != WII_EINSTALL)) {

View File

@ -24,5 +24,6 @@ extern s32 ios223rev;
extern s32 ios249rev;
extern s32 ios250rev;
#endif

View File

@ -95,7 +95,7 @@ s32 Apploader_Run(entry_point *entry, u8 cheat, u8 videoSelected, u8 vipatch, u8
appldr_entry(&appldr_init, &appldr_main, &appldr_final);
/* Initialize apploader */
appldr_init(__noprint);
appldr_init( gprintf );
if (error002fix!=0)
{

View File

@ -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);
}

View File

@ -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

View File

@ -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;
}

View File

@ -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
View 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
View 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

View File

@ -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));
}

View File

@ -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

View File

@ -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);
}

View File

@ -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);

View File

@ -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;
}

View File

@ -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

View File

@ -4,11 +4,12 @@
#include <ogcsys.h>
#include <unistd.h>
#include "title.h"
#include "utils.h"
#include "video.h"
#include "wad.h"
#include "nandtitle.h"
#include "prompts/PromptWindows.h"
@ -347,9 +348,9 @@ s32 Wad_Install(FILE *fp)
snprintf(imgPath, sizeof(imgPath), "%s%d...",tr(">> Installing content #"),content->cid);
msg4Txt.SetText(imgPath);
// Install content data
while (idx < len) {
//VIDEO_WaitVSync ();
while (idx < len) {
//VIDEO_WaitVSync ();
u32 size;
@ -569,7 +570,7 @@ s32 Wad_Uninstall(FILE *fp)
msg2Txt.SetText(tr(">> Deleting tickets..."));
// Get ticket views
ret = Title_GetTicketViews(tid, &viewData, &viewCnt);
ret = titles.GetTicketViews(tid, &viewData, &viewCnt);
if (ret < 0){
char errTxt[50];
sprintf(errTxt,"%sret = %d",tr(">> Deleting tickets...ERROR! "),ret);

View File

@ -2,6 +2,9 @@
#define _WAD_H_
/* Prototypes */
#define BLOCK_SIZE 1024
s32 Wad_Install(FILE *);
s32 Wad_Uninstall(FILE *);