Allow disabling SD cheats (this fixes e.g. Sm4sh from crashing)

This commit is contained in:
BullyWiiPlaza 2017-09-14 18:06:19 +02:00
parent ed5585bb50
commit c431bce8dc
8 changed files with 139 additions and 120 deletions

View File

@ -30,14 +30,16 @@ extern "C" {
void InitSysFunctionPointers(void); void InitSysFunctionPointers(void);
extern void(*_SYSLaunchTitleByPathFromLauncher)(const char* path, int len, int zero); extern void (*_SYSLaunchTitleByPathFromLauncher)(const char *path, int len, int zero);
extern int (* SYSRelaunchTitle)(int argc, char* argv);
extern int (* SYSLaunchMenu)(void);
extern int (* SYSCheckTitleExists)(u64 titleId);
extern int (*SYSRelaunchTitle)(int argc, char *argv);
extern int (*SYSLaunchMenu)(void);
extern int (*SYSCheckTitleExists)(u64 titleId);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif // __SYS_FUNCTIONS_H_ #endif

View File

@ -20,11 +20,9 @@
#include "patcher/function_patcher_gx2.h" #include "patcher/function_patcher_gx2.h"
#include "patcher/function_patcher_coreinit.h" #include "patcher/function_patcher_coreinit.h"
#include "utils/sd_ip_reader.hpp" #include "utils/sd_ip_reader.hpp"
#include "fs/sd_fat_devoptab.h"
bool isCodeHandlerInstalled; bool isCodeHandlerInstalled = false;
bool areSDCheatsEnabled = false;
#define PRINT_TEXT2(x, y, ...) { snprintf(messageBuffer, 80, __VA_ARGS__); OSScreenPutFontEx(0, x, y, messageBuffer); OSScreenPutFontEx(1, x, y, messageBuffer); }
typedef enum { typedef enum {
EXIT, EXIT,
@ -36,16 +34,38 @@ void applyFunctionPatches() {
patchIndividualMethodHooks(method_hooks_coreinit, method_hooks_size_coreinit, method_calls_coreinit); patchIndividualMethodHooks(method_hooks_coreinit, method_hooks_size_coreinit, method_calls_coreinit);
} }
bool isSDAccessEnabled() { void installCodeHandler() {
int result = mount_sd_fat("sd"); unsigned int physicalCodeHandlerAddress = (unsigned int) OSEffectiveToPhysical(
(void *) CODE_HANDLER_INSTALL_ADDRESS);
SC0x25_KernelCopyData((u32) physicalCodeHandlerAddress, (unsigned int) codeHandler, codeHandlerLength);
DCFlushRange((const void *) CODE_HANDLER_INSTALL_ADDRESS, (u32) codeHandlerLength);
isCodeHandlerInstalled = true;
}
if (result < 0) { unsigned char *screenBuffer;
return false;
}
unmount_sd_fat("sd"); #define PRINT_TEXT(x, y, ...) { snprintf(messageBuffer, 80, __VA_ARGS__); OSScreenPutFontEx(0, x, y, messageBuffer); OSScreenPutFontEx(1, x, y, messageBuffer); }
return true; void initializeScreen() {
// Init screen and screen buffers
OSScreenInit();
unsigned int screenBuffer0Size = OSScreenGetBufferSizeEx(0);
unsigned int screenBuffer1Size = OSScreenGetBufferSizeEx(1);
screenBuffer = (unsigned char *) MEM1_alloc(screenBuffer0Size + screenBuffer1Size, 0x40);
OSScreenSetBufferEx(0, screenBuffer);
OSScreenSetBufferEx(1, (screenBuffer + screenBuffer0Size));
OSScreenEnableEx(0, 1);
OSScreenEnableEx(1, 1);
}
void install() {
installCodeHandler();
initializeUDPLog();
log_print("Patching functions\n");
applyFunctionPatches();
} }
/* Entry point */ /* Entry point */
@ -99,49 +119,38 @@ int Menu_Main(void) {
// PatchMethodHooks(); // PatchMethodHooks();
memoryInitialize(); memoryInitialize();
VPADInit(); VPADInit();
initializeScreen();
// Init screen and screen buffers
OSScreenInit();
int screenBuffer0Size = OSScreenGetBufferSizeEx(0);
int screenBuffer1Size = OSScreenGetBufferSizeEx(1);
unsigned char *screenBuffer = (unsigned char *) MEM1_alloc(screenBuffer0Size + screenBuffer1Size, 0x40);
OSScreenSetBufferEx(0, screenBuffer);
OSScreenSetBufferEx(1, (screenBuffer + screenBuffer0Size));
OSScreenEnableEx(0, 1);
OSScreenEnableEx(1, 1);
char messageBuffer[80]; char messageBuffer[80];
int launchMethod; int launchMethod;
int update_screen = 1; int shouldUpdateScreen = 1;
s32 vpadError = -1; s32 vpadError = -1;
VPADData vpad_data; VPADData vpad_data;
while (true) { while (true) {
VPADRead(0, &vpad_data, 1, &vpadError); VPADRead(0, &vpad_data, 1, &vpadError);
if (update_screen) { if (shouldUpdateScreen) {
OSScreenClearBufferEx(0, 0); OSScreenClearBufferEx(0, 0);
OSScreenClearBufferEx(1, 0); OSScreenClearBufferEx(1, 0);
InitSocketFunctionPointers();
// Build the IP address message // Build the IP address message
char ipAddressMessageBuffer[64]; char ipAddressMessageBuffer[64];
InitSocketFunctionPointers();
__os_snprintf(ipAddressMessageBuffer, 64, "Your Wii U's IP address: %i.%i.%i.%i", __os_snprintf(ipAddressMessageBuffer, 64, "Your Wii U's IP address: %i.%i.%i.%i",
(hostIpAddress >> 24) & 0xFF, (hostIpAddress >> 16) & 0xFF, (hostIpAddress >> 8) & 0xFF, (hostIpAddress >> 24) & 0xFF, (hostIpAddress >> 16) & 0xFF, (hostIpAddress >> 8) & 0xFF,
hostIpAddress & 0xFF); hostIpAddress & 0xFF);
PRINT_TEXT2(14, 1, "-- TCP Gecko Installer --") PRINT_TEXT(14, 1, "-- TCP Gecko Installer --")
PRINT_TEXT2(7, 2, ipAddressMessageBuffer) PRINT_TEXT(7, 2, ipAddressMessageBuffer)
PRINT_TEXT2(0, 5, "Press A to install TCP Gecko (with built-in code handler)...") PRINT_TEXT(0, 5, "Press A to install TCP Gecko (with built-in code handler)...")
PRINT_TEXT(0, 6, "Press X to install TCP Gecko (with code handler and SD cheats)...")
PRINT_TEXT2(0, 8, "Note:") PRINT_TEXT(0, 8, "Note:")
PRINT_TEXT2(0, 9, "* You can enable loading SD cheats with Mocha SD access") PRINT_TEXT(0, 9, "* You can enable loading SD cheats with Mocha SD access")
PRINT_TEXT2(0, 10, "* Generate and store GCTUs to your SD card with JGecko U") PRINT_TEXT(0, 10, "* Generate and store GCTUs to your SD card with JGecko U")
// testMount(); // testMount();
/*if (isSDAccessEnabled()) { /*if (isSDAccessEnabled()) {
@ -150,7 +159,7 @@ int Menu_Main(void) {
PRINT_TEXT2(0, 8, "No SD card access: Please run Mocha SD Access by maschell for SD cheat support...") PRINT_TEXT2(0, 8, "No SD card access: Please run Mocha SD Access by maschell for SD cheat support...")
}*/ }*/
PRINT_TEXT2(0, 17, "Press Home to exit...") PRINT_TEXT(0, 17, "Press Home to exit...")
OSScreenFlipBuffersEx(0); OSScreenFlipBuffersEx(0);
OSScreenFlipBuffersEx(1); OSScreenFlipBuffersEx(1);
@ -163,27 +172,22 @@ int Menu_Main(void) {
launchMethod = EXIT; launchMethod = EXIT;
break; break;
} } else if (pressedButtons & VPAD_BUTTON_A) {
install();
// A Button pressed
if (pressedButtons & VPAD_BUTTON_A) {
unsigned int physicalCodeHandlerAddress = (unsigned int) OSEffectiveToPhysical(
(void *) CODE_HANDLER_INSTALL_ADDRESS);
SC0x25_KernelCopyData((u32) physicalCodeHandlerAddress, (unsigned int) codeHandler, codeHandlerLength);
DCFlushRange((const void *) CODE_HANDLER_INSTALL_ADDRESS, (u32) codeHandlerLength);
isCodeHandlerInstalled = true;
launchMethod = TCP_GECKO; launchMethod = TCP_GECKO;
initializeUDPLog();
log_print("Patching functions\n"); break;
applyFunctionPatches(); } else if (pressedButtons & VPAD_BUTTON_X) {
install();
launchMethod = TCP_GECKO;
areSDCheatsEnabled = true;
break; break;
} }
// Button pressed ? // Button pressed?
update_screen = (pressedButtons & (VPAD_BUTTON_LEFT | VPAD_BUTTON_RIGHT | VPAD_BUTTON_UP | VPAD_BUTTON_DOWN)) shouldUpdateScreen = (pressedButtons &
? 1 : 0; (VPAD_BUTTON_LEFT | VPAD_BUTTON_RIGHT | VPAD_BUTTON_UP | VPAD_BUTTON_DOWN)) ? 1 : 0;
usleep(20 * 1000); usleep(20 * 1000);
} }
@ -191,16 +195,17 @@ int Menu_Main(void) {
asm volatile ("mr 2, %0" : : "r" (old_sdata2_start)); asm volatile ("mr 2, %0" : : "r" (old_sdata2_start));
MEM1_free(screenBuffer); MEM1_free(screenBuffer);
screenBuffer = NULL;
memoryRelease(); memoryRelease();
if (launchMethod == EXIT) { if (launchMethod == EXIT) {
// RestoreInstructions(); // Exit the installer
return EXIT_SUCCESS; return EXIT_SUCCESS;
} else { } else {
// Launch system menu
SYSLaunchMenu(); SYSLaunchMenu();
} }
// For each title load, relaunch the TCP Gecko
return EXIT_RELAUNCH_ON_LOAD; return EXIT_RELAUNCH_ON_LOAD;
} }

View File

@ -13,6 +13,7 @@ extern "C" {
int Menu_Main(void); int Menu_Main(void);
extern bool isCodeHandlerInstalled; extern bool isCodeHandlerInstalled;
extern bool areSDCheatsEnabled;
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -5,11 +5,11 @@ int validateAddressRange(int starting_address, int ending_address) {
return __OSValidateAddressSpaceRange(1, (void *) starting_address, ending_address - starting_address + 1); return __OSValidateAddressSpaceRange(1, (void *) starting_address, ending_address - starting_address + 1);
} }
bool isValidDataAddress(int address) { /*bool isValidDataAddress(int address) {
return OSIsAddressValid((const void *) address) return OSIsAddressValid((const void *) address)
&& address >= 0x10000000 && address >= 0x10000000
&& address < 0x50000000; && address < 0x50000000;
} }*/
int roundUpToAligned(int number) { int roundUpToAligned(int number) {
return (number + 3) & ~0x03; return (number + 3) & ~0x03;

View File

@ -39,4 +39,4 @@ void MEMBucket_free(void *ptr);
} }
#endif #endif
#endif // __MEMORY_H_ #endif

View File

@ -1,5 +1,5 @@
#include "tcp_gecko.h" #include "tcp_gecko.h"
#include <iosuhax.h> // #include <iosuhax.h>
#include <stdarg.h> #include <stdarg.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
@ -91,7 +91,7 @@ struct pygecko_bss_t {
#define VERSION_HASH 0x7FB223 #define VERSION_HASH 0x7FB223
ZEXTERN int ZEXPORT /*ZEXTERN int ZEXPORT
deflateEnd OF((z_streamp deflateEnd OF((z_streamp
strm)); strm));
ZEXTERN int ZEXPORT ZEXTERN int ZEXPORT
@ -103,7 +103,7 @@ ZEXTERN int ZEXPORT
deflate OF((z_streamp deflate OF((z_streamp
strm, strm,
int flush int flush
)); ));*/
// ########## Being socket_functions.h ############ // ########## Being socket_functions.h ############
@ -547,45 +547,45 @@ static int processCommands(struct pygecko_bss_t *bss, int clientfd) {
break; break;
} }
case COMMAND_READ_MEMORY_COMPRESSED: { /*case COMMAND_READ_MEMORY_COMPRESSED: {
// Receive the starting address and length // Receive the starting address and length
ret = recvwait(bss, clientfd, buffer, sizeof(int) * 2); ret = recvwait(bss, clientfd, buffer, sizeof(int) * 2);
CHECK_ERROR(ret < 0) CHECK_ERROR(ret < 0)
int startingAddress = ((int *) buffer)[0]; int startingAddress = ((int *) buffer)[0];
unsigned int inputLength = ((unsigned int *) buffer)[1]; unsigned int inputLength = ((unsigned int *) buffer)[1];
z_stream stream; z_stream stream;
memset(&stream, 0, sizeof(stream)); memset(&stream, 0, sizeof(stream));
stream.zalloc = Z_NULL; stream.zalloc = Z_NULL;
stream.zfree = Z_NULL; stream.zfree = Z_NULL;
stream.opaque = Z_NULL; stream.opaque = Z_NULL;
// Initialize the stream struct // Initialize the stream struct
ret = deflateInit(&stream, Z_BEST_COMPRESSION); ret = deflateInit(&stream, Z_BEST_COMPRESSION);
ASSERT_INTEGER(ret, Z_OK, "deflateInit") ASSERT_INTEGER(ret, Z_OK, "deflateInit")
// Supply the data // Supply the data
stream.avail_in = inputLength; stream.avail_in = inputLength;
stream.next_in = (Bytef *) startingAddress; stream.next_in = (Bytef *) startingAddress;
stream.avail_out = DATA_BUFFER_SIZE; stream.avail_out = DATA_BUFFER_SIZE;
void *outputBuffer = (void *) (&buffer + 4); void *outputBuffer = (void *) (&buffer + 4);
stream.next_out = (Bytef *) outputBuffer; stream.next_out = (Bytef *) outputBuffer;
// Deflate // Deflate
ret = deflate(&stream, Z_FINISH); ret = deflate(&stream, Z_FINISH);
ASSERT_INTEGER(ret, Z_OK, "deflate"); ASSERT_INTEGER(ret, Z_OK, "deflate");
// Finish // Finish
ret = deflateEnd(&stream); ret = deflateEnd(&stream);
ASSERT_INTEGER(ret, Z_OK, "deflateEnd"); ASSERT_INTEGER(ret, Z_OK, "deflateEnd");
// Send the compressed buffer size and content // Send the compressed buffer size and content
int deflatedSize = stream.total_out; int deflatedSize = stream.total_out;
((int *) buffer)[0] = deflatedSize; ((int *) buffer)[0] = deflatedSize;
ret = sendwait(bss, clientfd, buffer, 4 + deflatedSize); ret = sendwait(bss, clientfd, buffer, 4 + deflatedSize);
ASSERT_FUNCTION_SUCCEEDED(ret, "sendwait (Compressed data)") ASSERT_FUNCTION_SUCCEEDED(ret, "sendwait (Compressed data)")
break; break;*/
// https://www.gamedev.net/resources/_/technical/game-programming/in-memory-data-compression-and-decompression-r2279 // https://www.gamedev.net/resources/_/technical/game-programming/in-memory-data-compression-and-decompression-r2279
/* /*
@ -620,7 +620,7 @@ static int processCommands(struct pygecko_bss_t *bss, int clientfd) {
OSFreeToSystem(compressedBuffer); OSFreeToSystem(compressedBuffer);
break;*/ break;*/
} // }
case COMMAND_KERNEL_WRITE: { case COMMAND_KERNEL_WRITE: {
ret = recvwait(bss, clientfd, buffer, sizeof(int) * 2); ret = recvwait(bss, clientfd, buffer, sizeof(int) * 2);
CHECK_ERROR(ret < 0) CHECK_ERROR(ret < 0)
@ -1098,21 +1098,29 @@ static int processCommands(struct pygecko_bss_t *bss, int clientfd) {
} }
int destinationAddress = baseAddress; int destinationAddress = baseAddress;
// Apply pointer offsets
for (offsetIndex = 0; offsetIndex < offsetsCount; offsetIndex++) {
int pointerValue = *(int *) destinationAddress;
int offset = offsets[offsetIndex];
destinationAddress = pointerValue + offset;
// Validate the pointer address #define INVALID_ADDRESS -1
bool isValidDestinationAddress = isValidDataAddress(destinationAddress);
// Bail out if invalid if ((bool) OSIsAddressValid((const void *) destinationAddress)) {
if (!isValidDestinationAddress) { // Apply pointer offsets
destinationAddress = -1; for (offsetIndex = 0; offsetIndex < offsetsCount; offsetIndex++) {
int pointerValue = *(int *) destinationAddress;
int offset = offsets[offsetIndex];
destinationAddress = pointerValue + offset;
break; // Validate the pointer address
bool isValidDestinationAddress = (bool) OSIsAddressValid((const void *) destinationAddress);
// Bail out if invalid
if (!isValidDestinationAddress) {
destinationAddress = INVALID_ADDRESS;
break;
}
} }
} else if (offsetsCount > 0) {
// Following pointers failed
destinationAddress = INVALID_ADDRESS;
} }
// Return the destination address // Return the destination address
@ -1128,14 +1136,14 @@ static int processCommands(struct pygecko_bss_t *bss, int clientfd) {
break; break;
} }
case COMMAND_REMOTE_PROCEDURE_CALL: { case COMMAND_REMOTE_PROCEDURE_CALL: {
long long (*fun)(int, int, int, int, int, int, int, int); long long (*function)(int, int, int, int, int, int, int, int);
int r3, r4, r5, r6, r7, r8, r9, r10; int r3, r4, r5, r6, r7, r8, r9, r10;
long long result; long long result;
ret = recvwait(bss, clientfd, buffer, 4 + 8 * 4); ret = recvwait(bss, clientfd, buffer, 4 + 8 * 4);
CHECK_ERROR(ret < 0); CHECK_ERROR(ret < 0);
fun = (long long int (*)(int, int, int, int, int, int, int, int)) ((void **) buffer)[0]; function = (long long int (*)(int, int, int, int, int, int, int, int)) ((void **) buffer)[0];
r3 = ((int *) buffer)[1]; r3 = ((int *) buffer)[1];
r4 = ((int *) buffer)[2]; r4 = ((int *) buffer)[2];
r5 = ((int *) buffer)[3]; r5 = ((int *) buffer)[3];
@ -1145,7 +1153,7 @@ static int processCommands(struct pygecko_bss_t *bss, int clientfd) {
r9 = ((int *) buffer)[7]; r9 = ((int *) buffer)[7];
r10 = ((int *) buffer)[8]; r10 = ((int *) buffer)[8];
result = fun(r3, r4, r5, r6, r7, r8, r9, r10); result = function(r3, r4, r5, r6, r7, r8, r9, r10);
((long long *) buffer)[0] = result; ((long long *) buffer)[0] = result;
ret = sendwait(bss, clientfd, buffer, 8); ret = sendwait(bss, clientfd, buffer, 8);
@ -1381,7 +1389,7 @@ static int processCommands(struct pygecko_bss_t *bss, int clientfd) {
break; break;
} }
case COMMAND_GET_ENTRY_POINT_ADDRESS: { case COMMAND_GET_ENTRY_POINT_ADDRESS: {
u32 *entryPointAddress = (u32 *) *((u32 *) OS_SPECIFICS->addr_OSTitle_main_entry); u32 *entryPointAddress = (u32 * ) * ((u32 * )OS_SPECIFICS->addr_OSTitle_main_entry);
((u32 *) buffer)[0] = (u32) entryPointAddress; ((u32 *) buffer)[0] = (u32) entryPointAddress;
ret = sendwait(bss, clientfd, buffer, sizeof(int)); ret = sendwait(bss, clientfd, buffer, sizeof(int));
ASSERT_FUNCTION_SUCCEEDED(ret, "sendwait (Entry point address)"); ASSERT_FUNCTION_SUCCEEDED(ret, "sendwait (Entry point address)");
@ -1487,7 +1495,7 @@ static s32 startTCPGeckoThread(s32 argc, void *argv) {
bss = (struct pygecko_bss_t *) memalign(0x40, sizeof(struct pygecko_bss_t)); bss = (struct pygecko_bss_t *) memalign(0x40, sizeof(struct pygecko_bss_t));
if (bss == 0) if (bss == 0)
return 0; return (s32) 0;
memset(bss, 0, sizeof(struct pygecko_bss_t)); memset(bss, 0, sizeof(struct pygecko_bss_t));
if (OSCreateThread(&bss->thread, (s32 (*)(s32, void *)) runTCPGeckoServer, 1, bss, if (OSCreateThread(&bss->thread, (s32 (*)(s32, void *)) runTCPGeckoServer, 1, bss,
@ -1518,13 +1526,15 @@ static s32 startTCPGeckoThread(s32 argc, void *argv) {
executeAssembly(); executeAssembly();
} }
considerApplyingSDCheats(); if (areSDCheatsEnabled) {
considerApplyingSDCheats();
}
} }
} else { } else {
log_print("Code handler not installed...\n"); log_print("Code handler not installed...\n");
} }
return 0; return (s32) 0;
} }
void startTCPGecko() { void startTCPGecko() {
@ -1540,9 +1550,10 @@ void startTCPGecko() {
ASSERT_ALLOCATED(thread, "TCP Gecko thread") ASSERT_ALLOCATED(thread, "TCP Gecko thread")
int status = OSCreateThread(thread, startTCPGeckoThread, (s32) 1, int status = OSCreateThread(thread, startTCPGeckoThread, (s32) 1,
NULL, (s32) (stack + sizeof(stack)), NULL, (s32)(stack + sizeof(stack)),
sizeof(stack), 0, sizeof(stack), 0,
(OS_THREAD_ATTR_AFFINITY_CORE1 | OS_THREAD_ATTR_PINNED_AFFINITY | OS_THREAD_ATTR_DETACH)); (OS_THREAD_ATTR_AFFINITY_CORE1 | OS_THREAD_ATTR_PINNED_AFFINITY |
OS_THREAD_ATTR_DETACH));
ASSERT_INTEGER(status, 1, "Creating TCP Gecko thread") ASSERT_INTEGER(status, 1, "Creating TCP Gecko thread")
// OSSetThreadName(thread, "TCP Gecko"); // OSSetThreadName(thread, "TCP Gecko");
OSResumeThread(thread); OSResumeThread(thread);

View File

@ -2,7 +2,7 @@
#include "title.h" #include "title.h"
bool isRunningTitleID(unsigned long long int japaneseTitleID) { bool isRunningTitleID(unsigned long long int japaneseTitleID) {
unsigned long long int currentTitleID = (unsigned long long int) OSGetTitleID(); u64 currentTitleID = OSGetTitleID();
return currentTitleID == japaneseTitleID // JAP return currentTitleID == japaneseTitleID // JAP
|| currentTitleID == japaneseTitleID + 0x100 // USA || currentTitleID == japaneseTitleID + 0x100 // USA
|| currentTitleID == japaneseTitleID + 0x200; // EUR || currentTitleID == japaneseTitleID + 0x200; // EUR
@ -12,6 +12,6 @@ bool isRunningAllowedTitleID() {
return OSGetTitleID != 0 return OSGetTitleID != 0
&& !isRunningTitleID(TITLE_ID_MII_VERSE) && !isRunningTitleID(TITLE_ID_MII_VERSE)
&& !isRunningTitleID(TITLE_ID_MII_MAKER) && !isRunningTitleID(TITLE_ID_MII_MAKER)
&& !isRunningTitleID(TITLE_ID_BAYONETTA_2) // && !isRunningTitleID(TITLE_ID_BAYONETTA_2)
&& !isRunningTitleID(TITLE_ID_INTERNET_BROWSER); && !isRunningTitleID(TITLE_ID_INTERNET_BROWSER);
} }

Binary file not shown.