2020-06-12 20:51:21 +02:00
|
|
|
#include "hooks_patcher_static.h"
|
2024-11-27 20:44:36 +01:00
|
|
|
|
|
|
|
#include "globals.h"
|
|
|
|
#include "utils/config/ConfigUtils.h"
|
|
|
|
|
2020-04-29 18:02:36 +02:00
|
|
|
#include <coreinit/core.h>
|
2022-02-04 16:25:44 +01:00
|
|
|
#include <coreinit/messagequeue.h>
|
2024-11-27 20:44:36 +01:00
|
|
|
#include <hooks.h>
|
2022-02-04 16:25:44 +01:00
|
|
|
#include <padscore/wpad.h>
|
|
|
|
#include <vpad/input.h>
|
2019-02-08 16:42:39 +01:00
|
|
|
|
2024-05-03 15:07:07 +02:00
|
|
|
static uint8_t sVpadPressCooldown = 0xFF;
|
|
|
|
static bool sWantsToOpenConfigMenu = false;
|
2021-04-07 00:23:23 +02:00
|
|
|
|
|
|
|
DECL_FUNCTION(void, GX2SwapScanBuffers, void) {
|
|
|
|
real_GX2SwapScanBuffers();
|
|
|
|
|
2024-12-01 09:13:16 +01:00
|
|
|
if (sWantsToOpenConfigMenu && !gConfigMenuOpened) {
|
|
|
|
gConfigMenuOpened = true;
|
2021-04-07 00:23:23 +02:00
|
|
|
ConfigUtils::openConfigMenu();
|
2024-12-01 09:13:16 +01:00
|
|
|
gConfigMenuOpened = false;
|
2024-05-03 15:07:07 +02:00
|
|
|
sWantsToOpenConfigMenu = false;
|
2021-04-07 00:23:23 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
DECL_FUNCTION(void, GX2SetTVBuffer, void *buffer, uint32_t buffer_size, int32_t tv_render_mode, GX2SurfaceFormat format, GX2BufferingMode buffering_mode) {
|
2022-05-14 14:00:20 +02:00
|
|
|
gStoredTVBuffer.buffer = buffer;
|
|
|
|
gStoredTVBuffer.buffer_size = buffer_size;
|
|
|
|
gStoredTVBuffer.mode = tv_render_mode;
|
|
|
|
gStoredTVBuffer.surface_format = format;
|
|
|
|
gStoredTVBuffer.buffering_mode = buffering_mode;
|
2021-04-07 00:23:23 +02:00
|
|
|
|
2021-09-25 14:26:18 +02:00
|
|
|
return real_GX2SetTVBuffer(buffer, buffer_size, tv_render_mode, format, buffering_mode);
|
2021-04-07 00:23:23 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
DECL_FUNCTION(void, GX2SetDRCBuffer, void *buffer, uint32_t buffer_size, uint32_t drc_mode, GX2SurfaceFormat surface_format, GX2BufferingMode buffering_mode) {
|
2022-05-14 14:00:20 +02:00
|
|
|
gStoredDRCBuffer.buffer = buffer;
|
|
|
|
gStoredDRCBuffer.buffer_size = buffer_size;
|
|
|
|
gStoredDRCBuffer.mode = drc_mode;
|
|
|
|
gStoredDRCBuffer.surface_format = surface_format;
|
|
|
|
gStoredDRCBuffer.buffering_mode = buffering_mode;
|
2021-04-07 00:23:23 +02:00
|
|
|
|
2021-09-25 14:26:18 +02:00
|
|
|
return real_GX2SetDRCBuffer(buffer, buffer_size, drc_mode, surface_format, buffering_mode);
|
2019-02-08 16:42:39 +01:00
|
|
|
}
|
|
|
|
|
2019-11-16 15:12:30 +01:00
|
|
|
static uint32_t lastData0 = 0;
|
2021-09-25 14:26:18 +02:00
|
|
|
|
2024-05-03 15:08:24 +02:00
|
|
|
|
|
|
|
DECL_FUNCTION(BOOL, OSSendMessage, OSMessageQueue *queue, OSMessage *message, OSMessageFlags flags) {
|
2024-12-01 09:13:16 +01:00
|
|
|
if (gConfigMenuOpened && queue == OSGetSystemMessageQueue()) {
|
2024-05-03 15:08:24 +02:00
|
|
|
if (message != nullptr) {
|
|
|
|
if (message->args[0] == 0xfacebacc) { // Release foreground
|
|
|
|
gConfigMenuShouldClose = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return real_OSSendMessage(queue, message, flags);
|
|
|
|
}
|
|
|
|
|
2020-06-12 20:51:21 +02:00
|
|
|
DECL_FUNCTION(uint32_t, OSReceiveMessage, OSMessageQueue *queue, OSMessage *message, uint32_t flags) {
|
2024-11-27 20:44:36 +01:00
|
|
|
const uint32_t res = real_OSReceiveMessage(queue, message, flags);
|
2020-05-03 12:30:15 +02:00
|
|
|
if (queue == OSGetSystemMessageQueue()) {
|
2020-12-26 14:17:50 +01:00
|
|
|
if (message != nullptr && res) {
|
2020-05-03 12:30:15 +02:00
|
|
|
if (lastData0 != message->args[0]) {
|
|
|
|
if (message->args[0] == 0xFACEF000) {
|
2022-05-14 14:00:20 +02:00
|
|
|
CallHook(gLoadedPlugins, WUPS_LOADER_HOOK_ACQUIRED_FOREGROUND);
|
2020-05-03 12:30:15 +02:00
|
|
|
} else if (message->args[0] == 0xD1E0D1E0) {
|
2021-09-25 14:26:18 +02:00
|
|
|
// Implemented via WUMS Hook
|
2019-11-16 15:12:30 +01:00
|
|
|
}
|
|
|
|
}
|
2020-04-29 18:02:36 +02:00
|
|
|
lastData0 = message->args[0];
|
2019-11-16 15:12:30 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2020-06-12 20:51:21 +02:00
|
|
|
DECL_FUNCTION(void, OSReleaseForeground) {
|
2020-05-03 12:30:15 +02:00
|
|
|
if (OSGetCoreId() == 1) {
|
2022-05-14 14:00:20 +02:00
|
|
|
CallHook(gLoadedPlugins, WUPS_LOADER_HOOK_RELEASE_FOREGROUND);
|
2019-11-16 15:12:30 +01:00
|
|
|
}
|
|
|
|
real_OSReleaseForeground();
|
|
|
|
}
|
|
|
|
|
2024-07-05 16:00:16 +02:00
|
|
|
DECL_FUNCTION(int32_t, VPADRead, int32_t chan, VPADStatus *buffer, uint32_t buffer_size, VPADReadError *error) {
|
2024-12-01 09:13:16 +01:00
|
|
|
if (gConfigMenuOpened) {
|
2024-05-03 13:00:18 +02:00
|
|
|
// Ignore reading vpad input only from other threads if the config menu is opened
|
|
|
|
if (OSGetCurrentThread() != gOnlyAcceptFromThread) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
2024-07-05 16:00:16 +02:00
|
|
|
VPADReadError real_error = VPAD_READ_SUCCESS;
|
2024-11-27 20:44:36 +01:00
|
|
|
const int32_t result = real_VPADRead(chan, buffer, buffer_size, &real_error);
|
2024-07-05 16:00:16 +02:00
|
|
|
|
2024-12-01 09:13:16 +01:00
|
|
|
if (result > 0 && real_error == VPAD_READ_SUCCESS && buffer && ((buffer[0].hold & 0xFFFFF) == (VPAD_BUTTON_L | VPAD_BUTTON_DOWN | VPAD_BUTTON_MINUS)) && sVpadPressCooldown == 0 && !gConfigMenuOpened) {
|
2021-04-07 00:23:23 +02:00
|
|
|
|
2024-05-03 15:07:07 +02:00
|
|
|
sWantsToOpenConfigMenu = true;
|
|
|
|
sVpadPressCooldown = 0x3C;
|
2024-05-03 13:00:18 +02:00
|
|
|
return 0;
|
2021-04-07 00:23:23 +02:00
|
|
|
}
|
2024-07-05 16:00:16 +02:00
|
|
|
if (error) {
|
|
|
|
*error = real_error;
|
|
|
|
}
|
2021-04-07 00:23:23 +02:00
|
|
|
|
2024-05-03 15:07:07 +02:00
|
|
|
if (sVpadPressCooldown > 0) {
|
|
|
|
sVpadPressCooldown--;
|
2021-04-07 00:23:23 +02:00
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2024-11-27 20:44:36 +01:00
|
|
|
DECL_FUNCTION(void, WPADRead, WPADChan chan, WPADStatus *data) {
|
2021-04-07 00:23:23 +02:00
|
|
|
real_WPADRead(chan, data);
|
|
|
|
|
2024-12-01 09:13:16 +01:00
|
|
|
if (!gConfigMenuOpened && data && data->error == 0) {
|
|
|
|
if (const auto extensionType = data->extensionType; extensionType != 0xFF) {
|
2024-11-27 20:44:36 +01:00
|
|
|
if (extensionType == WPAD_EXT_CORE || extensionType == WPAD_EXT_NUNCHUK ||
|
|
|
|
extensionType == WPAD_EXT_MPLUS || extensionType == WPAD_EXT_MPLUS_NUNCHUK) {
|
|
|
|
if (data->buttons == (WPAD_BUTTON_B | WPAD_BUTTON_DOWN | WPAD_BUTTON_MINUS)) {
|
2024-05-03 15:07:07 +02:00
|
|
|
sWantsToOpenConfigMenu = true;
|
2022-09-19 15:57:29 +02:00
|
|
|
}
|
2024-11-27 20:44:36 +01:00
|
|
|
} else if (extensionType == WPAD_EXT_CLASSIC || extensionType == WPAD_EXT_MPLUS_CLASSIC) {
|
|
|
|
const auto *classic = reinterpret_cast<WPADStatusClassic *>(data);
|
|
|
|
if (classic->buttons == (WPAD_CLASSIC_BUTTON_L | WPAD_CLASSIC_BUTTON_DOWN | WPAD_CLASSIC_BUTTON_MINUS)) {
|
2024-05-03 15:07:07 +02:00
|
|
|
sWantsToOpenConfigMenu = true;
|
2022-09-19 15:57:29 +02:00
|
|
|
}
|
2024-11-27 20:44:36 +01:00
|
|
|
} else if (extensionType == WPAD_EXT_PRO_CONTROLLER) {
|
|
|
|
const auto *pro = reinterpret_cast<WPADStatusPro *>(data);
|
|
|
|
if (pro->buttons == (WPAD_PRO_TRIGGER_L | WPAD_PRO_BUTTON_DOWN | WPAD_PRO_BUTTON_MINUS)) {
|
2024-05-03 15:07:07 +02:00
|
|
|
sWantsToOpenConfigMenu = true;
|
2022-09-19 15:57:29 +02:00
|
|
|
}
|
2021-04-07 00:23:23 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-02-11 22:18:15 +01:00
|
|
|
// clang-format off
|
|
|
|
#define KiReport ((void(*)(const char *, ...)) 0xfff0ad0c)
|
|
|
|
// clang-format on
|
2021-12-15 17:04:30 +01:00
|
|
|
|
|
|
|
#pragma GCC push_options
|
2022-02-04 16:25:44 +01:00
|
|
|
#pragma GCC optimize("O0")
|
2021-12-15 17:04:30 +01:00
|
|
|
|
|
|
|
DECL_FUNCTION(uint32_t, SC17_FindClosestSymbol,
|
|
|
|
uint32_t addr,
|
|
|
|
uint32_t *outDistance,
|
|
|
|
char *symbolNameBuffer,
|
|
|
|
uint32_t symbolNameBufferLength,
|
|
|
|
char *moduleNameBuffer,
|
|
|
|
uint32_t moduleNameBufferLength) {
|
2023-11-04 15:32:45 +01:00
|
|
|
for (const auto &plugin : gLoadedPlugins) {
|
2024-03-24 07:40:58 +01:00
|
|
|
const auto sectionInfo = plugin.getPluginInformation().getSectionInfo(".text");
|
2023-11-04 15:32:45 +01:00
|
|
|
if (!sectionInfo) {
|
2021-12-15 17:04:30 +01:00
|
|
|
continue;
|
|
|
|
}
|
2022-05-14 14:00:20 +02:00
|
|
|
|
|
|
|
if (!sectionInfo->isInSection(addr)) {
|
2021-12-15 17:04:30 +01:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2024-03-24 07:40:58 +01:00
|
|
|
strncpy(moduleNameBuffer, plugin.getMetaInformation().getName().c_str(), moduleNameBufferLength - 1);
|
2024-11-27 20:44:36 +01:00
|
|
|
if (const auto functionSymbolData = plugin.getPluginInformation().getNearestFunctionSymbolData(addr)) {
|
2023-11-04 15:32:45 +01:00
|
|
|
strncpy(symbolNameBuffer, functionSymbolData->getName().c_str(), moduleNameBufferLength - 1);
|
2022-05-14 14:00:20 +02:00
|
|
|
if (outDistance) {
|
2024-11-27 20:44:36 +01:00
|
|
|
*outDistance = addr - reinterpret_cast<uint32_t>(functionSymbolData->getAddress());
|
2021-12-15 17:04:30 +01:00
|
|
|
}
|
2022-05-14 14:00:20 +02:00
|
|
|
return 0;
|
2021-12-15 17:04:30 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
strncpy(symbolNameBuffer, ".text", symbolNameBufferLength);
|
|
|
|
|
|
|
|
if (outDistance) {
|
2024-11-27 20:44:36 +01:00
|
|
|
*outDistance = addr - sectionInfo->getAddress();
|
2021-12-15 17:04:30 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return real_SC17_FindClosestSymbol(addr, outDistance, symbolNameBuffer, symbolNameBufferLength, moduleNameBuffer, moduleNameBufferLength);
|
|
|
|
}
|
|
|
|
|
|
|
|
DECL_FUNCTION(uint32_t, KiGetAppSymbolName, uint32_t addr, char *buffer, int32_t bufSize) {
|
2023-11-04 15:32:45 +01:00
|
|
|
for (const auto &plugin : gLoadedPlugins) {
|
2024-03-24 07:40:58 +01:00
|
|
|
const auto sectionInfo = plugin.getPluginInformation().getSectionInfo(".text");
|
2023-11-04 15:32:45 +01:00
|
|
|
if (!sectionInfo) {
|
2021-12-15 17:04:30 +01:00
|
|
|
continue;
|
|
|
|
}
|
2022-05-14 14:00:20 +02:00
|
|
|
|
|
|
|
if (!sectionInfo->isInSection(addr)) {
|
2021-12-15 17:04:30 +01:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2024-11-27 20:44:36 +01:00
|
|
|
const auto pluginNameLen = strlen(plugin.getMetaInformation().getName().c_str());
|
|
|
|
int32_t spaceLeftInBuffer = bufSize - static_cast<int32_t>(pluginNameLen) - 1;
|
2021-12-15 17:04:30 +01:00
|
|
|
if (spaceLeftInBuffer < 0) {
|
|
|
|
spaceLeftInBuffer = 0;
|
|
|
|
}
|
2024-03-24 07:40:58 +01:00
|
|
|
strncpy(buffer, plugin.getMetaInformation().getName().c_str(), bufSize - 1);
|
2022-05-14 14:00:20 +02:00
|
|
|
|
2024-11-27 20:44:36 +01:00
|
|
|
if (const auto functionSymbolData = plugin.getPluginInformation().getNearestFunctionSymbolData(addr)) {
|
2022-05-14 14:00:20 +02:00
|
|
|
buffer[pluginNameLen] = '|';
|
|
|
|
buffer[pluginNameLen + 1] = '\0';
|
|
|
|
strncpy(buffer + pluginNameLen + 1, functionSymbolData->getName().c_str(), spaceLeftInBuffer - 1);
|
2021-12-15 17:04:30 +01:00
|
|
|
}
|
2022-05-14 14:00:20 +02:00
|
|
|
|
|
|
|
return 0;
|
2021-12-15 17:04:30 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return real_KiGetAppSymbolName(addr, buffer, bufSize);
|
|
|
|
}
|
2022-01-27 12:47:33 +01:00
|
|
|
|
2021-12-15 17:04:30 +01:00
|
|
|
#pragma GCC pop_options
|
|
|
|
|
2022-05-14 14:00:20 +02:00
|
|
|
function_replacement_data_t method_hooks_static[] __attribute__((section(".data"))) = {
|
2021-09-25 14:26:18 +02:00
|
|
|
REPLACE_FUNCTION(GX2SwapScanBuffers, LIBRARY_GX2, GX2SwapScanBuffers),
|
|
|
|
REPLACE_FUNCTION(GX2SetTVBuffer, LIBRARY_GX2, GX2SetTVBuffer),
|
|
|
|
REPLACE_FUNCTION(GX2SetDRCBuffer, LIBRARY_GX2, GX2SetDRCBuffer),
|
2024-05-03 15:08:24 +02:00
|
|
|
REPLACE_FUNCTION(OSSendMessage, LIBRARY_COREINIT, OSSendMessage),
|
2021-09-25 14:26:18 +02:00
|
|
|
REPLACE_FUNCTION(OSReceiveMessage, LIBRARY_COREINIT, OSReceiveMessage),
|
|
|
|
REPLACE_FUNCTION(OSReleaseForeground, LIBRARY_COREINIT, OSReleaseForeground),
|
|
|
|
REPLACE_FUNCTION(VPADRead, LIBRARY_VPAD, VPADRead),
|
|
|
|
REPLACE_FUNCTION(WPADRead, LIBRARY_PADSCORE, WPADRead),
|
2021-12-15 17:04:30 +01:00
|
|
|
REPLACE_FUNCTION_VIA_ADDRESS(SC17_FindClosestSymbol, 0xfff10218, 0xfff10218),
|
|
|
|
REPLACE_FUNCTION_VIA_ADDRESS(KiGetAppSymbolName, 0xfff0e3a0, 0xfff0e3a0),
|
2019-02-08 16:42:39 +01:00
|
|
|
};
|
|
|
|
|
2024-05-13 01:33:07 +02:00
|
|
|
uint32_t method_hooks_static_size __attribute__((section(".data"))) = sizeof(method_hooks_static) / sizeof(function_replacement_data_t);
|