This commit is contained in:
Maschell 2022-02-08 14:48:41 +01:00
parent 4993b321ce
commit 5a3bae8616
38 changed files with 603 additions and 1498 deletions

67
.clang-format Normal file
View File

@ -0,0 +1,67 @@
# Generated from CLion C/C++ Code Style settings
BasedOnStyle: LLVM
AccessModifierOffset: -4
AlignAfterOpenBracket: Align
AlignConsecutiveAssignments: Consecutive
AlignConsecutiveMacros: AcrossEmptyLinesAndComments
AlignOperands: Align
AllowAllArgumentsOnNextLine: false
AllowAllConstructorInitializersOnNextLine: false
AllowAllParametersOfDeclarationOnNextLine: false
AllowShortBlocksOnASingleLine: Always
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: All
AllowShortIfStatementsOnASingleLine: Always
AllowShortLambdasOnASingleLine: All
AllowShortLoopsOnASingleLine: true
AlwaysBreakAfterReturnType: None
AlwaysBreakTemplateDeclarations: Yes
BreakBeforeBraces: Custom
BraceWrapping:
AfterCaseLabel: false
AfterClass: false
AfterControlStatement: Never
AfterEnum: false
AfterFunction: false
AfterNamespace: false
AfterUnion: false
BeforeCatch: false
BeforeElse: false
IndentBraces: false
SplitEmptyFunction: false
SplitEmptyRecord: true
BreakBeforeBinaryOperators: None
BreakBeforeTernaryOperators: true
BreakConstructorInitializers: BeforeColon
BreakInheritanceList: BeforeColon
ColumnLimit: 0
CompactNamespaces: false
ContinuationIndentWidth: 8
IndentCaseLabels: true
IndentPPDirectives: None
IndentWidth: 4
KeepEmptyLinesAtTheStartOfBlocks: true
MaxEmptyLinesToKeep: 2
NamespaceIndentation: All
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: true
PointerAlignment: Right
ReflowComments: false
SpaceAfterCStyleCast: true
SpaceAfterLogicalNot: false
SpaceAfterTemplateKeyword: false
SpaceBeforeAssignmentOperators: true
SpaceBeforeCpp11BracedList: false
SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true
SpaceBeforeParens: ControlStatements
SpaceBeforeRangeBasedForLoopColon: true
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1
SpacesInAngles: false
SpacesInCStyleCastParentheses: false
SpacesInContainerLiterals: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
TabWidth: 4
UseTab: Never

7
.gitignore vendored Normal file
View File

@ -0,0 +1,7 @@
CMakeLists.txt
*.wps
*.elf
.idea/
build/
cmake-build-debug/
__pycache__/

6
Dockerfile Normal file
View File

@ -0,0 +1,6 @@
FROM wiiuenv/devkitppc:20211229
COPY --from=wiiuenv/wiiupluginsystem:20220123 /artifacts $DEVKITPRO
COPY --from=wiiuenv/libiosuhax:20220129 /artifacts $DEVKITPRO
WORKDIR project

142
Makefile Normal file
View File

@ -0,0 +1,142 @@
#-------------------------------------------------------------------------------
.SUFFIXES:
#-------------------------------------------------------------------------------
ifeq ($(strip $(DEVKITPRO)),)
$(error "Please set DEVKITPRO in your environment. export DEVKITPRO=<path to>/devkitpro")
endif
TOPDIR ?= $(CURDIR)
include $(DEVKITPRO)/wups/share/wups_rules
WUT_ROOT := $(DEVKITPRO)/wut
WUMS_ROOT := $(DEVKITPRO)/wums
#-------------------------------------------------------------------------------
# TARGET is the name of the output
# BUILD is the directory where object files & intermediate files will be placed
# SOURCES is a list of directories containing source code
# DATA is a list of directories containing data files
# INCLUDES is a list of directories containing header files
#-------------------------------------------------------------------------------
TARGET := debugger
BUILD := build
SOURCES := src src/utils
DATA := data
INCLUDES := src
#-------------------------------------------------------------------------------
# options for code generation
#-------------------------------------------------------------------------------
CFLAGS := -Wall -O2 -ffunction-sections \
$(MACHDEP)
CFLAGS += $(INCLUDE) -D__WIIU__ -D__WUT__ -D__WUPS__
CXXFLAGS := $(CFLAGS)
ASFLAGS := -g $(ARCH)
LDFLAGS = -g $(ARCH) $(RPXSPECS) -Wl,-Map,$(notdir $*.map) -T$(WUMS_ROOT)/share/libmappedmemory.ld -T$(WUMS_ROOT)/share/libkernel.ld $(WUPSSPECS)
ifeq ($(DEBUG),1)
CXXFLAGS += -DDEBUG -g
CFLAGS += -DDEBUG -g
endif
LIBS := -lwups -lwut -lkernel -lmappedmemory
#-------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level
# containing include and lib
#-------------------------------------------------------------------------------
LIBDIRS := $(PORTLIBS) $(WUPS_ROOT) $(WUMS_ROOT) $(WUT_ROOT) $(WUT_ROOT)/usr
#-------------------------------------------------------------------------------
# no real need to edit anything past this point unless you need to add additional
# rules for different file extensions
#-------------------------------------------------------------------------------
ifneq ($(BUILD),$(notdir $(CURDIR)))
#-------------------------------------------------------------------------------
export OUTPUT := $(CURDIR)/$(TARGET)
export TOPDIR := $(CURDIR)
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
export DEPSDIR := $(CURDIR)/$(BUILD)
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
#-------------------------------------------------------------------------------
# use CXX for linking C++ projects, CC for standard C
#-------------------------------------------------------------------------------
ifeq ($(strip $(CPPFILES)),)
#-------------------------------------------------------------------------------
export LD := $(CC)
#-------------------------------------------------------------------------------
else
#-------------------------------------------------------------------------------
export LD := $(CXX)
#-------------------------------------------------------------------------------
endif
#-------------------------------------------------------------------------------
export OFILES_BIN := $(addsuffix .o,$(BINFILES))
export OFILES_SRC := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
export OFILES := $(OFILES_BIN) $(OFILES_SRC)
export HFILES_BIN := $(addsuffix .h,$(subst .,_,$(BINFILES)))
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
-I$(CURDIR)/$(BUILD)
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
.PHONY: $(BUILD) clean all
#-------------------------------------------------------------------------------
all: $(BUILD)
$(BUILD):
@[ -d $@ ] || mkdir -p $@
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
#-------------------------------------------------------------------------------
clean:
@echo clean ...
@rm -fr $(BUILD) $(TARGET).wps $(TARGET).elf
#-------------------------------------------------------------------------------
else
.PHONY: all
DEPENDS := $(OFILES:.o=.d)
#-------------------------------------------------------------------------------
# main targets
#-------------------------------------------------------------------------------
all : $(OUTPUT).wps
$(OUTPUT).wps : $(OUTPUT).elf
$(OUTPUT).elf : $(OFILES)
$(OFILES_SRC) : $(HFILES_BIN)
#-------------------------------------------------------------------------------
# you need a rule like this for each extension you use as binary data
#-------------------------------------------------------------------------------
%.bin.o %_bin.h : %.bin
#-------------------------------------------------------------------------------
@echo $(notdir $<)
@$(bin2o)
-include $(DEPENDS)
#-------------------------------------------------------------------------------
endif
#-------------------------------------------------------------------------------

View File

@ -1,16 +0,0 @@
import os
import subprocess
PPC_GCC = r"C:\devkitPro\devkitPPC\bin\powerpc-eabi-g++"
files = []
for dirname, subdirs, subfiles in os.walk("src"):
for filename in subfiles:
if filename.endswith(".cpp") or filename.endswith(".c") or \
filename.endswith(".S") or filename.endswith(".s"):
filepath = os.path.join(dirname, filename)
files.append(filepath)
args = "-O2 -Isrc -fno-exceptions -nostartfiles -T src/link.ld -Wl,-n -Wl,--gc-sections"
subprocess.call("%s %s %s" %(PPC_GCC, args, " ".join(files)))

View File

@ -1,248 +0,0 @@
#include "cafe/coreinit.h"
#include "hbl.h"
#include <cstddef>
#include <cstdint>
int (*OSDynLoad_Acquire)(const char *name, uint32_t *handle);
int (*OSDynLoad_FindExport)(uint32_t handle, bool isData, const char *name, void *ptr);
int (*OSDynLoad_GetModuleName)(uint32_t handle, char *name, int *size);
OSMutex *OSDynLoad_gLoaderLock;
bool (*OSIsDebuggerInitialized)();
void (*exit)(int result);
void (*_Exit)(int result);
void (*OSFatal)(const char *msg);
uint32_t (*OSGetSymbolName)(uint32_t addr, char *buffer, size_t bufsize);
void (*DisassemblePPCRange)(uint32_t start, uint32_t end, DisassemblyPrintFn printFunc, DisassemblyFindSymbolFn symFunc, DisassemblyFlags flags);
void (*DisassemblePPCOpcode)(uint32_t addr, void *buffer, size_t bufsize, DisassemblyFindSymbolFn symFunc, DisassemblyFlags flags);
int (*OSSetExceptionCallback)(OSExceptionType type, OSExceptionCallback callback);
int (*OSSetExceptionCallbackEx)(OSExceptionMode mode, OSExceptionType type, OSExceptionCallback callback);
void (*OSLoadContext)(OSContext *context);
int (*OSDisableInterrupts)();
void (*OSRestoreInterrupts)(int state);
void (*__OSLockScheduler)(void *);
void (*__OSUnlockScheduler)(void *);
void (*OSInitMutex)(OSMutex *mutex);
void (*OSLockMutex)(OSMutex *mutex);
void (*OSUnlockMutex)(OSMutex *mutex);
void (*OSInitMessageQueue)(OSMessageQueue *queue, OSMessage *messages, int count);
bool (*OSSendMessage)(OSMessageQueue *queue, OSMessage *message, OSMessageFlags flags);
bool (*OSReceiveMessage)(OSMessageQueue *queue, OSMessage *message, OSMessageFlags flags);
void (*OSCreateAlarm)(OSAlarm *alarm);
bool (*OSSetAlarm)(OSAlarm *alarm, uint64_t timeout, OSAlarmCallback callback);
void (*OSCancelAlarm)(OSAlarm *alarm);
bool (*OSWaitAlarm)(OSAlarm *alarm);
OSThread *(*OSGetCurrentThread)();
OSThread *(*OSGetDefaultThread)(int core);
bool (*OSCreateThread)(OSThread *thread, OSThreadFunc func, int argc, void *argv, void *stack, uint32_t stackSize, int priority, int attr);
int (*OSResumeThread)(OSThread *thread);
bool (*OSJoinThread)(OSThread *thread, int *result);
void (*OSExitThread)(int result);
const char *(*OSGetThreadName)(OSThread *thread);
void (*OSSetThreadName)(OSThread *thread, const char *name);
uint32_t (*OSGetThreadAffinity)(OSThread *thread);
int (*OSGetThreadPriority)(OSThread *thread);
OSSystemInfo *(*OSGetSystemInfo)();
void (*OSSleepTicks)(uint64_t ticks);
uint64_t (*OSGetTitleID)();
int (*OSGetMemBound)(OSMemoryType type, uint32_t *startPtr, uint32_t *sizePtr);
uint32_t (*OSEffectiveToPhysical)(uint32_t addr);
void (*OSScreenInit)();
uint32_t (*OSScreenGetBufferSizeEx)(int screen);
void (*OSScreenSetBufferEx)(int screen, void *buffer);
void (*OSScreenEnableEx)(int screen, bool enabled);
void (*OSScreenClearBufferEx)(int screen, uint32_t color);
void (*OSScreenFlipBuffersEx)(int screen);
void (*OSScreenPutPixelEx)(int screen, int x, int y, uint32_t color);
void (*OSScreenPutFontEx)(int screen, int x, int y, const char *text);
void (*DCFlushRange)(const void *buffer, uint32_t length);
void (*DCInvalidateRange)(const void *buffer, uint32_t length);
void (*ICInvalidateRange)(const void *buffer, uint32_t length);
int (*IOS_Open)(const char *path, int mode);
int (*IOS_Ioctl)(int fd, uint32_t request, const void *inptr, uint32_t inlen, void *outptr, uint32_t outlen);
int (*IOS_Close)(int fd);
int (*FSInit)();
int (*FSAddClient)(FSClient *client, uint32_t flags);
int (*FSInitCmdBlock)(FSCmdBlock *block);
int (*FSGetMountSource)(FSClient *client, FSCmdBlock *block, FSMountSourceType type, FSMountSource *source, uint32_t flags);
int (*FSMount)(FSClient *client, FSCmdBlock *block, FSMountSource *source, char *path, uint32_t bytes, uint32_t flags);
int (*FSMakeDir)(FSClient *client, FSCmdBlock *block, const char *path, uint32_t flags);
int (*FSChangeDir)(FSClient *client, FSCmdBlock *block, const char *path, uint32_t flags);
int (*FSGetCwd)(FSClient *client, FSCmdBlock *block, char *path, int length, uint32_t flags);
int (*FSOpenDir)(FSClient *client, FSCmdBlock *block, const char *path, int *handle, uint32_t flags);
int (*FSReadDir)(FSClient *client, FSCmdBlock *block, int handle, FSDirectoryEntry *entry, uint32_t flags);
int (*FSCloseDir)(FSClient *client, FSCmdBlock *block, int handle, uint32_t flags);
int (*FSOpenFile)(FSClient *client, FSCmdBlock *block, const char *path, const char *mode, int *handle, uint32_t flags);
int (*FSGetStatFile)(FSClient *client, FSCmdBlock *block, int handle, FSStat *stat, uint32_t flags);
int (*FSReadFile)(FSClient *client, FSCmdBlock *block, void *buffer, int size, int count, int handle, int flag, uint32_t flags);
int (*FSWriteFile)(FSClient *client, FSCmdBlock *block, const void *buffer, int size, int count, int handle, int flag, uint32_t flags);
int (*FSCloseFile)(FSClient *client, FSCmdBlock *block, int handle, uint32_t flags);
int (*FSGetStat)(FSClient *client, FSCmdBlock *block, const char *path, FSStat *stat, uint32_t flags);
int (*FSRename)(FSClient *client, FSCmdBlock *block, const char *oldPath, const char *newPath, uint32_t flags);
int (*FSRemove)(FSClient *client, FSCmdBlock *block, const char *path, uint32_t flags);
int (*FSDelClient)(FSClient *client, uint32_t flags);
void (*FSShutdown)();
int (*MCP_Open)();
int (*MCP_GetDeviceId)(int handle, uint32_t *deviceId);
int (*MCP_TitleList)(int handle, uint32_t *count, MCPTitleListType *list, uint32_t size);
int (*MCP_TitleListByAppType)(int handle, uint32_t appType, uint32_t *count, MCPTitleListType *list, uint32_t size);
int (*MCP_TitleListByDevice)(int handle, const char *device, uint32_t *count, MCPTitleListType *list, uint32_t size);
void (*MCP_Close)(int handle);
void (*__KernelGetInfo)(KernelInfoType type, void *buffer, uint32_t size, uint32_t unk);
int (*snprintf)(char *str, size_t size, const char *format, ...);
void *(*MEMGetBaseHeapHandle)(int type);
uint32_t (*MEMGetAllocatableSizeForExpHeapEx)(void *handle, int alignment);
void *(**pMEMAllocFromDefaultHeap)(uint32_t size);
void *(**pMEMAllocFromDefaultHeapEx)(uint32_t size, int alignment);
void (**pMEMFreeToDefaultHeap)(void *ptr);
OSDynLoad_RPLInfo **pMainRPL;
OSDynLoad_RPLInfo **pFirstRPL;
OSThread **pThreadList;
void coreinitInitialize() {
*(uint32_t *) &OSDynLoad_Acquire = OS_SPECIFICS->OSDynLoad_Acquire;
*(uint32_t *) &OSDynLoad_FindExport = OS_SPECIFICS->OSDynLoad_FindExport;
uint32_t handle;
OSDynLoad_Acquire("coreinit.rpl", &handle);
OSDynLoad_FindExport(handle, false, "OSDynLoad_GetModuleName", &OSDynLoad_GetModuleName);
OSDynLoad_FindExport(handle, true, "OSDynLoad_gLoaderLock", &OSDynLoad_gLoaderLock);
OSDynLoad_FindExport(handle, false, "OSIsDebuggerInitialized", &OSIsDebuggerInitialized);
OSDynLoad_FindExport(handle, false, "exit", &exit);
OSDynLoad_FindExport(handle, false, "_Exit", &_Exit);
OSDynLoad_FindExport(handle, false, "OSFatal", &OSFatal);
OSDynLoad_FindExport(handle, false, "OSGetSymbolName", &OSGetSymbolName);
OSDynLoad_FindExport(handle, false, "DisassemblePPCRange", &DisassemblePPCRange);
OSDynLoad_FindExport(handle, false, "DisassemblePPCOpcode", &DisassemblePPCOpcode);
OSDynLoad_FindExport(handle, false, "OSSetExceptionCallback", &OSSetExceptionCallback);
OSDynLoad_FindExport(handle, false, "OSSetExceptionCallbackEx", &OSSetExceptionCallbackEx);
OSDynLoad_FindExport(handle, false, "OSLoadContext", &OSLoadContext);
OSDynLoad_FindExport(handle, false, "OSDisableInterrupts", &OSDisableInterrupts);
OSDynLoad_FindExport(handle, false, "OSRestoreInterrupts", &OSRestoreInterrupts);
OSDynLoad_FindExport(handle, false, "__OSLockScheduler", &__OSLockScheduler);
OSDynLoad_FindExport(handle, false, "__OSUnlockScheduler", &__OSUnlockScheduler);
OSDynLoad_FindExport(handle, false, "OSInitMutex", &OSInitMutex);
OSDynLoad_FindExport(handle, false, "OSLockMutex", &OSLockMutex);
OSDynLoad_FindExport(handle, false, "OSUnlockMutex", &OSUnlockMutex);
OSDynLoad_FindExport(handle, false, "OSInitMessageQueue", &OSInitMessageQueue);
OSDynLoad_FindExport(handle, false, "OSSendMessage", &OSSendMessage);
OSDynLoad_FindExport(handle, false, "OSReceiveMessage", &OSReceiveMessage);
OSDynLoad_FindExport(handle, false, "OSCreateAlarm", &OSCreateAlarm);
OSDynLoad_FindExport(handle, false, "OSSetAlarm", &OSSetAlarm);
OSDynLoad_FindExport(handle, false, "OSCancelAlarm", &OSCancelAlarm);
OSDynLoad_FindExport(handle, false, "OSWaitAlarm", &OSWaitAlarm);
OSDynLoad_FindExport(handle, false, "OSGetCurrentThread", &OSGetCurrentThread);
OSDynLoad_FindExport(handle, false, "OSGetDefaultThread", &OSGetDefaultThread);
OSDynLoad_FindExport(handle, false, "OSCreateThread", &OSCreateThread);
OSDynLoad_FindExport(handle, false, "OSResumeThread", &OSResumeThread);
OSDynLoad_FindExport(handle, false, "OSJoinThread", &OSJoinThread);
OSDynLoad_FindExport(handle, false, "OSExitThread", &OSExitThread);
OSDynLoad_FindExport(handle, false, "OSGetThreadName", &OSGetThreadName);
OSDynLoad_FindExport(handle, false, "OSSetThreadName", &OSSetThreadName);
OSDynLoad_FindExport(handle, false, "OSGetThreadAffinity", &OSGetThreadAffinity);
OSDynLoad_FindExport(handle, false, "OSGetThreadPriority", &OSGetThreadPriority);
OSDynLoad_FindExport(handle, false, "OSGetSystemInfo", &OSGetSystemInfo);
OSDynLoad_FindExport(handle, false, "OSSleepTicks", &OSSleepTicks);
OSDynLoad_FindExport(handle, false, "OSGetTitleID", &OSGetTitleID);
OSDynLoad_FindExport(handle, false, "OSGetMemBound", &OSGetMemBound);
OSDynLoad_FindExport(handle, false, "OSEffectiveToPhysical", &OSEffectiveToPhysical);
OSDynLoad_FindExport(handle, false, "OSScreenInit", &OSScreenInit);
OSDynLoad_FindExport(handle, false, "OSScreenGetBufferSizeEx", &OSScreenGetBufferSizeEx);
OSDynLoad_FindExport(handle, false, "OSScreenSetBufferEx", &OSScreenSetBufferEx);
OSDynLoad_FindExport(handle, false, "OSScreenEnableEx", &OSScreenEnableEx);
OSDynLoad_FindExport(handle, false, "OSScreenClearBufferEx", &OSScreenClearBufferEx);
OSDynLoad_FindExport(handle, false, "OSScreenFlipBuffersEx", &OSScreenFlipBuffersEx);
OSDynLoad_FindExport(handle, false, "OSScreenPutPixelEx", &OSScreenPutPixelEx);
OSDynLoad_FindExport(handle, false, "OSScreenPutFontEx", &OSScreenPutFontEx);
OSDynLoad_FindExport(handle, false, "DCFlushRange", &DCFlushRange);
OSDynLoad_FindExport(handle, false, "DCInvalidateRange", &DCInvalidateRange);
OSDynLoad_FindExport(handle, false, "ICInvalidateRange", &ICInvalidateRange);
OSDynLoad_FindExport(handle, false, "IOS_Open", &IOS_Open);
OSDynLoad_FindExport(handle, false, "IOS_Ioctl", &IOS_Ioctl);
OSDynLoad_FindExport(handle, false, "IOS_Close", &IOS_Close);
OSDynLoad_FindExport(handle, false, "FSInit", &FSInit);
OSDynLoad_FindExport(handle, false, "FSAddClient", &FSAddClient);
OSDynLoad_FindExport(handle, false, "FSInitCmdBlock", &FSInitCmdBlock);
OSDynLoad_FindExport(handle, false, "FSGetMountSource", &FSGetMountSource);
OSDynLoad_FindExport(handle, false, "FSMount", &FSMount);
OSDynLoad_FindExport(handle, false, "FSMakeDir", &FSMakeDir);
OSDynLoad_FindExport(handle, false, "FSChangeDir", &FSChangeDir);
OSDynLoad_FindExport(handle, false, "FSGetCwd", &FSGetCwd);
OSDynLoad_FindExport(handle, false, "FSOpenDir", &FSOpenDir);
OSDynLoad_FindExport(handle, false, "FSReadDir", &FSReadDir);
OSDynLoad_FindExport(handle, false, "FSCloseDir", &FSCloseDir);
OSDynLoad_FindExport(handle, false, "FSOpenFile", &FSOpenFile);
OSDynLoad_FindExport(handle, false, "FSGetStatFile", &FSGetStatFile);
OSDynLoad_FindExport(handle, false, "FSReadFile", &FSReadFile);
OSDynLoad_FindExport(handle, false, "FSWriteFile", &FSWriteFile);
OSDynLoad_FindExport(handle, false, "FSCloseFile", &FSCloseFile);
OSDynLoad_FindExport(handle, false, "FSGetStat", &FSGetStat);
OSDynLoad_FindExport(handle, false, "FSRename", &FSRename);
OSDynLoad_FindExport(handle, false, "FSRemove", &FSRemove);
OSDynLoad_FindExport(handle, false, "FSDelClient", &FSDelClient);
OSDynLoad_FindExport(handle, false, "FSShutdown", &FSShutdown);
OSDynLoad_FindExport(handle, false, "MCP_Open", &MCP_Open);
OSDynLoad_FindExport(handle, false, "MCP_GetDeviceId", &MCP_GetDeviceId);
OSDynLoad_FindExport(handle, false, "MCP_TitleList", &MCP_TitleList);
OSDynLoad_FindExport(handle, false, "MCP_TitleListByAppType", &MCP_TitleListByAppType);
OSDynLoad_FindExport(handle, false, "MCP_TitleListByDevice", &MCP_TitleListByDevice);
OSDynLoad_FindExport(handle, false, "MCP_Close", &MCP_Close);
OSDynLoad_FindExport(handle, false, "__KernelGetInfo", &__KernelGetInfo);
OSDynLoad_FindExport(handle, false, "__os_snprintf", &snprintf);
OSDynLoad_FindExport(handle, false, "MEMGetBaseHeapHandle", &MEMGetBaseHeapHandle);
OSDynLoad_FindExport(handle, false, "MEMGetAllocatableSizeForExpHeapEx", &MEMGetAllocatableSizeForExpHeapEx);
OSDynLoad_FindExport(handle, true, "MEMAllocFromDefaultHeap", &pMEMAllocFromDefaultHeap);
OSDynLoad_FindExport(handle, true, "MEMAllocFromDefaultHeapEx", &pMEMAllocFromDefaultHeapEx);
OSDynLoad_FindExport(handle, true, "MEMFreeToDefaultHeap", &pMEMFreeToDefaultHeap);
pMainRPL = (OSDynLoad_RPLInfo **) 0x10081014;
pFirstRPL = (OSDynLoad_RPLInfo **) 0x10081018;
pThreadList = (OSThread **) 0x100567F8;
}

View File

@ -1,512 +0,0 @@
#pragma once
#include <cstddef>
#include <cstdint>
// Timers
#define OSTimerClockSpeed ((OSGetSystemInfo()->busClockSpeed) / 4)
#define OSSecondsToTicks(val) ((uint64_t) (val) * (uint64_t) OSTimerClockSpeed)
#define OSMillisecondsToTicks(val) (((uint64_t) (val) * (uint64_t) OSTimerClockSpeed) / 1000ull)
#define OSTicksToSeconds(val) ((uint64_t) (val) / (uint64_t) OSTimerClockSpeed)
#define OSTicksToMilliseconds(val) (((uint64_t) (val) *1000ull) / (uint64_t) OSTimerClockSpeed)
// Memory
enum OSMemoryType {
MEM1 = 1,
MEM2 = 2
};
// System
enum KernelInfoType {
TITLE_INFO = 0,
SYSTEM_INFO = 1,
PLATFORM_INFO = 2,
KERNEL_STATISTICS = 4,
PERFORMANCE_NUMBERS = 5,
PROCESS_INFO = 8,
CRASH_INFO = 11,
APP_CRASH_CONTROL = 12,
COS_REPORT_MASKS = 13,
CRASH_RECOVERY = 14,
CRASH_DETAIL_LEVEL = 15,
CRASH_DUMP_TYPE = 16,
SHUTDOWN_REASON = 17,
WRITE_GATHER_REGS = 18,
PROC_DATA_BOUNDS = 19
};
struct OSSystemInfo {
uint32_t busClockSpeed;
uint32_t coreClockSpeed;
int64_t baseTime;
char _10[0x10];
};
struct OSTitleInfo {
char _0[0xC];
uint32_t ramStart;
uint32_t ramEnd;
char _14[0x20];
uint32_t systemHeapSize;
char _38[0x40];
uint32_t textStart;
uint32_t _7C;
uint32_t textSize;
uint32_t dataStart;
uint32_t _88;
uint32_t dataSize;
uint32_t loadStart;
uint32_t _94;
uint32_t loadSize;
char _9C[0xC];
};
struct OSTitleInfoEx {
OSTitleInfo info;
uint64_t osVersionId;
};
// OSDynLoad
struct OSDynLoad_NotifyData {
const char *path;
uint32_t textAddr;
uint32_t textOffset;
uint32_t textSize;
uint32_t dataAddr;
uint32_t dataOffset;
uint32_t dataSize;
uint32_t readAddr;
uint32_t readOffset;
uint32_t readSize;
};
struct OSDynLoad_RPLInfo {
uint32_t handle;
uint32_t _4;
const char *name;
char _C[0x1C];
OSDynLoad_NotifyData *notifyData;
void *entryPoint;
char _30[0x24];
OSDynLoad_RPLInfo *next;
char _58[0x3C];
};
// Thread / mutex / context
struct OSThread;
struct OSMutex;
struct OSAlarm;
struct OSContext {
uint64_t tag;
uint32_t gpr[32];
uint32_t cr;
uint32_t lr;
uint32_t ctr;
uint32_t xer;
uint32_t srr0;
uint32_t srr1;
uint32_t dsisr;
uint32_t dar;
char _A8[0xC];
uint32_t fpscr;
double fpr[32];
uint16_t spinLockCount;
uint16_t state;
uint32_t gqr[8];
uint32_t _1DC;
double psf[32];
uint64_t coretime[3];
uint64_t starttime;
uint32_t error;
uint32_t _304;
uint32_t pmc1;
uint32_t pmc2;
uint32_t pmc3;
uint32_t pmc4;
uint32_t mmcr0;
uint32_t mmcr1;
};
struct OSThreadQueue {
OSThread *head;
OSThread *tail;
void *parent;
uint32_t _C;
};
struct OSThreadLink {
OSThread *next;
OSThread *prev;
};
struct OSMutexLink {
OSMutex *next;
OSMutex *prev;
};
struct OSMutexQueue {
OSMutex *head;
OSMutex *tail;
void *parent;
uint32_t _C;
};
struct OSMutex {
uint32_t tag;
const char *name;
uint32_t _8;
OSThreadQueue queue;
OSThread *thread;
int count;
OSMutexLink link;
};
typedef int (*OSThreadFunc)(int argc, void *argv);
struct OSThread {
OSContext context;
uint32_t tag;
uint8_t state;
uint8_t attr;
uint16_t id;
uint32_t suspendCounter;
int priority;
int basePriority;
int exitValue;
char _338[0x24];
OSThreadQueue *queue;
OSThreadLink link;
OSThreadQueue joinQueue;
OSMutex *mutex;
OSMutexQueue mutexQueue;
OSThreadLink activeLink;
void *stackBase;
void *stackEnd;
OSThreadFunc entryPoint;
char _3A0[0x57C - 0x3A0];
void *specific[0x10];
int type;
const char *name;
char _5C4[0x6A0 - 0x5C4];
};
// Messages
enum OSMessageFlags {
OS_MESSAGE_FLAGS_NONE = 0,
OS_MESSAGE_FLAGS_BLOCKING = 1
};
struct OSMessage {
uint32_t message;
uint32_t args[3];
};
struct OSMessageQueue {
uint32_t tag;
const char *name;
uint32_t _8;
OSThreadQueue sendQueue;
OSThreadQueue recvQueue;
OSMessage *messages;
uint32_t size;
uint32_t first;
uint32_t used;
};
// Alarms
struct OSAlarmQueue {
uint32_t tag;
const char *name;
uint32_t _8;
OSThreadQueue threadQueue;
OSAlarm *head;
OSAlarm *tail;
};
struct OSAlarmLink {
OSAlarm *prev;
OSAlarm *next;
};
typedef void (*OSAlarmCallback)(OSAlarm *alarm, OSContext *context);
struct OSAlarm {
uint32_t tag;
const char *name;
uint32_t _8;
OSAlarmCallback callback;
uint32_t group;
uint32_t _14;
uint64_t nextFire;
OSAlarmLink link;
uint64_t period;
uint64_t start;
void *userData;
uint32_t state;
OSThreadQueue threadQueue;
OSAlarmQueue *alarmQueue;
OSContext *context;
};
// PPC disassembly
typedef void (*DisassemblyPrintFn)(const char *fmt, ...);
typedef uint32_t (*DisassemblyFindSymbolFn)(uint32_t addr, char *buffer, size_t bufsize);
enum DisassemblyFlags {
DISASSEMBLY_FLAGS_NONE = 0,
DISASSEMBLY_FLAGS_SIMPLIFY = 1,
DISASSEMBLY_FLAGS_SPACE = 0x20,
DISASSEMBLY_FLAGS_PLAIN = 0x40,
DISASSEMBLY_FLAGS_NO_OPCODE = 0x80,
DISASSEMBLY_FLAGS_PRINT_SYMBOLS = 0x100
};
// Exceptions
enum OSExceptionMode {
OS_EXCEPTION_MODE_THREAD = 1,
OS_EXCEPTION_MODE_GLOBAL = 2,
OS_EXCEPTION_MODE_THREAD_ALL_CORES = 3,
OS_EXCEPTION_MODE_GLOBAL_ALL_CORES = 4
};
enum OSExceptionType {
OS_EXCEPTION_TYPE_DSI = 2,
OS_EXCEPTION_TYPE_ISI = 3,
OS_EXCEPTION_TYPE_PROGRAM = 6
};
typedef bool (*OSExceptionCallback)(OSContext *context);
// File system
enum FSMode {
FS_MODE_READ_OWNER = 0x400,
FS_MODE_WRITE_OWNER = 0x200,
FS_MODE_EXEC_OWNER = 0x100,
FS_MODE_READ_GROUP = 0x040,
FS_MODE_WRITE_GROUP = 0x020,
FS_MODE_EXEC_GROUP = 0x010,
FS_MODE_READ_OTHER = 0x004,
FS_MODE_WRITE_OTHER = 0x002,
FS_MODE_EXEC_OTHER = 0x001
};
enum FSStatFlags {
FS_STAT_DIRECTORY = 0x80000000
};
enum FSMountSourceType {
FS_MOUNT_SOURCE_SD = 0
};
struct FSClient {
char data[0x1700];
};
struct FSCmdBlock {
char data[0xA80];
};
struct FSMountSource {
char data[0x300];
};
struct __attribute__((packed)) FSStat {
FSStatFlags flags;
FSMode mode;
uint32_t owner;
uint32_t group;
uint32_t size;
char _14[0xC];
uint32_t entryId;
int64_t created;
int64_t modified;
char _34[0x30];
};
struct FSDirectoryEntry {
FSStat info;
char name[256];
};
// MCP
struct MCPTitleListType {
uint64_t titleId;
uint32_t _4;
char path[56];
uint32_t appType;
char _48[0xC];
uint8_t device;
char _55;
char indexedDevice[10];
uint8_t _60;
};
// Function pointers
extern int (*OSDynLoad_Acquire)(const char *name, uint32_t *handle);
extern int (*OSDynLoad_FindExport)(uint32_t handle, bool isData, const char *name, void *ptr);
extern int (*OSDynLoad_GetModuleName)(uint32_t handle, char *name, int *size);
extern OSMutex *OSDynLoad_gLoaderLock;
extern bool (*OSIsDebuggerInitialized)();
extern void (*exit)(int result);
extern void (*_Exit)(int result);
extern void (*OSFatal)(const char *msg);
extern uint32_t (*OSGetSymbolName)(uint32_t addr, char *buffer, size_t bufsize);
extern void (*DisassemblePPCRange)(uint32_t start, uint32_t end, DisassemblyPrintFn printFunc, DisassemblyFindSymbolFn symFunc, DisassemblyFlags flags);
extern void (*DisassemblePPCOpcode)(uint32_t addr, void *buffer, size_t bufsize, DisassemblyFindSymbolFn symFunc, DisassemblyFlags flags);
extern int (*OSSetExceptionCallback)(OSExceptionType type, OSExceptionCallback callback);
extern int (*OSSetExceptionCallbackEx)(OSExceptionMode mode, OSExceptionType type, OSExceptionCallback callback);
extern void (*OSLoadContext)(OSContext *context);
extern int (*OSDisableInterrupts)();
extern void (*OSRestoreInterrupts)(int state);
extern void (*__OSLockScheduler)(void *);
extern void (*__OSUnlockScheduler)(void *);
extern void (*OSInitMutex)(OSMutex *mutex);
extern void (*OSLockMutex)(OSMutex *mutex);
extern void (*OSUnlockMutex)(OSMutex *mutex);
extern void (*OSInitMessageQueue)(OSMessageQueue *queue, OSMessage *messages, int count);
extern bool (*OSSendMessage)(OSMessageQueue *queue, OSMessage *message, OSMessageFlags flags);
extern bool (*OSReceiveMessage)(OSMessageQueue *queue, OSMessage *message, OSMessageFlags flags);
extern void (*OSCreateAlarm)(OSAlarm *alarm);
extern bool (*OSSetAlarm)(OSAlarm *alarm, uint64_t timeout, OSAlarmCallback callback);
extern void (*OSCancelAlarm)(OSAlarm *alarm);
extern bool (*OSWaitAlarm)(OSAlarm *alarm);
extern OSThread *(*OSGetCurrentThread)();
extern OSThread *(*OSGetDefaultThread)(int core);
extern bool (*OSCreateThread)(OSThread *thread, OSThreadFunc func, int argc, void *argv, void *stack, uint32_t stackSize, int priority, int attr);
extern int (*OSResumeThread)(OSThread *thread);
extern bool (*OSJoinThread)(OSThread *thread, int *result);
extern void (*OSExitThread)(int result);
extern const char *(*OSGetThreadName)(OSThread *thread);
extern void (*OSSetThreadName)(OSThread *thread, const char *name);
extern uint32_t (*OSGetThreadAffinity)(OSThread *thread);
extern int (*OSGetThreadPriority)(OSThread *thread);
extern OSSystemInfo *(*OSGetSystemInfo)();
extern void (*OSSleepTicks)(uint64_t ticks);
extern uint64_t (*OSGetTitleID)();
extern int (*OSGetMemBound)(OSMemoryType type, uint32_t *startPtr, uint32_t *sizePtr);
extern uint32_t (*OSEffectiveToPhysical)(uint32_t addr);
extern void (*OSScreenInit)();
extern uint32_t (*OSScreenGetBufferSizeEx)(int screen);
extern void (*OSScreenSetBufferEx)(int screen, void *buffer);
extern void (*OSScreenEnableEx)(int screen, bool enabled);
extern void (*OSScreenClearBufferEx)(int screen, uint32_t color);
extern void (*OSScreenFlipBuffersEx)(int screen);
extern void (*OSScreenPutPixelEx)(int screen, int x, int y, uint32_t color);
extern void (*OSScreenPutFontEx)(int screen, int x, int y, const char *text);
extern void (*DCFlushRange)(const void *buffer, uint32_t length);
extern void (*DCInvalidateRange)(const void *buffer, uint32_t length);
extern void (*ICInvalidateRange)(const void *buffer, uint32_t length);
extern int (*IOS_Open)(const char *path, int mode);
extern int (*IOS_Ioctl)(int fd, uint32_t request, const void *inptr, uint32_t inlen, void *outptr, uint32_t outlen);
extern int (*IOS_Close)(int fd);
extern int (*FSInit)();
extern int (*FSAddClient)(FSClient *client, uint32_t flags);
extern int (*FSInitCmdBlock)(FSCmdBlock *block);
extern int (*FSGetMountSource)(FSClient *client, FSCmdBlock *block, FSMountSourceType type, FSMountSource *source, uint32_t flags);
extern int (*FSMount)(FSClient *client, FSCmdBlock *block, FSMountSource *source, char *path, uint32_t bytes, uint32_t flags);
extern int (*FSMakeDir)(FSClient *client, FSCmdBlock *block, const char *path, uint32_t flags);
extern int (*FSChangeDir)(FSClient *client, FSCmdBlock *block, const char *path, uint32_t flags);
extern int (*FSGetCwd)(FSClient *client, FSCmdBlock *block, char *path, int length, uint32_t flags);
extern int (*FSOpenDir)(FSClient *client, FSCmdBlock *block, const char *path, int *handle, uint32_t flags);
extern int (*FSReadDir)(FSClient *client, FSCmdBlock *block, int handle, FSDirectoryEntry *entry, uint32_t flags);
extern int (*FSCloseDir)(FSClient *client, FSCmdBlock *block, int handle, uint32_t flags);
extern int (*FSOpenFile)(FSClient *client, FSCmdBlock *block, const char *path, const char *mode, int *handle, uint32_t flags);
extern int (*FSGetStatFile)(FSClient *client, FSCmdBlock *block, int handle, FSStat *stat, uint32_t flags);
extern int (*FSReadFile)(FSClient *client, FSCmdBlock *block, void *buffer, int size, int count, int handle, int flag, uint32_t flags);
extern int (*FSWriteFile)(FSClient *client, FSCmdBlock *block, const void *buffer, int size, int count, int handle, int flag, uint32_t flags);
extern int (*FSCloseFile)(FSClient *client, FSCmdBlock *block, int handle, uint32_t flags);
extern int (*FSGetStat)(FSClient *client, FSCmdBlock *block, const char *path, FSStat *stat, uint32_t flags);
extern int (*FSRename)(FSClient *client, FSCmdBlock *block, const char *oldPath, const char *newPath, uint32_t flags);
extern int (*FSRemove)(FSClient *client, FSCmdBlock *block, const char *path, uint32_t flags);
extern int (*FSDelClient)(FSClient *client, uint32_t flags);
extern void (*FSShutdown)();
extern int (*MCP_Open)();
extern int (*MCP_GetDeviceId)(int handle, uint32_t *deviceId);
extern int (*MCP_TitleList)(int handle, uint32_t *count, MCPTitleListType *list, uint32_t size);
extern int (*MCP_TitleListByAppType)(int handle, uint32_t appType, uint32_t *count, MCPTitleListType *list, uint32_t size);
extern int (*MCP_TitleListByDevice)(int handle, const char *device, uint32_t *count, MCPTitleListType *list, uint32_t size);
extern void (*MCP_Close)(int handle);
extern void (*__KernelGetInfo)(KernelInfoType type, void *buffer, uint32_t size, uint32_t unk);
extern int (*snprintf)(char *str, size_t size, const char *format, ...);
extern void *(*MEMGetBaseHeapHandle)(int type);
extern uint32_t (*MEMGetAllocatableSizeForExpHeapEx)(void *handle, int alignment);
extern void *(**pMEMAllocFromDefaultHeap)(uint32_t size);
extern void *(**pMEMAllocFromDefaultHeapEx)(uint32_t size, int alignment);
extern void (**pMEMFreeToDefaultHeap)(void *ptr);
#define MEMAllocFromDefaultHeap (*pMEMAllocFromDefaultHeap)
#define MEMAllocFromDefaultHeapEx (*pMEMAllocFromDefaultHeapEx)
#define MEMFreeToDefaultHeap (*pMEMFreeToDefaultHeap)
// Internal
extern OSDynLoad_RPLInfo **pMainRPL;
extern OSDynLoad_RPLInfo **pFirstRPL;
extern OSThread **pThreadList;
#define MainRPL (*pMainRPL)
#define FirstRPL (*pFirstRPL)
#define ThreadList (*pThreadList)
void coreinitInitialize();

View File

@ -1,20 +0,0 @@
#include "cafe/coreinit.h"
#include <cstdint>
namespace nn::act {
uint32_t (*Initialize)();
uint8_t (*GetSlotNo)();
uint32_t (*GetPersistentIdEx)(uint8_t slot);
uint32_t (*Finalize)();
} // namespace nn::act
void nnactInitialize() {
uint32_t handle;
OSDynLoad_Acquire("nn_act.rpl", &handle);
OSDynLoad_FindExport(handle, false, "Initialize__Q2_2nn3actFv", &nn::act::Initialize);
OSDynLoad_FindExport(handle, false, "GetSlotNo__Q2_2nn3actFv", &nn::act::GetSlotNo);
OSDynLoad_FindExport(handle, false, "GetPersistentIdEx__Q2_2nn3actFUc", &nn::act::GetPersistentIdEx);
OSDynLoad_FindExport(handle, false, "Finalize__Q2_2nn3actFv", &nn::act::Finalize);
}

View File

@ -1,11 +0,0 @@
#include <cstdint>
namespace nn::act {
extern uint32_t (*Initialize)();
extern uint8_t (*GetSlotNo)();
extern uint32_t (*GetPersistentIdEx)(uint8_t slot);
extern uint32_t (*Finalize)();
} // namespace nn::act
void nnactInitialize();

View File

@ -1,18 +0,0 @@
#include "cafe/coreinit.h"
#include <cstdint>
int (*SAVEInit)();
int (*SAVEOpenFile)(FSClient *client, FSCmdBlock *block, uint8_t slot, const char *path, int *handle, uint32_t flags);
int (*SAVEGetSharedDataTitlePath)(uint64_t titleId, const char *path, char *outpath, uint32_t outlen);
void (*SAVEShutdown)();
void nnsaveInitialize() {
uint32_t handle;
OSDynLoad_Acquire("nn_save.rpl", &handle);
OSDynLoad_FindExport(handle, false, "SAVEInit", &SAVEInit);
OSDynLoad_FindExport(handle, false, "SAVEOpenFile", &SAVEOpenFile);
OSDynLoad_FindExport(handle, false, "SAVEGetSharedDataTitlePath", &SAVEGetSharedDataTitlePath);
OSDynLoad_FindExport(handle, false, "SAVEShutdown", &SAVEShutdown);
}

View File

@ -1,12 +0,0 @@
#pragma once
#include "cafe/coreinit.h"
#include <cstdint>
extern int (*SAVEInit)();
extern int (*SAVEOpenFile)(FSClient *client, FSCmdBlock *block, uint8_t slot, const char *path, int *handle, uint32_t flags);
extern int (*SAVEGetSharedDataTitlePath)(uint64_t titleId, const char *path, char *outpath, uint32_t outlen);
extern void (*SAVEShutdown)();
void nnsaveInitialize();

View File

@ -1,35 +0,0 @@
#include "cafe/nsysnet.h"
#include "cafe/coreinit.h"
#include <cstdint>
int (*socket_lib_init)();
int (*inet_aton)(const char *ip, uint32_t *addr);
int (*socket)(int domain, int type, int protocol);
int (*setsockopt)(int socket, int level, int optname, void *optval, int optlen);
int (*connect)(int socket, sockaddr *addr, int addrlen);
int (*bind)(int socket, sockaddr *addr, int addrlen);
int (*listen)(int socket, int backlog);
int (*accept)(int socket, sockaddr *addr, int *addrlen);
int (*send)(int socket, const void *buffer, int size, int flags);
int (*recv)(int socket, void *buffer, int size, int flags);
int (*socketclose)(int socket);
int (*socket_lib_finish)();
void nsysnetInitialize() {
uint32_t handle;
OSDynLoad_Acquire("nsysnet.rpl", &handle);
OSDynLoad_FindExport(handle, false, "socket_lib_init", &socket_lib_init);
OSDynLoad_FindExport(handle, false, "inet_aton", &inet_aton);
OSDynLoad_FindExport(handle, false, "socket", &socket);
OSDynLoad_FindExport(handle, false, "setsockopt", &setsockopt);
OSDynLoad_FindExport(handle, false, "connect", &connect);
OSDynLoad_FindExport(handle, false, "bind", &bind);
OSDynLoad_FindExport(handle, false, "listen", &listen);
OSDynLoad_FindExport(handle, false, "accept", &accept);
OSDynLoad_FindExport(handle, false, "send", &send);
OSDynLoad_FindExport(handle, false, "recv", &recv);
OSDynLoad_FindExport(handle, false, "socketclose", &socketclose);
OSDynLoad_FindExport(handle, false, "socket_lib_finish", &socket_lib_finish);
}

View File

@ -1,37 +0,0 @@
#pragma once
#include <cstdint>
#define AF_INET 2
#define SOCK_STREAM 1
#define SOCK_DGRAM 2
#define IPPROTO_TCP 6
#define IPPROTO_UDP 17
#define SOL_SOCKET -1
#define SO_REUSEADDR 4
struct sockaddr {
uint16_t family;
uint16_t port;
uint32_t addr;
char zero[8];
};
extern int (*socket_lib_init)();
extern int (*inet_aton)(const char *ip, uint32_t *addr);
extern int (*socket)(int domain, int type, int protocol);
extern int (*setsockopt)(int socket, int level, int optname, void *optval, int optlen);
extern int (*connect)(int socket, sockaddr *addr, int addrlen);
extern int (*bind)(int socket, sockaddr *addr, int addrlen);
extern int (*listen)(int socket, int backlog);
extern int (*accept)(int socket, sockaddr *addr, int *addrlen);
extern int (*send)(int socket, const void *buffer, int size, int flags);
extern int (*recv)(int socket, void *buffer, int size, int flags);
extern int (*socketclose)(int socket);
extern int (*socket_lib_finish)();
void nsysnetInitialize();

View File

@ -1,20 +0,0 @@
#include "cafe/sysapp.h"
#include "cafe/coreinit.h"
bool (*SYSCheckTitleExists)(uint64_t titleId);
void (*SYSLaunchTitle)(uint64_t titleId);
void (*SYSLaunchMenu)();
void (*SYSLaunchTitleByPathFromLauncher)(const char *path, int len);
void sysappInitialize() {
uint32_t handle;
OSDynLoad_Acquire("sysapp.rpl", &handle);
OSDynLoad_FindExport(handle, false, "SYSCheckTitleExists", &SYSCheckTitleExists);
OSDynLoad_FindExport(handle, false, "SYSLaunchTitle", &SYSLaunchTitle);
OSDynLoad_FindExport(handle, false, "SYSLaunchMenu", &SYSLaunchMenu);
OSDynLoad_FindExport(handle, false, "_SYSLaunchTitleByPathFromLauncher", &SYSLaunchTitleByPathFromLauncher);
}

View File

@ -1,12 +0,0 @@
#pragma once
#include <cstdint>
extern bool (*SYSCheckTitleExists)(uint64_t titleId);
extern void (*SYSLaunchTitle)(uint64_t titleId);
extern void (*SYSLaunchMenu)();
extern void (*SYSLaunchTitleByPathFromLauncher)(const char *path, int len);
void sysappInitialize();

View File

@ -1,12 +0,0 @@
#include "cafe/vpad.h"
#include "cafe/coreinit.h"
void (*VPADRead)(int chan, VPADStatus *buffers, uint32_t count, int *error);
void vpadInitialize() {
uint32_t handle;
OSDynLoad_Acquire("vpad.rpl", &handle);
OSDynLoad_FindExport(handle, false, "VPADRead", &VPADRead);
}

View File

@ -1,89 +0,0 @@
#pragma once
#include <cstdint>
enum VPADButtons {
VPAD_BUTTON_A = 0x8000,
VPAD_BUTTON_B = 0x4000,
VPAD_BUTTON_X = 0x2000,
VPAD_BUTTON_Y = 0x1000,
VPAD_BUTTON_LEFT = 0x0800,
VPAD_BUTTON_RIGHT = 0x0400,
VPAD_BUTTON_UP = 0x0200,
VPAD_BUTTON_DOWN = 0x0100,
VPAD_BUTTON_ZL = 0x0080,
VPAD_BUTTON_ZR = 0x0040,
VPAD_BUTTON_L = 0x0020,
VPAD_BUTTON_R = 0x0010,
VPAD_BUTTON_PLUS = 0x0008,
VPAD_BUTTON_MINUS = 0x0004,
VPAD_BUTTON_HOME = 0x0002,
VPAD_BUTTON_SYNC = 0x0001,
VPAD_BUTTON_STICK_R = 0x00020000,
VPAD_BUTTON_STICK_L = 0x00040000,
VPAD_BUTTON_TV = 0x00010000
};
struct VPADVec2D {
float x;
float y;
};
struct VPADVec3D {
float x;
float y;
float z;
};
struct VPADDirection {
VPADVec3D x;
VPADVec3D y;
VPADVec3D z;
};
struct VPADTouchData {
uint16_t x;
uint16_t y;
uint16_t touched;
uint16_t validity;
};
struct VPADAccStatus {
VPADVec3D acc;
float magnitude;
float variation;
VPADVec2D vertical;
};
struct VPADStatus {
uint32_t hold;
uint32_t pressed;
uint32_t released;
VPADVec2D leftStick;
VPADVec2D rightStick;
VPADAccStatus accelerometer;
VPADVec3D gyro;
VPADVec3D angle;
uint8_t error;
uint8_t _51;
VPADTouchData tpNormal;
VPADTouchData tpFiltered1;
VPADTouchData tpFiltered2;
uint16_t _6A;
VPADDirection direction;
bool headphones;
VPADVec3D mag;
uint8_t volume;
uint8_t battery;
uint8_t micStatus;
uint8_t volumeEx;
char _A4[8];
};
extern void (*VPADRead)(int chan, VPADStatus *buffers, uint32_t count, int *error);
void vpadInitialize();

View File

@ -1,18 +1,22 @@
#include "cafe/coreinit.h"
#include "cafe/nsysnet.h"
#include "cafe/vpad.h"
#include "kernel.h"
#include "debugger.h"
#include "exceptions.h"
#include "input.h"
#include "logger.h"
#include "screen.h"
#include <coreinit/cache.h>
#include <coreinit/debug.h>
#include <coreinit/dynload.h>
#include <coreinit/exception.h>
#include <coreinit/memory.h>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <malloc.h>
#include <vpad/input.h>
Debugger *debugger;
bool BreakPoint::isRange(uint32_t addr, uint32_t length) {
bool BreakPoint::isRange(uint32_t addr, uint32_t length) const {
return address >= addr && address <= addr + length - 1;
}
@ -125,7 +129,7 @@ void BreakPointMgr::read(void *buffer, uint32_t addr, uint32_t length) {
char *bufptr = (char *) buffer + offset;
if (bp->address > addr + length - 4) {
uint32_t value = bp->instruction;
for (int i = 0; i < length - offset; i++) {
for (uint32_t i = 0; i < length - offset; i++) {
bufptr[i] = value >> 24;
value <<= 8;
}
@ -195,7 +199,7 @@ uint32_t BreakPointMgr::getInstr(uint32_t addr) {
void BreakPointMgr::clearSpecial(OSThread *thread) {
lock();
for (int i = 0; i < special.size(); i++) {
for (size_t i = 0; i < special.size(); i++) {
SpecialBreakPoint *bp = special[i];
if (bp->thread == thread) {
disable(bp);
@ -276,6 +280,7 @@ bool ExceptionState::isBreakpoint() {
}
void ExceptionState::resume() {
DEBUG_FUNCTION_LINE("OSLoadContext");
OSLoadContext(&context);
}
@ -294,12 +299,11 @@ void ExceptionMgr::unlock() {
void ExceptionMgr::cleanup() {
OSMessage message;
message.message = Debugger::STEP_CONTINUE;
message.message = (void *) Debugger::STEP_CONTINUE;
lock();
for (int i = 0; i < list.size(); i++) {
ExceptionState *state = list[i];
for (auto state : list) {
if (state->isPaused) {
OSSendMessage(&state->queue, &message, OS_MESSAGE_FLAGS_NONE);
}
@ -310,8 +314,7 @@ void ExceptionMgr::cleanup() {
ExceptionState *ExceptionMgr::find(OSThread *thread) {
lock();
for (int i = 0; i < list.size(); i++) {
ExceptionState *state = list[i];
for (auto state : list) {
if (state->thread == thread) {
unlock();
return state;
@ -493,7 +496,7 @@ void StepMgr::adjustAddress(ExceptionState *state) {
bool Debugger::checkDataRead(uint32_t addr, uint32_t length) {
uint32_t memStart, memSize;
OSGetMemBound(MEM2, &memStart, &memSize);
OSGetMemBound(OS_MEM2, &memStart, &memSize);
uint32_t memEnd = memStart + memSize;
@ -502,7 +505,7 @@ bool Debugger::checkDataRead(uint32_t addr, uint32_t length) {
Debugger::StepCommand Debugger::notifyBreak(ExceptionState *state) {
OSMessage message;
message.message = ExceptionState::PROGRAM;
message.message = (void *) ExceptionState::PROGRAM;
message.args[0] = (uint32_t) &state->context;
message.args[1] = sizeof(OSContext);
message.args[2] = (uint32_t) state->thread;
@ -511,7 +514,7 @@ Debugger::StepCommand Debugger::notifyBreak(ExceptionState *state) {
state->isPaused = true;
OSReceiveMessage(&state->queue, &message, OS_MESSAGE_FLAGS_BLOCKING);
state->isPaused = false;
return (StepCommand) message.message;
return (StepCommand) (uint32_t) message.message;
}
void Debugger::resumeBreakPoint(ExceptionState *state) {
@ -539,24 +542,28 @@ void Debugger::handleBreakPoint(ExceptionState *state) {
Screen screen;
screen.init();
screen.drawText(
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();
Screen::flip();
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);
}
@ -579,7 +586,7 @@ void Debugger::handleCrash(ExceptionState *state) {
stepper.adjustAddress(state);
if (connected) {
OSMessage message;
message.message = state->type;
message.message = (void *) state->type;
message.args[0] = (uint32_t) &state->context;
message.args[1] = sizeof(OSContext);
message.args[2] = (uint32_t) state->thread;
@ -628,7 +635,7 @@ void Debugger::exceptionHandler(OSContext *context, ExceptionState::Type type) {
debugger->handleException(context, type);
}
bool Debugger::dsiHandler(OSContext *context) {
BOOL Debugger::dsiHandler(OSContext *context) {
OSContext *info = new OSContext();
memcpy(info, context, sizeof(OSContext));
context->srr0 = (uint32_t) exceptionHandler;
@ -637,7 +644,7 @@ bool Debugger::dsiHandler(OSContext *context) {
return true;
}
bool Debugger::isiHandler(OSContext *context) {
BOOL Debugger::isiHandler(OSContext *context) {
OSContext *info = new OSContext();
memcpy(info, context, sizeof(OSContext));
context->srr0 = (uint32_t) exceptionHandler;
@ -646,7 +653,7 @@ bool Debugger::isiHandler(OSContext *context) {
return true;
}
bool Debugger::programHandler(OSContext *context) {
BOOL Debugger::programHandler(OSContext *context) {
OSContext *info = new OSContext();
memcpy(info, context, sizeof(OSContext));
context->srr0 = (uint32_t) exceptionHandler;
@ -664,13 +671,37 @@ 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",
"COMMAND_READ",
"COMMAND_WRITE",
"COMMAND_WRITE_CODE",
"COMMAND_GET_MODULE_NAME",
"COMMAND_GET_MODULE_LIST",
"COMMAND_GET_THREAD_LIST",
"COMMAND_GET_STACK_TRACE",
"COMMAND_TOGGLE_BREAKPOINT",
"COMMAND_POKE_REGISTERS",
"COMMAND_RECEIVE_MESSAGES",
"COMMAND_SEND_MESSAGE"};
void Debugger::mainLoop(Client *client) {
while (true) {
DEBUG_FUNCTION_LINE("About to enter mainLoop while");
while (!stopRunning) {
uint8_t cmd;
if (!client->recvall(&cmd, 1)) return;
if (cmd == COMMAND_CLOSE) return;
else if (cmd == COMMAND_READ) {
if (cmd <= 11) {
DEBUG_FUNCTION_LINE("Recieved command %s %d", commandNames[cmd], cmd);
}
if (cmd == COMMAND_CLOSE) {
return;
} else if (cmd == COMMAND_READ) {
uint32_t addr, length;
if (!client->recvall(&addr, 4)) return;
if (!client->recvall(&length, 4)) return;
@ -678,10 +709,10 @@ void Debugger::mainLoop(Client *client) {
char *buffer = new char[length];
breakpoints.read(buffer, addr, length);
if (!client->sendall(buffer, length)) {
delete buffer;
delete[] buffer;
return;
}
delete buffer;
delete[] buffer;
} else if (cmd == COMMAND_WRITE) {
uint32_t addr, length;
if (!client->recvall(&addr, 4)) return;
@ -694,47 +725,53 @@ void Debugger::mainLoop(Client *client) {
char *buffer = new char[length];
if (!client->recvall(buffer, length)) {
delete buffer;
delete[] buffer;
return;
}
breakpoints.write(buffer, addr, length);
delete buffer;
delete[] buffer;
} else if (cmd == COMMAND_GET_MODULE_NAME) {
char name[0x40];
int length = 0x40;
OSDynLoad_GetModuleName(-1, name, &length);
OSDynLoad_GetModuleName(reinterpret_cast<OSDynLoad_Module>(-1), name, &length);
length = strlen(name);
if (!client->sendall(&length, 4)) return;
if (!client->sendall(name, length)) return;
} else if (cmd == COMMAND_GET_MODULE_LIST) {
OSLockMutex(OSDynLoad_gLoaderLock);
int num_rpls = OSDynLoad_GetNumberOfRPLs();
if (num_rpls == 0) {
return;
}
std::vector<OSDynLoad_NotifyData> rpls;
rpls.resize(num_rpls);
bool ret = OSDynLoad_GetRPLInfo(0, num_rpls, rpls.data());
if (!ret) {
return;
}
char buffer[0x1000]; //This should be enough
uint32_t offset = 0;
OSDynLoad_RPLInfo *current = FirstRPL;
while (current) {
OSDynLoad_NotifyData *info = current->notifyData;
uint32_t namelen = strlen(current->name);
for (auto &info : rpls) {
uint32_t namelen = strlen(info.name);
if (offset + 0x18 + namelen > 0x1000) {
break;
}
uint32_t *infobuf = (uint32_t *) (buffer + offset);
infobuf[0] = info->textAddr;
infobuf[1] = info->textSize;
infobuf[2] = info->dataAddr;
infobuf[3] = info->dataSize;
infobuf[4] = (uint32_t) current->entryPoint;
auto *infobuf = (uint32_t *) (buffer + offset);
infobuf[0] = info.textAddr;
infobuf[1] = info.textSize;
infobuf[2] = info.dataAddr;
infobuf[3] = info.dataSize;
infobuf[4] = (uint32_t) 0; // TODO: missing
infobuf[5] = namelen;
memcpy(&infobuf[6], current->name, namelen);
offset += 0x18 + namelen;
current = current->next;
memcpy(&infobuf[6], info.name, namelen);
offset += 0x18 + strlen(info.name);
}
OSUnlockMutex(OSDynLoad_gLoaderLock);
//OSUnlockMutex(OSDynLoad_gLoaderLock);
if (!client->sendall(&offset, 4)) return;
if (!client->sendall(buffer, offset)) return;
@ -758,9 +795,10 @@ void Debugger::mainLoop(Client *client) {
}
int priority = current->basePriority;
if (current->type == 1) {
int type = *(uint32_t *) (current->__unk11);
if (type == 1) {
priority -= 0x20;
} else if (current->type == 2) {
} else if (type == 2) {
priority -= 0x40;
}
@ -768,7 +806,7 @@ void Debugger::mainLoop(Client *client) {
infobuf[0] = (uint32_t) current;
infobuf[1] = current->attr & 7;
infobuf[2] = priority;
infobuf[3] = (uint32_t) current->stackBase;
infobuf[3] = (uint32_t) current->stackStart;
infobuf[4] = (uint32_t) current->stackEnd;
infobuf[5] = (uint32_t) current->entryPoint;
infobuf[6] = namelen;
@ -851,7 +889,7 @@ void Debugger::mainLoop(Client *client) {
OSMessage message;
if (!client->recvall(&message, sizeof(OSMessage))) return;
OSThread *thread = (OSThread *) message.args[0];
auto *thread = (OSThread *) message.args[0];
exceptions.lock();
ExceptionState *state = exceptions.find(thread);
@ -859,30 +897,32 @@ void Debugger::mainLoop(Client *client) {
OSSendMessage(&state->queue, &message, OS_MESSAGE_FLAGS_NONE);
}
exceptions.unlock();
} else {
DEBUG_FUNCTION_LINE("Recieved unknown command %d", cmd);
}
}
}
void Debugger::threadFunc() {
int result = socket_lib_init();
if (result < 0) {
OSFatal("Failed to initialize socket library");
}
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.!");
Server server;
Client client;
DEBUG_FUNCTION_LINE("Set initialized = true");
initialized = true;
while (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();
@ -890,7 +930,8 @@ void Debugger::threadFunc() {
}
}
int Debugger::threadEntry(int argc, void *argv) {
int Debugger::threadEntry(int argc, const char **argv) {
DEBUG_FUNCTION_LINE("threadEntry");
debugger->threadFunc();
return 0;
}
@ -900,25 +941,45 @@ void Debugger::start() {
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();
serverThread = new OSThread();
char *stack = new char[0x8000];
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,
stack + STACK_SIZE, STACK_SIZE,
serverStack + STACK_SIZE, STACK_SIZE,
0, 12);
DEBUG_FUNCTION_LINE("Set thread name");
OSSetThreadName(serverThread, "Debug Server");
DEBUG_FUNCTION_LINE("Resume thread");
OSResumeThread(serverThread);
while (!initialized) {
DEBUG_FUNCTION_LINE("Wait for thread init");
OSSleepTicks(OSMillisecondsToTicks(20));
}
DEBUG_FUNCTION_LINE("Thread init done! Exit start()");
}
Debugger *debugger;
Debugger::~Debugger() {
stopRunning = true;
OSJoinThread(serverThread, nullptr);
free(serverStack);
serverStack = nullptr;
free(serverThread);
serverThread = nullptr;
}

View File

@ -1,9 +1,11 @@
#pragma once
#include "cafe/coreinit.h"
#include "kernel.h"
#include "socket.h"
#include <coreinit/messagequeue.h>
#include <coreinit/mutex.h>
#include <coreinit/thread.h>
#include <cstdint>
#include <vector>
@ -14,6 +16,10 @@
#define TRAP 0x7FE00008
extern OSThread **pThreadList;
#define ThreadList (*pThreadList)
template<int N>
class Bits {
public:
@ -26,7 +32,7 @@ public:
}
private:
uint32_t value;
uint32_t value{};
};
@ -42,14 +48,14 @@ public:
void resume();
Type type;
OSContext context;
OSContext context{};
OSThread *thread;
OSThread *thread{};
OSMessageQueue queue;
OSMessage message;
OSMessageQueue queue{};
OSMessage message{};
bool isPaused;
bool isPaused{};
};
@ -70,7 +76,7 @@ private:
class BreakPoint {
public:
bool isRange(uint32_t addr, uint32_t length);
bool isRange(uint32_t addr, uint32_t length) const;
uint32_t address;
uint32_t instruction;
@ -91,7 +97,7 @@ public:
}
T *alloc() {
for (int i = 0; i < size(); i++) {
for (size_t i = 0; i < size(); i++) {
if (list[i].address == 0) {
return &list[i];
}
@ -105,7 +111,7 @@ public:
}
T *find(uint32_t addr) {
for (int i = 0; i < size(); i++) {
for (size_t i = 0; i < size(); i++) {
if (list[i].address == addr) {
return &list[i];
}
@ -114,17 +120,17 @@ public:
}
T *findRange(uint32_t addr, uint32_t length, int *index) {
int i = *index;
size_t i = *index;
while (i < size()) {
if (list[i].isRange(addr, length)) {
*index = i + 1;
*index = (int) i + 1;
return &list[i];
}
i++;
}
if (i > *index) {
*index = i;
if ((int) i > *index) {
*index = (int) i;
}
return nullptr;
}
@ -134,7 +140,7 @@ public:
}
void cleanup() {
for (int i = 0; i < size(); i++) {
for (size_t i = 0; i < size(); i++) {
if (list[i].address != 0) {
KernelWriteU32(list[i].address, list[i].instruction);
list[i].address = 0;
@ -176,7 +182,7 @@ private:
BreakPointList<BreakPoint> breakpoints;
BreakPointList<SpecialBreakPoint> special;
OSMutex mutex;
OSMutex mutex{};
};
@ -194,7 +200,7 @@ private:
uint32_t *alloc();
void free(int index);
void branchConditional(ExceptionState *state, uint32_t instruction, uint32_t target, bool checkCtr);
static void branchConditional(ExceptionState *state, uint32_t instruction, uint32_t target, bool checkCtr);
OSMutex mutex;
@ -212,6 +218,8 @@ public:
void start();
~Debugger();
private:
enum Command {
COMMAND_CLOSE,
@ -228,10 +236,10 @@ private:
COMMAND_SEND_MESSAGE
};
static int threadEntry(int argc, void *argv);
static bool dsiHandler(OSContext *context);
static bool isiHandler(OSContext *context);
static bool programHandler(OSContext *context);
static int threadEntry(int argc, const char **argv);
static BOOL dsiHandler(OSContext *context);
static BOOL isiHandler(OSContext *context);
static BOOL programHandler(OSContext *context);
static void exceptionHandler(OSContext *context, ExceptionState::Type type);
void threadFunc();
@ -247,18 +255,20 @@ private:
bool checkDataRead(uint32_t addr, uint32_t length);
OSMessageQueue eventQueue;
OSMessage eventMessages[MESSAGE_COUNT];
OSMessageQueue eventQueue{};
OSMessage eventMessages[MESSAGE_COUNT]{};
OSThread *serverThread;
OSThread *serverThread{};
char *serverStack{};
BreakPointMgr breakpoints;
ExceptionMgr exceptions;
StepMgr stepper;
StepMgr stepper{};
bool initialized;
bool connected;
bool firstTrap;
bool stopRunning = false;
bool initialized{};
bool connected{};
bool firstTrap{};
};
extern Debugger *debugger;
extern "C" Debugger *debugger;

View File

@ -1,5 +1,9 @@
#include "cafe/coreinit.h"
#include <coreinit/context.h>
#include <coreinit/debug.h>
#include <coreinit/exception.h>
#include <cstdio>
void DumpContext(OSContext *context, const char *excType) {
char buffer[1000];
@ -28,17 +32,17 @@ void DumpContext(OSContext *context, const char *excType) {
OSFatal(buffer);
}
bool DSIHandler(OSContext *context) {
BOOL DSIHandler(OSContext *context) {
DumpContext(context, "A DSI");
return false;
}
bool ISIHandler(OSContext *context) {
BOOL ISIHandler(OSContext *context) {
DumpContext(context, "An ISI");
return false;
}
bool ProgramHandler(OSContext *context) {
BOOL ProgramHandler(OSContext *context) {
DumpContext(context, "A program");
return false;
}

View File

@ -1,15 +0,0 @@
#pragma once
#include <cstdint>
#define MEM_BASE 0x800000
struct OsSpecifics {
uint32_t OSDynLoad_Acquire;
uint32_t OSDynLoad_FindExport;
};
#define OS_SPECIFICS ((OsSpecifics *) (MEM_BASE + 0x1500))
#define EXIT_SUCCESS 0
#define EXIT_RELAUNCH_ON_LOAD -3

View File

@ -1,21 +1,20 @@
#include "cafe/vpad.h"
#include <cstdint>
#include <vpad/input.h>
uint32_t GetInput(uint32_t mask) {
VPADStatus input;
int error;
VPADRead(0, &input, 1, &error);
return input.pressed & mask;
VPADReadError error;
VPADRead(VPAD_CHAN_0, &input, 1, &error);
return input.trigger & mask;
}
uint32_t WaitInput(uint32_t mask) {
VPADStatus input;
int error;
VPADReadError error;
while (true) {
VPADRead(0, &input, 1, &error);
if (input.pressed & mask) {
return input.pressed & mask;
VPADRead(VPAD_CHAN_0, &input, 1, &error);
if (input.trigger & mask) {
return input.trigger & mask;
}
}
}

View File

@ -1,28 +0,0 @@
.global SCKernelCopyData
SCKernelCopyData:
// Disable data address translation
mfmsr %r6
li %r7, 0x10
andc %r6, %r6, %r7
mtmsr %r6
// Copy data
addi %r3, %r3, -1
addi %r4, %r4, -1
mtctr %r5
SCKernelCopyData_loop:
lbzu %r5, 1(%r4)
stbu %r5, 1(%r3)
bdnz SCKernelCopyData_loop
// Enable data address translation
ori %r6, %r6, 0x10
mtmsr %r6
blr
.global KernelCopyData
KernelCopyData:
li %r0, 0x2500
sc
blr

View File

@ -1,16 +1,7 @@
#include "cafe/coreinit.h"
#include <coreinit/cache.h>
#include <coreinit/memorymap.h>
#include <cstdint>
#define KERN_SYSCALL_TBL1 0xFFE84C70 //Unknown
#define KERN_SYSCALL_TBL2 0xFFE85070 //Games
#define KERN_SYSCALL_TBL3 0xFFE85470 //Loader
#define KERN_SYSCALL_TBL4 0xFFEAAA60 //Home menu
#define KERN_SYSCALL_TBL5 0xFFEAAE60 //Browser
extern "C" void SCKernelCopyData(uint32_t dst, uint32_t src, uint32_t len);
extern "C" void KernelCopyData(uint32_t dst, uint32_t src, uint32_t len);
#include <kernel/kernel.h>
void KernelWrite(uint32_t addr, const void *data, uint32_t length) {
uint32_t dst = OSEffectiveToPhysical(addr);
@ -27,36 +18,3 @@ void KernelWriteU32(uint32_t addr, uint32_t value) {
DCFlushRange((void *) addr, 4);
ICInvalidateRange((void *) addr, 4);
}
/* Write a 32-bit word with kernel permissions */
void __attribute__((noinline)) kern_write(uint32_t addr, uint32_t value) {
asm volatile(
"li 3,1\n"
"li 4,0\n"
"mr 5,%1\n"
"li 6,0\n"
"li 7,0\n"
"lis 8,1\n"
"mr 9,%0\n"
"mr %1,1\n"
"li 0,0x3500\n"
"sc\n"
"nop\n"
"mr 1,%1\n"
:
: "r"(addr), "r"(value)
: "memory", "ctr", "lr", "0", "3", "4", "5", "6", "7", "8", "9", "10",
"11", "12");
}
void PatchSyscall(int index, uint32_t addr) {
kern_write(KERN_SYSCALL_TBL1 + index * 4, addr);
kern_write(KERN_SYSCALL_TBL2 + index * 4, addr);
kern_write(KERN_SYSCALL_TBL3 + index * 4, addr);
kern_write(KERN_SYSCALL_TBL4 + index * 4, addr);
kern_write(KERN_SYSCALL_TBL5 + index * 4, addr);
}
void kernelInitialize() {
PatchSyscall(0x25, (uint32_t) SCKernelCopyData);
}

View File

@ -1,11 +1,6 @@
#pragma once
#include <cstdint>
void KernelWrite(uint32_t addr, const void *data, uint32_t length);
void KernelWriteU32(uint32_t addr, uint32_t value);
void PatchSyscall(int index, void *ptr);
void kernelInitialize();

View File

@ -1,26 +0,0 @@
OUTPUT(diibugger.elf)
ENTRY(entryPoint)
SECTIONS {
. = 0x00802000;
.text : {
*(.text*);
}
.rodata : {
*(.rodata*);
}
.data : {
*(.data*);
*(.sdata*);
}
.bss : {
*(.bss*);
*(.sbss*);
}
/DISCARD/ : {
*(*);
}
}

36
src/logger.c Normal file
View File

@ -0,0 +1,36 @@
#ifdef DEBUG
#include <stdint.h>
#include <whb/log_cafe.h>
#include <whb/log_module.h>
#include <whb/log_udp.h>
uint32_t moduleLogInit = false;
uint32_t cafeLogInit = false;
uint32_t udpLogInit = false;
#endif // DEBUG
void initLogging() {
#ifdef DEBUG
if (!(moduleLogInit = WHBLogModuleInit())) {
cafeLogInit = WHBLogCafeInit();
udpLogInit = WHBLogUdpInit();
}
#endif // DEBUG
}
void deinitLogging() {
#ifdef DEBUG
if (moduleLogInit) {
WHBLogModuleDeinit();
moduleLogInit = false;
}
if (cafeLogInit) {
WHBLogCafeDeinit();
cafeLogInit = false;
}
if (udpLogInit) {
WHBLogUdpDeinit();
udpLogInit = false;
}
#endif // DEBUG
}

43
src/logger.h Normal file
View File

@ -0,0 +1,43 @@
#pragma once
#include <string.h>
#include <whb/log.h>
#ifdef __cplusplus
extern "C" {
#endif
#ifdef DEBUG
#define __FILENAME_X__ (strrchr(__FILE__, '\\') ? strrchr(__FILE__, '\\') + 1 : __FILE__)
#define __FILENAME__ (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILENAME_X__)
#define DEBUG_FUNCTION_LINE_VERBOSE(FMT, ARGS...) while (0)
#define DEBUG_FUNCTION_LINE(FMT, ARGS...) \
do { \
WHBLogPrintf("[%23s]%30s@L%04d: " FMT "", __FILENAME__, __FUNCTION__, __LINE__, ##ARGS); \
} while (0)
#define DEBUG_FUNCTION_LINE_WRITE(FMT, ARGS...) \
do { \
WHBLogWritef("[%23s]%30s@L%04d: " FMT "", __FILENAME__, __FUNCTION__, __LINE__, ##ARGS); \
} while (0)
#else
#define DEBUG_FUNCTION_LINE_VERBOSE(FMT, ARGS...) while (0)
#define DEBUG_FUNCTION_LINE(FMT, ARGS...) while (0)
#define DEBUG_FUNCTION_LINE_WRITE(FMT, ARGS...) while (0)
#endif
void initLogging();
void deinitLogging();
#ifdef __cplusplus
}
#endif

View File

@ -1,87 +1,36 @@
#include "cafe/coreinit.h"
#include "cafe/nn_act.h"
#include "cafe/nn_save.h"
#include "cafe/nsysnet.h"
#include "cafe/sysapp.h"
#include "cafe/vpad.h"
#include "hbl.h"
#include "kernel.h"
#include "debugger.h"
#include "exceptions.h"
#include "menu.h"
#include "patches.h"
#include "screen.h"
#include "logger.h"
#include <coreinit/debug.h>
#include <wups.h>
OSThread **pThreadList;
bool GetTitleIdOnDisk(uint64_t *titleId) {
MCPTitleListType title;
uint32_t count = 0;
WUPS_PLUGIN_NAME("Debugger");
WUPS_PLUGIN_DESCRIPTION("FTP Server");
WUPS_PLUGIN_VERSION("0.1");
WUPS_PLUGIN_AUTHOR("Kinnay");
WUPS_PLUGIN_LICENSE("GPL");
int handle = MCP_Open();
MCP_TitleListByDevice(handle, "odd", &count, &title, sizeof(title));
MCP_Close(handle);
if (count > 0) {
*titleId = title.titleId;
return true;
}
return false;
}
int MenuMain() {
Screen screen;
screen.init();
Menu menu(&screen);
Menu::Option result = menu.show();
if (result == Menu::Exit) return EXIT_SUCCESS;
else if (result == Menu::LaunchDisk) {
uint64_t titleId;
if (GetTitleIdOnDisk(&titleId)) {
SYSLaunchTitle(titleId);
} else {
menu.setMessage("Please insert a valid disk");
}
} else if (result == Menu::ReturnToMenu) {
SYSLaunchMenu();
}
return EXIT_RELAUNCH_ON_LOAD;
}
int DebuggerMain() {
ApplyPatches();
debugger = new Debugger();
debugger->start();
return EXIT_RELAUNCH_ON_LOAD;
}
bool firstRun = true;
int start() {
coreinitInitialize();
kernelInitialize();
vpadInitialize();
sysappInitialize();
nsysnetInitialize();
nnsaveInitialize();
nnactInitialize();
WUPS_USE_WUT_DEVOPTAB();
INITIALIZE_PLUGIN() {
InstallExceptionHandlers();
int result;
if (firstRun) {
result = MenuMain();
} else {
result = DebuggerMain();
}
firstRun = false;
return result;
ON_APPLICATION_START() {
initLogging();
DEBUG_FUNCTION_LINE("Started Debugger plugin");
pThreadList = (OSThread **) 0x100567F8;
debugger = new Debugger();
DEBUG_FUNCTION_LINE("Created Debugger");
debugger->start();
DEBUG_FUNCTION_LINE("Started Debugger thread");
}
extern "C" int entryPoint() {
return start();
ON_APPLICATION_REQUESTS_EXIT() {
DEBUG_FUNCTION_LINE("Deleting Debugger thread");
delete debugger;
DEBUG_FUNCTION_LINE("Deleted Debugger thread");
deinitLogging();
}

View File

@ -1,28 +0,0 @@
#include "cafe/coreinit.h"
#include <cstddef>
void *operator new(size_t size) {
return MEMAllocFromDefaultHeap(size);
}
void *operator new[](size_t size) {
return MEMAllocFromDefaultHeap(size);
}
void *operator new(size_t size, int alignment) {
return MEMAllocFromDefaultHeapEx(size, alignment);
}
void *operator new[](size_t size, int alignment) {
return MEMAllocFromDefaultHeapEx(size, alignment);
}
void operator delete(void *ptr) {
MEMFreeToDefaultHeap(ptr);
}
void operator delete(void *ptr, size_t size) {
MEMFreeToDefaultHeap(ptr);
}

View File

@ -1,7 +0,0 @@
#pragma once
#include <cstddef>
void *operator new(size_t size, int alignment);
void *operator new[](size_t size, int alignment);

View File

@ -1,9 +1,8 @@
#include "menu.h"
#include "cafe/vpad.h"
#include "color.h"
#include "input.h"
#include "screen.h"
#include <vpad/input.h>
Menu::Menu(Screen *screen) : screen(screen) {
currentOption = LaunchDisk;
@ -30,14 +29,14 @@ void Menu::setMessage(const char *message) {
void Menu::redraw() {
screen->clear(COLOR_BLUE);
screen->drawText(5, 5, "Wii U Debugger");
screen->drawText(5, 7, "Choose an option:");
screen->drawText(8, 9, "Install and launch disc");
screen->drawText(8, 10, "Install and return to system menu");
screen->drawText(8, 11, "Exit without installing");
screen->drawText(5, 9 + currentOption, ">");
Screen::drawText(5, 5, "Wii U Debugger");
Screen::drawText(5, 7, "Choose an option:");
Screen::drawText(8, 9, "Install and launch disc");
Screen::drawText(8, 10, "Install and return to system menu");
Screen::drawText(8, 11, "Exit without installing");
Screen::drawText(5, 9 + currentOption, ">");
if (message) {
screen->drawText(5, 13, message);
Screen::drawText(5, 13, message);
}
screen->flip();
Screen::flip();
}

View File

@ -5,11 +5,9 @@
class Menu {
public:
enum Option {
LaunchDisk,
enum Option { LaunchDisk,
ReturnToMenu,
Exit
};
Exit };
Menu(Screen *screen);
Option show();

View File

@ -1,56 +1,17 @@
#include "cafe/coreinit.h"
#include "kernel.h"
#include <cstdint>
#include <wups.h>
int OSSetExceptionCallback_Patch() {
DECL_FUNCTION(int, OSSetExceptionCallback) {
return 0;
}
int OSSetExceptionCallbackEx_Patch() {
DECL_FUNCTION(int, OSSetExceptionCallbackEx) {
return 0;
}
bool OSIsDebuggerInitialized_Patch() {
DECL_FUNCTION(int, OSIsDebuggerInitialized) {
return true;
}
void Patch(void *funcPtr, void *patchPtr) {
OSDynLoad_NotifyData *sectionInfo = MainRPL->notifyData;
uint32_t func = (uint32_t) funcPtr;
uint32_t patch = (uint32_t) patchPtr;
if (func < 0x01800000) { //OS function (with trampoline)
for (uint32_t addr = sectionInfo->textAddr; addr < 0x10000000; addr += 4) {
uint32_t *instrs = (uint32_t *) addr;
if (instrs[0] == (0x3D600000 | (func >> 16)) && //lis r11, func@h
instrs[1] == (0x616B0000 | (func & 0xFFFF)) && //ori r11, r11, func@l
instrs[2] == 0x7D6903A6 && //mtctr r11
instrs[3] == 0x4E800420) //bctr
{
KernelWriteU32(addr, 0x3D600000 | (patch >> 16)); //lis r11, patch@h
KernelWriteU32(addr + 4, 0x616B0000 | (patch & 0xFFFF)); //ori r11, r11, patch@l
}
}
} else { //Dynamic function
for (uint32_t addr = sectionInfo->textAddr; addr < 0x10000000; addr += 4) {
uint32_t instr = *(uint32_t *) addr;
if ((instr & 0xFC000002) == 0x48000000) { //b or bl
if ((instr & 0x03FFFFFC) == func - addr) {
instr = instr & ~0x03FFFFFC;
instr |= patch;
instr |= 2; //Turn b/bl into ba/bla
KernelWriteU32(addr, instr);
}
}
}
}
}
void ApplyPatches() {
Patch((void *) OSSetExceptionCallback, (void *) OSSetExceptionCallback_Patch);
Patch((void *) OSSetExceptionCallbackEx, (void *) OSSetExceptionCallbackEx_Patch);
Patch((void *) OSIsDebuggerInitialized, (void *) OSIsDebuggerInitialized_Patch);
}
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);

View File

@ -1,37 +1,38 @@
#include "screen.h"
#include "cafe/coreinit.h"
#include "memory.h"
Screen::Screen() : screenBuffer(0) {}
#include <memory/mappedmemory.h>
Screen::Screen() : screenBuffer(nullptr) {}
Screen::~Screen() {
if (screenBuffer) {
operator delete(screenBuffer);
MEMFreeToMappedMemory(screenBuffer);
screenBuffer = nullptr;
}
}
void Screen::init() {
OSScreenInit();
uint32_t bufferSize0 = OSScreenGetBufferSizeEx(0);
uint32_t bufferSize1 = OSScreenGetBufferSizeEx(1);
screenBuffer = operator new(bufferSize0 + bufferSize1, 0x40);
OSScreenSetBufferEx(0, screenBuffer);
OSScreenSetBufferEx(1, (char *) screenBuffer + bufferSize0);
uint32_t bufferSize0 = OSScreenGetBufferSizeEx(SCREEN_TV);
uint32_t bufferSize1 = OSScreenGetBufferSizeEx(SCREEN_DRC);
screenBuffer = MEMAllocFromMappedMemoryForGX2Ex(bufferSize0 + bufferSize1, 0x100);
OSScreenSetBufferEx(SCREEN_TV, screenBuffer);
OSScreenSetBufferEx(SCREEN_DRC, (char *) screenBuffer + bufferSize0);
OSScreenEnableEx(0, 1);
OSScreenEnableEx(1, 1);
OSScreenClearBufferEx(0, 0);
OSScreenClearBufferEx(1, 0);
OSScreenFlipBuffersEx(0);
OSScreenFlipBuffersEx(1);
OSScreenEnableEx(SCREEN_TV, 1);
OSScreenEnableEx(SCREEN_DRC, 1);
OSScreenClearBufferEx(SCREEN_TV, 0);
OSScreenClearBufferEx(SCREEN_DRC, 0);
OSScreenFlipBuffersEx(SCREEN_TV);
OSScreenFlipBuffersEx(SCREEN_DRC);
}
void Screen::clear(Display screen, uint32_t color) {
void Screen::clear(OSScreenID screen, uint32_t color) {
OSScreenClearBufferEx(screen, color);
}
void Screen::drawRect(Display screen, int x1, int y1, int x2, int y2, uint32_t color) {
void Screen::drawRect(OSScreenID screen, int x1, int y1, int x2, int y2, uint32_t color) {
for (int x = x1; x < x2; x++) {
OSScreenPutPixelEx(screen, x, y1, color);
OSScreenPutPixelEx(screen, x, y2, color);
@ -42,7 +43,7 @@ void Screen::drawRect(Display screen, int x1, int y1, int x2, int y2, uint32_t c
}
}
void Screen::fillRect(Display screen, int x1, int y1, int x2, int y2, uint32_t color) {
void Screen::fillRect(OSScreenID screen, int x1, int y1, int x2, int y2, uint32_t color) {
for (int x = x1; x < x2; x++) {
for (int y = y1; y < y2; y++) {
OSScreenPutPixelEx(screen, x, y, color);
@ -50,11 +51,11 @@ void Screen::fillRect(Display screen, int x1, int y1, int x2, int y2, uint32_t c
}
}
void Screen::drawText(Display screen, int x, int y, const char *text) {
void Screen::drawText(OSScreenID screen, int x, int y, const char *text) {
OSScreenPutFontEx(screen, x, y, text);
}
void Screen::flip(Display screen) {
void Screen::flip(OSScreenID screen) {
OSScreenFlipBuffersEx(screen);
}
@ -62,26 +63,26 @@ int Screen::convx(int x) { return x * 854 / 1280; }
int Screen::convy(int y) { return y * 480 / 720; }
void Screen::clear(uint32_t color) {
clear(TV, color);
clear(DRC, color);
clear(SCREEN_TV, color);
clear(SCREEN_DRC, color);
}
void Screen::drawRect(int x1, int y1, int x2, int y2, uint32_t color) {
drawRect(TV, x1, y1, x2, y2, color);
drawRect(DRC, convx(x1), convy(y1), convx(x2), convy(y2), color);
drawRect(SCREEN_TV, x1, y1, x2, y2, color);
drawRect(SCREEN_DRC, convx(x1), convy(y1), convx(x2), convy(y2), color);
}
void Screen::fillRect(int x1, int y1, int x2, int y2, uint32_t color) {
fillRect(TV, x1, y1, x2, y2, color);
fillRect(DRC, convx(x1), convy(y1), convx(x2), convy(y2), color);
fillRect(SCREEN_TV, x1, y1, x2, y2, color);
fillRect(SCREEN_DRC, convx(x1), convy(y1), convx(x2), convy(y2), color);
}
void Screen::drawText(int x, int y, const char *text) {
drawText(TV, x, y, text);
drawText(DRC, x, y, text);
drawText(SCREEN_TV, x, y, text);
drawText(SCREEN_DRC, x, y, text);
}
void Screen::flip() {
flip(TV);
flip(DRC);
flip(SCREEN_TV);
flip(SCREEN_DRC);
}

View File

@ -1,15 +1,11 @@
#pragma once
#include <coreinit/screen.h>
#include <cstdint>
class Screen {
public:
enum Display {
TV,
DRC
};
Screen();
~Screen();
@ -17,18 +13,18 @@ public:
void clear(uint32_t color);
void drawRect(int x1, int y1, int x2, int y2, uint32_t color);
void fillRect(int x1, int y1, int x2, int y2, uint32_t color);
void drawText(int x, int y, const char *text);
void flip();
static void drawText(int x, int y, const char *text);
static void flip();
void clear(Display screen, uint32_t color);
void drawRect(Display screen, int x1, int y1, int x2, int y2, uint32_t color);
void fillRect(Display screen, int x1, int y1, int x2, int y2, uint32_t color);
void drawText(Display screen, int x, int y, const char *text);
void flip(Display screen);
static void clear(OSScreenID screen, uint32_t color);
static void drawRect(OSScreenID screen, int x1, int y1, int x2, int y2, uint32_t color);
static void fillRect(OSScreenID screen, int x1, int y1, int x2, int y2, uint32_t color);
static void drawText(OSScreenID screen, int x, int y, const char *text);
static void flip(OSScreenID screen);
private:
void *screenBuffer;
int convx(int x);
int convy(int y);
static int convx(int x);
static int convy(int y);
};

View File

@ -1,13 +1,15 @@
#include "cafe/nsysnet.h"
#include "socket.h"
#include "logger.h"
#include <arpa/inet.h>
#include <cstring>
#include <unistd.h>
Socket::Socket() : sock(-1) {}
Socket::~Socket() {
if (sock >= 0) {
socketclose(sock);
::shutdown(sock, SHUT_RDWR);
::close(sock);
}
}
@ -22,14 +24,13 @@ bool Socket::init(Type type) {
bool Socket::close() {
if (sock >= 0) {
int result = socketclose(sock);
int result = ::close(sock);
sock = -1;
return result == 0;
}
return true;
}
bool Client::sendall(const void *data, size_t length) {
size_t sent = 0;
while (sent < length) {
@ -60,6 +61,12 @@ bool Client::recvall(void *data, size_t length) {
return true;
}
struct sockaddr_kinnay {
uint16_t family;
uint16_t port;
uint32_t addr;
char zero[8];
};
bool Server::bind(int port) {
uint32_t reuseaddr = 1;
@ -69,28 +76,42 @@ bool Server::bind(int port) {
return false;
}
sockaddr serverAddr = {0};
/*
struct sockaddr_in bindAddress;
memset(&bindAddress, 0, sizeof(bindAddress));
bindAddress.sin_family = AF_INET;
bindAddress.sin_port = htons(port);
bindAddress.sin_addr.s_addr = htonl(INADDR_ANY);
result = ::bind(sock, (struct sockaddr *) &bindAddress, 16);*/
sockaddr_kinnay serverAddr = {0};
serverAddr.family = AF_INET;
serverAddr.port = port;
serverAddr.addr = 0;
result = ::bind(sock, &serverAddr, 16);
result = ::bind(sock, (const struct sockaddr *) &serverAddr, 16);
if (result < 0) {
DEBUG_FUNCTION_LINE("Bind was not successful");
close();
return false;
}
DEBUG_FUNCTION_LINE("Bind was successful");
return true;
}
bool Server::accept(Client *client) {
int result = listen(sock, 1);
if (result < 0) {
DEBUG_FUNCTION_LINE("listen failed");
close();
return false;
}
int fd = ::accept(sock, 0, 0);
if (fd < 0) {
DEBUG_FUNCTION_LINE("accept failed");
close();
return false;
}

View File

@ -5,10 +5,8 @@
class Socket {
public:
enum Type {
TCP,
UDP
};
enum Type { TCP,
UDP };
Socket();
~Socket();