mirror of
https://github.com/Fledge68/WiiFlow_Lite.git
synced 2024-11-27 13:44:15 +01:00
- beta 12 (external booter changes).
- fixed launching of real nand channels. - fixed launching of forwarder channels, but some apps (ie. wiimcc and savegame manager gx) don't connect with USB devices. if they are on real nand use the 'custom' option in game settings for these forwarders. - fixed launching HBC on real nand. don't know if its even possible on a emu nand. - 480p pixel patch for nand wiiware/vc games no longer requires apploader setting ON. - Exclude Prince of Persia: The Forgotten Sands and a few games that use MetaFortress from using 480p pixel patch - added giantpunes returnto patch for channels just in case not using d2x cios. some reason it was missing.
This commit is contained in:
parent
a45cc4cbdf
commit
9f7da43da4
Binary file not shown.
BIN
out/boot.dol
BIN
out/boot.dol
Binary file not shown.
Before Width: | Height: | Size: 4.4 MiB After Width: | Height: | Size: 4.4 MiB |
@ -42,11 +42,13 @@
|
|||||||
#include "videopatch.h"
|
#include "videopatch.h"
|
||||||
#include "video_tinyload.h"
|
#include "video_tinyload.h"
|
||||||
#include "apploader.h"
|
#include "apploader.h"
|
||||||
|
#include "memory.h"
|
||||||
|
|
||||||
void *dolchunkoffset[18];
|
void *dolchunkoffset[18];
|
||||||
u32 dolchunksize[18];
|
u32 dolchunksize[18];
|
||||||
u32 dolchunkcount;
|
u32 dolchunkcount;
|
||||||
u32 bootcontent;
|
u32 bootcontent;
|
||||||
|
bool isForwarder = false;
|
||||||
|
|
||||||
char filepath[ISFS_MAXPATH] ATTRIBUTE_ALIGN(32);
|
char filepath[ISFS_MAXPATH] ATTRIBUTE_ALIGN(32);
|
||||||
|
|
||||||
@ -78,29 +80,70 @@ static u8 *GetDol(u32 bootcontent, u64 title)
|
|||||||
|
|
||||||
static bool GetAppNameFromTmd(bool dol, u32 *bootcontent, u64 title, u32 *IOS)
|
static bool GetAppNameFromTmd(bool dol, u32 *bootcontent, u64 title, u32 *IOS)
|
||||||
{
|
{
|
||||||
bool ret = false;
|
static const u8 dolsign[6] = {0x00, 0x00, 0x01, 0x00, 0x00, 0x00};
|
||||||
|
static u8 dolhead[32] ATTRIBUTE_ALIGN(32);
|
||||||
|
bool found = false;
|
||||||
snprintf(filepath, ISFS_MAXPATH, "/title/%08x/%08x/content/title.tmd", TITLE_UPPER(title), TITLE_LOWER(title));
|
snprintf(filepath, ISFS_MAXPATH, "/title/%08x/%08x/content/title.tmd", TITLE_UPPER(title), TITLE_LOWER(title));
|
||||||
|
|
||||||
u32 size;
|
u32 size;
|
||||||
u8 *data = ISFS_GetFile(filepath, &size, -1);
|
u8 *data = ISFS_GetFile(filepath, &size, -1);
|
||||||
if(data == NULL || size < 0x208)
|
if(data == NULL || size < 0x208)
|
||||||
return ret;
|
return found;
|
||||||
*IOS = data[0x18B];
|
*IOS = data[0x18B];
|
||||||
|
|
||||||
_tmd *tmd_file = (_tmd *)SIGNATURE_PAYLOAD((u32 *)data);
|
_tmd *tmd_file = (_tmd *)SIGNATURE_PAYLOAD((u32 *)data);
|
||||||
for(u16 i = 0; i < tmd_file->num_contents; ++i)
|
|
||||||
|
if(dol)
|
||||||
{
|
{
|
||||||
if(tmd_file->contents[i].index == (dol ? 0x01 : tmd_file->boot_index))
|
// check for dol signature - channels and vc
|
||||||
|
for(u32 i = 0; i < tmd_file->num_contents; ++i)
|
||||||
|
{
|
||||||
|
if(tmd_file->contents[i].index == tmd_file->boot_index)
|
||||||
|
continue; // Skip app loader
|
||||||
|
|
||||||
|
snprintf(filepath, ISFS_MAXPATH, "/title/%08x/%08x/content/%08x.app", TITLE_UPPER(title), TITLE_LOWER(title), tmd_file->contents[i].cid);
|
||||||
|
|
||||||
|
s32 fd = ISFS_Open(filepath, ISFS_OPEN_READ);
|
||||||
|
if(fd < 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
s32 ret = ISFS_Read(fd, dolhead, 32);
|
||||||
|
ISFS_Close(fd);
|
||||||
|
|
||||||
|
if(ret != 32)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if(memcmp(dolhead, dolsign, sizeof(dolsign)) == 0)
|
||||||
|
{
|
||||||
|
// Normal channels and VC use 1
|
||||||
|
if(tmd_file->contents[i].index != 1)// forwarder channel
|
||||||
|
isForwarder = true;
|
||||||
|
*bootcontent = tmd_file->contents[i].cid;
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!found) // WiiWare not matching a dol signature or apploader selected
|
||||||
|
{
|
||||||
|
for(u32 i = 0; i < tmd_file->num_contents; ++i)
|
||||||
{
|
{
|
||||||
*bootcontent = tmd_file->contents[i].cid;
|
if(tmd_file->contents[i].index == (dol ? 0x01 : tmd_file->boot_index))
|
||||||
ret = true;
|
{
|
||||||
break;
|
*bootcontent = tmd_file->contents[i].cid;
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
//fall back to app loader if main dol wanted but not found
|
||||||
|
if(!found && dol)
|
||||||
|
{
|
||||||
|
*bootcontent = tmd_file->contents[tmd_file->boot_index].cid;
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
free(data);
|
free(data);
|
||||||
|
return found;
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static u32 MoveDol(u8 *buffer)
|
static u32 MoveDol(u8 *buffer)
|
||||||
@ -108,10 +151,10 @@ static u32 MoveDol(u8 *buffer)
|
|||||||
dolchunkcount = 0;
|
dolchunkcount = 0;
|
||||||
dolheader *dolfile = (dolheader *)buffer;
|
dolheader *dolfile = (dolheader *)buffer;
|
||||||
|
|
||||||
if(dolfile->bss_start)
|
if(dolfile->bss_start)// if start is not zero
|
||||||
{
|
{
|
||||||
if(!(dolfile->bss_start & 0x80000000))
|
if(!(dolfile->bss_start & 0x80000000))// if start isn't >=80000000
|
||||||
dolfile->bss_start |= 0x80000000;
|
dolfile->bss_start |= 0x80000000;// set it to 80000000 or greater
|
||||||
|
|
||||||
memset((void *)dolfile->bss_start, 0, dolfile->bss_size);
|
memset((void *)dolfile->bss_start, 0, dolfile->bss_size);
|
||||||
DCFlushRange((void *)dolfile->bss_start, dolfile->bss_size);
|
DCFlushRange((void *)dolfile->bss_start, dolfile->bss_size);
|
||||||
@ -120,11 +163,11 @@ static u32 MoveDol(u8 *buffer)
|
|||||||
|
|
||||||
for(u8 i = 0; i < 18; i++)
|
for(u8 i = 0; i < 18; i++)
|
||||||
{
|
{
|
||||||
if(!dolfile->section_size[i])
|
if(!dolfile->section_size[i])// if section size is zero don't move
|
||||||
continue;
|
continue;
|
||||||
if(dolfile->section_pos[i] < sizeof(dolheader))
|
if(dolfile->section_pos[i] < sizeof(dolheader)) // if section position is within the header don't move
|
||||||
continue;
|
continue;
|
||||||
if(!(dolfile->section_start[i] & 0x80000000))
|
if(!(dolfile->section_start[i] & 0x80000000)) // maker sure section start is 80000000 or greater
|
||||||
dolfile->section_start[i] |= 0x80000000;
|
dolfile->section_start[i] |= 0x80000000;
|
||||||
|
|
||||||
dolchunkoffset[dolchunkcount] = (void *)dolfile->section_start[i];
|
dolchunkoffset[dolchunkcount] = (void *)dolfile->section_start[i];
|
||||||
@ -146,11 +189,24 @@ u32 LoadChannel(u64 title, bool dol, u32 *IOS)
|
|||||||
entry = MoveDol(data);
|
entry = MoveDol(data);
|
||||||
free(data);
|
free(data);
|
||||||
|
|
||||||
|
// Preparations
|
||||||
|
memset((void *)Disc_ID, 0, 6);
|
||||||
|
*Disc_ID = TITLE_LOWER(title); // Game ID
|
||||||
|
*Arena_H = 0; // Arena High, the apploader does this too
|
||||||
|
*BI2 = 0x817FE000; // BI2, the apploader does this too
|
||||||
|
*Bus_Speed = 0x0E7BE2C0; // bus speed
|
||||||
|
*CPU_Speed = 0x2B73A840; // cpu speed
|
||||||
|
*GameID_Address = 0x81000000; // Game id address, while there's all 0s at 0x81000000 when using the apploader...
|
||||||
|
memcpy((void *)Online_Check, (void *)Disc_ID, 4); // online check
|
||||||
|
|
||||||
|
memset((void *)0x817FE000, 0, 0x2000); // Clearing BI2
|
||||||
|
DCFlushRange((void *)0x817FE000, 0x2000);
|
||||||
|
|
||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PatchChannel(u8 vidMode, GXRModeObj *vmode, bool vipatch, bool countryString, u8 patchVidModes, int aspectRatio,
|
void PatchChannel(u8 vidMode, GXRModeObj *vmode, bool vipatch, bool countryString, u8 patchVidModes, int aspectRatio,
|
||||||
u8 private_server, const char *server_addr, bool patchFix480p, u8 deflicker, u8 bootType)
|
u32 returnTo, u8 private_server, const char *server_addr, bool patchFix480p, u8 deflicker, u8 bootType)
|
||||||
{
|
{
|
||||||
u8 vfilter_off[7] = {0, 0, 21, 22, 21, 0, 0};
|
u8 vfilter_off[7] = {0, 0, 21, 22, 21, 0, 0};
|
||||||
u8 vfilter_low[7] = {4, 4, 16, 16, 16, 4, 4};
|
u8 vfilter_low[7] = {4, 4, 16, 16, 16, 4, 4};
|
||||||
@ -169,6 +225,8 @@ void PatchChannel(u8 vidMode, GXRModeObj *vmode, bool vipatch, bool countryStrin
|
|||||||
PatchCountryStrings(dolchunkoffset[i], dolchunksize[i]);
|
PatchCountryStrings(dolchunkoffset[i], dolchunksize[i]);
|
||||||
if(aspectRatio != -1)
|
if(aspectRatio != -1)
|
||||||
PatchAspectRatio(dolchunkoffset[i], dolchunksize[i], aspectRatio);
|
PatchAspectRatio(dolchunkoffset[i], dolchunksize[i], aspectRatio);
|
||||||
|
if(returnTo)
|
||||||
|
PatchReturnTo(dolchunkoffset[i], dolchunksize[i], returnTo);
|
||||||
if(private_server)
|
if(private_server)
|
||||||
PrivateServerPatcher(dolchunkoffset[i], dolchunksize[i], private_server, server_addr);
|
PrivateServerPatcher(dolchunkoffset[i], dolchunksize[i], private_server, server_addr);
|
||||||
if(hooktype != 0 && hookpatched == false)
|
if(hooktype != 0 && hookpatched == false)
|
||||||
@ -207,4 +265,7 @@ void PatchChannel(u8 vidMode, GXRModeObj *vmode, bool vipatch, bool countryStrin
|
|||||||
|
|
||||||
if(patchFix480p)
|
if(patchFix480p)
|
||||||
PatchFix480p();
|
PatchFix480p();
|
||||||
|
|
||||||
|
if(private_server == PRIVSERV_WIIMMFI)
|
||||||
|
do_new_wiimmfi_nonMKWii();
|
||||||
}
|
}
|
||||||
|
@ -13,8 +13,10 @@ typedef struct _dolheader
|
|||||||
u32 padding[7];
|
u32 padding[7];
|
||||||
} ATTRIBUTE_PACKED dolheader;
|
} ATTRIBUTE_PACKED dolheader;
|
||||||
|
|
||||||
void PatchChannel(u8 vidMode, GXRModeObj *vmode, bool vipatch, bool countryString,
|
void PatchChannel(u8 vidMode, GXRModeObj *vmode, bool vipatch, bool countryString, u8 patchVidModes, int aspectRatio,
|
||||||
u8 patchVidModes, int aspectRatio, u8 private_server, const char *server_addr, bool patchFix480p, u8 deflicker, u8 bootType);
|
u32 returnTo, u8 private_server, const char *server_addr, bool patchFix480p, u8 deflicker, u8 bootType);
|
||||||
u32 LoadChannel(u64 title, bool dol, u32 *IOS);
|
u32 LoadChannel(u64 title, bool dol, u32 *IOS);
|
||||||
|
|
||||||
|
extern bool isForwarder;
|
||||||
|
|
||||||
#endif /* __CHANHANDLE_HPP_ */
|
#endif /* __CHANHANDLE_HPP_ */
|
||||||
|
@ -52,12 +52,14 @@ u32 Apploader_Run(u8 vidMode, GXRModeObj *vmode, bool vipatch, bool countryStrin
|
|||||||
bool patchregion , u8 private_server, const char *server_addr, bool patchFix480p, u8 deflicker, u8 bootType)
|
bool patchregion , u8 private_server, const char *server_addr, bool patchFix480p, u8 deflicker, u8 bootType)
|
||||||
{
|
{
|
||||||
//! Disable private server for games that still have official servers.
|
//! Disable private server for games that still have official servers.
|
||||||
if (memcmp(GameID, "SC7", 3) == 0 || memcmp(GameID, "RJA", 3) == 0 ||
|
if(memcmp(GameID, "SC7", 3) == 0 || memcmp(GameID, "RJA", 3) == 0 ||
|
||||||
memcmp(GameID, "SM8", 3) == 0 || memcmp(GameID, "SZB", 3) == 0 || memcmp(GameID, "R9J", 3) == 0)
|
memcmp(GameID, "SM8", 3) == 0 || memcmp(GameID, "SZB", 3) == 0 || memcmp(GameID, "R9J", 3) == 0)
|
||||||
{
|
{
|
||||||
private_server = PRIVSERV_OFF; // Private server patching causes error 20100
|
private_server = PRIVSERV_OFF; // Private server patching causes error 20100
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if either of these 2 games - adds internal wip codes before do_wip_code() is called in maindolpatches()
|
||||||
|
// note: using external .wip codes for these games will prevent their internal codes.
|
||||||
PrinceOfPersiaPatch();
|
PrinceOfPersiaPatch();
|
||||||
NewSuperMarioBrosPatch();
|
NewSuperMarioBrosPatch();
|
||||||
|
|
||||||
@ -118,21 +120,35 @@ u32 Apploader_Run(u8 vidMode, GXRModeObj *vmode, bool vipatch, bool countryStrin
|
|||||||
if(hooktype != 0 && hookpatched)
|
if(hooktype != 0 && hookpatched)
|
||||||
ocarina_do_code();
|
ocarina_do_code();
|
||||||
|
|
||||||
if(patchFix480p)
|
//! Apply the 480p fix.
|
||||||
|
//! This needs to be done after the call to maindolpatches(), after loading any code handler.
|
||||||
|
//! Can (and should) be done before Wiimmfi patching, can't be done in maindolpatches() itself.
|
||||||
|
//! Exclude Prince of Persia: The Forgotten Sands and a few games that use MetaFortress
|
||||||
|
bool excludeGame = false;
|
||||||
|
if(memcmp(GameID, "RPW", 3) == 0 || memcmp(GameID, "SPX", 3) == 0 ||
|
||||||
|
memcmp(GameID, "R3D", 3) == 0 || memcmp(GameID, "SDV", 3) == 0 ||
|
||||||
|
memcmp(GameID, "SUK", 3) == 0 || memcmp(GameID, "STN", 3) == 0 ||
|
||||||
|
memcmp(GameID, "S7S", 3) == 0 || memcmp(GameID, "SDUP41", 6) == 0 ||
|
||||||
|
memcmp(GameID, "SDUE41", 6) == 0 || memcmp(GameID, "SDUX41", 6) == 0)
|
||||||
|
{
|
||||||
|
excludeGame = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(patchFix480p && !excludeGame)
|
||||||
PatchFix480p();
|
PatchFix480p();
|
||||||
|
|
||||||
//! If we're NOT on Wiimmfi, patch the known RCE vulnerability in MKWii.
|
//! If we're NOT on Wiimmfi, patch the known Remote Code Execution (RCE) vulnerability in MKWii.
|
||||||
//! Wiimmfi will handle that on its own through the update payload.
|
//! Wiimmfi will handle that on its own through the update payload.
|
||||||
//! This will also patch error 23400 for a couple games that still have official servers.
|
//! This will also patch error 23400 for a couple games that still have official servers.
|
||||||
if(private_server != PRIVSERV_WIIMMFI)
|
if(private_server != PRIVSERV_WIIMMFI)
|
||||||
Patch_23400_and_MKWii_vulnerability();
|
Patch_23400_and_MKWii_vulnerability();
|
||||||
|
|
||||||
else //wiimmfi patch
|
else //PRIVSERV_WIIMMFI
|
||||||
{
|
{
|
||||||
if(memcmp("RMC", GameID, 3) != 0)// This isn't MKWii, perform the patch for other games.
|
if(memcmp("RMC", GameID, 3) != 0)// This isn't MKWii, perform the patch for other games.
|
||||||
do_new_wiimmfi_nonMKWii();
|
do_new_wiimmfi_nonMKWii();// does not patch the server address - done in maindolpatches()
|
||||||
else // This is MKWii, perform the known patch from 2018.
|
else // This is MKWii, perform the known patch from 2018.
|
||||||
do_new_wiimmfi();
|
do_new_wiimmfi();// includes patching the server address
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set entry point from apploader */
|
/* Set entry point from apploader */
|
||||||
@ -174,7 +190,7 @@ void maindolpatches(void *dst, int len, u8 vidMode, GXRModeObj *vmode, bool vipa
|
|||||||
if(patchregion)
|
if(patchregion)
|
||||||
PatchRegion(dst, len);
|
PatchRegion(dst, len);
|
||||||
if(private_server)
|
if(private_server)
|
||||||
PrivateServerPatcher(dst, len, private_server, serverAddr);
|
PrivateServerPatcher(dst, len, private_server, serverAddr);
|
||||||
|
|
||||||
if(deflicker == DEFLICKER_ON_LOW)
|
if(deflicker == DEFLICKER_ON_LOW)
|
||||||
{
|
{
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
|
|
||||||
s32 Disc_Open(u8 type)
|
s32 Disc_Open(u8 type)
|
||||||
{
|
{
|
||||||
if(type > 0)
|
if(type > 0)// if not a wii disc (wbfs ext or wbfs drive)
|
||||||
{ /* Reset drive */
|
{ /* Reset drive */
|
||||||
s32 ret = WDVD_Reset();
|
s32 ret = WDVD_Reset();
|
||||||
if(ret < 0)
|
if(ret < 0)
|
||||||
@ -29,23 +29,7 @@ s32 Disc_Open(u8 type)
|
|||||||
return WDVD_ReadDiskId((u8*)Disc_ID);
|
return WDVD_ReadDiskId((u8*)Disc_ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Disc_SetLowMemPre()
|
void Disc_SetLowMem(void)
|
||||||
{
|
|
||||||
/* Setup low memory before Apploader */
|
|
||||||
*BI2 = 0x817E5480; // BI2
|
|
||||||
*(vu32*)0xCD00643C = 0x00000000; // 32Mhz on Bus
|
|
||||||
|
|
||||||
/* Clear Disc ID */
|
|
||||||
memset((u8*)Disc_ID, 0, 32);
|
|
||||||
|
|
||||||
/* For WiiRD */
|
|
||||||
memset((void*)0x80001800, 0, 0x1800);
|
|
||||||
|
|
||||||
/* Flush everything */
|
|
||||||
DCFlushRange((void*)0x80000000, 0x3f00);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Disc_SetLowMem(u32 IOS)
|
|
||||||
{
|
{
|
||||||
/* Setup low memory */
|
/* Setup low memory */
|
||||||
*Sys_Magic = 0x0D15EA5E; // Standard Boot Code
|
*Sys_Magic = 0x0D15EA5E; // Standard Boot Code
|
||||||
@ -58,35 +42,10 @@ void Disc_SetLowMem(u32 IOS)
|
|||||||
*Dev_Debugger = 0x81800000; // Dev Debugger Monitor Address
|
*Dev_Debugger = 0x81800000; // Dev Debugger Monitor Address
|
||||||
*Simulated_Mem = 0x01800000; // Simulated Memory Size
|
*Simulated_Mem = 0x01800000; // Simulated Memory Size
|
||||||
*GameID_Address = 0x80000000; // Fix for Sam & Max (WiiPower)
|
*GameID_Address = 0x80000000; // Fix for Sam & Max (WiiPower)
|
||||||
|
*(vu32 *) 0xCD00643C = 0x00000000; // 32Mhz on Bus
|
||||||
|
|
||||||
/* Copy Disc ID */
|
/* Copy Disc ID */
|
||||||
memcpy((void*)Online_Check, (void*)Disc_ID, 4);
|
memcpy((void*)Online_Check, (void*)Disc_ID, 4);
|
||||||
|
|
||||||
/* For WiiRD */
|
|
||||||
memcpy((void*)0x80001800, (void*)Disc_ID, 8);
|
|
||||||
|
|
||||||
/* Error 002 Fix (thanks WiiPower and uLoader) */
|
|
||||||
*Current_IOS = (IOS << 16) | 0xffff;
|
|
||||||
*Apploader_IOS = (IOS << 16) | 0xffff;
|
|
||||||
|
|
||||||
/* Flush everything */
|
|
||||||
DCFlushRange((void*)0x80000000, 0x3f00);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Thanks to triiforce for that code */
|
|
||||||
void Disc_SetLowMemChan()
|
|
||||||
{
|
|
||||||
/* Setup low mem */
|
|
||||||
*Arena_H = 0x00000000; // Arena High, the appldr does this too
|
|
||||||
*BI2 = 0x817FE000; // BI2, the appldr does this too
|
|
||||||
*GameID_Address = 0x81000000; // Game id address, 0s at 0x81000000 with appldr
|
|
||||||
|
|
||||||
/* Flush low mem */
|
|
||||||
DCFlushRange((void*)0x80000000, 0x3f00);
|
|
||||||
|
|
||||||
/* Clear BI2 */
|
|
||||||
memset((void *)0x817FE000, 0, 0x2000);
|
|
||||||
DCFlushRange((void*)0x817FE000, 0x2000);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Thanks Tinyload */
|
/* Thanks Tinyload */
|
||||||
|
@ -9,9 +9,7 @@ extern "C" {
|
|||||||
s32 Disc_Open(u8 type);
|
s32 Disc_Open(u8 type);
|
||||||
s32 Disc_FindPartition(u32 *outbuf);
|
s32 Disc_FindPartition(u32 *outbuf);
|
||||||
s32 Disc_SetUSB(const u8 *id, bool frag);
|
s32 Disc_SetUSB(const u8 *id, bool frag);
|
||||||
void Disc_SetLowMemPre();
|
void Disc_SetLowMem();
|
||||||
void Disc_SetLowMem(u32 IOS);
|
|
||||||
void Disc_SetLowMemChan();
|
|
||||||
|
|
||||||
GXRModeObj *Disc_SelectVMode(u8 videoselected, u32 *rmode_reg);
|
GXRModeObj *Disc_SelectVMode(u8 videoselected, u32 *rmode_reg);
|
||||||
void Disc_SetVMode(GXRModeObj *rmode, u32 rmode_reg);
|
void Disc_SetVMode(GXRModeObj *rmode, u32 rmode_reg);
|
||||||
|
@ -144,6 +144,7 @@ void app_pokevalues()
|
|||||||
|
|
||||||
void load_handler()
|
void load_handler()
|
||||||
{
|
{
|
||||||
|
memset((void*)0x80001800, 0, 0x1800);
|
||||||
if(debuggerselect == 0x01)
|
if(debuggerselect == 0x01)
|
||||||
{
|
{
|
||||||
gprintf("Ocarina: Debugger selected.\n");
|
gprintf("Ocarina: Debugger selected.\n");
|
||||||
|
@ -56,12 +56,12 @@ int main()
|
|||||||
InitGecko();
|
InitGecko();
|
||||||
gprintf("WiiFlow External Booter by FIX94\n");
|
gprintf("WiiFlow External Booter by FIX94\n");
|
||||||
memcpy(&normalCFG, ((void*)*EXT_ADDR_CFG), sizeof(the_CFG));
|
memcpy(&normalCFG, ((void*)*EXT_ADDR_CFG), sizeof(the_CFG));
|
||||||
VIDEO_Init();
|
VIDEO_Init();// libogc
|
||||||
video_init();
|
video_init();// tinyload progress bar
|
||||||
prog10();
|
prog10();
|
||||||
|
|
||||||
configbytes[0] = normalCFG.configbytes[0];
|
configbytes[0] = normalCFG.configbytes[0];// game language 0 - 9 or 0xCD = not patched
|
||||||
configbytes[1] = normalCFG.configbytes[1];
|
configbytes[1] = normalCFG.configbytes[1];// not used
|
||||||
hooktype = normalCFG.hooktype;
|
hooktype = normalCFG.hooktype;
|
||||||
debuggerselect = normalCFG.debugger;
|
debuggerselect = normalCFG.debugger;
|
||||||
CurrentIOS = normalCFG.IOS;
|
CurrentIOS = normalCFG.IOS;
|
||||||
@ -73,9 +73,6 @@ int main()
|
|||||||
wbfs_part_idx = normalCFG.wbfsPart;
|
wbfs_part_idx = normalCFG.wbfsPart;
|
||||||
prog10();
|
prog10();
|
||||||
|
|
||||||
/* Setup Low Memory */
|
|
||||||
Disc_SetLowMemPre();
|
|
||||||
|
|
||||||
if(normalCFG.BootType == TYPE_WII_GAME)
|
if(normalCFG.BootType == TYPE_WII_GAME)
|
||||||
{
|
{
|
||||||
WDVD_Init();
|
WDVD_Init();
|
||||||
@ -103,6 +100,7 @@ int main()
|
|||||||
u32 offset = 0;
|
u32 offset = 0;
|
||||||
Disc_FindPartition(&offset);
|
Disc_FindPartition(&offset);
|
||||||
WDVD_OpenPartition(offset, &GameIOS);
|
WDVD_OpenPartition(offset, &GameIOS);
|
||||||
|
Disc_SetLowMem();
|
||||||
if(normalCFG.vidMode == 5)
|
if(normalCFG.vidMode == 5)
|
||||||
normalCFG.patchVidMode = 1; //progressive mode requires this
|
normalCFG.patchVidMode = 1; //progressive mode requires this
|
||||||
vmode = Disc_SelectVMode(normalCFG.vidMode, &vmode_reg);
|
vmode = Disc_SelectVMode(normalCFG.vidMode, &vmode_reg);
|
||||||
@ -112,22 +110,24 @@ int main()
|
|||||||
}
|
}
|
||||||
else if(normalCFG.BootType == TYPE_CHANNEL)
|
else if(normalCFG.BootType == TYPE_CHANNEL)
|
||||||
{
|
{
|
||||||
ISFS_Initialize();
|
|
||||||
*Disc_ID = TITLE_LOWER(normalCFG.title);
|
|
||||||
vmode = Disc_SelectVMode(normalCFG.vidMode, &vmode_reg);
|
vmode = Disc_SelectVMode(normalCFG.vidMode, &vmode_reg);
|
||||||
|
ISFS_Initialize();
|
||||||
AppEntrypoint = LoadChannel(normalCFG.title, normalCFG.use_dol, &GameIOS);
|
AppEntrypoint = LoadChannel(normalCFG.title, normalCFG.use_dol, &GameIOS);
|
||||||
PatchChannel(normalCFG.vidMode, vmode, normalCFG.vipatch, normalCFG.countryString, normalCFG.patchVidMode, normalCFG.aspectRatio,
|
|
||||||
normalCFG.private_server, normalCFG.server_addr, normalCFG.patchFix480p, normalCFG.deflicker, normalCFG.BootType);
|
|
||||||
ISFS_Deinitialize();
|
ISFS_Deinitialize();
|
||||||
|
PatchChannel(normalCFG.vidMode, vmode, normalCFG.vipatch, normalCFG.countryString, normalCFG.patchVidMode, normalCFG.aspectRatio,
|
||||||
|
normalCFG.returnTo, normalCFG.private_server, normalCFG.server_addr, normalCFG.patchFix480p, normalCFG.deflicker, normalCFG.BootType);
|
||||||
}
|
}
|
||||||
gprintf("Entrypoint: %08x, Requested Game IOS: %i\n", AppEntrypoint, GameIOS);
|
gprintf("Entrypoint: %08x, Requested Game IOS: %i\n", AppEntrypoint, GameIOS);
|
||||||
setprog(320);
|
setprog(320);
|
||||||
|
|
||||||
/* Setup Low Memory */
|
/* Error 002 Fix (thanks WiiPower and uLoader) */
|
||||||
Disc_SetLowMem(GameIOS);
|
*Current_IOS = (GameIOS << 16) | 0xffff;
|
||||||
if(normalCFG.BootType == TYPE_CHANNEL && AppEntrypoint != 0x3400)
|
if(!isForwarder)
|
||||||
Disc_SetLowMemChan(); /* Real DOL without appldr */
|
*Apploader_IOS = (GameIOS << 16) | 0xffff;
|
||||||
|
|
||||||
|
/* Flush everything */
|
||||||
|
DCFlushRange((void*)0x80000000, 0x3f00);
|
||||||
|
|
||||||
/* Enable front LED if requested */
|
/* Enable front LED if requested */
|
||||||
if(normalCFG.use_led) *HW_GPIOB_OUT |= 0x20;
|
if(normalCFG.use_led) *HW_GPIOB_OUT |= 0x20;
|
||||||
|
|
||||||
|
@ -357,140 +357,148 @@ void PatchVideoSneek(void *addr, u32 len)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//giantpune's magic super patch to return to channels
|
// giantpune's magic super patch to return to channels
|
||||||
|
|
||||||
static u32 ad[ 4 ] = { 0, 0, 0, 0 };//these variables are global on the off chance the different parts needed
|
static u32 ad[4] = {0, 0, 0, 0}; // these variables are global on the off chance the different parts needed
|
||||||
static u8 found = 0; //to find in the dol are found in different sections of the dol
|
static u8 found = 0; // to find in the dol are found in different sections of the dol
|
||||||
static u8 returnToPatched = 0;
|
static u8 returnToPatched = 0;
|
||||||
|
|
||||||
bool PatchReturnTo( void *Address, int Size, u32 id )
|
bool PatchReturnTo(void *Address, int Size, u32 id)
|
||||||
{
|
{
|
||||||
if( !id || returnToPatched )
|
if(!id || returnToPatched)
|
||||||
return 0;
|
return 0;
|
||||||
//gprintf("PatchReturnTo( %p, %08x, %08x )\n", Address, Size, id );
|
//gprintf("PatchReturnTo( %p, %08x, %08x )\n", Address, Size, id );
|
||||||
|
|
||||||
//new __OSLoadMenu() (SM2.0 and higher)
|
// new __OSLoadMenu() (SM2.0 and higher)
|
||||||
u8 SearchPattern[ 12 ] = { 0x38, 0x80, 0x00, 0x02, 0x38, 0x60, 0x00, 0x01, 0x38, 0xa0, 0x00, 0x00 }; //li r4,2
|
u8 SearchPattern[12] = {0x38, 0x80, 0x00, 0x02, 0x38, 0x60, 0x00, 0x01, 0x38, 0xa0, 0x00, 0x00}; // li r4,2
|
||||||
//li r3,1
|
// li r3,1
|
||||||
//li r5,0
|
// li r5,0
|
||||||
//old _OSLoadMenu() (used in launch games)
|
// old _OSLoadMenu() (used in launch games)
|
||||||
u8 SearchPatternB[ 12 ] = { 0x38, 0xC0, 0x00, 0x02, 0x38, 0xA0, 0x00, 0x01, 0x38, 0xE0, 0x00, 0x00 }; //li r6,2
|
u8 SearchPatternB[12] = {0x38, 0xC0, 0x00, 0x02, 0x38, 0xA0, 0x00, 0x01, 0x38, 0xE0, 0x00, 0x00}; // li r6,2
|
||||||
//li r5,1
|
// li r5,1
|
||||||
//li r7,0
|
// li r7,0
|
||||||
//identifier for the safe place
|
// identifier for the safe place
|
||||||
u8 SearchPattern2[ 12 ] = { 0x4D, 0x65, 0x74, 0x72, 0x6F, 0x77, 0x65, 0x72, 0x6B, 0x73, 0x20, 0x54 }; //"Metrowerks T"
|
u8 SearchPattern2[12] = {0x4D, 0x65, 0x74, 0x72, 0x6F, 0x77, 0x65, 0x72, 0x6B, 0x73, 0x20, 0x54}; // "Metrowerks T"
|
||||||
|
|
||||||
u8 oldSDK = 0;
|
u8 oldSDK = 0;
|
||||||
found = 0;
|
found = 0;
|
||||||
|
|
||||||
void *Addr = Address;
|
void *Addr = Address;
|
||||||
void *Addr_end = Address+Size;
|
void *Addr_end = Address + Size;
|
||||||
|
|
||||||
while (Addr <= Addr_end - 12 )
|
while(Addr <= Addr_end - 12)
|
||||||
{
|
{
|
||||||
//find a safe place or the patch to hang out
|
// find a safe place for the patch to hang out
|
||||||
if ( ! ad[ 3 ] && memcmp( Addr, SearchPattern2, 12 ) == 0 )
|
if(!ad[3] && memcmp(Addr, SearchPattern2, 12) == 0)
|
||||||
{
|
{
|
||||||
ad[ 3 ] = (u32)Addr + 0x30;
|
ad[3] = (u32)Addr + 0x30;
|
||||||
}
|
}
|
||||||
//find __OSLaunchMenu() and remember some addresses in it
|
// find __OSLaunchMenu() and remember some addresses in it
|
||||||
else if ( memcmp( Addr, SearchPattern, 12 )==0 )
|
else if(memcmp(Addr, SearchPattern, 12) == 0)
|
||||||
{
|
{
|
||||||
ad[ found++ ] = (u32)Addr;
|
ad[found++] = (u32)Addr;
|
||||||
}
|
}
|
||||||
else if ( ad[ 0 ] && memcmp( Addr, SearchPattern, 8 )==0 ) //after the first match is found, only search the first 8 bytes for the other 2
|
else if(ad[0] && memcmp(Addr, SearchPattern, 8) == 0) // after the first match is found, only search the first 8 bytes for the other 2
|
||||||
{
|
{
|
||||||
if( !ad[ 1 ] ) ad[ found++ ] = (u32)Addr;
|
if(!ad[1])
|
||||||
else if( !ad[ 2 ] ) ad[ found++ ] = (u32)Addr;
|
ad[found++] = (u32)Addr;
|
||||||
if( found >= 3 )break;
|
else if(!ad[2])
|
||||||
}
|
ad[found++] = (u32)Addr;
|
||||||
Addr += 4;
|
if(found >= 3)
|
||||||
}
|
break;
|
||||||
//check for the older-ass version of the SDK
|
}
|
||||||
if( found < 3 && ad[ 3 ] )
|
Addr += 4;
|
||||||
{
|
}
|
||||||
Addr = Address;
|
// check for the older-ass version of the SDK
|
||||||
ad[ 0 ] = 0;
|
if(found < 3 && ad[3])
|
||||||
ad[ 1 ] = 0;
|
{
|
||||||
ad[ 2 ] = 0;
|
Addr = Address;
|
||||||
found = 0;
|
ad[0] = 0;
|
||||||
oldSDK = 1;
|
ad[1] = 0;
|
||||||
|
ad[2] = 0;
|
||||||
|
found = 0;
|
||||||
|
oldSDK = 1;
|
||||||
|
|
||||||
while (Addr <= Addr_end - 12 )
|
while(Addr <= Addr_end - 12)
|
||||||
{
|
{
|
||||||
//find __OSLaunchMenu() and remember some addresses in it
|
// find __OSLaunchMenu() and remember some addresses in it
|
||||||
if ( memcmp( Addr, SearchPatternB, 12 )==0 )
|
if(memcmp(Addr, SearchPatternB, 12) == 0)
|
||||||
{
|
{
|
||||||
ad[ found++ ] = (u32)Addr;
|
ad[found++] = (u32)Addr;
|
||||||
}
|
}
|
||||||
else if ( ad[ 0 ] && memcmp( Addr, SearchPatternB, 8 ) == 0 ) //after the first match is found, only search the first 8 bytes for the other 2
|
else if(ad[0] && memcmp(Addr, SearchPatternB, 8) == 0) // after the first match is found, only search the first 8 bytes for the other 2
|
||||||
{
|
{
|
||||||
if( !ad[ 1 ] ) ad[ found++ ] = (u32)Addr;
|
if(!ad[1])
|
||||||
else if( !ad[ 2 ] ) ad[ found++ ] = (u32)Addr;
|
ad[found++] = (u32)Addr;
|
||||||
if( found >= 3 )break;
|
else if(!ad[2])
|
||||||
}
|
ad[found++] = (u32)Addr;
|
||||||
Addr += 4;
|
if(found >= 3)
|
||||||
}
|
break;
|
||||||
}
|
}
|
||||||
|
Addr += 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//if the function is found
|
// if the function is found
|
||||||
if( found == 3 && ad[ 3 ] )
|
if(found == 3 && ad[3])
|
||||||
{
|
{
|
||||||
gprintf("patch __OSLaunchMenu( 0x00010001, 0x%08x )\n", id);
|
//gprintf("patch __OSLaunchMenu( 0x00010001, 0x%08x )\n", id);
|
||||||
u32 nop = 0x60000000;
|
u32 nop = 0x60000000;
|
||||||
|
|
||||||
//the magic that writes the TID to the registers
|
// the magic that writes the TID to the registers
|
||||||
u8 jump[ 20 ] = { 0x3C, 0x60, 0x00, 0x01, //lis r3,1
|
u8 jump[20] = {
|
||||||
0x60, 0x63, 0x00, 0x01, //ori r3,r3,1
|
0x3C, 0x60, 0x00, 0x01, // lis r3,1
|
||||||
0x3C, 0x80, (u8)( id >> 24 ), (u8)( id >> 16 ), //lis r4,(u16)(tid >> 16)
|
0x60, 0x63, 0x00, 0x01, // ori r3,r3,1
|
||||||
0x60, 0x84, (u8)( id >> 8 ), (u8)id, //ori r4,r4,(u16)(tid)
|
0x3C, 0x80, (u8)(id >> 24), (u8)(id >> 16), // lis r4,(u16)(tid >> 16)
|
||||||
0x4E, 0x80, 0x00, 0x20
|
0x60, 0x84, (u8)(id >> 8), (u8)id, // ori r4,r4,(u16)(tid)
|
||||||
}; //blr
|
0x4E, 0x80, 0x00, 0x20}; // blr
|
||||||
|
|
||||||
if( oldSDK )
|
if(oldSDK)
|
||||||
{
|
{
|
||||||
jump[ 1 ] = 0xA0; //3CA00001 //lis r5,1
|
jump[1] = 0xA0; // 3CA00001 // lis r5,1
|
||||||
jump[ 5 ] = 0xA5; //60A50001 //ori r5,r5,1
|
jump[5] = 0xA5; // 60A50001 // ori r5,r5,1
|
||||||
jump[ 9 ] = 0xC0; //3CC0AF1B //lis r6,(u16)(tid >> 16)
|
jump[9] = 0xC0; // 3CC0AF1B // lis r6,(u16)(tid >> 16)
|
||||||
jump[ 13 ] = 0xC6;//60C6F516 //ori r6,r6,(u16)(tid)
|
jump[13] = 0xC6; // 60C6F516 // ori r6,r6,(u16)(tid)
|
||||||
}
|
}
|
||||||
|
|
||||||
void* addr = (u32*)ad[ 3 ];
|
void *addr = (u32 *)ad[3];
|
||||||
|
|
||||||
//write new stuff to in a unused part of the main.dol
|
// write new stuff to in a unused part of the main.dol
|
||||||
memcpy( addr, jump, sizeof( jump ) );
|
memcpy(addr, jump, sizeof(jump));
|
||||||
|
|
||||||
//ES_GetTicketViews()
|
// ES_GetTicketViews()
|
||||||
u32 newval = ( ad[ 3 ] - ad[ 0 ] );
|
u32 newval = (ad[3] - ad[0]);
|
||||||
newval &= 0x03FFFFFC;
|
newval &= 0x03FFFFFC;
|
||||||
newval |= 0x48000001;
|
newval |= 0x48000001;
|
||||||
addr = (u32*)ad[ 0 ];
|
addr = (u32 *)ad[0];
|
||||||
memcpy( addr, &newval, sizeof( u32 ) ); //bl ad[ 3 ]
|
memcpy(addr, &newval, sizeof(u32)); // bl ad[ 3 ]
|
||||||
memcpy( addr + 4, &nop, sizeof( u32 ) ); //nop
|
memcpy(addr + 4, &nop, sizeof(u32)); // nop
|
||||||
//gprintf("\t%08x -> %08x\n", addr, newval );
|
//gprintf("\t%08x -> %08x\n", addr, newval );
|
||||||
|
|
||||||
//ES_GetTicketViews() again
|
// ES_GetTicketViews() again
|
||||||
newval = ( ad[ 3 ] - ad[ 1 ] );
|
newval = (ad[3] - ad[1]);
|
||||||
newval &= 0x03FFFFFC;
|
newval &= 0x03FFFFFC;
|
||||||
newval |= 0x48000001;
|
newval |= 0x48000001;
|
||||||
addr = (u32*)ad[ 1 ];
|
addr = (u32 *)ad[1];
|
||||||
memcpy( addr, &newval, sizeof( u32 ) ); //bl ad[ 3 ]
|
memcpy(addr, &newval, sizeof(u32)); // bl ad[ 3 ]
|
||||||
memcpy( addr + 4, &nop, sizeof( u32 ) ); //nop
|
memcpy(addr + 4, &nop, sizeof(u32)); // nop
|
||||||
//gprintf("\t%08x -> %08x\n", addr, newval );
|
//gprintf("\t%08x -> %08x\n", addr, newval );
|
||||||
|
|
||||||
//ES_LaunchTitle()
|
// ES_LaunchTitle()
|
||||||
newval = ( ad[ 3 ] - ad[ 2 ] );
|
newval = (ad[3] - ad[2]);
|
||||||
newval &= 0x03FFFFFC;
|
newval &= 0x03FFFFFC;
|
||||||
newval |= 0x48000001;
|
newval |= 0x48000001;
|
||||||
addr = (u32*)ad[ 2 ];
|
addr = (u32 *)ad[2];
|
||||||
memcpy( addr, &newval, sizeof( u32 ) ); //bl ad[ 3 ]
|
memcpy(addr, &newval, sizeof(u32)); // bl ad[ 3 ]
|
||||||
memcpy( addr + 4, &nop, sizeof( u32 ) ); //nop
|
memcpy(addr + 4, &nop, sizeof(u32)); // nop
|
||||||
//gprintf("\t%08x -> %08x\n", addr, newval );
|
//gprintf("\t%08x -> %08x\n", addr, newval );
|
||||||
|
|
||||||
returnToPatched = 1;
|
returnToPatched = 1;
|
||||||
}
|
}
|
||||||
|
if(returnToPatched)
|
||||||
|
gprintf("Return to %08X patched with old method.\n", (u32)id);
|
||||||
|
|
||||||
return returnToPatched;
|
return returnToPatched;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PatchAspectRatio(void *addr, u32 len, u8 aspect)
|
void PatchAspectRatio(void *addr, u32 len, u8 aspect)
|
||||||
@ -513,7 +521,7 @@ void PatchAspectRatio(void *addr, u32 len, u8 aspect)
|
|||||||
|
|
||||||
while(addr_start < addr_end)
|
while(addr_start < addr_end)
|
||||||
{
|
{
|
||||||
if( (memcmp(addr_start, aspect_searchpattern1, sizeof(aspect_searchpattern1)) == 0)
|
if((memcmp(addr_start, aspect_searchpattern1, sizeof(aspect_searchpattern1)) == 0)
|
||||||
&& (memcmp(addr_start + 4 + sizeof(aspect_searchpattern1), aspect_searchpattern2, sizeof(aspect_searchpattern2)) == 0))
|
&& (memcmp(addr_start + 4 + sizeof(aspect_searchpattern1), aspect_searchpattern2, sizeof(aspect_searchpattern2)) == 0))
|
||||||
{
|
{
|
||||||
*((u32 *)(addr_start+0x44)) = (0x38600000 | aspect);
|
*((u32 *)(addr_start+0x44)) = (0x38600000 | aspect);
|
||||||
|
@ -108,7 +108,7 @@ u64 *Channels::GetChannelList(u32 *count)
|
|||||||
return titles;
|
return titles;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Channels::GetAppNameFromTmd(u64 title, char *app, u32 *bootcontent)
|
bool Channels::GetAppNameFromTmd(u64 title, char *app, u32 *bootcontent)// get banner .app name
|
||||||
{
|
{
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
u32 size = 0;
|
u32 size = 0;
|
||||||
@ -128,10 +128,9 @@ bool Channels::GetAppNameFromTmd(u64 title, char *app, u32 *bootcontent)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
_tmd *tmd_file = (_tmd *)SIGNATURE_PAYLOAD((u32 *)data);
|
_tmd *tmd_file = (_tmd *)SIGNATURE_PAYLOAD((u32 *)data);
|
||||||
u16 i;
|
for(u32 i = 0; i < tmd_file->num_contents; ++i)
|
||||||
for(i = 0; i < tmd_file->num_contents; ++i)
|
|
||||||
{
|
{
|
||||||
if(tmd_file->contents[i].index == 0)
|
if(tmd_file->contents[i].index == 0)// banner app
|
||||||
{
|
{
|
||||||
*bootcontent = tmd_file->contents[i].cid;
|
*bootcontent = tmd_file->contents[i].cid;
|
||||||
snprintf(app, ISFS_MAXPATH, "/title/%08x/%08x/content/%08x.app", TITLE_UPPER(title), TITLE_LOWER(title), *bootcontent);
|
snprintf(app, ISFS_MAXPATH, "/title/%08x/%08x/content/%08x.app", TITLE_UPPER(title), TITLE_LOWER(title), *bootcontent);
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
|
|
||||||
#define APP_NAME "WiiFlow WFL"
|
#define APP_NAME "WiiFlow WFL"
|
||||||
#define APP_VERSION "5.5.0 beta 11"
|
#define APP_VERSION "5.5.0 beta 12"
|
||||||
|
|
||||||
#define APP_DATA_DIR "wiiflow"
|
#define APP_DATA_DIR "wiiflow"
|
||||||
#define APPS_DIR "apps/wiiflow"
|
#define APPS_DIR "apps/wiiflow"
|
||||||
|
@ -705,7 +705,7 @@ int CMenu::_loadGameIOS(u8 gameIOS, int userIOS, string id, bool RealNAND_Channe
|
|||||||
if(RealNAND_Channels && IOS_GetType(mainIOS) == IOS_TYPE_STUB)
|
if(RealNAND_Channels && IOS_GetType(mainIOS) == IOS_TYPE_STUB)
|
||||||
{
|
{
|
||||||
/* doesn't use cIOS so we don't check userIOS */
|
/* doesn't use cIOS so we don't check userIOS */
|
||||||
bool ret = loadIOS(gameIOS, false);//load game requested IOS and patch nothing
|
bool ret = loadIOS(gameIOS, false);//load game requested IOS and do not remount sd and USB
|
||||||
if(has_enabled_providers() || m_use_wifi_gecko)
|
if(has_enabled_providers() || m_use_wifi_gecko)
|
||||||
_initAsyncNetwork();// needed after IOS change
|
_initAsyncNetwork();// needed after IOS change
|
||||||
if(ret == false)
|
if(ret == false)
|
||||||
@ -740,7 +740,7 @@ int CMenu::_loadGameIOS(u8 gameIOS, int userIOS, string id, bool RealNAND_Channe
|
|||||||
if(gameIOS != CurrentIOS.Version)
|
if(gameIOS != CurrentIOS.Version)
|
||||||
{
|
{
|
||||||
gprintf("Reloading IOS into %d\n", gameIOS);
|
gprintf("Reloading IOS into %d\n", gameIOS);
|
||||||
bool ret = loadIOS(gameIOS, true);// cIOS patch everything
|
bool ret = loadIOS(gameIOS, true);//load cIOS requested and then remount sd and USB devices
|
||||||
if(has_enabled_providers() || m_use_wifi_gecko)
|
if(has_enabled_providers() || m_use_wifi_gecko)
|
||||||
_initAsyncNetwork();// always seem to do netinit after changing IOS
|
_initAsyncNetwork();// always seem to do netinit after changing IOS
|
||||||
if(ret == false)
|
if(ret == false)
|
||||||
@ -755,39 +755,52 @@ int CMenu::_loadGameIOS(u8 gameIOS, int userIOS, string id, bool RealNAND_Channe
|
|||||||
|
|
||||||
void CMenu::_launchChannel(dir_discHdr *hdr)
|
void CMenu::_launchChannel(dir_discHdr *hdr)
|
||||||
{
|
{
|
||||||
NANDemuView = hdr->type == TYPE_EMUCHANNEL;
|
|
||||||
|
|
||||||
/* clear coverflow, start wiiflow wait animation, set exit handler */
|
/* clear coverflow, start wiiflow wait animation, set exit handler */
|
||||||
_launchShutdown();
|
_launchShutdown();
|
||||||
string id = string(hdr->id);
|
|
||||||
|
|
||||||
/* WII_Launch is used for launching real nand channels */
|
NANDemuView = hdr->type == TYPE_EMUCHANNEL;
|
||||||
|
string id = string(hdr->id);
|
||||||
|
u64 gameTitle = TITLE_ID(hdr->settings[0],hdr->settings[1]);
|
||||||
|
m_gcfg1.setInt("PLAYCOUNT", id, m_gcfg1.getInt("PLAYCOUNT", id, 0) + 1);
|
||||||
|
m_gcfg1.setUInt("LASTPLAYED", id, time(NULL));
|
||||||
|
|
||||||
|
bool hbc = false;
|
||||||
|
if(gameTitle == HBC_OHBC || gameTitle == HBC_LULZ || gameTitle == HBC_108 || gameTitle == HBC_JODI || gameTitle == HBC_HAXX)
|
||||||
|
hbc = true;
|
||||||
|
|
||||||
|
/* WII_Launch is used only for launching real nand channels */
|
||||||
|
/* note: no patches, cheats, or cIOS settings allowed */
|
||||||
bool WII_Launch = (m_gcfg2.getBool(id, "custom", false) && !NANDemuView);
|
bool WII_Launch = (m_gcfg2.getBool(id, "custom", false) && !NANDemuView);
|
||||||
|
if(WII_Launch || (hbc && !NANDemuView))
|
||||||
|
{
|
||||||
|
/* configs no longer needed */
|
||||||
|
m_gcfg1.save(true);
|
||||||
|
m_gcfg2.save(true);
|
||||||
|
m_cat.save(true);
|
||||||
|
m_cfg.save(true);
|
||||||
|
cleanup();//no more error messages we can now cleanup
|
||||||
|
ShutdownBeforeExit();
|
||||||
|
WII_Initialize();
|
||||||
|
WII_LaunchTitle(gameTitle);
|
||||||
|
}
|
||||||
|
|
||||||
/* use_dol = true to use the channels dol or false to use the old apploader method to boot channel */
|
/* use_dol = true to use the channels dol or false to use the old apploader method to boot channel */
|
||||||
bool use_dol = !m_gcfg2.getBool(id, "apploader", false);
|
bool use_dol = !m_gcfg2.getBool(id, "apploader", false);
|
||||||
|
bool use_led = m_gcfg2.getBool(id, "led", false);
|
||||||
bool vipatch = m_gcfg2.getBool(id, "vipatch", false);
|
|
||||||
bool cheat = m_gcfg2.getBool(id, "cheat", false);
|
|
||||||
bool countryPatch = m_gcfg2.getBool(id, "country_patch", false);
|
|
||||||
|
|
||||||
u8 videoMode = min(m_gcfg2.getUInt(id, "video_mode", 0), ARRAY_SIZE(CMenu::_VideoModes) - 1u);
|
|
||||||
videoMode = (videoMode == 0) ? min(m_cfg.getUInt("GENERAL", "video_mode", 0), ARRAY_SIZE(CMenu::_GlobalVideoModes) - 1u) : videoMode - 1;
|
|
||||||
|
|
||||||
int language = min(m_gcfg2.getUInt(id, "language", 0), ARRAY_SIZE(CMenu::_languages) - 1u);
|
int language = min(m_gcfg2.getUInt(id, "language", 0), ARRAY_SIZE(CMenu::_languages) - 1u);
|
||||||
language = (language == 0) ? min(m_cfg.getUInt("GENERAL", "game_language", 0), ARRAY_SIZE(CMenu::_languages) - 1u) : language;
|
language = (language == 0) ? min(m_cfg.getUInt("GENERAL", "game_language", 0), ARRAY_SIZE(CMenu::_languages) - 1u) : language;
|
||||||
|
|
||||||
|
bool vipatch = m_gcfg2.getBool(id, "vipatch", false);
|
||||||
|
bool countryPatch = m_gcfg2.getBool(id, "country_patch", false);
|
||||||
|
|
||||||
|
u8 videoMode = min(m_gcfg2.getUInt(id, "video_mode", 0), ARRAY_SIZE(CMenu::_VideoModes) - 1u);
|
||||||
|
videoMode = (videoMode == 0) ? min(m_cfg.getUInt("GENERAL", "video_mode", 0), ARRAY_SIZE(CMenu::_GlobalVideoModes) - 1u) : videoMode - 1;
|
||||||
|
|
||||||
u8 patchVidMode = min(m_gcfg2.getUInt(id, "patch_video_modes", 0), ARRAY_SIZE(CMenu::_vidModePatch) - 1u);
|
u8 patchVidMode = min(m_gcfg2.getUInt(id, "patch_video_modes", 0), ARRAY_SIZE(CMenu::_vidModePatch) - 1u);
|
||||||
|
|
||||||
s8 aspectRatio = min(m_gcfg2.getUInt(id, "aspect_ratio", 0), ARRAY_SIZE(CMenu::_AspectRatio) - 1) - 1;// -1,0,1
|
s8 aspectRatio = min(m_gcfg2.getUInt(id, "aspect_ratio", 0), ARRAY_SIZE(CMenu::_AspectRatio) - 1) - 1;// -1,0,1
|
||||||
|
|
||||||
u8 private_server = m_gcfg2.getUInt(id, "private_server", 0);
|
|
||||||
string server_addr = "";
|
|
||||||
if(private_server > 2)
|
|
||||||
{
|
|
||||||
vector<string> custom_servers = stringToVector(m_cfg.getString("custom_servers", "servers"), '|');
|
|
||||||
server_addr = m_cfg.getString("custom_servers", fmt("%s_url", custom_servers[private_server - 3]), "");
|
|
||||||
}
|
|
||||||
|
|
||||||
int fix480pVal = m_gcfg2.getOptBool(id, "fix480p", 2);
|
int fix480pVal = m_gcfg2.getOptBool(id, "fix480p", 2);
|
||||||
bool fix480p = fix480pVal == 0 ? false : (fix480pVal == 1 ? true : m_cfg.getBool(WII_DOMAIN, "fix480p", false));
|
bool fix480p = fix480pVal == 0 ? false : (fix480pVal == 1 ? true : m_cfg.getBool(WII_DOMAIN, "fix480p", false));
|
||||||
|
|
||||||
@ -796,6 +809,14 @@ void CMenu::_launchChannel(dir_discHdr *hdr)
|
|||||||
u8 deflicker = min(m_gcfg2.getUInt(id, "deflicker_wii", 0), ARRAY_SIZE(CMenu::_DeflickerOptions) - 1u);
|
u8 deflicker = min(m_gcfg2.getUInt(id, "deflicker_wii", 0), ARRAY_SIZE(CMenu::_DeflickerOptions) - 1u);
|
||||||
deflicker = (deflicker == 0) ? min(m_cfg.getUInt("GENERAL", "deflicker_wii", 0), ARRAY_SIZE(CMenu::_GlobalDeflickerOptions) - 1u) : deflicker - 1;
|
deflicker = (deflicker == 0) ? min(m_cfg.getUInt("GENERAL", "deflicker_wii", 0), ARRAY_SIZE(CMenu::_GlobalDeflickerOptions) - 1u) : deflicker - 1;
|
||||||
|
|
||||||
|
u8 private_server = m_gcfg2.getUInt(id, "private_server", 0);
|
||||||
|
string server_addr = "";
|
||||||
|
if(private_server > 2)
|
||||||
|
{
|
||||||
|
vector<string> custom_servers = stringToVector(m_cfg.getString("custom_servers", "servers"), '|');
|
||||||
|
server_addr = m_cfg.getString("custom_servers", fmt("%s_url", custom_servers[private_server - 3]), "");
|
||||||
|
}
|
||||||
|
|
||||||
u32 returnTo = 0;
|
u32 returnTo = 0;
|
||||||
const char *rtrn = m_cfg.getString("GENERAL", "returnto").c_str();
|
const char *rtrn = m_cfg.getString("GENERAL", "returnto").c_str();
|
||||||
if(strlen(rtrn) == 4)
|
if(strlen(rtrn) == 4)
|
||||||
@ -803,31 +824,26 @@ void CMenu::_launchChannel(dir_discHdr *hdr)
|
|||||||
|
|
||||||
u8 *cheatFile = NULL;
|
u8 *cheatFile = NULL;
|
||||||
u32 cheatSize = 0;
|
u32 cheatSize = 0;
|
||||||
if(!WII_Launch)
|
bool cheat = m_gcfg2.getBool(id, "cheat", false);
|
||||||
{
|
hooktype = (u32) m_gcfg2.getInt(id, "hooktype", 0);
|
||||||
hooktype = (u32) m_gcfg2.getInt(id, "hooktype", 0);
|
debuggerselect = m_gcfg2.getInt(id, "debugger", 0);
|
||||||
debuggerselect = m_gcfg2.getInt(id, "debugger", 0);
|
if((cheat || debuggerselect == 1) && hooktype == 0)
|
||||||
if((cheat || debuggerselect == 1) && hooktype == 0)
|
hooktype = 1;
|
||||||
hooktype = 1;
|
else if(!cheat && debuggerselect != 1)
|
||||||
else if(!cheat && debuggerselect != 1)
|
hooktype = 0;
|
||||||
hooktype = 0;
|
if(cheat)
|
||||||
|
_loadFile(cheatFile, cheatSize, m_cheatDir.c_str(), fmt("%s.gct", id.c_str()));
|
||||||
|
|
||||||
if(cheat)
|
if(has_enabled_providers() && _initNetwork() == 0)
|
||||||
_loadFile(cheatFile, cheatSize, m_cheatDir.c_str(), fmt("%s.gct", id.c_str()));
|
add_game_to_card(id.c_str());
|
||||||
if(has_enabled_providers() && _initNetwork() == 0)
|
|
||||||
add_game_to_card(id.c_str());
|
|
||||||
}
|
|
||||||
m_gcfg1.setInt("PLAYCOUNT", id, m_gcfg1.getInt("PLAYCOUNT", id, 0) + 1);
|
|
||||||
m_gcfg1.setUInt("LASTPLAYED", id, time(NULL));
|
|
||||||
|
|
||||||
|
int userIOS = m_gcfg2.getInt(id, "ios", 0);
|
||||||
|
u32 gameIOS = ChannelHandle.GetRequestedIOS(gameTitle);
|
||||||
|
|
||||||
//interesting - there is only a global option for nand emulation - no per game choice
|
//interesting - there is only a global option for nand emulation - no per game choice
|
||||||
int emulate_mode = min(max(0, m_cfg.getInt(CHANNEL_DOMAIN, "emulation", 1)), (int)ARRAY_SIZE(CMenu::_NandEmu) - 1);
|
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);//if not in neek2o and use neek is set
|
bool useNK2o = m_gcfg2.getBool(id, "useneek", false);//if not in neek2o and use neek is set
|
||||||
bool use_led = m_gcfg2.getBool(id, "led", false);
|
|
||||||
u32 gameIOS = ChannelHandle.GetRequestedIOS(gameTitle);
|
|
||||||
|
|
||||||
if(NANDemuView)
|
if(NANDemuView)
|
||||||
{
|
{
|
||||||
@ -871,11 +887,13 @@ void CMenu::_launchChannel(dir_discHdr *hdr)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(WII_Launch == false && ExternalBooter_LoadBins(m_binsDir.c_str()) == false)
|
|
||||||
|
if(ExternalBooter_LoadBins(m_binsDir.c_str()) == false)
|
||||||
{
|
{
|
||||||
error(_t("errgame15", L"Missing ext_loader.bin or ext_booter.bin!"));
|
error(_t("errgame15", L"Missing ext_loader.bin or ext_booter.bin!"));
|
||||||
_exitWiiflow();
|
_exitWiiflow();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(_loadGameIOS(gameIOS, userIOS, id, !NANDemuView) == LOAD_IOS_FAILED)
|
if(_loadGameIOS(gameIOS, userIOS, id, !NANDemuView) == LOAD_IOS_FAILED)
|
||||||
{
|
{
|
||||||
/* error message already shown */
|
/* error message already shown */
|
||||||
@ -885,8 +903,9 @@ void CMenu::_launchChannel(dir_discHdr *hdr)
|
|||||||
if(CurrentIOS.Type == IOS_TYPE_D2X && returnTo != 0)
|
if(CurrentIOS.Type == IOS_TYPE_D2X && returnTo != 0)
|
||||||
{
|
{
|
||||||
if(D2X_PatchReturnTo(returnTo) >= 0)
|
if(D2X_PatchReturnTo(returnTo) >= 0)
|
||||||
memset(&returnTo, 0, sizeof(u32));// not needed - always set to 0 in external booter below
|
memset(&returnTo, 0, sizeof(u32));//Already patched - no need for giantpune patch in external booter
|
||||||
}
|
}
|
||||||
|
|
||||||
if(NANDemuView)
|
if(NANDemuView)
|
||||||
{
|
{
|
||||||
/* Enable our Emu NAND */
|
/* Enable our Emu NAND */
|
||||||
@ -912,26 +931,18 @@ void CMenu::_launchChannel(dir_discHdr *hdr)
|
|||||||
mask32(0xd8006a8, 0, 2);
|
mask32(0xd8006a8, 0, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(WII_Launch)
|
setLanguage(language);// set configbyte[0] for external booter
|
||||||
{
|
ocarina_load_code(cheatFile, cheatSize);// copy to address used by external booter
|
||||||
ShutdownBeforeExit();
|
if(cheatFile != NULL)
|
||||||
WII_Initialize();
|
MEM2_free(cheatFile);
|
||||||
WII_LaunchTitle(gameTitle);
|
NandHandle.Patch_AHB(); /* Identify maybe uses it so keep AHBPROT disabled */
|
||||||
}
|
PatchIOS(true, isWiiVC); /* Patch cIOS for everything */
|
||||||
else
|
Identify(gameTitle);// identify title with E-Ticket Service (ES) module
|
||||||
{
|
|
||||||
setLanguage(language);
|
ExternalBooter_ChannelSetup(gameTitle, use_dol);
|
||||||
ocarina_load_code(cheatFile, cheatSize);
|
WiiFlow_ExternalBooter(videoMode, vipatch, countryPatch, patchVidMode, aspectRatio, private_server, server_addr.c_str(),
|
||||||
if(cheatFile != NULL)
|
fix480p, deflicker, 0, TYPE_CHANNEL, use_led);
|
||||||
MEM2_free(cheatFile);
|
|
||||||
NandHandle.Patch_AHB(); /* Identify maybe uses it so keep AHBPROT disabled */
|
|
||||||
PatchIOS(true, isWiiVC); /* Patch for everything */
|
|
||||||
Identify(gameTitle);
|
|
||||||
|
|
||||||
ExternalBooter_ChannelSetup(gameTitle, use_dol);
|
|
||||||
WiiFlow_ExternalBooter(videoMode, vipatch, countryPatch, patchVidMode, aspectRatio, private_server, server_addr.c_str(),
|
|
||||||
fix480p, deflicker, 0, TYPE_CHANNEL, use_led);
|
|
||||||
}
|
|
||||||
Sys_Exit();
|
Sys_Exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1101,7 +1112,7 @@ void CMenu::_launchWii(dir_discHdr *hdr, bool dvd, bool disc_cfg)
|
|||||||
bool use_led = m_gcfg2.getBool(id, "led", false);
|
bool use_led = m_gcfg2.getBool(id, "led", false);
|
||||||
bool cheat = m_gcfg2.getBool(id, "cheat", false);
|
bool cheat = m_gcfg2.getBool(id, "cheat", false);
|
||||||
debuggerselect = m_gcfg2.getInt(id, "debugger", 0); // debuggerselect is defined in fst.h
|
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
|
if((id == "RPWE41" || id == "RPWZ41" || id == "SPXP41") && debuggerselect == 1) // Prince of Persia: Rival Swords
|
||||||
debuggerselect = 0;
|
debuggerselect = 0;
|
||||||
hooktype = (u32)m_gcfg2.getInt(id, "hooktype", 0); // hooktype is defined in patchcode.h
|
hooktype = (u32)m_gcfg2.getInt(id, "hooktype", 0); // hooktype is defined in patchcode.h
|
||||||
if((cheat || debuggerselect == 1) && hooktype == 0)
|
if((cheat || debuggerselect == 1) && hooktype == 0)
|
||||||
@ -1160,7 +1171,7 @@ void CMenu::_launchWii(dir_discHdr *hdr, bool dvd, bool disc_cfg)
|
|||||||
if(CurrentIOS.Type == IOS_TYPE_D2X)
|
if(CurrentIOS.Type == IOS_TYPE_D2X)
|
||||||
{
|
{
|
||||||
if(returnTo != 0 && !m_directLaunch && D2X_PatchReturnTo(returnTo) >= 0)
|
if(returnTo != 0 && !m_directLaunch && D2X_PatchReturnTo(returnTo) >= 0)
|
||||||
memset(&returnTo, 0, sizeof(u32));//set to null to keep external booter from setting it again if using d2x
|
memset(&returnTo, 0, sizeof(u32));//Already patched - no need for giantpune patch in external booter
|
||||||
if(emulate_mode)
|
if(emulate_mode)
|
||||||
{
|
{
|
||||||
/* Enable our Emu NAND */
|
/* Enable our Emu NAND */
|
||||||
@ -1186,9 +1197,11 @@ void CMenu::_launchWii(dir_discHdr *hdr, bool dvd, bool disc_cfg)
|
|||||||
if(!dvd)
|
if(!dvd)
|
||||||
{
|
{
|
||||||
DeviceHandle.OpenWBFS(currentPartition);
|
DeviceHandle.OpenWBFS(currentPartition);
|
||||||
wbfs_partition = (DeviceHandle.GetFSType(currentPartition) == PART_FS_WBFS);
|
wbfs_partition = (DeviceHandle.GetFSType(currentPartition) == PART_FS_WBFS);// if USB device formatted to WBFS
|
||||||
|
/* if not WBFS formatted get fragmented list. */
|
||||||
|
/* if SD card (currentPartition == 0) set sector size to 512 (0x200) */
|
||||||
if(!wbfs_partition && get_frag_list((u8 *)id.c_str(), (char*)path.c_str(), currentPartition == 0 ? 0x200 : USBStorage2_GetSectorSize()) < 0)
|
if(!wbfs_partition && get_frag_list((u8 *)id.c_str(), (char*)path.c_str(), currentPartition == 0 ? 0x200 : USBStorage2_GetSectorSize()) < 0)
|
||||||
Sys_Exit();
|
Sys_Exit();// failed to get frag list
|
||||||
WBFS_Close();
|
WBFS_Close();
|
||||||
}
|
}
|
||||||
if(cheatFile != NULL)
|
if(cheatFile != NULL)
|
||||||
|
Loading…
Reference in New Issue
Block a user