mirror of
https://github.com/Fledge68/WiiFlow_Lite.git
synced 2024-11-27 21:54:15 +01:00
1764 lines
54 KiB
C++
1764 lines
54 KiB
C++
|
|
#include <ogc/machine/processor.h>
|
|
#include <ogc/lwp_threads.h>
|
|
#include <unistd.h>
|
|
#include <time.h>
|
|
#include <network.h>
|
|
#include <errno.h>
|
|
|
|
#include "menu.hpp"
|
|
#include "types.h"
|
|
#include "banner/BannerWindow.hpp"
|
|
#include "booter/external_booter.hpp"
|
|
#include "channel/channel_launcher.h"
|
|
#include "channel/channels.h"
|
|
#include "channel/nand.hpp"
|
|
#include "channel/identify.h"
|
|
#include "devicemounter/DeviceHandler.hpp"
|
|
#include "devicemounter/sdhc.h"
|
|
#include "devicemounter/usbstorage.h"
|
|
#include "gc/gc.hpp"
|
|
#include "gc/gcdisc.hpp"
|
|
#include "gui/WiiMovie.hpp"
|
|
#include "gui/GameTDB.hpp"
|
|
#include "gui/Gekko.h"
|
|
#include "homebrew/homebrew.h"
|
|
#include "loader/alt_ios.h"
|
|
#include "loader/wdvd.h"
|
|
#include "loader/alt_ios.h"
|
|
#include "loader/playlog.h"
|
|
#include "loader/wbfs.h"
|
|
#include "loader/wip.h"
|
|
#include "loader/frag.h"
|
|
#include "loader/fst.h"
|
|
#include "loader/cios.h"
|
|
#include "loader/nk.h"
|
|
#include "memory/memory.h"
|
|
#include "network/http.h"
|
|
#include "network/gcard.h"
|
|
|
|
//sounds
|
|
extern const u8 gc_ogg[];
|
|
extern const u32 gc_ogg_size;
|
|
|
|
bool m_zoom_banner = false;
|
|
s16 m_gameBtnPlayFull;
|
|
s16 m_gameBtnBackFull;
|
|
s16 m_gameBtnToogle;
|
|
s16 m_gameBtnToogleFull;
|
|
|
|
const CMenu::SOption CMenu::_languages[11] = {
|
|
{ "lngdef", L"Default" },
|
|
{ "lngjap", L"Japanese" },
|
|
{ "lngeng", L"English" },
|
|
{ "lngger", L"German" },
|
|
{ "lngfre", L"French" },
|
|
{ "lngspa", L"Spanish" },
|
|
{ "lngita", L"Italian" },
|
|
{ "lngdut", L"Dutch" },
|
|
{ "lngsch", L"S. Chinese" },
|
|
{ "lngtch", L"T. Chinese" },
|
|
{ "lngkor", L"Korean" }
|
|
};
|
|
|
|
const CMenu::SOption CMenu::_GlobalVideoModes[6] = {
|
|
{ "vidgame", L"Game" },
|
|
{ "vidsys", L"System" },
|
|
{ "vidp50", L"PAL 50Hz" },
|
|
{ "vidp60", L"PAL 60Hz" },
|
|
{ "vidntsc", L"NTSC" },
|
|
{ "vidprog", L"Progressive" },
|
|
};
|
|
|
|
const CMenu::SOption CMenu::_VideoModes[7] = {
|
|
{ "viddef", L"Default" },
|
|
{ "vidgame", L"Game" },
|
|
{ "vidsys", L"System" },
|
|
{ "vidp50", L"PAL 50Hz" },
|
|
{ "vidp60", L"PAL 60Hz" },
|
|
{ "vidntsc", L"NTSC" },
|
|
{ "vidprog", L"Progressive" },
|
|
};
|
|
|
|
const CMenu::SOption CMenu::_GlobalDMLvideoModes[6] = {
|
|
{ "DMLdefG", L"Game" },
|
|
{ "DMLpal", L"PAL 576i" },
|
|
{ "DMLntsc", L"NTSC 480i" },
|
|
{ "DMLpal60", L"PAL 480i" },
|
|
{ "DMLprog", L"NTSC 480p" },
|
|
{ "DMLprogP", L"PAL 480p" }
|
|
};
|
|
|
|
const CMenu::SOption CMenu::_DMLvideoModes[7] = {
|
|
{ "DMLdef", L"Default" },
|
|
{ "DMLdefG", L"Game" },
|
|
{ "DMLpal", L"PAL 576i" },
|
|
{ "DMLntsc", L"NTSC 480i" },
|
|
{ "DMLpal60", L"PAL 480i" },
|
|
{ "DMLprog", L"NTSC 480p" },
|
|
{ "DMLprogP", L"PAL 480p" }
|
|
};
|
|
|
|
const CMenu::SOption CMenu::_GlobalGClanguages[7] = {
|
|
{ "lngsys", L"System" },
|
|
{ "lngeng", L"English" },
|
|
{ "lngger", L"German" },
|
|
{ "lngfre", L"French" },
|
|
{ "lngspa", L"Spanish" },
|
|
{ "lngita", L"Italian" },
|
|
{ "lngdut", L"Dutch" }
|
|
};
|
|
|
|
const CMenu::SOption CMenu::_GClanguages[8] = {
|
|
{ "lngdef", L"Default" },
|
|
{ "lngsys", L"System" },
|
|
{ "lngeng", L"English" },
|
|
{ "lngger", L"German" },
|
|
{ "lngfre", L"French" },
|
|
{ "lngspa", L"Spanish" },
|
|
{ "lngita", L"Italian" },
|
|
{ "lngdut", L"Dutch" }
|
|
};
|
|
|
|
const CMenu::SOption CMenu::_NandEmu[2] = {
|
|
{ "NANDpart", L"Partial" },
|
|
{ "NANDfull", L"Full" },
|
|
};
|
|
|
|
const CMenu::SOption CMenu::_GlobalSaveEmu[4] = {
|
|
{ "SaveOffG", L"Off" },
|
|
{ "SavePartG", L"Game save" },
|
|
{ "SaveRegG", L"Regionswitch" },
|
|
{ "SaveFullG", L"Full" },
|
|
};
|
|
|
|
const CMenu::SOption CMenu::_SaveEmu[5] = {
|
|
{ "SaveDef", L"Default" },
|
|
{ "SaveOff", L"Off" },
|
|
{ "SavePart", L"Game save" },
|
|
{ "SaveReg", L"Regionswitch" },
|
|
{ "SaveFull", L"Full" },
|
|
};
|
|
|
|
const CMenu::SOption CMenu::_AspectRatio[3] = {
|
|
{ "aspectDef", L"Default" },
|
|
{ "aspect43", L"Force 4:3" },
|
|
{ "aspect169", L"Force 16:9" },
|
|
};
|
|
|
|
const CMenu::SOption CMenu::_NMM[4] = {
|
|
{ "NMMDef", L"Default" },
|
|
{ "NMMOff", L"Disabled" },
|
|
{ "NMMon", L"Enabled" },
|
|
{ "NMMdebug", L"Debug" },
|
|
};
|
|
|
|
const CMenu::SOption CMenu::_NoDVD[3] = {
|
|
{ "NoDVDDef", L"Default" },
|
|
{ "NoDVDOff", L"Disabled" },
|
|
{ "NoDVDon", L"Enabled" },
|
|
};
|
|
|
|
const CMenu::SOption CMenu::_GlobalGCLoaders[3] = {
|
|
{ "GC_Auto", L"Auto MIOS" },
|
|
{ "GC_Devo", L"Devolution" },
|
|
{ "GC_Nindnt", L"Nintendont" },
|
|
};
|
|
|
|
const CMenu::SOption CMenu::_GCLoader[4] = {
|
|
{ "GC_Def", L"Default" },
|
|
{ "GC_Auto", L"Auto MIOS" },
|
|
{ "GC_Devo", L"Devolution" },
|
|
{ "GC_Nindnt", L"Nintendont" },
|
|
};
|
|
|
|
const CMenu::SOption CMenu::_vidModePatch[4] = {
|
|
{ "vmpnone", L"None" },
|
|
{ "vmpnormal", L"Normal" },
|
|
{ "vmpmore", L"More" },
|
|
{ "vmpall", L"All" }
|
|
};
|
|
|
|
const CMenu::SOption CMenu::_hooktype[8] = {
|
|
{ "hook_auto", L"AUTO" },
|
|
{ "hooktype1", L"VBI" },
|
|
{ "hooktype2", L"KPAD read" },
|
|
{ "hooktype3", L"Joypad" },
|
|
{ "hooktype4", L"GXDraw" },
|
|
{ "hooktype5", L"GXFlush" },
|
|
{ "hooktype6", L"OSSleepThread" },
|
|
{ "hooktype7", L"AXNextFrame" },
|
|
};
|
|
|
|
const CMenu::SOption CMenu::_debugger[3] = {
|
|
{ "disabled", L"Disabled" },
|
|
{ "dbg_gecko", L"Gecko" },
|
|
{ "dbgfwrite", L"OSReport" },
|
|
};
|
|
|
|
/*
|
|
0 No Hook
|
|
1 VBI
|
|
2 KPAD read
|
|
3 Joypad Hook
|
|
4 GXDraw Hook
|
|
5 GXFlush Hook
|
|
6 OSSleepThread Hook
|
|
7 AXNextFrame Hook
|
|
*/
|
|
|
|
map<u8, u8> CMenu::_installed_cios;
|
|
u8 banner_title[84];
|
|
|
|
static inline int loopNum(int i, int s)
|
|
{
|
|
return i < 0 ? (s - (-i % s)) % s : i % s;
|
|
}
|
|
|
|
|
|
static void _extractBannerTitle(int language)
|
|
{
|
|
memset(banner_title, 0, 84);
|
|
CurrentBanner.GetName(banner_title, language);
|
|
}
|
|
|
|
static void _extractChannelBnr(const u64 chantitle)
|
|
{
|
|
ChannelHandle.GetBanner(chantitle);
|
|
}
|
|
|
|
static void _extractBnr(const dir_discHdr *hdr)
|
|
{
|
|
u32 size = 0;
|
|
DeviceHandle.OpenWBFS(currentPartition);
|
|
wbfs_disc_t *disc = WBFS_OpenDisc((u8 *) &hdr->id, (char *) hdr->path);
|
|
if(disc != NULL)
|
|
{
|
|
void *bnr = NULL;
|
|
size = wbfs_extract_file(disc, (char*)"opening.bnr", &bnr);
|
|
if(size > 0)
|
|
CurrentBanner.SetBanner((u8*)bnr, size, false, true);
|
|
WBFS_CloseDisc(disc);
|
|
}
|
|
WBFS_Close();
|
|
}
|
|
|
|
static int GetLanguage(const char *lang)
|
|
{
|
|
if (strncmp(lang, "JP", 2) == 0) return CONF_LANG_JAPANESE;
|
|
else if (strncmp(lang, "EN", 2) == 0) return CONF_LANG_ENGLISH;
|
|
else if (strncmp(lang, "DE", 2) == 0) return CONF_LANG_GERMAN;
|
|
else if (strncmp(lang, "FR", 2) == 0) return CONF_LANG_FRENCH;
|
|
else if (strncmp(lang, "ES", 2) == 0) return CONF_LANG_SPANISH;
|
|
else if (strncmp(lang, "IT", 2) == 0) return CONF_LANG_ITALIAN;
|
|
else if (strncmp(lang, "NL", 2) == 0) return CONF_LANG_DUTCH;
|
|
else if (strncmp(lang, "ZHTW", 4) == 0) return CONF_LANG_TRAD_CHINESE;
|
|
else if (strncmp(lang, "ZH", 2) == 0) return CONF_LANG_SIMP_CHINESE;
|
|
else if (strncmp(lang, "KO", 2) == 0) return CONF_LANG_KOREAN;
|
|
|
|
return CONF_LANG_ENGLISH; // Default to EN
|
|
}
|
|
|
|
static u8 GetRequestedGameIOS(dir_discHdr *hdr)
|
|
{
|
|
u8 IOS = 0;
|
|
|
|
DeviceHandle.OpenWBFS(currentPartition);
|
|
wbfs_disc_t *disc = WBFS_OpenDisc((u8*)&hdr->id, hdr->path);
|
|
if(disc != NULL)
|
|
{
|
|
void *titleTMD = NULL;
|
|
u32 tmd_size = wbfs_extract_file(disc, (char*)"TMD", &titleTMD);
|
|
if(titleTMD != NULL)
|
|
{
|
|
if(tmd_size > 0x18B)
|
|
IOS = *((u8*)titleTMD + 0x18B);
|
|
MEM2_free(titleTMD);
|
|
}
|
|
WBFS_CloseDisc(disc);
|
|
}
|
|
WBFS_Close();
|
|
return IOS;
|
|
}
|
|
|
|
void CMenu::_hideGame(bool instant)
|
|
{
|
|
m_gameSelected = false;
|
|
m_fa.unload();
|
|
CoverFlow.showCover();
|
|
m_btnMgr.hide(m_gameBtnPlay, instant);
|
|
m_btnMgr.hide(m_gameBtnBack, instant);
|
|
m_btnMgr.hide(m_gameBtnPlayFull, instant);
|
|
m_btnMgr.hide(m_gameBtnBackFull, instant);
|
|
m_btnMgr.hide(m_gameBtnDelete, instant);
|
|
m_btnMgr.hide(m_gameBtnSettings, instant);
|
|
m_btnMgr.hide(m_gameBtnToogle, instant);
|
|
m_btnMgr.hide(m_gameBtnToogleFull, instant);
|
|
|
|
m_btnMgr.hide(m_gameBtnFavoriteOn, instant);
|
|
m_btnMgr.hide(m_gameBtnFavoriteOff, instant);
|
|
m_btnMgr.hide(m_gameBtnAdultOn, instant);
|
|
m_btnMgr.hide(m_gameBtnAdultOff, instant);
|
|
for(u8 i = 0; i < ARRAY_SIZE(m_gameLblUser); ++i)
|
|
if(m_gameLblUser[i] != -1)
|
|
m_btnMgr.hide(m_gameLblUser[i], instant);
|
|
}
|
|
|
|
void CMenu::_showGame(void)
|
|
{
|
|
CoverFlow.showCover();
|
|
|
|
if(m_fa.load(m_cfg, m_fanartDir.c_str(), CoverFlow.getId()))
|
|
{
|
|
const TexData *bg = NULL;
|
|
const TexData *bglq = NULL;
|
|
m_fa.getBackground(bg, bglq);
|
|
if(bg != NULL && bglq != NULL)
|
|
_setBg(*bg, *bglq);
|
|
if (m_fa.hideCover())
|
|
CoverFlow.hideCover();
|
|
}
|
|
else
|
|
_setBg(m_mainBg, m_mainBgLQ);
|
|
|
|
if(!m_zoom_banner)
|
|
{
|
|
for(u8 i = 0; i < ARRAY_SIZE(m_gameLblUser) - 1; ++i)
|
|
{
|
|
if(m_gameLblUser[i] != -1)
|
|
m_btnMgr.show(m_gameLblUser[i]);
|
|
}
|
|
m_btnMgr.show(m_gameBtnPlay);
|
|
m_btnMgr.show(m_gameBtnBack);
|
|
m_btnMgr.show(m_gameBtnToogle);
|
|
}
|
|
else
|
|
{
|
|
m_btnMgr.show(m_gameBtnPlayFull);
|
|
m_btnMgr.show(m_gameBtnBackFull);
|
|
m_btnMgr.show(m_gameBtnToogleFull);
|
|
}
|
|
}
|
|
|
|
static void setLanguage(int l)
|
|
{
|
|
if (l > 0 && l <= 10)
|
|
configbytes[0] = l - 1;
|
|
else
|
|
configbytes[0] = 0xCD;
|
|
}
|
|
|
|
void CMenu::_game(bool launch)
|
|
{
|
|
m_gcfg1.load(fmt("%s/" GAME_SETTINGS1_FILENAME, m_settingsDir.c_str()));
|
|
m_zoom_banner = m_cfg.getBool(_domainFromView(), "show_full_banner", false) && !NoGameID(CoverFlow.getHdr()->type);
|
|
if(!launch)
|
|
{
|
|
SetupInput();
|
|
_playGameSound();
|
|
_showGame();
|
|
m_gameSelected = true;
|
|
}
|
|
|
|
|
|
if(m_banner.GetZoomSetting() != m_zoom_banner)
|
|
m_banner.ToogleZoom();
|
|
|
|
s8 startGameSound = 1;
|
|
while(!m_exit)
|
|
{
|
|
if(startGameSound < 1)
|
|
startGameSound++;
|
|
|
|
u64 chantitle = CoverFlow.getChanTitle();
|
|
|
|
if(startGameSound == -5)
|
|
{
|
|
_playGameSound();
|
|
_showGame();
|
|
}
|
|
_mainLoopCommon(true);
|
|
|
|
if(startGameSound == 0)
|
|
{
|
|
m_gameSelected = true;
|
|
startGameSound = 1;
|
|
}
|
|
if(BTN_B_PRESSED && !m_locked && (m_btnMgr.selected(m_gameBtnFavoriteOn) || m_btnMgr.selected(m_gameBtnFavoriteOff)))
|
|
{
|
|
_hideGame();
|
|
m_banner.SetShowBanner(false);
|
|
_CategorySettings(true);
|
|
_showGame();
|
|
m_banner.SetShowBanner(true);
|
|
if(!m_gameSound.IsPlaying())
|
|
startGameSound = -6;
|
|
continue;
|
|
}
|
|
if(BTN_HOME_PRESSED || BTN_B_PRESSED)
|
|
{
|
|
m_gameSound.FreeMemory();
|
|
CheckGameSoundThread();
|
|
m_banner.DeleteBanner();
|
|
break;
|
|
}
|
|
else if(BTN_PLUS_PRESSED && m_GameTDBLoaded && (CoverFlow.getHdr()->type == TYPE_WII_GAME || CoverFlow.getHdr()->type == TYPE_GC_GAME || CoverFlow.getHdr()->type == TYPE_CHANNEL))
|
|
{
|
|
_hideGame();
|
|
m_banner.SetShowBanner(false);
|
|
m_gameSelected = true;
|
|
_gameinfo();
|
|
_showGame();
|
|
m_banner.SetShowBanner(true);
|
|
if(!m_gameSound.IsPlaying())
|
|
startGameSound = -6;
|
|
}
|
|
else if(BTN_MINUS_PRESSED)
|
|
{
|
|
const char *videoPath = fmt("%s/%.3s.thp", m_videoDir.c_str(), CoverFlow.getId());
|
|
if(fsop_FileExist(videoPath))
|
|
{
|
|
MusicPlayer.Stop();
|
|
m_gameSound.Stop();
|
|
m_banner.SetShowBanner(false);
|
|
_hideGame();
|
|
/* Set Background empty */
|
|
TexData EmptyBG;
|
|
_setBg(EmptyBG, EmptyBG);
|
|
/* Lets play the movie */
|
|
WiiMovie movie(videoPath);
|
|
movie.SetScreenSize(m_cfg.getInt("GENERAL", "tv_width", 640), m_cfg.getInt("GENERAL", "tv_height", 480), m_cfg.getInt("GENERAL", "tv_x", 0), m_cfg.getInt("GENERAL", "tv_y", 0));
|
|
movie.SetVolume(m_cfg.getInt("GENERAL", "sound_volume_bnr", 255));
|
|
m_video_playing = true;
|
|
movie.Play();
|
|
m_banner.ReSetup_GX();
|
|
m_vid.setup2DProjection();
|
|
while(!BTN_B_PRESSED && !BTN_A_PRESSED && !BTN_HOME_PRESSED && movie.GetNextFrame(&m_curBg))
|
|
{
|
|
/* Draw movie BG and render */
|
|
_drawBg();
|
|
m_vid.render();
|
|
free(m_curBg.data);
|
|
/* Check if we want to stop */
|
|
WPAD_ScanPads();
|
|
PAD_ScanPads();
|
|
ButtonsPressed();
|
|
}
|
|
movie.Stop();
|
|
TexHandle.Cleanup(m_curBg);
|
|
/* Finished, so lets re-setup the background */
|
|
_setBg(m_mainBg, m_mainBgLQ);
|
|
_updateBg();
|
|
/* Get back into our coverflow */
|
|
_showGame();
|
|
m_video_playing = false;
|
|
m_banner.SetShowBanner(true);
|
|
if(!m_gameSound.IsPlaying())
|
|
startGameSound = -6;
|
|
}
|
|
}
|
|
else if((BTN_1_PRESSED) || (BTN_2_PRESSED))
|
|
{
|
|
s8 direction = BTN_1_PRESSED ? 1 : -1;
|
|
const char *domain = _domainFromView();
|
|
int cfVersion = 1+loopNum((m_cfg.getInt(domain, "last_cf_mode", 1)-1) + direction, m_numCFVersions);
|
|
_loadCFLayout(cfVersion);
|
|
CoverFlow.applySettings();
|
|
m_cfg.setInt(domain, "last_cf_mode" , cfVersion);
|
|
}
|
|
else if(launch || BTN_A_PRESSED)
|
|
{
|
|
if (m_btnMgr.selected(m_mainBtnQuit))
|
|
break;
|
|
else if(m_btnMgr.selected(m_gameBtnDelete))
|
|
{
|
|
if(!m_locked)
|
|
{
|
|
_hideGame();
|
|
m_banner.SetShowBanner(false);
|
|
if(_wbfsOp(WO_REMOVE_GAME))
|
|
{
|
|
m_gameSound.FreeMemory();
|
|
CheckGameSoundThread();
|
|
m_banner.DeleteBanner();
|
|
break;
|
|
}
|
|
m_banner.SetShowBanner(true);
|
|
if(!m_gameSound.IsPlaying())
|
|
startGameSound = -6;
|
|
_showGame();
|
|
}
|
|
}
|
|
else if(m_btnMgr.selected(m_gameBtnFavoriteOn) || m_btnMgr.selected(m_gameBtnFavoriteOff))
|
|
m_gcfg1.setBool("FAVORITES", _getId(), !m_gcfg1.getBool("FAVORITES", _getId(), false));
|
|
else if(m_btnMgr.selected(m_gameBtnAdultOn) || m_btnMgr.selected(m_gameBtnAdultOff))
|
|
m_gcfg1.setBool("ADULTONLY", _getId(), !m_gcfg1.getBool("ADULTONLY", _getId(), false));
|
|
else if(m_btnMgr.selected(m_gameBtnBack) || m_btnMgr.selected(m_gameBtnBackFull))
|
|
{
|
|
m_gameSound.FreeMemory();
|
|
CheckGameSoundThread();
|
|
m_banner.DeleteBanner();
|
|
break;
|
|
}
|
|
else if((m_btnMgr.selected(m_gameBtnToogle) || m_btnMgr.selected(m_gameBtnToogleFull)) && !NoGameID(CoverFlow.getHdr()->type))
|
|
{
|
|
m_zoom_banner = m_banner.ToogleZoom();
|
|
m_cfg.setBool(_domainFromView(), "show_full_banner", m_zoom_banner);
|
|
m_show_zone_game = false;
|
|
m_btnMgr.hide(m_gameBtnPlayFull);
|
|
m_btnMgr.hide(m_gameBtnBackFull);
|
|
m_btnMgr.hide(m_gameBtnToogleFull);
|
|
}
|
|
else if(m_btnMgr.selected(m_gameBtnSettings))
|
|
{
|
|
_hideGame();
|
|
m_gameSelected = true;
|
|
|
|
m_banner.ToogleGameSettings();
|
|
_gameSettings();
|
|
m_banner.ToogleGameSettings();
|
|
|
|
_showGame();
|
|
if(!m_gameSound.IsPlaying())
|
|
startGameSound = -6;
|
|
}
|
|
else if(launch || m_btnMgr.selected(m_gameBtnPlay) || m_btnMgr.selected(m_gameBtnPlayFull) || !ShowPointer())
|
|
{
|
|
_hideGame();
|
|
MusicPlayer.Stop();
|
|
m_gameSound.FreeMemory();
|
|
CheckGameSoundThread();
|
|
m_banner.DeleteBanner();
|
|
dir_discHdr *hdr = (dir_discHdr*)MEM2_alloc(sizeof(dir_discHdr));
|
|
memcpy(hdr, CoverFlow.getHdr(), sizeof(dir_discHdr));
|
|
m_gcfg2.load(fmt("%s/" GAME_SETTINGS2_FILENAME, m_settingsDir.c_str()));
|
|
// change to current games partition and set last_view for recall later
|
|
m_cfg.setInt("GENERAL", "last_view", m_current_view);
|
|
m_cfg.setInt("GENERAL", "cat_startpage", m_catStartPage);
|
|
switch(hdr->type)
|
|
{
|
|
case TYPE_CHANNEL:
|
|
currentPartition = m_cfg.getInt(CHANNEL_DOMAIN, "partition", 1);
|
|
break;
|
|
case TYPE_HOMEBREW:
|
|
currentPartition = m_cfg.getInt(HOMEBREW_DOMAIN, "partition", 1);
|
|
break;
|
|
case TYPE_GC_GAME:
|
|
currentPartition = m_cfg.getInt(GC_DOMAIN, "partition", 1);
|
|
break;
|
|
case TYPE_WII_GAME:
|
|
currentPartition = m_cfg.getInt(WII_DOMAIN, "partition", 1);
|
|
break;
|
|
default:
|
|
m_plugin.GetEnabledPlugins(m_cfg, &enabledPluginsCount);
|
|
if(enabledPluginsCount == 1)
|
|
{
|
|
char PluginMagicWord[9];
|
|
memset(PluginMagicWord, 0, sizeof(PluginMagicWord));
|
|
strncpy(PluginMagicWord, fmt("%08x", hdr->settings[0]), 8);
|
|
currentPartition = m_cfg.getInt("PLUGINS/PARTITION", PluginMagicWord, 1);
|
|
m_cfg.setInt(PLUGIN_DOMAIN, "partition", currentPartition);
|
|
}
|
|
currentPartition = m_cfg.getInt(PLUGIN_DOMAIN, "partition", 1);
|
|
break;
|
|
}
|
|
/* Get Banner Title for Playlog */
|
|
CurrentBanner.ClearBanner();
|
|
if(hdr->type == TYPE_CHANNEL)
|
|
_extractChannelBnr(chantitle);
|
|
else if(hdr->type == TYPE_WII_GAME)
|
|
_extractBnr(hdr);
|
|
if(CurrentBanner.IsValid())
|
|
_extractBannerTitle(GetLanguage(m_loc.getString(m_curLanguage, "gametdb_code", "EN").c_str()));
|
|
if(hdr->type != TYPE_HOMEBREW && hdr->type != TYPE_PLUGIN)
|
|
{
|
|
if(Playlog_Update(hdr->id, banner_title) < 0)
|
|
Playlog_Delete();
|
|
}
|
|
gprintf("Launching game %s\n", hdr->id);
|
|
CurrentBanner.ClearBanner();
|
|
/* Finally boot it */
|
|
_launch(hdr);
|
|
|
|
if(m_exit)
|
|
break;
|
|
|
|
_hideWaitMessage();
|
|
launch = false;
|
|
|
|
for(int chan = WPAD_MAX_WIIMOTES-1; chan >= 0; chan--)
|
|
WPAD_SetVRes(chan, m_vid.width() + m_cursor[chan].width(), m_vid.height() + m_cursor[chan].height());
|
|
m_gcfg2.unload();
|
|
_showGame();
|
|
//_initCF();
|
|
//CoverFlow.select();
|
|
}
|
|
else
|
|
{
|
|
for(int chan = WPAD_MAX_WIIMOTES-1; chan >= 0; chan--)
|
|
if (CoverFlow.mouseOver(m_cursor[chan].x(), m_cursor[chan].y()))
|
|
CoverFlow.flip();
|
|
}
|
|
}
|
|
if((startGameSound == 1 || startGameSound < -8) && (BTN_UP_REPEAT || RIGHT_STICK_UP))
|
|
{
|
|
if(m_gameSoundThread != LWP_THREAD_NULL)
|
|
CheckGameSoundThread();
|
|
CoverFlow.up();
|
|
startGameSound = -10;
|
|
}
|
|
if((startGameSound == 1 || startGameSound < -8) && (BTN_RIGHT_REPEAT || RIGHT_STICK_RIGHT))
|
|
{
|
|
if(m_gameSoundThread != LWP_THREAD_NULL)
|
|
CheckGameSoundThread();
|
|
CoverFlow.right();
|
|
startGameSound = -10;
|
|
}
|
|
if((startGameSound == 1 || startGameSound < -8) && (BTN_DOWN_REPEAT || RIGHT_STICK_DOWN))
|
|
{
|
|
if(m_gameSoundThread != LWP_THREAD_NULL)
|
|
CheckGameSoundThread();
|
|
CoverFlow.down();
|
|
startGameSound = -10;
|
|
}
|
|
if((startGameSound == 1 || startGameSound < -8) && (BTN_LEFT_REPEAT || RIGHT_STICK_LEFT))
|
|
{
|
|
if(m_gameSoundThread != LWP_THREAD_NULL)
|
|
CheckGameSoundThread();
|
|
CoverFlow.left();
|
|
startGameSound = -10;
|
|
}
|
|
if(startGameSound == -10)
|
|
{
|
|
m_gameSound.Stop();
|
|
m_gameSelected = false;
|
|
m_fa.unload();
|
|
m_banner.DeleteBanner(true);
|
|
_setBg(m_mainBg, m_mainBgLQ);
|
|
}
|
|
if(m_show_zone_game && !m_zoom_banner)
|
|
{
|
|
bool b = m_gcfg1.getBool("FAVORITES", _getId(), false);
|
|
m_btnMgr.show(b ? m_gameBtnFavoriteOn : m_gameBtnFavoriteOff);
|
|
m_btnMgr.hide(b ? m_gameBtnFavoriteOff : m_gameBtnFavoriteOn);
|
|
m_btnMgr.show(m_gameBtnPlay);
|
|
m_btnMgr.show(m_gameBtnBack);
|
|
if(!m_fa.isLoaded())
|
|
m_btnMgr.show(m_gameBtnToogle);
|
|
else
|
|
m_btnMgr.hide(m_gameBtnToogle);
|
|
m_btnMgr.hide(m_gameBtnPlayFull);
|
|
m_btnMgr.hide(m_gameBtnBackFull);
|
|
m_btnMgr.hide(m_gameBtnToogleFull);
|
|
if(m_gameLblUser[4] != -1 && !NoGameID(CoverFlow.getHdr()->type) && !m_fa.isLoaded())
|
|
m_btnMgr.show(m_gameLblUser[4]);
|
|
else
|
|
m_btnMgr.hide(m_gameLblUser[4]);
|
|
for(u8 i = 0; i < ARRAY_SIZE(m_gameLblUser) - 1; ++i)
|
|
{
|
|
if(m_gameLblUser[i] != -1)
|
|
m_btnMgr.show(m_gameLblUser[i]);
|
|
}
|
|
if(!m_locked)
|
|
{
|
|
b = m_gcfg1.getBool("ADULTONLY", _getId(), false);
|
|
m_btnMgr.show(b ? m_gameBtnAdultOn : m_gameBtnAdultOff);
|
|
m_btnMgr.hide(b ? m_gameBtnAdultOff : m_gameBtnAdultOn);
|
|
m_btnMgr.show(m_gameBtnSettings);
|
|
}
|
|
if((CoverFlow.getHdr()->type != TYPE_HOMEBREW && (CoverFlow.getHdr()->type != TYPE_CHANNEL ||
|
|
(!m_cfg.getBool(CHANNEL_DOMAIN, "disable", true) && CoverFlow.getHdr()->type == TYPE_CHANNEL))) && !m_locked)
|
|
m_btnMgr.show(m_gameBtnDelete);
|
|
}
|
|
else
|
|
{
|
|
if(m_zoom_banner && !m_fa.isLoaded())
|
|
{
|
|
m_btnMgr.show(m_gameBtnPlayFull);
|
|
m_btnMgr.show(m_gameBtnBackFull);
|
|
m_btnMgr.show(m_gameBtnToogleFull);
|
|
}
|
|
m_btnMgr.hide(m_gameBtnFavoriteOn);
|
|
m_btnMgr.hide(m_gameBtnFavoriteOff);
|
|
m_btnMgr.hide(m_gameBtnAdultOn);
|
|
m_btnMgr.hide(m_gameBtnAdultOff);
|
|
m_btnMgr.hide(m_gameBtnSettings);
|
|
m_btnMgr.hide(m_gameBtnDelete);
|
|
m_btnMgr.hide(m_gameBtnPlay);
|
|
m_btnMgr.hide(m_gameBtnBack);
|
|
m_btnMgr.hide(m_gameBtnToogle);
|
|
if(m_gameLblUser[4] != -1)
|
|
{
|
|
if(!NoGameID(CoverFlow.getHdr()->type) && !m_zoom_banner && !m_fa.isLoaded())
|
|
m_btnMgr.show(m_gameLblUser[4]);
|
|
else
|
|
m_btnMgr.hide(m_gameLblUser[4], true);
|
|
}
|
|
for(u8 i = 0; i < ARRAY_SIZE(m_gameLblUser) - 1; ++i)
|
|
if (m_gameLblUser[i] != -1)
|
|
m_btnMgr.hide(m_gameLblUser[i]);
|
|
}
|
|
}
|
|
m_gcfg1.save(true);
|
|
_hideGame();
|
|
}
|
|
|
|
void CMenu::directlaunch(const char *GameID)
|
|
{
|
|
m_directLaunch = true;
|
|
for(currentPartition = SD; currentPartition < USB8; currentPartition++)
|
|
{
|
|
if(!DeviceHandle.IsInserted(currentPartition))
|
|
continue;
|
|
DeviceHandle.OpenWBFS(currentPartition);
|
|
string gameDir(fmt(wii_games_dir, DeviceName[currentPartition]));
|
|
string cacheDir(fmt("%s/%s_wii.db", m_listCacheDir.c_str(), DeviceName[currentPartition]));
|
|
m_gameList.CreateList(COVERFLOW_USB, currentPartition, gameDir,
|
|
stringToVector(".wbfs|.iso", '|'), cacheDir, false);
|
|
WBFS_Close();
|
|
for(u32 i = 0; i < m_gameList.size(); i++)
|
|
{
|
|
if(strncasecmp(GameID, m_gameList[i].id, 6) == 0)
|
|
{
|
|
_launchGame(&m_gameList[i], false); // Launch will exit wiiflow
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
error(sfmt("errgame1", L"Cannot find the game with ID: %s", GameID));
|
|
}
|
|
|
|
void CMenu::_launchShutdown()
|
|
{
|
|
CoverFlow.clear();
|
|
_showWaitMessage();
|
|
exitHandler(PRIILOADER_DEF); //Making wiiflow ready to boot something
|
|
}
|
|
|
|
void CMenu::_launch(const dir_discHdr *hdr)
|
|
{
|
|
dir_discHdr launchHdr;
|
|
memcpy(&launchHdr, hdr, sizeof(dir_discHdr));
|
|
/* Lets boot that shit */
|
|
if(launchHdr.type == TYPE_WII_GAME)
|
|
_launchGame(&launchHdr, false);
|
|
else if(launchHdr.type == TYPE_GC_GAME)
|
|
_launchGC(&launchHdr, false);
|
|
else if(launchHdr.type == TYPE_CHANNEL)
|
|
_launchChannel(&launchHdr);
|
|
else if(launchHdr.type == TYPE_PLUGIN)
|
|
{
|
|
const char *plugin_dol_name = m_plugin.GetDolName(launchHdr.settings[0]);
|
|
u8 plugin_dol_len = strlen(plugin_dol_name);
|
|
char title[101];
|
|
memset(&title, 0, sizeof(title));
|
|
u32 title_len_no_ext = 0;
|
|
const char *path = NULL;
|
|
if(strchr(launchHdr.path, ':') != NULL)
|
|
{
|
|
if(plugin_dol_len == strlen(MUSIC_DOMAIN) && strcmp(plugin_dol_name, MUSIC_DOMAIN) == 0)
|
|
{
|
|
MusicPlayer.LoadFile(launchHdr.path, false);
|
|
m_exit = false;
|
|
return;
|
|
}
|
|
strncpy(title, strrchr(launchHdr.path, '/') + 1, 100);
|
|
if(strchr(launchHdr.path, '.') != NULL)
|
|
title_len_no_ext = strlen(title) - strlen(strrchr(title, '.'));
|
|
*strrchr(launchHdr.path, '/') = '\0';
|
|
path = strchr(launchHdr.path, '/') + 1;
|
|
}
|
|
else
|
|
{
|
|
path = launchHdr.path;
|
|
wcstombs(title, launchHdr.title, 63);
|
|
}
|
|
m_cfg.setString(PLUGIN_DOMAIN, "current_item", title);
|
|
const char *mios_wad = NULL;
|
|
if(m_cfg.getBool("PLUGIN", "444d4c62", false))
|
|
{
|
|
if(currentPartition == SD && (m_mios_ver != 2 || m_sd_dm == false))
|
|
mios_wad = fmt("%s/qfsd.wad", m_miosDir.c_str());
|
|
else if(currentPartition != SD && (m_mios_ver != 2 || m_sd_dm == true))
|
|
mios_wad = fmt("%s/qfusb.wad", m_miosDir.c_str());
|
|
if(mios_wad != NULL && fsop_FileExist(mios_wad))
|
|
_Wad(mios_wad, true);//install mios
|
|
}
|
|
const char *device = (currentPartition == 0 ? "sd" : (DeviceHandle.GetFSType(currentPartition) == PART_FS_NTFS ? "ntfs" : "usb"));
|
|
const char *loader = fmt("%s:/%s/WiiFlowLoader.dol", device, strchr(m_pluginsDir.c_str(), '/') + 1);
|
|
|
|
vector<string> arguments = m_plugin.CreateArgs(device, path, title, loader, title_len_no_ext, launchHdr.settings[0]);
|
|
const char *plugin_file = plugin_dol_name; /* try full path */
|
|
if(strchr(plugin_file, ':') == NULL || !fsop_FileExist(plugin_file)) /* try universal plugin folder */
|
|
{
|
|
plugin_file = fmt("%s/%s", m_pluginsDir.c_str(), plugin_dol_name);
|
|
if(!fsop_FileExist(plugin_file)) /* try device search */
|
|
{
|
|
for(u8 i = SD; i < MAXDEVICES; ++i)
|
|
{
|
|
plugin_file = fmt("%s:/%s", DeviceName[i], plugin_dol_name);
|
|
if(fsop_FileExist(plugin_file))
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
_launchHomebrew(plugin_file, arguments);
|
|
}
|
|
else if(launchHdr.type == TYPE_HOMEBREW)
|
|
{
|
|
const char *gamepath = fmt("%s/boot.dol", launchHdr.path);
|
|
if(!fsop_FileExist(gamepath))
|
|
gamepath = fmt("%s/boot.elf", launchHdr.path);
|
|
if(fsop_FileExist(gamepath))
|
|
{
|
|
m_cfg.setString(HOMEBREW_DOMAIN, "current_item", strrchr(launchHdr.path, '/') + 1);
|
|
_launchHomebrew(gamepath, m_homebrewArgs);
|
|
}
|
|
}
|
|
ShutdownBeforeExit();
|
|
Sys_Exit();
|
|
}
|
|
// taken from Postloader by Stfour
|
|
#define QFIDN 9
|
|
static const char qfid[QFIDN][7] = {
|
|
"RELSAB", //Sample Header?
|
|
"GGPE01", //Mario Kart Arcade GP
|
|
"MKAGP1", //Mario Kart Arcade GP (Alt ID)
|
|
"GGPE02", //Mario Kart Arcade GP 2
|
|
"MKAGP2", //Mario Kart Arcade GP 2 (Alt ID)
|
|
"GFZJ8P", //F-Zero AX
|
|
"GVSJ8P", // Virtua Striker 4 Ver.2006 (PAL)
|
|
"GVS46E", // Virtua Striker 4 Ver.2006 (NTSC)
|
|
"GVS46J", // Virtua Striker 4 Ver.2006 (JAP)
|
|
};
|
|
|
|
bool CMenu::_QF_Game(const char *game_id)
|
|
{
|
|
if(game_id == NULL)
|
|
return false;
|
|
for(u8 i = 0; i < QFIDN; i++)
|
|
{
|
|
if(memcmp(game_id, qfid[i], 7) == 0)
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void CMenu::_launchGC(dir_discHdr *hdr, bool disc)
|
|
{
|
|
const char *id = hdr->id;
|
|
memcpy((u8*)Disc_ID, id, 6);
|
|
DCFlushRange((u8*)Disc_ID, 32);
|
|
|
|
const char *path = hdr->path;
|
|
m_gcfg1.setInt("PLAYCOUNT", id, m_gcfg1.getInt("PLAYCOUNT", id, 0) + 1);
|
|
m_gcfg1.setUInt("LASTPLAYED", id, time(NULL));
|
|
|
|
if(has_enabled_providers() && _initNetwork() == 0)
|
|
add_game_to_card(id);
|
|
|
|
u8 videoSetting = min(m_cfg.getInt(GC_DOMAIN, "video_setting", 1), 2);
|
|
|
|
u8 GClanguage = min((u32)m_gcfg2.getInt(id, "gc_language", 0), ARRAY_SIZE(CMenu::_GClanguages) - 1u);
|
|
GClanguage = (GClanguage == 0) ? min((u32)m_cfg.getInt(GC_DOMAIN, "game_language", 0), ARRAY_SIZE(CMenu::_GlobalGClanguages) - 1u) : GClanguage-1;
|
|
|
|
u8 videoMode = min((u32)m_gcfg2.getInt(id, "dml_video_mode", 0), ARRAY_SIZE(CMenu::_DMLvideoModes) - 1u);
|
|
videoMode = (videoMode == 0) ? min((u32)m_cfg.getInt(GC_DOMAIN, "video_mode", 0), ARRAY_SIZE(CMenu::_GlobalDMLvideoModes) - 1u) : videoMode-1;
|
|
if(disc || videoMode == 0)
|
|
{
|
|
if(id[3] == 'E' || id[3] == 'J')
|
|
videoMode = 2; //NTSC 480i
|
|
else
|
|
videoMode = 1; //PAL 576i
|
|
}
|
|
|
|
u8 loader = min((u32)m_gcfg2.getInt(id, "gc_loader", 0), ARRAY_SIZE(CMenu::_GCLoader) - 1u);
|
|
loader = (loader == 0) ? min((u32)m_cfg.getInt(GC_DOMAIN, "default_loader", 0), ARRAY_SIZE(CMenu::_GlobalGCLoaders) - 1u) : loader-1;
|
|
bool memcard_emu = m_gcfg2.getBool(id, "devo_memcard_emu", false);
|
|
bool widescreen = m_gcfg2.getBool(id, "dm_widescreen", false);
|
|
bool activity_led = m_gcfg2.getBool(id, "led", false);
|
|
|
|
u8 NMM = min((u32)m_gcfg2.getInt(id, "dml_nmm", 0), ARRAY_SIZE(CMenu::_NMM) - 1u);
|
|
NMM = (NMM == 0) ? m_cfg.getInt(GC_DOMAIN, "dml_nmm", 0) : NMM-1;
|
|
|
|
//if GC disc use DIOS MIOS to launch it
|
|
if(disc)
|
|
{
|
|
loader = 0;
|
|
gprintf("Booting GC Disc: %s\n", id);
|
|
}
|
|
else
|
|
m_cfg.setString(GC_DOMAIN, "current_item", id);
|
|
|
|
const char *mios_wad = NULL;
|
|
|
|
if(loader == 0) //auto selected
|
|
{
|
|
gprintf("Auto installing MIOS\n");
|
|
_showWaitMessage();
|
|
if(_QF_Game(id) == true)
|
|
{
|
|
if(currentPartition == SD && (m_mios_ver != 2 || m_sd_dm == false))
|
|
mios_wad = fmt("%s/qfsd.wad", m_miosDir.c_str());
|
|
else if(currentPartition != SD && (m_mios_ver != 2 || m_sd_dm == true))
|
|
mios_wad = fmt("%s/qfusb.wad", m_miosDir.c_str());
|
|
}
|
|
else if(disc == false)
|
|
{
|
|
if(currentPartition == SD && (m_mios_ver != 1 || m_sd_dm == false))
|
|
mios_wad = fmt("%s/dml.wad", m_miosDir.c_str());
|
|
else if(currentPartition != SD && (m_mios_ver != 1 || m_sd_dm == true))
|
|
mios_wad = fmt("%s/dm.wad", m_miosDir.c_str());
|
|
}
|
|
else if(m_mios_ver != 0)
|
|
mios_wad = fmt("%s/mios.wad", m_miosDir.c_str());
|
|
if(mios_wad != NULL && fsop_FileExist(mios_wad))
|
|
_Wad(mios_wad, true);//install mios
|
|
}
|
|
//copy DML game from USB to SD if needed for DML
|
|
if(disc == false && loader == 0 && currentPartition != SD && m_sd_dm == true && strcasestr(hdr->path, ".iso") == NULL)
|
|
{
|
|
bool foundOnSD = false;
|
|
ListGenerator SD_List;
|
|
string gameDir(fmt(DML_DIR, DeviceName[SD]));
|
|
string cacheDir(fmt("%s/%s_gamecube.db", m_listCacheDir.c_str(), DeviceName[SD]));
|
|
SD_List.CreateList(COVERFLOW_DML, SD, gameDir,
|
|
stringToVector(".iso|root", '|'), cacheDir, false);
|
|
for(vector<dir_discHdr>::iterator List = SD_List.begin(); List != SD_List.end(); List++)
|
|
{
|
|
if(strncasecmp(hdr->id, List->id, 6) == 0)
|
|
{
|
|
foundOnSD = true;
|
|
memset(hdr->path, 0, sizeof(hdr->path));
|
|
strncpy(hdr->path, List->path, sizeof(hdr->path));
|
|
break;
|
|
}
|
|
}
|
|
SD_List.clear();
|
|
if(!foundOnSD)
|
|
{
|
|
if(_wbfsOp(CMenu::WO_COPY_GAME))
|
|
{
|
|
char folder[50];
|
|
string GC_Path(hdr->path);
|
|
if(strcasestr(GC_Path.c_str(), "boot.bin") != NULL)
|
|
GC_Path.erase(GC_Path.end() - 13, GC_Path.end());
|
|
else
|
|
GC_Path.erase(GC_Path.end() - 9, GC_Path.end());
|
|
u32 Place = GC_Path.find_last_of("/");
|
|
GC_Path = hdr->path;
|
|
memset(hdr->path, 0, sizeof(hdr->path));
|
|
snprintf(folder, sizeof(folder), DML_DIR, DeviceName[SD]);
|
|
snprintf(hdr->path, sizeof(hdr->path), "%s/%s", folder, &GC_Path[Place]+1);
|
|
}
|
|
else
|
|
return;
|
|
}
|
|
currentPartition = SD;
|
|
}
|
|
_launchShutdown();
|
|
if(disc == true)
|
|
DML_New_SetBootDiscOption(m_new_dm_cfg);
|
|
else if(loader == 0)
|
|
{
|
|
char CheatPath[256];
|
|
u8 nodisc = min((u32)m_gcfg2.getInt(id, "no_disc_patch", 0), ARRAY_SIZE(CMenu::_NoDVD) - 1u);
|
|
nodisc = (nodisc == 0) ? m_cfg.getInt(GC_DOMAIN, "no_disc_patch", 0) : nodisc-1;
|
|
bool cheats = m_gcfg2.testOptBool(id, "cheat", m_cfg.getBool(GC_DOMAIN, "cheat", false));
|
|
bool DML_debug = (m_gcfg2.getInt(id, "debugger", 0) == 1);
|
|
bool screenshot = m_gcfg2.getBool(id, "screenshot", false);
|
|
/* Generate gct path */
|
|
char GC_Path[1024];
|
|
GC_Path[1023] = '\0';
|
|
strncpy(GC_Path, path, 1023);
|
|
if(strcasestr(path, "boot.bin") != NULL)
|
|
{
|
|
*strrchr(GC_Path, '/') = '\0'; //boot.bin
|
|
*(strrchr(GC_Path, '/')+1) = '\0'; //sys
|
|
}
|
|
else
|
|
*(strrchr(GC_Path, '/')+1) = '\0'; //iso path
|
|
const char *NewCheatPath = fmt("%s%s.gct", GC_Path, id);
|
|
if(cheats)
|
|
snprintf(CheatPath, sizeof(CheatPath), "%s/%s", m_cheatDir.c_str(), fmt("%s.gct", id));
|
|
const char *newPath = strcasestr(path, "boot.bin") == NULL ? strchr(path, '/') : strchr(GC_Path, '/');
|
|
if(m_new_dml)
|
|
DML_New_SetOptions(newPath, CheatPath, NewCheatPath, DeviceName[currentPartition],
|
|
cheats, DML_debug, NMM, nodisc, videoMode, videoSetting, widescreen, m_new_dm_cfg, activity_led, screenshot);
|
|
else
|
|
DML_Old_SetOptions(newPath);
|
|
if(!nodisc || !m_new_dml)
|
|
WDVD_StopMotor();
|
|
}
|
|
else if(loader == 1)
|
|
DEVO_GetLoader(m_dataDir.c_str());
|
|
else if(loader == 2)
|
|
Nintendont_SetOptions(path, NMM, videoSetting, widescreen);
|
|
|
|
m_gcfg1.save(true);
|
|
m_gcfg2.save(true);
|
|
m_cat.save(true);
|
|
m_cfg.save(true);
|
|
cleanup();
|
|
|
|
GC_SetVideoMode(videoMode, (disc ? 1 : videoSetting), loader);
|
|
GC_SetLanguage(GClanguage);
|
|
/* NTSC-J Patch by FIX94 */
|
|
if(id[3] == 'J')
|
|
*HW_PPCSPEED = 0x0002A9E0;
|
|
|
|
if(loader == 0)
|
|
{
|
|
DML_New_WriteOptions();
|
|
ShutdownBeforeExit();
|
|
WII_Initialize();
|
|
WII_LaunchTitle(0x100000100LL);
|
|
}
|
|
else if(loader == 1)
|
|
{
|
|
if(AHBRPOT_Patched())
|
|
loadIOS(58, false);
|
|
else //use cIOS instead to make sure Devolution works anyways
|
|
loadIOS(mainIOS, false);
|
|
ShutdownBeforeExit();
|
|
DEVO_SetOptions(path, id, memcard_emu,
|
|
widescreen, activity_led, m_use_wifi_gecko);
|
|
DEVO_Boot();
|
|
}
|
|
else
|
|
{
|
|
Nintendont_WriteOptions();
|
|
bool ret = (Nintendont_GetLoader() && LoadAppBooter(fmt("%s/app_booter.bin", m_binsDir.c_str())));
|
|
ShutdownBeforeExit();
|
|
if(ret == true)
|
|
{
|
|
loadIOS(58, false); //nintendont NEEDS ios58
|
|
BootHomebrew(); //regular dol
|
|
}
|
|
}
|
|
Sys_Exit();
|
|
}
|
|
|
|
void CMenu::_launchHomebrew(const char *filepath, vector<string> arguments)
|
|
{
|
|
_launchShutdown();
|
|
m_gcfg1.save(true);
|
|
m_gcfg2.save(true);
|
|
m_cat.save(true);
|
|
m_cfg.save(true);
|
|
|
|
Playlog_Delete();
|
|
cleanup(); // wifi and sd gecko doesnt work anymore after cleanup
|
|
|
|
bool ret = (LoadHomebrew(filepath) && LoadAppBooter(fmt("%s/app_booter.bin", m_binsDir.c_str())));
|
|
|
|
AddBootArgument(filepath);
|
|
for(u32 i = 0; i < arguments.size(); ++i)
|
|
{
|
|
gprintf("Argument: %s\n", arguments[i].c_str());
|
|
AddBootArgument(arguments[i].c_str());
|
|
}
|
|
|
|
ShutdownBeforeExit();
|
|
if(ret == true)
|
|
{
|
|
loadIOS(58, false);
|
|
BootHomebrew();
|
|
}
|
|
Sys_Exit();
|
|
}
|
|
|
|
int CMenu::_loadIOS(u8 gameIOS, int userIOS, string id, bool RealNAND_Channels)
|
|
{
|
|
gprintf("Game ID# %s requested IOS %d. User selected %d\n", id.c_str(), gameIOS, userIOS);
|
|
if(neek2o() || (RealNAND_Channels && IOS_GetType(mainIOS) == IOS_TYPE_STUB))
|
|
{
|
|
bool ret = loadIOS(gameIOS, false);
|
|
_netInit();
|
|
if(ret == false)
|
|
{
|
|
error(sfmt("errgame4", L"Couldn't load IOS %i", gameIOS));
|
|
return LOAD_IOS_FAILED;
|
|
}
|
|
return LOAD_IOS_SUCCEEDED;
|
|
}
|
|
|
|
if(userIOS)
|
|
{
|
|
for(CIOSItr itr = _installed_cios.begin(); itr != _installed_cios.end(); itr++)
|
|
{
|
|
if(itr->second == userIOS || itr->first == userIOS)
|
|
{
|
|
gameIOS = itr->first;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else if(gameIOS != 57)
|
|
gameIOS = mainIOS;
|
|
gprintf("Changed requested IOS to %d.\n", gameIOS);
|
|
|
|
// remap IOS to CIOS
|
|
if(gameIOS < 0x64)
|
|
{
|
|
if(_installed_cios.size() <= 0)
|
|
{
|
|
error(sfmt("errgame2", L"No cIOS found!"));
|
|
Sys_Exit();
|
|
}
|
|
u8 IOS[3];
|
|
IOS[0] = gameIOS;
|
|
IOS[1] = 56;
|
|
IOS[2] = 57;
|
|
bool found = false;
|
|
for(u8 num = 0; num < 3; num++)
|
|
{
|
|
if(found)
|
|
break;
|
|
if(IOS[num] == 0)
|
|
continue;
|
|
for(CIOSItr itr = _installed_cios.begin(); itr != _installed_cios.end(); itr++)
|
|
{
|
|
if(itr->second == IOS[num] || itr->first == IOS[num])
|
|
{
|
|
gameIOS = itr->first;
|
|
found = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if(!found)
|
|
return LOAD_IOS_FAILED;
|
|
}
|
|
|
|
if(gameIOS != CurrentIOS.Version)
|
|
{
|
|
gprintf("Reloading IOS into %d\n", gameIOS);
|
|
bool ret = loadIOS(gameIOS, true);
|
|
_netInit();
|
|
if(ret == false)
|
|
{
|
|
error(sfmt("errgame4", L"Couldn't load IOS %i", gameIOS));
|
|
return LOAD_IOS_FAILED;
|
|
}
|
|
return LOAD_IOS_SUCCEEDED;
|
|
}
|
|
return LOAD_IOS_NOT_NEEDED;
|
|
}
|
|
|
|
void CMenu::_launchChannel(dir_discHdr *hdr)
|
|
{
|
|
_launchShutdown();
|
|
string id = string(hdr->id);
|
|
|
|
bool NAND_Emu = !m_cfg.getBool(CHANNEL_DOMAIN, "disable", true);
|
|
bool WII_Launch = (m_gcfg2.getBool(id, "custom", false) && (!NAND_Emu || neek2o()));
|
|
bool use_dol = !m_gcfg2.getBool(id, "apploader", false);
|
|
|
|
bool vipatch = m_gcfg2.testOptBool(id, "vipatch", m_cfg.getBool("GENERAL", "vipatch", false));
|
|
bool cheat = m_gcfg2.testOptBool(id, "cheat", m_cfg.getBool(CHANNEL_DOMAIN, "cheat", false));
|
|
bool countryPatch = m_gcfg2.testOptBool(id, "country_patch", m_cfg.getBool("GENERAL", "country_patch", false));
|
|
|
|
u8 videoMode = (u8)min((u32)m_gcfg2.getInt(id, "video_mode", 0), ARRAY_SIZE(CMenu::_VideoModes) - 1u);
|
|
videoMode = (videoMode == 0) ? (u8)min((u32)m_cfg.getInt("GENERAL", "video_mode", 0), ARRAY_SIZE(CMenu::_GlobalVideoModes) - 1) : videoMode-1;
|
|
|
|
int language = min((u32)m_gcfg2.getInt(id, "language", 0), ARRAY_SIZE(CMenu::_languages) - 1u);
|
|
language = (language == 0) ? min((u32)m_cfg.getInt("GENERAL", "game_language", 0), ARRAY_SIZE(CMenu::_languages) - 1) : language;
|
|
|
|
const char *rtrn = m_gcfg2.getBool(id, "returnto", true) ? m_cfg.getString("GENERAL", "returnto").c_str() : NULL;
|
|
u8 patchVidMode = min((u32)m_gcfg2.getInt(id, "patch_video_modes", 0), ARRAY_SIZE(CMenu::_vidModePatch) - 1u);
|
|
int aspectRatio = min((u32)m_gcfg2.getInt(id, "aspect_ratio", 0), ARRAY_SIZE(CMenu::_AspectRatio) - 1u)-1;
|
|
u32 returnTo = rtrn[0] << 24 | rtrn[1] << 16 | rtrn[2] << 8 | rtrn[3];
|
|
|
|
u8 *cheatFile = NULL;
|
|
u32 cheatSize = 0;
|
|
if(!WII_Launch)
|
|
{
|
|
hooktype = (u32) m_gcfg2.getInt(id, "hooktype", 0);
|
|
debuggerselect = m_gcfg2.getInt(id, "debugger", 0);
|
|
if((cheat || debuggerselect == 1) && hooktype == 0)
|
|
hooktype = 1;
|
|
else if(!cheat && debuggerselect != 1)
|
|
hooktype = 0;
|
|
|
|
if(cheat)
|
|
_loadFile(cheatFile, cheatSize, m_cheatDir.c_str(), fmt("%s.gct", id.c_str()));
|
|
if(has_enabled_providers() && _initNetwork() == 0)
|
|
add_game_to_card(id.c_str());
|
|
}
|
|
m_cfg.setString(CHANNEL_DOMAIN, "current_item", id);
|
|
m_gcfg1.setInt("PLAYCOUNT", id, m_gcfg1.getInt("PLAYCOUNT", id, 0) + 1);
|
|
m_gcfg1.setUInt("LASTPLAYED", id, time(NULL));
|
|
|
|
string emuPath = m_cfg.getString(CHANNEL_DOMAIN, "path");
|
|
int emulate_mode = min(max(0, m_cfg.getInt(CHANNEL_DOMAIN, "emulation", 1)), (int)ARRAY_SIZE(CMenu::_NandEmu) - 1);
|
|
|
|
int userIOS = m_gcfg2.getInt(id, "ios", 0);
|
|
u64 gameTitle = TITLE_ID(hdr->settings[0],hdr->settings[1]);
|
|
bool useNK2o = (m_gcfg2.getBool(id, "useneek", false) && !neek2o());
|
|
bool use_led = m_gcfg2.getBool(id, "led", false);
|
|
u32 gameIOS = ChannelHandle.GetRequestedIOS(gameTitle);
|
|
|
|
m_gcfg1.save(true);
|
|
m_gcfg2.save(true);
|
|
m_cat.save(true);
|
|
m_cfg.save(true);
|
|
cleanup();
|
|
|
|
if(NAND_Emu && !neek2o())
|
|
{
|
|
NANDemuView = true;
|
|
if(useNK2o)
|
|
{
|
|
if(!Load_Neek2o_Kernel())
|
|
{
|
|
error(_t("errneek1", L"Cannot launch neek2o. Verify your neek2o setup"));
|
|
Sys_Exit();
|
|
}
|
|
ShutdownBeforeExit();
|
|
Launch_nk(gameTitle, NandHandle.Get_NandPath(),
|
|
returnTo ? (((u64)(0x00010001) << 32) | (returnTo & 0xFFFFFFFF)) : 0);
|
|
while(1) usleep(500);
|
|
}
|
|
}
|
|
if(_loadIOS(gameIOS, userIOS, id, !NAND_Emu) == LOAD_IOS_FAILED)
|
|
Sys_Exit();
|
|
if((CurrentIOS.Type == IOS_TYPE_D2X || neek2o()) && returnTo != 0)
|
|
{
|
|
if(D2X_PatchReturnTo(returnTo) >= 0)
|
|
memset(&returnTo, 0, sizeof(u32));
|
|
}
|
|
if(NAND_Emu && !neek2o())
|
|
{
|
|
/* Enable our Emu NAND */
|
|
DeviceHandle.UnMountAll();
|
|
if(emulate_mode == 1)
|
|
NandHandle.Set_FullMode(true);
|
|
else
|
|
NandHandle.Set_FullMode(false);
|
|
if(NandHandle.Enable_Emu() < 0)
|
|
{
|
|
NandHandle.Disable_Emu();
|
|
error(_t("errgame5", L"Enabling emu failed!"));
|
|
Sys_Exit();
|
|
}
|
|
DeviceHandle.MountAll();
|
|
}
|
|
if(WII_Launch)
|
|
{
|
|
ShutdownBeforeExit();
|
|
WII_Initialize();
|
|
WII_LaunchTitle(gameTitle);
|
|
}
|
|
else
|
|
{
|
|
setLanguage(language);
|
|
ocarina_load_code(cheatFile, cheatSize);
|
|
NandHandle.Patch_AHB(); /* Identify may takes it */
|
|
PatchIOS(true); /* Patch for everything */
|
|
Identify(gameTitle);
|
|
if(ExternalBooter_LoadBooter(fmt("%s/ext_booter.bin", m_binsDir.c_str())) == true)
|
|
{
|
|
ExternalBooter_ChannelSetup(gameTitle, use_dol);
|
|
WiiFlow_ExternalBooter(videoMode, vipatch, countryPatch, patchVidMode, aspectRatio, 0, TYPE_CHANNEL, use_led);
|
|
}
|
|
}
|
|
Sys_Exit();
|
|
}
|
|
|
|
void CMenu::_launchGame(dir_discHdr *hdr, bool dvd)
|
|
{
|
|
_launchShutdown();
|
|
string id(hdr->id);
|
|
string path(hdr->path);
|
|
if(neek2o())
|
|
{
|
|
int discID = id.c_str()[0] << 24 | id.c_str()[1] << 16 | id.c_str()[2] << 8 | id.c_str()[3];
|
|
if(WDVD_NEEK_LoadDisc((discID&0xFFFFFFFF), 0x5D1C9EA3) > 0)
|
|
{
|
|
dvd = true;
|
|
sleep(3);
|
|
}
|
|
}
|
|
|
|
if(dvd)
|
|
{
|
|
u32 cover = 0;
|
|
if(!neek2o() && !Sys_DolphinMode())
|
|
{
|
|
if(WDVD_GetCoverStatus(&cover) < 0)
|
|
{
|
|
error(_t("errgame7", L"WDVDGetCoverStatus Failed!"));
|
|
Sys_Exit();
|
|
}
|
|
if(!(cover & 0x2))
|
|
{
|
|
error(_t("errgame8", L"Please insert a game disc."));
|
|
do
|
|
{
|
|
WDVD_GetCoverStatus(&cover);
|
|
if(BTN_B_PRESSED)
|
|
return;
|
|
} while(!(cover & 0x2));
|
|
}
|
|
}
|
|
TempLoadIOS();
|
|
/* Open Disc */
|
|
if(Disc_Open(true) < 0)
|
|
{
|
|
error(_t("wbfsoperr2", L"Disc_Open failed"));
|
|
Sys_Exit();
|
|
}
|
|
/* Check disc */
|
|
if(Disc_IsWii() < 0)
|
|
{
|
|
if (Disc_IsGC() < 0)
|
|
{
|
|
error(_t("errgame9", L"This is not a Wii or GC disc"));
|
|
Sys_Exit();
|
|
}
|
|
else
|
|
{
|
|
/* Read GC disc header */
|
|
Disc_ReadGCHeader(&gc_hdr);
|
|
memcpy(hdr->id, gc_hdr.id, 6);
|
|
/* Launching GC Game */
|
|
_launchGC(hdr, true);
|
|
return;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* Read header */
|
|
Disc_ReadHeader(&wii_hdr);
|
|
id = string((const char*)wii_hdr.id, 6);
|
|
}
|
|
gprintf("Game ID: %s\n", id.c_str());
|
|
}
|
|
|
|
bool vipatch = m_gcfg2.testOptBool(id, "vipatch", m_cfg.getBool("GENERAL", "vipatch", false));
|
|
bool countryPatch = m_gcfg2.testOptBool(id, "country_patch", m_cfg.getBool("GENERAL", "country_patch", false));
|
|
|
|
u8 patchVidMode = min((u32)m_gcfg2.getInt(id, "patch_video_modes", 0), ARRAY_SIZE(CMenu::_vidModePatch) - 1u);
|
|
u8 videoMode = (u8)min((u32)m_gcfg2.getInt(id, "video_mode", 0), ARRAY_SIZE(CMenu::_VideoModes) - 1u);
|
|
videoMode = (videoMode == 0) ? (u8)min((u32)m_cfg.getInt("GENERAL", "video_mode", 0), ARRAY_SIZE(CMenu::_GlobalVideoModes) - 1) : videoMode-1;
|
|
|
|
int language = min((u32)m_gcfg2.getInt(id, "language", 0), ARRAY_SIZE(CMenu::_languages) - 1u);
|
|
language = (language == 0) ? min((u32)m_cfg.getInt("GENERAL", "game_language", 0), ARRAY_SIZE(CMenu::_languages) - 1) : language;
|
|
|
|
const char *rtrn = m_cfg.getString("GENERAL", "returnto", "").c_str();
|
|
int aspectRatio = min((u32)m_gcfg2.getInt(id, "aspect_ratio", 0), ARRAY_SIZE(CMenu::_AspectRatio) - 1u)-1;
|
|
|
|
string emuPath;
|
|
int emuPartition = 0;
|
|
|
|
u8 emulate_mode = min((u32)m_gcfg2.getInt(id, "emulate_save", 0), ARRAY_SIZE(CMenu::_SaveEmu) - 1u);
|
|
if(emulate_mode == 0)
|
|
{
|
|
emulate_mode = min(max(0, m_cfg.getInt(WII_DOMAIN, "save_emulation", 0)), (int)ARRAY_SIZE(CMenu::_GlobalSaveEmu) - 1);
|
|
if(emulate_mode != 0)
|
|
emulate_mode++;
|
|
}
|
|
else if(emulate_mode == 1)
|
|
emulate_mode = 0;
|
|
m_current_view = COVERFLOW_USB; // used for _FindEmuPart()
|
|
if(emulate_mode && !dvd && !neek2o())
|
|
{
|
|
emuPartition = _FindEmuPart(emuPath, false);
|
|
if(emuPartition < 0)
|
|
{
|
|
if(emulate_mode == 4)
|
|
{
|
|
_hideWaitMessage();
|
|
while(true)
|
|
{
|
|
_AutoCreateNand();
|
|
if(_TestEmuNand(m_cfg.getInt(WII_DOMAIN, "savepartition", 0), emuPath.c_str(), true))
|
|
{
|
|
emuPartition = m_cfg.getInt(WII_DOMAIN, "savepartition", -1);
|
|
emuPath = m_cfg.getString(WII_DOMAIN, "savepath", m_cfg.getString(CHANNEL_DOMAIN, "path", ""));
|
|
break;
|
|
}
|
|
}
|
|
_showWaitMessage();
|
|
}
|
|
else
|
|
{
|
|
emuPartition = _FindEmuPart(emuPath, true);
|
|
NandHandle.CreatePath("%s:/wiiflow", DeviceName[emuPartition]);
|
|
NandHandle.CreatePath("%s:/wiiflow/nandemu", DeviceName[emuPartition]);
|
|
}
|
|
}
|
|
/* Set them */
|
|
NANDemuView = true;
|
|
m_cfg.setInt(WII_DOMAIN, "savepartition", emuPartition);
|
|
m_cfg.setString(WII_DOMAIN, "savepath", emuPath);
|
|
if(emulate_mode == 2)
|
|
{
|
|
m_forceext = false;
|
|
_hideWaitMessage();
|
|
if(!_AutoExtractSave(id))
|
|
NandHandle.CreateTitleTMD(hdr);
|
|
_showWaitMessage();
|
|
}
|
|
else if(emulate_mode > 2)
|
|
{
|
|
NandHandle.CreateConfig();
|
|
NandHandle.Do_Region_Change(id);
|
|
}
|
|
}
|
|
else
|
|
emulate_mode = 0;
|
|
|
|
bool use_led = m_gcfg2.getBool(id, "led", false);
|
|
bool cheat = m_gcfg2.testOptBool(id, "cheat", m_cfg.getBool(WII_DOMAIN, "cheat", false));
|
|
debuggerselect = m_gcfg2.getInt(id, "debugger", 0); // debuggerselect is defined in fst.h
|
|
if((id == "RPWE41" || id == "RPWZ41" || id == "SPXP41") && debuggerselect == 1) // Prince of Persia, Rival Swords
|
|
debuggerselect = 0;
|
|
hooktype = (u32)m_gcfg2.getInt(id, "hooktype", 0); // hooktype is defined in patchcode.h
|
|
if((cheat || debuggerselect == 1) && hooktype == 0)
|
|
hooktype = 1;
|
|
else if(!cheat && debuggerselect != 1)
|
|
hooktype = 0;
|
|
|
|
u8 *cheatFile = NULL;
|
|
u8 *gameconfig = NULL;
|
|
u32 cheatSize = 0, gameconfigSize = 0, returnTo = 0;
|
|
|
|
m_cfg.setString(WII_DOMAIN, "current_item", id);
|
|
m_gcfg1.setInt("PLAYCOUNT", id, m_gcfg1.getInt("PLAYCOUNT", id, 0) + 1);
|
|
m_gcfg1.setUInt("LASTPLAYED", id, time(NULL));
|
|
|
|
if(has_enabled_providers() && _initNetwork() == 0)
|
|
add_game_to_card(id.c_str());
|
|
|
|
setLanguage(language);
|
|
|
|
load_wip_patches((u8 *)m_wipDir.c_str(), (u8 *) &id);
|
|
if(cheat)
|
|
_loadFile(cheatFile, cheatSize, m_cheatDir.c_str(), fmt("%s.gct", id.c_str()));
|
|
_loadFile(gameconfig, gameconfigSize, m_txtCheatDir.c_str(), "gameconfig.txt");
|
|
|
|
if(strlen(rtrn) == 4)
|
|
returnTo = rtrn[0] << 24 | rtrn[1] << 16 | rtrn[2] << 8 | rtrn[3];
|
|
int userIOS = m_gcfg2.getInt(id, "ios", 0);
|
|
int gameIOS = dvd && !neek2o() ? userIOS : GetRequestedGameIOS(hdr);
|
|
|
|
m_gcfg1.save(true);
|
|
m_gcfg2.save(true);
|
|
m_cat.save(true);
|
|
m_cfg.save(true);
|
|
cleanup(); // wifi and sd gecko doesnt work anymore after cleanup
|
|
|
|
if((!dvd || neek2o()) && !Sys_DolphinMode())
|
|
{
|
|
if(_loadIOS(gameIOS, userIOS, id) == LOAD_IOS_FAILED)
|
|
Sys_Exit();
|
|
}
|
|
if(CurrentIOS.Type == IOS_TYPE_D2X)
|
|
{
|
|
if(returnTo != 0 && !m_directLaunch && D2X_PatchReturnTo(returnTo) >= 0)
|
|
memset(&returnTo, 0, sizeof(u32));
|
|
if(emulate_mode)
|
|
{
|
|
/* Enable our Emu NAND */
|
|
DeviceHandle.UnMountAll();
|
|
if(emulate_mode == 3)
|
|
NandHandle.Set_RCMode(true);
|
|
else if(emulate_mode == 4)
|
|
NandHandle.Set_FullMode(true);
|
|
else
|
|
NandHandle.Set_FullMode(false);
|
|
if(NandHandle.Enable_Emu() < 0)
|
|
{
|
|
NandHandle.Disable_Emu();
|
|
error(_t("errgame6", L"Enabling emu after reload failed!"));
|
|
Sys_Exit();
|
|
}
|
|
DeviceHandle.MountAll();
|
|
}
|
|
}
|
|
bool wbfs_partition = false;
|
|
if(!dvd)
|
|
{
|
|
DeviceHandle.OpenWBFS(currentPartition);
|
|
wbfs_partition = (DeviceHandle.GetFSType(currentPartition) == PART_FS_WBFS);
|
|
if(!wbfs_partition && get_frag_list((u8 *)id.c_str(), (char*)path.c_str(), currentPartition == 0 ? 0x200 : USBStorage2_GetSectorSize()) < 0)
|
|
Sys_Exit();
|
|
WBFS_Close();
|
|
}
|
|
if(cheatFile != NULL)
|
|
{
|
|
ocarina_load_code(cheatFile, cheatSize);
|
|
free(cheatFile);
|
|
}
|
|
if(gameconfig != NULL)
|
|
{
|
|
app_gameconfig_load(id.c_str(), gameconfig, gameconfigSize);
|
|
free(gameconfig);
|
|
}
|
|
|
|
if(ExternalBooter_LoadBooter(fmt("%s/ext_booter.bin", m_binsDir.c_str())) == true)
|
|
{
|
|
ExternalBooter_WiiGameSetup(wbfs_partition, dvd, id.c_str());
|
|
WiiFlow_ExternalBooter(videoMode, vipatch, countryPatch, patchVidMode, aspectRatio, returnTo, TYPE_WII_GAME, use_led);
|
|
}
|
|
Sys_Exit();
|
|
}
|
|
|
|
void CMenu::_initGameMenu()
|
|
{
|
|
CColor fontColor(0xD0BFDFFF);
|
|
TexData texGameFavOn;
|
|
TexData texGameFavOnSel;
|
|
TexData texGameFavOff;
|
|
TexData texGameFavOffSel;
|
|
TexData texAdultOn;
|
|
TexData texAdultOnSel;
|
|
TexData texAdultOff;
|
|
TexData texAdultOffSel;
|
|
TexData texDelete;
|
|
TexData texDeleteSel;
|
|
TexData texSettings;
|
|
TexData texSettingsSel;
|
|
TexData texToggleBanner;
|
|
TexData bgLQ;
|
|
|
|
TexHandle.fromImageFile(texGameFavOn, fmt("%s/gamefavon.png", m_imgsDir.c_str()));
|
|
TexHandle.fromImageFile(texGameFavOnSel, fmt("%s/gamefavons.png", m_imgsDir.c_str()));
|
|
TexHandle.fromImageFile(texGameFavOff, fmt("%s/gamefavoff.png", m_imgsDir.c_str()));
|
|
TexHandle.fromImageFile(texGameFavOffSel, fmt("%s/gamefavoffs.png", m_imgsDir.c_str()));
|
|
TexHandle.fromImageFile(texAdultOn, fmt("%s/stopkidon.png", m_imgsDir.c_str()));
|
|
TexHandle.fromImageFile(texAdultOnSel, fmt("%s/stopkidons.png", m_imgsDir.c_str()));
|
|
TexHandle.fromImageFile(texAdultOff, fmt("%s/stopkidoff.png", m_imgsDir.c_str()));
|
|
TexHandle.fromImageFile(texAdultOffSel, fmt("%s/stopkidoffs.png", m_imgsDir.c_str()));
|
|
TexHandle.fromImageFile(texDelete, fmt("%s/delete.png", m_imgsDir.c_str()));
|
|
TexHandle.fromImageFile(texDeleteSel, fmt("%s/deletes.png", m_imgsDir.c_str()));
|
|
TexHandle.fromImageFile(texSettings, fmt("%s/btngamecfg.png", m_imgsDir.c_str()));
|
|
TexHandle.fromImageFile(texSettingsSel, fmt("%s/btngamecfgs.png", m_imgsDir.c_str()));
|
|
TexHandle.fromImageFile(texToggleBanner, fmt("%s/blank.png", m_imgsDir.c_str()));
|
|
|
|
_addUserLabels(m_gameLblUser, ARRAY_SIZE(m_gameLblUser), "GAME");
|
|
m_gameBg = _texture("GAME/BG", "texture", theme.bg, false);
|
|
if(m_theme.loaded() && TexHandle.fromImageFile(bgLQ, fmt("%s/%s", m_themeDataDir.c_str(), m_theme.getString("GAME/BG", "texture").c_str()), GX_TF_CMPR, 64, 64) == TE_OK)
|
|
m_gameBgLQ = bgLQ;
|
|
|
|
m_gameBtnPlay = _addButton("GAME/PLAY_BTN", theme.btnFont, L"", 420, 344, 200, 48, theme.btnFontColor);
|
|
m_gameBtnBack = _addButton("GAME/BACK_BTN", theme.btnFont, L"", 420, 400, 200, 48, theme.btnFontColor);
|
|
m_gameBtnFavoriteOn = _addPicButton("GAME/FAVORITE_ON", texGameFavOn, texGameFavOnSel, 460, 200, 48, 48);
|
|
m_gameBtnFavoriteOff = _addPicButton("GAME/FAVORITE_OFF", texGameFavOff, texGameFavOffSel, 460, 200, 48, 48);
|
|
m_gameBtnAdultOn = _addPicButton("GAME/ADULTONLY_ON", texAdultOn, texAdultOnSel, 532, 200, 48, 48);
|
|
m_gameBtnAdultOff = _addPicButton("GAME/ADULTONLY_OFF", texAdultOff, texAdultOffSel, 532, 200, 48, 48);
|
|
m_gameBtnSettings = _addPicButton("GAME/SETTINGS_BTN", texSettings, texSettingsSel, 460, 272, 48, 48);
|
|
m_gameBtnDelete = _addPicButton("GAME/DELETE_BTN", texDelete, texDeleteSel, 532, 272, 48, 48);
|
|
m_gameBtnBackFull = _addButton("GAME/BACK_FULL_BTN", theme.btnFont, L"", 100, 390, 200, 56, theme.btnFontColor);
|
|
m_gameBtnPlayFull = _addButton("GAME/PLAY_FULL_BTN", theme.btnFont, L"", 340, 390, 200, 56, theme.btnFontColor);
|
|
m_gameBtnToogle = _addPicButton("GAME/TOOGLE_BTN", texToggleBanner, texToggleBanner, 385, 31, 236, 127);
|
|
m_gameBtnToogleFull = _addPicButton("GAME/TOOGLE_FULL_BTN", texToggleBanner, texToggleBanner, 20, 12, 608, 344);
|
|
|
|
m_gameButtonsZone.x = m_theme.getInt("GAME/ZONES", "buttons_x", 0);
|
|
m_gameButtonsZone.y = m_theme.getInt("GAME/ZONES", "buttons_y", 0);
|
|
m_gameButtonsZone.w = m_theme.getInt("GAME/ZONES", "buttons_w", 640);
|
|
m_gameButtonsZone.h = m_theme.getInt("GAME/ZONES", "buttons_h", 480);
|
|
m_gameButtonsZone.hide = m_theme.getBool("GAME/ZONES", "buttons_hide", true);
|
|
|
|
_setHideAnim(m_gameBtnPlay, "GAME/PLAY_BTN", 0, 0, 1.f, -1.f);
|
|
_setHideAnim(m_gameBtnBack, "GAME/BACK_BTN", 0, 0, 1.f, -1.f);
|
|
_setHideAnim(m_gameBtnFavoriteOn, "GAME/FAVORITE_ON", 0, 0, 1.f, -1.f);
|
|
_setHideAnim(m_gameBtnFavoriteOff, "GAME/FAVORITE_OFF", 0, 0, 1.f, -1.f);
|
|
_setHideAnim(m_gameBtnAdultOn, "GAME/ADULTONLY_ON", 0, 0, 1.f, -1.f);
|
|
_setHideAnim(m_gameBtnAdultOff, "GAME/ADULTONLY_OFF", 0, 0, 1.f, -1.f);
|
|
_setHideAnim(m_gameBtnSettings, "GAME/SETTINGS_BTN", 0, 0, 1.f, -1.f);
|
|
_setHideAnim(m_gameBtnDelete, "GAME/DELETE_BTN", 0, 0, 1.f, -1.f);
|
|
_setHideAnim(m_gameBtnPlayFull, "GAME/PLAY_FULL_BTN", 0, 0, 1.f, 0.f);
|
|
_setHideAnim(m_gameBtnBackFull, "GAME/BACK_FULL_BTN", 0, 0, 1.f, 0.f);
|
|
_setHideAnim(m_gameBtnToogle, "GAME/TOOGLE_BTN", 200, 0, 1.f, 0.f);
|
|
_setHideAnim(m_gameBtnToogleFull, "GAME/TOOGLE_FULL_BTN", 200, 0, 1.f, 0.f);
|
|
_hideGame(true);
|
|
_textGame();
|
|
}
|
|
|
|
void CMenu::_textGame(void)
|
|
{
|
|
m_btnMgr.setText(m_gameBtnPlay, _t("gm1", L"Play"));
|
|
m_btnMgr.setText(m_gameBtnBack, _t("gm2", L"Back"));
|
|
m_btnMgr.setText(m_gameBtnPlayFull, _t("gm1", L"Play"));
|
|
m_btnMgr.setText(m_gameBtnBackFull, _t("gm2", L"Back"));
|
|
}
|
|
|
|
struct IMD5Header
|
|
{
|
|
u32 fcc;
|
|
u32 filesize;
|
|
u8 zeroes[8];
|
|
u8 crypto[16];
|
|
} ATTRIBUTE_PACKED;
|
|
|
|
static const u32 BNR_MAX_SIZE = 0x00200000; /* 2MB */
|
|
static u8 *BNR_LOC = (u8*)0x90000000;
|
|
|
|
void CMenu::_gameSoundThread(CMenu *m)
|
|
{
|
|
m->m_soundThrdBusy = true;
|
|
m->m_gamesound_changed = false;
|
|
CurrentBanner.ClearBanner();
|
|
|
|
const dir_discHdr *GameHdr = CoverFlow.getHdr();
|
|
if(GameHdr->type == TYPE_PLUGIN)
|
|
{
|
|
m_banner.DeleteBanner();
|
|
m->m_gameSound.Load(m_plugin.GetBannerSound(GameHdr->settings[0]), m_plugin.GetBannerSoundSize());
|
|
if(m->m_gameSound.IsLoaded())
|
|
m->m_gamesound_changed = true;
|
|
m->m_soundThrdBusy = false;
|
|
return;
|
|
}
|
|
u8 *custom_bnr_file = NULL;
|
|
u32 custom_bnr_size = 0;
|
|
|
|
u8 *cached_bnr_file = NULL;
|
|
u32 cached_bnr_size = 0;
|
|
|
|
char cached_banner[256];
|
|
cached_banner[255] = '\0';
|
|
char custom_banner[256];
|
|
custom_banner[255] = '\0';
|
|
/* check custom ID6 first */
|
|
strncpy(custom_banner, fmt("%s/%s.bnr", m->m_customBnrDir.c_str(), GameHdr->id), 255);
|
|
fsop_GetFileSizeBytes(custom_banner, &custom_bnr_size);
|
|
if(custom_bnr_size > 0 && custom_bnr_size < BNR_MAX_SIZE)
|
|
{
|
|
custom_bnr_file = BNR_LOC;
|
|
fsop_ReadFileLoc(custom_banner, custom_bnr_size, BNR_LOC);
|
|
}
|
|
else /* no custom ID6 or too big, try ID3 */
|
|
{
|
|
strncpy(custom_banner, fmt("%s/%.3s.bnr", m->m_customBnrDir.c_str(), GameHdr->id), 255);
|
|
fsop_GetFileSizeBytes(custom_banner, &custom_bnr_size);
|
|
if(custom_bnr_size > 0 && custom_bnr_size < BNR_MAX_SIZE)
|
|
{
|
|
custom_bnr_file = BNR_LOC;
|
|
fsop_ReadFileLoc(custom_banner, custom_bnr_size, BNR_LOC);
|
|
}
|
|
}
|
|
if(custom_bnr_file == NULL && GameHdr->type == TYPE_GC_GAME)
|
|
{
|
|
if(m->_QF_Game(GameHdr->id) == false)
|
|
{
|
|
GC_Disc_Reader.init(GameHdr->path);
|
|
u8 *opening_bnr = GC_Disc_Reader.GetGameCubeBanner();
|
|
if(opening_bnr != NULL)
|
|
m_banner.CreateGCBanner(opening_bnr, m->m_wbf1_font, m->m_wbf2_font, GameHdr->title);
|
|
GC_Disc_Reader.clear();
|
|
}
|
|
m->m_gameSound.Load(gc_ogg, gc_ogg_size, false);
|
|
if(m->m_gameSound.IsLoaded())
|
|
m->m_gamesound_changed = true;
|
|
m->m_soundThrdBusy = false;
|
|
return;
|
|
}
|
|
if(custom_bnr_file == NULL)/* no custom and not GC game try cached banner*/
|
|
{
|
|
strncpy(cached_banner, fmt("%s/%s.bnr", m->m_bnrCacheDir.c_str(), GameHdr->id), 255);
|
|
fsop_GetFileSizeBytes(cached_banner, &cached_bnr_size);
|
|
if(cached_bnr_size > 0 && cached_bnr_size < BNR_MAX_SIZE)
|
|
{
|
|
cached_bnr_file = BNR_LOC;
|
|
fsop_ReadFileLoc(cached_banner, cached_bnr_size, BNR_LOC);
|
|
}
|
|
}
|
|
|
|
if(custom_bnr_file != NULL)
|
|
CurrentBanner.SetBanner(custom_bnr_file, custom_bnr_size, true);
|
|
else if(cached_bnr_file != NULL)
|
|
CurrentBanner.SetBanner(cached_bnr_file, cached_bnr_size);
|
|
else if(GameHdr->type == TYPE_WII_GAME)
|
|
_extractBnr(GameHdr);
|
|
else if(GameHdr->type == TYPE_CHANNEL)
|
|
_extractChannelBnr(TITLE_ID(GameHdr->settings[0],
|
|
GameHdr->settings[1]));
|
|
if(!CurrentBanner.IsValid())
|
|
{
|
|
m->m_gameSound.FreeMemory();
|
|
m_banner.DeleteBanner();
|
|
CurrentBanner.ClearBanner();
|
|
m->m_soundThrdBusy = false;
|
|
return;
|
|
}
|
|
if(cached_bnr_file == NULL && custom_bnr_file == NULL)
|
|
fsop_WriteFile(cached_banner, CurrentBanner.GetBannerFile(), CurrentBanner.GetBannerFileSize());
|
|
|
|
u32 sndSize = 0;
|
|
m_banner.LoadBanner(m->m_wbf1_font, m->m_wbf2_font);
|
|
u8 *soundBin = CurrentBanner.GetFile("sound.bin", &sndSize);
|
|
CurrentBanner.ClearBanner();
|
|
|
|
if(soundBin != NULL)
|
|
{
|
|
if(memcmp(&((IMD5Header *)soundBin)->fcc, "IMD5", 4) == 0)
|
|
{
|
|
u32 newSize = 0;
|
|
u8 *newSound = DecompressCopy(soundBin, sndSize, &newSize);
|
|
if(newSound == NULL || newSize == 0 || !m->m_gameSound.Load(newSound, newSize))
|
|
{
|
|
free(soundBin);
|
|
m->m_gameSound.FreeMemory();
|
|
m_banner.DeleteBanner();
|
|
m->m_soundThrdBusy = false;
|
|
return;
|
|
}
|
|
free(soundBin);
|
|
}
|
|
else
|
|
m->m_gameSound.Load(soundBin, sndSize);
|
|
|
|
if(m->m_gameSound.IsLoaded())
|
|
m->m_gamesound_changed = true;
|
|
else
|
|
{
|
|
m->m_gameSound.FreeMemory();
|
|
m_banner.DeleteBanner();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
gprintf("WARNING: No sound found in banner!\n");
|
|
m->m_gamesound_changed = true;
|
|
m->m_gameSound.FreeMemory();
|
|
}
|
|
m->m_soundThrdBusy = false;
|
|
}
|
|
|
|
u8 *GameSoundStack = NULL;
|
|
u32 GameSoundSize = 0x10000; //64kb
|
|
void CMenu::_playGameSound(void)
|
|
{
|
|
m_gamesound_changed = false;
|
|
if(m_bnrSndVol == 0)
|
|
return;
|
|
|
|
if(m_gameSoundThread != LWP_THREAD_NULL)
|
|
CheckGameSoundThread();
|
|
GameSoundStack = (u8*)MEM2_alloc(GameSoundSize);
|
|
LWP_CreateThread(&m_gameSoundThread, (void *(*)(void *))CMenu::_gameSoundThread, (void*)this, GameSoundStack, GameSoundSize, 60);
|
|
}
|
|
|
|
void CMenu::CheckGameSoundThread()
|
|
{
|
|
if(m_gameSoundThread == LWP_THREAD_NULL)
|
|
return;
|
|
|
|
if(LWP_ThreadIsSuspended(m_gameSoundThread))
|
|
LWP_ResumeThread(m_gameSoundThread);
|
|
|
|
while(m_soundThrdBusy)
|
|
usleep(50);
|
|
|
|
LWP_JoinThread(m_gameSoundThread, NULL);
|
|
m_gameSoundThread = LWP_THREAD_NULL;
|
|
|
|
if(GameSoundStack)
|
|
free(GameSoundStack);
|
|
GameSoundStack = NULL;
|
|
}
|