mirror of
https://github.com/wiiu-env/gdbstub_plugin.git
synced 2024-11-25 21:14:23 +01:00
WIP
This commit is contained in:
parent
5a3bae8616
commit
60a0679699
20
main.py
20
main.py
@ -116,6 +116,7 @@ COMMAND_TOGGLE_BREAKPOINT = 8
|
||||
COMMAND_POKE_REGISTERS = 9
|
||||
COMMAND_RECEIVE_MESSAGES = 10
|
||||
COMMAND_SEND_MESSAGE = 11
|
||||
COMMAND_DISASM = 12
|
||||
|
||||
class Debugger:
|
||||
def __init__(self):
|
||||
@ -158,6 +159,12 @@ class Debugger:
|
||||
data = self.recvall(num)
|
||||
return data
|
||||
|
||||
def disasm(self, addr, num):
|
||||
self.sendbyte(COMMAND_DISASM)
|
||||
self.sendall(struct.pack(">II", addr, num))
|
||||
length = struct.unpack(">I", self.recvall(4))[0]
|
||||
return self.recvall(length).decode("ascii")
|
||||
|
||||
def write(self, addr, data):
|
||||
self.sendbyte(COMMAND_WRITE)
|
||||
self.sendall(struct.pack(">II", addr, len(data)))
|
||||
@ -504,17 +511,10 @@ class DisassemblyWidget(QTextEdit):
|
||||
self.updateHighlight()
|
||||
|
||||
def updateText(self):
|
||||
if debugger.connected:
|
||||
blob = debugger.read(self.base, 0x60)
|
||||
else:
|
||||
blob = b"\x00" * 0x60
|
||||
|
||||
text = ""
|
||||
for i in range(24):
|
||||
address = self.base + i * 4
|
||||
value = struct.unpack_from(">I", blob, i * 4)[0]
|
||||
instr = disassemble.disassemble(value, address)
|
||||
text += "%08X: %08X %s\n" %(address, value, instr)
|
||||
if debugger.connected:
|
||||
text = debugger.disasm(self.base, 0x60)
|
||||
|
||||
self.setPlainText(text)
|
||||
|
||||
def updateHighlight(self):
|
||||
|
158
src/debugger.cpp
158
src/debugger.cpp
@ -7,20 +7,27 @@
|
||||
#include <coreinit/debug.h>
|
||||
#include <coreinit/dynload.h>
|
||||
#include <coreinit/exception.h>
|
||||
#include <coreinit/interrupts.h>
|
||||
#include <coreinit/memory.h>
|
||||
#include <coreinit/scheduler.h>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <gx2/context.h>
|
||||
#include <malloc.h>
|
||||
#include <sysapp/switch.h>
|
||||
#include <vpad/input.h>
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <string>
|
||||
|
||||
Debugger *debugger;
|
||||
bool initDebugState = false;
|
||||
|
||||
bool BreakPoint::isRange(uint32_t addr, uint32_t length) const {
|
||||
return address >= addr && address <= addr + length - 1;
|
||||
}
|
||||
|
||||
|
||||
BreakPoint *BreakPointMgr::find(uint32_t addr, bool includeSpecial) {
|
||||
BreakPoint *bp = breakpoints.find(addr);
|
||||
if (!bp && includeSpecial) {
|
||||
@ -280,7 +287,6 @@ bool ExceptionState::isBreakpoint() {
|
||||
}
|
||||
|
||||
void ExceptionState::resume() {
|
||||
DEBUG_FUNCTION_LINE("OSLoadContext");
|
||||
OSLoadContext(&context);
|
||||
}
|
||||
|
||||
@ -540,30 +546,26 @@ void Debugger::handleBreakPoint(ExceptionState *state) {
|
||||
if (firstTrap) {
|
||||
firstTrap = false;
|
||||
|
||||
Screen screen;
|
||||
screen.init();
|
||||
auto *screen = new Screen;
|
||||
Screen::drawText(
|
||||
0, 0, "Waiting for debugger connection.\n"
|
||||
"Press the home button to continue without debugger.\n"
|
||||
"You can still connect while the game is running.");
|
||||
Screen::flip();
|
||||
delete screen;
|
||||
|
||||
while (!connected) {
|
||||
uint32_t buttons = GetInput(VPAD_BUTTON_HOME);
|
||||
if (buttons) {
|
||||
DEBUG_FUNCTION_LINE("Pressed home");
|
||||
state->context.srr0 += 4;
|
||||
state->resume();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DEBUG_FUNCTION_LINE("stepper.handleBreakPoint(state);");
|
||||
|
||||
stepper.handleBreakPoint(state);
|
||||
|
||||
if (!connected) {
|
||||
DEBUG_FUNCTION_LINE("if (!connected) {");
|
||||
handleFatalCrash(&state->context, state->type);
|
||||
}
|
||||
|
||||
@ -671,10 +673,6 @@ void Debugger::cleanup() {
|
||||
;
|
||||
}
|
||||
|
||||
extern "C" void OSRestoreInterrupts(int state);
|
||||
extern "C" void __OSLockScheduler(void *);
|
||||
extern "C" void __OSUnlockScheduler(void *);
|
||||
extern "C" int OSDisableInterrupts();
|
||||
|
||||
static const char **commandNames = (const char *[]){
|
||||
"COMMAND_CLOSE",
|
||||
@ -688,15 +686,49 @@ static const char **commandNames = (const char *[]){
|
||||
"COMMAND_TOGGLE_BREAKPOINT",
|
||||
"COMMAND_POKE_REGISTERS",
|
||||
"COMMAND_RECEIVE_MESSAGES",
|
||||
"COMMAND_SEND_MESSAGE"};
|
||||
"COMMAND_SEND_MESSAGE",
|
||||
"COMMAND_DISASM"};
|
||||
|
||||
|
||||
#define LOG_DISASSEMBLY_SIZE (4096)
|
||||
|
||||
static char
|
||||
sDisassemblyBuffer[LOG_DISASSEMBLY_SIZE];
|
||||
|
||||
static uint32_t
|
||||
sDisassemblyLength = 0;
|
||||
|
||||
|
||||
static void
|
||||
disassemblyPrintCallback(const char *fmt, ...) {
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
sDisassemblyLength += vsprintf(sDisassemblyBuffer + sDisassemblyLength,
|
||||
fmt, args);
|
||||
sDisassemblyBuffer[sDisassemblyLength] = 0;
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void eraseAllSubStr(std::string & mainStr, const std::string & toErase)
|
||||
{
|
||||
size_t pos = std::string::npos;
|
||||
// Search for the substring in string in a loop untill nothing is found
|
||||
while ((pos = mainStr.find(toErase) )!= std::string::npos)
|
||||
{
|
||||
// If found then erase it from string
|
||||
mainStr.erase(pos, toErase.length());
|
||||
}
|
||||
}
|
||||
|
||||
//#define OSIopShell_Command_Disassemble ((void (*)(void*, uint32_t))(0x101C400 + 0x173e0))
|
||||
#define __os_printf ((void (*)(char*, ...))(0x101C400 + 0x012e88))
|
||||
|
||||
void Debugger::mainLoop(Client *client) {
|
||||
DEBUG_FUNCTION_LINE("About to enter mainLoop while");
|
||||
while (!stopRunning) {
|
||||
uint8_t cmd;
|
||||
if (!client->recvall(&cmd, 1)) return;
|
||||
|
||||
if (cmd <= 11) {
|
||||
if (cmd <= 12 && cmd != 10) {
|
||||
DEBUG_FUNCTION_LINE("Recieved command %s %d", commandNames[cmd], cmd);
|
||||
}
|
||||
if (cmd == COMMAND_CLOSE) {
|
||||
@ -713,6 +745,50 @@ void Debugger::mainLoop(Client *client) {
|
||||
return;
|
||||
}
|
||||
delete[] buffer;
|
||||
} else if (cmd == COMMAND_DISASM) {
|
||||
uint32_t addr, length;
|
||||
if (!client->recvall(&addr, 4)) return;
|
||||
if (!client->recvall(&length, 4)) return;
|
||||
|
||||
|
||||
char *buffer = new char[0x40];
|
||||
|
||||
auto addrAsPtr = (uint32_t *) (addr & 0xfffffffc);
|
||||
|
||||
|
||||
|
||||
|
||||
DisassemblePPCRange(reinterpret_cast<void *>(addr + 0x20), reinterpret_cast<void *>(addr + length), reinterpret_cast<DisassemblyPrintFn>(__os_printf),OSGetSymbolName,
|
||||
static_cast<DisassemblePPCFlags>(0x121));
|
||||
|
||||
|
||||
for (int i = 0; i < length / 4; i++) {
|
||||
DisassemblePPCOpcode(&addrAsPtr[i],
|
||||
buffer,
|
||||
0x40,
|
||||
OSGetSymbolName,
|
||||
static_cast<DisassemblePPCFlags>(0x121));
|
||||
disassemblyPrintCallback("0x%08x 0x%08x %s\n",&addrAsPtr[i],addrAsPtr[i],buffer);
|
||||
}
|
||||
delete[] buffer;
|
||||
|
||||
|
||||
std::string shit(sDisassemblyBuffer);
|
||||
eraseAllSubStr(shit, "(null)");
|
||||
|
||||
|
||||
DEBUG_FUNCTION_LINE("done");
|
||||
|
||||
auto length_ = shit.length() + 1;
|
||||
if (!client->sendall(&length_, 4)) {
|
||||
sDisassemblyLength = 0;
|
||||
return;
|
||||
}
|
||||
if (!client->sendall(shit.c_str(), length_)) {
|
||||
sDisassemblyLength = 0;
|
||||
return;
|
||||
}
|
||||
sDisassemblyLength = 0;
|
||||
} else if (cmd == COMMAND_WRITE) {
|
||||
uint32_t addr, length;
|
||||
if (!client->recvall(&addr, 4)) return;
|
||||
@ -733,15 +809,18 @@ void Debugger::mainLoop(Client *client) {
|
||||
} else if (cmd == COMMAND_GET_MODULE_NAME) {
|
||||
char name[0x40];
|
||||
int length = 0x40;
|
||||
OSDynLoad_GetModuleName(reinterpret_cast<OSDynLoad_Module>(-1), name, &length);
|
||||
|
||||
if(OSDynLoad_GetModuleName(reinterpret_cast<OSDynLoad_Module>(-1), name, &length) != OS_DYNLOAD_OK){
|
||||
strncat(name, "ERROR", sizeof(name) -1);
|
||||
}
|
||||
length = strlen(name);
|
||||
|
||||
if (!client->sendall(&length, 4)) return;
|
||||
if (!client->sendall(name, length)) return;
|
||||
} else if (cmd == COMMAND_GET_MODULE_LIST) {
|
||||
|
||||
int num_rpls = OSDynLoad_GetNumberOfRPLs();
|
||||
if (num_rpls == 0) {
|
||||
return;
|
||||
continue;
|
||||
}
|
||||
|
||||
std::vector<OSDynLoad_NotifyData> rpls;
|
||||
@ -749,7 +828,7 @@ void Debugger::mainLoop(Client *client) {
|
||||
|
||||
bool ret = OSDynLoad_GetRPLInfo(0, num_rpls, rpls.data());
|
||||
if (!ret) {
|
||||
return;
|
||||
continue;
|
||||
}
|
||||
|
||||
char buffer[0x1000]; //This should be enough
|
||||
@ -784,6 +863,7 @@ void Debugger::mainLoop(Client *client) {
|
||||
OSThread *current = ThreadList;
|
||||
while (current) {
|
||||
const char *name = OSGetThreadName(current);
|
||||
OSReport("name %s", name);
|
||||
|
||||
uint32_t namelen = 0;
|
||||
if (name) {
|
||||
@ -795,7 +875,7 @@ void Debugger::mainLoop(Client *client) {
|
||||
}
|
||||
|
||||
int priority = current->basePriority;
|
||||
int type = *(uint32_t *) (current->__unk11);
|
||||
int type = *((uint32_t *) current->__unk11);
|
||||
if (type == 1) {
|
||||
priority -= 0x20;
|
||||
} else if (type == 2) {
|
||||
@ -905,24 +985,20 @@ void Debugger::mainLoop(Client *client) {
|
||||
|
||||
void Debugger::threadFunc() {
|
||||
DEBUG_FUNCTION_LINE("Hello from debugger thread :)!");
|
||||
OSSetExceptionCallbackEx(OS_EXCEPTION_MODE_GLOBAL_ALL_CORES, OS_EXCEPTION_TYPE_DSI, dsiHandler);
|
||||
OSSetExceptionCallbackEx(OS_EXCEPTION_MODE_GLOBAL_ALL_CORES, OS_EXCEPTION_TYPE_ISI, isiHandler);
|
||||
OSSetExceptionCallbackEx(OS_EXCEPTION_MODE_GLOBAL_ALL_CORES, OS_EXCEPTION_TYPE_PROGRAM, programHandler);
|
||||
DEBUG_FUNCTION_LINE("Callback init done.!");
|
||||
prevDsiHandler = OSSetExceptionCallbackEx(OS_EXCEPTION_MODE_GLOBAL_ALL_CORES, OS_EXCEPTION_TYPE_DSI, dsiHandler);
|
||||
prevIsiHandler = OSSetExceptionCallbackEx(OS_EXCEPTION_MODE_GLOBAL_ALL_CORES, OS_EXCEPTION_TYPE_ISI, isiHandler);
|
||||
prevProgramHandler = OSSetExceptionCallbackEx(OS_EXCEPTION_MODE_GLOBAL_ALL_CORES, OS_EXCEPTION_TYPE_PROGRAM, programHandler);
|
||||
|
||||
Server server;
|
||||
Client client;
|
||||
|
||||
DEBUG_FUNCTION_LINE("Set initialized = true");
|
||||
initialized = true;
|
||||
while (!stopRunning) {
|
||||
if (!server.init(Socket::TCP)) continue;
|
||||
if (!server.bind(1560)) continue;
|
||||
if (!server.accept(&client)) continue;
|
||||
DEBUG_FUNCTION_LINE("Accepted a connection");
|
||||
connected = true;
|
||||
mainLoop(&client);
|
||||
DEBUG_FUNCTION_LINE("Lets do some cleanup");
|
||||
cleanup();
|
||||
connected = false;
|
||||
client.close();
|
||||
@ -931,55 +1007,55 @@ void Debugger::threadFunc() {
|
||||
}
|
||||
|
||||
int Debugger::threadEntry(int argc, const char **argv) {
|
||||
DEBUG_FUNCTION_LINE("threadEntry");
|
||||
debugger->threadFunc();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void Debugger::start() {
|
||||
initialized = false;
|
||||
connected = false;
|
||||
firstTrap = true;
|
||||
|
||||
DEBUG_FUNCTION_LINE("OSInitMessageQueue");
|
||||
OSInitMessageQueue(&eventQueue, eventMessages, MESSAGE_COUNT);
|
||||
|
||||
DEBUG_FUNCTION_LINE("init breakpoints");
|
||||
breakpoints.init();
|
||||
DEBUG_FUNCTION_LINE("init exceptions");
|
||||
exceptions.init();
|
||||
DEBUG_FUNCTION_LINE("init stepper");
|
||||
stepper.init();
|
||||
|
||||
|
||||
DEBUG_FUNCTION_LINE("Alloc thread");
|
||||
serverThread = (OSThread *) memalign(0x20, sizeof(OSThread));
|
||||
DEBUG_FUNCTION_LINE("Alloc stack");
|
||||
serverStack = (char *) memalign(0x20, STACK_SIZE);
|
||||
|
||||
|
||||
DEBUG_FUNCTION_LINE("Create thread");
|
||||
OSCreateThread(
|
||||
serverThread, threadEntry, 0, 0,
|
||||
serverStack + STACK_SIZE, STACK_SIZE,
|
||||
0, 12);
|
||||
DEBUG_FUNCTION_LINE("Set thread name");
|
||||
0, OS_THREAD_ATTRIB_AFFINITY_CPU2 | OS_THREAD_ATTRIB_DETACHED);
|
||||
OSSetThreadName(serverThread, "Debug Server");
|
||||
DEBUG_FUNCTION_LINE("Resume thread");
|
||||
OSResumeThread(serverThread);
|
||||
|
||||
while (!initialized) {
|
||||
DEBUG_FUNCTION_LINE("Wait for thread init");
|
||||
OSSleepTicks(OSMillisecondsToTicks(20));
|
||||
}
|
||||
initDebugState = true;
|
||||
DCFlushRange(&initDebugState, sizeof(initDebugState));
|
||||
DEBUG_FUNCTION_LINE("Thread init done! Exit start()");
|
||||
}
|
||||
|
||||
Debugger::~Debugger() {
|
||||
stopRunning = true;
|
||||
DCFlushRange(&stopRunning, sizeof(stopRunning));
|
||||
OSJoinThread(serverThread, nullptr);
|
||||
free(serverStack);
|
||||
serverStack = nullptr;
|
||||
free(serverThread);
|
||||
serverThread = nullptr;
|
||||
|
||||
initialized = false;
|
||||
connected = false;
|
||||
firstTrap = true;
|
||||
|
||||
// Restore exceptions.
|
||||
OSSetExceptionCallbackEx(OS_EXCEPTION_MODE_GLOBAL_ALL_CORES, OS_EXCEPTION_TYPE_DSI, prevDsiHandler);
|
||||
OSSetExceptionCallbackEx(OS_EXCEPTION_MODE_GLOBAL_ALL_CORES, OS_EXCEPTION_TYPE_ISI, prevIsiHandler);
|
||||
OSSetExceptionCallbackEx(OS_EXCEPTION_MODE_GLOBAL_ALL_CORES, OS_EXCEPTION_TYPE_PROGRAM, prevProgramHandler);
|
||||
}
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include <coreinit/mutex.h>
|
||||
#include <coreinit/thread.h>
|
||||
|
||||
#include <coreinit/exception.h>
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
|
||||
@ -233,7 +234,8 @@ private:
|
||||
COMMAND_TOGGLE_BREAKPOINT,
|
||||
COMMAND_POKE_REGISTERS,
|
||||
COMMAND_RECEIVE_MESSAGES,
|
||||
COMMAND_SEND_MESSAGE
|
||||
COMMAND_SEND_MESSAGE,
|
||||
COMMAND_DISASM
|
||||
};
|
||||
|
||||
static int threadEntry(int argc, const char **argv);
|
||||
@ -269,6 +271,11 @@ private:
|
||||
bool initialized{};
|
||||
bool connected{};
|
||||
bool firstTrap{};
|
||||
|
||||
OSExceptionCallbackFn prevDsiHandler = nullptr;
|
||||
OSExceptionCallbackFn prevIsiHandler = nullptr;
|
||||
OSExceptionCallbackFn prevProgramHandler = nullptr;
|
||||
};
|
||||
|
||||
extern "C" Debugger *debugger;
|
||||
extern bool initDebugState;
|
||||
|
55
src/main.cpp
55
src/main.cpp
@ -1,28 +1,65 @@
|
||||
#include "debugger.h"
|
||||
#include "exceptions.h"
|
||||
#include "logger.h"
|
||||
#include <coreinit/cache.h>
|
||||
#include <coreinit/debug.h>
|
||||
#include <coreinit/dynload.h>
|
||||
#include <coreinit/memorymap.h>
|
||||
#include <kernel/kernel.h>
|
||||
#include <wups.h>
|
||||
|
||||
OSThread **pThreadList;
|
||||
|
||||
|
||||
WUPS_PLUGIN_NAME("Debugger");
|
||||
WUPS_PLUGIN_DESCRIPTION("FTP Server");
|
||||
WUPS_PLUGIN_DESCRIPTION("Wii U Debugger");
|
||||
WUPS_PLUGIN_VERSION("0.1");
|
||||
WUPS_PLUGIN_AUTHOR("Kinnay");
|
||||
WUPS_PLUGIN_AUTHOR("Kinnay, Maschell");
|
||||
WUPS_PLUGIN_LICENSE("GPL");
|
||||
|
||||
WUPS_USE_WUT_DEVOPTAB();
|
||||
|
||||
INITIALIZE_PLUGIN() {
|
||||
InstallExceptionHandlers();
|
||||
/* https://github.com/QuarkTheAwesome/CafeBinPatch/blob/main/src/runtime-patcher.cpp#L58 */
|
||||
bool PatchInstruction(void *instr, uint32_t original, uint32_t replacement) {
|
||||
uint32_t current = *(uint32_t *) instr;
|
||||
if (current != original) return current == replacement;
|
||||
|
||||
KernelCopyData(OSEffectiveToPhysical((uint32_t) instr), OSEffectiveToPhysical((uint32_t) &replacement), sizeof(replacement));
|
||||
//Only works on AROMA! WUPS 0.1's KernelCopyData is uncached, needs DCInvalidate here instead
|
||||
DCFlushRange(instr, 4);
|
||||
ICInvalidateRange(instr, 4);
|
||||
|
||||
current = *(uint32_t *) instr;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* https://github.com/QuarkTheAwesome/CafeBinPatch/blob/main/src/runtime-patcher.cpp#L74 */
|
||||
bool PatchDynLoadFunctions() {
|
||||
uint32_t *patch1 = ((uint32_t *) &OSDynLoad_GetNumberOfRPLs) + 6;
|
||||
uint32_t *patch2 = ((uint32_t *) &OSDynLoad_GetRPLInfo) + 22;
|
||||
|
||||
if (!PatchInstruction(patch1, 0x41820038 /* beq +38 */, 0x60000000 /*nop*/)) {
|
||||
return false;
|
||||
}
|
||||
if (!PatchInstruction(patch2, 0x41820100 /* beq +100 */, 0x60000000 /*nop*/)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
INITIALIZE_PLUGIN() {
|
||||
PatchDynLoadFunctions();
|
||||
}
|
||||
|
||||
ON_APPLICATION_START() {
|
||||
initLogging();
|
||||
DEBUG_FUNCTION_LINE("Started Debugger plugin");
|
||||
pThreadList = (OSThread **) 0x100567F8;
|
||||
DEBUG_FUNCTION_LINE("Hello from Debugger plugin");
|
||||
pThreadList = (OSThread **) 0x100567F8; // 100567f8
|
||||
debugger = new Debugger();
|
||||
DCFlushRange(&debugger, 4);
|
||||
DCFlushRange(debugger, sizeof(Debugger));
|
||||
DEBUG_FUNCTION_LINE("Created Debugger");
|
||||
debugger->start();
|
||||
DEBUG_FUNCTION_LINE("Started Debugger thread");
|
||||
@ -34,3 +71,7 @@ ON_APPLICATION_REQUESTS_EXIT() {
|
||||
DEBUG_FUNCTION_LINE("Deleted Debugger thread");
|
||||
deinitLogging();
|
||||
}
|
||||
ON_APPLICATION_ENDS() {
|
||||
initDebugState = false;
|
||||
DCFlushRange(&initDebugState, sizeof(initDebugState));
|
||||
}
|
||||
|
@ -1,17 +1,35 @@
|
||||
#include "logger.h"
|
||||
#include <coreinit/exception.h>
|
||||
#include <cstdint>
|
||||
#include <wups.h>
|
||||
|
||||
DECL_FUNCTION(int, OSSetExceptionCallback) {
|
||||
return 0;
|
||||
extern bool initDebugState;
|
||||
|
||||
DECL_FUNCTION(OSExceptionCallbackFn, OSSetExceptionCallback,
|
||||
OSExceptionType exceptionType,
|
||||
OSExceptionCallbackFn callback) {
|
||||
if (initDebugState) {
|
||||
return nullptr;
|
||||
} else {
|
||||
return real_OSSetExceptionCallback(exceptionType, callback);
|
||||
}
|
||||
}
|
||||
DECL_FUNCTION(int, OSSetExceptionCallbackEx) {
|
||||
return 0;
|
||||
DECL_FUNCTION(OSExceptionCallbackFn, OSSetExceptionCallbackEx,
|
||||
OSExceptionMode mode,
|
||||
OSExceptionType exceptionType,
|
||||
OSExceptionCallbackFn callback) {
|
||||
if (initDebugState) {
|
||||
return nullptr;
|
||||
} else {
|
||||
return real_OSSetExceptionCallbackEx(mode, exceptionType, callback);
|
||||
}
|
||||
}
|
||||
DECL_FUNCTION(int, OSIsDebuggerInitialized) {
|
||||
return true;
|
||||
return initDebugState;
|
||||
}
|
||||
|
||||
|
||||
WUPS_MUST_REPLACE(OSSetExceptionCallback, WUPS_LOADER_LIBRARY_COREINIT, OSSetExceptionCallback);
|
||||
WUPS_MUST_REPLACE(OSSetExceptionCallbackEx, WUPS_LOADER_LIBRARY_COREINIT, OSSetExceptionCallbackEx);
|
||||
WUPS_MUST_REPLACE(OSIsDebuggerInitialized, WUPS_LOADER_LIBRARY_COREINIT, OSIsDebuggerInitialized);
|
||||
// OSSetExceptionCallbackEx is just a branch to another function.
|
||||
// Instead of "fixing" the FunctionPatcher, we use this hacky solution :)
|
||||
WUPS_MUST_REPLACE_PHYSICAL_FOR_PROCESS(OSSetExceptionCallbackEx, (0x3201C400 + 0x286b0), (0x101C400 + 0x286b0), WUPS_FP_TARGET_PROCESS_GAME_AND_MENU);
|
||||
WUPS_MUST_REPLACE_FOR_PROCESS(OSSetExceptionCallback, WUPS_LOADER_LIBRARY_COREINIT, OSSetExceptionCallback, WUPS_FP_TARGET_PROCESS_GAME_AND_MENU);
|
||||
WUPS_MUST_REPLACE_FOR_PROCESS(OSIsDebuggerInitialized, WUPS_LOADER_LIBRARY_COREINIT, OSIsDebuggerInitialized, WUPS_FP_TARGET_PROCESS_GAME_AND_MENU);
|
||||
|
@ -1,14 +1,16 @@
|
||||
|
||||
#include "screen.h"
|
||||
#include "logger.h"
|
||||
#include <coreinit/debug.h>
|
||||
#include <gx2/state.h>
|
||||
|
||||
#include <memory/mappedmemory.h>
|
||||
|
||||
Screen::Screen() : screenBuffer(nullptr) {}
|
||||
Screen::Screen() : screenBuffer(nullptr) {
|
||||
init();
|
||||
}
|
||||
Screen::~Screen() {
|
||||
if (screenBuffer) {
|
||||
MEMFreeToMappedMemory(screenBuffer);
|
||||
screenBuffer = nullptr;
|
||||
}
|
||||
destroyBuffer();
|
||||
}
|
||||
|
||||
void Screen::init() {
|
||||
@ -17,6 +19,9 @@ void Screen::init() {
|
||||
uint32_t bufferSize0 = OSScreenGetBufferSizeEx(SCREEN_TV);
|
||||
uint32_t bufferSize1 = OSScreenGetBufferSizeEx(SCREEN_DRC);
|
||||
screenBuffer = MEMAllocFromMappedMemoryForGX2Ex(bufferSize0 + bufferSize1, 0x100);
|
||||
if (screenBuffer == nullptr) {
|
||||
OSFatal("Failed to allocate screenbuffer");
|
||||
}
|
||||
OSScreenSetBufferEx(SCREEN_TV, screenBuffer);
|
||||
OSScreenSetBufferEx(SCREEN_DRC, (char *) screenBuffer + bufferSize0);
|
||||
|
||||
@ -86,3 +91,11 @@ void Screen::flip() {
|
||||
flip(SCREEN_TV);
|
||||
flip(SCREEN_DRC);
|
||||
}
|
||||
void Screen::destroyBuffer() {
|
||||
if (screenBuffer) {
|
||||
MEMFreeToMappedMemory(screenBuffer);
|
||||
screenBuffer = nullptr;
|
||||
}
|
||||
|
||||
GX2Init(nullptr);
|
||||
}
|
||||
|
@ -22,6 +22,8 @@ public:
|
||||
static void drawText(OSScreenID screen, int x, int y, const char *text);
|
||||
static void flip(OSScreenID screen);
|
||||
|
||||
void destroyBuffer();
|
||||
|
||||
private:
|
||||
void *screenBuffer;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user