- 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:
Fledge68 2021-11-29 11:36:30 -06:00
parent a45cc4cbdf
commit 9f7da43da4
13 changed files with 332 additions and 275 deletions

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.4 MiB

After

Width:  |  Height:  |  Size: 4.4 MiB

View File

@ -42,11 +42,13 @@
#include "videopatch.h"
#include "video_tinyload.h"
#include "apploader.h"
#include "memory.h"
void *dolchunkoffset[18];
u32 dolchunksize[18];
u32 dolchunkcount;
u32 bootcontent;
bool isForwarder = false;
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)
{
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));
u32 size;
u8 *data = ISFS_GetFile(filepath, &size, -1);
if(data == NULL || size < 0x208)
return ret;
return found;
*IOS = data[0x18B];
_tmd *tmd_file = (_tmd *)SIGNATURE_PAYLOAD((u32 *)data);
for(u16 i = 0; i < tmd_file->num_contents; ++i)
if(dol)
{
// 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)
{
if(tmd_file->contents[i].index == (dol ? 0x01 : tmd_file->boot_index))
{
*bootcontent = tmd_file->contents[i].cid;
ret = true;
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);
return ret;
return found;
}
static u32 MoveDol(u8 *buffer)
@ -108,10 +151,10 @@ static u32 MoveDol(u8 *buffer)
dolchunkcount = 0;
dolheader *dolfile = (dolheader *)buffer;
if(dolfile->bss_start)
if(dolfile->bss_start)// if start is not zero
{
if(!(dolfile->bss_start & 0x80000000))
dolfile->bss_start |= 0x80000000;
if(!(dolfile->bss_start & 0x80000000))// if start isn't >=80000000
dolfile->bss_start |= 0x80000000;// set it to 80000000 or greater
memset((void *)dolfile->bss_start, 0, 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++)
{
if(!dolfile->section_size[i])
if(!dolfile->section_size[i])// if section size is zero don't move
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;
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;
dolchunkoffset[dolchunkcount] = (void *)dolfile->section_start[i];
@ -146,11 +189,24 @@ u32 LoadChannel(u64 title, bool dol, u32 *IOS)
entry = MoveDol(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;
}
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_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]);
if(aspectRatio != -1)
PatchAspectRatio(dolchunkoffset[i], dolchunksize[i], aspectRatio);
if(returnTo)
PatchReturnTo(dolchunkoffset[i], dolchunksize[i], returnTo);
if(private_server)
PrivateServerPatcher(dolchunkoffset[i], dolchunksize[i], private_server, server_addr);
if(hooktype != 0 && hookpatched == false)
@ -207,4 +265,7 @@ void PatchChannel(u8 vidMode, GXRModeObj *vmode, bool vipatch, bool countryStrin
if(patchFix480p)
PatchFix480p();
if(private_server == PRIVSERV_WIIMMFI)
do_new_wiimmfi_nonMKWii();
}

View File

@ -13,8 +13,10 @@ typedef struct _dolheader
u32 padding[7];
} ATTRIBUTE_PACKED dolheader;
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);
void PatchChannel(u8 vidMode, GXRModeObj *vmode, bool vipatch, bool countryString, u8 patchVidModes, int aspectRatio,
u32 returnTo, u8 private_server, const char *server_addr, bool patchFix480p, u8 deflicker, u8 bootType);
u32 LoadChannel(u64 title, bool dol, u32 *IOS);
extern bool isForwarder;
#endif /* __CHANHANDLE_HPP_ */

View File

@ -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)
{
//! 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)
{
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();
NewSuperMarioBrosPatch();
@ -118,21 +120,35 @@ u32 Apploader_Run(u8 vidMode, GXRModeObj *vmode, bool vipatch, bool countryStrin
if(hooktype != 0 && hookpatched)
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();
//! 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.
//! This will also patch error 23400 for a couple games that still have official servers.
if(private_server != PRIVSERV_WIIMMFI)
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.
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.
do_new_wiimmfi();
do_new_wiimmfi();// includes patching the server address
}
/* Set entry point from apploader */

View File

@ -18,7 +18,7 @@
s32 Disc_Open(u8 type)
{
if(type > 0)
if(type > 0)// if not a wii disc (wbfs ext or wbfs drive)
{ /* Reset drive */
s32 ret = WDVD_Reset();
if(ret < 0)
@ -29,23 +29,7 @@ s32 Disc_Open(u8 type)
return WDVD_ReadDiskId((u8*)Disc_ID);
}
void Disc_SetLowMemPre()
{
/* 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)
void Disc_SetLowMem(void)
{
/* Setup low memory */
*Sys_Magic = 0x0D15EA5E; // Standard Boot Code
@ -58,35 +42,10 @@ void Disc_SetLowMem(u32 IOS)
*Dev_Debugger = 0x81800000; // Dev Debugger Monitor Address
*Simulated_Mem = 0x01800000; // Simulated Memory Size
*GameID_Address = 0x80000000; // Fix for Sam & Max (WiiPower)
*(vu32 *) 0xCD00643C = 0x00000000; // 32Mhz on Bus
/* Copy Disc ID */
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 */

View File

@ -9,9 +9,7 @@ extern "C" {
s32 Disc_Open(u8 type);
s32 Disc_FindPartition(u32 *outbuf);
s32 Disc_SetUSB(const u8 *id, bool frag);
void Disc_SetLowMemPre();
void Disc_SetLowMem(u32 IOS);
void Disc_SetLowMemChan();
void Disc_SetLowMem();
GXRModeObj *Disc_SelectVMode(u8 videoselected, u32 *rmode_reg);
void Disc_SetVMode(GXRModeObj *rmode, u32 rmode_reg);

View File

@ -144,6 +144,7 @@ void app_pokevalues()
void load_handler()
{
memset((void*)0x80001800, 0, 0x1800);
if(debuggerselect == 0x01)
{
gprintf("Ocarina: Debugger selected.\n");

View File

@ -56,12 +56,12 @@ int main()
InitGecko();
gprintf("WiiFlow External Booter by FIX94\n");
memcpy(&normalCFG, ((void*)*EXT_ADDR_CFG), sizeof(the_CFG));
VIDEO_Init();
video_init();
VIDEO_Init();// libogc
video_init();// tinyload progress bar
prog10();
configbytes[0] = normalCFG.configbytes[0];
configbytes[1] = normalCFG.configbytes[1];
configbytes[0] = normalCFG.configbytes[0];// game language 0 - 9 or 0xCD = not patched
configbytes[1] = normalCFG.configbytes[1];// not used
hooktype = normalCFG.hooktype;
debuggerselect = normalCFG.debugger;
CurrentIOS = normalCFG.IOS;
@ -73,9 +73,6 @@ int main()
wbfs_part_idx = normalCFG.wbfsPart;
prog10();
/* Setup Low Memory */
Disc_SetLowMemPre();
if(normalCFG.BootType == TYPE_WII_GAME)
{
WDVD_Init();
@ -103,6 +100,7 @@ int main()
u32 offset = 0;
Disc_FindPartition(&offset);
WDVD_OpenPartition(offset, &GameIOS);
Disc_SetLowMem();
if(normalCFG.vidMode == 5)
normalCFG.patchVidMode = 1; //progressive mode requires this
vmode = Disc_SelectVMode(normalCFG.vidMode, &vmode_reg);
@ -112,21 +110,23 @@ int main()
}
else if(normalCFG.BootType == TYPE_CHANNEL)
{
ISFS_Initialize();
*Disc_ID = TITLE_LOWER(normalCFG.title);
vmode = Disc_SelectVMode(normalCFG.vidMode, &vmode_reg);
ISFS_Initialize();
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();
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);
setprog(320);
/* Setup Low Memory */
Disc_SetLowMem(GameIOS);
if(normalCFG.BootType == TYPE_CHANNEL && AppEntrypoint != 0x3400)
Disc_SetLowMemChan(); /* Real DOL without appldr */
/* Error 002 Fix (thanks WiiPower and uLoader) */
*Current_IOS = (GameIOS << 16) | 0xffff;
if(!isForwarder)
*Apploader_IOS = (GameIOS << 16) | 0xffff;
/* Flush everything */
DCFlushRange((void*)0x80000000, 0x3f00);
/* Enable front LED if requested */
if(normalCFG.use_led) *HW_GPIOB_OUT |= 0x20;

View File

@ -357,138 +357,146 @@ 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 u8 found = 0; //to find in the dol are found in different sections of the dol
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 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;
//gprintf("PatchReturnTo( %p, %08x, %08x )\n", Address, Size, id );
//new __OSLoadMenu() (SM2.0 and higher)
u8 SearchPattern[ 12 ] = { 0x38, 0x80, 0x00, 0x02, 0x38, 0x60, 0x00, 0x01, 0x38, 0xa0, 0x00, 0x00 }; //li r4,2
//li r3,1
//li r5,0
//old _OSLoadMenu() (used in launch games)
u8 SearchPatternB[ 12 ] = { 0x38, 0xC0, 0x00, 0x02, 0x38, 0xA0, 0x00, 0x01, 0x38, 0xE0, 0x00, 0x00 }; //li r6,2
//li r5,1
//li r7,0
//identifier for the safe place
u8 SearchPattern2[ 12 ] = { 0x4D, 0x65, 0x74, 0x72, 0x6F, 0x77, 0x65, 0x72, 0x6B, 0x73, 0x20, 0x54 }; //"Metrowerks T"
// new __OSLoadMenu() (SM2.0 and higher)
u8 SearchPattern[12] = {0x38, 0x80, 0x00, 0x02, 0x38, 0x60, 0x00, 0x01, 0x38, 0xa0, 0x00, 0x00}; // li r4,2
// li r3,1
// li r5,0
// old _OSLoadMenu() (used in launch games)
u8 SearchPatternB[12] = {0x38, 0xC0, 0x00, 0x02, 0x38, 0xA0, 0x00, 0x01, 0x38, 0xE0, 0x00, 0x00}; // li r6,2
// li r5,1
// li r7,0
// identifier for the safe place
u8 SearchPattern2[12] = {0x4D, 0x65, 0x74, 0x72, 0x6F, 0x77, 0x65, 0x72, 0x6B, 0x73, 0x20, 0x54}; // "Metrowerks T"
u8 oldSDK = 0;
found = 0;
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
if ( ! ad[ 3 ] && memcmp( Addr, SearchPattern2, 12 ) == 0 )
// find a safe place for the patch to hang out
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
else if ( memcmp( Addr, SearchPattern, 12 )==0 )
// find __OSLaunchMenu() and remember some addresses in it
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;
else if( !ad[ 2 ] ) ad[ found++ ] = (u32)Addr;
if( found >= 3 )break;
if(!ad[1])
ad[found++] = (u32)Addr;
else if(!ad[2])
ad[found++] = (u32)Addr;
if(found >= 3)
break;
}
Addr += 4;
}
//check for the older-ass version of the SDK
if( found < 3 && ad[ 3 ] )
// check for the older-ass version of the SDK
if(found < 3 && ad[3])
{
Addr = Address;
ad[ 0 ] = 0;
ad[ 1 ] = 0;
ad[ 2 ] = 0;
ad[0] = 0;
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
if ( memcmp( Addr, SearchPatternB, 12 )==0 )
// find __OSLaunchMenu() and remember some addresses in it
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;
else if( !ad[ 2 ] ) ad[ found++ ] = (u32)Addr;
if( found >= 3 )break;
if(!ad[1])
ad[found++] = (u32)Addr;
else if(!ad[2])
ad[found++] = (u32)Addr;
if(found >= 3)
break;
}
Addr += 4;
}
}
//if the function is found
if( found == 3 && ad[ 3 ] )
// if the function is found
if(found == 3 && ad[3])
{
gprintf("patch __OSLaunchMenu( 0x00010001, 0x%08x )\n", id);
//gprintf("patch __OSLaunchMenu( 0x00010001, 0x%08x )\n", id);
u32 nop = 0x60000000;
//the magic that writes the TID to the registers
u8 jump[ 20 ] = { 0x3C, 0x60, 0x00, 0x01, //lis r3,1
0x60, 0x63, 0x00, 0x01, //ori r3,r3,1
0x3C, 0x80, (u8)( id >> 24 ), (u8)( id >> 16 ), //lis r4,(u16)(tid >> 16)
0x60, 0x84, (u8)( id >> 8 ), (u8)id, //ori r4,r4,(u16)(tid)
0x4E, 0x80, 0x00, 0x20
}; //blr
// the magic that writes the TID to the registers
u8 jump[20] = {
0x3C, 0x60, 0x00, 0x01, // lis r3,1
0x60, 0x63, 0x00, 0x01, // ori r3,r3,1
0x3C, 0x80, (u8)(id >> 24), (u8)(id >> 16), // lis r4,(u16)(tid >> 16)
0x60, 0x84, (u8)(id >> 8), (u8)id, // ori r4,r4,(u16)(tid)
0x4E, 0x80, 0x00, 0x20}; // blr
if( oldSDK )
if(oldSDK)
{
jump[ 1 ] = 0xA0; //3CA00001 //lis r5,1
jump[ 5 ] = 0xA5; //60A50001 //ori r5,r5,1
jump[ 9 ] = 0xC0; //3CC0AF1B //lis r6,(u16)(tid >> 16)
jump[ 13 ] = 0xC6;//60C6F516 //ori r6,r6,(u16)(tid)
jump[1] = 0xA0; // 3CA00001 // lis r5,1
jump[5] = 0xA5; // 60A50001 // ori r5,r5,1
jump[9] = 0xC0; // 3CC0AF1B // lis r6,(u16)(tid >> 16)
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
memcpy( addr, jump, sizeof( jump ) );
// write new stuff to in a unused part of the main.dol
memcpy(addr, jump, sizeof(jump));
//ES_GetTicketViews()
u32 newval = ( ad[ 3 ] - ad[ 0 ] );
// ES_GetTicketViews()
u32 newval = (ad[3] - ad[0]);
newval &= 0x03FFFFFC;
newval |= 0x48000001;
addr = (u32*)ad[ 0 ];
memcpy( addr, &newval, sizeof( u32 ) ); //bl ad[ 3 ]
memcpy( addr + 4, &nop, sizeof( u32 ) ); //nop
addr = (u32 *)ad[0];
memcpy(addr, &newval, sizeof(u32)); // bl ad[ 3 ]
memcpy(addr + 4, &nop, sizeof(u32)); // nop
//gprintf("\t%08x -> %08x\n", addr, newval );
//ES_GetTicketViews() again
newval = ( ad[ 3 ] - ad[ 1 ] );
// ES_GetTicketViews() again
newval = (ad[3] - ad[1]);
newval &= 0x03FFFFFC;
newval |= 0x48000001;
addr = (u32*)ad[ 1 ];
memcpy( addr, &newval, sizeof( u32 ) ); //bl ad[ 3 ]
memcpy( addr + 4, &nop, sizeof( u32 ) ); //nop
addr = (u32 *)ad[1];
memcpy(addr, &newval, sizeof(u32)); // bl ad[ 3 ]
memcpy(addr + 4, &nop, sizeof(u32)); // nop
//gprintf("\t%08x -> %08x\n", addr, newval );
//ES_LaunchTitle()
newval = ( ad[ 3 ] - ad[ 2 ] );
// ES_LaunchTitle()
newval = (ad[3] - ad[2]);
newval &= 0x03FFFFFC;
newval |= 0x48000001;
addr = (u32*)ad[ 2 ];
memcpy( addr, &newval, sizeof( u32 ) ); //bl ad[ 3 ]
memcpy( addr + 4, &nop, sizeof( u32 ) ); //nop
addr = (u32 *)ad[2];
memcpy(addr, &newval, sizeof(u32)); // bl ad[ 3 ]
memcpy(addr + 4, &nop, sizeof(u32)); // nop
//gprintf("\t%08x -> %08x\n", addr, newval );
returnToPatched = 1;
}
if(returnToPatched)
gprintf("Return to %08X patched with old method.\n", (u32)id);
return returnToPatched;
}
@ -513,7 +521,7 @@ void PatchAspectRatio(void *addr, u32 len, u8 aspect)
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))
{
*((u32 *)(addr_start+0x44)) = (0x38600000 | aspect);

View File

@ -108,7 +108,7 @@ u64 *Channels::GetChannelList(u32 *count)
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;
u32 size = 0;
@ -128,10 +128,9 @@ bool Channels::GetAppNameFromTmd(u64 title, char *app, u32 *bootcontent)
return ret;
}
_tmd *tmd_file = (_tmd *)SIGNATURE_PAYLOAD((u32 *)data);
u16 i;
for(i = 0; i < tmd_file->num_contents; ++i)
for(u32 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;
snprintf(app, ISFS_MAXPATH, "/title/%08x/%08x/content/%08x.app", TITLE_UPPER(title), TITLE_LOWER(title), *bootcontent);

View File

@ -1,6 +1,6 @@
#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 APPS_DIR "apps/wiiflow"

View File

@ -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)
{
/* 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)
_initAsyncNetwork();// needed after IOS change
if(ret == false)
@ -740,7 +740,7 @@ int CMenu::_loadGameIOS(u8 gameIOS, int userIOS, string id, bool RealNAND_Channe
if(gameIOS != CurrentIOS.Version)
{
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)
_initAsyncNetwork();// always seem to do netinit after changing IOS
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)
{
NANDemuView = hdr->type == TYPE_EMUCHANNEL;
/* clear coverflow, start wiiflow wait animation, set exit handler */
_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);
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 */
bool use_dol = !m_gcfg2.getBool(id, "apploader", false);
bool use_led = m_gcfg2.getBool(id, "led", false);
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;
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);
language = (language == 0) ? min(m_cfg.getUInt("GENERAL", "game_language", 0), ARRAY_SIZE(CMenu::_languages) - 1u) : language;
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
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);
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);
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;
const char *rtrn = m_cfg.getString("GENERAL", "returnto").c_str();
if(strlen(rtrn) == 4)
@ -803,31 +824,26 @@ void CMenu::_launchChannel(dir_discHdr *hdr)
u8 *cheatFile = NULL;
u32 cheatSize = 0;
if(!WII_Launch)
{
bool cheat = m_gcfg2.getBool(id, "cheat", false);
hooktype = (u32) m_gcfg2.getInt(id, "hooktype", 0);
debuggerselect = m_gcfg2.getInt(id, "debugger", 0);
if((cheat || debuggerselect == 1) && hooktype == 0)
hooktype = 1;
else if(!cheat && debuggerselect != 1)
hooktype = 0;
if(cheat)
_loadFile(cheatFile, cheatSize, m_cheatDir.c_str(), fmt("%s.gct", id.c_str()));
if(has_enabled_providers() && _initNetwork() == 0)
add_game_to_card(id.c_str());
}
m_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
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 use_led = m_gcfg2.getBool(id, "led", false);
u32 gameIOS = ChannelHandle.GetRequestedIOS(gameTitle);
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!"));
_exitWiiflow();
}
if(_loadGameIOS(gameIOS, userIOS, id, !NANDemuView) == LOAD_IOS_FAILED)
{
/* error message already shown */
@ -885,8 +903,9 @@ void CMenu::_launchChannel(dir_discHdr *hdr)
if(CurrentIOS.Type == IOS_TYPE_D2X && 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)
{
/* Enable our Emu NAND */
@ -912,26 +931,18 @@ void CMenu::_launchChannel(dir_discHdr *hdr)
mask32(0xd8006a8, 0, 2);
}
if(WII_Launch)
{
ShutdownBeforeExit();
WII_Initialize();
WII_LaunchTitle(gameTitle);
}
else
{
setLanguage(language);
ocarina_load_code(cheatFile, cheatSize);
setLanguage(language);// set configbyte[0] for external booter
ocarina_load_code(cheatFile, cheatSize);// copy to address used by external booter
if(cheatFile != NULL)
MEM2_free(cheatFile);
NandHandle.Patch_AHB(); /* Identify maybe uses it so keep AHBPROT disabled */
PatchIOS(true, isWiiVC); /* Patch for everything */
Identify(gameTitle);
PatchIOS(true, isWiiVC); /* Patch cIOS for everything */
Identify(gameTitle);// identify title with E-Ticket Service (ES) module
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();
}
@ -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 cheat = m_gcfg2.getBool(id, "cheat", false);
debuggerselect = m_gcfg2.getInt(id, "debugger", 0); // debuggerselect is defined in fst.h
if((id == "RPWE41" || id == "RPWZ41" || id == "SPXP41") && debuggerselect == 1) // Prince of Persia, Rival Swords
if((id == "RPWE41" || id == "RPWZ41" || id == "SPXP41") && debuggerselect == 1) // Prince of Persia: Rival Swords
debuggerselect = 0;
hooktype = (u32)m_gcfg2.getInt(id, "hooktype", 0); // hooktype is defined in patchcode.h
if((cheat || debuggerselect == 1) && hooktype == 0)
@ -1160,7 +1171,7 @@ void CMenu::_launchWii(dir_discHdr *hdr, bool dvd, bool disc_cfg)
if(CurrentIOS.Type == IOS_TYPE_D2X)
{
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)
{
/* Enable our Emu NAND */
@ -1186,9 +1197,11 @@ void CMenu::_launchWii(dir_discHdr *hdr, bool dvd, bool disc_cfg)
if(!dvd)
{
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)
Sys_Exit();
Sys_Exit();// failed to get frag list
WBFS_Close();
}
if(cheatFile != NULL)