mirror of
https://github.com/wiidev/usbloadergx.git
synced 2024-11-18 09:19:17 +01:00
Refactored various game patches
This commit is contained in:
parent
2ee86d1281
commit
564ea6a534
@ -1,19 +0,0 @@
|
|||||||
#include <string.h>
|
|
||||||
#include <gctypes.h>
|
|
||||||
|
|
||||||
bool PatchDOL(u8 * Address, int Size, const u8 * SearchPattern, int SearchSize, const u8 * PatchData, int PatchSize)
|
|
||||||
{
|
|
||||||
u8 * Addr = Address;
|
|
||||||
u8 * Addr_end = Address + Size;
|
|
||||||
|
|
||||||
while (Addr <= Addr_end - SearchSize)
|
|
||||||
{
|
|
||||||
if (memcmp(Addr, SearchPattern, SearchSize) == 0)
|
|
||||||
{
|
|
||||||
memcpy(Addr, PatchData, PatchSize);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
Addr += 4;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
@ -1,8 +0,0 @@
|
|||||||
#ifndef DOLPATCHER_C_
|
|
||||||
#define DOLPATCHER_C_
|
|
||||||
|
|
||||||
#include <gctypes.h>
|
|
||||||
|
|
||||||
bool PatchDOL(u8 * Address, int Size, const u8 * SearchPattern, int SearchSize, const u8 * PatchData, int PatchSize);
|
|
||||||
|
|
||||||
#endif
|
|
@ -2,8 +2,8 @@
|
|||||||
#include <gccore.h>
|
#include <gccore.h>
|
||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "usbloader/disc.h"
|
#include "usbloader/disc.h"
|
||||||
#include "dolpatcher.h"
|
|
||||||
#include "wip.h"
|
#include "wip.h"
|
||||||
#include "gecko.h"
|
#include "gecko.h"
|
||||||
#include "patchcode.h"
|
#include "patchcode.h"
|
||||||
@ -67,8 +67,8 @@ void gamepatches(u8 videoSelected, u8 videoPatchDol, u8 aspectForce, u8 language
|
|||||||
u8 vfilter_high[7] = {8, 8, 10, 12, 10, 8, 8};
|
u8 vfilter_high[7] = {8, 8, 10, 12, 10, 8, 8};
|
||||||
|
|
||||||
// If a wip file is loaded for this game this does nothing - Dimok
|
// If a wip file is loaded for this game this does nothing - Dimok
|
||||||
PoPPatch();
|
patch_nsmb((u8 *)0x80000000);
|
||||||
NSMBPatch();
|
patch_pop((u8 *)0x80000000);
|
||||||
|
|
||||||
for (i = 0; i < dolCount; ++i)
|
for (i = 0; i < dolCount; ++i)
|
||||||
{
|
{
|
||||||
@ -77,6 +77,7 @@ void gamepatches(u8 videoSelected, u8 videoPatchDol, u8 aspectForce, u8 language
|
|||||||
|
|
||||||
VideoModePatcher(dst, len, videoSelected, videoPatchDol);
|
VideoModePatcher(dst, len, videoSelected, videoPatchDol);
|
||||||
|
|
||||||
|
if (hooktype)
|
||||||
dogamehooks(hooktype, dst, len);
|
dogamehooks(hooktype, dst, len);
|
||||||
|
|
||||||
if (vipatch)
|
if (vipatch)
|
||||||
@ -99,22 +100,22 @@ void gamepatches(u8 videoSelected, u8 videoPatchDol, u8 aspectForce, u8 language
|
|||||||
if (deflicker == DEFLICKER_ON_LOW)
|
if (deflicker == DEFLICKER_ON_LOW)
|
||||||
{
|
{
|
||||||
patch_vfilters(dst, len, vfilter_low);
|
patch_vfilters(dst, len, vfilter_low);
|
||||||
patch_vfilters_rouge(dst, len, vfilter_low);
|
patch_vfilters_rogue(dst, len, vfilter_low);
|
||||||
}
|
}
|
||||||
else if (deflicker == DEFLICKER_ON_MEDIUM)
|
else if (deflicker == DEFLICKER_ON_MEDIUM)
|
||||||
{
|
{
|
||||||
patch_vfilters(dst, len, vfilter_medium);
|
patch_vfilters(dst, len, vfilter_medium);
|
||||||
patch_vfilters_rouge(dst, len, vfilter_medium);
|
patch_vfilters_rogue(dst, len, vfilter_medium);
|
||||||
}
|
}
|
||||||
else if (deflicker == DEFLICKER_ON_HIGH)
|
else if (deflicker == DEFLICKER_ON_HIGH)
|
||||||
{
|
{
|
||||||
patch_vfilters(dst, len, vfilter_high);
|
patch_vfilters(dst, len, vfilter_high);
|
||||||
patch_vfilters_rouge(dst, len, vfilter_high);
|
patch_vfilters_rogue(dst, len, vfilter_high);
|
||||||
}
|
}
|
||||||
else if (deflicker != DEFLICKER_AUTO)
|
else if (deflicker != DEFLICKER_AUTO)
|
||||||
{
|
{
|
||||||
patch_vfilters(dst, len, vfilter_off);
|
patch_vfilters(dst, len, vfilter_off);
|
||||||
patch_vfilters_rouge(dst, len, vfilter_off);
|
patch_vfilters_rogue(dst, len, vfilter_off);
|
||||||
// This might break fade and brightness effects
|
// This might break fade and brightness effects
|
||||||
if (deflicker == DEFLICKER_OFF_EXTENDED)
|
if (deflicker == DEFLICKER_OFF_EXTENDED)
|
||||||
deflicker_patch(dst, len);
|
deflicker_patch(dst, len);
|
||||||
@ -154,8 +155,8 @@ void anti_002_fix(u8 *addr, u32 len)
|
|||||||
{
|
{
|
||||||
u32 SearchPattern[3] = {0x2C000000, 0x48000214, 0x3C608000};
|
u32 SearchPattern[3] = {0x2C000000, 0x48000214, 0x3C608000};
|
||||||
u8 *addr_start = addr;
|
u8 *addr_start = addr;
|
||||||
u8 *addr_end = addr + len;
|
u8 *addr_end = addr + len - sizeof(SearchPattern);
|
||||||
while (addr_start <= addr_end - sizeof(SearchPattern))
|
while (addr_start <= addr_end)
|
||||||
{
|
{
|
||||||
if (memcmp(addr_start, SearchPattern, sizeof(SearchPattern)) == 0)
|
if (memcmp(addr_start, SearchPattern, sizeof(SearchPattern)) == 0)
|
||||||
{
|
{
|
||||||
@ -177,8 +178,8 @@ void deflicker_patch(u8 *addr, u32 len)
|
|||||||
0x90698000, 0x99498000, 0x90E98000,
|
0x90698000, 0x99498000, 0x90E98000,
|
||||||
0x99498000, 0x91098000, 0x41820040};
|
0x99498000, 0x91098000, 0x41820040};
|
||||||
u8 *addr_start = addr;
|
u8 *addr_start = addr;
|
||||||
u8 *addr_end = addr + len;
|
u8 *addr_end = addr + len - sizeof(SearchPattern);
|
||||||
while (addr_start <= addr_end - sizeof(SearchPattern))
|
while (addr_start <= addr_end)
|
||||||
{
|
{
|
||||||
if (memcmp(addr_start, SearchPattern, sizeof(SearchPattern)) == 0)
|
if (memcmp(addr_start, SearchPattern, sizeof(SearchPattern)) == 0)
|
||||||
{
|
{
|
||||||
@ -192,7 +193,7 @@ void deflicker_patch(u8 *addr, u32 len)
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
480p Pixel Fix Patch by leseratte
|
480p Pixel Fix Patch by leseratte
|
||||||
fix for a Nintendo Revolution SDK bug found by Extrems affecting early Wii console when using 480p video mode.
|
Fix for a Nintendo Revolution SDK bug found by Extrems affecting early Wii console when using 480p video mode.
|
||||||
https://shmups.system11.org/viewtopic.php?p=1361158#p1361158
|
https://shmups.system11.org/viewtopic.php?p=1361158#p1361158
|
||||||
https://github.com/ExtremsCorner/libogc-rice/commit/941d687e271fada68c359bbed98bed1fbb454448
|
https://github.com/ExtremsCorner/libogc-rice/commit/941d687e271fada68c359bbed98bed1fbb454448
|
||||||
**/
|
**/
|
||||||
@ -863,11 +864,11 @@ void domainpatcher(void *addr, u32 len, const char *domain)
|
|||||||
} while (++cur < end);
|
} while (++cur < end);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NSMBPatch()
|
bool patch_nsmb(u8 *gameid)
|
||||||
{
|
{
|
||||||
WIP_Code *CodeList = NULL;
|
WIP_Code *CodeList = NULL;
|
||||||
|
|
||||||
if (memcmp("SMNE01", (char *)0x80000000, 6) == 0)
|
if (memcmp(gameid, "SMNE01", 6) == 0)
|
||||||
{
|
{
|
||||||
CodeList = MEM2_alloc(3 * sizeof(WIP_Code));
|
CodeList = MEM2_alloc(3 * sizeof(WIP_Code));
|
||||||
if (!CodeList)
|
if (!CodeList)
|
||||||
@ -883,7 +884,7 @@ bool NSMBPatch()
|
|||||||
CodeList[2].srcaddress = 0xDA000000;
|
CodeList[2].srcaddress = 0xDA000000;
|
||||||
CodeList[2].dstaddress = 0x71000000;
|
CodeList[2].dstaddress = 0x71000000;
|
||||||
}
|
}
|
||||||
else if (memcmp("SMNP01", (char *)0x80000000, 6) == 0)
|
else if (memcmp(gameid, "SMNP01", 6) == 0)
|
||||||
{
|
{
|
||||||
CodeList = MEM2_alloc(3 * sizeof(WIP_Code));
|
CodeList = MEM2_alloc(3 * sizeof(WIP_Code));
|
||||||
if (!CodeList)
|
if (!CodeList)
|
||||||
@ -899,7 +900,7 @@ bool NSMBPatch()
|
|||||||
CodeList[2].srcaddress = 0x388000DA;
|
CodeList[2].srcaddress = 0x388000DA;
|
||||||
CodeList[2].dstaddress = 0x38800071;
|
CodeList[2].dstaddress = 0x38800071;
|
||||||
}
|
}
|
||||||
else if (memcmp("SMNJ01", (char *)0x80000000, 6) == 0)
|
else if (memcmp(gameid, "SMNJ01", 6) == 0)
|
||||||
{
|
{
|
||||||
CodeList = MEM2_alloc(3 * sizeof(WIP_Code));
|
CodeList = MEM2_alloc(3 * sizeof(WIP_Code));
|
||||||
if (!CodeList)
|
if (!CodeList)
|
||||||
@ -922,13 +923,14 @@ bool NSMBPatch()
|
|||||||
CodeList = NULL;
|
CodeList = NULL;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (CodeList)
|
||||||
|
gprintf("Patched New Super Mario Bros\n");
|
||||||
return CodeList != NULL;
|
return CodeList != NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PoPPatch()
|
bool patch_pop(u8 *gameid)
|
||||||
{
|
{
|
||||||
if (memcmp("SPX", (char *)0x80000000, 3) != 0 && memcmp("RPW", (char *)0x80000000, 3) != 0)
|
if (memcmp(gameid, "SPX", 3) != 0 && memcmp(gameid, "RPW", 3) != 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
WIP_Code *CodeList = MEM2_alloc(5 * sizeof(WIP_Code));
|
WIP_Code *CodeList = MEM2_alloc(5 * sizeof(WIP_Code));
|
||||||
@ -954,8 +956,82 @@ bool PoPPatch()
|
|||||||
CodeList = NULL;
|
CodeList = NULL;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (CodeList)
|
||||||
|
gprintf("Patched Prince of Persia\n");
|
||||||
|
return CodeList != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
void patch_error_codes(u8 *gameid)
|
||||||
|
{
|
||||||
|
// Thanks to Seeky for the MKWii gecko codes
|
||||||
|
// Thanks to InvoxiPlayGames for the gecko codes for the 23400 fix.
|
||||||
|
// Reimplemented by Leseratte without the need for a code handler.
|
||||||
|
u32 *patch_addr = 0;
|
||||||
|
u32 *patched = 0;
|
||||||
|
|
||||||
|
// Patch error 23400 for CoD (Black Ops, Reflex, MW3) and Rock Band 3 / The Beatles
|
||||||
|
if (memcmp(gameid, "SC7", 3) == 0)
|
||||||
|
{
|
||||||
|
gprintf("Patching error 23400 for %s\n", gameid);
|
||||||
|
*(u32 *)0x8023c954 = 0x41414141;
|
||||||
|
}
|
||||||
|
else if (memcmp(gameid, "RJA", 3) == 0)
|
||||||
|
{
|
||||||
|
gprintf("Patching error 23400 for %s\n", gameid);
|
||||||
|
*(u32 *)0x801b838c = 0x41414141;
|
||||||
|
}
|
||||||
|
else if (memcmp(gameid, "SM8", 3) == 0)
|
||||||
|
{
|
||||||
|
gprintf("Patching error 23400 for %s\n", gameid);
|
||||||
|
*(u32 *)0x80238c74 = 0x41414141;
|
||||||
|
}
|
||||||
|
else if (memcmp(gameid, "SZB", 3) == 0)
|
||||||
|
{
|
||||||
|
gprintf("Patching error 23400 for %s\n", gameid);
|
||||||
|
*(u32 *)0x808e3b20 = 0x41414141;
|
||||||
|
}
|
||||||
|
else if (memcmp(gameid, "R9J", 3) == 0)
|
||||||
|
{
|
||||||
|
gprintf("Patching error 23400 for %s\n", gameid);
|
||||||
|
*(u32 *)0x808d6934 = 0x41414141;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Patch RCE vulnerability in MKWii.
|
||||||
|
else if (memcmp(gameid, "RMC", 3) == 0)
|
||||||
|
{
|
||||||
|
switch (gameid[3])
|
||||||
|
{
|
||||||
|
case 'P':
|
||||||
|
patched = (u32 *)0x80276054;
|
||||||
|
patch_addr = (u32 *)0x8089a194;
|
||||||
|
break;
|
||||||
|
case 'E':
|
||||||
|
patched = (u32 *)0x80271d14;
|
||||||
|
patch_addr = (u32 *)0x80895ac4;
|
||||||
|
break;
|
||||||
|
case 'J':
|
||||||
|
patched = (u32 *)0x802759f4;
|
||||||
|
patch_addr = (u32 *)0x808992f4;
|
||||||
|
break;
|
||||||
|
case 'K':
|
||||||
|
patched = (u32 *)0x80263E34;
|
||||||
|
patch_addr = (u32 *)0x808885cc;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
gprintf("NOT patching RCE vulnerability due to invalid game ID: %s\n", gameid);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*patched != '*')
|
||||||
|
gprintf("Game is already Wiimmfi-patched, don't apply the RCE fix\n");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
gprintf("Patching RCE vulnerability for %s\n", gameid);
|
||||||
|
|
||||||
|
for (int i = 0; i < 7; i++)
|
||||||
|
*patch_addr++ = 0xff;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Insert the individual gamepatches above with the patterns and patch data **/
|
/** Insert the individual gamepatches above with the patterns and patch data **/
|
||||||
@ -1269,9 +1345,10 @@ static void patch_videomode(GXRModeObj *mode1, GXRModeObj *mode2)
|
|||||||
mode1->viYOrigin = mode2->viYOrigin;
|
mode1->viYOrigin = mode2->viYOrigin;
|
||||||
mode1->viWidth = mode2->viWidth;
|
mode1->viWidth = mode2->viWidth;
|
||||||
mode1->viHeight = mode2->viHeight;
|
mode1->viHeight = mode2->viHeight;
|
||||||
} else {
|
|
||||||
gprintf("Skipped patching dimensions %d x %d\n", mode1->viWidth, mode1->viHeight);
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
gprintf("Skipped patching dimensions %d x %d\n", mode1->viWidth, mode1->viHeight);
|
||||||
|
|
||||||
mode1->xfbMode = mode2->xfbMode;
|
mode1->xfbMode = mode2->xfbMode;
|
||||||
mode1->field_rendering = mode2->field_rendering;
|
mode1->field_rendering = mode2->field_rendering;
|
||||||
mode1->aa = mode2->aa;
|
mode1->aa = mode2->aa;
|
||||||
@ -1358,9 +1435,10 @@ static bool Search_and_patch_Video_Modes(u8 *Address, u32 Size, GXRModeObj *Tabl
|
|||||||
// Patch known and unknown vfilters within GXRModeObj structures
|
// Patch known and unknown vfilters within GXRModeObj structures
|
||||||
void patch_vfilters(u8 *addr, u32 len, u8 *vfilter)
|
void patch_vfilters(u8 *addr, u32 len, u8 *vfilter)
|
||||||
{
|
{
|
||||||
|
u8 *addr_start = addr;
|
||||||
while (len >= sizeof(GXRModeObj))
|
while (len >= sizeof(GXRModeObj))
|
||||||
{
|
{
|
||||||
GXRModeObj *vidmode = (GXRModeObj *)addr;
|
GXRModeObj *vidmode = (GXRModeObj *)addr_start;
|
||||||
if ((memcmp(vidmode->sample_pattern, PATTERN, 24) == 0 || memcmp(vidmode->sample_pattern, PATTERN_AA, 24) == 0) &&
|
if ((memcmp(vidmode->sample_pattern, PATTERN, 24) == 0 || memcmp(vidmode->sample_pattern, PATTERN_AA, 24) == 0) &&
|
||||||
(vidmode->fbWidth == 640 || vidmode->fbWidth == 608 || vidmode->fbWidth == 512) &&
|
(vidmode->fbWidth == 640 || vidmode->fbWidth == 608 || vidmode->fbWidth == 512) &&
|
||||||
(vidmode->field_rendering == 0 || vidmode->field_rendering == 1) &&
|
(vidmode->field_rendering == 0 || vidmode->field_rendering == 1) &&
|
||||||
@ -1368,17 +1446,18 @@ void patch_vfilters(u8 *addr, u32 len, u8 *vfilter)
|
|||||||
{
|
{
|
||||||
gprintf("Replaced vfilter %02x%02x%02x%02x%02x%02x%02x @ %p (GXRModeObj)\n",
|
gprintf("Replaced vfilter %02x%02x%02x%02x%02x%02x%02x @ %p (GXRModeObj)\n",
|
||||||
vidmode->vfilter[0], vidmode->vfilter[1], vidmode->vfilter[2], vidmode->vfilter[3],
|
vidmode->vfilter[0], vidmode->vfilter[1], vidmode->vfilter[2], vidmode->vfilter[3],
|
||||||
vidmode->vfilter[4], vidmode->vfilter[5], vidmode->vfilter[6], addr);
|
vidmode->vfilter[4], vidmode->vfilter[5], vidmode->vfilter[6], addr_start);
|
||||||
memcpy(vidmode->vfilter, vfilter, 7);
|
memcpy(vidmode->vfilter, vfilter, 7);
|
||||||
addr += (sizeof(GXRModeObj) - 4);
|
addr_start += (sizeof(GXRModeObj) - 4);
|
||||||
len -= (sizeof(GXRModeObj) - 4);
|
len -= (sizeof(GXRModeObj) - 4);
|
||||||
}
|
}
|
||||||
addr += 4;
|
addr_start += 4;
|
||||||
len -= 4;
|
len -= 4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void patch_vfilters_rouge(u8 *addr, u32 len, u8 *vfilter)
|
// Patch rogue vfilters found in some games
|
||||||
|
void patch_vfilters_rogue(u8 *addr, u32 len, u8 *vfilter)
|
||||||
{
|
{
|
||||||
u8 known_vfilters[7][7] = {
|
u8 known_vfilters[7][7] = {
|
||||||
{8, 8, 10, 12, 10, 8, 8},
|
{8, 8, 10, 12, 10, 8, 8},
|
||||||
@ -1389,24 +1468,25 @@ void patch_vfilters_rouge(u8 *addr, u32 len, u8 *vfilter)
|
|||||||
{4, 4, 16, 16, 16, 4, 4},
|
{4, 4, 16, 16, 16, 4, 4},
|
||||||
{2, 2, 17, 22, 17, 2, 2}
|
{2, 2, 17, 22, 17, 2, 2}
|
||||||
};
|
};
|
||||||
|
u8 *addr_start = addr;
|
||||||
u8 *addr_end = addr + len - 8;
|
u8 *addr_end = addr + len - 8;
|
||||||
while (addr <= addr_end)
|
while (addr_start <= addr_end)
|
||||||
{
|
{
|
||||||
u8 known_vfilter[7];
|
u8 known_vfilter[7];
|
||||||
for (int i = 0; i < 7; i++)
|
for (int i = 0; i < 7; i++)
|
||||||
{
|
{
|
||||||
for (int x = 0; x < 7; x++)
|
for (int x = 0; x < 7; x++)
|
||||||
known_vfilter[x] = known_vfilters[i][x];
|
known_vfilter[x] = known_vfilters[i][x];
|
||||||
if (!addr[7] && memcmp(addr, known_vfilter, 7) == 0)
|
if (!addr_start[7] && memcmp(addr_start, known_vfilter, 7) == 0)
|
||||||
{
|
{
|
||||||
gprintf("Replaced vfilter %02x%02x%02x%02x%02x%02x%02x @ %p\n", addr[0], addr[1], addr[2],
|
gprintf("Replaced vfilter %02x%02x%02x%02x%02x%02x%02x @ %p\n", addr_start[0], addr_start[1],
|
||||||
addr[3], addr[4], addr[5], addr[6], addr);
|
addr_start[2], addr_start[3], addr_start[4], addr_start[5], addr_start[6], addr_start);
|
||||||
memcpy(addr, vfilter, 7);
|
memcpy(addr, vfilter, 7);
|
||||||
addr += 7;
|
addr_start += 7;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
addr += 1;
|
addr_start += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1711,7 +1791,7 @@ int PatchNewReturnTo(int es_fd, u64 title)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
int BlockIOSReload(int es_fd, u8 gameIOS)
|
int BlockIOSReload(int es_fd, u32 gameIOS)
|
||||||
{
|
{
|
||||||
if (es_fd < 0)
|
if (es_fd < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -14,19 +14,20 @@ void gamepatches(u8 videoSelected, u8 videoPatchDol, u8 aspectForce, u8 language
|
|||||||
void anti_002_fix(u8 *addr, u32 len);
|
void anti_002_fix(u8 *addr, u32 len);
|
||||||
void deflicker_patch(u8 *addr, u32 len);
|
void deflicker_patch(u8 *addr, u32 len);
|
||||||
void patch_vfilters(u8 *addr, u32 len, u8 *vfilter);
|
void patch_vfilters(u8 *addr, u32 len, u8 *vfilter);
|
||||||
void patch_vfilters_rouge(u8 *addr, u32 len, u8 *vfilter);
|
void patch_vfilters_rogue(u8 *addr, u32 len, u8 *vfilter);
|
||||||
void PrivateServerPatcher(void *addr, u32 len, u8 privateServer, const char *serverAddr);
|
void PrivateServerPatcher(void *addr, u32 len, u8 privateServer, const char *serverAddr);
|
||||||
void PatchFix480p();
|
void PatchFix480p();
|
||||||
s8 do_new_wiimmfi();
|
s8 do_new_wiimmfi();
|
||||||
s8 do_new_wiimmfi_nonMKWii(void *addr, u32 len);
|
s8 do_new_wiimmfi_nonMKWii(void *addr, u32 len);
|
||||||
void domainpatcher(void *addr, u32 len, const char *domain);
|
void domainpatcher(void *addr, u32 len, const char *domain);
|
||||||
bool NSMBPatch();
|
bool patch_nsmb(u8 *gameid);
|
||||||
bool PoPPatch();
|
bool patch_pop(u8 *gameid);
|
||||||
|
void patch_error_codes(u8 *gameid);
|
||||||
void VideoModePatcher(u8 *dst, int len, u8 videoSelected, u8 VideoPatchDol);
|
void VideoModePatcher(u8 *dst, int len, u8 videoSelected, u8 VideoPatchDol);
|
||||||
void sneek_video_patch(void *addr, u32 len);
|
void sneek_video_patch(void *addr, u32 len);
|
||||||
bool PatchReturnTo(void *Address, int Size, u32 id);
|
bool PatchReturnTo(void *Address, int Size, u32 id);
|
||||||
int PatchNewReturnTo(int es_fd, u64 title);
|
int PatchNewReturnTo(int es_fd, u64 title);
|
||||||
int BlockIOSReload(int es_fd, u8 gameIOS);
|
int BlockIOSReload(int es_fd, u32 gameIOS);
|
||||||
void PatchAspectRatio(void *addr, u32 len, u8 aspect);
|
void PatchAspectRatio(void *addr, u32 len, u8 aspect);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
@ -78,9 +78,6 @@ static const u32 langpatch[3] = {0x7C600775, 0x40820010, 0x38000000};
|
|||||||
void dogamehooks(u32 hooktype, void *addr, u32 len)
|
void dogamehooks(u32 hooktype, void *addr, u32 len)
|
||||||
//---------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------
|
||||||
{
|
{
|
||||||
if (hooktype == 0x00)
|
|
||||||
return;
|
|
||||||
|
|
||||||
bool isChannel = (*((char *)0x80000005) == 0) && (*((char *)0x80000006) == 0);
|
bool isChannel = (*((char *)0x80000005) == 0) && (*((char *)0x80000006) == 0);
|
||||||
void *addr_start = addr;
|
void *addr_start = addr;
|
||||||
void *addr_end = addr + len;
|
void *addr_end = addr + len;
|
||||||
@ -584,93 +581,6 @@ int LoadGameConfig(const char *CheatFilepath)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ocarina_patch(u8 *gameid)
|
|
||||||
{
|
|
||||||
// Thanks to Seeky for the MKWii gecko codes
|
|
||||||
// Thanks to InvoxiPlayGames for the gecko codes for the 23400 fix.
|
|
||||||
// Reimplemented by Leseratte without the need for a code handler.
|
|
||||||
|
|
||||||
u32 * patch_addr = 0;
|
|
||||||
char * patched = 0;
|
|
||||||
|
|
||||||
// Patch error 23400 for CoD (Black Ops, Reflex, MW3) and Rock Band 3 / The Beatles
|
|
||||||
|
|
||||||
if (memcmp(gameid, "SC7", 3) == 0)
|
|
||||||
{
|
|
||||||
gprintf("Patching error 23400 for game %s\n", gameid);
|
|
||||||
*(u32 *)0x8023c954 = 0x41414141;
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (memcmp(gameid, "RJA", 3) == 0)
|
|
||||||
{
|
|
||||||
gprintf("Patching error 23400 for game %s\n", gameid);
|
|
||||||
*(u32 *)0x801b838c = 0x41414141;
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (memcmp(gameid, "SM8", 3) == 0)
|
|
||||||
{
|
|
||||||
gprintf("Patching error 23400 for game %s\n", gameid);
|
|
||||||
*(u32 *)0x80238c74 = 0x41414141;
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (memcmp(gameid, "SZB", 3) == 0)
|
|
||||||
{
|
|
||||||
gprintf("Patching error 23400 for game %s\n", gameid);
|
|
||||||
*(u32 *)0x808e3b20 = 0x41414141;
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (memcmp(gameid, "R9J", 3) == 0)
|
|
||||||
{
|
|
||||||
gprintf("Patching error 23400 for game %s\n", gameid);
|
|
||||||
*(u32 *)0x808d6934 = 0x41414141;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Patch RCE vulnerability in MKWii.
|
|
||||||
else if (memcmp(gameid, "RMC", 3) == 0)
|
|
||||||
{
|
|
||||||
switch (gameid[3]) {
|
|
||||||
|
|
||||||
case 'P':
|
|
||||||
patched = (char *)0x80276054;
|
|
||||||
patch_addr = (u32 *)0x8089a194;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'E':
|
|
||||||
patched = (char *)0x80271d14;
|
|
||||||
patch_addr = (u32 *)0x80895ac4;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'J':
|
|
||||||
patched = (char *)0x802759f4;
|
|
||||||
patch_addr = (u32 *)0x808992f4;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'K':
|
|
||||||
patched = (char *)0x80263E34;
|
|
||||||
patch_addr = (u32 *)0x808885cc;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
gprintf("NOT patching RCE vulnerability due to invalid game ID: %s\n", gameid);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (*patched != '*') {
|
|
||||||
gprintf("Game is already Wiimmfi-patched, don't apply the RCE fix\n");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
gprintf("Patching RCE vulnerability for game ID %s\n", gameid);
|
|
||||||
|
|
||||||
for (int i = 0; i < 7; i++) {
|
|
||||||
*patch_addr++ = 0xff;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int ocarina_load_code(const char *CheatFilepath, u8 *gameid)
|
int ocarina_load_code(const char *CheatFilepath, u8 *gameid)
|
||||||
{
|
{
|
||||||
char filepath[150];
|
char filepath[150];
|
||||||
|
@ -36,7 +36,6 @@ void langpatcher(void *addr, u32 len, u8 languageChoice);
|
|||||||
void vidolpatcher(void *addr, u32 len);
|
void vidolpatcher(void *addr, u32 len);
|
||||||
void patchdebug(void *addr, u32 len);
|
void patchdebug(void *addr, u32 len);
|
||||||
int LoadGameConfig(const char *CheatFilepath);
|
int LoadGameConfig(const char *CheatFilepath);
|
||||||
int ocarina_patch(u8 *gameid);
|
|
||||||
int ocarina_load_code(const char *CheatFilepath, u8 *gameid);
|
int ocarina_load_code(const char *CheatFilepath, u8 *gameid);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
@ -76,6 +76,26 @@ extern "C"
|
|||||||
extern void __exception_closeall();
|
extern void __exception_closeall();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check if a game or channel is incompatible with some patches
|
||||||
|
bool GameBooter::exclude_game(u8 *gameid, bool skipChannels)
|
||||||
|
{
|
||||||
|
if (memcmp(gameid, "RPW", 3) == 0 || memcmp(gameid, "SPX", 3) == 0 ||
|
||||||
|
memcmp(gameid, "R3D", 3) == 0 || memcmp(gameid, "SDV", 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 || memcmp(gameid, "SD2", 3) == 0 ||
|
||||||
|
memcmp(gameid, "SXD", 3) == 0 || memcmp(gameid, "REX", 3) == 0)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (!skipChannels && (memcmp(gameid, "HAAA", 4) == 0 || memcmp(gameid, "HAYK", 4) == 0 ||
|
||||||
|
memcmp(gameid, "HAYC", 4) == 0))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
int GameBooter::BootGCMode(struct discHdr *gameHdr)
|
int GameBooter::BootGCMode(struct discHdr *gameHdr)
|
||||||
{
|
{
|
||||||
// check the settings
|
// check the settings
|
||||||
@ -180,14 +200,15 @@ void GameBooter::SetupNandEmu(u8 NandEmuMode, const char *NandEmuPath, struct di
|
|||||||
DeviceHandler::Instance()->UnMount(USB1 + partition);
|
DeviceHandler::Instance()->UnMount(USB1 + partition);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
DeviceHandler::Instance()->UnMountSD();
|
DeviceHandler::Instance()->UnMountSD();
|
||||||
|
}
|
||||||
|
|
||||||
Enable_Emu(strncmp(NandEmuPath, "usb", 3) == 0 ? EMU_USB : EMU_SD);
|
Enable_Emu(strncmp(NandEmuPath, "usb", 3) == 0 ? EMU_USB : EMU_SD);
|
||||||
|
|
||||||
//! Mount USB to start game, SD is not required
|
//! Mount USB to start game, SD is not required
|
||||||
if (strncmp(NandEmuPath, "usb", 3) == 0)
|
if (strncmp(NandEmuPath, "usb", 3) == 0)
|
||||||
DeviceHandler::Instance()->Mount(USB1 + partition);
|
DeviceHandler::Instance()->Mount(USB1 + partition);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -206,16 +227,19 @@ int GameBooter::SetupDisc(struct discHdr &gameHeader)
|
|||||||
gprintf("Disc_SetUSB...");
|
gprintf("Disc_SetUSB...");
|
||||||
ret = Disc_SetUSB(gameHeader.id);
|
ret = Disc_SetUSB(gameHeader.id);
|
||||||
gprintf("%d\n", ret);
|
gprintf("%d\n", ret);
|
||||||
if(ret < 0) return ret;
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
gprintf("Loading fragment list...");
|
gprintf("Loading fragment list...");
|
||||||
ret = get_frag_list(gameHeader.id);
|
ret = get_frag_list(gameHeader.id);
|
||||||
gprintf("%d\n", ret);
|
gprintf("%d\n", ret);
|
||||||
if(ret < 0) return ret;
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
ret = set_frag_list(gameHeader.id);
|
ret = set_frag_list(gameHeader.id);
|
||||||
if(ret < 0) return ret;
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
gprintf("\tUSB set to game\n");
|
gprintf("\tUSB set to game\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -228,6 +252,10 @@ int GameBooter::SetupDisc(struct discHdr &gameHeader)
|
|||||||
|
|
||||||
void GameBooter::ShutDownDevices(int gameUSBPort)
|
void GameBooter::ShutDownDevices(int gameUSBPort)
|
||||||
{
|
{
|
||||||
|
bool usbconnected = false;
|
||||||
|
if (DeviceHandler::Instance()->USB0_Inserted() || DeviceHandler::Instance()->USB1_Inserted())
|
||||||
|
usbconnected = true;
|
||||||
|
|
||||||
gprintf("Shutting down devices...\n");
|
gprintf("Shutting down devices...\n");
|
||||||
//! Flush all caches and close up all devices
|
//! Flush all caches and close up all devices
|
||||||
WBFS_CloseAll();
|
WBFS_CloseAll();
|
||||||
@ -236,10 +264,11 @@ void GameBooter::ShutDownDevices(int gameUSBPort)
|
|||||||
//! Shadow mload - Only needed on some games with Hermes v5.1 (Check is inside the function)
|
//! Shadow mload - Only needed on some games with Hermes v5.1 (Check is inside the function)
|
||||||
shadow_mload();
|
shadow_mload();
|
||||||
|
|
||||||
if(Settings.USBPort == 2)
|
|
||||||
//! Reset USB port because device handler changes it for cache flushing
|
//! Reset USB port because device handler changes it for cache flushing
|
||||||
|
if (Settings.USBPort == 2)
|
||||||
USBStorage2_SetPort(gameUSBPort);
|
USBStorage2_SetPort(gameUSBPort);
|
||||||
USBStorage2_Deinit();
|
USBStorage2_Deinit();
|
||||||
|
if (usbconnected)
|
||||||
USB_Deinitialize();
|
USB_Deinitialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -251,7 +280,11 @@ int GameBooter::BootGame(struct discHdr *gameHdr)
|
|||||||
struct discHdr gameHeader;
|
struct discHdr gameHeader;
|
||||||
memcpy(&gameHeader, gameHdr, sizeof(struct discHdr));
|
memcpy(&gameHeader, gameHdr, sizeof(struct discHdr));
|
||||||
|
|
||||||
gprintf("\tBootGame: %.6s\n", gameHeader.id);
|
gprintf("\tBoot Game: %s (%.6s)\n", gameHeader.title, gameHeader.id);
|
||||||
|
|
||||||
|
// Load the HBC from NAND instead of from the homebrew browser
|
||||||
|
if (memcmp(gameHeader.id, "JODI", 4) == 0)
|
||||||
|
Sys_BackToLoader();
|
||||||
|
|
||||||
if (Settings.Wiinnertag)
|
if (Settings.Wiinnertag)
|
||||||
Wiinnertag::TagGame((const char *)gameHeader.id);
|
Wiinnertag::TagGame((const char *)gameHeader.id);
|
||||||
@ -272,7 +305,7 @@ int GameBooter::BootGame(struct discHdr *gameHdr)
|
|||||||
u8 viChoice = game_cfg->vipatch == INHERIT ? Settings.videopatch : game_cfg->vipatch;
|
u8 viChoice = game_cfg->vipatch == INHERIT ? Settings.videopatch : game_cfg->vipatch;
|
||||||
u8 deflicker = game_cfg->deflicker == INHERIT ? Settings.deflicker : game_cfg->deflicker;
|
u8 deflicker = game_cfg->deflicker == INHERIT ? Settings.deflicker : game_cfg->deflicker;
|
||||||
u8 sneekChoice = game_cfg->sneekVideoPatch == INHERIT ? Settings.sneekVideoPatch : game_cfg->sneekVideoPatch;
|
u8 sneekChoice = game_cfg->sneekVideoPatch == INHERIT ? Settings.sneekVideoPatch : game_cfg->sneekVideoPatch;
|
||||||
u8 iosChoice = game_cfg->ios == INHERIT ? Settings.cios : game_cfg->ios;
|
s32 iosChoice = game_cfg->ios == INHERIT ? Settings.cios : game_cfg->ios;
|
||||||
u8 countrystrings = game_cfg->patchcountrystrings == INHERIT ? Settings.patchcountrystrings : game_cfg->patchcountrystrings;
|
u8 countrystrings = game_cfg->patchcountrystrings == INHERIT ? Settings.patchcountrystrings : game_cfg->patchcountrystrings;
|
||||||
u8 alternatedol = game_cfg->loadalternatedol;
|
u8 alternatedol = game_cfg->loadalternatedol;
|
||||||
u32 alternatedoloffset = game_cfg->alternatedolstart;
|
u32 alternatedoloffset = game_cfg->alternatedolstart;
|
||||||
@ -331,7 +364,6 @@ int GameBooter::BootGame(struct discHdr *gameHdr)
|
|||||||
Playlog_Update((char *)gameHeader.id, BNRInstance::Instance()->GetIMETTitle(CONF_GetLanguage()));
|
Playlog_Update((char *)gameHeader.id, BNRInstance::Instance()->GetIMETTitle(CONF_GetLanguage()));
|
||||||
}
|
}
|
||||||
|
|
||||||
gprintf("Game title: %s\n", gameHeader.title);
|
|
||||||
if (PrivServChoice == PRIVSERV_CUSTOM)
|
if (PrivServChoice == PRIVSERV_CUSTOM)
|
||||||
gprintf("Custom address: %s\n", customAddress);
|
gprintf("Custom address: %s\n", customAddress);
|
||||||
|
|
||||||
@ -358,6 +390,7 @@ int GameBooter::BootGame(struct discHdr *gameHdr)
|
|||||||
LoadGameConfig(Settings.Cheatcodespath);
|
LoadGameConfig(Settings.Cheatcodespath);
|
||||||
|
|
||||||
//! Setup NAND emulation
|
//! Setup NAND emulation
|
||||||
|
if (!exclude_game(gameHeader.id, true))
|
||||||
SetupNandEmu(NandEmuMode, NandEmuPath, gameHeader);
|
SetupNandEmu(NandEmuMode, NandEmuPath, gameHeader);
|
||||||
|
|
||||||
//! Setup disc stuff if we load a game
|
//! Setup disc stuff if we load a game
|
||||||
@ -392,9 +425,8 @@ int GameBooter::BootGame(struct discHdr *gameHdr)
|
|||||||
if (es_fd >= 0)
|
if (es_fd >= 0)
|
||||||
{
|
{
|
||||||
// IOS Reload Block
|
// IOS Reload Block
|
||||||
if (reloadblock != OFF) {
|
if (reloadblock != OFF)
|
||||||
BlockIOSReload(es_fd, iosChoice);
|
BlockIOSReload(es_fd, iosChoice);
|
||||||
}
|
|
||||||
// Check if new patch method for return to works otherwise old method will be used
|
// Check if new patch method for return to works otherwise old method will be used
|
||||||
if (PatchNewReturnTo(es_fd, returnToChoice) >= 0)
|
if (PatchNewReturnTo(es_fd, returnToChoice) >= 0)
|
||||||
returnToChoice = 0; // Patch successful, no need for old method
|
returnToChoice = 0; // Patch successful, no need for old method
|
||||||
@ -438,7 +470,6 @@ int GameBooter::BootGame(struct discHdr *gameHdr)
|
|||||||
//! Do all the game patches
|
//! Do all the game patches
|
||||||
gprintf("Applying game patches...\n");
|
gprintf("Applying game patches...\n");
|
||||||
|
|
||||||
|
|
||||||
//! Now this code block is responsible for the private server patch
|
//! Now this code block is responsible for the private server patch
|
||||||
//! and the gecko code handler loading
|
//! and the gecko code handler loading
|
||||||
|
|
||||||
@ -463,7 +494,6 @@ int GameBooter::BootGame(struct discHdr *gameHdr)
|
|||||||
deflicker, sneekChoice, Hooktype, returnToChoice, PRIVSERV_OFF, customAddress);
|
deflicker, sneekChoice, Hooktype, returnToChoice, PRIVSERV_OFF, customAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//! Load Code handler if needed
|
//! Load Code handler if needed
|
||||||
load_handler(Hooktype, WiirdDebugger, Settings.WiirdDebuggerPause);
|
load_handler(Hooktype, WiirdDebugger, Settings.WiirdDebuggerPause);
|
||||||
|
|
||||||
@ -471,28 +501,14 @@ int GameBooter::BootGame(struct discHdr *gameHdr)
|
|||||||
//! This needs to be done after the call to gamepatches(), after loading any code handler.
|
//! This needs to be done after the call to gamepatches(), after loading any code handler.
|
||||||
//! Can (and should) be done before Wiimmfi patching, can't be done in gamepatches() itself.
|
//! Can (and should) be done before Wiimmfi patching, can't be done in gamepatches() itself.
|
||||||
//! Exclude Prince of Persia: The Forgotten Sands and a few games that use MetaFortress
|
//! Exclude Prince of Persia: The Forgotten Sands and a few games that use MetaFortress
|
||||||
bool excludeGame = false;
|
if (patchFix480pChoice && !exclude_game(gameHeader.id))
|
||||||
if (memcmp(gameHeader.id, "RPW", 3) == 0 || memcmp(gameHeader.id, "SPX", 3) == 0 ||
|
|
||||||
memcmp(gameHeader.id, "R3D", 3) == 0 || memcmp(gameHeader.id, "SDV", 3) == 0 ||
|
|
||||||
memcmp(gameHeader.id, "SUK", 3) == 0 || memcmp(gameHeader.id, "STN", 3) == 0 ||
|
|
||||||
memcmp(gameHeader.id, "S7S", 3) == 0 || memcmp(gameHeader.id, "SDUP41", 6) == 0 ||
|
|
||||||
memcmp(gameHeader.id, "SDUE41", 6) == 0 || memcmp(gameHeader.id, "SDUX41", 6) == 0)
|
|
||||||
{
|
|
||||||
excludeGame = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (patchFix480pChoice && !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 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 (PrivServChoice != PRIVSERV_WIIMMFI)
|
if (PrivServChoice != PRIVSERV_WIIMMFI)
|
||||||
{
|
patch_error_codes(gameHeader.id);
|
||||||
ocarina_patch(gameHeader.id);
|
|
||||||
}
|
|
||||||
|
|
||||||
//! New Wiimmfi patch should be loaded last, after the codehandler, just before the call to the entry point
|
//! New Wiimmfi patch should be loaded last, after the codehandler, just before the call to the entry point
|
||||||
if (PrivServChoice == PRIVSERV_WIIMMFI && memcmp(gameHeader.id, "RMC", 3) == 0)
|
if (PrivServChoice == PRIVSERV_WIIMMFI && memcmp(gameHeader.id, "RMC", 3) == 0)
|
||||||
@ -614,7 +630,6 @@ int GameBooter::BootDIOSMIOS(struct discHdr *gameHdr)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Check DIOS MIOS config for specific versions
|
// Check DIOS MIOS config for specific versions
|
||||||
if (currentMIOS != QUADFORCE && currentMIOS != QUADFORCE_USB)
|
if (currentMIOS != QUADFORCE && currentMIOS != QUADFORCE_USB)
|
||||||
{
|
{
|
||||||
@ -662,7 +677,8 @@ int GameBooter::BootDIOSMIOS(struct discHdr *gameHdr)
|
|||||||
char disc2Path[255];
|
char disc2Path[255];
|
||||||
snprintf(disc2Path, sizeof(disc2Path), "%s", RealPath);
|
snprintf(disc2Path, sizeof(disc2Path), "%s", RealPath);
|
||||||
char *pathPtr = strrchr(disc2Path, '/');
|
char *pathPtr = strrchr(disc2Path, '/');
|
||||||
if(pathPtr) *pathPtr = 0;
|
if (pathPtr)
|
||||||
|
*pathPtr = 0;
|
||||||
snprintf(disc2Path + strlen(disc2Path), sizeof(disc2Path) - strlen(disc2Path), "/disc2.iso");
|
snprintf(disc2Path + strlen(disc2Path), sizeof(disc2Path) - strlen(disc2Path), "/disc2.iso");
|
||||||
if (CheckFile(disc2Path))
|
if (CheckFile(disc2Path))
|
||||||
{
|
{
|
||||||
@ -675,7 +691,8 @@ int GameBooter::BootDIOSMIOS(struct discHdr *gameHdr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
const char *gcPath = strchr(RealPath, '/');
|
const char *gcPath = strchr(RealPath, '/');
|
||||||
if(!gcPath) gcPath = "";
|
if (!gcPath)
|
||||||
|
gcPath = "";
|
||||||
|
|
||||||
char gamePath[255];
|
char gamePath[255];
|
||||||
snprintf(gamePath, sizeof(gamePath), "%s", gcPath);
|
snprintf(gamePath, sizeof(gamePath), "%s", gcPath);
|
||||||
@ -683,7 +700,8 @@ int GameBooter::BootDIOSMIOS(struct discHdr *gameHdr)
|
|||||||
if (bootDisc2)
|
if (bootDisc2)
|
||||||
{
|
{
|
||||||
char *pathPtr = strrchr(gamePath, '/');
|
char *pathPtr = strrchr(gamePath, '/');
|
||||||
if(pathPtr) *pathPtr = 0;
|
if (pathPtr)
|
||||||
|
*pathPtr = 0;
|
||||||
snprintf(gamePath + strlen(gamePath), sizeof(gamePath) - strlen(gamePath), "/disc2.iso");
|
snprintf(gamePath + strlen(gamePath), sizeof(gamePath) - strlen(gamePath), "/disc2.iso");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -725,7 +743,8 @@ int GameBooter::BootDIOSMIOS(struct discHdr *gameHdr)
|
|||||||
if (strcmp(DeviceHandler::GetDevicePrefix(RealPath), DeviceHandler::GetDevicePrefix(Settings.Cheatcodespath)) == 0)
|
if (strcmp(DeviceHandler::GetDevicePrefix(RealPath), DeviceHandler::GetDevicePrefix(Settings.Cheatcodespath)) == 0)
|
||||||
{
|
{
|
||||||
const char *CheatPath = strchr(Settings.Cheatcodespath, '/');
|
const char *CheatPath = strchr(Settings.Cheatcodespath, '/');
|
||||||
if(!CheatPath) CheatPath = "";
|
if (!CheatPath)
|
||||||
|
CheatPath = "";
|
||||||
snprintf(dml_config->CheatPath, sizeof(dml_config->CheatPath), "%s%.6s.gct", CheatPath, (char *)gameHdr->id);
|
snprintf(dml_config->CheatPath, sizeof(dml_config->CheatPath), "%s%.6s.gct", CheatPath, (char *)gameHdr->id);
|
||||||
}
|
}
|
||||||
else if (gameHdr->type != TYPE_GAME_GC_DISC)
|
else if (gameHdr->type != TYPE_GAME_GC_DISC)
|
||||||
@ -756,7 +775,6 @@ int GameBooter::BootDIOSMIOS(struct discHdr *gameHdr)
|
|||||||
if (bootDisc2 && IosLoader::GetDMLVersion() >= DML_VERSION_DM_2_6_0)
|
if (bootDisc2 && IosLoader::GetDMLVersion() >= DML_VERSION_DM_2_6_0)
|
||||||
dml_config->Config |= DML_CFG_BOOT_DISC2;
|
dml_config->Config |= DML_CFG_BOOT_DISC2;
|
||||||
|
|
||||||
|
|
||||||
// Setup Video Mode
|
// Setup Video Mode
|
||||||
if (dmlVideoChoice == DML_VIDEO_NONE) // No video mode
|
if (dmlVideoChoice == DML_VIDEO_NONE) // No video mode
|
||||||
{
|
{
|
||||||
@ -781,7 +799,6 @@ int GameBooter::BootDIOSMIOS(struct discHdr *gameHdr)
|
|||||||
if (dmlProgressivePatch)
|
if (dmlProgressivePatch)
|
||||||
dml_config->VideoMode |= DML_VID_PROG_PATCH;
|
dml_config->VideoMode |= DML_VID_PROG_PATCH;
|
||||||
|
|
||||||
|
|
||||||
DCFlushRange(dml_config, sizeof(DML_CFG));
|
DCFlushRange(dml_config, sizeof(DML_CFG));
|
||||||
memcpy((u8 *)DML_CONFIG_ADDRESS_V1_2, 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));
|
DCFlushRange((u8 *)DML_CONFIG_ADDRESS_V1_2, sizeof(DML_CFG));
|
||||||
@ -866,13 +883,15 @@ int GameBooter::BootDevolution(struct discHdr *gameHdr)
|
|||||||
}
|
}
|
||||||
fread(loader_bin, 1, size, f);
|
fread(loader_bin, 1, size, f);
|
||||||
|
|
||||||
//read Devolution version
|
// Read Devolution version
|
||||||
char version[5];
|
char version[5];
|
||||||
fseek(f, 23, SEEK_SET);
|
fseek(f, 23, SEEK_SET);
|
||||||
fread(version, 1, 4, f);
|
fread(version, 1, 4, f);
|
||||||
char *ptr = strchr(version, ' ');
|
char *ptr = strchr(version, ' ');
|
||||||
if(ptr) *ptr = 0;
|
if (ptr)
|
||||||
else version[4] = 0;
|
*ptr = 0;
|
||||||
|
else
|
||||||
|
version[4] = 0;
|
||||||
DEVO_version = atoi(version);
|
DEVO_version = atoi(version);
|
||||||
|
|
||||||
fclose(f);
|
fclose(f);
|
||||||
@ -883,7 +902,6 @@ int GameBooter::BootDevolution(struct discHdr *gameHdr)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Devolution config
|
// Devolution config
|
||||||
DEVO_CFG *devo_config = (DEVO_CFG *)0x80000020;
|
DEVO_CFG *devo_config = (DEVO_CFG *)0x80000020;
|
||||||
|
|
||||||
@ -895,14 +913,16 @@ int GameBooter::BootDevolution(struct discHdr *gameHdr)
|
|||||||
|
|
||||||
snprintf(disc2, sizeof(disc2), "%s", RealPath);
|
snprintf(disc2, sizeof(disc2), "%s", RealPath);
|
||||||
char *pathPtr = strrchr(disc2, '/');
|
char *pathPtr = strrchr(disc2, '/');
|
||||||
if(pathPtr) *pathPtr = 0;
|
if (pathPtr)
|
||||||
|
*pathPtr = 0;
|
||||||
snprintf(disc2 + strlen(disc2), sizeof(disc2) - strlen(disc2), "/disc2.iso");
|
snprintf(disc2 + strlen(disc2), sizeof(disc2) - strlen(disc2), "/disc2.iso");
|
||||||
if (CheckFile(disc2))
|
if (CheckFile(disc2))
|
||||||
multiDisc = true;
|
multiDisc = true;
|
||||||
|
|
||||||
snprintf(DEVO_memCard, sizeof(DEVO_memCard), "%s", RealPath); // Set memory card folder to Disc1 folder
|
snprintf(DEVO_memCard, sizeof(DEVO_memCard), "%s", RealPath); // Set memory card folder to Disc1 folder
|
||||||
char *ptr = strrchr(DEVO_memCard, '/');
|
char *ptr = strrchr(DEVO_memCard, '/');
|
||||||
if(ptr) *ptr = 0;
|
if (ptr)
|
||||||
|
*ptr = 0;
|
||||||
|
|
||||||
// Make sure the directory exists
|
// Make sure the directory exists
|
||||||
char devoPath[20];
|
char devoPath[20];
|
||||||
@ -922,8 +942,6 @@ int GameBooter::BootDevolution(struct discHdr *gameHdr)
|
|||||||
memset(devo_config, 0, sizeof(*devo_config));
|
memset(devo_config, 0, sizeof(*devo_config));
|
||||||
devo_config->signature = DEVO_SIG;
|
devo_config->signature = DEVO_SIG;
|
||||||
devo_config->version = DEVO_CONFIG_VERSION;
|
devo_config->version = DEVO_CONFIG_VERSION;
|
||||||
// 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.
|
|
||||||
devo_config->device_signature = st1.st_dev == 'WISD' ? 'SD' : 'SB'; // Set device type.
|
devo_config->device_signature = st1.st_dev == 'WISD' ? 'SD' : 'SB'; // Set device type.
|
||||||
devo_config->disc1_cluster = st1.st_ino; // set starting cluster for first disc ISO file
|
devo_config->disc1_cluster = st1.st_ino; // set starting cluster for first disc ISO file
|
||||||
if (multiDisc)
|
if (multiDisc)
|
||||||
@ -947,6 +965,7 @@ int GameBooter::BootDevolution(struct discHdr *gameHdr)
|
|||||||
if (devoDiscDelayChoice && DEVO_version >= 234)
|
if (devoDiscDelayChoice && DEVO_version >= 234)
|
||||||
devo_config->options |= DEVO_CFG_DISC_DELAY;
|
devo_config->options |= DEVO_CFG_DISC_DELAY;
|
||||||
// devo_config->options |= DEVO_CFG_PLAYLOG; // Playlog setting managed by USBLoaderGX features menu
|
// devo_config->options |= DEVO_CFG_PLAYLOG; // Playlog setting managed by USBLoaderGX features menu
|
||||||
|
|
||||||
if (devoProgressivePatch && DEVO_version >= 266)
|
if (devoProgressivePatch && DEVO_version >= 266)
|
||||||
{
|
{
|
||||||
devo_config->options |= DEVO_CFG_FORCE_480P;
|
devo_config->options |= DEVO_CFG_FORCE_480P;
|
||||||
@ -1004,7 +1023,6 @@ int GameBooter::BootDevolution(struct discHdr *gameHdr)
|
|||||||
devo_config->memcard_cluster = st.st_ino;
|
devo_config->memcard_cluster = st.st_ino;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// read 32 bytes of disc 1 to the start of MEM1
|
// read 32 bytes of disc 1 to the start of MEM1
|
||||||
FILE *iso_file = fopen(disc1, "rb");
|
FILE *iso_file = fopen(disc1, "rb");
|
||||||
if (!iso_file)
|
if (!iso_file)
|
||||||
@ -1050,7 +1068,6 @@ int GameBooter::BootDevolution(struct discHdr *gameHdr)
|
|||||||
|
|
||||||
int GameBooter::BootNintendont(struct discHdr *gameHdr)
|
int GameBooter::BootNintendont(struct discHdr *gameHdr)
|
||||||
{
|
{
|
||||||
|
|
||||||
char RealPath[100];
|
char RealPath[100];
|
||||||
if (gameHdr->type == TYPE_GAME_GC_DISC)
|
if (gameHdr->type == TYPE_GAME_GC_DISC)
|
||||||
snprintf(RealPath, sizeof(RealPath), "di");
|
snprintf(RealPath, sizeof(RealPath), "di");
|
||||||
@ -1091,14 +1108,12 @@ int GameBooter::BootNintendont(struct discHdr *gameHdr)
|
|||||||
|
|
||||||
const char *ninLoaderPath = game_cfg->NINLoaderPath.size() == 0 ? Settings.NINLoaderPath : game_cfg->NINLoaderPath.c_str();
|
const char *ninLoaderPath = game_cfg->NINLoaderPath.size() == 0 ? Settings.NINLoaderPath : game_cfg->NINLoaderPath.c_str();
|
||||||
|
|
||||||
|
|
||||||
if (!CheckAHBPROT())
|
if (!CheckAHBPROT())
|
||||||
{
|
{
|
||||||
WindowPrompt(tr("Error:"), fmt(tr("%s requires AHB access! Please launch USBLoaderGX from HBC or from an updated channel or forwarder."), LoaderName), tr("OK"));
|
WindowPrompt(tr("Error:"), fmt(tr("%s requires AHB access! Please launch USBLoaderGX from HBC or from an updated channel or forwarder."), LoaderName), tr("OK"));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Check if Nintendont boot.dol is available
|
// Check if Nintendont boot.dol is available
|
||||||
char NIN_loader_path[255];
|
char NIN_loader_path[255];
|
||||||
if (strncmp(RealPath, "usb", 3) == 0) // Nintendont r39 only
|
if (strncmp(RealPath, "usb", 3) == 0) // Nintendont r39 only
|
||||||
@ -1131,7 +1146,6 @@ int GameBooter::BootNintendont(struct discHdr *gameHdr)
|
|||||||
if (NINRev > 0) // Version available since 3.324
|
if (NINRev > 0) // Version available since 3.324
|
||||||
{
|
{
|
||||||
gprintf("NIN: Nintendont revision = %d \n", NINRev);
|
gprintf("NIN: Nintendont revision = %d \n", NINRev);
|
||||||
|
|
||||||
NINArgsboot = true; // no need to check argsboot string, 3.324+ supports it.
|
NINArgsboot = true; // no need to check argsboot string, 3.324+ supports it.
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -1205,7 +1219,6 @@ int GameBooter::BootNintendont(struct discHdr *gameHdr)
|
|||||||
NINRev = 304;
|
NINRev = 304;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// checks argsboot
|
// checks argsboot
|
||||||
if (ninAutobootChoice)
|
if (ninAutobootChoice)
|
||||||
{
|
{
|
||||||
@ -1250,7 +1263,6 @@ int GameBooter::BootNintendont(struct discHdr *gameHdr)
|
|||||||
else if (NINRev >= 487)
|
else if (NINRev >= 487)
|
||||||
NIN_cfg_version = 9;
|
NIN_cfg_version = 9;
|
||||||
|
|
||||||
|
|
||||||
// Check USB device
|
// Check USB device
|
||||||
if (gameHdr->type != TYPE_GAME_GC_DISC && strncmp(RealPath, "usb", 3) == 0)
|
if (gameHdr->type != TYPE_GAME_GC_DISC && strncmp(RealPath, "usb", 3) == 0)
|
||||||
{
|
{
|
||||||
@ -1318,7 +1330,6 @@ int GameBooter::BootNintendont(struct discHdr *gameHdr)
|
|||||||
snprintf(RealPath, sizeof(RealPath), "%s:/", DeviceHandler::GetDevicePrefix(Settings.GameCubeSDPath));
|
snprintf(RealPath, sizeof(RealPath), "%s:/", DeviceHandler::GetDevicePrefix(Settings.GameCubeSDPath));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Check Ocarina and cheat file location. the .gct file need to be located on the same partition than the game.
|
// Check Ocarina and cheat file location. the .gct file need to be located on the same partition than the game.
|
||||||
if (ocarinaChoice && strcmp(DeviceHandler::GetDevicePrefix(RealPath), DeviceHandler::GetDevicePrefix(Settings.Cheatcodespath)) != 0)
|
if (ocarinaChoice && strcmp(DeviceHandler::GetDevicePrefix(RealPath), DeviceHandler::GetDevicePrefix(Settings.Cheatcodespath)) != 0)
|
||||||
{
|
{
|
||||||
@ -1428,7 +1439,6 @@ int GameBooter::BootNintendont(struct discHdr *gameHdr)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1440,7 +1450,8 @@ int GameBooter::BootNintendont(struct discHdr *gameHdr)
|
|||||||
char disc2Path[255];
|
char disc2Path[255];
|
||||||
snprintf(disc2Path, sizeof(disc2Path), "%s", RealPath);
|
snprintf(disc2Path, sizeof(disc2Path), "%s", RealPath);
|
||||||
char *pathPtr = strrchr(disc2Path, '/');
|
char *pathPtr = strrchr(disc2Path, '/');
|
||||||
if(pathPtr) *pathPtr = 0;
|
if (pathPtr)
|
||||||
|
*pathPtr = 0;
|
||||||
snprintf(disc2Path + strlen(disc2Path), sizeof(disc2Path) - strlen(disc2Path), "/disc2.iso");
|
snprintf(disc2Path + strlen(disc2Path), sizeof(disc2Path) - strlen(disc2Path), "/disc2.iso");
|
||||||
if (CheckFile(disc2Path))
|
if (CheckFile(disc2Path))
|
||||||
{
|
{
|
||||||
@ -1452,7 +1463,8 @@ int GameBooter::BootNintendont(struct discHdr *gameHdr)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
const char *gcPath = strchr(RealPath, '/');
|
const char *gcPath = strchr(RealPath, '/');
|
||||||
if(!gcPath) gcPath = "";
|
if (!gcPath)
|
||||||
|
gcPath = "";
|
||||||
|
|
||||||
char gamePath[255];
|
char gamePath[255];
|
||||||
snprintf(gamePath, sizeof(gamePath), "%s", gcPath);
|
snprintf(gamePath, sizeof(gamePath), "%s", gcPath);
|
||||||
@ -1460,7 +1472,8 @@ int GameBooter::BootNintendont(struct discHdr *gameHdr)
|
|||||||
if (bootDisc2)
|
if (bootDisc2)
|
||||||
{
|
{
|
||||||
char *pathPtr = strrchr(gamePath, '/');
|
char *pathPtr = strrchr(gamePath, '/');
|
||||||
if(pathPtr) *pathPtr = 0;
|
if (pathPtr)
|
||||||
|
*pathPtr = 0;
|
||||||
snprintf(gamePath + strlen(gamePath), sizeof(gamePath) - strlen(gamePath), "/disc2.iso");
|
snprintf(gamePath + strlen(gamePath), sizeof(gamePath) - strlen(gamePath), "/disc2.iso");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1469,7 +1482,6 @@ int GameBooter::BootNintendont(struct discHdr *gameHdr)
|
|||||||
snprintf(gamePath, sizeof(gamePath), "di");
|
snprintf(gamePath, sizeof(gamePath), "di");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Nintendont Config file settings
|
// Nintendont Config file settings
|
||||||
NIN_CFG *nin_config = NULL;
|
NIN_CFG *nin_config = NULL;
|
||||||
nin_config = (NIN_CFG *)MEM2_alloc(sizeof(NIN_CFG));
|
nin_config = (NIN_CFG *)MEM2_alloc(sizeof(NIN_CFG));
|
||||||
@ -1486,7 +1498,6 @@ int GameBooter::BootNintendont(struct discHdr *gameHdr)
|
|||||||
nin_config->Magicbytes = NIN_MAGIC;
|
nin_config->Magicbytes = NIN_MAGIC;
|
||||||
nin_config->Version = NIN_cfg_version;
|
nin_config->Version = NIN_cfg_version;
|
||||||
|
|
||||||
|
|
||||||
// Game path
|
// Game path
|
||||||
strncpy(nin_config->GamePath, gamePath, sizeof(nin_config->GamePath));
|
strncpy(nin_config->GamePath, gamePath, sizeof(nin_config->GamePath));
|
||||||
|
|
||||||
@ -1497,7 +1508,8 @@ int GameBooter::BootNintendont(struct discHdr *gameHdr)
|
|||||||
if (strcmp(DeviceHandler::GetDevicePrefix(RealPath), DeviceHandler::GetDevicePrefix(Settings.Cheatcodespath)) == 0)
|
if (strcmp(DeviceHandler::GetDevicePrefix(RealPath), DeviceHandler::GetDevicePrefix(Settings.Cheatcodespath)) == 0)
|
||||||
{
|
{
|
||||||
const char *CheatPath = strchr(Settings.Cheatcodespath, '/');
|
const char *CheatPath = strchr(Settings.Cheatcodespath, '/');
|
||||||
if(!CheatPath) CheatPath = "";
|
if (!CheatPath)
|
||||||
|
CheatPath = "";
|
||||||
snprintf(nin_config->CheatPath, sizeof(nin_config->CheatPath), "%s%.6s.gct", CheatPath, (char *)gameHdr->id);
|
snprintf(nin_config->CheatPath, sizeof(nin_config->CheatPath), "%s%.6s.gct", CheatPath, (char *)gameHdr->id);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -1509,7 +1521,6 @@ int GameBooter::BootNintendont(struct discHdr *gameHdr)
|
|||||||
gprintf("NIN: Loading cheat %s\n", nin_config->CheatPath);
|
gprintf("NIN: Loading cheat %s\n", nin_config->CheatPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Set other settings
|
// Set other settings
|
||||||
if (ninDebugChoice && !isWiiU()) // only on Wii
|
if (ninDebugChoice && !isWiiU()) // only on Wii
|
||||||
nin_config->Config |= ninDebugChoice == ON ? NIN_CFG_DEBUGGER : NIN_CFG_DEBUGGER | NIN_CFG_DEBUGWAIT;
|
nin_config->Config |= ninDebugChoice == ON ? NIN_CFG_DEBUGGER : NIN_CFG_DEBUGGER | NIN_CFG_DEBUGWAIT;
|
||||||
@ -1629,7 +1640,6 @@ int GameBooter::BootNintendont(struct discHdr *gameHdr)
|
|||||||
}
|
}
|
||||||
gprintf("NIN: Language 0x%08x \n", nin_config->Language);
|
gprintf("NIN: Language 0x%08x \n", nin_config->Language);
|
||||||
|
|
||||||
|
|
||||||
// if WiiVC, force creation and use of nincfg.bin file to fix a nintendont bug if HID is connected before launching it.
|
// if WiiVC, force creation and use of nincfg.bin file to fix a nintendont bug if HID is connected before launching it.
|
||||||
if (isWiiVC)
|
if (isWiiVC)
|
||||||
{
|
{
|
||||||
@ -1652,7 +1662,6 @@ int GameBooter::BootNintendont(struct discHdr *gameHdr)
|
|||||||
snprintf(NINCfgPath, sizeof(NINCfgPath), "%s:/nincfg.bin", DeviceHandler::GetDevicePrefix(RealPath));
|
snprintf(NINCfgPath, sizeof(NINCfgPath), "%s:/nincfg.bin", DeviceHandler::GetDevicePrefix(RealPath));
|
||||||
RemoveFile(NINCfgPath);
|
RemoveFile(NINCfgPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
else if (ninSettingsChoice == ON || !NINArgsboot)
|
else if (ninSettingsChoice == ON || !NINArgsboot)
|
||||||
{
|
{
|
||||||
@ -1969,9 +1978,9 @@ void GameBooter::PatchSram(int language, bool patchVideoMode, bool progressive)
|
|||||||
while (!__SYS_SyncSram())
|
while (!__SYS_SyncSram())
|
||||||
usleep(100);
|
usleep(100);
|
||||||
|
|
||||||
|
|
||||||
// Log Sram's first 20 bytes
|
// Log Sram's first 20 bytes
|
||||||
/* char srambuff[64];
|
/*
|
||||||
|
char srambuff[64];
|
||||||
sram = __SYS_LockSram();
|
sram = __SYS_LockSram();
|
||||||
memcpy(srambuff, sram, 20);
|
memcpy(srambuff, sram, 20);
|
||||||
__SYS_UnlockSram(0);
|
__SYS_UnlockSram(0);
|
||||||
|
@ -26,6 +26,7 @@ class GameBooter
|
|||||||
static int BootGame(struct discHdr *gameHdr);
|
static int BootGame(struct discHdr *gameHdr);
|
||||||
static int BootGCMode(struct discHdr *gameHdr);
|
static int BootGCMode(struct discHdr *gameHdr);
|
||||||
private:
|
private:
|
||||||
|
static bool exclude_game(u8 *gameid, bool skipChannels = false);
|
||||||
static void SetupAltDOL(u8 * gameID, u8 &alternatedol, u32 &alternatedoloffset);
|
static void SetupAltDOL(u8 * gameID, u8 &alternatedol, u32 &alternatedoloffset);
|
||||||
static void SetupNandEmu(u8 NandEmuMode, const char *NandEmuPath, struct discHdr &gameHeader);
|
static void SetupNandEmu(u8 NandEmuMode, const char *NandEmuPath, struct discHdr &gameHeader);
|
||||||
static int SetupDisc(struct discHdr &gameHeader);
|
static int SetupDisc(struct discHdr &gameHeader);
|
||||||
|
Loading…
Reference in New Issue
Block a user