usbloadergx/source/prompts/TitleBrowser.cpp
dimok321 15bcbfa482 *Finished the background initialization thread for devices started by giantpune and merged it into trunk. Now you can startup the loader without a HDD. Also you can put in your device after startup and it will be recognized. Hot swapping not yet added (as in remove and than stick it in).
You will see the list of available channels on your system if you start without a HDD or if your HDD is slow and is being recognized late. The list of games is than reloading as soon as it is recognized.
*Hot swapping of the SD card was implemented into background thread (by giantpune)
*Made lots of cleanups and some fixes
*Format menu was moved to settings page 3 (only on godmode accessable)
*Added ScreenShot and Reset/Shutdown call to background thread. Removed the not needed ones. Now you can call for Screenshot/Reset/Shutdown anywhere in the loader (after gui is started).
2010-01-06 23:07:35 +00:00

548 lines
18 KiB
C++

/****************************************************************************
* 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 "../menu/menus.h"
#include "audio.h"
#include "wad/wad.h"
#include "xml/xml.h"
#include "../wad/title.h"
#include "../usbloader/getentries.h"
#include "../usbloader/utils.h"
#include "../gecko.h"
#define typei 0x00010001
struct discHdr * titleList=NULL;
//discHdr ** titleList;
u32 titleCnt;
extern struct discHdr * gameList;
extern u32 gameCnt;
/*** Extern variables ***/
extern GuiWindow * mainWindow;
extern u32 infilesize;
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) {
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];
ISFS_Initialize();
sprintf(path,"%s/config/database.txt",bootDevice);
f = fopen(path, "r");
// 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);
}
// 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);
}
// Get system titles
ret = getTitles_Type(0x00010002, sys_titles, num_sys_titles);
if (ret < 0) {
//printf("\tError! Can't get list of titles! (ret = %d)\n", ret);
//exit(1);
}
//this array will hold all the names for the titles so we only have to get them one time
char name[num_titles+num_sys_titles][50];
customOptionList options3(num_titles+num_sys_titles+1);
//write the titles on the option browser
u32 i = 0;
//first add the good stuff
while (i < num_titles) {
//start from the beginning of the file each loop
if (f)rewind(f);
//char name[50];
char text[15];
strcpy(name[i],"");//make sure name is empty
u8 found=0;
//set the title's name, number, ID to text
sprintf(text, "%s", titleText(type, titles[i]));
//get name from database cause i dont like the ADT function
char line[200];
char tmp[50];
snprintf(tmp,50," ");
//check if the content.bin is on the SD card for that game
//if there is content.bin,then the game is on the SDmenu and not the wii
sprintf(line,"SD:/private/wii/title/%s/content.bin",text);
if (!checkfile(line))
{
if (f) {
while (fgets(line, sizeof(line), f)) {
if (line[0]== text[0]&&
line[1]== text[1]&&
line[2]== text[2]) {
int j=0;
found=1;
for (j=0;(line[j+4]!='\0' || j<51);j++)
tmp[j]=line[j+4];
snprintf(name[i],sizeof(name[i]),"%s",tmp);
//break;
}
}
}
if (!found) {
if (getName00(name[i], TITLE_ID(type, titles[i]),CONF_GetLanguage()*2)>=0)
found=2;
if (!found) {
if (getNameBN(name[i], TITLE_ID(type, titles[i]))>=0)
found=3;
if (!found)
snprintf(name[i],sizeof(name[i]),"Unknown Title (%08x)",titles[i]);
}
}
//set the text to the option browser
options3.SetName(i, "%s",text);
options3.SetValue(i, "%s",name[i]);
//options3.SetValue(i, " (%08x) %s",titles[i],name[i]);//use this line to show the number to call to launch the channel
//move on to the next title
}
i++;
}
// now add the crappy system titles
while (i < num_titles+num_sys_titles) {
//start from the beginning of the file each loop
if (f)rewind(f);
//char name[50];
char text[15];
strcpy(name[i],"");//make sure name is empty
u8 found=0;
//set the title's name, number, ID to text
sprintf(text, "%s", titleText(0x00010002, sys_titles[i-num_titles]));
//get name from database cause i dont like the ADT function
char line[200];
char tmp[50];
snprintf(tmp,50," ");
//snprintf(name[i],sizeof(name[i]),"Unknown Title");
if (f) {
while (fgets(line, sizeof(line), f)) {
if (line[0]== text[0]&&
line[1]== text[1]&&
line[2]== text[2]) {
int j=0;
found=1;
for (j=0;(line[j+4]!='\0' || j<51);j++)
tmp[j]=line[j+4];
snprintf(name[i],sizeof(name[i]),"%s",tmp);
break;
}
}
}
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;
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, GuiText::SCROLL);
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 (num_titles > 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);
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);
HaltGui();
GuiWindow w(screenwidth, screenheight);
w.Append(&settingsbackgroundbtn);
w.Append(&titleTxt);
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) {
VIDEO_WaitVSync();
if (wifiBtn.GetState() == STATE_CLICKED) {
ResumeNetworkWait();
wifiBtn.ResetState();
}
if (IsNetworkInit()) {
wifiBtn.SetAlpha(255);
}
ret = optionBrowser3.GetClickedOption();
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) {
//set the title's name, number, ID to text
sprintf(text, "%s", titleText(type, titles[ret]));
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
//stop all this stuff before starting the channel
CloseXMLDatabase();
ExitGUIThreads();
ShutdownAudio();
StopGX();
WII_Initialize();
WII_LaunchTitle(TITLE_ID(type,titles[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 they clicked a system title
if (ret == tmp) {
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();
}
}
}
}
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"));
if(choice == 1) {
FILE *file = fopen(filepath, "wb");
int len = NETWORKBLOCKSIZE;
u8 *buffer = (u8*) malloc(NETWORKBLOCKSIZE);
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(buffer, len);
if (result < 0) {
WindowPrompt(tr("Error while transfering data."), 0, tr("OK"));
fclose(file);
remove(filepath);
break;
}
if (!result)
break;
fwrite(temp, 1, len, file);
read += result;
}
free(buffer);
fclose(file);
ProgressStop();
if (read != infilesize) {
WindowPrompt(tr("Error:"), tr("No data could be read."), tr("OK"));
remove(filepath);
} else {
//determine what type of file we just got
char filename[101];
char tmptxt[200];
network_read((u8*) &filename, 100);
sprintf(tmptxt,"%s",filename);
//if we got a wad
if (strcasestr(tmptxt,".wad")) {
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==infilesize) {
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);
}
//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("The file is not a .wad"),tr("OK"));
remove(filepath);
}
}
}
CloseConnection();
ResumeNetworkWait();
}
if (cancelBtn.GetState() == STATE_CLICKED) {
//break the loop and end the function
exit = true;
ret = -10;
}
}
CloseConnection();
if (IsNetworkInit())
HaltNetworkThread();
fclose(f);
HaltGui();
mainWindow->Remove(&w);
ResumeGui();
return ret;
}