mirror of
https://github.com/wiiu-env/gdbstub_plugin.git
synced 2024-11-26 05:24:22 +01:00
WIP
This commit is contained in:
parent
4993b321ce
commit
5a3bae8616
67
.clang-format
Normal file
67
.clang-format
Normal 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
7
.gitignore
vendored
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
CMakeLists.txt
|
||||||
|
*.wps
|
||||||
|
*.elf
|
||||||
|
.idea/
|
||||||
|
build/
|
||||||
|
cmake-build-debug/
|
||||||
|
__pycache__/
|
6
Dockerfile
Normal file
6
Dockerfile
Normal 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
142
Makefile
Normal 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
|
||||||
|
#-------------------------------------------------------------------------------
|
16
build.py
16
build.py
@ -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)))
|
|
@ -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;
|
|
||||||
}
|
|
@ -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();
|
|
@ -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);
|
|
||||||
}
|
|
@ -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();
|
|
@ -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);
|
|
||||||
}
|
|
@ -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();
|
|
@ -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);
|
|
||||||
}
|
|
@ -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();
|
|
@ -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);
|
|
||||||
}
|
|
@ -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();
|
|
@ -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);
|
|
||||||
}
|
|
@ -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();
|
|
189
src/debugger.cpp
189
src/debugger.cpp
@ -1,18 +1,22 @@
|
|||||||
|
|
||||||
#include "cafe/coreinit.h"
|
|
||||||
#include "cafe/nsysnet.h"
|
|
||||||
#include "cafe/vpad.h"
|
|
||||||
#include "kernel.h"
|
|
||||||
|
|
||||||
#include "debugger.h"
|
#include "debugger.h"
|
||||||
#include "exceptions.h"
|
#include "exceptions.h"
|
||||||
#include "input.h"
|
#include "input.h"
|
||||||
|
#include "logger.h"
|
||||||
#include "screen.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 <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;
|
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;
|
char *bufptr = (char *) buffer + offset;
|
||||||
if (bp->address > addr + length - 4) {
|
if (bp->address > addr + length - 4) {
|
||||||
uint32_t value = bp->instruction;
|
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;
|
bufptr[i] = value >> 24;
|
||||||
value <<= 8;
|
value <<= 8;
|
||||||
}
|
}
|
||||||
@ -195,7 +199,7 @@ uint32_t BreakPointMgr::getInstr(uint32_t addr) {
|
|||||||
|
|
||||||
void BreakPointMgr::clearSpecial(OSThread *thread) {
|
void BreakPointMgr::clearSpecial(OSThread *thread) {
|
||||||
lock();
|
lock();
|
||||||
for (int i = 0; i < special.size(); i++) {
|
for (size_t i = 0; i < special.size(); i++) {
|
||||||
SpecialBreakPoint *bp = special[i];
|
SpecialBreakPoint *bp = special[i];
|
||||||
if (bp->thread == thread) {
|
if (bp->thread == thread) {
|
||||||
disable(bp);
|
disable(bp);
|
||||||
@ -276,6 +280,7 @@ bool ExceptionState::isBreakpoint() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ExceptionState::resume() {
|
void ExceptionState::resume() {
|
||||||
|
DEBUG_FUNCTION_LINE("OSLoadContext");
|
||||||
OSLoadContext(&context);
|
OSLoadContext(&context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -294,12 +299,11 @@ void ExceptionMgr::unlock() {
|
|||||||
|
|
||||||
void ExceptionMgr::cleanup() {
|
void ExceptionMgr::cleanup() {
|
||||||
OSMessage message;
|
OSMessage message;
|
||||||
message.message = Debugger::STEP_CONTINUE;
|
message.message = (void *) Debugger::STEP_CONTINUE;
|
||||||
|
|
||||||
lock();
|
lock();
|
||||||
|
|
||||||
for (int i = 0; i < list.size(); i++) {
|
for (auto state : list) {
|
||||||
ExceptionState *state = list[i];
|
|
||||||
if (state->isPaused) {
|
if (state->isPaused) {
|
||||||
OSSendMessage(&state->queue, &message, OS_MESSAGE_FLAGS_NONE);
|
OSSendMessage(&state->queue, &message, OS_MESSAGE_FLAGS_NONE);
|
||||||
}
|
}
|
||||||
@ -310,8 +314,7 @@ void ExceptionMgr::cleanup() {
|
|||||||
|
|
||||||
ExceptionState *ExceptionMgr::find(OSThread *thread) {
|
ExceptionState *ExceptionMgr::find(OSThread *thread) {
|
||||||
lock();
|
lock();
|
||||||
for (int i = 0; i < list.size(); i++) {
|
for (auto state : list) {
|
||||||
ExceptionState *state = list[i];
|
|
||||||
if (state->thread == thread) {
|
if (state->thread == thread) {
|
||||||
unlock();
|
unlock();
|
||||||
return state;
|
return state;
|
||||||
@ -493,7 +496,7 @@ void StepMgr::adjustAddress(ExceptionState *state) {
|
|||||||
|
|
||||||
bool Debugger::checkDataRead(uint32_t addr, uint32_t length) {
|
bool Debugger::checkDataRead(uint32_t addr, uint32_t length) {
|
||||||
uint32_t memStart, memSize;
|
uint32_t memStart, memSize;
|
||||||
OSGetMemBound(MEM2, &memStart, &memSize);
|
OSGetMemBound(OS_MEM2, &memStart, &memSize);
|
||||||
|
|
||||||
uint32_t memEnd = 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) {
|
Debugger::StepCommand Debugger::notifyBreak(ExceptionState *state) {
|
||||||
OSMessage message;
|
OSMessage message;
|
||||||
message.message = ExceptionState::PROGRAM;
|
message.message = (void *) ExceptionState::PROGRAM;
|
||||||
message.args[0] = (uint32_t) &state->context;
|
message.args[0] = (uint32_t) &state->context;
|
||||||
message.args[1] = sizeof(OSContext);
|
message.args[1] = sizeof(OSContext);
|
||||||
message.args[2] = (uint32_t) state->thread;
|
message.args[2] = (uint32_t) state->thread;
|
||||||
@ -511,7 +514,7 @@ Debugger::StepCommand Debugger::notifyBreak(ExceptionState *state) {
|
|||||||
state->isPaused = true;
|
state->isPaused = true;
|
||||||
OSReceiveMessage(&state->queue, &message, OS_MESSAGE_FLAGS_BLOCKING);
|
OSReceiveMessage(&state->queue, &message, OS_MESSAGE_FLAGS_BLOCKING);
|
||||||
state->isPaused = false;
|
state->isPaused = false;
|
||||||
return (StepCommand) message.message;
|
return (StepCommand) (uint32_t) message.message;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Debugger::resumeBreakPoint(ExceptionState *state) {
|
void Debugger::resumeBreakPoint(ExceptionState *state) {
|
||||||
@ -539,24 +542,28 @@ void Debugger::handleBreakPoint(ExceptionState *state) {
|
|||||||
|
|
||||||
Screen screen;
|
Screen screen;
|
||||||
screen.init();
|
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();
|
||||||
|
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -579,7 +586,7 @@ void Debugger::handleCrash(ExceptionState *state) {
|
|||||||
stepper.adjustAddress(state);
|
stepper.adjustAddress(state);
|
||||||
if (connected) {
|
if (connected) {
|
||||||
OSMessage message;
|
OSMessage message;
|
||||||
message.message = state->type;
|
message.message = (void *) state->type;
|
||||||
message.args[0] = (uint32_t) &state->context;
|
message.args[0] = (uint32_t) &state->context;
|
||||||
message.args[1] = sizeof(OSContext);
|
message.args[1] = sizeof(OSContext);
|
||||||
message.args[2] = (uint32_t) state->thread;
|
message.args[2] = (uint32_t) state->thread;
|
||||||
@ -628,7 +635,7 @@ void Debugger::exceptionHandler(OSContext *context, ExceptionState::Type type) {
|
|||||||
debugger->handleException(context, type);
|
debugger->handleException(context, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Debugger::dsiHandler(OSContext *context) {
|
BOOL Debugger::dsiHandler(OSContext *context) {
|
||||||
OSContext *info = new OSContext();
|
OSContext *info = new OSContext();
|
||||||
memcpy(info, context, sizeof(OSContext));
|
memcpy(info, context, sizeof(OSContext));
|
||||||
context->srr0 = (uint32_t) exceptionHandler;
|
context->srr0 = (uint32_t) exceptionHandler;
|
||||||
@ -637,7 +644,7 @@ bool Debugger::dsiHandler(OSContext *context) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Debugger::isiHandler(OSContext *context) {
|
BOOL Debugger::isiHandler(OSContext *context) {
|
||||||
OSContext *info = new OSContext();
|
OSContext *info = new OSContext();
|
||||||
memcpy(info, context, sizeof(OSContext));
|
memcpy(info, context, sizeof(OSContext));
|
||||||
context->srr0 = (uint32_t) exceptionHandler;
|
context->srr0 = (uint32_t) exceptionHandler;
|
||||||
@ -646,7 +653,7 @@ bool Debugger::isiHandler(OSContext *context) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Debugger::programHandler(OSContext *context) {
|
BOOL Debugger::programHandler(OSContext *context) {
|
||||||
OSContext *info = new OSContext();
|
OSContext *info = new OSContext();
|
||||||
memcpy(info, context, sizeof(OSContext));
|
memcpy(info, context, sizeof(OSContext));
|
||||||
context->srr0 = (uint32_t) exceptionHandler;
|
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) {
|
void Debugger::mainLoop(Client *client) {
|
||||||
while (true) {
|
DEBUG_FUNCTION_LINE("About to enter mainLoop while");
|
||||||
|
while (!stopRunning) {
|
||||||
uint8_t cmd;
|
uint8_t cmd;
|
||||||
if (!client->recvall(&cmd, 1)) return;
|
if (!client->recvall(&cmd, 1)) return;
|
||||||
|
|
||||||
if (cmd == COMMAND_CLOSE) return;
|
if (cmd <= 11) {
|
||||||
else if (cmd == COMMAND_READ) {
|
DEBUG_FUNCTION_LINE("Recieved command %s %d", commandNames[cmd], cmd);
|
||||||
|
}
|
||||||
|
if (cmd == COMMAND_CLOSE) {
|
||||||
|
return;
|
||||||
|
} else if (cmd == COMMAND_READ) {
|
||||||
uint32_t addr, length;
|
uint32_t addr, length;
|
||||||
if (!client->recvall(&addr, 4)) return;
|
if (!client->recvall(&addr, 4)) return;
|
||||||
if (!client->recvall(&length, 4)) return;
|
if (!client->recvall(&length, 4)) return;
|
||||||
@ -678,10 +709,10 @@ void Debugger::mainLoop(Client *client) {
|
|||||||
char *buffer = new char[length];
|
char *buffer = new char[length];
|
||||||
breakpoints.read(buffer, addr, length);
|
breakpoints.read(buffer, addr, length);
|
||||||
if (!client->sendall(buffer, length)) {
|
if (!client->sendall(buffer, length)) {
|
||||||
delete buffer;
|
delete[] buffer;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
delete buffer;
|
delete[] buffer;
|
||||||
} 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;
|
||||||
@ -694,47 +725,53 @@ void Debugger::mainLoop(Client *client) {
|
|||||||
|
|
||||||
char *buffer = new char[length];
|
char *buffer = new char[length];
|
||||||
if (!client->recvall(buffer, length)) {
|
if (!client->recvall(buffer, length)) {
|
||||||
delete buffer;
|
delete[] buffer;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
breakpoints.write(buffer, addr, length);
|
breakpoints.write(buffer, addr, length);
|
||||||
delete buffer;
|
delete[] buffer;
|
||||||
} 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(-1, name, &length);
|
OSDynLoad_GetModuleName(reinterpret_cast<OSDynLoad_Module>(-1), name, &length);
|
||||||
|
|
||||||
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) {
|
||||||
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
|
char buffer[0x1000]; //This should be enough
|
||||||
uint32_t offset = 0;
|
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) {
|
if (offset + 0x18 + namelen > 0x1000) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
auto *infobuf = (uint32_t *) (buffer + offset);
|
||||||
uint32_t *infobuf = (uint32_t *) (buffer + offset);
|
infobuf[0] = info.textAddr;
|
||||||
infobuf[0] = info->textAddr;
|
infobuf[1] = info.textSize;
|
||||||
infobuf[1] = info->textSize;
|
infobuf[2] = info.dataAddr;
|
||||||
infobuf[2] = info->dataAddr;
|
infobuf[3] = info.dataSize;
|
||||||
infobuf[3] = info->dataSize;
|
infobuf[4] = (uint32_t) 0; // TODO: missing
|
||||||
infobuf[4] = (uint32_t) current->entryPoint;
|
|
||||||
infobuf[5] = namelen;
|
infobuf[5] = namelen;
|
||||||
memcpy(&infobuf[6], current->name, namelen);
|
memcpy(&infobuf[6], info.name, namelen);
|
||||||
offset += 0x18 + namelen;
|
offset += 0x18 + strlen(info.name);
|
||||||
|
|
||||||
current = current->next;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
OSUnlockMutex(OSDynLoad_gLoaderLock);
|
//OSUnlockMutex(OSDynLoad_gLoaderLock);
|
||||||
|
|
||||||
if (!client->sendall(&offset, 4)) return;
|
if (!client->sendall(&offset, 4)) return;
|
||||||
if (!client->sendall(buffer, offset)) return;
|
if (!client->sendall(buffer, offset)) return;
|
||||||
@ -758,9 +795,10 @@ void Debugger::mainLoop(Client *client) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int priority = current->basePriority;
|
int priority = current->basePriority;
|
||||||
if (current->type == 1) {
|
int type = *(uint32_t *) (current->__unk11);
|
||||||
|
if (type == 1) {
|
||||||
priority -= 0x20;
|
priority -= 0x20;
|
||||||
} else if (current->type == 2) {
|
} else if (type == 2) {
|
||||||
priority -= 0x40;
|
priority -= 0x40;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -768,7 +806,7 @@ void Debugger::mainLoop(Client *client) {
|
|||||||
infobuf[0] = (uint32_t) current;
|
infobuf[0] = (uint32_t) current;
|
||||||
infobuf[1] = current->attr & 7;
|
infobuf[1] = current->attr & 7;
|
||||||
infobuf[2] = priority;
|
infobuf[2] = priority;
|
||||||
infobuf[3] = (uint32_t) current->stackBase;
|
infobuf[3] = (uint32_t) current->stackStart;
|
||||||
infobuf[4] = (uint32_t) current->stackEnd;
|
infobuf[4] = (uint32_t) current->stackEnd;
|
||||||
infobuf[5] = (uint32_t) current->entryPoint;
|
infobuf[5] = (uint32_t) current->entryPoint;
|
||||||
infobuf[6] = namelen;
|
infobuf[6] = namelen;
|
||||||
@ -851,7 +889,7 @@ void Debugger::mainLoop(Client *client) {
|
|||||||
OSMessage message;
|
OSMessage message;
|
||||||
if (!client->recvall(&message, sizeof(OSMessage))) return;
|
if (!client->recvall(&message, sizeof(OSMessage))) return;
|
||||||
|
|
||||||
OSThread *thread = (OSThread *) message.args[0];
|
auto *thread = (OSThread *) message.args[0];
|
||||||
|
|
||||||
exceptions.lock();
|
exceptions.lock();
|
||||||
ExceptionState *state = exceptions.find(thread);
|
ExceptionState *state = exceptions.find(thread);
|
||||||
@ -859,30 +897,32 @@ void Debugger::mainLoop(Client *client) {
|
|||||||
OSSendMessage(&state->queue, &message, OS_MESSAGE_FLAGS_NONE);
|
OSSendMessage(&state->queue, &message, OS_MESSAGE_FLAGS_NONE);
|
||||||
}
|
}
|
||||||
exceptions.unlock();
|
exceptions.unlock();
|
||||||
|
} else {
|
||||||
|
DEBUG_FUNCTION_LINE("Recieved unknown command %d", cmd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Debugger::threadFunc() {
|
void Debugger::threadFunc() {
|
||||||
int result = socket_lib_init();
|
DEBUG_FUNCTION_LINE("Hello from debugger thread :)!");
|
||||||
if (result < 0) {
|
|
||||||
OSFatal("Failed to initialize socket library");
|
|
||||||
}
|
|
||||||
|
|
||||||
OSSetExceptionCallbackEx(OS_EXCEPTION_MODE_GLOBAL_ALL_CORES, OS_EXCEPTION_TYPE_DSI, dsiHandler);
|
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_ISI, isiHandler);
|
||||||
OSSetExceptionCallbackEx(OS_EXCEPTION_MODE_GLOBAL_ALL_CORES, OS_EXCEPTION_TYPE_PROGRAM, programHandler);
|
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 (true) {
|
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();
|
||||||
@ -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();
|
debugger->threadFunc();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -900,25 +941,45 @@ void Debugger::start() {
|
|||||||
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();
|
||||||
|
|
||||||
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(
|
OSCreateThread(
|
||||||
serverThread, threadEntry, 0, 0,
|
serverThread, threadEntry, 0, 0,
|
||||||
stack + STACK_SIZE, STACK_SIZE,
|
serverStack + STACK_SIZE, STACK_SIZE,
|
||||||
0, 12);
|
0, 12);
|
||||||
|
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));
|
||||||
}
|
}
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "cafe/coreinit.h"
|
|
||||||
#include "kernel.h"
|
#include "kernel.h"
|
||||||
#include "socket.h"
|
#include "socket.h"
|
||||||
|
#include <coreinit/messagequeue.h>
|
||||||
|
#include <coreinit/mutex.h>
|
||||||
|
#include <coreinit/thread.h>
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@ -14,6 +16,10 @@
|
|||||||
#define TRAP 0x7FE00008
|
#define TRAP 0x7FE00008
|
||||||
|
|
||||||
|
|
||||||
|
extern OSThread **pThreadList;
|
||||||
|
|
||||||
|
#define ThreadList (*pThreadList)
|
||||||
|
|
||||||
template<int N>
|
template<int N>
|
||||||
class Bits {
|
class Bits {
|
||||||
public:
|
public:
|
||||||
@ -26,7 +32,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint32_t value;
|
uint32_t value{};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -42,14 +48,14 @@ public:
|
|||||||
void resume();
|
void resume();
|
||||||
|
|
||||||
Type type;
|
Type type;
|
||||||
OSContext context;
|
OSContext context{};
|
||||||
|
|
||||||
OSThread *thread;
|
OSThread *thread{};
|
||||||
|
|
||||||
OSMessageQueue queue;
|
OSMessageQueue queue{};
|
||||||
OSMessage message;
|
OSMessage message{};
|
||||||
|
|
||||||
bool isPaused;
|
bool isPaused{};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -70,7 +76,7 @@ private:
|
|||||||
|
|
||||||
class BreakPoint {
|
class BreakPoint {
|
||||||
public:
|
public:
|
||||||
bool isRange(uint32_t addr, uint32_t length);
|
bool isRange(uint32_t addr, uint32_t length) const;
|
||||||
|
|
||||||
uint32_t address;
|
uint32_t address;
|
||||||
uint32_t instruction;
|
uint32_t instruction;
|
||||||
@ -91,7 +97,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
T *alloc() {
|
T *alloc() {
|
||||||
for (int i = 0; i < size(); i++) {
|
for (size_t i = 0; i < size(); i++) {
|
||||||
if (list[i].address == 0) {
|
if (list[i].address == 0) {
|
||||||
return &list[i];
|
return &list[i];
|
||||||
}
|
}
|
||||||
@ -105,7 +111,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
T *find(uint32_t addr) {
|
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) {
|
if (list[i].address == addr) {
|
||||||
return &list[i];
|
return &list[i];
|
||||||
}
|
}
|
||||||
@ -114,17 +120,17 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
T *findRange(uint32_t addr, uint32_t length, int *index) {
|
T *findRange(uint32_t addr, uint32_t length, int *index) {
|
||||||
int i = *index;
|
size_t i = *index;
|
||||||
while (i < size()) {
|
while (i < size()) {
|
||||||
if (list[i].isRange(addr, length)) {
|
if (list[i].isRange(addr, length)) {
|
||||||
*index = i + 1;
|
*index = (int) i + 1;
|
||||||
return &list[i];
|
return &list[i];
|
||||||
}
|
}
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i > *index) {
|
if ((int) i > *index) {
|
||||||
*index = i;
|
*index = (int) i;
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@ -134,7 +140,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void cleanup() {
|
void cleanup() {
|
||||||
for (int i = 0; i < size(); i++) {
|
for (size_t i = 0; i < size(); i++) {
|
||||||
if (list[i].address != 0) {
|
if (list[i].address != 0) {
|
||||||
KernelWriteU32(list[i].address, list[i].instruction);
|
KernelWriteU32(list[i].address, list[i].instruction);
|
||||||
list[i].address = 0;
|
list[i].address = 0;
|
||||||
@ -176,7 +182,7 @@ private:
|
|||||||
BreakPointList<BreakPoint> breakpoints;
|
BreakPointList<BreakPoint> breakpoints;
|
||||||
BreakPointList<SpecialBreakPoint> special;
|
BreakPointList<SpecialBreakPoint> special;
|
||||||
|
|
||||||
OSMutex mutex;
|
OSMutex mutex{};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -194,7 +200,7 @@ private:
|
|||||||
|
|
||||||
uint32_t *alloc();
|
uint32_t *alloc();
|
||||||
void free(int index);
|
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;
|
OSMutex mutex;
|
||||||
|
|
||||||
@ -212,6 +218,8 @@ public:
|
|||||||
|
|
||||||
void start();
|
void start();
|
||||||
|
|
||||||
|
~Debugger();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum Command {
|
enum Command {
|
||||||
COMMAND_CLOSE,
|
COMMAND_CLOSE,
|
||||||
@ -228,10 +236,10 @@ private:
|
|||||||
COMMAND_SEND_MESSAGE
|
COMMAND_SEND_MESSAGE
|
||||||
};
|
};
|
||||||
|
|
||||||
static int threadEntry(int argc, void *argv);
|
static int threadEntry(int argc, const char **argv);
|
||||||
static bool dsiHandler(OSContext *context);
|
static BOOL dsiHandler(OSContext *context);
|
||||||
static bool isiHandler(OSContext *context);
|
static BOOL isiHandler(OSContext *context);
|
||||||
static bool programHandler(OSContext *context);
|
static BOOL programHandler(OSContext *context);
|
||||||
static void exceptionHandler(OSContext *context, ExceptionState::Type type);
|
static void exceptionHandler(OSContext *context, ExceptionState::Type type);
|
||||||
|
|
||||||
void threadFunc();
|
void threadFunc();
|
||||||
@ -247,18 +255,20 @@ private:
|
|||||||
|
|
||||||
bool checkDataRead(uint32_t addr, uint32_t length);
|
bool checkDataRead(uint32_t addr, uint32_t length);
|
||||||
|
|
||||||
OSMessageQueue eventQueue;
|
OSMessageQueue eventQueue{};
|
||||||
OSMessage eventMessages[MESSAGE_COUNT];
|
OSMessage eventMessages[MESSAGE_COUNT]{};
|
||||||
|
|
||||||
OSThread *serverThread;
|
OSThread *serverThread{};
|
||||||
|
char *serverStack{};
|
||||||
|
|
||||||
BreakPointMgr breakpoints;
|
BreakPointMgr breakpoints;
|
||||||
ExceptionMgr exceptions;
|
ExceptionMgr exceptions;
|
||||||
StepMgr stepper;
|
StepMgr stepper{};
|
||||||
|
|
||||||
bool initialized;
|
bool stopRunning = false;
|
||||||
bool connected;
|
bool initialized{};
|
||||||
bool firstTrap;
|
bool connected{};
|
||||||
|
bool firstTrap{};
|
||||||
};
|
};
|
||||||
|
|
||||||
extern Debugger *debugger;
|
extern "C" Debugger *debugger;
|
||||||
|
@ -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) {
|
void DumpContext(OSContext *context, const char *excType) {
|
||||||
char buffer[1000];
|
char buffer[1000];
|
||||||
@ -28,17 +32,17 @@ void DumpContext(OSContext *context, const char *excType) {
|
|||||||
OSFatal(buffer);
|
OSFatal(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DSIHandler(OSContext *context) {
|
BOOL DSIHandler(OSContext *context) {
|
||||||
DumpContext(context, "A DSI");
|
DumpContext(context, "A DSI");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ISIHandler(OSContext *context) {
|
BOOL ISIHandler(OSContext *context) {
|
||||||
DumpContext(context, "An ISI");
|
DumpContext(context, "An ISI");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ProgramHandler(OSContext *context) {
|
BOOL ProgramHandler(OSContext *context) {
|
||||||
DumpContext(context, "A program");
|
DumpContext(context, "A program");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
15
src/hbl.h
15
src/hbl.h
@ -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
|
|
@ -1,21 +1,20 @@
|
|||||||
|
|
||||||
#include "cafe/vpad.h"
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <vpad/input.h>
|
||||||
|
|
||||||
uint32_t GetInput(uint32_t mask) {
|
uint32_t GetInput(uint32_t mask) {
|
||||||
VPADStatus input;
|
VPADStatus input;
|
||||||
int error;
|
VPADReadError error;
|
||||||
VPADRead(0, &input, 1, &error);
|
VPADRead(VPAD_CHAN_0, &input, 1, &error);
|
||||||
return input.pressed & mask;
|
return input.trigger & mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t WaitInput(uint32_t mask) {
|
uint32_t WaitInput(uint32_t mask) {
|
||||||
VPADStatus input;
|
VPADStatus input;
|
||||||
int error;
|
VPADReadError error;
|
||||||
while (true) {
|
while (true) {
|
||||||
VPADRead(0, &input, 1, &error);
|
VPADRead(VPAD_CHAN_0, &input, 1, &error);
|
||||||
if (input.pressed & mask) {
|
if (input.trigger & mask) {
|
||||||
return input.pressed & mask;
|
return input.trigger & mask;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
28
src/kernel.S
28
src/kernel.S
@ -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
|
|
@ -1,16 +1,7 @@
|
|||||||
|
#include <coreinit/cache.h>
|
||||||
#include "cafe/coreinit.h"
|
#include <coreinit/memorymap.h>
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <kernel/kernel.h>
|
||||||
#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);
|
|
||||||
|
|
||||||
void KernelWrite(uint32_t addr, const void *data, uint32_t length) {
|
void KernelWrite(uint32_t addr, const void *data, uint32_t length) {
|
||||||
uint32_t dst = OSEffectiveToPhysical(addr);
|
uint32_t dst = OSEffectiveToPhysical(addr);
|
||||||
@ -27,36 +18,3 @@ void KernelWriteU32(uint32_t addr, uint32_t value) {
|
|||||||
DCFlushRange((void *) addr, 4);
|
DCFlushRange((void *) addr, 4);
|
||||||
ICInvalidateRange((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);
|
|
||||||
}
|
|
||||||
|
@ -1,11 +1,6 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
void KernelWrite(uint32_t addr, const void *data, uint32_t length);
|
void KernelWrite(uint32_t addr, const void *data, uint32_t length);
|
||||||
void KernelWriteU32(uint32_t addr, uint32_t value);
|
void KernelWriteU32(uint32_t addr, uint32_t value);
|
||||||
|
|
||||||
void PatchSyscall(int index, void *ptr);
|
|
||||||
|
|
||||||
void kernelInitialize();
|
|
||||||
|
26
src/link.ld
26
src/link.ld
@ -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
36
src/logger.c
Normal 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
43
src/logger.h
Normal 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
|
101
src/main.cpp
101
src/main.cpp
@ -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 "debugger.h"
|
||||||
#include "exceptions.h"
|
#include "exceptions.h"
|
||||||
#include "menu.h"
|
#include "logger.h"
|
||||||
#include "patches.h"
|
#include <coreinit/debug.h>
|
||||||
#include "screen.h"
|
#include <wups.h>
|
||||||
|
|
||||||
|
OSThread **pThreadList;
|
||||||
|
|
||||||
|
|
||||||
bool GetTitleIdOnDisk(uint64_t *titleId) {
|
WUPS_PLUGIN_NAME("Debugger");
|
||||||
MCPTitleListType title;
|
WUPS_PLUGIN_DESCRIPTION("FTP Server");
|
||||||
uint32_t count = 0;
|
WUPS_PLUGIN_VERSION("0.1");
|
||||||
|
WUPS_PLUGIN_AUTHOR("Kinnay");
|
||||||
|
WUPS_PLUGIN_LICENSE("GPL");
|
||||||
|
|
||||||
int handle = MCP_Open();
|
WUPS_USE_WUT_DEVOPTAB();
|
||||||
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();
|
|
||||||
|
|
||||||
|
INITIALIZE_PLUGIN() {
|
||||||
InstallExceptionHandlers();
|
InstallExceptionHandlers();
|
||||||
|
|
||||||
int result;
|
|
||||||
if (firstRun) {
|
|
||||||
result = MenuMain();
|
|
||||||
} else {
|
|
||||||
result = DebuggerMain();
|
|
||||||
}
|
}
|
||||||
firstRun = false;
|
ON_APPLICATION_START() {
|
||||||
|
initLogging();
|
||||||
return result;
|
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() {
|
ON_APPLICATION_REQUESTS_EXIT() {
|
||||||
return start();
|
DEBUG_FUNCTION_LINE("Deleting Debugger thread");
|
||||||
|
delete debugger;
|
||||||
|
DEBUG_FUNCTION_LINE("Deleted Debugger thread");
|
||||||
|
deinitLogging();
|
||||||
}
|
}
|
||||||
|
@ -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);
|
|
||||||
}
|
|
@ -1,7 +0,0 @@
|
|||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <cstddef>
|
|
||||||
|
|
||||||
void *operator new(size_t size, int alignment);
|
|
||||||
void *operator new[](size_t size, int alignment);
|
|
19
src/menu.cpp
19
src/menu.cpp
@ -1,9 +1,8 @@
|
|||||||
|
|
||||||
#include "menu.h"
|
#include "menu.h"
|
||||||
#include "cafe/vpad.h"
|
|
||||||
#include "color.h"
|
#include "color.h"
|
||||||
#include "input.h"
|
#include "input.h"
|
||||||
#include "screen.h"
|
#include <vpad/input.h>
|
||||||
|
|
||||||
Menu::Menu(Screen *screen) : screen(screen) {
|
Menu::Menu(Screen *screen) : screen(screen) {
|
||||||
currentOption = LaunchDisk;
|
currentOption = LaunchDisk;
|
||||||
@ -30,14 +29,14 @@ void Menu::setMessage(const char *message) {
|
|||||||
|
|
||||||
void Menu::redraw() {
|
void Menu::redraw() {
|
||||||
screen->clear(COLOR_BLUE);
|
screen->clear(COLOR_BLUE);
|
||||||
screen->drawText(5, 5, "Wii U Debugger");
|
Screen::drawText(5, 5, "Wii U Debugger");
|
||||||
screen->drawText(5, 7, "Choose an option:");
|
Screen::drawText(5, 7, "Choose an option:");
|
||||||
screen->drawText(8, 9, "Install and launch disc");
|
Screen::drawText(8, 9, "Install and launch disc");
|
||||||
screen->drawText(8, 10, "Install and return to system menu");
|
Screen::drawText(8, 10, "Install and return to system menu");
|
||||||
screen->drawText(8, 11, "Exit without installing");
|
Screen::drawText(8, 11, "Exit without installing");
|
||||||
screen->drawText(5, 9 + currentOption, ">");
|
Screen::drawText(5, 9 + currentOption, ">");
|
||||||
if (message) {
|
if (message) {
|
||||||
screen->drawText(5, 13, message);
|
Screen::drawText(5, 13, message);
|
||||||
}
|
}
|
||||||
screen->flip();
|
Screen::flip();
|
||||||
}
|
}
|
||||||
|
@ -5,11 +5,9 @@
|
|||||||
|
|
||||||
class Menu {
|
class Menu {
|
||||||
public:
|
public:
|
||||||
enum Option {
|
enum Option { LaunchDisk,
|
||||||
LaunchDisk,
|
|
||||||
ReturnToMenu,
|
ReturnToMenu,
|
||||||
Exit
|
Exit };
|
||||||
};
|
|
||||||
|
|
||||||
Menu(Screen *screen);
|
Menu(Screen *screen);
|
||||||
Option show();
|
Option show();
|
||||||
|
@ -1,56 +1,17 @@
|
|||||||
|
|
||||||
#include "cafe/coreinit.h"
|
|
||||||
#include "kernel.h"
|
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <wups.h>
|
||||||
|
|
||||||
int OSSetExceptionCallback_Patch() {
|
DECL_FUNCTION(int, OSSetExceptionCallback) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
DECL_FUNCTION(int, OSSetExceptionCallbackEx) {
|
||||||
int OSSetExceptionCallbackEx_Patch() {
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
DECL_FUNCTION(int, OSIsDebuggerInitialized) {
|
||||||
bool OSIsDebuggerInitialized_Patch() {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Patch(void *funcPtr, void *patchPtr) {
|
|
||||||
OSDynLoad_NotifyData *sectionInfo = MainRPL->notifyData;
|
|
||||||
|
|
||||||
uint32_t func = (uint32_t) funcPtr;
|
WUPS_MUST_REPLACE(OSSetExceptionCallback, WUPS_LOADER_LIBRARY_COREINIT, OSSetExceptionCallback);
|
||||||
uint32_t patch = (uint32_t) patchPtr;
|
WUPS_MUST_REPLACE(OSSetExceptionCallbackEx, WUPS_LOADER_LIBRARY_COREINIT, OSSetExceptionCallbackEx);
|
||||||
if (func < 0x01800000) { //OS function (with trampoline)
|
WUPS_MUST_REPLACE(OSIsDebuggerInitialized, WUPS_LOADER_LIBRARY_COREINIT, OSIsDebuggerInitialized);
|
||||||
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);
|
|
||||||
}
|
|
@ -1,37 +1,38 @@
|
|||||||
|
|
||||||
#include "screen.h"
|
#include "screen.h"
|
||||||
#include "cafe/coreinit.h"
|
|
||||||
#include "memory.h"
|
|
||||||
|
|
||||||
Screen::Screen() : screenBuffer(0) {}
|
#include <memory/mappedmemory.h>
|
||||||
|
|
||||||
|
Screen::Screen() : screenBuffer(nullptr) {}
|
||||||
Screen::~Screen() {
|
Screen::~Screen() {
|
||||||
if (screenBuffer) {
|
if (screenBuffer) {
|
||||||
operator delete(screenBuffer);
|
MEMFreeToMappedMemory(screenBuffer);
|
||||||
|
screenBuffer = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Screen::init() {
|
void Screen::init() {
|
||||||
OSScreenInit();
|
OSScreenInit();
|
||||||
|
|
||||||
uint32_t bufferSize0 = OSScreenGetBufferSizeEx(0);
|
uint32_t bufferSize0 = OSScreenGetBufferSizeEx(SCREEN_TV);
|
||||||
uint32_t bufferSize1 = OSScreenGetBufferSizeEx(1);
|
uint32_t bufferSize1 = OSScreenGetBufferSizeEx(SCREEN_DRC);
|
||||||
screenBuffer = operator new(bufferSize0 + bufferSize1, 0x40);
|
screenBuffer = MEMAllocFromMappedMemoryForGX2Ex(bufferSize0 + bufferSize1, 0x100);
|
||||||
OSScreenSetBufferEx(0, screenBuffer);
|
OSScreenSetBufferEx(SCREEN_TV, screenBuffer);
|
||||||
OSScreenSetBufferEx(1, (char *) screenBuffer + bufferSize0);
|
OSScreenSetBufferEx(SCREEN_DRC, (char *) screenBuffer + bufferSize0);
|
||||||
|
|
||||||
OSScreenEnableEx(0, 1);
|
OSScreenEnableEx(SCREEN_TV, 1);
|
||||||
OSScreenEnableEx(1, 1);
|
OSScreenEnableEx(SCREEN_DRC, 1);
|
||||||
OSScreenClearBufferEx(0, 0);
|
OSScreenClearBufferEx(SCREEN_TV, 0);
|
||||||
OSScreenClearBufferEx(1, 0);
|
OSScreenClearBufferEx(SCREEN_DRC, 0);
|
||||||
OSScreenFlipBuffersEx(0);
|
OSScreenFlipBuffersEx(SCREEN_TV);
|
||||||
OSScreenFlipBuffersEx(1);
|
OSScreenFlipBuffersEx(SCREEN_DRC);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Screen::clear(Display screen, uint32_t color) {
|
void Screen::clear(OSScreenID screen, uint32_t color) {
|
||||||
OSScreenClearBufferEx(screen, 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++) {
|
for (int x = x1; x < x2; x++) {
|
||||||
OSScreenPutPixelEx(screen, x, y1, color);
|
OSScreenPutPixelEx(screen, x, y1, color);
|
||||||
OSScreenPutPixelEx(screen, x, y2, 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 x = x1; x < x2; x++) {
|
||||||
for (int y = y1; y < y2; y++) {
|
for (int y = y1; y < y2; y++) {
|
||||||
OSScreenPutPixelEx(screen, x, y, color);
|
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);
|
OSScreenPutFontEx(screen, x, y, text);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Screen::flip(Display screen) {
|
void Screen::flip(OSScreenID screen) {
|
||||||
OSScreenFlipBuffersEx(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; }
|
int Screen::convy(int y) { return y * 480 / 720; }
|
||||||
|
|
||||||
void Screen::clear(uint32_t color) {
|
void Screen::clear(uint32_t color) {
|
||||||
clear(TV, color);
|
clear(SCREEN_TV, color);
|
||||||
clear(DRC, color);
|
clear(SCREEN_DRC, color);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Screen::drawRect(int x1, int y1, int x2, int y2, uint32_t color) {
|
void Screen::drawRect(int x1, int y1, int x2, int y2, uint32_t color) {
|
||||||
drawRect(TV, x1, y1, x2, y2, color);
|
drawRect(SCREEN_TV, x1, y1, x2, y2, color);
|
||||||
drawRect(DRC, convx(x1), convy(y1), convx(x2), convy(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) {
|
void Screen::fillRect(int x1, int y1, int x2, int y2, uint32_t color) {
|
||||||
fillRect(TV, x1, y1, x2, y2, color);
|
fillRect(SCREEN_TV, x1, y1, x2, y2, color);
|
||||||
fillRect(DRC, convx(x1), convy(y1), convx(x2), convy(y2), color);
|
fillRect(SCREEN_DRC, convx(x1), convy(y1), convx(x2), convy(y2), color);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Screen::drawText(int x, int y, const char *text) {
|
void Screen::drawText(int x, int y, const char *text) {
|
||||||
drawText(TV, x, y, text);
|
drawText(SCREEN_TV, x, y, text);
|
||||||
drawText(DRC, x, y, text);
|
drawText(SCREEN_DRC, x, y, text);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Screen::flip() {
|
void Screen::flip() {
|
||||||
flip(TV);
|
flip(SCREEN_TV);
|
||||||
flip(DRC);
|
flip(SCREEN_DRC);
|
||||||
}
|
}
|
||||||
|
24
src/screen.h
24
src/screen.h
@ -1,15 +1,11 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <coreinit/screen.h>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
class Screen {
|
class Screen {
|
||||||
public:
|
public:
|
||||||
enum Display {
|
|
||||||
TV,
|
|
||||||
DRC
|
|
||||||
};
|
|
||||||
|
|
||||||
Screen();
|
Screen();
|
||||||
~Screen();
|
~Screen();
|
||||||
|
|
||||||
@ -17,18 +13,18 @@ public:
|
|||||||
void clear(uint32_t color);
|
void clear(uint32_t color);
|
||||||
void drawRect(int x1, int y1, int x2, int y2, 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 fillRect(int x1, int y1, int x2, int y2, uint32_t color);
|
||||||
void drawText(int x, int y, const char *text);
|
static void drawText(int x, int y, const char *text);
|
||||||
void flip();
|
static void flip();
|
||||||
|
|
||||||
void clear(Display screen, uint32_t color);
|
static void clear(OSScreenID screen, uint32_t color);
|
||||||
void drawRect(Display screen, int x1, int y1, int x2, int y2, uint32_t color);
|
static void drawRect(OSScreenID 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);
|
static void fillRect(OSScreenID screen, int x1, int y1, int x2, int y2, uint32_t color);
|
||||||
void drawText(Display screen, int x, int y, const char *text);
|
static void drawText(OSScreenID screen, int x, int y, const char *text);
|
||||||
void flip(Display screen);
|
static void flip(OSScreenID screen);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void *screenBuffer;
|
void *screenBuffer;
|
||||||
|
|
||||||
int convx(int x);
|
static int convx(int x);
|
||||||
int convy(int y);
|
static int convy(int y);
|
||||||
};
|
};
|
||||||
|
@ -1,13 +1,15 @@
|
|||||||
|
|
||||||
#include "cafe/nsysnet.h"
|
|
||||||
|
|
||||||
#include "socket.h"
|
#include "socket.h"
|
||||||
|
#include "logger.h"
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <cstring>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
Socket::Socket() : sock(-1) {}
|
Socket::Socket() : sock(-1) {}
|
||||||
|
|
||||||
Socket::~Socket() {
|
Socket::~Socket() {
|
||||||
if (sock >= 0) {
|
if (sock >= 0) {
|
||||||
socketclose(sock);
|
::shutdown(sock, SHUT_RDWR);
|
||||||
|
::close(sock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -22,14 +24,13 @@ bool Socket::init(Type type) {
|
|||||||
|
|
||||||
bool Socket::close() {
|
bool Socket::close() {
|
||||||
if (sock >= 0) {
|
if (sock >= 0) {
|
||||||
int result = socketclose(sock);
|
int result = ::close(sock);
|
||||||
sock = -1;
|
sock = -1;
|
||||||
return result == 0;
|
return result == 0;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool Client::sendall(const void *data, size_t length) {
|
bool Client::sendall(const void *data, size_t length) {
|
||||||
size_t sent = 0;
|
size_t sent = 0;
|
||||||
while (sent < length) {
|
while (sent < length) {
|
||||||
@ -60,6 +61,12 @@ bool Client::recvall(void *data, size_t length) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct sockaddr_kinnay {
|
||||||
|
uint16_t family;
|
||||||
|
uint16_t port;
|
||||||
|
uint32_t addr;
|
||||||
|
char zero[8];
|
||||||
|
};
|
||||||
|
|
||||||
bool Server::bind(int port) {
|
bool Server::bind(int port) {
|
||||||
uint32_t reuseaddr = 1;
|
uint32_t reuseaddr = 1;
|
||||||
@ -69,28 +76,42 @@ bool Server::bind(int port) {
|
|||||||
return false;
|
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.family = AF_INET;
|
||||||
serverAddr.port = port;
|
serverAddr.port = port;
|
||||||
serverAddr.addr = 0;
|
serverAddr.addr = 0;
|
||||||
|
|
||||||
result = ::bind(sock, &serverAddr, 16);
|
result = ::bind(sock, (const struct sockaddr *) &serverAddr, 16);
|
||||||
if (result < 0) {
|
if (result < 0) {
|
||||||
|
DEBUG_FUNCTION_LINE("Bind was not successful");
|
||||||
close();
|
close();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
DEBUG_FUNCTION_LINE("Bind was successful");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Server::accept(Client *client) {
|
bool Server::accept(Client *client) {
|
||||||
int result = listen(sock, 1);
|
int result = listen(sock, 1);
|
||||||
if (result < 0) {
|
if (result < 0) {
|
||||||
|
DEBUG_FUNCTION_LINE("listen failed");
|
||||||
close();
|
close();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int fd = ::accept(sock, 0, 0);
|
int fd = ::accept(sock, 0, 0);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
|
DEBUG_FUNCTION_LINE("accept failed");
|
||||||
close();
|
close();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -5,10 +5,8 @@
|
|||||||
|
|
||||||
class Socket {
|
class Socket {
|
||||||
public:
|
public:
|
||||||
enum Type {
|
enum Type { TCP,
|
||||||
TCP,
|
UDP };
|
||||||
UDP
|
|
||||||
};
|
|
||||||
|
|
||||||
Socket();
|
Socket();
|
||||||
~Socket();
|
~Socket();
|
||||||
|
Loading…
Reference in New Issue
Block a user