mirror of
https://github.com/wiiu-env/AromaBaseModule.git
synced 2025-02-17 03:36:23 +01:00
Initial commit
This commit is contained in:
commit
a89b932085
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
|
65
.github/workflows/ci.yml
vendored
Normal file
65
.github/workflows/ci.yml
vendored
Normal file
@ -0,0 +1,65 @@
|
||||
name: CI-Release
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
clang-format:
|
||||
runs-on: ubuntu-18.04
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: clang-format
|
||||
run: |
|
||||
docker run --rm -v ${PWD}:/src wiiuenv/clang-format:13.0.0-2 -r ./source
|
||||
build-binary:
|
||||
runs-on: ubuntu-18.04
|
||||
needs: clang-format
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: build binary
|
||||
run: |
|
||||
docker build . -t builder
|
||||
docker run --rm -v ${PWD}:/project builder make
|
||||
- uses: actions/upload-artifact@master
|
||||
with:
|
||||
name: binary
|
||||
path: "*.wms"
|
||||
deploy-binary:
|
||||
needs: build-binary
|
||||
runs-on: ubuntu-18.04
|
||||
steps:
|
||||
- name: Get environment variables
|
||||
id: get_repository_name
|
||||
run: |
|
||||
echo REPOSITORY_NAME=$(echo "$GITHUB_REPOSITORY" | awk -F / '{print $2}' | sed -e "s/:refs//") >> $GITHUB_ENV
|
||||
echo DATETIME=$(echo $(date '+%Y%m%d-%H%M%S')) >> $GITHUB_ENV
|
||||
- uses: actions/download-artifact@master
|
||||
with:
|
||||
name: binary
|
||||
- name: zip artifact
|
||||
run: zip -r ${{ env.REPOSITORY_NAME }}_${{ env.DATETIME }}.zip *.wms
|
||||
- name: Create Release
|
||||
id: create_release
|
||||
uses: actions/create-release@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
tag_name: ${{ env.REPOSITORY_NAME }}-${{ env.DATETIME }}
|
||||
release_name: Nightly-${{ env.REPOSITORY_NAME }}-${{ env.DATETIME }}
|
||||
draft: false
|
||||
prerelease: true
|
||||
body: |
|
||||
Not a stable release:
|
||||
${{ github.event.head_commit.message }}
|
||||
- name: Upload Release Asset
|
||||
id: upload-release-asset
|
||||
uses: actions/upload-release-asset@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ steps.create_release.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps
|
||||
asset_path: ./${{ env.REPOSITORY_NAME }}_${{ env.DATETIME }}.zip
|
||||
asset_name: ${{ env.REPOSITORY_NAME }}_${{ env.DATETIME }}.zip
|
||||
asset_content_type: application/zip
|
36
.github/workflows/pr.yml
vendored
Normal file
36
.github/workflows/pr.yml
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
name: CI-PR
|
||||
|
||||
on: [pull_request]
|
||||
|
||||
jobs:
|
||||
clang-format:
|
||||
runs-on: ubuntu-18.04
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: clang-format
|
||||
run: |
|
||||
docker run --rm -v ${PWD}:/src wiiuenv/clang-format:13.0.0-2 -r ./source
|
||||
check-build-with-logging:
|
||||
runs-on: ubuntu-18.04
|
||||
needs: clang-format
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: build binary with logging
|
||||
run: |
|
||||
docker build . -t builder
|
||||
docker run --rm -v ${PWD}:/project builder make DEBUG=VERBOSE
|
||||
docker run --rm -v ${PWD}:/project builder make clean
|
||||
docker run --rm -v ${PWD}:/project builder make DEBUG=1
|
||||
build-binary:
|
||||
runs-on: ubuntu-18.04
|
||||
needs: clang-format
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: build binary
|
||||
run: |
|
||||
docker build . -t builder
|
||||
docker run --rm -v ${PWD}:/project builder make
|
||||
- uses: actions/upload-artifact@master
|
||||
with:
|
||||
name: binary
|
||||
path: "*.wms"
|
10
.gitignore
vendored
Normal file
10
.gitignore
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
*.cbp
|
||||
*.elf
|
||||
*.layout
|
||||
*.rpx
|
||||
build/
|
||||
*.save-failed
|
||||
.idea/
|
||||
cmake-build-debug/
|
||||
CMakeLists.txt
|
||||
*.wms
|
6
Dockerfile
Normal file
6
Dockerfile
Normal file
@ -0,0 +1,6 @@
|
||||
FROM wiiuenv/devkitppc:20220806
|
||||
|
||||
COPY --from=wiiuenv/libfunctionpatcher:20220724 /artifacts $DEVKITPRO
|
||||
COPY --from=wiiuenv/wiiumodulesystem:20220724 /artifacts $DEVKITPRO
|
||||
|
||||
WORKDIR project
|
152
Makefile
Normal file
152
Makefile
Normal file
@ -0,0 +1,152 @@
|
||||
#-------------------------------------------------------------------------------
|
||||
.SUFFIXES:
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
ifeq ($(strip $(DEVKITPRO)),)
|
||||
$(error "Please set DEVKITPRO in your environment. export DEVKITPRO=<path to>/devkitpro")
|
||||
endif
|
||||
|
||||
TOPDIR ?= $(CURDIR)
|
||||
|
||||
include $(DEVKITPRO)/wums/share/wums_rules
|
||||
|
||||
WUMS_ROOT := $(DEVKITPRO)/wums
|
||||
WUT_ROOT := $(DEVKITPRO)/wut
|
||||
#-------------------------------------------------------------------------------
|
||||
# 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 := AromaBaseModule
|
||||
BUILD := build
|
||||
SOURCES := source \
|
||||
source/applicationendshook \
|
||||
source/dynload \
|
||||
source/sdrefcount \
|
||||
source/symbolnamepatcher
|
||||
DATA := data
|
||||
INCLUDES := source
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# options for code generation
|
||||
#-------------------------------------------------------------------------------
|
||||
CFLAGS := -Wall -Wextra -O3 -ffunction-sections\
|
||||
$(MACHDEP)
|
||||
|
||||
CFLAGS += $(INCLUDE) -D__WIIU__ -D__WUT__
|
||||
|
||||
CXXFLAGS := $(CFLAGS) -std=c++20
|
||||
|
||||
ASFLAGS := -g $(ARCH)
|
||||
LDFLAGS = -g $(ARCH) $(RPXSPECS) -Wl,-Map,$(notdir $*.map) -T$(WUMS_ROOT)/share/libfunctionpatcher.ld $(WUMSSPECS)
|
||||
|
||||
ifeq ($(DEBUG),1)
|
||||
CXXFLAGS += -DDEBUG -g
|
||||
CFLAGS += -DDEBUG -g
|
||||
endif
|
||||
|
||||
ifeq ($(DEBUG),VERBOSE)
|
||||
CXXFLAGS += -DDEBUG -DVERBOSE_DEBUG -g
|
||||
CFLAGS += -DDEBUG -DVERBOSE_DEBUG -g
|
||||
endif
|
||||
|
||||
LIBS := -lwums -lwut -lfunctionpatcher
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# list of directories containing libraries, this must be the top level
|
||||
# containing include and lib
|
||||
#-------------------------------------------------------------------------------
|
||||
LIBDIRS := $(PORTLIBS) $(WUT_ROOT) $(WUMS_ROOT)
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# 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).wms $(TARGET).elf
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
else
|
||||
.PHONY: all
|
||||
|
||||
DEPENDS := $(OFILES:.o=.d)
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# main targets
|
||||
#-------------------------------------------------------------------------------
|
||||
all : $(OUTPUT).wms
|
||||
|
||||
$(OUTPUT).wms : $(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
|
||||
#-------------------------------------------------------------------------------
|
37
README.md
Normal file
37
README.md
Normal file
@ -0,0 +1,37 @@
|
||||
[![CI-Release](https://github.com/wiiu-env/AromaBaseModule/actions/workflows/ci.yml/badge.svg)](https://github.com/wiiu-env/AromaBaseModule/actions/workflows/ci.yml)
|
||||
|
||||
## Usage
|
||||
(`[ENVIRONMENT]` is a placeholder for the actual environment name.)
|
||||
|
||||
1. Copy the file `AromaBaseModule.wms` into `sd:/wiiu/environments/[ENVIRONMENT]/modules`.
|
||||
2. Requires the [WUMSLoader](https://github.com/wiiu-env/WUMSLoader) in `sd:/wiiu/environments/[ENVIRONMENT]/modules/setup`.
|
||||
|
||||
## Buildflags
|
||||
|
||||
### Logging
|
||||
Building via `make` only logs errors (via OSReport). To enable logging via the [LoggingModule](https://github.com/wiiu-env/LoggingModule) set `DEBUG` to `1` or `VERBOSE`.
|
||||
|
||||
`make` Logs errors only (via OSReport).
|
||||
`make DEBUG=1` Enables information and error logging via [LoggingModule](https://github.com/wiiu-env/LoggingModule).
|
||||
`make DEBUG=VERBOSE` Enables verbose information and error logging via [LoggingModule](https://github.com/wiiu-env/LoggingModule).
|
||||
|
||||
If the [LoggingModule](https://github.com/wiiu-env/LoggingModule) is not present, it'll fallback to UDP (Port 4405) and [CafeOS](https://github.com/wiiu-env/USBSerialLoggingModule) logging.
|
||||
|
||||
## Building using the Dockerfile
|
||||
|
||||
It's possible to use a docker image for building. This way you don't need anything installed on your host system.
|
||||
|
||||
```
|
||||
# Build docker image (only needed once)
|
||||
docker build . -t aromabasemodule-builder
|
||||
|
||||
# make
|
||||
docker run -it --rm -v ${PWD}:/project aromabasemodule-builder make
|
||||
|
||||
# make clean
|
||||
docker run -it --rm -v ${PWD}:/project aromabasemodule-builder make clean
|
||||
```
|
||||
|
||||
## Format the code via docker
|
||||
|
||||
`docker run --rm -v ${PWD}:/src wiiuenv/clang-format:13.0.0-2 -r ./source -i`
|
14
source/applicationendshook/applicationendhook.cpp
Normal file
14
source/applicationendshook/applicationendhook.cpp
Normal file
@ -0,0 +1,14 @@
|
||||
#include "applicationendhook.h"
|
||||
#include "applicationends_function_replacements.h"
|
||||
#include "logger.h"
|
||||
|
||||
|
||||
void initApplicationEndsHook() {
|
||||
DEBUG_FUNCTION_LINE("Patch ApplicationEndsHook functions");
|
||||
for (uint32_t i = 0; i < applicationendshook_function_replacements_size; i++) {
|
||||
if (!FunctionPatcherPatchFunction(&applicationendshook_function_replacements[i], nullptr)) {
|
||||
OSFatal("AromaBaseModule: Failed to patch ApplicationEndsHook function");
|
||||
}
|
||||
}
|
||||
DEBUG_FUNCTION_LINE("Patch ApplicationEndsHook functions finished");
|
||||
}
|
3
source/applicationendshook/applicationendhook.h
Normal file
3
source/applicationendshook/applicationendhook.h
Normal file
@ -0,0 +1,3 @@
|
||||
#pragma once
|
||||
|
||||
void initApplicationEndsHook();
|
@ -0,0 +1,54 @@
|
||||
#include "applicationends_function_replacements.h"
|
||||
#include "globals.h"
|
||||
|
||||
#include <coreinit/dynload.h>
|
||||
#include <coreinit/messagequeue.h>
|
||||
#include <wums.h>
|
||||
|
||||
static uint32_t lastData0 = 0;
|
||||
|
||||
void CallHook(wums_hook_type_t type) {
|
||||
for (uint32_t i = 0; i < gModuleData->number_modules; i++) {
|
||||
auto *curModule = &gModuleData->modules[i];
|
||||
for (uint32_t j = 0; j < curModule->number_hook_entries; j++) {
|
||||
auto hook_entry = &curModule->hook_entries[j];
|
||||
auto hook_type = (wums_hook_type_t) hook_entry->type;
|
||||
if (hook_type == type) {
|
||||
if ((type == WUMS_HOOK_INIT_WRAPPER || type == WUMS_HOOK_FINI_WRAPPER) && curModule->skipInitFini) {
|
||||
continue;
|
||||
}
|
||||
const void *target = (const void *) hook_entry->target;
|
||||
((void (*)())((uint32_t *) target))();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DECL_FUNCTION(void, _Exit, uint32_t status) {
|
||||
CallHook(WUMS_HOOK_APPLICATION_ENDS);
|
||||
CallHook(WUMS_HOOK_FINI_WUT_SOCKETS);
|
||||
CallHook(WUMS_HOOK_FINI_WUT_DEVOPTAB);
|
||||
real__Exit(status);
|
||||
}
|
||||
|
||||
DECL_FUNCTION(uint32_t, OSReceiveMessage, OSMessageQueue *queue, OSMessage *message, uint32_t flags) {
|
||||
uint32_t res = real_OSReceiveMessage(queue, message, flags);
|
||||
if (queue == OSGetSystemMessageQueue()) {
|
||||
if (message != nullptr && res) {
|
||||
if (lastData0 != message->args[0]) {
|
||||
if (message->args[0] == 0xD1E0D1E0) {
|
||||
CallHook(WUMS_HOOK_APPLICATION_REQUESTS_EXIT);
|
||||
}
|
||||
}
|
||||
lastData0 = message->args[0];
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
function_replacement_data_t applicationendshook_function_replacements[] = {
|
||||
REPLACE_FUNCTION(OSReceiveMessage, LIBRARY_COREINIT, OSReceiveMessage),
|
||||
REPLACE_FUNCTION(_Exit, LIBRARY_COREINIT, _Exit),
|
||||
};
|
||||
|
||||
uint32_t applicationendshook_function_replacements_size = sizeof(applicationendshook_function_replacements) / sizeof(function_replacement_data_t);
|
@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <function_patcher/function_patching.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern function_replacement_data_t applicationendshook_function_replacements[];
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
extern uint32_t applicationendshook_function_replacements_size;
|
21
source/dynload/dynload.cpp
Normal file
21
source/dynload/dynload.cpp
Normal file
@ -0,0 +1,21 @@
|
||||
#include "dynload.h"
|
||||
#include "../globals.h"
|
||||
#include "dynload_function_replacements.h"
|
||||
#include "logger.h"
|
||||
#include <malloc.h>
|
||||
|
||||
void initDynload() {
|
||||
gRPLData = (LOADED_RPL *) malloc(sizeof(LOADED_RPL) * gModuleData->number_modules);
|
||||
if (!gRPLData) {
|
||||
DEBUG_FUNCTION_LINE_ERR("Failed to allocate gRPLData");
|
||||
OSFatal("AromaBaseModule: Failed to allocate gRPLData");
|
||||
}
|
||||
|
||||
DEBUG_FUNCTION_LINE("Patch functions for dynload patches");
|
||||
for (uint32_t i = 0; i < dynload_function_replacements_size; i++) {
|
||||
if (!FunctionPatcherPatchFunction(&dynload_function_replacements[i], nullptr)) {
|
||||
OSFatal("AromaBaseModule: Failed to patch function for dynload patches");
|
||||
}
|
||||
}
|
||||
DEBUG_FUNCTION_LINE("Patch functions finished for dynload patches");
|
||||
}
|
3
source/dynload/dynload.h
Normal file
3
source/dynload/dynload.h
Normal file
@ -0,0 +1,3 @@
|
||||
#pragma once
|
||||
|
||||
void initDynload();
|
147
source/dynload/dynload_function_replacements.cpp
Normal file
147
source/dynload/dynload_function_replacements.cpp
Normal file
@ -0,0 +1,147 @@
|
||||
#include "dynload_function_replacements.h"
|
||||
#include "globals.h"
|
||||
#include "loader_defines.h"
|
||||
#include "logger.h"
|
||||
#include <coreinit/dynload.h>
|
||||
#include <cstring>
|
||||
#include <wums.h>
|
||||
|
||||
DECL_FUNCTION(OSDynLoad_Error, OSDynLoad_Acquire, char const *name, OSDynLoad_Module *outModule) {
|
||||
DEBUG_FUNCTION_LINE_VERBOSE("Looking for module %s", name);
|
||||
for (uint32_t i = 0; i < gModuleData->number_modules; i++) {
|
||||
if (strcmp(name, gModuleData->modules[i].module_export_name) == 0) {
|
||||
*outModule = (OSDynLoad_Module) (0x13370000 + i);
|
||||
return OS_DYNLOAD_OK;
|
||||
}
|
||||
}
|
||||
|
||||
OSDynLoad_Error result = real_OSDynLoad_Acquire(name, outModule);
|
||||
if (result == OS_DYNLOAD_OK) {
|
||||
return OS_DYNLOAD_OK;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
DECL_FUNCTION(OSDynLoad_Error, OSDynLoad_FindExport, OSDynLoad_Module module, BOOL isData, char const *name, void **outAddr) {
|
||||
OSDynLoad_Error result = real_OSDynLoad_FindExport(module, isData, name, outAddr);
|
||||
if (result == OS_DYNLOAD_OK) {
|
||||
return OS_DYNLOAD_OK;
|
||||
}
|
||||
|
||||
if (((uint32_t) module & 0xFFFF0000) == 0x13370000) {
|
||||
uint32_t moduleHandle = ((uint32_t) module) & 0x0000FFFF;
|
||||
if (moduleHandle >= gModuleData->number_modules) {
|
||||
DEBUG_FUNCTION_LINE_ERR("Invalid module handle was encoded in OSDynLoad_Module %d (%08X)", moduleHandle, module);
|
||||
return result;
|
||||
}
|
||||
|
||||
auto *curModule = &gModuleData->modules[moduleHandle];
|
||||
DEBUG_FUNCTION_LINE_VERBOSE("Try to find export %s in module %s", name, curModule->module_export_name);
|
||||
for (uint32_t i = 0; i < curModule->number_export_entries; i++) {
|
||||
auto *curExport = &curModule->export_entries[i];
|
||||
if (strcmp(name, curExport->name) == 0) {
|
||||
if (isData && curExport->type == WUMS_FUNCTION_EXPORT) {
|
||||
DEBUG_FUNCTION_LINE_ERR("Requested data Export but only found a function export");
|
||||
return OS_DYNLOAD_INVALID_MODULE_NAME;
|
||||
}
|
||||
*outAddr = (void *) curExport->address;
|
||||
DEBUG_FUNCTION_LINE_VERBOSE("SUCCESS! Set outAddr to %08X. It's from module %s function %s",
|
||||
curExport->address,
|
||||
curModule->module_export_name,
|
||||
curExport->name);
|
||||
return OS_DYNLOAD_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
RPLFileInfo_v4_2 fileInfoBuffer;
|
||||
|
||||
DECL_FUNCTION(LOADED_RPL *, LiFindRPLByName, char *name) {
|
||||
for (uint32_t i = 0; i < gModuleData->number_modules; i++) {
|
||||
auto *curModule = &gModuleData->modules[i];
|
||||
if (strcmp(name, curModule->module_export_name) == 0) {
|
||||
fileInfoBuffer.tlsModuleIndex = 0;
|
||||
gRPLData[i].fileInfoBuffer = &fileInfoBuffer; // will be copied to the LiImportTracking array
|
||||
gRPLData[i].loadStateFlags = 0x0;
|
||||
gRPLData[i].entrypoint = 0x1; //needs to be != 0;
|
||||
gRPLData[i].funcExports = (Export *) (FUNCTION_EXPORT_MASK + i);
|
||||
gRPLData[i].numFuncExports = 1;
|
||||
gRPLData[i].dataExports = (Export *) (DATA_EXPORT_MASK + i);
|
||||
gRPLData[i].numDataExports = 1;
|
||||
return &gRPLData[i];
|
||||
}
|
||||
}
|
||||
return real_LiFindRPLByName(name);
|
||||
}
|
||||
|
||||
DECL_FUNCTION(uint32_t, __OSDynLoad_InternalAcquire, char *name, void *out, uint32_t u1, uint32_t u2, uint32_t u3) {
|
||||
for (uint32_t i = 0; i < gModuleData->number_modules; i++) {
|
||||
auto *curModule = &gModuleData->modules[i];
|
||||
if (strcmp(name, curModule->module_export_name) == 0) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return real___OSDynLoad_InternalAcquire(name, out, u1, u2, u3);
|
||||
}
|
||||
|
||||
Export ourExportThing;
|
||||
|
||||
DECL_FUNCTION(Export *, LiBinSearchExport, Export *exports, int numExports, char *name) {
|
||||
auto isFunc = (((uint32_t) exports) & 0xFFFF0000) == FUNCTION_EXPORT_MASK;
|
||||
auto isData = (((uint32_t) exports) & 0xFFFF0000) == DATA_EXPORT_MASK;
|
||||
if (isFunc || isData) {
|
||||
uint32_t moduleHandle = ((uint32_t) exports) & 0x0000FFFF;
|
||||
if (moduleHandle > gModuleData->number_modules) {
|
||||
DEBUG_FUNCTION_LINE_LOADER_ERR("Invalid module handle was encoded in Export %d (%08X)", moduleHandle, exports);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto *curModule = &gModuleData->modules[moduleHandle];
|
||||
DEBUG_FUNCTION_LINE_LOADER_VERBOSE("Try to find export %s in module %s", name, curModule->module_export_name);
|
||||
for (uint32_t i = 0; i < curModule->number_export_entries; i++) {
|
||||
auto *curExport = &curModule->export_entries[i];
|
||||
if (strcmp(name, curExport->name) == 0) {
|
||||
if ((isFunc && curExport->type == WUMS_FUNCTION_EXPORT) || (isData && curExport->type == WUMS_DATA_EXPORT)) {
|
||||
ourExportThing.value = curExport->address;
|
||||
ourExportThing.name = 0;
|
||||
return &ourExportThing;
|
||||
}
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
return real_LiBinSearchExport(exports, numExports, name);
|
||||
}
|
||||
|
||||
DECL_FUNCTION(int32_t, LiFixupRelocOneRPL, LOADED_RPL *rpl, void *imports, uint32_t unknown) {
|
||||
auto rplAddress = (uint32_t) rpl;
|
||||
if (rplAddress >= (uint32_t) &gRPLData[0] && rplAddress < (uint32_t) &gRPLData[gModuleData->number_modules]) {
|
||||
// Skip if this is our fake RPL
|
||||
return 0;
|
||||
}
|
||||
return real_LiFixupRelocOneRPL(rpl, imports, unknown);
|
||||
}
|
||||
|
||||
DECL_FUNCTION(int32_t, sCheckOne, LOADED_RPL *rpl) {
|
||||
auto rplAddress = (uint32_t) rpl;
|
||||
if (rplAddress >= (uint32_t) &gRPLData[0] && rplAddress < (uint32_t) &gRPLData[gModuleData->number_modules]) {
|
||||
// Skip if this is our fake RPL
|
||||
return 0;
|
||||
}
|
||||
return real_sCheckOne(rpl);
|
||||
}
|
||||
|
||||
function_replacement_data_t dynload_function_replacements[] = {
|
||||
REPLACE_FUNCTION_VIA_ADDRESS(__OSDynLoad_InternalAcquire, 0x32029054, 0x101C400 + 0x0cc54),
|
||||
REPLACE_FUNCTION_VIA_ADDRESS(LiFindRPLByName, 0x32004BC4, 0x01004bc4),
|
||||
REPLACE_FUNCTION_VIA_ADDRESS(LiBinSearchExport, 0x320002f8, 0x010002f8),
|
||||
REPLACE_FUNCTION_VIA_ADDRESS(sCheckOne, 0x32007294, 0x01007294),
|
||||
REPLACE_FUNCTION_VIA_ADDRESS(LiFixupRelocOneRPL, 0x320059f0, 0x010059f0),
|
||||
REPLACE_FUNCTION(OSDynLoad_Acquire, LIBRARY_COREINIT, OSDynLoad_Acquire),
|
||||
REPLACE_FUNCTION(OSDynLoad_FindExport, LIBRARY_COREINIT, OSDynLoad_FindExport),
|
||||
};
|
||||
|
||||
uint32_t dynload_function_replacements_size = sizeof(dynload_function_replacements) / sizeof(function_replacement_data_t);
|
7
source/dynload/dynload_function_replacements.h
Normal file
7
source/dynload/dynload_function_replacements.h
Normal file
@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <function_patcher/function_patching.h>
|
||||
|
||||
extern function_replacement_data_t dynload_function_replacements[];
|
||||
extern uint32_t dynload_function_replacements_size;
|
39
source/dynload/loader_defines.h
Normal file
39
source/dynload/loader_defines.h
Normal file
@ -0,0 +1,39 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
// see https://github.com/decaf-emu/decaf-emu/tree/43366a34e7b55ab9d19b2444aeb0ccd46ac77dea/src/libdecaf/src/cafe/loader
|
||||
struct LiImportTracking {
|
||||
uint32_t numExports;
|
||||
struct Export *exports;
|
||||
uint32_t tlsModuleIndex;
|
||||
struct LOADED_RPL *rpl;
|
||||
};
|
||||
|
||||
struct Export {
|
||||
uint32_t value;
|
||||
uint32_t name;
|
||||
};
|
||||
|
||||
struct RPLFileInfo_v4_2 {
|
||||
char field_0x0[88];
|
||||
uint16_t tlsModuleIndex;
|
||||
char field_0x5a[6];
|
||||
};
|
||||
|
||||
struct LOADED_RPL {
|
||||
char u1[88];
|
||||
struct RPLFileInfo_v4_2 *fileInfoBuffer;
|
||||
char u2[20];
|
||||
uint32_t loadStateFlags;
|
||||
uint32_t entrypoint;
|
||||
char u3[132];
|
||||
uint32_t numFuncExports;
|
||||
Export *funcExports;
|
||||
uint32_t numDataExports;
|
||||
Export *dataExports;
|
||||
char u4[12];
|
||||
};
|
||||
|
||||
#define FUNCTION_EXPORT_MASK 0x13370000
|
||||
#define DATA_EXPORT_MASK 0x13380000
|
5
source/globals.cpp
Normal file
5
source/globals.cpp
Normal file
@ -0,0 +1,5 @@
|
||||
#include "globals.h"
|
||||
|
||||
module_information_t *gModuleData __attribute__((section(".data"))) = NULL;
|
||||
int32_t gSDMountRefCount __attribute__((section(".data"))) = 0;
|
||||
LOADED_RPL *gRPLData __attribute__((section(".data"))) = nullptr;
|
6
source/globals.h
Normal file
6
source/globals.h
Normal file
@ -0,0 +1,6 @@
|
||||
#include "dynload/loader_defines.h"
|
||||
#include <wums.h>
|
||||
|
||||
extern module_information_t *gModuleData;
|
||||
extern int32_t gSDMountRefCount;
|
||||
extern LOADED_RPL *gRPLData;
|
36
source/logger.c
Normal file
36
source/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
|
||||
}
|
74
source/logger.h
Normal file
74
source/logger.h
Normal file
@ -0,0 +1,74 @@
|
||||
#pragma once
|
||||
|
||||
#include <coreinit/debug.h>
|
||||
#include <string.h>
|
||||
#include <whb/log.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define LOG_APP_TYPE "M"
|
||||
#define LOG_APP_NAME "application_ends"
|
||||
|
||||
#define __FILENAME_X__ (strrchr(__FILE__, '\\') ? strrchr(__FILE__, '\\') + 1 : __FILE__)
|
||||
#define __FILENAME__ (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILENAME_X__)
|
||||
|
||||
#define LOG(LOG_FUNC, FMT, ARGS...) LOG_EX_DEFAULT(LOG_FUNC, "", "", FMT, ##ARGS)
|
||||
|
||||
#define LOG_EX_DEFAULT(LOG_FUNC, LOG_LEVEL, LINE_END, FMT, ARGS...) LOG_EX(__FILENAME__, __FUNCTION__, __LINE__, LOG_FUNC, LOG_LEVEL, LINE_END, FMT, ##ARGS)
|
||||
|
||||
#define LOG_EX(FILENAME, FUNCTION, LINE, LOG_FUNC, LOG_LEVEL, LINE_END, FMT, ARGS...) \
|
||||
do { \
|
||||
LOG_FUNC("[(%s)%18s][%23s]%30s@L%04d: " LOG_LEVEL "" FMT "" LINE_END, LOG_APP_TYPE, LOG_APP_NAME, FILENAME, FUNCTION, LINE, ##ARGS); \
|
||||
} while (0)
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
#ifdef VERBOSE_DEBUG
|
||||
#define DEBUG_FUNCTION_LINE_VERBOSE(FMT, ARGS...) LOG(WHBLogPrintf, FMT, ##ARGS)
|
||||
#define DEBUG_FUNCTION_LINE_VERBOSE_EX(FILENAME, FUNCTION, LINE, FMT, ARGS...) LOG_EX(FILENAME, FUNCTION, LINE, WHBLogPrintf, "", "", FMT, ##ARGS);
|
||||
#define DEBUG_FUNCTION_LINE_LOADER_VERBOSE(FMT, ARGS...) LOG_EX_DEFAULT(((void (*)(const char *, ...))((uint32_t *) 0x010028d0)), "", "\n", FMT, ##ARGS)
|
||||
#else
|
||||
#define DEBUG_FUNCTION_LINE_VERBOSE(FMT, ARGS...) while (0)
|
||||
#define DEBUG_FUNCTION_LINE_VERBOSE_EX(FMT, ARGS...) while (0)
|
||||
#define DEBUG_FUNCTION_LINE_LOADER_VERBOSE(FMT, ARGS...) while (0)
|
||||
#endif
|
||||
|
||||
#define DEBUG_FUNCTION_LINE(FMT, ARGS...) LOG(WHBLogPrintf, FMT, ##ARGS)
|
||||
|
||||
#define DEBUG_FUNCTION_LINE_WRITE(FMT, ARGS...) LOG(WHBLogWritef, FMT, ##ARGS)
|
||||
|
||||
#define DEBUG_FUNCTION_LINE_WARN(FMT, ARGS...) LOG_EX_DEFAULT(WHBLogPrintf, "## WARN## ", "", FMT, ##ARGS)
|
||||
#define DEBUG_FUNCTION_LINE_ERR(FMT, ARGS...) LOG_EX_DEFAULT(WHBLogPrintf, "##ERROR## ", "", FMT, ##ARGS)
|
||||
|
||||
#define DEBUG_FUNCTION_LINE_ERR_LAMBDA(FILENAME, FUNCTION, LINE, FMT, ARGS...) LOG_EX(FILENAME, FUNCTION, LINE, WHBLogPrintf, "##ERROR## ", "", FMT, ##ARGS);
|
||||
|
||||
#else
|
||||
|
||||
#define DEBUG_FUNCTION_LINE_VERBOSE_EX(FMT, ARGS...) while (0)
|
||||
|
||||
#define DEBUG_FUNCTION_LINE_VERBOSE(FMT, ARGS...) while (0)
|
||||
|
||||
#define DEBUG_FUNCTION_LINE_LOADER_VERBOSE(FMT, ARGS...) while (0)
|
||||
|
||||
#define DEBUG_FUNCTION_LINE(FMT, ARGS...) while (0)
|
||||
|
||||
#define DEBUG_FUNCTION_LINE_WRITE(FMT, ARGS...) while (0)
|
||||
|
||||
#define DEBUG_FUNCTION_LINE_WARN(FMT, ARGS...) LOG_EX_DEFAULT(OSReport, "## WARN## ", "\n", FMT, ##ARGS)
|
||||
#define DEBUG_FUNCTION_LINE_ERR(FMT, ARGS...) LOG_EX_DEFAULT(OSReport, "##ERROR## ", "\n", FMT, ##ARGS)
|
||||
|
||||
#define DEBUG_FUNCTION_LINE_ERR_LAMBDA(FILENAME, FUNCTION, LINE, FMT, ARGS...) LOG_EX(FILENAME, FUNCTION, LINE, OSReport, "##ERROR## ", "\n", FMT, ##ARGS);
|
||||
|
||||
#endif
|
||||
|
||||
#define DEBUG_FUNCTION_LINE_LOADER_ERR(FMT, ARGS...) LOG_EX_DEFAULT(((void (*)(const char *, ...))((uint32_t *) 0x010028d0)), "##ERROR## ", "\n", FMT, ##ARGS)
|
||||
|
||||
void initLogging();
|
||||
|
||||
void deinitLogging();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
28
source/main.cpp
Normal file
28
source/main.cpp
Normal file
@ -0,0 +1,28 @@
|
||||
#include "applicationendshook/applicationendhook.h"
|
||||
#include "dynload/dynload.h"
|
||||
#include "globals.h"
|
||||
#include "logger.h"
|
||||
#include "sdrefcount/refcount.h"
|
||||
#include "symbolnamepatcher/symbolname.h"
|
||||
#include <wums.h>
|
||||
|
||||
WUMS_MODULE_EXPORT_NAME("homebrew_basemodule");
|
||||
WUMS_MODULE_SKIP_INIT_FINI();
|
||||
|
||||
WUMS_INITIALIZE(args) {
|
||||
initLogging();
|
||||
gModuleData = args.module_information;
|
||||
if (gModuleData == nullptr) {
|
||||
OSFatal("AromaBaseModule: Failed to get gModuleData pointer.");
|
||||
}
|
||||
if (gModuleData->version != MODULE_INFORMATION_VERSION) {
|
||||
OSFatal("AromaBaseModule: The module information struct version does not match.");
|
||||
}
|
||||
|
||||
initApplicationEndsHook();
|
||||
initSDRefCount();
|
||||
initSymbolNamePatcher();
|
||||
initDynload();
|
||||
|
||||
deinitLogging();
|
||||
}
|
29
source/sdrefcount/refcount.cpp
Normal file
29
source/sdrefcount/refcount.cpp
Normal file
@ -0,0 +1,29 @@
|
||||
#include "globals.h"
|
||||
#include "logger.h"
|
||||
#include "sd_function_replacements.h"
|
||||
#include <coreinit/filesystem_fsa.h>
|
||||
|
||||
void initSDRefCount() {
|
||||
FSAInit();
|
||||
auto client = FSAAddClient(nullptr);
|
||||
gSDMountRefCount = 0;
|
||||
if (client > 0) {
|
||||
auto res = FSAMount(client, "/dev/sdcard01", "/vol/external01", (FSAMountFlags) 0, nullptr, 0);
|
||||
if (res == FS_ERROR_ALREADY_EXISTS) {
|
||||
DEBUG_FUNCTION_LINE("SDCard is already mounted, set ref counter to 16");
|
||||
gSDMountRefCount = 16;
|
||||
} else {
|
||||
DEBUG_FUNCTION_LINE("Set ref counter to 0");
|
||||
FSAUnmount(client, "/vol/external01", FSA_UNMOUNT_FLAG_BIND_MOUNT);
|
||||
}
|
||||
FSADelClient(res);
|
||||
}
|
||||
|
||||
DEBUG_FUNCTION_LINE("Patch SDRefCount functions");
|
||||
for (uint32_t i = 0; i < sdrefcount_function_replacements_size; i++) {
|
||||
if (!FunctionPatcherPatchFunction(&sdrefcount_function_replacements[i], nullptr)) {
|
||||
OSFatal("AromaBaseModule: Failed to patch function for sd ref counting");
|
||||
}
|
||||
}
|
||||
DEBUG_FUNCTION_LINE("Patch SDRefCount functions finished");
|
||||
}
|
3
source/sdrefcount/refcount.h
Normal file
3
source/sdrefcount/refcount.h
Normal file
@ -0,0 +1,3 @@
|
||||
#pragma once
|
||||
|
||||
void initSDRefCount();
|
93
source/sdrefcount/sd_function_replacements.cpp
Normal file
93
source/sdrefcount/sd_function_replacements.cpp
Normal file
@ -0,0 +1,93 @@
|
||||
#include "sd_function_replacements.h"
|
||||
#include "globals.h"
|
||||
#include "logger.h"
|
||||
#include <coreinit/filesystem_fsa.h>
|
||||
#include <string_view>
|
||||
|
||||
DECL_FUNCTION(void, __PPCExit, uint32_t u1) {
|
||||
if (gSDMountRefCount > 0) {
|
||||
DEBUG_FUNCTION_LINE_WARN("SDCard is still mounted. Ref counter: %d\n", gSDMountRefCount);
|
||||
FSAInit();
|
||||
auto client = FSAAddClient(nullptr);
|
||||
if (client) {
|
||||
auto res = FSAUnmount(client, "/vol/external01/", FSA_UNMOUNT_FLAG_BIND_MOUNT);
|
||||
DEBUG_FUNCTION_LINE_WARN("Unmount res %d %s", res, FSAGetStatusStr(res));
|
||||
}
|
||||
gSDMountRefCount = 0;
|
||||
} else {
|
||||
DEBUG_FUNCTION_LINE_WARN("Refcount %d", gSDMountRefCount);
|
||||
}
|
||||
real___PPCExit(u1);
|
||||
}
|
||||
|
||||
DECL_FUNCTION(FSStatus, FSMount, FSClient *client, FSCmdBlock *cmd, FSMountSource *source, char *target, uint32_t bytes, FSErrorFlag errorMask) {
|
||||
if (std::string_view(target) == "/vol/external01") {
|
||||
if (gSDMountRefCount > 0) {
|
||||
gSDMountRefCount++;
|
||||
return FS_STATUS_OK;
|
||||
}
|
||||
DEBUG_FUNCTION_LINE_WARN("Do real mount for /vol/external01");
|
||||
auto res = real_FSMount(client, cmd, source, target, bytes, errorMask);
|
||||
if (res == FS_STATUS_OK) {
|
||||
gSDMountRefCount++;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
return real_FSMount(client, cmd, source, target, bytes, errorMask);
|
||||
}
|
||||
|
||||
DECL_FUNCTION(FSStatus, FSUnmount, FSClient *client, FSCmdBlock *cmd, const char *target, FSErrorFlag errorMask) {
|
||||
if (std::string_view(target) == "/vol/external01") {
|
||||
gSDMountRefCount--;
|
||||
if (gSDMountRefCount <= 0) {
|
||||
gSDMountRefCount = 0;
|
||||
DEBUG_FUNCTION_LINE_WARN("Do real unmount for /vol/external01");
|
||||
return real_FSUnmount(client, cmd, target, errorMask);
|
||||
}
|
||||
return FS_STATUS_OK;
|
||||
}
|
||||
return real_FSUnmount(client, cmd, target, errorMask);
|
||||
}
|
||||
|
||||
DECL_FUNCTION(FSError, FSAMount, FSAClientHandle client, const char *source, const char *target, FSAMountFlags flags, void *arg_buf, uint32_t arg_len) {
|
||||
if (std::string_view(target) == "/vol/external01") {
|
||||
if (gSDMountRefCount > 0) {
|
||||
gSDMountRefCount++;
|
||||
return FS_ERROR_OK;
|
||||
}
|
||||
DEBUG_FUNCTION_LINE_WARN("Do real mount for /vol/external01");
|
||||
auto res = real_FSAMount(client, source, target, flags, arg_buf, arg_len);
|
||||
if (res == FS_ERROR_OK || res == FS_ERROR_ALREADY_EXISTS) {
|
||||
gSDMountRefCount++;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
return real_FSAMount(client, source, target, flags, arg_buf, arg_len);
|
||||
}
|
||||
|
||||
DECL_FUNCTION(FSError, FSAUnmount, FSAClientHandle client, const char *mountedTarget, FSAUnmountFlags flags) {
|
||||
if (std::string_view(mountedTarget) == "/vol/external01") {
|
||||
gSDMountRefCount--;
|
||||
if (gSDMountRefCount <= 0) {
|
||||
DEBUG_FUNCTION_LINE_WARN("Do real unmount for /vol/external01");
|
||||
auto res = real_FSAUnmount(client, mountedTarget, flags);
|
||||
gSDMountRefCount = 0;
|
||||
return res;
|
||||
}
|
||||
return FS_ERROR_OK;
|
||||
}
|
||||
|
||||
return real_FSAUnmount(client, mountedTarget, flags);
|
||||
}
|
||||
|
||||
function_replacement_data_t sdrefcount_function_replacements[] = {
|
||||
REPLACE_FUNCTION(__PPCExit, LIBRARY_COREINIT, __PPCExit),
|
||||
REPLACE_FUNCTION(FSMount, LIBRARY_COREINIT, FSMount),
|
||||
REPLACE_FUNCTION(FSUnmount, LIBRARY_COREINIT, FSUnmount),
|
||||
REPLACE_FUNCTION(FSAMount, LIBRARY_COREINIT, FSAMount),
|
||||
REPLACE_FUNCTION(FSAUnmount, LIBRARY_COREINIT, FSAUnmount)};
|
||||
|
||||
uint32_t sdrefcount_function_replacements_size = sizeof(sdrefcount_function_replacements) / sizeof(function_replacement_data_t);
|
16
source/sdrefcount/sd_function_replacements.h
Normal file
16
source/sdrefcount/sd_function_replacements.h
Normal file
@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <function_patcher/function_patching.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern function_replacement_data_t sdrefcount_function_replacements[];
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
extern uint32_t sdrefcount_function_replacements_size;
|
88
source/symbolnamepatcher/sym_function_replacements.cpp
Normal file
88
source/symbolnamepatcher/sym_function_replacements.cpp
Normal file
@ -0,0 +1,88 @@
|
||||
#include "sym_function_replacements.h"
|
||||
#include "globals.h"
|
||||
#include <cstring>
|
||||
|
||||
#pragma GCC push_options
|
||||
#pragma GCC optimize("O0")
|
||||
|
||||
DECL_FUNCTION(uint32_t, SC17_FindClosestSymbol,
|
||||
uint32_t addr,
|
||||
uint32_t *outDistance,
|
||||
char *symbolNameBuffer,
|
||||
uint32_t symbolNameBufferLength,
|
||||
char *moduleNameBuffer,
|
||||
uint32_t moduleNameBufferLength) {
|
||||
for (uint32_t i = 0; i < gModuleData->number_modules; i++) {
|
||||
auto *module = &gModuleData->modules[i];
|
||||
if (addr < module->startAddress || addr >= module->endAddress) {
|
||||
continue;
|
||||
}
|
||||
|
||||
strncpy(moduleNameBuffer, module->module_export_name, moduleNameBufferLength);
|
||||
|
||||
if (module->function_symbol_entries != nullptr && module->number_function_symbols > 1) {
|
||||
for (uint32_t j = 0; j < module->number_function_symbols - 1; j++) {
|
||||
auto symbolData = &module->function_symbol_entries[j];
|
||||
auto symbolDataNext = &module->function_symbol_entries[j + 1];
|
||||
if (j == module->number_function_symbols - 2 || (addr >= (uint32_t) symbolData->address && addr < (uint32_t) symbolDataNext->address)) {
|
||||
strncpy(symbolNameBuffer, symbolData->name, moduleNameBufferLength);
|
||||
if (outDistance) {
|
||||
*outDistance = addr - (uint32_t) symbolData->address;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
strncpy(symbolNameBuffer, ".text", symbolNameBufferLength);
|
||||
|
||||
if (outDistance) {
|
||||
*outDistance = addr - (uint32_t) module->startAddress;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
return real_SC17_FindClosestSymbol(addr, outDistance, symbolNameBuffer, symbolNameBufferLength, moduleNameBuffer, moduleNameBufferLength);
|
||||
}
|
||||
|
||||
DECL_FUNCTION(uint32_t, KiGetAppSymbolName, uint32_t addr, char *buffer, int32_t bufSize) {
|
||||
for (uint32_t i = 0; i < gModuleData->number_modules; i++) {
|
||||
auto *module = &gModuleData->modules[i];
|
||||
if (addr < module->startAddress || addr >= module->endAddress) {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto moduleNameLen = strlen(module->module_export_name);
|
||||
int32_t spaceLeftInBuffer = (int32_t) bufSize - (int32_t) moduleNameLen - 1;
|
||||
if (spaceLeftInBuffer < 0) {
|
||||
spaceLeftInBuffer = 0;
|
||||
}
|
||||
strncpy(buffer, module->module_export_name, bufSize);
|
||||
|
||||
if (module->function_symbol_entries != nullptr && module->number_function_symbols > 1) {
|
||||
for (uint32_t j = 0; j < module->number_function_symbols - 1; j++) {
|
||||
auto symbolData = &module->function_symbol_entries[j];
|
||||
auto symbolDataNext = &module->function_symbol_entries[j + 1];
|
||||
if (j == module->number_function_symbols - 2 || (addr >= (uint32_t) symbolData->address && addr < (uint32_t) symbolDataNext->address)) {
|
||||
if (spaceLeftInBuffer > 2) {
|
||||
buffer[moduleNameLen] = '|';
|
||||
buffer[moduleNameLen + 1] = '\0';
|
||||
strncpy(buffer + moduleNameLen + 1, symbolData->name, spaceLeftInBuffer - 1);
|
||||
}
|
||||
return (uint32_t) symbolData->address;
|
||||
}
|
||||
}
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
|
||||
return real_KiGetAppSymbolName(addr, buffer, bufSize);
|
||||
}
|
||||
#pragma GCC pop_options
|
||||
|
||||
function_replacement_data_t symbolname_function_replacements[] = {
|
||||
REPLACE_FUNCTION_VIA_ADDRESS(SC17_FindClosestSymbol, 0xfff10218, 0xfff10218),
|
||||
REPLACE_FUNCTION_VIA_ADDRESS(KiGetAppSymbolName, 0xfff0e3a0, 0xfff0e3a0),
|
||||
};
|
||||
|
||||
uint32_t symbolname_function_replacements_size = sizeof(symbolname_function_replacements) / sizeof(function_replacement_data_t);
|
16
source/symbolnamepatcher/sym_function_replacements.h
Normal file
16
source/symbolnamepatcher/sym_function_replacements.h
Normal file
@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <function_patcher/function_patching.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern function_replacement_data_t symbolname_function_replacements[];
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
extern uint32_t symbolname_function_replacements_size;
|
13
source/symbolnamepatcher/symbolname.cpp
Normal file
13
source/symbolnamepatcher/symbolname.cpp
Normal file
@ -0,0 +1,13 @@
|
||||
#include "globals.h"
|
||||
#include "logger.h"
|
||||
#include "sym_function_replacements.h"
|
||||
|
||||
void initSymbolNamePatcher() {
|
||||
DEBUG_FUNCTION_LINE("Patch SymbolNamePatcher functions");
|
||||
for (uint32_t i = 0; i < symbolname_function_replacements_size; i++) {
|
||||
if (!FunctionPatcherPatchFunction(&symbolname_function_replacements[i], nullptr)) {
|
||||
OSFatal("AromaBaseModule: Failed to patch SymbolNamePatcher function");
|
||||
}
|
||||
}
|
||||
DEBUG_FUNCTION_LINE("Patch SymbolNamePatcher functions finished");
|
||||
}
|
3
source/symbolnamepatcher/symbolname.h
Normal file
3
source/symbolnamepatcher/symbolname.h
Normal file
@ -0,0 +1,3 @@
|
||||
#pragma once
|
||||
|
||||
void initSymbolNamePatcher();
|
Loading…
x
Reference in New Issue
Block a user