From ac912010f21425d1ac1e5fe4b8c9a5c6b86eab3e Mon Sep 17 00:00:00 2001 From: Maschell Date: Sun, 11 Feb 2018 18:33:07 +0100 Subject: [PATCH] [Plugins] Started on creating a SDCafiine plugin. Still WIP. - Stiil need to add iosuhax support (probably thrpugh iosuhax n the loader) - modpack chooser needs complety rewritten in C =( So currently this is only compatible with games with nativ sd access. Probably unstable! --- .travis.yml | 12 + plugins/sdcafiine/Makefile | 289 +++++++++++++++ plugins/sdcafiine/sdcafiine.cbp | 37 ++ plugins/sdcafiine/src/common/common.h | 59 ++++ plugins/sdcafiine/src/common/retain_vars.cpp | 14 + plugins/sdcafiine/src/common/retain_vars.h | 23 ++ .../src/fs_wrapper/FileReplacerUtils.cpp | 98 ++++++ .../src/fs_wrapper/FileReplacerUtils.h | 64 ++++ .../src/fs_wrapper/fs_async_wrapper.cpp | 217 ++++++++++++ .../src/fs_wrapper/fs_async_wrapper.h | 124 +++++++ .../src/fs_wrapper/fs_default_os_wrapper.cpp | 220 ++++++++++++ .../src/fs_wrapper/fs_default_os_wrapper.h | 43 +++ .../src/fs_wrapper/fs_retain_vars.cpp | 28 ++ .../sdcafiine/src/fs_wrapper/fs_retain_vars.h | 38 ++ .../src/fs_wrapper/fs_sync_wrapper.cpp | 226 ++++++++++++ .../src/fs_wrapper/fs_sync_wrapper.h | 54 +++ .../src/fs_wrapper/fs_wrapper_utils.cpp | 108 ++++++ .../src/fs_wrapper/fs_wrapper_utils.h | 53 +++ plugins/sdcafiine/src/main.cpp | 153 ++++++++ plugins/sdcafiine/src/main.h | 18 + plugins/sdcafiine/src/patches.cpp | 293 ++++++++++++++++ plugins/sdcafiine/src/utils/fs_utils.cpp | 147 ++++++++ plugins/sdcafiine/src/utils/fs_utils.h | 18 + plugins/sdcafiine/src/utils/vc_vector.c | 329 ++++++++++++++++++ plugins/sdcafiine/src/utils/vc_vector.h | 130 +++++++ 25 files changed, 2795 insertions(+) create mode 100644 plugins/sdcafiine/Makefile create mode 100644 plugins/sdcafiine/sdcafiine.cbp create mode 100644 plugins/sdcafiine/src/common/common.h create mode 100644 plugins/sdcafiine/src/common/retain_vars.cpp create mode 100644 plugins/sdcafiine/src/common/retain_vars.h create mode 100644 plugins/sdcafiine/src/fs_wrapper/FileReplacerUtils.cpp create mode 100644 plugins/sdcafiine/src/fs_wrapper/FileReplacerUtils.h create mode 100644 plugins/sdcafiine/src/fs_wrapper/fs_async_wrapper.cpp create mode 100644 plugins/sdcafiine/src/fs_wrapper/fs_async_wrapper.h create mode 100644 plugins/sdcafiine/src/fs_wrapper/fs_default_os_wrapper.cpp create mode 100644 plugins/sdcafiine/src/fs_wrapper/fs_default_os_wrapper.h create mode 100644 plugins/sdcafiine/src/fs_wrapper/fs_retain_vars.cpp create mode 100644 plugins/sdcafiine/src/fs_wrapper/fs_retain_vars.h create mode 100644 plugins/sdcafiine/src/fs_wrapper/fs_sync_wrapper.cpp create mode 100644 plugins/sdcafiine/src/fs_wrapper/fs_sync_wrapper.h create mode 100644 plugins/sdcafiine/src/fs_wrapper/fs_wrapper_utils.cpp create mode 100644 plugins/sdcafiine/src/fs_wrapper/fs_wrapper_utils.h create mode 100644 plugins/sdcafiine/src/main.cpp create mode 100644 plugins/sdcafiine/src/main.h create mode 100644 plugins/sdcafiine/src/patches.cpp create mode 100644 plugins/sdcafiine/src/utils/fs_utils.cpp create mode 100644 plugins/sdcafiine/src/utils/fs_utils.h create mode 100644 plugins/sdcafiine/src/utils/vc_vector.c create mode 100644 plugins/sdcafiine/src/utils/vc_vector.h diff --git a/.travis.yml b/.travis.yml index 358d646..35e54e4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -23,12 +23,22 @@ before_install: - wget http://download.sourceforge.net/devkitpro/devkitPPC_r29-1-x86_64-linux.tar.bz2 -O devkitPPC-linux.tar.bz2 - wget https://github.com/Maschell/dynamic_libs/archive/lib.tar.gz -O dynamic_libs.tar.gz - wget https://github.com/Maschell/libutils/archive/master.tar.gz -O libutils.tar.gz + - wget https://github.com/aliaspider/libfat/archive/master.tar.gz -O libfat.tar.gz + - wget https://github.com/dimok789/libiosuhax/archive/master.tar.gz -O libiosuhax.tar.gz + - wget https://github.com/Maschell/libntfs-wiiu/archive/master.tar.gz -O libntfs.tar.gz install: - tar -xjf devkitPPC-linux.tar.bz2 -C ${DEVKITPRO}/ - tar -xzvf dynamic_libs.tar.gz - tar -xzvf libutils.tar.gz + - tar -xzvf libfat.tar.gz + - tar -xzvf libiosuhax.tar.gz + - tar -xzvf libntfs.tar.gz + - tar -xzvf libiosuhax.tar.gz - 7z x -y ./dynamic_libs-lib/libs/portlibs.zip -o${DEVKITPRO} + - (cd libiosuhax-master && make -j8 && make install) + - (cd libfat-master && make wiiu-release && make wiiu-install) + - (cd libntfs-wiiu-master && make wiiu-install) - (cd dynamic_libs-lib && make -j8 && make install) - (cd libutils-master && make -j8 && make install) @@ -37,6 +47,7 @@ script: - (cd loader && make) - (cd example_plugin && make) - (cd plugins/padcon && make) +- (cd plugins/sdcafiine && make) before_deploy: - mkdir -p "wiiu/apps/wiiupluginloader" @@ -47,6 +58,7 @@ before_deploy: - (cd loader && make) - cp example_plugin/example_plugin.mod wiiu/plugins - cp plugins/padcon/padcon.mod wiiu/plugins +- cp plugins/sdcafiine/sdcafiine.mod wiiu/plugins - cp loader/meta/* wiiu/apps/wiiupluginloader - cp loader/wiiupluginloader.elf wiiu/apps/wiiupluginloader - zip -r WiiUPluginLoader_$versiontag.zip wiiu diff --git a/plugins/sdcafiine/Makefile b/plugins/sdcafiine/Makefile new file mode 100644 index 0000000..7296bb4 --- /dev/null +++ b/plugins/sdcafiine/Makefile @@ -0,0 +1,289 @@ +DO_LOGGING := 1 + +#--------------------------------------------------------------------------------- +# Clear the implicit built in rules +#--------------------------------------------------------------------------------- +.SUFFIXES: +#--------------------------------------------------------------------------------- +ifeq ($(strip $(DEVKITPPC)),) +$(error "Please set DEVKITPPC in your environment. export DEVKITPPC=devkitPPC") +endif +ifeq ($(strip $(DEVKITPRO)),) +$(error "Please set DEVKITPRO in your environment. export DEVKITPRO=devkitPRO") +endif +export PATH := $(DEVKITPPC)/bin:$(PORTLIBS)/bin:$(PATH) +export PORTLIBS := $(DEVKITPRO)/portlibs/ppc +export WUPSDIR := $(DEVKITPRO)/wups +export GCC_VER := $(shell $(DEVKITPPC)/bin/powerpc-eabi-gcc -dumpversion) + +PREFIX := powerpc-eabi- + +export AS := $(PREFIX)as +export CC := $(PREFIX)gcc +export CXX := $(PREFIX)g++ +export LD := $(PREFIX)ld +export AR := $(PREFIX)ar +export OBJCOPY := $(PREFIX)objcopy + +#--------------------------------------------------------------------------------- +# 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 +# INCLUDES is a list of directories containing extra header files +#--------------------------------------------------------------------------------- +TARGET := $(notdir $(CURDIR)).mod +BUILD := build +SOURCES := src + +DATA := + +INCLUDES := src + +MAP ?= $(TARGET:.mod=.map) + +#--------------------------------------------------------------------------------- +# options for code generation +#--------------------------------------------------------------------------------- + +# -Os: optimise size +# -Wall: generate lots of warnings +# -DGEKKO_U: define the symbol GEKKO (used in some headers) +# -D__wiiu__: define the symbol __wii__ (used in some headers) +# -mrvl: enable wii/gamecube compilation +# -mcpu=750: enable processor specific compilation +# -meabi: enable eabi specific compilation +# -mhard-float: enable hardware floating point instructions +# -fshort-wchar: use 16 bit whcar_t type in keeping with Wii executables +# -fno-common: stop common variables which the loader can't understand +# -msdata-none: do not use r2 or r13 as small data areas +# -memb: enable embedded application specific compilation +# -ffunction-sections: split up functions so linker can garbage collect +# -fdata-sections: split up data so linker can garbage collect +COMMON_CFLAGS += -Os -Wall -DGEKKO_U -D__wiiu__ -mrvl -mcpu=750 -meabi -mhard-float -fshort-wchar -fno-common -msdata=none -memb -ffunction-sections -fdata-sections + + +# -x c: compile as c code +# -std=c11: use the c11 standard +CFLAGS += $(COMMON_CFLAGS) -x c -std=c11 + +# -x c: compile as c++ code +# -std=gnu++11: use the c++11 standard +CXXFLAGS += $(COMMON_CFLAGS) -x c++ -std=gnu++11 + +ifeq ($(DO_LOGGING), 1) + CFLAGS += -D__LOGGING__ + CXXFLAGS += -D__LOGGING__ +endif + +ASFLAGS := -mregnames +# --relocatable: make sure ld doesn't remove relocations wups will need +# -s: strip local symbols to speed linking +# -u: keep certain sections +# -wrap: wrap function +# --gc-sections: remove unneeded symbols +# -T: use the linker script specified (to force certain wups sections together) +# -Map: generate a map file + +LDFLAG_COMMON += -u wups_load -u wups_meta -u wups_hooks -T $(WUPSDIR)/wups.ld \ + -Wl,-Map,$(notdir $@).map,-wrap,malloc,-wrap,free,-wrap,memalign,-wrap,calloc,-wrap,realloc,-wrap,malloc_usable_size,-wrap,_malloc_r,-wrap,_free_r,-wrap,_realloc_r,-wrap,_calloc_r,-wrap,_memalign_r,-wrap,_malloc_usable_size_r,--gc-sections + +LDFLAGS_MOD += $(LDFLAG_COMMON),--relocatable +LDFLAGS_ELF += --relocatable -s -T $(WUPSDIR)/wups_elf.ld + +#--------------------------------------------------------------------------------- +Q := @ +MAKEFLAGS += --no-print-directory +#--------------------------------------------------------------------------------- +# any extra libraries we wish to link with the project +#--------------------------------------------------------------------------------- +LIBS := -lutils -ldynamiclibs +# + +#--------------------------------------------------------------------------------- +# list of directories containing libraries, this must be the top level containing +# include and lib +#--------------------------------------------------------------------------------- +LIBDIRS := $(DEVKITPPC) + +#--------------------------------------------------------------------------------- +# 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 PROJECTDIR := $(CURDIR) +export OUTPUT := $(CURDIR)/$(TARGETDIR)/$(TARGET) +export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \ + $(foreach dir,$(DATA),$(CURDIR)/$(dir)) +export DEPSDIR := $(CURDIR)/$(BUILD) + +#--------------------------------------------------------------------------------- +# automatically build a list of object files for our project +#--------------------------------------------------------------------------------- +CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) +CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) +sFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) +SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.S))) +BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) +TTFFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.ttf))) +PNGFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.png))) + +#--------------------------------------------------------------------------------- +# use CXX for linking C++ projects, CC for standard C +#--------------------------------------------------------------------------------- +ifeq ($(strip $(CPPFILES)),) + export LD_MOD := $(CC) +else + export LD_MOD := $(CXX) +endif + +export OFILES := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) \ + $(sFILES:.s=.o) $(SFILES:.S=.o) \ + $(PNGFILES:.png=.png.o) $(addsuffix .o,$(BINFILES)) + +#--------------------------------------------------------------------------------- +# build a list of include paths +#--------------------------------------------------------------------------------- +export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \ + $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ + -I$(CURDIR)/$(BUILD) -I$(PORTLIBS)/include \ + -I$(PORTLIBS)/include/libutils -I$(WUPSDIR)/include + +#--------------------------------------------------------------------------------- +# build a list of library paths +#--------------------------------------------------------------------------------- +export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) \ + -L$(PORTLIBS)/lib + +export OUTPUT := $(CURDIR)/$(TARGET) +.PHONY: $(BUILD) clean install + +#--------------------------------------------------------------------------------- +$(BUILD): + @[ -d $@ ] || mkdir -p $@ + @$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile + +#--------------------------------------------------------------------------------- +clean: + @echo clean ... + @rm -fr $(BUILD) $(OUTPUT).elf $(OUTPUT).bin $(BUILD_DBG).elf $(OUTPUT) + +#--------------------------------------------------------------------------------- +else + +DEPENDS := $(OFILES:.o=.d) + +THIS_DIR := $(dir $(abspath $(lastword $(MAKEFILE_LIST)))) + +############################################################################### +# Rule to make everything. +PHONY += all + +all : $(OUTPUT) +############################################################################### +# Special build rules + +# Rule to make the module file. +$(OUTPUT) : output.elf + @echo "checking for missing symbols ..." + @$(LD_MOD) ../$(BUILD)/output.elf $(LDFLAG_COMMON) $(LIBS) $(LIBPATHS) -o check_linking.elf + @echo "linking ..." $@ + @$(LD_MOD) ../$(BUILD)/output.elf $(LDFLAGS_MOD) $(LIBS) $(LIBPATHS) -o $@ + +# Rule to make the module file. +output.elf : $(OFILES) + @echo "linking ... output.elf" + + + @$(LD) $(OFILES) $(LDFLAGS_ELF) $(LIBS) $(LIBPATHS) -o $@ + +############################################################################### +# Standard build rules +#--------------------------------------------------------------------------------- +%.a: +#--------------------------------------------------------------------------------- + @echo $(notdir $@) + @rm -f $@ + @$(AR) -rc $@ $^ + +#--------------------------------------------------------------------------------- +%.o: %.cpp + @echo $(notdir $<) + @$(CXX) -MMD -MP -MF $(DEPSDIR)/$*.d $(CXXFLAGS) $(INCLUDE) -c $< -o $@ $(ERROR_FILTER) + +#--------------------------------------------------------------------------------- +%.o: %.c + @echo $(notdir $<) + @$(CC) -MMD -MP -MF $(DEPSDIR)/$*.d $(CFLAGS) $(INCLUDE) -c $< -o $@ $(ERROR_FILTER) + +#--------------------------------------------------------------------------------- +%.o: %.S + @echo $(notdir $<) + @$(CC) -MMD -MP -MF $(DEPSDIR)/$*.d -x assembler-with-cpp $(ASFLAGS) -c $< -o $@ $(ERROR_FILTER) + +#--------------------------------------------------------------------------------- +%.png.o : %.png + @echo $(notdir $<) + @bin2s -a 32 $< | $(AS) -o $(@) + +#--------------------------------------------------------------------------------- +%.jpg.o : %.jpg + @echo $(notdir $<) + @bin2s -a 32 $< | $(AS) -o $(@) + +#--------------------------------------------------------------------------------- +%.ttf.o : %.ttf + @echo $(notdir $<) + @bin2s -a 32 $< | $(AS) -o $(@) + +#--------------------------------------------------------------------------------- +%.bin.o : %.bin + @echo $(notdir $<) + @bin2s -a 32 $< | $(AS) -o $(@) + +#--------------------------------------------------------------------------------- +%.wav.o : %.wav + @echo $(notdir $<) + @bin2s -a 32 $< | $(AS) -o $(@) + +#--------------------------------------------------------------------------------- +%.mp3.o : %.mp3 + @echo $(notdir $<) + @bin2s -a 32 $< | $(AS) -o $(@) + +#--------------------------------------------------------------------------------- +%.ogg.o : %.ogg + @echo $(notdir $<) + @bin2s -a 32 $< | $(AS) -o $(@) + +############################################################################### +# Assembly listing rules + +# Rule to make assembly listing. +PHONY += list +list : $(LIST) + +# Rule to make the listing file. +%.list : $(TARGET) + $(LOG) + -$Qmkdir -p $(dir $@) + $Q$(OBJDUMP) -d $< > $@ + +############################################################################### +# Clean rule + +# Rule to clean files. +PHONY += clean +clean : + $Qrm -rf $(wildcard $(BUILD) $(BIN)) + +############################################################################### +# Phony targets + +.PHONY : $(PHONY) + +-include $(DEPENDS) + +#--------------------------------------------------------------------------------- +endif +#--------------------------------------------------------------------------------- diff --git a/plugins/sdcafiine/sdcafiine.cbp b/plugins/sdcafiine/sdcafiine.cbp new file mode 100644 index 0000000..4d75b71 --- /dev/null +++ b/plugins/sdcafiine/sdcafiine.cbp @@ -0,0 +1,37 @@ + + + + + + diff --git a/plugins/sdcafiine/src/common/common.h b/plugins/sdcafiine/src/common/common.h new file mode 100644 index 0000000..797bc66 --- /dev/null +++ b/plugins/sdcafiine/src/common/common.h @@ -0,0 +1,59 @@ +#ifndef COMMON_H +#define COMMON_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#define CAFE_OS_SD_PATH "/vol/external01" +#define GAME_MOD_FOLDER "/sdcafiine" +#define SD_PATH "sd:" +#define USB_PATH "usb:" +#define DEFAULT_NAME_PACKAGE "DEFAULT" +#define NAME_PREFIX_SD "sd: " +#define NAME_PREFIX_USB "usb:" +#define WIIU_PATH "/wiiu" +#define IP_TXT "ip.txt" + +#define CONTENT_FOLDER "content" +#define AOC_FOLDER "aoc" +#define META_FOLDER "meta" + +#define BOOT_TV_TEX_TGA "bootTvTex.tga" +#define BOOT_DRC_TEX_TGA "bootDrcTex.tga" +#define BOOT_SOUND_BTSND "bootSound.btsnd" + +#define GAME_PATH_TYPE_CONTENT 1 +#define GAME_PATH_TYPE_AOC 2 +#define GAME_PATH_TYPE_STRIPPED_CONTENT 3 + +#define SDUSB_MOUNTED_NONE 0 +#define SDUSB_MOUNTED_FAKE (1<<0) +#define SDUSB_MOUNTED_OS_SD (1<<1) +#define SDUSB_LIBIOSU_LOADED (1<<2) +#define SD_MOUNTED_LIBFAT (1<<3) +#define USB_MOUNTED_LIBFAT (1<<4) +#define USB_MOUNTED_LIBNTFS (1<<5) + +#define FILELIST_NAME "filelist.txt" +#define DIR_IDENTIFY "?" /* maximum length = 1*/ +#define PARENT_DIR_IDENTIFY "?.." + +#define ELF_DATA_ADDR (*(volatile unsigned int*)(MEM_BASE + 0x1300 + 0x00)) +#define ELF_DATA_SIZE (*(volatile unsigned int*)(MEM_BASE + 0x1300 + 0x04)) +#define MAIN_ENTRY_ADDR (*(volatile unsigned int*)(MEM_BASE + 0x1400 + 0x00)) + +#ifndef EXIT_SUCCESS +#define EXIT_SUCCESS 0 +#endif +#define EXIT_HBL_EXIT 0xFFFFFFFE +#define EXIT_RELAUNCH_ON_LOAD 0xFFFFFFFD + +#ifdef __cplusplus +} +#endif + +#endif /* COMMON_H */ + diff --git a/plugins/sdcafiine/src/common/retain_vars.cpp b/plugins/sdcafiine/src/common/retain_vars.cpp new file mode 100644 index 0000000..1851dd6 --- /dev/null +++ b/plugins/sdcafiine/src/common/retain_vars.cpp @@ -0,0 +1,14 @@ +#include "retain_vars.h" + +u8 gUsingLibIOSUHAX __attribute__((section(".data"))) = 0; +u8 gAppStatus __attribute__((section(".data"))) = 0; +volatile u8 gSDInitDone __attribute__((section(".data"))) = 0; + +char gModFolder[FS_MAX_ENTNAME_SIZE] __attribute__((section(".data"))); +//char gLastMetaPath[FS_MAX_ENTNAME_SIZE] __attribute__((section(".data"))); + +void * ntfs_mounts __attribute__((section(".data"))) = NULL; +int ntfs_mount_count __attribute__((section(".data"))) = 0; + +vc_vector* g_dirhandles = NULL; +vc_vector* g_filehandles = NULL; diff --git a/plugins/sdcafiine/src/common/retain_vars.h b/plugins/sdcafiine/src/common/retain_vars.h new file mode 100644 index 0000000..c5c59fb --- /dev/null +++ b/plugins/sdcafiine/src/common/retain_vars.h @@ -0,0 +1,23 @@ +#ifndef RETAINS_VARS_H_ +#define RETAINS_VARS_H_ +#include +#include +#include "utils/vc_vector.h" + +#define ASYNC_RESULT_CACHE_SIZE 50 +#define FS_QUEUE_MESSAGE_COUNT 5 + +extern u8 gUsingLibIOSUHAX; +extern u8 gAppStatus; +extern volatile u8 gSDInitDone; + +extern char gModFolder[FS_MAX_ENTNAME_SIZE]; +//extern char gLastMetaPath[FS_MAX_ENTNAME_SIZE]; + +extern void * ntfs_mounts; +extern int ntfs_mount_count; + +extern vc_vector* g_dirhandles; +extern vc_vector* g_filehandles; + +#endif // RETAINS_VARS_H_ diff --git a/plugins/sdcafiine/src/fs_wrapper/FileReplacerUtils.cpp b/plugins/sdcafiine/src/fs_wrapper/FileReplacerUtils.cpp new file mode 100644 index 0000000..1ff4d61 --- /dev/null +++ b/plugins/sdcafiine/src/fs_wrapper/FileReplacerUtils.cpp @@ -0,0 +1,98 @@ +/**************************************************************************** + * Copyright (C) 2017 Maschell + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + ****************************************************************************/ +#include "FileReplacerUtils.h" +#include "fs_async_wrapper.h" +#include "common/retain_vars.h" + +OSMessageQueue lfFSQueue __attribute__((section(".data"))); +OSMessage lfFSQueueMessages[FS_QUEUE_MESSAGE_COUNT] __attribute__((section(".data"))); + +FSAsyncResult lfAsyncResultCache[ASYNC_RESULT_CACHE_SIZE] __attribute__((section(".data"))); +u8 lfAsyncResultCacheLock __attribute__((section(".data"))) = 0; +u8 lfAsyncResultCacheCur __attribute__((section(".data"))) = 0; + +int setErrorFlag(int error){ + int result = error; + if(error == -1){ + result = CHECKED_WITH_ALL_ERRORS; + }else{ + result |= CHECKED_MASK; + } + return result; +} + +int checkErrorFlag(int * error){ + if(*error == CHECKED_WITH_ALL_ERRORS){ + *error = -1; + return true; + }else if ((*error & CHECKED_MASK) == CHECKED_MASK){ + *error &= ~CHECKED_MASK; + return true; + } + return false; +} + + +void addFileHandleInternal(int handle){ + vc_vector_push_back(g_filehandles, &handle); +} + +void removeFileHandleInternal(int handle){ + int index = 0; + for (void* i = vc_vector_begin(g_filehandles);i != vc_vector_end(g_filehandles); i = vc_vector_next(g_filehandles, i)) { + int val = *(int*)i; + if(val == handle){ + vc_vector_erase(g_filehandles,index); + return; + } + index++; + } +} + +bool hasFileHandleInternal(int handle){ + for (void* i = vc_vector_begin(g_filehandles);i != vc_vector_end(g_filehandles); i = vc_vector_next(g_filehandles, i)) { + if(*(int*)i == handle){ + return true; + } + } + return false; +} + +void addDirHandleInternal(int handle){ + vc_vector_push_back(g_dirhandles, &handle); +} + +void removeDirHandleInternal(int handle){ + int index = 0; + for (void* i = vc_vector_begin(g_dirhandles);i != vc_vector_end(g_dirhandles); i = vc_vector_next(g_dirhandles, i)) { + int val = *(int*)i; + if(val == handle){ + vc_vector_erase(g_dirhandles,index); + return; + } + index++; + } +} + +bool hasDirHandleInternal(int handle){ + for (void* i = vc_vector_begin(g_dirhandles);i != vc_vector_end(g_dirhandles); i = vc_vector_next(g_dirhandles, i)) { + if(*(int*)i == handle){ + return true; + } + } + return false; +} diff --git a/plugins/sdcafiine/src/fs_wrapper/FileReplacerUtils.h b/plugins/sdcafiine/src/fs_wrapper/FileReplacerUtils.h new file mode 100644 index 0000000..89d1c4f --- /dev/null +++ b/plugins/sdcafiine/src/fs_wrapper/FileReplacerUtils.h @@ -0,0 +1,64 @@ +/**************************************************************************** + * Copyright (C) 2017 Maschell + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + ****************************************************************************/ + +#ifndef __FILE_REPLACER_UTILS_H_ +#define __FILE_REPLACER_UTILS_H_ + +#include +#include +#include +#include "utils/vc_vector.h" + +#include "fs_retain_vars.h" + +#define CHECKED_WITH_ALL_ERRORS 0x10000 +#define CHECKED_MASK 0x01000 + +#define FS_WRAPPER_DEBUG_LOG 0 + +#define USE_OS_FS_FUNCTION -1337 + + +/** +Returns a modified error flag. +This will be used to save the information if a file/handle was already +tried to be patched. +The non-async function internally call the async functions, and this way +we avoid testing it twice. +If the result contains our mask, we just straight to the OS functions. +**/ +int setErrorFlag(int error); + +/** +Check if we already checked the file/handle. +Returns true if it was already checked (+ revert the error) +Return false if it should be (tried) to be patched. +**/ +int checkErrorFlag(int * error); + +void addFileHandleInternal(int handle); + +void removeFileHandleInternal(int handle); + +bool hasFileHandleInternal(int handle); + +void addDirHandleInternal(int handle); + +void removeDirHandleInternal(int handle); + +bool hasDirHandleInternal(int handle); +#endif // __FILE_REPLACER_UTILS_H_ diff --git a/plugins/sdcafiine/src/fs_wrapper/fs_async_wrapper.cpp b/plugins/sdcafiine/src/fs_wrapper/fs_async_wrapper.cpp new file mode 100644 index 0000000..c431dfd --- /dev/null +++ b/plugins/sdcafiine/src/fs_wrapper/fs_async_wrapper.cpp @@ -0,0 +1,217 @@ +/**************************************************************************** + * Copyright (C) 2017 Maschell + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + ****************************************************************************/ + +#include +#include +#include +#include +#include + +#include "fs_async_wrapper.h" + +//Wii U fails to allocate memory if we do the functions async. =/ +#define DO_REAL_ASYNC 0 + +static int doFallback(CustomAsyncParamWrapper params){ + if(params.fallbackFunction != NULL){ + if(FS_WRAPPER_DEBUG_LOG){ DEBUG_FUNCTION_LINE("Calling the fallback function %08X\n",params.fallbackFunction); } + return ((FSAsyncFallback)params.fallbackFunction)(params.fallbackParams); + } + + if(params.params.needToFreePath){ + free((void*)params.params.params.path); + } + + DEBUG_FUNCTION_LINE("No fallback function provided\n"); + //OSFatal("No fallback given."); //We don't need to free stuff, because we'll (want to) crash anyway. + + return FS_STATUS_FATAL_ERROR; +} + +static int sendAsyncResult(CustomAsyncParamWrapper in, int result){ + //FileReplacerUtils::sendAsyncCommand(in.params.params.pClient, in.params.params.pCmd, in.params.params.asyncParams, result); + + if(in.params.needToFreePath){ + free((void*)in.params.params.path); + } + + return FS_STATUS_OK; +} + +static int fs_wrapper_async_template(CustomAsyncParam params,FSAsyncCustomCallback callback, FSAsyncFallback fallback, void * fallbackParams){ + if(FS_WRAPPER_DEBUG_LOG){ DEBUG_FUNCTION_LINE("Called!\n"); } + + CustomAsyncParamWrapper wrapper; + memset(&wrapper,0,sizeof(CustomAsyncParamWrapper)); + + wrapper.params = params; + + wrapper.fallbackFunction = fallback; + wrapper.fallbackParams = (void*)fallbackParams; + + if(!DO_REAL_ASYNC){ + return callback(wrapper); + } + + //TODO:! + + /*OSMessage message; + message.message = (u32) callback; + message.data0 = (u32) &wrapper; + + + //FileReplacerUtils::addFSQueueMSG(&message);*/ + + return FS_STATUS_OK; +} + +int fs_wrapper_FSCloseFileAsyncCallback(CustomAsyncParamWrapper params){ + if(FS_WRAPPER_DEBUG_LOG){ DEBUG_FUNCTION_LINE("Called! params: %08X \n",params); } + //if(params == NULL){ DEBUG_FUNCTION_LINE("!!!WARNING: Given parameter was NULL\n"); } + + OSAsyncParamWrapper * p = &(params.params.params); + + int result = USE_OS_FS_FUNCTION; + if((result = fs_wrapper_FSCloseFile(p->handle)) != USE_OS_FS_FUNCTION){ + return sendAsyncResult(params,result); + } + + return doFallback(params); +} + +int fs_wrapper_FSGetPosFileAsyncCallback(CustomAsyncParamWrapper params){ + if(FS_WRAPPER_DEBUG_LOG){ DEBUG_FUNCTION_LINE("Called! params: %08X \n",params); } + //if(params == NULL){ DEBUG_FUNCTION_LINE("!!!WARNING: Given parameter was NULL\n"); } + + OSAsyncParamWrapper * p = &(params.params.params); + + int result = USE_OS_FS_FUNCTION; + if((result = fs_wrapper_FSGetPosFile(p->handle,p->posPtr)) != USE_OS_FS_FUNCTION){ + return sendAsyncResult(params,result); + } + + return doFallback(params); +} + +int fs_wrapper_FSGetStatAsyncCallback(CustomAsyncParamWrapper params){ + if(FS_WRAPPER_DEBUG_LOG){ DEBUG_FUNCTION_LINE("Called! params: %08X \n",params); } + //if(params == NULL){ DEBUG_FUNCTION_LINE("!!!WARNING: Given parameter was NULL\n"); } + + OSAsyncParamWrapper * p = &(params.params.params); + + int result = USE_OS_FS_FUNCTION; + if((result = fs_wrapper_FSGetStat(p->path,p->stats)) != USE_OS_FS_FUNCTION){ + return sendAsyncResult(params,result); + } + + return doFallback(params); +} + +int fs_wrapper_FSGetStatFileAsyncCallback(CustomAsyncParamWrapper params){ + if(FS_WRAPPER_DEBUG_LOG){ DEBUG_FUNCTION_LINE("Called! params: %08X \n",params); } + //if(params == NULL){ DEBUG_FUNCTION_LINE("!!!WARNING: Given parameter was NULL\n"); } + + OSAsyncParamWrapper * p = &(params.params.params); + + int result = USE_OS_FS_FUNCTION; + if((result = fs_wrapper_FSGetStatFile(p->handle,p->stats)) != USE_OS_FS_FUNCTION){ + return sendAsyncResult(params,result); + } + + return doFallback(params); +} + +int fs_wrapper_FSIsEofAsyncCallback(CustomAsyncParamWrapper params){ + if(FS_WRAPPER_DEBUG_LOG){ DEBUG_FUNCTION_LINE("Called! params: %08X \n",params); } + //if(params == NULL){ DEBUG_FUNCTION_LINE("!!!WARNING: Given parameter was NULL\n"); } + + OSAsyncParamWrapper * p = &(params.params.params); + + int result = USE_OS_FS_FUNCTION; + if((result = fs_wrapper_FSIsEof(p->handle)) != USE_OS_FS_FUNCTION){ + return sendAsyncResult(params,result); + } + + return doFallback(params); +} + +int fs_wrapper_FSOpenFileAsyncCallback(CustomAsyncParamWrapper params){ + if(FS_WRAPPER_DEBUG_LOG){ DEBUG_FUNCTION_LINE("Called! params: %08X \n",params); } + //if(params == NULL){ DEBUG_FUNCTION_LINE("!!!WARNING: Given parameter was NULL\n"); } + + OSAsyncParamWrapper * p = &(params.params.params); + + int result = USE_OS_FS_FUNCTION; + if((result = fs_wrapper_FSOpenFile(p->path,p->mode,p->handlePtr)) != USE_OS_FS_FUNCTION){ + return sendAsyncResult(params,result); + } + + return doFallback(params); +} + +int fs_wrapper_FSReadFileAsyncCallback(CustomAsyncParamWrapper params){ + if(FS_WRAPPER_DEBUG_LOG){ DEBUG_FUNCTION_LINE("Called! params: %08X \n",params); } + //if(params == NULL){ DEBUG_FUNCTION_LINE("!!!WARNING: Given parameter was NULL\n"); } + + OSAsyncParamWrapper * p = &(params.params.params); + + int result = USE_OS_FS_FUNCTION; + if((result = fs_wrapper_FSReadFile(p->handle,p->buffer,p->size,p->count)) != USE_OS_FS_FUNCTION){ + return sendAsyncResult(params,result); + } + + return doFallback(params); +} + +int fs_wrapper_FSReadFileWithPosAsyncCallback(CustomAsyncParamWrapper params){ + if(FS_WRAPPER_DEBUG_LOG){ DEBUG_FUNCTION_LINE("Called! params: %08X \n",params); } + //if(params == NULL){ DEBUG_FUNCTION_LINE("!!!WARNING: Given parameter was NULL\n"); } + + OSAsyncParamWrapper * p = &(params.params.params); + + int result = USE_OS_FS_FUNCTION; + if((result = fs_wrapper_FSReadFileWithPos(p->buffer,p->size,p->count,p->pos,p->handle)) != USE_OS_FS_FUNCTION){ + return sendAsyncResult(params,result); + } + + return doFallback(params); +} + +int fs_wrapper_FSSetPosFileAsyncCallback(CustomAsyncParamWrapper params){ + if(FS_WRAPPER_DEBUG_LOG){ DEBUG_FUNCTION_LINE("Called! params: %08X \n",params); } + //if(params == NULL){ DEBUG_FUNCTION_LINE("!!!WARNING: Given parameter was NULL\n"); } + + OSAsyncParamWrapper * p = &(params.params.params); + + int result = USE_OS_FS_FUNCTION; + if((result = fs_wrapper_FSSetPosFile(p->handle,p->pos)) != USE_OS_FS_FUNCTION){ + return sendAsyncResult(params,result); + } + + return doFallback(params); +} + +DEFINE_FS_WRAPPER(FSCloseFileAsync) +DEFINE_FS_WRAPPER(FSGetStatAsync) +DEFINE_FS_WRAPPER(FSGetStatFileAsync) +DEFINE_FS_WRAPPER(FSGetPosFileAsync) +DEFINE_FS_WRAPPER(FSIsEofAsync) +DEFINE_FS_WRAPPER(FSOpenFileAsync) +DEFINE_FS_WRAPPER(FSReadFileAsync) +DEFINE_FS_WRAPPER(FSReadFileWithPosAsync) +DEFINE_FS_WRAPPER(FSSetPosFileAsync) + diff --git a/plugins/sdcafiine/src/fs_wrapper/fs_async_wrapper.h b/plugins/sdcafiine/src/fs_wrapper/fs_async_wrapper.h new file mode 100644 index 0000000..21d6a09 --- /dev/null +++ b/plugins/sdcafiine/src/fs_wrapper/fs_async_wrapper.h @@ -0,0 +1,124 @@ +/**************************************************************************** + * Copyright (C) 2017 Maschell + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + ****************************************************************************/ + +#ifndef __FS_ASYNC_WRAPPER_H_ +#define __FS_ASYNC_WRAPPER_H_ + +#include "FileReplacerUtils.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + +#include "fs_sync_wrapper.h" + +typedef int (*FSAsyncFallback)(void * params); + +typedef struct OSAsyncParamWrapper_{ + FSClient *pClient; + FSCmdBlock *pCmd; + const char *path; + const char *mode; + FSStat * stats; + void * buffer; + int handle; + int size; + int count; + int pos; + int flag; + int *handlePtr; + int *posPtr; + int error; + FSAsyncParams * asyncParams; +} OSAsyncParamWrapper; + +typedef struct FallbackParamWrapper_{ + OSAsyncParamWrapper params; + void * realFunctionAddress; +} FallbackParamWrapper; + +typedef struct CustomAsyncParam_{ + OSAsyncParamWrapper params; + bool needToFreePath; +} CustomAsyncParam; + +typedef struct CustomAsyncParamWrapper_{ + CustomAsyncParam params; + FSAsyncFallback fallbackFunction; + void * fallbackParams; +} CustomAsyncParamWrapper; + +typedef int (*FSAsyncCustomCallback)(CustomAsyncParamWrapper params); + + +#define DEFINE_FS_WRAPPER(name) \ + int fs_wrapper_##name##Ex(CustomAsyncParam params, FSAsyncFallback fallback, void * fallbackParams){\ + return fs_wrapper_async_template(params,fs_wrapper_##name##Callback,fallback,fallbackParams);\ + }\ + int fs_wrapper_##name(CustomAsyncParam params){ \ + return fs_wrapper_##name##Ex(params,NULL,NULL);\ + } + +#define DECLARE_FS_WRAPPER(name) \ + int fs_wrapper_##name##Ex(CustomAsyncParam params, FSAsyncFallback fallback, void * fallbackParams);\ + int fs_wrapper_##name(CustomAsyncParam params); + + int fs_wrapper_FSCloseFileAsync(CustomAsyncParam params); + + int fs_wrapper_FSCloseFileAsyncEx(CustomAsyncParam params, FSAsyncFallback fallback, void * fallbackParams); + + int fs_wrapper_FSGetStatAsync(CustomAsyncParam params); + + int fs_wrapper_FSGetStatAsyncEx(CustomAsyncParam params, FSAsyncFallback fallback, void * fallbackParams); + + int fs_wrapper_FSGetStatFileAsync(CustomAsyncParam params); + + int fs_wrapper_FSGetStatFileAsyncEx(CustomAsyncParam params, FSAsyncFallback fallback, void * fallbackParams); + + int fs_wrapper_FSGetPosFileAsync(CustomAsyncParam params); + + int fs_wrapper_FSGetPosFileAsyncEx(CustomAsyncParam params, FSAsyncFallback fallback, void * fallbackParams); + + int fs_wrapper_FSIsEofAsync(CustomAsyncParam params); + + int fs_wrapper_FSIsEofAsyncEx(CustomAsyncParam params, FSAsyncFallback fallback, void * fallbackParams); + + int fs_wrapper_FSOpenFileAsync(CustomAsyncParam params); + + int fs_wrapper_FSOpenFileAsyncEx(CustomAsyncParam params, FSAsyncFallback fallback, void * fallbackParams); + + int fs_wrapper_FSReadFileAsync(CustomAsyncParam params); + + int fs_wrapper_FSReadFileAsyncEx(CustomAsyncParam params, FSAsyncFallback fallback, void * fallbackParams); + + int fs_wrapper_FSReadFileWithPosAsync(CustomAsyncParam params); + + int fs_wrapper_FSReadFileWithPosAsyncEx(CustomAsyncParam params, FSAsyncFallback fallback, void * fallbackParams); + + int fs_wrapper_FSSetPosFileAsync(CustomAsyncParam params); + + int fs_wrapper_FSSetPosFileAsyncEx(CustomAsyncParam params, FSAsyncFallback fallback, void * fallbackParams); + +#ifdef __cplusplus +} +#endif + +#endif // __FS_ASYNC_WRAPPER_H_ diff --git a/plugins/sdcafiine/src/fs_wrapper/fs_default_os_wrapper.cpp b/plugins/sdcafiine/src/fs_wrapper/fs_default_os_wrapper.cpp new file mode 100644 index 0000000..b7a5461 --- /dev/null +++ b/plugins/sdcafiine/src/fs_wrapper/fs_default_os_wrapper.cpp @@ -0,0 +1,220 @@ +/**************************************************************************** + * Copyright (C) 2017 Maschell + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + ****************************************************************************/ + +#include + +#include "fs_default_os_wrapper.h" + +int fs_default_os_wrapper_FSCloseFileAsync(FSClient *pClient, FSCmdBlock *pCmd, int fd, int error, FSAsyncParams * asyncParams, void * realAddress){ + FallbackParamWrapper paramWrapper; + memset(¶mWrapper,0,sizeof(FallbackParamWrapper)); + + CustomAsyncParam params; + memset(¶ms,0,sizeof(CustomAsyncParam)); + + paramWrapper.params.pClient = pClient; + paramWrapper.params.pCmd = pCmd; + paramWrapper.params.handle = fd; + paramWrapper.params.error = error; + paramWrapper.params.asyncParams = asyncParams; + + paramWrapper.realFunctionAddress = (void*) realAddress; + + params.params = paramWrapper.params; + + return fs_wrapper_FSCloseFileAsyncEx(params,&fallbackFSCloseFileAsync,¶mWrapper); +} + +int fs_default_os_wrapper_FSGetPosFileAsync(FSClient *pClient, FSCmdBlock *pCmd, int fd, int *pos, int error, FSAsyncParams * asyncParams, void * realAddress){ + FallbackParamWrapper paramWrapper; + memset(¶mWrapper,0,sizeof(FallbackParamWrapper)); + + CustomAsyncParam params; + memset(¶ms,0,sizeof(CustomAsyncParam)); + + paramWrapper.params.pClient = pClient; + paramWrapper.params.pCmd = pCmd; + paramWrapper.params.handle = fd; + paramWrapper.params.posPtr = pos; + paramWrapper.params.error = error; + paramWrapper.params.asyncParams = asyncParams; + + paramWrapper.realFunctionAddress = (void*) realAddress; + + params.params = paramWrapper.params; + + return fs_wrapper_FSGetPosFileAsyncEx(params,fallbackFSGetPosFileAsync,¶mWrapper); +} + +int fs_default_os_wrapper_FSGetStatAsync(const char *libPath, FSClient *pClient, FSCmdBlock *pCmd, const char *path, FSStat *stats, int error, FSAsyncParams * asyncParams, void * realAddress){ + FallbackParamWrapper paramWrapper; + memset(¶mWrapper,0,sizeof(FallbackParamWrapper)); + + CustomAsyncParam params; + memset(¶ms,0,sizeof(CustomAsyncParam)); + + paramWrapper.params.pClient = pClient; + paramWrapper.params.pCmd = pCmd; + paramWrapper.params.path = (char*)path; + paramWrapper.params.stats = stats; + paramWrapper.params.error = error; + paramWrapper.params.asyncParams = asyncParams; + + paramWrapper.realFunctionAddress = (void*) realAddress; + + params.params = paramWrapper.params; + params.params.path = libPath; // Use modified path. + params.needToFreePath = 1; + + return fs_wrapper_FSGetPosFileAsyncEx(params,fallbackFSGetStatAsync,¶mWrapper); +} + +int fs_default_os_wrapper_FSGetStatFileAsync(FSClient *pClient, FSCmdBlock *pCmd, int fd, FSStat * stats, int error, FSAsyncParams * asyncParams, void * realAddress){ + FallbackParamWrapper paramWrapper; + memset(¶mWrapper,0,sizeof(FallbackParamWrapper)); + + CustomAsyncParam params; + memset(¶ms,0,sizeof(CustomAsyncParam)); + + paramWrapper.params.pClient = pClient; + paramWrapper.params.pCmd = pCmd; + paramWrapper.params.handle = fd; + paramWrapper.params.stats = stats; + paramWrapper.params.error = error; + paramWrapper.params.asyncParams = asyncParams; + + paramWrapper.realFunctionAddress = (void*) realAddress; + + params.params = paramWrapper.params; + + return fs_wrapper_FSGetStatFileAsyncEx(params,fallbackFSGetStatFileAsync,¶mWrapper); +} + +int fs_default_os_wrapper_FSIsEofAsync(FSClient *pClient, FSCmdBlock *pCmd, int fd, int error, FSAsyncParams * asyncParams, void * realAddress){ + FallbackParamWrapper paramWrapper; + memset(¶mWrapper,0,sizeof(FallbackParamWrapper)); + + CustomAsyncParam params; + memset(¶ms,0,sizeof(CustomAsyncParam)); + + paramWrapper.params.pClient = pClient; + paramWrapper.params.pCmd = pCmd; + paramWrapper.params.handle = fd; + paramWrapper.params.error = error; + paramWrapper.params.asyncParams = asyncParams; + + paramWrapper.realFunctionAddress = (void*) realAddress; + + params.params = paramWrapper.params; + + return fs_wrapper_FSIsEofAsyncEx(params,fallbackFSIsEofAsync,¶mWrapper); +} + +int fs_default_os_wrapper_FSOpenFileAsync(const char *libpath, FSClient *pClient, FSCmdBlock *pCmd, const char *path, const char *mode, int *handle, int error, FSAsyncParams *asyncParams, void * realAddress){ + + FallbackParamWrapper paramWrapper; + memset(¶mWrapper,0,sizeof(FallbackParamWrapper)); + + CustomAsyncParam params; + memset(¶ms,0,sizeof(CustomAsyncParam)); + + paramWrapper.params.pClient = pClient; + paramWrapper.params.pCmd = pCmd; + paramWrapper.params.path = path; + paramWrapper.params.mode = mode; + paramWrapper.params.handlePtr = handle; + paramWrapper.params.error = error; + paramWrapper.params.asyncParams = asyncParams; + + paramWrapper.realFunctionAddress = (void*) realAddress; + + params.params = paramWrapper.params; + params.params.path = libpath; // Use modified path. + params.needToFreePath = 1; + + return fs_wrapper_FSOpenFileAsyncEx(params,fallbackFSOpenFileAsync,¶mWrapper); +} + +int fs_default_os_wrapper_FSReadFileAsync(FSClient *pClient, FSCmdBlock *pCmd, void *buffer, int size, int count, int fd, int flag, int error, FSAsyncParams *asyncParams, void * realAddress){ + FallbackParamWrapper paramWrapper; + memset(¶mWrapper,0,sizeof(FallbackParamWrapper)); + + CustomAsyncParam params; + memset(¶ms,0,sizeof(CustomAsyncParam)); + + paramWrapper.params.pClient = pClient; + paramWrapper.params.pCmd = pCmd; + paramWrapper.params.buffer = buffer; + paramWrapper.params.size = size; + paramWrapper.params.count = count; + paramWrapper.params.handle = fd; + paramWrapper.params.flag = flag; + paramWrapper.params.error = error; + paramWrapper.params.asyncParams = asyncParams; + + paramWrapper.realFunctionAddress = (void*) realAddress; + + params.params = paramWrapper.params; + + return fs_wrapper_FSReadFileAsyncEx(params,fallbackFSReadFileAsync,¶mWrapper); +} + +int fs_default_os_wrapper_FSReadFileWithPosAsync(FSClient *pClient, FSCmdBlock *pCmd, void *buffer, int size, int count, u32 pos, int fd, int flag, int error, FSAsyncParams *asyncParams, void * realAddress){ + FallbackParamWrapper paramWrapper; + memset(¶mWrapper,0,sizeof(FallbackParamWrapper)); + + CustomAsyncParam params; + memset(¶ms,0,sizeof(CustomAsyncParam)); + + paramWrapper.params.pClient = pClient; + paramWrapper.params.pCmd = pCmd; + paramWrapper.params.buffer = buffer; + paramWrapper.params.size = size; + paramWrapper.params.count = count; + paramWrapper.params.pos = pos; + paramWrapper.params.handle = fd; + paramWrapper.params.flag = flag; + paramWrapper.params.error = error; + paramWrapper.params.asyncParams = asyncParams; + + paramWrapper.realFunctionAddress = (void*) realAddress; + + params.params = paramWrapper.params; + + return fs_wrapper_FSReadFileWithPosAsyncEx(params,fallbackFSReadFileWithPosAsync,¶mWrapper); +} + +int fs_default_os_wrapper_FSSetPosFileAsync(FSClient *pClient, FSCmdBlock *pCmd, int handle, u32 pos, int error, FSAsyncParams *asyncParams, void * realAddress){ + FallbackParamWrapper paramWrapper; + memset(¶mWrapper,0,sizeof(FallbackParamWrapper)); + + CustomAsyncParam params; + memset(¶ms,0,sizeof(CustomAsyncParam)); + + paramWrapper.params.pClient = pClient; + paramWrapper.params.pCmd = pCmd; + paramWrapper.params.handle = handle; + paramWrapper.params.pos = pos; + paramWrapper.params.error = error; + paramWrapper.params.asyncParams = asyncParams; + + paramWrapper.realFunctionAddress = (void*) realAddress; + + params.params = paramWrapper.params; + + return fs_wrapper_FSSetPosFileAsyncEx(params,fallbackFSSetPosFileAsync,¶mWrapper); +} diff --git a/plugins/sdcafiine/src/fs_wrapper/fs_default_os_wrapper.h b/plugins/sdcafiine/src/fs_wrapper/fs_default_os_wrapper.h new file mode 100644 index 0000000..3d8c4a5 --- /dev/null +++ b/plugins/sdcafiine/src/fs_wrapper/fs_default_os_wrapper.h @@ -0,0 +1,43 @@ +/**************************************************************************** + * Copyright (C) 2017 Maschell + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + ****************************************************************************/ + +#ifndef __FS_DEFAULT_OS_WRAPPER_H_ +#define __FS_DEFAULT_OS_WRAPPER_H_ + +#include "fs_async_wrapper.h" +#include "fs_sync_wrapper.h" +#include "fs_wrapper_utils.h" + +#ifdef __cplusplus +extern "C" { +#endif + +int fs_default_os_wrapper_FSCloseFileAsync(FSClient *pClient, FSCmdBlock *pCmd, int fd, int error, FSAsyncParams * asyncParams, void * realAddress); +int fs_default_os_wrapper_FSGetPosFileAsync(FSClient *pClient, FSCmdBlock *pCmd, int fd, int *pos, int error, FSAsyncParams * asyncParams, void * realAddress); +int fs_default_os_wrapper_FSGetStatAsync(const char *libpath, FSClient *pClient, FSCmdBlock *pCmd, const char *path, FSStat *stats, int error, FSAsyncParams * asyncParams, void * realAddress); +int fs_default_os_wrapper_FSGetStatFileAsync(FSClient *pClient, FSCmdBlock *pCmd, int fd, FSStat * stats, int error, FSAsyncParams * asyncParams, void * realAddress); +int fs_default_os_wrapper_FSIsEofAsync(FSClient *pClient, FSCmdBlock *pCmd, int fd, int error, FSAsyncParams * asyncParams, void * realAddress); +int fs_default_os_wrapper_FSOpenFileAsync(const char *libpath, FSClient *pClient, FSCmdBlock *pCmd, const char *path, const char *mode, int *handle, int error, FSAsyncParams *asyncParams, void * realAddress); +int fs_default_os_wrapper_FSReadFileAsync(FSClient *pClient, FSCmdBlock *pCmd, void *buffer, int size, int count, int fd, int flag, int error, FSAsyncParams *asyncParams, void * realAddress); +int fs_default_os_wrapper_FSReadFileWithPosAsync(FSClient *pClient, FSCmdBlock *pCmd, void *buffer, int size, int count, u32 pos, int fd, int flag, int error, FSAsyncParams *asyncParams, void * realAddress); +int fs_default_os_wrapper_FSSetPosFileAsync(FSClient *pClient, FSCmdBlock *pCmd, int handle, u32 pos, int error, FSAsyncParams *asyncParams, void * realAddress); + +#ifdef __cplusplus +} +#endif + +#endif // __FS_DEFAULT_OS_WRAPPER_H_ diff --git a/plugins/sdcafiine/src/fs_wrapper/fs_retain_vars.cpp b/plugins/sdcafiine/src/fs_wrapper/fs_retain_vars.cpp new file mode 100644 index 0000000..142c859 --- /dev/null +++ b/plugins/sdcafiine/src/fs_wrapper/fs_retain_vars.cpp @@ -0,0 +1,28 @@ +/**************************************************************************** + * Copyright (C) 2017 Maschell + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + ****************************************************************************/ +#include +#include "fs_retain_vars.h" + +OSMessageQueue fsFSQueue __attribute__((section(".data"))); +OSMessage fsFSQueueMessages[FS_QUEUE_MESSAGE_COUNT] __attribute__((section(".data"))); + +FSAsyncResult fsAsyncResultCache[ASYNC_RESULT_CACHE_SIZE] __attribute__((section(".data"))); +u8 fsAsyncResultCacheLock __attribute__((section(".data"))) = 0; +u8 fsAsyncResultCacheCur __attribute__((section(".data"))) = 0; + +u32 global_owner_id __attribute__((section(".data"))) = 0; +u32 global_group_id __attribute__((section(".data"))) = 0; diff --git a/plugins/sdcafiine/src/fs_wrapper/fs_retain_vars.h b/plugins/sdcafiine/src/fs_wrapper/fs_retain_vars.h new file mode 100644 index 0000000..0fe7fac --- /dev/null +++ b/plugins/sdcafiine/src/fs_wrapper/fs_retain_vars.h @@ -0,0 +1,38 @@ +/**************************************************************************** + * Copyright (C) 2017 Maschell + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + ****************************************************************************/ + +#ifndef FS_RETAINS_VARS_H_ +#define FS_RETAINS_VARS_H_ + +#include +#include + +#define ASYNC_RESULT_CACHE_SIZE 50 +#define FS_QUEUE_MESSAGE_COUNT 5 + +extern OSMessageQueue fsFSQueue __attribute__((section(".data"))); +extern OSMessage fsFSQueueMessages[FS_QUEUE_MESSAGE_COUNT] __attribute__((section(".data"))); + +extern FSAsyncResult fsAsyncResultCache[ASYNC_RESULT_CACHE_SIZE]; + +extern u8 fsAsyncResultCacheLock; +extern u8 fsAsyncResultCacheCur; + +extern u32 global_owner_id; +extern u32 global_group_id; + +#endif // FS_RETAINS_VARS_H_ diff --git a/plugins/sdcafiine/src/fs_wrapper/fs_sync_wrapper.cpp b/plugins/sdcafiine/src/fs_wrapper/fs_sync_wrapper.cpp new file mode 100644 index 0000000..3c114fe --- /dev/null +++ b/plugins/sdcafiine/src/fs_wrapper/fs_sync_wrapper.cpp @@ -0,0 +1,226 @@ +/**************************************************************************** + * Copyright (C) 2017 Maschell + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + ****************************************************************************/ + +#include +#include +#include +#include +#include + +#include "fs_sync_wrapper.h" +#include "fs_retain_vars.h" + +int fs_wrapper_FSCloseFile(int handle){ + if(FS_WRAPPER_DEBUG_LOG){ DEBUG_FUNCTION_LINE("Called! for handle: %08X \n",handle); } + if(hasFileHandleInternal(handle)){ + removeFileHandleInternal(handle); + close(handle); + DEBUG_FUNCTION_LINE("closed handle %08X\n",handle); + return FS_STATUS_OK; + } + return USE_OS_FS_FUNCTION; +} + +int fs_wrapper_FSGetPosFile(int handle,int * pos){ + if(FS_WRAPPER_DEBUG_LOG){ DEBUG_FUNCTION_LINE("Called! for handle: %08X \n",handle); } + if(hasFileHandleInternal(handle)){ + off_t currentPos = lseek(handle, (off_t)0, SEEK_CUR); + *pos = currentPos; + + DEBUG_FUNCTION_LINE("pos %08X for handle %08X\n",*pos,handle); + + return FS_STATUS_OK; + } + return USE_OS_FS_FUNCTION; +} + +void setCommonStats(FSStat * stats){ + if(stats == NULL){ + DEBUG_FUNCTION_LINE("STATS EMPTY\n"); + } + stats->permission = 0x00000400; + stats->owner_id = global_owner_id; + stats->group_id = global_group_id; + stats->flag |= 0x08000000; + stats->flag |= 0x04000000; + stats->ctime = 0x0003E8C3E677A740L; + stats->mtime = 0x0003F8AABBEAFBC0L; +} + +int fs_wrapper_FSGetStat(const char * path, FSStat * stats){ + if(FS_WRAPPER_DEBUG_LOG){ DEBUG_FUNCTION_LINE("Called!\n"); } + int result = USE_OS_FS_FUNCTION; + if(path != NULL){ + DEBUG_FUNCTION_LINE("Searching for path %s\n",path); + struct stat path_stat; + if(stat(path, &path_stat) < 0){ + result = USE_OS_FS_FUNCTION; + if(FS_WRAPPER_DEBUG_LOG){ DEBUG_FUNCTION_LINE("failed for path %s\n",path); } + }else{ + DEBUG_FUNCTION_LINE("success! path %s\n",path); + stats->flag = 0; + if(S_ISDIR(path_stat.st_mode)){ + stats->flag |= 0x80000000; + DEBUG_FUNCTION_LINE("set stats->flag: DIR\n"); + }else{ + stats->size = path_stat.st_size; + DEBUG_FUNCTION_LINE("stats->size: %08X\n",stats->size); + } + + setCommonStats(stats); + + result = FS_STATUS_OK; + } + } + return result; +} + +int fs_wrapper_FSGetStatFile(int handle, FSStat * stats){ + if(FS_WRAPPER_DEBUG_LOG){ DEBUG_FUNCTION_LINE("Called! for handle: %08X\n",handle); } + if(hasFileHandleInternal(handle)){ + struct stat path_stat; + if(fstat(handle, &path_stat) < 0){ + DEBUG_FUNCTION_LINE("failed! handle: %08X\n",handle); + return -1; + } + + stats->size = path_stat.st_size; + stats->flag = 0; + + setCommonStats(stats); + + DEBUG_FUNCTION_LINE("success! handle: %08X size: %08X\n",handle,stats->size); + + return FS_STATUS_OK; + } + return USE_OS_FS_FUNCTION; +} + +int fs_wrapper_FSIsEof(int handle){ + if(FS_WRAPPER_DEBUG_LOG){ DEBUG_FUNCTION_LINE("Called! handle: %08X\n",handle); } + int result = USE_OS_FS_FUNCTION; + if(hasFileHandleInternal(handle)){ + off_t currentPos = lseek(handle, (off_t) 0, SEEK_CUR); + off_t endPos = lseek(handle, (off_t) 0, SEEK_END); + + if(currentPos == endPos){ + result = FS_STATUS_EOF; + }else{ + lseek(handle, currentPos, SEEK_CUR); + result = FS_STATUS_OK; + } + DEBUG_FUNCTION_LINE("handle: %08X result: %08X\n",handle,result); + } + return result; +} + +int fs_wrapper_FSOpenFile(const char * path, const char * mode, int * handle){ + int result = USE_OS_FS_FUNCTION; + if(path != NULL){ + result = USE_OS_FS_FUNCTION; + DEBUG_FUNCTION_LINE("Searching for path %s\n",path); + int fd = open(path,O_RDONLY); //TODO: remove hardcoded mode. + if(fd != -1){ + DEBUG_FUNCTION_LINE("opened path: %s handle: %08X\n",path,fd); + addFileHandleInternal(fd); + *handle = fd; + result = FS_STATUS_OK; + + }else{ + if(FS_WRAPPER_DEBUG_LOG){DEBUG_FUNCTION_LINE("failed path: %s\n",path);} + } + } + + return result; +} + +#define MAXIMUM_READ_CHUNK 1024*1024 + +static int readIntoBuffer(int handle,void *buffer,size_t size, size_t count){ + int sizeToRead = size*count; + void * newBuffer = buffer; + int curResult = -1; + int totalSize = 0; + int toRead = 0; + while(sizeToRead > 0){ + if(sizeToRead < MAXIMUM_READ_CHUNK){ + toRead = sizeToRead; + }else{ + toRead = MAXIMUM_READ_CHUNK; + } + curResult = read(handle, newBuffer,toRead); + if(curResult < 0){ + DEBUG_FUNCTION_LINE("Error: Reading %08X bytes from handle %08X. result %08X \n",size*count,handle,curResult); + return -1; + } + if(curResult == 0 ){ + //EOF + break; + } + newBuffer = (void*)(((u32)newBuffer) + curResult); + totalSize += curResult; + sizeToRead -= curResult; + if(sizeToRead > 0){ + DEBUG_FUNCTION_LINE("Reading. missing %08X bytes\n",sizeToRead); + } + } + DEBUG_FUNCTION_LINE("Success: Read %08X bytes from handle %08X. result %08X \n",size*count,handle,totalSize); + return totalSize; +} + +int fs_wrapper_FSReadFile(int handle,void *buffer,size_t size, size_t count){ + if(FS_WRAPPER_DEBUG_LOG){ DEBUG_FUNCTION_LINE("Called! for handle: %08X \n",handle); } + int result = USE_OS_FS_FUNCTION; + if(hasFileHandleInternal(handle)){ + result = readIntoBuffer(handle,buffer,size,count); + } + return result; +} + +int fs_wrapper_FSReadFileWithPos(void *buffer, size_t size, size_t count, u32 pos, int handle){ + if(FS_WRAPPER_DEBUG_LOG){ DEBUG_FUNCTION_LINE("Called! \n"); } + int result = USE_OS_FS_FUNCTION; + if(hasFileHandleInternal(handle)){ + off_t newOffset = -1; + newOffset = lseek(handle, (off_t)pos, SEEK_SET); + if(newOffset == (off_t)pos){ + result = readIntoBuffer(handle, buffer,size,count); + DEBUG_FUNCTION_LINE("Reading %08X bytes from handle %08X at pos %08X. result %08X \n",size*count,handle,pos,result); + }else{ + return -1; + } + } + return result; +} + +int fs_wrapper_FSSetPosFile(int handle,u32 pos){ + if(FS_WRAPPER_DEBUG_LOG){ DEBUG_FUNCTION_LINE("Called! \n"); } + int result = USE_OS_FS_FUNCTION; + if(hasFileHandleInternal(handle)){ + off_t newOffset = -1; + result = -1; + newOffset = lseek(handle, (off_t)pos, SEEK_SET); + if(newOffset == (off_t)pos){ + result = FS_STATUS_OK; + DEBUG_FUNCTION_LINE("Set position to %08X for handle %08X\n",pos,handle); + }else{ + DEBUG_FUNCTION_LINE("Failed set position to %08X for handle %08X\n",pos,handle); + return FS_STATUS_OK; + } + } + return result; +} diff --git a/plugins/sdcafiine/src/fs_wrapper/fs_sync_wrapper.h b/plugins/sdcafiine/src/fs_wrapper/fs_sync_wrapper.h new file mode 100644 index 0000000..1f95939 --- /dev/null +++ b/plugins/sdcafiine/src/fs_wrapper/fs_sync_wrapper.h @@ -0,0 +1,54 @@ +/**************************************************************************** + * Copyright (C) 2017 Maschell + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + ****************************************************************************/ + +#ifndef __FS_SYNC_WRAPPER_H_ +#define __FS_SYNC_WRAPPER_H_ + +#include "FileReplacerUtils.h" + +#include +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif + +int fs_wrapper_FSCloseFile(int handle); + +int fs_wrapper_FSGetPosFile(int handle,int * pos); + +int fs_wrapper_FSGetStat(const char * path, FSStat * stats); + +int fs_wrapper_FSGetStatFile(int handle, FSStat * stats); + +int fs_wrapper_FSIsEof(int handle); + +int fs_wrapper_FSOpenFile(const char * path, const char * mode, int * handle); + +int fs_wrapper_FSReadFile(int handle,void *buffer,size_t size,size_t count); + +int fs_wrapper_FSReadFileWithPos(void *buffer, size_t size, size_t count, u32 pos, int handle); + +int fs_wrapper_FSSetPosFile(int handle,u32 pos); + +#ifdef __cplusplus +} +#endif + +#endif // __FS_SYNC_WRAPPER_H_ diff --git a/plugins/sdcafiine/src/fs_wrapper/fs_wrapper_utils.cpp b/plugins/sdcafiine/src/fs_wrapper/fs_wrapper_utils.cpp new file mode 100644 index 0000000..cf6b64b --- /dev/null +++ b/plugins/sdcafiine/src/fs_wrapper/fs_wrapper_utils.cpp @@ -0,0 +1,108 @@ +/**************************************************************************** + * Copyright (C) 2017 Maschell + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + ****************************************************************************/ +#include + +#include "fs_wrapper_utils.h" +#include "fs_async_wrapper.h" + +typedef int (*FallbackHelperInternal)(FallbackParamWrapper*, OSAsyncParamWrapper *); + +static int fallbackCaller(FallbackHelperInternal _function, void * fallbackparams){ + FallbackParamWrapper * paramsWrapper = (FallbackParamWrapper *)fallbackparams; + OSAsyncParamWrapper * params = &(paramsWrapper->params); + + if(paramsWrapper->realFunctionAddress == NULL){ return FS_STATUS_FATAL_ERROR; } // OSFatal("paramsWrapper->realFunctionAddress was NULL;");} + return _function(paramsWrapper,params); +} + +static int fallbackFSCloseFileAsyncInternal(FallbackParamWrapper * paramsWrapper, OSAsyncParamWrapper * params){ + int (*real_FSCloseFileAsyncCallback)(FSClient *, FSCmdBlock *, int, int, FSAsyncParams *); + real_FSCloseFileAsyncCallback = (int(*)(FSClient *, FSCmdBlock *, int, int, FSAsyncParams *)) paramsWrapper->realFunctionAddress; + int res = real_FSCloseFileAsyncCallback(params->pClient, params->pCmd, params->handle, params->error,params->asyncParams); + return res; +} + +static int fallbackFSGetPosFileAsyncInternal(FallbackParamWrapper * paramsWrapper, OSAsyncParamWrapper * params){ + int (*real_FSGetPosFileAsyncFunc)(FSClient *, FSCmdBlock *, int, int *, int, FSAsyncParams *); + real_FSGetPosFileAsyncFunc = (int(*)(FSClient *, FSCmdBlock *, int, int *, int, FSAsyncParams *)) paramsWrapper->realFunctionAddress; + int res = real_FSGetPosFileAsyncFunc(params->pClient, params->pCmd, params->handle, params->posPtr, params->error,params->asyncParams); + return res; +} + +static int fallbackFSGetStatAsyncInternal(FallbackParamWrapper * paramsWrapper, OSAsyncParamWrapper * params){ + int (*real_FSGetStatAsyncFunc)(FSClient *, FSCmdBlock *, const char *, FSStat *, int, FSAsyncParams *); + real_FSGetStatAsyncFunc = (int(*)(FSClient *, FSCmdBlock *, const char *, FSStat *, int, FSAsyncParams *)) paramsWrapper->realFunctionAddress; + int res = real_FSGetStatAsyncFunc(params->pClient, params->pCmd, params->path, params->stats, params->error,params->asyncParams); + return res; +} + +static int fallbackFSGetStatFileAsyncInternal(FallbackParamWrapper * paramsWrapper, OSAsyncParamWrapper * params){ + int (*real_FSGetStatFileAsyncFunc)(FSClient *, FSCmdBlock *, int, FSStat *, int, FSAsyncParams *); + real_FSGetStatFileAsyncFunc = (int(*)(FSClient *, FSCmdBlock *, int, FSStat *, int, FSAsyncParams *)) paramsWrapper->realFunctionAddress; + int res = real_FSGetStatFileAsyncFunc(params->pClient, params->pCmd, params->handle, params->stats, params->error,params->asyncParams); + return res; +} + +static int fallbackFSIsEofAsyncInternal(FallbackParamWrapper * paramsWrapper, OSAsyncParamWrapper * params){ + int (*real_FSIsEofAsyncFunc)(FSClient *, FSCmdBlock *, int, int, FSAsyncParams *); + real_FSIsEofAsyncFunc = (int(*)(FSClient *, FSCmdBlock *, int, int, FSAsyncParams *)) paramsWrapper->realFunctionAddress; + int res = real_FSIsEofAsyncFunc(params->pClient, params->pCmd, params->handle, params->error,params->asyncParams); + return res; +} + +static int fallbackFSOpenFileAsyncInternal(FallbackParamWrapper * paramsWrapper, OSAsyncParamWrapper * params){ + int (*real_FSOpenFileAsyncCallback)(FSClient *, FSCmdBlock *, const char *, const char *, int *, int, FSAsyncParams *); + real_FSOpenFileAsyncCallback = (int(*)(FSClient *, FSCmdBlock *, const char *, const char *, int *, int, FSAsyncParams *)) paramsWrapper->realFunctionAddress; + int res = real_FSOpenFileAsyncCallback(params->pClient, params->pCmd, params->path, params->mode, params->handlePtr, params->error, params->asyncParams); + return res; +} + +static int fallbackFSReadFileAsyncInternal(FallbackParamWrapper * paramsWrapper, OSAsyncParamWrapper * params){ + int (*real_FSReadFileAsyncFunc)(FSClient *, FSCmdBlock *, void *, int, int, int, int, int, FSAsyncParams *); + real_FSReadFileAsyncFunc = (int(*)(FSClient *, FSCmdBlock *, void *, int, int, int, int, int, FSAsyncParams *)) paramsWrapper->realFunctionAddress; + int res = real_FSReadFileAsyncFunc(params->pClient, params->pCmd, params->buffer, params->size, params->count, params->handle, params->flag, params->error, params->asyncParams); + return res; +} + +static int fallbackFSReadFileWithPosAsyncInternal(FallbackParamWrapper * paramsWrapper, OSAsyncParamWrapper * params){ + int (*real_FSReadFileWithPosAsyncFunc)(FSClient *, FSCmdBlock *, void *, int, int, u32, int, int, int, FSAsyncParams *); + real_FSReadFileWithPosAsyncFunc = (int(*)(FSClient *, FSCmdBlock *, void *, int, int, u32, int, int, int, FSAsyncParams *)) paramsWrapper->realFunctionAddress; + int res = real_FSReadFileWithPosAsyncFunc(params->pClient, params->pCmd, params->buffer, params->size, params->count, params->pos, params->handle, params->flag, params->error, params->asyncParams); + return res; +} + +static int fallbackFSSetPosFileAsyncInternal(FallbackParamWrapper * paramsWrapper, OSAsyncParamWrapper * params){ + int (*real_FSSetPosFileAsyncFunc)(FSClient *, FSCmdBlock *, int, u32, int, FSAsyncParams *); + real_FSSetPosFileAsyncFunc = (int(*)(FSClient *, FSCmdBlock *, int, u32, int, FSAsyncParams *)) paramsWrapper->realFunctionAddress; + int res = real_FSSetPosFileAsyncFunc(params->pClient, params->pCmd, params->handle, params->pos, params->error, params->asyncParams); + return res; +} + +#define DEFINE_FS_FALLBACK_CALLER(name) \ + int fallback##name(void * fallbackparams){\ + return fallbackCaller(fallback##name##Internal,fallbackparams);\ + } + +DEFINE_FS_FALLBACK_CALLER(FSCloseFileAsync) +DEFINE_FS_FALLBACK_CALLER(FSGetStatAsync) +DEFINE_FS_FALLBACK_CALLER(FSGetStatFileAsync) +DEFINE_FS_FALLBACK_CALLER(FSGetPosFileAsync) +DEFINE_FS_FALLBACK_CALLER(FSIsEofAsync) +DEFINE_FS_FALLBACK_CALLER(FSOpenFileAsync) +DEFINE_FS_FALLBACK_CALLER(FSReadFileAsync) +DEFINE_FS_FALLBACK_CALLER(FSReadFileWithPosAsync) +DEFINE_FS_FALLBACK_CALLER(FSSetPosFileAsync) diff --git a/plugins/sdcafiine/src/fs_wrapper/fs_wrapper_utils.h b/plugins/sdcafiine/src/fs_wrapper/fs_wrapper_utils.h new file mode 100644 index 0000000..3ba2a11 --- /dev/null +++ b/plugins/sdcafiine/src/fs_wrapper/fs_wrapper_utils.h @@ -0,0 +1,53 @@ +/**************************************************************************** + * Copyright (C) 2017 Maschell + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + ****************************************************************************/ + +#ifndef __FS_WRAPPER_UTILS_H_ +#define __FS_WRAPPER_UTILS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + + int fallbackFSCloseFileAsync(void * fallbackparams); + + int fallbackFSGetPosFileAsync(void * fallbackparams); + + int fallbackFSGetStatAsync(void * fallbackparams); + + int fallbackFSGetStatFileAsync(void * fallbackparams); + + int fallbackFSFSGetPosFileAsync(void * fallbackparams); + + int fallbackFSIsEofAsync(void * fallbackparams); + + int fallbackFSOpenFileAsync(void * fallbackparams); + + int fallbackFSReadFileAsync(void * fallbackparams); + + int fallbackFSReadFileWithPosAsync(void * fallbackparams); + + int fallbackFSSetPosFileAsync(void * fallbackparams); + +#ifdef __cplusplus +} +#endif + +#endif // __FS_WRAPPER_UTILS_H_ diff --git a/plugins/sdcafiine/src/main.cpp b/plugins/sdcafiine/src/main.cpp new file mode 100644 index 0000000..03b25e6 --- /dev/null +++ b/plugins/sdcafiine/src/main.cpp @@ -0,0 +1,153 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "utils/fs_utils.h" +#include "common/retain_vars.h" +#include +#include "common/common.h" +#include "main.h" + +#define DEBUG_LOG 1 + +WUPS_MODULE_NAME("SDCaffiine"); +WUPS_MODULE_VERSION("v1.0"); +WUPS_MODULE_AUTHOR("Maschell"); +WUPS_MODULE_LICENSE("GPL"); + +static bool setGroupAndOwnerID(); +void Init_SD_USB(); + +INITIALIZE(){ + if(gAppStatus == 2){ + return; + } + InitOSFunctionPointers(); + InitSocketFunctionPointers(); //For logging + + InitSysFunctionPointers(); // For SYSLaunchMenu() + InitProcUIFunctionPointers(); // For SYSLaunchMenu() + InitFSFunctionPointers(); + InitVPadFunctionPointers(); + + log_init(); + + gSDInitDone = 0; + snprintf(gModFolder, FS_MAX_ENTNAME_SIZE, "sd:/sdcafiine/%016llX",OSGetTitleID()); + + DEBUG_FUNCTION_LINE("Folder: %s\n",gModFolder); + DEBUG_FUNCTION_LINE("Mount SD partition\n"); + Init_SD_USB(); + + setGroupAndOwnerID(); + + g_dirhandles = vc_vector_create(0, sizeof(int), NULL); + g_filehandles = vc_vector_create(0, sizeof(int), NULL); + + log_print("Init of sd_cafiine!\n"); +} + + +static bool setGroupAndOwnerID(){ + int mcpHandle = MCP_Open(); + if(mcpHandle != 0) + { + unsigned char titleInfo[0x80]; + memset(titleInfo, 0, sizeof(titleInfo)); + + MCP_GetOwnTitleInfo(mcpHandle, titleInfo); + MCP_Close(mcpHandle); + u32 * test = (u32*)titleInfo; + global_owner_id = test[1]; + global_group_id = test[2]; + DEBUG_FUNCTION_LINE("Set group_id to %08X and owner_id to %08X\n",global_group_id,global_owner_id); + return true; + } + return false; +} + +void Init_SD_USB() { + //int res = IOSUHAX_Open(NULL); + //if(res < 0){ + //ExecuteIOSExploitWithDefaultConfig(); + // return; + //} + deleteDevTabsNames(); + mount_fake(); + gSDInitDone |= SDUSB_MOUNTED_FAKE; + + int res = -1; + if(res < 0){ + DEBUG_FUNCTION_LINE("IOSUHAX_open failed\n"); + if((res = mount_sd_fat("sd")) >= 0){ + DEBUG_FUNCTION_LINE("mount_sd_fat success\n"); + gSDInitDone |= SDUSB_MOUNTED_OS_SD; + }else{ + DEBUG_FUNCTION_LINE("mount_sd_fat failed %d\n",res); + } + }else{ + DEBUG_FUNCTION_LINE("Using IOSUHAX for SD/USB access\n"); + gSDInitDone |= SDUSB_LIBIOSU_LOADED; + int ntfs_mounts = 0; //mountAllNTFS(); + if(ntfs_mounts > 0){ + gSDInitDone |= USB_MOUNTED_LIBNTFS; + } + + /*if(mount_libfatAll() == 0){ + gSDInitDone |= SD_MOUNTED_LIBFAT; + gSDInitDone |= USB_MOUNTED_LIBFAT; + }*/ + } + DEBUG_FUNCTION_LINE("%08X\n",gSDInitDone); +} + +void deInit_SD_USB(){ + DEBUG_FUNCTION_LINE("Called this function.\n"); + + if(gSDInitDone & SDUSB_MOUNTED_FAKE){ + DEBUG_FUNCTION_LINE("Unmounting fake\n"); + unmount_fake(); + gSDInitDone &= ~SDUSB_MOUNTED_FAKE; + } + if(gSDInitDone & SDUSB_MOUNTED_OS_SD){ + DEBUG_FUNCTION_LINE("Unmounting OS SD\n"); + unmount_sd_fat("sd"); + gSDInitDone &= ~SDUSB_MOUNTED_OS_SD; + } + + /*if(gSDInitDone & SD_MOUNTED_LIBFAT){ + DEBUG_FUNCTION_LINE("Unmounting LIBFAT SD\n"); + unmount_libfat("sd"); + gSDInitDone &= ~SD_MOUNTED_LIBFAT; + } + + if(gSDInitDone & USB_MOUNTED_LIBFAT){ + DEBUG_FUNCTION_LINE("Unmounting LIBFAT USB\n"); + unmount_libfat("usb"); + gSDInitDone &= ~USB_MOUNTED_LIBFAT; + } + + if(gSDInitDone & USB_MOUNTED_LIBNTFS){ + DEBUG_FUNCTION_LINE("Unmounting LIBNTFS USB\n"); + unmountAllNTFS(); + gSDInitDone &= ~USB_MOUNTED_LIBNTFS; + }*/ + + if(gSDInitDone & SDUSB_LIBIOSU_LOADED){ + DEBUG_FUNCTION_LINE("Calling IOSUHAX_Close\n"); + IOSUHAX_Close(); + gSDInitDone &= ~SDUSB_LIBIOSU_LOADED; + } + deleteDevTabsNames(); + if(gSDInitDone != SDUSB_MOUNTED_NONE){ + DEBUG_FUNCTION_LINE("WARNING. Some devices are still mounted.\n"); + } + DEBUG_FUNCTION_LINE("Function end.\n"); +} diff --git a/plugins/sdcafiine/src/main.h b/plugins/sdcafiine/src/main.h new file mode 100644 index 0000000..10b159d --- /dev/null +++ b/plugins/sdcafiine/src/main.h @@ -0,0 +1,18 @@ +#ifndef _MAIN_H_ +#define _MAIN_H_ + +#include +#include + +/* Main */ +#ifdef __cplusplus +extern "C" { +#endif + +void deInit_SD_USB(); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/plugins/sdcafiine/src/patches.cpp b/plugins/sdcafiine/src/patches.cpp new file mode 100644 index 0000000..1ca0d8f --- /dev/null +++ b/plugins/sdcafiine/src/patches.cpp @@ -0,0 +1,293 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "utils/fs_utils.h" +#include "common/retain_vars.h" +#include "common/common.h" +#include "main.h" + +#define DEBUG_LOG 1 + +DECL_FUNCTION(void, __PPCExit, void){ + DEBUG_FUNCTION_LINE("__PPCExit\n"); + + deInit_SD_USB(); + + real___PPCExit(); +} + +DECL_FUNCTION(u32, ProcUIProcessMessages, u32 u){ + u32 res = real_ProcUIProcessMessages(u); + if(res != gAppStatus){ + DEBUG_FUNCTION_LINE("App status changed from %d to %d \n",gAppStatus,res); + gAppStatus = res; + } + + return res; +} + +DECL_FUNCTION(int, FSCloseFile, FSClient *pClient, FSCmdBlock *pCmd, int fd, int error) { + if(gAppStatus == 2 || gSDInitDone <= SDUSB_MOUNTED_FAKE){ return real_FSCloseFile(pClient, pCmd, fd, error); } + + int result = USE_OS_FS_FUNCTION; + if((result = fs_wrapper_FSCloseFile(fd)) != USE_OS_FS_FUNCTION){ + return result; + } + + return real_FSCloseFile(pClient, pCmd, fd, setErrorFlag(error)); +} + +DECL_FUNCTION(int, FSGetPosFile, FSClient *pClient, FSCmdBlock *pCmd, int fd, int *pos, int error) { + if(gAppStatus == 2 || gSDInitDone <= SDUSB_MOUNTED_FAKE){ return real_FSGetPosFile(pClient, pCmd, fd, pos, error); } + + int result = USE_OS_FS_FUNCTION; + if((result = fs_wrapper_FSGetPosFile(fd,pos)) != USE_OS_FS_FUNCTION){ + return result; + } + + return real_FSGetPosFile(pClient, pCmd, fd, pos, setErrorFlag(error)); +} + +DECL_FUNCTION(int, FSGetStat, FSClient *pClient, FSCmdBlock *pCmd, const char *path, FSStat *stats, int error) { + if(gAppStatus == 2 || gSDInitDone <= SDUSB_MOUNTED_FAKE){ return real_FSGetStat(pClient, pCmd, path, stats, error); } + + int result = USE_OS_FS_FUNCTION; + + if(DEBUG_LOG){ DEBUG_FUNCTION_LINE("for path %s\n",path); } + char * newPath = getPathWithNewBase(path,gModFolder); + if(newPath != NULL){ + if((result = fs_wrapper_FSGetStat(newPath,stats)) != USE_OS_FS_FUNCTION){ + if(newPath){ free(newPath); newPath = NULL;} + return result; + } + if(newPath){ free(newPath); newPath = NULL;} //Should be dead code... + } + + return real_FSGetStat(pClient, pCmd, path, stats, setErrorFlag(error)); +} + +DECL_FUNCTION(int, FSGetStatFile, FSClient *pClient, FSCmdBlock *pCmd, int fd, FSStat * stats, int error) { + if(gAppStatus == 2 || gSDInitDone <= SDUSB_MOUNTED_FAKE){ return real_FSGetStatFile(pClient, pCmd, fd, stats, error); } + + int result = USE_OS_FS_FUNCTION; + if((result = fs_wrapper_FSGetStatFile(fd,stats)) != USE_OS_FS_FUNCTION){ + return result; + } + + return real_FSGetStatFile(pClient, pCmd, fd, stats, setErrorFlag(error)); +} + +DECL_FUNCTION(int, FSIsEof, FSClient *pClient, FSCmdBlock *pCmd, int fd, int error) { + if(gAppStatus == 2 || gSDInitDone <= SDUSB_MOUNTED_FAKE) return real_FSIsEof(pClient, pCmd, fd, error); + + int result = USE_OS_FS_FUNCTION; + if((result = fs_wrapper_FSIsEof(fd)) != USE_OS_FS_FUNCTION){ + return result; + } + + return real_FSIsEof(pClient, pCmd, fd, setErrorFlag(error)); +} + +DECL_FUNCTION(int, FSOpenFile, FSClient *pClient, FSCmdBlock *pCmd, const char *path, const char *mode, int *handle, int error) { + if(gAppStatus == 2 || gSDInitDone <= SDUSB_MOUNTED_FAKE){ return real_FSOpenFile(pClient, pCmd, path, mode, handle, error); } + + /*if(endsWith(path,BOOT_TV_TEX_TGA,-1,-1)){ //Mario Party 10 crashes when pressing the home button. + if(startsWith("/vol/storage_mlc01/usr/title/",path)){ + u64 tID = getTitleIDFromPath(path); + HandleMultiModPacks(tID,false); + }else if(strlen(gLastMetaPath) > 0){ + DEBUG_FUNCTION_LINE("gLastMetaPath %s\n",gLastMetaPath); + if(startsWith("/vol/storage_usb01/usr/title/",gLastMetaPath) || + startsWith("/vol/storage_mlc01/usr/title/",gLastMetaPath) + ){ + u64 tID = getTitleIDFromPath(gLastMetaPath); + HandleMultiModPacks(tID,false); + } + } + }*/ + + if(DEBUG_LOG){ DEBUG_FUNCTION_LINE("for path %s\n",path); } + char * newPath = getPathWithNewBase(path,gModFolder); + int result = USE_OS_FS_FUNCTION; + + if(newPath != NULL){ + if((result = fs_wrapper_FSOpenFile(newPath,mode,handle)) != USE_OS_FS_FUNCTION){ + if(newPath){ free(newPath); newPath = NULL;} + return result; + } + if(newPath){ free(newPath); newPath = NULL;} //Should be dead code... + } + + return real_FSOpenFile(pClient, pCmd, path, mode, handle, setErrorFlag(error)); +} + +DECL_FUNCTION(int, FSReadFile, FSClient *pClient, FSCmdBlock *pCmd, void *buffer, int size, int count, int handle, int flag, int error) { + if(gAppStatus == 2 || gSDInitDone <= SDUSB_MOUNTED_FAKE){ return real_FSReadFile(pClient, pCmd, buffer, size, count, handle, flag, error); } + + int result = USE_OS_FS_FUNCTION; + if((result = fs_wrapper_FSReadFile(handle,buffer,size,count)) != USE_OS_FS_FUNCTION){ + return result; + } + + return real_FSReadFile(pClient, pCmd, buffer, size, count, handle, flag, setErrorFlag(error)); +} + +DECL_FUNCTION(int, FSSetPosFile, FSClient *pClient, FSCmdBlock *pCmd, int fd, u32 pos, int error) { + if(gAppStatus == 2 || gSDInitDone <= SDUSB_MOUNTED_FAKE) return real_FSSetPosFile(pClient, pCmd, fd, pos, error); + + int result = USE_OS_FS_FUNCTION; + if((result = fs_wrapper_FSSetPosFile(fd,pos)) != USE_OS_FS_FUNCTION){ + return result; + } + + return real_FSSetPosFile(pClient, pCmd, fd, pos, setErrorFlag(error)); +} + +DECL_FUNCTION(int, FSReadFileWithPos, FSClient *pClient, FSCmdBlock *pCmd, void *buffer, int size, int count, u32 pos, int fd, int flag, int error) { + if(gAppStatus == 2 || gSDInitDone <= SDUSB_MOUNTED_FAKE){ return real_FSReadFileWithPos(pClient, pCmd, buffer, size, count, pos, fd, flag, error); } + + int result = USE_OS_FS_FUNCTION; + if((result = fs_wrapper_FSReadFileWithPos(buffer,size,count,pos,fd)) != USE_OS_FS_FUNCTION){ + return result; + } + + return real_FSReadFileWithPos(pClient, pCmd, buffer, size, count, pos, fd, flag, setErrorFlag(error)); +} + + +/** +In theory it would be enough just to patch the "async" versions of the function. +The non-async functions internally use the async function anyway. +However this my be a bit faster/robust, when we handle the async functions async. +**/ + +DECL_FUNCTION(int, FSCloseFileAsync, FSClient *pClient, FSCmdBlock *pCmd, int fd, int error, FSAsyncParams * asyncParams) { + if(gAppStatus == 2 || checkErrorFlag(&error) || gSDInitDone <= SDUSB_MOUNTED_FAKE){ // Use the real implementation if the app is not in foreground or we already checked it. + return real_FSCloseFileAsync(pClient, pCmd, fd, error, asyncParams); + } + + return fs_default_os_wrapper_FSCloseFileAsync(pClient, pCmd, fd, error, asyncParams,(void*) real_FSCloseFileAsync); +} + +DECL_FUNCTION(int, FSGetPosFileAsync, FSClient *pClient, FSCmdBlock *pCmd, int fd, int *pos, int error, FSAsyncParams * asyncParams) { + if(gAppStatus == 2 || checkErrorFlag(&error) || gSDInitDone <= SDUSB_MOUNTED_FAKE){ // Use the real implementation if the app is not in foreground or we already checked it. + return real_FSGetPosFileAsync(pClient, pCmd, fd, pos, error, asyncParams); + } + + return fs_default_os_wrapper_FSGetPosFileAsync(pClient, pCmd, fd, pos, error, asyncParams,(void*) real_FSGetPosFileAsync); +} + +DECL_FUNCTION(int, FSGetStatAsync, FSClient *pClient, FSCmdBlock *pCmd, const char *path, FSStat *stats, int error, FSAsyncParams * asyncParams) { + if(gAppStatus == 2 || checkErrorFlag(&error) || gSDInitDone <= SDUSB_MOUNTED_FAKE){ // Use the real implementation if the app is not in foreground or we already checked it. + return real_FSGetStatAsync(pClient, pCmd, path, stats, error, asyncParams); + } + + return fs_default_os_wrapper_FSGetStatAsync(getPathWithNewBase((char*)path,gModFolder),pClient, pCmd, path, stats, error, asyncParams,(void*) real_FSGetStatAsync); +} + +DECL_FUNCTION(int, FSGetStatFileAsync, FSClient *pClient, FSCmdBlock *pCmd, int fd, FSStat * stats, int error, FSAsyncParams * asyncParams) { + if(gAppStatus == 2 || checkErrorFlag(&error) || gSDInitDone <= SDUSB_MOUNTED_FAKE){ // Use the real implementation if the app is not in foreground or we already checked it. + return real_FSGetStatFileAsync(pClient, pCmd, fd, stats, error, asyncParams); + } + + return fs_default_os_wrapper_FSGetStatFileAsync(pClient, pCmd, fd, stats, error, asyncParams,(void*) real_FSGetStatFileAsync); +} + +DECL_FUNCTION(int, FSIsEofAsync, FSClient *pClient, FSCmdBlock *pCmd, int fd, int error, FSAsyncParams *asyncParams) { + if(gAppStatus == 2 || checkErrorFlag(&error) || gSDInitDone <= SDUSB_MOUNTED_FAKE){ // Use the real implementation if the app is not in foreground or we already checked it. + return real_FSIsEofAsync(pClient, pCmd, fd, error,asyncParams); + } + + return fs_default_os_wrapper_FSIsEofAsync(pClient, pCmd, fd, error,asyncParams,(void*) real_FSIsEofAsync); +} +/* +u64 getTitleIDFromPath(const char * path){ + if(path == NULL || strlen(path) < 46) return 0; + char titleID[0x11]; + char titleIDHigh[0x09]; + char titleIDLow[0x09]; + char * test = (char * )&path[29]; + snprintf(titleIDHigh,0x09,"%s",test); + test = (char * ) &path[38]; + snprintf(titleIDLow,0x09,"%s",test); + snprintf(titleID,0x11,"%s%s",titleIDHigh,titleIDLow); + u64 tID = strtoll(titleID, NULL, 16); + tID &= ~ 0x0000000E00000000; // remove update flag + return tID; +}*/ + +DECL_FUNCTION(int, FSOpenFileAsync, FSClient *pClient, FSCmdBlock *pCmd, const char *path, const char *mode, int *handle, int error, FSAsyncParams *asyncParams) { + if(gAppStatus == 2 || checkErrorFlag(&error) || gSDInitDone <= SDUSB_MOUNTED_FAKE){ // Use the real implementation if the app is not in foreground or we already checked it. + return real_FSOpenFileAsync(pClient, pCmd, path, mode, handle,error, asyncParams); + } + + return fs_default_os_wrapper_FSOpenFileAsync(getPathWithNewBase((char*)path,gModFolder), pClient, pCmd, path, mode, handle,error, asyncParams,(void*) real_FSOpenFileAsync); +} + +DECL_FUNCTION(int, FSReadFileAsync, FSClient *pClient, FSCmdBlock *pCmd, void *buffer, int size, int count, int fd, int flag, int error, FSAsyncParams *asyncParams) { + if(gAppStatus == 2 || checkErrorFlag(&error) || gSDInitDone <= SDUSB_MOUNTED_FAKE){ // Use the real implementation if the app is not in foreground or we already checked it. + return real_FSReadFileAsync(pClient, pCmd, buffer, size, count, fd, flag, error, asyncParams); + } + + return fs_default_os_wrapper_FSReadFileAsync(pClient, pCmd, buffer, size, count, fd, flag, error, asyncParams, (void*) real_FSReadFileAsync); +} + +DECL_FUNCTION(int, FSReadFileWithPosAsync, FSClient *pClient, FSCmdBlock *pCmd, void *buffer, int size, int count, u32 pos, int fd, int flag, int error, FSAsyncParams *asyncParams) { + if(gAppStatus == 2 || checkErrorFlag(&error) || gSDInitDone <= SDUSB_MOUNTED_FAKE){ // Use the real implementation if the app is not in foreground or we already checked it. + return real_FSReadFileWithPosAsync(pClient, pCmd, buffer, size, count, pos, fd, flag, error, asyncParams); + } + + return fs_default_os_wrapper_FSReadFileWithPosAsync(pClient, pCmd, buffer, size, count, pos, fd, flag, error, asyncParams, (void*) real_FSReadFileWithPosAsync); +} + +DECL_FUNCTION(int, FSSetPosFileAsync, FSClient *pClient, FSCmdBlock *pCmd, int handle, u32 pos, int error, FSAsyncParams *asyncParams) { + if(gAppStatus == 2 || checkErrorFlag(&error) || gSDInitDone <= SDUSB_MOUNTED_FAKE){ // Use the real implementation if the app is not in foreground or we already checked it. + return real_FSSetPosFileAsync(pClient, pCmd, handle, pos, error,asyncParams); + } + + return fs_default_os_wrapper_FSSetPosFileAsync(pClient, pCmd, handle, pos, error,asyncParams, (void*) real_FSSetPosFileAsync); +} + +/* +DECL_FUNCTION(int, FSBindMount, void *pClient, void *pCmd, char *source, char *target, int error){ + if(gAppStatus == 2) return real_FSBindMount(pClient,pCmd,source,target,error); + memcpy(gLastMetaPath,source,strlen(source) + 1); + return real_FSBindMount(pClient,pCmd,source,target,error); +} +DECL_FUNCTION(int, FSBindUnmount, void *pClient, void *pCmd, char *target, int error){ + if(gAppStatus == 2) real_FSBindUnmount(pClient,pCmd,target,error); + gLastMetaPath[0] = 0; + return real_FSBindUnmount(pClient,pCmd,target,error); +}*/ + + +WUPS_MUST_REPLACE(FSCloseFile, WUPS_LOADER_LIBRARY_COREINIT, FSCloseFile); +WUPS_MUST_REPLACE(FSGetPosFile, WUPS_LOADER_LIBRARY_COREINIT, FSGetPosFile); +WUPS_MUST_REPLACE(FSGetStat, WUPS_LOADER_LIBRARY_COREINIT, FSGetStat); +WUPS_MUST_REPLACE(FSGetStatFile, WUPS_LOADER_LIBRARY_COREINIT, FSGetStatFile); +WUPS_MUST_REPLACE(FSIsEof, WUPS_LOADER_LIBRARY_COREINIT, FSIsEof); +WUPS_MUST_REPLACE(FSOpenFile, WUPS_LOADER_LIBRARY_COREINIT, FSOpenFile); +WUPS_MUST_REPLACE(FSReadFile, WUPS_LOADER_LIBRARY_COREINIT, FSReadFile); +WUPS_MUST_REPLACE(FSReadFileWithPos, WUPS_LOADER_LIBRARY_COREINIT, FSReadFileWithPos); +WUPS_MUST_REPLACE(FSSetPosFile, WUPS_LOADER_LIBRARY_COREINIT, FSSetPosFile); + +WUPS_MUST_REPLACE(FSCloseFileAsync, WUPS_LOADER_LIBRARY_COREINIT, FSCloseFileAsync); +WUPS_MUST_REPLACE(FSGetPosFileAsync, WUPS_LOADER_LIBRARY_COREINIT, FSGetPosFileAsync); +WUPS_MUST_REPLACE(FSGetStatAsync, WUPS_LOADER_LIBRARY_COREINIT, FSGetStatAsync); +WUPS_MUST_REPLACE(FSGetStatFileAsync, WUPS_LOADER_LIBRARY_COREINIT, FSGetStatFileAsync); +WUPS_MUST_REPLACE(FSIsEofAsync, WUPS_LOADER_LIBRARY_COREINIT, FSIsEofAsync); +WUPS_MUST_REPLACE(FSOpenFileAsync, WUPS_LOADER_LIBRARY_COREINIT, FSOpenFileAsync); +WUPS_MUST_REPLACE(FSReadFileAsync, WUPS_LOADER_LIBRARY_COREINIT, FSReadFileAsync); +WUPS_MUST_REPLACE(FSReadFileWithPosAsync, WUPS_LOADER_LIBRARY_COREINIT, FSReadFileWithPosAsync); +WUPS_MUST_REPLACE(FSSetPosFileAsync, WUPS_LOADER_LIBRARY_COREINIT, FSSetPosFileAsync); + + +WUPS_MUST_REPLACE(__PPCExit, WUPS_LOADER_LIBRARY_COREINIT, __PPCExit); +WUPS_MUST_REPLACE(ProcUIProcessMessages, WUPS_LOADER_LIBRARY_PROC_UI, ProcUIProcessMessages); diff --git a/plugins/sdcafiine/src/utils/fs_utils.cpp b/plugins/sdcafiine/src/utils/fs_utils.cpp new file mode 100644 index 0000000..047b58b --- /dev/null +++ b/plugins/sdcafiine/src/utils/fs_utils.cpp @@ -0,0 +1,147 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "fs_utils.h" +#include "common/common.h" +#include "common/retain_vars.h" + +int is_gamefile(const char *path) { + if(path == NULL) return 0; + if(strncmp(path,"CAFE/",5) == 0) return GAME_PATH_TYPE_STRIPPED_CONTENT; //Workaround for NSMBU + + // In case the path starts by "//" and not "/" (some games do that ... ...) + if (path[0] == '/' && path[1] == '/') + path = &path[1]; + + // In case the path does not start with "/" (some games do that too ...) + int len = 0; + char new_path[16]; + if(path[0] != '/') { + new_path[0] = '/'; + len++; + } + + while(*path && len < (int)(sizeof(new_path) - 1)) { + new_path[len++] = *path++; + } + new_path[len++] = 0; + + if(strncmp(new_path,"/vol/content",12) == 0) return GAME_PATH_TYPE_CONTENT; + //dlc support + if(strncmp(new_path,"/vol/aoc",8) == 0) return GAME_PATH_TYPE_AOC; + + return 0; +} +char * getPathWithNewBase(const char * inPath, const char * newBase){ + if(inPath == NULL || *inPath == 0 || newBase == NULL || *newBase == 0) return NULL; + char * relativePath = getRelativePath(inPath); + char * result = NULL; + + if(relativePath == NULL){ + /* + if(strlen(gModFolder) > 0){ + int file = 0; + if(endsWith(inPath,BOOT_TV_TEX_TGA,-1,-1)){ file = 1;} + else if(endsWith(inPath,BOOT_DRC_TEX_TGA,-1,-1)){ file = 2;} + else if(endsWith(inPath,BOOT_SOUND_BTSND,-1,-1)){ file = 3;} + if(file == 0){ return NULL;} + + result = (char*)malloc((sizeof(char) * (strlen(newBase) +1 + strlen(META_FOLDER) + 1 + 20) + 1)); + if(result == NULL){ + DEBUG_FUNCTION_LINE("malloc for result failed.\n"); + return NULL; + } + if(file == 1){sprintf(result,"%s/%s/%s",newBase,META_FOLDER,BOOT_TV_TEX_TGA);} + if(file == 2){sprintf(result,"%s/%s/%s",newBase,META_FOLDER,BOOT_DRC_TEX_TGA);} + if(file == 3){sprintf(result,"%s/%s/%s",newBase,META_FOLDER,BOOT_SOUND_BTSND);} + return result; + }*/ + + return NULL; + } + + result = (char*)malloc((sizeof(char) * (strlen(newBase) +1+ strlen(relativePath))) + 1); + if(result == NULL){ + DEBUG_FUNCTION_LINE("malloc for result failed.\n"); + OSFATAL_FUNCTION_LINE("malloc for result failed.\n"); + return NULL; + } + sprintf(result,"%s/%s",newBase,relativePath); + + free(relativePath); + relativePath = NULL; + + return result; +} + +char * getRelativePath(const char *path){ + if(path == NULL) return NULL; + char * pathForCheck = NULL; + + int gameFile = is_gamefile(path); + if(gameFile > 0) { + //if(DEBUG_LOG) log_printf("getNewPath %s\n", path); + int path_offset = 0; + + // In case the path starts by "//" and not "/" (some games do that ... ...) + if (path[0] == '/' && path[1] == '/') + path = &path[1]; + + // In case the path does not start with "/" set an offset for all the accesses + if(path[0] != '/') + path_offset = -1; + + + if(gameFile == GAME_PATH_TYPE_CONTENT) { // is content + //content + + // some games are doing /vol/content/./.... + if(path[13 + path_offset] == '.' && path[14 + path_offset] == '/') { + path_offset += 2; + } + char * pathForCheckInternal = (char*)path + 13 + path_offset; + if(pathForCheckInternal[0] == '/') pathForCheckInternal++; //Skip double slash + + pathForCheck = (char*)malloc(sizeof(CONTENT_FOLDER) + 1 + (sizeof(char) * (strlen(pathForCheckInternal) + 1))); + if(pathForCheck == NULL){ + DEBUG_FUNCTION_LINE("malloc failed\n"); + OSFATAL_FUNCTION_LINE("malloc failed\n"); + return NULL; + } + sprintf(pathForCheck,"%s/%s",CONTENT_FOLDER,pathForCheckInternal); + } else if (gameFile == GAME_PATH_TYPE_AOC) { // is aoc + //aoc + int aocFolderLength = 1; + char * aocFolderLengthCheck = (char*)path + 5 + path_offset; + while (aocFolderLengthCheck[0] != '/') { + aocFolderLength++; + aocFolderLengthCheck++; + } + char * pathForCheckInternal = (char*)path + 5 + aocFolderLength + path_offset; + if(pathForCheckInternal[0] == '/') pathForCheckInternal++; //Skip double slash + + pathForCheck = (char*)malloc(sizeof(AOC_FOLDER) + 1 + (sizeof(char) * (strlen(pathForCheckInternal) + 1))); + if(pathForCheck == NULL){ + DEBUG_FUNCTION_LINE("malloc failed\n"); + OSFATAL_FUNCTION_LINE("malloc failed\n"); + return NULL; + } + sprintf(pathForCheck,"%s/%s",AOC_FOLDER,pathForCheckInternal); + } else if (gameFile == GAME_PATH_TYPE_STRIPPED_CONTENT) { // is stripped content + pathForCheck = (char*)malloc(sizeof(CONTENT_FOLDER) + 1 + (sizeof(char) * (strlen(path) + 1))); + if(pathForCheck == NULL){ + DEBUG_FUNCTION_LINE("malloc failed\n"); + OSFATAL_FUNCTION_LINE("malloc failed\n"); + return NULL; + } + sprintf(pathForCheck,"%s/%s",CONTENT_FOLDER,path); + } + } + + return pathForCheck; +} diff --git a/plugins/sdcafiine/src/utils/fs_utils.h b/plugins/sdcafiine/src/utils/fs_utils.h new file mode 100644 index 0000000..4913a71 --- /dev/null +++ b/plugins/sdcafiine/src/utils/fs_utils.h @@ -0,0 +1,18 @@ +#ifndef __SDCAFIINE_FS_UTILS_H_ +#define __SDCAFIINE_FS_UTILS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +int is_gamefile(const char *path); +char * getPathWithNewBase(const char * inPath, const char * newBase); +char * getRelativePath(const char *path); + +#ifdef __cplusplus +} +#endif + +#endif // __FS_UTILS_H_ diff --git a/plugins/sdcafiine/src/utils/vc_vector.c b/plugins/sdcafiine/src/utils/vc_vector.c new file mode 100644 index 0000000..1e154f6 --- /dev/null +++ b/plugins/sdcafiine/src/utils/vc_vector.c @@ -0,0 +1,329 @@ +#include "vc_vector.h" +#include +#include + +#define GROWTH_FACTOR 1.5 +#define DEFAULT_COUNT_OF_ELEMENETS 8 +#define MINIMUM_COUNT_OF_ELEMENTS 2 + +// ---------------------------------------------------------------------------- + +// vc_vector structure + +struct vc_vector { + size_t count; + size_t element_size; + size_t reserved_size; + char* data; + vc_vector_deleter* deleter; +}; + +// ---------------------------------------------------------------------------- + +// auxillary methods + +bool vc_vector_realloc(vc_vector* vector, size_t new_count) { + const size_t new_size = new_count * vector->element_size; + char* new_data = (char*)realloc(vector->data, new_size); + if (!new_data) { + return false; + } + + vector->reserved_size = new_size; + vector->data = new_data; + return true; +} + +// [first_index, last_index) +void vc_vector_call_deleter(vc_vector* vector, size_t first_index, size_t last_index) { + for (size_t i = first_index; i < last_index; ++i) { + vector->deleter(vc_vector_at(vector, i)); + } +} + +void vc_vector_call_deleter_all(vc_vector* vector) { + vc_vector_call_deleter(vector, 0, vc_vector_count(vector)); +} + +// ---------------------------------------------------------------------------- + +// Contol + +vc_vector* vc_vector_create(size_t count_elements, size_t size_of_element, vc_vector_deleter* deleter) { + vc_vector* v = (vc_vector*)malloc(sizeof(vc_vector)); + if (v != NULL) { + v->data = NULL; + v->count = 0; + v->element_size = size_of_element; + v->deleter = deleter; + + if (count_elements < MINIMUM_COUNT_OF_ELEMENTS) { + count_elements = DEFAULT_COUNT_OF_ELEMENETS; + } + + if (size_of_element < 1 || + !vc_vector_realloc(v, count_elements)) { + free(v); + v = NULL; + } + } + + return v; +} + +vc_vector* vc_vector_create_copy(const vc_vector* vector) { + vc_vector* new_vector = vc_vector_create(vector->reserved_size / vector->count, + vector->element_size, + vector->deleter); + if (!new_vector) { + return new_vector; + } + + if (memcpy(vector->data, + new_vector->data, + new_vector->element_size * vector->count) == NULL) { + vc_vector_release(new_vector); + new_vector = NULL; + return new_vector; + } + + new_vector->count = vector->count; + return new_vector; +} + +void vc_vector_release(vc_vector* vector) { + if (vector->deleter != NULL) { + vc_vector_call_deleter_all(vector); + } + + if (vector->reserved_size != 0) { + free(vector->data); + } + + free(vector); +} + +bool vc_vector_is_equals(vc_vector* vector1, vc_vector* vector2) { + const size_t size_vector1 = vc_vector_size(vector1); + if (size_vector1 != vc_vector_size(vector2)) { + return false; + } + + return memcmp(vector1->data, vector2->data, size_vector1) == 0; +} + +float vc_vector_get_growth_factor() { + return GROWTH_FACTOR; +} + +size_t vc_vector_get_default_count_of_elements() { + return DEFAULT_COUNT_OF_ELEMENETS; +} + +size_t vc_vector_struct_size() { + return sizeof(vc_vector); +} + +// ---------------------------------------------------------------------------- + +// Element access + +void* vc_vector_at(vc_vector* vector, size_t index) { + return vector->data + index * vector->element_size; +} + +void* vc_vector_front(vc_vector* vector) { + return vector->data; +} + +void* vc_vector_back(vc_vector* vector) { + return vector->data + (vector->count - 1) * vector->element_size; +} + +void* vc_vector_data(vc_vector* vector) { + return vector->data; +} + +// ---------------------------------------------------------------------------- + +// Iterators + +void* vc_vector_begin(vc_vector* vector) { + return vector->data; +} + +void* vc_vector_end(vc_vector* vector) { + return vector->data + vector->element_size * vector->count; +} + +void* vc_vector_next(vc_vector* vector, void* i) { + return i + vector->element_size; +} + +// ---------------------------------------------------------------------------- + +// Capacity + +bool vc_vector_empty(vc_vector* vector) { + return vector->count == 0; +} + +size_t vc_vector_count(const vc_vector* vector) { + return vector->count; +} + +size_t vc_vector_size(const vc_vector* vector) { + return vector->count * vector->element_size; +} + +size_t vc_vector_max_count(const vc_vector* vector) { + return vector->reserved_size / vector->element_size; +} + +size_t vc_vector_max_size(const vc_vector* vector) { + return vector->reserved_size; +} + +bool vc_vector_reserve_count(vc_vector* vector, size_t new_count) { + if (new_count < vector->count) { + return false; + } + + size_t new_size = vector->element_size * new_count; + if (new_size == vector->reserved_size) { + return true; + } + + return vc_vector_realloc(vector, new_count); +} + +bool vc_vector_reserve_size(vc_vector* vector, size_t new_size) { + return vc_vector_reserve_count(vector, new_size / vector->element_size); +} + +// ---------------------------------------------------------------------------- + +// Modifiers + +void vc_vector_clear(vc_vector* vector) { + if (vector->deleter != NULL) { + vc_vector_call_deleter_all(vector); + } + + vector->count = 0; +} + +bool vc_vector_insert(vc_vector* vector, size_t index, const void* value) { + if (vc_vector_max_count(vector) < vector->count + 1) { + if (!vc_vector_realloc(vector, vc_vector_max_count(vector) * GROWTH_FACTOR)) { + return false; + } + } + + if (!memmove(vc_vector_at(vector, index + 1), + vc_vector_at(vector, index), + vector->element_size * (vector->count - index))) { + + return false; + } + + if (memcpy(vc_vector_at(vector, index), + value, + vector->element_size) == NULL) { + return false; + } + + ++vector->count; + return true; +} + +bool vc_vector_erase(vc_vector* vector, size_t index) { + if (vector->deleter != NULL) { + vector->deleter(vc_vector_at(vector, index)); + } + + if (!memmove(vc_vector_at(vector, index), + vc_vector_at(vector, index + 1), + vector->element_size * (vector->count - index))) { + return false; + } + + vector->count--; + return true; +} + +bool vc_vector_erase_range(vc_vector* vector, size_t first_index, size_t last_index) { + if (vector->deleter != NULL) { + vc_vector_call_deleter(vector, first_index, last_index); + } + + if (!memmove(vc_vector_at(vector, first_index), + vc_vector_at(vector, last_index), + vector->element_size * (vector->count - last_index))) { + return false; + } + + vector->count -= last_index - first_index; + return true; +} + +bool vc_vector_append(vc_vector* vector, const void* values, size_t count) { + const size_t count_new = count + vc_vector_count(vector); + + if (vc_vector_max_count(vector) < count_new) { + size_t max_count_to_reserved = vc_vector_max_count(vector) * GROWTH_FACTOR; + while (count_new > max_count_to_reserved) { + max_count_to_reserved *= GROWTH_FACTOR; + } + + if (!vc_vector_realloc(vector, max_count_to_reserved)) { + return false; + } + } + + if (memcpy(vector->data + vector->count * vector->element_size, + values, + vector->element_size * count) == NULL) { + return false; + } + + vector->count = count_new; + return true; +} + +bool vc_vector_push_back(vc_vector* vector, const void* value) { + if (!vc_vector_append(vector, value, 1)) { + return false; + } + + return true; +} + +bool vc_vector_pop_back(vc_vector* vector) { + if (vector->deleter != NULL) { + vector->deleter(vc_vector_back(vector)); + } + + vector->count--; + return true; +} + +bool vc_vector_replace(vc_vector* vector, size_t index, const void* value) { + if (vector->deleter != NULL) { + vector->deleter(vc_vector_at(vector, index)); + } + + return memcpy(vc_vector_at(vector, index), + value, + vector->element_size) != NULL; +} + +bool vc_vector_replace_multiple(vc_vector* vector, size_t index, const void* values, size_t count) { + if (vector->deleter != NULL) { + vc_vector_call_deleter(vector, index, index + count); + } + + return memcpy(vc_vector_at(vector, index), + values, + vector->element_size * count) != NULL; +} diff --git a/plugins/sdcafiine/src/utils/vc_vector.h b/plugins/sdcafiine/src/utils/vc_vector.h new file mode 100644 index 0000000..d61b1e8 --- /dev/null +++ b/plugins/sdcafiine/src/utils/vc_vector.h @@ -0,0 +1,130 @@ +#ifndef VCVECTOR_H +#define VCVECTOR_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct vc_vector vc_vector; +typedef void (vc_vector_deleter)(void *); + + + +// ---------------------------------------------------------------------------- +// Control +// ---------------------------------------------------------------------------- + +// Constructs an empty vector with an reserver size for count_elements. +vc_vector* vc_vector_create(size_t count_elements, size_t size_of_element, vc_vector_deleter* deleter); + +// Constructs a copy of an existing vector. +vc_vector* vc_vector_create_copy(const vc_vector* vector); + +// Releases the vector. +void vc_vector_release(vc_vector* vector); + +// Compares vector content +bool vc_vector_is_equals(vc_vector* vector1, vc_vector* vector2); + +// Returns constant value of the vector growth factor. +float vc_vector_get_growth_factor(); + +// Returns constant value of the vector default count of elements. +size_t vc_vector_get_default_count_of_elements(); + +// Returns constant value of the vector struct size. +size_t vc_vector_struct_size(); + +// ---------------------------------------------------------------------------- +// Element access +// ---------------------------------------------------------------------------- + +// Returns the item at index position in the vector. +void* vc_vector_at(vc_vector* vector, size_t index); + +// Returns the first item in the vector. +void* vc_vector_front(vc_vector* vector); + +// Returns the last item in the vector. +void* vc_vector_back(vc_vector* vector); + +// Returns a pointer to the data stored in the vector. The pointer can be used to access and modify the items in the vector. +void* vc_vector_data(vc_vector* vector); + +// ---------------------------------------------------------------------------- +// Iterators +// ---------------------------------------------------------------------------- + +// Returns a pointer to the first item in the vector. +void* vc_vector_begin(vc_vector* vector); + +// Returns a pointer to the imaginary item after the last item in the vector. +void* vc_vector_end(vc_vector* vector); + +// Returns a pointer to the next element of vector after 'i'. +void* vc_vector_next(vc_vector* vector, void* i); + +// ---------------------------------------------------------------------------- +// Capacity +// ---------------------------------------------------------------------------- + +// Returns true if the vector is empty; otherwise returns false. +bool vc_vector_empty(vc_vector* vector); + +// Returns the number of elements in the vector. +size_t vc_vector_count(const vc_vector* vector); + +// Returns the size (in bytes) of occurrences of value in the vector. +size_t vc_vector_size(const vc_vector* vector); + +// Returns the maximum number of elements that the vector can hold. +size_t vc_vector_max_count(const vc_vector* vector); + +// Returns the maximum size (in bytes) that the vector can hold. +size_t vc_vector_max_size(const vc_vector* vector); + +// Resizes the container so that it contains n elements. +bool vc_vector_reserve_count(vc_vector* vector, size_t new_count); + +// Resizes the container so that it contains new_size / element_size elements. +bool vc_vector_reserve_size(vc_vector* vector, size_t new_size); + +// ---------------------------------------------------------------------------- +// Modifiers +// ---------------------------------------------------------------------------- + +// Removes all elements from the vector (without reallocation). +void vc_vector_clear(vc_vector* vector); + +// The container is extended by inserting a new element at position. +bool vc_vector_insert(vc_vector* vector, size_t index, const void* value); + +// Removes from the vector a single element by 'index' +bool vc_vector_erase(vc_vector* vector, size_t index); + +// Removes from the vector a range of elements '[first_index, last_index)'. +bool vc_vector_erase_range(vc_vector* vector, size_t first_index, size_t last_index); + +// Inserts multiple values at the end of the vector. +bool vc_vector_append(vc_vector* vector, const void* values, size_t count); + +// Inserts value at the end of the vector. +bool vc_vector_push_back(vc_vector* vector, const void* value); + +// Removes the last item in the vector. +bool vc_vector_pop_back(vc_vector* vector); + +// Replace value by index in the vector. +bool vc_vector_replace(vc_vector* vector, size_t index, const void* value); + +// Replace multiple values by index in the vector. +bool vc_vector_replace_multiple(vc_vector* vector, size_t index, const void* values, size_t count); + +#ifdef __cplusplus +} +#endif + +#endif // VCVECTOR_H