Refactored various game patches

This commit is contained in:
wiidev 2023-01-01 17:00:25 +00:00
parent 2ee86d1281
commit 564ea6a534
8 changed files with 666 additions and 693 deletions

View File

@ -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;
}

View File

@ -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

View File

@ -2,8 +2,8 @@
#include <gccore.h>
#include <malloc.h>
#include <string.h>
#include "usbloader/disc.h"
#include "dolpatcher.h"
#include "wip.h"
#include "gecko.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};
// If a wip file is loaded for this game this does nothing - Dimok
PoPPatch();
NSMBPatch();
patch_nsmb((u8 *)0x80000000);
patch_pop((u8 *)0x80000000);
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);
if (hooktype)
dogamehooks(hooktype, dst, len);
if (vipatch)
@ -99,22 +100,22 @@ void gamepatches(u8 videoSelected, u8 videoPatchDol, u8 aspectForce, u8 language
if (deflicker == DEFLICKER_ON_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)
{
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)
{
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)
{
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
if (deflicker == DEFLICKER_OFF_EXTENDED)
deflicker_patch(dst, len);
@ -154,8 +155,8 @@ void anti_002_fix(u8 *addr, u32 len)
{
u32 SearchPattern[3] = {0x2C000000, 0x48000214, 0x3C608000};
u8 *addr_start = addr;
u8 *addr_end = addr + len;
while (addr_start <= addr_end - sizeof(SearchPattern))
u8 *addr_end = addr + len - sizeof(SearchPattern);
while (addr_start <= addr_end)
{
if (memcmp(addr_start, SearchPattern, sizeof(SearchPattern)) == 0)
{
@ -177,8 +178,8 @@ void deflicker_patch(u8 *addr, u32 len)
0x90698000, 0x99498000, 0x90E98000,
0x99498000, 0x91098000, 0x41820040};
u8 *addr_start = addr;
u8 *addr_end = addr + len;
while (addr_start <= addr_end - sizeof(SearchPattern))
u8 *addr_end = addr + len - sizeof(SearchPattern);
while (addr_start <= addr_end)
{
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
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://github.com/ExtremsCorner/libogc-rice/commit/941d687e271fada68c359bbed98bed1fbb454448
**/
@ -863,11 +864,11 @@ void domainpatcher(void *addr, u32 len, const char *domain)
} while (++cur < end);
}
bool NSMBPatch()
bool patch_nsmb(u8 *gameid)
{
WIP_Code *CodeList = NULL;
if (memcmp("SMNE01", (char *)0x80000000, 6) == 0)
if (memcmp(gameid, "SMNE01", 6) == 0)
{
CodeList = MEM2_alloc(3 * sizeof(WIP_Code));
if (!CodeList)
@ -883,7 +884,7 @@ bool NSMBPatch()
CodeList[2].srcaddress = 0xDA000000;
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));
if (!CodeList)
@ -899,7 +900,7 @@ bool NSMBPatch()
CodeList[2].srcaddress = 0x388000DA;
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));
if (!CodeList)
@ -922,13 +923,14 @@ bool NSMBPatch()
CodeList = NULL;
return false;
}
if (CodeList)
gprintf("Patched New Super Mario Bros\n");
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;
WIP_Code *CodeList = MEM2_alloc(5 * sizeof(WIP_Code));
@ -954,8 +956,82 @@ bool PoPPatch()
CodeList = NULL;
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 **/
@ -1269,9 +1345,10 @@ static void patch_videomode(GXRModeObj *mode1, GXRModeObj *mode2)
mode1->viYOrigin = mode2->viYOrigin;
mode1->viWidth = mode2->viWidth;
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->field_rendering = mode2->field_rendering;
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
void patch_vfilters(u8 *addr, u32 len, u8 *vfilter)
{
u8 *addr_start = addr;
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) &&
(vidmode->fbWidth == 640 || vidmode->fbWidth == 608 || vidmode->fbWidth == 512) &&
(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",
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);
addr += (sizeof(GXRModeObj) - 4);
addr_start += (sizeof(GXRModeObj) - 4);
len -= (sizeof(GXRModeObj) - 4);
}
addr += 4;
addr_start += 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] = {
{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},
{2, 2, 17, 22, 17, 2, 2}
};
u8 *addr_start = addr;
u8 *addr_end = addr + len - 8;
while (addr <= addr_end)
while (addr_start <= addr_end)
{
u8 known_vfilter[7];
for (int i = 0; i < 7; i++)
{
for (int x = 0; x < 7; 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],
addr[3], addr[4], addr[5], addr[6], addr);
gprintf("Replaced vfilter %02x%02x%02x%02x%02x%02x%02x @ %p\n", addr_start[0], addr_start[1],
addr_start[2], addr_start[3], addr_start[4], addr_start[5], addr_start[6], addr_start);
memcpy(addr, vfilter, 7);
addr += 7;
addr_start += 7;
break;
}
}
addr += 1;
addr_start += 1;
}
}
@ -1711,7 +1791,7 @@ int PatchNewReturnTo(int es_fd, u64 title)
return result;
}
int BlockIOSReload(int es_fd, u8 gameIOS)
int BlockIOSReload(int es_fd, u32 gameIOS)
{
if (es_fd < 0)
return -1;

View File

@ -14,19 +14,20 @@ void gamepatches(u8 videoSelected, u8 videoPatchDol, u8 aspectForce, u8 language
void anti_002_fix(u8 *addr, u32 len);
void deflicker_patch(u8 *addr, u32 len);
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 PatchFix480p();
s8 do_new_wiimmfi();
s8 do_new_wiimmfi_nonMKWii(void *addr, u32 len);
void domainpatcher(void *addr, u32 len, const char *domain);
bool NSMBPatch();
bool PoPPatch();
bool patch_nsmb(u8 *gameid);
bool patch_pop(u8 *gameid);
void patch_error_codes(u8 *gameid);
void VideoModePatcher(u8 *dst, int len, u8 videoSelected, u8 VideoPatchDol);
void sneek_video_patch(void *addr, u32 len);
bool PatchReturnTo(void *Address, int Size, u32 id);
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);
#ifdef __cplusplus

View File

@ -78,9 +78,6 @@ static const u32 langpatch[3] = {0x7C600775, 0x40820010, 0x38000000};
void dogamehooks(u32 hooktype, void *addr, u32 len)
//---------------------------------------------------------------------------------
{
if (hooktype == 0x00)
return;
bool isChannel = (*((char *)0x80000005) == 0) && (*((char *)0x80000006) == 0);
void *addr_start = addr;
void *addr_end = addr + len;
@ -584,93 +581,6 @@ int LoadGameConfig(const char *CheatFilepath)
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)
{
char filepath[150];

View File

@ -36,7 +36,6 @@ void langpatcher(void *addr, u32 len, u8 languageChoice);
void vidolpatcher(void *addr, u32 len);
void patchdebug(void *addr, u32 len);
int LoadGameConfig(const char *CheatFilepath);
int ocarina_patch(u8 *gameid);
int ocarina_load_code(const char *CheatFilepath, u8 *gameid);
#ifdef __cplusplus

View File

@ -76,6 +76,26 @@ extern "C"
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)
{
// check the settings
@ -180,14 +200,15 @@ void GameBooter::SetupNandEmu(u8 NandEmuMode, const char *NandEmuPath, struct di
DeviceHandler::Instance()->UnMount(USB1 + partition);
}
else
{
DeviceHandler::Instance()->UnMountSD();
}
Enable_Emu(strncmp(NandEmuPath, "usb", 3) == 0 ? EMU_USB : EMU_SD);
//! Mount USB to start game, SD is not required
if (strncmp(NandEmuPath, "usb", 3) == 0)
DeviceHandler::Instance()->Mount(USB1 + partition);
}
}
@ -206,16 +227,19 @@ int GameBooter::SetupDisc(struct discHdr &gameHeader)
gprintf("Disc_SetUSB...");
ret = Disc_SetUSB(gameHeader.id);
gprintf("%d\n", ret);
if(ret < 0) return ret;
if (ret < 0)
return ret;
}
else
{
gprintf("Loading fragment list...");
ret = get_frag_list(gameHeader.id);
gprintf("%d\n", ret);
if(ret < 0) return ret;
if (ret < 0)
return ret;
ret = set_frag_list(gameHeader.id);
if(ret < 0) return ret;
if (ret < 0)
return ret;
gprintf("\tUSB set to game\n");
}
@ -228,6 +252,10 @@ int GameBooter::SetupDisc(struct discHdr &gameHeader)
void GameBooter::ShutDownDevices(int gameUSBPort)
{
bool usbconnected = false;
if (DeviceHandler::Instance()->USB0_Inserted() || DeviceHandler::Instance()->USB1_Inserted())
usbconnected = true;
gprintf("Shutting down devices...\n");
//! Flush all caches and close up all devices
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();
if(Settings.USBPort == 2)
//! Reset USB port because device handler changes it for cache flushing
if (Settings.USBPort == 2)
USBStorage2_SetPort(gameUSBPort);
USBStorage2_Deinit();
if (usbconnected)
USB_Deinitialize();
}
@ -251,7 +280,11 @@ int GameBooter::BootGame(struct discHdr *gameHdr)
struct discHdr gameHeader;
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)
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 deflicker = game_cfg->deflicker == INHERIT ? Settings.deflicker : game_cfg->deflicker;
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 alternatedol = game_cfg->loadalternatedol;
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()));
}
gprintf("Game title: %s\n", gameHeader.title);
if (PrivServChoice == PRIVSERV_CUSTOM)
gprintf("Custom address: %s\n", customAddress);
@ -358,6 +390,7 @@ int GameBooter::BootGame(struct discHdr *gameHdr)
LoadGameConfig(Settings.Cheatcodespath);
//! Setup NAND emulation
if (!exclude_game(gameHeader.id, true))
SetupNandEmu(NandEmuMode, NandEmuPath, gameHeader);
//! Setup disc stuff if we load a game
@ -392,9 +425,8 @@ int GameBooter::BootGame(struct discHdr *gameHdr)
if (es_fd >= 0)
{
// IOS Reload Block
if (reloadblock != OFF) {
if (reloadblock != OFF)
BlockIOSReload(es_fd, iosChoice);
}
// Check if new patch method for return to works otherwise old method will be used
if (PatchNewReturnTo(es_fd, returnToChoice) >= 0)
returnToChoice = 0; // Patch successful, no need for old method
@ -438,7 +470,6 @@ int GameBooter::BootGame(struct discHdr *gameHdr)
//! Do all the game patches
gprintf("Applying game patches...\n");
//! Now this code block is responsible for the private server patch
//! and the gecko code handler loading
@ -463,7 +494,6 @@ int GameBooter::BootGame(struct discHdr *gameHdr)
deflicker, sneekChoice, Hooktype, returnToChoice, PRIVSERV_OFF, customAddress);
}
//! Load Code handler if needed
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.
//! 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
bool excludeGame = false;
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)
{
if (patchFix480pChoice && !exclude_game(gameHeader.id))
PatchFix480p();
}
//! If we're NOT on Wiimmfi, patch the known 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 (PrivServChoice != PRIVSERV_WIIMMFI)
{
ocarina_patch(gameHeader.id);
}
patch_error_codes(gameHeader.id);
//! 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)
@ -614,7 +630,6 @@ int GameBooter::BootDIOSMIOS(struct discHdr *gameHdr)
}
}
// Check DIOS MIOS config for specific versions
if (currentMIOS != QUADFORCE && currentMIOS != QUADFORCE_USB)
{
@ -662,7 +677,8 @@ int GameBooter::BootDIOSMIOS(struct discHdr *gameHdr)
char disc2Path[255];
snprintf(disc2Path, sizeof(disc2Path), "%s", RealPath);
char *pathPtr = strrchr(disc2Path, '/');
if(pathPtr) *pathPtr = 0;
if (pathPtr)
*pathPtr = 0;
snprintf(disc2Path + strlen(disc2Path), sizeof(disc2Path) - strlen(disc2Path), "/disc2.iso");
if (CheckFile(disc2Path))
{
@ -675,7 +691,8 @@ int GameBooter::BootDIOSMIOS(struct discHdr *gameHdr)
}
const char *gcPath = strchr(RealPath, '/');
if(!gcPath) gcPath = "";
if (!gcPath)
gcPath = "";
char gamePath[255];
snprintf(gamePath, sizeof(gamePath), "%s", gcPath);
@ -683,7 +700,8 @@ int GameBooter::BootDIOSMIOS(struct discHdr *gameHdr)
if (bootDisc2)
{
char *pathPtr = strrchr(gamePath, '/');
if(pathPtr) *pathPtr = 0;
if (pathPtr)
*pathPtr = 0;
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)
{
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);
}
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)
dml_config->Config |= DML_CFG_BOOT_DISC2;
// Setup Video Mode
if (dmlVideoChoice == DML_VIDEO_NONE) // No video mode
{
@ -781,7 +799,6 @@ int GameBooter::BootDIOSMIOS(struct discHdr *gameHdr)
if (dmlProgressivePatch)
dml_config->VideoMode |= DML_VID_PROG_PATCH;
DCFlushRange(dml_config, sizeof(DML_CFG));
memcpy((u8 *)DML_CONFIG_ADDRESS_V1_2, dml_config, sizeof(DML_CFG));
DCFlushRange((u8 *)DML_CONFIG_ADDRESS_V1_2, sizeof(DML_CFG));
@ -866,13 +883,15 @@ int GameBooter::BootDevolution(struct discHdr *gameHdr)
}
fread(loader_bin, 1, size, f);
//read Devolution version
// Read Devolution version
char version[5];
fseek(f, 23, SEEK_SET);
fread(version, 1, 4, f);
char *ptr = strchr(version, ' ');
if(ptr) *ptr = 0;
else version[4] = 0;
if (ptr)
*ptr = 0;
else
version[4] = 0;
DEVO_version = atoi(version);
fclose(f);
@ -883,7 +902,6 @@ int GameBooter::BootDevolution(struct discHdr *gameHdr)
return -1;
}
// Devolution config
DEVO_CFG *devo_config = (DEVO_CFG *)0x80000020;
@ -895,14 +913,16 @@ int GameBooter::BootDevolution(struct discHdr *gameHdr)
snprintf(disc2, sizeof(disc2), "%s", RealPath);
char *pathPtr = strrchr(disc2, '/');
if(pathPtr) *pathPtr = 0;
if (pathPtr)
*pathPtr = 0;
snprintf(disc2 + strlen(disc2), sizeof(disc2) - strlen(disc2), "/disc2.iso");
if (CheckFile(disc2))
multiDisc = true;
snprintf(DEVO_memCard, sizeof(DEVO_memCard), "%s", RealPath); // Set memory card folder to Disc1 folder
char *ptr = strrchr(DEVO_memCard, '/');
if(ptr) *ptr = 0;
if (ptr)
*ptr = 0;
// Make sure the directory exists
char devoPath[20];
@ -922,8 +942,6 @@ int GameBooter::BootDevolution(struct discHdr *gameHdr)
memset(devo_config, 0, sizeof(*devo_config));
devo_config->signature = DEVO_SIG;
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->disc1_cluster = st1.st_ino; // set starting cluster for first disc ISO file
if (multiDisc)
@ -947,6 +965,7 @@ int GameBooter::BootDevolution(struct discHdr *gameHdr)
if (devoDiscDelayChoice && DEVO_version >= 234)
devo_config->options |= DEVO_CFG_DISC_DELAY;
// devo_config->options |= DEVO_CFG_PLAYLOG; // Playlog setting managed by USBLoaderGX features menu
if (devoProgressivePatch && DEVO_version >= 266)
{
devo_config->options |= DEVO_CFG_FORCE_480P;
@ -1004,7 +1023,6 @@ int GameBooter::BootDevolution(struct discHdr *gameHdr)
devo_config->memcard_cluster = st.st_ino;
}
// read 32 bytes of disc 1 to the start of MEM1
FILE *iso_file = fopen(disc1, "rb");
if (!iso_file)
@ -1050,7 +1068,6 @@ int GameBooter::BootDevolution(struct discHdr *gameHdr)
int GameBooter::BootNintendont(struct discHdr *gameHdr)
{
char RealPath[100];
if (gameHdr->type == TYPE_GAME_GC_DISC)
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();
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"));
return -1;
}
// Check if Nintendont boot.dol is available
char NIN_loader_path[255];
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
{
gprintf("NIN: Nintendont revision = %d \n", NINRev);
NINArgsboot = true; // no need to check argsboot string, 3.324+ supports it.
}
else
@ -1205,7 +1219,6 @@ int GameBooter::BootNintendont(struct discHdr *gameHdr)
NINRev = 304;
}
// checks argsboot
if (ninAutobootChoice)
{
@ -1250,7 +1263,6 @@ int GameBooter::BootNintendont(struct discHdr *gameHdr)
else if (NINRev >= 487)
NIN_cfg_version = 9;
// Check USB device
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));
}
// 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)
{
@ -1428,7 +1439,6 @@ int GameBooter::BootNintendont(struct discHdr *gameHdr)
return -1;
}
}
}
}
}
@ -1440,7 +1450,8 @@ int GameBooter::BootNintendont(struct discHdr *gameHdr)
char disc2Path[255];
snprintf(disc2Path, sizeof(disc2Path), "%s", RealPath);
char *pathPtr = strrchr(disc2Path, '/');
if(pathPtr) *pathPtr = 0;
if (pathPtr)
*pathPtr = 0;
snprintf(disc2Path + strlen(disc2Path), sizeof(disc2Path) - strlen(disc2Path), "/disc2.iso");
if (CheckFile(disc2Path))
{
@ -1452,7 +1463,8 @@ int GameBooter::BootNintendont(struct discHdr *gameHdr)
}
}
const char *gcPath = strchr(RealPath, '/');
if(!gcPath) gcPath = "";
if (!gcPath)
gcPath = "";
char gamePath[255];
snprintf(gamePath, sizeof(gamePath), "%s", gcPath);
@ -1460,7 +1472,8 @@ int GameBooter::BootNintendont(struct discHdr *gameHdr)
if (bootDisc2)
{
char *pathPtr = strrchr(gamePath, '/');
if(pathPtr) *pathPtr = 0;
if (pathPtr)
*pathPtr = 0;
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");
}
// Nintendont Config file settings
NIN_CFG *nin_config = NULL;
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->Version = NIN_cfg_version;
// Game path
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)
{
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);
}
else
@ -1509,7 +1521,6 @@ int GameBooter::BootNintendont(struct discHdr *gameHdr)
gprintf("NIN: Loading cheat %s\n", nin_config->CheatPath);
}
// Set other settings
if (ninDebugChoice && !isWiiU()) // only on Wii
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);
// if WiiVC, force creation and use of nincfg.bin file to fix a nintendont bug if HID is connected before launching it.
if (isWiiVC)
{
@ -1652,7 +1662,6 @@ int GameBooter::BootNintendont(struct discHdr *gameHdr)
snprintf(NINCfgPath, sizeof(NINCfgPath), "%s:/nincfg.bin", DeviceHandler::GetDevicePrefix(RealPath));
RemoveFile(NINCfgPath);
}
}
else if (ninSettingsChoice == ON || !NINArgsboot)
{
@ -1969,9 +1978,9 @@ void GameBooter::PatchSram(int language, bool patchVideoMode, bool progressive)
while (!__SYS_SyncSram())
usleep(100);
// Log Sram's first 20 bytes
/* char srambuff[64];
/*
char srambuff[64];
sram = __SYS_LockSram();
memcpy(srambuff, sram, 20);
__SYS_UnlockSram(0);

View File

@ -26,6 +26,7 @@ class GameBooter
static int BootGame(struct discHdr *gameHdr);
static int BootGCMode(struct discHdr *gameHdr);
private:
static bool exclude_game(u8 *gameid, bool skipChannels = false);
static void SetupAltDOL(u8 * gameID, u8 &alternatedol, u32 &alternatedoloffset);
static void SetupNandEmu(u8 NandEmuMode, const char *NandEmuPath, struct discHdr &gameHeader);
static int SetupDisc(struct discHdr &gameHeader);