* brought back the return-to patch complete with settings and shit to click on

* in the global settings you can select any 0x10001 title that is actually installed in the nand.  in the game settings, you can decide whether or not to use the global setting for that 1 game.
This commit is contained in:
giantpune 2010-09-19 10:53:24 +00:00
parent 2547b9a2a5
commit dd4704cce3
19 changed files with 818 additions and 369 deletions

View File

@ -47,7 +47,7 @@ sec_t fs_ntfs_sec = 0;
int USBDevice_Init()
{
#ifdef DEBUG_FAT
gprintf( "\nUSBDevice_Init()" );
gprintf( "USBDevice_Init()" );
#endif
//closing all open Files write back the cache and then shutdown em!
fatUnmount( "USB:/" );
@ -59,7 +59,7 @@ int USBDevice_Init()
if ( !fatMount( "USB", &__io_usbstorage2, 0, CACHE, SECTORS ) )
{
#ifdef DEBUG_FAT
gprintf( ":-1" );
gprintf( ":-1\n" );
#endif
return -1;
}
@ -68,7 +68,7 @@ int USBDevice_Init()
fat_usb_mount = 1;
fat_usb_sec = _FAT_startSector;
#ifdef DEBUG_FAT
gprintf( ":0" );
gprintf( ":0\n" );
#endif
return 0;
}
@ -76,13 +76,16 @@ int USBDevice_Init()
void USBDevice_deInit()
{
#ifdef DEBUG_FAT
gprintf( "\nUSBDevice_deInit()" );
gprintf( "USBDevice_deInit(): " );
#endif
//closing all open Files write back the cache and then shutdown em!
fatUnmount( "USB:/" );
fat_usb_mount = 0;
fat_usb_sec = 0;
#ifdef DEBUG_FAT
gprintf( "ok\n" );
#endif
}
int WBFSDevice_Init( u32 sector )
@ -130,7 +133,7 @@ int isInserted( const char *path )
int SDCard_Init()
{
#ifdef DEBUG_FAT
gprintf( "\nSDCard_Init()" );
gprintf( "SDCard_Init()" );
#endif
//closing all open Files write back the cache and then shutdown em!
fatUnmount( "SD:/" );
@ -140,7 +143,7 @@ int SDCard_Init()
fat_sd_mount = MOUNT_SD;
fat_sd_sec = _FAT_startSector;
#ifdef DEBUG_FAT
gprintf( ":1" );
gprintf( ":1\n" );
#endif
return 1;
}
@ -149,12 +152,12 @@ int SDCard_Init()
fat_sd_mount = MOUNT_SDHC;
fat_sd_sec = _FAT_startSector;
#ifdef DEBUG_FAT
gprintf( ":1" );
gprintf( ":1\n" );
#endif
return 1;
}
#ifdef DEBUG_FAT
gprintf( ":-1" );
gprintf( ":-1\n" );
#endif
return -1;
}
@ -162,13 +165,16 @@ int SDCard_Init()
void SDCard_deInit()
{
#ifdef DEBUG_FAT
gprintf( "\nSDCard_deInit()" );
gprintf( "SDCard_deInit(): " );
#endif
//closing all open Files write back the cache and then shutdown em!
fatUnmount( "SD:/" );
fat_sd_mount = MOUNT_NONE;
fat_sd_sec = 0;
#ifdef DEBUG_FAT
gprintf( "ok\n" );
#endif
}
void ntfsInit();

View File

@ -14,7 +14,7 @@ void gprintf( const char *str, ... )
{
if ( !( geckoinit ) )return;
char astr[4096];
char astr[ 0x100 ];
va_list ap;
va_start( ap, str );
@ -23,8 +23,8 @@ void gprintf( const char *str, ... )
va_end( ap );
//usb_sendbuffer( 1, astr, strlen( astr ) );
usb_sendbuffer_safe( 1, astr, strlen(astr) );
usb_sendbuffer( 1, astr, strlen( astr ) );
//usb_sendbuffer_safe( 1, astr, strlen(astr) );
}
bool InitGecko()

View File

@ -60,6 +60,7 @@ extern char headlessID[8];
NandTitle titles;
PartList partitions;
int main( int argc, char *argv[] )
{
MEM2_init( 48 );

View File

@ -439,6 +439,7 @@ int MainMenu( int menu )
alternatedoloffset = game_cfg->alternatedolstart;
}
reloadblock = game_cfg->iosreloadblock;
returnToLoaderGV = game_cfg->returnTo;
}
else
{
@ -462,6 +463,7 @@ int MainMenu( int menu )
alternatedoloffset = 0;
}
reloadblock = off;
returnToLoaderGV = 1;
}
int ios2;
@ -667,9 +669,17 @@ int MainMenu( int menu )
vipatch = 0;
break;
}
u32 channel = 0;
if( returnToLoaderGV )
{
int idx = titles.FindU32( Settings.returnTo );
if( idx >= 0 )
channel = TITLE_LOWER( titles.At( idx ) );
}
gprintf( "\tDisc_wiiBoot\n" );
ret = Disc_WiiBoot( videoselected, cheat, vipatch, countrystrings, errorfixer002, alternatedol, alternatedoloffset );
ret = Disc_WiiBoot( videoselected, cheat, vipatch, countrystrings, errorfixer002, alternatedol, alternatedoloffset, channel );
if ( ret < 0 )
{
Sys_LoadMenu();

View File

@ -7,6 +7,7 @@
#include "network/networkops.h"
#include "prompts/gameinfo.h"
#include "prompts/DiscBrowser.h"
#include "prompts/TitleBrowser.h"
#include "settings/Settings.h"
#include "wpad.h"
#include "sys.h"

View File

@ -3,6 +3,7 @@
#include <string.h>
#include "dolpatcher.h"
#include "wip.h"
#include "gecko.h"
/** Anti 002 fix for IOS 249 rev > 12 thanks to WiiPower **/
bool Anti_002_fix( u8 * Address, int Size )
@ -280,3 +281,137 @@ void VideoModePatcher( u8 * dst, int len, u8 videoSelected )
Search_and_patch_Video_Modes( dst, len, table );
}
}
//giantpune's magic super patch to return to channels
bool PatchReturnTo( void *Address, int Size, u32 id ) {
if( !id )return 0;
//new __OSLoadMenu() (SM2.0 and higher)
u8 SearchPattern[ 12 ] = { 0x38, 0x80, 0x00, 0x02, 0x38, 0x60, 0x00, 0x01, 0x38, 0xa0, 0x00, 0x00 };
//old _OSLoadMenu() (used in launch games)
u8 SearchPatternB[ 12 ] = { 0x38, 0xC0, 0x00, 0x02, 0x38, 0xA0, 0x00, 0x01, 0x38, 0xE0, 0x00, 0x00 };
//identifier for the safe place
u8 SearchPattern2[ 12 ] = { 0x4D, 0x65, 0x74, 0x72, 0x6F, 0x77, 0x65, 0x72, 0x6B, 0x73, 0x20, 0x54 };
int found = 0;
int patched = 0;
u8 oldSDK = 0;
u32 ad[ 4 ] = { 0, 0, 0, 0 };
void *Addr = Address;
void *Addr_end = Address+Size;
while (Addr <= Addr_end - 12 ) {
//find a safe place or the patch to hang out
if ( ! ad[ 3 ] && memcmp( Addr, SearchPattern2, 12 )==0 ) {
ad[ 3 ] = (u32)Addr + 0x30;
//gprintf("found a safe place @ %08x\n", ad[ 3 ]);
//hexdump( Addr, 0x50 );
}
//find __OSLaunchMenu() and remember some addresses in it
else if ( memcmp( Addr, SearchPattern, 12 )==0 ) {
ad[ found++ ] = (u32)Addr;
}
else if ( ad[ 0 ] && memcmp( Addr, SearchPattern, 8 )==0 ) //after the first match is found, only search the first 8 bytes for the other 2
{
if( !ad[ 1 ] ) ad[ found++ ] = (u32)Addr;
else if( !ad[ 2 ] ) ad[ found++ ] = (u32)Addr;
if( found >= 3 )break;
}
Addr += 4;
}
//check for the older-ass version of the SDK
if( found < 3 && ad[ 3 ] )
{
Addr = Address;
ad[ 0 ] = 0; ad[ 1 ] = 0;
ad[ 2 ] = 0;
found = 0;
oldSDK = 1;
while (Addr <= Addr_end - 12 ) {
//find __OSLaunchMenu() and remember some addresses in it
if ( memcmp( Addr, SearchPatternB, 12 )==0 ) {
ad[ found++ ] = (u32)Addr;
}
else if ( ad[ 0 ] && memcmp( Addr, SearchPatternB, 8 ) == 0 ) //after the first match is found, only search the first 8 bytes for the other 2
{
if( !ad[ 1 ] ) ad[ found++ ] = (u32)Addr;
else if( !ad[ 2 ] ) ad[ found++ ] = (u32)Addr;
if( found >= 3 )break;
}
Addr += 4;
}
}
//if the function is found and if it is not too far into the main.dol
if( found == 3 && ( ad[ 2 ] - ad[ 3 ] < 0x1000001 ) && ad[ 3 ] )
{
//gprintf("patch __OSLaunchMenu( 0x00010001, 0x%08x )\n", id);
u32 nop = 0x60000000;
//the magic that writes the TID to the registers
u8 jump[ 20 ] = { 0x3C, 0x60, 0x00, 0x01, 0x60, 0x63, 0x00, 0x01,
0x3C, 0x80, 0x4A, 0x4F, 0x60, 0x84, 0x44, 0x49,
0x4E, 0x80, 0x00, 0x20 };
if( oldSDK )
{
jump[ 1 ] = 0xA0; //3CA00001 60A50001
jump[ 5 ] = 0xA5; //3CC04A4F 60C64449
jump[ 9 ] = 0xC0;
jump[ 13 ] = 0xC6;
}
//patch the thing to use the new TID
jump[ 10 ] = (u8)( id >> 24 );
jump[ 11 ] = (u8)( id >> 16 );
jump[ 14 ] = (u8)( id >> 8 );
jump[ 15 ] = (u8)id;
void* addr = (u32*)ad[ 3 ];
//write new stuff to memory main.dol in a unused part of the main.dol
memcpy( addr, jump, sizeof( jump ) );
//ES_GetTicketViews()
u32 newval = ( ad[ 3 ] - ad[ 0 ] );
newval &= 0x03FFFFFC;
newval |= 0x48000001;
addr = (u32*)ad[ 0 ];
memcpy( addr, &newval, sizeof( u32 ) );
memcpy( addr + 4, &nop, sizeof( u32 ) );
//gprintf("\t%p -> %08x\n", addr, newval );
//ES_GetTicketViews() again
newval = ( ad[ 3 ] - ad[ 1 ] );
newval &= 0x03FFFFFC;
newval |= 0x48000001;
addr = (u32*)ad[ 1 ];
memcpy( addr, &newval, sizeof( u32 ) );
memcpy( addr + 4, &nop, sizeof( u32 ) );
//gprintf("\t%p -> %08x\n", addr, newval );
//ES_LaunchTitle()
newval = ( ad[ 3 ] - ad[ 2 ] );
newval &= 0x03FFFFFC;
newval |= 0x48000001;
addr = (u32*)ad[ 2 ];
memcpy( addr, &newval, sizeof( u32 ) );
memcpy( addr + 4, &nop, sizeof( u32 ) );
//gprintf("\t%p -> %08x\n", addr, newval );
patched = 1;
}
else
{
gprintf("not patched\n");
gprintf("found %d addresses\n", found);
int i;
for( i = 0; i< 4; i++)
gprintf("ad[ %d ]: %08x\n", i, ad[ i ] );
gprintf("offset : %08x\n", ad[ 2 ] - ad[ 3 ] );
}
return patched;
}

View File

@ -8,5 +8,6 @@ bool NSMBPatch( u8 * Address, int Size );
bool PoPPatch();
bool Search_and_patch_Video_Modes( u8 * Address, u32 Size, GXRModeObj* Table[] );
void VideoModePatcher( u8 * dst, int len, u8 videoSelected );
bool PatchReturnTo( void *Address, int Size, u32 id );
#endif

View File

@ -51,8 +51,191 @@ extern wchar_t *gameFilter;
/********************************************************************************
* TitleBrowser- opens a browser with a list of installed Titles
* relies on code from any title deleter.
*********************************************************************************/
bool TitleSelector( char output[] )
{
gprintf("TitleSelector()\n");
u32 num_titles;
s32 r = -1;
bool ret = false;
u64 *titleList = NULL;
ISFS_Initialize();//initialize for "titles.Exists()"
// Get count of titles of the good titles
num_titles = titles.SetType( 0x10001 );
u32 n = num_titles;
//gprintf("num_titles: %u\n", num_titles );
for ( u32 i = 0; i < n; i++ )
{
u64 tid = titles.Next();
if ( !tid )
{
break;
}
//remove ones not actually installed on the nand
if ( !titles.Exists( tid ) )
{
num_titles--;
}
}
//gprintf("num_titles: %u\n", num_titles );
//make a list of just the tids we are adding to the titlebrowser
titleList = ( u64* )memalign( 32, num_titles * sizeof( u64 ) );
if ( !titleList )
{
gprintf( "TitleLister(): out of memory!\n" );
return false;
}
customOptionList options4( num_titles + 1 );
//write the titles on the option browser
u32 i = 0;
titles.SetType( 0x10001 );
while ( i < num_titles )
{
u64 tid = titles.Next();
if ( !tid )
{
gprintf( "shit happened\n" );
break;
}
if ( !titles.Exists( tid ) )
{
continue;
}
char id[ 5 ];
titles.AsciiTID( tid, ( char* )&id );
char* name = titles.NameOf( tid );
//gprintf("%016llx: %s: %s\n%p\t%p\n", tid, id, name, &id, name );
options4.SetName( i, "%s", id );
options4.SetValue( i, "%s", name ? titles.NameOf( tid ) : tr( "Unknown" ) );
titleList[ i ] = tid;
i++;
}
// gprintf("i: %u\n", i );
//hexdump( titleList, num_titles * sizeof( u64 ) );
options4.SetName( i, " " );
options4.SetValue( i, "%s", tr( "Clear" ) );
ISFS_Deinitialize();
bool exit = false;
GuiSound btnSoundOver( button_over_pcm, button_over_pcm_size, Settings.sfxvolume );
// because destroy GuiSound must wait while sound playing is finished, we use a global sound
if ( !btnClick2 ) btnClick2 = new GuiSound( button_click2_pcm, button_click2_pcm_size, Settings.sfxvolume );
char imgPath[100];
snprintf( imgPath, sizeof( imgPath ), "%sbutton_dialogue_box.png", CFG.theme_path );
GuiImageData btnOutline( imgPath, button_dialogue_box_png );
snprintf( imgPath, sizeof( imgPath ), "%sgamesettings_background.png", CFG.theme_path );
GuiImageData settingsbg( imgPath, settings_background_png );
GuiImage settingsbackground( &settingsbg );
GuiButton settingsbackgroundbtn( settingsbackground.GetWidth(), settingsbackground.GetHeight() );
settingsbackgroundbtn.SetAlignment( ALIGN_LEFT, ALIGN_TOP );
settingsbackgroundbtn.SetPosition( 0, 0 );
settingsbackgroundbtn.SetImage( &settingsbackground );
GuiTrigger trigA;
trigA.SetSimpleTrigger( -1, WPAD_BUTTON_A | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A );
GuiTrigger trigB;
trigB.SetButtonOnlyTrigger( -1, WPAD_BUTTON_B | WPAD_CLASSIC_BUTTON_B, PAD_BUTTON_B );
GuiText cancelBtnTxt( tr( "Back" ), 22, THEME.prompttext );
cancelBtnTxt.SetMaxWidth( btnOutline.GetWidth() - 30 );
GuiImage cancelBtnImg( &btnOutline );
if ( Settings.wsprompt == yes )
{
cancelBtnTxt.SetWidescreen( CFG.widescreen );
cancelBtnImg.SetWidescreen( CFG.widescreen );
}
GuiButton cancelBtn( &cancelBtnImg, &cancelBtnImg, 2, 3, 180, 400, &trigA, &btnSoundOver, btnClick2, 1 );
cancelBtn.SetLabel( &cancelBtnTxt );
cancelBtn.SetTrigger( &trigB );
u8 scrollbaron = 0;
if ( num_titles + 1 > 9 )
scrollbaron = 1;
GuiCustomOptionBrowser optionBrowser4( 396, 280, &options4, CFG.theme_path, "bg_options_gamesettings.png", bg_options_settings_png, scrollbaron, 200 );
optionBrowser4.SetPosition( 0, 90 );
optionBrowser4.SetAlignment( ALIGN_CENTRE, ALIGN_TOP );
GuiTrigger trigZ;
trigZ.SetButtonOnlyTrigger( -1, WPAD_NUNCHUK_BUTTON_Z | WPAD_CLASSIC_BUTTON_ZL, PAD_TRIGGER_Z );
GuiButton screenShotBtn( 0, 0 );
screenShotBtn.SetPosition( 0, 0 );
screenShotBtn.SetTrigger( &trigZ );
HaltGui();
GuiWindow w( screenwidth, screenheight );
w.Append( &settingsbackgroundbtn );
w.Append( &screenShotBtn );
w.Append( &cancelBtn );
w.Append( &optionBrowser4 );
mainWindow->SetState( STATE_DISABLED );
mainWindow->Append( &w );
ResumeGui();
while ( !exit )
{
VIDEO_WaitVSync();
if ( shutdown == 1 ) Sys_Shutdown();
if ( reset == 1 ) Sys_Reboot();
r = optionBrowser4.GetClickedOption();
if ( r > -1 )
{ //if a click happened
if( r < num_titles )
{
u64 tid = titleList[ r ];
sprintf( output, "%08x", TITLE_LOWER( tid ) );
}
else
output[ 0 ] = 0;
ret = true;
exit = true;
}
else if ( cancelBtn.GetState() == STATE_CLICKED )
{
//break the loop and end the function
exit = true;
}
else if ( screenShotBtn.GetState() == STATE_CLICKED )
{
screenShotBtn.ResetState();
ScreenShot();
}
}
HaltGui();
mainWindow->SetState( STATE_DEFAULT );
mainWindow->Remove( &w );
free( titleList );
ResumeGui();
return ret;
}
int TitleBrowser()
{
@ -139,7 +322,7 @@ int TitleBrowser()
char* name = titles.NameOf( tid );
options3.SetName( i, "%s", id );
options3.SetValue( i, "%s", name ? titles.NameOf( tid ) : "Unknown" );
options3.SetValue( i, "%s", name ? titles.NameOf( tid ) : tr( "Unknown" ) );
titleList[ i ] = tid;
i++;
}
@ -165,7 +348,7 @@ int TitleBrowser()
char* name = titles.NameOf( tid );
options3.SetName( i, "%s", id );
options3.SetValue( i, "%s", name ? titles.NameOf( tid ) : "Unknown" );
options3.SetValue( i, "%s", name ? titles.NameOf( tid ) : tr( "Unknown" ) );
titleList[ i ] = tid;
i++;
}
@ -526,10 +709,8 @@ int TitleBrowser()
}
else if ( screenShotBtn.GetState() == STATE_CLICKED )
{
gprintf( "\n\tscreenShotBtn clicked" );
screenShotBtn.ResetState();
ScreenShot();
gprintf( "...It's easy, mmmmmmKay" );
}
}

View File

@ -9,5 +9,6 @@
#define _TITLEBROWSER_H_
int TitleBrowser();
bool TitleSelector( char output[] );
#endif

View File

@ -21,6 +21,7 @@
#include "usbloader/utils.h"
#include "xml/xml.h"
#include "wad/nandtitle.h"
#include "prompts/TitleBrowser.h"
#define MAXOPTIONS 13
@ -1084,6 +1085,29 @@ int MenuSettings()
options2.SetValue( Idx, "%s", tr( opts_no_yes[Settings.fullcopy] ) );
}
if ( ret == ++Idx || firstRun )
{
char* name = NULL;
if ( firstRun ) options2.SetName( Idx, "%s", tr( "Return To" ) );
if ( ret == Idx )
{
char tidChar[ 10 ];
bool getChannel = TitleSelector( tidChar );
if( getChannel )
{
snprintf( Settings.returnTo, sizeof( Settings.returnTo ), "%s", tidChar );
}
}
int haveTitle = titles.FindU32( Settings.returnTo );
if( haveTitle >= 0 )
{
name = titles.NameFromIndex( haveTitle );
if( !strlen( name ) )
name = NULL;
}
options2.SetValue( Idx, "%s", name ? name : tr( opts_off_on[ 0 ] ) );
}
firstRun = false;
}
}
@ -2467,6 +2491,7 @@ int GameSettings( struct discHdr * header )
alternatedoloffset = game_cfg->alternatedolstart;
reloadblock = game_cfg->iosreloadblock;
strlcpy( alternatedname, game_cfg->alternatedolname, sizeof( alternatedname ) );
returnToLoaderGV = game_cfg->returnTo;
}
else
{
@ -2489,6 +2514,7 @@ int GameSettings( struct discHdr * header )
alternatedoloffset = 0;
reloadblock = off;
strcpy( alternatedname, "" );
returnToLoaderGV = 1;
}
ResumeGui();
@ -2521,7 +2547,6 @@ int GameSettings( struct discHdr * header )
w.Remove( &MainButton4 );
exit = false;
options2.SetLength( 0 );
// optionBrowser2.SetScrollbar(1);
w.Append( &optionBrowser2 );
optionBrowser2.SetClickable( true );
ResumeGui();
@ -2667,6 +2692,23 @@ int GameSettings( struct discHdr * header )
options2.SetValue( Idx, "%s", tr( opts_error002[fix002] ) );
}
if ( ret == ++Idx || firstRun )
{
if ( firstRun ) options2.SetName( Idx, "%s", tr( "Return To" ) );
if ( ret == Idx && ++returnToLoaderGV >= settings_off_on_max )
returnToLoaderGV = 0;
char text[ IMET_MAX_NAME_LEN ];
int channel = titles.FindU32( Settings.returnTo );//is the channel set in the global settings actually installed?
if( !returnToLoaderGV || channel < 0 )//channel is not installed or the uer wants to not use it
sprintf( text, "%s", tr( opts_off_on[ 0 ] ) );
else snprintf( text, sizeof( text ), "%s", titles.NameFromIndex( channel ) );
options2.SetValue( Idx, "%s", text );
}
if ( ret == ++Idx || firstRun )
{
if ( firstRun ) options2.SetName( Idx, "%s", tr( "Patch Country Strings" ) );
@ -3004,6 +3046,7 @@ int GameSettings( struct discHdr * header )
iosChoice = i249;
parentalcontrolChoice = 0;
strcpy( alternatedname, "" );
returnToLoaderGV = 1;
CFG_forget_game_opt( header->id );
/* commented because the database language now depends on the main language setting, this could be enabled again if there is a separate language setting for the database
// if default language is different than language from main settings, reload titles

View File

@ -41,6 +41,7 @@ u16 playcount = 0;
u8 listDisplay = 0;
u8 partition = -1;
char alternatedname[40];
u8 returnToLoaderGV = 1; //global variable used for returnToLoaderShit. defaults to "yes, patch return to loader"
struct ID_Title
{
@ -365,6 +366,7 @@ void Global_Default( void )
Settings.tooltips = TooltipsOn;
char * empty = "";
snprintf( Settings.unlockCode, sizeof( Settings.unlockCode ), empty );
snprintf( Settings.returnTo, sizeof( Settings.returnTo ), empty );
// Settings.godmode = 1;
Settings.gamesound = 1;
Settings.parentalcontrol = 0;
@ -1132,6 +1134,11 @@ void global_cfg_set( char *name, char *val )
strlcpy( Settings.unlockCode, val, sizeof( Settings.unlockCode ) );
return;
}
else if ( strcmp( name, "returnTo" ) == 0 )
{
strlcpy( Settings.returnTo, val, sizeof( Settings.returnTo ) );
return;
}
else if ( strcmp( name, "parentalcontrol" ) == 0 )
{
int i;
@ -1492,6 +1499,7 @@ void cfg_set_game_opt( struct Game_CFG *game, u8 *id )
}
game->alternatedolstart = alternatedoloffset;
strlcpy( game->alternatedolname, alternatedname, sizeof( game->alternatedolname ) );
game->returnTo = returnToLoaderGV;
}
struct Game_NUM* cfg_get_game_num( u8 *id )
@ -1602,6 +1610,7 @@ bool cfg_save_global() // save global settings
fprintf( f, "partitions = %d\n ", Settings.partitions_to_install );
fprintf( f, "fullcopy = %d\n ", Settings.fullcopy );
fprintf( f, "beta_upgrades = %d\n ", Settings.beta_upgrades );
fprintf( f, "returnTo = %s\n ", Settings.returnTo );
fclose( f );
return true;
}
@ -1715,6 +1724,10 @@ void game_set( char *name, char *val )
{
strlcpy( game->alternatedolname, opt_val, sizeof( game->alternatedolname ) );
}
if ( strcmp( "returnTo", opt_name ) == 0 )
{
strlcpy( game->returnTo, opt_val, sizeof( game->returnTo ) );
}
}
// next opt
if ( np ) p = np + 1;
@ -1880,6 +1893,7 @@ bool cfg_save_games()
fprintf( f, "loadalternatedol:%d;", cfg_game[i].loadalternatedol );
fprintf( f, "alternatedolstart:%d;", cfg_game[i].alternatedolstart );
fprintf( f, "alternatedolname:%s;\n", cfg_game[i].alternatedolname );
fprintf( f, "returnTo:%s;\n", cfg_game[i].returnTo );
}
fprintf( f, "# END\n" );
fclose( f );
@ -1956,6 +1970,7 @@ bool CFG_reset_all_playcounters()
return true;
}
#if 0
bool cfg_load_global()
{
char GXGlobal_cfg[26];
@ -1989,7 +2004,7 @@ bool cfg_load_global()
Settings.db_JPtoEN = 0;
return cfg_parsefile( GXGlobal_cfg, &global_cfg_set );
}
#endif
struct Game_CFG* CFG_get_game_opt( const u8 *id )

View File

@ -214,6 +214,7 @@ extern "C"
extern u16 playcount;
extern u8 favoritevar;
extern char alternatedname[40];
extern u8 returnToLoaderGV;
struct Game_CFG
@ -231,6 +232,7 @@ extern "C"
u32 alternatedolstart;
u8 patchcountrystrings;
char alternatedolname[40];
u8 returnTo;
};
struct Game_NUM
{
@ -462,6 +464,7 @@ extern "C"
u8 fullcopy;
u8 beta_upgrades;
struct SParental parental;
char returnTo[ 20 ];
};
extern struct SSettings Settings;

View File

@ -59,7 +59,7 @@ void gamepatches( void * dst, int len, u8 videoSelected, u8 patchcountrystring,
Anti_002_fix( dst, len );
}
s32 Apploader_Run( entry_point *entry, u8 cheat, u8 videoSelected, u8 vipatch, u8 patchcountrystring, u8 error002fix, u8 alternatedol, u32 alternatedoloffset )
s32 Apploader_Run( entry_point *entry, u8 cheat, u8 videoSelected, u8 vipatch, u8 patchcountrystring, u8 error002fix, u8 alternatedol, u32 alternatedoloffset, u32 returnTo )
{
app_entry appldr_entry;
app_init appldr_init;
@ -102,6 +102,9 @@ s32 Apploader_Run( entry_point *entry, u8 cheat, u8 videoSelected, u8 vipatch, u
*( u32 * )0x80003188 = *( u32 * )0x80003140;
}
u32 dolStart = 0x90000000;
u32 dolEnd = 0x0;
for ( ;; )
{
void *dst = NULL;
@ -117,6 +120,18 @@ s32 Apploader_Run( entry_point *entry, u8 cheat, u8 videoSelected, u8 vipatch, u
gamepatches( dst, len, videoSelected, patchcountrystring, vipatch, cheat );
DCFlushRange( dst, len );
if( (u32)dst < dolStart )dolStart = (u32)dst;
if( (u32)dst + len > dolEnd ) dolEnd = (u32)dst + len;
}
//this patch should be run on the entire dol at 1 time
if( !alternatedol && returnTo)
{
if( PatchReturnTo( (u32*)dolStart, dolEnd - dolStart , returnTo) )
{
DCFlushRange( (u32*)dolStart, dolEnd - dolStart );
}
}
*entry = appldr_final();

View File

@ -7,11 +7,11 @@ extern "C"
#endif
/* Entry point */
typedef void ( *entry_point )( void );
typedef void ( *entry_point )( void );
/* Prototypes */
s32 Apploader_Run( entry_point *, u8, u8, u8, u8, u8, u8, u32 );
void gamepatches( void * dst, int len, u8 videoSelected, u8 patchcountrystring, u8 vipatch, u8 cheat );
s32 Apploader_Run( entry_point *entry, u8 cheat, u8 videoSelected, u8 vipatch, u8 patchcountrystring, u8 error002fix, u8 alternatedol, u32 alternatedoloffset, u32 returnTo );
void gamepatches( void * dst, int len, u8 videoSelected, u8 patchcountrystring, u8 vipatch, u8 cheat );
#ifdef __cplusplus
}

View File

@ -296,7 +296,7 @@ s32 Disc_IsWii( void )
return 0;
}
s32 Disc_BootPartition( u64 offset, u8 videoselected, u8 cheat, u8 vipatch, u8 patchcountrystring, u8 error002fix, u8 alternatedol, u32 alternatedoloffset )
s32 Disc_BootPartition( u64 offset, u8 videoselected, u8 cheat, u8 vipatch, u8 patchcountrystring, u8 error002fix, u8 alternatedol, u32 alternatedoloffset, u32 returnTo )
{
entry_point p_entry;
@ -320,7 +320,7 @@ s32 Disc_BootPartition( u64 offset, u8 videoselected, u8 cheat, u8 vipatch, u8 p
PoPPatch();
/* Run apploader */
ret = Apploader_Run( &p_entry, cheat, videoselected, vipatch, patchcountrystring, error002fix, alternatedol, alternatedoloffset );
ret = Apploader_Run( &p_entry, cheat, videoselected, vipatch, patchcountrystring, error002fix, alternatedol, alternatedoloffset, returnTo );
if ( ret < 0 )
return ret;
@ -397,7 +397,7 @@ s32 Disc_BootPartition( u64 offset, u8 videoselected, u8 cheat, u8 vipatch, u8 p
return 0;
}
s32 Disc_WiiBoot( u8 videoselected, u8 cheat, u8 vipatch, u8 patchcountrystring, u8 error002fix, u8 alternatedol, u32 alternatedoloffset )
s32 Disc_WiiBoot( u8 videoselected, u8 cheat, u8 vipatch, u8 patchcountrystring, u8 error002fix, u8 alternatedol, u32 alternatedoloffset, u32 returnTo )
{
u64 offset;
s32 ret;
@ -408,7 +408,7 @@ s32 Disc_WiiBoot( u8 videoselected, u8 cheat, u8 vipatch, u8 patchcountrystring,
return ret;
/* Boot partition */
return Disc_BootPartition( offset, videoselected, cheat, vipatch, patchcountrystring, error002fix, alternatedol, alternatedoloffset );
return Disc_BootPartition( offset, videoselected, cheat, vipatch, patchcountrystring, error002fix, alternatedol, alternatedoloffset, returnTo );
}

View File

@ -50,8 +50,8 @@ extern "C"
s32 Disc_SetUSB( const u8 * );
s32 Disc_ReadHeader( void * );
s32 Disc_IsWii( void );
s32 Disc_BootPartition( u64, u8, u8, u8, u8, u8, u8, u32 );
s32 Disc_WiiBoot( u8, u8, u8, u8, u8, u8, u32 );
s32 Disc_BootPartition( u64, u8, u8, u8, u8, u8, u8, u32, u32 returnTo );
s32 Disc_WiiBoot( u8, u8, u8, u8, u8, u8, u32, u32 returnTo );
s32 __Disc_FindPartition( u64 *outbuf );
void PatchCountryStrings( void *Address, int Size );
s32 __Disc_FindPartition( u64 *outbuf );

View File

@ -8,6 +8,23 @@ extern "C"
static u8 tmd_buf[ MAX_SIGNED_TMD_SIZE ] ATTRIBUTE_ALIGN( 32 );
//based on one from comex's nand formatter
static u64 atoi_hex( const char *s ) {
u64 ret=0;
u32 n = strlen( s );
for( u32 i = 0; i < n; i++) {
if(s[i] > 0x39) {
ret += (s[i] & ~0x20) - 0x37;
} else {
ret += (s[i]-0x30);
}
if (i != (n-1)) ret *= 16;
}
return ret;
}
NandTitle::NandTitle()
{
numTitles = 0;
@ -444,3 +461,20 @@ err:
return ret;
}
int NandTitle::FindU64( const char *s )
{
u64 tid = atoi_hex( s );
return IndexOf( tid );
}
int NandTitle::FindU32( const char *s )
{
u64 tid = atoi_hex( s );
for ( u32 i = 0; i < numTitles; i++ )
{
if ( TITLE_LOWER( list[ i ] ) == TITLE_LOWER( tid ) )
return i;
}
return WII_EINSTALL;
}

View File

@ -86,6 +86,9 @@ class NandTitle
bool Exists( u64 tid );
bool ExistsFromIndex( u32 i );
int FindU64( const char *s );
int FindU32( const char *s );
s32 GetTicketViews( u64 tid, tikview **outbuf, u32 *outlen );
u64 operator[]( u32 i ) { return At( i ); }