2010-10-27 21:50:48 +02:00
|
|
|
#include "menu/menus.h"
|
2011-01-16 14:12:07 +01:00
|
|
|
#include "menu/WDMMenu.hpp"
|
2010-10-27 21:50:48 +02:00
|
|
|
#include "mload/mload.h"
|
|
|
|
#include "mload/mload_modules.h"
|
2010-11-07 13:16:34 +01:00
|
|
|
#include "system/IosLoader.h"
|
2010-12-31 00:49:22 +01:00
|
|
|
#include "Controls/DeviceHandler.hpp"
|
2010-10-27 21:50:48 +02:00
|
|
|
#include "usbloader/disc.h"
|
2010-11-06 16:30:14 +01:00
|
|
|
#include "usbloader/apploader.h"
|
|
|
|
#include "usbloader/wdvd.h"
|
2010-10-27 21:50:48 +02:00
|
|
|
#include "usbloader/GameList.h"
|
|
|
|
#include "settings/Settings.h"
|
|
|
|
#include "settings/CGameSettings.h"
|
|
|
|
#include "usbloader/frag.h"
|
|
|
|
#include "usbloader/wbfs.h"
|
2010-12-27 10:44:27 +01:00
|
|
|
#include "usbloader/playlog.h"
|
2010-12-31 00:49:22 +01:00
|
|
|
#include "usbloader/MountGamePartition.h"
|
2011-01-21 20:43:59 +01:00
|
|
|
#include "usbloader/AlternateDOLOffsets.h"
|
2010-10-27 21:50:48 +02:00
|
|
|
#include "settings/newtitles.h"
|
|
|
|
#include "patches/fst.h"
|
2010-11-06 16:30:14 +01:00
|
|
|
#include "patches/gamepatches.h"
|
|
|
|
#include "patches/wip.h"
|
|
|
|
#include "system/IosLoader.h"
|
2010-12-27 10:44:27 +01:00
|
|
|
#include "banner/OpeningBNR.hpp"
|
2010-10-27 21:50:48 +02:00
|
|
|
#include "wad/nandtitle.h"
|
2010-11-06 16:30:14 +01:00
|
|
|
#include "menu/menus.h"
|
|
|
|
#include "memory/memory.h"
|
2011-01-22 01:06:28 +01:00
|
|
|
#include "GameBooter.hpp"
|
2010-11-06 16:30:14 +01:00
|
|
|
#include "sys.h"
|
|
|
|
|
|
|
|
//appentrypoint has to be global because of asm
|
|
|
|
u32 AppEntrypoint = 0;
|
2010-10-27 21:50:48 +02:00
|
|
|
|
|
|
|
struct discHdr *dvdheader = NULL;
|
2011-01-28 22:19:43 +01:00
|
|
|
extern u32 hdd_sector_size;
|
2010-10-27 21:50:48 +02:00
|
|
|
extern int mountMethod;
|
|
|
|
|
2011-01-22 01:06:28 +01:00
|
|
|
int GameBooter::BootGCMode()
|
|
|
|
{
|
|
|
|
ExitApp();
|
|
|
|
gprintf("\nLoading BC for GameCube");
|
|
|
|
WII_Initialize();
|
|
|
|
return WII_LaunchTitle(0x0000000100000100ULL);
|
|
|
|
}
|
2010-11-06 16:30:14 +01:00
|
|
|
|
2011-01-22 01:06:28 +01:00
|
|
|
|
|
|
|
u32 GameBooter::BootPartition(char * dolpath, u8 videoselected, u8 languageChoice, u8 cheat, u8 vipatch, u8 patchcountrystring,
|
|
|
|
u8 alternatedol, u32 alternatedoloffset, u32 returnTo, u8 fix002)
|
2010-11-06 16:30:14 +01:00
|
|
|
{
|
2011-01-16 14:12:07 +01:00
|
|
|
gprintf("booting partition IOS %u r%u\n", IOS_GetVersion(), IOS_GetRevision());
|
2010-11-06 16:30:14 +01:00
|
|
|
entry_point p_entry;
|
|
|
|
s32 ret;
|
|
|
|
u64 offset;
|
|
|
|
|
|
|
|
/* Find game partition offset */
|
|
|
|
ret = __Disc_FindPartition(&offset);
|
|
|
|
if (ret < 0)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
/* Open specified partition */
|
|
|
|
ret = WDVD_OpenPartition(offset);
|
|
|
|
if (ret < 0)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
load_wip_code((u8*) Disc_ID);
|
|
|
|
|
|
|
|
/* If a wip file is loaded for this game this does nothing - Dimok */
|
|
|
|
PoPPatch();
|
2011-01-09 18:51:15 +01:00
|
|
|
NSMBPatch();
|
2010-11-06 16:30:14 +01:00
|
|
|
|
|
|
|
/* Setup low memory */
|
|
|
|
__Disc_SetLowMem();
|
|
|
|
|
|
|
|
/* Run apploader */
|
|
|
|
ret = Apploader_Run(&p_entry, dolpath, cheat, videoselected, languageChoice, vipatch, patchcountrystring,
|
|
|
|
alternatedol, alternatedoloffset, returnTo, fix002);
|
|
|
|
|
|
|
|
if (ret < 0)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
free_wip();
|
|
|
|
|
|
|
|
return (u32) p_entry;
|
|
|
|
}
|
|
|
|
|
2011-01-22 01:06:28 +01:00
|
|
|
int GameBooter::FindDiscHeader(const char * gameID, struct discHdr &gameHeader)
|
2010-10-27 21:50:48 +02:00
|
|
|
{
|
|
|
|
gameList.LoadUnfiltered();
|
|
|
|
|
2010-12-26 18:02:14 +01:00
|
|
|
if(mountMethod == 0 && !gameList.GetDiscHeader(gameID))
|
2010-10-27 21:50:48 +02:00
|
|
|
{
|
|
|
|
gprintf("Game was not found: %s\n", gameID);
|
|
|
|
return -1;
|
|
|
|
}
|
2010-12-26 18:02:14 +01:00
|
|
|
else if(mountMethod && !dvdheader)
|
|
|
|
{
|
|
|
|
gprintf("Error: Loading empty disc header from DVD\n");
|
|
|
|
return -1;
|
|
|
|
}
|
2010-10-27 21:50:48 +02:00
|
|
|
|
2010-12-26 18:02:14 +01:00
|
|
|
memcpy(&gameHeader, (mountMethod ? dvdheader : gameList.GetDiscHeader(gameID)), sizeof(struct discHdr));
|
2010-11-28 21:04:29 +01:00
|
|
|
|
2010-12-26 18:02:14 +01:00
|
|
|
delete dvdheader;
|
|
|
|
dvdheader = NULL;
|
2011-01-12 20:30:04 +01:00
|
|
|
|
2011-01-22 01:06:28 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void GameBooter::SetupAltDOL(u8 * gameID, u8 &alternatedol, u32 &alternatedoloffset)
|
|
|
|
{
|
|
|
|
if(alternatedol == ALT_DOL_ON_LAUNCH)
|
|
|
|
{
|
|
|
|
alternatedol = ALT_DOL_FROM_GAME;
|
|
|
|
alternatedoloffset = WDMMenu::GetAlternateDolOffset();
|
|
|
|
}
|
|
|
|
else if(alternatedol == ALT_DOL_DEFAULT)
|
|
|
|
{
|
|
|
|
alternatedol = ALT_DOL_FROM_GAME;
|
|
|
|
alternatedoloffset = defaultAltDol((char *) gameID);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(alternatedol == ALT_DOL_FROM_GAME && alternatedoloffset == 0)
|
|
|
|
alternatedol = OFF;
|
|
|
|
}
|
|
|
|
|
|
|
|
int GameBooter::SetupDisc(u8 * gameID)
|
|
|
|
{
|
|
|
|
if (mountMethod)
|
|
|
|
{
|
|
|
|
gprintf("\tloading DVD\n");
|
|
|
|
return Disc_Open();
|
|
|
|
}
|
|
|
|
|
|
|
|
int ret = -1;
|
|
|
|
|
2011-01-28 22:19:43 +01:00
|
|
|
if(((IosLoader::IsWaninkokoIOS() && IOS_GetRevision() < 18) ||
|
2011-02-02 19:30:15 +01:00
|
|
|
hdd_sector_size != 512) && gameList.GetGameFS(gameID) == PART_FS_WBFS)
|
2011-01-22 01:06:28 +01:00
|
|
|
{
|
|
|
|
gprintf("Disc_SetUSB...");
|
|
|
|
ret = Disc_SetUSB(gameID);
|
|
|
|
gprintf("%d\n", ret);
|
|
|
|
if(ret < 0) return ret;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
gprintf("Loading fragment list...");
|
|
|
|
ret = get_frag_list(gameID);
|
|
|
|
gprintf("%d\n", ret);
|
|
|
|
if(ret < 0) return ret;
|
|
|
|
ret = set_frag_list(gameID);
|
|
|
|
if(ret < 0) return ret;
|
|
|
|
gprintf("\tUSB set to game\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
gprintf("Disc_Open()...");
|
|
|
|
ret = Disc_Open();
|
|
|
|
gprintf("%d\n", ret);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool GameBooter::LoadOcarina(u8 *gameID)
|
|
|
|
{
|
|
|
|
if (ocarina_load_code(gameID) > 0)
|
|
|
|
{
|
|
|
|
ocarina_do_code();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
int GameBooter::BootGame(const char * gameID)
|
|
|
|
{
|
|
|
|
if(!gameID || strlen(gameID) < 3)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (mountMethod == 2)
|
|
|
|
return BootGCMode();
|
|
|
|
|
|
|
|
AppCleanUp();
|
2010-10-27 21:50:48 +02:00
|
|
|
|
2011-01-22 01:06:28 +01:00
|
|
|
gprintf("\tSettings.partition: %d\n", Settings.partition);
|
|
|
|
|
|
|
|
struct discHdr gameHeader;
|
|
|
|
|
|
|
|
//! Find disc header in the game list first
|
|
|
|
int ret = FindDiscHeader(gameID, gameHeader);
|
|
|
|
if(ret < 0)
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
//! Setup game configuration from game settings. If no game settings exist use global/default.
|
2010-12-26 18:02:14 +01:00
|
|
|
GameCFG * game_cfg = GameSettings.GetGameCFG(gameHeader.id);
|
2011-01-21 20:43:59 +01:00
|
|
|
u8 videoChoice = game_cfg->video;
|
|
|
|
u8 languageChoice = game_cfg->language;
|
|
|
|
u8 ocarinaChoice = game_cfg->ocarina;
|
|
|
|
u8 viChoice = game_cfg->vipatch;
|
|
|
|
u8 iosChoice = game_cfg->ios;
|
|
|
|
u8 fix002 = game_cfg->errorfix002;
|
|
|
|
u8 countrystrings = game_cfg->patchcountrystrings;
|
|
|
|
u8 alternatedol = game_cfg->loadalternatedol;
|
|
|
|
u32 alternatedoloffset = game_cfg->alternatedolstart;
|
|
|
|
u8 reloadblock = game_cfg->iosreloadblock;
|
|
|
|
u8 returnToLoaderGV = game_cfg->returnTo;
|
|
|
|
|
2011-01-22 01:06:28 +01:00
|
|
|
//! Prepare alternate dol settings
|
|
|
|
SetupAltDOL(gameHeader.id, alternatedol, alternatedoloffset);
|
|
|
|
|
|
|
|
//! Setup the return to Loader option
|
|
|
|
u32 channel = 0;
|
|
|
|
if (returnToLoaderGV)
|
2011-01-21 20:43:59 +01:00
|
|
|
{
|
2011-01-22 01:06:28 +01:00
|
|
|
int idx = NandTitles.FindU32(Settings.returnTo);
|
|
|
|
if (idx >= 0) channel = TITLE_LOWER( NandTitles.At( idx ) );
|
2011-01-21 20:43:59 +01:00
|
|
|
}
|
2011-01-16 14:12:07 +01:00
|
|
|
|
2011-01-22 01:06:28 +01:00
|
|
|
//! This is temporary - C <-> C++ transfer
|
|
|
|
SetCheatFilepath(Settings.Cheatcodespath);
|
|
|
|
SetBCAFilepath(Settings.BcaCodepath);
|
|
|
|
|
|
|
|
//! Reload game settings cIOS for this game
|
2010-11-06 16:30:14 +01:00
|
|
|
if(iosChoice != IOS_GetVersion())
|
|
|
|
{
|
2010-11-07 13:16:34 +01:00
|
|
|
gprintf("Reloading into game cIOS: %i...\n", iosChoice);
|
2010-11-06 16:30:14 +01:00
|
|
|
IosLoader::LoadGameCios(iosChoice);
|
|
|
|
if(MountGamePartition(false) < 0)
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2011-01-22 01:06:28 +01:00
|
|
|
//! Setup disc in cIOS and open it
|
|
|
|
ret = SetupDisc(gameHeader.id);
|
2010-11-07 13:16:34 +01:00
|
|
|
if (ret < 0)
|
|
|
|
Sys_BackToLoader();
|
2010-10-27 21:50:48 +02:00
|
|
|
|
2011-01-22 01:06:28 +01:00
|
|
|
//! Load BCA data for the game
|
2010-10-27 21:50:48 +02:00
|
|
|
gprintf("Loading BCA data...");
|
2010-12-26 18:02:14 +01:00
|
|
|
ret = do_bca_code(gameHeader.id);
|
2010-10-27 21:50:48 +02:00
|
|
|
gprintf("%d\n", ret);
|
|
|
|
|
2011-01-22 01:06:28 +01:00
|
|
|
//! Setup IOS reload block - only possible on Hermes cIOS
|
2010-11-07 13:16:34 +01:00
|
|
|
if (reloadblock == ON && IosLoader::IsHermesIOS())
|
2010-10-27 21:50:48 +02:00
|
|
|
{
|
|
|
|
enable_ES_ioctlv_vector();
|
2011-02-02 19:30:15 +01:00
|
|
|
if (gameList.GetGameFS(gameHeader.id) == PART_FS_WBFS)
|
2010-10-27 21:50:48 +02:00
|
|
|
mload_close();
|
|
|
|
}
|
2011-02-02 19:30:15 +01:00
|
|
|
|
|
|
|
//! Now we can free up the memory used by the game list
|
|
|
|
gameList.clear();
|
2010-10-27 21:50:48 +02:00
|
|
|
|
2011-01-22 01:06:28 +01:00
|
|
|
//! Load main.dol or alternative dol into memory, start the game apploader and get game entrypoint
|
2010-10-27 21:50:48 +02:00
|
|
|
gprintf("\tDisc_wiiBoot\n");
|
2010-11-06 16:30:14 +01:00
|
|
|
AppEntrypoint = BootPartition(Settings.dolpath, videoChoice, languageChoice, ocarinaChoice, viChoice, countrystrings,
|
2010-10-27 21:50:48 +02:00
|
|
|
alternatedol, alternatedoloffset, channel, fix002);
|
|
|
|
|
2011-01-22 01:06:28 +01:00
|
|
|
//! No entrypoint found...back to HBC/SystemMenu
|
2011-01-21 20:43:59 +01:00
|
|
|
if(AppEntrypoint == 0)
|
2010-11-06 16:30:14 +01:00
|
|
|
{
|
2011-01-21 20:43:59 +01:00
|
|
|
WDVD_ClosePartition();
|
|
|
|
Sys_BackToLoader();
|
|
|
|
}
|
|
|
|
|
2011-01-22 01:06:28 +01:00
|
|
|
//! Load Ocarina codes
|
2011-01-21 20:43:59 +01:00
|
|
|
bool enablecheat = false;
|
|
|
|
if (ocarinaChoice)
|
2011-01-22 01:06:28 +01:00
|
|
|
enablecheat = LoadOcarina(gameHeader.id);
|
2010-11-06 16:30:14 +01:00
|
|
|
|
2011-01-22 01:06:28 +01:00
|
|
|
//! Shadow mload - Only needed on some games with Hermes v5.1 (Check is inside the function)
|
2011-01-21 20:43:59 +01:00
|
|
|
shadow_mload();
|
2011-01-22 01:06:28 +01:00
|
|
|
|
|
|
|
//! Flush all caches and close up all devices
|
2011-02-02 19:30:15 +01:00
|
|
|
WBFS_CloseAll();
|
2011-01-21 20:43:59 +01:00
|
|
|
DeviceHandler::DestroyInstance();
|
|
|
|
USB_Deinitialize();
|
2010-11-06 16:30:14 +01:00
|
|
|
|
2011-01-22 01:06:28 +01:00
|
|
|
//! Modify Wii Message Board to display the game starting here
|
2011-01-21 20:43:59 +01:00
|
|
|
if(Settings.PlaylogUpdate)
|
2011-01-22 01:06:28 +01:00
|
|
|
Playlog_Update((char *) gameHeader.id, BNRInstance::Instance()->GetIMETTitle(CONF_GetLanguage()));
|
2010-10-27 21:50:48 +02:00
|
|
|
|
2011-01-22 01:06:28 +01:00
|
|
|
//! Jump to the entrypoint of the game - the last function of the USB Loader
|
2011-01-21 20:43:59 +01:00
|
|
|
gprintf("Jumping to game entrypoint: 0x%08X.\n", AppEntrypoint);
|
|
|
|
return Disc_JumpToEntrypoint(videoChoice, enablecheat, WDMMenu::GetDolParameter());
|
2010-10-27 21:50:48 +02:00
|
|
|
}
|