mirror of
https://github.com/wiiu-env/gdbstub_plugin.git
synced 2024-11-12 23:35:05 +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();
|
193
src/debugger.cpp
193
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 "exceptions.h"
|
||||
#include "input.h"
|
||||
#include "logger.h"
|
||||
#include "screen.h"
|
||||
|
||||
#include <coreinit/cache.h>
|
||||
#include <coreinit/debug.h>
|
||||
#include <coreinit/dynload.h>
|
||||
#include <coreinit/exception.h>
|
||||
#include <coreinit/memory.h>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <malloc.h>
|
||||
#include <vpad/input.h>
|
||||
|
||||
Debugger *debugger;
|
||||
|
||||
bool BreakPoint::isRange(uint32_t addr, uint32_t length) {
|
||||
bool BreakPoint::isRange(uint32_t addr, uint32_t length) const {
|
||||
return address >= addr && address <= addr + length - 1;
|
||||
}
|
||||
|
||||
@ -125,7 +129,7 @@ void BreakPointMgr::read(void *buffer, uint32_t addr, uint32_t length) {
|
||||
char *bufptr = (char *) buffer + offset;
|
||||
if (bp->address > addr + length - 4) {
|
||||
uint32_t value = bp->instruction;
|
||||
for (int i = 0; i < length - offset; i++) {
|
||||
for (uint32_t i = 0; i < length - offset; i++) {
|
||||
bufptr[i] = value >> 24;
|
||||
value <<= 8;
|
||||
}
|
||||
@ -195,7 +199,7 @@ uint32_t BreakPointMgr::getInstr(uint32_t addr) {
|
||||
|
||||
void BreakPointMgr::clearSpecial(OSThread *thread) {
|
||||
lock();
|
||||
for (int i = 0; i < special.size(); i++) {
|
||||
for (size_t i = 0; i < special.size(); i++) {
|
||||
SpecialBreakPoint *bp = special[i];
|
||||
if (bp->thread == thread) {
|
||||
disable(bp);
|
||||
@ -276,6 +280,7 @@ bool ExceptionState::isBreakpoint() {
|
||||
}
|
||||
|
||||
void ExceptionState::resume() {
|
||||
DEBUG_FUNCTION_LINE("OSLoadContext");
|
||||
OSLoadContext(&context);
|
||||
}
|
||||
|
||||
@ -294,12 +299,11 @@ void ExceptionMgr::unlock() {
|
||||
|
||||
void ExceptionMgr::cleanup() {
|
||||
OSMessage message;
|
||||
message.message = Debugger::STEP_CONTINUE;
|
||||
message.message = (void *) Debugger::STEP_CONTINUE;
|
||||
|
||||
lock();
|
||||
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
ExceptionState *state = list[i];
|
||||
for (auto state : list) {
|
||||
if (state->isPaused) {
|
||||
OSSendMessage(&state->queue, &message, OS_MESSAGE_FLAGS_NONE);
|
||||
}
|
||||
@ -310,8 +314,7 @@ void ExceptionMgr::cleanup() {
|
||||
|
||||
ExceptionState *ExceptionMgr::find(OSThread *thread) {
|
||||
lock();
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
ExceptionState *state = list[i];
|
||||
for (auto state : list) {
|
||||
if (state->thread == thread) {
|
||||
unlock();
|
||||
return state;
|
||||
@ -493,7 +496,7 @@ void StepMgr::adjustAddress(ExceptionState *state) {
|
||||
|
||||
bool Debugger::checkDataRead(uint32_t addr, uint32_t length) {
|
||||
uint32_t memStart, memSize;
|
||||
OSGetMemBound(MEM2, &memStart, &memSize);
|
||||
OSGetMemBound(OS_MEM2, &memStart, &memSize);
|
||||
|
||||
uint32_t memEnd = memStart + memSize;
|
||||
|
||||
@ -502,7 +505,7 @@ bool Debugger::checkDataRead(uint32_t addr, uint32_t length) {
|
||||
|
||||
Debugger::StepCommand Debugger::notifyBreak(ExceptionState *state) {
|
||||
OSMessage message;
|
||||
message.message = ExceptionState::PROGRAM;
|
||||
message.message = (void *) ExceptionState::PROGRAM;
|
||||
message.args[0] = (uint32_t) &state->context;
|
||||
message.args[1] = sizeof(OSContext);
|
||||
message.args[2] = (uint32_t) state->thread;
|
||||
@ -511,7 +514,7 @@ Debugger::StepCommand Debugger::notifyBreak(ExceptionState *state) {
|
||||
state->isPaused = true;
|
||||
OSReceiveMessage(&state->queue, &message, OS_MESSAGE_FLAGS_BLOCKING);
|
||||
state->isPaused = false;
|
||||
return (StepCommand) message.message;
|
||||
return (StepCommand) (uint32_t) message.message;
|
||||
}
|
||||
|
||||
void Debugger::resumeBreakPoint(ExceptionState *state) {
|
||||
@ -539,24 +542,28 @@ void Debugger::handleBreakPoint(ExceptionState *state) {
|
||||
|
||||
Screen screen;
|
||||
screen.init();
|
||||
screen.drawText(
|
||||
Screen::drawText(
|
||||
0, 0, "Waiting for debugger connection.\n"
|
||||
"Press the home button to continue without debugger.\n"
|
||||
"You can still connect while the game is running.");
|
||||
screen.flip();
|
||||
Screen::flip();
|
||||
|
||||
while (!connected) {
|
||||
uint32_t buttons = GetInput(VPAD_BUTTON_HOME);
|
||||
if (buttons) {
|
||||
DEBUG_FUNCTION_LINE("Pressed home");
|
||||
state->context.srr0 += 4;
|
||||
state->resume();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DEBUG_FUNCTION_LINE("stepper.handleBreakPoint(state);");
|
||||
|
||||
stepper.handleBreakPoint(state);
|
||||
|
||||
if (!connected) {
|
||||
DEBUG_FUNCTION_LINE("if (!connected) {");
|
||||
handleFatalCrash(&state->context, state->type);
|
||||
}
|
||||
|
||||
@ -579,7 +586,7 @@ void Debugger::handleCrash(ExceptionState *state) {
|
||||
stepper.adjustAddress(state);
|
||||
if (connected) {
|
||||
OSMessage message;
|
||||
message.message = state->type;
|
||||
message.message = (void *) state->type;
|
||||
message.args[0] = (uint32_t) &state->context;
|
||||
message.args[1] = sizeof(OSContext);
|
||||
message.args[2] = (uint32_t) state->thread;
|
||||
@ -628,7 +635,7 @@ void Debugger::exceptionHandler(OSContext *context, ExceptionState::Type type) {
|
||||
debugger->handleException(context, type);
|
||||
}
|
||||
|
||||
bool Debugger::dsiHandler(OSContext *context) {
|
||||
BOOL Debugger::dsiHandler(OSContext *context) {
|
||||
OSContext *info = new OSContext();
|
||||
memcpy(info, context, sizeof(OSContext));
|
||||
context->srr0 = (uint32_t) exceptionHandler;
|
||||
@ -637,7 +644,7 @@ bool Debugger::dsiHandler(OSContext *context) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Debugger::isiHandler(OSContext *context) {
|
||||
BOOL Debugger::isiHandler(OSContext *context) {
|
||||
OSContext *info = new OSContext();
|
||||
memcpy(info, context, sizeof(OSContext));
|
||||
context->srr0 = (uint32_t) exceptionHandler;
|
||||
@ -646,7 +653,7 @@ bool Debugger::isiHandler(OSContext *context) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Debugger::programHandler(OSContext *context) {
|
||||
BOOL Debugger::programHandler(OSContext *context) {
|
||||
OSContext *info = new OSContext();
|
||||
memcpy(info, context, sizeof(OSContext));
|
||||
context->srr0 = (uint32_t) exceptionHandler;
|
||||
@ -664,13 +671,37 @@ void Debugger::cleanup() {
|
||||
;
|
||||
}
|
||||
|
||||
extern "C" void OSRestoreInterrupts(int state);
|
||||
extern "C" void __OSLockScheduler(void *);
|
||||
extern "C" void __OSUnlockScheduler(void *);
|
||||
extern "C" int OSDisableInterrupts();
|
||||
|
||||
static const char **commandNames = (const char *[]){
|
||||
"COMMAND_CLOSE",
|
||||
"COMMAND_READ",
|
||||
"COMMAND_WRITE",
|
||||
"COMMAND_WRITE_CODE",
|
||||
"COMMAND_GET_MODULE_NAME",
|
||||
"COMMAND_GET_MODULE_LIST",
|
||||
"COMMAND_GET_THREAD_LIST",
|
||||
"COMMAND_GET_STACK_TRACE",
|
||||
"COMMAND_TOGGLE_BREAKPOINT",
|
||||
"COMMAND_POKE_REGISTERS",
|
||||
"COMMAND_RECEIVE_MESSAGES",
|
||||
"COMMAND_SEND_MESSAGE"};
|
||||
|
||||
void Debugger::mainLoop(Client *client) {
|
||||
while (true) {
|
||||
DEBUG_FUNCTION_LINE("About to enter mainLoop while");
|
||||
while (!stopRunning) {
|
||||
uint8_t cmd;
|
||||
if (!client->recvall(&cmd, 1)) return;
|
||||
|
||||
if (cmd == COMMAND_CLOSE) return;
|
||||
else if (cmd == COMMAND_READ) {
|
||||
if (cmd <= 11) {
|
||||
DEBUG_FUNCTION_LINE("Recieved command %s %d", commandNames[cmd], cmd);
|
||||
}
|
||||
if (cmd == COMMAND_CLOSE) {
|
||||
return;
|
||||
} else if (cmd == COMMAND_READ) {
|
||||
uint32_t addr, length;
|
||||
if (!client->recvall(&addr, 4)) return;
|
||||
if (!client->recvall(&length, 4)) return;
|
||||
@ -678,10 +709,10 @@ void Debugger::mainLoop(Client *client) {
|
||||
char *buffer = new char[length];
|
||||
breakpoints.read(buffer, addr, length);
|
||||
if (!client->sendall(buffer, length)) {
|
||||
delete buffer;
|
||||
delete[] buffer;
|
||||
return;
|
||||
}
|
||||
delete buffer;
|
||||
delete[] buffer;
|
||||
} else if (cmd == COMMAND_WRITE) {
|
||||
uint32_t addr, length;
|
||||
if (!client->recvall(&addr, 4)) return;
|
||||
@ -694,47 +725,53 @@ void Debugger::mainLoop(Client *client) {
|
||||
|
||||
char *buffer = new char[length];
|
||||
if (!client->recvall(buffer, length)) {
|
||||
delete buffer;
|
||||
delete[] buffer;
|
||||
return;
|
||||
}
|
||||
breakpoints.write(buffer, addr, length);
|
||||
delete buffer;
|
||||
delete[] buffer;
|
||||
} else if (cmd == COMMAND_GET_MODULE_NAME) {
|
||||
char name[0x40];
|
||||
int length = 0x40;
|
||||
OSDynLoad_GetModuleName(-1, name, &length);
|
||||
OSDynLoad_GetModuleName(reinterpret_cast<OSDynLoad_Module>(-1), name, &length);
|
||||
|
||||
length = strlen(name);
|
||||
if (!client->sendall(&length, 4)) return;
|
||||
if (!client->sendall(name, length)) return;
|
||||
} else if (cmd == COMMAND_GET_MODULE_LIST) {
|
||||
OSLockMutex(OSDynLoad_gLoaderLock);
|
||||
int num_rpls = OSDynLoad_GetNumberOfRPLs();
|
||||
if (num_rpls == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<OSDynLoad_NotifyData> rpls;
|
||||
rpls.resize(num_rpls);
|
||||
|
||||
bool ret = OSDynLoad_GetRPLInfo(0, num_rpls, rpls.data());
|
||||
if (!ret) {
|
||||
return;
|
||||
}
|
||||
|
||||
char buffer[0x1000]; //This should be enough
|
||||
uint32_t offset = 0;
|
||||
OSDynLoad_RPLInfo *current = FirstRPL;
|
||||
while (current) {
|
||||
OSDynLoad_NotifyData *info = current->notifyData;
|
||||
uint32_t offset = 0;
|
||||
|
||||
uint32_t namelen = strlen(current->name);
|
||||
for (auto &info : rpls) {
|
||||
uint32_t namelen = strlen(info.name);
|
||||
if (offset + 0x18 + namelen > 0x1000) {
|
||||
break;
|
||||
}
|
||||
|
||||
uint32_t *infobuf = (uint32_t *) (buffer + offset);
|
||||
infobuf[0] = info->textAddr;
|
||||
infobuf[1] = info->textSize;
|
||||
infobuf[2] = info->dataAddr;
|
||||
infobuf[3] = info->dataSize;
|
||||
infobuf[4] = (uint32_t) current->entryPoint;
|
||||
infobuf[5] = namelen;
|
||||
memcpy(&infobuf[6], current->name, namelen);
|
||||
offset += 0x18 + namelen;
|
||||
|
||||
current = current->next;
|
||||
auto *infobuf = (uint32_t *) (buffer + offset);
|
||||
infobuf[0] = info.textAddr;
|
||||
infobuf[1] = info.textSize;
|
||||
infobuf[2] = info.dataAddr;
|
||||
infobuf[3] = info.dataSize;
|
||||
infobuf[4] = (uint32_t) 0; // TODO: missing
|
||||
infobuf[5] = namelen;
|
||||
memcpy(&infobuf[6], info.name, namelen);
|
||||
offset += 0x18 + strlen(info.name);
|
||||
}
|
||||
|
||||
OSUnlockMutex(OSDynLoad_gLoaderLock);
|
||||
//OSUnlockMutex(OSDynLoad_gLoaderLock);
|
||||
|
||||
if (!client->sendall(&offset, 4)) return;
|
||||
if (!client->sendall(buffer, offset)) return;
|
||||
@ -758,9 +795,10 @@ void Debugger::mainLoop(Client *client) {
|
||||
}
|
||||
|
||||
int priority = current->basePriority;
|
||||
if (current->type == 1) {
|
||||
int type = *(uint32_t *) (current->__unk11);
|
||||
if (type == 1) {
|
||||
priority -= 0x20;
|
||||
} else if (current->type == 2) {
|
||||
} else if (type == 2) {
|
||||
priority -= 0x40;
|
||||
}
|
||||
|
||||
@ -768,7 +806,7 @@ void Debugger::mainLoop(Client *client) {
|
||||
infobuf[0] = (uint32_t) current;
|
||||
infobuf[1] = current->attr & 7;
|
||||
infobuf[2] = priority;
|
||||
infobuf[3] = (uint32_t) current->stackBase;
|
||||
infobuf[3] = (uint32_t) current->stackStart;
|
||||
infobuf[4] = (uint32_t) current->stackEnd;
|
||||
infobuf[5] = (uint32_t) current->entryPoint;
|
||||
infobuf[6] = namelen;
|
||||
@ -851,7 +889,7 @@ void Debugger::mainLoop(Client *client) {
|
||||
OSMessage message;
|
||||
if (!client->recvall(&message, sizeof(OSMessage))) return;
|
||||
|
||||
OSThread *thread = (OSThread *) message.args[0];
|
||||
auto *thread = (OSThread *) message.args[0];
|
||||
|
||||
exceptions.lock();
|
||||
ExceptionState *state = exceptions.find(thread);
|
||||
@ -859,30 +897,32 @@ void Debugger::mainLoop(Client *client) {
|
||||
OSSendMessage(&state->queue, &message, OS_MESSAGE_FLAGS_NONE);
|
||||
}
|
||||
exceptions.unlock();
|
||||
} else {
|
||||
DEBUG_FUNCTION_LINE("Recieved unknown command %d", cmd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Debugger::threadFunc() {
|
||||
int result = socket_lib_init();
|
||||
if (result < 0) {
|
||||
OSFatal("Failed to initialize socket library");
|
||||
}
|
||||
|
||||
DEBUG_FUNCTION_LINE("Hello from debugger thread :)!");
|
||||
OSSetExceptionCallbackEx(OS_EXCEPTION_MODE_GLOBAL_ALL_CORES, OS_EXCEPTION_TYPE_DSI, dsiHandler);
|
||||
OSSetExceptionCallbackEx(OS_EXCEPTION_MODE_GLOBAL_ALL_CORES, OS_EXCEPTION_TYPE_ISI, isiHandler);
|
||||
OSSetExceptionCallbackEx(OS_EXCEPTION_MODE_GLOBAL_ALL_CORES, OS_EXCEPTION_TYPE_PROGRAM, programHandler);
|
||||
DEBUG_FUNCTION_LINE("Callback init done.!");
|
||||
|
||||
Server server;
|
||||
Client client;
|
||||
|
||||
DEBUG_FUNCTION_LINE("Set initialized = true");
|
||||
initialized = true;
|
||||
while (true) {
|
||||
while (!stopRunning) {
|
||||
if (!server.init(Socket::TCP)) continue;
|
||||
if (!server.bind(1560)) continue;
|
||||
if (!server.accept(&client)) continue;
|
||||
DEBUG_FUNCTION_LINE("Accepted a connection");
|
||||
connected = true;
|
||||
mainLoop(&client);
|
||||
DEBUG_FUNCTION_LINE("Lets do some cleanup");
|
||||
cleanup();
|
||||
connected = false;
|
||||
client.close();
|
||||
@ -890,7 +930,8 @@ void Debugger::threadFunc() {
|
||||
}
|
||||
}
|
||||
|
||||
int Debugger::threadEntry(int argc, void *argv) {
|
||||
int Debugger::threadEntry(int argc, const char **argv) {
|
||||
DEBUG_FUNCTION_LINE("threadEntry");
|
||||
debugger->threadFunc();
|
||||
return 0;
|
||||
}
|
||||
@ -900,25 +941,45 @@ void Debugger::start() {
|
||||
connected = false;
|
||||
firstTrap = true;
|
||||
|
||||
DEBUG_FUNCTION_LINE("OSInitMessageQueue");
|
||||
OSInitMessageQueue(&eventQueue, eventMessages, MESSAGE_COUNT);
|
||||
|
||||
DEBUG_FUNCTION_LINE("init breakpoints");
|
||||
breakpoints.init();
|
||||
DEBUG_FUNCTION_LINE("init exceptions");
|
||||
exceptions.init();
|
||||
DEBUG_FUNCTION_LINE("init stepper");
|
||||
stepper.init();
|
||||
|
||||
serverThread = new OSThread();
|
||||
char *stack = new char[0x8000];
|
||||
|
||||
DEBUG_FUNCTION_LINE("Alloc thread");
|
||||
serverThread = (OSThread *) memalign(0x20, sizeof(OSThread));
|
||||
DEBUG_FUNCTION_LINE("Alloc stack");
|
||||
serverStack = (char *) memalign(0x20, STACK_SIZE);
|
||||
|
||||
|
||||
DEBUG_FUNCTION_LINE("Create thread");
|
||||
OSCreateThread(
|
||||
serverThread, threadEntry, 0, 0,
|
||||
stack + STACK_SIZE, STACK_SIZE,
|
||||
serverStack + STACK_SIZE, STACK_SIZE,
|
||||
0, 12);
|
||||
DEBUG_FUNCTION_LINE("Set thread name");
|
||||
OSSetThreadName(serverThread, "Debug Server");
|
||||
DEBUG_FUNCTION_LINE("Resume thread");
|
||||
OSResumeThread(serverThread);
|
||||
|
||||
while (!initialized) {
|
||||
DEBUG_FUNCTION_LINE("Wait for thread init");
|
||||
OSSleepTicks(OSMillisecondsToTicks(20));
|
||||
}
|
||||
DEBUG_FUNCTION_LINE("Thread init done! Exit start()");
|
||||
}
|
||||
|
||||
Debugger *debugger;
|
||||
Debugger::~Debugger() {
|
||||
stopRunning = true;
|
||||
OSJoinThread(serverThread, nullptr);
|
||||
free(serverStack);
|
||||
serverStack = nullptr;
|
||||
free(serverThread);
|
||||
serverThread = nullptr;
|
||||
}
|
||||
|
@ -1,9 +1,11 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "cafe/coreinit.h"
|
||||
#include "kernel.h"
|
||||
#include "socket.h"
|
||||
#include <coreinit/messagequeue.h>
|
||||
#include <coreinit/mutex.h>
|
||||
#include <coreinit/thread.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
@ -14,6 +16,10 @@
|
||||
#define TRAP 0x7FE00008
|
||||
|
||||
|
||||
extern OSThread **pThreadList;
|
||||
|
||||
#define ThreadList (*pThreadList)
|
||||
|
||||
template<int N>
|
||||
class Bits {
|
||||
public:
|
||||
@ -26,7 +32,7 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
uint32_t value;
|
||||
uint32_t value{};
|
||||
};
|
||||
|
||||
|
||||
@ -42,14 +48,14 @@ public:
|
||||
void resume();
|
||||
|
||||
Type type;
|
||||
OSContext context;
|
||||
OSContext context{};
|
||||
|
||||
OSThread *thread;
|
||||
OSThread *thread{};
|
||||
|
||||
OSMessageQueue queue;
|
||||
OSMessage message;
|
||||
OSMessageQueue queue{};
|
||||
OSMessage message{};
|
||||
|
||||
bool isPaused;
|
||||
bool isPaused{};
|
||||
};
|
||||
|
||||
|
||||
@ -70,7 +76,7 @@ private:
|
||||
|
||||
class BreakPoint {
|
||||
public:
|
||||
bool isRange(uint32_t addr, uint32_t length);
|
||||
bool isRange(uint32_t addr, uint32_t length) const;
|
||||
|
||||
uint32_t address;
|
||||
uint32_t instruction;
|
||||
@ -91,7 +97,7 @@ public:
|
||||
}
|
||||
|
||||
T *alloc() {
|
||||
for (int i = 0; i < size(); i++) {
|
||||
for (size_t i = 0; i < size(); i++) {
|
||||
if (list[i].address == 0) {
|
||||
return &list[i];
|
||||
}
|
||||
@ -105,7 +111,7 @@ public:
|
||||
}
|
||||
|
||||
T *find(uint32_t addr) {
|
||||
for (int i = 0; i < size(); i++) {
|
||||
for (size_t i = 0; i < size(); i++) {
|
||||
if (list[i].address == addr) {
|
||||
return &list[i];
|
||||
}
|
||||
@ -114,17 +120,17 @@ public:
|
||||
}
|
||||
|
||||
T *findRange(uint32_t addr, uint32_t length, int *index) {
|
||||
int i = *index;
|
||||
size_t i = *index;
|
||||
while (i < size()) {
|
||||
if (list[i].isRange(addr, length)) {
|
||||
*index = i + 1;
|
||||
*index = (int) i + 1;
|
||||
return &list[i];
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
if (i > *index) {
|
||||
*index = i;
|
||||
if ((int) i > *index) {
|
||||
*index = (int) i;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
@ -134,7 +140,7 @@ public:
|
||||
}
|
||||
|
||||
void cleanup() {
|
||||
for (int i = 0; i < size(); i++) {
|
||||
for (size_t i = 0; i < size(); i++) {
|
||||
if (list[i].address != 0) {
|
||||
KernelWriteU32(list[i].address, list[i].instruction);
|
||||
list[i].address = 0;
|
||||
@ -176,7 +182,7 @@ private:
|
||||
BreakPointList<BreakPoint> breakpoints;
|
||||
BreakPointList<SpecialBreakPoint> special;
|
||||
|
||||
OSMutex mutex;
|
||||
OSMutex mutex{};
|
||||
};
|
||||
|
||||
|
||||
@ -194,7 +200,7 @@ private:
|
||||
|
||||
uint32_t *alloc();
|
||||
void free(int index);
|
||||
void branchConditional(ExceptionState *state, uint32_t instruction, uint32_t target, bool checkCtr);
|
||||
static void branchConditional(ExceptionState *state, uint32_t instruction, uint32_t target, bool checkCtr);
|
||||
|
||||
OSMutex mutex;
|
||||
|
||||
@ -212,6 +218,8 @@ public:
|
||||
|
||||
void start();
|
||||
|
||||
~Debugger();
|
||||
|
||||
private:
|
||||
enum Command {
|
||||
COMMAND_CLOSE,
|
||||
@ -228,10 +236,10 @@ private:
|
||||
COMMAND_SEND_MESSAGE
|
||||
};
|
||||
|
||||
static int threadEntry(int argc, void *argv);
|
||||
static bool dsiHandler(OSContext *context);
|
||||
static bool isiHandler(OSContext *context);
|
||||
static bool programHandler(OSContext *context);
|
||||
static int threadEntry(int argc, const char **argv);
|
||||
static BOOL dsiHandler(OSContext *context);
|
||||
static BOOL isiHandler(OSContext *context);
|
||||
static BOOL programHandler(OSContext *context);
|
||||
static void exceptionHandler(OSContext *context, ExceptionState::Type type);
|
||||
|
||||
void threadFunc();
|
||||
@ -247,18 +255,20 @@ private:
|
||||
|
||||
bool checkDataRead(uint32_t addr, uint32_t length);
|
||||
|
||||
OSMessageQueue eventQueue;
|
||||
OSMessage eventMessages[MESSAGE_COUNT];
|
||||
OSMessageQueue eventQueue{};
|
||||
OSMessage eventMessages[MESSAGE_COUNT]{};
|
||||
|
||||
OSThread *serverThread;
|
||||
OSThread *serverThread{};
|
||||
char *serverStack{};
|
||||
|
||||
BreakPointMgr breakpoints;
|
||||
ExceptionMgr exceptions;
|
||||
StepMgr stepper;
|
||||
StepMgr stepper{};
|
||||
|
||||
bool initialized;
|
||||
bool connected;
|
||||
bool firstTrap;
|
||||
bool stopRunning = false;
|
||||
bool initialized{};
|
||||
bool connected{};
|
||||
bool firstTrap{};
|
||||
};
|
||||
|
||||
extern Debugger *debugger;
|
||||
extern "C" Debugger *debugger;
|
||||
|
@ -1,5 +1,9 @@
|
||||
|
||||
#include "cafe/coreinit.h"
|
||||
|
||||
#include <coreinit/context.h>
|
||||
#include <coreinit/debug.h>
|
||||
#include <coreinit/exception.h>
|
||||
#include <cstdio>
|
||||
|
||||
void DumpContext(OSContext *context, const char *excType) {
|
||||
char buffer[1000];
|
||||
@ -28,17 +32,17 @@ void DumpContext(OSContext *context, const char *excType) {
|
||||
OSFatal(buffer);
|
||||
}
|
||||
|
||||
bool DSIHandler(OSContext *context) {
|
||||
BOOL DSIHandler(OSContext *context) {
|
||||
DumpContext(context, "A DSI");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ISIHandler(OSContext *context) {
|
||||
BOOL ISIHandler(OSContext *context) {
|
||||
DumpContext(context, "An ISI");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ProgramHandler(OSContext *context) {
|
||||
BOOL ProgramHandler(OSContext *context) {
|
||||
DumpContext(context, "A program");
|
||||
return false;
|
||||
}
|
||||
|
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 <vpad/input.h>
|
||||
|
||||
uint32_t GetInput(uint32_t mask) {
|
||||
VPADStatus input;
|
||||
int error;
|
||||
VPADRead(0, &input, 1, &error);
|
||||
return input.pressed & mask;
|
||||
VPADReadError error;
|
||||
VPADRead(VPAD_CHAN_0, &input, 1, &error);
|
||||
return input.trigger & mask;
|
||||
}
|
||||
|
||||
uint32_t WaitInput(uint32_t mask) {
|
||||
VPADStatus input;
|
||||
int error;
|
||||
VPADReadError error;
|
||||
while (true) {
|
||||
VPADRead(0, &input, 1, &error);
|
||||
if (input.pressed & mask) {
|
||||
return input.pressed & mask;
|
||||
VPADRead(VPAD_CHAN_0, &input, 1, &error);
|
||||
if (input.trigger & mask) {
|
||||
return input.trigger & mask;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
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 "cafe/coreinit.h"
|
||||
|
||||
#include <coreinit/cache.h>
|
||||
#include <coreinit/memorymap.h>
|
||||
#include <cstdint>
|
||||
|
||||
#define KERN_SYSCALL_TBL1 0xFFE84C70 //Unknown
|
||||
#define KERN_SYSCALL_TBL2 0xFFE85070 //Games
|
||||
#define KERN_SYSCALL_TBL3 0xFFE85470 //Loader
|
||||
#define KERN_SYSCALL_TBL4 0xFFEAAA60 //Home menu
|
||||
#define KERN_SYSCALL_TBL5 0xFFEAAE60 //Browser
|
||||
|
||||
extern "C" void SCKernelCopyData(uint32_t dst, uint32_t src, uint32_t len);
|
||||
extern "C" void KernelCopyData(uint32_t dst, uint32_t src, uint32_t len);
|
||||
#include <kernel/kernel.h>
|
||||
|
||||
void KernelWrite(uint32_t addr, const void *data, uint32_t length) {
|
||||
uint32_t dst = OSEffectiveToPhysical(addr);
|
||||
@ -27,36 +18,3 @@ void KernelWriteU32(uint32_t addr, uint32_t value) {
|
||||
DCFlushRange((void *) addr, 4);
|
||||
ICInvalidateRange((void *) addr, 4);
|
||||
}
|
||||
|
||||
/* Write a 32-bit word with kernel permissions */
|
||||
void __attribute__((noinline)) kern_write(uint32_t addr, uint32_t value) {
|
||||
asm volatile(
|
||||
"li 3,1\n"
|
||||
"li 4,0\n"
|
||||
"mr 5,%1\n"
|
||||
"li 6,0\n"
|
||||
"li 7,0\n"
|
||||
"lis 8,1\n"
|
||||
"mr 9,%0\n"
|
||||
"mr %1,1\n"
|
||||
"li 0,0x3500\n"
|
||||
"sc\n"
|
||||
"nop\n"
|
||||
"mr 1,%1\n"
|
||||
:
|
||||
: "r"(addr), "r"(value)
|
||||
: "memory", "ctr", "lr", "0", "3", "4", "5", "6", "7", "8", "9", "10",
|
||||
"11", "12");
|
||||
}
|
||||
|
||||
void PatchSyscall(int index, uint32_t addr) {
|
||||
kern_write(KERN_SYSCALL_TBL1 + index * 4, addr);
|
||||
kern_write(KERN_SYSCALL_TBL2 + index * 4, addr);
|
||||
kern_write(KERN_SYSCALL_TBL3 + index * 4, addr);
|
||||
kern_write(KERN_SYSCALL_TBL4 + index * 4, addr);
|
||||
kern_write(KERN_SYSCALL_TBL5 + index * 4, addr);
|
||||
}
|
||||
|
||||
void kernelInitialize() {
|
||||
PatchSyscall(0x25, (uint32_t) SCKernelCopyData);
|
||||
}
|
||||
|
@ -1,11 +1,6 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
void KernelWrite(uint32_t addr, const void *data, uint32_t length);
|
||||
void KernelWriteU32(uint32_t addr, uint32_t value);
|
||||
|
||||
void PatchSyscall(int index, void *ptr);
|
||||
|
||||
void kernelInitialize();
|
||||
|
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
|
103
src/main.cpp
103
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 "exceptions.h"
|
||||
#include "menu.h"
|
||||
#include "patches.h"
|
||||
#include "screen.h"
|
||||
#include "logger.h"
|
||||
#include <coreinit/debug.h>
|
||||
#include <wups.h>
|
||||
|
||||
OSThread **pThreadList;
|
||||
|
||||
|
||||
bool GetTitleIdOnDisk(uint64_t *titleId) {
|
||||
MCPTitleListType title;
|
||||
uint32_t count = 0;
|
||||
WUPS_PLUGIN_NAME("Debugger");
|
||||
WUPS_PLUGIN_DESCRIPTION("FTP Server");
|
||||
WUPS_PLUGIN_VERSION("0.1");
|
||||
WUPS_PLUGIN_AUTHOR("Kinnay");
|
||||
WUPS_PLUGIN_LICENSE("GPL");
|
||||
|
||||
int handle = MCP_Open();
|
||||
MCP_TitleListByDevice(handle, "odd", &count, &title, sizeof(title));
|
||||
MCP_Close(handle);
|
||||
|
||||
if (count > 0) {
|
||||
*titleId = title.titleId;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int MenuMain() {
|
||||
Screen screen;
|
||||
screen.init();
|
||||
|
||||
Menu menu(&screen);
|
||||
|
||||
Menu::Option result = menu.show();
|
||||
if (result == Menu::Exit) return EXIT_SUCCESS;
|
||||
else if (result == Menu::LaunchDisk) {
|
||||
uint64_t titleId;
|
||||
if (GetTitleIdOnDisk(&titleId)) {
|
||||
SYSLaunchTitle(titleId);
|
||||
} else {
|
||||
menu.setMessage("Please insert a valid disk");
|
||||
}
|
||||
} else if (result == Menu::ReturnToMenu) {
|
||||
SYSLaunchMenu();
|
||||
}
|
||||
return EXIT_RELAUNCH_ON_LOAD;
|
||||
}
|
||||
|
||||
int DebuggerMain() {
|
||||
ApplyPatches();
|
||||
debugger = new Debugger();
|
||||
debugger->start();
|
||||
return EXIT_RELAUNCH_ON_LOAD;
|
||||
}
|
||||
|
||||
|
||||
bool firstRun = true;
|
||||
int start() {
|
||||
coreinitInitialize();
|
||||
kernelInitialize();
|
||||
vpadInitialize();
|
||||
sysappInitialize();
|
||||
nsysnetInitialize();
|
||||
nnsaveInitialize();
|
||||
nnactInitialize();
|
||||
WUPS_USE_WUT_DEVOPTAB();
|
||||
|
||||
INITIALIZE_PLUGIN() {
|
||||
InstallExceptionHandlers();
|
||||
|
||||
int result;
|
||||
if (firstRun) {
|
||||
result = MenuMain();
|
||||
} else {
|
||||
result = DebuggerMain();
|
||||
}
|
||||
firstRun = false;
|
||||
|
||||
return result;
|
||||
}
|
||||
ON_APPLICATION_START() {
|
||||
initLogging();
|
||||
DEBUG_FUNCTION_LINE("Started Debugger plugin");
|
||||
pThreadList = (OSThread **) 0x100567F8;
|
||||
debugger = new Debugger();
|
||||
DEBUG_FUNCTION_LINE("Created Debugger");
|
||||
debugger->start();
|
||||
DEBUG_FUNCTION_LINE("Started Debugger thread");
|
||||
}
|
||||
|
||||
extern "C" int entryPoint() {
|
||||
return start();
|
||||
ON_APPLICATION_REQUESTS_EXIT() {
|
||||
DEBUG_FUNCTION_LINE("Deleting Debugger thread");
|
||||
delete debugger;
|
||||
DEBUG_FUNCTION_LINE("Deleted Debugger thread");
|
||||
deinitLogging();
|
||||
}
|
||||
|
@ -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 "cafe/vpad.h"
|
||||
#include "color.h"
|
||||
#include "input.h"
|
||||
#include "screen.h"
|
||||
#include <vpad/input.h>
|
||||
|
||||
Menu::Menu(Screen *screen) : screen(screen) {
|
||||
currentOption = LaunchDisk;
|
||||
@ -30,14 +29,14 @@ void Menu::setMessage(const char *message) {
|
||||
|
||||
void Menu::redraw() {
|
||||
screen->clear(COLOR_BLUE);
|
||||
screen->drawText(5, 5, "Wii U Debugger");
|
||||
screen->drawText(5, 7, "Choose an option:");
|
||||
screen->drawText(8, 9, "Install and launch disc");
|
||||
screen->drawText(8, 10, "Install and return to system menu");
|
||||
screen->drawText(8, 11, "Exit without installing");
|
||||
screen->drawText(5, 9 + currentOption, ">");
|
||||
Screen::drawText(5, 5, "Wii U Debugger");
|
||||
Screen::drawText(5, 7, "Choose an option:");
|
||||
Screen::drawText(8, 9, "Install and launch disc");
|
||||
Screen::drawText(8, 10, "Install and return to system menu");
|
||||
Screen::drawText(8, 11, "Exit without installing");
|
||||
Screen::drawText(5, 9 + currentOption, ">");
|
||||
if (message) {
|
||||
screen->drawText(5, 13, message);
|
||||
Screen::drawText(5, 13, message);
|
||||
}
|
||||
screen->flip();
|
||||
Screen::flip();
|
||||
}
|
||||
|
@ -5,11 +5,9 @@
|
||||
|
||||
class Menu {
|
||||
public:
|
||||
enum Option {
|
||||
LaunchDisk,
|
||||
ReturnToMenu,
|
||||
Exit
|
||||
};
|
||||
enum Option { LaunchDisk,
|
||||
ReturnToMenu,
|
||||
Exit };
|
||||
|
||||
Menu(Screen *screen);
|
||||
Option show();
|
||||
|
@ -1,56 +1,17 @@
|
||||
|
||||
#include "cafe/coreinit.h"
|
||||
#include "kernel.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <wups.h>
|
||||
|
||||
int OSSetExceptionCallback_Patch() {
|
||||
DECL_FUNCTION(int, OSSetExceptionCallback) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int OSSetExceptionCallbackEx_Patch() {
|
||||
DECL_FUNCTION(int, OSSetExceptionCallbackEx) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool OSIsDebuggerInitialized_Patch() {
|
||||
DECL_FUNCTION(int, OSIsDebuggerInitialized) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void Patch(void *funcPtr, void *patchPtr) {
|
||||
OSDynLoad_NotifyData *sectionInfo = MainRPL->notifyData;
|
||||
|
||||
uint32_t func = (uint32_t) funcPtr;
|
||||
uint32_t patch = (uint32_t) patchPtr;
|
||||
if (func < 0x01800000) { //OS function (with trampoline)
|
||||
for (uint32_t addr = sectionInfo->textAddr; addr < 0x10000000; addr += 4) {
|
||||
uint32_t *instrs = (uint32_t *) addr;
|
||||
if (instrs[0] == (0x3D600000 | (func >> 16)) && //lis r11, func@h
|
||||
instrs[1] == (0x616B0000 | (func & 0xFFFF)) && //ori r11, r11, func@l
|
||||
instrs[2] == 0x7D6903A6 && //mtctr r11
|
||||
instrs[3] == 0x4E800420) //bctr
|
||||
{
|
||||
KernelWriteU32(addr, 0x3D600000 | (patch >> 16)); //lis r11, patch@h
|
||||
KernelWriteU32(addr + 4, 0x616B0000 | (patch & 0xFFFF)); //ori r11, r11, patch@l
|
||||
}
|
||||
}
|
||||
} else { //Dynamic function
|
||||
for (uint32_t addr = sectionInfo->textAddr; addr < 0x10000000; addr += 4) {
|
||||
uint32_t instr = *(uint32_t *) addr;
|
||||
if ((instr & 0xFC000002) == 0x48000000) { //b or bl
|
||||
if ((instr & 0x03FFFFFC) == func - addr) {
|
||||
instr = instr & ~0x03FFFFFC;
|
||||
instr |= patch;
|
||||
instr |= 2; //Turn b/bl into ba/bla
|
||||
KernelWriteU32(addr, instr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ApplyPatches() {
|
||||
Patch((void *) OSSetExceptionCallback, (void *) OSSetExceptionCallback_Patch);
|
||||
Patch((void *) OSSetExceptionCallbackEx, (void *) OSSetExceptionCallbackEx_Patch);
|
||||
|
||||
Patch((void *) OSIsDebuggerInitialized, (void *) OSIsDebuggerInitialized_Patch);
|
||||
}
|
||||
WUPS_MUST_REPLACE(OSSetExceptionCallback, WUPS_LOADER_LIBRARY_COREINIT, OSSetExceptionCallback);
|
||||
WUPS_MUST_REPLACE(OSSetExceptionCallbackEx, WUPS_LOADER_LIBRARY_COREINIT, OSSetExceptionCallbackEx);
|
||||
WUPS_MUST_REPLACE(OSIsDebuggerInitialized, WUPS_LOADER_LIBRARY_COREINIT, OSIsDebuggerInitialized);
|
@ -1,37 +1,38 @@
|
||||
|
||||
#include "screen.h"
|
||||
#include "cafe/coreinit.h"
|
||||
#include "memory.h"
|
||||
|
||||
Screen::Screen() : screenBuffer(0) {}
|
||||
#include <memory/mappedmemory.h>
|
||||
|
||||
Screen::Screen() : screenBuffer(nullptr) {}
|
||||
Screen::~Screen() {
|
||||
if (screenBuffer) {
|
||||
operator delete(screenBuffer);
|
||||
MEMFreeToMappedMemory(screenBuffer);
|
||||
screenBuffer = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void Screen::init() {
|
||||
OSScreenInit();
|
||||
|
||||
uint32_t bufferSize0 = OSScreenGetBufferSizeEx(0);
|
||||
uint32_t bufferSize1 = OSScreenGetBufferSizeEx(1);
|
||||
screenBuffer = operator new(bufferSize0 + bufferSize1, 0x40);
|
||||
OSScreenSetBufferEx(0, screenBuffer);
|
||||
OSScreenSetBufferEx(1, (char *) screenBuffer + bufferSize0);
|
||||
uint32_t bufferSize0 = OSScreenGetBufferSizeEx(SCREEN_TV);
|
||||
uint32_t bufferSize1 = OSScreenGetBufferSizeEx(SCREEN_DRC);
|
||||
screenBuffer = MEMAllocFromMappedMemoryForGX2Ex(bufferSize0 + bufferSize1, 0x100);
|
||||
OSScreenSetBufferEx(SCREEN_TV, screenBuffer);
|
||||
OSScreenSetBufferEx(SCREEN_DRC, (char *) screenBuffer + bufferSize0);
|
||||
|
||||
OSScreenEnableEx(0, 1);
|
||||
OSScreenEnableEx(1, 1);
|
||||
OSScreenClearBufferEx(0, 0);
|
||||
OSScreenClearBufferEx(1, 0);
|
||||
OSScreenFlipBuffersEx(0);
|
||||
OSScreenFlipBuffersEx(1);
|
||||
OSScreenEnableEx(SCREEN_TV, 1);
|
||||
OSScreenEnableEx(SCREEN_DRC, 1);
|
||||
OSScreenClearBufferEx(SCREEN_TV, 0);
|
||||
OSScreenClearBufferEx(SCREEN_DRC, 0);
|
||||
OSScreenFlipBuffersEx(SCREEN_TV);
|
||||
OSScreenFlipBuffersEx(SCREEN_DRC);
|
||||
}
|
||||
|
||||
void Screen::clear(Display screen, uint32_t color) {
|
||||
void Screen::clear(OSScreenID screen, uint32_t color) {
|
||||
OSScreenClearBufferEx(screen, color);
|
||||
}
|
||||
|
||||
void Screen::drawRect(Display screen, int x1, int y1, int x2, int y2, uint32_t color) {
|
||||
void Screen::drawRect(OSScreenID screen, int x1, int y1, int x2, int y2, uint32_t color) {
|
||||
for (int x = x1; x < x2; x++) {
|
||||
OSScreenPutPixelEx(screen, x, y1, color);
|
||||
OSScreenPutPixelEx(screen, x, y2, color);
|
||||
@ -42,7 +43,7 @@ void Screen::drawRect(Display screen, int x1, int y1, int x2, int y2, uint32_t c
|
||||
}
|
||||
}
|
||||
|
||||
void Screen::fillRect(Display screen, int x1, int y1, int x2, int y2, uint32_t color) {
|
||||
void Screen::fillRect(OSScreenID screen, int x1, int y1, int x2, int y2, uint32_t color) {
|
||||
for (int x = x1; x < x2; x++) {
|
||||
for (int y = y1; y < y2; y++) {
|
||||
OSScreenPutPixelEx(screen, x, y, color);
|
||||
@ -50,11 +51,11 @@ void Screen::fillRect(Display screen, int x1, int y1, int x2, int y2, uint32_t c
|
||||
}
|
||||
}
|
||||
|
||||
void Screen::drawText(Display screen, int x, int y, const char *text) {
|
||||
void Screen::drawText(OSScreenID screen, int x, int y, const char *text) {
|
||||
OSScreenPutFontEx(screen, x, y, text);
|
||||
}
|
||||
|
||||
void Screen::flip(Display screen) {
|
||||
void Screen::flip(OSScreenID screen) {
|
||||
OSScreenFlipBuffersEx(screen);
|
||||
}
|
||||
|
||||
@ -62,26 +63,26 @@ int Screen::convx(int x) { return x * 854 / 1280; }
|
||||
int Screen::convy(int y) { return y * 480 / 720; }
|
||||
|
||||
void Screen::clear(uint32_t color) {
|
||||
clear(TV, color);
|
||||
clear(DRC, color);
|
||||
clear(SCREEN_TV, color);
|
||||
clear(SCREEN_DRC, color);
|
||||
}
|
||||
|
||||
void Screen::drawRect(int x1, int y1, int x2, int y2, uint32_t color) {
|
||||
drawRect(TV, x1, y1, x2, y2, color);
|
||||
drawRect(DRC, convx(x1), convy(y1), convx(x2), convy(y2), color);
|
||||
drawRect(SCREEN_TV, x1, y1, x2, y2, color);
|
||||
drawRect(SCREEN_DRC, convx(x1), convy(y1), convx(x2), convy(y2), color);
|
||||
}
|
||||
|
||||
void Screen::fillRect(int x1, int y1, int x2, int y2, uint32_t color) {
|
||||
fillRect(TV, x1, y1, x2, y2, color);
|
||||
fillRect(DRC, convx(x1), convy(y1), convx(x2), convy(y2), color);
|
||||
fillRect(SCREEN_TV, x1, y1, x2, y2, color);
|
||||
fillRect(SCREEN_DRC, convx(x1), convy(y1), convx(x2), convy(y2), color);
|
||||
}
|
||||
|
||||
void Screen::drawText(int x, int y, const char *text) {
|
||||
drawText(TV, x, y, text);
|
||||
drawText(DRC, x, y, text);
|
||||
drawText(SCREEN_TV, x, y, text);
|
||||
drawText(SCREEN_DRC, x, y, text);
|
||||
}
|
||||
|
||||
void Screen::flip() {
|
||||
flip(TV);
|
||||
flip(DRC);
|
||||
flip(SCREEN_TV);
|
||||
flip(SCREEN_DRC);
|
||||
}
|
||||
|
24
src/screen.h
24
src/screen.h
@ -1,15 +1,11 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <coreinit/screen.h>
|
||||
#include <cstdint>
|
||||
|
||||
class Screen {
|
||||
public:
|
||||
enum Display {
|
||||
TV,
|
||||
DRC
|
||||
};
|
||||
|
||||
Screen();
|
||||
~Screen();
|
||||
|
||||
@ -17,18 +13,18 @@ public:
|
||||
void clear(uint32_t color);
|
||||
void drawRect(int x1, int y1, int x2, int y2, uint32_t color);
|
||||
void fillRect(int x1, int y1, int x2, int y2, uint32_t color);
|
||||
void drawText(int x, int y, const char *text);
|
||||
void flip();
|
||||
static void drawText(int x, int y, const char *text);
|
||||
static void flip();
|
||||
|
||||
void clear(Display screen, uint32_t color);
|
||||
void drawRect(Display screen, int x1, int y1, int x2, int y2, uint32_t color);
|
||||
void fillRect(Display screen, int x1, int y1, int x2, int y2, uint32_t color);
|
||||
void drawText(Display screen, int x, int y, const char *text);
|
||||
void flip(Display screen);
|
||||
static void clear(OSScreenID screen, uint32_t color);
|
||||
static void drawRect(OSScreenID screen, int x1, int y1, int x2, int y2, uint32_t color);
|
||||
static void fillRect(OSScreenID screen, int x1, int y1, int x2, int y2, uint32_t color);
|
||||
static void drawText(OSScreenID screen, int x, int y, const char *text);
|
||||
static void flip(OSScreenID screen);
|
||||
|
||||
private:
|
||||
void *screenBuffer;
|
||||
|
||||
int convx(int x);
|
||||
int convy(int y);
|
||||
static int convx(int x);
|
||||
static int convy(int y);
|
||||
};
|
||||
|
@ -1,13 +1,15 @@
|
||||
|
||||
#include "cafe/nsysnet.h"
|
||||
|
||||
#include "socket.h"
|
||||
#include "logger.h"
|
||||
#include <arpa/inet.h>
|
||||
#include <cstring>
|
||||
#include <unistd.h>
|
||||
|
||||
Socket::Socket() : sock(-1) {}
|
||||
|
||||
Socket::~Socket() {
|
||||
if (sock >= 0) {
|
||||
socketclose(sock);
|
||||
::shutdown(sock, SHUT_RDWR);
|
||||
::close(sock);
|
||||
}
|
||||
}
|
||||
|
||||
@ -22,14 +24,13 @@ bool Socket::init(Type type) {
|
||||
|
||||
bool Socket::close() {
|
||||
if (sock >= 0) {
|
||||
int result = socketclose(sock);
|
||||
int result = ::close(sock);
|
||||
sock = -1;
|
||||
return result == 0;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool Client::sendall(const void *data, size_t length) {
|
||||
size_t sent = 0;
|
||||
while (sent < length) {
|
||||
@ -60,6 +61,12 @@ bool Client::recvall(void *data, size_t length) {
|
||||
return true;
|
||||
}
|
||||
|
||||
struct sockaddr_kinnay {
|
||||
uint16_t family;
|
||||
uint16_t port;
|
||||
uint32_t addr;
|
||||
char zero[8];
|
||||
};
|
||||
|
||||
bool Server::bind(int port) {
|
||||
uint32_t reuseaddr = 1;
|
||||
@ -69,28 +76,42 @@ bool Server::bind(int port) {
|
||||
return false;
|
||||
}
|
||||
|
||||
sockaddr serverAddr = {0};
|
||||
|
||||
/*
|
||||
struct sockaddr_in bindAddress;
|
||||
memset(&bindAddress, 0, sizeof(bindAddress));
|
||||
bindAddress.sin_family = AF_INET;
|
||||
bindAddress.sin_port = htons(port);
|
||||
bindAddress.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
|
||||
result = ::bind(sock, (struct sockaddr *) &bindAddress, 16);*/
|
||||
|
||||
sockaddr_kinnay serverAddr = {0};
|
||||
serverAddr.family = AF_INET;
|
||||
serverAddr.port = port;
|
||||
serverAddr.addr = 0;
|
||||
|
||||
result = ::bind(sock, &serverAddr, 16);
|
||||
result = ::bind(sock, (const struct sockaddr *) &serverAddr, 16);
|
||||
if (result < 0) {
|
||||
DEBUG_FUNCTION_LINE("Bind was not successful");
|
||||
close();
|
||||
return false;
|
||||
}
|
||||
DEBUG_FUNCTION_LINE("Bind was successful");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Server::accept(Client *client) {
|
||||
int result = listen(sock, 1);
|
||||
if (result < 0) {
|
||||
DEBUG_FUNCTION_LINE("listen failed");
|
||||
close();
|
||||
return false;
|
||||
}
|
||||
|
||||
int fd = ::accept(sock, 0, 0);
|
||||
if (fd < 0) {
|
||||
DEBUG_FUNCTION_LINE("accept failed");
|
||||
close();
|
||||
return false;
|
||||
}
|
||||
|
@ -5,10 +5,8 @@
|
||||
|
||||
class Socket {
|
||||
public:
|
||||
enum Type {
|
||||
TCP,
|
||||
UDP
|
||||
};
|
||||
enum Type { TCP,
|
||||
UDP };
|
||||
|
||||
Socket();
|
||||
~Socket();
|
||||
|
Loading…
Reference in New Issue
Block a user