├── .gitignore ├── LICENSE ├── Makefile ├── README.md └── src ├── aes.c ├── aes.h ├── common ├── common.h ├── fs_defs.h ├── os_defs.h └── types.h ├── dynamic_libs ├── ax_functions.c ├── ax_functions.h ├── fs_functions.c ├── fs_functions.h ├── gx2_functions.c ├── gx2_functions.h ├── gx2_types.h ├── os_functions.c ├── os_functions.h ├── padscore_functions.c ├── padscore_functions.h ├── socket_functions.c ├── socket_functions.h ├── sys_functions.c ├── sys_functions.h ├── vpad_functions.c └── vpad_functions.h ├── entry.c ├── extractor.c ├── extractor.h ├── fs ├── fs_utils.c ├── fs_utils.h ├── sd_fat_devoptab.c └── sd_fat_devoptab.h ├── link.ld ├── main.c ├── main.h ├── menu_options.c ├── menu_options.h ├── system ├── memory.c └── memory.h └── utils ├── fsutils.c ├── fsutils.h ├── logger.c ├── logger.h ├── stringutils.c ├── stringutils.h └── utils.h /.gitignore: -------------------------------------------------------------------------------- 1 | .vscode/ 2 | build/ 3 | *.elf -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | #--------------------------------------------------------------------------------- 2 | # Clear the implicit built in rules 3 | #--------------------------------------------------------------------------------- 4 | .SUFFIXES: 5 | #--------------------------------------------------------------------------------- 6 | ifeq ($(strip $(DEVKITPPC)),) 7 | $(error "Please set DEVKITPPC in your environment. export DEVKITPPC=devkitPPC") 8 | endif 9 | ifeq ($(strip $(DEVKITPRO)),) 10 | $(error "Please set DEVKITPRO in your environment. export DEVKITPRO=devkitPRO") 11 | endif 12 | export PATH := $(DEVKITPPC)/bin:$(PORTLIBS)/bin:$(PATH) 13 | export LIBOGC_INC := $(DEVKITPRO)/libogc/include 14 | export LIBOGC_LIB := $(DEVKITPRO)/libogc/lib/wii 15 | export PORTLIBS := $(DEVKITPRO)/portlibs/ppc 16 | 17 | PREFIX := powerpc-eabi- 18 | 19 | export AS := $(PREFIX)as 20 | export CC := $(PREFIX)gcc 21 | export CXX := $(PREFIX)g++ 22 | export AR := $(PREFIX)ar 23 | export OBJCOPY := $(PREFIX)objcopy 24 | 25 | #--------------------------------------------------------------------------------- 26 | # TARGET is the name of the output 27 | # BUILD is the directory where object files & intermediate files will be placed 28 | # SOURCES is a list of directories containing source code 29 | # INCLUDES is a list of directories containing extra header files 30 | #--------------------------------------------------------------------------------- 31 | TARGET := vwii-nand-restorer 32 | BUILD := build 33 | BUILD_DBG := $(TARGET)_dbg 34 | SOURCES := src \ 35 | src/dynamic_libs \ 36 | src/fs \ 37 | src/system \ 38 | src/utils 39 | DATA := 40 | 41 | INCLUDES := src 42 | 43 | #--------------------------------------------------------------------------------- 44 | # options for code generation 45 | #--------------------------------------------------------------------------------- 46 | CFLAGS := -std=gnu11 -mrvl -mcpu=750 -meabi -mhard-float -ffast-math \ 47 | -O3 -Wall -Wextra -Wno-unused-parameter -Wno-strict-aliasing $(INCLUDE) 48 | CXXFLAGS := -std=gnu++11 -mrvl -mcpu=750 -meabi -mhard-float -ffast-math \ 49 | -O3 -Wall -Wextra -Wno-unused-parameter -Wno-strict-aliasing $(INCLUDE) 50 | ASFLAGS := -mregnames 51 | LDFLAGS := -nostartfiles -Wl,-Map,$(notdir $@).map,-wrap,malloc,-wrap,free,-wrap,memalign,-wrap,calloc,-wrap,realloc,-wrap,malloc_usable_size,-wrap,_malloc_r,-wrap,_free_r,-wrap,_realloc_r,-wrap,_calloc_r,-wrap,_memalign_r,-wrap,_malloc_usable_size_r,-wrap,valloc,-wrap,_valloc_r,-wrap,_pvalloc_r,--gc-sections 52 | 53 | #--------------------------------------------------------------------------------- 54 | Q := @ 55 | MAKEFLAGS += --no-print-directory 56 | #--------------------------------------------------------------------------------- 57 | # any extra libraries we wish to link with the project 58 | #--------------------------------------------------------------------------------- 59 | LIBS := -lgcc -lfat -liosuhax 60 | 61 | #--------------------------------------------------------------------------------- 62 | # list of directories containing libraries, this must be the top level containing 63 | # include and lib 64 | #--------------------------------------------------------------------------------- 65 | LIBDIRS := $(CURDIR) \ 66 | $(DEVKITPPC)/lib \ 67 | $(DEVKITPPC)/lib/gcc/powerpc-eabi/4.8.2 68 | 69 | 70 | #--------------------------------------------------------------------------------- 71 | # no real need to edit anything past this point unless you need to add additional 72 | # rules for different file extensions 73 | #--------------------------------------------------------------------------------- 74 | ifneq ($(BUILD),$(notdir $(CURDIR))) 75 | #--------------------------------------------------------------------------------- 76 | export PROJECTDIR := $(CURDIR) 77 | export OUTPUT := $(CURDIR)/$(TARGETDIR)/$(TARGET) 78 | export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \ 79 | $(foreach dir,$(DATA),$(CURDIR)/$(dir)) 80 | export DEPSDIR := $(CURDIR)/$(BUILD) 81 | 82 | #--------------------------------------------------------------------------------- 83 | # automatically build a list of object files for our project 84 | #--------------------------------------------------------------------------------- 85 | CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) 86 | CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) 87 | sFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) 88 | SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.S))) 89 | BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) 90 | TTFFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.ttf))) 91 | PNGFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.png))) 92 | 93 | #--------------------------------------------------------------------------------- 94 | # use CXX for linking C++ projects, CC for standard C 95 | #--------------------------------------------------------------------------------- 96 | ifeq ($(strip $(CPPFILES)),) 97 | export LD := $(CC) 98 | else 99 | export LD := $(CXX) 100 | endif 101 | 102 | export OFILES := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) \ 103 | $(sFILES:.s=.o) $(SFILES:.S=.o) \ 104 | $(PNGFILES:.png=.png.o) $(addsuffix .o,$(BINFILES)) 105 | 106 | #--------------------------------------------------------------------------------- 107 | # build a list of include paths 108 | #--------------------------------------------------------------------------------- 109 | export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \ 110 | $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ 111 | -I$(CURDIR)/$(BUILD) -I$(LIBOGC_INC) \ 112 | -I$(PORTLIBS)/include -I$(PORTLIBS)/include/freetype2 113 | 114 | #--------------------------------------------------------------------------------- 115 | # build a list of library paths 116 | #--------------------------------------------------------------------------------- 117 | export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) \ 118 | -L$(LIBOGC_LIB) -L$(PORTLIBS)/lib 119 | 120 | export OUTPUT := $(CURDIR)/$(TARGET) 121 | .PHONY: $(BUILD) clean install 122 | 123 | #--------------------------------------------------------------------------------- 124 | $(BUILD): 125 | @[ -d $@ ] || mkdir -p $@ 126 | @$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile 127 | 128 | #--------------------------------------------------------------------------------- 129 | clean: 130 | @echo clean ... 131 | @rm -fr $(BUILD) $(OUTPUT).elf $(OUTPUT).bin $(BUILD_DBG).elf 132 | 133 | #--------------------------------------------------------------------------------- 134 | else 135 | 136 | DEPENDS := $(OFILES:.o=.d) 137 | 138 | #--------------------------------------------------------------------------------- 139 | # main targets 140 | #--------------------------------------------------------------------------------- 141 | $(OUTPUT).elf: $(OFILES) 142 | 143 | #--------------------------------------------------------------------------------- 144 | # This rule links in binary data with the .jpg extension 145 | #--------------------------------------------------------------------------------- 146 | %.elf: link.ld $(OFILES) 147 | @echo "linking ... $(TARGET).elf" 148 | $(Q)$(LD) -n -T $^ $(LDFLAGS) -o ../$(BUILD_DBG).elf $(LIBPATHS) $(LIBS) 149 | $(Q)$(OBJCOPY) -S -R .comment -R .gnu.attributes ../$(BUILD_DBG).elf $@ 150 | 151 | ../data/loader.bin: 152 | $(MAKE) -C ../loader clean 153 | $(MAKE) -C ../loader 154 | #--------------------------------------------------------------------------------- 155 | %.a: 156 | #--------------------------------------------------------------------------------- 157 | @echo $(notdir $@) 158 | @rm -f $@ 159 | @$(AR) -rc $@ $^ 160 | 161 | #--------------------------------------------------------------------------------- 162 | %.o: %.cpp 163 | @echo $(notdir $<) 164 | @$(CXX) -MMD -MP -MF $(DEPSDIR)/$*.d $(CXXFLAGS) -c $< -o $@ $(ERROR_FILTER) 165 | 166 | #--------------------------------------------------------------------------------- 167 | %.o: %.c 168 | @echo $(notdir $<) 169 | @$(CC) -MMD -MP -MF $(DEPSDIR)/$*.d $(CFLAGS) -c $< -o $@ $(ERROR_FILTER) 170 | 171 | #--------------------------------------------------------------------------------- 172 | %.o: %.S 173 | @echo $(notdir $<) 174 | @$(CC) -MMD -MP -MF $(DEPSDIR)/$*.d -x assembler-with-cpp $(ASFLAGS) -c $< -o $@ $(ERROR_FILTER) 175 | 176 | #--------------------------------------------------------------------------------- 177 | %.png.o : %.png 178 | @echo $(notdir $<) 179 | @bin2s -a 32 $< | $(AS) -o $(@) 180 | 181 | #--------------------------------------------------------------------------------- 182 | %.jpg.o : %.jpg 183 | @echo $(notdir $<) 184 | @bin2s -a 32 $< | $(AS) -o $(@) 185 | 186 | #--------------------------------------------------------------------------------- 187 | %.ttf.o : %.ttf 188 | @echo $(notdir $<) 189 | @bin2s -a 32 $< | $(AS) -o $(@) 190 | 191 | #--------------------------------------------------------------------------------- 192 | %.bin.o : %.bin 193 | @echo $(notdir $<) 194 | @bin2s -a 32 $< | $(AS) -o $(@) 195 | 196 | #--------------------------------------------------------------------------------- 197 | %.wav.o : %.wav 198 | @echo $(notdir $<) 199 | @bin2s -a 32 $< | $(AS) -o $(@) 200 | 201 | #--------------------------------------------------------------------------------- 202 | %.mp3.o : %.mp3 203 | @echo $(notdir $<) 204 | @bin2s -a 32 $< | $(AS) -o $(@) 205 | 206 | #--------------------------------------------------------------------------------- 207 | %.ogg.o : %.ogg 208 | @echo $(notdir $<) 209 | @bin2s -a 32 $< | $(AS) -o $(@) 210 | 211 | -include $(DEPENDS) 212 | 213 | #--------------------------------------------------------------------------------- 214 | endif 215 | #--------------------------------------------------------------------------------- 216 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # vWii-NAND-Restorer 2 | Restore your vWii NAND backups from your Wii U 3 | 4 | ## Note: I recommend using [vWii Decaffeinator](https://github.com/GaryOderNichts/vWii-Decaffeinator) to restore (partially) bricked vWii's instead 5 | 6 | ## How to use 7 | - Copy your nand backup to `sd:/vwiinandrestorer/slccmpt.bin` and place your `keys.bin/otp.bin` in the same folder 8 | - Copy the .elf to sd:/wiiu/apps 9 | - Run cfw (mocha or haxchi) 10 | 11 | I recommend doing a slccmpt + otp backup with [Wii U Nand dumper](https://github.com/koolkdev/wiiu-nanddumper/releases) before using this tool. 12 | Please make sure that the `keys.bin/otp.bin` are from the console where the NAND Backup is from or else decryption will fail! 13 | 14 | ###### Restore NAND 15 | This will clear your SLCCMPT, extract the nand backup to your slccmpt and fix permissions 16 | 17 | ##### Additional Options: 18 | 19 | ###### Extract NAND 20 | Extracts your NAND to `sd:/vwiinandrestorer/extracted` 21 | 22 | ###### Clear SLCCMPT 23 | This clears your SLCCMPT 24 | 25 | ###### Copy extracted NAND to SLCCMPT 26 | Copies everything from `sd:/vwiinandrestorer/extracted` to your SLCCMPT 27 | This can be useful if you have an already extracted NAND Backup that you want to restore 28 | 29 | ###### Fix modes 30 | This fixes the modes of your SLCCMPT 31 | Needed after copying file to the SLCCMPT 32 | 33 | ### Logging 34 | A log of the console output gets written to `sd:/vwiinandrestorer/latest.log` 35 | If you want to report an issue please also send that logfile 36 | 37 | ## Changelog 38 | ``` 39 | v2 40 | - Add support for 'Dump Mii Nand' Nand Dumps 41 | - Fix issue that may have resulted in incorrect file sizes for a few files 42 | 43 | v1 44 | - Initial release 45 | ``` 46 | 47 | ## Disclaimer 48 | I am not responsible for any damage while using this tool or any additional bricks done to your device! 49 | 50 | ## Build 51 | Download devkitpro ppc, portlibs, libogc and build and install latest libiosuhax. 52 | Then run `make` 53 | -------------------------------------------------------------------------------- /src/aes.c: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | This is an implementation of the AES algorithm, specifically ECB, CTR and CBC mode. 4 | Block size can be chosen in aes.h - available choices are AES128, AES192, AES256. 5 | 6 | The implementation is verified against the test vectors in: 7 | National Institute of Standards and Technology Special Publication 800-38A 2001 ED 8 | 9 | ECB-AES128 10 | ---------- 11 | 12 | plain-text: 13 | 6bc1bee22e409f96e93d7e117393172a 14 | ae2d8a571e03ac9c9eb76fac45af8e51 15 | 30c81c46a35ce411e5fbc1191a0a52ef 16 | f69f2445df4f9b17ad2b417be66c3710 17 | 18 | key: 19 | 2b7e151628aed2a6abf7158809cf4f3c 20 | 21 | resulting cipher 22 | 3ad77bb40d7a3660a89ecaf32466ef97 23 | f5d3d58503b9699de785895a96fdbaaf 24 | 43b1cd7f598ece23881b00e3ed030688 25 | 7b0c785e27e8ad3f8223207104725dd4 26 | 27 | 28 | NOTE: String length must be evenly divisible by 16byte (str_len % 16 == 0) 29 | You should pad the end of the string with zeros if this is not the case. 30 | For AES192/256 the key size is proportionally larger. 31 | 32 | */ 33 | 34 | 35 | /*****************************************************************************/ 36 | /* Includes: */ 37 | /*****************************************************************************/ 38 | #include // CBC mode, for memset 39 | #include "aes.h" 40 | 41 | /*****************************************************************************/ 42 | /* Defines: */ 43 | /*****************************************************************************/ 44 | // The number of columns comprising a state in AES. This is a constant in AES. Value=4 45 | #define Nb 4 46 | 47 | #if defined(AES256) && (AES256 == 1) 48 | #define Nk 8 49 | #define Nr 14 50 | #elif defined(AES192) && (AES192 == 1) 51 | #define Nk 6 52 | #define Nr 12 53 | #else 54 | #define Nk 4 // The number of 32 bit words in a key. 55 | #define Nr 10 // The number of rounds in AES Cipher. 56 | #endif 57 | 58 | // jcallan@github points out that declaring Multiply as a function 59 | // reduces code size considerably with the Keil ARM compiler. 60 | // See this link for more information: https://github.com/kokke/tiny-AES-C/pull/3 61 | #ifndef MULTIPLY_AS_A_FUNCTION 62 | #define MULTIPLY_AS_A_FUNCTION 0 63 | #endif 64 | 65 | 66 | 67 | 68 | /*****************************************************************************/ 69 | /* Private variables: */ 70 | /*****************************************************************************/ 71 | // state - array holding the intermediate results during decryption. 72 | typedef uint8_t state_t[4][4]; 73 | 74 | 75 | 76 | // The lookup-tables are marked const so they can be placed in read-only storage instead of RAM 77 | // The numbers below can be computed dynamically trading ROM for RAM - 78 | // This can be useful in (embedded) bootloader applications, where ROM is often limited. 79 | static const uint8_t sbox[256] = { 80 | //0 1 2 3 4 5 6 7 8 9 A B C D E F 81 | 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, 82 | 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 83 | 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, 84 | 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, 85 | 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 86 | 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, 87 | 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, 88 | 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 89 | 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, 90 | 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, 91 | 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 92 | 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, 93 | 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, 94 | 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, 95 | 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, 96 | 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 }; 97 | 98 | static const uint8_t rsbox[256] = { 99 | 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, 100 | 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, 101 | 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, 102 | 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25, 103 | 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, 104 | 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84, 105 | 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06, 106 | 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, 107 | 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, 108 | 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e, 109 | 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, 110 | 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, 111 | 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f, 112 | 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, 113 | 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, 114 | 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d }; 115 | 116 | // The round constant word array, Rcon[i], contains the values given by 117 | // x to the power (i-1) being powers of x (x is denoted as {02}) in the field GF(2^8) 118 | static const uint8_t Rcon[11] = { 119 | 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36 }; 120 | 121 | /* 122 | * Jordan Goulder points out in PR #12 (https://github.com/kokke/tiny-AES-C/pull/12), 123 | * that you can remove most of the elements in the Rcon array, because they are unused. 124 | * 125 | * From Wikipedia's article on the Rijndael key schedule @ https://en.wikipedia.org/wiki/Rijndael_key_schedule#Rcon 126 | * 127 | * "Only the first some of these constants are actually used – up to rcon[10] for AES-128 (as 11 round keys are needed), 128 | * up to rcon[8] for AES-192, up to rcon[7] for AES-256. rcon[0] is not used in AES algorithm." 129 | */ 130 | 131 | 132 | /*****************************************************************************/ 133 | /* Private functions: */ 134 | /*****************************************************************************/ 135 | /* 136 | static uint8_t getSBoxValue(uint8_t num) 137 | { 138 | return sbox[num]; 139 | } 140 | */ 141 | #define getSBoxValue(num) (sbox[(num)]) 142 | /* 143 | static uint8_t getSBoxInvert(uint8_t num) 144 | { 145 | return rsbox[num]; 146 | } 147 | */ 148 | #define getSBoxInvert(num) (rsbox[(num)]) 149 | 150 | // This function produces Nb(Nr+1) round keys. The round keys are used in each round to decrypt the states. 151 | static void KeyExpansion(uint8_t* RoundKey, const uint8_t* Key) 152 | { 153 | unsigned i, j, k; 154 | uint8_t tempa[4]; // Used for the column/row operations 155 | 156 | // The first round key is the key itself. 157 | for (i = 0; i < Nk; ++i) 158 | { 159 | RoundKey[(i * 4) + 0] = Key[(i * 4) + 0]; 160 | RoundKey[(i * 4) + 1] = Key[(i * 4) + 1]; 161 | RoundKey[(i * 4) + 2] = Key[(i * 4) + 2]; 162 | RoundKey[(i * 4) + 3] = Key[(i * 4) + 3]; 163 | } 164 | 165 | // All other round keys are found from the previous round keys. 166 | for (i = Nk; i < Nb * (Nr + 1); ++i) 167 | { 168 | { 169 | k = (i - 1) * 4; 170 | tempa[0]=RoundKey[k + 0]; 171 | tempa[1]=RoundKey[k + 1]; 172 | tempa[2]=RoundKey[k + 2]; 173 | tempa[3]=RoundKey[k + 3]; 174 | 175 | } 176 | 177 | if (i % Nk == 0) 178 | { 179 | // This function shifts the 4 bytes in a word to the left once. 180 | // [a0,a1,a2,a3] becomes [a1,a2,a3,a0] 181 | 182 | // Function RotWord() 183 | { 184 | const uint8_t u8tmp = tempa[0]; 185 | tempa[0] = tempa[1]; 186 | tempa[1] = tempa[2]; 187 | tempa[2] = tempa[3]; 188 | tempa[3] = u8tmp; 189 | } 190 | 191 | // SubWord() is a function that takes a four-byte input word and 192 | // applies the S-box to each of the four bytes to produce an output word. 193 | 194 | // Function Subword() 195 | { 196 | tempa[0] = getSBoxValue(tempa[0]); 197 | tempa[1] = getSBoxValue(tempa[1]); 198 | tempa[2] = getSBoxValue(tempa[2]); 199 | tempa[3] = getSBoxValue(tempa[3]); 200 | } 201 | 202 | tempa[0] = tempa[0] ^ Rcon[i/Nk]; 203 | } 204 | #if defined(AES256) && (AES256 == 1) 205 | if (i % Nk == 4) 206 | { 207 | // Function Subword() 208 | { 209 | tempa[0] = getSBoxValue(tempa[0]); 210 | tempa[1] = getSBoxValue(tempa[1]); 211 | tempa[2] = getSBoxValue(tempa[2]); 212 | tempa[3] = getSBoxValue(tempa[3]); 213 | } 214 | } 215 | #endif 216 | j = i * 4; k=(i - Nk) * 4; 217 | RoundKey[j + 0] = RoundKey[k + 0] ^ tempa[0]; 218 | RoundKey[j + 1] = RoundKey[k + 1] ^ tempa[1]; 219 | RoundKey[j + 2] = RoundKey[k + 2] ^ tempa[2]; 220 | RoundKey[j + 3] = RoundKey[k + 3] ^ tempa[3]; 221 | } 222 | } 223 | 224 | void AES_init_ctx(struct AES_ctx* ctx, const uint8_t* key) 225 | { 226 | KeyExpansion(ctx->RoundKey, key); 227 | } 228 | #if (defined(CBC) && (CBC == 1)) || (defined(CTR) && (CTR == 1)) 229 | void AES_init_ctx_iv(struct AES_ctx* ctx, const uint8_t* key, const uint8_t* iv) 230 | { 231 | KeyExpansion(ctx->RoundKey, key); 232 | memcpy (ctx->Iv, iv, AES_BLOCKLEN); 233 | } 234 | void AES_ctx_set_iv(struct AES_ctx* ctx, const uint8_t* iv) 235 | { 236 | memcpy (ctx->Iv, iv, AES_BLOCKLEN); 237 | } 238 | #endif 239 | 240 | // This function adds the round key to state. 241 | // The round key is added to the state by an XOR function. 242 | static void AddRoundKey(uint8_t round, state_t* state, const uint8_t* RoundKey) 243 | { 244 | uint8_t i,j; 245 | for (i = 0; i < 4; ++i) 246 | { 247 | for (j = 0; j < 4; ++j) 248 | { 249 | (*state)[i][j] ^= RoundKey[(round * Nb * 4) + (i * Nb) + j]; 250 | } 251 | } 252 | } 253 | 254 | // The SubBytes Function Substitutes the values in the 255 | // state matrix with values in an S-box. 256 | static void SubBytes(state_t* state) 257 | { 258 | uint8_t i, j; 259 | for (i = 0; i < 4; ++i) 260 | { 261 | for (j = 0; j < 4; ++j) 262 | { 263 | (*state)[j][i] = getSBoxValue((*state)[j][i]); 264 | } 265 | } 266 | } 267 | 268 | // The ShiftRows() function shifts the rows in the state to the left. 269 | // Each row is shifted with different offset. 270 | // Offset = Row number. So the first row is not shifted. 271 | static void ShiftRows(state_t* state) 272 | { 273 | uint8_t temp; 274 | 275 | // Rotate first row 1 columns to left 276 | temp = (*state)[0][1]; 277 | (*state)[0][1] = (*state)[1][1]; 278 | (*state)[1][1] = (*state)[2][1]; 279 | (*state)[2][1] = (*state)[3][1]; 280 | (*state)[3][1] = temp; 281 | 282 | // Rotate second row 2 columns to left 283 | temp = (*state)[0][2]; 284 | (*state)[0][2] = (*state)[2][2]; 285 | (*state)[2][2] = temp; 286 | 287 | temp = (*state)[1][2]; 288 | (*state)[1][2] = (*state)[3][2]; 289 | (*state)[3][2] = temp; 290 | 291 | // Rotate third row 3 columns to left 292 | temp = (*state)[0][3]; 293 | (*state)[0][3] = (*state)[3][3]; 294 | (*state)[3][3] = (*state)[2][3]; 295 | (*state)[2][3] = (*state)[1][3]; 296 | (*state)[1][3] = temp; 297 | } 298 | 299 | static uint8_t xtime(uint8_t x) 300 | { 301 | return ((x<<1) ^ (((x>>7) & 1) * 0x1b)); 302 | } 303 | 304 | // MixColumns function mixes the columns of the state matrix 305 | static void MixColumns(state_t* state) 306 | { 307 | uint8_t i; 308 | uint8_t Tmp, Tm, t; 309 | for (i = 0; i < 4; ++i) 310 | { 311 | t = (*state)[i][0]; 312 | Tmp = (*state)[i][0] ^ (*state)[i][1] ^ (*state)[i][2] ^ (*state)[i][3] ; 313 | Tm = (*state)[i][0] ^ (*state)[i][1] ; Tm = xtime(Tm); (*state)[i][0] ^= Tm ^ Tmp ; 314 | Tm = (*state)[i][1] ^ (*state)[i][2] ; Tm = xtime(Tm); (*state)[i][1] ^= Tm ^ Tmp ; 315 | Tm = (*state)[i][2] ^ (*state)[i][3] ; Tm = xtime(Tm); (*state)[i][2] ^= Tm ^ Tmp ; 316 | Tm = (*state)[i][3] ^ t ; Tm = xtime(Tm); (*state)[i][3] ^= Tm ^ Tmp ; 317 | } 318 | } 319 | 320 | // Multiply is used to multiply numbers in the field GF(2^8) 321 | // Note: The last call to xtime() is unneeded, but often ends up generating a smaller binary 322 | // The compiler seems to be able to vectorize the operation better this way. 323 | // See https://github.com/kokke/tiny-AES-c/pull/34 324 | #if MULTIPLY_AS_A_FUNCTION 325 | static uint8_t Multiply(uint8_t x, uint8_t y) 326 | { 327 | return (((y & 1) * x) ^ 328 | ((y>>1 & 1) * xtime(x)) ^ 329 | ((y>>2 & 1) * xtime(xtime(x))) ^ 330 | ((y>>3 & 1) * xtime(xtime(xtime(x)))) ^ 331 | ((y>>4 & 1) * xtime(xtime(xtime(xtime(x)))))); /* this last call to xtime() can be omitted */ 332 | } 333 | #else 334 | #define Multiply(x, y) \ 335 | ( ((y & 1) * x) ^ \ 336 | ((y>>1 & 1) * xtime(x)) ^ \ 337 | ((y>>2 & 1) * xtime(xtime(x))) ^ \ 338 | ((y>>3 & 1) * xtime(xtime(xtime(x)))) ^ \ 339 | ((y>>4 & 1) * xtime(xtime(xtime(xtime(x)))))) \ 340 | 341 | #endif 342 | 343 | #if (defined(CBC) && CBC == 1) || (defined(ECB) && ECB == 1) 344 | // MixColumns function mixes the columns of the state matrix. 345 | // The method used to multiply may be difficult to understand for the inexperienced. 346 | // Please use the references to gain more information. 347 | static void InvMixColumns(state_t* state) 348 | { 349 | int i; 350 | uint8_t a, b, c, d; 351 | for (i = 0; i < 4; ++i) 352 | { 353 | a = (*state)[i][0]; 354 | b = (*state)[i][1]; 355 | c = (*state)[i][2]; 356 | d = (*state)[i][3]; 357 | 358 | (*state)[i][0] = Multiply(a, 0x0e) ^ Multiply(b, 0x0b) ^ Multiply(c, 0x0d) ^ Multiply(d, 0x09); 359 | (*state)[i][1] = Multiply(a, 0x09) ^ Multiply(b, 0x0e) ^ Multiply(c, 0x0b) ^ Multiply(d, 0x0d); 360 | (*state)[i][2] = Multiply(a, 0x0d) ^ Multiply(b, 0x09) ^ Multiply(c, 0x0e) ^ Multiply(d, 0x0b); 361 | (*state)[i][3] = Multiply(a, 0x0b) ^ Multiply(b, 0x0d) ^ Multiply(c, 0x09) ^ Multiply(d, 0x0e); 362 | } 363 | } 364 | 365 | 366 | // The SubBytes Function Substitutes the values in the 367 | // state matrix with values in an S-box. 368 | static void InvSubBytes(state_t* state) 369 | { 370 | uint8_t i, j; 371 | for (i = 0; i < 4; ++i) 372 | { 373 | for (j = 0; j < 4; ++j) 374 | { 375 | (*state)[j][i] = getSBoxInvert((*state)[j][i]); 376 | } 377 | } 378 | } 379 | 380 | static void InvShiftRows(state_t* state) 381 | { 382 | uint8_t temp; 383 | 384 | // Rotate first row 1 columns to right 385 | temp = (*state)[3][1]; 386 | (*state)[3][1] = (*state)[2][1]; 387 | (*state)[2][1] = (*state)[1][1]; 388 | (*state)[1][1] = (*state)[0][1]; 389 | (*state)[0][1] = temp; 390 | 391 | // Rotate second row 2 columns to right 392 | temp = (*state)[0][2]; 393 | (*state)[0][2] = (*state)[2][2]; 394 | (*state)[2][2] = temp; 395 | 396 | temp = (*state)[1][2]; 397 | (*state)[1][2] = (*state)[3][2]; 398 | (*state)[3][2] = temp; 399 | 400 | // Rotate third row 3 columns to right 401 | temp = (*state)[0][3]; 402 | (*state)[0][3] = (*state)[1][3]; 403 | (*state)[1][3] = (*state)[2][3]; 404 | (*state)[2][3] = (*state)[3][3]; 405 | (*state)[3][3] = temp; 406 | } 407 | #endif // #if (defined(CBC) && CBC == 1) || (defined(ECB) && ECB == 1) 408 | 409 | // Cipher is the main function that encrypts the PlainText. 410 | static void Cipher(state_t* state, const uint8_t* RoundKey) 411 | { 412 | uint8_t round = 0; 413 | 414 | // Add the First round key to the state before starting the rounds. 415 | AddRoundKey(0, state, RoundKey); 416 | 417 | // There will be Nr rounds. 418 | // The first Nr-1 rounds are identical. 419 | // These Nr rounds are executed in the loop below. 420 | // Last one without MixColumns() 421 | for (round = 1; ; ++round) 422 | { 423 | SubBytes(state); 424 | ShiftRows(state); 425 | if (round == Nr) { 426 | break; 427 | } 428 | MixColumns(state); 429 | AddRoundKey(round, state, RoundKey); 430 | } 431 | // Add round key to last round 432 | AddRoundKey(Nr, state, RoundKey); 433 | } 434 | 435 | #if (defined(CBC) && CBC == 1) || (defined(ECB) && ECB == 1) 436 | static void InvCipher(state_t* state, const uint8_t* RoundKey) 437 | { 438 | uint8_t round = 0; 439 | 440 | // Add the First round key to the state before starting the rounds. 441 | AddRoundKey(Nr, state, RoundKey); 442 | 443 | // There will be Nr rounds. 444 | // The first Nr-1 rounds are identical. 445 | // These Nr rounds are executed in the loop below. 446 | // Last one without InvMixColumn() 447 | for (round = (Nr - 1); ; --round) 448 | { 449 | InvShiftRows(state); 450 | InvSubBytes(state); 451 | AddRoundKey(round, state, RoundKey); 452 | if (round == 0) { 453 | break; 454 | } 455 | InvMixColumns(state); 456 | } 457 | 458 | } 459 | #endif // #if (defined(CBC) && CBC == 1) || (defined(ECB) && ECB == 1) 460 | 461 | /*****************************************************************************/ 462 | /* Public functions: */ 463 | /*****************************************************************************/ 464 | #if defined(ECB) && (ECB == 1) 465 | 466 | 467 | void AES_ECB_encrypt(const struct AES_ctx* ctx, uint8_t* buf) 468 | { 469 | // The next function call encrypts the PlainText with the Key using AES algorithm. 470 | Cipher((state_t*)buf, ctx->RoundKey); 471 | } 472 | 473 | void AES_ECB_decrypt(const struct AES_ctx* ctx, uint8_t* buf) 474 | { 475 | // The next function call decrypts the PlainText with the Key using AES algorithm. 476 | InvCipher((state_t*)buf, ctx->RoundKey); 477 | } 478 | 479 | 480 | #endif // #if defined(ECB) && (ECB == 1) 481 | 482 | 483 | 484 | 485 | 486 | #if defined(CBC) && (CBC == 1) 487 | 488 | 489 | static void XorWithIv(uint8_t* buf, const uint8_t* Iv) 490 | { 491 | uint8_t i; 492 | for (i = 0; i < AES_BLOCKLEN; ++i) // The block in AES is always 128bit no matter the key size 493 | { 494 | buf[i] ^= Iv[i]; 495 | } 496 | } 497 | 498 | void AES_CBC_encrypt_buffer(struct AES_ctx *ctx, uint8_t* buf, uint32_t length) 499 | { 500 | uintptr_t i; 501 | uint8_t *Iv = ctx->Iv; 502 | for (i = 0; i < length; i += AES_BLOCKLEN) 503 | { 504 | XorWithIv(buf, Iv); 505 | Cipher((state_t*)buf, ctx->RoundKey); 506 | Iv = buf; 507 | buf += AES_BLOCKLEN; 508 | //printf("Step %d - %d", i/16, i); 509 | } 510 | /* store Iv in ctx for next call */ 511 | memcpy(ctx->Iv, Iv, AES_BLOCKLEN); 512 | } 513 | 514 | void AES_CBC_decrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, uint32_t length) 515 | { 516 | uintptr_t i; 517 | uint8_t storeNextIv[AES_BLOCKLEN]; 518 | for (i = 0; i < length; i += AES_BLOCKLEN) 519 | { 520 | memcpy(storeNextIv, buf, AES_BLOCKLEN); 521 | InvCipher((state_t*)buf, ctx->RoundKey); 522 | XorWithIv(buf, ctx->Iv); 523 | memcpy(ctx->Iv, storeNextIv, AES_BLOCKLEN); 524 | buf += AES_BLOCKLEN; 525 | } 526 | 527 | } 528 | 529 | #endif // #if defined(CBC) && (CBC == 1) 530 | 531 | 532 | 533 | #if defined(CTR) && (CTR == 1) 534 | 535 | /* Symmetrical operation: same function for encrypting as for decrypting. Note any IV/nonce should never be reused with the same key */ 536 | void AES_CTR_xcrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, uint32_t length) 537 | { 538 | uint8_t buffer[AES_BLOCKLEN]; 539 | 540 | unsigned i; 541 | int bi; 542 | for (i = 0, bi = AES_BLOCKLEN; i < length; ++i, ++bi) 543 | { 544 | if (bi == AES_BLOCKLEN) /* we need to regen xor compliment in buffer */ 545 | { 546 | 547 | memcpy(buffer, ctx->Iv, AES_BLOCKLEN); 548 | Cipher((state_t*)buffer,ctx->RoundKey); 549 | 550 | /* Increment Iv and handle overflow */ 551 | for (bi = (AES_BLOCKLEN - 1); bi >= 0; --bi) 552 | { 553 | /* inc will overflow */ 554 | if (ctx->Iv[bi] == 255) 555 | { 556 | ctx->Iv[bi] = 0; 557 | continue; 558 | } 559 | ctx->Iv[bi] += 1; 560 | break; 561 | } 562 | bi = 0; 563 | } 564 | 565 | buf[i] = (buf[i] ^ buffer[bi]); 566 | } 567 | } 568 | 569 | #endif // #if defined(CTR) && (CTR == 1) 570 | 571 | -------------------------------------------------------------------------------- /src/aes.h: -------------------------------------------------------------------------------- 1 | #ifndef _AES_H_ 2 | #define _AES_H_ 3 | 4 | #include 5 | 6 | // #define the macros below to 1/0 to enable/disable the mode of operation. 7 | // 8 | // CBC enables AES encryption in CBC-mode of operation. 9 | // CTR enables encryption in counter-mode. 10 | // ECB enables the basic ECB 16-byte block algorithm. All can be enabled simultaneously. 11 | 12 | // The #ifndef-guard allows it to be configured before #include'ing or at compile time. 13 | #ifndef CBC 14 | #define CBC 1 15 | #endif 16 | 17 | #ifndef ECB 18 | #define ECB 1 19 | #endif 20 | 21 | #ifndef CTR 22 | #define CTR 1 23 | #endif 24 | 25 | 26 | #define AES128 1 27 | //#define AES192 1 28 | //#define AES256 1 29 | 30 | #define AES_BLOCKLEN 16 //Block length in bytes AES is 128b block only 31 | 32 | #if defined(AES256) && (AES256 == 1) 33 | #define AES_KEYLEN 32 34 | #define AES_keyExpSize 240 35 | #elif defined(AES192) && (AES192 == 1) 36 | #define AES_KEYLEN 24 37 | #define AES_keyExpSize 208 38 | #else 39 | #define AES_KEYLEN 16 // Key length in bytes 40 | #define AES_keyExpSize 176 41 | #endif 42 | 43 | struct AES_ctx 44 | { 45 | uint8_t RoundKey[AES_keyExpSize]; 46 | #if (defined(CBC) && (CBC == 1)) || (defined(CTR) && (CTR == 1)) 47 | uint8_t Iv[AES_BLOCKLEN]; 48 | #endif 49 | }; 50 | 51 | void AES_init_ctx(struct AES_ctx* ctx, const uint8_t* key); 52 | #if (defined(CBC) && (CBC == 1)) || (defined(CTR) && (CTR == 1)) 53 | void AES_init_ctx_iv(struct AES_ctx* ctx, const uint8_t* key, const uint8_t* iv); 54 | void AES_ctx_set_iv(struct AES_ctx* ctx, const uint8_t* iv); 55 | #endif 56 | 57 | #if defined(ECB) && (ECB == 1) 58 | // buffer size is exactly AES_BLOCKLEN bytes; 59 | // you need only AES_init_ctx as IV is not used in ECB 60 | // NB: ECB is considered insecure for most uses 61 | void AES_ECB_encrypt(const struct AES_ctx* ctx, uint8_t* buf); 62 | void AES_ECB_decrypt(const struct AES_ctx* ctx, uint8_t* buf); 63 | 64 | #endif // #if defined(ECB) && (ECB == !) 65 | 66 | 67 | #if defined(CBC) && (CBC == 1) 68 | // buffer size MUST be mutile of AES_BLOCKLEN; 69 | // Suggest https://en.wikipedia.org/wiki/Padding_(cryptography)#PKCS7 for padding scheme 70 | // NOTES: you need to set IV in ctx via AES_init_ctx_iv() or AES_ctx_set_iv() 71 | // no IV should ever be reused with the same key 72 | void AES_CBC_encrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, uint32_t length); 73 | void AES_CBC_decrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, uint32_t length); 74 | 75 | #endif // #if defined(CBC) && (CBC == 1) 76 | 77 | 78 | #if defined(CTR) && (CTR == 1) 79 | 80 | // Same function for encrypting as for decrypting. 81 | // IV is incremented for every block, and used after encryption as XOR-compliment for output 82 | // Suggesting https://en.wikipedia.org/wiki/Padding_(cryptography)#PKCS7 for padding scheme 83 | // NOTES: you need to set IV in ctx with AES_init_ctx_iv() or AES_ctx_set_iv() 84 | // no IV should ever be reused with the same key 85 | void AES_CTR_xcrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, uint32_t length); 86 | 87 | #endif // #if defined(CTR) && (CTR == 1) 88 | 89 | 90 | #endif //_AES_H_ 91 | -------------------------------------------------------------------------------- /src/common/common.h: -------------------------------------------------------------------------------- 1 | #ifndef COMMON_H 2 | #define COMMON_H 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #include "os_defs.h" 9 | 10 | #define CAFE_OS_SD_PATH "/vol/external01" 11 | #define SD_PATH "sd:" 12 | #define WIIU_PATH "/wiiu" 13 | 14 | #ifndef MEM_BASE 15 | #define MEM_BASE (0x00800000) 16 | #endif 17 | 18 | #define ELF_DATA_ADDR (*(volatile unsigned int*)(MEM_BASE + 0x1300 + 0x00)) 19 | #define ELF_DATA_SIZE (*(volatile unsigned int*)(MEM_BASE + 0x1300 + 0x04)) 20 | #define MAIN_ENTRY_ADDR (*(volatile unsigned int*)(MEM_BASE + 0x1400 + 0x00)) 21 | #define OS_FIRMWARE (*(volatile unsigned int*)(MEM_BASE + 0x1400 + 0x04)) 22 | 23 | #define OS_SPECIFICS ((OsSpecifics*)(MEM_BASE + 0x1500)) 24 | 25 | #ifndef EXIT_SUCCESS 26 | #define EXIT_SUCCESS 0 27 | #endif 28 | #define EXIT_HBL_EXIT 0xFFFFFFFE 29 | #define EXIT_RELAUNCH_ON_LOAD 0xFFFFFFFD 30 | 31 | #ifdef __cplusplus 32 | } 33 | #endif 34 | 35 | #endif /* COMMON_H */ 36 | 37 | -------------------------------------------------------------------------------- /src/common/fs_defs.h: -------------------------------------------------------------------------------- 1 | #ifndef FS_DEFS_H 2 | #define FS_DEFS_H 3 | 4 | #include "types.h" 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | 11 | /* FS defines and types */ 12 | #define FS_MAX_LOCALPATH_SIZE 511 13 | #define FS_MAX_MOUNTPATH_SIZE 128 14 | #define FS_MAX_FULLPATH_SIZE (FS_MAX_LOCALPATH_SIZE + FS_MAX_MOUNTPATH_SIZE) 15 | #define FS_MAX_ARGPATH_SIZE FS_MAX_FULLPATH_SIZE 16 | 17 | #define FS_STATUS_OK 0 18 | #define FS_RET_UNSUPPORTED_CMD 0x0400 19 | #define FS_RET_NO_ERROR 0x0000 20 | #define FS_RET_ALL_ERROR (unsigned int)(-1) 21 | 22 | #define FS_STAT_FLAG_IS_DIRECTORY 0x80000000 23 | 24 | /* max length of file/dir name */ 25 | #define FS_MAX_ENTNAME_SIZE 256 26 | 27 | #define FS_SOURCETYPE_EXTERNAL 0 28 | #define FS_SOURCETYPE_HFIO 1 29 | #define FS_SOURCETYPE_HFIO 1 30 | 31 | #define FS_MOUNT_SOURCE_SIZE 0x300 32 | #define FS_CLIENT_SIZE 0x1700 33 | #define FS_CMD_BLOCK_SIZE 0xA80 34 | 35 | typedef struct 36 | { 37 | uint32_t flag; 38 | uint32_t permission; 39 | uint32_t owner_id; 40 | uint32_t group_id; 41 | uint32_t size; 42 | uint32_t alloc_size; 43 | uint64_t quota_size; 44 | uint32_t ent_id; 45 | uint64_t ctime; 46 | uint64_t mtime; 47 | uint8_t attributes[48]; 48 | } __attribute__((packed)) FSStat; 49 | 50 | typedef struct 51 | { 52 | FSStat stat; 53 | char name[FS_MAX_ENTNAME_SIZE]; 54 | } FSDirEntry; 55 | 56 | 57 | #ifdef __cplusplus 58 | } 59 | #endif 60 | 61 | #endif /* FS_DEFS_H */ 62 | 63 | -------------------------------------------------------------------------------- /src/common/os_defs.h: -------------------------------------------------------------------------------- 1 | #ifndef __OS_DEFS_H_ 2 | #define __OS_DEFS_H_ 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | typedef struct _OsSpecifics 9 | { 10 | unsigned int addr_OSDynLoad_Acquire; 11 | unsigned int addr_OSDynLoad_FindExport; 12 | unsigned int addr_OSTitle_main_entry; 13 | 14 | unsigned int addr_KernSyscallTbl1; 15 | unsigned int addr_KernSyscallTbl2; 16 | unsigned int addr_KernSyscallTbl3; 17 | unsigned int addr_KernSyscallTbl4; 18 | unsigned int addr_KernSyscallTbl5; 19 | } OsSpecifics; 20 | 21 | #ifdef __cplusplus 22 | } 23 | #endif 24 | 25 | #endif // __OS_DEFS_H_ 26 | -------------------------------------------------------------------------------- /src/common/types.h: -------------------------------------------------------------------------------- 1 | #ifndef TYPES_H 2 | #define TYPES_H 3 | 4 | #include 5 | 6 | #endif /* TYPES_H */ 7 | 8 | -------------------------------------------------------------------------------- /src/dynamic_libs/ax_functions.c: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | * Copyright (C) 2015 3 | * by Dimok 4 | * 5 | * This software is provided 'as-is', without any express or implied 6 | * warranty. In no event will the authors be held liable for any 7 | * damages arising from the use of this software. 8 | * 9 | * Permission is granted to anyone to use this software for any 10 | * purpose, including commercial applications, and to alter it and 11 | * redistribute it freely, subject to the following restrictions: 12 | * 13 | * 1. The origin of this software must not be misrepresented; you 14 | * must not claim that you wrote the original software. If you use 15 | * this software in a product, an acknowledgment in the product 16 | * documentation would be appreciated but is not required. 17 | * 18 | * 2. Altered source versions must be plainly marked as such, and 19 | * must not be misrepresented as being the original software. 20 | * 21 | * 3. This notice may not be removed or altered from any source 22 | * distribution. 23 | ***************************************************************************/ 24 | #include "os_functions.h" 25 | #include "ax_functions.h" 26 | 27 | EXPORT_DECL(void, AXInitWithParams, u32 * params); 28 | EXPORT_DECL(void, AXQuit, void); 29 | EXPORT_DECL(u32, AXGetInputSamplesPerSec, void); 30 | EXPORT_DECL(u32, AXGetInputSamplesPerFrame, void); 31 | EXPORT_DECL(s32, AXVoiceBegin, void *v); 32 | EXPORT_DECL(s32, AXVoiceEnd, void *v); 33 | EXPORT_DECL(void, AXSetVoiceType, void *v, u16 type); 34 | EXPORT_DECL(void, AXSetVoiceOffsets, void *v, const void *buf); 35 | EXPORT_DECL(void, AXSetVoiceSrcType, void *v, u32 type); 36 | EXPORT_DECL(void, AXSetVoiceVe, void *v, const void *vol); 37 | EXPORT_DECL(s32, AXSetVoiceDeviceMix, void *v, s32 device, u32 id, void *mix); 38 | EXPORT_DECL(void, AXSetVoiceState, void *v, u16 state); 39 | EXPORT_DECL(void, AXSetVoiceSrc, void *v, const void *src); 40 | EXPORT_DECL(s32, AXSetVoiceSrcRatio, void *v,f32 ratio) 41 | EXPORT_DECL(void *, AXAcquireVoice, u32 prio, void * callback, u32 arg); 42 | EXPORT_DECL(void, AXFreeVoice, void *v); 43 | EXPORT_DECL(void, AXRegisterFrameCallback, void * callback); 44 | EXPORT_DECL(u32, AXGetVoiceLoopCount, void *v); 45 | EXPORT_DECL(void, AXSetVoiceEndOffset, void *v, u32 offset); 46 | EXPORT_DECL(void, AXSetVoiceLoopOffset, void *v, u32 offset); 47 | 48 | void InitAXFunctionPointers(void) 49 | { 50 | unsigned int *funcPointer = 0; 51 | unsigned int sound_handle; 52 | OSDynLoad_Acquire("sndcore2.rpl", &sound_handle); 53 | 54 | OS_FIND_EXPORT(sound_handle, AXInitWithParams); 55 | OS_FIND_EXPORT(sound_handle, AXQuit); 56 | OS_FIND_EXPORT(sound_handle, AXGetInputSamplesPerSec); 57 | OS_FIND_EXPORT(sound_handle, AXVoiceBegin); 58 | OS_FIND_EXPORT(sound_handle, AXVoiceEnd); 59 | OS_FIND_EXPORT(sound_handle, AXSetVoiceType); 60 | OS_FIND_EXPORT(sound_handle, AXSetVoiceOffsets); 61 | OS_FIND_EXPORT(sound_handle, AXSetVoiceSrcType); 62 | OS_FIND_EXPORT(sound_handle, AXSetVoiceVe); 63 | OS_FIND_EXPORT(sound_handle, AXSetVoiceDeviceMix); 64 | OS_FIND_EXPORT(sound_handle, AXSetVoiceState); 65 | OS_FIND_EXPORT(sound_handle, AXSetVoiceSrc); 66 | OS_FIND_EXPORT(sound_handle, AXSetVoiceSrcRatio); 67 | OS_FIND_EXPORT(sound_handle, AXAcquireVoice); 68 | OS_FIND_EXPORT(sound_handle, AXFreeVoice); 69 | OS_FIND_EXPORT(sound_handle, AXRegisterFrameCallback); 70 | OS_FIND_EXPORT(sound_handle, AXGetVoiceLoopCount); 71 | OS_FIND_EXPORT(sound_handle, AXSetVoiceEndOffset); 72 | OS_FIND_EXPORT(sound_handle, AXSetVoiceLoopOffset); 73 | } 74 | 75 | -------------------------------------------------------------------------------- /src/dynamic_libs/ax_functions.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | * Copyright (C) 2015 3 | * by Dimok 4 | * 5 | * This software is provided 'as-is', without any express or implied 6 | * warranty. In no event will the authors be held liable for any 7 | * damages arising from the use of this software. 8 | * 9 | * Permission is granted to anyone to use this software for any 10 | * purpose, including commercial applications, and to alter it and 11 | * redistribute it freely, subject to the following restrictions: 12 | * 13 | * 1. The origin of this software must not be misrepresented; you 14 | * must not claim that you wrote the original software. If you use 15 | * this software in a product, an acknowledgment in the product 16 | * documentation would be appreciated but is not required. 17 | * 18 | * 2. Altered source versions must be plainly marked as such, and 19 | * must not be misrepresented as being the original software. 20 | * 21 | * 3. This notice may not be removed or altered from any source 22 | * distribution. 23 | ***************************************************************************/ 24 | #ifndef __AX_FUNCTIONS_H_ 25 | #define __AX_FUNCTIONS_H_ 26 | 27 | #ifdef __cplusplus 28 | extern "C" { 29 | #endif 30 | 31 | #include 32 | 33 | void InitAXFunctionPointers(void); 34 | 35 | extern void (* AXInitWithParams)(u32 * params); 36 | extern void (* AXQuit)(void); 37 | extern u32 (* AXGetInputSamplesPerSec)(void); 38 | extern s32 (* AXVoiceBegin)(void *v); 39 | extern s32 (* AXVoiceEnd)(void *v); 40 | extern void (* AXSetVoiceType)(void *v, u16 type); 41 | extern void (* AXSetVoiceOffsets)(void *v, const void *buf); 42 | extern void (* AXSetVoiceSrcType)(void *v, u32 type); 43 | extern void (* AXSetVoiceVe)(void *v, const void *vol); 44 | extern s32 (* AXSetVoiceDeviceMix)(void *v, s32 device, u32 id, void *mix); 45 | extern void (* AXSetVoiceState)(void *v, u16 state); 46 | extern void (* AXSetVoiceSrc)(void *v, const void *src); 47 | extern s32 (* AXSetVoiceSrcRatio)(void *v, f32 ratio); 48 | extern void * (* AXAcquireVoice)(u32 prio, void * callback, u32 arg); 49 | extern void (* AXFreeVoice)(void *v); 50 | extern void (* AXRegisterFrameCallback)(void * callback); 51 | extern u32 (* AXGetVoiceLoopCount)(void * v); 52 | extern void (* AXSetVoiceEndOffset)(void * v, u32 offset); 53 | extern void (* AXSetVoiceLoopOffset)(void * v, u32 offset); 54 | 55 | #ifdef __cplusplus 56 | } 57 | #endif 58 | 59 | #endif // __VPAD_FUNCTIONS_H_ 60 | -------------------------------------------------------------------------------- /src/dynamic_libs/fs_functions.c: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | * Copyright (C) 2015 3 | * by Dimok 4 | * 5 | * This software is provided 'as-is', without any express or implied 6 | * warranty. In no event will the authors be held liable for any 7 | * damages arising from the use of this software. 8 | * 9 | * Permission is granted to anyone to use this software for any 10 | * purpose, including commercial applications, and to alter it and 11 | * redistribute it freely, subject to the following restrictions: 12 | * 13 | * 1. The origin of this software must not be misrepresented; you 14 | * must not claim that you wrote the original software. If you use 15 | * this software in a product, an acknowledgment in the product 16 | * documentation would be appreciated but is not required. 17 | * 18 | * 2. Altered source versions must be plainly marked as such, and 19 | * must not be misrepresented as being the original software. 20 | * 21 | * 3. This notice may not be removed or altered from any source 22 | * distribution. 23 | ***************************************************************************/ 24 | #include "fs_functions.h" 25 | #include "os_functions.h" 26 | #include "utils/utils.h" 27 | 28 | EXPORT_DECL(int, FSInit, void); 29 | EXPORT_DECL(int, FSShutdown, void); 30 | EXPORT_DECL(int, FSAddClientEx, void *pClient, int unk_zero_param, int errHandling); 31 | EXPORT_DECL(int, FSDelClient, void *pClient); 32 | EXPORT_DECL(void, FSInitCmdBlock, void *pCmd); 33 | EXPORT_DECL(int, FSGetMountSource, void *pClient, void *pCmd, int type, void *source, int errHandling); 34 | 35 | EXPORT_DECL(int, FSMount, void *pClient, void *pCmd, void *source, char *target, uint32_t bytes, int errHandling); 36 | EXPORT_DECL(int, FSUnmount, void *pClient, void *pCmd, const char *target, int errHandling); 37 | 38 | EXPORT_DECL(int, FSGetStat, void *pClient, void *pCmd, const char *path, FSStat *stats, int errHandling); 39 | EXPORT_DECL(int, FSGetStatAsync, void *pClient, void *pCmd, const char *path, void *stats, int error, void *asyncParams); 40 | EXPORT_DECL(int, FSRename, void *pClient, void *pCmd, const char *oldPath, const char *newPath, int error); 41 | EXPORT_DECL(int, FSRenameAsync, void *pClient, void *pCmd, const char *oldPath, const char *newPath, int error, void *asyncParams); 42 | EXPORT_DECL(int, FSRemove, void *pClient, void *pCmd, const char *path, int error); 43 | EXPORT_DECL(int, FSRemoveAsync, void *pClient, void *pCmd, const char *path, int error, void *asyncParams); 44 | EXPORT_DECL(int, FSFlushQuota, void *pClient, void *pCmd, const char* path, int error); 45 | EXPORT_DECL(int, FSFlushQuotaAsync, void *pClient, void *pCmd, const char *path, int error, void *asyncParams); 46 | EXPORT_DECL(int, FSGetFreeSpaceSize, void *pClient, void *pCmd, const char *path, uint64_t *returnedFreeSize, int error); 47 | EXPORT_DECL(int, FSGetFreeSpaceSizeAsync, void *pClient, void *pCmd, const char *path, uint64_t *returnedFreeSize, int error, void *asyncParams); 48 | EXPORT_DECL(int, FSRollbackQuota, void *pClient, void *pCmd, const char *path, int error); 49 | EXPORT_DECL(int, FSRollbackQuotaAsync, void *pClient, void *pCmd, const char *path, int error, void *asyncParams); 50 | 51 | EXPORT_DECL(int, FSOpenDir, void *pClient, void *pCmd, const char *path, int *dh, int errHandling); 52 | EXPORT_DECL(int, FSOpenDirAsync, void *pClient, void* pCmd, const char *path, int *handle, int error, void *asyncParams); 53 | EXPORT_DECL(int, FSReadDir, void *pClient, void *pCmd, int dh, FSDirEntry *dir_entry, int errHandling); 54 | EXPORT_DECL(int, FSRewindDir, void *pClient, void *pCmd, int dh, int errHandling); 55 | EXPORT_DECL(int, FSCloseDir, void *pClient, void *pCmd, int dh, int errHandling); 56 | EXPORT_DECL(int, FSChangeDir, void *pClient, void *pCmd, const char *path, int errHandling); 57 | EXPORT_DECL(int, FSChangeDirAsync, void *pClient, void *pCmd, const char *path, int error, void *asyncParams); 58 | EXPORT_DECL(int, FSMakeDir, void *pClient, void *pCmd, const char *path, int errHandling); 59 | EXPORT_DECL(int, FSMakeDirAsync, void *pClient, void *pCmd, const char *path, int error, void *asyncParams); 60 | 61 | EXPORT_DECL(int, FSOpenFile, void *pClient, void *pCmd, const char *path, const char *mode, int *fd, int errHandling); 62 | EXPORT_DECL(int, FSOpenFileAsync, void *pClient, void *pCmd, const char *path, const char *mode, int *handle, int error, const void *asyncParams); 63 | EXPORT_DECL(int, FSReadFile, void *pClient, void *pCmd, void *buffer, int size, int count, int fd, int flag, int errHandling); 64 | EXPORT_DECL(int, FSCloseFile, void *pClient, void *pCmd, int fd, int errHandling); 65 | 66 | EXPORT_DECL(int, FSFlushFile, void *pClient, void *pCmd, int fd, int error); 67 | EXPORT_DECL(int, FSTruncateFile, void *pClient, void *pCmd, int fd, int error); 68 | EXPORT_DECL(int, FSGetStatFile, void *pClient, void *pCmd, int fd, void *buffer, int error); 69 | EXPORT_DECL(int, FSSetPosFile, void *pClient, void *pCmd, int fd, int pos, int error); 70 | EXPORT_DECL(int, FSWriteFile, void *pClient, void *pCmd, const void *source, int block_size, int block_count, int fd, int flag, int error); 71 | 72 | void InitFSFunctionPointers(void) 73 | { 74 | unsigned int *funcPointer = 0; 75 | 76 | OS_FIND_EXPORT(coreinit_handle, FSInit); 77 | OS_FIND_EXPORT(coreinit_handle, FSShutdown); 78 | OS_FIND_EXPORT(coreinit_handle, FSAddClientEx); 79 | OS_FIND_EXPORT(coreinit_handle, FSDelClient); 80 | OS_FIND_EXPORT(coreinit_handle, FSInitCmdBlock); 81 | OS_FIND_EXPORT(coreinit_handle, FSGetMountSource); 82 | 83 | OS_FIND_EXPORT(coreinit_handle, FSMount); 84 | OS_FIND_EXPORT(coreinit_handle, FSUnmount); 85 | 86 | OS_FIND_EXPORT(coreinit_handle, FSGetStat); 87 | OS_FIND_EXPORT(coreinit_handle, FSGetStatAsync); 88 | OS_FIND_EXPORT(coreinit_handle, FSRename); 89 | OS_FIND_EXPORT(coreinit_handle, FSRenameAsync); 90 | OS_FIND_EXPORT(coreinit_handle, FSRemove); 91 | OS_FIND_EXPORT(coreinit_handle, FSRemoveAsync); 92 | OS_FIND_EXPORT(coreinit_handle, FSFlushQuota); 93 | OS_FIND_EXPORT(coreinit_handle, FSFlushQuotaAsync); 94 | OS_FIND_EXPORT(coreinit_handle, FSGetFreeSpaceSize); 95 | OS_FIND_EXPORT(coreinit_handle, FSGetFreeSpaceSizeAsync); 96 | OS_FIND_EXPORT(coreinit_handle, FSRollbackQuota); 97 | OS_FIND_EXPORT(coreinit_handle, FSRollbackQuotaAsync); 98 | 99 | OS_FIND_EXPORT(coreinit_handle, FSOpenDir); 100 | OS_FIND_EXPORT(coreinit_handle, FSOpenDirAsync); 101 | OS_FIND_EXPORT(coreinit_handle, FSReadDir); 102 | OS_FIND_EXPORT(coreinit_handle, FSRewindDir); 103 | OS_FIND_EXPORT(coreinit_handle, FSCloseDir); 104 | OS_FIND_EXPORT(coreinit_handle, FSChangeDir); 105 | OS_FIND_EXPORT(coreinit_handle, FSChangeDirAsync); 106 | OS_FIND_EXPORT(coreinit_handle, FSMakeDir); 107 | OS_FIND_EXPORT(coreinit_handle, FSMakeDirAsync); 108 | 109 | 110 | OS_FIND_EXPORT(coreinit_handle, FSOpenFile); 111 | OS_FIND_EXPORT(coreinit_handle, FSOpenFileAsync); 112 | OS_FIND_EXPORT(coreinit_handle, FSReadFile); 113 | OS_FIND_EXPORT(coreinit_handle, FSCloseFile); 114 | 115 | OS_FIND_EXPORT(coreinit_handle, FSFlushFile); 116 | OS_FIND_EXPORT(coreinit_handle, FSTruncateFile); 117 | OS_FIND_EXPORT(coreinit_handle, FSGetStatFile); 118 | OS_FIND_EXPORT(coreinit_handle, FSSetPosFile); 119 | OS_FIND_EXPORT(coreinit_handle, FSWriteFile); 120 | } 121 | -------------------------------------------------------------------------------- /src/dynamic_libs/fs_functions.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | * Copyright (C) 2015 3 | * by Dimok 4 | * 5 | * This software is provided 'as-is', without any express or implied 6 | * warranty. In no event will the authors be held liable for any 7 | * damages arising from the use of this software. 8 | * 9 | * Permission is granted to anyone to use this software for any 10 | * purpose, including commercial applications, and to alter it and 11 | * redistribute it freely, subject to the following restrictions: 12 | * 13 | * 1. The origin of this software must not be misrepresented; you 14 | * must not claim that you wrote the original software. If you use 15 | * this software in a product, an acknowledgment in the product 16 | * documentation would be appreciated but is not required. 17 | * 18 | * 2. Altered source versions must be plainly marked as such, and 19 | * must not be misrepresented as being the original software. 20 | * 21 | * 3. This notice may not be removed or altered from any source 22 | * distribution. 23 | ***************************************************************************/ 24 | #ifndef __FS_FUNCTIONS_H_ 25 | #define __FS_FUNCTIONS_H_ 26 | 27 | #ifdef __cplusplus 28 | extern "C" { 29 | #endif 30 | 31 | #include "common/fs_defs.h" 32 | 33 | void InitFSFunctionPointers(void); 34 | 35 | extern int (* FSInit)(void); 36 | extern int (* FSShutdown)(void); 37 | extern int (* FSAddClientEx)(void *pClient, int unk_zero_param, int errHandling); 38 | extern int (* FSDelClient)(void *pClient); 39 | extern void (* FSInitCmdBlock)(void *pCmd); 40 | extern int (* FSGetMountSource)(void *pClient, void *pCmd, int type, void *source, int errHandling); 41 | 42 | extern int (* FSMount)(void *pClient, void *pCmd, void *source, char *target, uint32_t bytes, int errHandling); 43 | extern int (* FSUnmount)(void *pClient, void *pCmd, const char *target, int errHandling); 44 | extern int (* FSRename)(void *pClient, void *pCmd, const char *oldPath, const char *newPath, int error); 45 | extern int (* FSRenameAsync)(void *pClient, void *pCmd, const char *oldPath, const char *newPath, int error, void *asyncParams); 46 | extern int (* FSRemove)(void *pClient, void *pCmd, const char *path, int error); 47 | extern int (* FSRemoveAsync)(void *pClient, void *pCmd, const char *path, int error, void *asyncParams); 48 | 49 | extern int (* FSGetStat)(void *pClient, void *pCmd, const char *path, FSStat *stats, int errHandling); 50 | extern int (* FSGetStatAsync)(void *pClient, void *pCmd, const char *path, void *stats, int error, void *asyncParams); 51 | extern int (* FSRename)(void *pClient, void *pCmd, const char *oldPath, const char *newPath, int error); 52 | extern int (* FSRenameAsync)(void *pClient, void *pCmd, const char *oldPath, const char *newPath, int error, void *asyncParams); 53 | extern int (* FSRemove)(void *pClient, void *pCmd, const char *path, int error); 54 | extern int (* FSRemoveAsync)(void *pClient, void *pCmd, const char *path, int error, void *asyncParams); 55 | extern int (* FSFlushQuota)(void *pClient, void *pCmd, const char* path, int error); 56 | extern int (* FSFlushQuotaAsync)(void *pClient, void *pCmd, const char *path, int error, void *asyncParams); 57 | extern int (* FSGetFreeSpaceSize)(void *pClient, void *pCmd, const char *path, uint64_t *returnedFreeSize, int error); 58 | extern int (* FSGetFreeSpaceSizeAsync)(void *pClient, void *pCmd, const char *path, uint64_t *returnedFreeSize, int error, void *asyncParams); 59 | extern int (* FSRollbackQuota)(void *pClient, void *pCmd, const char *path, int error); 60 | extern int (* FSRollbackQuotaAsync)(void *pClient, void *pCmd, const char *path, int error, void *asyncParams); 61 | 62 | extern int (* FSOpenDir)(void *pClient, void *pCmd, const char *path, int *dh, int errHandling); 63 | extern int (* FSOpenDirAsync)(void *pClient, void* pCmd, const char *path, int *handle, int error, void *asyncParams); 64 | extern int (* FSReadDir)(void *pClient, void *pCmd, int dh, FSDirEntry *dir_entry, int errHandling); 65 | extern int (* FSRewindDir)(void *pClient, void *pCmd, int dh, int errHandling); 66 | extern int (* FSCloseDir)(void *pClient, void *pCmd, int dh, int errHandling); 67 | extern int (* FSChangeDir)(void *pClient, void *pCmd, const char *path, int errHandling); 68 | extern int (* FSChangeDirAsync)(void *pClient, void *pCmd, const char *path, int error, void *asyncParams); 69 | extern int (* FSMakeDir)(void *pClient, void *pCmd, const char *path, int errHandling); 70 | extern int (* FSMakeDirAsync)(void *pClient, void *pCmd, const char *path, int error, void *asyncParams); 71 | 72 | extern int (* FSOpenFile)(void *pClient, void *pCmd, const char *path, const char *mode, int *fd, int errHandling); 73 | extern int (* FSOpenFileAsync)(void *pClient, void *pCmd, const char *path, const char *mode, int *handle, int error, const void *asyncParams); 74 | extern int (* FSReadFile)(void *pClient, void *pCmd, void *buffer, int size, int count, int fd, int flag, int errHandling); 75 | extern int (* FSCloseFile)(void *pClient, void *pCmd, int fd, int errHandling); 76 | 77 | extern int (* FSFlushFile)(void *pClient, void *pCmd, int fd, int error); 78 | extern int (* FSTruncateFile)(void *pClient, void *pCmd, int fd, int error); 79 | extern int (* FSGetStatFile)(void *pClient, void *pCmd, int fd, void *buffer, int error); 80 | extern int (* FSSetPosFile)(void *pClient, void *pCmd, int fd, int pos, int error); 81 | extern int (* FSWriteFile)(void *pClient, void *pCmd, const void *source, int block_size, int block_count, int fd, int flag, int error); 82 | 83 | #ifdef __cplusplus 84 | } 85 | #endif 86 | 87 | #endif // __FS_FUNCTIONS_H_ 88 | -------------------------------------------------------------------------------- /src/dynamic_libs/gx2_functions.c: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | * Copyright (C) 2015 3 | * by Dimok 4 | * 5 | * This software is provided 'as-is', without any express or implied 6 | * warranty. In no event will the authors be held liable for any 7 | * damages arising from the use of this software. 8 | * 9 | * Permission is granted to anyone to use this software for any 10 | * purpose, including commercial applications, and to alter it and 11 | * redistribute it freely, subject to the following restrictions: 12 | * 13 | * 1. The origin of this software must not be misrepresented; you 14 | * must not claim that you wrote the original software. If you use 15 | * this software in a product, an acknowledgment in the product 16 | * documentation would be appreciated but is not required. 17 | * 18 | * 2. Altered source versions must be plainly marked as such, and 19 | * must not be misrepresented as being the original software. 20 | * 21 | * 3. This notice may not be removed or altered from any source 22 | * distribution. 23 | ***************************************************************************/ 24 | #include "os_functions.h" 25 | #include "gx2_types.h" 26 | #include "utils/utils.h" 27 | 28 | EXPORT_DECL(void, GX2Init, u32 * init_attribs); 29 | EXPORT_DECL(void, GX2Shutdown, void); 30 | EXPORT_DECL(void, GX2Flush, void); 31 | EXPORT_DECL(s32, GX2GetMainCoreId, void) ; 32 | EXPORT_DECL(s32, GX2DrawDone, void); 33 | EXPORT_DECL(void, GX2ClearColor, GX2ColorBuffer *colorBuffer, f32 r, f32 g, f32 b, f32 a); 34 | EXPORT_DECL(void, GX2SetViewport, f32 x, f32 y, f32 w, f32 h, f32 nearZ, f32 farZ); 35 | EXPORT_DECL(void, GX2SetScissor, u32 x_orig, u32 y_orig, u32 wd, u32 ht); 36 | EXPORT_DECL(void, GX2SetContextState, const GX2ContextState* state); 37 | EXPORT_DECL(void, GX2DrawEx, s32 primitive_type, u32 count, u32 first_vertex, u32 instances_count); 38 | EXPORT_DECL(void, GX2DrawIndexedEx, s32 primitive_type, u32 count, s32 index_format, const void* idx, u32 first_vertex, u32 instances_count); 39 | EXPORT_DECL(void, GX2ClearDepthStencilEx, GX2DepthBuffer *depthBuffer, f32 depth_value, u8 stencil_value, s32 clear_mode); 40 | EXPORT_DECL(void, GX2CopyColorBufferToScanBuffer, const GX2ColorBuffer *colorBuffer, s32 scan_target); 41 | EXPORT_DECL(void, GX2SwapScanBuffers, void); 42 | EXPORT_DECL(void, GX2SetTVEnable, s32 enable); 43 | EXPORT_DECL(void, GX2SetSwapInterval, u32 swap_interval); 44 | EXPORT_DECL(u32, GX2GetSwapInterval, void); 45 | EXPORT_DECL(void, GX2WaitForVsync, void); 46 | EXPORT_DECL(void, GX2CalcTVSize, s32 tv_render_mode, s32 format, s32 buffering_mode, u32 * size, s32 * scale_needed); 47 | EXPORT_DECL(void, GX2Invalidate, s32 invalidate_type, void * ptr, u32 buffer_size); 48 | EXPORT_DECL(void, GX2SetTVBuffer, void *buffer, u32 buffer_size, s32 tv_render_mode, s32 format, s32 buffering_mode); 49 | EXPORT_DECL(void, GX2CalcSurfaceSizeAndAlignment, GX2Surface *surface); 50 | EXPORT_DECL(void, GX2InitDepthBufferRegs, GX2DepthBuffer *depthBuffer); 51 | EXPORT_DECL(void, GX2InitColorBufferRegs, GX2ColorBuffer *colorBuffer); 52 | EXPORT_DECL(void, GX2CalcColorBufferAuxInfo, GX2ColorBuffer *colorBuffer, u32 *size, u32 *align); 53 | EXPORT_DECL(void, GX2CalcDepthBufferHiZInfo, GX2DepthBuffer *depthBuffer, u32 *size, u32 *align); 54 | EXPORT_DECL(void, GX2InitDepthBufferHiZEnable, GX2DepthBuffer *depthBuffer, s32 hiZ_enable); 55 | EXPORT_DECL(void, GX2SetupContextStateEx, GX2ContextState* state, s32 enable_profiling); 56 | EXPORT_DECL(void, GX2SetColorBuffer, const GX2ColorBuffer *colorBuffer, s32 target); 57 | EXPORT_DECL(void, GX2SetDepthBuffer, const GX2DepthBuffer *depthBuffer); 58 | EXPORT_DECL(void, GX2SetAttribBuffer, u32 attr_index, u32 attr_size, u32 stride, const void* attr); 59 | EXPORT_DECL(void, GX2InitTextureRegs, GX2Texture *texture); 60 | EXPORT_DECL(void, GX2InitSampler, GX2Sampler *sampler, s32 tex_clamp, s32 min_mag_filter); 61 | EXPORT_DECL(u32, GX2CalcFetchShaderSizeEx, u32 num_attrib, s32 fetch_shader_type, s32 tessellation_mode); 62 | EXPORT_DECL(void, GX2InitFetchShaderEx, GX2FetchShader* fs, void* fs_buffer, u32 count, const GX2AttribStream* attribs, s32 fetch_shader_type, s32 tessellation_mode); 63 | EXPORT_DECL(void, GX2SetFetchShader, const GX2FetchShader* fs); 64 | EXPORT_DECL(void, GX2SetVertexUniformReg, u32 offset, u32 count, const void *values); 65 | EXPORT_DECL(void, GX2SetPixelUniformReg, u32 offset, u32 count, const void *values); 66 | EXPORT_DECL(void, GX2SetPixelTexture, const GX2Texture *texture, u32 texture_hw_location); 67 | EXPORT_DECL(void, GX2SetVertexTexture, const GX2Texture *texture, u32 texture_hw_location); 68 | EXPORT_DECL(void, GX2SetPixelSampler, const GX2Sampler *sampler, u32 sampler_hw_location); 69 | EXPORT_DECL(void, GX2SetVertexSampler, const GX2Sampler *sampler, u32 sampler_hw_location); 70 | EXPORT_DECL(void, GX2SetPixelShader, const GX2PixelShader* pixelShader); 71 | EXPORT_DECL(void, GX2SetVertexShader, const GX2VertexShader* vertexShader); 72 | EXPORT_DECL(void, GX2InitSamplerZMFilter, GX2Sampler *sampler, s32 z_filter, s32 mip_filter); 73 | EXPORT_DECL(void, GX2SetColorControl, s32 lop, u8 blend_enable_mask, s32 enable_multi_write, s32 enable_color_buffer); 74 | EXPORT_DECL(void, GX2SetDepthOnlyControl, s32 enable_depth, s32 enable_depth_write, s32 depth_comp_function); 75 | EXPORT_DECL(void, GX2SetBlendControl, s32 target, s32 color_src_blend, s32 color_dst_blend, s32 color_combine, s32 separate_alpha_blend, s32 alpha_src_blend, s32 alpha_dst_blend, s32 alpha_combine); 76 | EXPORT_DECL(void, GX2CalcDRCSize, s32 drc_mode, s32 format, s32 buffering_mode, u32 *size, s32 *scale_needed); 77 | EXPORT_DECL(void, GX2SetDRCBuffer, void *buffer, u32 buffer_size, s32 drc_mode, s32 surface_format, s32 buffering_mode); 78 | EXPORT_DECL(void, GX2SetDRCScale, u32 width, u32 height); 79 | EXPORT_DECL(void, GX2SetDRCEnable, s32 enable); 80 | EXPORT_DECL(void, GX2SetPolygonControl, s32 front_face_mode, s32 cull_front, s32 cull_back, s32 enable_mode, s32 mode_font, s32 mode_back, s32 poly_offset_front, s32 poly_offset_back, s32 point_line_offset); 81 | EXPORT_DECL(void, GX2SetCullOnlyControl, s32 front_face_mode, s32 cull_front, s32 cull_back); 82 | EXPORT_DECL(void, GX2SetDepthStencilControl, s32 enable_depth_test, s32 enable_depth_write, s32 depth_comp_function, s32 stencil_test_enable, s32 back_stencil_enable, 83 | s32 font_stencil_func, s32 front_stencil_z_pass, s32 front_stencil_z_fail, s32 front_stencil_fail, 84 | s32 back_stencil_func, s32 back_stencil_z_pass, s32 back_stencil_z_fail, s32 back_stencil_fail); 85 | EXPORT_DECL(void, GX2SetStencilMask, u8 mask_front, u8 write_mask_front, u8 ref_front, u8 mask_back, u8 write_mask_back, u8 ref_back); 86 | EXPORT_DECL(void, GX2SetLineWidth, f32 width); 87 | EXPORT_DECL(void, GX2SetTVGamma, f32 val); 88 | EXPORT_DECL(void, GX2SetDRCGamma, f32 gam); 89 | EXPORT_DECL(s32, GX2GetSystemTVScanMode, void); 90 | EXPORT_DECL(s32, GX2GetSystemDRCScanMode, void); 91 | EXPORT_DECL(void, GX2RSetAllocator, void * (* allocFunc)(u32, u32, u32), void (* freeFunc)(u32, void*)); 92 | 93 | 94 | void InitGX2FunctionPointers(void) 95 | { 96 | unsigned int *funcPointer = 0; 97 | unsigned int gx2_handle; 98 | OSDynLoad_Acquire("gx2.rpl", &gx2_handle); 99 | 100 | OS_FIND_EXPORT(gx2_handle, GX2Init); 101 | OS_FIND_EXPORT(gx2_handle, GX2Shutdown); 102 | OS_FIND_EXPORT(gx2_handle, GX2Flush); 103 | OS_FIND_EXPORT(gx2_handle, GX2GetMainCoreId); 104 | OS_FIND_EXPORT(gx2_handle, GX2DrawDone); 105 | OS_FIND_EXPORT(gx2_handle, GX2ClearColor); 106 | OS_FIND_EXPORT(gx2_handle, GX2SetViewport); 107 | OS_FIND_EXPORT(gx2_handle, GX2SetScissor); 108 | OS_FIND_EXPORT(gx2_handle, GX2SetContextState); 109 | OS_FIND_EXPORT(gx2_handle, GX2DrawEx); 110 | OS_FIND_EXPORT(gx2_handle, GX2DrawIndexedEx); 111 | OS_FIND_EXPORT(gx2_handle, GX2ClearDepthStencilEx); 112 | OS_FIND_EXPORT(gx2_handle, GX2CopyColorBufferToScanBuffer); 113 | OS_FIND_EXPORT(gx2_handle, GX2SwapScanBuffers); 114 | OS_FIND_EXPORT(gx2_handle, GX2SetTVEnable); 115 | OS_FIND_EXPORT(gx2_handle, GX2SetSwapInterval); 116 | OS_FIND_EXPORT(gx2_handle, GX2GetSwapInterval); 117 | OS_FIND_EXPORT(gx2_handle, GX2WaitForVsync); 118 | OS_FIND_EXPORT(gx2_handle, GX2CalcTVSize); 119 | OS_FIND_EXPORT(gx2_handle, GX2Invalidate); 120 | OS_FIND_EXPORT(gx2_handle, GX2SetTVBuffer); 121 | OS_FIND_EXPORT(gx2_handle, GX2CalcSurfaceSizeAndAlignment); 122 | OS_FIND_EXPORT(gx2_handle, GX2InitDepthBufferRegs); 123 | OS_FIND_EXPORT(gx2_handle, GX2InitColorBufferRegs); 124 | OS_FIND_EXPORT(gx2_handle, GX2CalcColorBufferAuxInfo); 125 | OS_FIND_EXPORT(gx2_handle, GX2CalcDepthBufferHiZInfo); 126 | OS_FIND_EXPORT(gx2_handle, GX2InitDepthBufferHiZEnable); 127 | OS_FIND_EXPORT(gx2_handle, GX2SetupContextStateEx); 128 | OS_FIND_EXPORT(gx2_handle, GX2SetColorBuffer); 129 | OS_FIND_EXPORT(gx2_handle, GX2SetDepthBuffer); 130 | OS_FIND_EXPORT(gx2_handle, GX2SetAttribBuffer); 131 | OS_FIND_EXPORT(gx2_handle, GX2InitTextureRegs); 132 | OS_FIND_EXPORT(gx2_handle, GX2InitSampler); 133 | OS_FIND_EXPORT(gx2_handle, GX2CalcFetchShaderSizeEx); 134 | OS_FIND_EXPORT(gx2_handle, GX2InitFetchShaderEx); 135 | OS_FIND_EXPORT(gx2_handle, GX2SetFetchShader); 136 | OS_FIND_EXPORT(gx2_handle, GX2SetVertexUniformReg); 137 | OS_FIND_EXPORT(gx2_handle, GX2SetPixelUniformReg); 138 | OS_FIND_EXPORT(gx2_handle, GX2SetPixelTexture); 139 | OS_FIND_EXPORT(gx2_handle, GX2SetVertexTexture); 140 | OS_FIND_EXPORT(gx2_handle, GX2SetPixelSampler); 141 | OS_FIND_EXPORT(gx2_handle, GX2SetVertexSampler); 142 | OS_FIND_EXPORT(gx2_handle, GX2SetPixelShader); 143 | OS_FIND_EXPORT(gx2_handle, GX2SetVertexShader); 144 | OS_FIND_EXPORT(gx2_handle, GX2InitSamplerZMFilter); 145 | OS_FIND_EXPORT(gx2_handle, GX2SetColorControl); 146 | OS_FIND_EXPORT(gx2_handle, GX2SetDepthOnlyControl); 147 | OS_FIND_EXPORT(gx2_handle, GX2SetBlendControl); 148 | OS_FIND_EXPORT(gx2_handle, GX2CalcDRCSize); 149 | OS_FIND_EXPORT(gx2_handle, GX2SetDRCBuffer); 150 | OS_FIND_EXPORT(gx2_handle, GX2SetDRCScale); 151 | OS_FIND_EXPORT(gx2_handle, GX2SetDRCEnable); 152 | OS_FIND_EXPORT(gx2_handle, GX2SetPolygonControl); 153 | OS_FIND_EXPORT(gx2_handle, GX2SetCullOnlyControl); 154 | OS_FIND_EXPORT(gx2_handle, GX2SetDepthStencilControl); 155 | OS_FIND_EXPORT(gx2_handle, GX2SetStencilMask); 156 | OS_FIND_EXPORT(gx2_handle, GX2SetLineWidth); 157 | OS_FIND_EXPORT(gx2_handle, GX2SetDRCGamma); 158 | OS_FIND_EXPORT(gx2_handle, GX2SetTVGamma); 159 | OS_FIND_EXPORT(gx2_handle, GX2GetSystemTVScanMode); 160 | OS_FIND_EXPORT(gx2_handle, GX2GetSystemDRCScanMode); 161 | OS_FIND_EXPORT(gx2_handle, GX2RSetAllocator); 162 | } 163 | -------------------------------------------------------------------------------- /src/dynamic_libs/gx2_functions.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | * Copyright (C) 2015 3 | * by Dimok 4 | * 5 | * This software is provided 'as-is', without any express or implied 6 | * warranty. In no event will the authors be held liable for any 7 | * damages arising from the use of this software. 8 | * 9 | * Permission is granted to anyone to use this software for any 10 | * purpose, including commercial applications, and to alter it and 11 | * redistribute it freely, subject to the following restrictions: 12 | * 13 | * 1. The origin of this software must not be misrepresented; you 14 | * must not claim that you wrote the original software. If you use 15 | * this software in a product, an acknowledgment in the product 16 | * documentation would be appreciated but is not required. 17 | * 18 | * 2. Altered source versions must be plainly marked as such, and 19 | * must not be misrepresented as being the original software. 20 | * 21 | * 3. This notice may not be removed or altered from any source 22 | * distribution. 23 | ***************************************************************************/ 24 | #ifndef __GX2_FUNCTIONS_H_ 25 | #define __GX2_FUNCTIONS_H_ 26 | 27 | #ifdef __cplusplus 28 | extern "C" { 29 | #endif 30 | 31 | #include "gx2_types.h" 32 | 33 | void InitGX2FunctionPointers(void); 34 | 35 | extern void (* GX2Init)(u32 * init_attribs); 36 | extern void (* GX2Shutdown)(void); 37 | extern void (* GX2Flush)(void); 38 | extern s32 (* GX2GetMainCoreId)(void) ; 39 | extern s32 (* GX2DrawDone)(void); 40 | extern void (* GX2ClearColor)(GX2ColorBuffer *colorBuffer, f32 r, f32 g, f32 b, f32 a); 41 | extern void (* GX2SetViewport)(f32 x, f32 y, f32 w, f32 h, f32 nearZ, f32 farZ); 42 | extern void (* GX2SetScissor)(u32 x_orig, u32 y_orig, u32 wd, u32 ht); 43 | extern void (* GX2SetContextState)(const GX2ContextState* state); 44 | extern void (* GX2DrawEx)(s32 primitive_type, u32 count, u32 first_vertex, u32 instances_count); 45 | extern void (* GX2DrawIndexedEx)(s32 primitive_type, u32 count, s32 index_format, const void* idx, u32 first_vertex, u32 instances_count); 46 | extern void (* GX2ClearDepthStencilEx)(GX2DepthBuffer *depthBuffer, f32 depth_value, u8 stencil_value, s32 clear_mode); 47 | extern void (* GX2CopyColorBufferToScanBuffer)(const GX2ColorBuffer *colorBuffer, s32 scan_target); 48 | extern void (* GX2SwapScanBuffers)(void); 49 | extern void (* GX2SetTVEnable)(s32 enable); 50 | extern void (* GX2SetSwapInterval)(u32 swap_interval); 51 | extern u32 (* GX2GetSwapInterval)(void); 52 | extern void (* GX2WaitForVsync)(void); 53 | extern void (* GX2CalcTVSize)(s32 tv_render_mode, s32 format, s32 buffering_mode, u32 * size, s32 * scale_needed); 54 | extern void (* GX2Invalidate)(s32 invalidate_type, void * ptr, u32 buffer_size); 55 | extern void (* GX2SetTVBuffer)(void *buffer, u32 buffer_size, s32 tv_render_mode, s32 format, s32 buffering_mode); 56 | extern void (* GX2CalcSurfaceSizeAndAlignment)(GX2Surface *surface); 57 | extern void (* GX2InitDepthBufferRegs)(GX2DepthBuffer *depthBuffer); 58 | extern void (* GX2InitColorBufferRegs)(GX2ColorBuffer *colorBuffer); 59 | extern void (* GX2CalcColorBufferAuxInfo)(GX2ColorBuffer *colorBuffer, u32 *size, u32 *align); 60 | extern void (* GX2CalcDepthBufferHiZInfo)(GX2DepthBuffer *depthBuffer, u32 *size, u32 *align); 61 | extern void (* GX2InitDepthBufferHiZEnable)(GX2DepthBuffer *depthBuffer, s32 hiZ_enable); 62 | extern void (* GX2SetupContextStateEx)(GX2ContextState* state, s32 enable_profiling); 63 | extern void (* GX2SetColorBuffer)(const GX2ColorBuffer *colorBuffer, s32 target); 64 | extern void (* GX2SetDepthBuffer)(const GX2DepthBuffer *depthBuffer); 65 | extern void (* GX2SetAttribBuffer)(u32 attr_index, u32 attr_size, u32 stride, const void* attr); 66 | extern void (* GX2InitTextureRegs)(GX2Texture *texture); 67 | extern void (* GX2InitSampler)(GX2Sampler *sampler, s32 tex_clamp, s32 min_mag_filter); 68 | extern u32 (* GX2CalcFetchShaderSizeEx)(u32 num_attrib, s32 fetch_shader_type, s32 tessellation_mode); 69 | extern void (* GX2InitFetchShaderEx)(GX2FetchShader* fs, void* fs_buffer, u32 count, const GX2AttribStream* attribs, s32 fetch_shader_type, s32 tessellation_mode); 70 | extern void (* GX2SetFetchShader)(const GX2FetchShader* fs); 71 | extern void (* GX2SetVertexUniformReg)(u32 offset, u32 count, const void *values); 72 | extern void (* GX2SetPixelUniformReg)(u32 offset, u32 count, const void *values); 73 | extern void (* GX2SetPixelTexture)(const GX2Texture *texture, u32 texture_hw_location); 74 | extern void (* GX2SetVertexTexture)(const GX2Texture *texture, u32 texture_hw_location); 75 | extern void (* GX2SetPixelSampler)(const GX2Sampler *sampler, u32 sampler_hw_location); 76 | extern void (* GX2SetVertexSampler)(const GX2Sampler *sampler, u32 sampler_hw_location); 77 | extern void (* GX2SetPixelShader)(const GX2PixelShader* pixelShader); 78 | extern void (* GX2SetVertexShader)(const GX2VertexShader* vertexShader); 79 | extern void (* GX2InitSamplerZMFilter)(GX2Sampler *sampler, s32 z_filter, s32 mip_filter); 80 | extern void (* GX2SetColorControl)(s32 lop, u8 blend_enable_mask, s32 enable_multi_write, s32 enable_color_buffer); 81 | extern void (* GX2SetDepthOnlyControl)(s32 enable_depth, s32 enable_depth_write, s32 depth_comp_function); 82 | extern void (* GX2SetBlendControl)(s32 target, s32 color_src_blend, s32 color_dst_blend, s32 color_combine, s32 separate_alpha_blend, s32 alpha_src_blend, s32 alpha_dst_blend, s32 alpha_combine); 83 | extern void (* GX2CalcDRCSize)(s32 drc_mode, s32 format, s32 buffering_mode, u32 *size, s32 *scale_needed); 84 | extern void (* GX2SetDRCBuffer)(void *buffer, u32 buffer_size, s32 drc_mode, s32 surface_format, s32 buffering_mode); 85 | extern void (* GX2SetDRCScale)(u32 width, u32 height); 86 | extern void (* GX2SetDRCEnable)(s32 enable); 87 | extern void (* GX2SetPolygonControl)(s32 front_face_mode, s32 cull_front, s32 cull_back, s32 enable_mode, s32 mode_font, s32 mode_back, s32 poly_offset_front, s32 poly_offset_back, s32 point_line_offset); 88 | extern void (* GX2SetCullOnlyControl)(s32 front_face_mode, s32 cull_front, s32 cull_back); 89 | extern void (* GX2SetDepthStencilControl)(s32 enable_depth_test, s32 enable_depth_write, s32 depth_comp_function, s32 stencil_test_enable, s32 back_stencil_enable, 90 | s32 font_stencil_func, s32 front_stencil_z_pass, s32 front_stencil_z_fail, s32 front_stencil_fail, 91 | s32 back_stencil_func, s32 back_stencil_z_pass, s32 back_stencil_z_fail, s32 back_stencil_fail); 92 | extern void (* GX2SetStencilMask)(u8 mask_front, u8 write_mask_front, u8 ref_front, u8 mask_back, u8 write_mask_back, u8 ref_back); 93 | extern void (* GX2SetLineWidth)(f32 width); 94 | extern void (* GX2SetTVGamma)(f32 val); 95 | extern void (* GX2SetDRCGamma)(f32 val); 96 | extern s32 (* GX2GetSystemTVScanMode)(void); 97 | extern s32 (* GX2GetSystemDRCScanMode)(void); 98 | extern void (* GX2RSetAllocator)(void * (*allocFunc)(u32, u32, u32), void (*freeFunc)(u32, void*)); 99 | 100 | static inline void GX2InitDepthBuffer(GX2DepthBuffer *depthBuffer, s32 dimension, u32 width, u32 height, u32 depth, s32 format, s32 aa) 101 | { 102 | depthBuffer->surface.dimension = dimension; 103 | depthBuffer->surface.width = width; 104 | depthBuffer->surface.height = height; 105 | depthBuffer->surface.depth = depth; 106 | depthBuffer->surface.num_mips = 1; 107 | depthBuffer->surface.format = format; 108 | depthBuffer->surface.aa = aa; 109 | depthBuffer->surface.use = ((format==GX2_SURFACE_FORMAT_D_D24_S8_UNORM) || (format==GX2_SURFACE_FORMAT_D_D24_S8_FLOAT)) ? GX2_SURFACE_USE_DEPTH_BUFFER : GX2_SURFACE_USE_DEPTH_BUFFER_TEXTURE; 110 | depthBuffer->surface.tile = GX2_TILE_MODE_DEFAULT; 111 | depthBuffer->surface.swizzle = 0; 112 | depthBuffer->view_mip = 0; 113 | depthBuffer->view_first_slice = 0; 114 | depthBuffer->view_slices_count = depth; 115 | depthBuffer->clear_depth = 1.0f; 116 | depthBuffer->clear_stencil = 0; 117 | depthBuffer->hiZ_data = NULL; 118 | depthBuffer->hiZ_size = 0; 119 | GX2CalcSurfaceSizeAndAlignment(&depthBuffer->surface); 120 | GX2InitDepthBufferRegs(depthBuffer); 121 | } 122 | 123 | static inline void GX2InitColorBuffer(GX2ColorBuffer *colorBuffer, s32 dimension, u32 width, u32 height, u32 depth, s32 format, s32 aa) 124 | { 125 | colorBuffer->surface.dimension = dimension; 126 | colorBuffer->surface.width = width; 127 | colorBuffer->surface.height = height; 128 | colorBuffer->surface.depth = depth; 129 | colorBuffer->surface.num_mips = 1; 130 | colorBuffer->surface.format = format; 131 | colorBuffer->surface.aa = aa; 132 | colorBuffer->surface.use = GX2_SURFACE_USE_COLOR_BUFFER_TEXTURE_FTV; 133 | colorBuffer->surface.image_size = 0; 134 | colorBuffer->surface.image_data = NULL; 135 | colorBuffer->surface.mip_size = 0; 136 | colorBuffer->surface.mip_data = NULL; 137 | colorBuffer->surface.tile = GX2_TILE_MODE_DEFAULT; 138 | colorBuffer->surface.swizzle = 0; 139 | colorBuffer->surface.align = 0; 140 | colorBuffer->surface.pitch = 0; 141 | u32 i; 142 | for(i = 0; i < 13; i++) 143 | colorBuffer->surface.mip_offset[i] = 0; 144 | colorBuffer->view_mip = 0; 145 | colorBuffer->view_first_slice = 0; 146 | colorBuffer->view_slices_count = depth; 147 | colorBuffer->aux_data = NULL; 148 | colorBuffer->aux_size = 0; 149 | for(i = 0; i < 5; i++) 150 | colorBuffer->regs[i] = 0; 151 | 152 | GX2CalcSurfaceSizeAndAlignment(&colorBuffer->surface); 153 | GX2InitColorBufferRegs(colorBuffer); 154 | } 155 | 156 | static inline void GX2InitAttribStream(GX2AttribStream* attr, u32 location, u32 buffer, u32 offset, s32 format) 157 | { 158 | attr->location = location; 159 | attr->buffer = buffer; 160 | attr->offset = offset; 161 | attr->format = format; 162 | attr->index_type = 0; 163 | attr->divisor = 0; 164 | attr->destination_selector = attribute_dest_comp_selector[format & 0xff]; 165 | attr->endian_swap = GX2_ENDIANSWAP_DEFAULT; 166 | } 167 | 168 | static inline void GX2InitTexture(GX2Texture *tex, u32 width, u32 height, u32 depth, u32 num_mips, s32 format, s32 dimension, s32 tile) 169 | { 170 | tex->surface.dimension = dimension; 171 | tex->surface.width = width; 172 | tex->surface.height = height; 173 | tex->surface.depth = depth; 174 | tex->surface.num_mips = num_mips; 175 | tex->surface.format = format; 176 | tex->surface.aa = GX2_AA_MODE_1X; 177 | tex->surface.use = GX2_SURFACE_USE_TEXTURE; 178 | tex->surface.image_size = 0; 179 | tex->surface.image_data = NULL; 180 | tex->surface.mip_size = 0; 181 | tex->surface.mip_data = NULL; 182 | tex->surface.tile = tile; 183 | tex->surface.swizzle = 0; 184 | tex->surface.align = 0; 185 | tex->surface.pitch = 0; 186 | u32 i; 187 | for(i = 0; i < 13; i++) 188 | tex->surface.mip_offset[i] = 0; 189 | tex->view_first_mip = 0; 190 | tex->view_mips_count = num_mips; 191 | tex->view_first_slice = 0; 192 | tex->view_slices_count = depth; 193 | tex->component_selector = texture_comp_selector[format & 0x3f]; 194 | for(i = 0; i < 5; i++) 195 | tex->regs[i] = 0; 196 | 197 | GX2CalcSurfaceSizeAndAlignment(&tex->surface); 198 | GX2InitTextureRegs(tex); 199 | } 200 | 201 | #ifdef __cplusplus 202 | } 203 | #endif 204 | 205 | #endif // __GX2_FUNCTIONS_H_ 206 | -------------------------------------------------------------------------------- /src/dynamic_libs/os_functions.c: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | * Copyright (C) 2015 3 | * by Dimok 4 | * 5 | * This software is provided 'as-is', without any express or implied 6 | * warranty. In no event will the authors be held liable for any 7 | * damages arising from the use of this software. 8 | * 9 | * Permission is granted to anyone to use this software for any 10 | * purpose, including commercial applications, and to alter it and 11 | * redistribute it freely, subject to the following restrictions: 12 | * 13 | * 1. The origin of this software must not be misrepresented; you 14 | * must not claim that you wrote the original software. If you use 15 | * this software in a product, an acknowledgment in the product 16 | * documentation would be appreciated but is not required. 17 | * 18 | * 2. Altered source versions must be plainly marked as such, and 19 | * must not be misrepresented as being the original software. 20 | * 21 | * 3. This notice may not be removed or altered from any source 22 | * distribution. 23 | ***************************************************************************/ 24 | #include "common/common.h" 25 | #include "os_functions.h" 26 | 27 | unsigned int coreinit_handle __attribute__((section(".data"))) = 0; 28 | 29 | //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 30 | //! Lib handle functions 31 | //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 32 | EXPORT_DECL(int, OSDynLoad_Acquire, const char* rpl, u32 *handle); 33 | EXPORT_DECL(int, OSDynLoad_FindExport, u32 handle, int isdata, const char *symbol, void *address); 34 | 35 | //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 36 | //! Security functions 37 | //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 38 | EXPORT_DECL(int, OSGetSecurityLevel, void); 39 | EXPORT_DECL(int, OSForceFullRelaunch, void); 40 | 41 | //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 42 | //! Thread functions 43 | //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 44 | EXPORT_DECL(int, OSCreateThread, void *thread, s32 (*callback)(s32, void*), s32 argc, void *args, u32 stack, u32 stack_size, s32 priority, u32 attr); 45 | EXPORT_DECL(int, OSResumeThread, void *thread); 46 | EXPORT_DECL(int, OSSuspendThread, void *thread); 47 | EXPORT_DECL(int, OSIsThreadTerminated, void *thread); 48 | EXPORT_DECL(int, OSIsThreadSuspended, void *thread); 49 | EXPORT_DECL(int, OSSetThreadPriority, void * thread, int priority); 50 | EXPORT_DECL(int, OSJoinThread, void * thread, int * ret_val); 51 | EXPORT_DECL(void, OSDetachThread, void * thread); 52 | EXPORT_DECL(void, OSSleepTicks, u64 ticks); 53 | EXPORT_DECL(u64, OSGetTick, void); 54 | EXPORT_DECL(u64, OSGetTime, void); 55 | //EXPORT_DECL(void, OSTicksToCalendarTime, u64 time, OSCalendarTime * calendarTime); 56 | 57 | 58 | //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 59 | //! Mutex functions 60 | //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 61 | EXPORT_DECL(void, OSInitMutex, void* mutex); 62 | EXPORT_DECL(void, OSLockMutex, void* mutex); 63 | EXPORT_DECL(void, OSUnlockMutex, void* mutex); 64 | EXPORT_DECL(int, OSTryLockMutex, void* mutex); 65 | 66 | //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 67 | //! System functions 68 | //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 69 | EXPORT_DECL(u64, OSGetTitleID, void); 70 | EXPORT_DECL(void, OSGetArgcArgv, int* argc, char*** argv); 71 | EXPORT_DECL(void, __Exit, void); 72 | EXPORT_DECL(void, OSFatal, const char* msg); 73 | EXPORT_DECL(void, OSSetExceptionCallback, u8 exceptionType, exception_callback newCallback); 74 | EXPORT_DECL(void, DCFlushRange, const void *addr, u32 length); 75 | EXPORT_DECL(void, DCStoreRange, const void *addr, u32 length); 76 | EXPORT_DECL(void, ICInvalidateRange, const void *addr, u32 length); 77 | EXPORT_DECL(void*, OSEffectiveToPhysical, const void*); 78 | EXPORT_DECL(int, __os_snprintf, char* s, int n, const char * format, ...); 79 | EXPORT_DECL(int *, __gh_errno_ptr, void); 80 | 81 | EXPORT_DECL(void, OSScreenInit, void); 82 | EXPORT_DECL(unsigned int, OSScreenGetBufferSizeEx, unsigned int bufferNum); 83 | EXPORT_DECL(int, OSScreenSetBufferEx, unsigned int bufferNum, void * addr); 84 | EXPORT_DECL(int, OSScreenClearBufferEx, unsigned int bufferNum, unsigned int temp); 85 | EXPORT_DECL(int, OSScreenFlipBuffersEx, unsigned int bufferNum); 86 | EXPORT_DECL(int, OSScreenPutFontEx, unsigned int bufferNum, unsigned int posX, unsigned int posY, const char * buffer); 87 | EXPORT_DECL(int, OSScreenEnableEx, unsigned int bufferNum, int enable); 88 | 89 | //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 90 | //! Memory functions 91 | //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 92 | EXPORT_VAR(unsigned int *, pMEMAllocFromDefaultHeapEx); 93 | EXPORT_VAR(unsigned int *, pMEMAllocFromDefaultHeap); 94 | EXPORT_VAR(unsigned int *, pMEMFreeToDefaultHeap); 95 | 96 | EXPORT_DECL(int, MEMGetBaseHeapHandle, int mem_arena); 97 | EXPORT_DECL(unsigned int, MEMGetAllocatableSizeForFrmHeapEx, int heap, int align); 98 | EXPORT_DECL(void *, MEMAllocFromFrmHeapEx, int heap, unsigned int size, int align); 99 | EXPORT_DECL(void, MEMFreeToFrmHeap, int heap, int mode); 100 | EXPORT_DECL(void *, MEMAllocFromExpHeapEx, int heap, unsigned int size, int align); 101 | EXPORT_DECL(int , MEMCreateExpHeapEx, void* address, unsigned int size, unsigned short flags); 102 | EXPORT_DECL(void *, MEMDestroyExpHeap, int heap); 103 | EXPORT_DECL(void, MEMFreeToExpHeap, int heap, void* ptr); 104 | 105 | //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 106 | //! MCP functions 107 | //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 108 | EXPORT_DECL(int, MCP_Open, void); 109 | EXPORT_DECL(int, MCP_Close, int handle); 110 | EXPORT_DECL(int, MCP_GetOwnTitleInfo, int handle, void * data); 111 | 112 | //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 113 | //! Loader functions (not real rpl) 114 | //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 115 | EXPORT_DECL(int, LiWaitIopComplete, int unknown_syscall_arg_r3, int * remaining_bytes); 116 | EXPORT_DECL(int, LiWaitIopCompleteWithInterrupts, int unknown_syscall_arg_r3, int * remaining_bytes); 117 | EXPORT_DECL(void, addr_LiWaitOneChunk, void); 118 | EXPORT_DECL(void, addr_sgIsLoadingBuffer, void); 119 | EXPORT_DECL(void, addr_gDynloadInitialized, void); 120 | 121 | //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 122 | //! Kernel function addresses 123 | //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 124 | EXPORT_DECL(void, addr_PrepareTitle_hook, void); 125 | 126 | //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 127 | //! Other function addresses 128 | //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 129 | EXPORT_DECL(void, DCInvalidateRange, void *buffer, uint32_t length); 130 | 131 | //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 132 | //! Energy Saver functions 133 | //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 134 | //Burn-in Reduction 135 | EXPORT_DECL(int, IMEnableDim,void); 136 | EXPORT_DECL(int, IMDisableDim,void); 137 | EXPORT_DECL(int, IMIsDimEnabled,int * result); 138 | //Auto power down 139 | EXPORT_DECL(int, IMEnableAPD,void); 140 | EXPORT_DECL(int, IMDisableAPD,void); 141 | EXPORT_DECL(int, IMIsAPDEnabled,int * result); 142 | EXPORT_DECL(int, IMIsAPDEnabledBySysSettings,int * result); 143 | 144 | 145 | EXPORT_DECL(int, IOS_Ioctl,int fd, unsigned int request, void *input_buffer,unsigned int input_buffer_len, void *output_buffer, unsigned int output_buffer_len); 146 | EXPORT_DECL(int, IOS_IoctlAsync,int fd, unsigned int request, void *input_buffer,unsigned int input_buffer_len, void *output_buffer, unsigned int output_buffer_len, void *cb, void *cbarg); 147 | EXPORT_DECL(int, IOS_Open,char *path, unsigned int mode); 148 | EXPORT_DECL(int, IOS_Close,int fd); 149 | void InitAcquireOS(void) 150 | { 151 | //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 152 | //! Lib handle functions 153 | //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 154 | EXPORT_FUNC_WRITE(OSDynLoad_Acquire, (int (*)(const char*, unsigned *))OS_SPECIFICS->addr_OSDynLoad_Acquire); 155 | EXPORT_FUNC_WRITE(OSDynLoad_FindExport, (int (*)(u32, int, const char *, void *))OS_SPECIFICS->addr_OSDynLoad_FindExport); 156 | 157 | OSDynLoad_Acquire("coreinit.rpl", &coreinit_handle); 158 | } 159 | 160 | void InitOSFunctionPointers(void) 161 | { 162 | unsigned int *funcPointer = 0; 163 | 164 | InitAcquireOS(); 165 | 166 | //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 167 | //! Security functions 168 | //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 169 | OS_FIND_EXPORT(coreinit_handle, OSGetSecurityLevel); 170 | OS_FIND_EXPORT(coreinit_handle, OSForceFullRelaunch); 171 | //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 172 | //! System functions 173 | //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 174 | OS_FIND_EXPORT(coreinit_handle, OSFatal); 175 | OS_FIND_EXPORT(coreinit_handle, OSGetTitleID); 176 | OS_FIND_EXPORT(coreinit_handle, OSGetArgcArgv); 177 | OS_FIND_EXPORT(coreinit_handle, OSSetExceptionCallback); 178 | OS_FIND_EXPORT(coreinit_handle, DCFlushRange); 179 | OS_FIND_EXPORT(coreinit_handle, DCStoreRange); 180 | OS_FIND_EXPORT(coreinit_handle, ICInvalidateRange); 181 | OS_FIND_EXPORT(coreinit_handle, OSEffectiveToPhysical); 182 | OS_FIND_EXPORT(coreinit_handle, __os_snprintf); 183 | OS_FIND_EXPORT(coreinit_handle, __gh_errno_ptr); 184 | 185 | OSDynLoad_FindExport(coreinit_handle, 0, "_Exit", &__Exit); 186 | 187 | OS_FIND_EXPORT(coreinit_handle, OSScreenInit); 188 | OS_FIND_EXPORT(coreinit_handle, OSScreenGetBufferSizeEx); 189 | OS_FIND_EXPORT(coreinit_handle, OSScreenSetBufferEx); 190 | OS_FIND_EXPORT(coreinit_handle, OSScreenClearBufferEx); 191 | OS_FIND_EXPORT(coreinit_handle, OSScreenFlipBuffersEx); 192 | OS_FIND_EXPORT(coreinit_handle, OSScreenPutFontEx); 193 | OS_FIND_EXPORT(coreinit_handle, OSScreenEnableEx); 194 | //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 195 | //! Thread functions 196 | //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 197 | OS_FIND_EXPORT(coreinit_handle, OSCreateThread); 198 | OS_FIND_EXPORT(coreinit_handle, OSResumeThread); 199 | OS_FIND_EXPORT(coreinit_handle, OSSuspendThread); 200 | OS_FIND_EXPORT(coreinit_handle, OSIsThreadTerminated); 201 | OS_FIND_EXPORT(coreinit_handle, OSIsThreadSuspended); 202 | OS_FIND_EXPORT(coreinit_handle, OSJoinThread); 203 | OS_FIND_EXPORT(coreinit_handle, OSSetThreadPriority); 204 | OS_FIND_EXPORT(coreinit_handle, OSDetachThread); 205 | OS_FIND_EXPORT(coreinit_handle, OSSleepTicks); 206 | OS_FIND_EXPORT(coreinit_handle, OSGetTick); 207 | OS_FIND_EXPORT(coreinit_handle, OSGetTime); 208 | //OS_FIND_EXPORT(coreinit_handle, OSTicksToCalendarTime); 209 | 210 | //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 211 | //! Mutex functions 212 | //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 213 | OS_FIND_EXPORT(coreinit_handle, OSInitMutex); 214 | OS_FIND_EXPORT(coreinit_handle, OSLockMutex); 215 | OS_FIND_EXPORT(coreinit_handle, OSUnlockMutex); 216 | OS_FIND_EXPORT(coreinit_handle, OSTryLockMutex); 217 | //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 218 | //! MCP functions 219 | //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 220 | OS_FIND_EXPORT(coreinit_handle, MCP_Open); 221 | OS_FIND_EXPORT(coreinit_handle, MCP_Close); 222 | OS_FIND_EXPORT(coreinit_handle, MCP_GetOwnTitleInfo); 223 | 224 | //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 225 | //! Memory functions 226 | //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 227 | OSDynLoad_FindExport(coreinit_handle, 1, "MEMAllocFromDefaultHeapEx", &pMEMAllocFromDefaultHeapEx); 228 | OSDynLoad_FindExport(coreinit_handle, 1, "MEMAllocFromDefaultHeap", &pMEMAllocFromDefaultHeap); 229 | OSDynLoad_FindExport(coreinit_handle, 1, "MEMFreeToDefaultHeap", &pMEMFreeToDefaultHeap); 230 | 231 | OS_FIND_EXPORT(coreinit_handle, MEMGetBaseHeapHandle); 232 | OS_FIND_EXPORT(coreinit_handle, MEMGetAllocatableSizeForFrmHeapEx); 233 | OS_FIND_EXPORT(coreinit_handle, MEMAllocFromFrmHeapEx); 234 | OS_FIND_EXPORT(coreinit_handle, MEMFreeToFrmHeap); 235 | OS_FIND_EXPORT(coreinit_handle, MEMAllocFromExpHeapEx); 236 | OS_FIND_EXPORT(coreinit_handle, MEMCreateExpHeapEx); 237 | OS_FIND_EXPORT(coreinit_handle, MEMDestroyExpHeap); 238 | OS_FIND_EXPORT(coreinit_handle, MEMFreeToExpHeap); 239 | 240 | //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 241 | //! Other function addresses 242 | //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 243 | OS_FIND_EXPORT(coreinit_handle, DCInvalidateRange); 244 | 245 | //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 246 | //! Energy Saver functions 247 | //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 248 | //Burn-in Reduction 249 | OS_FIND_EXPORT(coreinit_handle, IMEnableDim); 250 | OS_FIND_EXPORT(coreinit_handle, IMDisableDim); 251 | OS_FIND_EXPORT(coreinit_handle, IMIsDimEnabled); 252 | //Auto power down 253 | OS_FIND_EXPORT(coreinit_handle, IMEnableAPD); 254 | OS_FIND_EXPORT(coreinit_handle, IMDisableAPD); 255 | OS_FIND_EXPORT(coreinit_handle, IMIsAPDEnabled); 256 | OS_FIND_EXPORT(coreinit_handle, IMIsAPDEnabledBySysSettings); 257 | 258 | OS_FIND_EXPORT(coreinit_handle, IOS_Ioctl); 259 | OS_FIND_EXPORT(coreinit_handle, IOS_IoctlAsync); 260 | OS_FIND_EXPORT(coreinit_handle, IOS_Open); 261 | OS_FIND_EXPORT(coreinit_handle, IOS_Close); 262 | 263 | //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 264 | //! Special non library functions 265 | //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 266 | if(OS_FIRMWARE == 532 || OS_FIRMWARE == 540) 267 | { 268 | EXPORT_FUNC_WRITE(LiWaitIopComplete, (int (*)(int, int *))0x0100FFA4); // loader.elf 269 | EXPORT_FUNC_WRITE(LiWaitIopCompleteWithInterrupts, (int (*)(int, int *))0x0100FE90); // loader.elf 270 | EXPORT_FUNC_WRITE(addr_LiWaitOneChunk, (int (*)(int, int *))0x010007EC); // loader.elf 271 | EXPORT_FUNC_WRITE(addr_PrepareTitle_hook, (int (*)(int, int *))0xFFF18558); // kernel.elf 272 | 273 | EXPORT_FUNC_WRITE(addr_sgIsLoadingBuffer, (int (*)(int, int *))0xEFE19D00); // loader.elf 274 | EXPORT_FUNC_WRITE(addr_gDynloadInitialized, (int (*)(int, int *))0xEFE13C3C); // loader.elf 275 | } 276 | else if(OS_FIRMWARE == 500 || OS_FIRMWARE == 510) 277 | { 278 | EXPORT_FUNC_WRITE(LiWaitIopComplete, (int (*)(int, int *))0x0100FBC4); 279 | EXPORT_FUNC_WRITE(LiWaitIopCompleteWithInterrupts, (int (*)(int, int *))0x0100FAB0); 280 | EXPORT_FUNC_WRITE(addr_LiWaitOneChunk, (int (*)(int, int *))0x010007EC); 281 | EXPORT_FUNC_WRITE(addr_PrepareTitle_hook, (int (*)(int, int *))0xFFF18534); 282 | 283 | EXPORT_FUNC_WRITE(addr_sgIsLoadingBuffer, (int (*)(int, int *))0xEFE19D00); 284 | EXPORT_FUNC_WRITE(addr_gDynloadInitialized, (int (*)(int, int *))0xEFE13C3C); 285 | } 286 | else if(OS_FIRMWARE == 410) 287 | { 288 | EXPORT_FUNC_WRITE(LiWaitIopComplete, (int (*)(int, int *))0x0100F78C); 289 | EXPORT_FUNC_WRITE(LiWaitIopCompleteWithInterrupts, (int (*)(int, int *))0x0100F678); 290 | EXPORT_FUNC_WRITE(addr_LiWaitOneChunk, (int (*)(int, int *))0x010007F8); 291 | EXPORT_FUNC_WRITE(addr_PrepareTitle_hook, (int (*)(int, int *))0xFFF166DC); 292 | 293 | EXPORT_FUNC_WRITE(addr_sgIsLoadingBuffer, (int (*)(int, int *))0xEFE19CC0); 294 | EXPORT_FUNC_WRITE(addr_gDynloadInitialized, (int (*)(int, int *))0xEFE13BFC); 295 | } 296 | else if(OS_FIRMWARE == 400) //same for 402 and 403 297 | { 298 | EXPORT_FUNC_WRITE(LiWaitIopComplete, (int (*)(int, int *))0x0100F78C); 299 | EXPORT_FUNC_WRITE(LiWaitIopCompleteWithInterrupts, (int (*)(int, int *))0x0100F678); 300 | EXPORT_FUNC_WRITE(addr_LiWaitOneChunk, (int (*)(int, int *))0x010007F8); 301 | EXPORT_FUNC_WRITE(addr_PrepareTitle_hook, (int (*)(int, int *))0xFFF15E70); 302 | 303 | EXPORT_FUNC_WRITE(addr_sgIsLoadingBuffer, (int (*)(int, int *))0xEFE19CC0); 304 | EXPORT_FUNC_WRITE(addr_gDynloadInitialized, (int (*)(int, int *))0xEFE13BFC); 305 | } 306 | else if(OS_FIRMWARE == 550) 307 | { 308 | EXPORT_FUNC_WRITE(LiWaitIopComplete, (int (*)(int, int *))0x01010180); 309 | EXPORT_FUNC_WRITE(LiWaitIopCompleteWithInterrupts, (int (*)(int, int *))0x0101006C); 310 | EXPORT_FUNC_WRITE(addr_LiWaitOneChunk, (int (*)(int, int *))0x0100080C); 311 | EXPORT_FUNC_WRITE(addr_PrepareTitle_hook, (int (*)(int, int *))0xFFF184E4); 312 | 313 | EXPORT_FUNC_WRITE(addr_sgIsLoadingBuffer, (int (*)(int, int *))0xEFE19E80); 314 | EXPORT_FUNC_WRITE(addr_gDynloadInitialized, (int (*)(int, int *))0xEFE13DBC); 315 | } 316 | else if(OS_FIRMWARE == 310) 317 | { 318 | EXPORT_FUNC_WRITE(LiWaitIopComplete, (int (*)(int, int *))0x0100C4E4); 319 | EXPORT_FUNC_WRITE(LiWaitIopCompleteWithInterrupts, (int (*)(int, int *))0x0100C3D4); 320 | EXPORT_FUNC_WRITE(addr_LiWaitOneChunk, (int (*)(int, int *))0x010004D8); 321 | EXPORT_FUNC_WRITE(addr_PrepareTitle_hook, (int (*)(int, int *))0xFFF15A0C); 322 | 323 | EXPORT_FUNC_WRITE(addr_sgIsLoadingBuffer, (int (*)(int, int *))0xEFE19340); 324 | EXPORT_FUNC_WRITE(addr_gDynloadInitialized, (int (*)(int, int *))0xEFE1329C); 325 | } 326 | else if(OS_FIRMWARE == 300) 327 | { 328 | EXPORT_FUNC_WRITE(LiWaitIopComplete, (int (*)(int, int *))0x0100C4E4); 329 | EXPORT_FUNC_WRITE(LiWaitIopCompleteWithInterrupts, (int (*)(int, int *))0x0100C3D4); 330 | EXPORT_FUNC_WRITE(addr_LiWaitOneChunk, (int (*)(int, int *))0x010004D8); 331 | EXPORT_FUNC_WRITE(addr_PrepareTitle_hook, (int (*)(int, int *))0xFFF15974); 332 | 333 | EXPORT_FUNC_WRITE(addr_sgIsLoadingBuffer, (int (*)(int, int *))0xEFE19340); 334 | EXPORT_FUNC_WRITE(addr_gDynloadInitialized, (int (*)(int, int *))0xEFE1329C); 335 | } 336 | else 337 | { 338 | OSFatal("Missing all OS specific addresses."); 339 | } 340 | } -------------------------------------------------------------------------------- /src/dynamic_libs/os_functions.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | * Copyright (C) 2015 3 | * by Dimok 4 | * 5 | * This software is provided 'as-is', without any express or implied 6 | * warranty. In no event will the authors be held liable for any 7 | * damages arising from the use of this software. 8 | * 9 | * Permission is granted to anyone to use this software for any 10 | * purpose, including commercial applications, and to alter it and 11 | * redistribute it freely, subject to the following restrictions: 12 | * 13 | * 1. The origin of this software must not be misrepresented; you 14 | * must not claim that you wrote the original software. If you use 15 | * this software in a product, an acknowledgment in the product 16 | * documentation would be appreciated but is not required. 17 | * 18 | * 2. Altered source versions must be plainly marked as such, and 19 | * must not be misrepresented as being the original software. 20 | * 21 | * 3. This notice may not be removed or altered from any source 22 | * distribution. 23 | ***************************************************************************/ 24 | #ifndef __OS_FUNCTIONS_H_ 25 | #define __OS_FUNCTIONS_H_ 26 | 27 | #include 28 | #include "common/os_defs.h" 29 | 30 | #ifdef __cplusplus 31 | extern "C" { 32 | #endif 33 | 34 | #define BUS_SPEED 248625000 35 | #define SECS_TO_TICKS(sec) (((unsigned long long)(sec)) * (BUS_SPEED/4)) 36 | #define MILLISECS_TO_TICKS(msec) (SECS_TO_TICKS(msec) / 1000) 37 | #define MICROSECS_TO_TICKS(usec) (SECS_TO_TICKS(usec) / 1000000) 38 | 39 | #define usleep(usecs) OSSleepTicks(MICROSECS_TO_TICKS(usecs)) 40 | #define sleep(secs) OSSleepTicks(SECS_TO_TICKS(secs)) 41 | 42 | #define FLUSH_DATA_BLOCK(addr) asm volatile("dcbf 0, %0; sync" : : "r"(((addr) & ~31))) 43 | #define INVAL_DATA_BLOCK(addr) asm volatile("dcbi 0, %0; sync" : : "r"(((addr) & ~31))) 44 | 45 | #define EXPORT_DECL(res, func, ...) res (* func)(__VA_ARGS__) __attribute__((section(".data"))) = 0; 46 | #define EXPORT_VAR(type, var) type var __attribute__((section(".data"))); 47 | 48 | 49 | #define EXPORT_FUNC_WRITE(func, val) *(u32*)(((u32)&func) + 0) = (u32)val 50 | 51 | #define OS_FIND_EXPORT(handle, func) funcPointer = 0; \ 52 | OSDynLoad_FindExport(handle, 0, # func, &funcPointer); \ 53 | if(!funcPointer) \ 54 | OSFatal("Function " # func " is NULL"); \ 55 | EXPORT_FUNC_WRITE(func, funcPointer); 56 | 57 | #define OS_FIND_EXPORT_EX(handle, func, func_p) \ 58 | funcPointer = 0; \ 59 | OSDynLoad_FindExport(handle, 0, # func, &funcPointer); \ 60 | if(!funcPointer) \ 61 | OSFatal("Function " # func " is NULL"); \ 62 | EXPORT_FUNC_WRITE(func_p, funcPointer); 63 | 64 | #define OS_MUTEX_SIZE 44 65 | 66 | /* Handle for coreinit */ 67 | extern unsigned int coreinit_handle; 68 | void InitOSFunctionPointers(void); 69 | void InitAcquireOS(void); 70 | 71 | //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 72 | //! Lib handle functions 73 | //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 74 | extern int (* OSDynLoad_Acquire)(const char* rpl, u32 *handle); 75 | extern int (* OSDynLoad_FindExport)(u32 handle, int isdata, const char *symbol, void *address); 76 | 77 | //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 78 | //! Security functions 79 | //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 80 | extern int (* OSGetSecurityLevel)(void); 81 | extern int (* OSForceFullRelaunch)(void); 82 | 83 | //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 84 | //! Thread functions 85 | //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 86 | extern int (* OSCreateThread)(void *thread, s32 (*callback)(s32, void*), s32 argc, void *args, u32 stack, u32 stack_size, s32 priority, u32 attr); 87 | extern int (* OSResumeThread)(void *thread); 88 | extern int (* OSSuspendThread)(void *thread); 89 | extern int (* OSIsThreadTerminated)(void *thread); 90 | extern int (* OSIsThreadSuspended)(void *thread); 91 | extern int (* OSJoinThread)(void * thread, int * ret_val); 92 | extern int (* OSSetThreadPriority)(void * thread, int priority); 93 | extern void (* OSDetachThread)(void * thread); 94 | extern void (* OSSleepTicks)(u64 ticks); 95 | extern u64 (* OSGetTick)(void); 96 | extern u64 (* OSGetTime)(void); 97 | //extern void (*OSTicksToCalendarTime)(u64 time, OSCalendarTime *calendarTime); 98 | 99 | //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 100 | //! Mutex functions 101 | //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 102 | extern void (* OSInitMutex)(void* mutex); 103 | extern void (* OSLockMutex)(void* mutex); 104 | extern void (* OSUnlockMutex)(void* mutex); 105 | extern int (* OSTryLockMutex)(void* mutex); 106 | 107 | //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 108 | //! System functions 109 | //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 110 | extern u64 (* OSGetTitleID)(void); 111 | extern void (* OSGetArgcArgv)(int* argc, char*** argv); 112 | extern void (* __Exit)(void); 113 | extern void (* OSFatal)(const char* msg); 114 | extern void (* DCFlushRange)(const void *addr, u32 length); 115 | extern void (* DCStoreRange)(const void *addr, u32 length); 116 | extern void (* ICInvalidateRange)(const void *addr, u32 length); 117 | extern void* (* OSEffectiveToPhysical)(const void*); 118 | extern int (* __os_snprintf)(char* s, int n, const char * format, ...); 119 | extern int * (* __gh_errno_ptr)(void); 120 | 121 | extern void (*OSScreenInit)(void); 122 | extern unsigned int (*OSScreenGetBufferSizeEx)(unsigned int bufferNum); 123 | extern int (*OSScreenSetBufferEx)(unsigned int bufferNum, void * addr); 124 | extern int (*OSScreenClearBufferEx)(unsigned int bufferNum, unsigned int temp); 125 | extern int (*OSScreenFlipBuffersEx)(unsigned int bufferNum); 126 | extern int (*OSScreenPutFontEx)(unsigned int bufferNum, unsigned int posX, unsigned int posY, const char * buffer); 127 | extern int (*OSScreenEnableEx)(unsigned int bufferNum, int enable); 128 | 129 | typedef unsigned char (*exception_callback)(void * interruptedContext); 130 | extern void (* OSSetExceptionCallback)(u8 exceptionType, exception_callback newCallback); 131 | 132 | //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 133 | //! MCP functions 134 | //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 135 | extern int (* MCP_Open)(void); 136 | extern int (* MCP_Close)(int handle); 137 | extern int (* MCP_GetOwnTitleInfo)(int handle, void * data); 138 | 139 | //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 140 | //! LOADER functions 141 | //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 142 | extern int (* LiWaitIopComplete)(int unknown_syscall_arg_r3, int * remaining_bytes); 143 | extern int (* LiWaitIopCompleteWithInterrupts)(int unknown_syscall_arg_r3, int * remaining_bytes); 144 | extern void (* addr_LiWaitOneChunk)(void); 145 | extern void (* addr_sgIsLoadingBuffer)(void); 146 | extern void (* addr_gDynloadInitialized)(void); 147 | 148 | //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 149 | //! Kernel function addresses 150 | //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 151 | extern void (* addr_PrepareTitle_hook)(void); 152 | 153 | //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 154 | //! Other function addresses 155 | //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 156 | extern void (*DCInvalidateRange)(void *buffer, uint32_t length); 157 | 158 | //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 159 | //! Energy Saver functions 160 | //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 161 | ////Burn-in Reduction 162 | extern int (*IMEnableDim)(void); 163 | extern int (*IMDisableDim)(void); 164 | extern int (*IMIsDimEnabled)(int * result); 165 | //Auto power down 166 | extern int (*IMEnableAPD)(void); 167 | extern int (*IMDisableAPD)(void); 168 | extern int (*IMIsAPDEnabled)(int * result); 169 | extern int (*IMIsAPDEnabledBySysSettings)(int * result); 170 | 171 | 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); 172 | extern int (*IOS_IoctlAsync)(int fd, unsigned int request, void *input_buffer,unsigned int input_buffer_len, void *output_buffer, unsigned int output_buffer_len, void *cb, void *cbarg); 173 | extern int (*IOS_Open)(char *path, unsigned int mode); 174 | extern int (*IOS_Close)(int fd); 175 | #ifdef __cplusplus 176 | } 177 | #endif 178 | 179 | #endif // __OS_FUNCTIONS_H_ -------------------------------------------------------------------------------- /src/dynamic_libs/padscore_functions.c: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | * Copyright (C) 2015 3 | * by Dimok 4 | * 5 | * This software is provided 'as-is', without any express or implied 6 | * warranty. In no event will the authors be held liable for any 7 | * damages arising from the use of this software. 8 | * 9 | * Permission is granted to anyone to use this software for any 10 | * purpose, including commercial applications, and to alter it and 11 | * redistribute it freely, subject to the following restrictions: 12 | * 13 | * 1. The origin of this software must not be misrepresented; you 14 | * must not claim that you wrote the original software. If you use 15 | * this software in a product, an acknowledgment in the product 16 | * documentation would be appreciated but is not required. 17 | * 18 | * 2. Altered source versions must be plainly marked as such, and 19 | * must not be misrepresented as being the original software. 20 | * 21 | * 3. This notice may not be removed or altered from any source 22 | * distribution. 23 | ***************************************************************************/ 24 | #include "os_functions.h" 25 | #include "padscore_functions.h" 26 | 27 | EXPORT_DECL(void, KPADInit, void); 28 | EXPORT_DECL(s32, WPADProbe, s32 chan, u32 * pad_type); 29 | EXPORT_DECL(s32, WPADSetDataFormat, s32 chan, s32 format); 30 | EXPORT_DECL(void, WPADEnableURCC, s32 enable); 31 | EXPORT_DECL(void, WPADRead, s32 chan, void * data); 32 | EXPORT_DECL(s32, KPADRead, s32 chan, void * data, u32 size); 33 | 34 | void InitPadScoreFunctionPointers(void) 35 | { 36 | unsigned int *funcPointer = 0; 37 | unsigned int padscore_handle; 38 | OSDynLoad_Acquire("padscore.rpl", &padscore_handle); 39 | 40 | OS_FIND_EXPORT(padscore_handle, KPADInit); 41 | OS_FIND_EXPORT(padscore_handle, WPADProbe); 42 | OS_FIND_EXPORT(padscore_handle, WPADSetDataFormat); 43 | OS_FIND_EXPORT(padscore_handle, WPADEnableURCC); 44 | OS_FIND_EXPORT(padscore_handle, WPADRead); 45 | OS_FIND_EXPORT(padscore_handle, KPADRead); 46 | 47 | KPADInit(); 48 | WPADEnableURCC(1); 49 | } 50 | 51 | -------------------------------------------------------------------------------- /src/dynamic_libs/padscore_functions.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | * Copyright (C) 2015 3 | * by Dimok 4 | * 5 | * This software is provided 'as-is', without any express or implied 6 | * warranty. In no event will the authors be held liable for any 7 | * damages arising from the use of this software. 8 | * 9 | * Permission is granted to anyone to use this software for any 10 | * purpose, including commercial applications, and to alter it and 11 | * redistribute it freely, subject to the following restrictions: 12 | * 13 | * 1. The origin of this software must not be misrepresented; you 14 | * must not claim that you wrote the original software. If you use 15 | * this software in a product, an acknowledgment in the product 16 | * documentation would be appreciated but is not required. 17 | * 18 | * 2. Altered source versions must be plainly marked as such, and 19 | * must not be misrepresented as being the original software. 20 | * 21 | * 3. This notice may not be removed or altered from any source 22 | * distribution. 23 | ***************************************************************************/ 24 | #ifndef __PAD_SCORE_FUNCTIONS_H_ 25 | #define __PAD_SCORE_FUNCTIONS_H_ 26 | 27 | #ifdef __cplusplus 28 | extern "C" { 29 | #endif 30 | 31 | #include 32 | 33 | #define WPAD_BUTTON_LEFT 0x0001 34 | #define WPAD_BUTTON_RIGHT 0x0002 35 | #define WPAD_BUTTON_DOWN 0x0004 36 | #define WPAD_BUTTON_UP 0x0008 37 | #define WPAD_BUTTON_PLUS 0x0010 38 | #define WPAD_BUTTON_2 0x0100 39 | #define WPAD_BUTTON_1 0x0200 40 | #define WPAD_BUTTON_B 0x0400 41 | #define WPAD_BUTTON_A 0x0800 42 | #define WPAD_BUTTON_MINUS 0x1000 43 | #define WPAD_BUTTON_Z 0x2000 44 | #define WPAD_BUTTON_C 0x4000 45 | #define WPAD_BUTTON_HOME 0x8000 46 | 47 | #define WPAD_CLASSIC_BUTTON_UP 0x0001 48 | #define WPAD_CLASSIC_BUTTON_LEFT 0x0002 49 | #define WPAD_CLASSIC_BUTTON_ZR 0x0004 50 | #define WPAD_CLASSIC_BUTTON_X 0x0008 51 | #define WPAD_CLASSIC_BUTTON_A 0x0010 52 | #define WPAD_CLASSIC_BUTTON_Y 0x0020 53 | #define WPAD_CLASSIC_BUTTON_B 0x0040 54 | #define WPAD_CLASSIC_BUTTON_ZL 0x0080 55 | #define WPAD_CLASSIC_BUTTON_R 0x0200 56 | #define WPAD_CLASSIC_BUTTON_PLUS 0x0400 57 | #define WPAD_CLASSIC_BUTTON_HOME 0x0800 58 | #define WPAD_CLASSIC_BUTTON_MINUS 0x1000 59 | #define WPAD_CLASSIC_BUTTON_L 0x2000 60 | #define WPAD_CLASSIC_BUTTON_DOWN 0x4000 61 | #define WPAD_CLASSIC_BUTTON_RIGHT 0x8000 62 | 63 | void InitPadScoreFunctionPointers(void); 64 | 65 | 66 | typedef struct _KPADData 67 | { 68 | u32 btns_h; 69 | u32 btns_d; 70 | u32 btns_r; 71 | u32 unused_1[5]; 72 | f32 pos_x; 73 | f32 pos_y; 74 | u32 unused_2[3]; 75 | f32 angle_x; 76 | f32 angle_y; 77 | u32 unused_3[8]; 78 | u8 device_type; 79 | u8 wpad_error; 80 | u8 pos_valid; 81 | u8 unused_4[1]; 82 | 83 | union 84 | { 85 | struct 86 | { 87 | f32 stick_x; 88 | f32 stick_y; 89 | } nunchuck; 90 | 91 | struct 92 | { 93 | u32 btns_h; 94 | u32 btns_d; 95 | u32 btns_r; 96 | f32 lstick_x; 97 | f32 lstick_y; 98 | f32 rstick_x; 99 | f32 rstick_y; 100 | f32 ltrigger; 101 | f32 rtrigger; 102 | } classic; 103 | 104 | u32 unused_6[20]; 105 | }; 106 | u32 unused_7[16]; 107 | } KPADData; 108 | 109 | typedef void (* wpad_connect_callback_t)(s32 chan, s32 status); 110 | 111 | extern void (* KPADInit)(void); 112 | extern s32 (* WPADProbe)(s32 chan, u32 * pad_type); 113 | extern s32 (* WPADSetDataFormat)(s32 chan, s32 format); 114 | extern void (* WPADEnableURCC)(s32 enable); 115 | extern void (* WPADRead)(s32 chan, void * data); 116 | extern s32 (* KPADRead)(s32 chan, void * data, u32 size); 117 | 118 | #ifdef __cplusplus 119 | } 120 | #endif 121 | 122 | #endif // __PAD_SCORE_FUNCTIONS_H_ 123 | -------------------------------------------------------------------------------- /src/dynamic_libs/socket_functions.c: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | * Copyright (C) 2015 3 | * by Dimok 4 | * 5 | * This software is provided 'as-is', without any express or implied 6 | * warranty. In no event will the authors be held liable for any 7 | * damages arising from the use of this software. 8 | * 9 | * Permission is granted to anyone to use this software for any 10 | * purpose, including commercial applications, and to alter it and 11 | * redistribute it freely, subject to the following restrictions: 12 | * 13 | * 1. The origin of this software must not be misrepresented; you 14 | * must not claim that you wrote the original software. If you use 15 | * this software in a product, an acknowledgment in the product 16 | * documentation would be appreciated but is not required. 17 | * 18 | * 2. Altered source versions must be plainly marked as such, and 19 | * must not be misrepresented as being the original software. 20 | * 21 | * 3. This notice may not be removed or altered from any source 22 | * distribution. 23 | ***************************************************************************/ 24 | #include "os_functions.h" 25 | #include "socket_functions.h" 26 | 27 | u32 hostIpAddress = 0; 28 | 29 | EXPORT_DECL(void, socket_lib_init, void); 30 | EXPORT_DECL(int, socket, int domain, int type, int protocol); 31 | EXPORT_DECL(int, socketclose, int s); 32 | EXPORT_DECL(int, connect, int s, void *addr, int addrlen); 33 | EXPORT_DECL(int, bind, s32 s,struct sockaddr *name,s32 namelen); 34 | EXPORT_DECL(int, listen, s32 s,u32 backlog); 35 | EXPORT_DECL(int, accept, s32 s,struct sockaddr *addr,s32 *addrlen); 36 | EXPORT_DECL(int, send, int s, const void *buffer, int size, int flags); 37 | EXPORT_DECL(int, recv, int s, void *buffer, int size, int flags); 38 | EXPORT_DECL(int, sendto, int s, const void *buffer, int size, int flags, const struct sockaddr *dest, int dest_len); 39 | EXPORT_DECL(int, setsockopt, int s, int level, int optname, void *optval, int optlen); 40 | EXPORT_DECL(char *, inet_ntoa, struct in_addr in); 41 | EXPORT_DECL(int, inet_aton, const char *cp, struct in_addr *inp); 42 | EXPORT_DECL(int, socketlasterr, void); 43 | 44 | void InitSocketFunctionPointers(void) 45 | { 46 | unsigned int nsysnet_handle; 47 | unsigned int *funcPointer = 0; 48 | OSDynLoad_Acquire("nsysnet.rpl", &nsysnet_handle); 49 | 50 | unsigned int nn_ac_handle; 51 | int(*ACInitialize)(); 52 | int(*ACGetStartupId) (unsigned int *id); 53 | int(*ACConnectWithConfigId) (unsigned int id); 54 | int(*ACGetAssignedAddress) (u32 * ip); 55 | OSDynLoad_Acquire("nn_ac.rpl", &nn_ac_handle); 56 | OSDynLoad_FindExport(nn_ac_handle, 0, "ACInitialize", &ACInitialize); 57 | OSDynLoad_FindExport(nn_ac_handle, 0, "ACGetStartupId", &ACGetStartupId); 58 | OSDynLoad_FindExport(nn_ac_handle, 0, "ACConnectWithConfigId",&ACConnectWithConfigId); 59 | OSDynLoad_FindExport(nn_ac_handle, 0, "ACGetAssignedAddress",&ACGetAssignedAddress); 60 | 61 | OS_FIND_EXPORT(nsysnet_handle, socket_lib_init); 62 | OS_FIND_EXPORT(nsysnet_handle, socket); 63 | OS_FIND_EXPORT(nsysnet_handle, socketclose); 64 | OS_FIND_EXPORT(nsysnet_handle, connect); 65 | OS_FIND_EXPORT(nsysnet_handle, bind); 66 | OS_FIND_EXPORT(nsysnet_handle, listen); 67 | OS_FIND_EXPORT(nsysnet_handle, accept); 68 | OS_FIND_EXPORT(nsysnet_handle, send); 69 | OS_FIND_EXPORT(nsysnet_handle, recv); 70 | OS_FIND_EXPORT(nsysnet_handle, sendto); 71 | OS_FIND_EXPORT(nsysnet_handle, setsockopt); 72 | OS_FIND_EXPORT(nsysnet_handle, inet_ntoa); 73 | OS_FIND_EXPORT(nsysnet_handle, inet_aton); 74 | OS_FIND_EXPORT(nsysnet_handle, socketlasterr); 75 | 76 | unsigned int nn_startupid; 77 | ACInitialize(); 78 | ACGetStartupId(&nn_startupid); 79 | ACConnectWithConfigId(nn_startupid); 80 | ACGetAssignedAddress(&hostIpAddress); 81 | 82 | socket_lib_init(); 83 | } 84 | 85 | -------------------------------------------------------------------------------- /src/dynamic_libs/socket_functions.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | * Copyright (C) 2015 3 | * by Dimok 4 | * 5 | * This software is provided 'as-is', without any express or implied 6 | * warranty. In no event will the authors be held liable for any 7 | * damages arising from the use of this software. 8 | * 9 | * Permission is granted to anyone to use this software for any 10 | * purpose, including commercial applications, and to alter it and 11 | * redistribute it freely, subject to the following restrictions: 12 | * 13 | * 1. The origin of this software must not be misrepresented; you 14 | * must not claim that you wrote the original software. If you use 15 | * this software in a product, an acknowledgment in the product 16 | * documentation would be appreciated but is not required. 17 | * 18 | * 2. Altered source versions must be plainly marked as such, and 19 | * must not be misrepresented as being the original software. 20 | * 21 | * 3. This notice may not be removed or altered from any source 22 | * distribution. 23 | ***************************************************************************/ 24 | #ifndef __SOCKET_FUNCTIONS_H_ 25 | #define __SOCKET_FUNCTIONS_H_ 26 | 27 | #ifdef __cplusplus 28 | extern "C" { 29 | #endif 30 | 31 | #include 32 | 33 | #define INADDR_ANY 0 34 | 35 | #define AF_INET 2 36 | 37 | #define SOCK_STREAM 1 38 | #define SOCK_DGRAM 2 39 | 40 | #define IPPROTO_IP 0 41 | #define IPPROTO_TCP 6 42 | #define IPPROTO_UDP 17 43 | 44 | #define TCP_NODELAY 0x2004 45 | 46 | #define SOL_SOCKET -1 47 | #define SO_REUSEADDR 0x0004 48 | #define SO_NONBLOCK 0x1016 49 | #define SO_MYADDR 0x1013 50 | 51 | #define ENODATA 1 52 | #define EISCONN 3 53 | #define EWOULDBLOCK 6 54 | #define EALREADY 10 55 | #define EAGAIN EWOULDBLOCK 56 | #define EINVAL 11 57 | #define ENOMEM 18 58 | #define EINPROGRESS 22 59 | 60 | #define htonl(x) x 61 | #define htons(x) x 62 | #define ntohl(x) x 63 | #define ntohs(x) x 64 | 65 | 66 | struct in_addr { 67 | unsigned int s_addr; 68 | }; 69 | struct sockaddr_in { 70 | short sin_family; 71 | unsigned short sin_port; 72 | struct in_addr sin_addr; 73 | char sin_zero[8]; 74 | }; 75 | 76 | struct sockaddr 77 | { 78 | unsigned short sa_family; 79 | char sa_data[14]; 80 | }; 81 | 82 | 83 | void InitSocketFunctionPointers(void); 84 | 85 | extern void (*socket_lib_init)(void); 86 | extern int (*socket)(int domain, int type, int protocol); 87 | extern int (*socketclose)(int s); 88 | extern int (*connect)(int s, void *addr, int addrlen); 89 | extern int (*bind)(s32 s,struct sockaddr *name,s32 namelen); 90 | extern int (*listen)(s32 s,u32 backlog); 91 | extern int (*accept)(s32 s,struct sockaddr *addr,s32 *addrlen); 92 | extern int (*send)(int s, const void *buffer, int size, int flags); 93 | extern int (*recv)(int s, void *buffer, int size, int flags); 94 | extern int (*sendto)(int s, const void *buffer, int size, int flags, const struct sockaddr *dest, int dest_len); 95 | extern int (*setsockopt)(int s, int level, int optname, void *optval, int optlen); 96 | 97 | extern char * (*inet_ntoa)(struct in_addr in); 98 | extern int (*inet_aton)(const char *cp, struct in_addr *inp); 99 | 100 | extern int (*socketlasterr)(void); 101 | 102 | #define geterrno() (socketlasterr()) 103 | 104 | #ifdef __cplusplus 105 | } 106 | #endif 107 | 108 | #endif // __SOCKET_FUNCTIONS_H_ 109 | -------------------------------------------------------------------------------- /src/dynamic_libs/sys_functions.c: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | * Copyright (C) 2015 3 | * by Dimok 4 | * 5 | * This software is provided 'as-is', without any express or implied 6 | * warranty. In no event will the authors be held liable for any 7 | * damages arising from the use of this software. 8 | * 9 | * Permission is granted to anyone to use this software for any 10 | * purpose, including commercial applications, and to alter it and 11 | * redistribute it freely, subject to the following restrictions: 12 | * 13 | * 1. The origin of this software must not be misrepresented; you 14 | * must not claim that you wrote the original software. If you use 15 | * this software in a product, an acknowledgment in the product 16 | * documentation would be appreciated but is not required. 17 | * 18 | * 2. Altered source versions must be plainly marked as such, and 19 | * must not be misrepresented as being the original software. 20 | * 21 | * 3. This notice may not be removed or altered from any source 22 | * distribution. 23 | ***************************************************************************/ 24 | #include "os_functions.h" 25 | 26 | EXPORT_DECL(void, _SYSLaunchTitleByPathFromLauncher, const char* path, int len, int zero); 27 | EXPORT_DECL(int, SYSRelaunchTitle, int argc, char* argv); 28 | EXPORT_DECL(int, SYSLaunchMenu, void); 29 | 30 | void InitSysFunctionPointers(void) 31 | { 32 | unsigned int *funcPointer = 0; 33 | unsigned int sysapp_handle; 34 | OSDynLoad_Acquire("sysapp.rpl", &sysapp_handle); 35 | 36 | OS_FIND_EXPORT(sysapp_handle, _SYSLaunchTitleByPathFromLauncher); 37 | OS_FIND_EXPORT(sysapp_handle, SYSRelaunchTitle); 38 | OS_FIND_EXPORT(sysapp_handle, SYSLaunchMenu); 39 | } 40 | 41 | -------------------------------------------------------------------------------- /src/dynamic_libs/sys_functions.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | * Copyright (C) 2015 3 | * by Dimok 4 | * 5 | * This software is provided 'as-is', without any express or implied 6 | * warranty. In no event will the authors be held liable for any 7 | * damages arising from the use of this software. 8 | * 9 | * Permission is granted to anyone to use this software for any 10 | * purpose, including commercial applications, and to alter it and 11 | * redistribute it freely, subject to the following restrictions: 12 | * 13 | * 1. The origin of this software must not be misrepresented; you 14 | * must not claim that you wrote the original software. If you use 15 | * this software in a product, an acknowledgment in the product 16 | * documentation would be appreciated but is not required. 17 | * 18 | * 2. Altered source versions must be plainly marked as such, and 19 | * must not be misrepresented as being the original software. 20 | * 21 | * 3. This notice may not be removed or altered from any source 22 | * distribution. 23 | ***************************************************************************/ 24 | #ifndef __SYS_FUNCTIONS_H_ 25 | #define __SYS_FUNCTIONS_H_ 26 | 27 | #ifdef __cplusplus 28 | extern "C" { 29 | #endif 30 | 31 | void InitSysFunctionPointers(void); 32 | 33 | extern void(*_SYSLaunchTitleByPathFromLauncher)(const char* path, int len, int zero); 34 | extern int (* SYSRelaunchTitle)(int argc, char* argv); 35 | extern int (* SYSLaunchMenu)(void); 36 | 37 | 38 | #ifdef __cplusplus 39 | } 40 | #endif 41 | 42 | #endif // __SYS_FUNCTIONS_H_ 43 | -------------------------------------------------------------------------------- /src/dynamic_libs/vpad_functions.c: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | * Copyright (C) 2015 3 | * by Dimok 4 | * 5 | * This software is provided 'as-is', without any express or implied 6 | * warranty. In no event will the authors be held liable for any 7 | * damages arising from the use of this software. 8 | * 9 | * Permission is granted to anyone to use this software for any 10 | * purpose, including commercial applications, and to alter it and 11 | * redistribute it freely, subject to the following restrictions: 12 | * 13 | * 1. The origin of this software must not be misrepresented; you 14 | * must not claim that you wrote the original software. If you use 15 | * this software in a product, an acknowledgment in the product 16 | * documentation would be appreciated but is not required. 17 | * 18 | * 2. Altered source versions must be plainly marked as such, and 19 | * must not be misrepresented as being the original software. 20 | * 21 | * 3. This notice may not be removed or altered from any source 22 | * distribution. 23 | ***************************************************************************/ 24 | #include "os_functions.h" 25 | #include "vpad_functions.h" 26 | 27 | EXPORT_DECL(void, VPADInit, void); 28 | EXPORT_DECL(void, VPADRead, int chan, VPADData *buffer, u32 buffer_size, s32 *error); 29 | 30 | void InitVPadFunctionPointers(void) 31 | { 32 | unsigned int *funcPointer = 0; 33 | unsigned int vpad_handle; 34 | OSDynLoad_Acquire("vpad.rpl", &vpad_handle); 35 | 36 | OS_FIND_EXPORT(vpad_handle, VPADInit); 37 | OS_FIND_EXPORT(vpad_handle, VPADRead); 38 | } 39 | 40 | -------------------------------------------------------------------------------- /src/dynamic_libs/vpad_functions.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | * Copyright (C) 2015 3 | * by Dimok 4 | * 5 | * This software is provided 'as-is', without any express or implied 6 | * warranty. In no event will the authors be held liable for any 7 | * damages arising from the use of this software. 8 | * 9 | * Permission is granted to anyone to use this software for any 10 | * purpose, including commercial applications, and to alter it and 11 | * redistribute it freely, subject to the following restrictions: 12 | * 13 | * 1. The origin of this software must not be misrepresented; you 14 | * must not claim that you wrote the original software. If you use 15 | * this software in a product, an acknowledgment in the product 16 | * documentation would be appreciated but is not required. 17 | * 18 | * 2. Altered source versions must be plainly marked as such, and 19 | * must not be misrepresented as being the original software. 20 | * 21 | * 3. This notice may not be removed or altered from any source 22 | * distribution. 23 | ***************************************************************************/ 24 | #ifndef __VPAD_FUNCTIONS_H_ 25 | #define __VPAD_FUNCTIONS_H_ 26 | 27 | #ifdef __cplusplus 28 | extern "C" { 29 | #endif 30 | 31 | #include 32 | 33 | #define VPAD_BUTTON_A 0x8000 34 | #define VPAD_BUTTON_B 0x4000 35 | #define VPAD_BUTTON_X 0x2000 36 | #define VPAD_BUTTON_Y 0x1000 37 | #define VPAD_BUTTON_LEFT 0x0800 38 | #define VPAD_BUTTON_RIGHT 0x0400 39 | #define VPAD_BUTTON_UP 0x0200 40 | #define VPAD_BUTTON_DOWN 0x0100 41 | #define VPAD_BUTTON_ZL 0x0080 42 | #define VPAD_BUTTON_ZR 0x0040 43 | #define VPAD_BUTTON_L 0x0020 44 | #define VPAD_BUTTON_R 0x0010 45 | #define VPAD_BUTTON_PLUS 0x0008 46 | #define VPAD_BUTTON_MINUS 0x0004 47 | #define VPAD_BUTTON_HOME 0x0002 48 | #define VPAD_BUTTON_SYNC 0x0001 49 | #define VPAD_BUTTON_STICK_R 0x00020000 50 | #define VPAD_BUTTON_STICK_L 0x00040000 51 | #define VPAD_BUTTON_TV 0x00010000 52 | 53 | #define VPAD_STICK_R_EMULATION_LEFT 0x04000000 54 | #define VPAD_STICK_R_EMULATION_RIGHT 0x02000000 55 | #define VPAD_STICK_R_EMULATION_UP 0x01000000 56 | #define VPAD_STICK_R_EMULATION_DOWN 0x00800000 57 | 58 | #define VPAD_STICK_L_EMULATION_LEFT 0x40000000 59 | #define VPAD_STICK_L_EMULATION_RIGHT 0x20000000 60 | #define VPAD_STICK_L_EMULATION_UP 0x10000000 61 | #define VPAD_STICK_L_EMULATION_DOWN 0x08000000 62 | 63 | 64 | typedef struct 65 | { 66 | f32 x,y; 67 | } Vec2D; 68 | 69 | typedef struct 70 | { 71 | u16 x, y; /* Touch coordinates */ 72 | u16 touched; /* 1 = Touched, 0 = Not touched */ 73 | u16 invalid; /* 0 = All valid, 1 = X invalid, 2 = Y invalid, 3 = Both invalid? */ 74 | } VPADTPData; 75 | 76 | typedef struct 77 | { 78 | u32 btns_h; /* Held buttons */ 79 | u32 btns_d; /* Buttons that are pressed at that instant */ 80 | u32 btns_r; /* Released buttons */ 81 | Vec2D lstick, rstick; /* Each contains 4-byte X and Y components */ 82 | char unknown1c[0x52 - 0x1c]; /* Contains accelerometer and gyroscope data somewhere */ 83 | VPADTPData tpdata; /* Normal touchscreen data */ 84 | VPADTPData tpdata1; /* Modified touchscreen data 1 */ 85 | VPADTPData tpdata2; /* Modified touchscreen data 2 */ 86 | char unknown6a[0xa0 - 0x6a]; 87 | uint8_t volume; 88 | uint8_t battery; /* 0 to 6 */ 89 | uint8_t unk_volume; /* One less than volume */ 90 | char unknowna4[0xac - 0xa4]; 91 | } VPADData; 92 | 93 | void InitVPadFunctionPointers(void); 94 | 95 | extern void (* VPADInit)(void); 96 | extern void (* VPADRead)(int chan, VPADData *buffer, u32 buffer_size, s32 *error); 97 | 98 | #ifdef __cplusplus 99 | } 100 | #endif 101 | 102 | #endif // __VPAD_FUNCTIONS_H_ 103 | -------------------------------------------------------------------------------- /src/entry.c: -------------------------------------------------------------------------------- 1 | #include "main.h" 2 | 3 | int __entry_menu(int argc, char **argv) 4 | { 5 | // Jump to our application 6 | return Menu_Main(); 7 | } 8 | -------------------------------------------------------------------------------- /src/extractor.c: -------------------------------------------------------------------------------- 1 | /* This file is part of Wii (U) NAND Extractor C. 2 | * Copyright (C) 2020 GaryOderNichts 3 | * 4 | * This file was ported from Wii NAND Extractor. 5 | * Copyright (C) 2009 Ben Wilson 6 | * 7 | * Wii NAND Extractor is free software: you can redistribute it and/or 8 | * modify it under the terms of the GNU General Public License as published 9 | * by the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * Wii NAND Extractor is distributed in the hope that it will be 13 | * useful, but WITHOUT ANY WARRANTY; without even the implied warranty 14 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | #include "extractor.h" 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include "aes.h" 27 | #include 28 | #include "main.h" 29 | #include 30 | #include "dynamic_libs/fs_functions.h" 31 | #include "utils/stringutils.h" 32 | 33 | byte_t* key; 34 | FILE* rom; 35 | int32_t loc_super; 36 | int32_t loc_fat; 37 | int32_t loc_fst; 38 | FileType fileType = Invalid; 39 | NandType nandType; 40 | 41 | char* outNandDst; 42 | char* NandPath; 43 | int8_t initSuccess = 0; 44 | 45 | uint8_t initNand(const char* nandFile) 46 | { 47 | rom = fopen(nandFile, "rb"); 48 | if (rom == NULL) 49 | { 50 | console_printf(1, "error opening %s\n", nandFile); 51 | return 0; 52 | } 53 | 54 | NandPath = malloc(FS_MAX_FULLPATH_SIZE); 55 | strcpy(NandPath, nandFile); 56 | char *pos = strrchr(NandPath, '/'); 57 | if (pos != NULL) { 58 | *pos = '\0'; 59 | } 60 | 61 | if (!getFileType() || !getNandType() || !getKey()) 62 | return 0; 63 | 64 | loc_super = findSuperblock(); 65 | if (loc_super == -1) 66 | { 67 | console_printf(1, "cannot find superblock!\n"); 68 | return 0; 69 | } 70 | 71 | int32_t fatlen = getClusterSize() * 4; 72 | loc_fat = loc_super; 73 | loc_fst = loc_fat + 0x0C + fatlen; 74 | 75 | initSuccess = 1; 76 | 77 | return 1; 78 | } 79 | 80 | void cleanup(void) 81 | { 82 | fclose(rom); 83 | free(key); 84 | free(NandPath); 85 | free(outNandDst); 86 | } 87 | 88 | int32_t getPageSize(void) 89 | { 90 | if (fileType == NoECC) 91 | return PAGE_SIZE; 92 | else 93 | return PAGE_SIZE + SPARE_SIZE; 94 | } 95 | 96 | int32_t getClusterSize(void) 97 | { 98 | return getPageSize() * 8; 99 | } 100 | 101 | uint8_t getFileType(void) 102 | { 103 | rewind(rom); 104 | fseek(rom, 0, SEEK_END); 105 | uint64_t lenght = ftell(rom); 106 | console_printf(1, "File size: %llu", lenght); 107 | switch (lenght) 108 | { 109 | case PAGE_SIZE * 8 * CLUSTERS_COUNT: 110 | fileType = NoECC; 111 | return 1; 112 | case (PAGE_SIZE + SPARE_SIZE) * 8 * CLUSTERS_COUNT: 113 | fileType = ECC; 114 | return 1; 115 | case (PAGE_SIZE + SPARE_SIZE) * 8 * CLUSTERS_COUNT + 0x400: 116 | fileType = BootMii; 117 | return 1; 118 | default: 119 | console_printf(1, "Error determining File type!"); 120 | return 0; 121 | } 122 | } 123 | 124 | uint8_t getNandType(void) 125 | { 126 | rewind(rom); 127 | fseek(rom, getClusterSize() * 0x7FF0, SEEK_SET); 128 | uint32_t cluster; 129 | fread(&cluster, sizeof(uint32_t), 1, rom); 130 | switch (bswap32(cluster)) 131 | { 132 | case 0x53464653: 133 | nandType = Wii; 134 | return 1; 135 | case 0x53465321: 136 | if (fileType == BootMii) return 0; // Invalid dump type for WiiU 137 | nandType = WiiU; 138 | console_printf(1, "Wii U backup detected! Make sure to use slccmpt.bin\n"); 139 | return 0; 140 | default: 141 | console_printf(1, "Error determining NAND type!"); 142 | return 0; 143 | } 144 | } 145 | 146 | uint8_t getKey(void) 147 | { 148 | //TODO key from text 149 | 150 | if (fileType == BootMii) 151 | { 152 | rewind(rom); 153 | fseek(rom, 0x21000158, SEEK_SET); 154 | byte_t* bootmiikey = calloc(16, sizeof(byte_t)); 155 | fread(bootmiikey, sizeof(byte_t), 16, rom); 156 | key = bootmiikey; 157 | return 1; 158 | } 159 | else 160 | { 161 | char* otppath = (char*) malloc(FS_MAX_FULLPATH_SIZE); 162 | strcpy(otppath, NandPath); 163 | strcat(otppath, "/otp.bin"); 164 | 165 | key = readOTP(otppath); 166 | free(otppath); 167 | if (key != NULL) 168 | return 1; 169 | 170 | if (nandType == Wii) 171 | { 172 | char* keyspath = malloc(FS_MAX_FULLPATH_SIZE); 173 | strcpy(keyspath, NandPath); 174 | strcat(keyspath, "/keys.bin"); 175 | 176 | key = readKeyfile(keyspath); 177 | free(keyspath); 178 | if (key != NULL) 179 | return 1; 180 | } 181 | } 182 | 183 | console_printf(1, "Error reading key\n"); 184 | return 0; 185 | } 186 | 187 | byte_t* readKeyfile(char* path) 188 | { 189 | byte_t* retval = malloc(sizeof(char) * 16); 190 | 191 | FILE* keyfile = fopen(path, "rb"); 192 | if (keyfile == NULL) 193 | { 194 | free(retval); 195 | return NULL; 196 | } 197 | 198 | fseek(keyfile, 0x158, SEEK_SET); 199 | fread(retval, sizeof(byte_t), 16, keyfile); 200 | fclose(keyfile); 201 | 202 | return retval; 203 | } 204 | 205 | byte_t* readOTP(char* path) 206 | { 207 | byte_t* retval = malloc(sizeof(char) * 16); 208 | 209 | FILE* otpfile = fopen(path, "rb"); 210 | if (otpfile == NULL) 211 | { 212 | free(retval); 213 | return NULL; 214 | } 215 | 216 | if (nandType == Wii) 217 | fseek(otpfile, 0x058, SEEK_SET); 218 | else 219 | fseek(otpfile, 0x170, SEEK_SET); 220 | 221 | fread(retval, sizeof(byte_t), 16, otpfile); 222 | fclose(otpfile); 223 | 224 | return retval; 225 | } 226 | 227 | int32_t findSuperblock(void) 228 | { 229 | uint32_t loc = ((nandType == Wii) ? 0x7F00 : 0x7C00) * getClusterSize(); 230 | uint32_t end = CLUSTERS_COUNT * getClusterSize(); 231 | uint32_t len = getClusterSize() * 0x10; 232 | uint32_t current, magic, last = 0; 233 | 234 | uint8_t irewind = 1; 235 | for (; loc < end; loc += len) 236 | { 237 | rewind(rom); 238 | fseek(rom, loc, SEEK_SET); 239 | fread(&magic, 4, 1, rom); 240 | if (magic != 0x53464653) 241 | { 242 | console_printf(1, "Finding superblock... this is not a supercluster"); 243 | irewind++; 244 | continue; 245 | } 246 | 247 | fread(¤t, 4, 1, rom); 248 | current = bswap32(current); 249 | 250 | if (current > last) 251 | last = current; 252 | else 253 | { 254 | irewind = 1; 255 | break; 256 | } 257 | 258 | if (loc == end) 259 | irewind = 1; 260 | } 261 | 262 | if (!last) 263 | return -1; 264 | 265 | loc -= len * irewind; 266 | 267 | return loc; 268 | } 269 | 270 | fst_t getFST(uint16_t entry) 271 | { 272 | fst_t fst; 273 | 274 | // compensate for 64 bytes of ecc data every 64 fst entries 275 | int32_t n_fst = (fileType == NoECC) ? 0 : 2; 276 | int32_t loc_entry = (((entry / 0x40) * n_fst) + entry) * 0x20; 277 | 278 | rewind(rom); 279 | fseek(rom, loc_fst + loc_entry, SEEK_SET); 280 | 281 | fread(&fst.filename, sizeof(byte_t), 0x0C, rom); 282 | fread(&fst.mode, sizeof(byte_t), 1, rom); 283 | fread(&fst.attr, sizeof(byte_t), 1, rom); 284 | 285 | uint16_t sub; 286 | fread(&sub, sizeof(uint16_t), 1, rom); 287 | sub = bswap16(sub); 288 | fst.sub = sub; 289 | 290 | uint16_t sib; 291 | fread(&sib, sizeof(uint16_t), 1, rom); 292 | sib = bswap16(sib); 293 | fst.sib = sib; 294 | 295 | uint32_t size; 296 | if ((entry + 1) % 64 == 0) //the entry for every 64th fst item is inturrupeted 297 | { 298 | fread(&size, 2, 1, rom); 299 | fseek(rom, 0x40, SEEK_CUR); 300 | fread((char*) (&size) + 2, 2, 1, rom); 301 | } 302 | else 303 | { 304 | fread(&size, sizeof(uint32_t), 1, rom); 305 | } 306 | size = bswap32(size); 307 | fst.size = size; 308 | 309 | uint32_t uid; 310 | fread(&uid, sizeof(uint32_t), 1, rom); 311 | uid = bswap32(uid); 312 | fst.uid = uid; 313 | 314 | uint16_t gid; 315 | fread(&gid, sizeof(uint16_t), 1, rom); 316 | gid = bswap16(gid); 317 | fst.gid = gid; 318 | 319 | uint32_t x3; 320 | fread(&x3, sizeof(uint32_t), 1, rom); 321 | x3 = bswap32(x3); 322 | fst.x3 = x3; 323 | 324 | fst.mode &= 1; 325 | 326 | return fst; 327 | } 328 | 329 | void extractNand(const char* dest) 330 | { 331 | if (initSuccess != 1 || rom == NULL) 332 | { 333 | console_printf(1, "NAND has not been initialized successfully!"); 334 | return; 335 | } 336 | 337 | char* _outNandDst = malloc(FS_MAX_FULLPATH_SIZE); 338 | strcpy(_outNandDst, dest); 339 | outNandDst = _outNandDst; 340 | 341 | mkdir(outNandDst, 0777); 342 | extractFST(0, ""); 343 | } 344 | 345 | byte_t* getCluster(uint16_t cluster_entry) 346 | { 347 | byte_t* cluster = calloc(0x4000, sizeof(byte_t)); 348 | byte_t* page = calloc(getPageSize(), sizeof(byte_t)); 349 | 350 | rewind(rom); 351 | fseek(rom, cluster_entry * getClusterSize(), SEEK_SET); 352 | 353 | for (int i = 0; i < 8; i++) 354 | { 355 | fread(page, sizeof(byte_t), getPageSize(), rom); 356 | memcpy((byte_t*) cluster + (i * 0x800), page, 0x800); 357 | } 358 | 359 | free(page); 360 | 361 | return aesDecrypt(key, cluster, 0x4000); 362 | } 363 | 364 | uint16_t getFAT(uint16_t fat_entry) 365 | { 366 | /* 367 | * compensate for "off-16" storage at beginning of superblock 368 | * 53 46 46 53 XX XX XX XX 00 00 00 00 369 | * S F F S "version" padding? 370 | * 1 2 3 4 5 6 371 | */ 372 | fat_entry += 6; 373 | 374 | // location in fat of cluster chain 375 | int32_t n_fat = (fileType == NoECC) ? 0 : 0x20; 376 | int32_t loc = loc_fat + ((((fat_entry / 0x400) * n_fat) + fat_entry) * 2); 377 | 378 | rewind(rom); 379 | fseek(rom, loc, SEEK_SET); 380 | 381 | uint16_t fat; 382 | fread(&fat, sizeof(uint16_t), 1, rom); 383 | return bswap16(fat); 384 | } 385 | 386 | void extractFST(uint16_t entry, char* parent) 387 | { 388 | fst_t fst = getFST(entry); 389 | 390 | if (fst.sib != 0xffff) 391 | extractFST(fst.sib, parent); 392 | 393 | switch (fst.mode) 394 | { 395 | case 0: 396 | extractDir(fst, entry, parent); 397 | break; 398 | case 1: 399 | extractFile(fst, entry, parent); 400 | break; 401 | default: 402 | console_printf(1, "Ignoring unsupported mode %s", fst.mode); 403 | break; 404 | } 405 | } 406 | 407 | void extractDir(fst_t fst, uint16_t entry, char* parent) 408 | { 409 | char* filename = malloc(FS_MAX_FULLPATH_SIZE); 410 | snprintf(filename, 13, "%s", fst.filename); 411 | //strncpy(filename, (char*) fst.filename, 12); 412 | 413 | char* newfilename = malloc(FS_MAX_FULLPATH_SIZE); 414 | newfilename[0] = '\0'; 415 | 416 | char* path = malloc(FS_MAX_FULLPATH_SIZE); 417 | path[0] = '\0'; 418 | 419 | 420 | if (strcmp(filename, "/") != 0) 421 | { 422 | if (strcmp(parent, "/") != 0 && strcmp(parent, "") != 0) 423 | { 424 | strcat(newfilename, parent); 425 | strcat(newfilename, "/"); 426 | strcat(newfilename, filename); 427 | } 428 | else 429 | { 430 | strcpy(newfilename, filename); 431 | } 432 | 433 | strcat(path, outNandDst); 434 | strcat(path, "/"); 435 | strcat(path, newfilename); 436 | 437 | console_printf(1, "Created dir: %s\n", filename); 438 | 439 | mkdir(path, 0777); 440 | 441 | } 442 | else 443 | { 444 | strcpy(newfilename, filename); 445 | } 446 | 447 | free(filename); 448 | free(path); 449 | 450 | if (fst.sub != 0xffff) 451 | extractFST(fst.sub, newfilename); 452 | 453 | free(newfilename); 454 | } 455 | 456 | void extractFile(fst_t fst, uint16_t entry, char* parent) 457 | { 458 | uint16_t fat; 459 | uint32_t cluster_span = (uint32_t) (fst.size / 0x4000) + 1; 460 | byte_t* data = calloc(cluster_span * 0x4000, sizeof(byte_t)); 461 | 462 | char* filename = malloc(FS_MAX_FULLPATH_SIZE); 463 | snprintf(filename, 13, "%s", fst.filename); 464 | //strlcpy(filename, (char*) fst.filename, 12); 465 | stringReplaceAll(":", "-", filename); 466 | 467 | char* newfilename = malloc(FS_MAX_FULLPATH_SIZE); 468 | newfilename[0] = '\0'; 469 | strcat(newfilename, "/"); 470 | strcat(newfilename, parent); 471 | strcat(newfilename, "/"); 472 | strcat(newfilename, filename); 473 | 474 | char* path = malloc(FS_MAX_FULLPATH_SIZE); 475 | path[0] = '\0'; 476 | 477 | strcat(path, outNandDst); 478 | strcat(path, newfilename); 479 | 480 | FILE* bf = fopen(path, "wb"); 481 | if(bf == NULL) 482 | { 483 | console_printf(1, "Error opening %s: %d\n", path, errno); 484 | } 485 | 486 | console_printf(1, "\n"); 487 | fat = fst.sub; 488 | for (int i = 0; fat < 0xFFF0; i++) 489 | { 490 | //extracting... 491 | console_printf(0, " extracting %s cluster %i\r", filename, i); 492 | byte_t* cluster = getCluster(fat); 493 | memcpy((byte_t*) (data + (i * 0x4000)), cluster, 0x4000); 494 | fat = getFAT(fat); 495 | free(cluster); 496 | } 497 | 498 | fwrite(data, fst.size, 1, bf); 499 | fclose(bf); 500 | 501 | free(data); 502 | free(filename); 503 | free(path); 504 | 505 | console_printf(1, "extracted file: %s\n", newfilename); 506 | 507 | free(newfilename); 508 | } 509 | 510 | byte_t* aesDecrypt(byte_t* key, byte_t* enc_data, size_t data_size) 511 | { 512 | byte_t* dec_data = calloc(data_size, sizeof(byte_t)); 513 | memcpy(dec_data, enc_data, data_size); 514 | free(enc_data); 515 | 516 | const byte_t* iv = calloc(16, sizeof(byte_t)); 517 | 518 | struct AES_ctx ctx; 519 | AES_init_ctx_iv(&ctx, key, iv); 520 | 521 | AES_CBC_decrypt_buffer(&ctx, dec_data, data_size); 522 | 523 | free((byte_t*) iv); 524 | return dec_data; 525 | } 526 | 527 | /* 528 | required on LITTLE ENDIAN devices returns only input on the wii u 529 | */ 530 | uint16_t bswap16(uint16_t value) 531 | { 532 | return value; 533 | // return (uint16_t) ((0x00FF & (value >> 8)) | (0xFF00 & (value << 8))); 534 | } 535 | 536 | uint32_t bswap32(uint32_t value) 537 | { 538 | return value; 539 | // uint32_t swapped = (((0x000000FF) & (value >> 24)) 540 | // | ((0x0000FF00) & (value >> 8)) 541 | // | ((0x00FF0000) & (value << 8)) 542 | // | ((0xFF000000) & (value << 24))); 543 | // return swapped; 544 | } -------------------------------------------------------------------------------- /src/extractor.h: -------------------------------------------------------------------------------- 1 | /* This file is part of Wii (U) NAND Extractor C. 2 | * Copyright (C) 2020 GaryOderNichts 3 | * 4 | * This file was ported from Wii NAND Extractor. 5 | * Copyright (C) 2009 Ben Wilson 6 | * 7 | * Wii NAND Extractor is free software: you can redistribute it and/or 8 | * modify it under the terms of the GNU General Public License as published 9 | * by the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * Wii NAND Extractor is distributed in the hope that it will be 13 | * useful, but WITHOUT ANY WARRANTY; without even the implied warranty 14 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | #ifndef _EXTRACTOR_H_ 22 | #define _EXTRACTOR_H_ 23 | 24 | #include 25 | #include 26 | 27 | #define PAGE_SIZE 0x800 28 | #define SPARE_SIZE 0x40 29 | #define CLUSTERS_COUNT 0x8000 30 | 31 | typedef uint8_t byte_t; 32 | 33 | typedef struct 34 | { 35 | byte_t filename[0x0C]; 36 | byte_t mode; 37 | byte_t attr; 38 | uint16_t sub; 39 | uint16_t sib; 40 | uint32_t size; 41 | uint32_t uid; 42 | uint32_t gid; 43 | uint32_t x3; 44 | } fst_t; 45 | 46 | typedef enum 47 | { 48 | Invalid, 49 | NoECC, 50 | ECC, 51 | BootMii 52 | } FileType; 53 | 54 | typedef enum 55 | { 56 | Wii, 57 | WiiU 58 | } NandType; 59 | 60 | uint8_t initNand(const char* nandFile); 61 | void cleanup(void); 62 | int32_t getPageSize(void); 63 | int32_t getClusterSize(void); 64 | uint8_t getFileType(void); 65 | uint8_t getNandType(void); 66 | uint8_t getKey(void); 67 | byte_t* readKeyfile(char* path); 68 | byte_t* readOTP(char* path); 69 | int32_t findSuperblock(void); 70 | 71 | byte_t* getCluster(uint16_t cluster_entry); 72 | uint16_t getFAT(uint16_t fat_entry); 73 | fst_t getFST(uint16_t entry); 74 | void extractNand(const char* dest); 75 | void extractFST(uint16_t entry, char* parent); 76 | 77 | void extractDir(fst_t fst, uint16_t entry, char* parent); 78 | void extractFile(fst_t fst, uint16_t entry, char* parent); 79 | 80 | byte_t* aesDecrypt(byte_t* key, byte_t* enc_data, size_t data_size); 81 | uint16_t bswap16(uint16_t value); 82 | uint32_t bswap32(uint32_t value); 83 | 84 | #endif -------------------------------------------------------------------------------- /src/fs/fs_utils.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "common/fs_defs.h" 7 | #include "dynamic_libs/fs_functions.h" 8 | 9 | 10 | int MountFS(void *pClient, void *pCmd, char **mount_path) 11 | { 12 | int result = -1; 13 | 14 | void *mountSrc = malloc(FS_MOUNT_SOURCE_SIZE); 15 | if(!mountSrc) 16 | return -3; 17 | 18 | char* mountPath = (char*) malloc(FS_MAX_MOUNTPATH_SIZE); 19 | if(!mountPath) { 20 | free(mountSrc); 21 | return -4; 22 | } 23 | 24 | memset(mountSrc, 0, FS_MOUNT_SOURCE_SIZE); 25 | memset(mountPath, 0, FS_MAX_MOUNTPATH_SIZE); 26 | 27 | // Mount sdcard 28 | if (FSGetMountSource(pClient, pCmd, FS_SOURCETYPE_EXTERNAL, mountSrc, -1) == 0) 29 | { 30 | result = FSMount(pClient, pCmd, mountSrc, mountPath, FS_MAX_MOUNTPATH_SIZE, -1); 31 | if((result == 0) && mount_path) { 32 | *mount_path = (char*)malloc(strlen(mountPath) + 1); 33 | if(*mount_path) 34 | strcpy(*mount_path, mountPath); 35 | } 36 | } 37 | 38 | free(mountPath); 39 | free(mountSrc); 40 | return result; 41 | } 42 | 43 | int UmountFS(void *pClient, void *pCmd, const char *mountPath) 44 | { 45 | int result = -1; 46 | result = FSUnmount(pClient, pCmd, mountPath, -1); 47 | 48 | return result; 49 | } 50 | 51 | int LoadFileToMem(const char *filepath, u8 **inbuffer, u32 *size) 52 | { 53 | //! always initialze input 54 | *inbuffer = NULL; 55 | if(size) 56 | *size = 0; 57 | 58 | int iFd = open(filepath, O_RDONLY); 59 | if (iFd < 0) 60 | return -1; 61 | 62 | u32 filesize = lseek(iFd, 0, SEEK_END); 63 | lseek(iFd, 0, SEEK_SET); 64 | 65 | u8 *buffer = (u8 *) malloc(filesize); 66 | if (buffer == NULL) 67 | { 68 | close(iFd); 69 | return -2; 70 | } 71 | 72 | u32 blocksize = 0x4000; 73 | u32 done = 0; 74 | int readBytes = 0; 75 | 76 | while(done < filesize) 77 | { 78 | if(done + blocksize > filesize) { 79 | blocksize = filesize - done; 80 | } 81 | readBytes = read(iFd, buffer + done, blocksize); 82 | if(readBytes <= 0) 83 | break; 84 | done += readBytes; 85 | } 86 | 87 | close(iFd); 88 | 89 | if (done != filesize) 90 | { 91 | free(buffer); 92 | return -3; 93 | } 94 | 95 | *inbuffer = buffer; 96 | 97 | //! sign is optional input 98 | if(size) 99 | *size = filesize; 100 | 101 | return filesize; 102 | } 103 | 104 | int CheckFile(const char * filepath) 105 | { 106 | if(!filepath) 107 | return 0; 108 | 109 | struct stat filestat; 110 | 111 | char dirnoslash[strlen(filepath)+2]; 112 | snprintf(dirnoslash, sizeof(dirnoslash), "%s", filepath); 113 | 114 | while(dirnoslash[strlen(dirnoslash)-1] == '/') 115 | dirnoslash[strlen(dirnoslash)-1] = '\0'; 116 | 117 | char * notRoot = strrchr(dirnoslash, '/'); 118 | if(!notRoot) 119 | { 120 | strcat(dirnoslash, "/"); 121 | } 122 | 123 | if (stat(dirnoslash, &filestat) == 0) 124 | return 1; 125 | 126 | return 0; 127 | } 128 | 129 | int CreateSubfolder(const char * fullpath) 130 | { 131 | if(!fullpath) 132 | return 0; 133 | 134 | int result = 0; 135 | 136 | char dirnoslash[strlen(fullpath)+1]; 137 | strcpy(dirnoslash, fullpath); 138 | 139 | int pos = strlen(dirnoslash)-1; 140 | while(dirnoslash[pos] == '/') 141 | { 142 | dirnoslash[pos] = '\0'; 143 | pos--; 144 | } 145 | 146 | if(CheckFile(dirnoslash)) 147 | { 148 | return 1; 149 | } 150 | else 151 | { 152 | char parentpath[strlen(dirnoslash)+2]; 153 | strcpy(parentpath, dirnoslash); 154 | char * ptr = strrchr(parentpath, '/'); 155 | 156 | if(!ptr) 157 | { 158 | //!Device root directory (must be with '/') 159 | strcat(parentpath, "/"); 160 | struct stat filestat; 161 | if (stat(parentpath, &filestat) == 0) 162 | return 1; 163 | 164 | return 0; 165 | } 166 | 167 | ptr++; 168 | ptr[0] = '\0'; 169 | 170 | result = CreateSubfolder(parentpath); 171 | } 172 | 173 | if(!result) 174 | return 0; 175 | 176 | if (mkdir(dirnoslash, 0777) == -1) 177 | { 178 | return 0; 179 | } 180 | 181 | return 1; 182 | } 183 | -------------------------------------------------------------------------------- /src/fs/fs_utils.h: -------------------------------------------------------------------------------- 1 | #ifndef __FS_UTILS_H_ 2 | #define __FS_UTILS_H_ 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #include 9 | 10 | int MountFS(void *pClient, void *pCmd, char **mount_path); 11 | int UmountFS(void *pClient, void *pCmd, const char *mountPath); 12 | 13 | int LoadFileToMem(const char *filepath, u8 **inbuffer, u32 *size); 14 | 15 | //! todo: C++ class 16 | int CreateSubfolder(const char * fullpath); 17 | int CheckFile(const char * filepath); 18 | 19 | #ifdef __cplusplus 20 | } 21 | #endif 22 | 23 | #endif // __FS_UTILS_H_ 24 | -------------------------------------------------------------------------------- /src/fs/sd_fat_devoptab.c: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright (C) 2015 3 | * by Dimok 4 | * 5 | * This software is provided 'as-is', without any express or implied 6 | * warranty. In no event will the authors be held liable for any 7 | * damages arising from the use of this software. 8 | * 9 | * Permission is granted to anyone to use this software for any 10 | * purpose, including commercial applications, and to alter it and 11 | * redistribute it freely, subject to the following restrictions: 12 | * 13 | * 1. The origin of this software must not be misrepresented; you 14 | * must not claim that you wrote the original software. If you use 15 | * this software in a product, an acknowledgment in the product 16 | * documentation would be appreciated but is not required. 17 | * 18 | * 2. Altered source versions must be plainly marked as such, and 19 | * must not be misrepresented as being the original software. 20 | * 21 | * 3. This notice may not be removed or altered from any source 22 | * distribution. 23 | ***************************************************************************/ 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include "dynamic_libs/fs_functions.h" 33 | #include "dynamic_libs/os_functions.h" 34 | #include "fs_utils.h" 35 | 36 | #define FS_ALIGNMENT 0x40 37 | #define FS_ALIGN(x) (((x) + FS_ALIGNMENT - 1) & ~(FS_ALIGNMENT - 1)) 38 | 39 | typedef struct _sd_fat_private_t { 40 | char *mount_path; 41 | void *pClient; 42 | void *pCmd; 43 | void *pMutex; 44 | } sd_fat_private_t; 45 | 46 | typedef struct _sd_fat_file_state_t { 47 | sd_fat_private_t *dev; 48 | int fd; /* File descriptor */ 49 | int flags; /* Opening flags */ 50 | bool read; /* True if allowed to read from file */ 51 | bool write; /* True if allowed to write to file */ 52 | bool append; /* True if allowed to append to file */ 53 | u64 pos; /* Current position within the file (in bytes) */ 54 | u64 len; /* Total length of the file (in bytes) */ 55 | struct _sd_fat_file_state_t *prevOpenFile; /* The previous entry in a double-linked FILO list of open files */ 56 | struct _sd_fat_file_state_t *nextOpenFile; /* The next entry in a double-linked FILO list of open files */ 57 | } sd_fat_file_state_t; 58 | 59 | typedef struct _sd_fat_dir_entry_t { 60 | sd_fat_private_t *dev; 61 | int dirHandle; 62 | } sd_fat_dir_entry_t; 63 | 64 | static sd_fat_private_t *sd_fat_get_device_data(const char *path) 65 | { 66 | const devoptab_t *devoptab = NULL; 67 | char name[128] = {0}; 68 | int i; 69 | 70 | // Get the device name from the path 71 | strncpy(name, path, 127); 72 | strtok(name, ":/"); 73 | 74 | // Search the devoptab table for the specified device name 75 | // NOTE: We do this manually due to a 'bug' in GetDeviceOpTab 76 | // which ignores names with suffixes and causes names 77 | // like "ntfs" and "ntfs1" to be seen as equals 78 | for (i = 3; i < STD_MAX; i++) { 79 | devoptab = devoptab_list[i]; 80 | if (devoptab && devoptab->name) { 81 | if (strcmp(name, devoptab->name) == 0) { 82 | return (sd_fat_private_t *)devoptab->deviceData; 83 | } 84 | } 85 | } 86 | 87 | return NULL; 88 | } 89 | 90 | static char *sd_fat_real_path (const char *path, sd_fat_private_t *dev) 91 | { 92 | // Sanity check 93 | if (!path) 94 | return NULL; 95 | 96 | // Move the path pointer to the start of the actual path 97 | if (strchr(path, ':') != NULL) { 98 | path = strchr(path, ':') + 1; 99 | } 100 | 101 | int mount_len = strlen(dev->mount_path); 102 | 103 | char *new_name = (char*)malloc(mount_len + strlen(path) + 1); 104 | if(new_name) { 105 | strcpy(new_name, dev->mount_path); 106 | strcpy(new_name + mount_len, path); 107 | return new_name; 108 | } 109 | return new_name; 110 | } 111 | 112 | static int sd_fat_open_r (struct _reent *r, void *fileStruct, const char *path, int flags, int mode) 113 | { 114 | sd_fat_private_t *dev = sd_fat_get_device_data(path); 115 | if(!dev) { 116 | r->_errno = ENODEV; 117 | return -1; 118 | } 119 | 120 | sd_fat_file_state_t *file = (sd_fat_file_state_t *)fileStruct; 121 | 122 | file->dev = dev; 123 | // Determine which mode the file is opened for 124 | file->flags = flags; 125 | 126 | const char *mode_str; 127 | 128 | if ((flags & 0x03) == O_RDONLY) { 129 | file->read = true; 130 | file->write = false; 131 | file->append = false; 132 | mode_str = "r"; 133 | } else if ((flags & 0x03) == O_WRONLY) { 134 | file->read = false; 135 | file->write = true; 136 | file->append = (flags & O_APPEND); 137 | mode_str = file->append ? "a" : "w"; 138 | } else if ((flags & 0x03) == O_RDWR) { 139 | file->read = true; 140 | file->write = true; 141 | file->append = (flags & O_APPEND); 142 | mode_str = file->append ? "a+" : "r+"; 143 | } else { 144 | r->_errno = EACCES; 145 | return -1; 146 | } 147 | 148 | int fd = -1; 149 | 150 | OSLockMutex(dev->pMutex); 151 | 152 | char *real_path = sd_fat_real_path(path, dev); 153 | if(!path) { 154 | r->_errno = ENOMEM; 155 | OSUnlockMutex(dev->pMutex); 156 | return -1; 157 | } 158 | 159 | int result = FSOpenFile(dev->pClient, dev->pCmd, real_path, mode_str, &fd, -1); 160 | 161 | free(real_path); 162 | 163 | if(result == 0) 164 | { 165 | FSStat stats; 166 | result = FSGetStatFile(dev->pClient, dev->pCmd, fd, &stats, -1); 167 | if(result != 0) { 168 | FSCloseFile(dev->pClient, dev->pCmd, fd, -1); 169 | r->_errno = result; 170 | OSUnlockMutex(dev->pMutex); 171 | return -1; 172 | } 173 | file->fd = fd; 174 | file->pos = 0; 175 | file->len = stats.size; 176 | OSUnlockMutex(dev->pMutex); 177 | return (int)file; 178 | } 179 | 180 | r->_errno = result; 181 | OSUnlockMutex(dev->pMutex); 182 | return -1; 183 | } 184 | 185 | 186 | static int sd_fat_close_r (struct _reent *r, int fd) 187 | { 188 | sd_fat_file_state_t *file = (sd_fat_file_state_t *)fd; 189 | if(!file->dev) { 190 | r->_errno = ENODEV; 191 | return -1; 192 | } 193 | 194 | OSLockMutex(file->dev->pMutex); 195 | 196 | int result = FSCloseFile(file->dev->pClient, file->dev->pCmd, file->fd, -1); 197 | 198 | OSUnlockMutex(file->dev->pMutex); 199 | 200 | if(result < 0) 201 | { 202 | r->_errno = result; 203 | return -1; 204 | } 205 | return 0; 206 | } 207 | 208 | static off_t sd_fat_seek_r (struct _reent *r, int fd, off_t pos, int dir) 209 | { 210 | sd_fat_file_state_t *file = (sd_fat_file_state_t *)fd; 211 | if(!file->dev) { 212 | r->_errno = ENODEV; 213 | return 0; 214 | } 215 | 216 | OSLockMutex(file->dev->pMutex); 217 | 218 | switch(dir) 219 | { 220 | case SEEK_SET: 221 | file->pos = pos; 222 | break; 223 | case SEEK_CUR: 224 | file->pos += pos; 225 | break; 226 | case SEEK_END: 227 | file->pos = file->len + pos; 228 | break; 229 | default: 230 | r->_errno = EINVAL; 231 | return -1; 232 | } 233 | 234 | int result = FSSetPosFile(file->dev->pClient, file->dev->pCmd, file->fd, file->pos, -1); 235 | 236 | OSUnlockMutex(file->dev->pMutex); 237 | 238 | if(result == 0) 239 | { 240 | return file->pos; 241 | } 242 | 243 | return result; 244 | } 245 | 246 | static ssize_t sd_fat_write_r (struct _reent *r, int fd, const char *ptr, size_t len) 247 | { 248 | sd_fat_file_state_t *file = (sd_fat_file_state_t *)fd; 249 | if(!file->dev) { 250 | r->_errno = ENODEV; 251 | return 0; 252 | } 253 | 254 | if(!file->write) 255 | { 256 | r->_errno = EACCES; 257 | return 0; 258 | } 259 | 260 | OSLockMutex(file->dev->pMutex); 261 | 262 | size_t len_aligned = FS_ALIGN(len); 263 | if(len_aligned > 0x4000) 264 | len_aligned = 0x4000; 265 | 266 | unsigned char *tmpBuf = (unsigned char *)memalign(FS_ALIGNMENT, len_aligned); 267 | if(!tmpBuf) { 268 | r->_errno = ENOMEM; 269 | OSUnlockMutex(file->dev->pMutex); 270 | return 0; 271 | } 272 | 273 | size_t done = 0; 274 | 275 | while(done < len) 276 | { 277 | size_t write_size = (len_aligned < (len - done)) ? len_aligned : (len - done); 278 | memcpy(tmpBuf, ptr + done, write_size); 279 | 280 | int result = FSWriteFile(file->dev->pClient, file->dev->pCmd, tmpBuf, 0x01, write_size, file->fd, 0, -1); 281 | if(result < 0) 282 | { 283 | r->_errno = result; 284 | break; 285 | } 286 | else if(result == 0) 287 | { 288 | if(write_size > 0) 289 | done = 0; 290 | break; 291 | } 292 | else 293 | { 294 | done += result; 295 | file->pos += result; 296 | } 297 | } 298 | 299 | free(tmpBuf); 300 | OSUnlockMutex(file->dev->pMutex); 301 | return done; 302 | } 303 | 304 | static ssize_t sd_fat_read_r (struct _reent *r, int fd, char *ptr, size_t len) 305 | { 306 | sd_fat_file_state_t *file = (sd_fat_file_state_t *)fd; 307 | if(!file->dev) { 308 | r->_errno = ENODEV; 309 | return 0; 310 | } 311 | 312 | if(!file->read) 313 | { 314 | r->_errno = EACCES; 315 | return 0; 316 | } 317 | 318 | OSLockMutex(file->dev->pMutex); 319 | 320 | size_t len_aligned = FS_ALIGN(len); 321 | if(len_aligned > 0x4000) 322 | len_aligned = 0x4000; 323 | 324 | unsigned char *tmpBuf = (unsigned char *)memalign(FS_ALIGNMENT, len_aligned); 325 | if(!tmpBuf) { 326 | r->_errno = ENOMEM; 327 | OSUnlockMutex(file->dev->pMutex); 328 | return 0; 329 | } 330 | 331 | size_t done = 0; 332 | 333 | while(done < len) 334 | { 335 | size_t read_size = (len_aligned < (len - done)) ? len_aligned : (len - done); 336 | 337 | int result = FSReadFile(file->dev->pClient, file->dev->pCmd, tmpBuf, 0x01, read_size, file->fd, 0, -1); 338 | if(result < 0) 339 | { 340 | r->_errno = result; 341 | done = 0; 342 | break; 343 | } 344 | else if(result == 0) 345 | { 346 | //! TODO: error on read_size > 0 347 | break; 348 | } 349 | else 350 | { 351 | memcpy(ptr + done, tmpBuf, read_size); 352 | done += result; 353 | file->pos += result; 354 | } 355 | } 356 | 357 | free(tmpBuf); 358 | OSUnlockMutex(file->dev->pMutex); 359 | return done; 360 | } 361 | 362 | 363 | static int sd_fat_fstat_r (struct _reent *r, int fd, struct stat *st) 364 | { 365 | sd_fat_file_state_t *file = (sd_fat_file_state_t *)fd; 366 | if(!file->dev) { 367 | r->_errno = ENODEV; 368 | return -1; 369 | } 370 | 371 | OSLockMutex(file->dev->pMutex); 372 | 373 | // Zero out the stat buffer 374 | memset(st, 0, sizeof(struct stat)); 375 | 376 | FSStat stats; 377 | int result = FSGetStatFile(file->dev->pClient, file->dev->pCmd, file->fd, &stats, -1); 378 | if(result != 0) { 379 | r->_errno = result; 380 | OSUnlockMutex(file->dev->pMutex); 381 | return -1; 382 | } 383 | 384 | st->st_mode = S_IFREG; 385 | st->st_size = stats.size; 386 | st->st_blocks = (stats.size + 511) >> 9; 387 | st->st_nlink = 1; 388 | 389 | // Fill in the generic entry stats 390 | st->st_dev = stats.ent_id; 391 | st->st_uid = stats.owner_id; 392 | st->st_gid = stats.group_id; 393 | st->st_ino = stats.ent_id; 394 | st->st_atime = stats.mtime; 395 | st->st_ctime = stats.ctime; 396 | st->st_mtime = stats.mtime; 397 | OSUnlockMutex(file->dev->pMutex); 398 | return 0; 399 | } 400 | 401 | static int sd_fat_ftruncate_r (struct _reent *r, int fd, off_t len) 402 | { 403 | sd_fat_file_state_t *file = (sd_fat_file_state_t *)fd; 404 | if(!file->dev) { 405 | r->_errno = ENODEV; 406 | return -1; 407 | } 408 | 409 | OSLockMutex(file->dev->pMutex); 410 | 411 | int result = FSTruncateFile(file->dev->pClient, file->dev->pCmd, file->fd, -1); 412 | 413 | OSUnlockMutex(file->dev->pMutex); 414 | 415 | if(result < 0) { 416 | r->_errno = result; 417 | return -1; 418 | } 419 | 420 | return 0; 421 | } 422 | 423 | static int sd_fat_fsync_r (struct _reent *r, int fd) 424 | { 425 | sd_fat_file_state_t *file = (sd_fat_file_state_t *)fd; 426 | if(!file->dev) { 427 | r->_errno = ENODEV; 428 | return -1; 429 | } 430 | 431 | OSLockMutex(file->dev->pMutex); 432 | 433 | int result = FSFlushFile(file->dev->pClient, file->dev->pCmd, file->fd, -1); 434 | 435 | OSUnlockMutex(file->dev->pMutex); 436 | 437 | if(result < 0) { 438 | r->_errno = result; 439 | return -1; 440 | } 441 | 442 | return 0; 443 | } 444 | 445 | static int sd_fat_stat_r (struct _reent *r, const char *path, struct stat *st) 446 | { 447 | sd_fat_private_t *dev = sd_fat_get_device_data(path); 448 | if(!dev) { 449 | r->_errno = ENODEV; 450 | return -1; 451 | } 452 | 453 | OSLockMutex(dev->pMutex); 454 | 455 | // Zero out the stat buffer 456 | memset(st, 0, sizeof(struct stat)); 457 | 458 | char *real_path = sd_fat_real_path(path, dev); 459 | if(!real_path) { 460 | r->_errno = ENOMEM; 461 | OSUnlockMutex(dev->pMutex); 462 | return -1; 463 | } 464 | 465 | FSStat stats; 466 | 467 | int result = FSGetStat(dev->pClient, dev->pCmd, real_path, &stats, -1); 468 | 469 | free(real_path); 470 | 471 | if(result < 0) { 472 | r->_errno = result; 473 | OSUnlockMutex(dev->pMutex); 474 | return -1; 475 | } 476 | 477 | // mark root also as directory 478 | st->st_mode = ((stats.flag & 0x80000000) || (strlen(dev->mount_path) + 1 == strlen(real_path)))? S_IFDIR : S_IFREG; 479 | st->st_nlink = 1; 480 | st->st_size = stats.size; 481 | st->st_blocks = (stats.size + 511) >> 9; 482 | // Fill in the generic entry stats 483 | st->st_dev = stats.ent_id; 484 | st->st_uid = stats.owner_id; 485 | st->st_gid = stats.group_id; 486 | st->st_ino = stats.ent_id; 487 | st->st_atime = stats.mtime; 488 | st->st_ctime = stats.ctime; 489 | st->st_mtime = stats.mtime; 490 | 491 | OSUnlockMutex(dev->pMutex); 492 | 493 | return 0; 494 | } 495 | 496 | static int sd_fat_link_r (struct _reent *r, const char *existing, const char *newLink) 497 | { 498 | r->_errno = ENOTSUP; 499 | return -1; 500 | } 501 | 502 | static int sd_fat_unlink_r (struct _reent *r, const char *name) 503 | { 504 | sd_fat_private_t *dev = sd_fat_get_device_data(name); 505 | if(!dev) { 506 | r->_errno = ENODEV; 507 | return -1; 508 | } 509 | 510 | OSLockMutex(dev->pMutex); 511 | 512 | char *real_path = sd_fat_real_path(name, dev); 513 | if(!real_path) { 514 | r->_errno = ENOMEM; 515 | OSUnlockMutex(dev->pMutex); 516 | return -1; 517 | } 518 | 519 | 520 | int result = FSRemove(dev->pClient, dev->pCmd, real_path, -1); 521 | 522 | free(real_path); 523 | 524 | OSUnlockMutex(dev->pMutex); 525 | 526 | if(result < 0) { 527 | r->_errno = result; 528 | return -1; 529 | } 530 | 531 | return 0; 532 | } 533 | 534 | static int sd_fat_chdir_r (struct _reent *r, const char *name) 535 | { 536 | sd_fat_private_t *dev = sd_fat_get_device_data(name); 537 | if(!dev) { 538 | r->_errno = ENODEV; 539 | return -1; 540 | } 541 | 542 | OSLockMutex(dev->pMutex); 543 | 544 | char *real_path = sd_fat_real_path(name, dev); 545 | if(!real_path) { 546 | r->_errno = ENOMEM; 547 | OSUnlockMutex(dev->pMutex); 548 | return -1; 549 | } 550 | 551 | int result = FSChangeDir(dev->pClient, dev->pCmd, real_path, -1); 552 | 553 | free(real_path); 554 | 555 | OSUnlockMutex(dev->pMutex); 556 | 557 | if(result < 0) { 558 | r->_errno = result; 559 | return -1; 560 | } 561 | 562 | return 0; 563 | } 564 | 565 | static int sd_fat_rename_r (struct _reent *r, const char *oldName, const char *newName) 566 | { 567 | sd_fat_private_t *dev = sd_fat_get_device_data(oldName); 568 | if(!dev) { 569 | r->_errno = ENODEV; 570 | return -1; 571 | } 572 | 573 | OSLockMutex(dev->pMutex); 574 | 575 | char *real_oldpath = sd_fat_real_path(oldName, dev); 576 | if(!real_oldpath) { 577 | r->_errno = ENOMEM; 578 | OSUnlockMutex(dev->pMutex); 579 | return -1; 580 | } 581 | char *real_newpath = sd_fat_real_path(newName, dev); 582 | if(!real_newpath) { 583 | r->_errno = ENOMEM; 584 | free(real_oldpath); 585 | OSUnlockMutex(dev->pMutex); 586 | return -1; 587 | } 588 | 589 | int result = FSRename(dev->pClient, dev->pCmd, real_oldpath, real_newpath, -1); 590 | 591 | free(real_oldpath); 592 | free(real_newpath); 593 | 594 | OSUnlockMutex(dev->pMutex); 595 | 596 | if(result < 0) { 597 | r->_errno = result; 598 | return -1; 599 | } 600 | 601 | return 0; 602 | 603 | } 604 | 605 | static int sd_fat_mkdir_r (struct _reent *r, const char *path, int mode) 606 | { 607 | sd_fat_private_t *dev = sd_fat_get_device_data(path); 608 | if(!dev) { 609 | r->_errno = ENODEV; 610 | return -1; 611 | } 612 | 613 | OSLockMutex(dev->pMutex); 614 | 615 | char *real_path = sd_fat_real_path(path, dev); 616 | if(!real_path) { 617 | r->_errno = ENOMEM; 618 | OSUnlockMutex(dev->pMutex); 619 | return -1; 620 | } 621 | 622 | int result = FSMakeDir(dev->pClient, dev->pCmd, real_path, -1); 623 | 624 | free(real_path); 625 | 626 | OSUnlockMutex(dev->pMutex); 627 | 628 | if(result < 0) { 629 | r->_errno = result; 630 | return -1; 631 | } 632 | 633 | return 0; 634 | } 635 | 636 | static int sd_fat_statvfs_r (struct _reent *r, const char *path, struct statvfs *buf) 637 | { 638 | sd_fat_private_t *dev = sd_fat_get_device_data(path); 639 | if(!dev) { 640 | r->_errno = ENODEV; 641 | return -1; 642 | } 643 | 644 | OSLockMutex(dev->pMutex); 645 | 646 | // Zero out the stat buffer 647 | memset(buf, 0, sizeof(struct statvfs)); 648 | 649 | char *real_path = sd_fat_real_path(path, dev); 650 | if(!real_path) { 651 | r->_errno = ENOMEM; 652 | OSUnlockMutex(dev->pMutex); 653 | return -1; 654 | } 655 | 656 | u64 size; 657 | 658 | int result = FSGetFreeSpaceSize(dev->pClient, dev->pCmd, real_path, &size, -1); 659 | 660 | free(real_path); 661 | 662 | if(result < 0) { 663 | r->_errno = result; 664 | OSUnlockMutex(dev->pMutex); 665 | return -1; 666 | } 667 | 668 | // File system block size 669 | buf->f_bsize = 512; 670 | 671 | // Fundamental file system block size 672 | buf->f_frsize = 512; 673 | 674 | // Total number of blocks on file system in units of f_frsize 675 | buf->f_blocks = size >> 9; // this is unknown 676 | 677 | // Free blocks available for all and for non-privileged processes 678 | buf->f_bfree = buf->f_bavail = size >> 9; 679 | 680 | // Number of inodes at this point in time 681 | buf->f_files = 0xffffffff; 682 | 683 | // Free inodes available for all and for non-privileged processes 684 | buf->f_ffree = 0xffffffff; 685 | 686 | // File system id 687 | buf->f_fsid = (int)dev; 688 | 689 | // Bit mask of f_flag values. 690 | buf->f_flag = 0; 691 | 692 | // Maximum length of filenames 693 | buf->f_namemax = 255; 694 | 695 | OSUnlockMutex(dev->pMutex); 696 | 697 | return 0; 698 | } 699 | 700 | static DIR_ITER *sd_fat_diropen_r (struct _reent *r, DIR_ITER *dirState, const char *path) 701 | { 702 | sd_fat_private_t *dev = sd_fat_get_device_data(path); 703 | if(!dev) { 704 | r->_errno = ENODEV; 705 | return NULL; 706 | } 707 | 708 | sd_fat_dir_entry_t *dirIter = (sd_fat_dir_entry_t *)dirState->dirStruct; 709 | 710 | OSLockMutex(dev->pMutex); 711 | 712 | char *real_path = sd_fat_real_path(path, dev); 713 | if(!real_path) { 714 | r->_errno = ENOMEM; 715 | OSUnlockMutex(dev->pMutex); 716 | return NULL; 717 | } 718 | 719 | int dirHandle; 720 | 721 | int result = FSOpenDir(dev->pClient, dev->pCmd, real_path, &dirHandle, -1); 722 | 723 | free(real_path); 724 | 725 | OSUnlockMutex(dev->pMutex); 726 | 727 | if(result < 0) 728 | { 729 | r->_errno = result; 730 | return NULL; 731 | } 732 | 733 | dirIter->dev = dev; 734 | dirIter->dirHandle = dirHandle; 735 | 736 | return dirState; 737 | } 738 | 739 | static int sd_fat_dirclose_r (struct _reent *r, DIR_ITER *dirState) 740 | { 741 | sd_fat_dir_entry_t *dirIter = (sd_fat_dir_entry_t *)dirState->dirStruct; 742 | if(!dirIter->dev) { 743 | r->_errno = ENODEV; 744 | return -1; 745 | } 746 | 747 | OSLockMutex(dirIter->dev->pMutex); 748 | 749 | int result = FSCloseDir(dirIter->dev->pClient, dirIter->dev->pCmd, dirIter->dirHandle, -1); 750 | 751 | OSUnlockMutex(dirIter->dev->pMutex); 752 | 753 | if(result < 0) 754 | { 755 | r->_errno = result; 756 | return -1; 757 | } 758 | return 0; 759 | } 760 | 761 | static int sd_fat_dirreset_r (struct _reent *r, DIR_ITER *dirState) 762 | { 763 | sd_fat_dir_entry_t *dirIter = (sd_fat_dir_entry_t *)dirState->dirStruct; 764 | if(!dirIter->dev) { 765 | r->_errno = ENODEV; 766 | return -1; 767 | } 768 | 769 | OSLockMutex(dirIter->dev->pMutex); 770 | 771 | int result = FSRewindDir(dirIter->dev->pClient, dirIter->dev->pCmd, dirIter->dirHandle, -1); 772 | 773 | OSUnlockMutex(dirIter->dev->pMutex); 774 | 775 | if(result < 0) 776 | { 777 | r->_errno = result; 778 | return -1; 779 | } 780 | return 0; 781 | } 782 | 783 | static int sd_fat_dirnext_r (struct _reent *r, DIR_ITER *dirState, char *filename, struct stat *st) 784 | { 785 | sd_fat_dir_entry_t *dirIter = (sd_fat_dir_entry_t *)dirState->dirStruct; 786 | if(!dirIter->dev) { 787 | r->_errno = ENODEV; 788 | return -1; 789 | } 790 | 791 | OSLockMutex(dirIter->dev->pMutex); 792 | 793 | FSDirEntry * dir_entry = malloc(sizeof(FSDirEntry)); 794 | 795 | int result = FSReadDir(dirIter->dev->pClient, dirIter->dev->pCmd, dirIter->dirHandle, dir_entry, -1); 796 | if(result < 0) 797 | { 798 | free(dir_entry); 799 | r->_errno = result; 800 | OSUnlockMutex(dirIter->dev->pMutex); 801 | return -1; 802 | } 803 | 804 | // Fetch the current entry 805 | strcpy(filename, dir_entry->name); 806 | 807 | if(st) 808 | { 809 | memset(st, 0, sizeof(struct stat)); 810 | st->st_mode = (dir_entry->stat.flag & 0x80000000) ? S_IFDIR : S_IFREG; 811 | st->st_nlink = 1; 812 | st->st_size = dir_entry->stat.size; 813 | st->st_blocks = (dir_entry->stat.size + 511) >> 9; 814 | st->st_dev = dir_entry->stat.ent_id; 815 | st->st_uid = dir_entry->stat.owner_id; 816 | st->st_gid = dir_entry->stat.group_id; 817 | st->st_ino = dir_entry->stat.ent_id; 818 | st->st_atime = dir_entry->stat.mtime; 819 | st->st_ctime = dir_entry->stat.ctime; 820 | st->st_mtime = dir_entry->stat.mtime; 821 | } 822 | 823 | free(dir_entry); 824 | OSUnlockMutex(dirIter->dev->pMutex); 825 | return 0; 826 | } 827 | 828 | // NTFS device driver devoptab 829 | static const devoptab_t devops_sd_fat = { 830 | NULL, /* Device name */ 831 | sizeof (sd_fat_file_state_t), 832 | sd_fat_open_r, 833 | sd_fat_close_r, 834 | sd_fat_write_r, 835 | sd_fat_read_r, 836 | sd_fat_seek_r, 837 | sd_fat_fstat_r, 838 | sd_fat_stat_r, 839 | sd_fat_link_r, 840 | sd_fat_unlink_r, 841 | sd_fat_chdir_r, 842 | sd_fat_rename_r, 843 | sd_fat_mkdir_r, 844 | sizeof (sd_fat_dir_entry_t), 845 | sd_fat_diropen_r, 846 | sd_fat_dirreset_r, 847 | sd_fat_dirnext_r, 848 | sd_fat_dirclose_r, 849 | sd_fat_statvfs_r, 850 | sd_fat_ftruncate_r, 851 | sd_fat_fsync_r, 852 | NULL, /* sd_fat_chmod_r */ 853 | NULL, /* sd_fat_fchmod_r */ 854 | NULL /* Device data */ 855 | }; 856 | 857 | static int sd_fat_add_device (const char *name, const char *mount_path, void *pClient, void *pCmd) 858 | { 859 | devoptab_t *dev = NULL; 860 | char *devname = NULL; 861 | char *devpath = NULL; 862 | int i; 863 | 864 | // Sanity check 865 | if (!name) { 866 | errno = EINVAL; 867 | return -1; 868 | } 869 | 870 | // Allocate a devoptab for this device 871 | dev = (devoptab_t *) malloc(sizeof(devoptab_t) + strlen(name) + 1); 872 | if (!dev) { 873 | errno = ENOMEM; 874 | return -1; 875 | } 876 | 877 | // Use the space allocated at the end of the devoptab for storing the device name 878 | devname = (char*)(dev + 1); 879 | strcpy(devname, name); 880 | 881 | // create private data 882 | sd_fat_private_t *priv = (sd_fat_private_t *)malloc(sizeof(sd_fat_private_t) + strlen(mount_path) + 1); 883 | if(!priv) { 884 | free(dev); 885 | errno = ENOMEM; 886 | return -1; 887 | } 888 | 889 | devpath = (char*)(priv+1); 890 | strcpy(devpath, mount_path); 891 | 892 | // setup private data 893 | priv->mount_path = devpath; 894 | priv->pClient = pClient; 895 | priv->pCmd = pCmd; 896 | priv->pMutex = malloc(OS_MUTEX_SIZE); 897 | 898 | if(!priv->pMutex) { 899 | free(dev); 900 | free(priv); 901 | errno = ENOMEM; 902 | return -1; 903 | } 904 | 905 | OSInitMutex(priv->pMutex); 906 | 907 | // Setup the devoptab 908 | memcpy(dev, &devops_sd_fat, sizeof(devoptab_t)); 909 | dev->name = devname; 910 | dev->deviceData = priv; 911 | 912 | // Add the device to the devoptab table (if there is a free slot) 913 | for (i = 3; i < STD_MAX; i++) { 914 | if (devoptab_list[i] == devoptab_list[0]) { 915 | devoptab_list[i] = dev; 916 | return 0; 917 | } 918 | } 919 | 920 | // failure, free all memory 921 | free(priv); 922 | free(dev); 923 | 924 | // If we reach here then there are no free slots in the devoptab table for this device 925 | errno = EADDRNOTAVAIL; 926 | return -1; 927 | } 928 | 929 | static int sd_fat_remove_device (const char *path, void **pClient, void **pCmd, char **mountPath) 930 | { 931 | const devoptab_t *devoptab = NULL; 932 | char name[128] = {0}; 933 | int i; 934 | 935 | // Get the device name from the path 936 | strncpy(name, path, 127); 937 | strtok(name, ":/"); 938 | 939 | // Find and remove the specified device from the devoptab table 940 | // NOTE: We do this manually due to a 'bug' in RemoveDevice 941 | // which ignores names with suffixes and causes names 942 | // like "ntfs" and "ntfs1" to be seen as equals 943 | for (i = 3; i < STD_MAX; i++) { 944 | devoptab = devoptab_list[i]; 945 | if (devoptab && devoptab->name) { 946 | if (strcmp(name, devoptab->name) == 0) { 947 | devoptab_list[i] = devoptab_list[0]; 948 | 949 | if(devoptab->deviceData) 950 | { 951 | sd_fat_private_t *priv = (sd_fat_private_t *)devoptab->deviceData; 952 | *pClient = priv->pClient; 953 | *pCmd = priv->pCmd; 954 | *mountPath = (char*) malloc(strlen(priv->mount_path)+1); 955 | if(*mountPath) 956 | strcpy(*mountPath, priv->mount_path); 957 | if(priv->pMutex) 958 | free(priv->pMutex); 959 | free(devoptab->deviceData); 960 | } 961 | 962 | free((devoptab_t*)devoptab); 963 | return 0; 964 | } 965 | } 966 | } 967 | 968 | return -1; 969 | } 970 | 971 | int mount_sd_fat(const char *path) 972 | { 973 | int result = -1; 974 | 975 | // get command and client 976 | void* pClient = malloc(FS_CLIENT_SIZE); 977 | void* pCmd = malloc(FS_CMD_BLOCK_SIZE); 978 | 979 | if(!pClient || !pCmd) { 980 | // just in case free if not 0 981 | if(pClient) 982 | free(pClient); 983 | if(pCmd) 984 | free(pCmd); 985 | return -2; 986 | } 987 | 988 | FSInit(); 989 | FSInitCmdBlock(pCmd); 990 | FSAddClientEx(pClient, 0, -1); 991 | 992 | char *mountPath = NULL; 993 | 994 | if(MountFS(pClient, pCmd, &mountPath) == 0) { 995 | result = sd_fat_add_device(path, mountPath, pClient, pCmd); 996 | free(mountPath); 997 | } 998 | 999 | return result; 1000 | } 1001 | 1002 | int unmount_sd_fat(const char *path) 1003 | { 1004 | void *pClient = 0; 1005 | void *pCmd = 0; 1006 | char *mountPath = 0; 1007 | 1008 | int result = sd_fat_remove_device(path, &pClient, &pCmd, &mountPath); 1009 | if(result == 0) 1010 | { 1011 | UmountFS(pClient, pCmd, mountPath); 1012 | FSDelClient(pClient); 1013 | free(pClient); 1014 | free(pCmd); 1015 | free(mountPath); 1016 | //FSShutdown(); 1017 | } 1018 | return result; 1019 | } 1020 | -------------------------------------------------------------------------------- /src/fs/sd_fat_devoptab.h: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright (C) 2015 3 | * by Dimok 4 | * 5 | * This software is provided 'as-is', without any express or implied 6 | * warranty. In no event will the authors be held liable for any 7 | * damages arising from the use of this software. 8 | * 9 | * Permission is granted to anyone to use this software for any 10 | * purpose, including commercial applications, and to alter it and 11 | * redistribute it freely, subject to the following restrictions: 12 | * 13 | * 1. The origin of this software must not be misrepresented; you 14 | * must not claim that you wrote the original software. If you use 15 | * this software in a product, an acknowledgment in the product 16 | * documentation would be appreciated but is not required. 17 | * 18 | * 2. Altered source versions must be plainly marked as such, and 19 | * must not be misrepresented as being the original software. 20 | * 21 | * 3. This notice may not be removed or altered from any source 22 | * distribution. 23 | ***************************************************************************/ 24 | #ifndef __SD_FAT_DEVOPTAB_H_ 25 | #define __SD_FAT_DEVOPTAB_H_ 26 | 27 | #ifdef __cplusplus 28 | extern "C" { 29 | #endif 30 | 31 | int mount_sd_fat(const char *path); 32 | int unmount_sd_fat(const char *path); 33 | 34 | #ifdef __cplusplus 35 | } 36 | #endif 37 | 38 | #endif // __SD_FAT_DEVOPTAB_H_ 39 | -------------------------------------------------------------------------------- /src/link.ld: -------------------------------------------------------------------------------- 1 | OUTPUT(vwii-nand-restorer.elf); 2 | 3 | /* Tell linker where our application entry is so the garbage collect can work correct */ 4 | ENTRY(__entry_menu); 5 | 6 | SECTIONS { 7 | . = 0x00802000; 8 | .text : { 9 | *(.text*); 10 | } 11 | .rodata : { 12 | *(.rodata*); 13 | } 14 | .data : { 15 | *(.data*); 16 | 17 | __sdata_start = .; 18 | *(.sdata*); 19 | __sdata_end = .; 20 | 21 | __sdata2_start = .; 22 | *(.sdata2*); 23 | __sdata2_end = .; 24 | } 25 | .bss : { 26 | __bss_start = .; 27 | *(.bss*); 28 | *(.sbss*); 29 | *(COMMON); 30 | __bss_end = .; 31 | } 32 | __CODE_END = .; 33 | 34 | /DISCARD/ : { 35 | *(*); 36 | } 37 | } 38 | 39 | /******************************************************** FS ********************************************************/ 40 | /* coreinit.rpl difference in addresses 0xFE3C00 */ 41 | -------------------------------------------------------------------------------- /src/main.c: -------------------------------------------------------------------------------- 1 | #include "main.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "dynamic_libs/vpad_functions.h" 7 | #include "dynamic_libs/sys_functions.h" 8 | #include "dynamic_libs/fs_functions.h" 9 | #include "dynamic_libs/socket_functions.h" 10 | #include "fs/sd_fat_devoptab.h" 11 | #include "menu_options.h" 12 | #include 13 | #include 14 | #include "utils/fsutils.h" 15 | 16 | #define MAX_CONSOLE_LINES_TV 27 17 | #define MAX_CONSOLE_LINES_DRC 18 18 | 19 | static char* consoleArrayTv[MAX_CONSOLE_LINES_TV]; 20 | static char* consoleArrayDrc[MAX_CONSOLE_LINES_DRC]; 21 | 22 | static void console_print_pos(int x, int y, const char *format, ...) 23 | { 24 | char* tmp = NULL; 25 | 26 | va_list va; 27 | va_start(va, format); 28 | if((vasprintf(&tmp, format, va) >= 0) && tmp) 29 | { 30 | if(strlen(tmp) > 79) 31 | tmp[79] = 0; 32 | 33 | OSScreenPutFontEx(0, x, y, tmp); 34 | OSScreenPutFontEx(1, x, y, tmp); 35 | 36 | } 37 | va_end(va); 38 | 39 | if(tmp) 40 | free(tmp); 41 | } 42 | 43 | uint8_t enableLogToFile = 0; 44 | 45 | void console_printf(int newline, const char *format, ...) 46 | { 47 | char* tmp = NULL; 48 | 49 | va_list va; 50 | va_start(va, format); 51 | if((vasprintf(&tmp, format, va) >= 0) && tmp) 52 | { 53 | if(newline) 54 | { 55 | if(consoleArrayTv[0]) 56 | free(consoleArrayTv[0]); 57 | if(consoleArrayDrc[0]) 58 | free(consoleArrayDrc[0]); 59 | 60 | for(int i = 1; i < MAX_CONSOLE_LINES_TV; i++) 61 | consoleArrayTv[i-1] = consoleArrayTv[i]; 62 | 63 | for(int i = 1; i < MAX_CONSOLE_LINES_DRC; i++) 64 | consoleArrayDrc[i-1] = consoleArrayDrc[i]; 65 | } 66 | else 67 | { 68 | if(consoleArrayTv[MAX_CONSOLE_LINES_TV-1]) 69 | free(consoleArrayTv[MAX_CONSOLE_LINES_TV-1]); 70 | if(consoleArrayDrc[MAX_CONSOLE_LINES_DRC-1]) 71 | free(consoleArrayDrc[MAX_CONSOLE_LINES_DRC-1]); 72 | 73 | consoleArrayTv[MAX_CONSOLE_LINES_TV-1] = NULL; 74 | consoleArrayDrc[MAX_CONSOLE_LINES_DRC-1] = NULL; 75 | } 76 | 77 | if(strlen(tmp) > 79) 78 | tmp[79] = 0; 79 | 80 | consoleArrayTv[MAX_CONSOLE_LINES_TV-1] = (char*)malloc(strlen(tmp) + 1); 81 | if(consoleArrayTv[MAX_CONSOLE_LINES_TV-1]) 82 | strcpy(consoleArrayTv[MAX_CONSOLE_LINES_TV-1], tmp); 83 | 84 | consoleArrayDrc[MAX_CONSOLE_LINES_DRC-1] = (tmp); 85 | 86 | if (enableLogToFile) 87 | { 88 | FILE* logfile = fopen(LOG_PATH, "a"); 89 | if (logfile != NULL) 90 | { 91 | fprintf(logfile, "%s\n", tmp); 92 | fclose(logfile); 93 | } 94 | } 95 | 96 | } 97 | va_end(va); 98 | 99 | // Clear screens 100 | OSScreenClearBufferEx(0, 0); 101 | OSScreenClearBufferEx(1, 0); 102 | 103 | 104 | for(int i = 0; i < MAX_CONSOLE_LINES_TV; i++) 105 | { 106 | if(consoleArrayTv[i]) 107 | OSScreenPutFontEx(0, 0, i, consoleArrayTv[i]); 108 | } 109 | 110 | for(int i = 0; i < MAX_CONSOLE_LINES_DRC; i++) 111 | { 112 | if(consoleArrayDrc[i]) 113 | OSScreenPutFontEx(1, 0, i, consoleArrayDrc[i]); 114 | } 115 | 116 | OSScreenFlipBuffersEx(0); 117 | OSScreenFlipBuffersEx(1); 118 | } 119 | 120 | //just to be able to call async 121 | void someFunc(void *arg) 122 | { 123 | (void)arg; 124 | } 125 | 126 | static int mcp_hook_fd = -1; 127 | int MCPHookOpen() 128 | { 129 | //take over mcp thread 130 | mcp_hook_fd = MCP_Open(); 131 | if(mcp_hook_fd < 0) 132 | return -1; 133 | IOS_IoctlAsync(mcp_hook_fd, 0x62, (void*)0, 0, (void*)0, 0, someFunc, (void*)0); 134 | //let wupserver start up 135 | sleep(1); 136 | if(IOSUHAX_Open("/dev/mcp") < 0) 137 | return -1; 138 | return 0; 139 | } 140 | 141 | void MCPHookClose() 142 | { 143 | if(mcp_hook_fd < 0) 144 | return; 145 | //close down wupserver, return control to mcp 146 | IOSUHAX_Close(); 147 | //wait for mcp to return 148 | sleep(1); 149 | MCP_Close(mcp_hook_fd); 150 | mcp_hook_fd = -1; 151 | } 152 | 153 | int Menu_Main(void) 154 | { 155 | InitOSFunctionPointers(); 156 | InitSocketFunctionPointers(); 157 | InitFSFunctionPointers(); 158 | InitVPadFunctionPointers(); 159 | 160 | VPADInit(); 161 | 162 | for(int i = 0; i < MAX_CONSOLE_LINES_TV; i++) 163 | consoleArrayTv[i] = NULL; 164 | 165 | for(int i = 0; i < MAX_CONSOLE_LINES_DRC; i++) 166 | consoleArrayDrc[i] = NULL; 167 | 168 | // Prepare screen 169 | int screen_buf0_size = 0; 170 | 171 | // Init screen and screen buffers 172 | OSScreenInit(); 173 | screen_buf0_size = OSScreenGetBufferSizeEx(0); 174 | OSScreenSetBufferEx(0, (void *)0xF4000000); 175 | OSScreenSetBufferEx(1, (void *)(0xF4000000 + screen_buf0_size)); 176 | 177 | OSScreenEnableEx(0, 1); 178 | OSScreenEnableEx(1, 1); 179 | 180 | // Clear screens 181 | OSScreenClearBufferEx(0, 0); 182 | OSScreenClearBufferEx(1, 0); 183 | 184 | // Flip buffers 185 | OSScreenFlipBuffersEx(0); 186 | OSScreenFlipBuffersEx(1); 187 | 188 | int mountsdres = mount_sd_fat("sd"); 189 | if (mountsdres < 0) 190 | { 191 | console_printf(1, "Error mounting sd: %i\n", mountsdres); 192 | sleep(2); 193 | return 0; 194 | } 195 | 196 | if (fileExists(LOG_PATH)) 197 | { 198 | remove(LOG_PATH); 199 | } 200 | 201 | enableLogToFile = 1; 202 | 203 | int res = IOSUHAX_Open(NULL); 204 | if (res < 0) 205 | res = MCPHookOpen(); 206 | if(res < 0) 207 | { 208 | console_printf(1, "IOSUHAX_open failed: %i\n", res); 209 | console_printf(1, "Did you forget to run CFW?\n"); 210 | sleep(4); 211 | return 0; 212 | } 213 | 214 | int fsaFd = IOSUHAX_FSA_Open(); 215 | if(fsaFd < 0) 216 | { 217 | console_printf(1, "IOSUHAX_FSA_Open failed: %i\n", fsaFd); 218 | sleep(2); 219 | return 0; 220 | } 221 | 222 | int mountres = mount_fs("dev", fsaFd, SLCCMPT_DEV_PATH, SLCCMPT_MOUNT_PATH); 223 | if(mountres < 0) 224 | { 225 | console_printf(1, "%i Mount of %s to %s failed", mountres, SLCCMPT_DEV_PATH, SLCCMPT_MOUNT_PATH); 226 | sleep(5); 227 | return 0; 228 | } 229 | 230 | int vpadError = -1; 231 | VPADData vpad; 232 | 233 | int initScreen = 1; 234 | 235 | static const char* default_menu_options[] = 236 | { 237 | "Restore NAND", 238 | }; 239 | 240 | static const char* additional_menu_options[] = 241 | { 242 | "Extract NAND", 243 | "Clear SLCCMPT", 244 | "Copy extracted NAND to SLCCMPT", 245 | "Fix modes", 246 | }; 247 | 248 | int selectedItem = 0; 249 | 250 | while (1) 251 | { 252 | VPADRead(0, &vpad, 1, &vpadError); 253 | 254 | if (initScreen) 255 | { 256 | initScreen = 0; 257 | 258 | //! free memory 259 | for(int i = 0; i < MAX_CONSOLE_LINES_TV; i++) 260 | { 261 | if(consoleArrayTv[i]) 262 | free(consoleArrayTv[i]); 263 | consoleArrayTv[i] = 0; 264 | } 265 | 266 | for(int i = 0; i < MAX_CONSOLE_LINES_DRC; i++) 267 | { 268 | if(consoleArrayDrc[i]) 269 | free(consoleArrayDrc[i]); 270 | consoleArrayDrc[i] = 0; 271 | } 272 | 273 | // Clear screens 274 | OSScreenClearBufferEx(0, 0); 275 | OSScreenClearBufferEx(1, 0); 276 | 277 | console_print_pos(0, 0, "vWii NAND Restorer v2 by GaryOderNichts"); 278 | 279 | console_print_pos(0, 2, "Place your vWii NAND Backup to %s", NAND_FILE_PATH); 280 | 281 | uint32_t defi; 282 | for (defi = 0; defi < (sizeof(default_menu_options) / 4); defi++) 283 | { 284 | if(selectedItem == (int)defi) 285 | { 286 | console_print_pos(0, 4 + defi, "--> %s", default_menu_options[defi]); 287 | } 288 | else 289 | { 290 | console_print_pos(0, 4 + defi, " %s", default_menu_options[defi]); 291 | } 292 | } 293 | 294 | uint32_t addstart = 4 + defi + 1; 295 | console_print_pos(0, addstart, "Additional Options:"); 296 | 297 | uint32_t addi; 298 | for (addi = 0; addi < (sizeof(additional_menu_options) / 4); addi++) 299 | { 300 | if(selectedItem == (int) (defi + addi)) 301 | { 302 | console_print_pos(0, addstart + 2 + addi, "--> %s", additional_menu_options[addi]); 303 | } 304 | else 305 | { 306 | console_print_pos(0, addstart + 2 + addi, " %s", additional_menu_options[addi]); 307 | } 308 | } 309 | 310 | if(selectedItem == (int) (defi + addi)) 311 | { 312 | console_print_pos(0, addstart + addi + 3, "--> Exit"); 313 | } 314 | else 315 | { 316 | console_print_pos(0, addstart + addi + 3, " Exit"); 317 | } 318 | 319 | OSScreenFlipBuffersEx(0); 320 | OSScreenFlipBuffersEx(1); 321 | } 322 | 323 | if(vpadError == 0 && vpad.btns_d & VPAD_BUTTON_DOWN) 324 | { 325 | selectedItem = (selectedItem + 1) % ((sizeof(default_menu_options) / 4) + ((sizeof(additional_menu_options) / 4) + 1)); 326 | initScreen = 1; 327 | } 328 | 329 | if(vpadError == 0 && vpad.btns_d & VPAD_BUTTON_UP) 330 | { 331 | selectedItem--; 332 | if(selectedItem < 0) 333 | selectedItem = ((sizeof(default_menu_options) / 4) + ((sizeof(additional_menu_options) / 4) + 1)) - 1; 334 | initScreen = 1; 335 | } 336 | 337 | if(vpadError == 0 && vpad.btns_d & VPAD_BUTTON_A) 338 | { 339 | switch (selectedItem) 340 | { 341 | case 0: // Restore nand 342 | if (OPTION_restoreNand(fsaFd)) 343 | sleep(2); 344 | else 345 | sleep(6); 346 | break; 347 | case 1: // Extract nand 348 | if (OPTION_extractNand()) 349 | sleep(2); 350 | else 351 | sleep(6); 352 | break; 353 | case 2: // Clear SLCCMPT 354 | if (OPTION_clearSlccmpt()) 355 | sleep(2); 356 | else 357 | sleep(6); 358 | break; 359 | case 3: // Copy extracted NAND to SLCCMPT 360 | if (OPTION_copyNAND()) 361 | sleep(2); 362 | else 363 | sleep(6); 364 | break; 365 | case 4: // Fix modes 366 | if (OPTION_fixModes(fsaFd)) 367 | sleep(2); 368 | else 369 | sleep(6); 370 | break; 371 | case 5: // exit 372 | goto exit; 373 | default: 374 | break; 375 | } 376 | initScreen = 1; 377 | } 378 | 379 | if(vpadError == 0 && ((vpad.btns_d | vpad.btns_h) & VPAD_BUTTON_HOME)) 380 | { 381 | break; 382 | } 383 | 384 | usleep(20000); 385 | } 386 | exit: 387 | 388 | console_printf(1, "Exiting..."); 389 | 390 | for(int i = 0; i < MAX_CONSOLE_LINES_TV; i++) 391 | { 392 | if(consoleArrayTv[i]) 393 | free(consoleArrayTv[i]); 394 | } 395 | 396 | for(int i = 0; i < MAX_CONSOLE_LINES_DRC; i++) 397 | { 398 | if(consoleArrayDrc[i]) 399 | free(consoleArrayDrc[i]); 400 | } 401 | 402 | unmount_fs("dev"); 403 | 404 | unmount_sd_fat("sd"); 405 | 406 | IOSUHAX_FSA_Close(fsaFd); 407 | 408 | if(mcp_hook_fd >= 0) 409 | MCPHookClose(); 410 | else 411 | IOSUHAX_Close(); 412 | 413 | sleep(1); 414 | 415 | return 0; 416 | } 417 | 418 | -------------------------------------------------------------------------------- /src/main.h: -------------------------------------------------------------------------------- 1 | #ifndef _MAIN_H_ 2 | #define _MAIN_H_ 3 | 4 | #include "common/types.h" 5 | #include "common/common.h" 6 | #include "dynamic_libs/os_functions.h" 7 | 8 | #define NAND_FILE_PATH "sd:/vwiinandrestorer/slccmpt.bin" 9 | #define EXTRACTED_NAND_PATH "sd:/vwiinandrestorer/extracted" 10 | #define LOG_PATH "sd:/vwiinandrestorer/latest.log" 11 | 12 | #define SLCCMPT_DEV_PATH "/dev/slccmpt01" 13 | #define SLCCMPT_MOUNT_PATH "/vol/storage_slccmpt01" 14 | 15 | #define SLCCMPT_MODE 0x666 16 | 17 | /* Main */ 18 | #ifdef __cplusplus 19 | extern "C" { 20 | #endif 21 | 22 | int Menu_Main(void); 23 | void console_printf(int newline, const char *format, ...); 24 | 25 | #ifdef __cplusplus 26 | } 27 | #endif 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /src/menu_options.c: -------------------------------------------------------------------------------- 1 | #include "menu_options.h" 2 | #include "extractor.h" 3 | #include "utils/fsutils.h" 4 | #include "main.h" 5 | 6 | uint8_t OPTION_restoreNand(int fsaFd) 7 | { 8 | console_printf(1, "Restoring NAND..."); 9 | sleep(1); 10 | 11 | if (!initNand(NAND_FILE_PATH)) 12 | { 13 | console_printf(1, "Error initializing NAND!"); 14 | return 0; 15 | } 16 | console_printf(1, "Nand initialized successful"); 17 | 18 | if (!OPTION_clearSlccmpt()) 19 | { 20 | console_printf(1, "Error clearing SLCCMPT!"); 21 | return 0; 22 | } 23 | 24 | console_printf(1, "Extracting NAND to SLCCMPT"); 25 | 26 | extractNand("dev:"); 27 | cleanup(); 28 | 29 | if (OPTION_fixModes(fsaFd)) 30 | return 1; 31 | 32 | console_printf(1, "Error fixing modes!"); 33 | return 0; 34 | } 35 | 36 | uint8_t OPTION_extractNand(void) 37 | { 38 | console_printf(1, "Extracting NAND to %s", EXTRACTED_NAND_PATH); 39 | sleep(1); 40 | if (initNand(NAND_FILE_PATH)) 41 | { 42 | console_printf(1, "Nand initialized successful"); 43 | if (dirExists(EXTRACTED_NAND_PATH)) 44 | if (!removeRecursive(EXTRACTED_NAND_PATH)) 45 | return 0; 46 | 47 | extractNand(EXTRACTED_NAND_PATH); 48 | cleanup(); 49 | return 1; 50 | } 51 | console_printf(1, "Error extracting NAND!\n"); 52 | return 0; 53 | } 54 | 55 | uint8_t OPTION_clearSlccmpt() 56 | { 57 | console_printf(1, "Clearing SLCCMPT..."); 58 | sleep(1); 59 | 60 | return removeRecursive("dev:"); 61 | } 62 | 63 | uint8_t OPTION_fixModes(int fsaFd) 64 | { 65 | console_printf(1, "Setting correct modes..."); 66 | sleep(1); 67 | 68 | return chmodRecursive(fsaFd, "dev:", SLCCMPT_MODE); 69 | } 70 | 71 | uint8_t OPTION_copyNAND() 72 | { 73 | console_printf(1, "Copying NAND to SLCCMPT..."); 74 | sleep(1); 75 | 76 | return copyDir(EXTRACTED_NAND_PATH, "dev:"); 77 | } -------------------------------------------------------------------------------- /src/menu_options.h: -------------------------------------------------------------------------------- 1 | #ifndef _MENU_OPTIONS_H_ 2 | #define _MENU_OPTIONS_H_ 3 | 4 | #include 5 | 6 | uint8_t OPTION_restoreNand(int fsaFd); 7 | uint8_t OPTION_extractNand(void); 8 | uint8_t OPTION_clearSlccmpt(); 9 | uint8_t OPTION_fixModes(int fsaFd); 10 | uint8_t OPTION_copyNAND(); 11 | 12 | #endif -------------------------------------------------------------------------------- /src/system/memory.c: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | * Copyright (C) 2015 Dimok 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | ****************************************************************************/ 17 | #include 18 | #include 19 | #include "dynamic_libs/os_functions.h" 20 | #include "common/common.h" 21 | #include "memory.h" 22 | 23 | #define MEMORY_ARENA_1 0 24 | #define MEMORY_ARENA_2 1 25 | #define MEMORY_ARENA_3 2 26 | #define MEMORY_ARENA_4 3 27 | #define MEMORY_ARENA_5 4 28 | #define MEMORY_ARENA_6 5 29 | #define MEMORY_ARENA_7 6 30 | #define MEMORY_ARENA_8 7 31 | #define MEMORY_ARENA_FG_BUCKET 8 32 | 33 | //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 34 | //! Memory functions 35 | //! This is the only place where those are needed so lets keep them more or less private 36 | //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 37 | extern unsigned int * pMEMAllocFromDefaultHeapEx; 38 | extern unsigned int * pMEMAllocFromDefaultHeap; 39 | extern unsigned int * pMEMFreeToDefaultHeap; 40 | 41 | extern int (* MEMGetBaseHeapHandle)(int mem_arena); 42 | extern unsigned int (* MEMGetAllocatableSizeForFrmHeapEx)(int heap, int align); 43 | extern void *(* MEMAllocFromFrmHeapEx)(int heap, unsigned int size, int align); 44 | extern void (* MEMFreeToFrmHeap)(int heap, int mode); 45 | extern void *(* MEMAllocFromExpHeapEx)(int heap, unsigned int size, int align); 46 | extern int (* MEMCreateExpHeapEx)(void* address, unsigned int size, unsigned short flags); 47 | extern void *(* MEMDestroyExpHeap)(int heap); 48 | extern void (* MEMFreeToExpHeap)(int heap, void* ptr); 49 | 50 | static int mem1_heap = -1; 51 | static int bucket_heap = -1; 52 | 53 | void memory_init(void) 54 | { 55 | int mem1_heap_handle = MEMGetBaseHeapHandle(MEMORY_ARENA_1); 56 | unsigned int mem1_allocatable_size = MEMGetAllocatableSizeForFrmHeapEx(mem1_heap_handle, 4); 57 | void *mem1_memory = MEMAllocFromFrmHeapEx(mem1_heap_handle, mem1_allocatable_size, 4); 58 | if(mem1_memory) 59 | mem1_heap = MEMCreateExpHeapEx(mem1_memory, mem1_allocatable_size, 0); 60 | 61 | int bucket_heap_handle = MEMGetBaseHeapHandle(MEMORY_ARENA_FG_BUCKET); 62 | unsigned int bucket_allocatable_size = MEMGetAllocatableSizeForFrmHeapEx(bucket_heap_handle, 4); 63 | void *bucket_memory = MEMAllocFromFrmHeapEx(bucket_heap_handle, bucket_allocatable_size, 4); 64 | if(bucket_memory) 65 | bucket_heap = MEMCreateExpHeapEx(bucket_memory, bucket_allocatable_size, 0); 66 | } 67 | 68 | void memory_end(void) 69 | { 70 | MEMDestroyExpHeap(mem1_heap); 71 | MEMFreeToFrmHeap(MEMGetBaseHeapHandle(MEMORY_ARENA_1), 3); 72 | mem1_heap = -1; 73 | 74 | MEMDestroyExpHeap(bucket_heap); 75 | MEMFreeToFrmHeap(MEMGetBaseHeapHandle(MEMORY_ARENA_FG_BUCKET), 3); 76 | bucket_heap = -1; 77 | } 78 | 79 | //!------------------------------------------------------------------------------------------- 80 | //! wraps 81 | //!------------------------------------------------------------------------------------------- 82 | void *__wrap_malloc(size_t size) 83 | { 84 | // pointer to a function resolve 85 | return ((void * (*)(size_t))(*pMEMAllocFromDefaultHeap))(size); 86 | } 87 | 88 | void *__wrap_memalign(size_t align, size_t size) 89 | { 90 | if (align < 4) 91 | align = 4; 92 | 93 | // pointer to a function resolve 94 | return ((void * (*)(size_t, size_t))(*pMEMAllocFromDefaultHeapEx))(size, align); 95 | } 96 | 97 | void __wrap_free(void *p) 98 | { 99 | // pointer to a function resolve 100 | if(p != 0) 101 | ((void (*)(void *))(*pMEMFreeToDefaultHeap))(p); 102 | } 103 | 104 | void *__wrap_calloc(size_t n, size_t size) 105 | { 106 | void *p = __wrap_malloc(n * size); 107 | if (p != 0) { 108 | memset(p, 0, n * size); 109 | } 110 | return p; 111 | } 112 | 113 | size_t __wrap_malloc_usable_size(void *p) 114 | { 115 | //! TODO: this is totally wrong and needs to be addressed 116 | return 0x7FFFFFFF; 117 | } 118 | 119 | void *__wrap_realloc(void *p, size_t size) 120 | { 121 | void *new_ptr = __wrap_malloc(size); 122 | if (new_ptr != 0) 123 | { 124 | memcpy(new_ptr, p, __wrap_malloc_usable_size(p) < size ? __wrap_malloc_usable_size(p) : size); 125 | __wrap_free(p); 126 | } 127 | return new_ptr; 128 | } 129 | 130 | //!------------------------------------------------------------------------------------------- 131 | //! reent versions 132 | //!------------------------------------------------------------------------------------------- 133 | void *__wrap__malloc_r(struct _reent *r, size_t size) 134 | { 135 | return __wrap_malloc(size); 136 | } 137 | 138 | void *__wrap__calloc_r(struct _reent *r, size_t n, size_t size) 139 | { 140 | return __wrap_calloc(n, size); 141 | } 142 | 143 | void *__wrap__memalign_r(struct _reent *r, size_t align, size_t size) 144 | { 145 | return __wrap_memalign(align, size); 146 | } 147 | 148 | void __wrap__free_r(struct _reent *r, void *p) 149 | { 150 | __wrap_free(p); 151 | } 152 | 153 | size_t __wrap__malloc_usable_size_r(struct _reent *r, void *p) 154 | { 155 | return __wrap_malloc_usable_size(p); 156 | } 157 | 158 | void *__wrap__realloc_r(struct _reent *r, void *p, size_t size) 159 | { 160 | return __wrap_realloc(p, size); 161 | } 162 | 163 | //!------------------------------------------------------------------------------------------- 164 | //! some wrappers 165 | //!------------------------------------------------------------------------------------------- 166 | void * MEM2_alloc(unsigned int size, unsigned int align) 167 | { 168 | return __wrap_memalign(align, size); 169 | } 170 | 171 | void MEM2_free(void *ptr) 172 | { 173 | __wrap_free(ptr); 174 | } 175 | 176 | void * MEM1_alloc(unsigned int size, unsigned int align) 177 | { 178 | if (align < 4) 179 | align = 4; 180 | return MEMAllocFromExpHeapEx(mem1_heap, size, align); 181 | } 182 | 183 | void MEM1_free(void *ptr) 184 | { 185 | MEMFreeToExpHeap(mem1_heap, ptr); 186 | } 187 | 188 | void * MEMBucket_alloc(unsigned int size, unsigned int align) 189 | { 190 | if (align < 4) 191 | align = 4; 192 | return MEMAllocFromExpHeapEx(bucket_heap, size, align); 193 | } 194 | 195 | void MEMBucket_free(void *ptr) 196 | { 197 | MEMFreeToExpHeap(bucket_heap, ptr); 198 | } 199 | -------------------------------------------------------------------------------- /src/system/memory.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | * Copyright (C) 2015 Dimok 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | ****************************************************************************/ 17 | #ifndef __MEMORY_H_ 18 | #define __MEMORY_H_ 19 | 20 | #ifdef __cplusplus 21 | extern "C" { 22 | #endif 23 | 24 | #include 25 | 26 | void memory_init(void); 27 | void memory_end(void); 28 | 29 | void * MEM2_alloc(unsigned int size, unsigned int align); 30 | void MEM2_free(void *ptr); 31 | 32 | void * MEM1_alloc(unsigned int size, unsigned int align); 33 | void MEM1_free(void *ptr); 34 | 35 | void * MEMBucket_alloc(unsigned int size, unsigned int align); 36 | void MEMBucket_free(void *ptr); 37 | 38 | #ifdef __cplusplus 39 | } 40 | #endif 41 | 42 | #endif // __MEMORY_H_ 43 | -------------------------------------------------------------------------------- /src/utils/fsutils.c: -------------------------------------------------------------------------------- 1 | #include "fsutils.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "dynamic_libs/fs_functions.h" 9 | #include "stringutils.h" 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include "../main.h" 15 | 16 | #define BUFFER_SIZE 0x80000 17 | 18 | uint8_t removeRecursive(const char* path) 19 | { 20 | DIR* dir = opendir(path); 21 | if (dir == NULL) 22 | { 23 | console_printf(1, "Error opening %s for removal!", path); 24 | return 0; 25 | } 26 | 27 | size_t path_len = strlen(path); 28 | 29 | struct dirent *entry; 30 | while ((entry = readdir(dir)) != NULL) 31 | { 32 | if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) 33 | continue; 34 | 35 | char* full_path = calloc(path_len + strlen(entry->d_name) + 1, sizeof(char)); 36 | strcpy(full_path, path); 37 | strcat(full_path, "/"); 38 | strcat(full_path, entry->d_name); 39 | 40 | if (entry->d_type & DT_DIR) 41 | { 42 | removeRecursive(full_path); 43 | } 44 | else 45 | { 46 | if (remove(full_path) != 0) 47 | { 48 | console_printf(1, "Error removing %s!", full_path); 49 | } 50 | else 51 | { 52 | console_printf(1, "Removed %s", full_path); 53 | } 54 | 55 | } 56 | 57 | free(full_path); 58 | } 59 | 60 | closedir(dir); 61 | 62 | if (strcmp(path, "dev:") != 0) 63 | { 64 | if (remove(path) != 0) 65 | { 66 | console_printf(1, "Error removing %s %i!", path, errno); 67 | } 68 | else 69 | { 70 | console_printf(1, "Removed %s", path); 71 | } 72 | } 73 | 74 | 75 | return 1; 76 | } 77 | 78 | uint8_t dirExists(const char* path) 79 | { 80 | DIR* dir = opendir(path); 81 | if (dir != NULL) 82 | { 83 | closedir(dir); 84 | return 1; 85 | } 86 | 87 | return 0; 88 | } 89 | 90 | uint8_t fileExists(const char* path) 91 | { 92 | FILE* file = fopen(path, "r"); 93 | if (file != NULL) 94 | { 95 | fclose(file); 96 | return 1; 97 | } 98 | 99 | return 0; 100 | } 101 | 102 | uint8_t chmodRecursive(int fsaFd, char *pPath, int mode) 103 | { 104 | if (fsaFd < 0) 105 | { 106 | console_printf(1, "Invalid fsaFd %i", fsaFd); 107 | return 0; 108 | } 109 | 110 | DIR *dir; 111 | dir = opendir(pPath); 112 | if (dir == NULL) 113 | { 114 | console_printf(1, "Cannot open %s", pPath); 115 | return 0; 116 | } 117 | 118 | struct dirent* entry; 119 | while ((entry = readdir(dir)) != NULL) 120 | { 121 | if(strcmp(entry->d_name, "..") == 0 || strcmp(entry->d_name, ".") == 0) 122 | continue; 123 | 124 | char* path = calloc(FS_MAX_FULLPATH_SIZE, sizeof(char)); 125 | char* rootpath = calloc(FS_MAX_FULLPATH_SIZE, sizeof(char)); 126 | 127 | snprintf(path, FS_MAX_FULLPATH_SIZE, "%s/%s", pPath, entry->d_name); 128 | 129 | strcpy(rootpath, path); 130 | stringReplace("dev:", SLCCMPT_MOUNT_PATH, rootpath); 131 | 132 | int ret = IOSUHAX_FSA_ChangeMode(fsaFd, rootpath, mode); 133 | if (ret < 0) 134 | { 135 | console_printf(1, "chmod error %i for %s", ret, entry->d_name); 136 | } 137 | else 138 | { 139 | console_printf(1, "chmod successful for %s", entry->d_name); 140 | } 141 | 142 | if (entry->d_type & DT_DIR) 143 | { 144 | chmodRecursive(fsaFd, path, mode); 145 | } 146 | 147 | free(path); 148 | free(rootpath); 149 | } 150 | closedir(dir); 151 | 152 | return 1; 153 | } 154 | 155 | uint8_t copyDir(const char* src, const char* dst) 156 | { 157 | DIR* dir = opendir(src); 158 | if (dir == NULL) 159 | { 160 | console_printf(1, "Cannot open %s\n", src); 161 | return 0; 162 | } 163 | 164 | if (!dirExists(dst)) 165 | if(mkdir(dst, 0777) != 0) 166 | { 167 | console_printf(1, "Error creating %s", dst); 168 | return 0; 169 | } 170 | 171 | struct dirent* entry; 172 | while ((entry = readdir(dir)) != NULL) 173 | { 174 | if(strcmp(entry->d_name, "..") == 0 || strcmp(entry->d_name, ".") == 0) 175 | continue; 176 | 177 | char* srcPath = calloc(FS_MAX_FULLPATH_SIZE, sizeof(char)); 178 | strcpy(srcPath, src); 179 | strcat(srcPath, "/"); 180 | strcat(srcPath, entry->d_name); 181 | 182 | char* dstPath = calloc(FS_MAX_FULLPATH_SIZE, sizeof(char)); 183 | strcpy(dstPath, dst); 184 | strcat(dstPath, "/"); 185 | strcat(dstPath, entry->d_name); 186 | 187 | if (entry->d_type & DT_DIR) 188 | { 189 | if (!dirExists(dstPath)) 190 | if (mkdir(dstPath, 0777) != 0) 191 | { 192 | continue; 193 | } 194 | console_printf(1, "Created %s\n", entry->d_name); 195 | copyDir(srcPath, dstPath); 196 | } 197 | else 198 | { 199 | unsigned char* dataBuffer = memalign(0x40, BUFFER_SIZE); 200 | if (!dataBuffer) 201 | { 202 | console_printf(1, "Out of memory!\n"); 203 | return 0; 204 | } 205 | 206 | FILE* readFile = fopen(srcPath, "rb"); 207 | if(readFile == NULL) 208 | { 209 | console_printf(1, "Cannot open file %s\n", srcPath); 210 | continue; 211 | } 212 | 213 | FILE* writeFile = fopen(dstPath, "wb"); 214 | if(writeFile == NULL) 215 | { 216 | console_printf(1, "Cannot create file %s\n", srcPath); 217 | continue; 218 | } 219 | 220 | unsigned int size = 0; 221 | unsigned int ret; 222 | u32 passedMs = 1; 223 | u64 startTime = OSGetTime(); 224 | 225 | console_printf(1, "\n"); 226 | while ((ret = fread(dataBuffer, 0x1, BUFFER_SIZE, readFile)) > 0) 227 | { 228 | passedMs = (OSGetTime() - startTime) * 4000ULL / BUS_SPEED; 229 | if(passedMs == 0) 230 | passedMs = 1; // avoid 0 div 231 | 232 | // write buffer to file 233 | fwrite(dataBuffer, 0x01, ret, writeFile); 234 | size += ret; 235 | console_printf(0, " %s - 0x%X (%i kB/s)\r", entry->d_name, size, (u32)(((u64)size * 1000) / ((u64)1024 * passedMs))); 236 | } 237 | console_printf(1, "Copied %s\n", entry->d_name); 238 | free(dataBuffer); 239 | fclose(writeFile); 240 | fclose(readFile); 241 | } 242 | 243 | free(srcPath); 244 | free(dstPath); 245 | } 246 | closedir(dir); 247 | 248 | return 1; 249 | } -------------------------------------------------------------------------------- /src/utils/fsutils.h: -------------------------------------------------------------------------------- 1 | #ifndef _FSUTILS_H_ 2 | #define _FSUTILS_H_ 3 | 4 | #include 5 | 6 | uint8_t removeRecursive(const char* path); 7 | uint8_t dirExists(const char* path); 8 | uint8_t fileExists(const char* path); 9 | uint8_t chmodRecursive(int fsaFd, char *pPath, int mode); 10 | uint8_t copyDir(const char* src, const char* dst); 11 | 12 | #endif -------------------------------------------------------------------------------- /src/utils/logger.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "common/common.h" 7 | #include "dynamic_libs/os_functions.h" 8 | #include "dynamic_libs/socket_functions.h" 9 | #include "logger.h" 10 | 11 | #ifdef DEBUG_LOGGER 12 | static int log_socket = -1; 13 | static volatile int log_lock = 0; 14 | 15 | 16 | void log_init(const char * ipString) 17 | { 18 | log_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); 19 | if (log_socket < 0) 20 | return; 21 | 22 | struct sockaddr_in connect_addr; 23 | memset(&connect_addr, 0, sizeof(connect_addr)); 24 | connect_addr.sin_family = AF_INET; 25 | connect_addr.sin_port = 4405; 26 | inet_aton(ipString, &connect_addr.sin_addr); 27 | 28 | if(connect(log_socket, (struct sockaddr*)&connect_addr, sizeof(connect_addr)) < 0) 29 | { 30 | socketclose(log_socket); 31 | log_socket = -1; 32 | } 33 | } 34 | 35 | void log_deinit(void) 36 | { 37 | if(log_socket >= 0) 38 | { 39 | socketclose(log_socket); 40 | log_socket = -1; 41 | } 42 | } 43 | 44 | void log_print(const char *str) 45 | { 46 | // socket is always 0 initially as it is in the BSS 47 | if(log_socket < 0) { 48 | return; 49 | } 50 | 51 | while(log_lock) 52 | usleep(1000); 53 | log_lock = 1; 54 | 55 | int len = strlen(str); 56 | int ret; 57 | while (len > 0) { 58 | int block = len < 1400 ? len : 1400; // take max 1400 bytes per UDP packet 59 | ret = send(log_socket, str, block, 0); 60 | if(ret < 0) 61 | break; 62 | 63 | len -= ret; 64 | str += ret; 65 | } 66 | 67 | log_lock = 0; 68 | } 69 | 70 | void log_printf(const char *format, ...) 71 | { 72 | if(log_socket < 0) { 73 | return; 74 | } 75 | 76 | char * tmp = NULL; 77 | 78 | va_list va; 79 | va_start(va, format); 80 | if((vasprintf(&tmp, format, va) >= 0) && tmp) 81 | { 82 | log_print(tmp); 83 | } 84 | va_end(va); 85 | 86 | if(tmp) 87 | free(tmp); 88 | } 89 | #endif 90 | -------------------------------------------------------------------------------- /src/utils/logger.h: -------------------------------------------------------------------------------- 1 | #ifndef __LOGGER_H_ 2 | #define __LOGGER_H_ 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | //#define DEBUG_LOGGER 1 9 | 10 | #ifdef DEBUG_LOGGER 11 | void log_init(const char * ip); 12 | void log_deinit(void); 13 | void log_print(const char *str); 14 | void log_printf(const char *format, ...); 15 | #else 16 | #define log_init(x) 17 | #define log_deinit() 18 | #define log_print(x) 19 | #define log_printf(x, ...) 20 | #endif 21 | 22 | #ifdef __cplusplus 23 | } 24 | #endif 25 | 26 | #endif 27 | -------------------------------------------------------------------------------- /src/utils/stringutils.c: -------------------------------------------------------------------------------- 1 | #include "stringutils.h" 2 | #include 3 | #include 4 | 5 | char* stringReplaceAll(const char *search, const char *replace, char *string) 6 | { 7 | char* searchStart = strstr(string, search); 8 | while (searchStart != NULL) 9 | { 10 | char* tempString = (char*) malloc(strlen(string) * sizeof(char)); 11 | if(tempString == NULL) { 12 | return NULL; 13 | } 14 | 15 | strcpy(tempString, string); 16 | 17 | int len = searchStart - string; 18 | string[len] = '\0'; 19 | 20 | strcat(string, replace); 21 | 22 | len += strlen(search); 23 | strcat(string, (char*)tempString+len); 24 | 25 | free(tempString); 26 | 27 | searchStart = strstr(string, search); 28 | } 29 | 30 | return string; 31 | } 32 | 33 | char* stringReplace(char *search, char *replace, char *string) 34 | { 35 | char* searchStart = strstr(string, search); 36 | if(searchStart == NULL) { 37 | return string; 38 | } 39 | 40 | char* tempString = (char*) malloc(strlen(string) * sizeof(char)); 41 | if(tempString == NULL) { 42 | return NULL; 43 | } 44 | 45 | strcpy(tempString, string); 46 | 47 | int len = searchStart - string; 48 | string[len] = '\0'; 49 | 50 | strcat(string, replace); 51 | 52 | len += strlen(search); 53 | strcat(string, (char*)tempString+len); 54 | 55 | free(tempString); 56 | 57 | return string; 58 | } -------------------------------------------------------------------------------- /src/utils/stringutils.h: -------------------------------------------------------------------------------- 1 | #ifndef _STRINGUTILS_H_ 2 | #define _STRINGUTILS_H_ 3 | 4 | char* stringReplaceAll(const char *search, const char *replace, char *string); 5 | char* stringReplace(char *search, char *replace, char *string); 6 | 7 | #endif -------------------------------------------------------------------------------- /src/utils/utils.h: -------------------------------------------------------------------------------- 1 | #ifndef __UTILS_H_ 2 | #define __UTILS_H_ 3 | 4 | #include 5 | #include "../common/types.h" 6 | 7 | #ifdef __cplusplus 8 | extern "C" { 9 | #endif 10 | 11 | #define FlushBlock(addr) asm volatile("dcbf %0, %1\n" \ 12 | "icbi %0, %1\n" \ 13 | "sync\n" \ 14 | "eieio\n" \ 15 | "isync\n" \ 16 | : \ 17 | :"r"(0), "r"(((addr) & ~31)) \ 18 | :"memory", "ctr", "lr", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12" \ 19 | ); 20 | 21 | #define LIMIT(x, min, max) \ 22 | ({ \ 23 | typeof( x ) _x = x; \ 24 | typeof( min ) _min = min; \ 25 | typeof( max ) _max = max; \ 26 | ( ( ( _x ) < ( _min ) ) ? ( _min ) : ( ( _x ) > ( _max ) ) ? ( _max) : ( _x ) ); \ 27 | }) 28 | 29 | #define DegToRad(a) ( (a) * 0.01745329252f ) 30 | #define RadToDeg(a) ( (a) * 57.29577951f ) 31 | 32 | #define ALIGN4(x) (((x) + 3) & ~3) 33 | #define ALIGN32(x) (((x) + 31) & ~31) 34 | 35 | // those work only in powers of 2 36 | #define ROUNDDOWN(val, align) ((val) & ~(align-1)) 37 | #define ROUNDUP(val, align) ROUNDDOWN(((val) + (align-1)), align) 38 | 39 | #define le16(i) ((((u16) ((i) & 0xFF)) << 8) | ((u16) (((i) & 0xFF00) >> 8))) 40 | #define le32(i) ((((u32)le16((i) & 0xFFFF)) << 16) | ((u32)le16(((i) & 0xFFFF0000) >> 16))) 41 | #define le64(i) ((((u64)le32((i) & 0xFFFFFFFFLL)) << 32) | ((u64)le32(((i) & 0xFFFFFFFF00000000LL) >> 32))) 42 | 43 | #ifdef __cplusplus 44 | } 45 | #endif 46 | 47 | #endif // __UTILS_H_ 48 | --------------------------------------------------------------------------------