2011-07-29 22:59:31 +02:00
/****************************************************************************
2013-03-17 14:48:15 +01:00
* Copyright ( C ) 2012 - 2013 Cyan
2011-07-29 22:59:31 +02:00
* Copyright ( C ) 2011 Dimok
*
* This program is free software : you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation , either version 3 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program . If not , see < http : //www.gnu.org/licenses/>.
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
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"
2011-11-12 19:14:09 +01:00
# include "Channels/channels.h"
2010-10-27 21:50:48 +02:00
# include "usbloader/disc.h"
2010-11-06 16:30:14 +01:00
# include "usbloader/apploader.h"
2011-02-05 22:06:52 +01:00
# include "usbloader/usbstorage2.h"
2010-11-06 16:30:14 +01:00
# include "usbloader/wdvd.h"
2010-10-27 21:50:48 +02:00
# include "usbloader/GameList.h"
# include "settings/CGameSettings.h"
2012-07-16 18:07:24 +02:00
# include "settings/SettingsEnums.h"
2010-10-27 21:50:48 +02:00
# 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"
2012-02-09 22:18:16 +01:00
# include "GameCube/GCGames.h"
2010-10-27 21:50:48 +02:00
# include "settings/newtitles.h"
2011-06-18 09:00:42 +02:00
# include "network/Wiinnertag.h"
2011-07-29 22:59:31 +02:00
# include "patches/patchcode.h"
2010-11-06 16:30:14 +01:00
# include "patches/gamepatches.h"
# include "patches/wip.h"
2011-07-29 22:59:31 +02:00
# include "patches/bca.h"
2010-11-06 16:30:14 +01:00
# 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"
2011-07-26 10:57:12 +02:00
# include "NandEmu.h"
2011-07-24 18:32:09 +02:00
# include "SavePath.h"
2010-11-06 16:30:14 +01:00
# include "sys.h"
2012-07-16 18:07:24 +02:00
# include "FileOperations/fileops.h"
# include "prompts/ProgressWindow.h"
2010-11-06 16:30:14 +01:00
//appentrypoint has to be global because of asm
u32 AppEntrypoint = 0 ;
2010-10-27 21:50:48 +02:00
2013-01-06 14:41:22 +01:00
extern u32 hdd_sector_size [ 2 ] ;
2012-02-09 22:18:16 +01:00
extern " C "
{
syssram * __SYS_LockSram ( ) ;
u32 __SYS_UnlockSram ( u32 write ) ;
u32 __SYS_SyncSram ( void ) ;
2012-08-24 18:55:49 +02:00
extern void __exception_closeall ( ) ;
2012-02-09 22:18:16 +01:00
}
2010-10-27 21:50:48 +02:00
2012-02-09 22:18:16 +01:00
int GameBooter : : BootGCMode ( struct discHdr * gameHdr )
2011-01-22 01:06:28 +01:00
{
2012-07-16 18:07:24 +02:00
// check the settings
GameCFG * game_cfg = GameSettings . GetGameCFG ( gameHdr - > id ) ;
u8 GCMode = game_cfg - > GameCubeMode = = INHERIT ? Settings . GameCubeMode : game_cfg - > GameCubeMode ;
2012-08-24 18:55:49 +02:00
// Devolution
if ( GCMode = = GC_MODE_DEVOLUTION )
return BootDevolution ( gameHdr ) ;
2012-07-16 18:07:24 +02:00
2012-08-24 18:55:49 +02:00
// DIOS MIOS (Lite) and QuadForce
2012-06-27 22:01:37 +02:00
int currentMIOS = IosLoader : : GetMIOSInfo ( ) ;
2012-08-24 18:55:49 +02:00
if ( currentMIOS = = DIOS_MIOS | | currentMIOS = = DIOS_MIOS_LITE | | currentMIOS = = QUADFORCE )
return BootDIOSMIOS ( gameHdr ) ;
// MIOS or Wiigator cMIOS
if ( gameHdr - > type = = TYPE_GAME_GC_DISC )
2012-07-16 18:07:24 +02:00
{
ExitApp ( ) ;
gprintf ( " \n Loading BC for GameCube " ) ;
WII_Initialize ( ) ;
return WII_LaunchTitle ( 0x0000000100000100ULL ) ;
}
2012-05-09 21:27:54 +02:00
2013-03-17 14:48:15 +01:00
// Check if Devolution is available
char DEVO_loader_path [ 100 ] ;
snprintf ( DEVO_loader_path , sizeof ( DEVO_loader_path ) , " %sloader.bin " , Settings . DEVOLoaderPath ) ;
if ( CheckFile ( DEVO_loader_path ) )
{
WindowPrompt ( tr ( " Error: " ) , tr ( " You need to set GameCube Mode to Devolution to launch GameCube games from USB or SD card " ) , tr ( " OK " ) ) ;
return 0 ;
}
2012-08-24 18:55:49 +02:00
WindowPrompt ( tr ( " Error: " ) , tr ( " You need to install Devolution or DIOS MIOS (Lite) to launch GameCube games from USB or SD card " ) , tr ( " OK " ) ) ;
2012-02-09 22:18:16 +01:00
2012-08-24 18:55:49 +02:00
return 0 ;
2011-01-22 01:06:28 +01:00
}
2010-11-06 16:30:14 +01:00
2011-01-22 01:06:28 +01:00
2011-05-30 21:49:12 +02:00
u32 GameBooter : : BootPartition ( char * dolpath , u8 videoselected , u8 alternatedol , u32 alternatedoloffset )
2010-11-06 16:30:14 +01:00
{
2011-07-26 00:28:22 +02:00
gprintf ( " booting partition IOS %u r%u \n " , IOS_GetVersion ( ) , IOS_GetRevision ( ) ) ;
entry_point p_entry ;
s32 ret ;
u64 offset ;
2010-11-06 16:30:14 +01:00
2011-07-26 00:28:22 +02:00
/* Find game partition offset */
ret = Disc_FindPartition ( & offset ) ;
if ( ret < 0 )
return 0 ;
2010-11-06 16:30:14 +01:00
2011-07-26 00:28:22 +02:00
/* Open specified partition */
ret = WDVD_OpenPartition ( offset ) ;
if ( ret < 0 )
return 0 ;
2010-11-06 16:30:14 +01:00
2011-07-26 00:28:22 +02:00
/* Setup low memory */
Disc_SetLowMem ( ) ;
2011-03-14 22:19:21 +01:00
2011-07-26 00:28:22 +02:00
/* Setup video mode */
2012-08-24 18:55:49 +02:00
Disc_SelectVMode ( videoselected , false , NULL ) ;
2010-11-06 16:30:14 +01:00
2011-07-26 00:28:22 +02:00
/* Run apploader */
ret = Apploader_Run ( & p_entry , dolpath , alternatedol , alternatedoloffset ) ;
2010-11-06 16:30:14 +01:00
2011-07-26 00:28:22 +02:00
if ( ret < 0 )
return 0 ;
2010-11-06 16:30:14 +01:00
2011-07-26 00:28:22 +02:00
return ( u32 ) p_entry ;
2010-11-06 16:30:14 +01:00
}
2011-01-22 01:06:28 +01:00
void GameBooter : : SetupAltDOL ( u8 * gameID , u8 & alternatedol , u32 & alternatedoloffset )
{
2011-07-26 00:28:22 +02:00
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 ;
2011-01-22 01:06:28 +01:00
}
2011-11-12 19:14:09 +01:00
void GameBooter : : SetupNandEmu ( u8 NandEmuMode , const char * NandEmuPath , struct discHdr & gameHeader )
2011-07-29 22:59:31 +02:00
{
2011-11-12 19:14:09 +01:00
if ( NandEmuMode & & strchr ( NandEmuPath , ' / ' ) )
2011-07-29 22:59:31 +02:00
{
2012-02-05 19:38:26 +01:00
int partition = - 1 ;
2011-07-29 22:59:31 +02:00
//! Create save game path and title.tmd for not existing saves
CreateSavePath ( & gameHeader ) ;
2011-11-12 19:14:09 +01:00
gprintf ( " Enabling Nand Emulation on: %s \n " , NandEmuPath ) ;
2011-09-03 11:39:26 +02:00
Set_FullMode ( NandEmuMode = = 2 ) ;
2011-11-12 19:14:09 +01:00
Set_Path ( strchr ( NandEmuPath , ' / ' ) ) ;
2011-07-29 22:59:31 +02:00
2012-02-05 19:38:26 +01:00
//! Unmount devices to flush data before activating NAND Emu
2011-11-12 19:14:09 +01:00
if ( strncmp ( NandEmuPath , " usb " , 3 ) = = 0 )
2012-02-05 19:38:26 +01:00
{
//! Set which partition to use (USB only)
partition = atoi ( NandEmuPath + 3 ) - 1 ;
2012-05-06 12:59:58 +02:00
Set_Partition ( DeviceHandler : : PartitionToPortPartition ( partition ) ) ;
2012-02-05 19:38:26 +01:00
DeviceHandler : : Instance ( ) - > UnMount ( USB1 + partition ) ;
}
else
2011-07-29 22:59:31 +02:00
DeviceHandler : : Instance ( ) - > UnMountSD ( ) ;
2011-11-12 19:14:09 +01:00
Enable_Emu ( strncmp ( NandEmuPath , " usb " , 3 ) = = 0 ? EMU_USB : EMU_SD ) ;
2012-02-05 19:38:26 +01:00
//! Mount USB to start game, SD is not required
if ( strncmp ( NandEmuPath , " usb " , 3 ) = = 0 )
DeviceHandler : : Instance ( ) - > Mount ( USB1 + partition ) ;
2011-07-29 22:59:31 +02:00
}
}
2012-02-09 22:18:16 +01:00
int GameBooter : : SetupDisc ( struct discHdr & gameHeader )
2011-01-22 01:06:28 +01:00
{
2012-02-09 22:18:16 +01:00
if ( gameHeader . type = = TYPE_GAME_WII_DISC )
2011-07-26 00:28:22 +02:00
{
gprintf ( " \t loading DVD \n " ) ;
return Disc_Open ( ) ;
}
int ret = - 1 ;
if ( IosLoader : : IsWaninkokoIOS ( ) & & IOS_GetRevision ( ) < 18 )
{
gprintf ( " Disc_SetUSB... " ) ;
2012-02-09 22:18:16 +01:00
ret = Disc_SetUSB ( gameHeader . id ) ;
2011-07-26 00:28:22 +02:00
gprintf ( " %d \n " , ret ) ;
if ( ret < 0 ) return ret ;
}
else
{
gprintf ( " Loading fragment list... " ) ;
2012-02-09 22:18:16 +01:00
ret = get_frag_list ( gameHeader . id ) ;
2011-07-26 00:28:22 +02:00
gprintf ( " %d \n " , ret ) ;
if ( ret < 0 ) return ret ;
2012-02-09 22:18:16 +01:00
ret = set_frag_list ( gameHeader . id ) ;
2011-07-26 00:28:22 +02:00
if ( ret < 0 ) return ret ;
gprintf ( " \t USB set to game \n " ) ;
}
gprintf ( " Disc_Open()... " ) ;
ret = Disc_Open ( ) ;
gprintf ( " %d \n " , ret ) ;
return ret ;
2011-01-22 01:06:28 +01:00
}
2011-11-20 11:46:07 +01:00
void GameBooter : : ShutDownDevices ( int gameUSBPort )
{
gprintf ( " Shutting down devices... \n " ) ;
//! Flush all caches and close up all devices
WBFS_CloseAll ( ) ;
DeviceHandler : : DestroyInstance ( ) ;
//! Shadow mload - Only needed on some games with Hermes v5.1 (Check is inside the function)
shadow_mload ( ) ;
if ( Settings . USBPort = = 2 )
//! Reset USB port because device handler changes it for cache flushing
USBStorage2_SetPort ( gameUSBPort ) ;
USBStorage2_Deinit ( ) ;
USB_Deinitialize ( ) ;
}
2011-12-22 23:44:48 +01:00
int GameBooter : : BootGame ( struct discHdr * gameHdr )
2011-01-22 01:06:28 +01:00
{
2011-12-22 23:44:48 +01:00
if ( ! gameHdr )
2011-07-26 00:28:22 +02:00
return - 1 ;
2011-01-22 01:06:28 +01:00
2012-02-09 22:18:16 +01:00
struct discHdr gameHeader ;
memcpy ( & gameHeader , gameHdr , sizeof ( struct discHdr ) ) ;
gprintf ( " \t BootGame: %.6s \n " , gameHeader . id ) ;
2011-12-22 23:44:48 +01:00
2011-07-26 00:28:22 +02:00
if ( Settings . Wiinnertag )
2012-02-09 22:18:16 +01:00
Wiinnertag : : TagGame ( ( const char * ) gameHeader . id ) ;
2011-06-18 09:00:42 +02:00
2012-05-06 12:59:58 +02:00
if ( gameHeader . type = = TYPE_GAME_GC_IMG | | gameHeader . type = = TYPE_GAME_GC_DISC | | gameHdr - > type = = TYPE_GAME_GC_EXTRACTED )
2012-02-09 22:18:16 +01:00
return BootGCMode ( & gameHeader ) ;
2011-12-20 22:41:00 +01:00
2011-07-26 00:28:22 +02:00
AppCleanUp ( ) ;
2010-10-27 21:50:48 +02:00
2011-07-26 00:28:22 +02:00
gprintf ( " \t Settings.partition: %d \n " , Settings . partition ) ;
2011-01-22 01:06:28 +01:00
2011-12-22 23:44:48 +01:00
s32 ret = - 1 ;
2011-12-20 22:41:00 +01:00
2011-07-26 00:28:22 +02:00
//! Remember game's USB port
int partition = gameList . GetPartitionNumber ( gameHeader . id ) ;
int usbport = DeviceHandler : : PartitionToUSBPort ( partition ) ;
2011-06-22 19:57:37 +02:00
2011-07-26 00:28:22 +02:00
//! Setup game configuration from game settings. If no game settings exist use global/default.
GameCFG * game_cfg = GameSettings . GetGameCFG ( gameHeader . id ) ;
u8 videoChoice = game_cfg - > video = = INHERIT ? Settings . videomode : game_cfg - > video ;
2011-12-23 16:48:20 +01:00
u8 aspectChoice = game_cfg - > aspectratio = = INHERIT ? Settings . GameAspectRatio : game_cfg - > aspectratio ;
2011-07-26 00:28:22 +02:00
u8 languageChoice = game_cfg - > language = = INHERIT ? Settings . language : game_cfg - > language ;
u8 ocarinaChoice = game_cfg - > ocarina = = INHERIT ? Settings . ocarina : game_cfg - > ocarina ;
u8 viChoice = game_cfg - > vipatch = = INHERIT ? Settings . videopatch : game_cfg - > vipatch ;
u8 sneekChoice = game_cfg - > sneekVideoPatch = = INHERIT ? Settings . sneekVideoPatch : game_cfg - > sneekVideoPatch ;
u8 iosChoice = game_cfg - > ios = = INHERIT ? Settings . cios : game_cfg - > ios ;
u8 fix002 = game_cfg - > errorfix002 = = INHERIT ? Settings . error002 : game_cfg - > errorfix002 ;
u8 countrystrings = game_cfg - > patchcountrystrings = = INHERIT ? Settings . patchcountrystrings : game_cfg - > patchcountrystrings ;
u8 alternatedol = game_cfg - > loadalternatedol ;
u32 alternatedoloffset = game_cfg - > alternatedolstart ;
u8 reloadblock = game_cfg - > iosreloadblock = = INHERIT ? Settings . BlockIOSReload : game_cfg - > iosreloadblock ;
2011-09-03 11:39:26 +02:00
u8 Hooktype = game_cfg - > Hooktype = = INHERIT ? Settings . Hooktype : game_cfg - > Hooktype ;
u8 WiirdDebugger = game_cfg - > WiirdDebugger = = INHERIT ? Settings . WiirdDebugger : game_cfg - > WiirdDebugger ;
2011-07-26 00:28:22 +02:00
u64 returnToChoice = game_cfg - > returnTo ? NandTitles . FindU32 ( Settings . returnTo ) : 0 ;
2011-12-20 22:41:00 +01:00
u8 NandEmuMode = game_cfg - > NandEmuMode = = INHERIT ? Settings . NandEmuMode : game_cfg - > NandEmuMode ;
const char * NandEmuPath = game_cfg - > NandEmuPath . size ( ) = = 0 ? Settings . NandEmuPath : game_cfg - > NandEmuPath . c_str ( ) ;
2011-12-22 23:44:48 +01:00
if ( gameHeader . tid ! = 0 )
2011-12-20 22:41:00 +01:00
{
2012-01-08 19:24:46 +01:00
NandEmuMode = ( gameHeader . type = = TYPE_GAME_EMUNANDCHAN )
? ( game_cfg - > NandEmuMode = = INHERIT ? Settings . NandEmuChanMode : game_cfg - > NandEmuMode ) //! Emulated nand title
: 0 ; //! Real nand title
2011-12-20 22:41:00 +01:00
NandEmuPath = game_cfg - > NandEmuPath . size ( ) = = 0 ? Settings . NandEmuChanPath : game_cfg - > NandEmuPath . c_str ( ) ;
}
2011-01-21 20:43:59 +01:00
2011-09-04 12:13:47 +02:00
if ( ocarinaChoice & & Hooktype = = OFF )
Hooktype = 1 ;
2011-07-24 18:32:09 +02:00
2011-07-26 00:28:22 +02:00
//! Prepare alternate dol settings
SetupAltDOL ( gameHeader . id , alternatedol , alternatedoloffset ) ;
//! Reload game settings cIOS for this game
if ( iosChoice ! = IOS_GetVersion ( ) )
{
gprintf ( " Reloading into game cIOS: %i... \n " , iosChoice ) ;
IosLoader : : LoadGameCios ( iosChoice ) ;
if ( MountGamePartition ( false ) < 0 )
return - 1 ;
}
2011-07-29 22:59:31 +02:00
//! Modify Wii Message Board to display the game starting here (before Nand Emu)
if ( Settings . PlaylogUpdate )
2012-05-06 12:59:58 +02:00
{
BNRInstance : : Instance ( ) - > Load ( & gameHeader ) ;
2011-07-29 22:59:31 +02:00
Playlog_Update ( ( char * ) gameHeader . id , BNRInstance : : Instance ( ) - > GetIMETTitle ( CONF_GetLanguage ( ) ) ) ;
2012-05-06 12:59:58 +02:00
}
2011-07-29 22:59:31 +02:00
2012-01-08 19:24:46 +01:00
//! Load wip codes
2011-11-12 19:14:09 +01:00
load_wip_code ( gameHeader . id ) ;
2011-07-26 00:28:22 +02:00
2011-11-12 19:14:09 +01:00
//! Load Ocarina codes
if ( ocarinaChoice )
2011-11-15 22:01:25 +01:00
ocarina_load_code ( Settings . Cheatcodespath , gameHeader . id ) ;
2011-11-12 19:14:09 +01:00
2012-01-08 19:24:46 +01:00
//! Setup NAND emulation
SetupNandEmu ( NandEmuMode , NandEmuPath , gameHeader ) ;
2011-11-12 19:14:09 +01:00
//! Setup disc stuff if we load a game
2011-12-22 23:44:48 +01:00
if ( gameHeader . tid = = 0 )
2011-11-12 19:14:09 +01:00
{
//! Setup disc in cIOS and open it
2012-02-09 22:18:16 +01:00
ret = SetupDisc ( gameHeader ) ;
2011-11-12 19:14:09 +01:00
if ( ret < 0 )
Sys_BackToLoader ( ) ;
//! Load BCA data for the game
gprintf ( " Loading BCA data... " ) ;
ret = do_bca_code ( Settings . BcaCodepath , gameHeader . id ) ;
gprintf ( " %d \n " , ret ) ;
}
2011-07-26 00:28:22 +02:00
2012-01-01 18:58:10 +01:00
if ( IosLoader : : IsHermesIOS ( iosChoice ) )
2011-07-26 00:28:22 +02:00
{
if ( reloadblock = = ON )
{
2011-12-22 23:44:48 +01:00
//! Setup IOS reload block
2011-07-26 00:28:22 +02:00
enable_ES_ioctlv_vector ( ) ;
if ( gameList . GetGameFS ( gameHeader . id ) = = PART_FS_WBFS )
mload_close ( ) ;
}
}
2012-01-01 18:58:10 +01:00
else if ( IosLoader : : IsD2X ( iosChoice ) )
2011-07-26 00:28:22 +02:00
{
2011-12-22 23:44:48 +01:00
// Open ES file descriptor for the d2x patches
static char es_fs [ ] ATTRIBUTE_ALIGN ( 32 ) = " /dev/es " ;
int es_fd = IOS_Open ( es_fs , 0 ) ;
if ( es_fd > = 0 )
{
// IOS Reload Block
if ( reloadblock ! = OFF ) {
BlockIOSReload ( es_fd , iosChoice ) ;
}
// Check if new patch method for return to works otherwise old method will be used
2011-12-28 10:55:00 +01:00
if ( PatchNewReturnTo ( es_fd , returnToChoice ) > = 0 )
2011-12-22 23:44:48 +01:00
returnToChoice = 0 ; // Patch successful, no need for old method
// Close ES file descriptor
IOS_Close ( es_fd ) ;
}
2011-07-26 00:28:22 +02:00
}
2011-02-05 22:06:52 +01:00
2011-11-12 19:14:09 +01:00
//! Now we can free up the memory used by the game/channel lists
2011-07-26 00:28:22 +02:00
gameList . clear ( ) ;
2011-11-12 19:14:09 +01:00
Channels : : DestroyInstance ( ) ;
2011-07-26 00:28:22 +02:00
//! Load main.dol or alternative dol into memory, start the game apploader and get game entrypoint
2011-12-22 23:44:48 +01:00
if ( gameHeader . tid = = 0 )
2011-11-12 19:14:09 +01:00
{
gprintf ( " \t Game Boot \n " ) ;
AppEntrypoint = BootPartition ( Settings . dolpath , videoChoice , alternatedol , alternatedoloffset ) ;
2011-11-20 11:46:07 +01:00
// Reading of game is done we can close devices now
ShutDownDevices ( usbport ) ;
2011-11-12 19:14:09 +01:00
}
else
{
2011-11-20 11:46:07 +01:00
//! shutdown now and avoid later crashs with free if memory gets overwritten by channel
2012-05-06 12:59:58 +02:00
ShutDownDevices ( DeviceHandler : : PartitionToUSBPort ( std : : max ( atoi ( NandEmuPath + 3 ) - 1 , 0 ) ) ) ;
2011-11-12 19:14:09 +01:00
gprintf ( " \t Channel Boot \n " ) ;
/* Setup video mode */
2012-08-24 18:55:49 +02:00
Disc_SelectVMode ( videoChoice , false , NULL ) ;
2012-05-06 12:59:58 +02:00
// Load dol
AppEntrypoint = Channels : : LoadChannel ( gameHeader . tid ) ;
2011-11-12 19:14:09 +01:00
}
2011-07-26 00:28:22 +02:00
//! No entrypoint found...back to HBC/SystemMenu
if ( AppEntrypoint = = 0 )
{
2011-11-12 19:14:09 +01:00
gprintf ( " AppEntryPoint is 0, something went wrong \n " ) ;
2011-07-26 00:28:22 +02:00
WDVD_ClosePartition ( ) ;
Sys_BackToLoader ( ) ;
}
//! Do all the game patches
gprintf ( " Applying game patches... \n " ) ;
2011-12-23 16:48:20 +01:00
gamepatches ( videoChoice , aspectChoice , languageChoice , countrystrings , viChoice , sneekChoice , Hooktype , fix002 , returnToChoice ) ;
2011-07-26 00:28:22 +02:00
2011-07-29 22:59:31 +02:00
//! Load Code handler if needed
2011-11-12 19:14:09 +01:00
load_handler ( Hooktype , WiirdDebugger , Settings . WiirdDebuggerPause ) ;
2011-07-26 00:28:22 +02:00
//! Jump to the entrypoint of the game - the last function of the USB Loader
gprintf ( " Jumping to game entrypoint: 0x%08X. \n " , AppEntrypoint ) ;
2011-09-04 12:13:47 +02:00
return Disc_JumpToEntrypoint ( Hooktype , WDMMenu : : GetDolParameter ( ) ) ;
2010-10-27 21:50:48 +02:00
}
2012-08-24 18:55:49 +02:00
int GameBooter : : BootDIOSMIOS ( struct discHdr * gameHdr )
{
const char * RealPath = GCGames : : Instance ( ) - > GetPath ( ( const char * ) gameHdr - > id ) ;
GameCFG * game_cfg = GameSettings . GetGameCFG ( gameHdr - > id ) ;
u8 videoChoice = game_cfg - > video = = INHERIT ? Settings . videomode : game_cfg - > video ;
u8 languageChoice = game_cfg - > language = = INHERIT ? 6 : game_cfg - > language ;
u8 ocarinaChoice = game_cfg - > ocarina = = INHERIT ? Settings . ocarina : game_cfg - > ocarina ;
u8 dmlVideoChoice = game_cfg - > DMLVideo = = INHERIT ? Settings . DMLVideo : game_cfg - > DMLVideo ;
u8 dmlProgressivePatch = game_cfg - > DMLProgPatch = = INHERIT ? Settings . DMLProgPatch : game_cfg - > DMLProgPatch ;
u8 dmlNMMChoice = game_cfg - > DMLNMM = = INHERIT ? Settings . DMLNMM : game_cfg - > DMLNMM ;
u8 dmlActivityLEDChoice = game_cfg - > DMLActivityLED = = INHERIT ? Settings . DMLActivityLED : game_cfg - > DMLActivityLED ;
u8 dmlPADHookChoice = game_cfg - > DMLPADHOOK = = INHERIT ? Settings . DMLPADHOOK : game_cfg - > DMLPADHOOK ;
u8 dmlNoDisc2Choice = game_cfg - > DMLNoDisc2 = = INHERIT ? Settings . DMLNoDisc2 : game_cfg - > DMLNoDisc2 ;
u8 dmlWidescreenChoice = game_cfg - > DMLWidescreen = = INHERIT ? Settings . DMLWidescreen : game_cfg - > DMLWidescreen ;
2012-11-11 14:47:02 +01:00
u8 dmlScreenshotChoice = game_cfg - > DMLScreenshot = = INHERIT ? Settings . DMLScreenshot : game_cfg - > DMLScreenshot ;
2012-08-24 18:55:49 +02:00
u8 dmlJPNPatchChoice = game_cfg - > DMLJPNPatch = = INHERIT ? Settings . DMLJPNPatch : game_cfg - > DMLJPNPatch ;
u8 dmlDebugChoice = game_cfg - > DMLDebug = = INHERIT ? Settings . DMLDebug : game_cfg - > DMLDebug ;
int currentMIOS = IosLoader : : GetMIOSInfo ( ) ;
// DIOS MIOS
if ( currentMIOS = = DIOS_MIOS )
{
// Check Main GameCube Path location
if ( strncmp ( Settings . GameCubePath , " sd " , 2 ) = = 0 | | strncmp ( DeviceHandler : : PathToFSName ( Settings . GameCubePath ) , " FAT " , 3 ) ! = 0 )
{
WindowPrompt ( tr ( " Error: " ) , tr ( " To run GameCube games with DIOS MIOS you need to set your 'Main GameCube Path' to an USB FAT32 partition. " ) , tr ( " OK " ) ) ;
return 0 ;
}
// Check current game location
if ( strncmp ( RealPath , " sd " , 2 ) = = 0 )
{
WindowPrompt ( tr ( " The game is on SD Card. " ) , tr ( " To run GameCube games with DIOS MIOS you need to place them on an USB FAT32 partition. " ) , tr ( " OK " ) ) ;
// Todo: Add here copySD2USB.
return 0 ;
}
2013-01-06 14:41:22 +01:00
// Check if the partition is the first partition on the drive
int part_num = atoi ( Settings . GameCubePath + 3 ) ;
int portPart = DeviceHandler : : PartitionToPortPartition ( part_num - USB1 ) ;
int usbport = DeviceHandler : : PartitionToUSBPort ( part_num - USB1 ) ;
PartitionHandle * usbHandle = DeviceHandler : : Instance ( ) - > GetUSBHandleFromPartition ( part_num - USB1 ) ;
if ( usbHandle - > GetPartitionNum ( portPart ) )
{
WindowPrompt ( tr ( " Error: " ) , tr ( " To run GameCube games with DIOS MIOS you need to set your 'Main GameCube Path' on the first partition of the Hard Drive. " ) , tr ( " OK " ) ) ;
return 0 ;
}
// Check if the partition is primary
if ( usbHandle - > GetPartitionTableType ( portPart ) ! = MBR )
{
WindowPrompt ( tr ( " Error: " ) , tr ( " To run GameCube games with DIOS MIOS you need to set your 'Main GameCube Path' on a primary partition. " ) , tr ( " OK " ) ) ;
return 0 ;
}
// Check HDD sector size. Only 512 bytes/sector is supported by DIOS MIOS
if ( hdd_sector_size [ usbport ] ! = BYTES_PER_SECTOR )
{
WindowPrompt ( tr ( " Error: " ) , tr ( " To run GameCube games with DIOS MIOS you need to use a 512 bytes/sector Hard Drive. " ) , tr ( " OK " ) ) ;
return 0 ;
}
2013-03-17 14:48:15 +01:00
if ( usbHandle - > GetPartitionClusterSize ( usbHandle - > GetLBAStart ( portPart ) ) > 32768 )
{
WindowPrompt ( tr ( " Error: " ) , tr ( " To run GameCube games with DIOS MIOS you need to use a partition with 32k bytes/cluster or less. " ) , tr ( " OK " ) ) ;
return 0 ;
}
2012-08-24 18:55:49 +02:00
}
// DIOS MIOS Lite
else if ( currentMIOS = = DIOS_MIOS_LITE | | currentMIOS = = QUADFORCE )
{
if ( ( ( gameHdr - > type = = TYPE_GAME_GC_IMG ) | | ( gameHdr - > type = = TYPE_GAME_GC_EXTRACTED ) ) & & strncmp ( RealPath , " usb " , 3 ) = = 0 )
{
if ( ! GCGames : : Instance ( ) - > CopyUSB2SD ( gameHdr ) )
return 0 ;
RealPath = GCGames : : Instance ( ) - > GetPath ( ( const char * ) gameHdr - > id ) ;
}
}
// Check DIOS MIOS config for specific versions
if ( currentMIOS ! = QUADFORCE )
{
if ( IosLoader : : GetDMLVersion ( ) < DML_VERSION_DML_1_2 )
{
WindowPrompt ( tr ( " Error: " ) , tr ( " You need to install DIOS MIOS Lite v1.2 or a newer version. " ) , tr ( " OK " ) ) ;
return 0 ;
}
if ( dmlWidescreenChoice & & IosLoader : : GetDMLVersion ( ) < DML_VERSION_DM_2_1 ) // DML Force Widescreen setting : added in DM v2.1+, config v1.
{
2012-10-14 18:27:01 +02:00
if ( Settings . DMLWidescreen ) // Display the warning only if set as Global setting. Individual game setting is not displayed.
WindowPrompt ( tr ( " Warning: " ) , tr ( " The Force Widescreen setting requires DIOS MIOS v2.1 or more. This setting will be ignored. " ) , tr ( " OK " ) ) ;
2012-08-24 18:55:49 +02:00
dmlWidescreenChoice = OFF ;
}
2012-10-14 18:27:01 +02:00
if ( dmlNoDisc2Choice & & ( IosLoader : : GetDMLVersion ( ) < DML_VERSION_DM_2_2_2 | | IosLoader : : GetDMLVersion ( ) > DML_VERSION_DML_2_2_1 ) ) // DML NoDisc+ setting : Added in DM 2.2 upate 2, config v2, removed in DM(L) v2.3
2012-08-24 18:55:49 +02:00
{
2012-10-14 18:27:01 +02:00
if ( Settings . DMLNoDisc2 ) // Display the warning only if set as Global setting. Individual game setting is not displayed.
WindowPrompt ( tr ( " Warning: " ) , tr ( " The No Disc+ setting requires DIOS MIOS 2.2 update2. This setting will be ignored. " ) , tr ( " OK " ) ) ;
dmlNoDisc2Choice = false ;
2012-08-24 18:55:49 +02:00
}
}
2012-10-14 18:27:01 +02:00
// Check Ocarina and cheat file location. the .gct file need to be located on the same partition than the game.
2012-12-09 21:31:55 +01:00
if ( gameHdr - > type ! = TYPE_GAME_GC_DISC & & ocarinaChoice & & strcmp ( DeviceHandler : : GetDevicePrefix ( RealPath ) , DeviceHandler : : GetDevicePrefix ( Settings . Cheatcodespath ) ) ! = 0 )
2012-10-14 18:27:01 +02:00
{
char path [ 255 ] , destPath [ 255 ] ;
int res = - 1 ;
snprintf ( path , sizeof ( path ) , " %s%.6s.gct " , Settings . Cheatcodespath , ( char * ) gameHdr - > id ) ;
snprintf ( destPath , sizeof ( destPath ) , " %s:/DMLTemp.gct " , DeviceHandler : : GetDevicePrefix ( RealPath ) ) ;
gprintf ( " DML: Copying %s to %s \n " , path , destPath ) ;
res = CopyFile ( path , destPath ) ;
if ( res < 0 )
{
gprintf ( " DML: Couldn't copy the file. ret %d. Ocarina Disabled \n " , res ) ;
RemoveFile ( destPath ) ;
ocarinaChoice = false ;
}
}
2012-12-09 21:31:55 +01:00
// Check if game has multi Discs
bool bootDisc2 = false ;
if ( gameHdr - > type ! = TYPE_GAME_GC_DISC & & gameHdr - > disc_no = = 0 & & currentMIOS ! = QUADFORCE )
{
2013-01-06 14:41:22 +01:00
char disc2Path [ 255 ] ;
snprintf ( disc2Path , sizeof ( disc2Path ) , " %s " , RealPath ) ;
char * pathPtr = strrchr ( disc2Path , ' / ' ) ;
if ( pathPtr ) * pathPtr = 0 ;
snprintf ( disc2Path , sizeof ( disc2Path ) , " %s/disc2.iso " , disc2Path ) ;
if ( CheckFile ( disc2Path ) )
2012-12-09 21:31:55 +01:00
{
2013-01-06 14:41:22 +01:00
int choice = WindowPrompt ( gameHdr - > title , tr ( " This game has multiple discs. Please select the disc to launch. " ) , tr ( " Disc 1 " ) , tr ( " Disc 2 " ) , tr ( " Cancel " ) ) ;
if ( choice = = 0 )
return 0 ;
else if ( choice = = 2 )
bootDisc2 = true ;
}
2012-12-09 21:31:55 +01:00
}
2012-10-14 18:27:01 +02:00
2012-08-24 18:55:49 +02:00
const char * gcPath = strchr ( RealPath , ' / ' ) ;
if ( ! gcPath ) gcPath = " " ;
char gamePath [ 255 ] ;
snprintf ( gamePath , sizeof ( gamePath ) , " %s " , gcPath ) ;
2012-12-09 21:31:55 +01:00
if ( bootDisc2 )
{
char * pathPtr = strrchr ( gamePath , ' / ' ) ;
if ( pathPtr ) * pathPtr = 0 ;
snprintf ( gamePath , sizeof ( gamePath ) , " %s/disc2.iso " , gamePath ) ;
}
2012-08-24 18:55:49 +02:00
ExitApp ( ) ;
// Game ID
memcpy ( ( u8 * ) Disc_ID , gameHdr - > id , 6 ) ;
DCFlushRange ( ( u8 * ) Disc_ID , 6 ) ;
2012-10-14 18:27:01 +02:00
// *(vu32*)0xCC003024 |= 7; // DML 1.1- only?
2012-08-24 18:55:49 +02:00
DML_CFG * dml_config = ( DML_CFG * ) DML_CONFIG_ADDRESS ;
memset ( dml_config , 0 , sizeof ( DML_CFG ) ) ;
// Magic and version for DML
dml_config - > Magicbytes = DML_MAGIC ;
dml_config - > Version = IosLoader : : GetDMLVersion ( ) > = DML_VERSION_DM_2_2 ? 0x00000002 : 0x00000001 ;
// Select disc source
if ( ( gameHdr - > type = = TYPE_GAME_GC_IMG ) | | ( gameHdr - > type = = TYPE_GAME_GC_EXTRACTED ) )
{
dml_config - > Config | = DML_CFG_GAME_PATH ;
strncpy ( dml_config - > GamePath , gamePath , sizeof ( dml_config - > GamePath ) ) ;
// Extended NoDisc patch
2013-03-17 14:48:15 +01:00
if ( dmlNoDisc2Choice & & IosLoader : : GetDMLVersion ( ) > = DML_VERSION_DM_2_2_2 & & IosLoader : : GetDMLVersion ( ) < DML_VERSION_DML_2_3m )
dml_config - > Config | = DML_CFG_NODISC2 ; // used by v2.2 update2 as an Extended NoDisc patching
2012-08-24 18:55:49 +02:00
gprintf ( " DML: Loading game %s \n " , dml_config - > GamePath ) ;
}
else
{
dml_config - > Config | = DML_CFG_BOOT_DISC ;
}
// setup cheat and path
if ( ocarinaChoice )
{
2012-12-09 21:31:55 +01:00
// Check if the .gct folder is on the same partition than the game, if not load the temporary .gct file.
2012-10-14 18:27:01 +02:00
if ( strcmp ( DeviceHandler : : GetDevicePrefix ( RealPath ) , DeviceHandler : : GetDevicePrefix ( Settings . Cheatcodespath ) ) = = 0 )
{
const char * CheatPath = strchr ( Settings . Cheatcodespath , ' / ' ) ;
if ( ! CheatPath ) CheatPath = " " ;
snprintf ( dml_config - > CheatPath , sizeof ( dml_config - > CheatPath ) , " %s%.6s.gct " , CheatPath , ( char * ) gameHdr - > id ) ;
}
2012-12-09 21:31:55 +01:00
else if ( gameHdr - > type ! = TYPE_GAME_GC_DISC )
2012-10-14 18:27:01 +02:00
{
snprintf ( dml_config - > CheatPath , sizeof ( dml_config - > CheatPath ) , " DMLTemp.gct " ) ;
}
2012-08-24 18:55:49 +02:00
2012-10-14 18:27:01 +02:00
dml_config - > Config | = DML_CFG_CHEATS | DML_CFG_CHEAT_PATH ;
2012-08-24 18:55:49 +02:00
gprintf ( " DML: Loading cheat %s \n " , dml_config - > CheatPath ) ;
}
2012-11-11 14:47:02 +01:00
// other DML configs
2012-08-24 18:55:49 +02:00
if ( dmlPADHookChoice )
dml_config - > Config | = DML_CFG_PADHOOK ;
if ( dmlActivityLEDChoice )
dml_config - > Config | = DML_CFG_ACTIVITY_LED ;
if ( dmlNMMChoice )
dml_config - > Config | = dmlNMMChoice = = ON ? DML_CFG_NMM : DML_CFG_NMM_DEBUG ;
if ( dmlDebugChoice )
dml_config - > Config | = dmlDebugChoice = = ON ? DML_CFG_DEBUGGER : DML_CFG_DEBUGWAIT ;
if ( dmlWidescreenChoice )
dml_config - > Config | = DML_CFG_FORCE_WIDE ;
2012-11-11 14:47:02 +01:00
if ( dmlScreenshotChoice )
dml_config - > Config | = DML_CFG_SCREENSHOT ;
2013-01-06 14:41:22 +01:00
if ( bootDisc2 & & IosLoader : : GetDMLVersion ( ) > = DML_VERSION_DM_2_6_0 )
2012-12-09 21:31:55 +01:00
dml_config - > Config | = DML_CFG_BOOT_DISC2 ;
2012-08-24 18:55:49 +02:00
// Setup Video Mode
if ( dmlVideoChoice = = DML_VIDEO_NONE ) // No video mode
{
dml_config - > VideoMode = DML_VID_NONE ;
}
else
{
if ( dmlVideoChoice = = DML_VIDEO_AUTO ) // Auto select video mode
{
dml_config - > VideoMode = DML_VID_DML_AUTO ;
Disc_SelectVMode ( VIDEO_MODE_DISCDEFAULT , false , NULL ) ;
}
else // Force user choice
{
dml_config - > VideoMode = DML_VID_FORCE ;
Disc_SelectVMode ( videoChoice , false , & dml_config - > VideoMode ) ;
}
Disc_SetVMode ( ) ;
}
if ( dmlProgressivePatch )
dml_config - > VideoMode | = DML_VID_PROG_PATCH ;
DCFlushRange ( dml_config , sizeof ( DML_CFG ) ) ;
memcpy ( ( u8 * ) DML_CONFIG_ADDRESS_V1_2 , dml_config , sizeof ( DML_CFG ) ) ;
DCFlushRange ( ( u8 * ) DML_CONFIG_ADDRESS_V1_2 , sizeof ( DML_CFG ) ) ;
// print the config set for DML
gprintf ( " DML: setup configuration 0x%X \n " , dml_config - > Config ) ;
gprintf ( " DML: setup video mode 0x%X \n " , dml_config - > VideoMode ) ;
syssram * sram = __SYS_LockSram ( ) ;
if ( dml_config - > VideoMode & DML_VID_FORCE_PROG | | dml_config - > VideoMode & DML_VID_PROG_PATCH ) {
sram - > flags | = 0x80 ; //set progressive flag
}
else {
sram - > flags & = 0x7F ; //clear progressive flag
}
// setup video mode flags
if ( * Video_Mode = = VI_NTSC ) {
sram - > flags & = ~ 1 ; // Clear bit 0 to set the video mode to NTSC
sram - > ntd & = 0xBF ; //clear pal60 flag
}
else {
sram - > flags | = 1 ; // Set bit 0 to set the video mode to PAL
sram - > ntd | = 0x40 ; //set pal60 flag
}
// Set language flag
if ( languageChoice < = GC_DUTCH )
{
sram - > lang = languageChoice ;
}
else // console default
{
sram - > lang = GC_ENGLISH ;
if ( CONF_GetLanguage ( ) > = CONF_LANG_ENGLISH & & CONF_GetLanguage ( ) < = CONF_LANG_DUTCH )
{
sram - > lang = CONF_GetLanguage ( ) - 1 ;
}
}
gprintf ( " DML: setup language 0x%X \n " , sram - > lang ) ;
__SYS_UnlockSram ( 1 ) ; // 1 -> write changes
while ( ! __SYS_SyncSram ( ) )
usleep ( 100 ) ;
/* NTSC-J Patch */ // Thanks to Fix94
u8 * diskid = ( u8 * ) Disc_ID ;
if ( dmlJPNPatchChoice & & diskid [ 3 ] = = ' J ' )
* HW_PPCSPEED = 0x0002A9E0 ;
2012-10-14 18:27:01 +02:00
gprintf ( " \n Loading BC for GameCube \n " ) ;
2012-08-24 18:55:49 +02:00
WII_Initialize ( ) ;
return WII_LaunchTitle ( 0x0000000100000100ULL ) ;
}
int GameBooter : : BootDevolution ( struct discHdr * gameHdr )
{
// check the settings
GameCFG * game_cfg = GameSettings . GetGameCFG ( gameHdr - > id ) ;
u8 videoChoice = game_cfg - > video = = INHERIT ? Settings . videomode : game_cfg - > video ;
u8 devoMCEmulation = game_cfg - > DEVOMCEmulation = = INHERIT ? Settings . DEVOMCEmulation : game_cfg - > DEVOMCEmulation ;
2012-10-14 18:27:01 +02:00
u8 devoActivityLEDChoice = game_cfg - > DEVOActivityLED = = INHERIT ? Settings . DEVOActivityLED : game_cfg - > DEVOActivityLED ;
u8 devoWidescreenChoice = game_cfg - > DEVOWidescreen = = INHERIT ? Settings . DEVOWidescreen : game_cfg - > DEVOWidescreen ;
2012-08-24 18:55:49 +02:00
if ( gameHdr - > type = = TYPE_GAME_GC_DISC )
{
WindowPrompt ( tr ( " Error: " ) , tr ( " To run GameCube games from Disc you need to set the GameCube mode to MIOS in the game settings. " ) , tr ( " OK " ) ) ;
return 0 ;
}
2013-03-17 14:48:15 +01:00
if ( ! CheckAHBPROT ( ) )
{
WindowPrompt ( tr ( " Error: " ) , tr ( " Devolution requires AHB access! Please launch USBLoaderGX from HBC or from an updated channel or forwarder. " ) , tr ( " OK " ) ) ;
return 0 ;
}
2012-08-24 18:55:49 +02:00
// Check if Devolution is available
u8 * loader_bin = NULL ;
2013-03-17 14:48:15 +01:00
int DEVO_version = 0 ;
2012-08-24 18:55:49 +02:00
char DEVO_loader_path [ 100 ] ;
snprintf ( DEVO_loader_path , sizeof ( DEVO_loader_path ) , " %sloader.bin " , Settings . DEVOLoaderPath ) ;
FILE * f = fopen ( DEVO_loader_path , " rb " ) ;
if ( f )
{
fseek ( f , 0 , SEEK_END ) ;
u32 size = ftell ( f ) ;
rewind ( f ) ;
loader_bin = ( u8 * ) MEM2_alloc ( size ) ;
if ( ! loader_bin )
{
fclose ( f ) ;
WindowPrompt ( tr ( " Error: " ) , tr ( " Devolution's loader.bin file can't be loaded. " ) , tr ( " OK " ) ) ;
return 0 ;
}
fread ( loader_bin , 1 , size , f ) ;
2013-03-17 14:48:15 +01:00
//read Devolution version
char version [ 5 ] ;
fseek ( f , 23 , SEEK_SET ) ;
fread ( version , 1 , 4 , f ) ;
char * ptr = strchr ( version , ' ' ) ;
if ( ptr ) * ptr = 0 ;
else version [ 4 ] = 0 ;
DEVO_version = atoi ( version ) ;
2012-08-24 18:55:49 +02:00
fclose ( f ) ;
}
else
{
WindowPrompt ( tr ( " Error: " ) , tr ( " To run GameCube games with Devolution you need the loader.bin file in your Devolution Path. " ) , tr ( " OK " ) ) ;
return 0 ;
}
// Devolution config
2012-10-14 18:27:01 +02:00
DEVO_CGF * devo_config = ( DEVO_CGF * ) 0x80000020 ;
2012-08-24 18:55:49 +02:00
// Get the Game's data
const char * RealPath = GCGames : : Instance ( ) - > GetPath ( ( const char * ) gameHdr - > id ) ;
char disc1 [ 100 ] ;
2012-12-09 21:31:55 +01:00
char disc2 [ 100 ] ;
bool multiDisc = false ;
2012-08-24 18:55:49 +02:00
char DEVO_memCard [ 100 ] ;
snprintf ( disc1 , sizeof ( disc1 ) , " %s " , RealPath ) ;
2012-12-09 21:31:55 +01:00
snprintf ( disc2 , sizeof ( disc2 ) , " %s " , RealPath ) ;
char * pathPtr = strrchr ( disc2 , ' / ' ) ;
if ( pathPtr ) * pathPtr = 0 ;
snprintf ( disc2 , sizeof ( disc2 ) , " %s/disc2.iso " , disc2 ) ;
if ( CheckFile ( disc2 ) )
multiDisc = true ;
2012-08-24 18:55:49 +02:00
snprintf ( DEVO_memCard , sizeof ( DEVO_memCard ) , " %s " , RealPath ) ; // Set memory card folder to Disc1 folder
char * ptr = strrchr ( DEVO_memCard , ' / ' ) ;
if ( ptr ) * ptr = 0 ;
// Make sure the directory exists
char devoPath [ 20 ] ;
snprintf ( devoPath , sizeof ( devoPath ) , " %s:/apps/gc_devo " , DeviceHandler : : GetDevicePrefix ( RealPath ) ) ;
CreateSubfolder ( devoPath ) ;
// Get the starting cluster (and device ID) for the ISO file 1
struct stat st1 ;
stat ( disc1 , & st1 ) ;
// Get the starting cluster for the ISO file 2
2012-12-09 21:31:55 +01:00
struct stat st2 ;
if ( multiDisc )
stat ( disc2 , & st2 ) ;
2012-08-24 18:55:49 +02:00
// setup Devolution
2012-10-14 18:27:01 +02:00
memset ( devo_config , 0 , sizeof ( * devo_config ) ) ;
devo_config - > signature = DEVO_SIG ;
devo_config - > version = DEVO_CONFIG_VERSION ;
2012-08-24 18:55:49 +02:00
// st1.st_dev doesn't work with our current device type. It returns Wii_UMS 'WUMS' instead of Wii_USB 'WUSB'.
// Only last two letters are returned by DevkitPro, so we set them manually to Devolution config.
2012-10-14 18:27:01 +02:00
devo_config - > device_signature = st1 . st_dev = = ' SD ' ? ' SD ' : ' SB ' ; // Set device type.
devo_config - > disc1_cluster = st1 . st_ino ; // set starting cluster for first disc ISO file
2012-12-09 21:31:55 +01:00
if ( multiDisc )
devo_config - > disc2_cluster = st2 . st_ino ; // set starting cluster for second disc ISO file
2012-08-24 18:55:49 +02:00
2012-10-14 18:27:01 +02:00
// Devolution configs
2012-08-24 18:55:49 +02:00
// use wifi logging if USB gecko is not found in slot B
2012-10-14 18:27:01 +02:00
// devo_config->options |= DEVO_CFG_WIFILOG; // removed on Tueidj request
2013-03-17 14:48:15 +01:00
if ( devoWidescreenChoice & & DEVO_version > = 188 )
2012-10-14 18:27:01 +02:00
devo_config - > options | = DEVO_CFG_WIDE ;
2013-03-17 14:48:15 +01:00
if ( ! devoActivityLEDChoice & & DEVO_version > = 142 )
2012-10-14 18:27:01 +02:00
devo_config - > options | = DEVO_CFG_NOLED ; // ON by default
2012-08-24 18:55:49 +02:00
// check memory card
if ( devoMCEmulation = = DEVO_MC_OFF )
{
2012-10-14 18:27:01 +02:00
devo_config - > memcard_cluster = 0 ;
2012-08-24 18:55:49 +02:00
snprintf ( DEVO_memCard , sizeof ( DEVO_memCard ) , " Original " ) ;
}
else
{
if ( devoMCEmulation = = DEVO_MC_INDIVIDUAL )
{
snprintf ( DEVO_memCard , sizeof ( DEVO_memCard ) , " %s/memcard_%.6s.bin " , DEVO_memCard , ( const char * ) gameHdr - > id ) ;
}
else // same for all games
{
snprintf ( DEVO_memCard , sizeof ( DEVO_memCard ) , " %s:/apps/gc_devo/memcard.bin " , DeviceHandler : : GetDevicePrefix ( RealPath ) ) ;
}
// check if file doesn't exist or is less than 512KB (59 Blocks)
struct stat st ;
if ( stat ( DEVO_memCard , & st ) = = - 1 | | st . st_size < 1 < < 19 )
{
// need to enlarge or create it
FILE * f = fopen ( DEVO_memCard , " wb " ) ;
if ( f )
{
// make it 16MB
ShowProgress ( tr ( " Please wait... " ) , 0 , 0 ) ;
gprintf ( " Resizing memcard file... \n " ) ;
fseek ( f , ( 16 < < 20 ) - 1 , SEEK_SET ) ;
fputc ( 0 , f ) ;
fclose ( f ) ;
if ( stat ( DEVO_memCard , & st ) = = - 1 | | st . st_size < 1 < < 19 )
{
// it still isn't big enough. Give up.
st . st_ino = 0 ;
}
ProgressStop ( ) ;
}
else
{
// couldn't open or create the memory card file
st . st_ino = 0 ;
}
}
2012-10-14 18:27:01 +02:00
devo_config - > memcard_cluster = st . st_ino ;
2012-08-24 18:55:49 +02:00
}
// read 32 bytes of disc 1 to the start of MEM1
FILE * iso_file = fopen ( disc1 , " rb " ) ;
if ( ! iso_file )
{
WindowPrompt ( tr ( " Error: " ) , tr ( " File not found. " ) , tr ( " OK " ) ) ;
return 0 ;
}
u8 * lowmem = ( u8 * ) 0x80000000 ;
fread ( lowmem , 1 , 32 , iso_file ) ;
fclose ( iso_file ) ;
// setup video mode
Disc_SelectVMode ( videoChoice , true , NULL ) ;
Disc_SetVMode ( ) ;
// flush disc ID and Devolution config out to memory
DCFlushRange ( lowmem , 64 ) ;
ExitApp ( ) ;
IosLoader : : ReloadIosKeepingRights ( 58 ) ; // reload IOS 58 with AHBPROT rights
gprintf ( " DEVO: Loading game: %s \n " , disc1 ) ;
gprintf ( " DEVO: Memory Card: %s \n \n " , DEVO_memCard ) ;
gprintf ( " %.72s " , ( const char * ) loader_bin + 4 ) ;
u32 cpu_isr ;
SYS_ResetSystem ( SYS_SHUTDOWN , 0 , 0 ) ;
_CPU_ISR_Disable ( cpu_isr ) ;
__exception_closeall ( ) ;
LAUNCH_DEVO ( ) ;
_CPU_ISR_Restore ( cpu_isr ) ;
return 0 ;
}