diff --git a/Makefile.common b/Makefile.common index 2a715f4786a2..c69472a61b6f 100644 --- a/Makefile.common +++ b/Makefile.common @@ -2381,12 +2381,37 @@ ifeq ($(HAVE_STATIC_VIDEO_FILTERS), 1) gfx/video_filters/upscale_mix_240x160_320x240.o endif -ifeq ($(WANT_IOSUHAX), 1) - DEFINES += -DHAVE_IOSUHAX - INCLUDE_DIRS += -I$(DEPS_DIR)/libiosuhax/include - OBJ += $(DEPS_DIR)/libiosuhax/source/iosuhax.o \ - $(DEPS_DIR)/libiosuhax/source/iosuhax_devoptab.o \ - $(DEPS_DIR)/libiosuhax/source/iosuhax_disc_interface.o +ifeq ($(WANT_LIBMOCHA), 1) + DEFINES += -DHAVE_LIBMOCHA + INCLUDE_DIRS += -I$(DEPS_DIR)/libmocha/include + OBJ += $(DEPS_DIR)/libmocha/source/disc_interface.o \ + $(DEPS_DIR)/libmocha/source/fsa.o \ + $(DEPS_DIR)/libmocha/source/utils.o \ + $(DEPS_DIR)/libmocha/source/devoptab/devoptab_fsa_chdir.o \ + $(DEPS_DIR)/libmocha/source/devoptab/devoptab_fsa_chmod.o \ + $(DEPS_DIR)/libmocha/source/devoptab/devoptab_fsa_close.o \ + $(DEPS_DIR)/libmocha/source/devoptab/devoptab_fsa.o \ + $(DEPS_DIR)/libmocha/source/devoptab/devoptab_fsa_dirclose.o \ + $(DEPS_DIR)/libmocha/source/devoptab/devoptab_fsa_dirnext.o \ + $(DEPS_DIR)/libmocha/source/devoptab/devoptab_fsa_diropen.o \ + $(DEPS_DIR)/libmocha/source/devoptab/devoptab_fsa_dirreset.o \ + $(DEPS_DIR)/libmocha/source/devoptab/devoptab_fsa_fchmod.o \ + $(DEPS_DIR)/libmocha/source/devoptab/devoptab_fsa_fstat.o \ + $(DEPS_DIR)/libmocha/source/devoptab/devoptab_fsa_fsync.o \ + $(DEPS_DIR)/libmocha/source/devoptab/devoptab_fsa_link.o \ + $(DEPS_DIR)/libmocha/source/devoptab/devoptab_fsa_mkdir.o \ + $(DEPS_DIR)/libmocha/source/devoptab/devoptab_fsa_open.o \ + $(DEPS_DIR)/libmocha/source/devoptab/devoptab_fsa_read.o \ + $(DEPS_DIR)/libmocha/source/devoptab/devoptab_fsa_rename.o \ + $(DEPS_DIR)/libmocha/source/devoptab/devoptab_fsa_rmdir.o \ + $(DEPS_DIR)/libmocha/source/devoptab/devoptab_fsa_seek.o \ + $(DEPS_DIR)/libmocha/source/devoptab/devoptab_fsa_stat.o \ + $(DEPS_DIR)/libmocha/source/devoptab/devoptab_fsa_statvfs.o \ + $(DEPS_DIR)/libmocha/source/devoptab/devoptab_fsa_truncate.o \ + $(DEPS_DIR)/libmocha/source/devoptab/devoptab_fsa_unlink.o \ + $(DEPS_DIR)/libmocha/source/devoptab/devoptab_fsa_utils.o \ + $(DEPS_DIR)/libmocha/source/devoptab/devoptab_fsa_utimes.o \ + $(DEPS_DIR)/libmocha/source/devoptab/devoptab_fsa_write.o endif ifeq ($(WANT_LIBFAT), 1) diff --git a/Makefile.wiiu b/Makefile.wiiu index e1f96a04ebb0..c6d1a8884e7a 100644 --- a/Makefile.wiiu +++ b/Makefile.wiiu @@ -1,10 +1,8 @@ TARGET := retroarch_wiiu -BUILD_HBL_ELF = 1 -BUILD_RPX = 1 DEBUG = 0 GRIFFIN_BUILD = 0 -SALAMANDER_BUILD = 0 +SALAMANDER_BUILD ?= 0 HAVE_STATIC_DUMMY ?= 0 WHOLE_ARCHIVE_LINK = 0 WIIU_HID = 1 @@ -37,25 +35,20 @@ INCDIRS := #----------------------------- # Features and object files -OBJ += wiiu/main.o OBJ += wiiu/system/memory.o OBJ += wiiu/system/atomic.o OBJ += wiiu/system/exception_handler.o OBJ += wiiu/system/missing_libc_functions.o -OBJ += wiiu/fs/sd_fat_devoptab.o -OBJ += wiiu/fs/fs_utils.o -OBJ += wiiu/hbl.o - -RPX_OBJ = $(BUILD_DIR)/wiiu/system/stubs_rpl.o -HBL_ELF_OBJ = $(BUILD_DIR)/wiiu/system/dynamic.o \ - $(BUILD_DIR)/wiiu/system/stubs_elf.o ifeq ($(SALAMANDER_BUILD),1) DEFINES += -DRARCH_CONSOLE -DIS_SALAMANDER + INCDIRS += -Ideps/libmocha/include + OBJ += frontend/frontend_salamander.o OBJ += frontend/frontend_driver.o OBJ += frontend/drivers/platform_wiiu.o + OBJ += deps/libmocha/source/utils.o OBJ += libretro-common/encodings/encoding_utf.o OBJ += libretro-common/compat/compat_strcasestr.o OBJ += libretro-common/compat/fopen_utf8.o @@ -110,7 +103,7 @@ endif INCDIRS += -Ilibretro-common/include/compat/zlib # for stb, libfat, iosuhax - INCDIRS += -Ideps -Ideps/libfat/include -Ideps/libiosuhax/include + INCDIRS += -Ideps # pad_functions uses wiiu/input.h INCDIRS += -Iinput/include INCDIRS += -Ideps/SPIRV-Cross @@ -126,7 +119,6 @@ endif #DEFINES += -DHAVE_FREETYPE DEFINES += -DHAVE_XMB -DHAVE_MATERIALUI DEFINES += -DHAVE_HID - DEFINES += -DWANT_LIBFAT -DHAVE_LIBFAT -DWANT_IOSUHAX -DHAVE_IOSUHAX DEFINES += -DHAVE_CORE_INFO_CACHE DEFINES += -DSPIRV_CROSS_EXCEPTIONS_TO_ASSERTIONS @@ -171,7 +163,7 @@ endif HAVE_STATIC_VIDEO_FILTERS = 1 HAVE_STATIC_AUDIO_FILTERS = 1 WANT_LIBFAT = 1 - WANT_IOSUHAX = 1 + WANT_LIBMOCHA = 1 HAVE_CORE_INFO_CACHE = 1 include Makefile.common @@ -248,15 +240,6 @@ ifeq ($(HAVE_BUILTINZLIB),0) endif endif -LDFLAGS += -Wl,--gc-sections - -RPX_LDFLAGS := -pie -fPIE -RPX_LDFLAGS += -z common-page-size=64 -z max-page-size=64 -RPX_LDFLAGS += -T wiiu/link_rpl.ld -RPX_LDFLAGS += -nostartfiles - -HBL_ELF_LDFLAGS := -T wiiu/link_elf.ld - #----------------------------- # Compiler setup @@ -267,7 +250,7 @@ ifeq ($(strip $(DEVKITPRO)),) $(error "Please set DEVKITPRO in your environment. export DEVKITPRO=devkitPRO") endif -export PATH := $(PATH):$(DEVKITPPC)/bin +export PATH := $(PATH):$(DEVKITPPC)/bin:$(DEVKITPRO)/tools/bin PREFIX := powerpc-eabi- @@ -280,25 +263,19 @@ STRIP := $(PREFIX)strip NM := $(PREFIX)nm LD := $(CXX) -ELF2RPL := wiiu/wut/elf2rpl/elf2rpl +WUT_ROOT ?= $(DEVKITPRO)/wut -ifneq ($(findstring Linux,$(shell uname -a)),) -else ifneq ($(findstring Darwin,$(shell uname -a)),) -else - ELF2RPL := $(ELF2RPL).exe -endif +RPXSPECS := -specs=$(WUT_ROOT)/share/wut.specs +RPLSPECS := -specs=$(WUT_ROOT)/share/wut.specs -specs=$(WUT_ROOT)/share/rpl.specs + +INCDIRS += -I$(WUT_ROOT)/include +LIBDIRS += -L$(WUT_ROOT)/lib +LIBS += -lwut #----------------------------- # Targets and build rules -TARGETS := -ifeq ($(BUILD_RPX), 1) -TARGETS += $(TARGET).rpx -endif - -ifeq ($(BUILD_HBL_ELF), 1) -TARGETS += $(TARGET).elf -endif +TARGETS := $(TARGET).rpx DEPFLAGS = -MT $@ -MMD -MP -MF $(BUILD_DIR)/$*.depend @@ -334,38 +311,21 @@ $(BUILD_DIR)/%.o: %.s %.depend %.depend: ; %.last: ; -$(ELF2RPL): - @$(if $(Q), echo MAKE $@,) - $(Q)$(MAKE) -C wiiu/wut/elf2rpl/ - -$(BUILD_DIR)/$(TARGET).elf: $(OBJ) $(HBL_ELF_OBJ) libretro_wiiu.a wiiu/link_elf.ld .$(TARGET).elf.last +$(BUILD_DIR)/$(TARGET).rpx.elf: $(OBJ) libretro_wiiu.a @$(if $(Q), echo LD $@,) - @touch .$(TARGET).elf.last - $(Q)$(LD) $(OBJ) $(HBL_ELF_OBJ) $(LDFLAGS) $(HBL_ELF_LDFLAGS) $(LIBDIRS) $(LIBS) -o $@ + $(Q)$(LD) $(OBJ) $(RPXSPECS) $(LDFLAGS) $(LIBDIRS) $(LIBS) -o $@ -$(BUILD_DIR)/$(TARGET).rpx.elf: $(OBJ) $(RPX_OBJ) libretro_wiiu.a wiiu/link_elf.ld - @$(if $(Q), echo LD $@,) - $(Q)$(LD) $(OBJ) $(RPX_OBJ) $(LDFLAGS) $(RPX_LDFLAGS) $(LIBDIRS) $(LIBS) -o $@ - -$(BUILD_DIR)/$(TARGET).large.rpx: $(BUILD_DIR)/$(TARGET).rpx.elf $(ELF2RPL) .$(TARGET).rpx.large.last +$(BUILD_DIR)/$(TARGET).rpx: $(BUILD_DIR)/$(TARGET).rpx.elf @$(if $(Q), echo ELF2RPL $@,) - @touch .$(TARGET).rpx.large.last - $(Q)-$(ELF2RPL) $< $@ - -$(BUILD_DIR)/$(TARGET).rpx: $(BUILD_DIR)/$(TARGET).large.rpx .$(TARGET).rpx.last - @$(if $(Q), echo COMPRESS $@,) - @touch .$(TARGET).rpx.large.last - $(Q)wiiurpxtool -c $< $@ + $(Q)elf2rpl $< $@ clean: @$(if $(Q), echo $@,) - $(Q)rm -f $(OBJ) $(RPX_OBJ) $(HBL_ELF_OBJ) $(TARGET).elf $(TARGET).rpx.elf $(TARGET).rpx - $(Q)rm -f $(BUILD_DIR)/$(TARGET).elf $(BUILD_DIR)/$(TARGET).rpx.elf $(BUILD_DIR)/$(TARGET).large.rpx $(BUILD_DIR)/$(TARGET).rpx - $(Q)rm -f .$(TARGET).elf.last .$(TARGET).rpx.elf.last .$(TARGET).rpx.large.last .$(TARGET).rpx.last - $(Q)rm -f $(OBJ:.o=.depend) $(RPX_OBJ:.o=.depend) $(HBL_ELF_OBJ:.o=.depend) - $(Q)$(MAKE) -C wiiu/wut/elf2rpl/ clean + $(Q)rm -f $(OBJ) $(TARGET).rpx.elf $(TARGET).rpx + $(Q)rm -f $(BUILD_DIR)/$(TARGET).rpx.elf $(BUILD_DIR)/$(TARGET).rpx + $(Q)rm -f $(OBJ:.o=.depend) .PHONY: clean all .PRECIOUS: %.depend %.last --include $(OBJ:.o=.depend) $(RPX_OBJ:.o=.depend) $(HBL_ELF_OBJ:.o=.depend) +-include $(OBJ:.o=.depend) diff --git a/audio/drivers/wiiu_audio.c b/audio/drivers/wiiu_audio.c index de5d3d93531c..9065a66297fa 100644 --- a/audio/drivers/wiiu_audio.c +++ b/audio/drivers/wiiu_audio.c @@ -18,8 +18,12 @@ #include #include -#include -#include + +#include +#include +#include +#include +#include #include "../../wiiu/wiiu_dbg.h" #include "../../wiiu/system/memory.h" @@ -75,16 +79,15 @@ void wiiu_ax_callback(void) } } -extern void AXRegisterFrameCallback(void *cb); - static void* ax_audio_init(const char* device, unsigned rate, unsigned latency, unsigned block_frames, unsigned *new_rate) { AXVoiceOffsets offsets[2]; - u16 setup_buf[0x30] = {0}; - setup_buf[0x25] = 2; /* we request 2 channels */ - AXInitParams init = {AX_INIT_RENDERER_48KHZ, 0, 0}; + DspConfig setup_buf = {0}; + setup_buf.multi_ch_count = 2; + + AXInitParams init = {AX_INIT_RENDERER_48KHZ, {0, 0}}; AXVoiceVeData ve = {0x8000, 0}; ax_audio_t* ax = (ax_audio_t*)calloc(1, sizeof(ax_audio_t)); @@ -93,7 +96,7 @@ static void* ax_audio_init(const char* device, unsigned rate, unsigned latency, AXInitWithParams(&init); - AXAcquireMultiVoice(31, NULL, 0, setup_buf, &ax->mvoice); + AXAcquireMultiVoice(31, NULL, 0, &setup_buf, &ax->mvoice); if (!ax->mvoice || ax->mvoice->channels != 2) { diff --git a/config.def.h b/config.def.h index cc69a5b4a0ef..c9282607ae20 100644 --- a/config.def.h +++ b/config.def.h @@ -894,7 +894,7 @@ #define DEFAULT_SYSTEMFILES_IN_CONTENT_DIR false #define DEFAULT_SCREENSHOTS_IN_CONTENT_DIR false -#if defined(RS90) || defined(RETROFW) || defined(MIYOO) || defined(SWITCH) || defined(ORBIS) || defined(__WINRT__) +#if defined(RS90) || defined(RETROFW) || defined(MIYOO) || defined(SWITCH) || defined(ORBIS) || defined(__WINRT__) || defined(WIIU) #define DEFAULT_MENU_TOGGLE_GAMEPAD_COMBO INPUT_COMBO_START_SELECT #elif defined(_XBOX1) || defined(__PS3__) || defined(_XBOX360) || defined(DINGUX) #define DEFAULT_MENU_TOGGLE_GAMEPAD_COMBO INPUT_COMBO_L3_R3 @@ -943,6 +943,12 @@ #define DEFAULT_ALL_USERS_CONTROL_MENU false #endif +#if defined(WIIU) +/* On Wii U, whether the HOME button should open the OS's HOME menu, or simply toggle the RetroArch menu (as it did in + * older HBL/Tiramisu builds of RetroArch) */ +#define DEFAULT_WIIU_ENABLE_HBM true +#endif + #define DEFAULT_QUIT_PRESS_TWICE true #define DEFAULT_LOG_TO_FILE false diff --git a/configuration.c b/configuration.c index 989fa64bfab5..564afb654b20 100644 --- a/configuration.c +++ b/configuration.c @@ -2103,6 +2103,9 @@ static struct config_bool_setting *populate_settings_bool( #endif #if defined(HAVE_DINPUT) || defined(HAVE_WINRAWINPUT) SETTING_BOOL("input_nowinkey_enable", &settings->bools.input_nowinkey_enable, true, false, false); +#endif +#ifdef WIIU + SETTING_BOOL("input_wiiu_enable_hbm", &settings->bools.input_wiiu_enable_hbm, true, DEFAULT_WIIU_ENABLE_HBM, false); #endif SETTING_BOOL("input_sensors_enable", &settings->bools.input_sensors_enable, true, DEFAULT_INPUT_SENSORS_ENABLE, false); SETTING_BOOL("vibrate_on_keypress", &settings->bools.vibrate_on_keypress, true, DEFAULT_VIBRATE_ON_KEYPRESS, false); diff --git a/configuration.h b/configuration.h index 71d194f8288d..96947d14d4c9 100644 --- a/configuration.h +++ b/configuration.h @@ -704,6 +704,9 @@ typedef struct settings bool input_touch_vmouse_trackball; bool input_touch_vmouse_gesture; #endif +#ifdef WIIU + bool input_wiiu_enable_hbm; +#endif /* Frame time counter */ bool frame_time_counter_reset_after_fastforwarding; diff --git a/deps/libfat/common.h b/deps/libfat/common.h index 66ca7bf77ed3..d5e4191aa0d5 100644 --- a/deps/libfat/common.h +++ b/deps/libfat/common.h @@ -42,7 +42,7 @@ /* Platform specific includes */ #if defined (__wiiu__) - #include + #include typedef uint8_t u8; typedef uint16_t u16; typedef int32_t s32; diff --git a/deps/libfat/disc.c b/deps/libfat/disc.c index 15397e9953a7..89cd299a016b 100644 --- a/deps/libfat/disc.c +++ b/deps/libfat/disc.c @@ -40,16 +40,16 @@ The list is terminated by a NULL/NULL entry. /* ====================== Wii U ====================== */ #if defined (__wiiu__) -#include +#include static const DISC_INTERFACE* get_io_wiiu_sd (void) { - return &IOSUHAX_sdio_disc_interface; + return &Mocha_sdio_disc_interface; } static const DISC_INTERFACE* get_io_wiiu_usb (void) { - return &IOSUHAX_usb_disc_interface; + return &Mocha_usb_disc_interface; } const INTERFACE_ID _FAT_disc_interfaces[] = { diff --git a/deps/libfat/include/fat.h b/deps/libfat/include/fat.h index d466ffee895f..36878d286f61 100644 --- a/deps/libfat/include/fat.h +++ b/deps/libfat/include/fat.h @@ -48,7 +48,7 @@ extern "C" { #include #if defined (__wiiu__) -# include +# include #elif defined(__gamecube__) || defined (__wii__) # include #else diff --git a/deps/libfat/mem_allocate.h b/deps/libfat/mem_allocate.h index 35ad3966b6ad..585471080c39 100644 --- a/deps/libfat/mem_allocate.h +++ b/deps/libfat/mem_allocate.h @@ -5,7 +5,7 @@ malloc is unavailable Copyright (c) 2006 Michael "Chishm" Chisholm - + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -42,6 +42,8 @@ static inline void* _FAT_mem_align (size_t size) { #ifdef __wii__ return memalign (32, size); +#elif defined(__wiiu__) + return memalign (64, size); #else return malloc (size); #endif diff --git a/deps/libiosuhax/.github/workflows/push_image.yml b/deps/libiosuhax/.github/workflows/push_image.yml deleted file mode 100644 index 9cd7bbdb42c7..000000000000 --- a/deps/libiosuhax/.github/workflows/push_image.yml +++ /dev/null @@ -1,25 +0,0 @@ -name: Publish Docker Image -on: - push: - branches: - - master -jobs: - build: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@master - - name: Get release version - id: get_release_tag - run: | - echo RELEASE_VERSION=$(echo $(date '+%Y%m%d')) >> $GITHUB_ENV - echo REPOSITORY_NAME=$(echo "$GITHUB_REPOSITORY" | awk -F / '{print $2}' | sed -e "s/:refs//" | tr '[:upper:]' '[:lower:]') >> $GITHUB_ENV - echo REPOSITORY_OWNER=$(echo "$GITHUB_REPOSITORY" | awk -F / '{print $1}' | sed 's/[^a-zA-Z0-9]//g' | tr '[:upper:]' '[:lower:]') >> $GITHUB_ENV - - name: Publish to Registry - uses: elgohr/Publish-Docker-Github-Action@master - with: - name: ${{ env.REPOSITORY_OWNER }}/${{ env.REPOSITORY_NAME }} - username: ${{ secrets.DOCKER_USERNAME }} - password: ${{ secrets.DOCKER_PASSWORD }} - snapshot: true - cache: true - tags: "latest, ${{ env.RELEASE_VERSION }}" \ No newline at end of file diff --git a/deps/libiosuhax/.gitignore b/deps/libiosuhax/.gitignore deleted file mode 100644 index 0955c90e6e43..000000000000 --- a/deps/libiosuhax/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -/*.a -/build -*.bz2 -release/ -lib/ diff --git a/deps/libiosuhax/.travis.yml b/deps/libiosuhax/.travis.yml deleted file mode 100644 index ff1f980eaa31..000000000000 --- a/deps/libiosuhax/.travis.yml +++ /dev/null @@ -1,29 +0,0 @@ -language: cpp - -os: linux -sudo: false -dist: trusty - -env: - global: - - DEVKITPRO=/opt/devkitpro - - DEVKITPPC=/opt/devkitpro/devkitPPC - -cache: - directories: - - "$HOME/.local" - - "$DEVKITPRO" - -addons: - apt: - packages: - - p7zip-full - -before_install: - - mkdir -p "${DEVKITPRO}" - - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then wget https://github.com/devkitPro/pacman/releases/download/devkitpro-pacman-1.0.1/devkitpro-pacman.deb -O /tmp/devkitpro-pacman.deb; fi - - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo dpkg -i /tmp/devkitpro-pacman.deb; fi - - yes | sudo dkp-pacman -Syu devkitPPC --needed - -script: - - make && make install \ No newline at end of file diff --git a/deps/libiosuhax/README.md b/deps/libiosuhax/README.md deleted file mode 100644 index 1fc12350920e..000000000000 --- a/deps/libiosuhax/README.md +++ /dev/null @@ -1,10 +0,0 @@ -[![Build Status](https://travis-ci.org/dimok789/libiosuhax.svg)](https://travis-ci.org/dimok789/libiosuhax) -# libiosuhax -A PPC library to access IOSUHAX from PPC and a devoptab for any device or path. -It's only compatible to RPX-Files. - -## Building -Make you to have [wut](https://github.com/devkitPro/wut/) installed and use the following command for build: -``` -make install -``` diff --git a/deps/libiosuhax/include/iosuhax.h b/deps/libiosuhax/include/iosuhax.h deleted file mode 100644 index 9b2350b7fdb0..000000000000 --- a/deps/libiosuhax/include/iosuhax.h +++ /dev/null @@ -1,112 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2016 - * by Dimok - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event will the authors be held liable for any - * damages arising from the use of this software. - * - * Permission is granted to anyone to use this software for any - * purpose, including commercial applications, and to alter it and - * redistribute it freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented; you - * must not claim that you wrote the original software. If you use - * this software in a product, an acknowledgment in the product - * documentation would be appreciated but is not required. - * - * 2. Altered source versions must be plainly marked as such, and - * must not be misrepresented as being the original software. - * - * 3. This notice may not be removed or altered from any source - * distribution. - ***************************************************************************/ -#ifndef _LIB_IOSUHAX_H_ -#define _LIB_IOSUHAX_H_ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#define IOS_ERROR_UNKNOWN_VALUE 0xFFFFFFD6 -#define IOS_ERROR_INVALID_ARG 0xFFFFFFE3 -#define IOS_ERROR_INVALID_SIZE 0xFFFFFFE9 -#define IOS_ERROR_UNKNOWN 0xFFFFFFF7 -#define IOS_ERROR_NOEXISTS 0xFFFFFFFA - -typedef struct -{ - uint32_t flag; - uint32_t permission; - uint32_t owner_id; - uint32_t group_id; - uint32_t size; // size in bytes - uint32_t physsize; // physical size on disk in bytes - uint32_t unk[3]; - uint32_t id; - uint32_t ctime; - uint32_t mtime; - uint32_t unk2[0x0D]; -}fileStat_s; - -typedef struct -{ - fileStat_s stat; - char name[0x100]; -}directoryEntry_s; - -#define DIR_ENTRY_IS_DIRECTORY 0x80000000 - -#define FSA_MOUNTFLAGS_BINDMOUNT (1 << 0) -#define FSA_MOUNTFLAGS_GLOBAL (1 << 1) - -int IOSUHAX_Open(const char *dev); // if dev == NULL the default path /dev/iosuhax will be used -int IOSUHAX_Close(void); - -int IOSUHAX_memwrite(uint32_t address, const uint8_t * buffer, uint32_t size); // IOSU external input -int IOSUHAX_memread(uint32_t address, uint8_t * out_buffer, uint32_t size); // IOSU external output -int IOSUHAX_memcpy(uint32_t dst, uint32_t src, uint32_t size); // IOSU internal memcpy only - -int IOSUHAX_kern_write32(uint32_t address, uint32_t value); -int IOSUHAX_kern_read32(uint32_t address, uint32_t* out_buffer, uint32_t count); - -int IOSUHAX_SVC(uint32_t svc_id, uint32_t * args, uint32_t arg_cnt); - -int IOSUHAX_FSA_Open(); -int IOSUHAX_FSA_Close(int fsaFd); - -int IOSUHAX_FSA_Mount(int fsaFd, const char* device_path, const char* volume_path, uint32_t flags, const char* arg_string, int arg_string_len); -int IOSUHAX_FSA_Unmount(int fsaFd, const char* path, uint32_t flags); -int IOSUHAX_FSA_FlushVolume(int fsaFd, const char* volume_path); - -int IOSUHAX_FSA_GetDeviceInfo(int fsaFd, const char* device_path, int type, uint32_t* out_data); - -int IOSUHAX_FSA_MakeDir(int fsaFd, const char* path, uint32_t flags); -int IOSUHAX_FSA_OpenDir(int fsaFd, const char* path, int* outHandle); -int IOSUHAX_FSA_ReadDir(int fsaFd, int handle, directoryEntry_s* out_data); -int IOSUHAX_FSA_RewindDir(int fsaFd, int dirHandle); -int IOSUHAX_FSA_CloseDir(int fsaFd, int handle); -int IOSUHAX_FSA_ChangeDir(int fsaFd, const char *path); - -int IOSUHAX_FSA_OpenFile(int fsaFd, const char* path, const char* mode, int* outHandle); -int IOSUHAX_FSA_ReadFile(int fsaFd, void* data, uint32_t size, uint32_t cnt, int fileHandle, uint32_t flags); -int IOSUHAX_FSA_WriteFile(int fsaFd, const void* data, uint32_t size, uint32_t cnt, int fileHandle, uint32_t flags); -int IOSUHAX_FSA_StatFile(int fsaFd, int fileHandle, fileStat_s* out_data); -int IOSUHAX_FSA_CloseFile(int fsaFd, int fileHandle); -int IOSUHAX_FSA_SetFilePos(int fsaFd, int fileHandle, uint32_t position); -int IOSUHAX_FSA_GetStat(int fsaFd, const char *path, fileStat_s* out_data); -int IOSUHAX_FSA_Remove(int fsaFd, const char *path); -int IOSUHAX_FSA_ChangeMode(int fsaFd, const char* path, int mode); - -int IOSUHAX_FSA_RawOpen(int fsaFd, const char* device_path, int* outHandle); -int IOSUHAX_FSA_RawRead(int fsaFd, void* data, uint32_t block_size, uint32_t block_cnt, uint64_t sector_offset, int device_handle); -int IOSUHAX_FSA_RawWrite(int fsaFd, const void* data, uint32_t block_size, uint32_t block_cnt, uint64_t sector_offset, int device_handle); -int IOSUHAX_FSA_RawClose(int fsaFd, int device_handle); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/deps/libiosuhax/include/iosuhax_devoptab.h b/deps/libiosuhax/include/iosuhax_devoptab.h deleted file mode 100644 index 18847a683c0b..000000000000 --- a/deps/libiosuhax/include/iosuhax_devoptab.h +++ /dev/null @@ -1,42 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2015 - * by Dimok - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event will the authors be held liable for any - * damages arising from the use of this software. - * - * Permission is granted to anyone to use this software for any - * purpose, including commercial applications, and to alter it and - * redistribute it freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented; you - * must not claim that you wrote the original software. If you use - * this software in a product, an acknowledgment in the product - * documentation would be appreciated but is not required. - * - * 2. Altered source versions must be plainly marked as such, and - * must not be misrepresented as being the original software. - * - * 3. This notice may not be removed or altered from any source - * distribution. - ***************************************************************************/ -#ifndef __IOSUHAX_DEVOPTAB_H_ -#define __IOSUHAX_DEVOPTAB_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -//! virtual name example: sd or odd (for sd:/ or odd:/ access) -//! fsaFd: fd received by IOSUHAX_FSA_Open(); -//! dev_path: (optional) if a device should be mounted to the mount_path. If NULL no IOSUHAX_FSA_Mount is not executed. -//! mount_path: path to map to virtual device name -int mount_fs(const char *virt_name, int fsaFd, const char *dev_path, const char *mount_path); -int unmount_fs(const char *virt_name); - -#ifdef __cplusplus -} -#endif - -#endif // __IOSUHAX_DEVOPTAB_H_ diff --git a/deps/libiosuhax/source/iosuhax.c b/deps/libiosuhax/source/iosuhax.c deleted file mode 100644 index bf6032850d19..000000000000 --- a/deps/libiosuhax/source/iosuhax.c +++ /dev/null @@ -1,956 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2016 - * by Dimok - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event will the authors be held liable for any - * damages arising from the use of this software. - * - * Permission is granted to anyone to use this software for any - * purpose, including commercial applications, and to alter it and - * redistribute it freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented; you - * must not claim that you wrote the original software. If you use - * this software in a product, an acknowledgment in the product - * documentation would be appreciated but is not required. - * - * 2. Altered source versions must be plainly marked as such, and - * must not be misrepresented as being the original software. - * - * 3. This notice may not be removed or altered from any source - * distribution. - ***************************************************************************/ -#include -#include -#include "os_functions.h" -#include "iosuhax.h" - -#define IOSUHAX_MAGIC_WORD 0x4E696365 - -#define IOCTL_MEM_WRITE 0x00 -#define IOCTL_MEM_READ 0x01 -#define IOCTL_SVC 0x02 -#define IOCTL_MEMCPY 0x04 -#define IOCTL_REPEATED_WRITE 0x05 -#define IOCTL_KERN_READ32 0x06 -#define IOCTL_KERN_WRITE32 0x07 - -#define IOCTL_FSA_OPEN 0x40 -#define IOCTL_FSA_CLOSE 0x41 -#define IOCTL_FSA_MOUNT 0x42 -#define IOCTL_FSA_UNMOUNT 0x43 -#define IOCTL_FSA_GETDEVICEINFO 0x44 -#define IOCTL_FSA_OPENDIR 0x45 -#define IOCTL_FSA_READDIR 0x46 -#define IOCTL_FSA_CLOSEDIR 0x47 -#define IOCTL_FSA_MAKEDIR 0x48 -#define IOCTL_FSA_OPENFILE 0x49 -#define IOCTL_FSA_READFILE 0x4A -#define IOCTL_FSA_WRITEFILE 0x4B -#define IOCTL_FSA_STATFILE 0x4C -#define IOCTL_FSA_CLOSEFILE 0x4D -#define IOCTL_FSA_SETFILEPOS 0x4E -#define IOCTL_FSA_GETSTAT 0x4F -#define IOCTL_FSA_REMOVE 0x50 -#define IOCTL_FSA_REWINDDIR 0x51 -#define IOCTL_FSA_CHDIR 0x52 -#define IOCTL_FSA_RENAME 0x53 -#define IOCTL_FSA_RAW_OPEN 0x54 -#define IOCTL_FSA_RAW_READ 0x55 -#define IOCTL_FSA_RAW_WRITE 0x56 -#define IOCTL_FSA_RAW_CLOSE 0x57 -#define IOCTL_FSA_CHANGEMODE 0x58 -#define IOCTL_FSA_FLUSHVOLUME 0x59 -#define IOCTL_CHECK_IF_IOSUHAX 0x5B - -static int iosuhaxHandle = -1; - -#define ALIGN(align) __attribute__((aligned(align))) -#define ROUNDUP(x, align) (((x) + ((align) - 1)) & ~((align) - 1)) - -int IOSUHAX_Open(const char *dev) -{ - if(iosuhaxHandle >= 0) - return iosuhaxHandle; - - iosuhaxHandle = IOS_Open((char*)(dev ? dev : "/dev/iosuhax"), 0); - if(iosuhaxHandle >= 0 && dev) //make sure device is actually iosuhax - { - ALIGN(0x20) int res[0x20 >> 2]; - *res = 0; - - IOS_Ioctl(iosuhaxHandle, IOCTL_CHECK_IF_IOSUHAX, (void*)0, 0, res, 4); - if(*res != IOSUHAX_MAGIC_WORD) - { - IOS_Close(iosuhaxHandle); - iosuhaxHandle = -1; - } - } - - return iosuhaxHandle; -} - -int IOSUHAX_Close(void) -{ - if(iosuhaxHandle < 0) - return 0; - - int res = IOS_Close(iosuhaxHandle); - iosuhaxHandle = -1; - return res; -} - -int IOSUHAX_memwrite(uint32_t address, const uint8_t * buffer, uint32_t size) -{ - if(iosuhaxHandle < 0) - return iosuhaxHandle; - - uint32_t *io_buf = (uint32_t*)memalign(0x20, ROUNDUP(size + 4, 0x20)); - if(!io_buf) - return -2; - - io_buf[0] = address; - memcpy(io_buf + 1, buffer, size); - - int res = IOS_Ioctl(iosuhaxHandle, IOCTL_MEM_WRITE, io_buf, size + 4, 0, 0); - - free(io_buf); - return res; -} - -int IOSUHAX_memread(uint32_t address, uint8_t * out_buffer, uint32_t size) -{ - if(iosuhaxHandle < 0) - return iosuhaxHandle; - - ALIGN(0x20) int io_buf[0x20 >> 2]; - io_buf[0] = address; - - void* tmp_buf = NULL; - - if(((uintptr_t)out_buffer & 0x1F) || (size & 0x1F)) - { - tmp_buf = (uint32_t*)memalign(0x20, ROUNDUP(size, 0x20)); - if(!tmp_buf) - return -2; - } - - int res = IOS_Ioctl(iosuhaxHandle, IOCTL_MEM_READ, io_buf, sizeof(address), tmp_buf ? tmp_buf : out_buffer, size); - - if(res >= 0 && tmp_buf) - memcpy(out_buffer, tmp_buf, size); - - free(tmp_buf); - return res; -} - -int IOSUHAX_memcpy(uint32_t dst, uint32_t src, uint32_t size) -{ - if(iosuhaxHandle < 0) - return iosuhaxHandle; - - ALIGN(0x20) uint32_t io_buf[0x20 >> 2]; - io_buf[0] = dst; - io_buf[1] = src; - io_buf[2] = size; - - return IOS_Ioctl(iosuhaxHandle, IOCTL_MEMCPY, io_buf, 3 * sizeof(uint32_t), 0, 0); -} - -int IOSUHAX_kern_write32(uint32_t address, uint32_t value) -{ - if(iosuhaxHandle < 0) - return iosuhaxHandle; - - ALIGN(0x20) uint32_t io_buf[0x20 >> 2]; - io_buf[0] = address; - io_buf[1] = value; - - return IOS_Ioctl(iosuhaxHandle, IOCTL_KERN_WRITE32, io_buf, 2 * sizeof(uint32_t), 0, 0); -} - -int IOSUHAX_kern_read32(uint32_t address, uint32_t* out_buffer, uint32_t count) -{ - if(iosuhaxHandle < 0) - return iosuhaxHandle; - - ALIGN(0x20) uint32_t io_buf[0x20 >> 2]; - io_buf[0] = address; - - void* tmp_buf = NULL; - - if(((uintptr_t)out_buffer & 0x1F) || ((count * 4) & 0x1F)) - { - tmp_buf = (uint32_t*)memalign(0x20, ROUNDUP((count * 4), 0x20)); - if(!tmp_buf) - return -2; - } - - int res = IOS_Ioctl(iosuhaxHandle, IOCTL_KERN_READ32, io_buf, sizeof(address), tmp_buf ? tmp_buf : out_buffer, count * 4); - - if(res >= 0 && tmp_buf) - memcpy(out_buffer, tmp_buf, count * 4); - - free(tmp_buf); - return res; -} - -int IOSUHAX_SVC(uint32_t svc_id, uint32_t * args, uint32_t arg_cnt) -{ - if(iosuhaxHandle < 0) - return iosuhaxHandle; - - ALIGN(0x20) uint32_t arguments[0x40 >> 2]; - arguments[0] = svc_id; - - if(args && arg_cnt) - { - if(arg_cnt > 8) - arg_cnt = 8; - - memcpy(arguments + 1, args, arg_cnt * 4); - } - - ALIGN(0x20) int result[0x20 >> 2]; - int ret = IOS_Ioctl(iosuhaxHandle, IOCTL_SVC, arguments, (1 + arg_cnt) * 4, result, 4); - if(ret < 0) - return ret; - - return *result; -} - -int IOSUHAX_FSA_Open(void) -{ - if(iosuhaxHandle < 0) - return iosuhaxHandle; - - ALIGN(0x20) int io_buf[0x20 >> 2]; - - int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_OPEN, 0, 0, io_buf, sizeof(int)); - if(res < 0) - return res; - - return io_buf[0]; -} - -int IOSUHAX_FSA_Close(int fsaFd) -{ - if(iosuhaxHandle < 0) - return iosuhaxHandle; - - ALIGN(0x20) int io_buf[0x20 >> 2]; - io_buf[0] = fsaFd; - - int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_CLOSE, io_buf, sizeof(fsaFd), io_buf, sizeof(fsaFd)); - if(res < 0) - return res; - - return io_buf[0]; -} - -int IOSUHAX_FSA_Mount(int fsaFd, const char* device_path, const char* volume_path, uint32_t flags, const char* arg_string, int arg_string_len) -{ - if(iosuhaxHandle < 0) - return iosuhaxHandle; - - const int input_cnt = 6; - - int io_buf_size = (sizeof(uint32_t) * input_cnt) + strlen(device_path) + strlen(volume_path) + arg_string_len + 3; - - ALIGN(0x20) int io_buf[ROUNDUP(io_buf_size, 0x20) >> 2]; - memset(io_buf, 0, io_buf_size); - - io_buf[0] = fsaFd; - io_buf[1] = sizeof(uint32_t) * input_cnt; - io_buf[2] = io_buf[1] + strlen(device_path) + 1; - io_buf[3] = flags; - io_buf[4] = arg_string_len ? ( io_buf[2] + strlen(volume_path) + 1) : 0; - io_buf[5] = arg_string_len; - - strcpy(((char*)io_buf) + io_buf[1], device_path); - strcpy(((char*)io_buf) + io_buf[2], volume_path); - - if(arg_string_len) - memcpy(((char*)io_buf) + io_buf[4], arg_string, arg_string_len); - - int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_MOUNT, io_buf, io_buf_size, io_buf, 4); - if(res < 0) - return res; - - return io_buf[0]; -} - -int IOSUHAX_FSA_Unmount(int fsaFd, const char* path, uint32_t flags) -{ - if(iosuhaxHandle < 0) - return iosuhaxHandle; - - const int input_cnt = 3; - - int io_buf_size = sizeof(uint32_t) * input_cnt + strlen(path) + 1; - - ALIGN(0x20) int io_buf[ROUNDUP(io_buf_size, 0x20) >> 2]; - - io_buf[0] = fsaFd; - io_buf[1] = sizeof(uint32_t) * input_cnt; - io_buf[2] = flags; - strcpy(((char*)io_buf) + io_buf[1], path); - - int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_UNMOUNT, io_buf, io_buf_size, io_buf, 4); - if(res < 0) - return res; - - return io_buf[0]; -} - -int IOSUHAX_FSA_FlushVolume(int fsaFd, const char *volume_path) -{ - if(iosuhaxHandle < 0) - return iosuhaxHandle; - - const int input_cnt = 2; - - int io_buf_size = sizeof(uint32_t) * input_cnt + strlen(volume_path) + 1; - - ALIGN(0x20) int io_buf[ROUNDUP(io_buf_size, 0x20) >> 2]; - - io_buf[0] = fsaFd; - io_buf[1] = sizeof(uint32_t) * input_cnt; - strcpy(((char*)io_buf) + io_buf[1], volume_path); - - int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_FLUSHVOLUME, io_buf, io_buf_size, io_buf, 4); - if(res < 0) - return res; - - return io_buf[0]; -} - -int IOSUHAX_FSA_GetDeviceInfo(int fsaFd, const char* device_path, int type, uint32_t* out_data) -{ - if(iosuhaxHandle < 0) - return iosuhaxHandle; - - const int input_cnt = 3; - - int io_buf_size = sizeof(uint32_t) * input_cnt + strlen(device_path) + 1; - - uint32_t *io_buf = (uint32_t*)memalign(0x20, io_buf_size); - if(!io_buf) - return -2; - - io_buf[0] = fsaFd; - io_buf[1] = sizeof(uint32_t) * input_cnt; - io_buf[2] = type; - strcpy(((char*)io_buf) + io_buf[1], device_path); - - uint32_t out_buf[1 + 0x64 / 4]; - - int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_GETDEVICEINFO, io_buf, io_buf_size, out_buf, sizeof(out_buf)); - if(res < 0) - { - free(io_buf); - return res; - } - - memcpy(out_data, out_buf + 1, 0x64); - free(io_buf); - return out_buf[0]; -} - -int IOSUHAX_FSA_MakeDir(int fsaFd, const char* path, uint32_t flags) -{ - if(iosuhaxHandle < 0) - return iosuhaxHandle; - - const int input_cnt = 3; - - int io_buf_size = sizeof(uint32_t) * input_cnt + strlen(path) + 1; - - uint32_t *io_buf = (uint32_t*)memalign(0x20, io_buf_size); - if(!io_buf) - return -2; - - io_buf[0] = fsaFd; - io_buf[1] = sizeof(uint32_t) * input_cnt; - io_buf[2] = flags; - strcpy(((char*)io_buf) + io_buf[1], path); - - int result; - int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_MAKEDIR, io_buf, io_buf_size, &result, sizeof(result)); - if(res < 0) - { - free(io_buf); - return res; - } - - free(io_buf); - return result; -} - -int IOSUHAX_FSA_OpenDir(int fsaFd, const char* path, int* outHandle) -{ - if(iosuhaxHandle < 0) - return iosuhaxHandle; - - const int input_cnt = 2; - - int io_buf_size = sizeof(uint32_t) * input_cnt + strlen(path) + 1; - - uint32_t *io_buf = (uint32_t*)memalign(0x20, io_buf_size); - if(!io_buf) - return -2; - - io_buf[0] = fsaFd; - io_buf[1] = sizeof(uint32_t) * input_cnt; - strcpy(((char*)io_buf) + io_buf[1], path); - - int result_vec[2]; - - int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_OPENDIR, io_buf, io_buf_size, result_vec, sizeof(result_vec)); - if(res < 0) - { - free(io_buf); - return res; - } - - *outHandle = result_vec[1]; - free(io_buf); - return result_vec[0]; -} - -int IOSUHAX_FSA_ReadDir(int fsaFd, int handle, directoryEntry_s* out_data) -{ - if(iosuhaxHandle < 0) - return iosuhaxHandle; - - const int input_cnt = 2; - - int io_buf_size = sizeof(uint32_t) * input_cnt; - - uint32_t *io_buf = (uint32_t*)memalign(0x20, io_buf_size); - if(!io_buf) - return -2; - - io_buf[0] = fsaFd; - io_buf[1] = handle; - - int result_vec_size = 4 + sizeof(directoryEntry_s); - uint8_t *result_vec = (uint8_t*) memalign(0x20, result_vec_size); - if(!result_vec) - { - free(io_buf); - return -2; - } - - int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_READDIR, io_buf, io_buf_size, result_vec, result_vec_size); - if(res < 0) - { - free(result_vec); - free(io_buf); - return res; - } - - int result = *(int*)result_vec; - memcpy(out_data, result_vec + 4, sizeof(directoryEntry_s)); - free(io_buf); - free(result_vec); - return result; -} - -int IOSUHAX_FSA_RewindDir(int fsaFd, int dirHandle) -{ - if(iosuhaxHandle < 0) - return iosuhaxHandle; - - const int input_cnt = 2; - - int io_buf_size = sizeof(uint32_t) * input_cnt; - - uint32_t *io_buf = (uint32_t*)memalign(0x20, io_buf_size); - if(!io_buf) - return -2; - - io_buf[0] = fsaFd; - io_buf[1] = dirHandle; - - int result; - - int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_REWINDDIR, io_buf, io_buf_size, &result, sizeof(result)); - if(res < 0) - { - free(io_buf); - return res; - } - - free(io_buf); - return result; -} - -int IOSUHAX_FSA_CloseDir(int fsaFd, int handle) -{ - if(iosuhaxHandle < 0) - return iosuhaxHandle; - - const int input_cnt = 2; - - int io_buf_size = sizeof(uint32_t) * input_cnt; - - uint32_t *io_buf = (uint32_t*)memalign(0x20, io_buf_size); - if(!io_buf) - return -2; - - io_buf[0] = fsaFd; - io_buf[1] = handle; - - int result; - - int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_CLOSEDIR, io_buf, io_buf_size, &result, sizeof(result)); - if(res < 0) - { - free(io_buf); - return res; - } - - free(io_buf); - return result; -} - -int IOSUHAX_FSA_ChangeDir(int fsaFd, const char *path) -{ - if(iosuhaxHandle < 0) - return iosuhaxHandle; - - const int input_cnt = 2; - - int io_buf_size = sizeof(uint32_t) * input_cnt + strlen(path) + 1; - - uint32_t *io_buf = (uint32_t*)memalign(0x20, io_buf_size); - if(!io_buf) - return -2; - - io_buf[0] = fsaFd; - io_buf[1] = sizeof(uint32_t) * input_cnt; - strcpy(((char*)io_buf) + io_buf[1], path); - - int result; - - int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_CHDIR, io_buf, io_buf_size, &result, sizeof(result)); - if(res < 0) - { - free(io_buf); - return res; - } - - free(io_buf); - return result; -} - -int IOSUHAX_FSA_OpenFile(int fsaFd, const char* path, const char* mode, int* outHandle) -{ - if(iosuhaxHandle < 0) - return iosuhaxHandle; - - const int input_cnt = 3; - - int io_buf_size = sizeof(uint32_t) * input_cnt + strlen(path) + strlen(mode) + 2; - - uint32_t *io_buf = (uint32_t*)memalign(0x20, io_buf_size); - if(!io_buf) - return -2; - - io_buf[0] = fsaFd; - io_buf[1] = sizeof(uint32_t) * input_cnt; - io_buf[2] = io_buf[1] + strlen(path) + 1; - strcpy(((char*)io_buf) + io_buf[1], path); - strcpy(((char*)io_buf) + io_buf[2], mode); - - int result_vec[2]; - - int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_OPENFILE, io_buf, io_buf_size, result_vec, sizeof(result_vec)); - if(res < 0) - { - free(io_buf); - return res; - } - - *outHandle = result_vec[1]; - free(io_buf); - return result_vec[0]; -} - -int IOSUHAX_FSA_ReadFile(int fsaFd, void* data, uint32_t size, uint32_t cnt, int fileHandle, uint32_t flags) -{ - if(iosuhaxHandle < 0) - return iosuhaxHandle; - - const int input_cnt = 5; - - int io_buf_size = sizeof(uint32_t) * input_cnt; - - uint32_t *io_buf = (uint32_t*)memalign(0x20, io_buf_size); - if(!io_buf) - return -2; - - io_buf[0] = fsaFd; - io_buf[1] = size; - io_buf[2] = cnt; - io_buf[3] = fileHandle; - io_buf[4] = flags; - - int out_buf_size = ((size * cnt + 0x40) + 0x3F) & ~0x3F; - - uint32_t *out_buffer = (uint32_t*)memalign(0x40, out_buf_size); - if(!out_buffer) - { - free(io_buf); - return -2; - } - - int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_READFILE, io_buf, io_buf_size, out_buffer, out_buf_size); - if(res < 0) - { - free(out_buffer); - free(io_buf); - return res; - } - - //! data is put to offset 0x40 to align the buffer output - memcpy(data, ((uint8_t*)out_buffer) + 0x40, size * cnt); - - int result = out_buffer[0]; - - free(out_buffer); - free(io_buf); - return result; -} - -int IOSUHAX_FSA_WriteFile(int fsaFd, const void* data, uint32_t size, uint32_t cnt, int fileHandle, uint32_t flags) -{ - if(iosuhaxHandle < 0) - return iosuhaxHandle; - - const int input_cnt = 5; - - int io_buf_size = ((sizeof(uint32_t) * input_cnt + size * cnt + 0x40) + 0x3F) & ~0x3F; - - uint32_t *io_buf = (uint32_t*)memalign(0x20, io_buf_size); - if(!io_buf) - return -2; - - io_buf[0] = fsaFd; - io_buf[1] = size; - io_buf[2] = cnt; - io_buf[3] = fileHandle; - io_buf[4] = flags; - - //! data is put to offset 0x40 to align the buffer input - memcpy(((uint8_t*)io_buf) + 0x40, data, size * cnt); - - int result; - int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_WRITEFILE, io_buf, io_buf_size, &result, sizeof(result)); - if(res < 0) - { - free(io_buf); - return res; - } - free(io_buf); - return result; -} - -int IOSUHAX_FSA_StatFile(int fsaFd, int fileHandle, fileStat_s* out_data) -{ - if(iosuhaxHandle < 0) - return iosuhaxHandle; - - const int input_cnt = 2; - - int io_buf_size = sizeof(uint32_t) * input_cnt; - - uint32_t *io_buf = (uint32_t*)memalign(0x20, io_buf_size); - if(!io_buf) - return -2; - - io_buf[0] = fsaFd; - io_buf[1] = fileHandle; - - int out_buf_size = 4 + sizeof(fileStat_s); - uint32_t *out_buffer = (uint32_t*)memalign(0x20, out_buf_size); - if(!out_buffer) - { - free(io_buf); - return -2; - } - - int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_STATFILE, io_buf, io_buf_size, out_buffer, out_buf_size); - if(res < 0) - { - free(io_buf); - free(out_buffer); - return res; - } - - int result = out_buffer[0]; - memcpy(out_data, out_buffer + 1, sizeof(fileStat_s)); - - free(io_buf); - free(out_buffer); - return result; -} - -int IOSUHAX_FSA_CloseFile(int fsaFd, int fileHandle) -{ - if(iosuhaxHandle < 0) - return iosuhaxHandle; - - const int input_cnt = 2; - - int io_buf_size = sizeof(uint32_t) * input_cnt; - - uint32_t *io_buf = (uint32_t*)memalign(0x20, io_buf_size); - if(!io_buf) - return -2; - - io_buf[0] = fsaFd; - io_buf[1] = fileHandle; - - int result; - - int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_CLOSEFILE, io_buf, io_buf_size, &result, sizeof(result)); - if(res < 0) - { - free(io_buf); - return res; - } - - free(io_buf); - return result; -} - -int IOSUHAX_FSA_SetFilePos(int fsaFd, int fileHandle, uint32_t position) -{ - if(iosuhaxHandle < 0) - return iosuhaxHandle; - - const int input_cnt = 3; - - int io_buf_size = sizeof(uint32_t) * input_cnt; - - uint32_t *io_buf = (uint32_t*)memalign(0x20, io_buf_size); - if(!io_buf) - return -2; - - io_buf[0] = fsaFd; - io_buf[1] = fileHandle; - io_buf[2] = position; - - int result; - - int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_SETFILEPOS, io_buf, io_buf_size, &result, sizeof(result)); - if(res < 0) - { - free(io_buf); - return res; - } - - free(io_buf); - return result; -} - -int IOSUHAX_FSA_GetStat(int fsaFd, const char *path, fileStat_s* out_data) -{ - if(iosuhaxHandle < 0) - return iosuhaxHandle; - - const int input_cnt = 2; - - int io_buf_size = sizeof(uint32_t) * input_cnt + strlen(path) + 1; - - uint32_t *io_buf = (uint32_t*)memalign(0x20, io_buf_size); - if(!io_buf) - return -2; - - io_buf[0] = fsaFd; - io_buf[1] = sizeof(uint32_t) * input_cnt; - strcpy(((char*)io_buf) + io_buf[1], path); - - int out_buf_size = 4 + sizeof(fileStat_s); - uint32_t *out_buffer = (uint32_t*)memalign(0x20, out_buf_size); - if(!out_buffer) - { - free(io_buf); - return -2; - } - - int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_GETSTAT, io_buf, io_buf_size, out_buffer, out_buf_size); - if(res < 0) - { - free(io_buf); - free(out_buffer); - return res; - } - - int result = out_buffer[0]; - memcpy(out_data, out_buffer + 1, sizeof(fileStat_s)); - - free(io_buf); - free(out_buffer); - return result; -} - -int IOSUHAX_FSA_Remove(int fsaFd, const char *path) -{ - if(iosuhaxHandle < 0) - return iosuhaxHandle; - - const int input_cnt = 2; - - int io_buf_size = sizeof(uint32_t) * input_cnt + strlen(path) + 1; - - uint32_t *io_buf = (uint32_t*)memalign(0x20, ROUNDUP(io_buf_size, 0x20)); - if(!io_buf) - return -2; - - io_buf[0] = fsaFd; - io_buf[1] = sizeof(uint32_t) * input_cnt; - strcpy(((char*)io_buf) + io_buf[1], path); - - int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_REMOVE, io_buf, io_buf_size, io_buf, 4); - if(res >= 0) - res = io_buf[0]; - - free(io_buf); - return res; -} - -int IOSUHAX_FSA_ChangeMode(int fsaFd, const char* path, int mode) -{ - if(iosuhaxHandle < 0) - return iosuhaxHandle; - - const int input_cnt = 3; - - int io_buf_size = sizeof(uint32_t) * input_cnt + strlen(path) + 1; - - ALIGN(0x20) uint32_t io_buf[ROUNDUP(io_buf_size, 0x20) >> 2]; - - io_buf[0] = fsaFd; - io_buf[1] = sizeof(uint32_t) * input_cnt; - io_buf[2] = mode; - strcpy(((char*)io_buf) + io_buf[1], path); - - int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_CHANGEMODE, io_buf, io_buf_size, io_buf, 4); - if(res < 0) - return res; - - return io_buf[0]; -} - -int IOSUHAX_FSA_RawOpen(int fsaFd, const char* device_path, int* outHandle) -{ - if(iosuhaxHandle < 0) - return iosuhaxHandle; - - const int input_cnt = 2; - - int io_buf_size = sizeof(uint32_t) * input_cnt + strlen(device_path) + 1; - - ALIGN(0x20) uint32_t io_buf[ROUNDUP(io_buf_size, 0x20) >> 2]; - - io_buf[0] = fsaFd; - io_buf[1] = sizeof(uint32_t) * input_cnt; - strcpy(((char*)io_buf) + io_buf[1], device_path); - - int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_RAW_OPEN, io_buf, io_buf_size, io_buf, 2 * sizeof(int)); - if(res < 0) - return res; - - if(outHandle) - *outHandle = io_buf[1]; - - return io_buf[0]; -} - -int IOSUHAX_FSA_RawRead(int fsaFd, void* data, uint32_t block_size, uint32_t block_cnt, uint64_t sector_offset, int device_handle) -{ - if(iosuhaxHandle < 0) - return iosuhaxHandle; - - const int input_cnt = 6; - - int io_buf_size = 0x40 + block_size * block_cnt; - uint32_t *io_buf = (uint32_t*)memalign(0x40, ROUNDUP(io_buf_size, 0x40)); - - if(!io_buf) - return -2; - - io_buf[0] = fsaFd; - io_buf[1] = block_size; - io_buf[2] = block_cnt; - io_buf[3] = (sector_offset >> 32) & 0xFFFFFFFF; - io_buf[4] = sector_offset & 0xFFFFFFFF; - io_buf[5] = device_handle; - - int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_RAW_READ, io_buf, sizeof(uint32_t) * input_cnt, io_buf, io_buf_size); - if(res >= 0) - { - //! data is put to offset 0x40 to align the buffer output - memcpy(data, ((uint8_t*)io_buf) + 0x40, block_size * block_cnt); - - res = io_buf[0]; - } - - free(io_buf); - return res; -} - -int IOSUHAX_FSA_RawWrite(int fsaFd, const void* data, uint32_t block_size, uint32_t block_cnt, uint64_t sector_offset, int device_handle) -{ - if(iosuhaxHandle < 0) - return iosuhaxHandle; - - int io_buf_size = ROUNDUP(0x40 + block_size * block_cnt, 0x40); - - uint32_t *io_buf = (uint32_t*)memalign(0x40, io_buf_size); - if(!io_buf) - return -2; - - io_buf[0] = fsaFd; - io_buf[1] = block_size; - io_buf[2] = block_cnt; - io_buf[3] = (sector_offset >> 32) & 0xFFFFFFFF; - io_buf[4] = sector_offset & 0xFFFFFFFF; - io_buf[5] = device_handle; - - //! data is put to offset 0x40 to align the buffer input - memcpy(((uint8_t*)io_buf) + 0x40, data, block_size * block_cnt); - - int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_RAW_WRITE, io_buf, io_buf_size, io_buf, 4); - if(res >= 0) - res = io_buf[0]; - - free(io_buf); - return res; -} - - -int IOSUHAX_FSA_RawClose(int fsaFd, int device_handle) -{ - if(iosuhaxHandle < 0) - return iosuhaxHandle; - - const int input_cnt = 2; - - int io_buf_size = sizeof(uint32_t) * input_cnt; - - ALIGN(0x20) uint32_t io_buf[ROUNDUP(io_buf_size, 0x20) >> 2]; - - io_buf[0] = fsaFd; - io_buf[1] = device_handle; - - int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_RAW_CLOSE, io_buf, io_buf_size, io_buf, 4); - if(res < 0) - return res; - - return io_buf[0]; -} diff --git a/deps/libiosuhax/source/iosuhax_devoptab.c b/deps/libiosuhax/source/iosuhax_devoptab.c deleted file mode 100644 index 5e945f8ad4d7..000000000000 --- a/deps/libiosuhax/source/iosuhax_devoptab.c +++ /dev/null @@ -1,993 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2015 - * by Dimok - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event will the authors be held liable for any - * damages arising from the use of this software. - * - * Permission is granted to anyone to use this software for any - * purpose, including commercial applications, and to alter it and - * redistribute it freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented; you - * must not claim that you wrote the original software. If you use - * this software in a product, an acknowledgment in the product - * documentation would be appreciated but is not required. - * - * 2. Altered source versions must be plainly marked as such, and - * must not be misrepresented as being the original software. - * - * 3. This notice may not be removed or altered from any source - * distribution. - ***************************************************************************/ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "os_functions.h" -#include "iosuhax.h" - -typedef struct _fs_dev_private_t { - char *mount_path; - int fsaFd; - int mounted; - void *pMutex; -} fs_dev_private_t; - -typedef struct _fs_dev_file_state_t { - fs_dev_private_t *dev; - int fd; /* File descriptor */ - int flags; /* Opening flags */ - int read; /* True if allowed to read from file */ - int write; /* True if allowed to write to file */ - int append; /* True if allowed to append to file */ - uint32_t pos; /* Current position within the file (in bytes) */ - uint32_t len; /* Total length of the file (in bytes) */ - struct _fs_dev_file_state_t *prevOpenFile; /* The previous entry in a double-linked FILO list of open files */ - struct _fs_dev_file_state_t *nextOpenFile; /* The next entry in a double-linked FILO list of open files */ -} fs_dev_file_state_t; - -typedef struct _fs_dev_dir_entry_t { - fs_dev_private_t *dev; - int dirHandle; -} fs_dev_dir_entry_t; - -static fs_dev_private_t *fs_dev_get_device_data(const char *path) -{ - const devoptab_t *devoptab = NULL; - char name[128] = {0}; - int i; - - // Get the device name from the path - strncpy(name, path, 127); - strtok(name, ":/"); - - // Search the devoptab table for the specified device name - // NOTE: We do this manually due to a 'bug' in GetDeviceOpTab - // which ignores names with suffixes and causes names - // like "ntfs" and "ntfs1" to be seen as equals - for (i = 3; i < STD_MAX; i++) { - devoptab = devoptab_list[i]; - if (devoptab && devoptab->name) { - if (strcmp(name, devoptab->name) == 0) { - return (fs_dev_private_t *)devoptab->deviceData; - } - } - } - - return NULL; -} - -static char *fs_dev_real_path (const char *path, fs_dev_private_t *dev) -{ - // Sanity check - if (!path) - return NULL; - - // Move the path pointer to the start of the actual path - if (strchr(path, ':') != NULL) { - path = strchr(path, ':') + 1; - } - - int mount_len = strlen(dev->mount_path); - - char *new_name = (char*)malloc(mount_len + strlen(path) + 1); - if(new_name) { - strcpy(new_name, dev->mount_path); - strcpy(new_name + mount_len, path); - return new_name; - } - return new_name; -} - -static int fs_dev_open_r (struct _reent *r, void *fileStruct, const char *path, int flags, int mode) -{ - fs_dev_private_t *dev = fs_dev_get_device_data(path); - if(!dev) { - r->_errno = ENODEV; - return -1; - } - - fs_dev_file_state_t *file = (fs_dev_file_state_t *)fileStruct; - - file->dev = dev; - // Determine which mode the file is opened for - file->flags = flags; - - const char *fsMode; - - // Map flags to open modes - if (flags == 0) { - file->read = 1; - file->write = 0; - file->append = 0; - fsMode = "r"; - } else if (flags == 2) { - file->read = 1; - file->write = 1; - file->append = 0; - fsMode = "r+"; - } else if (flags == 0x601) { - file->read = 0; - file->write = 1; - file->append = 0; - fsMode = "w"; - } else if(flags == 0x602) { - file->read = 1; - file->write = 1; - file->append = 0; - fsMode = "w+"; - } else if(flags == 0x209) { - file->read = 0; - file->write = 1; - file->append = 1; - fsMode = "a"; - } else if(flags == 0x20A) { - file->read = 1; - file->write = 1; - file->append = 1; - fsMode = "a+"; - } else { - r->_errno = EINVAL; - return -1; - } - - - int fd = -1; - - OSLockMutex(dev->pMutex); - - char *real_path = fs_dev_real_path(path, dev); - if(!path) { - r->_errno = ENOMEM; - OSUnlockMutex(dev->pMutex); - return -1; - } - - int result = IOSUHAX_FSA_OpenFile(dev->fsaFd, real_path, fsMode, &fd); - - free(real_path); - - if(result == 0) - { - fileStat_s stats; - result = IOSUHAX_FSA_StatFile(dev->fsaFd, fd, &stats); - if(result != 0) { - IOSUHAX_FSA_CloseFile(dev->fsaFd, fd); - r->_errno = result; - OSUnlockMutex(dev->pMutex); - return -1; - } - file->fd = fd; - file->pos = 0; - file->len = stats.size; - OSUnlockMutex(dev->pMutex); - return (int)file; - } - - r->_errno = result; - OSUnlockMutex(dev->pMutex); - return -1; -} - - -static int fs_dev_close_r (struct _reent *r, void *fd) -{ - fs_dev_file_state_t *file = (fs_dev_file_state_t *)fd; - if(!file->dev) { - r->_errno = ENODEV; - return -1; - } - - OSLockMutex(file->dev->pMutex); - - int result = IOSUHAX_FSA_CloseFile(file->dev->fsaFd, file->fd); - - OSUnlockMutex(file->dev->pMutex); - - if(result < 0) - { - r->_errno = result; - return -1; - } - return 0; -} - -static off_t fs_dev_seek_r (struct _reent *r, void *fd, off_t pos, int dir) -{ - fs_dev_file_state_t *file = (fs_dev_file_state_t *)fd; - if(!file->dev) { - r->_errno = ENODEV; - return 0; - } - - OSLockMutex(file->dev->pMutex); - - switch(dir) - { - case SEEK_SET: - file->pos = pos; - break; - case SEEK_CUR: - file->pos += pos; - break; - case SEEK_END: - file->pos = file->len + pos; - break; - default: - r->_errno = EINVAL; - return -1; - } - - int result = IOSUHAX_FSA_SetFilePos(file->dev->fsaFd, file->fd, file->pos); - - OSUnlockMutex(file->dev->pMutex); - - if(result == 0) - { - return file->pos; - } - - return result; -} - -static ssize_t fs_dev_write_r (struct _reent *r, void *fd, const char *ptr, size_t len) -{ - fs_dev_file_state_t *file = (fs_dev_file_state_t *)fd; - if(!file->dev) { - r->_errno = ENODEV; - return 0; - } - - if(!file->write) - { - r->_errno = EACCES; - return 0; - } - - OSLockMutex(file->dev->pMutex); - - size_t done = 0; - - while(done < len) - { - size_t write_size = len - done; - - int result = IOSUHAX_FSA_WriteFile(file->dev->fsaFd, ptr + done, 0x01, write_size, file->fd, 0); - if(result < 0) - { - r->_errno = result; - break; - } - else if(result == 0) - { - if(write_size > 0) - done = 0; - break; - } - else - { - done += result; - file->pos += result; - } - } - - OSUnlockMutex(file->dev->pMutex); - return done; -} - -static ssize_t fs_dev_read_r (struct _reent *r, void *fd, char *ptr, size_t len) -{ - fs_dev_file_state_t *file = (fs_dev_file_state_t *)fd; - if(!file->dev) { - r->_errno = ENODEV; - return 0; - } - - if(!file->read) - { - r->_errno = EACCES; - return 0; - } - - OSLockMutex(file->dev->pMutex); - - size_t done = 0; - - while(done < len) - { - size_t read_size = len - done; - - int result = IOSUHAX_FSA_ReadFile(file->dev->fsaFd, ptr + done, 0x01, read_size, file->fd, 0); - if(result < 0) - { - r->_errno = result; - done = 0; - break; - } - else if(result == 0) - { - //! TODO: error on read_size > 0 - break; - } - else - { - done += result; - file->pos += result; - } - } - - OSUnlockMutex(file->dev->pMutex); - return done; -} - - -static int fs_dev_fstat_r (struct _reent *r, void *fd, struct stat *st) -{ - fs_dev_file_state_t *file = (fs_dev_file_state_t *)fd; - if(!file->dev) { - r->_errno = ENODEV; - return -1; - } - - OSLockMutex(file->dev->pMutex); - - // Zero out the stat buffer - memset(st, 0, sizeof(struct stat)); - - fileStat_s stats; - int result = IOSUHAX_FSA_StatFile(file->dev->fsaFd, (int)fd, &stats); - if(result != 0) { - r->_errno = result; - OSUnlockMutex(file->dev->pMutex); - return -1; - } - - st->st_mode = S_IFREG; - st->st_size = stats.size; - st->st_blocks = (stats.size + 511) >> 9; - st->st_nlink = 1; - - // Fill in the generic entry stats - st->st_dev = stats.id; - st->st_uid = stats.owner_id; - st->st_gid = stats.group_id; - st->st_ino = stats.id; - st->st_atime = stats.mtime; - st->st_ctime = stats.ctime; - st->st_mtime = stats.mtime; - OSUnlockMutex(file->dev->pMutex); - return 0; -} - -static int fs_dev_ftruncate_r (struct _reent *r, void *fd, off_t len) -{ - fs_dev_file_state_t *file = (fs_dev_file_state_t *)fd; - if(!file->dev) { - r->_errno = ENODEV; - return -1; - } - - r->_errno = ENOTSUP; - // TODO - return -1; -} - -static int fs_dev_fsync_r (struct _reent *r, void *fd) -{ - fs_dev_file_state_t *file = (fs_dev_file_state_t *)fd; - if(!file->dev) { - r->_errno = ENODEV; - return -1; - } - - r->_errno = ENOTSUP; - // TODO - return -1; -} - -static int fs_dev_stat_r (struct _reent *r, const char *path, struct stat *st) -{ - fs_dev_private_t *dev = fs_dev_get_device_data(path); - if(!dev) { - r->_errno = ENODEV; - return -1; - } - - OSLockMutex(dev->pMutex); - - // Zero out the stat buffer - memset(st, 0, sizeof(struct stat)); - - char *real_path = fs_dev_real_path(path, dev); - if(!real_path) { - r->_errno = ENOMEM; - OSUnlockMutex(dev->pMutex); - return -1; - } - - fileStat_s stats; - - int result = IOSUHAX_FSA_GetStat(dev->fsaFd, real_path, &stats); - - free(real_path); - - if(result < 0) { - r->_errno = result; - OSUnlockMutex(dev->pMutex); - return -1; - } - - // mark root also as directory - st->st_mode = ((stats.flag & 0x80000000) || (strlen(dev->mount_path) + 1 == strlen(real_path)))? S_IFDIR : S_IFREG; - st->st_nlink = 1; - st->st_size = stats.size; - st->st_blocks = (stats.size + 511) >> 9; - // Fill in the generic entry stats - st->st_dev = stats.id; - st->st_uid = stats.owner_id; - st->st_gid = stats.group_id; - st->st_ino = stats.id; - st->st_atime = stats.mtime; - st->st_ctime = stats.ctime; - st->st_mtime = stats.mtime; - - OSUnlockMutex(dev->pMutex); - - return 0; -} - -static int fs_dev_link_r (struct _reent *r, const char *existing, const char *newLink) -{ - r->_errno = ENOTSUP; - return -1; -} - -static int fs_dev_unlink_r (struct _reent *r, const char *name) -{ - fs_dev_private_t *dev = fs_dev_get_device_data(name); - if(!dev) { - r->_errno = ENODEV; - return -1; - } - - OSLockMutex(dev->pMutex); - - char *real_path = fs_dev_real_path(name, dev); - if(!real_path) { - r->_errno = ENOMEM; - OSUnlockMutex(dev->pMutex); - return -1; - } - - int result = IOSUHAX_FSA_Remove(dev->fsaFd, real_path); - - free(real_path); - - OSUnlockMutex(dev->pMutex); - - if(result < 0) { - r->_errno = result; - return -1; - } - - return result; -} - -static int fs_dev_chdir_r (struct _reent *r, const char *name) -{ - fs_dev_private_t *dev = fs_dev_get_device_data(name); - if(!dev) { - r->_errno = ENODEV; - return -1; - } - - OSLockMutex(dev->pMutex); - - char *real_path = fs_dev_real_path(name, dev); - if(!real_path) { - r->_errno = ENOMEM; - OSUnlockMutex(dev->pMutex); - return -1; - } - - int result = IOSUHAX_FSA_ChangeDir(dev->fsaFd, real_path); - - free(real_path); - - OSUnlockMutex(dev->pMutex); - - if(result < 0) { - r->_errno = result; - return -1; - } - - return 0; -} - -static int fs_dev_rename_r (struct _reent *r, const char *oldName, const char *newName) -{ - fs_dev_private_t *dev = fs_dev_get_device_data(oldName); - if(!dev) { - r->_errno = ENODEV; - return -1; - } - - OSLockMutex(dev->pMutex); - - char *real_oldpath = fs_dev_real_path(oldName, dev); - if(!real_oldpath) { - r->_errno = ENOMEM; - OSUnlockMutex(dev->pMutex); - return -1; - } - char *real_newpath = fs_dev_real_path(newName, dev); - if(!real_newpath) { - r->_errno = ENOMEM; - free(real_oldpath); - OSUnlockMutex(dev->pMutex); - return -1; - } - - //! TODO - int result = -ENOTSUP; - - free(real_oldpath); - free(real_newpath); - - OSUnlockMutex(dev->pMutex); - - if(result < 0) { - r->_errno = result; - return -1; - } - - return 0; - -} - -static int fs_dev_mkdir_r (struct _reent *r, const char *path, int mode) -{ - fs_dev_private_t *dev = fs_dev_get_device_data(path); - if(!dev) { - r->_errno = ENODEV; - return -1; - } - - OSLockMutex(dev->pMutex); - - char *real_path = fs_dev_real_path(path, dev); - if(!real_path) { - r->_errno = ENOMEM; - OSUnlockMutex(dev->pMutex); - return -1; - } - - int result = IOSUHAX_FSA_MakeDir(dev->fsaFd, real_path, mode); - - free(real_path); - - OSUnlockMutex(dev->pMutex); - - if(result < 0) { - r->_errno = result; - return -1; - } - - return 0; -} - -static int fs_dev_chmod_r (struct _reent *r, const char *path, int mode) -{ - fs_dev_private_t *dev = fs_dev_get_device_data(path); - if(!dev) { - r->_errno = ENODEV; - return -1; - } - - OSLockMutex(dev->pMutex); - - char *real_path = fs_dev_real_path(path, dev); - if(!real_path) { - r->_errno = ENOMEM; - OSUnlockMutex(dev->pMutex); - return -1; - } - - int result = IOSUHAX_FSA_ChangeMode(dev->fsaFd, real_path, mode); - - free(real_path); - - OSUnlockMutex(dev->pMutex); - - if(result < 0) { - r->_errno = result; - return -1; - } - - return 0; -} - -static int fs_dev_statvfs_r (struct _reent *r, const char *path, struct statvfs *buf) -{ - fs_dev_private_t *dev = fs_dev_get_device_data(path); - if(!dev) { - r->_errno = ENODEV; - return -1; - } - - OSLockMutex(dev->pMutex); - - // Zero out the stat buffer - memset(buf, 0, sizeof(struct statvfs)); - - char *real_path = fs_dev_real_path(path, dev); - if(!real_path) { - r->_errno = ENOMEM; - OSUnlockMutex(dev->pMutex); - return -1; - } - - uint64_t size; - - int result = IOSUHAX_FSA_GetDeviceInfo(dev->fsaFd, real_path, 0x00, (uint32_t*)&size); - - free(real_path); - - if(result < 0) { - r->_errno = result; - OSUnlockMutex(dev->pMutex); - return -1; - } - - // File system block size - buf->f_bsize = 512; - - // Fundamental file system block size - buf->f_frsize = 512; - - // Total number of blocks on file system in units of f_frsize - buf->f_blocks = size >> 9; // this is unknown - - // Free blocks available for all and for non-privileged processes - buf->f_bfree = buf->f_bavail = size >> 9; - - // Number of inodes at this point in time - buf->f_files = 0xffffffff; - - // Free inodes available for all and for non-privileged processes - buf->f_ffree = 0xffffffff; - - // File system id - buf->f_fsid = (int)dev; - - // Bit mask of f_flag values. - buf->f_flag = 0; - - // Maximum length of filenames - buf->f_namemax = 255; - - OSUnlockMutex(dev->pMutex); - - return 0; -} - -static DIR_ITER *fs_dev_diropen_r (struct _reent *r, DIR_ITER *dirState, const char *path) -{ - fs_dev_private_t *dev = fs_dev_get_device_data(path); - if(!dev) { - r->_errno = ENODEV; - return NULL; - } - - fs_dev_dir_entry_t *dirIter = (fs_dev_dir_entry_t *)dirState->dirStruct; - - OSLockMutex(dev->pMutex); - - char *real_path = fs_dev_real_path(path, dev); - if(!real_path) { - r->_errno = ENOMEM; - OSUnlockMutex(dev->pMutex); - return NULL; - } - - int dirHandle; - - int result = IOSUHAX_FSA_OpenDir(dev->fsaFd, real_path, &dirHandle); - - free(real_path); - - OSUnlockMutex(dev->pMutex); - - if(result < 0) - { - r->_errno = result; - return NULL; - } - - dirIter->dev = dev; - dirIter->dirHandle = dirHandle; - - return dirState; -} - -static int fs_dev_dirclose_r (struct _reent *r, DIR_ITER *dirState) -{ - fs_dev_dir_entry_t *dirIter = (fs_dev_dir_entry_t *)dirState->dirStruct; - if(!dirIter->dev) { - r->_errno = ENODEV; - return -1; - } - - OSLockMutex(dirIter->dev->pMutex); - - int result = IOSUHAX_FSA_CloseDir(dirIter->dev->fsaFd, dirIter->dirHandle); - - OSUnlockMutex(dirIter->dev->pMutex); - - if(result < 0) - { - r->_errno = result; - return -1; - } - return 0; -} - -static int fs_dev_dirreset_r (struct _reent *r, DIR_ITER *dirState) -{ - fs_dev_dir_entry_t *dirIter = (fs_dev_dir_entry_t *)dirState->dirStruct; - if(!dirIter->dev) { - r->_errno = ENODEV; - return -1; - } - - OSLockMutex(dirIter->dev->pMutex); - - int result = IOSUHAX_FSA_RewindDir(dirIter->dev->fsaFd, dirIter->dirHandle); - - OSUnlockMutex(dirIter->dev->pMutex); - - if(result < 0) - { - r->_errno = result; - return -1; - } - return 0; -} - -static int fs_dev_dirnext_r (struct _reent *r, DIR_ITER *dirState, char *filename, struct stat *st) -{ - fs_dev_dir_entry_t *dirIter = (fs_dev_dir_entry_t *)dirState->dirStruct; - if(!dirIter->dev) { - r->_errno = ENODEV; - return -1; - } - - OSLockMutex(dirIter->dev->pMutex); - - directoryEntry_s * dir_entry = malloc(sizeof(directoryEntry_s)); - - int result = IOSUHAX_FSA_ReadDir(dirIter->dev->fsaFd, dirIter->dirHandle, dir_entry); - if(result < 0) - { - free(dir_entry); - r->_errno = result; - OSUnlockMutex(dirIter->dev->pMutex); - return -1; - } - - // Fetch the current entry - strcpy(filename, dir_entry->name); - - if(st) - { - memset(st, 0, sizeof(struct stat)); - st->st_mode = (dir_entry->stat.flag & 0x80000000) ? S_IFDIR : S_IFREG; - st->st_nlink = 1; - st->st_size = dir_entry->stat.size; - st->st_blocks = (dir_entry->stat.size + 511) >> 9; - st->st_dev = dir_entry->stat.id; - st->st_uid = dir_entry->stat.owner_id; - st->st_gid = dir_entry->stat.group_id; - st->st_ino = dir_entry->stat.id; - st->st_atime = dir_entry->stat.mtime; - st->st_ctime = dir_entry->stat.ctime; - st->st_mtime = dir_entry->stat.mtime; - } - - free(dir_entry); - OSUnlockMutex(dirIter->dev->pMutex); - return 0; -} - -// NTFS device driver devoptab -static const devoptab_t devops_fs = { - NULL, /* Device name */ - sizeof (fs_dev_file_state_t), - fs_dev_open_r, - fs_dev_close_r, - fs_dev_write_r, - fs_dev_read_r, - fs_dev_seek_r, - fs_dev_fstat_r, - fs_dev_stat_r, - fs_dev_link_r, - fs_dev_unlink_r, - fs_dev_chdir_r, - fs_dev_rename_r, - fs_dev_mkdir_r, - sizeof (fs_dev_dir_entry_t), - fs_dev_diropen_r, - fs_dev_dirreset_r, - fs_dev_dirnext_r, - fs_dev_dirclose_r, - fs_dev_statvfs_r, - fs_dev_ftruncate_r, - fs_dev_fsync_r, - fs_dev_chmod_r, - NULL, /* fs_dev_fchmod_r */ - NULL /* Device data */ -}; - -static int fs_dev_add_device (const char *name, const char *mount_path, int fsaFd, int isMounted) -{ - devoptab_t *dev = NULL; - char *devname = NULL; - char *devpath = NULL; - int i; - - // Sanity check - if (!name) { - errno = EINVAL; - return -1; - } - - // Allocate a devoptab for this device - dev = (devoptab_t *) malloc(sizeof(devoptab_t) + strlen(name) + 1); - if (!dev) { - errno = ENOMEM; - return -1; - } - - // Use the space allocated at the end of the devoptab for storing the device name - devname = (char*)(dev + 1); - strcpy(devname, name); - - // create private data - fs_dev_private_t *priv = (fs_dev_private_t *)malloc(sizeof(fs_dev_private_t) + strlen(mount_path) + 1); - if(!priv) { - free(dev); - errno = ENOMEM; - return -1; - } - - devpath = (char*)(priv+1); - strcpy(devpath, mount_path); - - // setup private data - priv->mount_path = devpath; - priv->fsaFd = fsaFd; - priv->mounted = isMounted; - priv->pMutex = malloc(OS_MUTEX_SIZE); - - if(!priv->pMutex) { - free(dev); - free(priv); - errno = ENOMEM; - return -1; - } - - OSInitMutex(priv->pMutex); - - // Setup the devoptab - memcpy(dev, &devops_fs, sizeof(devoptab_t)); - dev->name = devname; - dev->deviceData = priv; - - // Add the device to the devoptab table (if there is a free slot) - for (i = 3; i < STD_MAX; i++) { - if (devoptab_list[i] == devoptab_list[0]) { - devoptab_list[i] = dev; - return 0; - } - } - - // failure, free all memory - free(priv); - free(dev); - - // If we reach here then there are no free slots in the devoptab table for this device - errno = EADDRNOTAVAIL; - return -1; -} - -static int fs_dev_remove_device (const char *path) -{ - const devoptab_t *devoptab = NULL; - char name[128] = {0}; - int i; - - // Get the device name from the path - strncpy(name, path, 127); - strtok(name, ":/"); - - // Find and remove the specified device from the devoptab table - // NOTE: We do this manually due to a 'bug' in RemoveDevice - // which ignores names with suffixes and causes names - // like "ntfs" and "ntfs1" to be seen as equals - for (i = 3; i < STD_MAX; i++) { - devoptab = devoptab_list[i]; - if (devoptab && devoptab->name) { - if (strcmp(name, devoptab->name) == 0) { - devoptab_list[i] = devoptab_list[0]; - - if(devoptab->deviceData) - { - fs_dev_private_t *priv = (fs_dev_private_t *)devoptab->deviceData; - - if(priv->mounted) - IOSUHAX_FSA_Unmount(priv->fsaFd, priv->mount_path, 2); - - if(priv->pMutex) - free(priv->pMutex); - free(devoptab->deviceData); - } - - free((devoptab_t*)devoptab); - return 0; - } - } - } - - return -1; -} - -int mount_fs(const char *virt_name, int fsaFd, const char *dev_path, const char *mount_path) -{ - int isMounted = 0; - - if(dev_path) - { - isMounted = 1; - - int res = IOSUHAX_FSA_Mount(fsaFd, dev_path, mount_path, 2, 0, 0); - if(res != 0) - { - return res; - } - } - - return fs_dev_add_device(virt_name, mount_path, fsaFd, isMounted); -} - -int unmount_fs(const char *virt_name) -{ - return fs_dev_remove_device(virt_name); -} diff --git a/deps/libiosuhax/source/iosuhax_disc_interface.c b/deps/libiosuhax/source/iosuhax_disc_interface.c deleted file mode 100644 index 1160fc192463..000000000000 --- a/deps/libiosuhax/source/iosuhax_disc_interface.c +++ /dev/null @@ -1,262 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2016 - * by Dimok - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event will the authors be held liable for any - * damages arising from the use of this software. - * - * Permission is granted to anyone to use this software for any - * purpose, including commercial applications, and to alter it and - * redistribute it freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented; you - * must not claim that you wrote the original software. If you use - * this software in a product, an acknowledgment in the product - * documentation would be appreciated but is not required. - * - * 2. Altered source versions must be plainly marked as such, and - * must not be misrepresented as being the original software. - * - * 3. This notice may not be removed or altered from any source - * distribution. - ***************************************************************************/ -#include -#include -#include "iosuhax.h" -#include "iosuhax_disc_interface.h" - -#define FSA_REF_SD 0x01 -#define FSA_REF_USB 0x02 - -static int initialized = 0; - -static int fsaFdSd = 0; -static int fsaFdUsb = 0; -static int sdioFd = 0; -static int usbFd = 0; - -static void IOSUHAX_disc_io_initialize(void) -{ - if(initialized == 0) - { - initialized = 1; - fsaFdSd = -1; - fsaFdUsb = -1; - sdioFd = -1; - usbFd = -1; - } -} - -static bool IOSUHAX_disc_io_fsa_open(int fsaFd) -{ - IOSUHAX_disc_io_initialize(); - - if(IOSUHAX_Open(NULL) < 0) - return false; - - if(fsaFd == FSA_REF_SD) - { - if(fsaFdSd < 0) - { - fsaFdSd = IOSUHAX_FSA_Open(); - } - - if(fsaFdSd >= 0) - return true; - } - else if(fsaFd == FSA_REF_USB) - { - if(fsaFdUsb < 0) - { - fsaFdUsb = IOSUHAX_FSA_Open(); - } - - if(fsaFdUsb >= 0) - return true; - } - - return false; -} - -static void IOSUHAX_disc_io_fsa_close(int fsaFd) -{ - if(fsaFd == FSA_REF_SD) - { - if(fsaFdSd >= 0) - { - IOSUHAX_FSA_Close(fsaFdSd); - fsaFdSd = -1; - } - } - else if(fsaFd == FSA_REF_USB) - { - if(fsaFdUsb >= 0) - { - IOSUHAX_FSA_Close(fsaFdUsb); - fsaFdUsb = -1; - } - } -} - -static bool IOSUHAX_sdio_startup(void) -{ - if(!IOSUHAX_disc_io_fsa_open(FSA_REF_SD)) - return false; - - if(sdioFd < 0) - { - int res = IOSUHAX_FSA_RawOpen(fsaFdSd, "/dev/sdcard01", &sdioFd); - if(res < 0) - { - IOSUHAX_disc_io_fsa_close(FSA_REF_SD); - sdioFd = -1; - } - } - - return (sdioFd >= 0); -} - -static bool IOSUHAX_sdio_isInserted(void) -{ - //! TODO: check for SD card inserted with IOSUHAX_FSA_GetDeviceInfo() - return initialized && (fsaFdSd >= 0) && (sdioFd >= 0); -} - -static bool IOSUHAX_sdio_clearStatus(void) -{ - return true; -} - -static bool IOSUHAX_sdio_shutdown(void) -{ - if(!IOSUHAX_sdio_isInserted()) - return false; - - IOSUHAX_FSA_RawClose(fsaFdSd, sdioFd); - IOSUHAX_disc_io_fsa_close(FSA_REF_SD); - sdioFd = -1; - return true; -} - -static bool IOSUHAX_sdio_readSectors(uint32_t sector, uint32_t numSectors, void* buffer) -{ - if(!IOSUHAX_sdio_isInserted()) - return false; - - int res = IOSUHAX_FSA_RawRead(fsaFdSd, buffer, 512, numSectors, sector, sdioFd); - if(res < 0) - { - return false; - } - - return true; -} - -static bool IOSUHAX_sdio_writeSectors(uint32_t sector, uint32_t numSectors, const void* buffer) -{ - if(!IOSUHAX_sdio_isInserted()) - return false; - - int res = IOSUHAX_FSA_RawWrite(fsaFdSd, buffer, 512, numSectors, sector, sdioFd); - if(res < 0) - { - return false; - } - - return true; -} - -const DISC_INTERFACE IOSUHAX_sdio_disc_interface = -{ - DEVICE_TYPE_WII_U_SD, - FEATURE_MEDIUM_CANREAD | FEATURE_MEDIUM_CANWRITE | FEATURE_WII_U_SD, - IOSUHAX_sdio_startup, - IOSUHAX_sdio_isInserted, - IOSUHAX_sdio_readSectors, - IOSUHAX_sdio_writeSectors, - IOSUHAX_sdio_clearStatus, - IOSUHAX_sdio_shutdown -}; - -static bool IOSUHAX_usb_startup(void) -{ - if(!IOSUHAX_disc_io_fsa_open(FSA_REF_USB)) - return false; - - if(usbFd < 0) - { - int res = IOSUHAX_FSA_RawOpen(fsaFdUsb, "/dev/usb01", &usbFd); - if(res < 0) - { - res = IOSUHAX_FSA_RawOpen(fsaFdUsb, "/dev/usb02", &usbFd); - if(res < 0) - { - IOSUHAX_disc_io_fsa_close(FSA_REF_USB); - usbFd = -1; - } - } - } - return (usbFd >= 0); -} - -static bool IOSUHAX_usb_isInserted(void) -{ - return initialized && (fsaFdUsb >= 0) && (usbFd >= 0); -} - -static bool IOSUHAX_usb_clearStatus(void) -{ - return true; -} - -static bool IOSUHAX_usb_shutdown(void) -{ - if(!IOSUHAX_usb_isInserted()) - return false; - - IOSUHAX_FSA_RawClose(fsaFdUsb, usbFd); - IOSUHAX_disc_io_fsa_close(FSA_REF_USB); - usbFd = -1; - return true; -} - -static bool IOSUHAX_usb_readSectors(uint32_t sector, uint32_t numSectors, void* buffer) -{ - if(!IOSUHAX_usb_isInserted()) - return false; - - int res = IOSUHAX_FSA_RawRead(fsaFdUsb, buffer, 512, numSectors, sector, usbFd); - if(res < 0) - { - return false; - } - - return true; -} - -static bool IOSUHAX_usb_writeSectors(uint32_t sector, uint32_t numSectors, const void* buffer) -{ - if(!IOSUHAX_usb_isInserted()) - return false; - - int res = IOSUHAX_FSA_RawWrite(fsaFdUsb, buffer, 512, numSectors, sector, usbFd); - if(res < 0) - { - return false; - } - - return true; -} - -const DISC_INTERFACE IOSUHAX_usb_disc_interface = -{ - DEVICE_TYPE_WII_U_USB, - FEATURE_MEDIUM_CANREAD | FEATURE_MEDIUM_CANWRITE | FEATURE_WII_U_USB, - IOSUHAX_usb_startup, - IOSUHAX_usb_isInserted, - IOSUHAX_usb_readSectors, - IOSUHAX_usb_writeSectors, - IOSUHAX_usb_clearStatus, - IOSUHAX_usb_shutdown -}; diff --git a/deps/libiosuhax/source/os_functions.h b/deps/libiosuhax/source/os_functions.h deleted file mode 100644 index a9d9d003172c..000000000000 --- a/deps/libiosuhax/source/os_functions.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef __OS_FUNCTIONS_H_ -#define __OS_FUNCTIONS_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#define OS_MUTEX_SIZE 44 - -//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -//! Mutex functions -//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -extern void OSInitMutex(void* mutex); -extern void OSLockMutex(void* mutex); -extern void OSUnlockMutex(void* mutex); - -//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -//! IOS function -//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -extern int IOS_Ioctl(int fd, unsigned int request, void *input_buffer,unsigned int input_buffer_len, void *output_buffer, unsigned int output_buffer_len); -extern int IOS_Open(char *path, unsigned int mode); -extern int IOS_Close(int fd); - -#ifdef __cplusplus -} -#endif - -#endif // __OS_FUNCTIONS_H_ diff --git a/deps/libmocha/.clang-format b/deps/libmocha/.clang-format new file mode 100644 index 000000000000..56cc68554a27 --- /dev/null +++ b/deps/libmocha/.clang-format @@ -0,0 +1,67 @@ +# Generated from CLion C/C++ Code Style settings +BasedOnStyle: LLVM +AccessModifierOffset: -4 +AlignAfterOpenBracket: Align +AlignConsecutiveAssignments: Consecutive +AlignConsecutiveMacros: AcrossEmptyLinesAndComments +AlignOperands: Align +AllowAllArgumentsOnNextLine: false +AllowAllConstructorInitializersOnNextLine: false +AllowAllParametersOfDeclarationOnNextLine: false +AllowShortBlocksOnASingleLine: Always +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: All +AllowShortIfStatementsOnASingleLine: Always +AllowShortLambdasOnASingleLine: All +AllowShortLoopsOnASingleLine: true +AlwaysBreakAfterReturnType: None +AlwaysBreakTemplateDeclarations: Yes +BreakBeforeBraces: Custom +BraceWrapping: + AfterCaseLabel: false + AfterClass: false + AfterControlStatement: Never + AfterEnum: false + AfterFunction: false + AfterNamespace: false + AfterUnion: false + BeforeCatch: false + BeforeElse: false + IndentBraces: false + SplitEmptyFunction: false + SplitEmptyRecord: true +BreakBeforeBinaryOperators: None +BreakBeforeTernaryOperators: true +BreakConstructorInitializers: BeforeColon +BreakInheritanceList: BeforeColon +ColumnLimit: 0 +CompactNamespaces: false +ContinuationIndentWidth: 8 +IndentCaseLabels: true +IndentPPDirectives: None +IndentWidth: 4 +KeepEmptyLinesAtTheStartOfBlocks: true +MaxEmptyLinesToKeep: 2 +NamespaceIndentation: All +ObjCSpaceAfterProperty: false +ObjCSpaceBeforeProtocolList: true +PointerAlignment: Right +ReflowComments: false +SpaceAfterCStyleCast: true +SpaceAfterLogicalNot: false +SpaceAfterTemplateKeyword: false +SpaceBeforeAssignmentOperators: true +SpaceBeforeCpp11BracedList: false +SpaceBeforeCtorInitializerColon: true +SpaceBeforeInheritanceColon: true +SpaceBeforeParens: ControlStatements +SpaceBeforeRangeBasedForLoopColon: true +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 1 +SpacesInAngles: false +SpacesInCStyleCastParentheses: false +SpacesInContainerLiterals: false +SpacesInParentheses: false +SpacesInSquareBrackets: false +TabWidth: 4 +UseTab: Never diff --git a/deps/libmocha/.github/workflows/pr.yml b/deps/libmocha/.github/workflows/pr.yml new file mode 100644 index 000000000000..6636ab0158c9 --- /dev/null +++ b/deps/libmocha/.github/workflows/pr.yml @@ -0,0 +1,25 @@ +name: CI-PR + +on: [pull_request] + +jobs: + clang-format: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: clang-format + run: | + docker run --rm -v ${PWD}:/src ghcr.io/wiiu-env/clang-format:13.0.0-2 -r ./source ./include + build-lib: + runs-on: ubuntu-latest + needs: clang-format + steps: + - uses: actions/checkout@v3 + - name: build lib + run: | + docker build . -f Dockerfile.buildlocal -t builder + docker run --rm -v ${PWD}:/project builder make + - uses: actions/upload-artifact@master + with: + name: lib + path: "lib/*.a" \ No newline at end of file diff --git a/deps/libmocha/.github/workflows/push_image.yml b/deps/libmocha/.github/workflows/push_image.yml new file mode 100644 index 000000000000..a69fa5e8da12 --- /dev/null +++ b/deps/libmocha/.github/workflows/push_image.yml @@ -0,0 +1,43 @@ +name: Publish Docker Image +on: + push: + branches: + - main + +env: + REGISTRY: ghcr.io + IMAGE_NAME: ${{ github.repository }} + +jobs: + build-and-push-image: + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + - name: Extract Docker metadata + id: meta + uses: docker/metadata-action@v4 + with: + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + tags: | + type=raw,value={{date 'YYYYMMDD'}}-{{sha}} + type=raw,value={{date 'YYYYMMDD'}} + type=raw,value=latest + - name: Log into registry ${{ env.REGISTRY }} + uses: docker/login-action@v2.1.0 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.CI_PAT_WRITE_PACKAGE }} + + - name: Build and push Docker image + uses: docker/build-push-action@v4 + with: + context: . + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + push: true \ No newline at end of file diff --git a/deps/libmocha/.gitignore b/deps/libmocha/.gitignore new file mode 100644 index 000000000000..6f6ace41c763 --- /dev/null +++ b/deps/libmocha/.gitignore @@ -0,0 +1,9 @@ +/*.a +/build +*.bz2 +release/ +lib/ +CMakeLists.txt +.idea/ +cmake-build-debug/ +share/ diff --git a/deps/libmocha/.gitrepo b/deps/libmocha/.gitrepo new file mode 100644 index 000000000000..615726131222 --- /dev/null +++ b/deps/libmocha/.gitrepo @@ -0,0 +1,12 @@ +; DO NOT EDIT (unless you know what you are doing) +; +; This subdirectory is a git "subrepo", and this file is maintained by the +; git-subrepo command. See https://github.com/ingydotnet/git-subrepo#readme +; +[subrepo] + remote = https://github.com/wiiu-env/libmocha + branch = main + commit = 630d9681bc0f29cc03a373cad94b76f17cfae763 + parent = 2ca2d96f462272e2e7c1ded77ac884b9cdad010c + method = merge + cmdver = 0.4.6 diff --git a/deps/libiosuhax/Dockerfile b/deps/libmocha/Dockerfile similarity index 84% rename from deps/libiosuhax/Dockerfile rename to deps/libmocha/Dockerfile index 27aa8936e809..3421a87fc827 100644 --- a/deps/libiosuhax/Dockerfile +++ b/deps/libmocha/Dockerfile @@ -1,4 +1,4 @@ -FROM wiiuenv/devkitppc:20210101 +FROM ghcr.io/wiiu-env/devkitppc:20230621 WORKDIR tmp_build COPY . . diff --git a/deps/libmocha/Dockerfile.buildlocal b/deps/libmocha/Dockerfile.buildlocal new file mode 100644 index 000000000000..2c6958560339 --- /dev/null +++ b/deps/libmocha/Dockerfile.buildlocal @@ -0,0 +1,3 @@ +FROM ghcr.io/wiiu-env/devkitppc:20230621 + +WORKDIR project \ No newline at end of file diff --git a/deps/libmocha/LICENSE b/deps/libmocha/LICENSE new file mode 100644 index 000000000000..57e7a5350ad1 --- /dev/null +++ b/deps/libmocha/LICENSE @@ -0,0 +1,155 @@ +GNU LESSER GENERAL PUBLIC LICENSE +Version 3, 29 June 2007 + +Copyright (C) 2007 Free Software Foundation, Inc. + +Everyone is permitted to copy and distribute verbatim copies of this license +document, but changing it is not allowed. + +This version of the GNU Lesser General Public License incorporates the terms +and conditions of version 3 of the GNU General Public License, supplemented +by the additional permissions listed below. + +0. Additional Definitions. + +As used herein, “this License” refers to version 3 of the GNU Lesser General +Public License, and the “GNU GPL” refers to version 3 of the +GNU General Public License. + +“The Library” refers to a covered work governed by this License, other than +an Application or a Combined Work as defined below. + +An “Application” is any work that makes use of an interface provided by the +Library, but which is not otherwise based on the Library. Defining a subclass +of a class defined by the Library is deemed a mode of using an interface +provided by the Library. + +A “Combined Work” is a work produced by combining or linking an Application +with the Library. The particular version of the Library with which the +Combined Work was made is also called the “Linked Version”. + +The “Minimal Corresponding Source” for a Combined Work means the Corresponding +Source for the Combined Work, excluding any source code for portions of the +Combined Work that, considered in isolation, are based on the Application, +and not on the Linked Version. + +The “Corresponding Application Code” for a Combined Work means the object code +and/or source code for the Application, including any data and utility programs +needed for reproducing the Combined Work from the Application, but excluding +the System Libraries of the Combined Work. + +1. Exception to Section 3 of the GNU GPL. + +You may convey a covered work under sections 3 and 4 of this License without +being bound by section 3 of the GNU GPL. + +2. Conveying Modified Versions. + +If you modify a copy of the Library, and, in your modifications, a facility +refers to a function or data to be supplied by an Application that uses the +facility (other than as an argument passed when the facility is invoked), +then you may convey a copy of the modified version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the function or + data, the facility still operates, and performs whatever part of its + purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of this + License applicable to that copy. + +3. Object Code Incorporating Material from Library Header Files. + +The object code form of an Application may incorporate material from a header +file that is part of the Library. You may convey such object code under terms +of your choice, provided that, if the incorporated material is not limited to +numerical parameters, data structure layouts and accessors, or small macros, +inline functions and templates (ten or fewer lines in length), +you do both of the following: + + a) Give prominent notice with each copy of the object code that the Library + is used in it and that the Library and its use are covered by this License. + + b) Accompany the object code with a copy of the GNU GPL + and this license document. + +4. Combined Works. + +You may convey a Combined Work under terms of your choice that, taken together, +effectively do not restrict modification of the portions of the Library +contained in the Combined Work and reverse engineering for debugging such +modifications, if you also do each of the following: + + a) Give prominent notice with each copy of the Combined Work that the + Library is used in it and that the Library and its use are covered + by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and + this license document. + + c) For a Combined Work that displays copyright notices during execution, + include the copyright notice for the Library among these notices, as well + as a reference directing the user to the copies of the GNU GPL + and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form suitable + for, and under terms that permit, the user to recombine or relink + the Application with a modified version of the Linked Version to + produce a modified Combined Work, in the manner specified by section 6 + of the GNU GPL for conveying Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time a + copy of the Library already present on the user's computer system, + and (b) will operate properly with a modified version of the Library + that is interface-compatible with the Linked Version. + + e) Provide Installation Information, but only if you would otherwise be + required to provide such information under section 6 of the GNU GPL, and + only to the extent that such information is necessary to install and + execute a modified version of the Combined Work produced by recombining + or relinking the Application with a modified version of the Linked Version. + (If you use option 4d0, the Installation Information must accompany the + Minimal Corresponding Source and Corresponding Application Code. If you + use option 4d1, you must provide the Installation Information in the + manner specified by section 6 of the GNU GPL for + conveying Corresponding Source.) + +5. Combined Libraries. + +You may place library facilities that are a work based on the Library side by +side in a single library together with other library facilities that are not +Applications and are not covered by this License, and convey such a combined +library under terms of your choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based on + the Library, uncombined with any other library facilities, conveyed under + the terms of this License. + + b) Give prominent notice with the combined library that part of it is a + work based on the Library, and explaining where to find the accompanying + uncombined form of the same work. + +6. Revised Versions of the GNU Lesser General Public License. + +The Free Software Foundation may publish revised and/or new versions of the +GNU Lesser General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Library as you +received it specifies that a certain numbered version of the GNU Lesser +General Public License “or any later version” applies to it, you have the +option of following the terms and conditions either of that published version +or of any later version published by the Free Software Foundation. If the +Library as you received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser General +Public License ever published by the Free Software Foundation. + +If the Library as you received it specifies that a proxy can decide whether +future versions of the GNU Lesser General Public License shall apply, that +proxy's public statement of acceptance of any version is permanent +authorization for you to choose that version for the Library. \ No newline at end of file diff --git a/deps/libiosuhax/Makefile b/deps/libmocha/Makefile similarity index 92% rename from deps/libiosuhax/Makefile rename to deps/libmocha/Makefile index 03af789f3d7b..2c9fcb20968b 100644 --- a/deps/libiosuhax/Makefile +++ b/deps/libmocha/Makefile @@ -25,7 +25,8 @@ VERSION := $(VER_MAJOR).$(VER_MINOR).$(VER_PATCH) #------------------------------------------------------------------------------- TARGET := $(notdir $(CURDIR)) BUILD := build -SOURCES := source +SOURCES := source \ + source/devoptab DATA := data INCLUDES := source \ include \ @@ -38,9 +39,9 @@ CFLAGS := -Wall -Werror -save-temps \ $(MACHDEP) \ $(BUILD_CFLAGS) -CFLAGS += $(INCLUDE) -D__WIIU__ -D__WUT__ +CFLAGS += $(INCLUDE) -D__WIIU__ -D__WUT__ -fno-exceptions -CXXFLAGS := $(CFLAGS) -std=gnu++17 +CXXFLAGS := $(CFLAGS) -std=gnu++20 ASFLAGS := $(MACHDEP) @@ -99,19 +100,19 @@ export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \ .PHONY: all dist-bin dist-src dist install clean #--------------------------------------------------------------------------------- -all: lib/libiosuhax.a +all: lib/libmocha.a dist-bin: all - @tar --exclude=*~ -cjf libiosuhax-$(VERSION).tar.bz2 include lib + @tar --exclude=*~ -cjf libmocha-$(VERSION).tar.bz2 include lib dist-src: - @tar --exclude=*~ -cjf libiosuhax-src-$(VERSION).tar.bz2 include source Makefile + @tar --exclude=*~ -cjf libmocha-src-$(VERSION).tar.bz2 include source Makefile dist: dist-src dist-bin install: dist-bin mkdir -p $(DESTDIR)$(DEVKITPRO)/wut/usr - bzip2 -cd libiosuhax-$(VERSION).tar.bz2 | tar -xf - -C $(DESTDIR)$(DEVKITPRO)/wut/usr + bzip2 -cd libmocha-$(VERSION).tar.bz2 | tar -xf - -C $(DESTDIR)$(DEVKITPRO)/wut/usr lib: @[ -d $@ ] || mkdir -p $@ @@ -119,7 +120,7 @@ lib: release: @[ -d $@ ] || mkdir -p $@ -lib/libiosuhax.a :$(SOURCES) $(INCLUDES) | lib release +lib/libmocha.a :$(SOURCES) $(INCLUDES) | lib release @$(MAKE) BUILD=release OUTPUT=$(CURDIR)/$@ \ BUILD_CFLAGS="-DNDEBUG=1 -O2 -s" \ DEPSDIR=$(CURDIR)/release \ diff --git a/deps/libmocha/README.md b/deps/libmocha/README.md new file mode 100644 index 000000000000..a69acf783190 --- /dev/null +++ b/deps/libmocha/README.md @@ -0,0 +1,27 @@ +[![Publish Docker Image](https://github.com/wiiu-env/libmocha/actions/workflows/push_image.yml/badge.svg)](https://github.com/wiiu-env/libmocha/actions/workflows/push_image.yml) + +**This library is still WIP, may not work as expected or have breaking changes in the near future** + +# libmocha +Requires the [MochaPayload](https://github.com/wiiu-env/MochaPayload) to be running via [EnvironmentLoader](https://github.com/wiiu-env/EnvironmentLoader). +Requires [wut](https://github.com/devkitPro/wut) for building. +Install via `make install`. + +## Usage +Make sure to add `-lmocha` to `LIBS` and `$(WUT_ROOT)/usr` to `LIBDIRS` in your makefile. + +After that you can simply include `` to get access to the mocha functions after calling `Mocha_InitLibrary()`. + +## Use this lib in Dockerfiles. +A prebuilt version of this lib can found on dockerhub. To use it for your projects, add this to your Dockerfile. +``` +[...] +COPY --from=ghcr.io/wiiu-env/libmocha:[tag] /artifacts $DEVKITPRO +[...] +``` +Replace [tag] with a tag you want to use, a list of tags can be found [here](https://github.com/orgs/wiiu-env/packages/container/libmocha/versions). +It's highly recommended to pin the version to the **latest date** instead of using `latest`. + +## Format the code via docker + +`docker run --rm -v ${PWD}:/src ghcr.io/wiiu-env/clang-format:13.0.0-2 -r ./source ./include -i` diff --git a/deps/libmocha/include/mocha/commands.h b/deps/libmocha/include/mocha/commands.h new file mode 100644 index 000000000000..ed6e2756624f --- /dev/null +++ b/deps/libmocha/include/mocha/commands.h @@ -0,0 +1,30 @@ +#pragma once + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define IPC_CUSTOM_START_MCP_THREAD 0xFE +#define IPC_CUSTOM_MEN_RPX_HOOK_COMPLETED 0xFD +#define IPC_CUSTOM_LOAD_CUSTOM_RPX 0xFC +#define IPC_CUSTOM_START_USB_LOGGING 0xFA +#define IPC_CUSTOM_COPY_ENVIRONMENT_PATH 0xF9 +#define IPC_CUSTOM_GET_MOCHA_API_VERSION 0xF8 + +typedef enum LoadRPXTargetEnum { + LOAD_RPX_TARGET_SD_CARD = 0, + LOAD_RPX_TARGET_EXTRA_REVERT_PREPARE = 0x42424242, +} LoadRPXTargetEnum; + +typedef struct __attribute((packed)) { + LoadRPXTargetEnum target; // Target where the file will be loaded from. + uint32_t filesize; // Size of RPX inside given file. 0 for full filesize. + uint32_t fileoffset; // Offset of RPX inside given file. + char path[256]; // Relative path on target device +} MochaRPXLoadInfo; + +#ifdef __cplusplus +} // extern "C" +#endif \ No newline at end of file diff --git a/deps/libiosuhax/include/iosuhax_disc_interface.h b/deps/libmocha/include/mocha/disc_interface.h similarity index 50% rename from deps/libiosuhax/include/iosuhax_disc_interface.h rename to deps/libmocha/include/mocha/disc_interface.h index c5b703b7bc9f..fd284814db65 100644 --- a/deps/libiosuhax/include/iosuhax_disc_interface.h +++ b/deps/libmocha/include/mocha/disc_interface.h @@ -21,53 +21,54 @@ * 3. This notice may not be removed or altered from any source * distribution. ***************************************************************************/ -#ifndef _IOSUHAX_DISC_INTERFACE_H_ -#define _IOSUHAX_DISC_INTERFACE_H_ +#pragma once -#include #include +#include #ifdef __cplusplus extern "C" { #endif -#define DEVICE_TYPE_WII_U_SD (('W'<<24)|('U'<<16)|('S'<<8)|'D') -#define DEVICE_TYPE_WII_U_USB (('W'<<24)|('U'<<16)|('S'<<8)|'B') -#define FEATURE_WII_U_SD 0x00001000 -#define FEATURE_WII_U_USB 0x00002000 +#define DEVICE_TYPE_WII_U_SD (('W' << 24) | ('U' << 16) | ('S' << 8) | 'D') +#define DEVICE_TYPE_WII_U_USB (('W' << 24) | ('U' << 16) | ('S' << 8) | 'B') +#define FEATURE_WII_U_SD 0x00001000 +#define FEATURE_WII_U_USB 0x00002000 #ifndef OGC_DISC_IO_INCLUDE typedef uint32_t sec_t; -#define FEATURE_MEDIUM_CANREAD 0x00000001 -#define FEATURE_MEDIUM_CANWRITE 0x00000002 +#define FEATURE_MEDIUM_CANREAD 0x00000001 +#define FEATURE_MEDIUM_CANWRITE 0x00000002 + +typedef bool (*FN_MEDIUM_STARTUP)(void); + +typedef bool (*FN_MEDIUM_ISINSERTED)(void); + +typedef bool (*FN_MEDIUM_READSECTORS)(uint32_t sector, uint32_t numSectors, void *buffer); -typedef bool (* FN_MEDIUM_STARTUP)(void) ; -typedef bool (* FN_MEDIUM_ISINSERTED)(void) ; -typedef bool (* FN_MEDIUM_READSECTORS)(uint32_t sector, uint32_t numSectors, void* buffer) ; -typedef bool (* FN_MEDIUM_WRITESECTORS)(uint32_t sector, uint32_t numSectors, const void* buffer) ; -typedef bool (* FN_MEDIUM_CLEARSTATUS)(void) ; -typedef bool (* FN_MEDIUM_SHUTDOWN)(void) ; +typedef bool (*FN_MEDIUM_WRITESECTORS)(uint32_t sector, uint32_t numSectors, const void *buffer); + +typedef bool (*FN_MEDIUM_CLEARSTATUS)(void); + +typedef bool (*FN_MEDIUM_SHUTDOWN)(void); struct DISC_INTERFACE_STRUCT { - unsigned long ioType ; - unsigned long features ; - FN_MEDIUM_STARTUP startup ; - FN_MEDIUM_ISINSERTED isInserted ; - FN_MEDIUM_READSECTORS readSectors ; - FN_MEDIUM_WRITESECTORS writeSectors ; - FN_MEDIUM_CLEARSTATUS clearStatus ; - FN_MEDIUM_SHUTDOWN shutdown ; -} ; + unsigned long ioType; + unsigned long features; + FN_MEDIUM_STARTUP startup; + FN_MEDIUM_ISINSERTED isInserted; + FN_MEDIUM_READSECTORS readSectors; + FN_MEDIUM_WRITESECTORS writeSectors; + FN_MEDIUM_CLEARSTATUS clearStatus; + FN_MEDIUM_SHUTDOWN shutdown; +}; -typedef struct DISC_INTERFACE_STRUCT DISC_INTERFACE ; +typedef struct DISC_INTERFACE_STRUCT DISC_INTERFACE; #endif - -extern const DISC_INTERFACE IOSUHAX_sdio_disc_interface; -extern const DISC_INTERFACE IOSUHAX_usb_disc_interface; +extern const DISC_INTERFACE Mocha_sdio_disc_interface; +extern const DISC_INTERFACE Mocha_usb_disc_interface; #ifdef __cplusplus } #endif - -#endif diff --git a/deps/libmocha/include/mocha/fsa.h b/deps/libmocha/include/mocha/fsa.h new file mode 100644 index 000000000000..076c59f1797e --- /dev/null +++ b/deps/libmocha/include/mocha/fsa.h @@ -0,0 +1,100 @@ +#pragma once + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Opens a device for raw read/write + * @param client valid FSClient pointer with unlocked permissions + * @param device_path path of the device. e.g. /dev/sdcard01 + * @param outHandle pointer where the handle of the raw device will be stored + * @return + */ +FSError FSAEx_RawOpen(FSClient *client, const char *device_path, int32_t *outHandle); + +/** + * Opens a device for raw read/write + * @param clientHandle valid /dev/fsa handle with unlocked permissions + * @param device_path path of the device. e.g. /dev/sdcard01 + * @param outHandle pointer where the handle of the raw device will be stored + * @return + */ +FSError FSAEx_RawOpenEx(FSAClientHandle clientHandle, const char *device_path, int32_t *outHandle); + +/** + * Closes a devices that was previously opened via FSAEx_RawOpen + * @param client valid FSClient pointer with unlocked permissions + * @param device_handle device handle + * @return + */ +FSError FSAEx_RawClose(FSClient *client, int32_t device_handle); + +/** + * Closes a devices that was previously opened via FSAEx_RawOpen + * @param clientHandle valid /dev/fsa handle with unlocked permissions + * @param device_handle device handle + * @return + */ +FSError FSAEx_RawCloseEx(FSAClientHandle clientHandle, int32_t device_handle); + +/** + * Read data from a device handle. + * + * @param client valid FSClient pointer with unlocked permissions + * @param data buffer where the result will be stored. Requires 0x40 alignment for the buffer itself and buffer size. + * @param size_bytes size of sector. + * @param cnt number of sectors that should be read. + * @param blocks_offset read offset in sectors. + * @param device_handle valid device handle. + * @return + */ +FSError FSAEx_RawRead(FSClient *client, void *data, uint32_t size_bytes, uint32_t cnt, uint64_t blocks_offset, int device_handle); + +/** + * Read data from a raw device handle. + * + * @param clientHandle valid /dev/fsa handle with unlocked permissions + * @param data buffer where the result will be stored. Requires 0x40 alignment for the buffer itself and buffer size. + * @param size_bytes size of sector. + * @param cnt number of sectors that should be read. + * @param blocks_offset read offset in sectors. + * @param device_handle valid device handle. + * @return + */ +FSError FSAEx_RawReadEx(FSAClientHandle clientHandle, void *data, uint32_t size_bytes, uint32_t cnt, uint64_t blocks_offset, int device_handle); + + +/** + * Write data to raw device handle + * + * @param client valid FSClient pointer with unlocked permissions + * @param data buffer of data that should be written.. Requires 0x40 alignment for the buffer itself and buffer size. + * @param size_bytes size of sector. + * @param cnt number of sectors that should be written. + * @param blocks_offset write offset in sectors. + * @param device_handle valid device handle. + * @return + */ +FSError FSAEx_RawWrite(FSClient *client, const void *data, uint32_t size_bytes, uint32_t cnt, uint64_t blocks_offset, int device_handle); + +/** + * Write data to raw device handle + * + * @param clientHandle valid /dev/fsa handle with unlocked permissions + * @param data buffer of data that should be written.. Requires 0x40 alignment for the buffer itself and buffer size. + * @param size_bytes size of sector. + * @param cnt number of sectors that should be written. + * @param blocks_offset write offset in sectors. + * @param device_handle valid device handle. + * @return + */ +FSError FSAEx_RawWriteEx(FSAClientHandle clientHandle, const void *data, uint32_t size_bytes, uint32_t cnt, uint64_t blocks_offset, int device_handle); + +#ifdef __cplusplus +} // extern "C" +#endif \ No newline at end of file diff --git a/deps/libmocha/include/mocha/mocha.h b/deps/libmocha/include/mocha/mocha.h new file mode 100644 index 000000000000..da99d2eed129 --- /dev/null +++ b/deps/libmocha/include/mocha/mocha.h @@ -0,0 +1,307 @@ +#pragma once +#include "commands.h" +#include "otp.h" +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum MochaUtilsStatus { + MOCHA_RESULT_SUCCESS = 0, + MOCHA_RESULT_INVALID_ARGUMENT = -0x01, + MOCHA_RESULT_MAX_CLIENT = -0x02, + MOCHA_RESULT_OUT_OF_MEMORY = -0x03, + MOCHA_RESULT_ALREADY_EXISTS = -0x04, + MOCHA_RESULT_ADD_DEVOPTAB_FAILED = -0x05, + MOCHA_RESULT_NOT_FOUND = -0x06, + MOCHA_RESULT_UNSUPPORTED_API_VERSION = -0x10, + MOCHA_RESULT_UNSUPPORTED_COMMAND = -0x11, + MOCHA_RESULT_UNSUPPORTED_CFW = -0x12, + MOCHA_RESULT_LIB_UNINITIALIZED = -0x20, + MOCHA_RESULT_UNKNOWN_ERROR = -0x100, +} MochaUtilsStatus; + +const char *Mocha_GetStatusStr(MochaUtilsStatus status); + +/** + * Initializes the mocha lib. Needs to be called before any other functions can be used + * @return MOCHA_RESULT_SUCCESS: Library has been successfully initialized
+ * MOCHA_RESULT_UNSUPPORTED_COMMAND: Failed to initialize the library caused by an outdated mocha version. + */ +MochaUtilsStatus Mocha_InitLibrary(); + +/** + * Deinitializes the mocha lib + * @return + */ +MochaUtilsStatus Mocha_DeInitLibrary(); + +/** + * Retrieves the API Version of the running mocha. + * + * @param outVersion pointer to the variable where the version will be stored. + * + * @return MOCHA_RESULT_SUCCESS: The API version has been store in the version ptr
+ * MOCHA_RESULT_INVALID_ARGUMENT: Invalid version pointer
+ * MOCHA_RESULT_UNSUPPORTED_API_VERSION: Failed to get the API version caused by an outdated mocha version.
+ * MOCHA_RESULT_UNSUPPORTED_CFW: Failed to get the API version caused by not using a (compatible) CFW. + */ +MochaUtilsStatus Mocha_CheckAPIVersion(uint32_t *outVersion); + +/** + * Copies data within IOSU with MCP permission. + * @param dst - Destination address + * @param src - Source address + * @param size - Bytes to copy. + * @return MOCHA_RESULT_SUCCESS: The data has been copied successfully
+ * MOCHA_RESULT_INVALID_ARGUMENT: Invalid dst or src pointer
+ * MOCHA_RESULT_LIB_UNINITIALIZED: Library was not initialized. Call Mocha_InitLibrary() before using this function.
+ * MOCHA_RESULT_UNKNOWN_ERROR: Unknown error + */ +MochaUtilsStatus Mocha_IOSUMemoryMemcpy(uint32_t dst, uint32_t src, uint32_t size); + +/** + * Writes data to a given address with MCP permission. + * @param address - Address where the data will be written to. + * @param buffer - Pointer to the data which should be written. + * @param size - Bytes to write. + * @return MOCHA_RESULT_SUCCESS: The data has been written successfully
+ * MOCHA_RESULT_INVALID_ARGUMENT: Invalid address or buffer pointer
+ * MOCHA_RESULT_LIB_UNINITIALIZED: Library was not initialized. Call Mocha_InitLibrary() before using this function.
+ * MOCHA_RESULT_OUT_OF_MEMORY: Not enough memory
+ * MOCHA_RESULT_UNKNOWN_ERROR: Unknown error + */ +MochaUtilsStatus Mocha_IOSUMemoryWrite(uint32_t address, const uint8_t *buffer, uint32_t size); + +/** + * Reads data from a given address with MCP permission. + * @param address - Address where the data will be read from. + * @param buffer - Pointer to the buffer where the read will be stored + * @param size - Bytes to read. + * @return MOCHA_RESULT_SUCCESS: The data has been read successfully
+ * MOCHA_RESULT_INVALID_ARGUMENT: Invalid source address
+ * MOCHA_RESULT_LIB_UNINITIALIZED: Library was not initialized. Call Mocha_InitLibrary() before using this function.
+ * MOCHA_RESULT_UNKNOWN_ERROR: Unknown error + */ +MochaUtilsStatus Mocha_IOSUMemoryRead(uint32_t address, uint8_t *out_buffer, uint32_t size); + +/** + * Writes 4 bytes with IOSU kernel permission + * @param address Address where the value will be written. + * @param value Value that will be written to address. + * @return MOCHA_RESULT_SUCCESS: The data has been written successfully
+ * MOCHA_RESULT_INVALID_ARGUMENT: Invalid target address
+ * MOCHA_RESULT_LIB_UNINITIALIZED: Library was not initialized. Call Mocha_InitLibrary() before using this function.
+ * MOCHA_RESULT_OUT_OF_MEMORY: Not enough memory
+ * MOCHA_RESULT_UNKNOWN_ERROR: Unknown error + */ +MochaUtilsStatus Mocha_IOSUKernelWrite32(uint32_t address, uint32_t value); + +/** + * Reads 4 bytes with IOSU kernel permission + * @param address Address from which the data will be read. + * @param out_buffer Pointer where the result will be stored + * @return MOCHA_RESULT_SUCCESS: The data has been read successfully
+ * MOCHA_RESULT_INVALID_ARGUMENT: Invalid target address
+ * MOCHA_RESULT_LIB_UNINITIALIZED: Library was not initialized. Call Mocha_InitLibrary() before using this function.
+ * MOCHA_RESULT_UNKNOWN_ERROR: Unknown error + */ +MochaUtilsStatus Mocha_IOSUKernelRead32(uint32_t address, uint32_t *out_buffer); + +/** + * Reads the consoles OTP into the given buffer. + * + * @param out_buffer Buffer where the result will be stored. + * @return MOCHA_RESULT_SUCCESS: The OTP has been read into the buffer
+ * MOCHA_RESULT_INVALID_ARGUMENT: Invalid environmentPathBuffer pointer or bufferLen \< 0x100
+ * MOCHA_RESULT_LIB_UNINITIALIZED: Library was not initialized. Call Mocha_InitLibrary() before using this function.
+ * MOCHA_RESULT_UNKNOWN_ERROR: Failed to retrieve the environment path. + */ +MochaUtilsStatus Mocha_ReadOTP(WiiUConsoleOTP *out_buffer); + +/** + * Calls an iosu SVC. + * @param svc_id + * @param args array of argument with the length arg_cnt + * @param arg_cnt number of arguments + * @param outResult + * @return MOCHA_RESULT_SUCCESS: The SVC has been called successfully, the result has been stored in outResult.
+ * MOCHA_RESULT_LIB_UNINITIALIZED: Library was not initialized. Call Mocha_InitLibrary() before using this function.
+ * MOCHA_RESULT_UNKNOWN_ERROR + */ +int Mocha_IOSUCallSVC(uint32_t svc_id, uint32_t *args, uint32_t arg_cnt, int32_t *outResult); + +/** + * Returns the path of the currently loaded environment + * @param environmentPathBuffer: buffer where the result will be stored + * @param bufferLen: length of the buffer. Required to be >= 0x100 + * @return MOCHA_RESULT_SUCCESS: The environment path has been stored in environmentPathBuffer
+ * MOCHA_RESULT_INVALID_ARGUMENT: Invalid environmentPathBuffer pointer or bufferLen \< 0x100
+ * MOCHA_RESULT_LIB_UNINITIALIZED: Library was not initialized. Call Mocha_InitLibrary() before using this function.
+ * MOCHA_RESULT_UNSUPPORTED_COMMAND: Command not supported by the currently loaded mocha version.
+ * MOCHA_RESULT_UNKNOWN_ERROR: Failed to retrieve the environment path. + */ +MochaUtilsStatus Mocha_GetEnvironmentPath(char *environmentPathBuffer, uint32_t bufferLen); + +/** + * Enables logging via USB (FTDI FT232 chipset only) via OSReport and friends.
+ * @param notSkipExistingLogs If set to true, existing logs of this session won't be skipped. + * @return MOCHA_RESULT_SUCCESS: Logging via USB starts or has already been started
+ * MOCHA_RESULT_LIB_UNINITIALIZED: Library was not initialized. Call Mocha_InitLibrary() before using this function.
+ * MOCHA_RESULT_UNSUPPORTED_COMMAND: Command not supported by the currently loaded mocha version.
+ * MOCHA_RESULT_UNKNOWN_ERROR: Failed to retrieve the environment path. + */ +MochaUtilsStatus Mocha_StartUSBLogging(bool notSkipExistingLogs); + +/** + * Gives a FSClient full permissions.
+ * Requires Mocha API Version: 1 + * @param client The FSClient that should have full permission + * @return MOCHA_RESULT_SUCCESS: The has been unlocked successfully.
+ * MOCHA_RESULT_INVALID_ARGUMENT: Client was NULL
+ * MOCHA_RESULT_MAX_CLIENT: The maximum number of FS Clients have been unlocked.
+ * MOCHA_RESULT_LIB_UNINITIALIZED: Library was not initialized. Call Mocha_InitLibrary() before using this function.
+ * MOCHA_RESULT_UNSUPPORTED_COMMAND: Command not supported by the currently loaded mocha version.
+ * MOCHA_RESULT_UNKNOWN_ERROR: Failed to unlock a given FSClient + */ +MochaUtilsStatus Mocha_UnlockFSClient(FSClient *client); + +/** + * Gives a /dev/fsa handle full permissions.
+ * Requires Mocha API Version: 1 + * @param client The /dev/fsa handle that should have full permission + * @return MOCHA_RESULT_SUCCESS: The has been unlocked successfully.
+ * MOCHA_RESULT_MAX_CLIENT: The maximum number of FS Clients have been unlocked.
+ * MOCHA_RESULT_LIB_UNINITIALIZED: Library was not initialized. Call Mocha_InitLibrary() before using this function.
+ * MOCHA_RESULT_UNSUPPORTED_COMMAND: Command not supported by the currently loaded mocha version.
+ * MOCHA_RESULT_UNKNOWN_ERROR: Failed to unlock the given client + */ +MochaUtilsStatus Mocha_UnlockFSClientEx(int clientHandle); + +/** + * Set the .rpx that will be loaded the next time the homebrew wrapper application is launched (e.g. Health & Safety or Daily Log). + *
+ * Loading a .rpx from within a file (archive e.g. a WUHB) is supported.
+ * To achieve this, the fileoffset (offset inside file specified via path) and filesize (size of the .rpx) need to be set.
+ * If filesize is set to 0, the whole file (starting at fileoffset) will be loaded as .rpx
+ *
+ * The path is **relative** to the root of the given target device.
+ * The target LOAD_RPX_TARGET_EXTRA_REVERT_PREPARE will revert a prepare call.
+ *
+ * To launch the prepared RPX call Mocha_LaunchHomebrewWrapper if this call was successful. + * + * @param loadInfo Information about the .rpx replacement. + * @return MOCHA_RESULT_SUCCESS: Loading the next RPX will be redirected.
+ * MOCHA_RESULT_INVALID_ARGUMENT: The given loadInfo was NULL
+ * MOCHA_RESULT_LIB_UNINITIALIZED: Library was not initialized. Call Mocha_InitLibrary() before using this function.
+ * MOCHA_RESULT_UNSUPPORTED_COMMAND: Command not supported by the currently loaded mocha version.
+ * MOCHA_RESULT_UNKNOWN_ERROR: Failed to setup a redirect of RPX. + */ +MochaUtilsStatus Mocha_PrepareRPXLaunch(MochaRPXLoadInfo *loadInfo); + +/** + * Launches the wrapper app for launching .rpx
+ * To launch a RPX call `Mocha_PrepareRPXLaunch` before this function.
+ *
+ * see: `Mocha_LaunchRPX` to prepare and launch a RPX in one command. + * + * @return MOCHA_RESULT_SUCCESS: App is launching
+ * MOCHA_RESULT_LIB_UNINITIALIZED: Library was not initialized. Call Mocha_InitLibrary() before using this function.
+ * MOCHA_RESULT_UNSUPPORTED_COMMAND: Command not supported by the currently loaded mocha version.
+ * MOCHA_RESULT_NOT_FOUND: Not application that can be used as homebrew wrapper found. + */ +MochaUtilsStatus Mocha_LaunchHomebrewWrapper(); + +/** + * Launches the wrapper app for launching .rpx, with custom SYS args.
+ * To launch a RPX call `Mocha_PrepareRPXLaunch` before this function.
+ *
+ * see: `Mocha_LaunchRPX` to prepare and launch a RPX in one command. + * + * @param args sysapp args to pass to the homebrew app. + * @return MOCHA_RESULT_SUCCESS: App is launching
+ * MOCHA_RESULT_LIB_UNINITIALIZED: Library was not initialized. Call Mocha_InitLibrary() before using this function.
+ * MOCHA_RESULT_UNSUPPORTED_COMMAND: Command not supported by the currently loaded mocha version.
+ * MOCHA_RESULT_NOT_FOUND: Not application that can be used as homebrew wrapper found. + */ +MochaUtilsStatus Mocha_LaunchHomebrewWrapperEx(SYSStandardArgsIn *args); + +/** + * Launches a given RPX by launching a wrapper application and replacing the RPX on the fly.
+ * See Mocha_PrepareRPXLaunch for more information.
+ * + * Note: Combines Mocha_PrepareRPXLaunch and Mocha_LaunchHomebrewWrapper. + * @param loadInfo + * @return MOCHA_RESULT_SUCCESS: Requested RPX will be launched
+ * MOCHA_RESULT_LIB_UNINITIALIZED: Library was not initialized. Call Mocha_InitLibrary() before using this function.
+ * MOCHA_RESULT_UNSUPPORTED_COMMAND: Command not supported by the currently loaded mocha version.
+ * MOCHA_RESULT_INVALID_ARGUMENT: The given loadInfo was NULL
+ * MOCHA_RESULT_NOT_FOUND: Not application that can be used as homebrew wrapper found. + * MOCHA_RESULT_UNKNOWN_ERROR: Failed to setup a redirect of RPX. + */ +MochaUtilsStatus Mocha_LaunchRPX(MochaRPXLoadInfo *loadInfo); + +typedef struct WUDDiscKey { + uint8_t key[0x10]; +} WUDDiscKey; + +/** + * Reads the disc key (used to decrypt the SI partition) of the inserted disc. + * + * @param discKey target buffer where the result will be stored. + * @return MOCHA_RESULT_SUCCESS: The disc key of the inserted disc has been read into the given buffer.
+ * MOCHA_RESULT_INVALID_ARGUMENT: The given discKey buffer was NULL
+ * MOCHA_RESULT_LIB_UNINITIALIZED: Library was not initialized. Call Mocha_InitLibrary() before using this function.
+ * MOCHA_RESULT_UNSUPPORTED_COMMAND: Command not supported by the currently loaded mocha version.
+ * MOCHA_RESULT_NOT_FOUND: Failed to obtain disc key, no disc inserted?. + * MOCHA_RESULT_UNKNOWN_ERROR: Unknown error. + */ +MochaUtilsStatus Mocha_ODMGetDiscKey(WUDDiscKey *discKey); + +/** + * Reads *size* bytes from *offset* from the SEEPROM of the console. Total size of SEEPROM is 0x200 + * @param out_buffer buffer where the result will be stored + * @param offset offset in bytes. Must be an even number. + * @param size size in bytes + * @return MOCHA_RESULT_SUCCESS: The SEEPROM has been read into the given buffer.
+ * MOCHA_RESULT_INVALID_ARGUMENT: The given out_buffer was NULL or the offset was < 0 or an odd value
+ * MOCHA_RESULT_LIB_UNINITIALIZED: Library was not initialized. Call Mocha_InitLibrary() before using this function.
+ * MOCHA_RESULT_UNSUPPORTED_COMMAND: Command not supported by the currently loaded mocha version.
+ * MOCHA_RESULT_UNKNOWN_ERROR: Failed to read the seeprom. + */ +MochaUtilsStatus Mocha_SEEPROMRead(uint8_t *out_buffer, uint32_t offset, uint32_t size); + +/** + * Mounts a device (dev_path) to a given path (mount_path) and make a accessible via the + * newlib devoptab (standard POSIX file I/O) + * + * Requires Mocha API Version: 1 + * @param virt_name Name which should be used for the devoptab. When choosing e.g. "storage_usb" the mounted device can be accessed via "storage_usb:/". + * @param dev_path (optional) Cafe OS internal device path (e.g. /dev/slc01). If the given dev_path is NULL, an existing mount will be used (and is expected) + * @param mount_path Path where CafeOS should mount the device to. Must be globally unique and start with "/vol/storage_" + * @return MOCHA_RESULT_SUCCESS: The device has been mounted successfully
+ * MOCHA_RESULT_MAX_CLIENT: The maximum number of FSAClients have been registered.
+ * MOCHA_RESULT_LIB_UNINITIALIZED: Library was not initialized. Call Mocha_InitLibrary() before using this function.
+ * MOCHA_RESULT_UNSUPPORTED_COMMAND: Command not supported by the currently loaded mocha version.
+ * MOCHA_RESULT_UNKNOWN_ERROR: Failed to retrieve the environment path. + */ +MochaUtilsStatus Mocha_MountFS(const char *virt_name, const char *dev_path, const char *mount_path); + +MochaUtilsStatus Mocha_MountFSEx(const char *virt_name, const char *dev_path, const char *mount_path, FSAMountFlags mountFlags, void *mountArgBuf, int mountArgBufLen); + +/** + * Unmounts a mount by it's name. + * @param virt_name Name of the mount. + * @return MOCHA_RESULT_SUCCESS: The unmount was successful
+ * MOCHA_RESULT_INVALID_ARGUMENT:
+ * MOCHA_RESULT_NOT_FOUND: No mount with the given name has been found. + */ +MochaUtilsStatus Mocha_UnmountFS(const char *virt_name); + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/deps/libmocha/include/mocha/otp.h b/deps/libmocha/include/mocha/otp.h new file mode 100644 index 000000000000..a876b847e05a --- /dev/null +++ b/deps/libmocha/include/mocha/otp.h @@ -0,0 +1,193 @@ +#pragma once +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct WiiUConsoleOTP WiiUConsoleOTP; +typedef struct OTPWiiBank OTPWiiBank; +typedef struct OTPWiiUBank OTPWiiUBank; +typedef struct OTPWiiUNGBank OTPWiiUNGBank; +typedef struct OTPWiiUCertBank OTPWiiUCertBank; +typedef struct OTPWiiCertBank OTPWiiCertBank; +typedef struct OTPMiscBank OTPMiscBank; + +typedef uint32_t OTPJTAGStatus; +typedef uint32_t OTPSecurityLevel; + +typedef enum OTPSecurityLevelFlags { + SECURITY_FLAG_UNKNOWN = 0x40000000, // Unknown, causes error in boot0 + SECURITY_FLAG_CONSOLE_PROGRAMMED = 0x80000000, // Console type has been programmed + SECURITY_FLAG_USE_DEBUG_KEY_IMAGE = 0x08000000, // Use first RSA key and debug ancast images in boot0 + SECURITY_FLAG_USE_RETAIL_KEY_IMAGE = 0x10000000 // Use second RSA key and retail ancast images in boot0 +} OTPSecurityLevelFlags; + +typedef enum OTPIOStrength { + IO_HW_IOSTRCTRL0 = 0x00008000, + IO_HW_IOSTRCTRL1_3 = 0x00002000, + IO_HW_IOSTRCTRL1_2 = 0x00000800, + IO_HW_IOSTRCTRL1_1 = 0x00000080, + IO_HW_IOSTRCTRL1_0 = 0x00000008, + IO_NONE = 0x00000000 +} OTPIOStrength; + +typedef enum OTPPulseLength { + PULSE_BOOT0 = 0x0000002F, + PULSE_NONE = 0x00000000 +} OTPPulseLength; + +typedef enum OTPJTAGMask { + JTAG_MASK_DISABLED = 0x80 +} OTPJTAGMask; + +struct OTPWiiBank { + uint8_t boot1SHA1Hash[0x14]; + uint8_t commonKey[0x10]; + uint32_t ngId; + uint8_t ngPrivateKey[0x1C]; + uint8_t nandHMAC[0x14]; + uint8_t nandKey[0x10]; + uint8_t rngKey[0x10]; + WUT_UNKNOWN_BYTES(0x08); +}; +WUT_CHECK_SIZE(OTPWiiBank, 0x80); +WUT_CHECK_OFFSET(OTPWiiBank, 0x00, boot1SHA1Hash); +WUT_CHECK_OFFSET(OTPWiiBank, 0x14, commonKey); +WUT_CHECK_OFFSET(OTPWiiBank, 0x24, ngId); +WUT_CHECK_OFFSET(OTPWiiBank, 0x28, ngPrivateKey); +WUT_CHECK_OFFSET(OTPWiiBank, 0x44, nandHMAC); +WUT_CHECK_OFFSET(OTPWiiBank, 0x58, nandKey); +WUT_CHECK_OFFSET(OTPWiiBank, 0x68, rngKey); + +struct OTPWiiUBank { + OTPSecurityLevel securityLevel; + OTPIOStrength ioStrength; + OTPPulseLength pulseLength; + uint32_t signature; + uint8_t starbuckAncastKey[0x10]; + uint8_t seepromKey[0x10]; + WUT_UNKNOWN_BYTES(0x10); + WUT_UNKNOWN_BYTES(0x10); + uint8_t vWiiCommonKey[0x10]; + uint8_t wiiUCommonKey[0x10]; + WUT_UNKNOWN_BYTES(0x10); + WUT_UNKNOWN_BYTES(0x10); + WUT_UNKNOWN_BYTES(0x10); + uint8_t sslRSAKey[0x10]; + uint8_t usbStorageSeedsKey[0x10]; + WUT_UNKNOWN_BYTES(0x10); + uint8_t xorKey[0x10]; + uint8_t rngKey[0x10]; + uint8_t slcKey[0x10]; + uint8_t mlcKey[0x10]; + uint8_t sshdKey[0x10]; + uint8_t drhWLAN[0x10]; + WUT_UNKNOWN_BYTES(0x30); + uint8_t slcHmac[0x14]; + WUT_UNKNOWN_BYTES(0x0C); +}; +WUT_CHECK_SIZE(OTPWiiUBank, 0x180); +WUT_CHECK_OFFSET(OTPWiiUBank, 0x00, securityLevel); +WUT_CHECK_OFFSET(OTPWiiUBank, 0x04, ioStrength); +WUT_CHECK_OFFSET(OTPWiiUBank, 0x08, pulseLength); +WUT_CHECK_OFFSET(OTPWiiUBank, 0x10, starbuckAncastKey); +WUT_CHECK_OFFSET(OTPWiiUBank, 0x20, seepromKey); +WUT_CHECK_OFFSET(OTPWiiUBank, 0x50, vWiiCommonKey); +WUT_CHECK_OFFSET(OTPWiiUBank, 0x60, wiiUCommonKey); +WUT_CHECK_OFFSET(OTPWiiUBank, 0xA0, sslRSAKey); +WUT_CHECK_OFFSET(OTPWiiUBank, 0xB0, usbStorageSeedsKey); +WUT_CHECK_OFFSET(OTPWiiUBank, 0xD0, xorKey); +WUT_CHECK_OFFSET(OTPWiiUBank, 0xE0, rngKey); +WUT_CHECK_OFFSET(OTPWiiUBank, 0xF0, slcKey); +WUT_CHECK_OFFSET(OTPWiiUBank, 0x100, mlcKey); +WUT_CHECK_OFFSET(OTPWiiUBank, 0x110, sshdKey); +WUT_CHECK_OFFSET(OTPWiiUBank, 0x120, drhWLAN); +WUT_CHECK_OFFSET(OTPWiiUBank, 0x160, slcHmac); + +struct OTPWiiUNGBank { + WUT_UNKNOWN_BYTES(0x10); + WUT_UNKNOWN_BYTES(0x0C); + uint32_t ngId; + uint8_t ngPrivateKey[0x20]; + uint8_t privateNSSDeviceCertKey[0x20]; + uint8_t otpRNGSeed[0x10]; + WUT_UNKNOWN_BYTES(0x10); +}; +WUT_CHECK_SIZE(OTPWiiUNGBank, 0x80); +WUT_CHECK_OFFSET(OTPWiiUNGBank, 0x1C, ngId); +WUT_CHECK_OFFSET(OTPWiiUNGBank, 0x20, ngPrivateKey); +WUT_CHECK_OFFSET(OTPWiiUNGBank, 0x40, privateNSSDeviceCertKey); +WUT_CHECK_OFFSET(OTPWiiUNGBank, 0x60, otpRNGSeed); + +struct OTPWiiUCertBank { + uint32_t rootCertMSId; + uint32_t rootCertCAId; + uint32_t rootCertNGKeyId; + uint8_t rootCertNGSignature[0x3C]; + WUT_UNKNOWN_BYTES(0x18); + WUT_UNKNOWN_BYTES(0x20); +}; +WUT_CHECK_SIZE(OTPWiiUCertBank, 0x80); +WUT_CHECK_OFFSET(OTPWiiUCertBank, 0x00, rootCertMSId); +WUT_CHECK_OFFSET(OTPWiiUCertBank, 0x04, rootCertCAId); +WUT_CHECK_OFFSET(OTPWiiUCertBank, 0x08, rootCertNGKeyId); +WUT_CHECK_OFFSET(OTPWiiUCertBank, 0x0C, rootCertNGSignature); + +struct OTPWiiCertBank { + uint32_t rootCertMSId; + uint32_t rootCertCAId; + uint32_t rootCertNGKeyId; + uint8_t rootCertNGSignature[0x3C]; + uint8_t koreanKey[0x10]; + WUT_UNKNOWN_BYTES(0x08); + uint8_t privateNSSDeviceCertKey[0x20]; +}; +WUT_CHECK_SIZE(OTPWiiCertBank, 0x80); +WUT_CHECK_OFFSET(OTPWiiCertBank, 0x00, rootCertMSId); +WUT_CHECK_OFFSET(OTPWiiCertBank, 0x04, rootCertCAId); +WUT_CHECK_OFFSET(OTPWiiCertBank, 0x08, rootCertNGKeyId); +WUT_CHECK_OFFSET(OTPWiiCertBank, 0x0C, rootCertNGSignature); +WUT_CHECK_OFFSET(OTPWiiCertBank, 0x48, koreanKey); +WUT_CHECK_OFFSET(OTPWiiCertBank, 0x60, privateNSSDeviceCertKey); + +struct OTPMiscBank { + WUT_UNKNOWN_BYTES(0x20); + uint8_t boot1Key_protected[0x10]; + WUT_UNKNOWN_BYTES(0x10); + WUT_UNKNOWN_BYTES(0x20); + WUT_UNKNOWN_BYTES(0x04); + uint32_t otpVersionAndRevision; + uint64_t otpDateCode; + char otpVersionName[0x08]; + WUT_UNKNOWN_BYTES(0x04); + OTPJTAGStatus jtagStatus; +}; +WUT_CHECK_SIZE(OTPMiscBank, 0x80); +WUT_CHECK_OFFSET(OTPMiscBank, 0x20, boot1Key_protected); +WUT_CHECK_OFFSET(OTPMiscBank, 0x64, otpVersionAndRevision); +WUT_CHECK_OFFSET(OTPMiscBank, 0x68, otpDateCode); +WUT_CHECK_OFFSET(OTPMiscBank, 0x70, otpVersionName); +WUT_CHECK_OFFSET(OTPMiscBank, 0x7C, jtagStatus); + +struct WiiUConsoleOTP { + OTPWiiBank wiiBank; + OTPWiiUBank wiiUBank; + OTPWiiUNGBank wiiUNGBank; + OTPWiiUCertBank wiiUCertBank; + OTPWiiCertBank wiiCertBank; + OTPMiscBank miscBank; +}; +WUT_CHECK_SIZE(WiiUConsoleOTP, 0x400); +WUT_CHECK_OFFSET(WiiUConsoleOTP, 0x00, wiiBank); +WUT_CHECK_OFFSET(WiiUConsoleOTP, 0x80, wiiUBank); +WUT_CHECK_OFFSET(WiiUConsoleOTP, 0x200, wiiUNGBank); +WUT_CHECK_OFFSET(WiiUConsoleOTP, 0x280, wiiUCertBank); +WUT_CHECK_OFFSET(WiiUConsoleOTP, 0x300, wiiCertBank); +WUT_CHECK_OFFSET(WiiUConsoleOTP, 0x380, miscBank); + +#ifdef __cplusplus +} // extern "C" +#endif \ No newline at end of file diff --git a/deps/libmocha/source/devoptab/MutexWrapper.h b/deps/libmocha/source/devoptab/MutexWrapper.h new file mode 100644 index 000000000000..d3b079df7692 --- /dev/null +++ b/deps/libmocha/source/devoptab/MutexWrapper.h @@ -0,0 +1,25 @@ +#pragma once + +#include "coreinit/cache.h" +#include + +class MutexWrapper { +public: + MutexWrapper() = default; + + void init(const char *name) { + OSInitMutexEx(&mutex, name); + } + + void lock() { + OSLockMutex(&mutex); + } + + void unlock() { + OSUnlockMutex(&mutex); + OSMemoryBarrier(); + } + +private: + OSMutex mutex{}; +}; diff --git a/deps/libmocha/source/devoptab/devoptab_fsa.cpp b/deps/libmocha/source/devoptab/devoptab_fsa.cpp new file mode 100644 index 000000000000..52acc88ef6c6 --- /dev/null +++ b/deps/libmocha/source/devoptab/devoptab_fsa.cpp @@ -0,0 +1,205 @@ +#include "devoptab_fsa.h" +#include "logger.h" +#include "mocha/mocha.h" +#include +#include +#include +#include + +static const devoptab_t fsa_default_devoptab = { + .structSize = sizeof(__fsa_file_t), + .open_r = __fsa_open, + .close_r = __fsa_close, + .write_r = __fsa_write, + .read_r = __fsa_read, + .seek_r = __fsa_seek, + .fstat_r = __fsa_fstat, + .stat_r = __fsa_stat, + .link_r = __fsa_link, + .unlink_r = __fsa_unlink, + .chdir_r = __fsa_chdir, + .rename_r = __fsa_rename, + .mkdir_r = __fsa_mkdir, + .dirStateSize = sizeof(__fsa_dir_t), + .diropen_r = __fsa_diropen, + .dirreset_r = __fsa_dirreset, + .dirnext_r = __fsa_dirnext, + .dirclose_r = __fsa_dirclose, + .statvfs_r = __fsa_statvfs, + .ftruncate_r = __fsa_ftruncate, + .fsync_r = __fsa_fsync, + .chmod_r = __fsa_chmod, + .fchmod_r = __fsa_fchmod, + .rmdir_r = __fsa_rmdir, + .lstat_r = __fsa_stat, + .utimes_r = __fsa_utimes, +}; + +static bool fsa_initialised = false; +static FSADeviceData fsa_mounts[0x10]; + +static void fsaResetMount(FSADeviceData *mount, uint32_t id) { + *mount = {}; + memcpy(&mount->device, &fsa_default_devoptab, sizeof(fsa_default_devoptab)); + mount->device.name = mount->name; + mount->device.deviceData = mount; + mount->id = id; + mount->setup = false; + mount->mounted = false; + mount->clientHandle = -1; + mount->deviceSizeInSectors = 0; + mount->deviceSectorSize = 0; + memset(mount->mount_path, 0, sizeof(mount->mount_path)); + memset(mount->name, 0, sizeof(mount->name)); + DCFlushRange(mount, sizeof(*mount)); +} + +void fsaInit() { + if (!fsa_initialised) { + uint32_t total = sizeof(fsa_mounts) / sizeof(fsa_mounts[0]); + for (uint32_t i = 0; i < total; i++) { + fsaResetMount(&fsa_mounts[i], i); + } + fsa_initialised = true; + } +} + +std::mutex fsaMutex; + +FSADeviceData *fsa_alloc() { + uint32_t i; + uint32_t total = sizeof(fsa_mounts) / sizeof(fsa_mounts[0]); + FSADeviceData *mount; + + fsaInit(); + + for (i = 0; i < total; i++) { + mount = &fsa_mounts[i]; + if (!mount->setup) { + return mount; + } + } + + return nullptr; +} + +static void fsa_free(FSADeviceData *mount) { + FSError res; + if (mount->mounted) { + if ((res = FSAUnmount(mount->clientHandle, mount->mount_path, FSA_UNMOUNT_FLAG_FORCE)) < 0) { + DEBUG_FUNCTION_LINE_WARN("FSAUnmount %s for %s failed: %s", mount->mount_path, mount->name, FSAGetStatusStr(res)); + } + } + res = FSADelClient(mount->clientHandle); + if (res < 0) { + DEBUG_FUNCTION_LINE_WARN("FSADelClient for %s failed: %s", mount->name, FSAGetStatusStr(res)); + } + fsaResetMount(mount, mount->id); +} + +MochaUtilsStatus Mocha_UnmountFS(const char *virt_name) { + if (!virt_name) { + return MOCHA_RESULT_INVALID_ARGUMENT; + } + std::lock_guard lock(fsaMutex); + uint32_t total = sizeof(fsa_mounts) / sizeof(fsa_mounts[0]); + + fsaInit(); + + for (uint32_t i = 0; i < total; i++) { + FSADeviceData *mount = &fsa_mounts[i]; + if (!mount->setup) { + continue; + } + if (strcmp(mount->name, virt_name) == 0) { + std::string removeName = std::string(mount->name).append(":"); + RemoveDevice(removeName.c_str()); + fsa_free(mount); + return MOCHA_RESULT_SUCCESS; + } + } + + DEBUG_FUNCTION_LINE_WARN("Failed to find fsa mount data for %s", virt_name); + return MOCHA_RESULT_NOT_FOUND; +} +extern int mochaInitDone; + +MochaUtilsStatus Mocha_MountFS(const char *virt_name, const char *dev_path, const char *mount_path) { + return Mocha_MountFSEx(virt_name, dev_path, mount_path, FSA_MOUNT_FLAG_GLOBAL_MOUNT, nullptr, 0); +} + +MochaUtilsStatus Mocha_MountFSEx(const char *virt_name, const char *dev_path, const char *mount_path, FSAMountFlags mountFlags, void *mountArgBuf, int mountArgBufLen) { + if (!mochaInitDone) { + if (Mocha_InitLibrary() != MOCHA_RESULT_SUCCESS) { + DEBUG_FUNCTION_LINE_ERR("Mocha_InitLibrary failed"); + return MOCHA_RESULT_UNSUPPORTED_COMMAND; + } + } + + FSAInit(); + std::lock_guard lock(fsaMutex); + + FSADeviceData *mount = fsa_alloc(); + if (mount == nullptr) { + DEBUG_FUNCTION_LINE_ERR("fsa_alloc() failed"); + OSMemoryBarrier(); + return MOCHA_RESULT_MAX_CLIENT; + } + + mount->clientHandle = FSAAddClient(nullptr); + if (mount->clientHandle < 0) { + DEBUG_FUNCTION_LINE_ERR("FSAAddClient() failed: %s", FSAGetStatusStr(static_cast(mount->clientHandle))); + fsa_free(mount); + return MOCHA_RESULT_MAX_CLIENT; + } + + MochaUtilsStatus status; + if ((status = Mocha_UnlockFSClientEx(mount->clientHandle)) != MOCHA_RESULT_SUCCESS) { + DEBUG_FUNCTION_LINE_ERR("Mocha_UnlockFSClientEx failed: %s", Mocha_GetStatusStr(status)); + return MOCHA_RESULT_UNSUPPORTED_COMMAND; + } + + mount->mounted = false; + + strncpy(mount->name, virt_name, sizeof(mount->name) - 1); + strncpy(mount->mount_path, mount_path, sizeof(mount->mount_path) - 1); + FSError res; + if (dev_path) { + res = FSAMount(mount->clientHandle, dev_path, mount_path, mountFlags, mountArgBuf, mountArgBufLen); + if (res < 0) { + DEBUG_FUNCTION_LINE_ERR("FSAMount(0x%08X, %s, %s, %08X, %08X, %08X) failed: %s", mount->clientHandle, dev_path, mount_path, mountFlags, mountArgBuf, mountArgBufLen, FSAGetStatusStr(res)); + fsa_free(mount); + if (res == FS_ERROR_ALREADY_EXISTS) { + return MOCHA_RESULT_ALREADY_EXISTS; + } + return MOCHA_RESULT_UNKNOWN_ERROR; + } + mount->mounted = true; + } else { + mount->mounted = false; + } + + if ((res = FSAChangeDir(mount->clientHandle, mount->mount_path)) < 0) { + DEBUG_FUNCTION_LINE_WARN("FSAChangeDir(0x%08X, %s) failed: %s", mount->clientHandle, mount->mount_path, FSAGetStatusStr(res)); + } + + FSADeviceInfo deviceInfo; + if ((res = FSAGetDeviceInfo(mount->clientHandle, mount_path, &deviceInfo)) >= 0) { + mount->deviceSizeInSectors = deviceInfo.deviceSizeInSectors; + mount->deviceSectorSize = deviceInfo.deviceSectorSize; + } else { + mount->deviceSizeInSectors = 0xFFFFFFFF; + mount->deviceSectorSize = 512; + DEBUG_FUNCTION_LINE_WARN("Failed to get DeviceInfo for %s: %s", mount_path, FSAGetStatusStr(res)); + } + + if (AddDevice(&mount->device) < 0) { + DEBUG_FUNCTION_LINE_ERR("AddDevice failed for %s.", virt_name); + fsa_free(mount); + return MOCHA_RESULT_ADD_DEVOPTAB_FAILED; + } + + mount->setup = true; + + return MOCHA_RESULT_SUCCESS; +} diff --git a/deps/libmocha/source/devoptab/devoptab_fsa.h b/deps/libmocha/source/devoptab/devoptab_fsa.h new file mode 100644 index 000000000000..2e3b7db1efe3 --- /dev/null +++ b/deps/libmocha/source/devoptab/devoptab_fsa.h @@ -0,0 +1,118 @@ +#pragma once +#include "MutexWrapper.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +typedef struct FSADeviceData { + devoptab_t device{}; + bool setup{}; + bool mounted{}; + uint32_t id{}; + char name[32]{}; + char mount_path[256]{}; + FSAClientHandle clientHandle{}; + uint64_t deviceSizeInSectors{}; + uint32_t deviceSectorSize{}; +} FSADeviceData; + +/** + * Open file struct + */ +typedef struct +{ + //! FS handle + FSAFileHandle fd; + + //! Flags used in open(2) + int flags; + + //! Current file offset + uint32_t offset; + + //! Path stored for internal path tracking + char fullPath[FS_MAX_PATH + 1]; + + //! Guard file access + MutexWrapper mutex; + + //! Current file size (only valid if O_APPEND is set) + uint32_t appendOffset; +} __fsa_file_t; + +/** + * Open directory struct + */ +typedef struct { + //! Should be set to FS_DIRITER_MAGIC + uint32_t magic; + + //! FS handle + FSADirectoryHandle fd; + + //! Temporary storage for reading entries + FSADirectoryEntry entry_data; + + //! Current file path + char name[FS_MAX_PATH + 1]; + + //! Guard dir access + MutexWrapper mutex; +} __fsa_dir_t; + +#define FSA_DIRITER_MAGIC 0x77696975 + +#ifdef __cplusplus +extern "C" { +#endif + +int __fsa_open(struct _reent *r, void *fileStruct, const char *path, + int flags, int mode); +int __fsa_close(struct _reent *r, void *fd); +ssize_t __fsa_write(struct _reent *r, void *fd, const char *ptr, + size_t len); +ssize_t __fsa_read(struct _reent *r, void *fd, char *ptr, size_t len); +off_t __fsa_seek(struct _reent *r, void *fd, off_t pos, int dir); +int __fsa_fstat(struct _reent *r, void *fd, struct stat *st); +int __fsa_stat(struct _reent *r, const char *file, struct stat *st); +int __fsa_link(struct _reent *r, const char *existing, + const char *newLink); +int __fsa_unlink(struct _reent *r, const char *name); +int __fsa_chdir(struct _reent *r, const char *name); +int __fsa_rename(struct _reent *r, const char *oldName, + const char *newName); +int __fsa_mkdir(struct _reent *r, const char *path, int mode); +DIR_ITER *__fsa_diropen(struct _reent *r, DIR_ITER *dirState, + const char *path); +int __fsa_dirreset(struct _reent *r, DIR_ITER *dirState); +int __fsa_dirnext(struct _reent *r, DIR_ITER *dirState, char *filename, + struct stat *filestat); +int __fsa_dirclose(struct _reent *r, DIR_ITER *dirState); +int __fsa_statvfs(struct _reent *r, const char *path, + struct statvfs *buf); +int __fsa_ftruncate(struct _reent *r, void *fd, off_t len); +int __fsa_fsync(struct _reent *r, void *fd); +int __fsa_chmod(struct _reent *r, const char *path, mode_t mode); +int __fsa_fchmod(struct _reent *r, void *fd, mode_t mode); +int __fsa_rmdir(struct _reent *r, const char *name); +int __fsa_utimes(struct _reent *r, const char *filename, const struct timeval times[2]); + +// devoptab_fs_utils.c +char *__fsa_fixpath(struct _reent *r, const char *path); +int __fsa_translate_error(FSError error); +time_t __fsa_translate_time(FSTime timeValue); +FSMode __fsa_translate_permission_mode(mode_t mode); +mode_t __fsa_translate_stat_mode(FSAStat *fileStat); +void __fsa_translate_stat(FSAStat *fsStat, struct stat *posStat); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/deps/libmocha/source/devoptab/devoptab_fsa_chdir.cpp b/deps/libmocha/source/devoptab/devoptab_fsa_chdir.cpp new file mode 100644 index 000000000000..8165bcebfc19 --- /dev/null +++ b/deps/libmocha/source/devoptab/devoptab_fsa_chdir.cpp @@ -0,0 +1,31 @@ +#include "devoptab_fsa.h" +#include "logger.h" +#include + +int __fsa_chdir(struct _reent *r, + const char *path) { + FSError status; + + if (!path) { + r->_errno = EINVAL; + return -1; + } + + char *fixedPath = __fsa_fixpath(r, path); + if (!fixedPath) { + r->_errno = ENOMEM; + return -1; + } + auto *deviceData = (FSADeviceData *) r->deviceData; + + status = FSAChangeDir(deviceData->clientHandle, fixedPath); + if (status < 0) { + DEBUG_FUNCTION_LINE_ERR("FSAChangeDir(0x%08X, %s) failed: %s", deviceData->clientHandle, fixedPath, FSAGetStatusStr(status)); + free(fixedPath); + r->_errno = __fsa_translate_error(status); + return -1; + } + free(fixedPath); + + return 0; +} diff --git a/deps/libmocha/source/devoptab/devoptab_fsa_chmod.cpp b/deps/libmocha/source/devoptab/devoptab_fsa_chmod.cpp new file mode 100644 index 000000000000..73ddb7154644 --- /dev/null +++ b/deps/libmocha/source/devoptab/devoptab_fsa_chmod.cpp @@ -0,0 +1,36 @@ +#include "devoptab_fsa.h" +#include "logger.h" +#include +#include + +int __fsa_chmod(struct _reent *r, + const char *path, + mode_t mode) { + FSError status; + + if (!path) { + r->_errno = EINVAL; + return -1; + } + + char *fixedPath = __fsa_fixpath(r, path); + if (!fixedPath) { + r->_errno = ENOMEM; + return -1; + } + + FSMode translatedMode = __fsa_translate_permission_mode(mode); + + auto *deviceData = (FSADeviceData *) r->deviceData; + + status = FSAChangeMode(deviceData->clientHandle, fixedPath, translatedMode); + if (status < 0) { + DEBUG_FUNCTION_LINE_ERR("FSAChangeMode(0x%08X, %s, 0x%X) failed: %s", deviceData->clientHandle, fixedPath, translatedMode, FSAGetStatusStr(status)); + free(fixedPath); + r->_errno = __fsa_translate_error(status); + return -1; + } + free(fixedPath); + + return 0; +} diff --git a/deps/libmocha/source/devoptab/devoptab_fsa_close.cpp b/deps/libmocha/source/devoptab/devoptab_fsa_close.cpp new file mode 100644 index 000000000000..cc3783a1ffed --- /dev/null +++ b/deps/libmocha/source/devoptab/devoptab_fsa_close.cpp @@ -0,0 +1,29 @@ +#include "devoptab_fsa.h" +#include "logger.h" +#include + +int __fsa_close(struct _reent *r, + void *fd) { + FSError status; + __fsa_file_t *file; + + if (!fd) { + r->_errno = EINVAL; + return -1; + } + + file = (__fsa_file_t *) fd; + + auto *deviceData = (FSADeviceData *) r->deviceData; + + std::lock_guard lock(file->mutex); + + status = FSACloseFile(deviceData->clientHandle, file->fd); + if (status < 0) { + DEBUG_FUNCTION_LINE_ERR("FSACloseFile(0x%08X, 0x%08X) failed: %s", deviceData->clientHandle, file->fd, FSAGetStatusStr(status)); + r->_errno = __fsa_translate_error(status); + return -1; + } + + return 0; +} diff --git a/deps/libmocha/source/devoptab/devoptab_fsa_dirclose.cpp b/deps/libmocha/source/devoptab/devoptab_fsa_dirclose.cpp new file mode 100644 index 000000000000..44ad08059703 --- /dev/null +++ b/deps/libmocha/source/devoptab/devoptab_fsa_dirclose.cpp @@ -0,0 +1,28 @@ +#include "devoptab_fsa.h" +#include "logger.h" +#include + +int __fsa_dirclose(struct _reent *r, + DIR_ITER *dirState) { + FSError status; + + if (!dirState) { + r->_errno = EINVAL; + return -1; + } + + auto *dir = (__fsa_dir_t *) (dirState->dirStruct); + auto *deviceData = (FSADeviceData *) r->deviceData; + + std::lock_guard lock(dir->mutex); + + status = FSACloseDir(deviceData->clientHandle, dir->fd); + if (status < 0) { + DEBUG_FUNCTION_LINE_ERR("FSACloseDir(0x%08X, 0x%08X) (%s) failed: %s", + deviceData->clientHandle, dir->fd, dir->name, FSAGetStatusStr(status)); + r->_errno = __fsa_translate_error(status); + return -1; + } + + return 0; +} diff --git a/deps/libmocha/source/devoptab/devoptab_fsa_dirnext.cpp b/deps/libmocha/source/devoptab/devoptab_fsa_dirnext.cpp new file mode 100644 index 000000000000..e13a5554f0f3 --- /dev/null +++ b/deps/libmocha/source/devoptab/devoptab_fsa_dirnext.cpp @@ -0,0 +1,39 @@ +#include "devoptab_fsa.h" +#include "logger.h" +#include +#include + +int __fsa_dirnext(struct _reent *r, + DIR_ITER *dirState, + char *filename, + struct stat *filestat) { + FSError status; + + if (!dirState || !filename || !filestat) { + r->_errno = EINVAL; + return -1; + } + + auto *deviceData = (FSADeviceData *) r->deviceData; + auto *dir = (__fsa_dir_t *) (dirState->dirStruct); + + std::lock_guard lock(dir->mutex); + memset(&dir->entry_data, 0, sizeof(dir->entry_data)); + + status = FSAReadDir(deviceData->clientHandle, dir->fd, &dir->entry_data); + if (status < 0) { + if (status != FS_ERROR_END_OF_DIR) { + DEBUG_FUNCTION_LINE_ERR("FSAReadDir(0x%08X, 0x%08X, 0x%08X) (%s) failed: %s", + deviceData->clientHandle, dir->fd, &dir->entry_data, dir->name, FSAGetStatusStr(status)); + } + r->_errno = __fsa_translate_error(status); + return -1; + } + + __fsa_translate_stat(&dir->entry_data.info, filestat); + + if (snprintf(filename, NAME_MAX, "%s", dir->entry_data.name) >= NAME_MAX) { + DEBUG_FUNCTION_LINE_ERR("snprintf filename result was truncated\n"); + } + return 0; +} diff --git a/deps/libmocha/source/devoptab/devoptab_fsa_diropen.cpp b/deps/libmocha/source/devoptab/devoptab_fsa_diropen.cpp new file mode 100644 index 000000000000..088687061595 --- /dev/null +++ b/deps/libmocha/source/devoptab/devoptab_fsa_diropen.cpp @@ -0,0 +1,41 @@ +#include "devoptab_fsa.h" +#include "logger.h" +#include + +DIR_ITER * +__fsa_diropen(struct _reent *r, + DIR_ITER *dirState, + const char *path) { + FSADirectoryHandle fd; + FSError status; + + if (!dirState || !path) { + r->_errno = EINVAL; + return nullptr; + } + + char *fixedPath = __fsa_fixpath(r, path); + if (!fixedPath) { + return nullptr; + } + auto *dir = (__fsa_dir_t *) (dirState->dirStruct); + strncpy(dir->name, fixedPath, sizeof(dir->name) - 1); + free(fixedPath); + + dir->mutex.init(dir->name); + std::lock_guard lock(dir->mutex); + + auto *deviceData = (FSADeviceData *) r->deviceData; + status = FSAOpenDir(deviceData->clientHandle, dir->name, &fd); + if (status < 0) { + DEBUG_FUNCTION_LINE_ERR("FSAOpenDir(0x%08X, %s, 0x%08X) failed: %s", + deviceData->clientHandle, dir->name, &fd, FSAGetStatusStr(status)); + r->_errno = __fsa_translate_error(status); + return nullptr; + } + + dir->magic = FSA_DIRITER_MAGIC; + dir->fd = fd; + memset(&dir->entry_data, 0, sizeof(dir->entry_data)); + return dirState; +} diff --git a/deps/libmocha/source/devoptab/devoptab_fsa_dirreset.cpp b/deps/libmocha/source/devoptab/devoptab_fsa_dirreset.cpp new file mode 100644 index 000000000000..7fa348aa24e4 --- /dev/null +++ b/deps/libmocha/source/devoptab/devoptab_fsa_dirreset.cpp @@ -0,0 +1,28 @@ +#include "devoptab_fsa.h" +#include "logger.h" +#include + +int __fsa_dirreset(struct _reent *r, + DIR_ITER *dirState) { + FSError status; + + if (!dirState) { + r->_errno = EINVAL; + return -1; + } + + auto *dir = (__fsa_dir_t *) (dirState->dirStruct); + auto *deviceData = (FSADeviceData *) r->deviceData; + + std::lock_guard lock(dir->mutex); + + status = FSARewindDir(deviceData->clientHandle, dir->fd); + if (status < 0) { + DEBUG_FUNCTION_LINE_ERR("FSARewindDir(0x%08X, 0x%08X) (%s) failed: %s", + deviceData->clientHandle, dir->fd, dir->name, FSAGetStatusStr(status)); + r->_errno = __fsa_translate_error(status); + return -1; + } + + return 0; +} diff --git a/deps/libmocha/source/devoptab/devoptab_fsa_fchmod.cpp b/deps/libmocha/source/devoptab/devoptab_fsa_fchmod.cpp new file mode 100644 index 000000000000..e0bd6ec6eadc --- /dev/null +++ b/deps/libmocha/source/devoptab/devoptab_fsa_fchmod.cpp @@ -0,0 +1,11 @@ +#include "devoptab_fsa.h" +#include "logger.h" +#include + +int __fsa_fchmod(struct _reent *r, + void *fd, + mode_t mode) { + // FSChangeMode on open files is not possible on Cafe OS + r->_errno = ENOSYS; + return -1; +} diff --git a/deps/libmocha/source/devoptab/devoptab_fsa_fstat.cpp b/deps/libmocha/source/devoptab/devoptab_fsa_fstat.cpp new file mode 100644 index 000000000000..0bdfc9e5f31d --- /dev/null +++ b/deps/libmocha/source/devoptab/devoptab_fsa_fstat.cpp @@ -0,0 +1,32 @@ +#include "devoptab_fsa.h" +#include "logger.h" +#include + +int __fsa_fstat(struct _reent *r, + void *fd, + struct stat *st) { + FSError status; + FSAStat fsStat; + + if (!fd || !st) { + r->_errno = EINVAL; + return -1; + } + + auto *file = (__fsa_file_t *) fd; + auto *deviceData = (FSADeviceData *) r->deviceData; + + std::lock_guard lock(file->mutex); + + status = FSAGetStatFile(deviceData->clientHandle, file->fd, &fsStat); + if (status < 0) { + DEBUG_FUNCTION_LINE_ERR("FSAGetStatFile(0x%08X, 0x%08X, 0x%08X) (%s) failed: %s", + deviceData->clientHandle, file->fd, &fsStat, file->fullPath, FSAGetStatusStr(status)); + r->_errno = __fsa_translate_error(status); + return -1; + } + + __fsa_translate_stat(&fsStat, st); + + return 0; +} diff --git a/deps/libmocha/source/devoptab/devoptab_fsa_fsync.cpp b/deps/libmocha/source/devoptab/devoptab_fsa_fsync.cpp new file mode 100644 index 000000000000..38503911c855 --- /dev/null +++ b/deps/libmocha/source/devoptab/devoptab_fsa_fsync.cpp @@ -0,0 +1,28 @@ +#include "devoptab_fsa.h" +#include "logger.h" +#include + +int __fsa_fsync(struct _reent *r, + void *fd) { + FSError status; + + if (!fd) { + r->_errno = EINVAL; + return -1; + } + + auto *file = (__fsa_file_t *) fd; + auto *deviceData = (FSADeviceData *) r->deviceData; + + std::lock_guard lock(file->mutex); + + status = FSAFlushFile(deviceData->clientHandle, file->fd); + if (status < 0) { + DEBUG_FUNCTION_LINE_ERR("FSAFlushFile(0x%08X, 0x%08X) (%s) failed: %s", + deviceData->clientHandle, file->fd, file->fullPath, FSAGetStatusStr(status)); + r->_errno = __fsa_translate_error(status); + return -1; + } + + return 0; +} diff --git a/deps/libmocha/source/devoptab/devoptab_fsa_link.cpp b/deps/libmocha/source/devoptab/devoptab_fsa_link.cpp new file mode 100644 index 000000000000..ce1697d56526 --- /dev/null +++ b/deps/libmocha/source/devoptab/devoptab_fsa_link.cpp @@ -0,0 +1,8 @@ +#include "devoptab_fsa.h" + +int __fsa_link(struct _reent *r, + const char *existing, + const char *newLink) { + r->_errno = ENOSYS; + return -1; +} diff --git a/deps/libmocha/source/devoptab/devoptab_fsa_mkdir.cpp b/deps/libmocha/source/devoptab/devoptab_fsa_mkdir.cpp new file mode 100644 index 000000000000..467567d2cba4 --- /dev/null +++ b/deps/libmocha/source/devoptab/devoptab_fsa_mkdir.cpp @@ -0,0 +1,37 @@ +#include "devoptab_fsa.h" +#include "logger.h" +#include + +int __fsa_mkdir(struct _reent *r, + const char *path, + int mode) { + FSError status; + char *fixedPath; + + if (!path) { + r->_errno = EINVAL; + return -1; + } + + fixedPath = __fsa_fixpath(r, path); + if (!fixedPath) { + r->_errno = ENOMEM; + return -1; + } + + auto *deviceData = (FSADeviceData *) r->deviceData; + + FSMode translatedMode = __fsa_translate_permission_mode(mode); + + status = FSAMakeDir(deviceData->clientHandle, fixedPath, translatedMode); + if (status < 0) { + DEBUG_FUNCTION_LINE_ERR("FSAMakeDir(0x%08X, %s, 0x%X) failed: %s", + deviceData->clientHandle, fixedPath, translatedMode, FSAGetStatusStr(status)); + free(fixedPath); + r->_errno = __fsa_translate_error(status); + return -1; + } + free(fixedPath); + + return 0; +} diff --git a/deps/libmocha/source/devoptab/devoptab_fsa_open.cpp b/deps/libmocha/source/devoptab/devoptab_fsa_open.cpp new file mode 100644 index 000000000000..faa3a22fe9eb --- /dev/null +++ b/deps/libmocha/source/devoptab/devoptab_fsa_open.cpp @@ -0,0 +1,144 @@ +#include "devoptab_fsa.h" +#include "logger.h" +#include + +// Extended "magic" value that allows opening files with FS_OPEN_FLAG_UNENCRYPTED in underlying FSOpenFileEx() call similar to O_DIRECTORY +#ifndef O_UNENCRYPTED +#define O_UNENCRYPTED 0x4000000 +#endif + +int __fsa_open(struct _reent *r, + void *fileStruct, + const char *path, + int flags, + int mode) { + FSAFileHandle fd; + FSError status; + const char *fsMode; + + if (!fileStruct || !path) { + r->_errno = EINVAL; + return -1; + } + + bool createFileIfNotFound = false; + bool failIfFileNotFound = false; + // Map flags to open modes + int commonFlagMask = O_CREAT | O_TRUNC | O_APPEND; + if (((flags & O_ACCMODE) == O_RDONLY) && !(flags & commonFlagMask)) { + fsMode = "r"; + } else if (((flags & O_ACCMODE) == O_RDWR) && !(flags & commonFlagMask)) { + fsMode = "r+"; + } else if (((flags & O_ACCMODE) == O_WRONLY) && ((flags & commonFlagMask) == (O_CREAT | O_TRUNC))) { + fsMode = "w"; + } else if (((flags & O_ACCMODE) == O_RDWR) && ((flags & commonFlagMask) == (O_CREAT | O_TRUNC))) { + fsMode = "w+"; + } else if (((flags & O_ACCMODE) == O_WRONLY) && ((flags & commonFlagMask) == (O_CREAT | O_APPEND))) { + fsMode = "a"; + } else if (((flags & O_ACCMODE) == O_RDWR) && ((flags & commonFlagMask) == (O_CREAT | O_APPEND))) { + fsMode = "a+"; + } else if (((flags & O_ACCMODE) == O_WRONLY) && ((flags & commonFlagMask) == (O_CREAT))) { + // Cafe OS doesn't have a matching mode for this, so we have to be creative and create the file. + createFileIfNotFound = true; + // It's not possible to open a file with write only mode which doesn't truncate the file + // Technically we could read from the file, but our read implementation is blocking this. + fsMode = "r+"; + } else if (((flags & O_ACCMODE) == O_WRONLY) && ((flags & commonFlagMask) == (O_APPEND))) { + // Cafe OS doesn't have a matching mode for this, so we have to check if the file exists. + failIfFileNotFound = true; + fsMode = "a"; + } else if (((flags & O_ACCMODE) == O_WRONLY) && ((flags & commonFlagMask) == (O_TRUNC))) { + // As above + failIfFileNotFound = true; + fsMode = "w"; + } else { + r->_errno = EINVAL; + return -1; + } + + char *fixedPath = __fsa_fixpath(r, path); + if (!fixedPath) { + r->_errno = ENOMEM; + return -1; + } + + auto *file = (__fsa_file_t *) fileStruct; + strncpy(file->fullPath, fixedPath, sizeof(file->fullPath) - 1); + free(fixedPath); + + // Prepare flags + FSOpenFileFlags openFlags = (flags & O_UNENCRYPTED) ? FS_OPEN_FLAG_UNENCRYPTED : FS_OPEN_FLAG_NONE; + FSMode translatedMode = __fsa_translate_permission_mode(mode); + uint32_t preAllocSize = 0; + + // Init mutex and lock + file->mutex.init(file->fullPath); + std::lock_guard lock(file->mutex); + + auto *deviceData = (FSADeviceData *) r->deviceData; + + if (createFileIfNotFound || failIfFileNotFound || (flags & (O_EXCL | O_CREAT)) == (O_EXCL | O_CREAT)) { + // Check if file exists + FSAStat stat; + status = FSAGetStat(deviceData->clientHandle, file->fullPath, &stat); + if (status == FS_ERROR_NOT_FOUND) { + if (createFileIfNotFound) { // Create new file if needed + status = FSAOpenFileEx(deviceData->clientHandle, file->fullPath, "w", translatedMode, + openFlags, preAllocSize, &fd); + if (status == FS_ERROR_OK) { + if (FSACloseFile(deviceData->clientHandle, fd) != FS_ERROR_OK) { + DEBUG_FUNCTION_LINE_ERR("FSACloseFile(0x%08X, 0x%08X) (%s) failed: %s", + deviceData->clientHandle, fd, file->fullPath, FSAGetStatusStr(status)); + } + fd = -1; + } else { + DEBUG_FUNCTION_LINE_ERR("FSAOpenFileEx(0x%08X, %s, %s, 0x%X, 0x%08X, 0x%08X, 0x%08X) failed: %s", + deviceData->clientHandle, file->fullPath, "w", translatedMode, openFlags, preAllocSize, &fd, + FSAGetStatusStr(status)); + r->_errno = __fsa_translate_error(status); + return -1; + } + } else if (failIfFileNotFound) { // Return an error if we don't we create new files + r->_errno = __fsa_translate_error(status); + return -1; + } + } else if (status == FS_ERROR_OK) { + // If O_CREAT and O_EXCL are set, open() shall fail if the file exists. + if ((flags & (O_EXCL | O_CREAT)) == (O_EXCL | O_CREAT)) { + r->_errno = EEXIST; + return -1; + } + } + } + + status = FSAOpenFileEx(deviceData->clientHandle, file->fullPath, fsMode, translatedMode, openFlags, preAllocSize, &fd); + if (status < 0) { + DEBUG_FUNCTION_LINE_ERR("FSAOpenFileEx(0x%08X, %s, %s, 0x%X, 0x%08X, 0x%08X, 0x%08X) failed: %s", + deviceData->clientHandle, file->fullPath, fsMode, translatedMode, openFlags, preAllocSize, &fd, + FSAGetStatusStr(status)); + r->_errno = __fsa_translate_error(status); + return -1; + } + + file->fd = fd; + file->flags = (flags & (O_ACCMODE | O_APPEND | O_SYNC)); + // Is always 0, even if O_APPEND is set. + file->offset = 0; + + if (flags & O_APPEND) { + FSAStat stat; + status = FSAGetStatFile(deviceData->clientHandle, fd, &stat); + if (status < 0) { + DEBUG_FUNCTION_LINE_ERR("FSAGetStatFile(0x%08X, 0x%08X, 0x%08X) (%s) failed: %s", + deviceData->clientHandle, fd, &stat, file->fullPath, FSAGetStatusStr(status)); + r->_errno = __fsa_translate_error(status); + if (FSACloseFile(deviceData->clientHandle, fd) < 0) { + DEBUG_FUNCTION_LINE_ERR("FSACloseFile(0x%08X, 0x%08X) (%d) failed: %s", + deviceData->clientHandle, fd, file->fullPath, FSAGetStatusStr(status)); + } + return -1; + } + file->appendOffset = stat.size; + } + return 0; +} \ No newline at end of file diff --git a/deps/libmocha/source/devoptab/devoptab_fsa_read.cpp b/deps/libmocha/source/devoptab/devoptab_fsa_read.cpp new file mode 100644 index 000000000000..00131ae47f4e --- /dev/null +++ b/deps/libmocha/source/devoptab/devoptab_fsa_read.cpp @@ -0,0 +1,79 @@ +#include "devoptab_fsa.h" +#include "logger.h" + +#include +#include + +ssize_t __fsa_read(struct _reent *r, void *fd, char *ptr, size_t len) { + FSError status; + if (!fd || !ptr) { + r->_errno = EINVAL; + return -1; + } + + // Check that the file was opened with read access + auto *file = (__fsa_file_t *) fd; + if ((file->flags & O_ACCMODE) == O_WRONLY) { + r->_errno = EBADF; + return -1; + } + + // cache-aligned, cache-line-sized + __attribute__((aligned(0x40))) uint8_t alignedBuffer[0x40]; + + auto *deviceData = (FSADeviceData *) r->deviceData; + + std::lock_guard lock(file->mutex); + + size_t bytesRead = 0; + while (bytesRead < len) { + // only use input buffer if cache-aligned and read size is a multiple of cache line size + // otherwise read into alignedBuffer + uint8_t *tmp = (uint8_t *) ptr; + size_t size = len - bytesRead; + + if ((uintptr_t) ptr & 0x3F) { + // read partial cache-line front-end + tmp = alignedBuffer; + size = MIN(size, 0x40 - ((uintptr_t) ptr & 0x3F)); + } else if (size < 0x40) { + // read partial cache-line back-end + tmp = alignedBuffer; + } else { + // read whole cache lines + size &= ~0x3F; + } + + // Limit each request to 1 MiB + if (size > 0x100000) { + size = 0x100000; + } + + status = FSAReadFile(deviceData->clientHandle, tmp, 1, size, file->fd, 0); + + if (status < 0) { + DEBUG_FUNCTION_LINE_ERR("FSAReadFile(0x%08X, 0x%08X, 1, 0x%08X, 0x%08X, 0) (%s) failed: %s", + deviceData->clientHandle, tmp, size, file->fd, file->fullPath, FSAGetStatusStr(status)); + if (bytesRead != 0) { + return bytesRead; // error after partial read + } + + r->_errno = __fsa_translate_error(status); + return -1; + } + + if (tmp == alignedBuffer) { + memcpy(ptr, alignedBuffer, status); + } + + file->offset += status; + bytesRead += status; + ptr += status; + + if ((size_t) status != size) { + return bytesRead; // partial read + } + } + + return bytesRead; +} \ No newline at end of file diff --git a/deps/libmocha/source/devoptab/devoptab_fsa_rename.cpp b/deps/libmocha/source/devoptab/devoptab_fsa_rename.cpp new file mode 100644 index 000000000000..b551f93b414f --- /dev/null +++ b/deps/libmocha/source/devoptab/devoptab_fsa_rename.cpp @@ -0,0 +1,44 @@ +#include "devoptab_fsa.h" +#include "logger.h" +#include + +int __fsa_rename(struct _reent *r, + const char *oldName, + const char *newName) { + FSError status; + char *fixedOldPath, *fixedNewPath; + + if (!oldName || !newName) { + r->_errno = EINVAL; + return -1; + } + + fixedOldPath = __fsa_fixpath(r, oldName); + if (!fixedOldPath) { + r->_errno = ENOMEM; + return -1; + } + + fixedNewPath = __fsa_fixpath(r, newName); + if (!fixedNewPath) { + free(fixedOldPath); + r->_errno = ENOMEM; + return -1; + } + + auto *deviceData = (FSADeviceData *) r->deviceData; + + status = FSARename(deviceData->clientHandle, fixedOldPath, fixedNewPath); + if (status < 0) { + DEBUG_FUNCTION_LINE_ERR("FSARename(0x%08X, %s, %s) failed: %s", + deviceData->clientHandle, fixedOldPath, fixedNewPath, FSAGetStatusStr(status)); + free(fixedOldPath); + free(fixedNewPath); + r->_errno = __fsa_translate_error(status); + return -1; + } + free(fixedOldPath); + free(fixedNewPath); + + return 0; +} diff --git a/deps/libmocha/source/devoptab/devoptab_fsa_rmdir.cpp b/deps/libmocha/source/devoptab/devoptab_fsa_rmdir.cpp new file mode 100644 index 000000000000..31aa59b2a311 --- /dev/null +++ b/deps/libmocha/source/devoptab/devoptab_fsa_rmdir.cpp @@ -0,0 +1,34 @@ +#include "devoptab_fsa.h" +#include "logger.h" +#include + +int __fsa_rmdir(struct _reent *r, + const char *name) { + FSError status; + + if (!name) { + r->_errno = EINVAL; + return -1; + } + + char *fixedPath = __fsa_fixpath(r, name); + if (!fixedPath) { + r->_errno = ENOMEM; + return -1; + } + + auto *deviceData = (FSADeviceData *) r->deviceData; + + status = FSARemove(deviceData->clientHandle, fixedPath); + if (status < 0) { + DEBUG_FUNCTION_LINE_ERR("FSARemove(0x%08X, %s) failed: %s", + deviceData->clientHandle, fixedPath, FSAGetStatusStr(status)); + free(fixedPath); + r->_errno = status == FS_ERROR_ALREADY_EXISTS ? ENOTEMPTY : __fsa_translate_error(status); + return -1; + } + + free(fixedPath); + + return 0; +} diff --git a/deps/libmocha/source/devoptab/devoptab_fsa_seek.cpp b/deps/libmocha/source/devoptab/devoptab_fsa_seek.cpp new file mode 100644 index 000000000000..74b2bb5df159 --- /dev/null +++ b/deps/libmocha/source/devoptab/devoptab_fsa_seek.cpp @@ -0,0 +1,77 @@ +#include "devoptab_fsa.h" +#include "logger.h" +#include + +off_t __fsa_seek(struct _reent *r, + void *fd, + off_t pos, + int whence) { + FSError status; + FSAStat fsStat; + uint64_t offset; + + if (!fd) { + r->_errno = EINVAL; + return -1; + } + + auto *file = (__fsa_file_t *) fd; + auto *deviceData = (FSADeviceData *) r->deviceData; + + std::lock_guard lock(file->mutex); + + // Find the offset to see from + switch (whence) { + case SEEK_SET: { // Set absolute position; start offset is 0 + offset = 0; + break; + } + case SEEK_CUR: { // Set position relative to the current position + offset = file->offset; + break; + } + case SEEK_END: { // Set position relative to the end of the file + status = FSAGetStatFile(deviceData->clientHandle, file->fd, &fsStat); + if (status < 0) { + DEBUG_FUNCTION_LINE_ERR("FSAGetStatFile(0x%08X, 0x%08X, 0x%08X) (%s) failed: %s", + deviceData->clientHandle, file->fd, &fsStat, file->fullPath, FSAGetStatusStr(status)); + r->_errno = __fsa_translate_error(status); + return -1; + } + offset = fsStat.size; + break; + } + default: { // An invalid option was provided + r->_errno = EINVAL; + return -1; + } + } + + if (pos < 0 && (off_t) offset < -pos) { + // Don't allow seek to before the beginning of the file + r->_errno = EINVAL; + return -1; + } else if (offset + pos > UINT32_MAX) { + // Check for overflow + r->_errno = EINVAL; + return -1; + } + + if ((uint32_t) (offset + pos) == file->offset) { + return file->offset; + } + + uint32_t old_pos = file->offset; + file->offset = offset + pos; + + status = FSASetPosFile(deviceData->clientHandle, file->fd, file->offset); + if (status < 0) { + DEBUG_FUNCTION_LINE_ERR("FSASetPosFile(0x%08X, 0x%08X, 0x%08X) (%s) failed: %s", + deviceData->clientHandle, file->fd, file->offset, file->fullPath, FSAGetStatusStr(status)); + file->offset = old_pos; + r->_errno = __fsa_translate_error(status); + return -1; + } + + return file->offset; +} diff --git a/deps/libmocha/source/devoptab/devoptab_fsa_stat.cpp b/deps/libmocha/source/devoptab/devoptab_fsa_stat.cpp new file mode 100644 index 000000000000..562b27aaff37 --- /dev/null +++ b/deps/libmocha/source/devoptab/devoptab_fsa_stat.cpp @@ -0,0 +1,36 @@ +#include "devoptab_fsa.h" +#include "logger.h" +#include + +int __fsa_stat(struct _reent *r, + const char *path, + struct stat *st) { + FSError status; + FSAStat fsStat; + + if (!path || !st) { + r->_errno = EINVAL; + return -1; + } + + char *fixedPath = __fsa_fixpath(r, path); + if (!fixedPath) { + r->_errno = ENOMEM; + return -1; + } + + auto *deviceData = (FSADeviceData *) r->deviceData; + + status = FSAGetStat(deviceData->clientHandle, fixedPath, &fsStat); + if (status < 0) { + DEBUG_FUNCTION_LINE_ERR("FSAGetStat(0x%08X, %s, 0x%08X) failed: %s", + deviceData->clientHandle, fixedPath, &fsStat, FSAGetStatusStr(status)); + free(fixedPath); + r->_errno = __fsa_translate_error(status); + return -1; + } + free(fixedPath); + + __fsa_translate_stat(&fsStat, st); + return 0; +} \ No newline at end of file diff --git a/deps/libmocha/source/devoptab/devoptab_fsa_statvfs.cpp b/deps/libmocha/source/devoptab/devoptab_fsa_statvfs.cpp new file mode 100644 index 000000000000..94574a242c48 --- /dev/null +++ b/deps/libmocha/source/devoptab/devoptab_fsa_statvfs.cpp @@ -0,0 +1,51 @@ +#include "devoptab_fsa.h" +#include "logger.h" +#include + +int __fsa_statvfs(struct _reent *r, + const char *path, + struct statvfs *buf) { + FSError status; + uint64_t freeSpace; + + memset(buf, 0, sizeof(struct statvfs)); + + char *fixedPath = __fsa_fixpath(r, path); + if (!fixedPath) { + r->_errno = ENOMEM; + return -1; + } + + auto *deviceData = (FSADeviceData *) r->deviceData; + + status = FSAGetFreeSpaceSize(deviceData->clientHandle, fixedPath, &freeSpace); + if (status < 0) { + DEBUG_FUNCTION_LINE_ERR("FSAGetFreeSpaceSize(0x%08X, %s, 0x%08X) failed: %s", + deviceData->clientHandle, fixedPath, &freeSpace, FSAGetStatusStr(status)); + free(fixedPath); + r->_errno = __fsa_translate_error(status); + return -1; + } + free(fixedPath); + + // File system block size + buf->f_bsize = deviceData->deviceSectorSize; + // Fundamental file system block size + buf->f_frsize = deviceData->deviceSectorSize; + // Total number of blocks on file system in units of f_frsize + buf->f_blocks = deviceData->deviceSizeInSectors; + // Free blocks available for all and for non-privileged processes + buf->f_bfree = buf->f_bavail = (uint32_t) (freeSpace / buf->f_frsize); + // Number of inodes at this point in time + buf->f_files = 0xFFFFFFFF; + // Free inodes available for all and for non-privileged processes + buf->f_ffree = 0xFFFFFFFF; + // File system id + buf->f_fsid = (unsigned long) deviceData->clientHandle; + // Bit mask of f_flag values. + buf->f_flag = 0; + // Maximum length of filenames + buf->f_namemax = 255; + + return 0; +} \ No newline at end of file diff --git a/deps/libmocha/source/devoptab/devoptab_fsa_truncate.cpp b/deps/libmocha/source/devoptab/devoptab_fsa_truncate.cpp new file mode 100644 index 000000000000..562ee720095c --- /dev/null +++ b/deps/libmocha/source/devoptab/devoptab_fsa_truncate.cpp @@ -0,0 +1,39 @@ +#include "devoptab_fsa.h" +#include "logger.h" +#include + +int __fsa_ftruncate(struct _reent *r, + void *fd, + off_t len) { + FSError status; + + // Make sure length is non-negative + if (!fd || len < 0) { + r->_errno = EINVAL; + return -1; + } + + auto *file = (__fsa_file_t *) fd; + auto *deviceData = (FSADeviceData *) r->deviceData; + + std::lock_guard lock(file->mutex); + + // Set the new file size + status = FSASetPosFile(deviceData->clientHandle, file->fd, len); + if (status < 0) { + DEBUG_FUNCTION_LINE_ERR("FSASetPosFile(0x%08X, 0x%08X, 0x%08X) failed: %s", + deviceData->clientHandle, file->fd, len, FSAGetStatusStr(status)); + r->_errno = __fsa_translate_error(status); + return -1; + } + + status = FSATruncateFile(deviceData->clientHandle, file->fd); + if (status < 0) { + DEBUG_FUNCTION_LINE_ERR("FSATruncateFile(0x%08X, 0x%08X) failed: %s", + deviceData->clientHandle, file->fd, FSAGetStatusStr(status)); + r->_errno = __fsa_translate_error(status); + return -1; + } + + return 0; +} diff --git a/deps/libmocha/source/devoptab/devoptab_fsa_unlink.cpp b/deps/libmocha/source/devoptab/devoptab_fsa_unlink.cpp new file mode 100644 index 000000000000..e55ec684e78e --- /dev/null +++ b/deps/libmocha/source/devoptab/devoptab_fsa_unlink.cpp @@ -0,0 +1,34 @@ +#include "devoptab_fsa.h" +#include "logger.h" +#include + +int __fsa_unlink(struct _reent *r, + const char *name) { + FSError status; + char *fixedPath; + + if (!name) { + r->_errno = EINVAL; + return -1; + } + + fixedPath = __fsa_fixpath(r, name); + if (!fixedPath) { + r->_errno = ENOMEM; + return -1; + } + auto *deviceData = (FSADeviceData *) r->deviceData; + + status = FSARemove(deviceData->clientHandle, fixedPath); + if (status < 0) { + DEBUG_FUNCTION_LINE_ERR("FSARemove(0x%08X, %s) failed: %s", + deviceData->clientHandle, fixedPath, FSAGetStatusStr(status)); + free(fixedPath); + r->_errno = __fsa_translate_error(status); + return -1; + } + + free(fixedPath); + + return 0; +} diff --git a/deps/libmocha/source/devoptab/devoptab_fsa_utils.cpp b/deps/libmocha/source/devoptab/devoptab_fsa_utils.cpp new file mode 100644 index 000000000000..0ed5fd6f096d --- /dev/null +++ b/deps/libmocha/source/devoptab/devoptab_fsa_utils.cpp @@ -0,0 +1,194 @@ +#include "devoptab_fsa.h" + +char * +__fsa_fixpath(struct _reent *r, + const char *path) { + char *p; + char *fixedPath; + + if (!path) { + r->_errno = EINVAL; + return nullptr; + } + + p = strchr(path, ':') + 1; + if (!strchr(path, ':')) { + p = (char *) path; + } + + size_t pathLength = strlen(p); + if (pathLength > FS_MAX_PATH) { + r->_errno = ENAMETOOLONG; + return nullptr; + } + + // wii u softlocks on empty strings so give expected error back + if (pathLength == 0) { + r->_errno = ENOENT; + return nullptr; + } + + fixedPath = static_cast(memalign(0x40, FS_MAX_PATH + 1)); + if (!fixedPath) { + r->_errno = ENOMEM; + return nullptr; + } + + if (p[0] == '/') { + auto *deviceData = (FSADeviceData *) r->deviceData; + strcpy(fixedPath, deviceData->mount_path); + strcat(fixedPath, p); + } else { + strcpy(fixedPath, p); + } + + return fixedPath; +} + +mode_t __fsa_translate_stat_mode(FSAStat *fileStat) { + mode_t retMode = 0; + + if ((fileStat->flags & FS_STAT_LINK) == FS_STAT_LINK) { + retMode |= S_IFLNK; + } else if ((fileStat->flags & FS_STAT_DIRECTORY) == FS_STAT_DIRECTORY) { + retMode |= S_IFDIR; + } else if ((fileStat->flags & FS_STAT_FILE) == FS_STAT_FILE) { + retMode |= S_IFREG; + } else if (fileStat->size == 0) { + // Mounted paths like /vol/external01 have no flags set. + // If no flag is set and the size is 0, it's a (root) dir + retMode |= S_IFDIR; + } else if (fileStat->size > 0) { + // Some regular Wii U files have no type info but will have a size + retMode |= S_IFREG; + } + + // Convert normal CafeOS hexadecimal permission bits into Unix octal permission bits + mode_t permissionMode = (((fileStat->mode >> 2) & S_IRWXU) | ((fileStat->mode >> 1) & S_IRWXG) | (fileStat->mode & S_IRWXO)); + + return retMode | permissionMode; +} + +void __fsa_translate_stat(FSAStat *fsStat, struct stat *posStat) { + memset(posStat, 0, sizeof(struct stat)); + posStat->st_dev = (dev_t) nullptr; + posStat->st_ino = fsStat->entryId; + posStat->st_mode = __fsa_translate_stat_mode(fsStat); + posStat->st_nlink = 1; + posStat->st_uid = fsStat->owner; + posStat->st_gid = fsStat->group; + posStat->st_rdev = posStat->st_dev; + posStat->st_size = fsStat->size; + posStat->st_atime = __fsa_translate_time(fsStat->modified); + posStat->st_ctime = __fsa_translate_time(fsStat->created); + posStat->st_mtime = __fsa_translate_time(fsStat->modified); + posStat->st_blksize = 512; + posStat->st_blocks = (posStat->st_size + posStat->st_blksize - 1) / posStat->st_size; +} + +// The Wii U FSTime epoch is at 1980, so we must map it to 1970 for gettime +#define WIIU_FSTIME_EPOCH_YEAR (1980) + +#define EPOCH_YEAR (1970) +#define EPOCH_YEARS_SINCE_LEAP 2 +#define EPOCH_YEARS_SINCE_CENTURY 70 +#define EPOCH_YEARS_SINCE_LEAP_CENTURY 370 + +#define EPOCH_DIFF_YEARS(year) (year - EPOCH_YEAR) +#define EPOCH_DIFF_DAYS(year) \ + ((EPOCH_DIFF_YEARS(year) * 365) + \ + (EPOCH_DIFF_YEARS(year) - 1 + EPOCH_YEARS_SINCE_LEAP) / 4 - \ + (EPOCH_DIFF_YEARS(year) - 1 + EPOCH_YEARS_SINCE_CENTURY) / 100 + \ + (EPOCH_DIFF_YEARS(year) - 1 + EPOCH_YEARS_SINCE_LEAP_CENTURY) / 400) +#define EPOCH_DIFF_SECS(year) (60ull * 60ull * 24ull * (uint64_t) EPOCH_DIFF_DAYS(year)) + +time_t __fsa_translate_time(FSTime timeValue) { + return (timeValue / 1000000) + EPOCH_DIFF_SECS(WIIU_FSTIME_EPOCH_YEAR); +} + +FSMode __fsa_translate_permission_mode(mode_t mode) { + // Convert normal Unix octal permission bits into CafeOS hexadecimal permission bits + return (FSMode) (((mode & S_IRWXU) << 2) | ((mode & S_IRWXG) << 1) | (mode & S_IRWXO)); +} + +int __fsa_translate_error(FSError error) { + switch (error) { + case FS_ERROR_END_OF_DIR: + case FS_ERROR_END_OF_FILE: + return ENOENT; + case FS_ERROR_ALREADY_EXISTS: + return EEXIST; + case FS_ERROR_MEDIA_ERROR: + return EIO; + case FS_ERROR_NOT_FOUND: + return ENOENT; + case FS_ERROR_PERMISSION_ERROR: + return EPERM; + case FS_ERROR_STORAGE_FULL: + return ENOSPC; + case FS_ERROR_BUSY: + return EBUSY; + case FS_ERROR_CANCELLED: + return ECANCELED; + case FS_ERROR_FILE_TOO_BIG: + return EFBIG; + case FS_ERROR_INVALID_PATH: + return ENAMETOOLONG; + case FS_ERROR_NOT_DIR: + return ENOTDIR; + case FS_ERROR_NOT_FILE: + return EISDIR; + case FS_ERROR_OUT_OF_RANGE: + return ESPIPE; + case FS_ERROR_UNSUPPORTED_COMMAND: + return ENOTSUP; + case FS_ERROR_WRITE_PROTECTED: + return EROFS; + case FS_ERROR_NOT_INIT: + return ENODEV; + // TODO + case FS_ERROR_MAX_MOUNT_POINTS: + break; + case FS_ERROR_MAX_VOLUMES: + break; + case FS_ERROR_MAX_CLIENTS: + break; + case FS_ERROR_MAX_FILES: + break; + case FS_ERROR_MAX_DIRS: + break; + case FS_ERROR_ALREADY_OPEN: + break; + case FS_ERROR_NOT_EMPTY: + break; + case FS_ERROR_ACCESS_ERROR: + break; + case FS_ERROR_DATA_CORRUPTED: + break; + case FS_ERROR_JOURNAL_FULL: + break; + case FS_ERROR_UNAVAILABLE_COMMAND: + break; + case FS_ERROR_INVALID_PARAM: + break; + case FS_ERROR_INVALID_BUFFER: + break; + case FS_ERROR_INVALID_ALIGNMENT: + break; + case FS_ERROR_INVALID_CLIENTHANDLE: + break; + case FS_ERROR_INVALID_FILEHANDLE: + break; + case FS_ERROR_INVALID_DIRHANDLE: + break; + case FS_ERROR_OUT_OF_RESOURCES: + break; + case FS_ERROR_MEDIA_NOT_READY: + break; + case FS_ERROR_INVALID_MEDIA: + break; + default: + break; + } + return (int) EIO; +} diff --git a/deps/libmocha/source/devoptab/devoptab_fsa_utimes.cpp b/deps/libmocha/source/devoptab/devoptab_fsa_utimes.cpp new file mode 100644 index 000000000000..7cfc7dbf7cf9 --- /dev/null +++ b/deps/libmocha/source/devoptab/devoptab_fsa_utimes.cpp @@ -0,0 +1,8 @@ +#include "devoptab_fsa.h" + +int __fsa_utimes(struct _reent *r, + const char *filename, + const struct timeval times[2]) { + r->_errno = ENOSYS; + return -1; +} diff --git a/deps/libmocha/source/devoptab/devoptab_fsa_write.cpp b/deps/libmocha/source/devoptab/devoptab_fsa_write.cpp new file mode 100644 index 000000000000..1fc10166c6dc --- /dev/null +++ b/deps/libmocha/source/devoptab/devoptab_fsa_write.cpp @@ -0,0 +1,84 @@ +#include "devoptab_fsa.h" +#include "logger.h" +#include + +ssize_t __fsa_write(struct _reent *r, void *fd, const char *ptr, size_t len) { + FSError status; + + if (!fd || !ptr) { + r->_errno = EINVAL; + return -1; + } + + // Check that the file was opened with write access + auto *file = (__fsa_file_t *) fd; + if ((file->flags & O_ACCMODE) == O_RDONLY) { + r->_errno = EBADF; + return -1; + } + + // cache-aligned, cache-line-sized + __attribute__((aligned(0x40))) uint8_t alignedBuffer[0x40]; + + auto *deviceData = (FSADeviceData *) r->deviceData; + + std::lock_guard lock(file->mutex); + + // If O_APPEND is set, we always write to the end of the file. + // When writing we file->offset to the file size to keep in sync. + if (file->flags & O_APPEND) { + file->offset = file->appendOffset; + } + + size_t bytesWritten = 0; + while (bytesWritten < len) { + // only use input buffer if cache-aligned and write size is a multiple of cache line size + // otherwise write from alignedBuffer + uint8_t *tmp = (uint8_t *) ptr; + size_t size = len - bytesWritten; + + if ((uintptr_t) ptr & 0x3F) { + // write partial cache-line front-end + tmp = alignedBuffer; + size = MIN(size, 0x40 - ((uintptr_t) ptr & 0x3F)); + } else if (size < 0x40) { + // write partial cache-line back-end + tmp = alignedBuffer; + } else { + // write whole cache lines + size &= ~0x3F; + } + + // Limit each request to 256 KiB + if (size > 0x40000) { + size = 0x40000; + } + + if (tmp == alignedBuffer) { + memcpy(tmp, ptr, size); + } + + status = FSAWriteFile(deviceData->clientHandle, tmp, 1, size, file->fd, 0); + if (status < 0) { + DEBUG_FUNCTION_LINE_ERR("FSAWriteFile(0x%08X, 0x%08X, 1, 0x%08X, 0x%08X, 0) (%s) failed: %s", + deviceData->clientHandle, tmp, size, file->fd, file->fullPath, FSAGetStatusStr(status)); + if (bytesWritten != 0) { + return bytesWritten; // error after partial write + } + + r->_errno = __fsa_translate_error(status); + return -1; + } + + file->appendOffset += status; + file->offset += status; + bytesWritten += status; + ptr += status; + + if ((size_t) status != size) { + return bytesWritten; // partial write + } + } + + return bytesWritten; +} diff --git a/deps/libmocha/source/devoptab/logger.h b/deps/libmocha/source/devoptab/logger.h new file mode 100644 index 000000000000..62bf352edf8f --- /dev/null +++ b/deps/libmocha/source/devoptab/logger.h @@ -0,0 +1 @@ +#include "../logger.h" diff --git a/deps/libmocha/source/disc_interface.c b/deps/libmocha/source/disc_interface.c new file mode 100644 index 000000000000..28853391bc04 --- /dev/null +++ b/deps/libmocha/source/disc_interface.c @@ -0,0 +1,236 @@ +/*************************************************************************** + * Copyright (C) 2016 + * by Dimok + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any + * damages arising from the use of this software. + * + * Permission is granted to anyone to use this software for any + * purpose, including commercial applications, and to alter it and + * redistribute it freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you + * must not claim that you wrote the original software. If you use + * this software in a product, an acknowledgment in the product + * documentation would be appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and + * must not be misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + ***************************************************************************/ +#include "mocha/disc_interface.h" +#include "mocha/fsa.h" +#include "mocha/mocha.h" +#include +#include + +#define FSA_REF_SD 0x01 +#define FSA_REF_USB 0x02 + +static int initialized = 0; + +static int fsaFdSd = 0; +static int fsaFdUsb = 0; +static int sdioFd = 0; +static int usbFd = 0; + +static void Mocha_disc_io_initialize(void) { + if (initialized == 0) { + initialized = 1; + fsaFdSd = -1; + fsaFdUsb = -1; + sdioFd = -1; + usbFd = -1; + } +} + +static bool Mocha_disc_io_fsa_open(int fsaFd) { + Mocha_disc_io_initialize(); + + if (fsaFd == FSA_REF_SD) { + if (fsaFdSd < 0) { + fsaFdSd = IOS_Open("/dev/fsa", IOS_OPEN_READWRITE); + if (fsaFdSd >= 0 && Mocha_UnlockFSClientEx(fsaFdSd) != MOCHA_RESULT_SUCCESS) { + IOS_Close(fsaFdSd); + fsaFdSd = -1; + } + } + + if (fsaFdSd >= 0) { + return true; + } + } else if (fsaFd == FSA_REF_USB) { + if (fsaFdUsb < 0) { + fsaFdUsb = IOS_Open("/dev/fsa", IOS_OPEN_READWRITE); + if (fsaFdUsb >= 0 && Mocha_UnlockFSClientEx(fsaFdUsb) != MOCHA_RESULT_SUCCESS) { + IOS_Close(fsaFdUsb); + fsaFdUsb = -1; + } + } + if (fsaFdUsb >= 0) { + return true; + } + } + + return false; +} + +static void Mocha_disc_io_fsa_close(int fsaFd) { + if (fsaFd == FSA_REF_SD) { + if (fsaFdSd >= 0) { + IOS_Close(fsaFdSd); + fsaFdSd = -1; + } + } else if (fsaFd == FSA_REF_USB) { + if (fsaFdUsb >= 0) { + IOS_Close(fsaFdUsb); + fsaFdUsb = -1; + } + } +} + +static bool Mocha_sdio_startup(void) { + if (!Mocha_disc_io_fsa_open(FSA_REF_SD)) + return false; + + if (sdioFd < 0) { + int res = FSAEx_RawOpenEx(fsaFdSd, "/dev/sdcard01", &sdioFd); + if (res < 0) { + Mocha_disc_io_fsa_close(FSA_REF_SD); + sdioFd = -1; + } + } + + return (sdioFd >= 0); +} + +static bool Mocha_sdio_isInserted(void) { + //! TODO: check for SD card inserted with Mocha_FSA_GetDeviceInfo() + return initialized && (fsaFdSd >= 0) && (sdioFd >= 0); +} + +static bool Mocha_sdio_clearStatus(void) { + return true; +} + +static bool Mocha_sdio_shutdown(void) { + if (!Mocha_sdio_isInserted()) + return false; + + FSAEx_RawCloseEx(fsaFdSd, sdioFd); + Mocha_disc_io_fsa_close(FSA_REF_SD); + sdioFd = -1; + return true; +} + +static bool Mocha_sdio_readSectors(uint32_t sector, uint32_t numSectors, void *buffer) { + if (!Mocha_sdio_isInserted()) { + return false; + } + + int res = FSAEx_RawReadEx(fsaFdSd, buffer, 512, numSectors, sector, sdioFd); + if (res < 0) { + return false; + } + + return true; +} + +static bool Mocha_sdio_writeSectors(uint32_t sector, uint32_t numSectors, const void *buffer) { + if (!Mocha_sdio_isInserted()) { + return false; + } + + int res = FSAEx_RawWriteEx(fsaFdSd, buffer, 512, numSectors, sector, sdioFd); + if (res < 0) { + return false; + } + + return true; +} + +const DISC_INTERFACE Mocha_sdio_disc_interface = { + DEVICE_TYPE_WII_U_SD, + FEATURE_MEDIUM_CANREAD | FEATURE_MEDIUM_CANWRITE | FEATURE_WII_U_SD, + Mocha_sdio_startup, + Mocha_sdio_isInserted, + Mocha_sdio_readSectors, + Mocha_sdio_writeSectors, + Mocha_sdio_clearStatus, + Mocha_sdio_shutdown}; + +static bool Mocha_usb_startup(void) { + if (!Mocha_disc_io_fsa_open(FSA_REF_USB)) { + return false; + } + + if (usbFd < 0) { + int res = FSAEx_RawOpenEx(fsaFdUsb, "/dev/usb01", &usbFd); + if (res < 0) { + res = FSAEx_RawOpenEx(fsaFdUsb, "/dev/usb02", &usbFd); + if (res < 0) { + Mocha_disc_io_fsa_close(FSA_REF_USB); + usbFd = -1; + } + } + } + return (usbFd >= 0); +} + +static bool Mocha_usb_isInserted(void) { + return initialized && (fsaFdUsb >= 0) && (usbFd >= 0); +} + +static bool Mocha_usb_clearStatus(void) { + return true; +} + +static bool Mocha_usb_shutdown(void) { + if (!Mocha_usb_isInserted()) { + return false; + } + + FSAEx_RawCloseEx(fsaFdUsb, usbFd); + Mocha_disc_io_fsa_close(FSA_REF_USB); + usbFd = -1; + return true; +} + +static bool Mocha_usb_readSectors(uint32_t sector, uint32_t numSectors, void *buffer) { + if (!Mocha_usb_isInserted()) { + return false; + } + + int res = FSAEx_RawReadEx(fsaFdUsb, buffer, 512, numSectors, sector, usbFd); + if (res < 0) { + return false; + } + + return true; +} + +static bool Mocha_usb_writeSectors(uint32_t sector, uint32_t numSectors, const void *buffer) { + if (!Mocha_usb_isInserted()) { + return false; + } + + int res = FSAEx_RawWriteEx(fsaFdUsb, buffer, 512, numSectors, sector, usbFd); + if (res < 0) { + return false; + } + + return true; +} + +const DISC_INTERFACE Mocha_usb_disc_interface = { + DEVICE_TYPE_WII_U_USB, + FEATURE_MEDIUM_CANREAD | FEATURE_MEDIUM_CANWRITE | FEATURE_WII_U_USB, + Mocha_usb_startup, + Mocha_usb_isInserted, + Mocha_usb_readSectors, + Mocha_usb_writeSectors, + Mocha_usb_clearStatus, + Mocha_usb_shutdown}; diff --git a/deps/libmocha/source/fsa.cpp b/deps/libmocha/source/fsa.cpp new file mode 100644 index 000000000000..ff84e30f1968 --- /dev/null +++ b/deps/libmocha/source/fsa.cpp @@ -0,0 +1,193 @@ +#include "mocha/fsa.h" +#include "logger.h" +#include "utils.h" +#include +#include +#include +#include +#include + +FSError FSAEx_RawOpen(FSClient *client, const char *device_path, int32_t *outHandle) { + if (!client) { + return FS_ERROR_INVALID_CLIENTHANDLE; + } + return FSAEx_RawOpenEx(FSGetClientBody(client)->clientHandle, device_path, outHandle); +} + +FSError FSAEx_RawOpenEx(int clientHandle, const char *device_path, int32_t *outHandle) { + if (!outHandle) { + return FS_ERROR_INVALID_BUFFER; + } + if (!device_path) { + return FS_ERROR_INVALID_PATH; + } + auto *shim = (FSAShimBuffer *) memalign(0x40, sizeof(FSAShimBuffer)); + if (!shim) { + return FS_ERROR_INVALID_BUFFER; + } + + shim->clientHandle = clientHandle; + shim->command = FSA_COMMAND_RAW_OPEN; + shim->ipcReqType = FSA_IPC_REQUEST_IOCTL; + shim->response.word0 = 0xFFFFFFFF; + + FSARequestRawOpen *requestBuffer = &shim->request.rawOpen; + + strncpy(requestBuffer->path, device_path, 0x27F); + + auto res = __FSAShimSend(shim, 0); + if (res >= 0) { + *outHandle = shim->response.rawOpen.handle; + } + free(shim); + return res; +} + +FSError FSAEx_RawClose(FSClient *client, int32_t device_handle) { + if (!client) { + return FS_ERROR_INVALID_CLIENTHANDLE; + } + return FSAEx_RawCloseEx(FSGetClientBody(client)->clientHandle, device_handle); +} + +FSError FSAEx_RawCloseEx(int clientHandle, int32_t device_handle) { + auto *buffer = (FSAShimBuffer *) memalign(0x40, sizeof(FSAShimBuffer)); + if (!buffer) { + return FS_ERROR_INVALID_BUFFER; + } + + buffer->clientHandle = clientHandle; + buffer->command = FSA_COMMAND_RAW_CLOSE; + buffer->ipcReqType = FSA_IPC_REQUEST_IOCTL; + buffer->response.word0 = 0xFFFFFFFF; + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Waddress-of-packed-member" + auto *requestBuffer = &buffer->request.rawClose; +#pragma GCC diagnostic pop + + requestBuffer->handle = device_handle; + + auto res = __FSAShimSend(buffer, 0); + free(buffer); + return res; +} + +FSError FSAEx_RawRead(FSClient *client, void *data, uint32_t size_bytes, uint32_t cnt, uint64_t blocks_offset, int device_handle) { + if (!client) { + return FS_ERROR_INVALID_CLIENTHANDLE; + } + return FSAEx_RawReadEx(FSGetClientBody(client)->clientHandle, data, size_bytes, cnt, blocks_offset, device_handle); +} + +FSError FSAEx_RawReadEx(int clientHandle, void *data, uint32_t size_bytes, uint32_t cnt, uint64_t blocks_offset, int device_handle) { + if (data == nullptr) { + return FS_ERROR_INVALID_BUFFER; + } + auto *shim = (FSAShimBuffer *) memalign(0x40, sizeof(FSAShimBuffer)); + if (!shim) { + return FS_ERROR_INVALID_BUFFER; + } + + shim->clientHandle = clientHandle; + shim->ipcReqType = FSA_IPC_REQUEST_IOCTLV; + shim->command = FSA_COMMAND_RAW_READ; + + shim->ioctlvVecIn = uint8_t{1}; + shim->ioctlvVecOut = uint8_t{2}; + + shim->ioctlvVec[0].vaddr = &shim->request; + shim->ioctlvVec[0].len = sizeof(FSARequest); + + auto *tmp = data; + + if ((uint32_t) data & 0x3F) { + auto *alignedBuffer = memalign(0x40, ROUNDUP(size_bytes * cnt, 0x40)); + if (!alignedBuffer) { + DEBUG_FUNCTION_LINE_ERR("Buffer not aligned (%08X).\n", data); + return FS_ERROR_INVALID_ALIGNMENT; + } + DEBUG_FUNCTION_LINE_WARN("Buffer not aligned (%08X). Align to 0x40 for best performance\n", data); + tmp = alignedBuffer; + } + + shim->ioctlvVec[1].vaddr = (void *) tmp; + shim->ioctlvVec[1].len = size_bytes * cnt; + + shim->ioctlvVec[2].vaddr = &shim->response; + shim->ioctlvVec[2].len = sizeof(FSAResponse); + + auto &request = shim->request.rawRead; + request.blocks_offset = blocks_offset; + request.count = cnt; + request.size = size_bytes; + request.device_handle = device_handle; + + auto res = __FSAShimSend(shim, 0); + if (res >= 0 && tmp != data) { + memcpy(data, tmp, size_bytes * cnt); + } + if (tmp != data) { + free(tmp); + } + + free(shim); + return res; +} + +FSError FSAEx_RawWrite(FSClient *client, const void *data, uint32_t size_bytes, uint32_t cnt, uint64_t blocks_offset, int device_handle) { + if (!client) { + return FS_ERROR_INVALID_CLIENTHANDLE; + } + return FSAEx_RawWriteEx(FSGetClientBody(client)->clientHandle, data, size_bytes, cnt, blocks_offset, device_handle); +} + +FSError FSAEx_RawWriteEx(int clientHandle, const void *data, uint32_t size_bytes, uint32_t cnt, uint64_t blocks_offset, int device_handle) { + auto *shim = (FSAShimBuffer *) memalign(0x40, sizeof(FSAShimBuffer)); + if (!shim) { + return FS_ERROR_INVALID_BUFFER; + } + + shim->clientHandle = clientHandle; + shim->ipcReqType = FSA_IPC_REQUEST_IOCTLV; + shim->command = FSA_COMMAND_RAW_WRITE; + + shim->ioctlvVecIn = uint8_t{2}; + shim->ioctlvVecOut = uint8_t{1}; + + shim->ioctlvVec[0].vaddr = &shim->request; + shim->ioctlvVec[0].len = sizeof(FSARequest); + + void *tmp = (void *) data; + if ((uint32_t) data & 0x3F) { + auto *alignedBuffer = memalign(0x40, ROUNDUP(size_bytes * cnt, 0x40)); + if (!alignedBuffer) { + DEBUG_FUNCTION_LINE_ERR("Buffer not aligned (%08X).", data); + return FS_ERROR_INVALID_ALIGNMENT; + } + DEBUG_FUNCTION_LINE_WARN("Buffer not aligned (%08X). Align to 0x40 for best performance", data); + tmp = alignedBuffer; + memcpy(tmp, data, size_bytes * cnt); + } + + shim->ioctlvVec[1].vaddr = tmp; + shim->ioctlvVec[1].len = size_bytes * cnt; + + shim->ioctlvVec[2].vaddr = &shim->response; + shim->ioctlvVec[2].len = sizeof(FSAResponse); + + auto &request = shim->request.rawWrite; + request.blocks_offset = blocks_offset; + request.count = cnt; + request.size = size_bytes; + request.device_handle = device_handle; + + auto res = __FSAShimSend(shim, 0); + + if (tmp != data) { + free(tmp); + } + + free(shim); + return res; +} \ No newline at end of file diff --git a/deps/libmocha/source/logger.h b/deps/libmocha/source/logger.h new file mode 100644 index 000000000000..ffa747ef40d0 --- /dev/null +++ b/deps/libmocha/source/logger.h @@ -0,0 +1,23 @@ +#pragma once +#include +#include + +#define __FILENAME__ ({ \ + const char *__filename = __FILE__; \ + const char *__pos = strrchr(__filename, '/'); \ + if (!__pos) __pos = strrchr(__filename, '\\'); \ + __pos ? __pos + 1 : __filename; \ +}) + +#define LOG_APP_TYPE "L" +#define LOG_APP_NAME "libmocha" + +#define LOG_EX(FILENAME, FUNCTION, LINE, LOG_FUNC, LOG_LEVEL, LINE_END, FMT, ARGS...) \ + do { \ + LOG_FUNC("[(%s)%18s][%23s]%30s@L%04d: " LOG_LEVEL "" FMT "" LINE_END, LOG_APP_TYPE, LOG_APP_NAME, FILENAME, FUNCTION, LINE, ##ARGS); \ + } while (0) + +#define LOG_EX_DEFAULT(LOG_FUNC, LOG_LEVEL, LINE_END, FMT, ARGS...) LOG_EX(__FILENAME__, __FUNCTION__, __LINE__, LOG_FUNC, LOG_LEVEL, LINE_END, FMT, ##ARGS) + +#define DEBUG_FUNCTION_LINE_ERR(FMT, ARGS...) LOG_EX_DEFAULT(OSReport, "##ERROR## ", "\n", FMT, ##ARGS) +#define DEBUG_FUNCTION_LINE_WARN(FMT, ARGS...) LOG_EX_DEFAULT(OSReport, "##WARNING## ", "\n", FMT, ##ARGS) diff --git a/deps/libmocha/source/utils.cpp b/deps/libmocha/source/utils.cpp new file mode 100644 index 000000000000..a9cbf3de2a59 --- /dev/null +++ b/deps/libmocha/source/utils.cpp @@ -0,0 +1,509 @@ +#include "utils.h" +#include "logger.h" +#include "mocha/commands.h" +#include "mocha/mocha.h" +#include "mocha/otp.h" +#include +#include +#include +#include +#include +#include + +int iosuhaxHandle = -1; +int mochaInitDone = 0; +uint32_t mochaApiVersion = 0; + +#define IOCTL_MEM_WRITE 0x00 +#define IOCTL_MEM_READ 0x01 +#define IOCTL_SVC 0x02 +#define IOCTL_MEMCPY 0x04 +#define IOCTL_REPEATED_WRITE 0x05 +#define IOCTL_KERN_READ32 0x06 +#define IOCTL_KERN_WRITE32 0x07 +#define IOCTL_READ_OTP 0x08 + +const char *Mocha_GetStatusStr(MochaUtilsStatus status) { + switch (status) { + case MOCHA_RESULT_SUCCESS: + return "MOCHA_RESULT_SUCCESS"; + case MOCHA_RESULT_INVALID_ARGUMENT: + return "MOCHA_RESULT_INVALID_ARGUMENT"; + case MOCHA_RESULT_MAX_CLIENT: + return "MOCHA_RESULT_MAX_CLIENT"; + case MOCHA_RESULT_OUT_OF_MEMORY: + return "MOCHA_RESULT_OUT_OF_MEMORY"; + case MOCHA_RESULT_ALREADY_EXISTS: + return "MOCHA_RESULT_ALREADY_EXISTS"; + case MOCHA_RESULT_ADD_DEVOPTAB_FAILED: + return "MOCHA_RESULT_ADD_DEVOPTAB_FAILED"; + case MOCHA_RESULT_NOT_FOUND: + return "MOCHA_RESULT_NOT_FOUND"; + case MOCHA_RESULT_UNSUPPORTED_API_VERSION: + return "MOCHA_RESULT_UNSUPPORTED_API_VERSION"; + case MOCHA_RESULT_UNSUPPORTED_COMMAND: + return "MOCHA_RESULT_UNSUPPORTED_COMMAND"; + case MOCHA_RESULT_UNSUPPORTED_CFW: + return "MOCHA_RESULT_UNSUPPORTED_CFW"; + case MOCHA_RESULT_LIB_UNINITIALIZED: + return "MOCHA_RESULT_LIB_UNINITIALIZED"; + case MOCHA_RESULT_UNKNOWN_ERROR: + return "MOCHA_RESULT_UNKNOWN_ERROR"; + } + return "MOCHA_RESULT_UNKNOWN_ERROR"; +} + + +MochaUtilsStatus Mocha_InitLibrary() { + if (mochaInitDone) { + return MOCHA_RESULT_SUCCESS; + } + + if (iosuhaxHandle < 0) { + int haxHandle = IOS_Open((char *) ("/dev/iosuhax"), static_cast(0)); + if (haxHandle < 0) { + DEBUG_FUNCTION_LINE_ERR("Failed to open /dev/iosuhax"); + return MOCHA_RESULT_UNSUPPORTED_COMMAND; + } + iosuhaxHandle = haxHandle; + } + + mochaInitDone = 1; + mochaApiVersion = 0; + uint32_t version = 0; + if (Mocha_CheckAPIVersion(&version) != MOCHA_RESULT_SUCCESS) { + IOS_Close(iosuhaxHandle); + iosuhaxHandle = -1; + return MOCHA_RESULT_UNSUPPORTED_COMMAND; + } + + mochaApiVersion = version; + + return MOCHA_RESULT_SUCCESS; +} + +MochaUtilsStatus Mocha_DeInitLibrary() { + mochaInitDone = 0; + mochaApiVersion = 0; + + if (iosuhaxHandle >= 0) { + IOS_Close(iosuhaxHandle); + iosuhaxHandle = -1; + } + + return MOCHA_RESULT_SUCCESS; +} + +MochaUtilsStatus Mocha_CheckAPIVersion(uint32_t *version) { + if (!version) { + return MOCHA_RESULT_INVALID_ARGUMENT; + } + MochaUtilsStatus res = MOCHA_RESULT_UNKNOWN_ERROR; + int mcpFd = IOS_Open("/dev/mcp", IOS_OPEN_READ); + if (mcpFd >= 0) { + ALIGN_0x40 uint32_t io_buffer[0x40 / 4]; + io_buffer[0] = IPC_CUSTOM_GET_MOCHA_API_VERSION; + + if (IOS_Ioctl(mcpFd, 100, io_buffer, 4, io_buffer, 8) == IOS_ERROR_OK) { + // IOCTL_100 hook is available + if (io_buffer[0] == 0xCAFEBABE) { + // Updated MochaPayload returns magic word + *version = io_buffer[1]; + res = MOCHA_RESULT_SUCCESS; + } else if (io_buffer[0] == 1) { + // Old MochaPayload returns success, but zero as magic word + res = MOCHA_RESULT_UNSUPPORTED_API_VERSION; + } else { + // No known implementations are known to trigger this + res = MOCHA_RESULT_UNSUPPORTED_CFW; + } + } else { + // If IOCTL_100 hook is not available the call returns -1 + // This is the case with old Mocha CFW or no CFW at all + res = MOCHA_RESULT_UNSUPPORTED_CFW; + } + + IOS_Close(mcpFd); + } else { + return res; + } + + return res; +} + +MochaUtilsStatus Mocha_IOSUKernelMemcpy(uint32_t dst, uint32_t src, uint32_t size) { + if (size == 0) { + return MOCHA_RESULT_SUCCESS; + } + if (dst == 0 || src == 0) { + return MOCHA_RESULT_INVALID_ARGUMENT; + } + if (!mochaInitDone || iosuhaxHandle < 0) { + return MOCHA_RESULT_LIB_UNINITIALIZED; + } + + ALIGN_0x40 uint32_t io_buf[0x40 >> 2]; + io_buf[0] = dst; + io_buf[1] = src; + io_buf[2] = size; + + int res = IOS_Ioctl(iosuhaxHandle, IOCTL_MEMCPY, io_buf, 3 * sizeof(uint32_t), nullptr, 0); + return res >= 0 ? MOCHA_RESULT_SUCCESS : MOCHA_RESULT_UNKNOWN_ERROR; +} + +MochaUtilsStatus Mocha_IOSUMemoryWrite(uint32_t address, const uint8_t *buffer, uint32_t size) { + if (size == 0) { + return MOCHA_RESULT_SUCCESS; + } + if (address == 0 || buffer == nullptr) { + return MOCHA_RESULT_INVALID_ARGUMENT; + } + if (!mochaInitDone || iosuhaxHandle < 0) { + return MOCHA_RESULT_LIB_UNINITIALIZED; + } + + auto *io_buf = (uint32_t *) memalign(0x40, ROUNDUP(size + 4, 0x40)); + if (!io_buf) { + return MOCHA_RESULT_OUT_OF_MEMORY; + } + + io_buf[0] = address; + memcpy(io_buf + 1, buffer, size); + + int res = IOS_Ioctl(iosuhaxHandle, IOCTL_MEM_WRITE, io_buf, size + 4, nullptr, 0); + + free(io_buf); + return res >= 0 ? MOCHA_RESULT_SUCCESS : MOCHA_RESULT_UNKNOWN_ERROR; +} + +MochaUtilsStatus Mocha_IOSUMemoryRead(uint32_t address, uint8_t *out_buffer, uint32_t size) { + if (size == 0) { + return MOCHA_RESULT_SUCCESS; + } + if (address == 0 || out_buffer == nullptr) { + return MOCHA_RESULT_INVALID_ARGUMENT; + } + if (!mochaInitDone || iosuhaxHandle < 0) { + return MOCHA_RESULT_LIB_UNINITIALIZED; + } + + ALIGN_0x40 uint32_t io_buf[0x40 >> 2]; + io_buf[0] = address; + + void *tmp_buf = nullptr; + + if (((uintptr_t) out_buffer & 0x3F) || (size & 0x3F)) { + tmp_buf = (uint32_t *) memalign(0x40, ROUNDUP(size, 0x40)); + if (!tmp_buf) { + return MOCHA_RESULT_OUT_OF_MEMORY; + } + } + + int res = IOS_Ioctl(iosuhaxHandle, IOCTL_MEM_READ, io_buf, sizeof(address), tmp_buf ? tmp_buf : out_buffer, size); + + if (res >= 0 && tmp_buf) { + memcpy(out_buffer, tmp_buf, size); + } + + free(tmp_buf); + return res >= 0 ? MOCHA_RESULT_SUCCESS : MOCHA_RESULT_UNKNOWN_ERROR; +} + +MochaUtilsStatus Mocha_IOSUKernelWrite32(uint32_t address, uint32_t value) { + if (address == 0) { + return MOCHA_RESULT_INVALID_ARGUMENT; + } + if (!mochaInitDone || iosuhaxHandle < 0) { + return MOCHA_RESULT_LIB_UNINITIALIZED; + } + + ALIGN_0x40 uint32_t io_buf[0x40 >> 2]; + io_buf[0] = address; + io_buf[1] = value; + + auto res = IOS_Ioctl(iosuhaxHandle, IOCTL_KERN_WRITE32, io_buf, 2 * sizeof(uint32_t), 0, 0); + return res >= 0 ? MOCHA_RESULT_SUCCESS : MOCHA_RESULT_UNKNOWN_ERROR; +} + +MochaUtilsStatus Mocha_IOSUKernelRead32(uint32_t address, uint32_t *out_buffer) { + if (address == 0 || out_buffer == nullptr) { + return MOCHA_RESULT_INVALID_ARGUMENT; + } + if (!mochaInitDone || iosuhaxHandle < 0) { + return MOCHA_RESULT_LIB_UNINITIALIZED; + } + + ALIGN_0x40 uint32_t io_buf[0x40 >> 2]; + io_buf[0] = address; + + void *tmp_buf = NULL; + int32_t count = 1; + + if (((uintptr_t) out_buffer & 0x3F) || ((count * 4) & 0x3F)) { + tmp_buf = (uint32_t *) memalign(0x40, ROUNDUP((count * 4), 0x40)); + if (!tmp_buf) { + return MOCHA_RESULT_OUT_OF_MEMORY; + } + } + + int res = IOS_Ioctl(iosuhaxHandle, IOCTL_KERN_READ32, io_buf, sizeof(address), tmp_buf ? tmp_buf : out_buffer, count * 4); + + if (res >= 0 && tmp_buf) { + memcpy(out_buffer, tmp_buf, count * 4); + } + + free(tmp_buf); + return res >= 0 ? MOCHA_RESULT_SUCCESS : MOCHA_RESULT_UNKNOWN_ERROR; +} + +MochaUtilsStatus Mocha_ReadOTP(WiiUConsoleOTP *out_buffer) { + if (out_buffer == nullptr) { + return MOCHA_RESULT_INVALID_ARGUMENT; + } + if (!mochaInitDone || iosuhaxHandle < 0) { + return MOCHA_RESULT_LIB_UNINITIALIZED; + } + + ALIGN_0x40 uint32_t io_buf[0x400 >> 2]; + + int res = IOS_Ioctl(iosuhaxHandle, IOCTL_READ_OTP, nullptr, 0, io_buf, 0x400); + + if (res < 0) { + return MOCHA_RESULT_UNKNOWN_ERROR; + } + memcpy(out_buffer, io_buf, 0x400); + + return MOCHA_RESULT_SUCCESS; +} + +int Mocha_IOSUCallSVC(uint32_t svc_id, uint32_t *args, uint32_t arg_cnt, int32_t *outResult) { + if (!mochaInitDone || iosuhaxHandle < 0) { + return MOCHA_RESULT_LIB_UNINITIALIZED; + } + + ALIGN_0x40 uint32_t arguments[0x40 >> 2]; + arguments[0] = svc_id; + + if (args && arg_cnt) { + if (arg_cnt > 8) { + arg_cnt = 8; + } + + memcpy(arguments + 1, args, arg_cnt * 4); + } + + ALIGN_0x40 int result[0x40 >> 2]; + int res = IOS_Ioctl(iosuhaxHandle, IOCTL_SVC, arguments, (1 + arg_cnt) * 4, result, 4); + + if (res >= 0 && outResult) { + *outResult = *result; + } + + return res >= 0 ? MOCHA_RESULT_SUCCESS : MOCHA_RESULT_UNKNOWN_ERROR; +} + +MochaUtilsStatus Mocha_GetEnvironmentPath(char *environmentPathBuffer, uint32_t bufferLen) { + if (!mochaInitDone) { + return MOCHA_RESULT_LIB_UNINITIALIZED; + } + if (mochaApiVersion < 1) { + return MOCHA_RESULT_UNSUPPORTED_COMMAND; + } + if (!environmentPathBuffer || bufferLen < 0x100) { + return MOCHA_RESULT_INVALID_ARGUMENT; + } + MochaUtilsStatus res = MOCHA_RESULT_UNKNOWN_ERROR; + int mcpFd = IOS_Open("/dev/mcp", (IOSOpenMode) 0); + if (mcpFd >= 0) { + ALIGN_0x40 uint32_t io_buffer[0x100 / 4]; + io_buffer[0] = IPC_CUSTOM_COPY_ENVIRONMENT_PATH; + + if (IOS_Ioctl(mcpFd, 100, io_buffer, 4, io_buffer, 0x100) == IOS_ERROR_OK) { + memcpy(environmentPathBuffer, reinterpret_cast(io_buffer), 0xFF); + environmentPathBuffer[bufferLen - 1] = 0; + res = MOCHA_RESULT_SUCCESS; + } + + IOS_Close(mcpFd); + } + + return res; +} + +MochaUtilsStatus Mocha_StartUSBLogging(bool notSkipExistingLogs) { + if (!mochaInitDone) { + return MOCHA_RESULT_LIB_UNINITIALIZED; + } + if (mochaApiVersion < 1) { + return MOCHA_RESULT_UNSUPPORTED_COMMAND; + } + MochaUtilsStatus res = MOCHA_RESULT_UNKNOWN_ERROR; + int mcpFd = IOS_Open("/dev/mcp", (IOSOpenMode) 0); + if (mcpFd >= 0) { + ALIGN_0x40 uint32_t io_buffer[0x40 / 4]; + io_buffer[0] = IPC_CUSTOM_START_USB_LOGGING; + io_buffer[1] = notSkipExistingLogs; + + if (IOS_Ioctl(mcpFd, 100, io_buffer, 8, io_buffer, 0x4) == IOS_ERROR_OK) { + res = MOCHA_RESULT_SUCCESS; + } + + IOS_Close(mcpFd); + } + + return res; +} + +MochaUtilsStatus Mocha_UnlockFSClient(FSClient *client) { + if (!client) { + return MOCHA_RESULT_INVALID_ARGUMENT; + } + + return Mocha_UnlockFSClientEx(FSGetClientBody(client)->clientHandle); +} + +MochaUtilsStatus Mocha_UnlockFSClientEx(int clientHandle) { + if (!mochaInitDone) { + return MOCHA_RESULT_LIB_UNINITIALIZED; + } + if (mochaApiVersion < 1) { + return MOCHA_RESULT_UNSUPPORTED_COMMAND; + } + ALIGN_0x40 int dummy[0x40 >> 2]; + + auto res = IOS_Ioctl(clientHandle, 0x28, dummy, sizeof(dummy), dummy, sizeof(dummy)); + if (res == 0) { + return MOCHA_RESULT_SUCCESS; + } + if (res == -5) { + return MOCHA_RESULT_MAX_CLIENT; + } + return MOCHA_RESULT_UNKNOWN_ERROR; +} + +MochaUtilsStatus Mocha_PrepareRPXLaunch(MochaRPXLoadInfo *loadInfo) { + if (!mochaInitDone) { + return MOCHA_RESULT_LIB_UNINITIALIZED; + } + if (mochaApiVersion < 1) { + return MOCHA_RESULT_UNSUPPORTED_COMMAND; + } + if (!loadInfo) { + return MOCHA_RESULT_INVALID_ARGUMENT; + } + MochaUtilsStatus res = MOCHA_RESULT_UNKNOWN_ERROR; + int mcpFd = IOS_Open("/dev/mcp", (IOSOpenMode) 0); + if (mcpFd >= 0) { + ALIGN_0x40 uint32_t io_buffer[ROUNDUP(sizeof(MochaRPXLoadInfo) + 4, 0x40)]; + io_buffer[0] = IPC_CUSTOM_LOAD_CUSTOM_RPX; + memcpy(&io_buffer[1], loadInfo, sizeof(MochaRPXLoadInfo)); + + if (IOS_Ioctl(mcpFd, 100, io_buffer, sizeof(MochaRPXLoadInfo) + 4, io_buffer, 0x4) == IOS_ERROR_OK) { + res = MOCHA_RESULT_SUCCESS; + } + IOS_Close(mcpFd); + } + + return res; +} + +MochaUtilsStatus Mocha_LaunchRPX(MochaRPXLoadInfo *loadInfo) { + auto res = Mocha_PrepareRPXLaunch(loadInfo); + if (res == MOCHA_RESULT_SUCCESS) { + res = Mocha_LaunchHomebrewWrapper(); + if (res != MOCHA_RESULT_SUCCESS) { + MochaRPXLoadInfo loadInfoRevert; + loadInfoRevert.target = LOAD_RPX_TARGET_EXTRA_REVERT_PREPARE; + Mocha_PrepareRPXLaunch(&loadInfoRevert); + } + } + return res; +} + +MochaUtilsStatus Mocha_LaunchHomebrewWrapperEx(SYSStandardArgsIn *args) { + if (!mochaInitDone) { + return MOCHA_RESULT_LIB_UNINITIALIZED; + } + if (mochaApiVersion < 1) { + return MOCHA_RESULT_UNSUPPORTED_COMMAND; + } + uint64_t titleID = _SYSGetSystemApplicationTitleId(SYSTEM_APP_ID_HEALTH_AND_SAFETY); + if (!SYSCheckTitleExists(titleID)) { // Fallback to daily log app if H&S doesn't exist. + titleID = _SYSGetSystemApplicationTitleId(SYSTEM_APP_ID_DAILY_LOG); + } + if (!SYSCheckTitleExists(titleID)) { + return MOCHA_RESULT_NOT_FOUND; + } + + _SYSLaunchTitleWithStdArgsInNoSplash(titleID, args); + + return MOCHA_RESULT_SUCCESS; +} + +MochaUtilsStatus Mocha_LaunchHomebrewWrapper() { + return Mocha_LaunchHomebrewWrapperEx(nullptr); +} + +MochaUtilsStatus Mocha_ODMGetDiscKey(WUDDiscKey *discKey) { + if (!mochaInitDone) { + return MOCHA_RESULT_LIB_UNINITIALIZED; + } + if (mochaApiVersion < 1) { + return MOCHA_RESULT_UNSUPPORTED_COMMAND; + } + if (!discKey) { + return MOCHA_RESULT_INVALID_ARGUMENT; + } + int odm_handle = IOS_Open("/dev/odm", IOS_OPEN_READ); + MochaUtilsStatus res = MOCHA_RESULT_UNKNOWN_ERROR; + if (odm_handle >= 0) { + ALIGN_0x40 uint32_t io_buffer[0x40 / 4]; + // disc encryption key, only works with patched IOSU + io_buffer[0] = 3; + IOSError ioctlResult = IOS_Ioctl(odm_handle, 0x06, io_buffer, 0x14, io_buffer, 0x20); + if (ioctlResult == IOS_ERROR_OK) { + memcpy(discKey, io_buffer, 16); + res = MOCHA_RESULT_SUCCESS; + } else if (ioctlResult == (IOSError) 0xFFF1EFFF) { + res = MOCHA_RESULT_NOT_FOUND; + } + IOS_Close(odm_handle); + } + return res; +} + +extern "C" int bspRead(const char *, uint32_t, const char *, uint32_t, uint16_t *); +MochaUtilsStatus Mocha_SEEPROMRead(uint8_t *out_buffer, uint32_t offset, uint32_t size) { + if (!mochaInitDone) { + return MOCHA_RESULT_LIB_UNINITIALIZED; + } + if (mochaApiVersion < 1) { + return MOCHA_RESULT_UNSUPPORTED_COMMAND; + } + if (out_buffer == nullptr || offset > 0x200 || offset & 0x01) { + return MOCHA_RESULT_INVALID_ARGUMENT; + } + + uint32_t sizeInShorts = size >> 1; + uint32_t offsetInShorts = offset >> 1; + int32_t maxReadCount = 0x100 - offsetInShorts; + + if (maxReadCount <= 0) { + return MOCHA_RESULT_SUCCESS; + } + + uint32_t count = sizeInShorts > (uint32_t) maxReadCount ? (uint32_t) maxReadCount : sizeInShorts; + auto *ptr = (uint16_t *) out_buffer; + + int res = 0; + + for (uint32_t i = 0; i < count; i++) { + if (bspRead("EE", offsetInShorts + i, "access", 2, ptr) != 0) { + return MOCHA_RESULT_UNKNOWN_ERROR; + } + res += 2; + ptr++; + } + + return static_cast(res); +} diff --git a/deps/libmocha/source/utils.h b/deps/libmocha/source/utils.h new file mode 100644 index 000000000000..c8c2a1988384 --- /dev/null +++ b/deps/libmocha/source/utils.h @@ -0,0 +1,12 @@ +#pragma once +#include +#include +#include + +#define ALIGN(align) __attribute__((aligned(align))) +#define ALIGN_0x40 ALIGN(0x40) +#define ROUNDUP(x, align) (((x) + ((align) -1)) & ~((align) -1)) + +#define __FSAShimSetupRequestMount ((FSError(*)(FSAShimBuffer *, uint32_t, const char *, const char *, uint32_t, void *, uint32_t))(0x101C400 + 0x042f88)) +#define __FSAShimSetupRequestUnmount ((FSError(*)(FSAShimBuffer *, uint32_t, const char *, uint32_t))(0x101C400 + 0x43130)) +#define __FSAShimSend ((FSError(*)(FSAShimBuffer *, uint32_t))(0x101C400 + 0x042d90)) diff --git a/dist-scripts/wiiu-cores.sh b/dist-scripts/wiiu-cores.sh index be2d06ee0789..84152165826c 100755 --- a/dist-scripts/wiiu-cores.sh +++ b/dist-scripts/wiiu-cores.sh @@ -1,141 +1,60 @@ #!/bin/sh # usage: -# copy core libs (*_libretro_wiiu.a), info files (https://github.com/libretro/libretro-super/tree/master/dist/info) -# and icons (https://github.com/libretro/retroarch-assets/tree/master/pkg/wiiu) to this directory then run -# the script. the output will be in retroarch/pkg/wiiu +# copy core libs (*_libretro_wiiu.a) and assets (https://buildbot.libretro.com/assets/frontend/assets.zip) to this +# directory then run the script. the output will be in retroarch/pkg/wiiu . ../version.all platform=wiiu EXT=a -mkdir -p ../pkg/wiiu/retroarch/cores/info -cp *.info ../pkg/wiiu/retroarch/cores/info/ -mkdir -p ../pkg/wiiu/rpx/retroarch/cores/info -cp *.info ../pkg/wiiu/rpx/retroarch/cores/info/ +retroarch_dir=../pkg/wiiu/retroarch +apps_dir=../pkg/wiiu/wiiu/apps +mkdir -p $retroarch_dir/cores $apps_dir +echo "-- Building launcher (Salamander) --" make -C ../ -f Makefile.${platform} SALAMANDER_BUILD=1 clean || exit 1 -make -C ../ -f Makefile.${platform} SALAMANDER_BUILD=1 BUILD_HBL_ELF=1 BUILD_RPX=1 -j3 || exit 1 +make -C ../ -f Makefile.${platform} SALAMANDER_BUILD=1 -j$(nproc) || exit 1 -mkdir -p ../pkg/wiiu/wiiu/apps/retroarch -mv -f ../retroarch_wiiu_salamander.elf ../pkg/wiiu/wiiu/apps/retroarch/retroarch.elf -cp -f ../pkg/wiiu/meta.xml ../pkg/wiiu/wiiu/apps/retroarch/meta.xml -cp -f ../pkg/wiiu/icon.png ../pkg/wiiu/wiiu/apps/retroarch/icon.png -mkdir -p ../pkg/wiiu/rpx/wiiu/apps/retroarch -mv -f ../retroarch_wiiu_salamander.rpx ../pkg/wiiu/rpx/wiiu/apps/retroarch/retroarch.rpx -rm -f ../retroarch_wiiu_salamander.rpx.elf -cp -f ../pkg/wiiu/meta.xml ../pkg/wiiu/rpx/wiiu/apps/retroarch/meta.xml -cp -f ../pkg/wiiu/icon.png ../pkg/wiiu/rpx/wiiu/apps/retroarch/icon.png +if [ -e assets.zip ]; then + # This is named "build" because we're building the assets, but it's also got a broad rule in the gitignore + mkdir -p build/assets + unzip -o assets.zip -d build/assets -make -C ../ -f Makefile.${platform} clean || exit 1 + wuhbtool ../retroarch_wiiu_salamander.rpx $apps_dir/retroarch.wuhb \ + --name="RetroArch" \ + --short-name="RetroArch" \ + --author="libretro" \ + --icon=../pkg/wiiu/booticon.png \ + --tv-image=../pkg/wiiu/bootTvTex.tga \ + --drc-image=../pkg/wiiu/bootDrcTex.tga \ + --content=build/ || exit 1 -lookup() -{ - cat | grep "$1 = " | sed "s/$1 = \"//" | sed s/\"// -} + rm -rf build +fi -gen_meta_xml() -{ - info="$1"_libretro.info - if [ -e $info ] ; then - display_name=`cat $info | lookup "display_name"` - corename=`cat $info | lookup "corename"` - authors=`cat $info | lookup "authors" | sed s/\|/\ -\ /g` - systemname=`cat $info | lookup "systemname"` - license=`cat $info | lookup "license"` - date=`date +%Y%m%d%H%M%S` - build_hash=`git rev-parse --short HEAD 2>/dev/null` - echo '' > "$1"_meta.xml - echo '' >> "$1"_meta.xml - echo ' '$corename'' >> "$1"_meta.xml - echo ' '$authors'' >> "$1"_meta.xml - echo ' '$PACKAGE_VERSION' r'$build_hash'' >> "$1"_meta.xml - echo ' '$date'' >> "$1"_meta.xml - echo ' RetroArch' >> "$1"_meta.xml - echo -e ' '$display_name'\n\nSystem: '$systemname'\nLicense: '$license'' >> "$1"_meta.xml - echo ' emu' >> "$1"_meta.xml - echo ' https://github.com/libretro' >> "$1"_meta.xml - echo '' >> "$1"_meta.xml - fi -} +make -C ../ -f Makefile.${platform} clean || exit 1 for f in `ls -v *_${platform}.${EXT}`; do name=`echo "$f" | sed "s/\(_libretro_${platform}\|\).${EXT}$//"` whole_archive= - build_hbl_elf=1 - build_rpx=1 if [ $name = "nxengine" ] ; then echo "Applying whole archive linking..." whole_archive="WHOLE_ARCHIVE_LINK=1" fi - if [ $name = "mame2003" ] ; then - build_hbl_elf=0 - fi - - if [ $name = "fbalpha2012" ] ; then - build_hbl_elf=0 - fi - - if [ $name = "mame2003_midway" ] ; then - build_rpx=0 - fi - if [ $name = "fbalpha2012_cps1" ] ; then - build_rpx=0 - fi - if [ $name = "fbalpha2012_cps2" ] ; then - build_rpx=0 - fi - if [ $name = "fbalpha2012_cps3" ] ; then - build_rpx=0 - fi - if [ $name = "fbalpha2012_neogeo" ] ; then - build_rpx=0 - fi - echo "-- Building core: $name --" cp -f "$f" ../libretro_${platform}.${EXT} echo NAME: $name # Compile core - make -C ../ -f Makefile.${platform} LIBRETRO=$name BUILD_HBL_ELF=$build_hbl_elf BUILD_RPX=$build_rpx $whole_archive -j3 || exit 1 - gen_meta_xml $name + make -C ../ -f Makefile.${platform} LIBRETRO=$name $whole_archive -j$(nproc) || exit 1 - if [ -e ../retroarch_wiiu.elf ] ; then - cp ../retroarch_wiiu.elf ../pkg/wiiu/retroarch/cores/${name}_libretro.elf - mkdir -p ../pkg/wiiu/wiiu/apps/${name}_libretro - mv -f ../retroarch_wiiu.elf ../pkg/wiiu/wiiu/apps/${name}_libretro/${name}_libretro.elf - if [ -e ${name}_meta.xml ] ; then - cp -f ${name}_meta.xml ../pkg/wiiu/wiiu/apps/${name}_libretro/meta.xml - else - cp -f ../pkg/wiiu/meta.xml ../pkg/wiiu/wiiu/apps/${name}_libretro/meta.xml - fi - if [ -e $name.png ] ; then - cp -f $name.png ../pkg/wiiu/wiiu/apps/${name}_libretro/icon.png - else - cp -f ../pkg/wiiu/icon.png ../pkg/wiiu/wiiu/apps/${name}_libretro/icon.png - fi - fi if [ -e ../retroarch_wiiu.rpx ] ; then - cp ../retroarch_wiiu.rpx ../pkg/wiiu/rpx/retroarch/cores/${name}_libretro.rpx - mkdir -p ../pkg/wiiu/rpx/wiiu/apps/${name}_libretro - mv -f ../retroarch_wiiu.rpx ../pkg/wiiu/rpx/wiiu/apps/${name}_libretro/${name}_libretro.rpx - rm -f ../retroarch_wiiu.rpx.elf - if [ -e ${name}_meta.xml ] ; then - cp -f ${name}_meta.xml ../pkg/wiiu/rpx/wiiu/apps/${name}_libretro/meta.xml - else - cp -f ../pkg/wiiu/meta.xml ../pkg/wiiu/rpx/wiiu/apps/${name}_libretro/meta.xml - fi - if [ -e $name.png ] ; then - cp -f $name.png ../pkg/wiiu/rpx/wiiu/apps/${name}_libretro/icon.png - else - cp -f ../pkg/wiiu/icon.png ../pkg/wiiu/rpx/wiiu/apps/${name}_libretro/icon.png - fi + cp ../retroarch_wiiu.rpx $retroarch_dir/cores/${name}_libretro.rpx fi - rm -rf ${name}_meta.xml - done # Additional build step diff --git a/dist-scripts/wiiu-new-cores.sh b/dist-scripts/wiiu-new-cores.sh deleted file mode 100755 index e02231e2b66a..000000000000 --- a/dist-scripts/wiiu-new-cores.sh +++ /dev/null @@ -1,194 +0,0 @@ -#!/bin/bash - -. ../version.all -platform=wiiu -EXT=a -scriptDir= -pngDir= -infoDir= - -original_pwd=$(pwd) - -setScriptDir() -{ - scriptDir=$(dirname $(readlink -f $1)) -} - -setInfoDir() -{ - if [ -d ../../dist/info ]; then - infoDir=$(readlink -f ../../dist/info) - elif [ $(ls -1 *.info |wc -l) > 0 ]; then - infoDir=$(pwd) - fi - - if [ -z "$infoDir" ]; then - echo "WARNING: Could not find your *.info files. meta.xml files will not be generated." - fi -} - -setPngDir() -{ - pwd - if [ -d ../media/assets/pkg/wiiu ]; then - pngDir=$(readlink -f ../media/assets/pkg/wiiu) - elif [ $(ls -1 *.png |wc -l) > 0 ]; then - pngDir=$(pwd) - fi - - if [ -z "$pngDir" ]; then - echo "WARNING: Could not find your *.png files. icon.png files will not be generated." - fi -} - -getCores() -{ - if [ -d ../../dist/wiiu ]; then - ls -1 ../../dist/wiiu/*.a - elif [ $(ls -1 *.a |wc -l) > 0 ]; then - ls -1 *.a - fi -} - -clean() -{ - local here=$(pwd) - - cd $scriptDir/.. - make -f Makefile.wiiu clean || exit 1 - - for trash in libretro_wiiu.a libretro_wiiu.elf libretro_wiiu.rpx \ - objs/wiiu pkg/wiiu/wiiu pkg/wiiu/retroarch pkg/wiiu/rpx - do - rm -rf $trash - done - - cd $here -} - -# $1 = core filename (e.g. ../../dist/wiiu/somecore_libretro_wiiu.a -# $2 = desired package type, e.g. rpx or elf -coreNameToPackageName() -{ - local packageName=$(basename $1 |awk -F'\.a' '{print $1}' |sed 's/_wiiu//') - echo "$packageName" -} - -lookup() -{ - cat | grep "$1 = " | sed "s/$1 = \"//" | sed s/\"// -} - -generateMetaXml() -{ - local infoFile=$1 - local xmlDir=$2 - local outFile=$xmlDir/meta.xml - - if [ ! -e $infoFile ]; then - return 1 - fi - - local display_name=$(cat $infoFile |lookup "display_name") - local corename=$(cat $infoFile |lookup "corename") - local authors=$(cat $infoFile |lookup "authors" |sed s/\|/\ -\ /g) - local systemname=$(cat $infoFile |lookup "systemname") - local license=$(cat $infoFile |lookup "license") - local build_date=$(date +%Y%m%d%H%M%S) - local build_hash=$(git rev-parse --short HEAD 2>/dev/null) - - mkdir -p $xmlDir - echo '' > $outFile - echo '' >> $outFile - echo ' '$corename'' >> $outFile - echo ' '$authors'' >> $outFile - echo ' '$RARCH_VERSION' r'$build_hash'' >> $outFile - echo ' '$build_date'' >> $outFile - echo ' RetroArch' >> $outFile - echo -e ' '$display_name'\n\nSystem: '$systemname'\nLicense: '$license'' >> $outFile - echo ' emu' >> $outFile - echo ' https://github.com/libretro' >> $outFile - echo '' >> $outFile -} - -copyPng() -{ - local pngFilename=$(echo $1 |sed 's/_libretro//').png - local destFilename=$2/icon.png - - if [ -e $pngDir/$pngFilename ]; then - cp $pngDir/$pngFilename $destFilename - fi -} - -buildCore() -{ - local core=$1 - local distDir=$(pwd) - local buildDir=$(dirname $(pwd)) - local packageName=$(coreNameToPackageName $core) - local rpxResult=$packageName.rpx - local elfResult=$packageName.elf - - cd $buildDir - - if [ -f Makefile.wiiu ]; then - echo "--- building core: $packageName ---" - rm -f libretro_wiiu.a - cp $distDir/$core libretro_wiiu.a - make -f Makefile.wiiu \ - PC_DEVELOPMENT_TCP_PORT=$PC_DEVELOPMENT_TCP_PORT \ - -j3 || exit 1 - - if [ ! -z "$infoDir" ]; then - for i in 'pkg/wiiu/retroarch/cores' 'pkg/wiiu/rpx/retroarch/cores'; do - mkdir -p $i/info - cp $infoDir/$packageName.info $i/info - generateMetaXml $i/info/$packageName.info $i/../../wiiu/apps/$packageName - done - fi - - if [ ! -z "$pngDir" ]; then - for i in 'pkg/wiiu/wiiu/apps' 'pkg/wiiu/rpx/wiiu/apps'; do - copyPng $packageName $i/$packageName - done - fi - - for i in "pkg/wiiu/wiiu/apps/$packageName" 'pkg/wiiu/retroarch/cores'; do - mkdir -p $i - cp retroarch_wiiu.elf $i/$elfResult - done - for i in "pkg/wiiu/rpx/wiiu/apps/$packageName" 'pkg/wiiu/rpx/retroarch/cores'; do - mkdir -p $i - cp retroarch_wiiu.rpx $i/$rpxResult - done - else - echo "ERROR: Something went wrong. Makefile.wiiu not found." - exit 1 - fi - - cd $distDir -} - -setScriptDir $0 - -clean - -cd $scriptDir -if [ -e ../wiiu-devel.properties ]; then - . ../wiiu-devel.properties -fi - -setInfoDir -setPngDir - -cores=$(getCores) - -if [ -z "$cores" ]; then - echo "ERROR: No cores found. Nothing to do." - exit 1 -fi - -for core in $cores; do - buildCore $core -done diff --git a/dist-scripts/wiiu-rpx-upload.sh b/dist-scripts/wiiu-rpx-upload.sh index d27821ddf100..89c3029d220e 100755 --- a/dist-scripts/wiiu-rpx-upload.sh +++ b/dist-scripts/wiiu-rpx-upload.sh @@ -37,10 +37,10 @@ fi filesToUpload() { - find . -type f \( -name "*.rpx" -o -name "*.xml" -o -name "*.png" -o -name "*.info" \) + find . -type f \( -name "*.rpx" -o -name "*.wuhb" -o -name "*.info" \) } -cd ../pkg/wiiu/rpx +cd ../pkg/wiiu # First, delete any previous *.remote files from previous uploads. find . -name '*.remote' | xargs rm -f {} diff --git a/frontend/drivers/platform_wiiu.c b/frontend/drivers/platform_wiiu.c index c87607cd0b9a..4ee2ef9ff575 100644 --- a/frontend/drivers/platform_wiiu.c +++ b/frontend/drivers/platform_wiiu.c @@ -22,8 +22,6 @@ #include #include -#include -#include #include #ifndef IS_SALAMANDER @@ -32,14 +30,24 @@ #include -#include -#include -#include -#include -#include -#include - - +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "../configuration.h" #include "../frontend.h" #include "../frontend_driver.h" #include "../../file_path_special.h" @@ -59,13 +67,22 @@ #endif #endif -#include "hbl.h" +// We always have a minimal version of libmocha for Salamander + core loading, so no #ifdef here +#include +#ifdef HAVE_LIBFAT +#include +#include +#endif + #include "wiiu_dbg.h" #include "system/exception_handler.h" +#include "system/memory.h" -#define WIIU_SD_PATH "sd:/" -#define WIIU_USB_PATH "usb:/" -#define WIIU_STORAGE_USB_PATH "storage_usb:/" +#define WIIU_SD_PATH "fs:/vol/external01/" +#define WIIU_VOL_CONTENT_PATH "fs:/vol/content/" +#define WIIU_SD_FAT_PATH "sd:/" +#define WIIU_USB_FAT_PATH "usb:/" +#define WIIU_USB_WFS_PATH "storage_usb:/" /** * The Wii U frontend driver, along with the main() method. @@ -73,8 +90,11 @@ #ifndef IS_SALAMANDER static enum frontend_fork wiiu_fork_mode = FRONTEND_FORK_NONE; +static bool have_libfat_usb = false; +static bool have_libfat_sdcard = false; +static bool have_wfs_usb = false; #endif -static const char *elf_path_cst = WIIU_SD_PATH "retroarch/retroarch.elf"; +static bool in_exec = false; static bool exists(char *path) { @@ -100,16 +120,36 @@ static void fix_asset_directory(void) rename(src_path_buf, dst_path_buf); } +static bool vol_content_assets_exist(void) +{ + char path_buf[PATH_MAX_LENGTH] = {0}; + + fill_pathname_join(path_buf, WIIU_VOL_CONTENT_PATH, "assets", sizeof(path_buf)); + + return exists(path_buf); +} + static void frontend_wiiu_get_env_settings(int *argc, char *argv[], void *args, void *params_data) { - fill_pathname_basedir(g_defaults.dirs[DEFAULT_DIR_PORT], elf_path_cst, sizeof(g_defaults.dirs[DEFAULT_DIR_PORT])); +#ifndef IS_SALAMANDER + if (have_libfat_sdcard) + strncpy(g_defaults.dirs[DEFAULT_DIR_PORT], WIIU_SD_FAT_PATH "retroarch/", sizeof(g_defaults.dirs[DEFAULT_DIR_PORT])); + else +#endif + strncpy(g_defaults.dirs[DEFAULT_DIR_PORT], WIIU_SD_PATH "retroarch/", sizeof(g_defaults.dirs[DEFAULT_DIR_PORT])); fill_pathname_join(g_defaults.dirs[DEFAULT_DIR_CORE_ASSETS], g_defaults.dirs[DEFAULT_DIR_PORT], "downloads", sizeof(g_defaults.dirs[DEFAULT_DIR_CORE_ASSETS])); + fix_asset_directory(); - fill_pathname_join(g_defaults.dirs[DEFAULT_DIR_ASSETS], g_defaults.dirs[DEFAULT_DIR_PORT], - "assets", sizeof(g_defaults.dirs[DEFAULT_DIR_ASSETS])); + if (vol_content_assets_exist()) + fill_pathname_join(g_defaults.dirs[DEFAULT_DIR_ASSETS], WIIU_VOL_CONTENT_PATH, + "assets", sizeof(g_defaults.dirs[DEFAULT_DIR_ASSETS])); + else + fill_pathname_join(g_defaults.dirs[DEFAULT_DIR_ASSETS], g_defaults.dirs[DEFAULT_DIR_PORT], + "assets", sizeof(g_defaults.dirs[DEFAULT_DIR_ASSETS])); + fill_pathname_join(g_defaults.dirs[DEFAULT_DIR_CORE], g_defaults.dirs[DEFAULT_DIR_PORT], "cores", sizeof(g_defaults.dirs[DEFAULT_DIR_CORE])); fill_pathname_join(g_defaults.dirs[DEFAULT_DIR_CORE_INFO], g_defaults.dirs[DEFAULT_DIR_CORE], @@ -166,7 +206,10 @@ static void frontend_wiiu_init(void *data) DEBUG_LINE(); } -static int frontend_wiiu_get_rating(void) { return 10; } +static int frontend_wiiu_get_rating(void) +{ + return 10; +} enum frontend_architecture frontend_wiiu_get_arch(void) { @@ -184,99 +227,145 @@ static int frontend_wiiu_parse_drive_list(void *data, bool load_content) if (!list) return -1; - menu_entries_append(list, WIIU_SD_PATH, - msg_hash_to_str(MENU_ENUM_LABEL_FILE_DETECT_CORE_LIST_PUSH_DIR), - enum_idx, - FILE_TYPE_DIRECTORY, 0, 0, NULL); - - menu_entries_append(list, WIIU_USB_PATH, - msg_hash_to_str(MENU_ENUM_LABEL_FILE_DETECT_CORE_LIST_PUSH_DIR), - enum_idx, - FILE_TYPE_DIRECTORY, 0, 0, NULL); - menu_entries_append(list, WIIU_STORAGE_USB_PATH, - msg_hash_to_str(MENU_ENUM_LABEL_FILE_DETECT_CORE_LIST_PUSH_DIR), - enum_idx, - FILE_TYPE_DIRECTORY, 0, 0, NULL); + + if (have_libfat_sdcard) + menu_entries_append(list, WIIU_SD_FAT_PATH, + msg_hash_to_str(MENU_ENUM_LABEL_FILE_DETECT_CORE_LIST_PUSH_DIR), + enum_idx, + FILE_TYPE_DIRECTORY, 0, 0, NULL); + else + menu_entries_append(list, WIIU_SD_PATH, + msg_hash_to_str(MENU_ENUM_LABEL_FILE_DETECT_CORE_LIST_PUSH_DIR), + enum_idx, + FILE_TYPE_DIRECTORY, 0, 0, NULL); + + if (have_libfat_usb) + menu_entries_append(list, WIIU_USB_FAT_PATH, + msg_hash_to_str(MENU_ENUM_LABEL_FILE_DETECT_CORE_LIST_PUSH_DIR), + enum_idx, + FILE_TYPE_DIRECTORY, 0, 0, NULL); + + if (have_wfs_usb) + menu_entries_append(list, WIIU_USB_WFS_PATH, + msg_hash_to_str(MENU_ENUM_LABEL_FILE_DETECT_CORE_LIST_PUSH_DIR), + enum_idx, + FILE_TYPE_DIRECTORY, 0, 0, NULL); + #endif return 0; } static void frontend_wiiu_exec(const char *path, bool should_load_content) { - struct - { - u32 magic; - u32 argc; + /* goal: make one big buffer with all the argv's, seperated by NUL. we can + * then pass this thru sysapp! */ + char *argv_buf; + size_t n, argv_len = strlen(path) + 1; /* argv[0] plus null */ + #ifndef IS_SALAMANDER + const char *content = path_get(RARCH_PATH_CONTENT); + const char *content_args[2] = {content, NULL}; #ifdef HAVE_NETWORKING - char *argv[NETPLAY_FORK_MAX_ARGS + 1]; -#else - char *argv[3]; + const char *netplay_args[NETPLAY_FORK_MAX_ARGS]; #endif -#else - char *argv[2]; #endif - char args[]; - } *param = getApplicationEndAddr(); - char *arg = param->args; - - DEBUG_STR(path); + /* args will select between content_args, netplay_args, or no args (default) */ + const char **args = NULL; - param->argc = 1; - param->argv[0] = arg; - arg += strlcpy(arg, elf_path_cst, PATH_MAX_LENGTH); - arg += 1; - - param->argv[1] = NULL; + /* and some other stuff (C89) */ + MochaRPXLoadInfo load_info = {0}; + MochaUtilsStatus ret; + SYSStandardArgsIn std_args = {0}; #ifndef IS_SALAMANDER if (should_load_content) { - const char *content = path_get(RARCH_PATH_CONTENT); #ifdef HAVE_NETWORKING - char *arg_data[NETPLAY_FORK_MAX_ARGS]; - - if (netplay_driver_ctl(RARCH_NETPLAY_CTL_GET_FORK_ARGS, (void*)arg_data)) + if (netplay_driver_ctl(RARCH_NETPLAY_CTL_GET_FORK_ARGS, + (void *) netplay_args)) { - char **cur_arg = arg_data; + const char **cur_arg = netplay_args; do - { - param->argv[param->argc++] = arg; - arg += strlcpy(arg, *cur_arg, PATH_MAX_LENGTH); - arg += 1; - } + argv_len += strnlen(*cur_arg, PATH_MAX_LENGTH) + 1; while (*(++cur_arg)); - param->argv[param->argc] = NULL; - } - else + args = netplay_args; + } else #endif if (!string_is_empty(content)) { - param->argc = 2; - param->argv[1] = arg; - arg += strlcpy(arg, content, PATH_MAX_LENGTH); - arg += 1; - - param->argv[2] = NULL; + argv_len += strnlen(content, PATH_MAX_LENGTH) + 1; + args = content_args; } } #endif - if (HBL_loadToMemory(path, (u32)arg - (u32)param) < 0) + argv_buf = malloc(argv_len); + argv_buf[0] = '\0'; + + n = strlcpy(argv_buf, path, argv_len); + n++; /* leave room for the NUL */ + if (args) { - RARCH_ERR("Failed to load core\n"); + const char **cur_arg = args; + do + { + n += strlcpy(argv_buf + n, *cur_arg, argv_len - n); + n++; + } while (*(++cur_arg)); } - else + + if (string_starts_with(path, "fs:/vol/external01/")) + path_relative_to(load_info.path, path, "fs:/vol/external01/", sizeof(load_info.path)); + else if (string_starts_with(path, "sd:/")) + path_relative_to(load_info.path, path, "sd:/", sizeof(load_info.path)); + else goto cleanup; /* bail if not on the SD card */ + + /* Mocha might not be init'd (Salamander) */ + if (Mocha_InitLibrary() != MOCHA_RESULT_SUCCESS) + goto cleanup; + + load_info.target = LOAD_RPX_TARGET_SD_CARD; + ret = Mocha_PrepareRPXLaunch(&load_info); + if (ret != MOCHA_RESULT_SUCCESS) + goto cleanup; + + std_args.argString = argv_buf; + std_args.size = argv_len; + ret = Mocha_LaunchHomebrewWrapperEx(&std_args); + if (ret != MOCHA_RESULT_SUCCESS) { - param->magic = ARGV_MAGIC; - ARGV_PTR = param; + MochaRPXLoadInfo load_info_revert; + load_info_revert.target = LOAD_RPX_TARGET_EXTRA_REVERT_PREPARE; + Mocha_PrepareRPXLaunch(&load_info_revert); + goto cleanup; + } - DEBUG_VAR(param->argc); - DEBUG_VAR(param->argv); + in_exec = true; + + cleanup: + free(argv_buf); + argv_buf = NULL; +} + +/* ProcUI lifetime: this gets called from main_exit/salamander_main, which we call from main + * This is BEFORE the final shutdown loop so we can just exec cores and it'll handle the mess */ +#ifdef IS_SALAMANDER +static void frontend_wiiu_exitspawn(char *s, size_t len, char *args) +{ + frontend_wiiu_exec(s, false); +} +#else /* ifndef IS_SALAMANDER */ +static void frontend_wiiu_exitspawn(char *s, size_t len, char *args) +{ + if (wiiu_fork_mode != FRONTEND_FORK_NONE) { + /* Load a core */ + bool should_load_content = wiiu_fork_mode == FRONTEND_FORK_CORE_WITH_ARGS; + frontend_wiiu_exec(s, should_load_content); } } +#endif /* IS_SALAMANDER */ #ifndef IS_SALAMANDER static bool frontend_wiiu_set_fork(enum frontend_fork fork_mode) @@ -284,15 +373,13 @@ static bool frontend_wiiu_set_fork(enum frontend_fork fork_mode) switch (fork_mode) { case FRONTEND_FORK_CORE: - wiiu_fork_mode = fork_mode; - break; case FRONTEND_FORK_CORE_WITH_ARGS: - wiiu_fork_mode = fork_mode; + wiiu_fork_mode = fork_mode; break; case FRONTEND_FORK_RESTART: /* NOTE: We don't implement Salamander, so just turn * this into FRONTEND_FORK_CORE. */ - wiiu_fork_mode = FRONTEND_FORK_CORE; + wiiu_fork_mode = FRONTEND_FORK_CORE; break; case FRONTEND_FORK_NONE: default: @@ -303,25 +390,6 @@ static bool frontend_wiiu_set_fork(enum frontend_fork fork_mode) } #endif -static void frontend_wiiu_exitspawn(char *s, size_t len, char *args) -{ - bool should_load_content = false; -#ifndef IS_SALAMANDER - if (wiiu_fork_mode == FRONTEND_FORK_NONE) - return; - - switch (wiiu_fork_mode) - { - case FRONTEND_FORK_CORE_WITH_ARGS: - should_load_content = true; - break; - default: - break; - } -#endif - frontend_wiiu_exec(s, should_load_content); -} - frontend_ctx_driver_t frontend_ctx_wiiu = { frontend_wiiu_get_env_settings, @@ -373,38 +441,20 @@ static void get_arguments(int *argc, char ***argv); static void main_loop(void); #endif static void main_teardown(void); - -static void init_network(void); -static void deinit_network(void); +static void init_filesystems(void); +static void deinit_filesystems(void); static void init_logging(void); static void deinit_logging(void); -static void wiiu_log_init(int port); -static void wiiu_log_deinit(void); static ssize_t wiiu_log_write(struct _reent *r, void *fd, const char *ptr, size_t len); static void init_pad_libraries(void); static void deinit_pad_libraries(void); -static void SaveCallback(void); - -static struct sockaddr_in broadcast; -static int wiiu_log_socket = -1; -static volatile int wiiu_log_lock = 0; - -#if !defined(PC_DEVELOPMENT_TCP_PORT) -#define PC_DEVELOPMENT_TCP_PORT 4405 -#endif - -static devoptab_t dotab_stdout = -{ - "stdout_net", /* device name */ - 0, /* size of file structure */ - NULL, /* device open */ - NULL, /* device close */ - wiiu_log_write, /* device write */ - NULL, /* ... */ -}; +static void proc_setup(void); +static void proc_exit(void); +static void proc_save_callback(void); int main(int argc, char **argv) { + proc_setup(); main_setup(); get_arguments(&argc, &argv); @@ -416,45 +466,38 @@ int main(int argc, char **argv) main_loop(); main_exit(NULL); #endif /* IS_SALAMANDER */ - main_teardown(); - - /* We always return 0 because if we don't, it can prevent loading a - * different RPX/ELF in HBL. */ - return 0; -} -static void get_arguments(int *argc, char ***argv) -{ - DEBUG_VAR(ARGV_PTR); - if (ARGV_PTR && ((u32)ARGV_PTR < 0x01000000)) + if (!ProcUIInShutdown()) { - struct - { - u32 magic; - u32 argc; - char *argv[3]; - } *param = ARGV_PTR; - - if (param->magic == ARGV_MAGIC) + // Final proc loop to negotiate shutdown + ProcUIStatus os_status; + while ((os_status = ProcUIProcessMessages(TRUE)) != PROCUI_STATUS_EXITING) { - *argc = param->argc; - *argv = param->argv; + // If nobody has requested a new app already (e.g. a core switch), we'll still be in foreground + // We should exit to menu + if (os_status == PROCUI_STATUS_IN_FOREGROUND) + SYSLaunchMenu(); + // Core switch puts us here, we're good to release + else if (os_status == PROCUI_STATUS_RELEASE_FOREGROUND) + ProcUIDrawDoneRelease(); + else + DEBUG_LINE(); // BUG } - ARGV_PTR = NULL; } - DEBUG_VAR(argc); - DEBUG_VAR(argv[0]); - DEBUG_VAR(argv[1]); - fflush(stdout); + main_teardown(); + proc_exit(); + /* We always return 0 because if we don't, it can prevent loading a + * different RPX/ELF in HBL. */ + return 0; } static void main_setup(void) { - setup_os_exceptions(); - ProcUIInit(&SaveCallback); - init_network(); + memoryInitialize(); + //init_os_exceptions(); init_logging(); + init_filesystems(); init_pad_libraries(); verbosity_enable(); fflush(stdout); @@ -463,216 +506,277 @@ static void main_setup(void) static void main_teardown(void) { deinit_pad_libraries(); - ProcUIShutdown(); + deinit_filesystems(); deinit_logging(); - deinit_network(); + //deinit_os_exceptions(); + memoryRelease(); } -#ifndef IS_SALAMANDER -static bool swap_is_pending(void *start_time) -{ - uint32_t swap_count, flip_count; - OSTime last_flip, last_vsync; +static bool in_aroma = false; +static void* procui_mem1Storage = NULL; +static void* procui_bucketStorage = NULL; - GX2GetSwapStatus(&swap_count, &flip_count, &last_flip, &last_vsync); - return last_vsync < *(OSTime *)start_time; -} - -static void main_loop(void) +static void proc_setup(void) { - OSTime start_time; - int status; - - for (;;) + /* Detect Aroma explicitly (it's possible to run under H&S while using Tiramisu) */ + OSDynLoad_Module rpxModule; + if (OSDynLoad_Acquire("homebrew_rpx_loader", &rpxModule) == OS_DYNLOAD_OK) { - if (video_driver_get_ptr()) - { - start_time = OSGetSystemTime(); - task_queue_wait(swap_is_pending, &start_time); - } - else - task_queue_wait(NULL, NULL); + in_aroma = true; + OSDynLoad_Release(rpxModule); + } - status = runloop_iterate(); + ProcUIInit(&proc_save_callback); - if (status == -1) - break; + uint32_t addr = 0; + uint32_t size = 0; + if (OSGetMemBound(OS_MEM1, &addr, &size) == 0) { + procui_mem1Storage = malloc(size); + if (procui_mem1Storage) { + ProcUISetMEM1Storage(procui_mem1Storage, size); + } + } + if (OSGetForegroundBucketFreeArea(&addr, &size)) { + procui_bucketStorage = malloc(size); + if (procui_bucketStorage) { + ProcUISetBucketStorage(procui_bucketStorage, size); + } } } -#endif -static void SaveCallback(void) +static void proc_exit(void) { - OSSavesDone_ReadyToRelease(); + if (procui_mem1Storage) { + free(procui_mem1Storage); + procui_mem1Storage = NULL; + } + if (procui_bucketStorage) { + free(procui_bucketStorage); + procui_bucketStorage = NULL; + } + ProcUIShutdown(); } - -static void init_network(void) +static void proc_save_callback(void) { - ACInitialize(); - ACConnect(); -#ifdef IS_SALAMANDER - socket_lib_init(); -#else - network_init(); -#endif /* IS_SALAMANDER */ + OSSavesDone_ReadyToRelease(); } -static void deinit_network(void) +static void sysapp_arg_cb(SYSDeserializeArg *arg, void *usr) { - ACClose(); - ACFinalize(); + SYSStandardArgs *std_args = (SYSStandardArgs *) usr; + + if (_SYSDeserializeStandardArg(arg, std_args)) + return; + + if (strcmp(arg->argName, "sys:pack") == 0) + { + // Recurse + SYSDeserializeSysArgsFromBlock(arg->data, arg->size, sysapp_arg_cb, usr); + return; + } } -int getBroadcastAddress(ACIpAddress *broadcast) +static void get_arguments(int *argc, char ***argv) { - ACIpAddress myIp, mySubnet; - ACResult result; +#ifdef HAVE_NETWORKING + static char *_argv[1 + NETPLAY_FORK_MAX_ARGS]; +#else + static char* _argv[2]; +#endif + int _argc = 0; + SYSStandardArgs std_args = {0}; - if (!broadcast) - return -1; + /* we could do something more rich with the content path and things here - + * but since there's not a great way to actually pass that info along to RA, + * just emulate argc/argv */ + SYSDeserializeSysArgs(sysapp_arg_cb, &std_args); - result = ACGetAssignedAddress(&myIp); - if (result < 0) - return -1; - result = ACGetAssignedSubnet(&mySubnet); - if (result < 0) - return -1; + char *argv_buf = std_args.anchorData; + size_t argv_len = std_args.anchorSize; + if (!argv_buf || argv_len == 0) + return; - *broadcast = myIp | (~mySubnet); - return 0; -} + size_t n = 0; + while (n < argv_len && _argc < ARRAY_SIZE(_argv)) + { + char *s = argv_buf + n; + _argv[_argc++] = s; + n += strlen(s); + n++; /* skip the null */ + } -static void init_logging(void) -{ - wiiu_log_init(PC_DEVELOPMENT_TCP_PORT); - devoptab_list[STD_OUT] = &dotab_stdout; - devoptab_list[STD_ERR] = &dotab_stdout; + *argc = _argc; + *argv = _argv; } -static void deinit_logging(void) +#ifndef IS_SALAMANDER +static bool swap_is_pending(void *start_time) { - fflush(stdout); - fflush(stderr); + uint32_t swap_count, flip_count; + OSTime last_flip, last_vsync; - wiiu_log_deinit(); + GX2GetSwapStatus(&swap_count, &flip_count, &last_flip, &last_vsync); + return last_vsync < *(OSTime *)start_time; } -static int broadcast_init(int port) +static bool in_main = false; +static uint32_t proc_home_button_deny(void *context) { - ACIpAddress broadcast_ip; - if (getBroadcastAddress(&broadcast_ip) < 0) - return -1; - - memset(&broadcast, 0, sizeof(broadcast)); - broadcast.sin_family = AF_INET; - broadcast.sin_port = htons(port); - broadcast.sin_addr.s_addr = htonl(broadcast_ip); + /* Don't toggle the menu in, like, the middle of a core switch */ + if (in_main) + command_event(CMD_EVENT_MENU_TOGGLE, NULL); return 0; } -static void wiiu_log_init(int port) +static void main_loop(void) { - wiiu_log_lock = 0; + OSTime start_time; + ProcUIStatus os_status; + int status; + settings_t *settings = config_get_ptr(); - if (wiiu_log_socket >= 0) - return; + ProcUIRegisterCallback(PROCUI_CALLBACK_HOME_BUTTON_DENIED, &proc_home_button_deny, NULL, 1000); + in_main = true; - if (broadcast_init(port) < 0) - return; + while ((os_status = ProcUIProcessMessages(TRUE)) != PROCUI_STATUS_EXITING) + { + if (os_status == PROCUI_STATUS_IN_BACKGROUND) continue; - wiiu_log_socket = socket(AF_INET, SOCK_DGRAM, 0); + if (os_status == PROCUI_STATUS_IN_FOREGROUND) { + if (video_driver_get_ptr()) { + start_time = OSGetSystemTime(); + task_queue_wait(swap_is_pending, &start_time); + } + else + task_queue_wait(NULL, NULL); - if (wiiu_log_socket < 0) - return; + status = runloop_iterate(); + if (status == -1) { + /* RetroArch requested core switch or exit */ + break; + } - struct sockaddr_in connect_addr; - memset(&connect_addr, 0, sizeof(connect_addr)); - connect_addr.sin_family = AF_INET; - connect_addr.sin_port = 0; - connect_addr.sin_addr.s_addr = htonl(INADDR_ANY); + } else if (os_status == PROCUI_STATUS_RELEASE_FOREGROUND) { + /* Home menu opened - also open RA menu + * This could also be like, an OS poweroff, but it doesn't really matter if we open the menu for 1 frame in + * that case*/ + if (!(menu_state_get_ptr()->flags & MENU_ST_FLAG_ALIVE)) { + command_event(CMD_EVENT_MENU_TOGGLE, NULL); + } + ProcUIDrawDoneRelease(); + } - if ( bind(wiiu_log_socket, (struct sockaddr *)&connect_addr, sizeof(connect_addr)) < 0) - { - socketclose(wiiu_log_socket); - wiiu_log_socket = -1; - return; + if (OSIsHomeButtonMenuEnabled() != settings->bools.input_wiiu_enable_hbm) + OSEnableHomeButtonMenu(settings->bools.input_wiiu_enable_hbm); } + + in_main = false; + OSEnableHomeButtonMenu(FALSE); } +#endif -static void wiiu_log_deinit(void) +static void init_filesystems(void) { - if (wiiu_log_socket >= 0) +#if defined(HAVE_LIBMOCHA) + if (Mocha_InitLibrary() == MOCHA_RESULT_SUCCESS) { - socketclose(wiiu_log_socket); - wiiu_log_socket = -1; + if (Mocha_MountFS("storage_usb", NULL, "/vol/storage_usb01") == MOCHA_RESULT_SUCCESS) { + if (exists(WIIU_USB_WFS_PATH)) + have_wfs_usb = true; + else /* Liar! */ + Mocha_UnmountFS("storage_usb"); + } + + +#if defined(HAVE_LIBFAT) + have_libfat_usb = fatMount("usb", &Mocha_usb_disc_interface, 0, 512, 128); + /* Mounting SD card with libfat is unsafe under Aroma */ + if (!in_aroma) + have_libfat_sdcard = fatMount("sd", &Mocha_sdio_disc_interface, 0, 512, 128); +#endif /* HAVE_LIBFAT */ } +#endif /* HAVE_LIBMOCHA */ } -static void init_pad_libraries(void) +static void deinit_filesystems(void) { -#ifndef IS_SALAMANDER - KPADInit(); - WPADEnableURCC(true); - WPADEnableWiiRemote(true); -#endif /* IS_SALAMANDER */ -} +#if defined(HAVE_LIBMOCHA) + if (have_wfs_usb) + Mocha_UnmountFS("storage_usb"); -static void deinit_pad_libraries(void) -{ -#ifndef IS_SALAMANDER - KPADShutdown(); -#endif /* IS_SALAMANDER */ +#if defined(HAVE_LIBFAT) + if (have_libfat_usb) + fatUnmount("usb"); + if (have_libfat_sdcard) + fatUnmount("sd"); +#endif /* HAVE_LIBFAT */ + + Mocha_DeInitLibrary(); +#endif /* HAVE_LIBMOCHA */ } -/* logging routines */ +static devoptab_t dotab_stdout = +{ + "stdout_whb", /* device name */ + 0, /* size of file structure */ + NULL, /* device open */ + NULL, /* device close */ + wiiu_log_write, /* device write */ + NULL, /* ... */ +}; -void net_print(const char *str) +static void init_logging(void) { - wiiu_log_write(NULL, 0, str, strlen(str)); + WHBLogUdpInit(); + WHBLogCafeInit(); + devoptab_list[STD_OUT] = &dotab_stdout; + devoptab_list[STD_ERR] = &dotab_stdout; } -void net_print_exp(const char *str) +static void deinit_logging(void) { - sendto(wiiu_log_socket, str, strlen(str), 0, (struct sockaddr *)&broadcast, sizeof(broadcast)); -} + fflush(stdout); + fflush(stderr); -/* RFC 791 specifies that any IP host must be able - * to receive a datagram of 576 bytes. - * Since we're generally never logging more than a - * line or two's worth of data (~100 bytes) - * this is a reasonable size for our use. */ -#define DGRAM_SIZE 576 + WHBLogCafeDeinit(); + WHBLogUdpDeinit(); +} static ssize_t wiiu_log_write(struct _reent *r, - void *fd, const char *ptr, size_t len) + void *fd, const char *ptr, size_t len) { - int remaining; - if (wiiu_log_socket < 0) - return len; + // Do a bit of line buffering to try and make the log output nicer + // we just truncate if a line goes over + static char linebuf[2048]; //match wut's PRINTF_BUFFER_LENGTH + static size_t linebuf_pos = 0; - while (wiiu_log_lock) - OSSleepTicks(((248625000 / 4)) / 1000); + snprintf(linebuf + linebuf_pos, sizeof(linebuf) - linebuf_pos - 1, "%.*s", + len, ptr); + linebuf_pos = strlen(linebuf); - wiiu_log_lock = 1; - - remaining = len; - - while (remaining > 0) + if (linebuf[linebuf_pos - 1] == '\n' || linebuf_pos >= sizeof(linebuf) - 2) { - int block = remaining < DGRAM_SIZE ? remaining : DGRAM_SIZE; - int sent = sendto(wiiu_log_socket, ptr, block, 0, - (struct sockaddr *)&broadcast, sizeof(broadcast)); - - if (sent < 0) - break; - - remaining -= sent; - ptr += sent; + WHBLogWrite(linebuf); + linebuf_pos = 0; } - wiiu_log_lock = 0; + return (ssize_t) len; +} - return len; +static void init_pad_libraries(void) +{ +#ifndef IS_SALAMANDER + KPADInit(); + WPADEnableURCC(true); + WPADEnableWiiRemote(true); +#endif /* IS_SALAMANDER */ +} + +static void deinit_pad_libraries(void) +{ +#ifndef IS_SALAMANDER + KPADShutdown(); +#endif /* IS_SALAMANDER */ } diff --git a/gfx/common/gx2_defines.h b/gfx/common/gx2_defines.h index 05a71d912fc7..857a468ca63b 100644 --- a/gfx/common/gx2_defines.h +++ b/gfx/common/gx2_defines.h @@ -1,7 +1,22 @@ #ifndef __GX2_DEFINES_H #define __GX2_DEFINES_H -#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define GX2_INVALIDATE_MODE_CPU_UNIFORM_BLOCK (GX2_INVALIDATE_MODE_CPU | GX2_INVALIDATE_MODE_UNIFORM_BLOCK) #include "../video_defines.h" #include "../video_shader_parse.h" @@ -26,8 +41,8 @@ #define _1 0x05 #define GX2_COMP_SEL(c0, c1, c2, c3) (((c0) << 24) | ((c1) << 16) | ((c2) << 8) | (c3)) -#define COLOR_ARGB(r, g, b, a) (((u32)(a) << 24) | ((u32)(r) << 16) | ((u32)(g) << 8) | ((u32)(b) << 0)) -#define COLOR_RGBA(r, g, b, a) (((u32)(r) << 24) | ((u32)(g) << 16) | ((u32)(b) << 8) | ((u32)(a) << 0)) +#define COLOR_ARGB(r, g, b, a) (((uint32_t)(a) << 24) | ((uint32_t)(r) << 16) | ((uint32_t)(g) << 8) | ((uint32_t)(b) << 0)) +#define COLOR_RGBA(r, g, b, a) (((uint32_t)(r) << 24) | ((uint32_t)(g) << 16) | ((uint32_t)(b) << 8) | ((uint32_t)(a) << 0)) typedef struct { @@ -70,8 +85,8 @@ typedef struct GX2_mat4x4 *ubo_mvp; void *input_ring_buffer; void *output_ring_buffer; - u32 input_ring_buffer_size; - u32 output_ring_buffer_size; + uint32_t input_ring_buffer_size; + uint32_t output_ring_buffer_size; int width; int height; diff --git a/gfx/drivers/gx2_gfx.c b/gfx/drivers/gx2_gfx.c index 48e9c6eca65c..8b1c576d4ae1 100644 --- a/gfx/drivers/gx2_gfx.c +++ b/gfx/drivers/gx2_gfx.c @@ -19,13 +19,11 @@ #include #include -#include -#include - #include #include #include #include +#include #include "../../driver.h" #include "../../configuration.h" @@ -1016,8 +1014,8 @@ static void *gx2_init(const video_info_t *video, { unsigned i; float refresh_rate = 60.0f / 1.001f; - u32 size = 0; - u32 tmp = 0; + uint32_t size = 0; + uint32_t tmp = 0; void *wiiuinput = NULL; wiiu_video_t *wiiu = (wiiu_video_t*)calloc(1, sizeof(*wiiu)); settings_t *settings = config_get_ptr(); @@ -1039,9 +1037,9 @@ static void *gx2_init(const video_info_t *video, /* video initialize */ wiiu->cmd_buffer = MEM2_alloc(0x400000, 0x40); - u32 init_attributes[] = + uint32_t init_attributes[] = { - GX2_INIT_CMD_BUF_BASE, (u32)wiiu->cmd_buffer, + GX2_INIT_CMD_BUF_BASE, (uint32_t)wiiu->cmd_buffer, GX2_INIT_CMD_BUF_POOL_SIZE, 0x400000, GX2_INIT_ARGC, 0, GX2_INIT_ARGV, 0, @@ -1496,19 +1494,21 @@ static void gx2_free(void *data) if (!wiiu) return; - /* clear leftover image */ - GX2ClearColor(&wiiu->color_buffer, 0.0f, 0.0f, 0.0f, 1.0f); - GX2CopyColorBufferToScanBuffer(&wiiu->color_buffer, GX2_SCAN_TARGET_DRC); - GX2CopyColorBufferToScanBuffer(&wiiu->color_buffer, GX2_SCAN_TARGET_TV); + if (ProcUIInForeground()) { + /* clear leftover image */ + GX2ClearColor(&wiiu->color_buffer, 0.0f, 0.0f, 0.0f, 1.0f); + GX2CopyColorBufferToScanBuffer(&wiiu->color_buffer, GX2_SCAN_TARGET_DRC); + GX2CopyColorBufferToScanBuffer(&wiiu->color_buffer, GX2_SCAN_TARGET_TV); - GX2SwapScanBuffers(); - GX2Flush(); - GX2DrawDone(); - GX2WaitForVsync(); - GX2Shutdown(); + GX2SwapScanBuffers(); + GX2Flush(); + GX2DrawDone(); + GX2WaitForVsync(); - GX2SetTVEnable(GX2_DISABLE); - GX2SetDRCEnable(GX2_DISABLE); + GX2SetTVEnable(GX2_DISABLE); + GX2SetDRCEnable(GX2_DISABLE); + } + GX2Shutdown(); GX2DestroyShader(&frame_shader); GX2DestroyShader(&tex_shader); @@ -1752,21 +1752,21 @@ static void gx2_update_uniform_block(wiiu_video_t *wiiu, *dst = wiiu->shader_preset->pass[pass].frame_count_mod ? frame_count % wiiu->shader_preset->pass[pass].frame_count_mod : frame_count; - *(u32 *)dst = __builtin_bswap32(*(u32 *)dst); + *(uint32_t *)dst = __builtin_bswap32(*(uint32_t *)dst); continue; } if (string_is_equal(id, "FrameDirection")) { *dst = frame_direction; - *(u32 *)dst = __builtin_bswap32(*(u32 *)dst); + *(uint32_t *)dst = __builtin_bswap32(*(uint32_t *)dst); continue; } if (string_is_equal(id, "Rotation")) { - *dst = rotation; - *(u32 *)dst = __builtin_bswap32(*(u32 *)dst); + *dst = rotation; + *(uint32_t *)dst = __builtin_bswap32(*(uint32_t *)dst); continue; } @@ -1863,8 +1863,8 @@ static void gx2_update_uniform_block(wiiu_video_t *wiiu, { if (string_is_equal(id, wiiu->shader_preset->parameters[k].id)) { - *dst = wiiu->shader_preset->parameters[k].current; - *(u32 *)dst = __builtin_bswap32(*(u32 *)dst); + *dst = wiiu->shader_preset->parameters[k].current; + *(uint32_t *)dst = __builtin_bswap32(*(uint32_t *)dst); break; } } @@ -1901,7 +1901,7 @@ static bool gx2_frame(void *data, const void *frame, if (wiiu->last_vsync >= last_vsync) { GX2WaitForVsync(); - wiiu->last_vsync = last_vsync + ms_to_ticks(17); + wiiu->last_vsync = last_vsync + OSMillisecondsToTicks(17); } else wiiu->last_vsync = last_vsync; diff --git a/gfx/drivers/gx2_shaders/bokeh.c b/gfx/drivers/gx2_shaders/bokeh.c index 050b4378adb3..8e025794c75c 100644 --- a/gfx/drivers/gx2_shaders/bokeh.c +++ b/gfx/drivers/gx2_shaders/bokeh.c @@ -16,15 +16,16 @@ #include #include #include -#include +#include +#include #include "gx2_shader_inl.h" #include "menu_shaders.h" -__attribute__((aligned(GX2_SHADER_ALIGNMENT))) +__attribute__((aligned(GX2_SHADER_PROGRAM_ALIGNMENT))) static struct { - u64 cf[32]; - u64 alu[16]; + uint64_t cf[32]; + uint64_t alu[16]; } vs_program = { { @@ -62,23 +63,23 @@ static struct }, }; -__attribute__((aligned(GX2_SHADER_ALIGNMENT))) +__attribute__((aligned(GX2_SHADER_PROGRAM_ALIGNMENT))) static struct { - u64 cf[32]; - u64 alu[70]; - u64 alu1[19]; - u64 alu2[31]; - u64 alu3[25]; - u64 alu4[31]; - u64 alu5[25]; - u64 alu6[31]; - u64 alu7[25]; - u64 alu8[31]; - u64 alu9[25]; - u64 alu10[31]; - u64 alu11[25]; - u64 alu12[17]; + uint64_t cf[32]; + uint64_t alu[70]; + uint64_t alu1[19]; + uint64_t alu2[31]; + uint64_t alu3[25]; + uint64_t alu4[31]; + uint64_t alu5[25]; + uint64_t alu6[31]; + uint64_t alu7[25]; + uint64_t alu8[31]; + uint64_t alu9[25]; + uint64_t alu10[31]; + uint64_t alu11[25]; + uint64_t alu12[17]; } ps_program = { { diff --git a/gfx/drivers/gx2_shaders/frame.c b/gfx/drivers/gx2_shaders/frame.c index ad9d1b416b04..09793fbb2ebb 100644 --- a/gfx/drivers/gx2_shaders/frame.c +++ b/gfx/drivers/gx2_shaders/frame.c @@ -16,15 +16,16 @@ #include #include #include -#include +#include +#include #include "gx2_shader_inl.h" #include "frame.h" -__attribute__((aligned(GX2_SHADER_ALIGNMENT))) +__attribute__((aligned(GX2_SHADER_PROGRAM_ALIGNMENT))) static struct { - u64 cf[32]; - u64 alu[18]; + uint64_t cf[32]; + uint64_t alu[18]; } vs_program = { { @@ -60,11 +61,11 @@ static struct } }; -__attribute__((aligned(GX2_SHADER_ALIGNMENT))) +__attribute__((aligned(GX2_SHADER_PROGRAM_ALIGNMENT))) static struct { - u64 cf[16]; - u64 tex[1 * 2]; + uint64_t cf[16]; + uint64_t tex[1 * 2]; } ps_program = { @@ -102,7 +103,7 @@ static GX2UniformBlock uniform_blocks[] = { }; static GX2UniformVar uniform_vars[] = { - {"global.MVP", GX2_SHADER_VAR_TYPE_MATRIX4X4, 1, 0, 0}, + {"global.MVP", GX2_SHADER_VAR_TYPE_FLOAT4X4, 1, 0, 0}, }; GX2Shader frame_shader = diff --git a/gfx/drivers/gx2_shaders/ribbon.c b/gfx/drivers/gx2_shaders/ribbon.c index 1cafaa5b7fa1..39c17bfcf3ed 100644 --- a/gfx/drivers/gx2_shaders/ribbon.c +++ b/gfx/drivers/gx2_shaders/ribbon.c @@ -16,15 +16,16 @@ #include #include #include -#include +#include +#include #include "gx2_shader_inl.h" #include "menu_shaders.h" -__attribute__((aligned(GX2_SHADER_ALIGNMENT))) +__attribute__((aligned(GX2_SHADER_PROGRAM_ALIGNMENT))) static struct { - u64 cf[32]; - u64 alu[123 + 51]; + uint64_t cf[32]; + uint64_t alu[123 + 51]; } vs_program = { { @@ -243,12 +244,12 @@ static struct } }; -__attribute__((aligned(GX2_SHADER_ALIGNMENT))) +__attribute__((aligned(GX2_SHADER_PROGRAM_ALIGNMENT))) static struct { - u64 cf[32]; - u64 alu[64-32]; - u64 tex[2 * 2]; + uint64_t cf[32]; + uint64_t alu[64-32]; + uint64_t tex[2 * 2]; } ps_program = { diff --git a/gfx/drivers/gx2_shaders/ribbon_simple.c b/gfx/drivers/gx2_shaders/ribbon_simple.c index 214f6ab3d2bd..738a30bf007c 100644 --- a/gfx/drivers/gx2_shaders/ribbon_simple.c +++ b/gfx/drivers/gx2_shaders/ribbon_simple.c @@ -16,15 +16,16 @@ #include #include #include -#include +#include +#include #include "gx2_shader_inl.h" #include "menu_shaders.h" -__attribute__((aligned(GX2_SHADER_ALIGNMENT))) +__attribute__((aligned(GX2_SHADER_PROGRAM_ALIGNMENT))) static struct { - u64 cf[32]; - u64 alu[88]; + uint64_t cf[32]; + uint64_t alu[88]; } vs_program = { { @@ -167,11 +168,11 @@ static struct }, }; -__attribute__((aligned(GX2_SHADER_ALIGNMENT))) +__attribute__((aligned(GX2_SHADER_PROGRAM_ALIGNMENT))) static struct { - u64 cf[32]; - u64 alu[3]; + uint64_t cf[32]; + uint64_t alu[3]; } ps_program = { { diff --git a/gfx/drivers/gx2_shaders/snow.c b/gfx/drivers/gx2_shaders/snow.c index 455facee0791..2387cd22a3b1 100644 --- a/gfx/drivers/gx2_shaders/snow.c +++ b/gfx/drivers/gx2_shaders/snow.c @@ -16,15 +16,16 @@ #include #include #include -#include +#include +#include #include "gx2_shader_inl.h" #include "menu_shaders.h" -__attribute__((aligned(GX2_SHADER_ALIGNMENT))) +__attribute__((aligned(GX2_SHADER_PROGRAM_ALIGNMENT))) static struct { - u64 cf[32]; - u64 alu[16]; + uint64_t cf[32]; + uint64_t alu[16]; } vs_program = { { @@ -62,27 +63,27 @@ static struct }, }; -__attribute__((aligned(GX2_SHADER_ALIGNMENT))) +__attribute__((aligned(GX2_SHADER_PROGRAM_ALIGNMENT))) static struct { - u64 cf[32]; - u64 alu[56]; - u64 alu1[27]; - u64 alu2[51]; - u64 alu3[27]; - u64 alu4[52]; - u64 alu5[27]; - u64 alu6[51]; - u64 alu7[27]; - u64 alu8[52]; - u64 alu9[27]; - u64 alu10[52]; - u64 alu11[27]; - u64 alu12[52]; - u64 alu13[27]; - u64 alu14[52]; - u64 alu15[27]; - u64 alu16[6]; + uint64_t cf[32]; + uint64_t alu[56]; + uint64_t alu1[27]; + uint64_t alu2[51]; + uint64_t alu3[27]; + uint64_t alu4[52]; + uint64_t alu5[27]; + uint64_t alu6[51]; + uint64_t alu7[27]; + uint64_t alu8[52]; + uint64_t alu9[27]; + uint64_t alu10[52]; + uint64_t alu11[27]; + uint64_t alu12[52]; + uint64_t alu13[27]; + uint64_t alu14[52]; + uint64_t alu15[27]; + uint64_t alu16[6]; } ps_program = { { diff --git a/gfx/drivers/gx2_shaders/snow_simple.c b/gfx/drivers/gx2_shaders/snow_simple.c index 7f6715f458ee..1ed7106fbc3d 100644 --- a/gfx/drivers/gx2_shaders/snow_simple.c +++ b/gfx/drivers/gx2_shaders/snow_simple.c @@ -16,15 +16,16 @@ #include #include #include -#include +#include +#include #include "gx2_shader_inl.h" #include "menu_shaders.h" -__attribute__((aligned(GX2_SHADER_ALIGNMENT))) +__attribute__((aligned(GX2_SHADER_PROGRAM_ALIGNMENT))) static struct { - u64 cf[32]; - u64 alu[16]; + uint64_t cf[32]; + uint64_t alu[16]; } vs_program = { { @@ -62,27 +63,27 @@ static struct }, }; -__attribute__((aligned(GX2_SHADER_ALIGNMENT))) +__attribute__((aligned(GX2_SHADER_PROGRAM_ALIGNMENT))) static struct { - u64 cf[32]; - u64 alu[56]; - u64 alu1[27]; - u64 alu2[51]; - u64 alu3[27]; - u64 alu4[52]; - u64 alu5[27]; - u64 alu6[51]; - u64 alu7[27]; - u64 alu8[52]; - u64 alu9[27]; - u64 alu10[52]; - u64 alu11[27]; - u64 alu12[52]; - u64 alu13[27]; - u64 alu14[52]; - u64 alu15[27]; - u64 alu16[6]; + uint64_t cf[32]; + uint64_t alu[56]; + uint64_t alu1[27]; + uint64_t alu2[51]; + uint64_t alu3[27]; + uint64_t alu4[52]; + uint64_t alu5[27]; + uint64_t alu6[51]; + uint64_t alu7[27]; + uint64_t alu8[52]; + uint64_t alu9[27]; + uint64_t alu10[52]; + uint64_t alu11[27]; + uint64_t alu12[52]; + uint64_t alu13[27]; + uint64_t alu14[52]; + uint64_t alu15[27]; + uint64_t alu16[6]; } ps_program = { { diff --git a/gfx/drivers/gx2_shaders/snowflake.c b/gfx/drivers/gx2_shaders/snowflake.c index b01bbcf1e6c9..7f66732590c7 100644 --- a/gfx/drivers/gx2_shaders/snowflake.c +++ b/gfx/drivers/gx2_shaders/snowflake.c @@ -16,15 +16,16 @@ #include #include #include -#include +#include +#include #include "gx2_shader_inl.h" #include "menu_shaders.h" -__attribute__((aligned(GX2_SHADER_ALIGNMENT))) +__attribute__((aligned(GX2_SHADER_PROGRAM_ALIGNMENT))) static struct { - u64 cf[32]; - u64 alu[16]; + uint64_t cf[32]; + uint64_t alu[16]; } vs_program = { { @@ -62,16 +63,16 @@ static struct }, }; -__attribute__((aligned(GX2_SHADER_ALIGNMENT))) +__attribute__((aligned(GX2_SHADER_PROGRAM_ALIGNMENT))) static struct { - u64 cf[32]; - u64 alu[120]; - u64 alu1[19]; - u64 alu2[1]; - u64 alu3[106]; - u64 alu4[19]; - u64 alu5[2]; + uint64_t cf[32]; + uint64_t alu[120]; + uint64_t alu1[19]; + uint64_t alu2[1]; + uint64_t alu3[106]; + uint64_t alu4[19]; + uint64_t alu5[2]; } ps_program = { { diff --git a/gfx/drivers/gx2_shaders/sprite.c b/gfx/drivers/gx2_shaders/sprite.c index 4d729c70b43c..c791d7cab962 100644 --- a/gfx/drivers/gx2_shaders/sprite.c +++ b/gfx/drivers/gx2_shaders/sprite.c @@ -16,15 +16,16 @@ #include #include #include -#include +#include +#include #include "gx2_shader_inl.h" #include "sprite.h" -__attribute__((aligned(GX2_SHADER_ALIGNMENT))) +__attribute__((aligned(GX2_SHADER_PROGRAM_ALIGNMENT))) static struct { - u64 cf[32]; - u64 alu[26]; + uint64_t cf[32]; + uint64_t alu[26]; } vs_program = { { @@ -71,12 +72,12 @@ static struct } }; -__attribute__((aligned(GX2_SHADER_ALIGNMENT))) +__attribute__((aligned(GX2_SHADER_PROGRAM_ALIGNMENT))) static struct { - u64 cf[32]; /* @0 */ - u64 alu[16]; /* @32 */ - u64 tex[1 * 2]; /* @48 */ + uint64_t cf[32]; /* @0 */ + uint64_t alu[16]; /* @32 */ + uint64_t tex[1 * 2]; /* @48 */ } ps_program = { { @@ -97,12 +98,12 @@ static struct } }; -__attribute__((aligned(GX2_SHADER_ALIGNMENT))) +__attribute__((aligned(GX2_SHADER_PROGRAM_ALIGNMENT))) static struct { - u64 cf[32]; /* @0 */ - u64 alu[80-32]; /* @32 */ - u64 tex[3 * 2]; /* @80 */ + uint64_t cf[32]; /* @0 */ + uint64_t alu[80-32]; /* @32 */ + uint64_t tex[3 * 2]; /* @80 */ } gs_program = { { @@ -175,11 +176,11 @@ static struct } }; -__attribute__((aligned(GX2_SHADER_ALIGNMENT))) +__attribute__((aligned(GX2_SHADER_PROGRAM_ALIGNMENT))) static struct { - u64 cf[16]; /* @0 */ - u64 vtx[3 * 2]; /* @16 */ + uint64_t cf[16]; /* @0 */ + uint64_t vtx[3 * 2]; /* @16 */ } gs_copy_program= { { diff --git a/gfx/drivers/gx2_shaders/sprite.h b/gfx/drivers/gx2_shaders/sprite.h index dfbf4a6f5676..2ece24298c6d 100644 --- a/gfx/drivers/gx2_shaders/sprite.h +++ b/gfx/drivers/gx2_shaders/sprite.h @@ -40,7 +40,7 @@ typedef struct float height; }coord; - u32 color; + uint32_t color; }sprite_vertex_t; extern GX2Shader sprite_shader; diff --git a/gfx/drivers/gx2_shaders/tex.c b/gfx/drivers/gx2_shaders/tex.c index 5a8b7ede357b..8c2f486df34b 100644 --- a/gfx/drivers/gx2_shaders/tex.c +++ b/gfx/drivers/gx2_shaders/tex.c @@ -16,15 +16,16 @@ #include #include #include -#include +#include +#include #include "gx2_shader_inl.h" #include "tex.h" -__attribute__((aligned(GX2_SHADER_ALIGNMENT))) +__attribute__((aligned(GX2_SHADER_PROGRAM_ALIGNMENT))) static struct { - u64 cf[32]; - u64 alu[16]; + uint64_t cf[32]; + uint64_t alu[16]; } vs_program = { { @@ -59,12 +60,12 @@ static struct } }; -__attribute__((aligned(GX2_SHADER_ALIGNMENT))) +__attribute__((aligned(GX2_SHADER_PROGRAM_ALIGNMENT))) static struct { - u64 cf[32]; - u64 alu[16]; - u64 tex[1 * 2]; + uint64_t cf[32]; + uint64_t alu[16]; + uint64_t tex[1 * 2]; } ps_program = { @@ -113,7 +114,7 @@ static GX2UniformBlock uniform_blocks[] = { }; static GX2UniformVar uniform_vars[] = { - {"global.MVP", GX2_SHADER_VAR_TYPE_MATRIX4X4, 1, 0, 0}, + {"global.MVP", GX2_SHADER_VAR_TYPE_FLOAT4X4, 1, 0, 0}, }; GX2Shader tex_shader = diff --git a/gfx/drivers_font_renderer/freetype.c b/gfx/drivers_font_renderer/freetype.c index 1e83a0895f83..e5ff62843f37 100644 --- a/gfx/drivers_font_renderer/freetype.c +++ b/gfx/drivers_font_renderer/freetype.c @@ -39,7 +39,7 @@ #endif #ifdef WIIU -#include +#include #endif #include FT_FREETYPE_H @@ -278,7 +278,7 @@ static void *font_renderer_ft_init(const char *font_path, float font_size) void* font_data = NULL; uint32_t font_data_size = 0; - if (!OSGetSharedData(SHARED_FONT_DEFAULT, 0, + if (!OSGetSharedData(OS_SHAREDDATATYPE_FONT_STANDARD, 0, &font_data, &font_data_size)) goto error; diff --git a/gfx/drivers_font_renderer/stb_unicode.c b/gfx/drivers_font_renderer/stb_unicode.c index 7ed6bd6c2d67..947e17b35fe2 100644 --- a/gfx/drivers_font_renderer/stb_unicode.c +++ b/gfx/drivers_font_renderer/stb_unicode.c @@ -22,7 +22,7 @@ #include #ifdef WIIU -#include +#include #endif #include "../font_driver.h" @@ -252,7 +252,7 @@ static void *font_renderer_stb_unicode_init(const char *font_path, float font_si if (!*font_path) { uint32_t size = 0; - if (!OSGetSharedData(SHARED_FONT_DEFAULT, 0, (void**)&self->font_data, &size)) + if (!OSGetSharedData(OS_SHAREDDATATYPE_FONT_STANDARD, 0, (void**)&self->font_data, &size)) goto error; } else diff --git a/input/drivers/wiiu_input.c b/input/drivers/wiiu_input.c index c26276ad8684..ae64ad42170d 100644 --- a/input/drivers/wiiu_input.c +++ b/input/drivers/wiiu_input.c @@ -21,7 +21,7 @@ #include #include -#include +#include #include #ifdef HAVE_CONFIG_H diff --git a/input/drivers_hid/wiiu_hid.c b/input/drivers_hid/wiiu_hid.c index 285bcb9e0a47..79b7e03778c0 100644 --- a/input/drivers_hid/wiiu_hid.c +++ b/input/drivers_hid/wiiu_hid.c @@ -16,7 +16,9 @@ #include #include "../include/wiiu/hid.h" -#include +#include +#include +#include #include /* TODO/FIXME - static globals */ @@ -397,7 +399,7 @@ static void wiiu_poll_adapters(wiiu_hid_t *hid) static wiiu_attach_event *wiiu_hid_synchronized_get_events_list(void) { - return (wiiu_attach_event *)SwapAtomic32((uint32_t *)&events.list, 0); + return (wiiu_attach_event *)OSSwapAtomic((uint32_t *)&events.list, 0); } static int wiiu_hid_polling_thread(int argc, const char **argv) @@ -408,6 +410,7 @@ static int wiiu_hid_polling_thread(int argc, const char **argv) { wiiu_handle_attach_events(hid, wiiu_hid_synchronized_get_events_list()); wiiu_poll_adapters(hid); + OSSleepTicks(OSMicrosecondsToTicks(500)); } return 0; @@ -479,10 +482,10 @@ static void wiiu_hid_stop_polling_thread(wiiu_hid_t *hid) static void wiiu_hid_synchronized_add_event(wiiu_attach_event *event) { - wiiu_attach_event *head = (wiiu_attach_event *)SwapAtomic32((uint32_t *)&events.list, 0); + wiiu_attach_event *head = (wiiu_attach_event *)OSSwapAtomic((uint32_t *)&events.list, 0); event->next = head; head = event; - SwapAtomic32((uint32_t *)&events.list, (uint32_t)head); + OSSwapAtomic((uint32_t *)&events.list, (uint32_t)head); } static void wiiu_hid_synchronized_add_to_adapters_list(wiiu_adapter_t *adapter) @@ -496,14 +499,14 @@ static void wiiu_hid_synchronized_add_to_adapters_list(wiiu_adapter_t *adapter) static void wiiu_hid_log_device(HIDDevice *device) { RARCH_LOG(" handle: %d\n", device->handle); - RARCH_LOG(" physical_device_inst: %d\n", device->physical_device_inst); + RARCH_LOG(" physical_device_inst: %d\n", device->physicalDeviceInst); RARCH_LOG(" vid: 0x%04x\n", SWAP_IF_BIG(device->vid)); RARCH_LOG(" pid: 0x%04x\n", SWAP_IF_BIG(device->pid)); - RARCH_LOG(" interface_index: %d\n", device->interface_index); - RARCH_LOG(" sub_class: %d\n", device->sub_class); + RARCH_LOG(" interface_index: %d\n", device->interfaceIndex); + RARCH_LOG(" sub_class: %d\n", device->subClass); RARCH_LOG(" protocol: %d\n", device->protocol); - RARCH_LOG(" max_packet_size_rx: %d\n", device->max_packet_size_rx); - RARCH_LOG(" max_packet_size_tx: %d\n", device->max_packet_size_tx); + RARCH_LOG(" max_packet_size_rx: %d\n", device->maxPacketSizeRx); + RARCH_LOG(" max_packet_size_tx: %d\n", device->maxPacketSizeTx); } static void wiiu_hid_get_device_name(HIDDevice *device, wiiu_attach_event *event) @@ -546,13 +549,13 @@ static wiiu_attach_event *wiiu_hid_new_attach_event(HIDDevice *device) event->handle = device->handle; event->vendor_id = device->vid; event->product_id = device->pid; - event->interface_index = device->interface_index; - event->is_keyboard = (device->sub_class == 1 + event->interface_index = device->interfaceIndex; + event->is_keyboard = (device->subClass == 1 && device->protocol == 1); - event->is_mouse = (device->sub_class == 1 + event->is_mouse = (device->subClass == 1 && device->protocol == 2); - event->max_packet_size_rx = device->max_packet_size_rx; - event->max_packet_size_tx = device->max_packet_size_tx; + event->max_packet_size_rx = device->maxPacketSizeRx; + event->max_packet_size_tx = device->maxPacketSizeTx; wiiu_hid_get_device_name(device, event); return event; @@ -832,6 +835,7 @@ static int32_t wiiu_hid_set_idle(void *data, uint8_t duration) return HIDSetIdle(adapter->handle, adapter->interface_index, + 0, // reportId? duration, NULL, NULL); } diff --git a/input/drivers_joypad/wiiu/kpad_driver.c b/input/drivers_joypad/wiiu/kpad_driver.c index a5c9da957b3e..8d7629a5a07a 100644 --- a/input/drivers_joypad/wiiu/kpad_driver.c +++ b/input/drivers_joypad/wiiu/kpad_driver.c @@ -173,37 +173,37 @@ static void kpad_register(unsigned channel, uint8_t device_type) } } -static void kpad_poll_one_channel(unsigned channel, KPADData *kpad) +static void kpad_poll_one_channel(unsigned channel, KPADStatus *kpad) { - kpad_register(channel, kpad->device_type); - switch (kpad->device_type) + kpad_register(channel, kpad->extensionType); + switch (kpad->extensionType) { case WIIMOTE_TYPE_PRO: - joypad_state.kpad.wiimotes[channel].button_state = kpad->classic.btns_h + joypad_state.kpad.wiimotes[channel].button_state = kpad->classic.hold & ~WIIU_PRO_BUTTON_MASK; pad_functions.set_axis_value(joypad_state.kpad.wiimotes[channel].analog_state, - WIIU_READ_STICK(kpad->classic.lstick_x), - WIIU_READ_STICK(kpad->classic.lstick_y), - WIIU_READ_STICK(kpad->classic.rstick_x), - WIIU_READ_STICK(kpad->classic.rstick_y), 0, 0); + WIIU_READ_STICK(kpad->classic.leftStick.x), + WIIU_READ_STICK(kpad->classic.leftStick.y), + WIIU_READ_STICK(kpad->classic.rightStick.x), + WIIU_READ_STICK(kpad->classic.rightStick.y), 0, 0); break; case WIIMOTE_TYPE_CLASSIC: - joypad_state.kpad.wiimotes[channel].button_state = kpad->classic.btns_h + joypad_state.kpad.wiimotes[channel].button_state = kpad->classic.hold & ~CLASSIC_BUTTON_MASK; pad_functions.set_axis_value(joypad_state.kpad.wiimotes[channel].analog_state, - WIIU_READ_STICK(kpad->classic.lstick_x), - WIIU_READ_STICK(kpad->classic.lstick_y), - WIIU_READ_STICK(kpad->classic.rstick_x), - WIIU_READ_STICK(kpad->classic.rstick_y), 0, 0); + WIIU_READ_STICK(kpad->classic.leftStick.x), + WIIU_READ_STICK(kpad->classic.leftStick.y), + WIIU_READ_STICK(kpad->classic.rightStick.x), + WIIU_READ_STICK(kpad->classic.rightStick.y), 0, 0); break; case WIIMOTE_TYPE_NUNCHUK: - joypad_state.kpad.wiimotes[channel].button_state = kpad->btns_h; + joypad_state.kpad.wiimotes[channel].button_state = kpad->hold; pad_functions.set_axis_value(joypad_state.kpad.wiimotes[channel].analog_state, - WIIU_READ_STICK(kpad->nunchuck.stick_x), - WIIU_READ_STICK(kpad->nunchuck.stick_y), 0, 0, 0, 0); + WIIU_READ_STICK(kpad->nunchuck.stick.x), + WIIU_READ_STICK(kpad->nunchuck.stick.y), 0, 0, 0, 0); break; case WIIMOTE_TYPE_WIIPLUS: - joypad_state.kpad.wiimotes[channel].button_state = kpad->btns_h; + joypad_state.kpad.wiimotes[channel].button_state = kpad->hold; pad_functions.set_axis_value(joypad_state.kpad.wiimotes[channel].analog_state, 0, 0, 0, 0, 0, 0); break; @@ -226,7 +226,7 @@ static void kpad_deregister(unsigned channel) static void kpad_poll(void) { - KPADData kpad; + KPADStatus kpad; unsigned channel; int32_t result = 0; @@ -248,7 +248,7 @@ static void kpad_poll(void) /* Several reads when a device is connected or an attachment added give */ /* bogus results, try to weed them out */ - if (kpad.wpad_error || kpad.device_type == 255) + if (kpad.error || kpad.extensionType == 255) continue; kpad_poll_one_channel(channel, &kpad); diff --git a/input/drivers_joypad/wiiu_joypad.c b/input/drivers_joypad/wiiu_joypad.c index 6c4c972159e5..8adf4083f547 100644 --- a/input/drivers_joypad/wiiu_joypad.c +++ b/input/drivers_joypad/wiiu_joypad.c @@ -17,6 +17,7 @@ #include "../include/wiiu/input.h" static bool ready = false; +const hid_driver_t *hid_driver; wiiu_joypad_t joypad_state = {0}; @@ -25,7 +26,7 @@ static void *wiiu_joypad_init(void *data) memset(&joypad_state, 0, sizeof(wiiu_joypad_t)); joypad_state.pads[MAX_USERS].data = (void *)0xdeadbeef; joypad_state.max_slot = MAX_USERS; - input_hid_init_first(); + hid_driver = input_hid_init_first(); wpad_driver.init(data); kpad_driver.init(data); @@ -50,6 +51,12 @@ static void wiiu_joypad_destroy(void) wpad_driver.destroy(); kpad_driver.destroy(); hidpad_driver.destroy(); + + if(hid_driver) { + hid_driver->free((void *)hid_driver_get_data()); + hid_driver_reset_data(); + hid_driver = NULL; + } } static int32_t wiiu_joypad_button(unsigned port, uint16_t joykey) diff --git a/input/include/wiiu/hid.h b/input/include/wiiu/hid.h index f4833c7c3bb1..5767f8f522da 100644 --- a/input/include/wiiu/hid.h +++ b/input/include/wiiu/hid.h @@ -19,6 +19,9 @@ #include "hid_types.h" #include "input.h" +#include +#include +#include #define DEVICE_UNUSED 0 #define DEVICE_USED 1 diff --git a/input/include/wiiu/input.h b/input/include/wiiu/input.h index e0c36d2b9edf..bae638795908 100644 --- a/input/include/wiiu/input.h +++ b/input/include/wiiu/input.h @@ -24,12 +24,12 @@ #include "hid_types.h" #include "../gamepad.h" -#include -#include #include -#include #include +#include +#include + #include "../../connect/joypad_connection.h" #include "../../../retroarch.h" #include "../../../verbosity.h" diff --git a/input/input_autodetect_builtin.c b/input/input_autodetect_builtin.c index d2e59efbfa71..a4cbff38d503 100644 --- a/input/input_autodetect_builtin.c +++ b/input/input_autodetect_builtin.c @@ -350,7 +350,6 @@ DECL_AXIS_EX(r_y_plus, +3, "C-stick up") \ DECL_AXIS_EX(r_y_minus, -3, "C-stick down") #define WIIUINPUT_DS3_DEFAULT_BINDS \ -DECL_BTN_EX(menu_toggle, 16, "Playstation") \ DECL_BTN_EX(select, 2, "Select") \ DECL_BTN_EX(start, 3, "Start") \ DECL_BTN_EX(a, 8, "Circle") \ @@ -377,7 +376,6 @@ DECL_AXIS_EX(r_y_plus, +3, "R Analog up") \ DECL_AXIS_EX(r_y_minus, -3, "R Analog down") #define WIIUINPUT_GAMEPAD_DEFAULT_BINDS \ -DECL_BTN_EX(menu_toggle, 1, "Home") \ DECL_BTN_EX(select, 2, "-") \ DECL_BTN_EX(start, 3, "+") \ DECL_BTN_EX(r, 4, "R") \ @@ -414,7 +412,6 @@ DECL_BTN_EX(b, 6, "B") \ DECL_BTN_EX(l2, 7, "ZL") \ DECL_BTN_EX(r, 9, "R") \ DECL_BTN_EX(start, 10, "+") \ -DECL_BTN_EX(menu_toggle, 11, "Home") \ DECL_BTN_EX(select, 12, "-") \ DECL_BTN_EX(l, 13, "L") \ DECL_BTN_EX(down, 14, "D-Pad Down") \ @@ -441,7 +438,6 @@ DECL_BTN_EX(b, 6, "B") \ DECL_BTN_EX(l2, 7, "ZL") \ DECL_BTN_EX(r, 9, "R") \ DECL_BTN_EX(start, 10, "+") \ -DECL_BTN_EX(menu_toggle, 11, "Home") \ DECL_BTN_EX(select, 12, "-") \ DECL_BTN_EX(l, 13, "L") \ DECL_BTN_EX(down, 14, "D-Pad Down") \ @@ -468,7 +464,6 @@ DECL_BTN_EX(y, 11, "A") \ DECL_BTN_EX(select, 12, "-") \ DECL_BTN_EX(l, 13, "Z") \ DECL_BTN_EX(r, 14, "C") \ -DECL_BTN_EX(menu_toggle, 15, "Home") #define WIIUINPUT_NUNCHUK_DEFAULT_BINDS \ DECL_BTN_EX(left, 0, "D-Pad Left") \ @@ -483,7 +478,6 @@ DECL_BTN_EX(a, 11, "A") \ DECL_BTN_EX(select, 12, "-") \ DECL_BTN_EX(l, 13, "Z") \ DECL_BTN_EX(r, 14, "C") \ -DECL_BTN_EX(menu_toggle, 15, "Home") \ DECL_AXIS_EX(l_x_plus, +0, "Stick Right") \ DECL_AXIS_EX(l_x_minus, -0, "Stick Left") \ DECL_AXIS_EX(l_y_minus, +1, "Stick Up") \ diff --git a/intl/msg_hash_lbl.h b/intl/msg_hash_lbl.h index 2a7731689923..8fcdbb87e860 100644 --- a/intl/msg_hash_lbl.h +++ b/intl/msg_hash_lbl.h @@ -1852,6 +1852,12 @@ MSG_HASH( "input_android_physical_keyboard" ) #endif +#ifdef WIIU +MSG_HASH( + MENU_ENUM_LABEL_INPUT_WIIU_ENABLE_HBM, + "input_wiiu_enable_hbm" + ) +#endif MSG_HASH( MENU_ENUM_LABEL_INPUT_SENSORS_ENABLE, "input_sensors_enable" diff --git a/intl/msg_hash_us.h b/intl/msg_hash_us.h index 887a643c0133..6ef06e641148 100644 --- a/intl/msg_hash_us.h +++ b/intl/msg_hash_us.h @@ -3613,6 +3613,16 @@ MSG_HASH( MENU_ENUM_SUBLABEL_INPUT_ALL_USERS_CONTROL_MENU, "Allow any user to control the menu. If disabled, only User 1 can control the menu." ) +#ifdef WIIU +MSG_HASH( + MENU_ENUM_LABEL_VALUE_INPUT_WIIU_ENABLE_HBM, + "Allow Wii U HOME menu" + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_INPUT_WIIU_ENABLE_HBM, + "Enable the Wii U's HOME menu overlay. If disabled, the Home button toggles the RetroArch menu." + ) +#endif /* Settings > Input > Hotkeys */ diff --git a/libretro-common/features/features_cpu.c b/libretro-common/features/features_cpu.c index 98b85024d9db..cad2e193d043 100644 --- a/libretro-common/features/features_cpu.c +++ b/libretro-common/features/features_cpu.c @@ -92,7 +92,7 @@ #endif #ifdef WIIU -#include +#include #endif #if defined(HAVE_LIBNX) @@ -231,7 +231,7 @@ retro_time_t cpu_features_get_time_usec(void) #elif defined(GEKKO) return ticks_to_microsecs(gettime()); #elif defined(WIIU) - return ticks_to_us(OSGetSystemTime()); + return OSTicksToMicroseconds(OSGetSystemTime()); #elif defined(SWITCH) || defined(HAVE_LIBNX) return (svcGetSystemTick() * 10) / 192; #elif defined(_3DS) diff --git a/libretro-common/include/net/net_compat.h b/libretro-common/include/net/net_compat.h index 05970a79d1ba..079f310207e6 100644 --- a/libretro-common/include/net/net_compat.h +++ b/libretro-common/include/net/net_compat.h @@ -350,8 +350,6 @@ static INLINE bool isagain(int val) return (sys_net_errno == SYS_NET_EAGAIN) || (sys_net_errno == SYS_NET_EWOULDBLOCK); #elif defined(VITA) return (val == SCE_NET_ERROR_EAGAIN) || (val == SCE_NET_ERROR_EWOULDBLOCK); -#elif defined(WIIU) - return (val == -1) && (socketlasterr() == SO_SUCCESS || socketlasterr() == SO_EWOULDBLOCK); #elif defined(GEKKO) return (-val == EAGAIN); #else @@ -367,8 +365,6 @@ static INLINE bool isinprogress(int val) return (sys_net_errno == SYS_NET_EINPROGRESS); #elif defined(VITA) return (val == SCE_NET_ERROR_EINPROGRESS); -#elif defined(WIIU) - return (val == -1) && (socketlasterr() == SO_EINPROGRESS); #elif defined(GEKKO) return (-val == EINPROGRESS); #else diff --git a/libretro-common/include/retro_timers.h b/libretro-common/include/retro_timers.h index 96041255a3f1..2efe851b10eb 100644 --- a/libretro-common/include/retro_timers.h +++ b/libretro-common/include/retro_timers.h @@ -32,7 +32,7 @@ #elif defined(GEKKO) || defined(__PSL1GHT__) || defined(__QNX__) #include #elif defined(WIIU) -#include +#include #elif defined(PSP) #include #elif defined(VITA) @@ -99,7 +99,7 @@ static int nanosleepDOS(const struct timespec *rqtp, struct timespec *rmtp) #elif defined(GEKKO) || defined(__PSL1GHT__) || defined(__QNX__) #define retro_sleep(msec) (usleep(1000 * (msec))) #elif defined(WIIU) -#define retro_sleep(msec) (OSSleepTicks(ms_to_ticks((msec)))) +#define retro_sleep(msec) (OSSleepTicks(OSMillisecondsToTicks((msec)))) #elif defined(EMSCRIPTEN) #define retro_sleep(msec) (emscripten_sleep(msec)) #else diff --git a/libretro-common/net/net_compat.c b/libretro-common/net/net_compat.c index e291bbee90c2..d1becb5753f9 100644 --- a/libretro-common/net/net_compat.c +++ b/libretro-common/net/net_compat.c @@ -233,28 +233,6 @@ int inet_pton(int af, const char *src, void *dst) return 0; } -#elif defined(WIIU) -#include - -static int _net_compat_thread_entry(int argc, const char **argv) -{ - void *buf = memalign(128, WIIU_RCVBUF + WIIU_SNDBUF); - - if (!buf) - return -1; - - somemopt(1, buf, WIIU_RCVBUF + WIIU_SNDBUF, 0); - - free(buf); - - return 0; -} - -static void _net_compat_thread_cleanup(OSThread *thread, void *stack) -{ - free(stack); -} - #elif defined(_3DS) #include #include <3ds/types.h> @@ -568,36 +546,6 @@ bool network_init(void) initialized = true; } - return true; -#elif defined(WIIU) - static OSThread net_compat_thread; - static bool initialized = false; - - if (!initialized) - { - void *stack = malloc(0x1000); - - if (!stack) - return false; - - socket_lib_init(); - - if (!OSCreateThread(&net_compat_thread, _net_compat_thread_entry, - 0, NULL, (void*)((size_t)stack + 0x1000), 0x1000, 3, - OS_THREAD_ATTRIB_AFFINITY_ANY)) - { - free(stack); - - return false; - } - - OSSetThreadName(&net_compat_thread, "Network compat thread"); - OSSetThreadDeallocator(&net_compat_thread, _net_compat_thread_cleanup); - OSResumeThread(&net_compat_thread); - - initialized = true; - } - return true; #elif defined(_3DS) static bool initialized = false; diff --git a/libretro-common/net/net_socket.c b/libretro-common/net/net_socket.c index 039a0b670ed5..50308fedc386 100644 --- a/libretro-common/net/net_socket.c +++ b/libretro-common/net/net_socket.c @@ -212,7 +212,7 @@ int socket_close(int fd) #if defined(_WIN32) && !defined(_XBOX360) /* WinSock has headers from the stone age. */ return closesocket(fd); -#elif defined(__PS3__) || defined(WIIU) +#elif defined(__PS3__) return socketclose(fd); #elif defined(VITA) return sceNetSocketClose(fd); @@ -691,25 +691,6 @@ int socket_connect(int fd, void *data) { struct addrinfo *addr = (struct addrinfo*)data; -#ifdef WIIU - { - int op = 1; - - setsockopt(fd, SOL_SOCKET, SO_WINSCALE, &op, sizeof(op)); - - if (addr->ai_socktype == SOCK_STREAM) - { - int recvsz = WIIU_RCVBUF; - int sendsz = WIIU_SNDBUF; - - setsockopt(fd, SOL_SOCKET, SO_TCPSACK, &op, sizeof(op)); - setsockopt(fd, SOL_SOCKET, SO_RUSRBUF, &op, sizeof(op)); - setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &recvsz, sizeof(recvsz)); - setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &sendsz, sizeof(sendsz)); - } - } -#endif - return connect(fd, addr->ai_addr, addr->ai_addrlen); } @@ -721,25 +702,6 @@ bool socket_connect_with_timeout(int fd, void *data, int timeout) if (!socket_nonblock(fd)) return false; -#ifdef WIIU - { - int op = 1; - - setsockopt(fd, SOL_SOCKET, SO_WINSCALE, &op, sizeof(op)); - - if (addr->ai_socktype == SOCK_STREAM) - { - int recvsz = WIIU_RCVBUF; - int sendsz = WIIU_SNDBUF; - - setsockopt(fd, SOL_SOCKET, SO_TCPSACK, &op, sizeof(op)); - setsockopt(fd, SOL_SOCKET, SO_RUSRBUF, &op, sizeof(op)); - setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &recvsz, sizeof(recvsz)); - setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &sendsz, sizeof(sendsz)); - } - } -#endif - res = connect(fd, addr->ai_addr, addr->ai_addrlen); if (res) { @@ -764,12 +726,6 @@ bool socket_connect_with_timeout(int fd, void *data, int timeout) /* libctru getsockopt does not return expected value */ if ((connect(fd, addr->ai_addr, addr->ai_addrlen) < 0) && errno != EISCONN) return false; -#elif defined(WIIU) - /* On WiiU, getsockopt() returns -1 and sets lastsocketerr() (Wii's - * equivalent to errno) to 16. */ - if ((connect(fd, addr->ai_addr, addr->ai_addrlen) == -1) - && socketlasterr() != SO_EISCONN) - return false; #else { int error = -1; diff --git a/libretro-common/vfs/vfs_implementation.c b/libretro-common/vfs/vfs_implementation.c index e98a27db696a..e70c5e4e6cdd 100644 --- a/libretro-common/vfs/vfs_implementation.c +++ b/libretro-common/vfs/vfs_implementation.c @@ -475,9 +475,6 @@ libretro_vfs_implementation_file *retro_vfs_file_open_impl( stream->buf = (char*)memalign(0x40, bufsize); if (stream->fp) setvbuf(stream->fp, stream->buf, _IOFBF, bufsize); - stream->buf = (char*)calloc(1, 0x4000); - if (stream->fp) - setvbuf(stream->fp, stream->buf, _IOFBF, 0x4000); } #endif } diff --git a/menu/cbs/menu_cbs_sublabel.c b/menu/cbs/menu_cbs_sublabel.c index a2a3a7f9b073..34238fc62a72 100644 --- a/menu/cbs/menu_cbs_sublabel.c +++ b/menu/cbs/menu_cbs_sublabel.c @@ -534,6 +534,9 @@ DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_location_allow, MENU_ DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_input_max_users, MENU_ENUM_SUBLABEL_INPUT_MAX_USERS) DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_input_poll_type_behavior, MENU_ENUM_SUBLABEL_INPUT_POLL_TYPE_BEHAVIOR) DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_input_all_users_control_menu, MENU_ENUM_SUBLABEL_INPUT_ALL_USERS_CONTROL_MENU) +#ifdef WIIU +DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_input_wiiu_enable_hbm, MENU_ENUM_SUBLABEL_INPUT_WIIU_ENABLE_HBM) +#endif DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_input_bind_timeout, MENU_ENUM_SUBLABEL_INPUT_BIND_TIMEOUT) DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_input_bind_hold, MENU_ENUM_SUBLABEL_INPUT_BIND_HOLD) DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_audio_volume, MENU_ENUM_SUBLABEL_AUDIO_VOLUME) @@ -4597,6 +4600,11 @@ int menu_cbs_init_bind_sublabel(menu_file_list_cbs_t *cbs, case MENU_ENUM_LABEL_INPUT_ALL_USERS_CONTROL_MENU: BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_input_all_users_control_menu); break; +#ifdef WIIU + case MENU_ENUM_LABEL_INPUT_WIIU_ENABLE_HBM: + BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_input_wiiu_enable_hbm); + break; +#endif case MENU_ENUM_LABEL_INPUT_POLL_TYPE_BEHAVIOR: BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_input_poll_type_behavior); break; diff --git a/menu/menu_displaylist.c b/menu/menu_displaylist.c index 8f006cad5b24..879529054bff 100644 --- a/menu/menu_displaylist.c +++ b/menu/menu_displaylist.c @@ -7839,6 +7839,9 @@ unsigned menu_displaylist_build_list( {MENU_ENUM_LABEL_MENU_INPUT_SWAP_OK_CANCEL, PARSE_ONLY_BOOL, true }, {MENU_ENUM_LABEL_MENU_INPUT_SWAP_SCROLL, PARSE_ONLY_BOOL, true }, {MENU_ENUM_LABEL_INPUT_ALL_USERS_CONTROL_MENU, PARSE_ONLY_BOOL, true }, +#ifdef WIIU + {MENU_ENUM_LABEL_INPUT_WIIU_ENABLE_HBM, PARSE_ONLY_BOOL, true }, +#endif {MENU_ENUM_LABEL_MENU_SCROLL_FAST, PARSE_ONLY_BOOL, true }, {MENU_ENUM_LABEL_MENU_SCROLL_DELAY, PARSE_ONLY_UINT, true }, {MENU_ENUM_LABEL_INPUT_DISABLE_INFO_BUTTON, PARSE_ONLY_BOOL, true }, diff --git a/menu/menu_driver.c b/menu/menu_driver.c index 569bfe757f8e..9c20c858c2e2 100644 --- a/menu/menu_driver.c +++ b/menu/menu_driver.c @@ -1,8084 +1,8084 @@ -/* RetroArch - A frontend for libretro. - * Copyright (C) 2011-2021 - Daniel De Matteis - * Copyright (C) 2014-2017 - Jean-André Santoni - * Copyright (C) 2016-2019 - Andrés Suárez - * Copyright (C) 2016-2019 - Brad Parker - * - * RetroArch 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 Found- - * ation, either version 3 of the License, or (at your option) any later version. - * - * RetroArch 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 RetroArch. - * If not, see . - */ - -#if defined(HAVE_CONFIG_H) -#include "../config.h" -#endif - -#include -#include -#include -#include -#include -#include -#include -#include