This commit is contained in:
Maschell 2022-07-26 19:29:41 +02:00
parent 5a3bae8616
commit 60a0679699
7 changed files with 232 additions and 75 deletions

22
main.py
View File

@ -116,6 +116,7 @@ COMMAND_TOGGLE_BREAKPOINT = 8
COMMAND_POKE_REGISTERS = 9 COMMAND_POKE_REGISTERS = 9
COMMAND_RECEIVE_MESSAGES = 10 COMMAND_RECEIVE_MESSAGES = 10
COMMAND_SEND_MESSAGE = 11 COMMAND_SEND_MESSAGE = 11
COMMAND_DISASM = 12
class Debugger: class Debugger:
def __init__(self): def __init__(self):
@ -157,6 +158,12 @@ class Debugger:
self.sendall(struct.pack(">II", addr, num)) self.sendall(struct.pack(">II", addr, num))
data = self.recvall(num) data = self.recvall(num)
return data 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): def write(self, addr, data):
self.sendbyte(COMMAND_WRITE) self.sendbyte(COMMAND_WRITE)
@ -503,18 +510,11 @@ class DisassemblyWidget(QTextEdit):
self.updateText() self.updateText()
self.updateHighlight() self.updateHighlight()
def updateText(self): def updateText(self):
if debugger.connected:
blob = debugger.read(self.base, 0x60)
else:
blob = b"\x00" * 0x60
text = "" text = ""
for i in range(24): if debugger.connected:
address = self.base + i * 4 text = debugger.disasm(self.base, 0x60)
value = struct.unpack_from(">I", blob, i * 4)[0]
instr = disassemble.disassemble(value, address)
text += "%08X: %08X %s\n" %(address, value, instr)
self.setPlainText(text) self.setPlainText(text)
def updateHighlight(self): def updateHighlight(self):

View File

@ -7,20 +7,27 @@
#include <coreinit/debug.h> #include <coreinit/debug.h>
#include <coreinit/dynload.h> #include <coreinit/dynload.h>
#include <coreinit/exception.h> #include <coreinit/exception.h>
#include <coreinit/interrupts.h>
#include <coreinit/memory.h> #include <coreinit/memory.h>
#include <coreinit/scheduler.h>
#include <cstdio> #include <cstdio>
#include <cstdlib> #include <cstdlib>
#include <cstring> #include <cstring>
#include <gx2/context.h>
#include <malloc.h> #include <malloc.h>
#include <sysapp/switch.h>
#include <vpad/input.h> #include <vpad/input.h>
#include <stdarg.h>
#include <string>
Debugger *debugger; Debugger *debugger;
bool initDebugState = false;
bool BreakPoint::isRange(uint32_t addr, uint32_t length) const { bool BreakPoint::isRange(uint32_t addr, uint32_t length) const {
return address >= addr && address <= addr + length - 1; return address >= addr && address <= addr + length - 1;
} }
BreakPoint *BreakPointMgr::find(uint32_t addr, bool includeSpecial) { BreakPoint *BreakPointMgr::find(uint32_t addr, bool includeSpecial) {
BreakPoint *bp = breakpoints.find(addr); BreakPoint *bp = breakpoints.find(addr);
if (!bp && includeSpecial) { if (!bp && includeSpecial) {
@ -280,7 +287,6 @@ bool ExceptionState::isBreakpoint() {
} }
void ExceptionState::resume() { void ExceptionState::resume() {
DEBUG_FUNCTION_LINE("OSLoadContext");
OSLoadContext(&context); OSLoadContext(&context);
} }
@ -540,30 +546,26 @@ void Debugger::handleBreakPoint(ExceptionState *state) {
if (firstTrap) { if (firstTrap) {
firstTrap = false; firstTrap = false;
Screen screen; auto *screen = new Screen;
screen.init();
Screen::drawText( Screen::drawText(
0, 0, "Waiting for debugger connection.\n" 0, 0, "Waiting for debugger connection.\n"
"Press the home button to continue without debugger.\n" "Press the home button to continue without debugger.\n"
"You can still connect while the game is running."); "You can still connect while the game is running.");
Screen::flip(); Screen::flip();
delete screen;
while (!connected) { while (!connected) {
uint32_t buttons = GetInput(VPAD_BUTTON_HOME); uint32_t buttons = GetInput(VPAD_BUTTON_HOME);
if (buttons) { if (buttons) {
DEBUG_FUNCTION_LINE("Pressed home");
state->context.srr0 += 4; state->context.srr0 += 4;
state->resume(); state->resume();
} }
} }
} }
DEBUG_FUNCTION_LINE("stepper.handleBreakPoint(state);");
stepper.handleBreakPoint(state); stepper.handleBreakPoint(state);
if (!connected) { if (!connected) {
DEBUG_FUNCTION_LINE("if (!connected) {");
handleFatalCrash(&state->context, state->type); 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 *[]){ static const char **commandNames = (const char *[]){
"COMMAND_CLOSE", "COMMAND_CLOSE",
@ -688,15 +686,49 @@ static const char **commandNames = (const char *[]){
"COMMAND_TOGGLE_BREAKPOINT", "COMMAND_TOGGLE_BREAKPOINT",
"COMMAND_POKE_REGISTERS", "COMMAND_POKE_REGISTERS",
"COMMAND_RECEIVE_MESSAGES", "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) { void Debugger::mainLoop(Client *client) {
DEBUG_FUNCTION_LINE("About to enter mainLoop while");
while (!stopRunning) { while (!stopRunning) {
uint8_t cmd; uint8_t cmd;
if (!client->recvall(&cmd, 1)) return; if (!client->recvall(&cmd, 1)) return;
if (cmd <= 11) { if (cmd <= 12 && cmd != 10) {
DEBUG_FUNCTION_LINE("Recieved command %s %d", commandNames[cmd], cmd); DEBUG_FUNCTION_LINE("Recieved command %s %d", commandNames[cmd], cmd);
} }
if (cmd == COMMAND_CLOSE) { if (cmd == COMMAND_CLOSE) {
@ -713,6 +745,50 @@ void Debugger::mainLoop(Client *client) {
return; return;
} }
delete[] buffer; 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) { } else if (cmd == COMMAND_WRITE) {
uint32_t addr, length; uint32_t addr, length;
if (!client->recvall(&addr, 4)) return; if (!client->recvall(&addr, 4)) return;
@ -733,15 +809,18 @@ void Debugger::mainLoop(Client *client) {
} else if (cmd == COMMAND_GET_MODULE_NAME) { } else if (cmd == COMMAND_GET_MODULE_NAME) {
char name[0x40]; char name[0x40];
int length = 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); length = strlen(name);
if (!client->sendall(&length, 4)) return; if (!client->sendall(&length, 4)) return;
if (!client->sendall(name, length)) return; if (!client->sendall(name, length)) return;
} else if (cmd == COMMAND_GET_MODULE_LIST) { } else if (cmd == COMMAND_GET_MODULE_LIST) {
int num_rpls = OSDynLoad_GetNumberOfRPLs(); int num_rpls = OSDynLoad_GetNumberOfRPLs();
if (num_rpls == 0) { if (num_rpls == 0) {
return; continue;
} }
std::vector<OSDynLoad_NotifyData> rpls; std::vector<OSDynLoad_NotifyData> rpls;
@ -749,7 +828,7 @@ void Debugger::mainLoop(Client *client) {
bool ret = OSDynLoad_GetRPLInfo(0, num_rpls, rpls.data()); bool ret = OSDynLoad_GetRPLInfo(0, num_rpls, rpls.data());
if (!ret) { if (!ret) {
return; continue;
} }
char buffer[0x1000]; //This should be enough char buffer[0x1000]; //This should be enough
@ -784,6 +863,7 @@ void Debugger::mainLoop(Client *client) {
OSThread *current = ThreadList; OSThread *current = ThreadList;
while (current) { while (current) {
const char *name = OSGetThreadName(current); const char *name = OSGetThreadName(current);
OSReport("name %s", name);
uint32_t namelen = 0; uint32_t namelen = 0;
if (name) { if (name) {
@ -795,7 +875,7 @@ void Debugger::mainLoop(Client *client) {
} }
int priority = current->basePriority; int priority = current->basePriority;
int type = *(uint32_t *) (current->__unk11); int type = *((uint32_t *) current->__unk11);
if (type == 1) { if (type == 1) {
priority -= 0x20; priority -= 0x20;
} else if (type == 2) { } else if (type == 2) {
@ -905,24 +985,20 @@ void Debugger::mainLoop(Client *client) {
void Debugger::threadFunc() { void Debugger::threadFunc() {
DEBUG_FUNCTION_LINE("Hello from debugger thread :)!"); DEBUG_FUNCTION_LINE("Hello from debugger thread :)!");
OSSetExceptionCallbackEx(OS_EXCEPTION_MODE_GLOBAL_ALL_CORES, OS_EXCEPTION_TYPE_DSI, dsiHandler); prevDsiHandler = OSSetExceptionCallbackEx(OS_EXCEPTION_MODE_GLOBAL_ALL_CORES, OS_EXCEPTION_TYPE_DSI, dsiHandler);
OSSetExceptionCallbackEx(OS_EXCEPTION_MODE_GLOBAL_ALL_CORES, OS_EXCEPTION_TYPE_ISI, isiHandler); prevIsiHandler = OSSetExceptionCallbackEx(OS_EXCEPTION_MODE_GLOBAL_ALL_CORES, OS_EXCEPTION_TYPE_ISI, isiHandler);
OSSetExceptionCallbackEx(OS_EXCEPTION_MODE_GLOBAL_ALL_CORES, OS_EXCEPTION_TYPE_PROGRAM, programHandler); prevProgramHandler = OSSetExceptionCallbackEx(OS_EXCEPTION_MODE_GLOBAL_ALL_CORES, OS_EXCEPTION_TYPE_PROGRAM, programHandler);
DEBUG_FUNCTION_LINE("Callback init done.!");
Server server; Server server;
Client client; Client client;
DEBUG_FUNCTION_LINE("Set initialized = true");
initialized = true; initialized = true;
while (!stopRunning) { while (!stopRunning) {
if (!server.init(Socket::TCP)) continue; if (!server.init(Socket::TCP)) continue;
if (!server.bind(1560)) continue; if (!server.bind(1560)) continue;
if (!server.accept(&client)) continue; if (!server.accept(&client)) continue;
DEBUG_FUNCTION_LINE("Accepted a connection");
connected = true; connected = true;
mainLoop(&client); mainLoop(&client);
DEBUG_FUNCTION_LINE("Lets do some cleanup");
cleanup(); cleanup();
connected = false; connected = false;
client.close(); client.close();
@ -931,55 +1007,55 @@ void Debugger::threadFunc() {
} }
int Debugger::threadEntry(int argc, const char **argv) { int Debugger::threadEntry(int argc, const char **argv) {
DEBUG_FUNCTION_LINE("threadEntry");
debugger->threadFunc(); debugger->threadFunc();
return 0; return 0;
} }
void Debugger::start() { void Debugger::start() {
initialized = false; initialized = false;
connected = false; connected = false;
firstTrap = true; firstTrap = true;
DEBUG_FUNCTION_LINE("OSInitMessageQueue");
OSInitMessageQueue(&eventQueue, eventMessages, MESSAGE_COUNT); OSInitMessageQueue(&eventQueue, eventMessages, MESSAGE_COUNT);
DEBUG_FUNCTION_LINE("init breakpoints");
breakpoints.init(); breakpoints.init();
DEBUG_FUNCTION_LINE("init exceptions");
exceptions.init(); exceptions.init();
DEBUG_FUNCTION_LINE("init stepper");
stepper.init(); stepper.init();
DEBUG_FUNCTION_LINE("Alloc thread");
serverThread = (OSThread *) memalign(0x20, sizeof(OSThread)); serverThread = (OSThread *) memalign(0x20, sizeof(OSThread));
DEBUG_FUNCTION_LINE("Alloc stack"); serverStack = (char *) memalign(0x20, STACK_SIZE);
serverStack = (char *) memalign(0x20, STACK_SIZE);
DEBUG_FUNCTION_LINE("Create thread");
OSCreateThread( OSCreateThread(
serverThread, threadEntry, 0, 0, serverThread, threadEntry, 0, 0,
serverStack + STACK_SIZE, STACK_SIZE, serverStack + STACK_SIZE, STACK_SIZE,
0, 12); 0, OS_THREAD_ATTRIB_AFFINITY_CPU2 | OS_THREAD_ATTRIB_DETACHED);
DEBUG_FUNCTION_LINE("Set thread name");
OSSetThreadName(serverThread, "Debug Server"); OSSetThreadName(serverThread, "Debug Server");
DEBUG_FUNCTION_LINE("Resume thread");
OSResumeThread(serverThread); OSResumeThread(serverThread);
while (!initialized) { while (!initialized) {
DEBUG_FUNCTION_LINE("Wait for thread init");
OSSleepTicks(OSMillisecondsToTicks(20)); OSSleepTicks(OSMillisecondsToTicks(20));
} }
initDebugState = true;
DCFlushRange(&initDebugState, sizeof(initDebugState));
DEBUG_FUNCTION_LINE("Thread init done! Exit start()"); DEBUG_FUNCTION_LINE("Thread init done! Exit start()");
} }
Debugger::~Debugger() { Debugger::~Debugger() {
stopRunning = true; stopRunning = true;
DCFlushRange(&stopRunning, sizeof(stopRunning));
OSJoinThread(serverThread, nullptr); OSJoinThread(serverThread, nullptr);
free(serverStack); free(serverStack);
serverStack = nullptr; serverStack = nullptr;
free(serverThread); free(serverThread);
serverThread = nullptr; 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);
} }

View File

@ -7,6 +7,7 @@
#include <coreinit/mutex.h> #include <coreinit/mutex.h>
#include <coreinit/thread.h> #include <coreinit/thread.h>
#include <coreinit/exception.h>
#include <cstdint> #include <cstdint>
#include <vector> #include <vector>
@ -233,7 +234,8 @@ private:
COMMAND_TOGGLE_BREAKPOINT, COMMAND_TOGGLE_BREAKPOINT,
COMMAND_POKE_REGISTERS, COMMAND_POKE_REGISTERS,
COMMAND_RECEIVE_MESSAGES, COMMAND_RECEIVE_MESSAGES,
COMMAND_SEND_MESSAGE COMMAND_SEND_MESSAGE,
COMMAND_DISASM
}; };
static int threadEntry(int argc, const char **argv); static int threadEntry(int argc, const char **argv);
@ -269,6 +271,11 @@ private:
bool initialized{}; bool initialized{};
bool connected{}; bool connected{};
bool firstTrap{}; bool firstTrap{};
OSExceptionCallbackFn prevDsiHandler = nullptr;
OSExceptionCallbackFn prevIsiHandler = nullptr;
OSExceptionCallbackFn prevProgramHandler = nullptr;
}; };
extern "C" Debugger *debugger; extern "C" Debugger *debugger;
extern bool initDebugState;

View File

@ -1,28 +1,65 @@
#include "debugger.h" #include "debugger.h"
#include "exceptions.h" #include "exceptions.h"
#include "logger.h" #include "logger.h"
#include <coreinit/cache.h>
#include <coreinit/debug.h> #include <coreinit/debug.h>
#include <coreinit/dynload.h>
#include <coreinit/memorymap.h>
#include <kernel/kernel.h>
#include <wups.h> #include <wups.h>
OSThread **pThreadList; OSThread **pThreadList;
WUPS_PLUGIN_NAME("Debugger"); WUPS_PLUGIN_NAME("Debugger");
WUPS_PLUGIN_DESCRIPTION("FTP Server"); WUPS_PLUGIN_DESCRIPTION("Wii U Debugger");
WUPS_PLUGIN_VERSION("0.1"); WUPS_PLUGIN_VERSION("0.1");
WUPS_PLUGIN_AUTHOR("Kinnay"); WUPS_PLUGIN_AUTHOR("Kinnay, Maschell");
WUPS_PLUGIN_LICENSE("GPL"); WUPS_PLUGIN_LICENSE("GPL");
WUPS_USE_WUT_DEVOPTAB(); WUPS_USE_WUT_DEVOPTAB();
INITIALIZE_PLUGIN() { /* https://github.com/QuarkTheAwesome/CafeBinPatch/blob/main/src/runtime-patcher.cpp#L58 */
InstallExceptionHandlers(); 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() { ON_APPLICATION_START() {
initLogging(); initLogging();
DEBUG_FUNCTION_LINE("Started Debugger plugin"); DEBUG_FUNCTION_LINE("Hello from Debugger plugin");
pThreadList = (OSThread **) 0x100567F8; pThreadList = (OSThread **) 0x100567F8; // 100567f8
debugger = new Debugger(); debugger = new Debugger();
DCFlushRange(&debugger, 4);
DCFlushRange(debugger, sizeof(Debugger));
DEBUG_FUNCTION_LINE("Created Debugger"); DEBUG_FUNCTION_LINE("Created Debugger");
debugger->start(); debugger->start();
DEBUG_FUNCTION_LINE("Started Debugger thread"); DEBUG_FUNCTION_LINE("Started Debugger thread");
@ -34,3 +71,7 @@ ON_APPLICATION_REQUESTS_EXIT() {
DEBUG_FUNCTION_LINE("Deleted Debugger thread"); DEBUG_FUNCTION_LINE("Deleted Debugger thread");
deinitLogging(); deinitLogging();
} }
ON_APPLICATION_ENDS() {
initDebugState = false;
DCFlushRange(&initDebugState, sizeof(initDebugState));
}

View File

@ -1,17 +1,35 @@
#include "logger.h"
#include <coreinit/exception.h>
#include <cstdint> #include <cstdint>
#include <wups.h> #include <wups.h>
DECL_FUNCTION(int, OSSetExceptionCallback) { extern bool initDebugState;
return 0;
DECL_FUNCTION(OSExceptionCallbackFn, OSSetExceptionCallback,
OSExceptionType exceptionType,
OSExceptionCallbackFn callback) {
if (initDebugState) {
return nullptr;
} else {
return real_OSSetExceptionCallback(exceptionType, callback);
}
} }
DECL_FUNCTION(int, OSSetExceptionCallbackEx) { DECL_FUNCTION(OSExceptionCallbackFn, OSSetExceptionCallbackEx,
return 0; OSExceptionMode mode,
OSExceptionType exceptionType,
OSExceptionCallbackFn callback) {
if (initDebugState) {
return nullptr;
} else {
return real_OSSetExceptionCallbackEx(mode, exceptionType, callback);
}
} }
DECL_FUNCTION(int, OSIsDebuggerInitialized) { DECL_FUNCTION(int, OSIsDebuggerInitialized) {
return true; return initDebugState;
} }
// OSSetExceptionCallbackEx is just a branch to another function.
WUPS_MUST_REPLACE(OSSetExceptionCallback, WUPS_LOADER_LIBRARY_COREINIT, OSSetExceptionCallback); // Instead of "fixing" the FunctionPatcher, we use this hacky solution :)
WUPS_MUST_REPLACE(OSSetExceptionCallbackEx, WUPS_LOADER_LIBRARY_COREINIT, OSSetExceptionCallbackEx); WUPS_MUST_REPLACE_PHYSICAL_FOR_PROCESS(OSSetExceptionCallbackEx, (0x3201C400 + 0x286b0), (0x101C400 + 0x286b0), WUPS_FP_TARGET_PROCESS_GAME_AND_MENU);
WUPS_MUST_REPLACE(OSIsDebuggerInitialized, WUPS_LOADER_LIBRARY_COREINIT, OSIsDebuggerInitialized); 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);

View File

@ -1,14 +1,16 @@
#include "screen.h" #include "screen.h"
#include "logger.h"
#include <coreinit/debug.h>
#include <gx2/state.h>
#include <memory/mappedmemory.h> #include <memory/mappedmemory.h>
Screen::Screen() : screenBuffer(nullptr) {} Screen::Screen() : screenBuffer(nullptr) {
init();
}
Screen::~Screen() { Screen::~Screen() {
if (screenBuffer) { destroyBuffer();
MEMFreeToMappedMemory(screenBuffer);
screenBuffer = nullptr;
}
} }
void Screen::init() { void Screen::init() {
@ -17,6 +19,9 @@ void Screen::init() {
uint32_t bufferSize0 = OSScreenGetBufferSizeEx(SCREEN_TV); uint32_t bufferSize0 = OSScreenGetBufferSizeEx(SCREEN_TV);
uint32_t bufferSize1 = OSScreenGetBufferSizeEx(SCREEN_DRC); uint32_t bufferSize1 = OSScreenGetBufferSizeEx(SCREEN_DRC);
screenBuffer = MEMAllocFromMappedMemoryForGX2Ex(bufferSize0 + bufferSize1, 0x100); screenBuffer = MEMAllocFromMappedMemoryForGX2Ex(bufferSize0 + bufferSize1, 0x100);
if (screenBuffer == nullptr) {
OSFatal("Failed to allocate screenbuffer");
}
OSScreenSetBufferEx(SCREEN_TV, screenBuffer); OSScreenSetBufferEx(SCREEN_TV, screenBuffer);
OSScreenSetBufferEx(SCREEN_DRC, (char *) screenBuffer + bufferSize0); OSScreenSetBufferEx(SCREEN_DRC, (char *) screenBuffer + bufferSize0);
@ -86,3 +91,11 @@ void Screen::flip() {
flip(SCREEN_TV); flip(SCREEN_TV);
flip(SCREEN_DRC); flip(SCREEN_DRC);
} }
void Screen::destroyBuffer() {
if (screenBuffer) {
MEMFreeToMappedMemory(screenBuffer);
screenBuffer = nullptr;
}
GX2Init(nullptr);
}

View File

@ -22,6 +22,8 @@ public:
static void drawText(OSScreenID screen, int x, int y, const char *text); static void drawText(OSScreenID screen, int x, int y, const char *text);
static void flip(OSScreenID screen); static void flip(OSScreenID screen);
void destroyBuffer();
private: private:
void *screenBuffer; void *screenBuffer;