usbloadergx/source/menu.cpp

362 lines
10 KiB
C++
Raw Normal View History

/****************************************************************************
* USB Loader GX Team
*
* libwiigui Template
* by Tantric 2009
*
* menu.cpp
* Menu flow routines - handles all menu logic
***************************************************************************/
#include <unistd.h>
#include "libwiigui/gui.h"
#include "homebrewboot/BootHomebrew.h"
#include "homebrewboot/HomebrewBrowse.h"
#include "prompts/ProgressWindow.h"
#include "menu/menus.h"
#include "mload/mload.h"
#include "mload/mload_modules.h"
#include "network/networkops.h"
#include "patches/patchcode.h"
#include "settings/Settings.h"
#include "settings/CGameSettings.h"
#include "themes/CTheme.h"
#include "themes/Theme_Downloader.h"
#include "usbloader/disc.h"
#include "usbloader/GameList.h"
#include "mload/mload_modules.h"
#include "xml/xml.h"
#include "audio.h"
#include "gecko.h"
#include "menu.h"
#include "sys.h"
#include "wpad.h"
#include "settings/newtitles.h"
#include "patches/fst.h"
#include "usbloader/frag.h"
#include "usbloader/wbfs.h"
#include "wad/nandtitle.h"
#include "GameBootProcess.h"
/*** Variables that are also used extern ***/
GuiWindow * mainWindow = NULL;
GuiImageData * pointer[4];
GuiImage * bgImg = NULL;
GuiImageData * background = NULL;
GuiBGM * bgMusic = NULL;
GuiSound *btnClick2 = NULL;
int currentMenu;
u8 mountMethod = 0;
char game_partition[6];
int load_from_fs;
/*** Variables used only in the menus ***/
GuiText * GameIDTxt = NULL;
GuiText * GameRegionTxt = NULL;
GuiImage * coverImg = NULL;
GuiImageData * cover = NULL;
bool altdoldefault = true;
static lwp_t guithread = LWP_THREAD_NULL;
static bool guiHalt = true;
static int ExitRequested = 0;
/*** Extern variables ***/
extern u8 shutdown;
extern u8 reset;
extern s32 gameSelected, gameStart;
extern u8 boothomebrew;
/****************************************************************************
* ResumeGui
*
* Signals the GUI thread to start, and resumes the thread. This is called
* after finishing the removal/insertion of new elements, and after initial
* GUI setup.
***************************************************************************/
void ResumeGui()
{
guiHalt = false;
2010-09-24 02:48:03 +02:00
LWP_ResumeThread(guithread);
}
/****************************************************************************
* HaltGui
*
* Signals the GUI thread to stop, and waits for GUI thread to stop
* This is necessary whenever removing/inserting new elements into the GUI.
* This eliminates the possibility that the GUI is in the middle of accessing
* an element that is being changed.
***************************************************************************/
void HaltGui()
{
2010-09-24 02:48:03 +02:00
if (guiHalt) return;
guiHalt = true;
// wait for thread to finish
2010-09-24 02:48:03 +02:00
while (!LWP_ThreadIsSuspended(guithread))
usleep(50);
}
/****************************************************************************
* UpdateGUI
*
* Primary thread to allow GUI to respond to state changes, and draws GUI
***************************************************************************/
2010-09-24 02:48:03 +02:00
static void * UpdateGUI(void *arg)
{
int i;
2010-09-24 02:48:03 +02:00
while (!ExitRequested)
{
2010-09-24 02:48:03 +02:00
if (guiHalt)
{
2010-09-24 02:48:03 +02:00
LWP_SuspendThread(guithread);
continue;
}
mainWindow->Draw();
2010-10-27 16:45:27 +02:00
if (Settings.tooltips == ON && Theme.show_tooltip != 0 && mainWindow->GetState() != STATE_DISABLED) mainWindow->DrawTooltip();
2010-09-24 02:48:03 +02:00
for (i = 3; i >= 0; i--)
{
2010-09-24 02:48:03 +02:00
if (userInput[i].wpad.ir.valid)
{
2010-09-24 02:48:03 +02:00
Menu_DrawImg(userInput[i].wpad.ir.x - 48, userInput[i].wpad.ir.y - 48, 200.0, 96, 96,
pointer[i]->GetImage(), userInput[i].wpad.ir.angle, Settings.widescreen ? 0.8 : 1, 1, 255, 0,
0, 0, 0, 0, 0, 0, 0);
}
}
Menu_Render();
UpdatePads();
2010-09-24 02:48:03 +02:00
for (i = 0; i < 4; i++)
mainWindow->Update(&userInput[i]);
2010-09-24 02:48:03 +02:00
if (bgMusic) bgMusic->UpdateState();
2010-09-24 02:48:03 +02:00
switch (Settings.screensaver)
{
case 1:
2010-09-24 02:48:03 +02:00
WPad_SetIdleTime(180);
break;
case 2:
2010-09-24 02:48:03 +02:00
WPad_SetIdleTime(300);
break;
case 3:
2010-09-24 02:48:03 +02:00
WPad_SetIdleTime(600);
break;
case 4:
2010-09-24 02:48:03 +02:00
WPad_SetIdleTime(1200);
break;
case 5:
2010-09-24 02:48:03 +02:00
WPad_SetIdleTime(1800);
break;
case 6:
2010-09-24 02:48:03 +02:00
WPad_SetIdleTime(3600);
break;
}
}
2010-09-24 02:48:03 +02:00
for (i = 5; i < 255; i += 10)
{
mainWindow->Draw();
2010-09-26 20:19:45 +02:00
Menu_DrawRectangle(0, 0, screenwidth, screenheight, (GXColor) {0, 0, 0, i}, 1);
Menu_Render();
}
mainWindow->RemoveAll();
ShutoffRumble();
return NULL;
}
/****************************************************************************
* InitGUIThread
*
* Startup GUI threads
***************************************************************************/
void InitGUIThreads()
{
2010-09-24 02:48:03 +02:00
LWP_CreateThread(&guithread, UpdateGUI, NULL, NULL, 65536, LWP_PRIO_HIGHEST);
InitProgressThread();
InitNetworkThread();
2010-09-24 02:48:03 +02:00
if (Settings.autonetwork) ResumeNetworkThread();
}
void ExitGUIThreads()
{
ExitRequested = 1;
2010-09-24 02:48:03 +02:00
LWP_JoinThread(guithread, NULL);
guithread = LWP_THREAD_NULL;
}
/****************************************************************************
* LoadCoverImage
***************************************************************************/
2010-09-24 02:48:03 +02:00
GuiImageData *LoadCoverImage(struct discHdr *header, bool Prefere3D, bool noCover)
{
2010-09-24 02:48:03 +02:00
if (!header) return NULL;
GuiImageData *Cover = NULL;
char ID[4];
char IDfull[7];
char Path[100];
bool flag = Prefere3D;
2010-09-24 02:48:03 +02:00
snprintf(ID, sizeof(ID), "%c%c%c", header->id[0], header->id[1], header->id[2]);
snprintf(IDfull, sizeof(IDfull), "%s%c%c%c", ID, header->id[3], header->id[4], header->id[5]);
2010-09-24 02:48:03 +02:00
for (int i = 0; i < 2; ++i)
{
2010-09-24 02:48:03 +02:00
char *coverPath = flag ? Settings.covers_path : Settings.covers2d_path;
flag = !flag;
//Load full id image
2010-09-24 02:48:03 +02:00
snprintf(Path, sizeof(Path), "%s%s.png", coverPath, IDfull);
delete Cover;
Cover = new (std::nothrow) GuiImageData(Path);
//Load short id image
2010-09-24 02:48:03 +02:00
if (!Cover || !Cover->GetImage())
{
2010-09-24 02:48:03 +02:00
snprintf(Path, sizeof(Path), "%s%s.png", coverPath, ID);
delete Cover;
Cover = new (std::nothrow) GuiImageData(Path);
}
2010-09-24 02:48:03 +02:00
if (Cover && Cover->GetImage()) break;
}
//Load no image
2010-09-24 02:48:03 +02:00
if (noCover && (!Cover || !Cover->GetImage()))
{
flag = Prefere3D;
2010-09-24 02:48:03 +02:00
for (int i = 0; i < 2; ++i)
{
2010-09-24 02:48:03 +02:00
flag = !flag;
delete Cover;
2010-09-26 20:19:45 +02:00
Cover = Resources::GetImageData(Prefere3D ? "nocover.png" : "nocoverFlat.png");
2010-09-24 02:48:03 +02:00
if (Cover && Cover->GetImage()) break;
}
}
2010-09-24 02:48:03 +02:00
if (Cover && !Cover->GetImage())
{
delete Cover;
Cover = NULL;
}
return Cover;
}
/****************************************************************************
* MainMenu
***************************************************************************/
2010-09-24 02:48:03 +02:00
int MainMenu(int menu)
{
currentMenu = menu;
MountGamePartition();
2010-09-26 20:19:45 +02:00
pointer[0] = Resources::GetImageData("player1_point.png");
pointer[1] = Resources::GetImageData("player2_point.png");
pointer[2] = Resources::GetImageData("player3_point.png");
pointer[3] = Resources::GetImageData("player4_point.png");
2010-09-24 02:48:03 +02:00
mainWindow = new GuiWindow(screenwidth, screenheight);
2010-09-26 20:19:45 +02:00
background = Resources::GetImageData(Settings.widescreen ? "wbackground.png" : "background.png");
2010-09-24 02:48:03 +02:00
bgImg = new GuiImage(background);
mainWindow->Append(bgImg);
ResumeGui();
2010-09-24 02:48:03 +02:00
bgMusic = new GuiBGM(bg_music_ogg, bg_music_ogg_size, Settings.volume);
bgMusic->SetLoop(Settings.musicloopmode); //loop music
bgMusic->Load(Settings.ogg_path);
bgMusic->Play();
2010-09-24 02:48:03 +02:00
while (currentMenu != MENU_EXIT)
{
2010-09-24 02:48:03 +02:00
bgMusic->SetVolume(Settings.volume);
// gprintf("Current menu: %d\n", currentMenu);
2010-09-24 02:48:03 +02:00
switch (currentMenu)
{
case MENU_INSTALL:
currentMenu = MenuInstall();
break;
case MENU_SETTINGS:
currentMenu = MenuSettings();
break;
case MENU_THEMEDOWNLOADER:
currentMenu = Theme_Downloader();
break;
case MENU_HOMEBREWBROWSE:
currentMenu = MenuHomebrewBrowse();
break;
case MENU_DISCLIST:
default: // unrecognized menu
currentMenu = MenuDiscList();
break;
}
}
// MemInfoPrompt();
2010-09-24 02:48:03 +02:00
gprintf("Exiting main GUI. mountMethod = %d\n", mountMethod);
CloseXMLDatabase();
NewTitles::DestroyInstance();
2010-01-20 19:33:30 +01:00
ResumeGui();
ExitGUIThreads();
bgMusic->Stop();
delete bgMusic;
delete background;
delete bgImg;
delete mainWindow;
2010-09-24 02:48:03 +02:00
for (int i = 0; i < 4; i++)
delete pointer[i];
delete GameRegionTxt;
delete GameIDTxt;
delete cover;
delete coverImg;
delete fontSystem;
ShutdownAudio();
StopGX();
gettextCleanUp();
2010-09-24 02:48:03 +02:00
if (mountMethod == 3)
{
struct discHdr *header = gameList[gameSelected];
char tmp[20];
u32 tid;
2010-09-24 02:48:03 +02:00
sprintf(tmp, "%c%c%c%c", header->id[0], header->id[1], header->id[2], header->id[3]);
memcpy(&tid, tmp, 4);
gprintf("\nBooting title %016llx", TITLE_ID( ( header->id[5] == '1' ? 0x00010001 : 0x00010002 ), tid ));
WII_Initialize();
2010-09-24 02:48:03 +02:00
WII_LaunchTitle(TITLE_ID( ( header->id[5] == '1' ? 0x00010001 : 0x00010002 ), tid ));
}
2010-09-24 02:48:03 +02:00
if (mountMethod == 2)
{
2010-09-24 02:48:03 +02:00
gprintf("\nLoading BC for GameCube");
WII_Initialize();
2010-09-24 02:48:03 +02:00
WII_LaunchTitle(0x0000000100000100ULL);
}
2010-09-24 02:48:03 +02:00
if (boothomebrew == 1)
{
2010-09-24 02:48:03 +02:00
gprintf("\nBootHomebrew");
BootHomebrew(Settings.selected_homebrew);
return 0;
}
2010-09-24 02:48:03 +02:00
else if (boothomebrew == 2)
{
2010-09-24 02:48:03 +02:00
gprintf("\nBootHomebrew from Menu");
BootHomebrewFromMem();
return 0;
}
return BootGame((const char *) gameList[gameSelected]->id);
}