usbloadergx/source/prompts/TitleBrowser.cpp

731 lines
19 KiB
C++
Raw Normal View History

/****************************************************************************
* TitleBrowser
* USB Loader GX 2009
*
* TitleBrowser.cpp *giantpune*
***************************************************************************/
#include <dirent.h>
#include "language/gettext.h"
#include "libwiigui/gui.h"
#include "libwiigui/gui_customoptionbrowser.h"
#include "prompts/PromptWindows.h"
#include "prompts/ProgressWindow.h"
#include "network/networkops.h"
#include "network/http.h"
#include "filelist.h"
#include "listfiles.h"
#include "settings/cfg.h"
#include "sys.h"
#include "menu.h"
#include "audio.h"
#include "wad/wad.h"
#include "xml/xml.h"
#include "wad/nandtitle.h"
#include "../usbloader/utils.h"
#include "../gecko.h"
u32 titleCnt;
extern u32 infilesize;
extern u32 uncfilesize;
extern char wiiloadVersion[2];
#include <zlib.h>
#include "settings/cfg.h"
#include "unzip/unzip.h"
#include "unzip/miniunz.h"
/*** Extern functions ***/
extern void ResumeGui();
extern void HaltGui();
/*** Extern variables ***/
extern GuiWindow * mainWindow;
extern u8 shutdown;
extern u8 reset;
extern u32 infilesize;
extern wchar_t *gameFilter;
/********************************************************************************
* TitleBrowser- opens a browser with a list of installed Titles
*********************************************************************************/
bool TitleSelector( char output[] )
{
gprintf("TitleSelector()\n");
s32 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
s32 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 );
2010-09-19 15:03:16 +02:00
const 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()
{
u32 num_titles;
u32 num_sys_titles;
s32 ret = -1;
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;
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--;
}
}
// Get count of system titles
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--;
}
}
//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;
}
customOptionList options3( num_titles + num_sys_titles + 1 );
//write the titles on the option browser
u32 i = 0;
titles.SetType( 0x10001 );
//first add the good stuff
while ( i < num_titles )
{
u64 tid = titles.Next();
if ( !tid )
{
gprintf( "shit happened3\n" );
break;
}
2010-09-19 15:03:16 +02:00
gprintf("[ %u ] tid: %016llx\t%s\n", i, tid, titles.NameOf( tid ) );
if ( !titles.Exists( tid ) )
{
continue;
}
char id[ 5 ];
titles.AsciiTID( tid, ( char* )&id );
2010-09-19 15:03:16 +02:00
const char* name = titles.NameOf( tid );
options3.SetName( i, "%s", id );
options3.SetValue( i, "%s", name ? titles.NameOf( tid ) : tr( "Unknown" ) );
titleList[ i ] = tid;
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 );
2010-09-19 15:03:16 +02:00
const char* name = titles.NameOf( tid );
options3.SetName( i, "%s", id );
options3.SetValue( i, "%s", name ? titles.NameOf( tid ) : tr( "Unknown" ) );
titleList[ i ] = tid;
i++;
}
ISFS_Deinitialize();
if ( i == num_titles + num_sys_titles )
{
options3.SetName( i, " " );
options3.SetValue( i, "%s", tr( "Wii Settings" ) );
}
bool exit = false;
int total = num_titles + num_sys_titles;
if ( IsNetworkInit() )
ResumeNetworkWait();
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 );
// GuiSound btnClick(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 );
GuiTrigger trigA;
trigA.SetSimpleTrigger( -1, WPAD_BUTTON_A | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A );
GuiTrigger trigHome;
trigHome.SetButtonOnlyTrigger( -1, WPAD_BUTTON_HOME | WPAD_CLASSIC_BUTTON_HOME, 0 );
GuiTrigger trigB;
trigB.SetButtonOnlyTrigger( -1, WPAD_BUTTON_B | WPAD_CLASSIC_BUTTON_B, PAD_BUTTON_B );
GuiText titleTxt( tr( "Title Launcher" ), 28, ( GXColor ) {0, 0, 0, 255} );
titleTxt.SetAlignment( ALIGN_CENTRE, ALIGN_TOP );
titleTxt.SetPosition( 12, 40 );
titleTxt.SetMaxWidth( 356, SCROLL_HORIZONTAL );
GuiImage settingsbackground( &settingsbg );
GuiButton settingsbackgroundbtn( settingsbackground.GetWidth(), settingsbackground.GetHeight() );
settingsbackgroundbtn.SetAlignment( ALIGN_LEFT, ALIGN_TOP );
settingsbackgroundbtn.SetPosition( 0, 0 );
settingsbackgroundbtn.SetImage( &settingsbackground );
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.SetScale( 0.9 );
cancelBtn.SetLabel( &cancelBtnTxt );
cancelBtn.SetTrigger( &trigB );
u8 scrollbaron = 0;
if ( total + 1 > 9 )
scrollbaron = 1;
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 );
snprintf( imgPath, sizeof( imgPath ), "%sWifi_btn.png", CFG.theme_path );
GuiImageData wifiImgData( imgPath, Wifi_btn_png );
GuiImage wifiImg( &wifiImgData );
if ( Settings.wsprompt == yes )
{
wifiImg.SetWidescreen( CFG.widescreen );
}
GuiButton wifiBtn( wifiImg.GetWidth(), wifiImg.GetHeight() );
wifiBtn.SetImage( &wifiImg );
wifiBtn.SetPosition( 100, 400 );
wifiBtn.SetEffectGrow();
wifiBtn.SetAlpha( 80 );
wifiBtn.SetTrigger( &trigA );
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( &screenShotBtn );
w.Append( &settingsbackgroundbtn );
w.Append( &titleTxt );
w.Append( &cancelBtn );
w.Append( &wifiBtn );
w.Append( &optionBrowser3 );
mainWindow->Append( &w );
ResumeGui();
while ( !exit )
{
VIDEO_WaitVSync();
if ( shutdown == 1 ) Sys_Shutdown();
if ( reset == 1 ) Sys_Reboot();
else if ( wifiBtn.GetState() == STATE_CLICKED )
{
ResumeNetworkWait();
wifiBtn.ResetState();
}
if ( IsNetworkInit() )
{
wifiBtn.SetAlpha( 255 );
}
ret = optionBrowser3.GetClickedOption();
if ( ret > -1 )
{ //if a click happened
if ( ret < total )
{
//set the title's name, number, ID to text
char text[ 0x100 ];
char id[ 5 ];
titles.AsciiTID( titleList[ ret ], ( char* )&id );
snprintf( text, sizeof( text ), "%s : %s", id, titles.NameOf( titleList[ ret ] ) );
//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( titleList[ ret ] );
//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();
}
}
else if ( ret == total )
{ //if they clicked to go to the wii settings
CloseXMLDatabase();
ExitGUIThreads();
ShutdownAudio();
StopGX();
WII_Initialize();
WII_ReturnToSettings();
}
}
#if 0
if ( infilesize > 0 )
{
char filesizetxt[50];
char temp[50];
char filepath[100];
// u32 read = 0;
//make sure there is a folder for this to be saved in
struct stat st;
snprintf( filepath, sizeof( filepath ), "%s/wad/", bootDevice );
if ( stat( filepath, &st ) != 0 )
{
if ( subfoldercreate( filepath ) != 1 )
{
WindowPrompt( tr( "Error !" ), tr( "Can't create directory" ), tr( "OK" ) );
}
}
snprintf( filepath, sizeof( filepath ), "%s/wad/tmp.tmp", bootDevice );
if ( infilesize < MB_SIZE )
snprintf( filesizetxt, sizeof( filesizetxt ), tr( "Incoming file %0.2fKB" ), infilesize / KB_SIZE );
else
snprintf( filesizetxt, sizeof( filesizetxt ), tr( "Incoming file %0.2fMB" ), infilesize / MB_SIZE );
snprintf( temp, sizeof( temp ), tr( "Load file from: %s ?" ), GetIncommingIP() );
int choice = WindowPrompt( filesizetxt, temp, tr( "OK" ), tr( "Cancel" ) );
gprintf( "\nchoice:%d", choice );
if ( choice == 1 )
{
u32 read = 0;
u8 *temp = NULL;
int len = NETWORKBLOCKSIZE;
temp = ( u8 * ) malloc( infilesize );
bool error = false;
u8 *ptr = temp;
gprintf( "\nrecieving shit" );
while ( read < infilesize )
{
ShowProgress( tr( "Receiving file from:" ), GetIncommingIP(), NULL, read, infilesize, true );
if ( infilesize - read < ( u32 ) len )
len = infilesize - read;
else
len = NETWORKBLOCKSIZE;
int result = network_read( ptr, len );
if ( result < 0 )
{
WindowPrompt( tr( "Error while transfering data." ), 0, tr( "OK" ) );
error = true;
break;
}
if ( !result )
{
gprintf( "\n!RESULT" );
break;
}
ptr += result;
read += result;
}
ProgressStop();
char filename[101];
char tmptxt[200];
//bool installWad=0;
if ( !error )
{
gprintf( "\nno error yet" );
network_read( ( u8* ) &filename, 100 );
gprintf( "\nfilename: %s", filename );
// Do we need to unzip this thing?
if ( wiiloadVersion[0] > 0 || wiiloadVersion[1] > 4 )
{
gprintf( "\nusing newer wiiload version" );
if ( uncfilesize != 0 ) // if uncfilesize == 0, it's not compressed
{
gprintf( "\ntrying to uncompress" );
// It's compressed, uncompress
u8 *unc = ( u8 * ) malloc( uncfilesize );
uLongf f = uncfilesize;
error = uncompress( unc, &f, temp, infilesize ) != Z_OK;
uncfilesize = f;
free( temp );
temp = unc;
}
}
if ( !error )
{
sprintf( tmptxt, "%s", filename );
//if we got a wad
if ( strcasestr( tmptxt, ".wad" ) )
{
FILE *file = fopen( filepath, "wb" );
fwrite( temp, 1, ( uncfilesize > 0 ? uncfilesize : infilesize ), file );
fclose( file );
sprintf( tmptxt, "%s/wad/%s", bootDevice, filename );
if ( checkfile( tmptxt ) )remove( tmptxt );
rename( filepath, tmptxt );
//check and make sure the wad we just saved is the correct size
u32 lSize;
file = fopen( tmptxt, "rb" );
// obtain file size:
fseek ( file , 0 , SEEK_END );
lSize = ftell ( file );
rewind ( file );
if ( lSize == ( uncfilesize > 0 ? uncfilesize : infilesize ) )
{
gprintf( "\nsize is ok" );
int pick = WindowPrompt( tr( " Wad Saved as:" ), tmptxt, tr( "Install" ), tr( "Uninstall" ), tr( "Cancel" ) );
//install or uninstall it
if ( pick == 1 )
{
HaltGui();
w.Remove( &titleTxt );
w.Remove( &cancelBtn );
w.Remove( &wifiBtn );
w.Remove( &optionBrowser3 );
ResumeGui();
Wad_Install( file );
HaltGui();
w.Append( &titleTxt );
w.Append( &cancelBtn );
w.Append( &wifiBtn );
w.Append( &optionBrowser3 );
ResumeGui();
}
if ( pick == 2 )Wad_Uninstall( file );
}
else gprintf( "\nBad size" );
//close that beast, we're done with it
fclose ( file );
//do we want to keep the file in the wad folder
if ( WindowPrompt( tr( "Delete ?" ), tmptxt, tr( "Delete" ), tr( "Keep" ) ) != 0 )
remove( tmptxt );
}
else
{
WindowPrompt( tr( "ERROR:" ), tr( "Not a WAD file." ), tr( "OK" ) );
}
}
}
if ( error || read != infilesize )
{
WindowPrompt( tr( "Error:" ), tr( "No data could be read." ), tr( "OK" ) );
}
if ( temp )free( temp );
}
CloseConnection();
ResumeNetworkWait();
}
#endif
if ( cancelBtn.GetState() == STATE_CLICKED )
{
//break the loop and end the function
exit = true;
ret = -10;
}
else if ( screenShotBtn.GetState() == STATE_CLICKED )
{
screenShotBtn.ResetState();
ScreenShot();
}
}
CloseConnection();
if ( IsNetworkInit() )
HaltNetworkThread();
HaltGui();
mainWindow->Remove( &w );
free( titleList );
ResumeGui();
return ret;
}