Allow disabling SD cheats (this fixes e.g. Sm4sh from crashing)
This commit is contained in:
parent
ed5585bb50
commit
c431bce8dc
@ -30,14 +30,16 @@ extern "C" {
|
||||
|
||||
void InitSysFunctionPointers(void);
|
||||
|
||||
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 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);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // __SYS_FUNCTIONS_H_
|
||||
#endif
|
113
src/main.cpp
113
src/main.cpp
@ -20,11 +20,9 @@
|
||||
#include "patcher/function_patcher_gx2.h"
|
||||
#include "patcher/function_patcher_coreinit.h"
|
||||
#include "utils/sd_ip_reader.hpp"
|
||||
#include "fs/sd_fat_devoptab.h"
|
||||
|
||||
bool isCodeHandlerInstalled;
|
||||
|
||||
#define PRINT_TEXT2(x, y, ...) { snprintf(messageBuffer, 80, __VA_ARGS__); OSScreenPutFontEx(0, x, y, messageBuffer); OSScreenPutFontEx(1, x, y, messageBuffer); }
|
||||
bool isCodeHandlerInstalled = false;
|
||||
bool areSDCheatsEnabled = false;
|
||||
|
||||
typedef enum {
|
||||
EXIT,
|
||||
@ -36,16 +34,38 @@ void applyFunctionPatches() {
|
||||
patchIndividualMethodHooks(method_hooks_coreinit, method_hooks_size_coreinit, method_calls_coreinit);
|
||||
}
|
||||
|
||||
bool isSDAccessEnabled() {
|
||||
int result = mount_sd_fat("sd");
|
||||
void installCodeHandler() {
|
||||
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) {
|
||||
return false;
|
||||
}
|
||||
unsigned char *screenBuffer;
|
||||
|
||||
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 */
|
||||
@ -99,49 +119,38 @@ int Menu_Main(void) {
|
||||
// PatchMethodHooks();
|
||||
|
||||
memoryInitialize();
|
||||
|
||||
VPADInit();
|
||||
|
||||
// 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);
|
||||
initializeScreen();
|
||||
|
||||
char messageBuffer[80];
|
||||
int launchMethod;
|
||||
int update_screen = 1;
|
||||
int shouldUpdateScreen = 1;
|
||||
s32 vpadError = -1;
|
||||
VPADData vpad_data;
|
||||
|
||||
while (true) {
|
||||
VPADRead(0, &vpad_data, 1, &vpadError);
|
||||
|
||||
if (update_screen) {
|
||||
if (shouldUpdateScreen) {
|
||||
OSScreenClearBufferEx(0, 0);
|
||||
OSScreenClearBufferEx(1, 0);
|
||||
|
||||
InitSocketFunctionPointers();
|
||||
|
||||
// Build the IP address message
|
||||
char ipAddressMessageBuffer[64];
|
||||
InitSocketFunctionPointers();
|
||||
__os_snprintf(ipAddressMessageBuffer, 64, "Your Wii U's IP address: %i.%i.%i.%i",
|
||||
(hostIpAddress >> 24) & 0xFF, (hostIpAddress >> 16) & 0xFF, (hostIpAddress >> 8) & 0xFF,
|
||||
hostIpAddress & 0xFF);
|
||||
|
||||
PRINT_TEXT2(14, 1, "-- TCP Gecko Installer --")
|
||||
PRINT_TEXT2(7, 2, ipAddressMessageBuffer)
|
||||
PRINT_TEXT2(0, 5, "Press A to install TCP Gecko (with built-in code handler)...")
|
||||
PRINT_TEXT(14, 1, "-- TCP Gecko Installer --")
|
||||
PRINT_TEXT(7, 2, ipAddressMessageBuffer)
|
||||
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_TEXT2(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, 8, "Note:")
|
||||
PRINT_TEXT(0, 9, "* You can enable loading SD cheats with Mocha SD access")
|
||||
PRINT_TEXT(0, 10, "* Generate and store GCTUs to your SD card with JGecko U")
|
||||
|
||||
// testMount();
|
||||
/*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, 17, "Press Home to exit...")
|
||||
PRINT_TEXT(0, 17, "Press Home to exit...")
|
||||
|
||||
OSScreenFlipBuffersEx(0);
|
||||
OSScreenFlipBuffersEx(1);
|
||||
@ -163,27 +172,22 @@ int Menu_Main(void) {
|
||||
launchMethod = EXIT;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
// 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;
|
||||
} else if (pressedButtons & VPAD_BUTTON_A) {
|
||||
install();
|
||||
launchMethod = TCP_GECKO;
|
||||
initializeUDPLog();
|
||||
log_print("Patching functions\n");
|
||||
applyFunctionPatches();
|
||||
|
||||
break;
|
||||
} else if (pressedButtons & VPAD_BUTTON_X) {
|
||||
install();
|
||||
launchMethod = TCP_GECKO;
|
||||
areSDCheatsEnabled = true;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
// Button pressed ?
|
||||
update_screen = (pressedButtons & (VPAD_BUTTON_LEFT | VPAD_BUTTON_RIGHT | VPAD_BUTTON_UP | VPAD_BUTTON_DOWN))
|
||||
? 1 : 0;
|
||||
// Button pressed?
|
||||
shouldUpdateScreen = (pressedButtons &
|
||||
(VPAD_BUTTON_LEFT | VPAD_BUTTON_RIGHT | VPAD_BUTTON_UP | VPAD_BUTTON_DOWN)) ? 1 : 0;
|
||||
usleep(20 * 1000);
|
||||
}
|
||||
|
||||
@ -191,16 +195,17 @@ int Menu_Main(void) {
|
||||
asm volatile ("mr 2, %0" : : "r" (old_sdata2_start));
|
||||
|
||||
MEM1_free(screenBuffer);
|
||||
screenBuffer = NULL;
|
||||
|
||||
memoryRelease();
|
||||
|
||||
if (launchMethod == EXIT) {
|
||||
// RestoreInstructions();
|
||||
// Exit the installer
|
||||
return EXIT_SUCCESS;
|
||||
} else {
|
||||
// Launch system menu
|
||||
SYSLaunchMenu();
|
||||
}
|
||||
|
||||
// For each title load, relaunch the TCP Gecko
|
||||
return EXIT_RELAUNCH_ON_LOAD;
|
||||
}
|
||||
}
|
@ -13,6 +13,7 @@ extern "C" {
|
||||
int Menu_Main(void);
|
||||
|
||||
extern bool isCodeHandlerInstalled;
|
||||
extern bool areSDCheatsEnabled;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -5,11 +5,11 @@ int validateAddressRange(int starting_address, int ending_address) {
|
||||
return __OSValidateAddressSpaceRange(1, (void *) starting_address, ending_address - starting_address + 1);
|
||||
}
|
||||
|
||||
bool isValidDataAddress(int address) {
|
||||
/*bool isValidDataAddress(int address) {
|
||||
return OSIsAddressValid((const void *) address)
|
||||
&& address >= 0x10000000
|
||||
&& address < 0x50000000;
|
||||
}
|
||||
}*/
|
||||
|
||||
int roundUpToAligned(int number) {
|
||||
return (number + 3) & ~0x03;
|
||||
|
@ -39,4 +39,4 @@ void MEMBucket_free(void *ptr);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // __MEMORY_H_
|
||||
#endif
|
||||
|
@ -1,5 +1,5 @@
|
||||
#include "tcp_gecko.h"
|
||||
#include <iosuhax.h>
|
||||
// #include <iosuhax.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
@ -91,7 +91,7 @@ struct pygecko_bss_t {
|
||||
|
||||
#define VERSION_HASH 0x7FB223
|
||||
|
||||
ZEXTERN int ZEXPORT
|
||||
/*ZEXTERN int ZEXPORT
|
||||
deflateEnd OF((z_streamp
|
||||
strm));
|
||||
ZEXTERN int ZEXPORT
|
||||
@ -103,7 +103,7 @@ ZEXTERN int ZEXPORT
|
||||
deflate OF((z_streamp
|
||||
strm,
|
||||
int flush
|
||||
));
|
||||
));*/
|
||||
|
||||
// ########## Being socket_functions.h ############
|
||||
|
||||
@ -547,45 +547,45 @@ static int processCommands(struct pygecko_bss_t *bss, int clientfd) {
|
||||
|
||||
break;
|
||||
}
|
||||
case COMMAND_READ_MEMORY_COMPRESSED: {
|
||||
// Receive the starting address and length
|
||||
ret = recvwait(bss, clientfd, buffer, sizeof(int) * 2);
|
||||
CHECK_ERROR(ret < 0)
|
||||
int startingAddress = ((int *) buffer)[0];
|
||||
unsigned int inputLength = ((unsigned int *) buffer)[1];
|
||||
/*case COMMAND_READ_MEMORY_COMPRESSED: {
|
||||
// Receive the starting address and length
|
||||
ret = recvwait(bss, clientfd, buffer, sizeof(int) * 2);
|
||||
CHECK_ERROR(ret < 0)
|
||||
int startingAddress = ((int *) buffer)[0];
|
||||
unsigned int inputLength = ((unsigned int *) buffer)[1];
|
||||
|
||||
z_stream stream;
|
||||
memset(&stream, 0, sizeof(stream));
|
||||
stream.zalloc = Z_NULL;
|
||||
stream.zfree = Z_NULL;
|
||||
stream.opaque = Z_NULL;
|
||||
z_stream stream;
|
||||
memset(&stream, 0, sizeof(stream));
|
||||
stream.zalloc = Z_NULL;
|
||||
stream.zfree = Z_NULL;
|
||||
stream.opaque = Z_NULL;
|
||||
|
||||
// Initialize the stream struct
|
||||
ret = deflateInit(&stream, Z_BEST_COMPRESSION);
|
||||
ASSERT_INTEGER(ret, Z_OK, "deflateInit")
|
||||
// Initialize the stream struct
|
||||
ret = deflateInit(&stream, Z_BEST_COMPRESSION);
|
||||
ASSERT_INTEGER(ret, Z_OK, "deflateInit")
|
||||
|
||||
// Supply the data
|
||||
stream.avail_in = inputLength;
|
||||
stream.next_in = (Bytef *) startingAddress;
|
||||
stream.avail_out = DATA_BUFFER_SIZE;
|
||||
void *outputBuffer = (void *) (&buffer + 4);
|
||||
stream.next_out = (Bytef *) outputBuffer;
|
||||
// Supply the data
|
||||
stream.avail_in = inputLength;
|
||||
stream.next_in = (Bytef *) startingAddress;
|
||||
stream.avail_out = DATA_BUFFER_SIZE;
|
||||
void *outputBuffer = (void *) (&buffer + 4);
|
||||
stream.next_out = (Bytef *) outputBuffer;
|
||||
|
||||
// Deflate
|
||||
ret = deflate(&stream, Z_FINISH);
|
||||
ASSERT_INTEGER(ret, Z_OK, "deflate");
|
||||
// Deflate
|
||||
ret = deflate(&stream, Z_FINISH);
|
||||
ASSERT_INTEGER(ret, Z_OK, "deflate");
|
||||
|
||||
// Finish
|
||||
ret = deflateEnd(&stream);
|
||||
ASSERT_INTEGER(ret, Z_OK, "deflateEnd");
|
||||
// Finish
|
||||
ret = deflateEnd(&stream);
|
||||
ASSERT_INTEGER(ret, Z_OK, "deflateEnd");
|
||||
|
||||
// Send the compressed buffer size and content
|
||||
int deflatedSize = stream.total_out;
|
||||
((int *) buffer)[0] = deflatedSize;
|
||||
ret = sendwait(bss, clientfd, buffer, 4 + deflatedSize);
|
||||
ASSERT_FUNCTION_SUCCEEDED(ret, "sendwait (Compressed data)")
|
||||
// Send the compressed buffer size and content
|
||||
int deflatedSize = stream.total_out;
|
||||
((int *) buffer)[0] = deflatedSize;
|
||||
ret = sendwait(bss, clientfd, buffer, 4 + deflatedSize);
|
||||
ASSERT_FUNCTION_SUCCEEDED(ret, "sendwait (Compressed data)")
|
||||
|
||||
break;
|
||||
break;*/
|
||||
|
||||
// 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);
|
||||
|
||||
break;*/
|
||||
}
|
||||
// }
|
||||
case COMMAND_KERNEL_WRITE: {
|
||||
ret = recvwait(bss, clientfd, buffer, sizeof(int) * 2);
|
||||
CHECK_ERROR(ret < 0)
|
||||
@ -1098,21 +1098,29 @@ static int processCommands(struct pygecko_bss_t *bss, int clientfd) {
|
||||
}
|
||||
|
||||
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
|
||||
bool isValidDestinationAddress = isValidDataAddress(destinationAddress);
|
||||
#define INVALID_ADDRESS -1
|
||||
|
||||
// Bail out if invalid
|
||||
if (!isValidDestinationAddress) {
|
||||
destinationAddress = -1;
|
||||
if ((bool) OSIsAddressValid((const void *) destinationAddress)) {
|
||||
// Apply pointer offsets
|
||||
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
|
||||
@ -1128,14 +1136,14 @@ static int processCommands(struct pygecko_bss_t *bss, int clientfd) {
|
||||
break;
|
||||
}
|
||||
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;
|
||||
long long result;
|
||||
|
||||
ret = recvwait(bss, clientfd, buffer, 4 + 8 * 4);
|
||||
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];
|
||||
r4 = ((int *) buffer)[2];
|
||||
r5 = ((int *) buffer)[3];
|
||||
@ -1145,7 +1153,7 @@ static int processCommands(struct pygecko_bss_t *bss, int clientfd) {
|
||||
r9 = ((int *) buffer)[7];
|
||||
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;
|
||||
ret = sendwait(bss, clientfd, buffer, 8);
|
||||
@ -1381,7 +1389,7 @@ static int processCommands(struct pygecko_bss_t *bss, int clientfd) {
|
||||
break;
|
||||
}
|
||||
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;
|
||||
ret = sendwait(bss, clientfd, buffer, sizeof(int));
|
||||
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));
|
||||
if (bss == 0)
|
||||
return 0;
|
||||
return (s32) 0;
|
||||
memset(bss, 0, sizeof(struct pygecko_bss_t));
|
||||
|
||||
if (OSCreateThread(&bss->thread, (s32 (*)(s32, void *)) runTCPGeckoServer, 1, bss,
|
||||
@ -1518,13 +1526,15 @@ static s32 startTCPGeckoThread(s32 argc, void *argv) {
|
||||
executeAssembly();
|
||||
}
|
||||
|
||||
considerApplyingSDCheats();
|
||||
if (areSDCheatsEnabled) {
|
||||
considerApplyingSDCheats();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
log_print("Code handler not installed...\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
return (s32) 0;
|
||||
}
|
||||
|
||||
void startTCPGecko() {
|
||||
@ -1540,9 +1550,10 @@ void startTCPGecko() {
|
||||
ASSERT_ALLOCATED(thread, "TCP Gecko thread")
|
||||
|
||||
int status = OSCreateThread(thread, startTCPGeckoThread, (s32) 1,
|
||||
NULL, (s32) (stack + sizeof(stack)),
|
||||
NULL, (s32)(stack + sizeof(stack)),
|
||||
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")
|
||||
// OSSetThreadName(thread, "TCP Gecko");
|
||||
OSResumeThread(thread);
|
||||
|
@ -2,7 +2,7 @@
|
||||
#include "title.h"
|
||||
|
||||
bool isRunningTitleID(unsigned long long int japaneseTitleID) {
|
||||
unsigned long long int currentTitleID = (unsigned long long int) OSGetTitleID();
|
||||
u64 currentTitleID = OSGetTitleID();
|
||||
return currentTitleID == japaneseTitleID // JAP
|
||||
|| currentTitleID == japaneseTitleID + 0x100 // USA
|
||||
|| currentTitleID == japaneseTitleID + 0x200; // EUR
|
||||
@ -12,6 +12,6 @@ bool isRunningAllowedTitleID() {
|
||||
return OSGetTitleID != 0
|
||||
&& !isRunningTitleID(TITLE_ID_MII_VERSE)
|
||||
&& !isRunningTitleID(TITLE_ID_MII_MAKER)
|
||||
&& !isRunningTitleID(TITLE_ID_BAYONETTA_2)
|
||||
// && !isRunningTitleID(TITLE_ID_BAYONETTA_2)
|
||||
&& !isRunningTitleID(TITLE_ID_INTERNET_BROWSER);
|
||||
}
|
BIN
tcpgecko.elf
BIN
tcpgecko.elf
Binary file not shown.
Loading…
Reference in New Issue
Block a user