From 85bd3bb70e240cdecfb0c2c6c3694010b7e92efa Mon Sep 17 00:00:00 2001 From: Ash Logan Date: Fri, 5 Sep 2025 15:13:23 +1000 Subject: [PATCH 01/14] (WiiU) remove libiosuhax (for conversion to subtree) --- .../.github/workflows/push_image.yml | 25 - deps/libiosuhax/.gitignore | 5 - deps/libiosuhax/.travis.yml | 29 - deps/libiosuhax/Dockerfile | 9 - deps/libiosuhax/Makefile | 157 --- deps/libiosuhax/README.md | 10 - deps/libiosuhax/include/iosuhax.h | 112 -- deps/libiosuhax/include/iosuhax_devoptab.h | 42 - .../include/iosuhax_disc_interface.h | 73 -- deps/libiosuhax/source/iosuhax.c | 956 ----------------- deps/libiosuhax/source/iosuhax_devoptab.c | 993 ------------------ .../source/iosuhax_disc_interface.c | 262 ----- deps/libiosuhax/source/os_functions.h | 28 - 13 files changed, 2701 deletions(-) delete mode 100644 deps/libiosuhax/.github/workflows/push_image.yml delete mode 100644 deps/libiosuhax/.gitignore delete mode 100644 deps/libiosuhax/.travis.yml delete mode 100644 deps/libiosuhax/Dockerfile delete mode 100644 deps/libiosuhax/Makefile delete mode 100644 deps/libiosuhax/README.md delete mode 100644 deps/libiosuhax/include/iosuhax.h delete mode 100644 deps/libiosuhax/include/iosuhax_devoptab.h delete mode 100644 deps/libiosuhax/include/iosuhax_disc_interface.h delete mode 100644 deps/libiosuhax/source/iosuhax.c delete mode 100644 deps/libiosuhax/source/iosuhax_devoptab.c delete mode 100644 deps/libiosuhax/source/iosuhax_disc_interface.c delete mode 100644 deps/libiosuhax/source/os_functions.h 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/Dockerfile b/deps/libiosuhax/Dockerfile deleted file mode 100644 index 27aa8936e809..000000000000 --- a/deps/libiosuhax/Dockerfile +++ /dev/null @@ -1,9 +0,0 @@ -FROM wiiuenv/devkitppc:20210101 - -WORKDIR tmp_build -COPY . . -RUN make clean && make && mkdir -p /artifacts/wut/usr && cp -r lib /artifacts/wut/usr && cp -r include /artifacts/wut/usr -WORKDIR /artifacts - -FROM scratch -COPY --from=0 /artifacts /artifacts \ No newline at end of file diff --git a/deps/libiosuhax/Makefile b/deps/libiosuhax/Makefile deleted file mode 100644 index 03af789f3d7b..000000000000 --- a/deps/libiosuhax/Makefile +++ /dev/null @@ -1,157 +0,0 @@ -#------------------------------------------------------------------------------- -.SUFFIXES: -#------------------------------------------------------------------------------- - -ifeq ($(strip $(DEVKITPRO)),) -$(error "Please set DEVKITPRO in your environment. export DEVKITPRO=/devkitpro") -endif - -TOPDIR ?= $(CURDIR) - -include $(DEVKITPRO)/wut/share/wut_rules - -export VER_MAJOR := 1 -export VER_MINOR := 0 -export VER_PATCH := 0 - -VERSION := $(VER_MAJOR).$(VER_MINOR).$(VER_PATCH) - -#------------------------------------------------------------------------------- -# TARGET is the name of the output -# BUILD is the directory where object files & intermediate files will be placed -# SOURCES is a list of directories containing source code -# DATA is a list of directories containing data files -# INCLUDES is a list of directories containing header files -#------------------------------------------------------------------------------- -TARGET := $(notdir $(CURDIR)) -BUILD := build -SOURCES := source -DATA := data -INCLUDES := source \ - include \ - -#--------------------------------------------------------------------------------- -# options for code generation -#--------------------------------------------------------------------------------- -CFLAGS := -Wall -Werror -save-temps \ - -ffunction-sections -fdata-sections \ - $(MACHDEP) \ - $(BUILD_CFLAGS) - -CFLAGS += $(INCLUDE) -D__WIIU__ -D__WUT__ - -CXXFLAGS := $(CFLAGS) -std=gnu++17 - -ASFLAGS := $(MACHDEP) - -LDFLAGS = $(ARCH) -Wl,--gc-sections - - -LIBS := - -#--------------------------------------------------------------------------------- -# list of directories containing libraries, this must be the top level containing -# include and lib -#--------------------------------------------------------------------------------- -LIBDIRS := $(PORTLIBS) $(WUT_ROOT) - -#--------------------------------------------------------------------------------- -# no real need to edit anything past this point unless you need to add additional -# rules for different file extensions -#--------------------------------------------------------------------------------- -ifneq ($(BUILD),$(notdir $(CURDIR))) -#--------------------------------------------------------------------------------- - -export TOPDIR := $(CURDIR) - -export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \ - $(foreach dir,$(DATA),$(CURDIR)/$(dir)) - -CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) -CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) -SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) -DEFFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.def))) -BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) - -#--------------------------------------------------------------------------------- -# use CXX for linking C++ projects, CC for standard C -#--------------------------------------------------------------------------------- -ifeq ($(strip $(CPPFILES)),) -#--------------------------------------------------------------------------------- - export LD := $(CC) -#--------------------------------------------------------------------------------- -else -#--------------------------------------------------------------------------------- - export LD := $(CXX) -#--------------------------------------------------------------------------------- -endif -#--------------------------------------------------------------------------------- - -export OFILES_BIN := $(addsuffix .o,$(BINFILES)) -export OFILES_SRC := $(DEFFILES:.def=.o) $(SFILES:.s=.o) $(CFILES:.c=.o) $(CPPFILES:.cpp=.o) -export OFILES := $(OFILES_BIN) $(OFILES_SRC) -export HFILES := $(addsuffix .h,$(subst .,_,$(BINFILES))) - -export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \ - $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ - -I. - -.PHONY: all dist-bin dist-src dist install clean - -#--------------------------------------------------------------------------------- -all: lib/libiosuhax.a - -dist-bin: all - @tar --exclude=*~ -cjf libiosuhax-$(VERSION).tar.bz2 include lib - -dist-src: - @tar --exclude=*~ -cjf libiosuhax-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 - -lib: - @[ -d $@ ] || mkdir -p $@ - -release: - @[ -d $@ ] || mkdir -p $@ - -lib/libiosuhax.a :$(SOURCES) $(INCLUDES) | lib release - @$(MAKE) BUILD=release OUTPUT=$(CURDIR)/$@ \ - BUILD_CFLAGS="-DNDEBUG=1 -O2 -s" \ - DEPSDIR=$(CURDIR)/release \ - --no-print-directory -C release \ - -f $(CURDIR)/Makefile - -#--------------------------------------------------------------------------------- -clean: - @echo clean ... - @rm -rf release lib - -#--------------------------------------------------------------------------------- -else - -DEPENDS := $(OFILES:.o=.d) - -#--------------------------------------------------------------------------------- -# main targets -#--------------------------------------------------------------------------------- -$(OUTPUT) : $(OFILES) - -$(OFILES_SRC) : $(HFILES) - -#--------------------------------------------------------------------------------- -%_bin.h %.bin.o : %.bin -#--------------------------------------------------------------------------------- - @echo $(notdir $<) - @$(bin2o) - - --include $(DEPENDS) - -#--------------------------------------------------------------------------------------- -endif -#--------------------------------------------------------------------------------------- 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/include/iosuhax_disc_interface.h b/deps/libiosuhax/include/iosuhax_disc_interface.h deleted file mode 100644 index c5b703b7bc9f..000000000000 --- a/deps/libiosuhax/include/iosuhax_disc_interface.h +++ /dev/null @@ -1,73 +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 _IOSUHAX_DISC_INTERFACE_H_ -#define _IOSUHAX_DISC_INTERFACE_H_ - -#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 - -#ifndef OGC_DISC_IO_INCLUDE -typedef uint32_t sec_t; - -#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_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 ; -} ; - -typedef struct DISC_INTERFACE_STRUCT DISC_INTERFACE ; -#endif - -extern const DISC_INTERFACE IOSUHAX_sdio_disc_interface; -extern const DISC_INTERFACE IOSUHAX_usb_disc_interface; - -#ifdef __cplusplus -} -#endif - -#endif 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_ From 8ed79217adbe1f954641fee925fb90205b921c57 Mon Sep 17 00:00:00 2001 From: Ash Logan Date: Fri, 19 Sep 2025 20:02:53 +1000 Subject: [PATCH 02/14] Squashed 'deps/libmocha/' content from commit 89438aa9f3 git-subtree-dir: deps/libmocha git-subtree-split: 89438aa9f3a9d471ff848422f9dc3db581726127 --- .clang-format | 67 +++ .github/workflows/pr.yml | 25 ++ .github/workflows/push_image.yml | 43 ++ .gitignore | 9 + Dockerfile | 9 + Dockerfile.buildlocal | 3 + LICENSE | 155 +++++++ Makefile | 158 +++++++ README.md | 27 ++ include/mocha/commands.h | 30 ++ include/mocha/disc_interface.h | 74 ++++ include/mocha/fsa.h | 100 +++++ include/mocha/mocha.h | 307 +++++++++++++ include/mocha/otp.h | 193 ++++++++ source/devoptab/MutexWrapper.h | 25 ++ source/devoptab/devoptab_fsa.cpp | 205 +++++++++ source/devoptab/devoptab_fsa.h | 118 +++++ source/devoptab/devoptab_fsa_chdir.cpp | 31 ++ source/devoptab/devoptab_fsa_chmod.cpp | 36 ++ source/devoptab/devoptab_fsa_close.cpp | 29 ++ source/devoptab/devoptab_fsa_dirclose.cpp | 28 ++ source/devoptab/devoptab_fsa_dirnext.cpp | 39 ++ source/devoptab/devoptab_fsa_diropen.cpp | 41 ++ source/devoptab/devoptab_fsa_dirreset.cpp | 28 ++ source/devoptab/devoptab_fsa_fchmod.cpp | 11 + source/devoptab/devoptab_fsa_fstat.cpp | 32 ++ source/devoptab/devoptab_fsa_fsync.cpp | 28 ++ source/devoptab/devoptab_fsa_link.cpp | 8 + source/devoptab/devoptab_fsa_mkdir.cpp | 37 ++ source/devoptab/devoptab_fsa_open.cpp | 144 ++++++ source/devoptab/devoptab_fsa_read.cpp | 79 ++++ source/devoptab/devoptab_fsa_rename.cpp | 44 ++ source/devoptab/devoptab_fsa_rmdir.cpp | 34 ++ source/devoptab/devoptab_fsa_seek.cpp | 77 ++++ source/devoptab/devoptab_fsa_stat.cpp | 36 ++ source/devoptab/devoptab_fsa_statvfs.cpp | 51 +++ source/devoptab/devoptab_fsa_truncate.cpp | 39 ++ source/devoptab/devoptab_fsa_unlink.cpp | 34 ++ source/devoptab/devoptab_fsa_utils.cpp | 194 +++++++++ source/devoptab/devoptab_fsa_utimes.cpp | 8 + source/devoptab/devoptab_fsa_write.cpp | 84 ++++ source/disc_interface.c | 236 ++++++++++ source/fsa.cpp | 193 ++++++++ source/logger.h | 23 + source/utils.cpp | 509 ++++++++++++++++++++++ source/utils.h | 12 + 46 files changed, 3693 insertions(+) create mode 100644 .clang-format create mode 100644 .github/workflows/pr.yml create mode 100644 .github/workflows/push_image.yml create mode 100644 .gitignore create mode 100644 Dockerfile create mode 100644 Dockerfile.buildlocal create mode 100644 LICENSE create mode 100644 Makefile create mode 100644 README.md create mode 100644 include/mocha/commands.h create mode 100644 include/mocha/disc_interface.h create mode 100644 include/mocha/fsa.h create mode 100644 include/mocha/mocha.h create mode 100644 include/mocha/otp.h create mode 100644 source/devoptab/MutexWrapper.h create mode 100644 source/devoptab/devoptab_fsa.cpp create mode 100644 source/devoptab/devoptab_fsa.h create mode 100644 source/devoptab/devoptab_fsa_chdir.cpp create mode 100644 source/devoptab/devoptab_fsa_chmod.cpp create mode 100644 source/devoptab/devoptab_fsa_close.cpp create mode 100644 source/devoptab/devoptab_fsa_dirclose.cpp create mode 100644 source/devoptab/devoptab_fsa_dirnext.cpp create mode 100644 source/devoptab/devoptab_fsa_diropen.cpp create mode 100644 source/devoptab/devoptab_fsa_dirreset.cpp create mode 100644 source/devoptab/devoptab_fsa_fchmod.cpp create mode 100644 source/devoptab/devoptab_fsa_fstat.cpp create mode 100644 source/devoptab/devoptab_fsa_fsync.cpp create mode 100644 source/devoptab/devoptab_fsa_link.cpp create mode 100644 source/devoptab/devoptab_fsa_mkdir.cpp create mode 100644 source/devoptab/devoptab_fsa_open.cpp create mode 100644 source/devoptab/devoptab_fsa_read.cpp create mode 100644 source/devoptab/devoptab_fsa_rename.cpp create mode 100644 source/devoptab/devoptab_fsa_rmdir.cpp create mode 100644 source/devoptab/devoptab_fsa_seek.cpp create mode 100644 source/devoptab/devoptab_fsa_stat.cpp create mode 100644 source/devoptab/devoptab_fsa_statvfs.cpp create mode 100644 source/devoptab/devoptab_fsa_truncate.cpp create mode 100644 source/devoptab/devoptab_fsa_unlink.cpp create mode 100644 source/devoptab/devoptab_fsa_utils.cpp create mode 100644 source/devoptab/devoptab_fsa_utimes.cpp create mode 100644 source/devoptab/devoptab_fsa_write.cpp create mode 100644 source/disc_interface.c create mode 100644 source/fsa.cpp create mode 100644 source/logger.h create mode 100644 source/utils.cpp create mode 100644 source/utils.h diff --git a/.clang-format b/.clang-format new file mode 100644 index 000000000000..56cc68554a27 --- /dev/null +++ b/.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/.github/workflows/pr.yml b/.github/workflows/pr.yml new file mode 100644 index 000000000000..6636ab0158c9 --- /dev/null +++ b/.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/.github/workflows/push_image.yml b/.github/workflows/push_image.yml new file mode 100644 index 000000000000..a69fa5e8da12 --- /dev/null +++ b/.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/.gitignore b/.gitignore new file mode 100644 index 000000000000..6f6ace41c763 --- /dev/null +++ b/.gitignore @@ -0,0 +1,9 @@ +/*.a +/build +*.bz2 +release/ +lib/ +CMakeLists.txt +.idea/ +cmake-build-debug/ +share/ diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 000000000000..3421a87fc827 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,9 @@ +FROM ghcr.io/wiiu-env/devkitppc:20230621 + +WORKDIR tmp_build +COPY . . +RUN make clean && make && mkdir -p /artifacts/wut/usr && cp -r lib /artifacts/wut/usr && cp -r include /artifacts/wut/usr +WORKDIR /artifacts + +FROM scratch +COPY --from=0 /artifacts /artifacts \ No newline at end of file diff --git a/Dockerfile.buildlocal b/Dockerfile.buildlocal new file mode 100644 index 000000000000..2c6958560339 --- /dev/null +++ b/Dockerfile.buildlocal @@ -0,0 +1,3 @@ +FROM ghcr.io/wiiu-env/devkitppc:20230621 + +WORKDIR project \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 000000000000..57e7a5350ad1 --- /dev/null +++ b/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/Makefile b/Makefile new file mode 100644 index 000000000000..2c9fcb20968b --- /dev/null +++ b/Makefile @@ -0,0 +1,158 @@ +#------------------------------------------------------------------------------- +.SUFFIXES: +#------------------------------------------------------------------------------- + +ifeq ($(strip $(DEVKITPRO)),) +$(error "Please set DEVKITPRO in your environment. export DEVKITPRO=/devkitpro") +endif + +TOPDIR ?= $(CURDIR) + +include $(DEVKITPRO)/wut/share/wut_rules + +export VER_MAJOR := 1 +export VER_MINOR := 0 +export VER_PATCH := 0 + +VERSION := $(VER_MAJOR).$(VER_MINOR).$(VER_PATCH) + +#------------------------------------------------------------------------------- +# TARGET is the name of the output +# BUILD is the directory where object files & intermediate files will be placed +# SOURCES is a list of directories containing source code +# DATA is a list of directories containing data files +# INCLUDES is a list of directories containing header files +#------------------------------------------------------------------------------- +TARGET := $(notdir $(CURDIR)) +BUILD := build +SOURCES := source \ + source/devoptab +DATA := data +INCLUDES := source \ + include \ + +#--------------------------------------------------------------------------------- +# options for code generation +#--------------------------------------------------------------------------------- +CFLAGS := -Wall -Werror -save-temps \ + -ffunction-sections -fdata-sections \ + $(MACHDEP) \ + $(BUILD_CFLAGS) + +CFLAGS += $(INCLUDE) -D__WIIU__ -D__WUT__ -fno-exceptions + +CXXFLAGS := $(CFLAGS) -std=gnu++20 + +ASFLAGS := $(MACHDEP) + +LDFLAGS = $(ARCH) -Wl,--gc-sections + + +LIBS := + +#--------------------------------------------------------------------------------- +# list of directories containing libraries, this must be the top level containing +# include and lib +#--------------------------------------------------------------------------------- +LIBDIRS := $(PORTLIBS) $(WUT_ROOT) + +#--------------------------------------------------------------------------------- +# no real need to edit anything past this point unless you need to add additional +# rules for different file extensions +#--------------------------------------------------------------------------------- +ifneq ($(BUILD),$(notdir $(CURDIR))) +#--------------------------------------------------------------------------------- + +export TOPDIR := $(CURDIR) + +export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \ + $(foreach dir,$(DATA),$(CURDIR)/$(dir)) + +CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) +CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) +SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) +DEFFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.def))) +BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) + +#--------------------------------------------------------------------------------- +# use CXX for linking C++ projects, CC for standard C +#--------------------------------------------------------------------------------- +ifeq ($(strip $(CPPFILES)),) +#--------------------------------------------------------------------------------- + export LD := $(CC) +#--------------------------------------------------------------------------------- +else +#--------------------------------------------------------------------------------- + export LD := $(CXX) +#--------------------------------------------------------------------------------- +endif +#--------------------------------------------------------------------------------- + +export OFILES_BIN := $(addsuffix .o,$(BINFILES)) +export OFILES_SRC := $(DEFFILES:.def=.o) $(SFILES:.s=.o) $(CFILES:.c=.o) $(CPPFILES:.cpp=.o) +export OFILES := $(OFILES_BIN) $(OFILES_SRC) +export HFILES := $(addsuffix .h,$(subst .,_,$(BINFILES))) + +export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \ + $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ + -I. + +.PHONY: all dist-bin dist-src dist install clean + +#--------------------------------------------------------------------------------- +all: lib/libmocha.a + +dist-bin: all + @tar --exclude=*~ -cjf libmocha-$(VERSION).tar.bz2 include lib + +dist-src: + @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 libmocha-$(VERSION).tar.bz2 | tar -xf - -C $(DESTDIR)$(DEVKITPRO)/wut/usr + +lib: + @[ -d $@ ] || mkdir -p $@ + +release: + @[ -d $@ ] || mkdir -p $@ + +lib/libmocha.a :$(SOURCES) $(INCLUDES) | lib release + @$(MAKE) BUILD=release OUTPUT=$(CURDIR)/$@ \ + BUILD_CFLAGS="-DNDEBUG=1 -O2 -s" \ + DEPSDIR=$(CURDIR)/release \ + --no-print-directory -C release \ + -f $(CURDIR)/Makefile + +#--------------------------------------------------------------------------------- +clean: + @echo clean ... + @rm -rf release lib + +#--------------------------------------------------------------------------------- +else + +DEPENDS := $(OFILES:.o=.d) + +#--------------------------------------------------------------------------------- +# main targets +#--------------------------------------------------------------------------------- +$(OUTPUT) : $(OFILES) + +$(OFILES_SRC) : $(HFILES) + +#--------------------------------------------------------------------------------- +%_bin.h %.bin.o : %.bin +#--------------------------------------------------------------------------------- + @echo $(notdir $<) + @$(bin2o) + + +-include $(DEPENDS) + +#--------------------------------------------------------------------------------------- +endif +#--------------------------------------------------------------------------------------- diff --git a/README.md b/README.md new file mode 100644 index 000000000000..a69acf783190 --- /dev/null +++ b/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/include/mocha/commands.h b/include/mocha/commands.h new file mode 100644 index 000000000000..ed6e2756624f --- /dev/null +++ b/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/include/mocha/disc_interface.h b/include/mocha/disc_interface.h new file mode 100644 index 000000000000..fd284814db65 --- /dev/null +++ b/include/mocha/disc_interface.h @@ -0,0 +1,74 @@ +/*************************************************************************** + * 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. + ***************************************************************************/ +#pragma once + +#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 + +#ifndef OGC_DISC_IO_INCLUDE +typedef uint32_t sec_t; + +#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_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; +}; + +typedef struct DISC_INTERFACE_STRUCT DISC_INTERFACE; +#endif +extern const DISC_INTERFACE Mocha_sdio_disc_interface; +extern const DISC_INTERFACE Mocha_usb_disc_interface; + +#ifdef __cplusplus +} +#endif diff --git a/include/mocha/fsa.h b/include/mocha/fsa.h new file mode 100644 index 000000000000..076c59f1797e --- /dev/null +++ b/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/include/mocha/mocha.h b/include/mocha/mocha.h new file mode 100644 index 000000000000..da99d2eed129 --- /dev/null +++ b/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/include/mocha/otp.h b/include/mocha/otp.h new file mode 100644 index 000000000000..a876b847e05a --- /dev/null +++ b/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/source/devoptab/MutexWrapper.h b/source/devoptab/MutexWrapper.h new file mode 100644 index 000000000000..d3b079df7692 --- /dev/null +++ b/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/source/devoptab/devoptab_fsa.cpp b/source/devoptab/devoptab_fsa.cpp new file mode 100644 index 000000000000..35164914601c --- /dev/null +++ b/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, %p, %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/source/devoptab/devoptab_fsa.h b/source/devoptab/devoptab_fsa.h new file mode 100644 index 000000000000..2e3b7db1efe3 --- /dev/null +++ b/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/source/devoptab/devoptab_fsa_chdir.cpp b/source/devoptab/devoptab_fsa_chdir.cpp new file mode 100644 index 000000000000..8165bcebfc19 --- /dev/null +++ b/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/source/devoptab/devoptab_fsa_chmod.cpp b/source/devoptab/devoptab_fsa_chmod.cpp new file mode 100644 index 000000000000..73ddb7154644 --- /dev/null +++ b/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/source/devoptab/devoptab_fsa_close.cpp b/source/devoptab/devoptab_fsa_close.cpp new file mode 100644 index 000000000000..cc3783a1ffed --- /dev/null +++ b/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/source/devoptab/devoptab_fsa_dirclose.cpp b/source/devoptab/devoptab_fsa_dirclose.cpp new file mode 100644 index 000000000000..44ad08059703 --- /dev/null +++ b/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/source/devoptab/devoptab_fsa_dirnext.cpp b/source/devoptab/devoptab_fsa_dirnext.cpp new file mode 100644 index 000000000000..a087cb3d3847 --- /dev/null +++ b/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, %p) (%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/source/devoptab/devoptab_fsa_diropen.cpp b/source/devoptab/devoptab_fsa_diropen.cpp new file mode 100644 index 000000000000..f3c74bf4c782 --- /dev/null +++ b/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, %p) 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/source/devoptab/devoptab_fsa_dirreset.cpp b/source/devoptab/devoptab_fsa_dirreset.cpp new file mode 100644 index 000000000000..7fa348aa24e4 --- /dev/null +++ b/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/source/devoptab/devoptab_fsa_fchmod.cpp b/source/devoptab/devoptab_fsa_fchmod.cpp new file mode 100644 index 000000000000..e0bd6ec6eadc --- /dev/null +++ b/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/source/devoptab/devoptab_fsa_fstat.cpp b/source/devoptab/devoptab_fsa_fstat.cpp new file mode 100644 index 000000000000..f54d1e17888a --- /dev/null +++ b/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, %p) (%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/source/devoptab/devoptab_fsa_fsync.cpp b/source/devoptab/devoptab_fsa_fsync.cpp new file mode 100644 index 000000000000..38503911c855 --- /dev/null +++ b/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/source/devoptab/devoptab_fsa_link.cpp b/source/devoptab/devoptab_fsa_link.cpp new file mode 100644 index 000000000000..ce1697d56526 --- /dev/null +++ b/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/source/devoptab/devoptab_fsa_mkdir.cpp b/source/devoptab/devoptab_fsa_mkdir.cpp new file mode 100644 index 000000000000..467567d2cba4 --- /dev/null +++ b/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/source/devoptab/devoptab_fsa_open.cpp b/source/devoptab/devoptab_fsa_open.cpp new file mode 100644 index 000000000000..8870e859a834 --- /dev/null +++ b/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, %p) 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, %p) 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, %p) (%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) (%s) 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/source/devoptab/devoptab_fsa_read.cpp b/source/devoptab/devoptab_fsa_read.cpp new file mode 100644 index 000000000000..29e3355f38ca --- /dev/null +++ b/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, %p, 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/source/devoptab/devoptab_fsa_rename.cpp b/source/devoptab/devoptab_fsa_rename.cpp new file mode 100644 index 000000000000..b551f93b414f --- /dev/null +++ b/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/source/devoptab/devoptab_fsa_rmdir.cpp b/source/devoptab/devoptab_fsa_rmdir.cpp new file mode 100644 index 000000000000..31aa59b2a311 --- /dev/null +++ b/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/source/devoptab/devoptab_fsa_seek.cpp b/source/devoptab/devoptab_fsa_seek.cpp new file mode 100644 index 000000000000..65a7a6bdf169 --- /dev/null +++ b/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, %p) (%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/source/devoptab/devoptab_fsa_stat.cpp b/source/devoptab/devoptab_fsa_stat.cpp new file mode 100644 index 000000000000..eda59f1d024c --- /dev/null +++ b/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, %p) 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/source/devoptab/devoptab_fsa_statvfs.cpp b/source/devoptab/devoptab_fsa_statvfs.cpp new file mode 100644 index 000000000000..0906c05b1c9b --- /dev/null +++ b/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, %p) 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/source/devoptab/devoptab_fsa_truncate.cpp b/source/devoptab/devoptab_fsa_truncate.cpp new file mode 100644 index 000000000000..0f1bba36b3fc --- /dev/null +++ b/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%08llX) 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/source/devoptab/devoptab_fsa_unlink.cpp b/source/devoptab/devoptab_fsa_unlink.cpp new file mode 100644 index 000000000000..e55ec684e78e --- /dev/null +++ b/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/source/devoptab/devoptab_fsa_utils.cpp b/source/devoptab/devoptab_fsa_utils.cpp new file mode 100644 index 000000000000..0ed5fd6f096d --- /dev/null +++ b/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/source/devoptab/devoptab_fsa_utimes.cpp b/source/devoptab/devoptab_fsa_utimes.cpp new file mode 100644 index 000000000000..7cfc7dbf7cf9 --- /dev/null +++ b/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/source/devoptab/devoptab_fsa_write.cpp b/source/devoptab/devoptab_fsa_write.cpp new file mode 100644 index 000000000000..39bc50ceac27 --- /dev/null +++ b/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, %p, 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/source/disc_interface.c b/source/disc_interface.c new file mode 100644 index 000000000000..28853391bc04 --- /dev/null +++ b/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/source/fsa.cpp b/source/fsa.cpp new file mode 100644 index 000000000000..ceb358b695e7 --- /dev/null +++ b/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 (%p).\n", data); + return FS_ERROR_INVALID_ALIGNMENT; + } + DEBUG_FUNCTION_LINE_WARN("Buffer not aligned (%p). 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 (%p).", data); + return FS_ERROR_INVALID_ALIGNMENT; + } + DEBUG_FUNCTION_LINE_WARN("Buffer not aligned (%p). 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/source/logger.h b/source/logger.h new file mode 100644 index 000000000000..ffa747ef40d0 --- /dev/null +++ b/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/source/utils.cpp b/source/utils.cpp new file mode 100644 index 000000000000..a9cbf3de2a59 --- /dev/null +++ b/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/source/utils.h b/source/utils.h new file mode 100644 index 000000000000..c8c2a1988384 --- /dev/null +++ b/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)) From b3872f3d6035eafca3acb501c110fe6c9789accc Mon Sep 17 00:00:00 2001 From: Ash Logan Date: Sat, 6 Sep 2025 00:14:04 +1000 Subject: [PATCH 03/14] (wiiu) libmocha: Use relative includes --- deps/libmocha/source/devoptab/devoptab_fsa.cpp | 2 +- deps/libmocha/source/devoptab/devoptab_fsa_chdir.cpp | 2 +- deps/libmocha/source/devoptab/devoptab_fsa_chmod.cpp | 2 +- deps/libmocha/source/devoptab/devoptab_fsa_close.cpp | 2 +- deps/libmocha/source/devoptab/devoptab_fsa_dirclose.cpp | 2 +- deps/libmocha/source/devoptab/devoptab_fsa_dirnext.cpp | 2 +- deps/libmocha/source/devoptab/devoptab_fsa_diropen.cpp | 2 +- deps/libmocha/source/devoptab/devoptab_fsa_dirreset.cpp | 2 +- deps/libmocha/source/devoptab/devoptab_fsa_fchmod.cpp | 2 +- deps/libmocha/source/devoptab/devoptab_fsa_fstat.cpp | 2 +- deps/libmocha/source/devoptab/devoptab_fsa_fsync.cpp | 2 +- deps/libmocha/source/devoptab/devoptab_fsa_mkdir.cpp | 2 +- deps/libmocha/source/devoptab/devoptab_fsa_open.cpp | 4 ++-- deps/libmocha/source/devoptab/devoptab_fsa_read.cpp | 4 ++-- deps/libmocha/source/devoptab/devoptab_fsa_rename.cpp | 2 +- deps/libmocha/source/devoptab/devoptab_fsa_rmdir.cpp | 2 +- deps/libmocha/source/devoptab/devoptab_fsa_seek.cpp | 2 +- deps/libmocha/source/devoptab/devoptab_fsa_stat.cpp | 4 ++-- deps/libmocha/source/devoptab/devoptab_fsa_statvfs.cpp | 4 ++-- deps/libmocha/source/devoptab/devoptab_fsa_truncate.cpp | 2 +- deps/libmocha/source/devoptab/devoptab_fsa_unlink.cpp | 2 +- deps/libmocha/source/devoptab/devoptab_fsa_write.cpp | 2 +- 22 files changed, 26 insertions(+), 26 deletions(-) diff --git a/deps/libmocha/source/devoptab/devoptab_fsa.cpp b/deps/libmocha/source/devoptab/devoptab_fsa.cpp index 35164914601c..c6eb03c88a4d 100644 --- a/deps/libmocha/source/devoptab/devoptab_fsa.cpp +++ b/deps/libmocha/source/devoptab/devoptab_fsa.cpp @@ -1,5 +1,5 @@ #include "devoptab_fsa.h" -#include "logger.h" +#include "../logger.h" #include "mocha/mocha.h" #include #include diff --git a/deps/libmocha/source/devoptab/devoptab_fsa_chdir.cpp b/deps/libmocha/source/devoptab/devoptab_fsa_chdir.cpp index 8165bcebfc19..addb36913065 100644 --- a/deps/libmocha/source/devoptab/devoptab_fsa_chdir.cpp +++ b/deps/libmocha/source/devoptab/devoptab_fsa_chdir.cpp @@ -1,5 +1,5 @@ #include "devoptab_fsa.h" -#include "logger.h" +#include "../logger.h" #include int __fsa_chdir(struct _reent *r, diff --git a/deps/libmocha/source/devoptab/devoptab_fsa_chmod.cpp b/deps/libmocha/source/devoptab/devoptab_fsa_chmod.cpp index 73ddb7154644..c3a3f75b82bf 100644 --- a/deps/libmocha/source/devoptab/devoptab_fsa_chmod.cpp +++ b/deps/libmocha/source/devoptab/devoptab_fsa_chmod.cpp @@ -1,5 +1,5 @@ #include "devoptab_fsa.h" -#include "logger.h" +#include "../logger.h" #include #include diff --git a/deps/libmocha/source/devoptab/devoptab_fsa_close.cpp b/deps/libmocha/source/devoptab/devoptab_fsa_close.cpp index cc3783a1ffed..5fbe8011aa99 100644 --- a/deps/libmocha/source/devoptab/devoptab_fsa_close.cpp +++ b/deps/libmocha/source/devoptab/devoptab_fsa_close.cpp @@ -1,5 +1,5 @@ #include "devoptab_fsa.h" -#include "logger.h" +#include "../logger.h" #include int __fsa_close(struct _reent *r, diff --git a/deps/libmocha/source/devoptab/devoptab_fsa_dirclose.cpp b/deps/libmocha/source/devoptab/devoptab_fsa_dirclose.cpp index 44ad08059703..b845c689f7db 100644 --- a/deps/libmocha/source/devoptab/devoptab_fsa_dirclose.cpp +++ b/deps/libmocha/source/devoptab/devoptab_fsa_dirclose.cpp @@ -1,5 +1,5 @@ #include "devoptab_fsa.h" -#include "logger.h" +#include "../logger.h" #include int __fsa_dirclose(struct _reent *r, diff --git a/deps/libmocha/source/devoptab/devoptab_fsa_dirnext.cpp b/deps/libmocha/source/devoptab/devoptab_fsa_dirnext.cpp index a087cb3d3847..f276071751c4 100644 --- a/deps/libmocha/source/devoptab/devoptab_fsa_dirnext.cpp +++ b/deps/libmocha/source/devoptab/devoptab_fsa_dirnext.cpp @@ -1,5 +1,5 @@ #include "devoptab_fsa.h" -#include "logger.h" +#include "../logger.h" #include #include diff --git a/deps/libmocha/source/devoptab/devoptab_fsa_diropen.cpp b/deps/libmocha/source/devoptab/devoptab_fsa_diropen.cpp index f3c74bf4c782..93ced6460e99 100644 --- a/deps/libmocha/source/devoptab/devoptab_fsa_diropen.cpp +++ b/deps/libmocha/source/devoptab/devoptab_fsa_diropen.cpp @@ -1,5 +1,5 @@ #include "devoptab_fsa.h" -#include "logger.h" +#include "../logger.h" #include DIR_ITER * diff --git a/deps/libmocha/source/devoptab/devoptab_fsa_dirreset.cpp b/deps/libmocha/source/devoptab/devoptab_fsa_dirreset.cpp index 7fa348aa24e4..a9acc3961a03 100644 --- a/deps/libmocha/source/devoptab/devoptab_fsa_dirreset.cpp +++ b/deps/libmocha/source/devoptab/devoptab_fsa_dirreset.cpp @@ -1,5 +1,5 @@ #include "devoptab_fsa.h" -#include "logger.h" +#include "../logger.h" #include int __fsa_dirreset(struct _reent *r, diff --git a/deps/libmocha/source/devoptab/devoptab_fsa_fchmod.cpp b/deps/libmocha/source/devoptab/devoptab_fsa_fchmod.cpp index e0bd6ec6eadc..9c137fc1fcd1 100644 --- a/deps/libmocha/source/devoptab/devoptab_fsa_fchmod.cpp +++ b/deps/libmocha/source/devoptab/devoptab_fsa_fchmod.cpp @@ -1,5 +1,5 @@ #include "devoptab_fsa.h" -#include "logger.h" +#include "../logger.h" #include int __fsa_fchmod(struct _reent *r, diff --git a/deps/libmocha/source/devoptab/devoptab_fsa_fstat.cpp b/deps/libmocha/source/devoptab/devoptab_fsa_fstat.cpp index f54d1e17888a..d3227e2778d3 100644 --- a/deps/libmocha/source/devoptab/devoptab_fsa_fstat.cpp +++ b/deps/libmocha/source/devoptab/devoptab_fsa_fstat.cpp @@ -1,5 +1,5 @@ #include "devoptab_fsa.h" -#include "logger.h" +#include "../logger.h" #include int __fsa_fstat(struct _reent *r, diff --git a/deps/libmocha/source/devoptab/devoptab_fsa_fsync.cpp b/deps/libmocha/source/devoptab/devoptab_fsa_fsync.cpp index 38503911c855..c2f57da38c7e 100644 --- a/deps/libmocha/source/devoptab/devoptab_fsa_fsync.cpp +++ b/deps/libmocha/source/devoptab/devoptab_fsa_fsync.cpp @@ -1,5 +1,5 @@ #include "devoptab_fsa.h" -#include "logger.h" +#include "../logger.h" #include int __fsa_fsync(struct _reent *r, diff --git a/deps/libmocha/source/devoptab/devoptab_fsa_mkdir.cpp b/deps/libmocha/source/devoptab/devoptab_fsa_mkdir.cpp index 467567d2cba4..3ff272579d23 100644 --- a/deps/libmocha/source/devoptab/devoptab_fsa_mkdir.cpp +++ b/deps/libmocha/source/devoptab/devoptab_fsa_mkdir.cpp @@ -1,5 +1,5 @@ #include "devoptab_fsa.h" -#include "logger.h" +#include "../logger.h" #include int __fsa_mkdir(struct _reent *r, diff --git a/deps/libmocha/source/devoptab/devoptab_fsa_open.cpp b/deps/libmocha/source/devoptab/devoptab_fsa_open.cpp index 8870e859a834..3e38433ce61b 100644 --- a/deps/libmocha/source/devoptab/devoptab_fsa_open.cpp +++ b/deps/libmocha/source/devoptab/devoptab_fsa_open.cpp @@ -1,5 +1,5 @@ #include "devoptab_fsa.h" -#include "logger.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 @@ -141,4 +141,4 @@ int __fsa_open(struct _reent *r, 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 index 29e3355f38ca..993351cf6d7f 100644 --- a/deps/libmocha/source/devoptab/devoptab_fsa_read.cpp +++ b/deps/libmocha/source/devoptab/devoptab_fsa_read.cpp @@ -1,5 +1,5 @@ #include "devoptab_fsa.h" -#include "logger.h" +#include "../logger.h" #include #include @@ -76,4 +76,4 @@ ssize_t __fsa_read(struct _reent *r, void *fd, char *ptr, size_t len) { } 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 index b551f93b414f..6dee635064c6 100644 --- a/deps/libmocha/source/devoptab/devoptab_fsa_rename.cpp +++ b/deps/libmocha/source/devoptab/devoptab_fsa_rename.cpp @@ -1,5 +1,5 @@ #include "devoptab_fsa.h" -#include "logger.h" +#include "../logger.h" #include int __fsa_rename(struct _reent *r, diff --git a/deps/libmocha/source/devoptab/devoptab_fsa_rmdir.cpp b/deps/libmocha/source/devoptab/devoptab_fsa_rmdir.cpp index 31aa59b2a311..c3500ff87ca1 100644 --- a/deps/libmocha/source/devoptab/devoptab_fsa_rmdir.cpp +++ b/deps/libmocha/source/devoptab/devoptab_fsa_rmdir.cpp @@ -1,5 +1,5 @@ #include "devoptab_fsa.h" -#include "logger.h" +#include "../logger.h" #include int __fsa_rmdir(struct _reent *r, diff --git a/deps/libmocha/source/devoptab/devoptab_fsa_seek.cpp b/deps/libmocha/source/devoptab/devoptab_fsa_seek.cpp index 65a7a6bdf169..795a994d97c7 100644 --- a/deps/libmocha/source/devoptab/devoptab_fsa_seek.cpp +++ b/deps/libmocha/source/devoptab/devoptab_fsa_seek.cpp @@ -1,5 +1,5 @@ #include "devoptab_fsa.h" -#include "logger.h" +#include "../logger.h" #include off_t __fsa_seek(struct _reent *r, diff --git a/deps/libmocha/source/devoptab/devoptab_fsa_stat.cpp b/deps/libmocha/source/devoptab/devoptab_fsa_stat.cpp index eda59f1d024c..214b41150b76 100644 --- a/deps/libmocha/source/devoptab/devoptab_fsa_stat.cpp +++ b/deps/libmocha/source/devoptab/devoptab_fsa_stat.cpp @@ -1,5 +1,5 @@ #include "devoptab_fsa.h" -#include "logger.h" +#include "../logger.h" #include int __fsa_stat(struct _reent *r, @@ -33,4 +33,4 @@ int __fsa_stat(struct _reent *r, __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 index 0906c05b1c9b..9fa1e950c8cd 100644 --- a/deps/libmocha/source/devoptab/devoptab_fsa_statvfs.cpp +++ b/deps/libmocha/source/devoptab/devoptab_fsa_statvfs.cpp @@ -1,5 +1,5 @@ #include "devoptab_fsa.h" -#include "logger.h" +#include "../logger.h" #include int __fsa_statvfs(struct _reent *r, @@ -48,4 +48,4 @@ int __fsa_statvfs(struct _reent *r, 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 index 0f1bba36b3fc..4da9de85e8e1 100644 --- a/deps/libmocha/source/devoptab/devoptab_fsa_truncate.cpp +++ b/deps/libmocha/source/devoptab/devoptab_fsa_truncate.cpp @@ -1,5 +1,5 @@ #include "devoptab_fsa.h" -#include "logger.h" +#include "../logger.h" #include int __fsa_ftruncate(struct _reent *r, diff --git a/deps/libmocha/source/devoptab/devoptab_fsa_unlink.cpp b/deps/libmocha/source/devoptab/devoptab_fsa_unlink.cpp index e55ec684e78e..6cd73067dfd8 100644 --- a/deps/libmocha/source/devoptab/devoptab_fsa_unlink.cpp +++ b/deps/libmocha/source/devoptab/devoptab_fsa_unlink.cpp @@ -1,5 +1,5 @@ #include "devoptab_fsa.h" -#include "logger.h" +#include "../logger.h" #include int __fsa_unlink(struct _reent *r, diff --git a/deps/libmocha/source/devoptab/devoptab_fsa_write.cpp b/deps/libmocha/source/devoptab/devoptab_fsa_write.cpp index 39bc50ceac27..bdf6866461bc 100644 --- a/deps/libmocha/source/devoptab/devoptab_fsa_write.cpp +++ b/deps/libmocha/source/devoptab/devoptab_fsa_write.cpp @@ -1,5 +1,5 @@ #include "devoptab_fsa.h" -#include "logger.h" +#include "../logger.h" #include ssize_t __fsa_write(struct _reent *r, void *fd, const char *ptr, size_t len) { From 7072f78a9d32736451e71ec653cd382611e3bdb5 Mon Sep 17 00:00:00 2001 From: Ash Logan Date: Sat, 6 Sep 2025 00:45:26 +1000 Subject: [PATCH 04/14] (wiiu) Port to wut toolchain This commit is enough to compile RetroArch using wut and more modern versions of devkitPPC. Among the requisite ports and bugfixes, the wiiu code has been switched to use wut's h. There's a handful of headers where RA's are more precise, and these have been put into the `wiiu/include/` hierarchy mirroring WUT's folder structure, but with `ra_` prepended to the filename to avoid include directory priority fighting. Other changes are related to the header changes: - update defines to use WUT's new definition - remove some workarounds/hacks in favor of more precise handling in WUT. Cut features that will be re-added later: - Current rpx symbol names in the exception handler - somemopt networking optimisations - Core loading --- Makefile.common | 38 +- Makefile.wiiu | 99 +- audio/drivers/wiiu_audio.c | 12 +- deps/libfat/common.h | 2 +- deps/libfat/disc.c | 6 +- deps/libfat/include/fat.h | 2 +- deps/libfat/mem_allocate.h | 4 +- deps/libmocha/source/utils.cpp | 2 +- frontend/drivers/platform_wiiu.c | 620 ++---- gfx/drivers/gx2_gfx.c | 34 +- gfx/drivers/gx2_shaders/bokeh.c | 18 +- gfx/drivers/gx2_shaders/frame.c | 19 +- gfx/drivers/gx2_shaders/ribbon.c | 17 +- gfx/drivers/gx2_shaders/ribbon_simple.c | 17 +- gfx/drivers/gx2_shaders/snow.c | 17 +- gfx/drivers/gx2_shaders/snow_simple.c | 17 +- gfx/drivers/gx2_shaders/snowflake.c | 17 +- gfx/drivers/gx2_shaders/sprite.c | 21 +- gfx/drivers/gx2_shaders/tex.c | 20 +- gfx/drivers_font_renderer/stb_unicode.c | 8 +- input/drivers/wiiu_input.c | 6 +- input/drivers_hid/wiiu_hid.c | 29 +- input/drivers_joypad/wiiu/kpad_driver.c | 65 +- input/include/wiiu/hid.h | 3 + input/include/wiiu/input.h | 7 +- libretro-common/features/features_cpu.c | 8 +- libretro-common/include/net/net_compat.h | 10 +- libretro-common/include/retro_timers.h | 4 +- libretro-common/net/net_compat.c | 52 - libretro-common/net/net_socket.c | 46 +- menu/menu_driver.c | 2 +- wiiu/fs/fs_utils.c | 66 - wiiu/fs/fs_utils.h | 16 - wiiu/fs/sd_fat_devoptab.c | 1073 ---------- wiiu/fs/sd_fat_devoptab.h | 38 - wiiu/hbl.c | 307 --- wiiu/hbl.h | 26 - wiiu/include/arpa/inet.h | 21 - .../{wiiu/gx2/shaders.h => gx2/ra_shaders.h} | 7 +- wiiu/include/netdb.h | 63 - wiiu/include/netinet/in.h | 36 - wiiu/include/netinet/tcp.h | 14 - wiiu/include/nn/ac/ra_ac.h | 24 + .../{wiiu/nsyskbd.h => nsyskbd/ra_nsyskbd.h} | 0 .../multivoice.h => sndcore2/ra_multivoice.h} | 2 +- wiiu/include/sys/socket.h | 143 -- wiiu/include/vpad/ra_input.h | 56 + wiiu/include/wiiu/ac.h | 23 - wiiu/include/wiiu/ax.h | 8 - wiiu/include/wiiu/ax/core.h | 50 - wiiu/include/wiiu/ax/device.h | 39 - wiiu/include/wiiu/ax/drcvs.h | 54 - wiiu/include/wiiu/ax/result.h | 19 - wiiu/include/wiiu/ax/voice.h | 178 -- wiiu/include/wiiu/fs.h | 267 --- wiiu/include/wiiu/gx2.h | 18 - wiiu/include/wiiu/gx2/common.h | 15 - wiiu/include/wiiu/gx2/context.h | 37 - wiiu/include/wiiu/gx2/display.h | 30 - wiiu/include/wiiu/gx2/displaylist.h | 21 - wiiu/include/wiiu/gx2/draw.h | 50 - wiiu/include/wiiu/gx2/enum.h | 502 ----- wiiu/include/wiiu/gx2/event.h | 35 - wiiu/include/wiiu/gx2/mem.h | 13 - wiiu/include/wiiu/gx2/registers.h | 235 --- wiiu/include/wiiu/gx2/sampler.h | 34 - wiiu/include/wiiu/gx2/state.h | 15 - wiiu/include/wiiu/gx2/surface.h | 78 - wiiu/include/wiiu/gx2/swap.h | 20 - wiiu/include/wiiu/gx2/tessellation.h | 15 - wiiu/include/wiiu/gx2/texture.h | 29 - wiiu/include/wiiu/gx2r.h | 8 - wiiu/include/wiiu/gx2r/buffer.h | 32 - wiiu/include/wiiu/gx2r/displaylist.h | 17 - wiiu/include/wiiu/gx2r/draw.h | 17 - wiiu/include/wiiu/gx2r/mem.h | 20 - wiiu/include/wiiu/gx2r/resource.h | 43 - wiiu/include/wiiu/gx2r/surface.h | 19 - wiiu/include/wiiu/ios.h | 15 - wiiu/include/wiiu/kpad.h | 97 - wiiu/include/wiiu/mcp.h | 61 - wiiu/include/wiiu/mem.h | 9 - wiiu/include/wiiu/mem/baseheap.h | 23 - wiiu/include/wiiu/mem/blockheap.h | 74 - wiiu/include/wiiu/mem/expandedheap.h | 65 - wiiu/include/wiiu/mem/frameheap.h | 44 - wiiu/include/wiiu/mem/memheap.h | 81 - wiiu/include/wiiu/mem/memlist.h | 33 - wiiu/include/wiiu/mem/unitheap.h | 32 - wiiu/include/wiiu/mp/taskqueue.h | 110 - wiiu/include/wiiu/os.h | 27 - wiiu/include/wiiu/os/alarm.h | 66 - wiiu/include/wiiu/os/atomic.h | 14 - wiiu/include/wiiu/os/atomic64.h | 22 - wiiu/include/wiiu/os/cache.h | 19 - wiiu/include/wiiu/os/condition.h | 26 - wiiu/include/wiiu/os/core.h | 17 - wiiu/include/wiiu/os/coroutine.h | 28 - wiiu/include/wiiu/os/debug.h | 18 - wiiu/include/wiiu/os/dynload.h | 22 - wiiu/include/wiiu/os/energy.h | 18 - wiiu/include/wiiu/os/event.h | 36 - wiiu/include/wiiu/os/exception.h | 36 - wiiu/include/wiiu/os/fastcondition.h | 25 - wiiu/include/wiiu/os/fastmutex.h | 33 - wiiu/include/wiiu/os/foreground.h | 14 - wiiu/include/wiiu/os/memory.h | 28 - wiiu/include/wiiu/os/messagequeue.h | 43 - wiiu/include/wiiu/os/mutex.h | 39 - wiiu/include/wiiu/os/rendezvous.h | 20 - wiiu/include/wiiu/os/screen.h | 25 - wiiu/include/wiiu/os/semaphore.h | 28 - wiiu/include/wiiu/os/spinlock.h | 31 - wiiu/include/wiiu/os/systeminfo.h | 22 - wiiu/include/wiiu/os/thread.h | 277 --- wiiu/include/wiiu/os/time.h | 49 - wiiu/include/wiiu/os/title.h | 12 - wiiu/include/wiiu/procui.h | 35 - wiiu/include/wiiu/sysapp.h | 26 - wiiu/include/wiiu/syshid.h | 125 -- wiiu/include/wiiu/vpad.h | 192 -- wiiu/include/wiiu/wpad.h | 104 - wiiu/link.ld | 36 - wiiu/link_elf.ld | 261 --- wiiu/link_rpl.ld | 264 --- wiiu/main.c | 249 --- wiiu/shader_utils.c | 69 +- wiiu/shader_utils.h | 13 +- wiiu/system/atomic.c | 35 - wiiu/system/dynamic.c | 26 - wiiu/system/dynamic.h | 6 - wiiu/system/exception_handler.c | 122 +- wiiu/system/exception_handler.h | 7 +- wiiu/system/imports.h | 324 --- wiiu/system/memory.c | 144 +- wiiu/system/missing_libc_functions.c | 284 +-- wiiu/system/stubs_elf.S | 31 - wiiu/system/stubs_rpl.S | 51 - wiiu/wiiu_dbg.h | 13 - wiiu/wut.ld | 411 ++++ wiiu/wut/elf2rpl/Makefile | 27 - wiiu/wut/elf2rpl/be_val.h | 72 - wiiu/wut/elf2rpl/elf.h | 314 --- wiiu/wut/elf2rpl/elf2rpl.vcxproj | 172 -- wiiu/wut/elf2rpl/elf2rpl.vcxproj.filters | 39 - wiiu/wut/elf2rpl/main.cpp | 1816 ----------------- wiiu/wut/elf2rpl/utils.h | 119 -- 147 files changed, 1242 insertions(+), 10839 deletions(-) delete mode 100644 wiiu/fs/fs_utils.c delete mode 100644 wiiu/fs/fs_utils.h delete mode 100644 wiiu/fs/sd_fat_devoptab.c delete mode 100644 wiiu/fs/sd_fat_devoptab.h delete mode 100644 wiiu/hbl.c delete mode 100644 wiiu/hbl.h delete mode 100644 wiiu/include/arpa/inet.h rename wiiu/include/{wiiu/gx2/shaders.h => gx2/ra_shaders.h} (99%) delete mode 100644 wiiu/include/netdb.h delete mode 100644 wiiu/include/netinet/in.h delete mode 100644 wiiu/include/netinet/tcp.h create mode 100644 wiiu/include/nn/ac/ra_ac.h rename wiiu/include/{wiiu/nsyskbd.h => nsyskbd/ra_nsyskbd.h} (100%) rename wiiu/include/{wiiu/ax/multivoice.h => sndcore2/ra_multivoice.h} (96%) delete mode 100644 wiiu/include/sys/socket.h create mode 100644 wiiu/include/vpad/ra_input.h delete mode 100644 wiiu/include/wiiu/ac.h delete mode 100644 wiiu/include/wiiu/ax.h delete mode 100644 wiiu/include/wiiu/ax/core.h delete mode 100644 wiiu/include/wiiu/ax/device.h delete mode 100644 wiiu/include/wiiu/ax/drcvs.h delete mode 100644 wiiu/include/wiiu/ax/result.h delete mode 100644 wiiu/include/wiiu/ax/voice.h delete mode 100644 wiiu/include/wiiu/fs.h delete mode 100644 wiiu/include/wiiu/gx2.h delete mode 100644 wiiu/include/wiiu/gx2/common.h delete mode 100644 wiiu/include/wiiu/gx2/context.h delete mode 100644 wiiu/include/wiiu/gx2/display.h delete mode 100644 wiiu/include/wiiu/gx2/displaylist.h delete mode 100644 wiiu/include/wiiu/gx2/draw.h delete mode 100644 wiiu/include/wiiu/gx2/enum.h delete mode 100644 wiiu/include/wiiu/gx2/event.h delete mode 100644 wiiu/include/wiiu/gx2/mem.h delete mode 100644 wiiu/include/wiiu/gx2/registers.h delete mode 100644 wiiu/include/wiiu/gx2/sampler.h delete mode 100644 wiiu/include/wiiu/gx2/state.h delete mode 100644 wiiu/include/wiiu/gx2/surface.h delete mode 100644 wiiu/include/wiiu/gx2/swap.h delete mode 100644 wiiu/include/wiiu/gx2/tessellation.h delete mode 100644 wiiu/include/wiiu/gx2/texture.h delete mode 100644 wiiu/include/wiiu/gx2r.h delete mode 100644 wiiu/include/wiiu/gx2r/buffer.h delete mode 100644 wiiu/include/wiiu/gx2r/displaylist.h delete mode 100644 wiiu/include/wiiu/gx2r/draw.h delete mode 100644 wiiu/include/wiiu/gx2r/mem.h delete mode 100644 wiiu/include/wiiu/gx2r/resource.h delete mode 100644 wiiu/include/wiiu/gx2r/surface.h delete mode 100644 wiiu/include/wiiu/ios.h delete mode 100644 wiiu/include/wiiu/kpad.h delete mode 100644 wiiu/include/wiiu/mcp.h delete mode 100644 wiiu/include/wiiu/mem.h delete mode 100644 wiiu/include/wiiu/mem/baseheap.h delete mode 100644 wiiu/include/wiiu/mem/blockheap.h delete mode 100644 wiiu/include/wiiu/mem/expandedheap.h delete mode 100644 wiiu/include/wiiu/mem/frameheap.h delete mode 100644 wiiu/include/wiiu/mem/memheap.h delete mode 100644 wiiu/include/wiiu/mem/memlist.h delete mode 100644 wiiu/include/wiiu/mem/unitheap.h delete mode 100644 wiiu/include/wiiu/mp/taskqueue.h delete mode 100644 wiiu/include/wiiu/os.h delete mode 100644 wiiu/include/wiiu/os/alarm.h delete mode 100644 wiiu/include/wiiu/os/atomic.h delete mode 100644 wiiu/include/wiiu/os/atomic64.h delete mode 100644 wiiu/include/wiiu/os/cache.h delete mode 100644 wiiu/include/wiiu/os/condition.h delete mode 100644 wiiu/include/wiiu/os/core.h delete mode 100644 wiiu/include/wiiu/os/coroutine.h delete mode 100644 wiiu/include/wiiu/os/debug.h delete mode 100644 wiiu/include/wiiu/os/dynload.h delete mode 100644 wiiu/include/wiiu/os/energy.h delete mode 100644 wiiu/include/wiiu/os/event.h delete mode 100644 wiiu/include/wiiu/os/exception.h delete mode 100644 wiiu/include/wiiu/os/fastcondition.h delete mode 100644 wiiu/include/wiiu/os/fastmutex.h delete mode 100644 wiiu/include/wiiu/os/foreground.h delete mode 100644 wiiu/include/wiiu/os/memory.h delete mode 100644 wiiu/include/wiiu/os/messagequeue.h delete mode 100644 wiiu/include/wiiu/os/mutex.h delete mode 100644 wiiu/include/wiiu/os/rendezvous.h delete mode 100644 wiiu/include/wiiu/os/screen.h delete mode 100644 wiiu/include/wiiu/os/semaphore.h delete mode 100644 wiiu/include/wiiu/os/spinlock.h delete mode 100644 wiiu/include/wiiu/os/systeminfo.h delete mode 100644 wiiu/include/wiiu/os/thread.h delete mode 100644 wiiu/include/wiiu/os/time.h delete mode 100644 wiiu/include/wiiu/os/title.h delete mode 100644 wiiu/include/wiiu/procui.h delete mode 100644 wiiu/include/wiiu/sysapp.h delete mode 100644 wiiu/include/wiiu/syshid.h delete mode 100644 wiiu/include/wiiu/vpad.h delete mode 100644 wiiu/include/wiiu/wpad.h delete mode 100644 wiiu/link.ld delete mode 100644 wiiu/link_elf.ld delete mode 100644 wiiu/link_rpl.ld delete mode 100644 wiiu/main.c delete mode 100644 wiiu/system/atomic.c delete mode 100644 wiiu/system/dynamic.c delete mode 100644 wiiu/system/dynamic.h delete mode 100644 wiiu/system/imports.h delete mode 100644 wiiu/system/stubs_elf.S create mode 100644 wiiu/wut.ld delete mode 100644 wiiu/wut/elf2rpl/Makefile delete mode 100644 wiiu/wut/elf2rpl/be_val.h delete mode 100644 wiiu/wut/elf2rpl/elf.h delete mode 100644 wiiu/wut/elf2rpl/elf2rpl.vcxproj delete mode 100644 wiiu/wut/elf2rpl/elf2rpl.vcxproj.filters delete mode 100644 wiiu/wut/elf2rpl/main.cpp delete mode 100644 wiiu/wut/elf2rpl/utils.h diff --git a/Makefile.common b/Makefile.common index 411f959f392e..26596a67f312 100644 --- a/Makefile.common +++ b/Makefile.common @@ -2622,12 +2622,38 @@ 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.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_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 1c457bcf26bf..b1cbc0af1e66 100644 --- a/Makefile.wiiu +++ b/Makefile.wiiu @@ -1,19 +1,17 @@ TARGET := retroarch_wiiu -BUILD_HBL_ELF = 1 -BUILD_RPX = 1 DEBUG = 0 GRIFFIN_BUILD = 0 SALAMANDER_BUILD = 0 -HAVE_STATIC_DUMMY ?= 0 +HAVE_STATIC_DUMMY ?= 0 WHOLE_ARCHIVE_LINK = 0 WIIU_HID = 1 HAVE_HID = 1 HAVE_RUNAHEAD = 1 WIIU_LOG_RPX = 0 BUILD_DIR = objs/wiiu -PC_DEVELOPMENT_TCP_PORT ?= -LOAD_WITHOUT_CORE_INFO ?= 0 +PC_DEVELOPMENT_TCP_PORT ?= +LOAD_WITHOUT_CORE_INFO ?= 0 ifeq ($(SALAMANDER_BUILD),1) BUILD_DIR := $(BUILD_DIR)-salamander @@ -37,18 +35,10 @@ 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 +OBJ += wiiu/system/stubs_rpl.o ifeq ($(SALAMANDER_BUILD),1) DEFINES += -DRARCH_CONSOLE -DIS_SALAMANDER @@ -109,8 +99,8 @@ endif OBJ += griffin/griffin.o griffin/griffin_cpp.o INCDIRS += -Ilibretro-common/include/compat/zlib - # for stb, libfat, iosuhax - INCDIRS += -Ideps -Ideps/libfat/include -Ideps/libiosuhax/include + # for stb, libfat, libmocha + INCDIRS += -Ideps -Ideps/libfat/include -Ideps/libmocha/include # pad_functions uses wiiu/input.h INCDIRS += -Iinput/include INCDIRS += -Ideps/SPIRV-Cross @@ -118,7 +108,7 @@ endif DEFINES += -DHAVE_AUDIOMIXER DEFINES += -DHAVE_RWAV DEFINES += -DHAVE_GRIFFIN=1 -DHAVE_MENU -DHAVE_GFX_WIDGETS -DHAVE_CONFIGFILE -DHAVE_PATCH -DHAVE_CHEATS -DHAVE_RGUI -DHAVE_LIBRETRODB - DEFINES += -DHAVE_REWIND + DEFINES += -DHAVE_REWIND DEFINES += -DHAVE_ZLIB -DHAVE_RPNG -DHAVE_RJPEG -DHAVE_RBMP -DHAVE_RTGA -DHAVE_CC_RESAMPLER DEFINES += -DHAVE_SPIRV_CROSS -DHAVE_SLANG DEFINES += -DHAVE_STB_FONT -DHAVE_STB_VORBIS -DHAVE_LANGEXTRA -DHAVE_LIBRETRODB -DHAVE_NETWORKING -DHAVE_IFINFO -DHAVE_NETPLAYDISCOVERY @@ -126,7 +116,7 @@ endif #DEFINES += -DHAVE_FREETYPE DEFINES += -DHAVE_XMB -DHAVE_MATERIALUI DEFINES += -DHAVE_HID - DEFINES += -DWANT_LIBFAT -DHAVE_LIBFAT -DWANT_IOSUHAX -DHAVE_IOSUHAX + DEFINES += -DWANT_LIBFAT -DHAVE_LIBFAT -DWANT_LIBMOCHA -DHAVE_LIBMOCHA DEFINES += -DHAVE_CORE_INFO_CACHE DEFINES += -DSPIRV_CROSS_EXCEPTIONS_TO_ASSERTIONS @@ -171,7 +161,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 @@ -206,7 +196,10 @@ CFLAGS := -mcpu=750 -meabi -mhard-float CFLAGS += -Werror=implicit-function-declaration CFLAGS += -ffunction-sections -fdata-sections #CFLAGS += -fomit-frame-pointer -mword-relocations -CFLAGS += -Wall +# Some Wii U dependencies and headers are using C++ style comments, so use gnu89 here instead of C89 proper +CFLAGS += -Wall -std=gnu89 -Wno-scalar-storage-order +# wut's 'gx2/shaders.h' isn't c89-compliant +$(BUILD_DIR)/wiiu/shader_utils.o: CFLAGS += -std=c99 ifeq ($(DEBUG), 1) CFLAGS += -O0 -g @@ -248,15 +241,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 +251,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 +264,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 @@ -365,38 +343,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 8350a0130529..d4f03391c638 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 #include "../../wiiu/wiiu_dbg.h" #include "../../wiiu/system/memory.h" @@ -75,8 +79,6 @@ 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) @@ -84,7 +86,7 @@ static void* ax_audio_init(const char* device, unsigned rate, unsigned latency, AXVoiceOffsets offsets[2]; u16 setup_buf[0x30] = {0}; setup_buf[0x25] = 2; /* we request 2 channels */ - AXInitParams init = {AX_INIT_RENDERER_48KHZ, 0, 0}; + AXInitParams init = {AX_INIT_RENDERER_48KHZ}; AXVoiceVeData ve = {0x8000, 0}; ax_audio_t* ax = (ax_audio_t*)calloc(1, sizeof(ax_audio_t)); 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/libmocha/source/utils.cpp b/deps/libmocha/source/utils.cpp index a9cbf3de2a59..11865afc2d55 100644 --- a/deps/libmocha/source/utils.cpp +++ b/deps/libmocha/source/utils.cpp @@ -74,7 +74,7 @@ MochaUtilsStatus Mocha_InitLibrary() { if (Mocha_CheckAPIVersion(&version) != MOCHA_RESULT_SUCCESS) { IOS_Close(iosuhaxHandle); iosuhaxHandle = -1; - return MOCHA_RESULT_UNSUPPORTED_COMMAND; + return MOCHA_RESULT_UNSUPPORTED_API_VERSION; } mochaApiVersion = version; diff --git a/frontend/drivers/platform_wiiu.c b/frontend/drivers/platform_wiiu.c index 10e21a1d3c67..4416fae31330 100644 --- a/frontend/drivers/platform_wiiu.c +++ b/frontend/drivers/platform_wiiu.c @@ -19,11 +19,8 @@ #include #include #include -#include -#include #include -#include #include #ifndef IS_SALAMANDER @@ -32,14 +29,6 @@ #include -#include -#include -#include -#include -#include -#include - - #include "../frontend.h" #include "../frontend_driver.h" #include "../../file_path_special.h" @@ -47,7 +36,6 @@ #include "../../paths.h" #include "../../retroarch.h" #include "../../verbosity.h" -#include "../../tasks/tasks_internal.h" #ifndef IS_SALAMANDER #ifdef HAVE_MENU @@ -59,10 +47,27 @@ #endif #endif -#include "hbl.h" -#include "wiiu_dbg.h" +#if defined(HAVE_LIBMOCHA) && defined(HAVE_LIBFAT) +#include +#include +#include +#endif + +#include "system/memory.h" #include "system/exception_handler.h" +#include "wiiu_dbg.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + #define WIIU_SD_PATH "sd:/" #define WIIU_USB_PATH "usb:/" #define WIIU_STORAGE_USB_PATH "storage_usb:/" @@ -72,11 +77,13 @@ */ #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_aroma = false; -static bool exists(char *path) +static bool exists(char* path) { struct stat stat_buf = {0}; @@ -91,8 +98,10 @@ static void fix_asset_directory(void) char src_path_buf[PATH_MAX_LENGTH] = {0}; char dst_path_buf[PATH_MAX_LENGTH] = {0}; - fill_pathname_join(src_path_buf, g_defaults.dirs[DEFAULT_DIR_PORT], "media", sizeof(g_defaults.dirs[DEFAULT_DIR_PORT])); - fill_pathname_join(dst_path_buf, g_defaults.dirs[DEFAULT_DIR_PORT], "assets", sizeof(g_defaults.dirs[DEFAULT_DIR_PORT])); + fill_pathname_join(src_path_buf, g_defaults.dirs[DEFAULT_DIR_PORT], "media", + sizeof(g_defaults.dirs[DEFAULT_DIR_PORT])); + fill_pathname_join(dst_path_buf, g_defaults.dirs[DEFAULT_DIR_PORT], "assets", + sizeof(g_defaults.dirs[DEFAULT_DIR_PORT])); if (exists(dst_path_buf) || !exists(src_path_buf)) return; @@ -100,55 +109,56 @@ static void fix_asset_directory(void) rename(src_path_buf, dst_path_buf); } -static void frontend_wiiu_get_env_settings(int *argc, char *argv[], - void *args, void *params_data) +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])); + fill_pathname_join(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])); + "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])); + "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])); + "cores", sizeof(g_defaults.dirs[DEFAULT_DIR_CORE])); fill_pathname_join(g_defaults.dirs[DEFAULT_DIR_CORE_INFO], g_defaults.dirs[DEFAULT_DIR_CORE], - "info", sizeof(g_defaults.dirs[DEFAULT_DIR_CORE_INFO])); + "info", sizeof(g_defaults.dirs[DEFAULT_DIR_CORE_INFO])); fill_pathname_join(g_defaults.dirs[DEFAULT_DIR_SAVESTATE], g_defaults.dirs[DEFAULT_DIR_CORE], - "savestates", sizeof(g_defaults.dirs[DEFAULT_DIR_SAVESTATE])); + "savestates", sizeof(g_defaults.dirs[DEFAULT_DIR_SAVESTATE])); fill_pathname_join(g_defaults.dirs[DEFAULT_DIR_SRAM], g_defaults.dirs[DEFAULT_DIR_CORE], - "savefiles", sizeof(g_defaults.dirs[DEFAULT_DIR_SRAM])); + "savefiles", sizeof(g_defaults.dirs[DEFAULT_DIR_SRAM])); fill_pathname_join(g_defaults.dirs[DEFAULT_DIR_SYSTEM], g_defaults.dirs[DEFAULT_DIR_CORE], - "system", sizeof(g_defaults.dirs[DEFAULT_DIR_SYSTEM])); + "system", sizeof(g_defaults.dirs[DEFAULT_DIR_SYSTEM])); fill_pathname_join(g_defaults.dirs[DEFAULT_DIR_PLAYLIST], g_defaults.dirs[DEFAULT_DIR_CORE], - "playlists", sizeof(g_defaults.dirs[DEFAULT_DIR_PLAYLIST])); + "playlists", sizeof(g_defaults.dirs[DEFAULT_DIR_PLAYLIST])); fill_pathname_join(g_defaults.dirs[DEFAULT_DIR_MENU_CONFIG], g_defaults.dirs[DEFAULT_DIR_PORT], - "config", sizeof(g_defaults.dirs[DEFAULT_DIR_MENU_CONFIG])); + "config", sizeof(g_defaults.dirs[DEFAULT_DIR_MENU_CONFIG])); fill_pathname_join(g_defaults.dirs[DEFAULT_DIR_REMAP], g_defaults.dirs[DEFAULT_DIR_PORT], - "config/remaps", sizeof(g_defaults.dirs[DEFAULT_DIR_REMAP])); + "config/remaps", sizeof(g_defaults.dirs[DEFAULT_DIR_REMAP])); fill_pathname_join(g_defaults.dirs[DEFAULT_DIR_VIDEO_FILTER], g_defaults.dirs[DEFAULT_DIR_PORT], - "filters", sizeof(g_defaults.dirs[DEFAULT_DIR_VIDEO_FILTER])); + "filters", sizeof(g_defaults.dirs[DEFAULT_DIR_VIDEO_FILTER])); fill_pathname_join(g_defaults.dirs[DEFAULT_DIR_DATABASE], g_defaults.dirs[DEFAULT_DIR_PORT], - "database/rdb", sizeof(g_defaults.dirs[DEFAULT_DIR_DATABASE])); + "database/rdb", sizeof(g_defaults.dirs[DEFAULT_DIR_DATABASE])); fill_pathname_join(g_defaults.dirs[DEFAULT_DIR_LOGS], g_defaults.dirs[DEFAULT_DIR_CORE], - "logs", sizeof(g_defaults.dirs[DEFAULT_DIR_LOGS])); + "logs", sizeof(g_defaults.dirs[DEFAULT_DIR_LOGS])); fill_pathname_join(g_defaults.dirs[DEFAULT_DIR_THUMBNAILS], g_defaults.dirs[DEFAULT_DIR_PORT], - "thumbnails", sizeof(g_defaults.dirs[DEFAULT_DIR_THUMBNAILS])); + "thumbnails", sizeof(g_defaults.dirs[DEFAULT_DIR_THUMBNAILS])); fill_pathname_join(g_defaults.dirs[DEFAULT_DIR_OVERLAY], g_defaults.dirs[DEFAULT_DIR_PORT], - "overlays", sizeof(g_defaults.dirs[DEFAULT_DIR_OVERLAY])); + "overlays", sizeof(g_defaults.dirs[DEFAULT_DIR_OVERLAY])); fill_pathname_join(g_defaults.dirs[DEFAULT_DIR_SCREENSHOT], g_defaults.dirs[DEFAULT_DIR_PORT], - "screenshots", sizeof(g_defaults.dirs[DEFAULT_DIR_SCREENSHOT])); + "screenshots", sizeof(g_defaults.dirs[DEFAULT_DIR_SCREENSHOT])); fill_pathname_join(g_defaults.dirs[DEFAULT_DIR_AUTOCONFIG], g_defaults.dirs[DEFAULT_DIR_PORT], - "autoconfig", sizeof(g_defaults.dirs[DEFAULT_DIR_AUTOCONFIG])); + "autoconfig", sizeof(g_defaults.dirs[DEFAULT_DIR_AUTOCONFIG])); fill_pathname_join(g_defaults.path_config, g_defaults.dirs[DEFAULT_DIR_PORT], - FILE_PATH_MAIN_CONFIG, sizeof(g_defaults.path_config)); + FILE_PATH_MAIN_CONFIG, sizeof(g_defaults.path_config)); #ifndef IS_SALAMANDER dir_check_defaults("custom.ini"); #endif } -static void frontend_wiiu_deinit(void *data) +static void frontend_wiiu_deinit(void* data) { (void)data; } @@ -158,7 +168,7 @@ static void frontend_wiiu_shutdown(bool unused) (void)unused; } -static void frontend_wiiu_init(void *data) +static void frontend_wiiu_init(void* data) { (void)data; DEBUG_LINE(); @@ -173,243 +183,104 @@ enum frontend_architecture frontend_wiiu_get_arch(void) return FRONTEND_ARCH_PPC; } -static int frontend_wiiu_parse_drive_list(void *data, bool load_content) +static int frontend_wiiu_parse_drive_list(void* data, bool load_content) { #ifndef IS_SALAMANDER - file_list_t *list = (file_list_t *)data; - enum msg_hash_enums enum_idx = load_content ? - MENU_ENUM_LABEL_FILE_DETECT_CORE_LIST_PUSH_DIR : - MENU_ENUM_LABEL_FILE_BROWSER_DIRECTORY; + file_list_t* list = (file_list_t*)data; + enum msg_hash_enums enum_idx = load_content + ? MENU_ENUM_LABEL_FILE_DETECT_CORE_LIST_PUSH_DIR + : MENU_ENUM_LABEL_FILE_BROWSER_DIRECTORY; 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); + 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_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_STORAGE_USB_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; -#ifndef IS_SALAMANDER -#ifdef HAVE_NETWORKING - char *argv[NETPLAY_FORK_MAX_ARGS + 1]; -#else - char *argv[3]; -#endif -#else - char *argv[2]; -#endif - char args[]; - } *param = getApplicationEndAddr(); - char *arg = param->args; - - DEBUG_STR(path); - - param->argc = 1; - param->argv[0] = arg; - arg += strlcpy(arg, elf_path_cst, PATH_MAX_LENGTH); - arg += 1; - - param->argv[1] = NULL; - -#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)) - { - char **cur_arg = arg_data; - - do - { - param->argv[param->argc++] = arg; - arg += strlcpy(arg, *cur_arg, PATH_MAX_LENGTH); - arg += 1; - } - while (*(++cur_arg)); - - param->argv[param->argc] = NULL; - } - 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; - } - } -#endif - - if (HBL_loadToMemory(path, (u32)arg - (u32)param) < 0) - { - RARCH_ERR("Failed to load core.\n"); - } - else - { - param->magic = ARGV_MAGIC; - ARGV_PTR = param; - - DEBUG_VAR(param->argc); - DEBUG_VAR(param->argv); - } -} - -#ifndef IS_SALAMANDER -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; - 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; - break; - case FRONTEND_FORK_NONE: - default: - return false; - } - - return true; -} -#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, frontend_wiiu_init, frontend_wiiu_deinit, - frontend_wiiu_exitspawn, - NULL, /* process_args */ - frontend_wiiu_exec, + NULL, /* exitspawn */ + NULL, /* process_args */ + NULL, /* exec */ #ifdef IS_SALAMANDER - NULL, /* set_fork */ + NULL, /* set_fork */ #else - frontend_wiiu_set_fork, + NULL, /* set_fork */ #endif frontend_wiiu_shutdown, - NULL, /* get_name */ - NULL, /* get_os */ + NULL, /* get_name */ + NULL, /* get_os */ frontend_wiiu_get_rating, - NULL, /* content_loaded */ - frontend_wiiu_get_arch, /* get_architecture */ - NULL, /* get_powerstate */ + NULL, /* content_loaded */ + frontend_wiiu_get_arch, /* get_architecture */ + NULL, /* get_powerstate */ frontend_wiiu_parse_drive_list, - NULL, /* get_total_mem */ - NULL, /* get_free_mem */ - NULL, /* install_signal_handler */ - NULL, /* get_signal_handler_state */ - NULL, /* set_signal_handler_state */ - NULL, /* destroy_signal_handler_state */ - NULL, /* attach_console */ - NULL, /* detach_console */ - NULL, /* get_lakka_version */ - NULL, /* set_screen_brightness */ - NULL, /* watch_path_for_changes */ - NULL, /* check_for_path_changes */ - NULL, /* set_sustained_performance_mode */ - NULL, /* get_cpu_model_name */ - NULL, /* get_user_language */ - NULL, /* is_narrator_running */ - NULL, /* accessibility_speak */ - NULL, /* set_gamemode */ - "wiiu", /* ident */ - NULL /* get_video_driver */ + NULL, /* get_total_mem */ + NULL, /* get_free_mem */ + NULL, /* install_signal_handler */ + NULL, /* get_signal_handler_state */ + NULL, /* set_signal_handler_state */ + NULL, /* destroy_signal_handler_state */ + NULL, /* attach_console */ + NULL, /* detach_console */ + NULL, /* get_lakka_version */ + NULL, /* set_screen_brightness */ + NULL, /* watch_path_for_changes */ + NULL, /* check_for_path_changes */ + NULL, /* set_sustained_performance_mode */ + NULL, /* get_cpu_model_name */ + NULL, /* get_user_language */ + NULL, /* is_narrator_running */ + NULL, /* accessibility_speak */ + NULL, /* set_gamemode */ + "wiiu", /* ident */ + NULL /* get_video_driver */ }; /* main() and its supporting functions */ static void main_setup(void); -static void get_arguments(int *argc, char ***argv); #ifndef IS_SALAMANDER static void main_loop(void); #endif static void main_teardown(void); -static void init_network(void); -static void deinit_network(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 void init_logging(void); +static void deinit_logging(void); +static void init_filesystems(void); +static void deinit_filesystems(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 proc_setup(void); +static void proc_exit(void); +static void proc_save_callback(void); -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, /* ... */ -}; - -int main(int argc, char **argv) +int main(int argc, char** argv) { + proc_setup(); main_setup(); - get_arguments(&argc, &argv); #ifdef IS_SALAMANDER - int salamander_main(int argc, char **argv); + int salamander_main(int argc, char** argv); salamander_main(argc, argv); #else rarch_main(argc, argv, NULL); @@ -418,43 +289,17 @@ int main(int argc, char **argv) #endif /* IS_SALAMANDER */ 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 get_arguments(int *argc, char ***argv) -{ - DEBUG_VAR(ARGV_PTR); - if (ARGV_PTR && ((u32)ARGV_PTR < 0x01000000)) - { - struct - { - u32 magic; - u32 argc; - char *argv[3]; - } *param = ARGV_PTR; - - if (param->magic == ARGV_MAGIC) - { - *argc = param->argc; - *argv = param->argv; - } - ARGV_PTR = NULL; - } - - DEBUG_VAR(argc); - DEBUG_VAR(argv[0]); - DEBUG_VAR(argv[1]); - fflush(stdout); -} - static void main_setup(void) { - setup_os_exceptions(); - ProcUIInit(&SaveCallback); - init_network(); + init_os_exceptions(); init_logging(); + init_filesystems(); init_pad_libraries(); verbosity_enable(); fflush(stdout); @@ -463,25 +308,48 @@ static void main_setup(void) static void main_teardown(void) { deinit_pad_libraries(); - ProcUIShutdown(); + deinit_filesystems(); deinit_logging(); - deinit_network(); + deinit_os_exceptions(); +} + +static void proc_setup(void) +{ + OSDynLoad_Module rpx_module; + // Explicitly detect Aroma + if (OSDynLoad_Acquire("homebrew_rpx_loader", &rpx_module) == OS_DYNLOAD_OK) + { + in_aroma = true; + OSDynLoad_Release(rpx_module); + } + + ProcUIInit(&proc_save_callback); +} + +static void proc_exit(void) +{ + ProcUIShutdown(); +} + +static void proc_save_callback(void) +{ + OSSavesDone_ReadyToRelease(); } #ifndef IS_SALAMANDER -static bool swap_is_pending(void *start_time) +static bool swap_is_pending(void* start_time) { uint32_t swap_count, flip_count; - OSTime last_flip, last_vsync; + OSTime last_flip, last_vsync; GX2GetSwapStatus(&swap_count, &flip_count, &last_flip, &last_vsync); - return last_vsync < *(OSTime *)start_time; + return last_vsync < *(OSTime*)start_time; } static void main_loop(void) { OSTime start_time; - int status; + int status; for (;;) { @@ -501,51 +369,24 @@ static void main_loop(void) } #endif -static void SaveCallback(void) -{ - OSSavesDone_ReadyToRelease(); -} - - -static void init_network(void) -{ - ACInitialize(); - ACConnect(); -#ifdef IS_SALAMANDER - socket_lib_init(); -#else - network_init(); -#endif /* IS_SALAMANDER */ -} - -static void deinit_network(void) -{ - ACClose(); - ACFinalize(); -} - -int getBroadcastAddress(ACIpAddress *broadcast) +static devoptab_t dotab_stdout = { - ACIpAddress myIp, mySubnet; - ACResult result; - - if (!broadcast) - return -1; - - result = ACGetAssignedAddress(&myIp); - if (result < 0) - return -1; - result = ACGetAssignedSubnet(&mySubnet); - if (result < 0) - return -1; - - *broadcast = myIp | (~mySubnet); - return 0; -} + "stdout_whb", /* device name */ + 0, /* size of file structure */ + NULL, /* device open */ + NULL, /* device close */ + wiiu_log_write, /* device write */ + NULL, /* ... */ +}; static void init_logging(void) { - wiiu_log_init(PC_DEVELOPMENT_TCP_PORT); + if (!WHBLogModuleInit()) + { + WHBLogUdpInit(); + WHBLogCafeInit(); + } + devoptab_list[STD_OUT] = &dotab_stdout; devoptab_list[STD_ERR] = &dotab_stdout; } @@ -555,59 +396,30 @@ static void deinit_logging(void) fflush(stdout); fflush(stderr); - wiiu_log_deinit(); + WHBLogModuleDeinit(); + WHBLogUdpDeinit(); + WHBLogCafeDeinit(); } -static int broadcast_init(int port) +static ssize_t wiiu_log_write(struct _reent* r, + void* fd, const char* ptr, size_t len) { - 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); - - return 0; -} - -static void wiiu_log_init(int port) -{ - wiiu_log_lock = 0; - - if (wiiu_log_socket >= 0) - return; - - if (broadcast_init(port) < 0) - return; - - wiiu_log_socket = socket(AF_INET, SOCK_DGRAM, 0); - - if (wiiu_log_socket < 0) - return; + // 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; - 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); + snprintf(linebuf + linebuf_pos, sizeof(linebuf) - linebuf_pos - 1, "%.*s", + len, ptr); + linebuf_pos = strlen(linebuf); - if ( bind(wiiu_log_socket, (struct sockaddr *)&connect_addr, sizeof(connect_addr)) < 0) + if (linebuf[linebuf_pos - 1] == '\n' || linebuf_pos >= sizeof(linebuf) - 2) { - socketclose(wiiu_log_socket); - wiiu_log_socket = -1; - return; + WHBLogWrite(linebuf); + linebuf_pos = 0; } -} -static void wiiu_log_deinit(void) -{ - if (wiiu_log_socket >= 0) - { - socketclose(wiiu_log_socket); - wiiu_log_socket = -1; - } + return (ssize_t)len; } static void init_pad_libraries(void) @@ -626,53 +438,55 @@ static void deinit_pad_libraries(void) #endif /* IS_SALAMANDER */ } -/* logging routines */ - -void net_print(const char *str) -{ - wiiu_log_write(NULL, 0, str, strlen(str)); -} - -void net_print_exp(const char *str) +static void init_filesystems(void) { - sendto(wiiu_log_socket, str, strlen(str), 0, (struct sockaddr *)&broadcast, sizeof(broadcast)); -} - -/* 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 +#if defined(HAVE_LIBMOCHA) + MochaUtilsStatus mocha_res; -static ssize_t wiiu_log_write(struct _reent *r, - void *fd, const char *ptr, size_t len) -{ - int remaining; - if (wiiu_log_socket < 0) - return len; - - while (wiiu_log_lock) - OSSleepTicks(((248625000 / 4)) / 1000); + mocha_res = Mocha_InitLibrary(); + DEBUG_VAR(mocha_res); + if (mocha_res != MOCHA_RESULT_SUCCESS) + return; - wiiu_log_lock = 1; + Mocha_MountFS("storage_usb", NULL, "/vol/storage_usb01"); + have_wfs_usb = exists(WIIU_STORAGE_USB_PATH); + DEBUG_VAR(have_wfs_usb); - remaining = len; +#if defined(HAVE_LIBFAT) + if (!in_aroma) + have_libfat_sdcard = fatMountSimple("sd", &Mocha_sdio_disc_interface); + else + Mocha_MountFS("sd", NULL, "/vol/external01"); + DEBUG_VAR(have_libfat_sdcard); - while (remaining > 0) - { - int block = remaining < DGRAM_SIZE ? remaining : DGRAM_SIZE; - int sent = sendto(wiiu_log_socket, ptr, block, 0, - (struct sockaddr *)&broadcast, sizeof(broadcast)); + have_libfat_usb = fatMountSimple("usb", &Mocha_usb_disc_interface); + DEBUG_VAR(have_libfat_usb); +#else + Mocha_MountFS("sd", NULL, "/vol/external01"); +#endif +#endif +} - if (sent < 0) - break; +static void deinit_filesystems(void) +{ +#if defined(HAVE_LIBMOCHA) + if (have_wfs_usb) + Mocha_UnmountFS("usb"); - remaining -= sent; - ptr += sent; - } +#if defined(HAVE_LIBFAT) + if (have_libfat_usb) + fatUnmount("usb"); + if (have_libfat_sdcard) + fatUnmount("sd"); + else if (in_aroma) + Mocha_UnmountFS("sd"); - wiiu_log_lock = 0; + Mocha_sdio_disc_interface.shutdown(); + Mocha_usb_disc_interface.shutdown(); +#else + Mocha_UnmountFS("sd"); +#endif - return len; + Mocha_DeInitLibrary(); +#endif } diff --git a/gfx/drivers/gx2_gfx.c b/gfx/drivers/gx2_gfx.c index 381750f1d505..4c26eebac21e 100644 --- a/gfx/drivers/gx2_gfx.c +++ b/gfx/drivers/gx2_gfx.c @@ -19,8 +19,20 @@ #include #include -#include -#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include #include @@ -286,7 +298,7 @@ static bool gx2_set_shader(void *data, wiiu->pass[i].vs_ubos[j] = MEM2_alloc(wiiu->pass[i].gfd->vs->uniformBlocks[j].size, GX2_UNIFORM_BLOCK_ALIGNMENT); memset(wiiu->pass[i].vs_ubos[j], 0, wiiu->pass[i].gfd->vs->uniformBlocks[j].size); - GX2Invalidate(GX2_INVALIDATE_MODE_CPU_UNIFORM_BLOCK, wiiu->pass[i].vs_ubos[j], + GX2Invalidate(GX2_INVALIDATE_MODE_CPU | GX2_INVALIDATE_MODE_UNIFORM_BLOCK, wiiu->pass[i].vs_ubos[j], wiiu->pass[i].gfd->vs->uniformBlocks[j].size); } @@ -295,7 +307,7 @@ static bool gx2_set_shader(void *data, wiiu->pass[i].ps_ubos[j] = MEM2_alloc(wiiu->pass[i].gfd->ps->uniformBlocks[j].size, GX2_UNIFORM_BLOCK_ALIGNMENT); memset(wiiu->pass[i].ps_ubos[j], 0, wiiu->pass[i].gfd->ps->uniformBlocks[j].size); - GX2Invalidate(GX2_INVALIDATE_MODE_CPU_UNIFORM_BLOCK, wiiu->pass[i].ps_ubos[j], + GX2Invalidate(GX2_INVALIDATE_MODE_CPU | GX2_INVALIDATE_MODE_UNIFORM_BLOCK, wiiu->pass[i].ps_ubos[j], wiiu->pass[i].gfd->ps->uniformBlocks[j].size); } } @@ -592,7 +604,7 @@ static void gfx_display_wiiu_draw_pipeline( else wiiu->menu_shader_ubo->time += 0.01f; - GX2Invalidate(GX2_INVALIDATE_MODE_CPU_UNIFORM_BLOCK, wiiu->menu_shader_ubo, sizeof(*wiiu->menu_shader_ubo)); + GX2Invalidate(GX2_INVALIDATE_MODE_CPU | GX2_INVALIDATE_MODE_UNIFORM_BLOCK, wiiu->menu_shader_ubo, sizeof(*wiiu->menu_shader_ubo)); GX2SetVertexUniformBlock(1, sizeof(*wiiu->menu_shader_ubo), wiiu->menu_shader_ubo); GX2SetPixelUniformBlock(1, sizeof(*wiiu->menu_shader_ubo), wiiu->menu_shader_ubo); } @@ -684,7 +696,7 @@ static void* gx2_font_init(void* data, const char* font_path, font->ubo_tex = MEM1_alloc(sizeof(*font->ubo_tex), GX2_UNIFORM_BLOCK_ALIGNMENT); font->ubo_tex->width = font->texture.surface.width; font->ubo_tex->height = font->texture.surface.height; - GX2Invalidate(GX2_INVALIDATE_MODE_CPU_UNIFORM_BLOCK, font->ubo_tex, + GX2Invalidate(GX2_INVALIDATE_MODE_CPU | GX2_INVALIDATE_MODE_UNIFORM_BLOCK, font->ubo_tex, sizeof(*font->ubo_tex)); return font; @@ -1034,7 +1046,7 @@ static void gx2_set_projection(wiiu_video_t *wiiu) MAT_ELEM_4X4(rot, 1, 0) = sine; MAT_ELEM_4X4(rot, 1, 1) = cosine; matrix_4x4_multiply((*wiiu->ubo_mvp), rot, proj); - GX2Invalidate(GX2_INVALIDATE_MODE_CPU_UNIFORM_BLOCK, wiiu->ubo_mvp, sizeof(*wiiu->ubo_mvp)); + GX2Invalidate(GX2_INVALIDATE_MODE_CPU | GX2_INVALIDATE_MODE_UNIFORM_BLOCK, wiiu->ubo_mvp, sizeof(*wiiu->ubo_mvp)); } static void gx2_update_viewport(wiiu_video_t *wiiu) @@ -1199,12 +1211,12 @@ static void *gx2_init(const video_info_t *video, wiiu->ubo_vp = MEM1_alloc(sizeof(*wiiu->ubo_vp), GX2_UNIFORM_BLOCK_ALIGNMENT); wiiu->ubo_vp->width = wiiu->color_buffer.surface.width; wiiu->ubo_vp->height = wiiu->color_buffer.surface.height; - GX2Invalidate(GX2_INVALIDATE_MODE_CPU_UNIFORM_BLOCK, wiiu->ubo_vp, sizeof(*wiiu->ubo_vp)); + GX2Invalidate(GX2_INVALIDATE_MODE_CPU | GX2_INVALIDATE_MODE_UNIFORM_BLOCK, wiiu->ubo_vp, sizeof(*wiiu->ubo_vp)); wiiu->ubo_tex = MEM1_alloc(sizeof(*wiiu->ubo_tex), GX2_UNIFORM_BLOCK_ALIGNMENT); wiiu->ubo_tex->width = 1.0; wiiu->ubo_tex->height = 1.0; - GX2Invalidate(GX2_INVALIDATE_MODE_CPU_UNIFORM_BLOCK, wiiu->ubo_tex, sizeof(*wiiu->ubo_tex)); + GX2Invalidate(GX2_INVALIDATE_MODE_CPU | GX2_INVALIDATE_MODE_UNIFORM_BLOCK, wiiu->ubo_tex, sizeof(*wiiu->ubo_tex)); wiiu->ubo_mvp = MEM1_alloc(sizeof(*wiiu->ubo_mvp), GX2_UNIFORM_BLOCK_ALIGNMENT); gx2_set_projection(wiiu); @@ -1963,7 +1975,7 @@ static void gx2_update_uniform_block(wiiu_video_t *wiiu, } } - GX2Invalidate(GX2_INVALIDATE_MODE_CPU_UNIFORM_BLOCK, ubo, size); + GX2Invalidate(GX2_INVALIDATE_MODE_CPU | GX2_INVALIDATE_MODE_UNIFORM_BLOCK, ubo, size); } static bool gx2_frame(void *data, const void *frame, @@ -1994,7 +2006,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..25f48c4acd6d 100644 --- a/gfx/drivers/gx2_shaders/bokeh.c +++ b/gfx/drivers/gx2_shaders/bokeh.c @@ -16,11 +16,13 @@ #include #include #include -#include +#include "gx2/ra_shaders.h" #include "gx2_shader_inl.h" #include "menu_shaders.h" +#include +#include -__attribute__((aligned(GX2_SHADER_ALIGNMENT))) +__attribute__((aligned(GX2_SHADER_PROGRAM_ALIGNMENT))) static struct { u64 cf[32]; @@ -62,7 +64,7 @@ static struct }, }; -__attribute__((aligned(GX2_SHADER_ALIGNMENT))) +__attribute__((aligned(GX2_SHADER_PROGRAM_ALIGNMENT))) static struct { u64 cf[32]; @@ -709,13 +711,13 @@ static struct }, }; -static GX2AttribVar attributes[] = +static GX2AttribVar attributes[2] = { { "Position", GX2_SHADER_VAR_TYPE_FLOAT4, 0, 0}, { "TexCoord", GX2_SHADER_VAR_TYPE_FLOAT2, 0, 1}, }; -static GX2AttribStream attribute_stream[] = +static GX2AttribStream attribute_stream[2] = { {0, 0, 0, GX2_ATTRIB_FORMAT_FLOAT_32_32, GX2_ATTRIB_INDEX_PER_VERTEX, 0, GX2_COMP_SEL(_x, _y, _0, _1), GX2_ENDIAN_SWAP_DEFAULT}, @@ -723,16 +725,16 @@ static GX2AttribStream attribute_stream[] = GX2_ATTRIB_INDEX_PER_VERTEX, 0, GX2_COMP_SEL(_x, _y, _0, _0), GX2_ENDIAN_SWAP_DEFAULT}, }; -static GX2SamplerVar samplers[] = +static GX2SamplerVar samplers[1] = { { "Source", GX2_SAMPLER_VAR_TYPE_SAMPLER_2D, 0 }, }; -static GX2UniformBlock uniform_blocks[] = { +static GX2UniformBlock uniform_blocks[1] = { {"UBO", 1, 96} }; -static GX2UniformVar uniform_vars[] = { +static GX2UniformVar uniform_vars[3] = { {"global.MVP", GX2_SHADER_VAR_TYPE_FLOAT, 1, 0, 0}, {"global.OutputSize", GX2_SHADER_VAR_TYPE_FLOAT, 1, 16, 0}, {"global.time", GX2_SHADER_VAR_TYPE_FLOAT, 1, 20, 0}, diff --git a/gfx/drivers/gx2_shaders/frame.c b/gfx/drivers/gx2_shaders/frame.c index ad9d1b416b04..2f6ddaf068b6 100644 --- a/gfx/drivers/gx2_shaders/frame.c +++ b/gfx/drivers/gx2_shaders/frame.c @@ -16,11 +16,12 @@ #include #include #include -#include +#include "gx2/ra_shaders.h" #include "gx2_shader_inl.h" #include "frame.h" +#include -__attribute__((aligned(GX2_SHADER_ALIGNMENT))) +__attribute__((aligned(GX2_SHADER_PROGRAM_ALIGNMENT))) static struct { u64 cf[32]; @@ -60,7 +61,7 @@ static struct } }; -__attribute__((aligned(GX2_SHADER_ALIGNMENT))) +__attribute__((aligned(GX2_SHADER_PROGRAM_ALIGNMENT))) static struct { u64 cf[16]; @@ -78,13 +79,13 @@ ps_program = } }; -static GX2AttribVar attributes[] = +static GX2AttribVar attributes[2] = { { "Position", GX2_SHADER_VAR_TYPE_FLOAT4, 0, 0}, { "TexCoord", GX2_SHADER_VAR_TYPE_FLOAT2, 0, 1}, }; -static GX2AttribStream attribute_stream[] = +static GX2AttribStream attribute_stream[2] = { {0, 0, offsetof(frame_vertex_t, pos), GX2_ATTRIB_FORMAT_FLOAT_32_32, GX2_ATTRIB_INDEX_PER_VERTEX, 0, GX2_COMP_SEL(_x, _y, _0, _1), GX2_ENDIAN_SWAP_DEFAULT}, @@ -92,17 +93,17 @@ static GX2AttribStream attribute_stream[] = GX2_ATTRIB_INDEX_PER_VERTEX, 0, GX2_COMP_SEL(_x, _y, _0, _0), GX2_ENDIAN_SWAP_DEFAULT}, }; -static GX2SamplerVar samplers[] = +static GX2SamplerVar samplers[1] = { { "Source", GX2_SAMPLER_VAR_TYPE_SAMPLER_2D, 0 }, }; -static GX2UniformBlock uniform_blocks[] = { +static GX2UniformBlock uniform_blocks[1] = { {"UBO", 1, 64} }; -static GX2UniformVar uniform_vars[] = { - {"global.MVP", GX2_SHADER_VAR_TYPE_MATRIX4X4, 1, 0, 0}, +static GX2UniformVar uniform_vars[1] = { + {"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..c390772bee75 100644 --- a/gfx/drivers/gx2_shaders/ribbon.c +++ b/gfx/drivers/gx2_shaders/ribbon.c @@ -16,11 +16,12 @@ #include #include #include -#include +#include "gx2/ra_shaders.h" #include "gx2_shader_inl.h" #include "menu_shaders.h" +#include -__attribute__((aligned(GX2_SHADER_ALIGNMENT))) +__attribute__((aligned(GX2_SHADER_PROGRAM_ALIGNMENT))) static struct { u64 cf[32]; @@ -243,7 +244,7 @@ static struct } }; -__attribute__((aligned(GX2_SHADER_ALIGNMENT))) +__attribute__((aligned(GX2_SHADER_PROGRAM_ALIGNMENT))) static struct { u64 cf[32]; @@ -307,27 +308,27 @@ ps_program = } }; -static GX2AttribVar attributes[] = +static GX2AttribVar attributes[1] = { { "VertexCoord", GX2_SHADER_VAR_TYPE_FLOAT2, 0, 0}, }; -static GX2AttribStream attribute_stream[] = +static GX2AttribStream attribute_stream[1] = { {0, 0, 0, GX2_ATTRIB_FORMAT_FLOAT_32_32, GX2_ATTRIB_INDEX_PER_VERTEX, 0, GX2_COMP_SEL(_x, _y, _0, _1), GX2_ENDIAN_SWAP_DEFAULT} }; -static GX2SamplerVar samplers[] = +static GX2SamplerVar samplers[1] = { { "Source", GX2_SAMPLER_VAR_TYPE_SAMPLER_2D, 0 }, }; -static GX2UniformBlock uniform_blocks[] = { +static GX2UniformBlock uniform_blocks[1] = { {"UBO", 1, 16} }; -static GX2UniformVar uniform_vars[] = { +static GX2UniformVar uniform_vars[1] = { {"constants.time", GX2_SHADER_VAR_TYPE_FLOAT, 1, 0, 0}, }; diff --git a/gfx/drivers/gx2_shaders/ribbon_simple.c b/gfx/drivers/gx2_shaders/ribbon_simple.c index 214f6ab3d2bd..f6377ce6f3f8 100644 --- a/gfx/drivers/gx2_shaders/ribbon_simple.c +++ b/gfx/drivers/gx2_shaders/ribbon_simple.c @@ -16,11 +16,12 @@ #include #include #include -#include +#include "gx2/ra_shaders.h" #include "gx2_shader_inl.h" #include "menu_shaders.h" +#include -__attribute__((aligned(GX2_SHADER_ALIGNMENT))) +__attribute__((aligned(GX2_SHADER_PROGRAM_ALIGNMENT))) static struct { u64 cf[32]; @@ -167,7 +168,7 @@ static struct }, }; -__attribute__((aligned(GX2_SHADER_ALIGNMENT))) +__attribute__((aligned(GX2_SHADER_PROGRAM_ALIGNMENT))) static struct { u64 cf[32]; @@ -188,13 +189,13 @@ static struct }, }; -static GX2AttribVar attributes[] = +static GX2AttribVar attributes[2] = { { "Position", GX2_SHADER_VAR_TYPE_FLOAT4, 0, 0}, { "TexCoord", GX2_SHADER_VAR_TYPE_FLOAT2, 0, 1}, }; -static GX2AttribStream attribute_stream[] = +static GX2AttribStream attribute_stream[2] = { {0, 0, 0, GX2_ATTRIB_FORMAT_FLOAT_32_32, GX2_ATTRIB_INDEX_PER_VERTEX, 0, GX2_COMP_SEL(_x, _y, _0, _1), GX2_ENDIAN_SWAP_DEFAULT}, @@ -202,16 +203,16 @@ static GX2AttribStream attribute_stream[] = GX2_ATTRIB_INDEX_PER_VERTEX, 0, GX2_COMP_SEL(_x, _y, _0, _0), GX2_ENDIAN_SWAP_DEFAULT}, }; -static GX2SamplerVar samplers[] = +static GX2SamplerVar samplers[1] = { { "Source", GX2_SAMPLER_VAR_TYPE_SAMPLER_2D, 0 }, }; -static GX2UniformBlock uniform_blocks[] = { +static GX2UniformBlock uniform_blocks[1] = { {"UBO", 1, 96} }; -static GX2UniformVar uniform_vars[] = { +static GX2UniformVar uniform_vars[3] = { {"global.MVP", GX2_SHADER_VAR_TYPE_FLOAT, 1, 0, 0}, {"global.OutputSize", GX2_SHADER_VAR_TYPE_FLOAT, 1, 16, 0}, {"global.time", GX2_SHADER_VAR_TYPE_FLOAT, 1, 20, 0}, diff --git a/gfx/drivers/gx2_shaders/snow.c b/gfx/drivers/gx2_shaders/snow.c index 455facee0791..9378d7bc37cf 100644 --- a/gfx/drivers/gx2_shaders/snow.c +++ b/gfx/drivers/gx2_shaders/snow.c @@ -16,11 +16,12 @@ #include #include #include -#include +#include "gx2/ra_shaders.h" #include "gx2_shader_inl.h" #include "menu_shaders.h" +#include -__attribute__((aligned(GX2_SHADER_ALIGNMENT))) +__attribute__((aligned(GX2_SHADER_PROGRAM_ALIGNMENT))) static struct { u64 cf[32]; @@ -62,7 +63,7 @@ static struct }, }; -__attribute__((aligned(GX2_SHADER_ALIGNMENT))) +__attribute__((aligned(GX2_SHADER_PROGRAM_ALIGNMENT))) static struct { u64 cf[32]; @@ -1374,13 +1375,13 @@ static struct }, }; -static GX2AttribVar attributes[] = +static GX2AttribVar attributes[2] = { { "Position", GX2_SHADER_VAR_TYPE_FLOAT4, 0, 0}, { "TexCoord", GX2_SHADER_VAR_TYPE_FLOAT2, 0, 1}, }; -static GX2AttribStream attribute_stream[] = +static GX2AttribStream attribute_stream[2] = { {0, 0, 0, GX2_ATTRIB_FORMAT_FLOAT_32_32, GX2_ATTRIB_INDEX_PER_VERTEX, 0, GX2_COMP_SEL(_x, _y, _0, _1), GX2_ENDIAN_SWAP_DEFAULT}, @@ -1388,16 +1389,16 @@ static GX2AttribStream attribute_stream[] = GX2_ATTRIB_INDEX_PER_VERTEX, 0, GX2_COMP_SEL(_x, _y, _0, _0), GX2_ENDIAN_SWAP_DEFAULT}, }; -static GX2SamplerVar samplers[] = +static GX2SamplerVar samplers[1] = { { "Source", GX2_SAMPLER_VAR_TYPE_SAMPLER_2D, 0 }, }; -static GX2UniformBlock uniform_blocks[] = { +static GX2UniformBlock uniform_blocks[1] = { {"UBO", 1, 96} }; -static GX2UniformVar uniform_vars[] = { +static GX2UniformVar uniform_vars[3] = { {"global.MVP", GX2_SHADER_VAR_TYPE_FLOAT, 1, 0, 0}, {"global.OutputSize", GX2_SHADER_VAR_TYPE_FLOAT, 1, 16, 0}, {"global.time", GX2_SHADER_VAR_TYPE_FLOAT, 1, 20, 0}, diff --git a/gfx/drivers/gx2_shaders/snow_simple.c b/gfx/drivers/gx2_shaders/snow_simple.c index 7f6715f458ee..4531290a1050 100644 --- a/gfx/drivers/gx2_shaders/snow_simple.c +++ b/gfx/drivers/gx2_shaders/snow_simple.c @@ -16,11 +16,12 @@ #include #include #include -#include +#include "gx2/ra_shaders.h" #include "gx2_shader_inl.h" #include "menu_shaders.h" +#include -__attribute__((aligned(GX2_SHADER_ALIGNMENT))) +__attribute__((aligned(GX2_SHADER_PROGRAM_ALIGNMENT))) static struct { u64 cf[32]; @@ -62,7 +63,7 @@ static struct }, }; -__attribute__((aligned(GX2_SHADER_ALIGNMENT))) +__attribute__((aligned(GX2_SHADER_PROGRAM_ALIGNMENT))) static struct { u64 cf[32]; @@ -1374,13 +1375,13 @@ static struct }, }; -static GX2AttribVar attributes[] = +static GX2AttribVar attributes[2] = { { "Position", GX2_SHADER_VAR_TYPE_FLOAT4, 0, 0}, { "TexCoord", GX2_SHADER_VAR_TYPE_FLOAT2, 0, 1}, }; -static GX2AttribStream attribute_stream[] = +static GX2AttribStream attribute_stream[2] = { {0, 0, 0, GX2_ATTRIB_FORMAT_FLOAT_32_32, GX2_ATTRIB_INDEX_PER_VERTEX, 0, GX2_COMP_SEL(_x, _y, _0, _1), GX2_ENDIAN_SWAP_DEFAULT}, @@ -1388,16 +1389,16 @@ static GX2AttribStream attribute_stream[] = GX2_ATTRIB_INDEX_PER_VERTEX, 0, GX2_COMP_SEL(_x, _y, _0, _0), GX2_ENDIAN_SWAP_DEFAULT}, }; -static GX2SamplerVar samplers[] = +static GX2SamplerVar samplers[1] = { { "Source", GX2_SAMPLER_VAR_TYPE_SAMPLER_2D, 0 }, }; -static GX2UniformBlock uniform_blocks[] = { +static GX2UniformBlock uniform_blocks[1] = { {"UBO", 1, 96} }; -static GX2UniformVar uniform_vars[] = { +static GX2UniformVar uniform_vars[3] = { {"global.MVP", GX2_SHADER_VAR_TYPE_FLOAT, 1, 0, 0}, {"global.OutputSize", GX2_SHADER_VAR_TYPE_FLOAT, 1, 16, 0}, {"global.time", GX2_SHADER_VAR_TYPE_FLOAT, 1, 20, 0}, diff --git a/gfx/drivers/gx2_shaders/snowflake.c b/gfx/drivers/gx2_shaders/snowflake.c index b01bbcf1e6c9..2e156b743545 100644 --- a/gfx/drivers/gx2_shaders/snowflake.c +++ b/gfx/drivers/gx2_shaders/snowflake.c @@ -16,11 +16,12 @@ #include #include #include -#include +#include "gx2/ra_shaders.h" #include "gx2_shader_inl.h" #include "menu_shaders.h" +#include -__attribute__((aligned(GX2_SHADER_ALIGNMENT))) +__attribute__((aligned(GX2_SHADER_PROGRAM_ALIGNMENT))) static struct { u64 cf[32]; @@ -62,7 +63,7 @@ static struct }, }; -__attribute__((aligned(GX2_SHADER_ALIGNMENT))) +__attribute__((aligned(GX2_SHADER_PROGRAM_ALIGNMENT))) static struct { u64 cf[32]; @@ -554,13 +555,13 @@ static struct }, }; -static GX2AttribVar attributes[] = +static GX2AttribVar attributes[2] = { { "Position", GX2_SHADER_VAR_TYPE_FLOAT4, 0, 0}, { "TexCoord", GX2_SHADER_VAR_TYPE_FLOAT2, 0, 1}, }; -static GX2AttribStream attribute_stream[] = +static GX2AttribStream attribute_stream[2] = { {0, 0, 0, GX2_ATTRIB_FORMAT_FLOAT_32_32, GX2_ATTRIB_INDEX_PER_VERTEX, 0, GX2_COMP_SEL(_x, _y, _0, _1), GX2_ENDIAN_SWAP_DEFAULT}, @@ -568,16 +569,16 @@ static GX2AttribStream attribute_stream[] = GX2_ATTRIB_INDEX_PER_VERTEX, 0, GX2_COMP_SEL(_x, _y, _0, _0), GX2_ENDIAN_SWAP_DEFAULT}, }; -static GX2SamplerVar samplers[] = +static GX2SamplerVar samplers[1] = { { "Source", GX2_SAMPLER_VAR_TYPE_SAMPLER_2D, 0 }, }; -static GX2UniformBlock uniform_blocks[] = { +static GX2UniformBlock uniform_blocks[1] = { {"UBO", 1, 96} }; -static GX2UniformVar uniform_vars[] = { +static GX2UniformVar uniform_vars[3] = { {"global.MVP", GX2_SHADER_VAR_TYPE_FLOAT, 1, 0, 0}, {"global.OutputSize", GX2_SHADER_VAR_TYPE_FLOAT, 1, 16, 0}, {"global.time", GX2_SHADER_VAR_TYPE_FLOAT, 1, 20, 0}, diff --git a/gfx/drivers/gx2_shaders/sprite.c b/gfx/drivers/gx2_shaders/sprite.c index 4d729c70b43c..4f4556184f67 100644 --- a/gfx/drivers/gx2_shaders/sprite.c +++ b/gfx/drivers/gx2_shaders/sprite.c @@ -16,11 +16,12 @@ #include #include #include -#include +#include "gx2/ra_shaders.h" #include "gx2_shader_inl.h" #include "sprite.h" +#include -__attribute__((aligned(GX2_SHADER_ALIGNMENT))) +__attribute__((aligned(GX2_SHADER_PROGRAM_ALIGNMENT))) static struct { u64 cf[32]; @@ -71,7 +72,7 @@ static struct } }; -__attribute__((aligned(GX2_SHADER_ALIGNMENT))) +__attribute__((aligned(GX2_SHADER_PROGRAM_ALIGNMENT))) static struct { u64 cf[32]; /* @0 */ @@ -97,7 +98,7 @@ static struct } }; -__attribute__((aligned(GX2_SHADER_ALIGNMENT))) +__attribute__((aligned(GX2_SHADER_PROGRAM_ALIGNMENT))) static struct { u64 cf[32]; /* @0 */ @@ -175,7 +176,7 @@ static struct } }; -__attribute__((aligned(GX2_SHADER_ALIGNMENT))) +__attribute__((aligned(GX2_SHADER_PROGRAM_ALIGNMENT))) static struct { u64 cf[16]; /* @0 */ @@ -195,14 +196,14 @@ static struct } }; -static GX2AttribVar attributes[] = +static GX2AttribVar attributes[3] = { {"position", GX2_SHADER_VAR_TYPE_FLOAT4, 0, 0}, {"coords", GX2_SHADER_VAR_TYPE_FLOAT4, 0, 1}, {"color", GX2_SHADER_VAR_TYPE_FLOAT4, 0, 2}, }; -static GX2AttribStream attribute_stream[] = +static GX2AttribStream attribute_stream[3] = { {0, 0, offsetof(sprite_vertex_t, pos), GX2_ATTRIB_FORMAT_FLOAT_32_32_32_32, GX2_ATTRIB_INDEX_PER_VERTEX, 0, GX2_COMP_SEL(_x, _y, _z, _w), GX2_ENDIAN_SWAP_DEFAULT}, @@ -212,18 +213,18 @@ static GX2AttribStream attribute_stream[] = GX2_ATTRIB_INDEX_PER_VERTEX, 0, GX2_COMP_SEL(_x, _y, _z, _w), GX2_ENDIAN_SWAP_DEFAULT}, }; -static GX2SamplerVar samplers[] = +static GX2SamplerVar samplers[1] = { { "s", GX2_SAMPLER_VAR_TYPE_SAMPLER_2D, 0 }, }; -static GX2UniformBlock uniform_blocks[] = +static GX2UniformBlock uniform_blocks[2] = { {"UBO_vp", 1, sizeof(GX2_vec2)}, {"UBO_tex", 2, sizeof(GX2_vec2)}, }; -static GX2UniformVar uniform_vars[] = +static GX2UniformVar uniform_vars[2] = { {"vp_size", GX2_SHADER_VAR_TYPE_FLOAT2, 1, 0, 0}, {"tex_size", GX2_SHADER_VAR_TYPE_FLOAT2, 1, 0, 1}, diff --git a/gfx/drivers/gx2_shaders/tex.c b/gfx/drivers/gx2_shaders/tex.c index 5a8b7ede357b..d282fb83f771 100644 --- a/gfx/drivers/gx2_shaders/tex.c +++ b/gfx/drivers/gx2_shaders/tex.c @@ -16,11 +16,13 @@ #include #include #include -#include +#include "gx2/ra_shaders.h" #include "gx2_shader_inl.h" #include "tex.h" +#include +#include -__attribute__((aligned(GX2_SHADER_ALIGNMENT))) +__attribute__((aligned(GX2_SHADER_PROGRAM_ALIGNMENT))) static struct { u64 cf[32]; @@ -59,7 +61,7 @@ static struct } }; -__attribute__((aligned(GX2_SHADER_ALIGNMENT))) +__attribute__((aligned(GX2_SHADER_PROGRAM_ALIGNMENT))) static struct { u64 cf[32]; @@ -86,14 +88,14 @@ ps_program = } }; -static GX2AttribVar attributes[] = +static GX2AttribVar attributes[3] = { { "position", GX2_SHADER_VAR_TYPE_FLOAT2, 0, 0}, { "tex_coord", GX2_SHADER_VAR_TYPE_FLOAT2, 0, 1}, { "color", GX2_SHADER_VAR_TYPE_FLOAT4, 0, 2}, }; -static GX2AttribStream attribute_stream[] = +static GX2AttribStream attribute_stream[3] = { {0, 0, offsetof(tex_shader_vertex_t, pos), GX2_ATTRIB_FORMAT_FLOAT_32_32, GX2_ATTRIB_INDEX_PER_VERTEX, 0, GX2_COMP_SEL(_x, _y, _0, _1), GX2_ENDIAN_SWAP_DEFAULT}, @@ -103,17 +105,17 @@ static GX2AttribStream attribute_stream[] = GX2_ATTRIB_INDEX_PER_VERTEX, 0, GX2_COMP_SEL(_x, _y, _z, _w), GX2_ENDIAN_SWAP_DEFAULT}, }; -static GX2SamplerVar samplers[] = +static GX2SamplerVar samplers[1] = { { "s", GX2_SAMPLER_VAR_TYPE_SAMPLER_2D, 0 }, }; -static GX2UniformBlock uniform_blocks[] = { +static GX2UniformBlock uniform_blocks[1] = { {"UBO", 1, 64} }; -static GX2UniformVar uniform_vars[] = { - {"global.MVP", GX2_SHADER_VAR_TYPE_MATRIX4X4, 1, 0, 0}, +static GX2UniformVar uniform_vars[1] = { + {"global.MVP", GX2_SHADER_VAR_TYPE_FLOAT4X4, 1, 0, 0}, }; GX2Shader tex_shader = diff --git a/gfx/drivers_font_renderer/stb_unicode.c b/gfx/drivers_font_renderer/stb_unicode.c index 7ed6bd6c2d67..74efc4479ed8 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" @@ -172,7 +172,7 @@ static const struct font_glyph *font_renderer_stb_unicode_get_glyph( * *nearest* integer */ glyph_advance_x = (float)advance_width * self->scale_factor; atlas_slot->glyph.advance_x = (int)((glyph_advance_x > 0.0f) - ? (glyph_advance_x + 0.5f) + ? (glyph_advance_x + 0.5f) : (glyph_advance_x - 0.5f)); /* advance_y is always zero */ atlas_slot->glyph.advance_y = 0; @@ -185,7 +185,7 @@ static const struct font_glyph *font_renderer_stb_unicode_get_glyph( * to the nearest integer */ glyph_draw_offset_y = (float)(-y1) * self->scale_factor; atlas_slot->glyph.draw_offset_y = (int)((glyph_draw_offset_y < 0.0f) - ? floor((double)glyph_draw_offset_y) + ? floor((double)glyph_draw_offset_y) : ceil((double)glyph_draw_offset_y)); self->atlas.dirty = true; @@ -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 8a7ed23f0407..f2ef105996d3 100644 --- a/input/drivers/wiiu_input.c +++ b/input/drivers/wiiu_input.c @@ -21,8 +21,8 @@ #include #include -#include -#include +#include <../../wiiu/include/nsyskbd/ra_nsyskbd.h> +#include <../../wiiu/include/vpad/ra_input.h> #ifdef HAVE_CONFIG_H #include "../../config.h" @@ -97,7 +97,7 @@ static int16_t wiiu_input_state( unsigned idx, unsigned id) { - if (!(port < DEFAULT_MAX_PADS) || !binds || !binds[port]) + if (!(port < DEFAULT_MAX_PADS) || !binds) return 0; switch (device) diff --git a/input/drivers_hid/wiiu_hid.c b/input/drivers_hid/wiiu_hid.c index fcf95095c356..f0b2f0076f52 100644 --- a/input/drivers_hid/wiiu_hid.c +++ b/input/drivers_hid/wiiu_hid.c @@ -16,7 +16,7 @@ #include #include "../include/wiiu/hid.h" -#include +#include #include /* TODO/FIXME - static globals */ @@ -395,7 +395,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) @@ -477,10 +477,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) @@ -494,14 +494,14 @@ static void wiiu_hid_synchronized_add_to_adapters_list(wiiu_adapter_t *adapter) static void wiiu_hid_log_device(HIDDevice *device) { RARCH_DBG(" handle: %d\n", device->handle); - RARCH_DBG(" physical_device_inst: %d\n", device->physical_device_inst); + RARCH_DBG(" physical_device_inst: %d\n", device->physicalDeviceInst); RARCH_DBG(" vid: 0x%04x\n", SWAP_IF_BIG(device->vid)); RARCH_DBG(" pid: 0x%04x\n", SWAP_IF_BIG(device->pid)); - RARCH_DBG(" interface_index: %d\n", device->interface_index); - RARCH_DBG(" sub_class: %d\n", device->sub_class); + RARCH_DBG(" interface_index: %d\n", device->interfaceIndex); + RARCH_DBG(" sub_class: %d\n", device->subClass); RARCH_DBG(" protocol: %d\n", device->protocol); - RARCH_DBG(" max_packet_size_rx: %d\n", device->max_packet_size_rx); - RARCH_DBG(" max_packet_size_tx: %d\n", device->max_packet_size_tx); + RARCH_DBG(" max_packet_size_rx: %d\n", device->maxPacketSizeRx); + RARCH_DBG(" max_packet_size_tx: %d\n", device->maxPacketSizeTx); } static void wiiu_hid_get_device_name(HIDDevice *device, wiiu_attach_event *event) @@ -544,13 +544,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; @@ -831,6 +831,7 @@ static int32_t wiiu_hid_set_idle(void *data, uint8_t duration) return HIDSetIdle(adapter->handle, adapter->interface_index, + 0, duration, NULL, NULL); } diff --git a/input/drivers_joypad/wiiu/kpad_driver.c b/input/drivers_joypad/wiiu/kpad_driver.c index 4413e8ff500b..ac967952fea6 100644 --- a/input/drivers_joypad/wiiu/kpad_driver.c +++ b/input/drivers_joypad/wiiu/kpad_driver.c @@ -171,37 +171,40 @@ 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 + case WPAD_EXT_PRO_CONTROLLER: + joypad_state.kpad.wiimotes[channel].button_state = kpad->pro.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->pro.leftStick.x), + WIIU_READ_STICK(kpad->pro.leftStick.y), + WIIU_READ_STICK(kpad->pro.rightStick.x), + WIIU_READ_STICK(kpad->pro.rightStick.y), 0, 0); break; - case WIIMOTE_TYPE_CLASSIC: - joypad_state.kpad.wiimotes[channel].button_state = kpad->classic.btns_h + case WPAD_EXT_MPLUS_CLASSIC: + case WPAD_EXT_CLASSIC: + 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; + case WPAD_EXT_MPLUS_NUNCHUK: + case WPAD_EXT_NUNCHUK: + 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->nunchuk.stick.x), + WIIU_READ_STICK(kpad->nunchuk.stick.y), 0, 0, 0, 0); break; - case WIIMOTE_TYPE_WIIPLUS: - joypad_state.kpad.wiimotes[channel].button_state = kpad->btns_h; + case WPAD_EXT_MPLUS: + case WPAD_EXT_CORE: + 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; @@ -224,9 +227,8 @@ static void kpad_deregister(unsigned channel) static void kpad_poll(void) { - KPADData kpad; + KPADStatus kpad; unsigned channel; - int32_t result = 0; for (channel = 0; channel < WIIU_WIIMOTE_CHANNELS; channel++) { @@ -235,7 +237,7 @@ static void kpad_poll(void) /* This is a hack to prevent spurious disconnects */ /* TODO: use KPADSetConnectCallback and use callbacks to detect */ /* pad disconnects properly. */ - if ((result = KPADRead(channel, &kpad, 1)) == 0) + if (KPADRead(channel, &kpad, 1) != 1) { joypad_state.kpad.poll_failures[channel]++; if (joypad_state.kpad.poll_failures[channel] > 5) @@ -246,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 == WPAD_EXT_UNKNOWN) continue; kpad_poll_one_channel(channel, &kpad); @@ -261,15 +263,18 @@ static const char *kpad_name(unsigned pad) switch (joypad_state.kpad.wiimotes[channel].type) { - case WIIMOTE_TYPE_PRO: + case WPAD_EXT_PRO_CONTROLLER: return PAD_NAME_WIIU_PRO; - case WIIMOTE_TYPE_CLASSIC: + case WPAD_EXT_MPLUS_CLASSIC: + case WPAD_EXT_CLASSIC: return PAD_NAME_CLASSIC; - case WIIMOTE_TYPE_NUNCHUK: + case WPAD_EXT_MPLUS_NUNCHUK: + case WPAD_EXT_NUNCHUK: return PAD_NAME_NUNCHUK; - case WIIMOTE_TYPE_WIIPLUS: + case WPAD_EXT_MPLUS: + case WPAD_EXT_CORE: return PAD_NAME_WIIMOTE; - case WIIMOTE_TYPE_NONE: + case WPAD_EXT_DEV_NOT_FOUND: default: #ifdef DEBUG RARCH_LOG("[kpad] Unknown pad type %d\n", joypad_state.kpad.wiimotes[pad].type); 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..bfd60a31c3af 100644 --- a/input/include/wiiu/input.h +++ b/input/include/wiiu/input.h @@ -24,11 +24,10 @@ #include "hid_types.h" #include "../gamepad.h" -#include -#include -#include -#include +#include <../../../wiiu/include/vpad/ra_input.h> #include +#include +#include #include "../../connect/joypad_connection.h" #include "../../../retroarch.h" diff --git a/libretro-common/features/features_cpu.c b/libretro-common/features/features_cpu.c index eb7f35ff027a..85577e219485 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) @@ -176,6 +176,8 @@ retro_perf_tick_t cpu_features_get_perf_counter(void) time_ticks = (1000000 * tv_sec + tv_usec); #elif defined(GEKKO) time_ticks = gettime(); +#elif defined(WIIU) + time_ticks = OSGetSystemTime(); #elif !defined(__MACH__) && !defined(__FreeBSD__) && (defined(_XBOX360) || defined(__powerpc__) || defined(__ppc__) || defined(__POWERPC__) || defined(__PSL1GHT__) || defined(__PPC64__) || defined(__powerpc64__)) time_ticks = __mftb(); #elif (defined(_POSIX_MONOTONIC_CLOCK) && _POSIX_MONOTONIC_CLOCK > 0) || defined(__QNX__) || defined(ANDROID) @@ -202,8 +204,6 @@ retro_perf_tick_t cpu_features_get_perf_counter(void) time_ticks = ps2_clock(); #elif defined(_3DS) time_ticks = svcGetSystemTick(); -#elif defined(WIIU) - time_ticks = OSGetSystemTime(); #elif defined(HAVE_LIBNX) time_ticks = armGetSystemTick(); #elif defined(EMSCRIPTEN) @@ -233,7 +233,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..bfba267950ac 100644 --- a/libretro-common/include/net/net_compat.h +++ b/libretro-common/include/net/net_compat.h @@ -44,7 +44,7 @@ #include #if _MSC_VER && _MSC_VER <= 1600 -/* If we are using MSVC2010 or lower, disable WSAPoll support +/* If we are using MSVC2010 or lower, disable WSAPoll support * to ensure Windows XP and earlier backwards compatibility */ #else #ifndef WIN32_SUPPORTS_POLL @@ -181,10 +181,6 @@ #define NETWORK_HAVE_POLL 1 -#elif defined(WIIU) -#define WIIU_RCVBUF 0x40000 -#define WIIU_SNDBUF 0x40000 - #elif !defined(__PS3__) #include @@ -350,8 +346,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 +361,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 2ff7d76f3d87..94bf473a2409 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) @@ -97,7 +97,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__) /* defined in frontend */ #ifdef __cplusplus diff --git a/libretro-common/net/net_compat.c b/libretro-common/net/net_compat.c index 7c9b09e3a65b..09b9993feefa 100644 --- a/libretro-common/net/net_compat.c +++ b/libretro-common/net/net_compat.c @@ -234,28 +234,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> @@ -569,36 +547,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 53dcef0a6e44..aab357d62fe0 100644 --- a/libretro-common/net/net_socket.c +++ b/libretro-common/net/net_socket.c @@ -208,7 +208,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); @@ -686,25 +686,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); } @@ -716,25 +697,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) { @@ -759,12 +721,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 err = -1; diff --git a/menu/menu_driver.c b/menu/menu_driver.c index 4e71c804dd9a..6e24547dca2e 100644 --- a/menu/menu_driver.c +++ b/menu/menu_driver.c @@ -31,7 +31,7 @@ #include