├── 3dshaxarm11_ctrserver ├── network.h ├── armdebug.h ├── armcfg.s ├── ctrserver_main.c ├── armdebug.s └── 3dshax11_start.s ├── 3dshaxarm11_ctrserver_data └── .gitignore ├── 3dshaxarm9 ├── arm9_svc.h ├── a9_memfs.h ├── arm9_nand.h ├── ctr-gamecard.h ├── arm9_a11kernel.h ├── yls8_aes.h ├── arm9fs.h ├── a9_memfs.c ├── arm9_nand.c ├── arm9_svc.s ├── arm9_a11kernel.c ├── ctr-gamecard.c ├── yls8_aes.c ├── nandredir.s ├── firmlaunch_hookpatches.s ├── arm9fs.s └── firmpatches.s ├── 3dshaxarm11.specs ├── Makefile.3dshax_parsedebug ├── Makefile.3dshaxclient ├── 3dshaxarm11_ctrserverold ├── necir.h └── necir.c ├── 3dshax_common └── ctrclient.h ├── 3dshaxarm9new3dsmem.ld ├── 3dshaxarm9.ld ├── 3dshaxarm9fcram.ld ├── Makefile_ctrserver.arm11 ├── Makefile ├── Makefile.arm9 ├── 3dshax_parsedebug.c └── README.md /3dshaxarm11_ctrserver/network.h: -------------------------------------------------------------------------------- 1 | void network_stuff(u32 *payloadptr, u32 payload_maxsize); 2 | 3 | -------------------------------------------------------------------------------- /3dshaxarm11_ctrserver_data/.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore everything in this directory 2 | * 3 | # Except this file 4 | !.gitignore 5 | -------------------------------------------------------------------------------- /3dshaxarm9/arm9_svc.h: -------------------------------------------------------------------------------- 1 | #ifndef ARM9_SVC_H 2 | #define ARM9_SVC_H 3 | 4 | void launchcode_kernelmode(void*); 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /3dshaxarm11.specs: -------------------------------------------------------------------------------- 1 | %rename link old_link 2 | 3 | *link: 4 | %(old_link) -T ../3dshaxarm11.ld%s 5 | 6 | *startfile: 7 | ../3dshax11_start%O%s crti%O%s crtbegin%O%s 8 | 9 | -------------------------------------------------------------------------------- /3dshaxarm9/a9_memfs.h: -------------------------------------------------------------------------------- 1 | #ifndef A9MEMFS_H 2 | #define A9MEMFS_H 3 | 4 | void dump_fcramvram(); 5 | void dump_fcramaxiwram(); 6 | u32 loadfile_charpath(char *path, u32 *addr, u32 maxsize); 7 | 8 | #endif 9 | -------------------------------------------------------------------------------- /3dshaxarm9/arm9_nand.h: -------------------------------------------------------------------------------- 1 | #ifndef ARM9_NAND_H 2 | #define ARM9_NAND_H 3 | 4 | void dump_nandfile(char *path); 5 | u32 nand_rwsector(u32 sector, u32 *outbuf, u32 sectorcount, u32 rw); 6 | void dump_nandimage(); 7 | 8 | #endif 9 | -------------------------------------------------------------------------------- /3dshaxarm9/ctr-gamecard.h: -------------------------------------------------------------------------------- 1 | #ifndef CTRGAMECARD_H 2 | #define CTRGAMECARD_H 3 | 4 | u32 ctrcard_cmdc6(u32 *outbuf); 5 | u32 gamecard_readsectors(u32 *outbuf, u32 sector, u32 sectorcount); 6 | void read_gamecard(); 7 | 8 | #endif 9 | -------------------------------------------------------------------------------- /Makefile.3dshax_parsedebug: -------------------------------------------------------------------------------- 1 | 2 | LIBS = 3 | OBJS = 3dshax_parsedebug.o 4 | CXXFLAGS = -Wall -Os -I. 5 | CFLAGS = $(CXXFLAGS) 6 | OUTPUT = 3dshax_parsedebug 7 | CC = gcc 8 | 9 | ifneq ($(strip $(NIX)),) 10 | CFLAGS := $(CFLAGS) -DNIX 11 | endif 12 | 13 | ifneq ($(strip $(WIN32)),) 14 | CFLAGS := $(CFLAGS) -D_WIN32 15 | endif 16 | 17 | main: $(OBJS) 18 | $(CC) -o $(OUTPUT) $(OBJS) $(LIBS) 19 | clean: 20 | rm -rf $(OUTPUT) $(OBJS) 21 | -------------------------------------------------------------------------------- /3dshaxarm11_ctrserver/armdebug.h: -------------------------------------------------------------------------------- 1 | u32 getdebug_didr(); 2 | u32 getdebug_dscr(); 3 | u32 setdebug_dscr(u32 val); 4 | u32 getdebug_vcr(); 5 | u32 setdebug_vcr(u32 val); 6 | u32 getdebug_bvr(u32 id); 7 | u32 setdebug_bvr(u32 id, u32 val); 8 | u32 getdebug_bcr(u32 id); 9 | u32 setdebug_bcr(u32 id, u32 val); 10 | u32 getdebug_wvr(u32 id); 11 | u32 setdebug_wvr(u32 id, u32 val); 12 | u32 getdebug_wcr(u32 id); 13 | u32 setdebug_wcr(u32 id, u32 val); 14 | 15 | -------------------------------------------------------------------------------- /3dshaxarm9/arm9_a11kernel.h: -------------------------------------------------------------------------------- 1 | #ifndef ARM9_A11KERNEL_H 2 | #define ARM9_A11KERNEL_H 3 | 4 | u32 *get_kprocessptr(u64 procname, u32 num, u32 get_mmutableptr); 5 | u8 *get_kprocess_contextid(u32 *kprocess); 6 | u8 *mmutable_convert_vaddr2physaddr(u32 *mmutable, u32 vaddr, u32 *remaining_pagesize); 7 | u32 *patch_mmutables(u64 procname, u32 patch_permissions, u32 num); 8 | void writepatch_arm11kernel_kernelpanicbkpt(u32 *ptr, u32 size); 9 | 10 | #endif 11 | -------------------------------------------------------------------------------- /3dshaxarm9/yls8_aes.h: -------------------------------------------------------------------------------- 1 | #ifndef YLS8AES_H 2 | #define YLS8AES_H 3 | 4 | void aes_mutexenter(); 5 | void aes_mutexleave(); 6 | void aes_set_ctr(u32 *ctr); 7 | void aes_set_iv(u32 *iv); 8 | void aes_select_key(u32 keyslot); 9 | void aes_select_key(u32 keyslot); 10 | void aes_set_ykey(u32 keyslot, u32 *key); 11 | void aes_set_xkey(u32 keyslot, u32 *key); 12 | void aes_set_key(u32 keyslot, u32 *key); 13 | void aes_ctr_crypt(u32 *buf, u32 size); 14 | void aes_cbc_decrypt(u32 *buf, u32 size); 15 | void aes_cbc_encrypt(u32 *buf, u32 size); 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /Makefile.3dshaxclient: -------------------------------------------------------------------------------- 1 | ifeq ($(strip $(CTRCLIENT)),) 2 | $(error "The CTRCLIENT Makefile param is required, this should be: /ctr/ramtracer/ctrclient") 3 | endif 4 | 5 | LIBS = 6 | OBJS = 3dshaxclient.o $(CTRCLIENT)/ctrclient.o 7 | CXXFLAGS = -Wall -Os -I. -I$(CTRCLIENT) 8 | CFLAGS = $(CXXFLAGS) 9 | OUTPUT = 3dshaxclient 10 | CC = gcc 11 | 12 | ifneq ($(strip $(NIX)),) 13 | CFLAGS := $(CFLAGS) -DNIX 14 | endif 15 | 16 | ifneq ($(strip $(WIN32)),) 17 | CFLAGS := $(CFLAGS) -D_WIN32 18 | LIBS := $(LIBS) -lws2_32 19 | endif 20 | 21 | main: $(OBJS) 22 | $(CC) -o $(OUTPUT) $(OBJS) $(LIBS) 23 | clean: 24 | rm -rf $(OUTPUT) $(OBJS) 25 | -------------------------------------------------------------------------------- /3dshaxarm11_ctrserverold/necir.h: -------------------------------------------------------------------------------- 1 | #define NEC_IR_ADDRESS_LG_TV 0x04 2 | 3 | // The actual remote key command codes we implement here are as 4 | // follows. (Of course, I didn't really _need_ any other than 5 | // the IN_START and the EZ_ADJUST codes, but the others were a 6 | // nice thing to have for initial testing.) 7 | 8 | #define IRKEY_CHANNEL_PLUS 0x00 9 | #define IRKEY_CHANNEL_MINUS 0x01 10 | #define IRKEY_VOLUME_PLUS 0x02 11 | #define IRKEY_VOLUME_MINUS 0x03 12 | #define IRKEY_MUTE 0x09 13 | #define IRKEY_Q_MENU 0x45 14 | #define IRKEY_IN_START 0xFB 15 | #define IRKEY_EZ_ADJUST 0xFF 16 | 17 | void transmit_nec_ir_command(uint8_t address, uint8_t command); 18 | 19 | -------------------------------------------------------------------------------- /3dshaxarm9/arm9fs.h: -------------------------------------------------------------------------------- 1 | #ifndef ARM9FS_H 2 | #define ARM9FS_H 3 | 4 | u32 dumpmem(u32 *addr, u32 size); 5 | u32 loadfile(u32 *addr, u32 size, u16 *path, u32 pathsize); 6 | u32 openfile(u32 *archiveobj, u32 lowpathtype, void* path, u32 pathsize, u32 openflags, u32 **fileobj); 7 | u32 closefile(u32 *fileobj); 8 | u32 fileread(u32 *fileobj, u32 *buf, u32 size, u32 filepos); 9 | u32 filewrite(u32 *fileobj, u32 *buf, u32 size, u32 filepos); 10 | u32 getfilesize(u32 *fileobj); 11 | u32 setfilesize(u32 *fileobj, u32 size); 12 | u32 archive_rwsectors(u32 *archiveobj, u32 *buf, u32 sectorcount, u32 mediaoffset, u32 rw); 13 | u32 pxifs_openarchive(u32 **archiveobj, u32 archiveid, u32 *lowpath);//lowpath is a ptr to the following structure: +0 = lowpathtype, +4 = dataptr, +8 = datasize 14 | 15 | extern u32 *pxifs_state; 16 | extern u32 *sdarchive_obj; 17 | extern u32 *nandarchive_obj; 18 | extern u16 input_filepath[]; 19 | extern u16 dump_filepath[]; 20 | 21 | #endif 22 | 23 | -------------------------------------------------------------------------------- /3dshaxarm11_ctrserver/armcfg.s: -------------------------------------------------------------------------------- 1 | .text 2 | .cpu mpcore 3 | .arm 4 | 5 | .global get_armcfgregs 6 | .type get_armcfgregs, %function 7 | get_armcfgregs: 8 | mrc p15, 0, r1, c0, c0, 0 @ Main ID Register 9 | str r1, [r0, #0x0] 10 | mrc p15, 0, r1, c0, c0, 1 @ Cache Type Register 11 | str r1, [r0, #0x4] 12 | mrc p15, 0, r1, c0, c0, 3 @ TLB Type Register 13 | str r1, [r0, #0x8] 14 | mrc p15, 0, r1, c0, c0, 3 @ CPUID Register 15 | str r1, [r0, #0xc] 16 | 17 | mrc p15, 0, r1, c0, c1, 0 @ ID_PFR0, Processor Feature Register 0 18 | str r1, [r0, #0x10] 19 | mrc p15, 0, r1, c0, c1, 1 @ ID_PFR1, Processor Feature Register 1 20 | str r1, [r0, #0x14] 21 | mrc p15, 0, r1, c0, c1, 2 @ ID_DFR0, Debug Feature Register 0 22 | str r1, [r0, #0x18] 23 | mrc p15, 0, r1, c0, c1, 4 @ IDMMFR0, Memory Model Feature Register 0 24 | str r1, [r0, #0x1c] 25 | mrc p15, 0, r1, c0, c1, 5 @ IDMMFR0, Memory Model Feature Register 1 26 | str r1, [r0, #0x20] 27 | mrc p15, 0, r1, c0, c1, 6 @ IDMMFR0, Memory Model Feature Register 2 28 | str r1, [r0, #0x24] 29 | mrc p15, 0, r1, c0, c1, 7 @ IDMMFR0, Memory Model Feature Register 3. 30 | str r1, [r0, #0x28] 31 | 32 | mrc p15, 0, r1, c0, c2, 0 @ ID_ISAR0, ISA Feature Register 0 33 | str r1, [r0, #0x2c] 34 | mrc p15, 0, r1, c0, c2, 1 @ ID_ISAR1, ISA Feature Register 1 35 | str r1, [r0, #0x30] 36 | mrc p15, 0, r1, c0, c2, 2 @ ID_ISAR2, ISA Feature Register 2 37 | str r1, [r0, #0x34] 38 | mrc p15, 0, r1, c0, c2, 3 @ ID_ISAR3, ISA Feature Register 3 39 | str r1, [r0, #0x38] 40 | mrc p15, 0, r1, c0, c2, 4 @ ID_ISAR4, ISA Feature Register 4 41 | str r1, [r0, #0x3c] 42 | 43 | bx lr 44 | 45 | -------------------------------------------------------------------------------- /3dshaxarm9/a9_memfs.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include <3ds.h> 6 | 7 | #include "arm9_svc.h" 8 | #include "arm9fs.h" 9 | 10 | extern u32 RUNNINGFWVER; 11 | 12 | /*void dump_fcramvram() 13 | { 14 | u32 pos=0; 15 | u16 filepath[64]; 16 | u32 *fileobj = NULL; 17 | char *path = (char*)"/3dshax_vram.bin"; 18 | 19 | memset(filepath, 0, 64*2); 20 | for(pos=0; pos maxsize)filesize = maxsize; 70 | 71 | if((ret = fileread(fileobj, addr, filesize, 0))!=0) 72 | { 73 | return ret; 74 | } 75 | 76 | closefile(fileobj); 77 | 78 | svcFlushProcessDataCache(0xffff8001, addr, filesize); 79 | 80 | return 0; 81 | } 82 | 83 | -------------------------------------------------------------------------------- /3dshaxarm9/arm9_nand.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include <3ds.h> 6 | 7 | #include "arm9fs.h" 8 | 9 | /*void dump_nandfile(char *path) 10 | { 11 | u32 ret=0; 12 | u32 pos=0; 13 | u32 filesize = 0; 14 | u16 filepath[256]; 15 | u32 *fileobj = NULL; 16 | 17 | if(initialize_nandarchiveobj()!=0)return; 18 | 19 | memset(filepath, 0, 256*2); 20 | for(pos=0; pos 2 | #include 3 | #include 4 | #include 5 | 6 | #include <3ds.h> 7 | 8 | #include "network.h" 9 | 10 | extern u64 PROCESSNAME;//Name of the process this code is running under, if set by the code-loader. 11 | 12 | Result initsrvhandle_allservices(); 13 | 14 | extern char* fake_heap_start; 15 | extern char* fake_heap_end; 16 | static u32 linearheapsize; 17 | 18 | extern u32 __ctru_heap; 19 | extern u32 __ctru_heap_size; 20 | extern u32 __ctru_linear_heap; 21 | extern u32 __ctru_linear_heap_size; 22 | 23 | void __system_allocateHeaps() { 24 | u32 tmp=0; 25 | Result ret; 26 | u32 heapsize; 27 | 28 | if(PROCESSNAME != 0x454d414e434f5250LL)//This is only executed when the PROCESSNAME is not set to the default "PROCNAME" string. 29 | { 30 | if(PROCESSNAME == 0x706c64)//"dlp" 31 | { 32 | linearheapsize = 0x2000; 33 | if(*((u8*)0x1FF80030) >= 6)linearheapsize = 0x500000;//New3DS 34 | } 35 | else 36 | { 37 | linearheapsize = 0x500000; 38 | } 39 | } 40 | else 41 | { 42 | linearheapsize = 0x500000; 43 | } 44 | 45 | heapsize = 0x00088000; 46 | __ctru_heap_size = heapsize; 47 | __ctru_linear_heap_size = linearheapsize; 48 | 49 | // Allocate the application heap 50 | __ctru_heap = 0x08000000; 51 | ret = svcControlMemory(&tmp, __ctru_heap, 0x0, heapsize, MEMOP_ALLOC, 0x3); 52 | 53 | if(ret!=0) 54 | { 55 | ((u32*)0x99000000)[0] = ret; 56 | } 57 | 58 | // Allocate the linear heap 59 | ret = svcControlMemory(&__ctru_linear_heap, 0x0, 0x0, linearheapsize, MEMOP_ALLOC_LINEAR, 0x3); 60 | 61 | if(ret!=0) 62 | { 63 | ((u32*)0x99000000)[1] = ret; 64 | } 65 | 66 | // Set up newlib heap 67 | fake_heap_start = (char*)__ctru_heap; 68 | fake_heap_end = fake_heap_start + heapsize; 69 | } 70 | 71 | void __appInit() { 72 | Result ret; 73 | // Initialize services 74 | 75 | ret = initsrvhandle_allservices(); 76 | if(ret!=0) 77 | { 78 | ((u32*)0x94000000)[0x800>>2] = ret; 79 | } 80 | 81 | fsInit(); 82 | } 83 | 84 | int main(int argc, char **argv) 85 | { 86 | Result ret=0; 87 | u32 *ptr; 88 | 89 | if(PROCESSNAME == 0x706c64)svcSleepThread(10000000000LL);//Delay 10 seconds when running under the dlp module. 90 | 91 | if(PROCESSNAME != 0x454d414e434f5250LL)//This is only executed when the PROCESSNAME is not set to the default "PROCNAME" string. 92 | { 93 | if(PROCESSNAME == 0x706c64)//"dlp" 94 | { 95 | gspInit(); 96 | } 97 | else 98 | { 99 | //aptInit(); 100 | 101 | gfxInitDefault(); 102 | } 103 | } 104 | else 105 | { 106 | aptInit(); 107 | 108 | gfxInitDefault(); 109 | } 110 | 111 | acWaitInternetConnection(); 112 | 113 | ptr = memalign(0x1000, 0x48000); 114 | if(ptr==NULL)((u32*)0x84000000)[2] = 0x50505050; 115 | 116 | ret = socInit(ptr, 0x48000); 117 | if(ret!=0) 118 | { 119 | ((u32*)0x84000000)[1] = ret; 120 | } 121 | 122 | network_stuff((u32*)__ctru_linear_heap, linearheapsize); 123 | 124 | while(1); 125 | 126 | return 0; 127 | } 128 | 129 | -------------------------------------------------------------------------------- /3dshaxarm9/arm9_a11kernel.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include <3ds.h> 6 | 7 | #include "arm9_a11kernel.h" 8 | 9 | extern u32 RUNNINGFWVER; 10 | 11 | u32 slabheap_physaddr = 0x1FFA0000; 12 | u32 slabheap_vaddr = 0; 13 | 14 | u32 arm11kernel_initialize_slabheapvaddr() 15 | { 16 | u32 pos; 17 | u8 *ptr8; 18 | 19 | for(pos=0; pos<0x100; pos++) 20 | { 21 | ptr8 = mmutable_convert_vaddr2physaddr((u32*)0x1FFF8000, 0xFFF00000 + (pos<<12), NULL); 22 | if((u32)ptr8 == slabheap_physaddr) 23 | { 24 | slabheap_vaddr = 0xFFF00000 + (pos<<12); 25 | return 0; 26 | } 27 | } 28 | 29 | return 1; 30 | } 31 | 32 | u32 *get_kprocessptr(u64 procname, u32 num, u32 get_mmutableptr) 33 | { 34 | u32 pos=0; 35 | //u32 pos2=0; 36 | u32 kcodeset_adr=0; 37 | u32 *wram = (u32*)0x1FF80000; 38 | u32 *kprocess = NULL; 39 | u32 kernelfcram_phys2vaddr_value = 0xd0000000; 40 | u32 kprocess_adjustoffset = 0; 41 | 42 | if(((u8)RUNNINGFWVER)>=44)//v8.0 43 | { 44 | kernelfcram_phys2vaddr_value = 0xc0000000; 45 | kprocess_adjustoffset = 8; 46 | } 47 | 48 | if(RUNNINGFWVER & 0x40000000)kprocess_adjustoffset+= 8; 49 | 50 | if(slabheap_vaddr==0) 51 | { 52 | if(arm11kernel_initialize_slabheapvaddr())return NULL; 53 | } 54 | 55 | for(pos=(slabheap_physaddr - (u32)wram)>>2; pos<(0x80000>>2)-1; pos++)//kcodeset_adr = KCodeSet object arm11 kernel vaddr for the specified process name. 56 | { 57 | if(wram[pos]==((u32)procname) && wram[pos+1]==((u32)(procname>>32))) 58 | { 59 | kcodeset_adr = ((pos<<2) - 0x50) + 0x1FF80000; 60 | kcodeset_adr = (kcodeset_adr - slabheap_physaddr) + slabheap_vaddr; 61 | break; 62 | } 63 | } 64 | 65 | if(kcodeset_adr==0)return NULL; 66 | 67 | for(pos=0; pos<(0x80000>>2); pos++)//kprocess = physical addr for KProcess object containing the above KCodeSet addr. 68 | { 69 | if(wram[pos]==kcodeset_adr) 70 | { 71 | if(num) 72 | { 73 | num--; 74 | } 75 | else 76 | { 77 | kprocess = &wram[pos - ((0xa8+kprocess_adjustoffset)>>2)]; 78 | break; 79 | } 80 | } 81 | } 82 | 83 | if(kprocess==NULL)return NULL; 84 | 85 | if(get_mmutableptr)return (u32*)(kprocess[(0x54+kprocess_adjustoffset)>>2] - kernelfcram_phys2vaddr_value); 86 | return kprocess; 87 | } 88 | 89 | u8 *get_kprocess_contextid(u32 *kprocess) 90 | { 91 | u32 kprocess_adjustoffset = 0; 92 | 93 | if(kprocess==NULL)return NULL; 94 | 95 | if(RUNNINGFWVER & 0x40000000)kprocess_adjustoffset+= 8; 96 | 97 | return (u8*)&kprocess[(0x44 + kprocess_adjustoffset) >> 2]; 98 | } 99 | 100 | u8 *mmutable_convert_vaddr2physaddr(u32 *mmutable, u32 vaddr, u32 *remaining_pagesize) 101 | { 102 | u32 *ptr; 103 | u32 val; 104 | 105 | if(mmutable==NULL)return NULL; 106 | 107 | val = mmutable[vaddr >> 20]; 108 | if((val & 0x3) == 0x0 || (val & 0x3) == 0x3)return NULL; 109 | if((val & 0x3) == 0x2) 110 | { 111 | if(((val >> 18) & 1) == 0) 112 | { 113 | if(remaining_pagesize)*remaining_pagesize = 0x100000 - (vaddr & 0xFFFFF); 114 | 115 | return (u8*)((val & ~0xFFFFF) | (vaddr & 0xFFFFF)); 116 | } 117 | 118 | if(remaining_pagesize)*remaining_pagesize = 0x1000000 - (vaddr & 0xFFFFFF); 119 | 120 | return (u8*)((val & ~0xFFFFFF) | (vaddr & 0xFFFFFF)); 121 | } 122 | 123 | ptr = (u32*)(val & ~0x3FF); 124 | val = ptr[(vaddr >> 12) & 0xff]; 125 | if((val & 0x3) == 0)return NULL; 126 | if((val & 0x2) == 0) 127 | { 128 | if(remaining_pagesize)*remaining_pagesize = 0x10000 - (vaddr & 0xFFFF); 129 | 130 | return (u8*)((val & ~0xFFFF) | (vaddr & 0xFFFF)); 131 | } 132 | 133 | if(remaining_pagesize)*remaining_pagesize = 0x1000 - (vaddr & 0xFFF); 134 | 135 | return (u8*)((val & ~0xFFF) | (vaddr & 0xFFF)); 136 | } 137 | 138 | /*u32 *patch_mmutables(u64 procname, u32 patch_permissions, u32 num) 139 | { 140 | u32 pos=0, pos2=0; 141 | //u32 *wram = (u32*)0x1FF80000; 142 | u32 *kprocess; 143 | u32 *mmutable = NULL; 144 | u32 *mmutableL2; 145 | u32 *page_physaddr = 0; 146 | 147 | kprocess = get_kprocessptr(procname, num, 0); 148 | if(kprocess==NULL)return NULL; 149 | 150 | mmutable = (u32*)(kprocess[0x54>>2] - 0xd0000000); 151 | 152 | for(pos=1; pos<0x10; pos++) 153 | { 154 | if(mmutable[pos]==0)break; 155 | 156 | mmutableL2 = (u32*)((mmutable[pos] >> 10) << 10); 157 | 158 | for(pos2=0; pos2<0x100; pos2++) 159 | { 160 | if(mmutableL2[pos2]==0)break; 161 | 162 | if(page_physaddr==0)page_physaddr = (u32*)((mmutableL2[pos2] >> 12) << 12); 163 | if(patch_permissions)mmutableL2[pos2] |= 0x30;//Set permissions to usr-RW/priv-RW. 164 | } 165 | } 166 | 167 | if(patch_permissions) 168 | { 169 | kprocess[(28+8 + 0)>>2] |= 0x0101;//Set the TLB invalidation flags used when doing a process context switch.(CPUID0+CPUID1) 170 | } 171 | 172 | return page_physaddr; 173 | }*/ 174 | 175 | void writepatch_arm11kernel_kernelpanicbkpt(u32 *ptr, u32 size) 176 | { 177 | u32 pos, i; 178 | 179 | pos = 0; 180 | while(size) 181 | { 182 | if(ptr[pos] == 0xffff9004 && ptr[pos+1] == 0x010000ff)//Locate the kernelpanic() function(s) via the .pool data. Note that older kernel versions had two kernelpanic() functions. 183 | { 184 | for(i=0; i<(0x400/4); i++) 185 | { 186 | if(ptr[pos-i] == 0xe92d4010)//"push {r4, lr}" 187 | { 188 | //The actual start of the function is this instruction, immediately before the push instruction: "ldr r0, [pc, ]" 189 | ptr[pos-i-1] = 0xE1200070;//"bkpt #0" 190 | break; 191 | } 192 | } 193 | } 194 | 195 | pos++; 196 | size-= 4; 197 | } 198 | } 199 | 200 | -------------------------------------------------------------------------------- /3dshaxarm11_ctrserver/armdebug.s: -------------------------------------------------------------------------------- 1 | .text 2 | .cpu mpcore 3 | .arm 4 | 5 | .global getdebug_didr 6 | .type getdebug_didr, %function 7 | getdebug_didr: 8 | mrc p14, 0, r0, c0, c0, 0 9 | bx lr 10 | 11 | .global getdebug_dscr 12 | .type getdebug_dscr, %function 13 | getdebug_dscr: 14 | mrc p14, 0, r0, c0, c1, 0 15 | bx lr 16 | 17 | .global setdebug_dscr 18 | .type setdebug_dscr, %function 19 | setdebug_dscr: 20 | mcr p14, 0, r0, c0, c1, 0 21 | bx lr 22 | 23 | .global getdebug_vcr 24 | .type getdebug_vcr, %function 25 | getdebug_vcr: 26 | mrc p14, 0, r0, c0, c7, 0 27 | bx lr 28 | 29 | .global setdebug_vcr 30 | .type setdebug_vcr, %function 31 | setdebug_vcr: 32 | mcr p14, 0, r0, c0, c7, 0 33 | b kernelmode_cachestuff 34 | 35 | .global getdebug_bvr 36 | .type getdebug_bvr, %function 37 | getdebug_bvr: 38 | cmp r0, #0 39 | beq getdebug_bvr_l0 40 | cmp r0, #1 41 | beq getdebug_bvr_l1 42 | cmp r0, #2 43 | beq getdebug_bvr_l2 44 | cmp r0, #3 45 | beq getdebug_bvr_l3 46 | cmp r0, #4 47 | beq getdebug_bvr_l4 48 | cmp r0, #5 49 | beq getdebug_bvr_l5 50 | mov r0, #0 @ Invalid 51 | bx lr 52 | 53 | getdebug_bvr_l0: 54 | mrc p14, 0, r0, c0, c0, 4 55 | bx lr 56 | 57 | getdebug_bvr_l1: 58 | mrc p14, 0, r0, c0, c1, 4 59 | bx lr 60 | 61 | getdebug_bvr_l2: 62 | mrc p14, 0, r0, c0, c2, 4 63 | bx lr 64 | 65 | getdebug_bvr_l3: 66 | mrc p14, 0, r0, c0, c3, 4 67 | bx lr 68 | 69 | getdebug_bvr_l4: 70 | mrc p14, 0, r0, c0, c4, 4 71 | bx lr 72 | 73 | getdebug_bvr_l5: 74 | mrc p14, 0, r0, c0, c5, 4 75 | bx lr 76 | 77 | .global setdebug_bvr 78 | .type setdebug_bvr, %function 79 | setdebug_bvr: 80 | cmp r0, #0 81 | beq setdebug_bvr_l0 82 | cmp r0, #1 83 | beq setdebug_bvr_l1 84 | cmp r0, #2 85 | beq setdebug_bvr_l2 86 | cmp r0, #3 87 | beq setdebug_bvr_l3 88 | cmp r0, #4 89 | beq setdebug_bvr_l4 90 | cmp r0, #5 91 | beq setdebug_bvr_l5 92 | mov r0, #1 @ Invalid 93 | bx lr 94 | 95 | setdebug_bvr_l0: 96 | mcr p14, 0, r1, c0, c0, 4 97 | mov r0, #0 98 | b kernelmode_cachestuff 99 | 100 | setdebug_bvr_l1: 101 | mcr p14, 0, r1, c0, c1, 4 102 | mov r0, #0 103 | b kernelmode_cachestuff 104 | 105 | setdebug_bvr_l2: 106 | mcr p14, 0, r1, c0, c2, 4 107 | mov r0, #0 108 | b kernelmode_cachestuff 109 | 110 | setdebug_bvr_l3: 111 | mcr p14, 0, r1, c0, c3, 4 112 | mov r0, #0 113 | b kernelmode_cachestuff 114 | 115 | setdebug_bvr_l4: 116 | mcr p14, 0, r1, c0, c4, 4 117 | mov r0, #0 118 | b kernelmode_cachestuff 119 | 120 | setdebug_bvr_l5: 121 | mcr p14, 0, r1, c0, c5, 4 122 | mov r0, #0 123 | b kernelmode_cachestuff 124 | 125 | .global getdebug_bcr 126 | .type getdebug_bcr, %function 127 | getdebug_bcr: 128 | cmp r0, #0 129 | beq getdebug_bcr_l0 130 | cmp r0, #1 131 | beq getdebug_bcr_l1 132 | cmp r0, #2 133 | beq getdebug_bcr_l2 134 | cmp r0, #3 135 | beq getdebug_bcr_l3 136 | cmp r0, #4 137 | beq getdebug_bcr_l4 138 | cmp r0, #5 139 | beq getdebug_bcr_l5 140 | mov r0, #0 @ Invalid 141 | bx lr 142 | 143 | getdebug_bcr_l0: 144 | mrc p14, 0, r0, c0, c0, 5 145 | bx lr 146 | 147 | getdebug_bcr_l1: 148 | mrc p14, 0, r0, c0, c1, 5 149 | bx lr 150 | 151 | getdebug_bcr_l2: 152 | mrc p14, 0, r0, c0, c2, 5 153 | bx lr 154 | 155 | getdebug_bcr_l3: 156 | mrc p14, 0, r0, c0, c3, 5 157 | bx lr 158 | 159 | getdebug_bcr_l4: 160 | mrc p14, 0, r0, c0, c4, 5 161 | bx lr 162 | 163 | getdebug_bcr_l5: 164 | mrc p14, 0, r0, c0, c5, 5 165 | bx lr 166 | 167 | .global setdebug_bcr 168 | .type setdebug_bcr, %function 169 | setdebug_bcr: 170 | cmp r0, #0 171 | beq setdebug_bcr_l0 172 | cmp r0, #1 173 | beq setdebug_bcr_l1 174 | cmp r0, #2 175 | beq setdebug_bcr_l2 176 | cmp r0, #3 177 | beq setdebug_bcr_l3 178 | cmp r0, #4 179 | beq setdebug_bcr_l4 180 | cmp r0, #5 181 | beq setdebug_bcr_l5 182 | mov r0, #1 @ Invalid 183 | bx lr 184 | 185 | setdebug_bcr_l0: 186 | mcr p14, 0, r1, c0, c0, 5 187 | mov r0, #0 188 | b kernelmode_cachestuff 189 | 190 | setdebug_bcr_l1: 191 | mcr p14, 0, r1, c0, c1, 5 192 | mov r0, #0 193 | b kernelmode_cachestuff 194 | 195 | setdebug_bcr_l2: 196 | mcr p14, 0, r1, c0, c2, 5 197 | mov r0, #0 198 | b kernelmode_cachestuff 199 | 200 | setdebug_bcr_l3: 201 | mcr p14, 0, r1, c0, c3, 5 202 | mov r0, #0 203 | b kernelmode_cachestuff 204 | 205 | setdebug_bcr_l4: 206 | mcr p14, 0, r1, c0, c4, 5 207 | mov r0, #0 208 | bx lr 209 | 210 | setdebug_bcr_l5: 211 | mcr p14, 0, r1, c0, c5, 5 212 | mov r0, #0 213 | b kernelmode_cachestuff 214 | 215 | .global getdebug_wvr 216 | .type getdebug_wvr, %function 217 | getdebug_wvr: 218 | cmp r0, #0 219 | beq getdebug_wvr_l0 220 | cmp r0, #1 221 | beq getdebug_wvr_l1 222 | mov r0, #0 @ Invalid 223 | bx lr 224 | 225 | getdebug_wvr_l0: 226 | mrc p14, 0, r0, c0, c0, 6 227 | bx lr 228 | 229 | getdebug_wvr_l1: 230 | mrc p14, 0, r0, c0, c1, 6 231 | bx lr 232 | 233 | .global setdebug_wvr 234 | .type setdebug_wvr, %function 235 | setdebug_wvr: 236 | cmp r0, #0 237 | beq setdebug_wvr_l0 238 | cmp r0, #1 239 | beq setdebug_wvr_l1 240 | mov r0, #1 @ Invalid 241 | bx lr 242 | 243 | setdebug_wvr_l0: 244 | mcr p14, 0, r1, c0, c0, 6 245 | mov r0, #0 246 | b kernelmode_cachestuff 247 | 248 | setdebug_wvr_l1: 249 | mcr p14, 0, r1, c0, c1, 6 250 | mov r0, #0 251 | b kernelmode_cachestuff 252 | 253 | .global getdebug_wcr 254 | .type getdebug_wcr, %function 255 | getdebug_wcr: 256 | cmp r0, #0 257 | beq getdebug_wcr_l0 258 | cmp r0, #1 259 | beq getdebug_wcr_l1 260 | mov r0, #0 @ Invalid 261 | bx lr 262 | 263 | getdebug_wcr_l0: 264 | mrc p14, 0, r0, c0, c0, 7 265 | bx lr 266 | 267 | getdebug_wcr_l1: 268 | mrc p14, 0, r0, c0, c1, 7 269 | bx lr 270 | 271 | .global setdebug_wcr 272 | .type setdebug_wcr, %function 273 | setdebug_wcr: 274 | cmp r0, #0 275 | beq setdebug_wcr_l0 276 | cmp r0, #1 277 | beq setdebug_wcr_l1 278 | mov r0, #1 @ Invalid 279 | bx lr 280 | 281 | setdebug_wcr_l0: 282 | mcr p14, 0, r1, c0, c0, 7 283 | mov r0, #0 284 | b kernelmode_cachestuff 285 | 286 | setdebug_wcr_l1: 287 | mcr p14, 0, r1, c0, c1, 7 288 | mov r0, #0 289 | b kernelmode_cachestuff 290 | 291 | -------------------------------------------------------------------------------- /3dshaxarm9new3dsmem.ld: -------------------------------------------------------------------------------- 1 | OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm") 2 | OUTPUT_ARCH(arm) 3 | ENTRY(_start) 4 | 5 | MEMORY { 6 | 7 | memregion : ORIGIN = 0x0816e000, LENGTH = 64K 8 | } 9 | 10 | __memregion_start = ORIGIN(memregion); 11 | __memregion_top = ORIGIN(memregion)+ LENGTH(memregion); 12 | 13 | SECTIONS 14 | { 15 | .init : 16 | { 17 | __text_start = . ; 18 | KEEP (*(.init)) 19 | . = ALIGN(4); /* REQUIRED. LD is flaky without it. */ 20 | } >memregion = 0xff 21 | 22 | .plt : 23 | { 24 | *(.plt) 25 | } >memregion = 0xff 26 | 27 | .text : /* ALIGN (4): */ 28 | { 29 | 30 | *(.text*) 31 | *(.stub) 32 | /* .gnu.warning sections are handled specially by elf32.em. */ 33 | *(.gnu.warning) 34 | *(.gnu.linkonce.t*) 35 | *(.glue_7) 36 | *(.glue_7t) 37 | . = ALIGN(4); /* REQUIRED. LD is flaky without it. */ 38 | } >memregion = 0xff 39 | 40 | .fini : 41 | { 42 | KEEP (*(.fini)) 43 | } >memregion =0xff 44 | 45 | __text_end = . ; 46 | 47 | .rodata : 48 | { 49 | *(.rodata) 50 | *all.rodata*(*) 51 | *(.roda) 52 | *(.rodata.*) 53 | *(.gnu.linkonce.r*) 54 | SORT(CONSTRUCTORS) 55 | . = ALIGN(4); /* REQUIRED. LD is flaky without it. */ 56 | } >memregion = 0xff 57 | 58 | .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >memregion 59 | __exidx_start = .; 60 | .ARM.exidx : { *(.ARM.exidx* .gnu.linkonce.armexidx.*) } >memregion 61 | __exidx_end = .; 62 | 63 | /* Ensure the __preinit_array_start label is properly aligned. We 64 | could instead move the label definition inside the section, but 65 | the linker would then create the section even if it turns out to 66 | be empty, which isn't pretty. */ 67 | . = ALIGN(32 / 8); 68 | PROVIDE (__preinit_array_start = .); 69 | .preinit_array : { KEEP (*(.preinit_array)) } >memregion = 0xff 70 | PROVIDE (__preinit_array_end = .); 71 | PROVIDE (__init_array_start = .); 72 | .init_array : { KEEP (*(.init_array)) } >memregion = 0xff 73 | PROVIDE (__init_array_end = .); 74 | PROVIDE (__fini_array_start = .); 75 | .fini_array : { KEEP (*(.fini_array)) } >memregion = 0xff 76 | PROVIDE (__fini_array_end = .); 77 | 78 | .ctors : 79 | { 80 | /* gcc uses crtbegin.o to find the start of the constructors, so 81 | we make sure it is first. Because this is a wildcard, it 82 | doesn't matter if the user does not actually link against 83 | crtbegin.o; the linker won't look for a file to match a 84 | wildcard. The wildcard also means that it doesn't matter which 85 | directory crtbegin.o is in. */ 86 | KEEP (*crtbegin.o(.ctors)) 87 | KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) 88 | KEEP (*(SORT(.ctors.*))) 89 | KEEP (*(.ctors)) 90 | . = ALIGN(4); /* REQUIRED. LD is flaky without it. */ 91 | } >memregion = 0xff 92 | 93 | .dtors : 94 | { 95 | KEEP (*crtbegin.o(.dtors)) 96 | KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) 97 | KEEP (*(SORT(.dtors.*))) 98 | KEEP (*(.dtors)) 99 | . = ALIGN(4); /* REQUIRED. LD is flaky without it. */ 100 | } >memregion = 0xff 101 | 102 | .eh_frame : 103 | { 104 | KEEP (*(.eh_frame)) 105 | . = ALIGN(4); /* REQUIRED. LD is flaky without it. */ 106 | } >memregion = 0xff 107 | 108 | .gcc_except_table : 109 | { 110 | *(.gcc_except_table) 111 | . = ALIGN(4); /* REQUIRED. LD is flaky without it. */ 112 | } >memregion = 0xff 113 | .jcr : { KEEP (*(.jcr)) } >memregion = 0 114 | .got : { *(.got.plt) *(.got) } >memregion = 0 115 | 116 | 117 | .memregion ALIGN(4) : 118 | { 119 | __memregion_start = ABSOLUTE(.) ; 120 | *(.memregion) 121 | *memregion.*(.text) 122 | . = ALIGN(4); /* REQUIRED. LD is flaky without it. */ 123 | __memregion_end = ABSOLUTE(.) ; 124 | } >memregion = 0xff 125 | 126 | 127 | .data ALIGN(4) : { 128 | __data_start = ABSOLUTE(.); 129 | *(.data) 130 | *(.data.*) 131 | *(.gnu.linkonce.d*) 132 | CONSTRUCTORS 133 | . = ALIGN(4); 134 | __data_end = ABSOLUTE(.) ; 135 | } >memregion = 0xff 136 | 137 | 138 | 139 | .bss ALIGN(4) : 140 | { 141 | __bss_start = ABSOLUTE(.); 142 | __bss_start__ = ABSOLUTE(.); 143 | *(.dynbss) 144 | *(.gnu.linkonce.b*) 145 | *(.bss*) 146 | *(COMMON) 147 | . = ALIGN(4); /* REQUIRED. LD is flaky without it. */ 148 | } >memregion 149 | 150 | __bss_end = . ; 151 | __bss_end__ = . ; 152 | 153 | _end = . ; 154 | __end__ = . ; 155 | PROVIDE (end = _end); 156 | 157 | /* Stabs debugging sections. */ 158 | .stab 0 : { *(.stab) } 159 | .stabstr 0 : { *(.stabstr) } 160 | .stab.excl 0 : { *(.stab.excl) } 161 | .stab.exclstr 0 : { *(.stab.exclstr) } 162 | .stab.index 0 : { *(.stab.index) } 163 | .stab.indexstr 0 : { *(.stab.indexstr) } 164 | .comment 0 : { *(.comment) } 165 | /* DWARF debug sections. 166 | Symbols in the DWARF debugging sections are relative to the beginning 167 | of the section so we begin them at 0. */ 168 | /* DWARF 1 */ 169 | .debug 0 : { *(.debug) } 170 | .line 0 : { *(.line) } 171 | /* GNU DWARF 1 extensions */ 172 | .debug_srcinfo 0 : { *(.debug_srcinfo) } 173 | .debug_sfnames 0 : { *(.debug_sfnames) } 174 | /* DWARF 1.1 and DWARF 2 */ 175 | .debug_aranges 0 : { *(.debug_aranges) } 176 | .debug_pubnames 0 : { *(.debug_pubnames) } 177 | /* DWARF 2 */ 178 | .debug_info 0 : { *(.debug_info) } 179 | .debug_abbrev 0 : { *(.debug_abbrev) } 180 | .debug_line 0 : { *(.debug_line) } 181 | .debug_frame 0 : { *(.debug_frame) } 182 | .debug_str 0 : { *(.debug_str) } 183 | .debug_loc 0 : { *(.debug_loc) } 184 | .debug_macinfo 0 : { *(.debug_macinfo) } 185 | /* SGI/MIPS DWARF 2 extensions */ 186 | .debug_weaknames 0 : { *(.debug_weaknames) } 187 | .debug_funcnames 0 : { *(.debug_funcnames) } 188 | .debug_typenames 0 : { *(.debug_typenames) } 189 | .debug_varnames 0 : { *(.debug_varnames) } 190 | .stack 0x80000 : { _stack = .; *(.stack) } 191 | /* These must appear regardless of . */ 192 | } 193 | -------------------------------------------------------------------------------- /3dshaxarm9.ld: -------------------------------------------------------------------------------- 1 | OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm") 2 | OUTPUT_ARCH(arm) 3 | ENTRY(_start) 4 | 5 | MEMORY { 6 | 7 | memregion : ORIGIN = 0x01ff8000, LENGTH = 14K 8 | } 9 | 10 | /* 0x01ff8000 14K */ 11 | 12 | __memregion_start = ORIGIN(memregion); 13 | __memregion_top = ORIGIN(memregion)+ LENGTH(memregion); 14 | 15 | SECTIONS 16 | { 17 | .init : 18 | { 19 | __text_start = . ; 20 | KEEP (*(.init)) 21 | . = ALIGN(4); /* REQUIRED. LD is flaky without it. */ 22 | } >memregion = 0xff 23 | 24 | .plt : 25 | { 26 | *(.plt) 27 | } >memregion = 0xff 28 | 29 | .text : /* ALIGN (4): */ 30 | { 31 | 32 | *(.text*) 33 | *(.stub) 34 | /* .gnu.warning sections are handled specially by elf32.em. */ 35 | *(.gnu.warning) 36 | *(.gnu.linkonce.t*) 37 | *(.glue_7) 38 | *(.glue_7t) 39 | . = ALIGN(4); /* REQUIRED. LD is flaky without it. */ 40 | } >memregion = 0xff 41 | 42 | .fini : 43 | { 44 | KEEP (*(.fini)) 45 | } >memregion =0xff 46 | 47 | __text_end = . ; 48 | 49 | .rodata : 50 | { 51 | *(.rodata) 52 | *all.rodata*(*) 53 | *(.roda) 54 | *(.rodata.*) 55 | *(.gnu.linkonce.r*) 56 | SORT(CONSTRUCTORS) 57 | . = ALIGN(4); /* REQUIRED. LD is flaky without it. */ 58 | } >memregion = 0xff 59 | 60 | .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >memregion 61 | __exidx_start = .; 62 | .ARM.exidx : { *(.ARM.exidx* .gnu.linkonce.armexidx.*) } >memregion 63 | __exidx_end = .; 64 | 65 | /* Ensure the __preinit_array_start label is properly aligned. We 66 | could instead move the label definition inside the section, but 67 | the linker would then create the section even if it turns out to 68 | be empty, which isn't pretty. */ 69 | . = ALIGN(32 / 8); 70 | PROVIDE (__preinit_array_start = .); 71 | .preinit_array : { KEEP (*(.preinit_array)) } >memregion = 0xff 72 | PROVIDE (__preinit_array_end = .); 73 | PROVIDE (__init_array_start = .); 74 | .init_array : { KEEP (*(.init_array)) } >memregion = 0xff 75 | PROVIDE (__init_array_end = .); 76 | PROVIDE (__fini_array_start = .); 77 | .fini_array : { KEEP (*(.fini_array)) } >memregion = 0xff 78 | PROVIDE (__fini_array_end = .); 79 | 80 | .ctors : 81 | { 82 | /* gcc uses crtbegin.o to find the start of the constructors, so 83 | we make sure it is first. Because this is a wildcard, it 84 | doesn't matter if the user does not actually link against 85 | crtbegin.o; the linker won't look for a file to match a 86 | wildcard. The wildcard also means that it doesn't matter which 87 | directory crtbegin.o is in. */ 88 | KEEP (*crtbegin.o(.ctors)) 89 | KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) 90 | KEEP (*(SORT(.ctors.*))) 91 | KEEP (*(.ctors)) 92 | . = ALIGN(4); /* REQUIRED. LD is flaky without it. */ 93 | } >memregion = 0xff 94 | 95 | .dtors : 96 | { 97 | KEEP (*crtbegin.o(.dtors)) 98 | KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) 99 | KEEP (*(SORT(.dtors.*))) 100 | KEEP (*(.dtors)) 101 | . = ALIGN(4); /* REQUIRED. LD is flaky without it. */ 102 | } >memregion = 0xff 103 | 104 | .eh_frame : 105 | { 106 | KEEP (*(.eh_frame)) 107 | . = ALIGN(4); /* REQUIRED. LD is flaky without it. */ 108 | } >memregion = 0xff 109 | 110 | .gcc_except_table : 111 | { 112 | *(.gcc_except_table) 113 | . = ALIGN(4); /* REQUIRED. LD is flaky without it. */ 114 | } >memregion = 0xff 115 | .jcr : { KEEP (*(.jcr)) } >memregion = 0 116 | .got : { *(.got.plt) *(.got) } >memregion = 0 117 | 118 | 119 | .memregion ALIGN(4) : 120 | { 121 | __memregion_start = ABSOLUTE(.) ; 122 | *(.memregion) 123 | *memregion.*(.text) 124 | . = ALIGN(4); /* REQUIRED. LD is flaky without it. */ 125 | __memregion_end = ABSOLUTE(.) ; 126 | } >memregion = 0xff 127 | 128 | 129 | .data ALIGN(4) : { 130 | __data_start = ABSOLUTE(.); 131 | *(.data) 132 | *(.data.*) 133 | *(.gnu.linkonce.d*) 134 | CONSTRUCTORS 135 | . = ALIGN(4); 136 | __data_end = ABSOLUTE(.) ; 137 | } >memregion = 0xff 138 | 139 | 140 | 141 | .bss ALIGN(4) : 142 | { 143 | __bss_start = ABSOLUTE(.); 144 | __bss_start__ = ABSOLUTE(.); 145 | *(.dynbss) 146 | *(.gnu.linkonce.b*) 147 | *(.bss*) 148 | *(COMMON) 149 | . = ALIGN(4); /* REQUIRED. LD is flaky without it. */ 150 | } >memregion 151 | 152 | __bss_end = . ; 153 | __bss_end__ = . ; 154 | 155 | _end = . ; 156 | __end__ = . ; 157 | PROVIDE (end = _end); 158 | 159 | /* Stabs debugging sections. */ 160 | .stab 0 : { *(.stab) } 161 | .stabstr 0 : { *(.stabstr) } 162 | .stab.excl 0 : { *(.stab.excl) } 163 | .stab.exclstr 0 : { *(.stab.exclstr) } 164 | .stab.index 0 : { *(.stab.index) } 165 | .stab.indexstr 0 : { *(.stab.indexstr) } 166 | .comment 0 : { *(.comment) } 167 | /* DWARF debug sections. 168 | Symbols in the DWARF debugging sections are relative to the beginning 169 | of the section so we begin them at 0. */ 170 | /* DWARF 1 */ 171 | .debug 0 : { *(.debug) } 172 | .line 0 : { *(.line) } 173 | /* GNU DWARF 1 extensions */ 174 | .debug_srcinfo 0 : { *(.debug_srcinfo) } 175 | .debug_sfnames 0 : { *(.debug_sfnames) } 176 | /* DWARF 1.1 and DWARF 2 */ 177 | .debug_aranges 0 : { *(.debug_aranges) } 178 | .debug_pubnames 0 : { *(.debug_pubnames) } 179 | /* DWARF 2 */ 180 | .debug_info 0 : { *(.debug_info) } 181 | .debug_abbrev 0 : { *(.debug_abbrev) } 182 | .debug_line 0 : { *(.debug_line) } 183 | .debug_frame 0 : { *(.debug_frame) } 184 | .debug_str 0 : { *(.debug_str) } 185 | .debug_loc 0 : { *(.debug_loc) } 186 | .debug_macinfo 0 : { *(.debug_macinfo) } 187 | /* SGI/MIPS DWARF 2 extensions */ 188 | .debug_weaknames 0 : { *(.debug_weaknames) } 189 | .debug_funcnames 0 : { *(.debug_funcnames) } 190 | .debug_typenames 0 : { *(.debug_typenames) } 191 | .debug_varnames 0 : { *(.debug_varnames) } 192 | .stack 0x80000 : { _stack = .; *(.stack) } 193 | /* These must appear regardless of . */ 194 | } 195 | -------------------------------------------------------------------------------- /3dshaxarm9fcram.ld: -------------------------------------------------------------------------------- 1 | OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm") 2 | OUTPUT_ARCH(arm) 3 | ENTRY(_start) 4 | 5 | MEMORY { 6 | 7 | memregion : ORIGIN = 0x20008000, LENGTH = 14K 8 | } 9 | 10 | /* 0x01ff8000 14K */ 11 | 12 | __memregion_start = ORIGIN(memregion); 13 | __memregion_top = ORIGIN(memregion)+ LENGTH(memregion); 14 | 15 | SECTIONS 16 | { 17 | .init : 18 | { 19 | __text_start = . ; 20 | KEEP (*(.init)) 21 | . = ALIGN(4); /* REQUIRED. LD is flaky without it. */ 22 | } >memregion = 0xff 23 | 24 | .plt : 25 | { 26 | *(.plt) 27 | } >memregion = 0xff 28 | 29 | .text : /* ALIGN (4): */ 30 | { 31 | 32 | *(.text*) 33 | *(.stub) 34 | /* .gnu.warning sections are handled specially by elf32.em. */ 35 | *(.gnu.warning) 36 | *(.gnu.linkonce.t*) 37 | *(.glue_7) 38 | *(.glue_7t) 39 | . = ALIGN(4); /* REQUIRED. LD is flaky without it. */ 40 | } >memregion = 0xff 41 | 42 | .fini : 43 | { 44 | KEEP (*(.fini)) 45 | } >memregion =0xff 46 | 47 | __text_end = . ; 48 | 49 | .rodata : 50 | { 51 | *(.rodata) 52 | *all.rodata*(*) 53 | *(.roda) 54 | *(.rodata.*) 55 | *(.gnu.linkonce.r*) 56 | SORT(CONSTRUCTORS) 57 | . = ALIGN(4); /* REQUIRED. LD is flaky without it. */ 58 | } >memregion = 0xff 59 | 60 | .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >memregion 61 | __exidx_start = .; 62 | .ARM.exidx : { *(.ARM.exidx* .gnu.linkonce.armexidx.*) } >memregion 63 | __exidx_end = .; 64 | 65 | /* Ensure the __preinit_array_start label is properly aligned. We 66 | could instead move the label definition inside the section, but 67 | the linker would then create the section even if it turns out to 68 | be empty, which isn't pretty. */ 69 | . = ALIGN(32 / 8); 70 | PROVIDE (__preinit_array_start = .); 71 | .preinit_array : { KEEP (*(.preinit_array)) } >memregion = 0xff 72 | PROVIDE (__preinit_array_end = .); 73 | PROVIDE (__init_array_start = .); 74 | .init_array : { KEEP (*(.init_array)) } >memregion = 0xff 75 | PROVIDE (__init_array_end = .); 76 | PROVIDE (__fini_array_start = .); 77 | .fini_array : { KEEP (*(.fini_array)) } >memregion = 0xff 78 | PROVIDE (__fini_array_end = .); 79 | 80 | .ctors : 81 | { 82 | /* gcc uses crtbegin.o to find the start of the constructors, so 83 | we make sure it is first. Because this is a wildcard, it 84 | doesn't matter if the user does not actually link against 85 | crtbegin.o; the linker won't look for a file to match a 86 | wildcard. The wildcard also means that it doesn't matter which 87 | directory crtbegin.o is in. */ 88 | KEEP (*crtbegin.o(.ctors)) 89 | KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) 90 | KEEP (*(SORT(.ctors.*))) 91 | KEEP (*(.ctors)) 92 | . = ALIGN(4); /* REQUIRED. LD is flaky without it. */ 93 | } >memregion = 0xff 94 | 95 | .dtors : 96 | { 97 | KEEP (*crtbegin.o(.dtors)) 98 | KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) 99 | KEEP (*(SORT(.dtors.*))) 100 | KEEP (*(.dtors)) 101 | . = ALIGN(4); /* REQUIRED. LD is flaky without it. */ 102 | } >memregion = 0xff 103 | 104 | .eh_frame : 105 | { 106 | KEEP (*(.eh_frame)) 107 | . = ALIGN(4); /* REQUIRED. LD is flaky without it. */ 108 | } >memregion = 0xff 109 | 110 | .gcc_except_table : 111 | { 112 | *(.gcc_except_table) 113 | . = ALIGN(4); /* REQUIRED. LD is flaky without it. */ 114 | } >memregion = 0xff 115 | .jcr : { KEEP (*(.jcr)) } >memregion = 0 116 | .got : { *(.got.plt) *(.got) } >memregion = 0 117 | 118 | 119 | .memregion ALIGN(4) : 120 | { 121 | __memregion_start = ABSOLUTE(.) ; 122 | *(.memregion) 123 | *memregion.*(.text) 124 | . = ALIGN(4); /* REQUIRED. LD is flaky without it. */ 125 | __memregion_end = ABSOLUTE(.) ; 126 | } >memregion = 0xff 127 | 128 | 129 | .data ALIGN(4) : { 130 | __data_start = ABSOLUTE(.); 131 | *(.data) 132 | *(.data.*) 133 | *(.gnu.linkonce.d*) 134 | CONSTRUCTORS 135 | . = ALIGN(4); 136 | __data_end = ABSOLUTE(.) ; 137 | } >memregion = 0xff 138 | 139 | 140 | 141 | .bss ALIGN(4) : 142 | { 143 | __bss_start = ABSOLUTE(.); 144 | __bss_start__ = ABSOLUTE(.); 145 | *(.dynbss) 146 | *(.gnu.linkonce.b*) 147 | *(.bss*) 148 | *(COMMON) 149 | . = ALIGN(4); /* REQUIRED. LD is flaky without it. */ 150 | } >memregion 151 | 152 | __bss_end = . ; 153 | __bss_end__ = . ; 154 | 155 | _end = . ; 156 | __end__ = . ; 157 | PROVIDE (end = _end); 158 | 159 | /* Stabs debugging sections. */ 160 | .stab 0 : { *(.stab) } 161 | .stabstr 0 : { *(.stabstr) } 162 | .stab.excl 0 : { *(.stab.excl) } 163 | .stab.exclstr 0 : { *(.stab.exclstr) } 164 | .stab.index 0 : { *(.stab.index) } 165 | .stab.indexstr 0 : { *(.stab.indexstr) } 166 | .comment 0 : { *(.comment) } 167 | /* DWARF debug sections. 168 | Symbols in the DWARF debugging sections are relative to the beginning 169 | of the section so we begin them at 0. */ 170 | /* DWARF 1 */ 171 | .debug 0 : { *(.debug) } 172 | .line 0 : { *(.line) } 173 | /* GNU DWARF 1 extensions */ 174 | .debug_srcinfo 0 : { *(.debug_srcinfo) } 175 | .debug_sfnames 0 : { *(.debug_sfnames) } 176 | /* DWARF 1.1 and DWARF 2 */ 177 | .debug_aranges 0 : { *(.debug_aranges) } 178 | .debug_pubnames 0 : { *(.debug_pubnames) } 179 | /* DWARF 2 */ 180 | .debug_info 0 : { *(.debug_info) } 181 | .debug_abbrev 0 : { *(.debug_abbrev) } 182 | .debug_line 0 : { *(.debug_line) } 183 | .debug_frame 0 : { *(.debug_frame) } 184 | .debug_str 0 : { *(.debug_str) } 185 | .debug_loc 0 : { *(.debug_loc) } 186 | .debug_macinfo 0 : { *(.debug_macinfo) } 187 | /* SGI/MIPS DWARF 2 extensions */ 188 | .debug_weaknames 0 : { *(.debug_weaknames) } 189 | .debug_funcnames 0 : { *(.debug_funcnames) } 190 | .debug_typenames 0 : { *(.debug_typenames) } 191 | .debug_varnames 0 : { *(.debug_varnames) } 192 | .stack 0x80000 : { _stack = .; *(.stack) } 193 | /* These must appear regardless of . */ 194 | } 195 | -------------------------------------------------------------------------------- /3dshaxarm11_ctrserver/3dshax11_start.s: -------------------------------------------------------------------------------- 1 | .global _init 2 | .global _fini 3 | .global launchcode_kernelmode 4 | .global call_arbitaryfuncptr 5 | .global svcControlProcessMemory 6 | 7 | .type _init STT_FUNC 8 | .type _fini STT_FUNC 9 | .type launchcode_kernelmode STT_FUNC 10 | .type call_arbitaryfuncptr STT_FUNC 11 | .type svcControlProcessMemory STT_FUNC 12 | 13 | .global PROCESSNAME 14 | .global arm11kernel_textvaddr 15 | 16 | @--------------------------------------------------------------------------------- 17 | @ 3DS processor selection 18 | @--------------------------------------------------------------------------------- 19 | .cpu mpcore 20 | @--------------------------------------------------------------------------------- 21 | 22 | @--------------------------------------------------------------------------------- 23 | .section ".init" 24 | .global _start, __service_ptr, __apt_appid, __heap_size, __linear_heap_size, __system_arglist, __system_runflags 25 | @--------------------------------------------------------------------------------- 26 | .align 2 27 | .arm 28 | @--------------------------------------------------------------------------------- 29 | _start: 30 | @--------------------------------------------------------------------------------- 31 | b startup 32 | .ascii "_prm" 33 | __service_ptr: 34 | .word 0 @ Pointer to service handle override list -- if non-NULL it is assumed that we have been launched from a homebrew launcher 35 | __apt_appid: 36 | .word 0x300 @ Program APPID 37 | __heap_size: 38 | .word 24*1024*1024 @ Default heap size (24 MiB) 39 | __linear_heap_size: 40 | .word 32*1024*1024 @ Default linear heap size (32 MiB) 41 | __system_arglist: 42 | .word 0 @ Pointer to argument list (argc (u32) followed by that many NULL terminated strings) 43 | __system_runflags: 44 | .word 0 @ Flags to signal runtime restrictions to ctrulib 45 | 46 | .word 0x58584148 @ "HAXX", indicating that the following parameters can be set by the code loader. 47 | 48 | PROCESSNAME: 49 | .word 0x434f5250 @ "PROC" 50 | .word 0x454d414e @ "NAME" 51 | 52 | arm11kernel_textvaddr: 53 | .word 0x5458544b 54 | 55 | startup: 56 | push {r4, r5, r6, r7, r8, lr} 57 | 58 | adr r0, PROCESSNAME 59 | ldr r1, [r0, #0] 60 | ldr r2, [r0, #4] 61 | ldr r0, =0x434f5250 62 | ldr r3, =0x454d414e 63 | cmp r1, r0 64 | cmpeq r2, r3 65 | beq clearbss @ When the PROCESSNAME wasn't changed, assume we're running under an actual CXI. 66 | 67 | ldr r1, =0xFFFF8001 68 | svc 0x27 69 | mov r6, r1 70 | cmp r0, #0 71 | bne fail 72 | 73 | ldr r3, =__end__ 74 | ldr r4, =0xfff 75 | add r3, r3, r4 76 | lsr r3, r3, #12 77 | lsl r3, r3, #12 78 | mov r8, r3 79 | 80 | ldr r7, =0x00100000 81 | 82 | change_permissions_lp: 83 | mov r0, r6 84 | mov r1, r7 85 | mov r2, #0 86 | ldr r3, =0x1000 87 | mov r4, #6 88 | mov r5, #7 89 | svc 0x70 90 | cmp r0, #0 91 | bne fail 92 | ldr r1, =0x1000 93 | add r7, r7, r1 94 | cmp r7, r8 95 | blt change_permissions_lp 96 | 97 | clearbss: 98 | ldr r1, =__bss_start__ @ Clear .bss 99 | ldr r2, =__bss_end__ 100 | mov r3, #0 101 | 102 | bss_clr: 103 | cmp r1, r2 104 | beq _start_done 105 | str r3, [r1] 106 | add r1, r1, #4 107 | b bss_clr 108 | 109 | _start_done: 110 | pop {r4, r5, r6, r7, r8, lr} 111 | 112 | @ System initialization 113 | mov r0, lr 114 | bl initSystem 115 | 116 | @ Set up argc/argv arguments for main() 117 | ldr r0, =__system_argc 118 | ldr r1, =__system_argv 119 | ldr r0, [r0] 120 | ldr r1, [r1] 121 | 122 | @ Jump to user code 123 | ldr r3, =main 124 | ldr lr, =__ctru_exit 125 | bx r3 126 | 127 | .pool 128 | 129 | _init: 130 | bx lr 131 | 132 | _fini: 133 | bx lr 134 | 135 | fail: 136 | .word 0xffffffff 137 | 138 | kernelmodestub: 139 | cpsid i @ Disable IRQs 140 | push {lr} 141 | mov r0, r3 142 | blx r4 143 | mov r2, r0 144 | pop {lr} 145 | //cpsie i @ Enable IRQs (don't re-enable IRQs since the svc-handler will just disable IRQs after the SVC returns) 146 | bx lr 147 | 148 | launchcode_kernelmode: 149 | push {r4, lr} 150 | mov r4, r0 151 | mov r3, r1 152 | adr r0, kernelmodestub 153 | svc 0x7b 154 | mov r0, r2 155 | pop {r4, pc} 156 | 157 | call_arbitaryfuncptr: 158 | push {r4, r5, r6, r7, r8, lr} 159 | mov r7, r0 160 | mov r8, r1 161 | ldm r8, {r0, r1, r2, r3, r4, r5, r6} 162 | blx r7 163 | stm r8, {r0, r1, r2, r3, r4, r5, r6} 164 | pop {r4, r5, r6, r7, r8, pc} 165 | 166 | .global initsrvhandle_allservices 167 | .type initsrvhandle_allservices, %function 168 | initsrvhandle_allservices: @ Init a srv handle which has access to all services. 169 | push {r4, r5, r6, r7, lr} 170 | sub sp, sp, #0x20 171 | 172 | mov r7, #0 173 | 174 | mov r0, sp 175 | ldr r1, =0xffff8001 176 | bl svcGetProcessId 177 | 178 | mov r7, r0 179 | cmp r7, #0 180 | bne initsrvhandle_allservices_end 181 | 182 | mov r4, #0 183 | ldr r5, [sp, #0] 184 | mov r6, #0 185 | 186 | adr r0, kernelmode_searchval_overwrite @ r4=address(0=cur kprocess), r5=searchval, r6=val to write 187 | svc 0x7b @ Overwrite kprocess PID with 0. 188 | 189 | mov r4, r3 190 | ldr r5, [sp, #0] 191 | 192 | bl srvInit 193 | mov r7, r0 194 | 195 | adr r0, kernelmode_writeval @ r4=addr, r5=u32val 196 | svc 0x7b @ Restore the original PID. 197 | 198 | initsrvhandle_allservices_end: 199 | mov r0, r7 200 | add sp, sp, #0x20 201 | pop {r4, r5, r6, r7, pc} 202 | .pool 203 | 204 | kernelmode_searchval_overwrite: @ r4=kprocess, r5=searchval, r6=val to write. out r3 = overwritten addr. 205 | cpsid i @ disable IRQs 206 | push {r4, r5, r6} 207 | 208 | cmp r4, #0 209 | bne kernelmode_searchval_overwrite_lp 210 | ldr r4, =0xffff9004 211 | ldr r4, [r4] 212 | 213 | kernelmode_searchval_overwrite_lp: 214 | ldr r0, [r4] 215 | cmp r0, r5 216 | addne r4, r4, #4 217 | bne kernelmode_searchval_overwrite_lp 218 | 219 | str r6, [r4] 220 | mov r3, r4 221 | pop {r4, r5, r6} 222 | bx lr 223 | .pool 224 | 225 | kernelmode_writeval: @ r4=addr, r5=u32val 226 | cpsid i @ disable IRQs 227 | str r5, [r4] 228 | bx lr 229 | 230 | .global kernelmode_cachestuff 231 | .type kernelmode_cachestuff, %function 232 | kernelmode_cachestuff: 233 | mov r0, #0 234 | mcr p15, 0, r0, c7, c14, 0 @ "Clean and Invalidate Entire Data Cache" 235 | mcr p15, 0, r0, c7, c10, 5 @ "Data Memory Barrier" 236 | mcr p15, 0, r0, c7, c5, 0 @ "Invalidate Entire Instruction Cache. Also flushes the branch target cache" 237 | mcr p15, 0, r0, c7, c5, 4 @ "Flush Prefetch Buffer" 238 | mcr p15, 0, r0, c7, c5, 6 @ "Flush Entire Branch Target Cache" 239 | mcr p15, 0, r0, c7, c10, 4 @ "Data Synchronization Barrier" 240 | bx lr 241 | 242 | -------------------------------------------------------------------------------- /3dshaxarm9/ctr-gamecard.c: -------------------------------------------------------------------------------- 1 | #ifdef ENABLE_GAMECARD 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include <3ds.h> 8 | 9 | #include "arm9fs.h" 10 | 11 | extern u32 proc9_textstartaddr; 12 | 13 | u32 *gamecard_archiveobj = NULL; 14 | u32 (*funcptr_ctrcard_cmdc6)(u32*, u32*) = NULL; 15 | u32 *gamecard_stateptr = NULL; 16 | 17 | u32 *locate_cmdhandler_code(u32 *ptr, u32 size, u32 *pool_cmpdata, u32 pool_cmpdata_wordcount, u32 locate_ldrcc); 18 | u32 parse_branch(u32 branchaddr, u32 branchval); 19 | 20 | /*u32 gamecardslot_getpowerstate() 21 | { 22 | u32 (*funcptr)() = (void*)0x806238b; 23 | return funcptr(); 24 | } 25 | 26 | u32 gamecardslot_poweron() 27 | { 28 | u32 (*funcptr)() = (void*)0x8062f79; 29 | return funcptr(); 30 | }*/ 31 | 32 | /*void patch_mountcontent() 33 | { 34 | u32 (*funcptr)(u32*, u64*, u8, u32, u64, u32) = (void*)0x8061d11; //archive_mountcontent 35 | u64 archivehandle=0; 36 | u64 programID = 0x0000000000000000LL;//0x00040000000b6e00LL; 37 | u8 mediatype = 0;//1; 38 | u32 tmpdata[3]; 39 | 40 | while(*((vu16*)0x10146000) & 2);//Wait for button B to be pressed. 41 | 42 | *((u16*)0x805b6b4) = 0x2000; 43 | 44 | //tmpdata[0] = gamecardslot_getpowerstate(); 45 | //tmpdata[1] = gamecardslot_poweron(); 46 | 47 | tmpdata[2] = funcptr(&pxifs_state[0x2f1c>>2], &archivehandle, mediatype, 0, programID, 0); 48 | dumpmem(tmpdata, 12); 49 | }*/ 50 | 51 | /*void wait_systicks(u32 ticks) 52 | { 53 | u64 start, cur; 54 | 55 | start = svcGetSystemTick(); 56 | 57 | while(1) 58 | { 59 | cur = svcGetSystemTick(); 60 | if((u32)(cur - start) >= ticks)break; 61 | } 62 | } 63 | 64 | u32 ctrcard_cmdbf_begindataread(u64 mediaoffset, u16 total_datablocks) 65 | { 66 | u32 (*funcptr)(u32*, u32, u64, u16) = (void*)0x807428d; 67 | u32 ctx[5]; 68 | ctx[0] = 0; 69 | ctx[1] = 0; 70 | ctx[2] = 0; 71 | ctx[3] = 0; 72 | ctx[4] = 0; 73 | 74 | return funcptr(ctx, 0, mediaoffset, total_datablocks); 75 | }*/ 76 | 77 | void locatefunc_ctrcard_cmdc6() 78 | { 79 | u32 *ptr; 80 | u32 pos; 81 | u32 pool_cmpdata[6] = {0xd9001830, 0x000100c6, 0x00010041, 0x00020284, 0x00020041, 0x00030284}; 82 | 83 | ptr = locate_cmdhandler_code((u32*)proc9_textstartaddr, 0x080ff000-proc9_textstartaddr, pool_cmpdata, 6, 1); 84 | if(ptr==NULL)return; 85 | 86 | ptr = (u32*)ptr[0x6];//ptr = addr of code in pxips9 cmdhandler func for GetRomId. 87 | pos = 0; 88 | 89 | while(1) 90 | { 91 | if((ptr[pos] >> 24) == 0xeb)break; 92 | pos++; 93 | } 94 | 95 | ptr = (u32*)parse_branch((u32)&ptr[pos], 0);//ptr = address of the function handling this command. 96 | pos = 0; 97 | 98 | while(1) 99 | { 100 | if((ptr[pos] >> 24) == 0xfa)break; 101 | pos++; 102 | } 103 | 104 | funcptr_ctrcard_cmdc6 = (void*)(parse_branch((u32)&ptr[pos], 0) | 1); 105 | 106 | while(1)//Locate the first word of the .pool. 107 | { 108 | if(ptr[pos] == 0xe8bd8010)break; 109 | pos++; 110 | } 111 | pos++; 112 | 113 | gamecard_stateptr = (u32*)ptr[pos]; 114 | } 115 | 116 | u32 ctrcard_cmdc6(u32 *outbuf) 117 | { 118 | if(funcptr_ctrcard_cmdc6==NULL || gamecard_stateptr==NULL) 119 | { 120 | locatefunc_ctrcard_cmdc6(); 121 | if(funcptr_ctrcard_cmdc6==NULL || gamecard_stateptr==NULL)return ~0; 122 | } 123 | 124 | return funcptr_ctrcard_cmdc6(gamecard_stateptr, outbuf); 125 | } 126 | 127 | u32 gamecard_initarchiveobj() 128 | { 129 | u32 lowpath[3]; 130 | u32 lowpathdata[4]; 131 | 132 | lowpath[0] = 2;//type 133 | lowpath[1] = (u32)lowpathdata;//dataptr 134 | lowpath[2] = 0x10;//size 135 | 136 | lowpathdata[0] = 0x0;//programID-low 137 | lowpathdata[1] = 0x0;//programID-high 138 | lowpathdata[2] = 0x2;//mediatype 139 | lowpathdata[3] = 0x0;//reserved 140 | 141 | return pxifs_openarchive(&gamecard_archiveobj, 0x2345678A, lowpath); 142 | } 143 | 144 | u32 gamecard_readsectors(u32 *outbuf, u32 sector, u32 sectorcount) 145 | { 146 | u32 ret=0; 147 | u32 *ptr; 148 | 149 | if(gamecard_archiveobj==NULL) 150 | { 151 | ret = gamecard_initarchiveobj(); 152 | if(ret!=0)return ret; 153 | if(gamecard_archiveobj==NULL)return ~0; 154 | } 155 | 156 | ptr = (u32*)(gamecard_archiveobj[0x24>>2]+8); 157 | ptr = (u32*)*ptr; 158 | 159 | return archive_rwsectors(ptr, outbuf, sectorcount, sector, 0); 160 | } 161 | 162 | /*u32 read_gamecardsector(u64 mediaoffset, u32 *outbuf, u32 readsize, u16 total_datablocks) 163 | { 164 | u32 ret, pos, val; 165 | 166 | ret = ctrcard_cmdbf_begindataread(mediaoffset, total_datablocks); 167 | if(ret!=1)return ret; 168 | 169 | pos = 0; 170 | while(1) 171 | { 172 | if(*((vu32*)0x10004000) & (1<<27)) 173 | { 174 | val = *((vu32*)0x10004030); 175 | outbuf[pos] = val; 176 | pos++; 177 | 178 | if(pos >= (readsize>>2))break; 179 | } 180 | 181 | if(*((vu32*)0x10004000) & 0x10)return 0; 182 | } 183 | 184 | //while(*((vu32*)0x10004000) & (1<<31))val = *((vu32*)0x10004030); 185 | 186 | wait_systicks(4000); 187 | 188 | return 1; 189 | }*/ 190 | 191 | /*void read_gamecard() 192 | { 193 | u32 *fileobj = NULL; 194 | u64 mediaoffset = 0x000000 >> 9; 195 | u32 ret; 196 | u32 pos=0; 197 | u32 val = 0; 198 | u32 *sectorbuf = (u32*)0x20000000; 199 | u32 dumpsize = 0x100000; 200 | 201 | if(openfile(sdarchive_obj, 4, dump_filepath, 0x22, 7, &fileobj)!=0)return; 202 | 203 | *((u16*)0x807431c) = 0x2302; 204 | svcFlushProcessDataCache((u32*)0x807431c, 4);//patch the arm9fw code for ctrcard_cmdbf_begindataread() so that it doesn't set the REG_CTRCARDCNT IRQ enable bit. 205 | 206 | //sectorbuf[0] = ctrcard_cmdc6(§orbuf[1]); 207 | //if(filewrite(fileobj, sectorbuf, 0x44, 0)!=0)return; 208 | 209 | //memset(framebuf_addr, 0xffffffff, 0x46500); 210 | //memset(&framebuf_addr[(0x46500+0x10)>>2], 0xffffffff, 0x46500); 211 | 212 | memset(sectorbuf, 0x0, dumpsize); 213 | ret = read_gamecardsector(mediaoffset, sectorbuf, dumpsize, dumpsize>>9); 214 | if(ret!=1)return; 215 | if(filewrite(fileobj, sectorbuf, dumpsize, (u32)(mediaoffset<<9))!=0)return; 216 | 217 | //ret = read_gamecardsector(mediaoffset + (dumpsize>>9), sectorbuf, dumpsize, dumpsize>>9); 218 | //if(filewrite(fileobj, sectorbuf, dumpsize, dumpsize)!=0)return; 219 | 220 | //mediaoffset = sectorbuf[0x120>>2]; 221 | */ 222 | /*mediaoffset = 0x27D84800>>9;//0x20; 223 | for(pos=0; pos<((0x28E9FA00 - 0x27D84800)>>9); pos+=(dumpsize>>9)) 224 | { 225 | memset(sectorbuf, 0, dumpsize); 226 | ret = read_gamecardsector(mediaoffset, sectorbuf, dumpsize, dumpsize>>9); 227 | if(ret!=1)return; 228 | if(filewrite(fileobj, sectorbuf, dumpsize, pos << 9)!=0)return; 229 | 230 | svcSleepThread(1000000000LL); 231 | 232 | memset(framebuf_addr, val, 0x46500); 233 | memset(&framebuf_addr[(0x46500+0x10)>>2], val, 0x46500); 234 | 235 | val +=0x456789ab; 236 | 237 | mediaoffset+= dumpsize>>9; 238 | }*/ 239 | 240 | //memset(framebuf_addr, 0x20202020, 0x46500); 241 | //memset(&framebuf_addr[(0x46500+0x10)>>2], 0x20202020, 0x46500); 242 | 243 | //*((u16*)0x807431c) = 0x2303; 244 | //svcFlushProcessDataCache((u32*)0x807431c, 4); 245 | //} 246 | 247 | #endif 248 | 249 | -------------------------------------------------------------------------------- /3dshaxarm9/yls8_aes.c: -------------------------------------------------------------------------------- 1 | #ifdef ENABLEAES 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include <3ds.h> 8 | 9 | #include "arm9_svc.h" 10 | 11 | #define REG_AESCNT *((vu32*)0x10009000) 12 | #define REG_AESBLKCNT *((vu32*)0x10009004) 13 | #define REG_AESWRFIFO *((vu32*)0x10009008) 14 | #define REG_AESRDFIFO *((vu32*)0x1000900C) 15 | #define REG_AESKEYSEL *((vu8*)0x10009010) 16 | #define REG_AESKEYCNT *((vu8*)0x10009011) 17 | #define REG_AESCTR ((vu32*)0x10009020) 18 | #define REG_AESMAC ((vu32*)0x10009030) 19 | #define REG_AESKEY0 ((vu32*)0x10009040) 20 | #define REG_AESKEY1 ((vu32*)0x10009070) 21 | #define REG_AESKEY2 ((vu32*)0x100090A0) 22 | #define REG_AESKEY3 ((vu32*)0x100090D0) 23 | #define REG_AESKEYFIFO *((vu32*)0x10009100) 24 | #define REG_AESKEYXFIFO *((vu32*)0x10009104) 25 | #define REG_AESKEYYFIFO *((vu32*)0x10009108) 26 | #define REG_AESKEYFIFO_PTR ((vu32*)0x10009100) 27 | #define REG_AESKEYXFIFO_PTR ((vu32*)0x10009104) 28 | #define REG_AESKEYYFIFO_PTR ((vu32*)0x10009108) 29 | 30 | #define AES_CHUNKSIZE 0xffff0 31 | 32 | extern u32 proc9_textstartaddr; 33 | 34 | u32 aesiv[4]; 35 | 36 | void (*funcptr_aesmutex_enter)() = NULL; 37 | void (*funcptr_aesmutex_leave)() = NULL; 38 | 39 | void aesengine_waitdone(); 40 | void aesengine_flushfifo(); 41 | 42 | void ctr_add_counter( u8 *ctr, u32 carry ); 43 | 44 | u32 parse_branch(u32 branchaddr, u32 branchval); 45 | 46 | void aes_mutex_ptrsinitialize() 47 | { 48 | u32 *ptr = (u32*)proc9_textstartaddr; 49 | u32 *ptr2; 50 | u32 pos; 51 | u32 pos2; 52 | 53 | for(pos=0; pos<(0x080ff000-proc9_textstartaddr)>>2; pos++) 54 | { 55 | if(ptr[pos]==0xe8bd8008 && ptr[pos+1]==0x10011000)//"pop {r3, pc}" + reg addr 56 | { 57 | pos--; 58 | 59 | for(pos2=0; pos2<0x40; pos2++)//Find the push instruction. 60 | { 61 | if(ptr[pos-pos2] == 0xe92d4008)break; 62 | if(pos2==0x3f)return; 63 | } 64 | 65 | for(; pos2>0; pos2--)//Find the first blx instruction. 66 | { 67 | if((ptr[pos-pos2] >> 24) == 0xfa)break; 68 | if(pos2==0)return; 69 | } 70 | pos2--; 71 | if((ptr[pos-pos2] >> 24) != 0xfa)return; 72 | 73 | ptr2 = (u32*)(parse_branch((u32)&ptr[pos-pos2], 0) | 1); 74 | 75 | ptr = (u32*)(parse_branch((u32)&ptr[pos], 0) | 1); 76 | 77 | funcptr_aesmutex_leave = (void*)ptr; 78 | 79 | funcptr_aesmutex_enter = (void*)((u32)ptr2); 80 | return; 81 | } 82 | } 83 | } 84 | 85 | void aes_mutexenter() 86 | { 87 | if(funcptr_aesmutex_enter==NULL) 88 | { 89 | aes_mutex_ptrsinitialize(); 90 | if(funcptr_aesmutex_enter==NULL)return; 91 | } 92 | 93 | funcptr_aesmutex_enter(); 94 | } 95 | 96 | void aes_mutexleave() 97 | { 98 | if(funcptr_aesmutex_leave==NULL) 99 | { 100 | aes_mutex_ptrsinitialize(); 101 | if(funcptr_aesmutex_leave==NULL)return; 102 | } 103 | 104 | funcptr_aesmutex_leave(); 105 | } 106 | 107 | void aes_set_ctr(u32 *ctr) 108 | { 109 | u32 i; 110 | 111 | if(ctr)memcpy(aesiv, ctr, 16); 112 | if(ctr==NULL)ctr = aesiv; 113 | 114 | if((REG_AESCNT >> 23) & 4) 115 | { 116 | for(i=0; i<4; i++)REG_AESCTR[i] = ctr[3-i]; 117 | } 118 | else 119 | { 120 | for(i=0; i<4; i++)REG_AESCTR[i] = ctr[i]; 121 | } 122 | } 123 | 124 | void aes_set_iv(u32 *iv) 125 | { 126 | aes_set_ctr(iv); 127 | } 128 | 129 | void aes_select_key(u32 keyslot) 130 | { 131 | REG_AESKEYSEL = keyslot; 132 | REG_AESCNT |= 1<<26; 133 | 134 | if(keyslot<4) 135 | { 136 | REG_AESCNT &= ~(0xf<<22); 137 | //REG_AESCNT |= (0xa<<22); 138 | } 139 | else 140 | { 141 | REG_AESCNT |= (0xf<<22); 142 | } 143 | } 144 | 145 | void aes_set_keydata(u32 keyslot, u32 *key, u32 keytype) 146 | { 147 | u32 *ptr = NULL; 148 | u32 i; 149 | 150 | if(keyslot<4) 151 | { 152 | REG_AESCNT &= ~(0xf<<22); 153 | //REG_AESCNT |= (0xa<<22); 154 | } 155 | else 156 | { 157 | REG_AESCNT |= (0xf<<22); 158 | } 159 | 160 | REG_AESKEYCNT = (REG_AESKEYCNT & ~0x3f) | keyslot | 0x80; 161 | 162 | if(keytype>2)return; 163 | if(keytype==0)ptr = (u32*)REG_AESKEYFIFO_PTR; 164 | if(keytype==1)ptr = (u32*)REG_AESKEYXFIFO_PTR; 165 | if(keytype==2)ptr = (u32*)REG_AESKEYYFIFO_PTR; 166 | 167 | if(keyslot>=4) 168 | { 169 | for(i=0; i<4; i++)*ptr = key[i]; 170 | } 171 | else 172 | { 173 | ptr = (u32*)REG_AESKEY0; 174 | 175 | ptr = &ptr[0xc*keyslot + keytype*4]; 176 | for(i=0; i<4; i++)ptr[i] = key[i]; 177 | } 178 | } 179 | 180 | void aes_set_ykey(u32 keyslot, u32 *key) 181 | { 182 | aes_set_keydata(keyslot, key, 2); 183 | } 184 | 185 | void aes_set_xkey(u32 keyslot, u32 *key) 186 | { 187 | aes_set_keydata(keyslot, key, 1); 188 | } 189 | 190 | void aes_set_key(u32 keyslot, u32 *key) 191 | { 192 | aes_set_keydata(keyslot, key, 0); 193 | } 194 | 195 | void aesengine_initoperation(u32 mode, u16 aesblks, u16 macassocblks) 196 | { 197 | u32 val = (REG_AESCNT >> 22) & 0xf;//Save the endian/word-order values. 198 | 199 | REG_AESCNT = 0; 200 | REG_AESBLKCNT = macassocblks | (aesblks<<16); 201 | 202 | aesengine_flushfifo(); 203 | REG_AESCNT |= (val << 22) | ((mode & 0x7) << 27) | (1<<31); 204 | } 205 | 206 | void aesengine_cryptdata_wrap(u32 *output, u32 *input, u32 size) 207 | { 208 | u32 pos, i; 209 | u32 chunkwords; 210 | 211 | pos=0; 212 | 213 | while(size>0) 214 | { 215 | chunkwords = size>>2; 216 | if(chunkwords>0x10)chunkwords = 0x10; 217 | 218 | while((REG_AESCNT & 0x1f) != 0); 219 | 220 | for(i=0; i> 5) != chunkwords); 223 | 224 | for(i=0; iAES_CHUNKSIZE)chunksize = AES_CHUNKSIZE; 242 | 243 | aes_set_iv(NULL); 244 | 245 | aesengine_initoperation(mode, chunksize>>4, 0); 246 | 247 | if(mode==4)//AES-CBC decrypt 248 | { 249 | memcpy(aesiv, &input[(pos + chunksize - 0x10)>>2], 0x10); 250 | } 251 | else if(mode!=5)//AES-CTR 252 | { 253 | ctr_add_counter((u8*)aesiv, chunksize>>4); 254 | } 255 | 256 | aesengine_cryptdata_wrap(&output[pos>>2], &input[pos>>2], chunksize); 257 | 258 | if(mode==5)//AES-CBC encrypt 259 | { 260 | memcpy(aesiv, &output[(pos + chunksize - 0x10)>>2], 0x10); 261 | } 262 | } 263 | 264 | aesengine_flushfifo(); 265 | } 266 | 267 | void aesengine_waitdone() 268 | { 269 | while(REG_AESCNT>>31); 270 | } 271 | 272 | void aesengine_flushfifo() 273 | { 274 | REG_AESCNT |= 0xc00; 275 | } 276 | 277 | void aes_ctr_crypt(u32 *buf, u32 size) 278 | { 279 | aesengine_cryptdata(2, buf, buf, size, 0); 280 | } 281 | 282 | void aes_cbc_decrypt(u32 *buf, u32 size) 283 | { 284 | aesengine_cryptdata(4, buf, buf, size, 0); 285 | } 286 | 287 | void aes_cbc_encrypt(u32 *buf, u32 size) 288 | { 289 | aesengine_cryptdata(5, buf, buf, size, 0); 290 | } 291 | 292 | void ctr_add_counter( u8 *ctr, u32 carry )//Based on the ctrtool function. 293 | { 294 | u32 counter[4]; 295 | u32 sum; 296 | int i; 297 | 298 | for(i=0; i<4; i++) 299 | counter[i] = (ctr[i*4+0]<<24) | (ctr[i*4+1]<<16) | (ctr[i*4+2]<<8) | (ctr[i*4+3]<<0); 300 | 301 | for(i=3; i>=0; i--) 302 | { 303 | sum = counter[i] + carry; 304 | 305 | if (sum < counter[i]) 306 | carry = 1; 307 | else 308 | carry = 0; 309 | 310 | counter[i] = sum; 311 | } 312 | 313 | for(i=0; i<4; i++) 314 | { 315 | ctr[i*4+0] = counter[i]>>24; 316 | ctr[i*4+1] = counter[i]>>16; 317 | ctr[i*4+2] = counter[i]>>8; 318 | ctr[i*4+3] = counter[i]>>0; 319 | } 320 | } 321 | 322 | #endif 323 | 324 | -------------------------------------------------------------------------------- /Makefile_ctrserver.arm11: -------------------------------------------------------------------------------- 1 | #--------------------------------------------------------------------------------- 2 | .SUFFIXES: 3 | #--------------------------------------------------------------------------------- 4 | 5 | ifeq ($(strip $(DEVKITARM)),) 6 | $(error "Please set DEVKITARM in your environment. export DEVKITARM=devkitARM") 7 | endif 8 | 9 | TOPDIR ?= $(CURDIR) 10 | include $(DEVKITARM)/3ds_rules 11 | 12 | #--------------------------------------------------------------------------------- 13 | # TARGET is the name of the output 14 | # BUILD is the directory where object files & intermediate files will be placed 15 | # SOURCES is a list of directories containing source code 16 | # DATA is a list of directories containing data files 17 | # INCLUDES is a list of directories containing header files 18 | # 19 | # NO_SMDH: if set to anything, no SMDH file is generated. 20 | # APP_TITLE is the name of the app stored in the SMDH file (Optional) 21 | # APP_DESCRIPTION is the description of the app stored in the SMDH file (Optional) 22 | # APP_AUTHOR is the author of the app stored in the SMDH file (Optional) 23 | # ICON is the filename of the icon (.png), relative to the project folder. 24 | # If not set, it attempts to use one of the following (in this order): 25 | # - .png 26 | # - icon.png 27 | # - /default_icon.png 28 | #--------------------------------------------------------------------------------- 29 | TARGET := 3dshax_arm11_ctrserver 30 | BUILD := build11 31 | SOURCES := 3dshaxarm11_ctrserver 3dshax11_common 3dshax_common 32 | INCLUDES := include 3dshax11_common 3dshax_common 33 | DATA := 3dshaxarm11_ctrserver_data 34 | 35 | BINCPCMD := 36 | ifneq ($(strip $(OUTPATH)),) 37 | BINCPCMD := @cp $(OUTPUT).bin $(OUTPATH)/3dshax_arm11.bin 38 | endif 39 | 40 | #--------------------------------------------------------------------------------- 41 | # options for code generation 42 | #--------------------------------------------------------------------------------- 43 | ARCH := -flto -march=armv6k -mtune=mpcore -mfloat-abi=hard 44 | 45 | CFLAGS := -g -Wall -O2 -mword-relocations \ 46 | -fomit-frame-pointer -ffast-math \ 47 | $(ARCH) 48 | 49 | CFLAGS += $(INCLUDE) -DARM11 -D_3DS 50 | 51 | CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11 52 | 53 | ASFLAGS := -g $(ARCH) 54 | LDFLAGS = -nostartfiles -T$(DEVKITARM)/arm-none-eabi/lib/3dsx.ld -g $(ARCH) -Wl,-Map,$(notdir $*.map) 55 | 56 | LIBS := -lctru -lm 57 | 58 | #--------------------------------------------------------------------------------- 59 | # list of directories containing libraries, this must be the top level containing 60 | # include and lib 61 | #--------------------------------------------------------------------------------- 62 | LIBDIRS := $(CTRULIB) 63 | 64 | 65 | #--------------------------------------------------------------------------------- 66 | # no real need to edit anything past this point unless you need to add additional 67 | # rules for different file extensions 68 | #--------------------------------------------------------------------------------- 69 | ifneq ($(BUILD),$(notdir $(CURDIR))) 70 | #--------------------------------------------------------------------------------- 71 | 72 | export OUTPUT := $(CURDIR)/$(TARGET) 73 | export TOPDIR := $(CURDIR) 74 | 75 | export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \ 76 | $(foreach dir,$(DATA),$(CURDIR)/$(dir)) 77 | 78 | export DEPSDIR := $(CURDIR)/$(BUILD) 79 | 80 | CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) 81 | CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) 82 | SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) 83 | BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) 84 | 85 | #--------------------------------------------------------------------------------- 86 | # use CXX for linking C++ projects, CC for standard C 87 | #--------------------------------------------------------------------------------- 88 | ifeq ($(strip $(CPPFILES)),) 89 | #--------------------------------------------------------------------------------- 90 | export LD := $(CC) 91 | #--------------------------------------------------------------------------------- 92 | else 93 | #--------------------------------------------------------------------------------- 94 | export LD := $(CXX) 95 | #--------------------------------------------------------------------------------- 96 | endif 97 | #--------------------------------------------------------------------------------- 98 | 99 | export OFILES := $(addsuffix .o,$(BINFILES)) \ 100 | $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o) 101 | 102 | export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \ 103 | $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ 104 | -I$(CURDIR)/$(BUILD) 105 | 106 | export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) 107 | 108 | ifeq ($(strip $(ICON)),) 109 | icons := $(wildcard *.png) 110 | ifneq (,$(findstring $(TARGET).png,$(icons))) 111 | export APP_ICON := $(TOPDIR)/$(TARGET).png 112 | else 113 | ifneq (,$(findstring icon.png,$(icons))) 114 | export APP_ICON := $(TOPDIR)/icon.png 115 | endif 116 | endif 117 | else 118 | export APP_ICON := $(TOPDIR)/$(ICON) 119 | endif 120 | 121 | ifeq ($(strip $(NO_SMDH)),) 122 | export _3DSXFLAGS += --smdh=$(CURDIR)/$(TARGET).smdh 123 | endif 124 | 125 | .PHONY: $(BUILD) clean all 126 | 127 | #--------------------------------------------------------------------------------- 128 | all: $(BUILD) 129 | 130 | $(BUILD): 131 | @[ -d $@ ] || mkdir -p $@ 132 | @$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile_ctrserver.arm11 133 | 134 | #--------------------------------------------------------------------------------- 135 | clean: 136 | @echo clean ... 137 | @rm -fr $(BUILD) $(TARGET).3dsx $(OUTPUT).smdh $(TARGET).elf $(TARGET).bin 138 | 139 | 140 | #--------------------------------------------------------------------------------- 141 | else 142 | 143 | DEPENDS := $(OFILES:.o=.d) 144 | 145 | #--------------------------------------------------------------------------------- 146 | # main targets 147 | #--------------------------------------------------------------------------------- 148 | ifeq ($(strip $(NO_SMDH)),) 149 | $(OUTPUT).3dsx : $(OUTPUT).bin $(OUTPUT).elf $(OUTPUT).smdh 150 | else 151 | $(OUTPUT).3dsx : $(OUTPUT).bin $(OUTPUT).elf 152 | endif 153 | 154 | $(OUTPUT).elf : $(OFILES) 155 | 156 | $(OUTPUT).bin : $(OUTPUT).elf 157 | @$(OBJCOPY) -O binary $< $@ 158 | $(BINCPCMD) 159 | @echo built ... $(notdir $@) 160 | 161 | #--------------------------------------------------------------------------------- 162 | # you need a rule like this for each extension you use as binary data 163 | #--------------------------------------------------------------------------------- 164 | %.bin.o : %.bin 165 | #--------------------------------------------------------------------------------- 166 | @echo $(notdir $<) 167 | @$(bin2o) 168 | 169 | # WARNING: This is not the right way to do this! TODO: Do it right! 170 | #--------------------------------------------------------------------------------- 171 | %.vsh.o : %.vsh 172 | #--------------------------------------------------------------------------------- 173 | @echo $(notdir $<) 174 | @python $(AEMSTRO)/aemstro_as.py $< ../$(notdir $<).shbin 175 | @bin2s ../$(notdir $<).shbin | $(PREFIX)as -o $@ 176 | @echo "extern const u8" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"_end[];" > `(echo $(notdir $<).shbin | tr . _)`.h 177 | @echo "extern const u8" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"[];" >> `(echo $(notdir $<).shbin | tr . _)`.h 178 | @echo "extern const u32" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`_size";" >> `(echo $(notdir $<).shbin | tr . _)`.h 179 | @rm ../$(notdir $<).shbin 180 | 181 | -include $(DEPENDS) 182 | 183 | #--------------------------------------------------------------------------------------- 184 | endif 185 | #--------------------------------------------------------------------------------------- 186 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | PARAMS := 2 | 3 | ifneq ($(strip $(DISABLEAES)),) 4 | PARAMS := $(PARAMS) DISABLEAES=1 5 | endif 6 | 7 | ifneq ($(strip $(DISABLENANDREDIR)),) 8 | PARAMS := $(PARAMS) DISABLENANDREDIR=1 9 | endif 10 | 11 | ifneq ($(strip $(DISABLE_ARM9DEBUGGING)),) 12 | PARAMS := $(PARAMS) DISABLE_ARM9DEBUGGING=1 13 | endif 14 | 15 | ifneq ($(strip $(DISABLE_ARM11KERNEL_DEBUG)),) 16 | PARAMS := $(PARAMS) DISABLE_ARM11KERNEL_DEBUG=1 17 | endif 18 | 19 | ifneq ($(strip $(DISABLE_ARM11KERNEL_PROCSTARTHOOK)),) 20 | PARAMS := $(PARAMS) DISABLE_ARM11KERNEL_PROCSTARTHOOK=1 21 | endif 22 | 23 | ifneq ($(strip $(DISABLE_ARM11KERNEL_SVCHANDLER_PATCH)),) 24 | PARAMS := $(PARAMS) DISABLE_ARM11KERNEL_SVCHANDLER_PATCH=1 25 | endif 26 | 27 | ifneq ($(strip $(DISABLE_NETDEBUG)),) 28 | PARAMS := $(PARAMS) DISABLE_NETDEBUG=1 29 | endif 30 | 31 | ifneq ($(strip $(ENABLE_ARM11KERNEL_SVCBREAKPATCH)),) 32 | PARAMS := $(PARAMS) ENABLE_ARM11KERNEL_SVCBREAKPATCH=1 33 | endif 34 | 35 | ifneq ($(strip $(DISABLE_GETEXHDRHOOK)),) 36 | PARAMS := $(PARAMS) DISABLE_GETEXHDRHOOK=1 37 | endif 38 | 39 | ifneq ($(strip $(ENABLE_LOADA9_x01FFB800)),) 40 | PARAMS := $(PARAMS) ENABLE_LOADA9_x01FFB800=1 41 | endif 42 | 43 | ifneq ($(strip $(LOADA9_x01FFB800_INCFILEPATH)),) 44 | PARAMS := $(PARAMS) LOADA9_x01FFB800_INCFILEPATH=$(LOADA9_x01FFB800_INCFILEPATH) 45 | endif 46 | 47 | ifneq ($(strip $(ENABLE_ARM11PROCLIST_OVERRIDE)),) 48 | PARAMS := $(PARAMS) ENABLE_ARM11PROCLIST_OVERRIDE=1 49 | endif 50 | 51 | ifneq ($(strip $(ADDEXHDR_SYSMODULE_DEPENDENCY)),) 52 | PARAMS := $(PARAMS) ADDEXHDR_SYSMODULE_DEPENDENCY=$(ADDEXHDR_SYSMODULE_DEPENDENCY) 53 | endif 54 | 55 | ifneq ($(strip $(ADDEXHDR_SYSMODULE_DEPENDENCY_PADCHECK)),) 56 | PARAMS := $(PARAMS) ADDEXHDR_SYSMODULE_DEPENDENCY_PADCHECK=$(ADDEXHDR_SYSMODULE_DEPENDENCY_PADCHECK) 57 | endif 58 | 59 | ifneq ($(strip $(ENABLE_BROWSER_APPMEM)),) 60 | PARAMS := $(PARAMS) ENABLE_BROWSER_APPMEM=1 61 | endif 62 | 63 | ifneq ($(strip $(ENABLE_GAMECARD)),) 64 | PARAMS := $(PARAMS) ENABLE_GAMECARD=1 65 | endif 66 | 67 | ifneq ($(strip $(ENABLE_ARM11CODELOAD_SERVACCESSCONTROL_OVERWRITE)),) 68 | PARAMS := $(PARAMS) ENABLE_ARM11CODELOAD_SERVACCESSCONTROL_OVERWRITE=1 69 | endif 70 | 71 | ifneq ($(strip $(DISABLE_FSACCESSINFO_OVERWRITE)),) 72 | PARAMS := $(PARAMS) DISABLE_FSACCESSINFO_OVERWRITE=1 73 | endif 74 | 75 | ifneq ($(strip $(DISABLE_A9THREAD)),) 76 | PARAMS := $(PARAMS) DISABLE_A9THREAD=1 77 | endif 78 | 79 | ifneq ($(strip $(ENABLE_CONFIGMEM_DEVUNIT)),) 80 | PARAMS := $(PARAMS) ENABLE_CONFIGMEM_DEVUNIT=1 81 | endif 82 | 83 | ifneq ($(strip $(ENABLE_FIRMLAUNCH_HOOK)),) 84 | PARAMS := $(PARAMS) ENABLE_FIRMLAUNCH_HOOK=1 85 | endif 86 | 87 | ifneq ($(strip $(DISABLE_FIRMLAUNCH_LOADSD)),) 88 | PARAMS := $(PARAMS) DISABLE_FIRMLAUNCH_LOADSD=1 89 | endif 90 | 91 | ifneq ($(strip $(ENABLE_FIRMLAUNCH_LOADNAND)),) 92 | PARAMS := $(PARAMS) ENABLE_FIRMLAUNCH_LOADNAND=1 93 | endif 94 | 95 | ifneq ($(strip $(ALTSD_FIRMPATH)),) 96 | PARAMS := $(PARAMS) ALTSD_FIRMPATH=1 97 | endif 98 | 99 | ifneq ($(strip $(DISABLE_MATCHINGFIRM_HWCHECK)),) 100 | PARAMS := $(PARAMS) DISABLE_MATCHINGFIRM_HWCHECK=1 101 | endif 102 | 103 | ifneq ($(strip $(ENABLE_BOOTSAFEFIRM_STARTUP)),) 104 | PARAMS := $(PARAMS) ENABLE_BOOTSAFEFIRM_STARTUP=1 105 | endif 106 | 107 | ifneq ($(strip $(ENABLE_REGIONFREE)),) 108 | PARAMS := $(PARAMS) ENABLE_REGIONFREE=$(ENABLE_REGIONFREE) 109 | endif 110 | 111 | ifneq ($(strip $(ENABLE_THEMECACHENAME)),) 112 | PARAMS := $(PARAMS) ENABLE_THEMECACHENAME=$(ENABLE_THEMECACHENAME) 113 | endif 114 | 115 | ifneq ($(strip $(DISABLE_GAMECARDUPDATE)),) 116 | PARAMS := $(PARAMS) DISABLE_GAMECARDUPDATE=1 117 | endif 118 | 119 | ifneq ($(strip $(ENABLE_OLDFS_AUTOLOCATE)),) 120 | PARAMS := $(PARAMS) ENABLE_OLDFS_AUTOLOCATE=1 121 | endif 122 | 123 | ifneq ($(strip $(ENABLE_DMA)),) 124 | PARAMS := $(PARAMS) ENABLE_DMA=$(ENABLE_DMA) 125 | endif 126 | 127 | ifneq ($(strip $(ENABLE_CMDLOGGING)),) 128 | PARAMS := $(PARAMS) ENABLE_CMDLOGGING=1 129 | endif 130 | 131 | ifneq ($(strip $(CMDLOGGING_PADCHECK)),) 132 | PARAMS := $(PARAMS) CMDLOGGING_PADCHECK=$(CMDLOGGING_PADCHECK) 133 | endif 134 | 135 | ifneq ($(strip $(CMDLOGGING_PROCNAME0)),) 136 | PARAMS := $(PARAMS) CMDLOGGING_PROCNAME0=$(CMDLOGGING_PROCNAME0) 137 | endif 138 | 139 | ifneq ($(strip $(CMDLOGGING_PROCNAME1)),) 140 | PARAMS := $(PARAMS) CMDLOGGING_PROCNAME1=$(CMDLOGGING_PROCNAME1) 141 | endif 142 | 143 | ifneq ($(strip $(CMDLOGGING_ALTPROCNAME)),) 144 | PARAMS := $(PARAMS) CMDLOGGING_ALTPROCNAME=$(CMDLOGGING_ALTPROCNAME) 145 | endif 146 | 147 | ifneq ($(strip $(CMDLOGGING_IGNORE_PROCNAME)),) 148 | PARAMS := $(PARAMS) CMDLOGGING_IGNORE_PROCNAME=$(CMDLOGGING_IGNORE_PROCNAME) 149 | endif 150 | 151 | ifneq ($(strip $(CMDLOGGING_CMDHDR_FILTER)),) 152 | PARAMS := $(PARAMS) CMDLOGGING_CMDHDR_FILTER=$(CMDLOGGING_CMDHDR_FILTER) 153 | endif 154 | 155 | ifneq ($(strip $(ENABLE_DUMP_NANDIMAGE)),) 156 | PARAMS := $(PARAMS) ENABLE_DUMP_NANDIMAGE=1 157 | endif 158 | 159 | ifneq ($(strip $(NANDREDIR_SECTORNUM)),) 160 | PARAMS := $(PARAMS) NANDREDIR_SECTORNUM=$(NANDREDIR_SECTORNUM) 161 | endif 162 | 163 | ifneq ($(strip $(NANDREDIR_SECTORNUM_PADCHECK0)),) 164 | PARAMS := $(PARAMS) NANDREDIR_SECTORNUM_PADCHECK0=$(NANDREDIR_SECTORNUM_PADCHECK0) 165 | endif 166 | 167 | ifneq ($(strip $(NANDREDIR_SECTORNUM_PADCHECK0VAL)),) 168 | PARAMS := $(PARAMS) NANDREDIR_SECTORNUM_PADCHECK0VAL=$(NANDREDIR_SECTORNUM_PADCHECK0VAL) 169 | endif 170 | 171 | ifneq ($(strip $(NANDREDIR_SECTORNUM_PADCHECK1)),) 172 | PARAMS := $(PARAMS) NANDREDIR_SECTORNUM_PADCHECK1=$(NANDREDIR_SECTORNUM_PADCHECK1) 173 | endif 174 | 175 | ifneq ($(strip $(NANDREDIR_SECTORNUM_PADCHECK1VAL)),) 176 | PARAMS := $(PARAMS) NANDREDIR_SECTORNUM_PADCHECK1VAL=$(NANDREDIR_SECTORNUM_PADCHECK1VAL) 177 | endif 178 | 179 | ifneq ($(strip $(LOADA9_NEW3DSMEM)),) 180 | PARAMS := $(PARAMS) LOADA9_NEW3DSMEM=1 181 | endif 182 | 183 | ifneq ($(strip $(LOADA9_FCRAM)),) 184 | PARAMS := $(PARAMS) LOADA9_FCRAM=1 185 | endif 186 | 187 | ifneq ($(strip $(NEW3DS_MEMDUMPA9_DISABLEVRAMCLR)),) 188 | PARAMS := $(PARAMS) NEW3DS_MEMDUMPA9_DISABLEVRAMCLR=1 189 | endif 190 | 191 | ifneq ($(strip $(NEW3DS_MEMDUMPA9_ADR)),) 192 | PARAMS := $(PARAMS) NEW3DS_MEMDUMPA9_ADR=$(NEW3DS_MEMDUMPA9_ADR) 193 | endif 194 | 195 | ifneq ($(strip $(NEW3DS_MEMDUMPA9_SIZE)),) 196 | PARAMS := $(PARAMS) NEW3DS_MEMDUMPA9_SIZE=$(NEW3DS_MEMDUMPA9_SIZE) 197 | endif 198 | 199 | ifneq ($(strip $(NEW3DS_ARM9BINLDR_PATCHADDR0)),) 200 | PARAMS := $(PARAMS) NEW3DS_ARM9BINLDR_PATCHADDR0=$(NEW3DS_ARM9BINLDR_PATCHADDR0) 201 | endif 202 | 203 | ifneq ($(strip $(NEW3DS_ARM9BINLDR_PATCHADDR0_VAL)),) 204 | PARAMS := $(PARAMS) NEW3DS_ARM9BINLDR_PATCHADDR0_VAL=$(NEW3DS_ARM9BINLDR_PATCHADDR0_VAL) 205 | endif 206 | 207 | ifneq ($(strip $(NEW3DS_ARM9BINLDR_PATCHADDR1)),) 208 | PARAMS := $(PARAMS) NEW3DS_ARM9BINLDR_PATCHADDR1=$(NEW3DS_ARM9BINLDR_PATCHADDR1) 209 | endif 210 | 211 | ifneq ($(strip $(NEW3DS_ARM9BINLDR_PATCHADDR1_VAL)),) 212 | PARAMS := $(PARAMS) NEW3DS_ARM9BINLDR_PATCHADDR1_VAL=$(NEW3DS_ARM9BINLDR_PATCHADDR1_VAL) 213 | endif 214 | 215 | ifneq ($(strip $(NEW3DS_ARM9BINLDR_CLRMEM)),) 216 | PARAMS := $(PARAMS) NEW3DS_ARM9BINLDR_CLRMEM=$(NEW3DS_ARM9BINLDR_CLRMEM) 217 | endif 218 | 219 | ifneq ($(strip $(NEW3DS_ARM9BINLDR_CLRMEM_SIZE)),) 220 | PARAMS := $(PARAMS) NEW3DS_ARM9BINLDR_CLRMEM_SIZE=$(NEW3DS_ARM9BINLDR_CLRMEM_SIZE) 221 | endif 222 | 223 | ifneq ($(strip $(ENABLE_NIMURLS_PATCHES)),) 224 | PARAMS := $(PARAMS) ENABLE_NIMURLS_PATCHES=1 225 | endif 226 | 227 | ifneq ($(strip $(NIMPATCHURL_UPDATE)),) 228 | PARAMS := $(PARAMS) NIMPATCHURL_UPDATE=$(NIMPATCHURL_UPDATE) 229 | endif 230 | 231 | ifneq ($(strip $(NIMPATCHURL_ECOMMERCE)),) 232 | PARAMS := $(PARAMS) NIMPATCHURL_ECOMMERCE=$(NIMPATCHURL_ECOMMERCE) 233 | endif 234 | 235 | ifneq ($(strip $(ENABLE_LOADSD_AESKEYS)),) 236 | PARAMS := $(PARAMS) ENABLE_LOADSD_AESKEYS=1 237 | endif 238 | 239 | ifneq ($(strip $(MEMDUMPBOOT_SRCADDR)),) 240 | PARAMS := $(PARAMS) MEMDUMPBOOT_SRCADDR=$(MEMDUMPBOOT_SRCADDR) 241 | 242 | ifneq ($(strip $(MEMDUMPBOOT_DSTADDR)),) 243 | PARAMS := $(PARAMS) MEMDUMPBOOT_DSTADDR=$(MEMDUMPBOOT_DSTADDR) 244 | else 245 | PARAMS := $(PARAMS) MEMDUMPBOOT_DSTADDR=0x08001000 246 | endif 247 | 248 | ifneq ($(strip $(MEMDUMPBOOT_SIZE)),) 249 | PARAMS := $(PARAMS) MEMDUMPBOOT_SIZE=$(MEMDUMPBOOT_SIZE) 250 | else 251 | PARAMS := $(PARAMS) MEMDUMPBOOT_SIZE=0x200 252 | endif 253 | endif 254 | 255 | .PHONY: clean 256 | 257 | all: 3dshax_arm9.bin 3dshax_arm11_ctrserver.bin 258 | 259 | clean: 260 | make clean -f Makefile.arm9 261 | make clean -f Makefile_ctrserver.arm11 CTRULIB=$(CTRULIB) 262 | 263 | export OUTPATH 264 | export ARM9BINCPOUT_PATH 265 | 266 | 3dshax_arm9.bin: 267 | make -f Makefile.arm9 $(PARAMS) 268 | 269 | 3dshax_arm11_ctrserver.bin: 270 | make -f Makefile_ctrserver.arm11 271 | -------------------------------------------------------------------------------- /3dshaxarm9/nandredir.s: -------------------------------------------------------------------------------- 1 | #ifdef ENABLENANDREDIR 2 | 3 | .arch armv5te 4 | .fpu softvfp 5 | .text 6 | .arm 7 | 8 | .global patch_nandredir 9 | .global patch_nandredir_autolocate 10 | .type patch_nandredir STT_FUNC 11 | .type patch_nandredir_autolocate STT_FUNC 12 | 13 | .thumb 14 | .align 2 15 | arm9_nandredir_stub: 16 | ldr r7, =arm9_nandredir_code 17 | blx r7 18 | .pool 19 | 20 | arm9_nandredir_stub2: 21 | ldr r7, =arm9_nandredir_readcodefinal 22 | blx r7 23 | .pool 24 | 25 | arm9_nandredir_stub3: 26 | ldr r7, =arm9_nandredir_writecodefinal 27 | blx r7 28 | .pool 29 | 30 | /*arm9_nandredir_stub4: 31 | ldr r0, =arm9_nandredir_debugcode 32 | bx r0 33 | .pool*/ 34 | 35 | .arm 36 | /*arm9_nandredir_dumpdebug: 37 | push {r4, lr} 38 | ldr r0, arm9_nandredir_code_savaddr 39 | mov r3, #2 40 | ldr r4, =cardWriteEeprom 41 | blx r4 42 | pop {r4, pc} 43 | .pool*/ 44 | 45 | nandredir_getsdstate_offset: 46 | ldr r0, =0x14f0 47 | ldr r1, =FIRMLAUNCH_FWVER 48 | ldr r1, [r1] 49 | lsr r2, r1, #30 50 | and r1, r1, #0xff 51 | ands r2, r2, #1 52 | bne nandredir_getsdstate_offset_new3ds 53 | 54 | @ Old3DS: 55 | cmp r1, #46 @ v9.0 56 | ldrge r0, =0x11f0 57 | bge nandredir_getsdstate_offset_end 58 | cmp r1, #32 @ v3.0 59 | ldrls r0, =0x14d8 60 | b nandredir_getsdstate_offset_end 61 | 62 | nandredir_getsdstate_offset_new3ds: 63 | cmp r1, #46 @ v9.0 64 | ldrge r0, =0x11f0 65 | 66 | nandredir_getsdstate_offset_end: 67 | bx lr 68 | .pool 69 | 70 | arm9_nandredir_code: 71 | push {r0, r1, r2, r3, r4, r5, r6, r7, ip, lr} 72 | sub sp, sp, #0x40 73 | mov r5, r0 74 | ldr r2, =0x101 75 | ldr ip, [r5, #4] 76 | ldr ip, [ip, #32] 77 | cmp ip, r2 @ 0x101=NAND device, 0x100=SD device 78 | mov r6, #0 79 | bne arm9_nandredir_code_end 80 | 81 | /*ldr r2, arm9_nandredir_code_savaddr 82 | cmp r2, #0x10000 83 | bge arm9_nandredir_code_debugend*/ 84 | 85 | /*mov r0, sp 86 | add r1, sp, #0x40 87 | mov r2, #0x20 88 | arm9_nandredir_code_debugcpy: 89 | ldr r3, [r1], #4 90 | str r3, [r0], #4 91 | subs r2, r2, #4 92 | bgt arm9_nandredir_code_debugcpy 93 | 94 | ldr r3, [r5, #8] 95 | str r3, [sp, #4] 96 | ldr r1, [sp, #0x80] 97 | str r1, [sp, #0x1c]*/ 98 | 99 | //add r0, sp, #0x40 100 | //mov r1, #0x20 101 | //bl dumpmem 102 | //bl arm9_nandredir_dumpdebug 103 | 104 | /*ldr r0, arm9_nandredir_code_savaddr 105 | ldr r2, =0x10000 106 | add r0, r0, r2 107 | str r0, arm9_nandredir_code_savaddr 108 | 109 | arm9_nandredir_code_debugend:*/ 110 | 111 | bl nandredir_getsdstate_offset 112 | ldr r1, [r5, #4] @ Change the object ptr to the SD one. 113 | add r1, r1, r0 114 | ldr r2, =NANDREDIR_SECTORNUM @ Sector# of the NAND image "partition" on the SD card. 115 | ldr r2, [r2] 116 | ldr r3, [r5, #8] 117 | add r3, r3, r2 118 | str r3, [r5, #8] 119 | str r1, [r5, #4] 120 | mov r6, #1 121 | 122 | arm9_nandredir_code_end: 123 | str r6, arm9_nandredir_code_hookflag 124 | add sp, sp, #0x40 125 | pop {r0, r1, r2, r3, r4, r5, r6, r7, ip, lr} 126 | mov r4, r0 127 | mov r5, r1 128 | mov r7, r2 129 | mov r6, r3 130 | add lr, lr, #4 131 | bx lr 132 | .pool 133 | 134 | arm9_nandredir_rwcodefinal: 135 | push {r0, r1, r2, r3, r4, r5, r6, ip, lr} 136 | ldr r1, arm9_nandredir_code_hookflag 137 | mov r2, #0 138 | cmp r1, r2 139 | beq arm9_nandredir_rwcodefinal_end 140 | str r2, arm9_nandredir_code_hookflag 141 | 142 | bl nandredir_getsdstate_offset 143 | mov r3, r0 144 | 145 | ldr r2, =NANDREDIR_SECTORNUM 146 | ldr r2, [r2] 147 | ldr r1, [r4, #8] 148 | sub r1, r1, r2 149 | str r1, [r4, #8] 150 | ldr r1, [r4, #4] 151 | sub r1, r1, r3 152 | str r1, [r4, #4] 153 | 154 | /*ldr r1, arm9_nandredir_code_savaddr 155 | cmp r1, #0x10000 156 | bge arm9_nandredir_rwcodefinal_end 157 | 158 | //sub r1, sp, #0x200 159 | //mov r2, #0x200 160 | mov r1, sp 161 | mov r2, #0x20 162 | //ldr r1, =0x01ff8000 163 | //ldr r2, =0x8000 164 | //bl arm9_nandredir_dumpdebug 165 | 166 | ldr r1, arm9_nandredir_code_savaddr 167 | //ldr r2, =0x8000 168 | mov r2, #0x20 169 | add r1, r1, r2 170 | str r1, arm9_nandredir_code_savaddr*/ 171 | 172 | arm9_nandredir_rwcodefinal_end: 173 | pop {r0, r1, r2, r3, r4, r5, r6, ip, pc} 174 | .pool 175 | 176 | arm9_nandredir_readcodefinal: 177 | add r2, #12 178 | mov r0, ip 179 | ldr r5, =arm9_nandredir_readcodefinal_jumpaddr 180 | ldr r5, [r5] 181 | blx r5 182 | bl arm9_nandredir_rwcodefinal 183 | pop {r1, r2, r3, r4, r5, r6, r7, pc} 184 | .pool 185 | 186 | arm9_nandredir_writecodefinal: 187 | add r2, #12 188 | mov r0, ip 189 | ldr r5, =arm9_nandredir_writecodefinal_jumpaddr 190 | ldr r5, [r5] 191 | blx r5 192 | bl arm9_nandredir_rwcodefinal 193 | pop {r1, r2, r3, r4, r5, r6, r7, pc} 194 | .pool 195 | 196 | /*arm9_nandredir_debugcode: 197 | cmp r1, #0 198 | moveq r0, #0 199 | bxeq lr 200 | 201 | ldr r0, =0x20001000 202 | str r1, [r0], #4 203 | //sub r1, sp, #0x200 204 | //mov r1, sp 205 | ldr r1, =0x10006000 206 | mov r2, #0x200 207 | 208 | arm9_nandredir_debugcode_cpylp: 209 | ldr r3, [r1], #4 210 | str r3, [r0], #4 211 | subs r2, r2, #4 212 | bgt arm9_nandredir_debugcode_cpylp 213 | 214 | push {r0, r1, r2, r3, r4, r5, r6, lr} 215 | 216 | ldr r1, arm9_nandredir_code_savaddr 217 | cmp r1, #0x10000 218 | bge arm9_nandredir_debugcode_end 219 | 220 | ldr r1, =0x20001000 221 | add r1, r1, #4 222 | ldr r2, =0x200 223 | bl arm9_nandredir_dumpdebug 224 | 225 | ldr r1, arm9_nandredir_code_savaddr 226 | ldr r2, =0x200 227 | add r1, r1, r2 228 | str r1, arm9_nandredir_code_savaddr 229 | 230 | arm9_nandredir_debugcode_end: 231 | pop {r0, r1, r2, r3, r4, r5, r6, lr} 232 | 233 | ldr r0, =0x20001000 234 | ldr r1, [r0] 235 | 236 | ldr r0, =0x40200000 237 | tst r1, r0 238 | ldr pc, =0x8078a99 239 | .pool*/ 240 | 241 | patch_nandredir: 242 | push {r0, r1, r2, r3, r4, r5, lr} 243 | adr r2, arm9_nandredir_stub 244 | add r0, r0, #0x2//0x2a 245 | add r1, r1, #0x2//0x2a 246 | ldrh r3, [r2, #0] 247 | strh r3, [r0, #0] 248 | strh r3, [r1, #0] 249 | ldrh r3, [r2, #2] 250 | strh r3, [r0, #2] 251 | strh r3, [r1, #2] 252 | ldrh r3, [r2, #4] 253 | strh r3, [r0, #4] 254 | strh r3, [r1, #4] 255 | ldrh r3, [r2, #6] 256 | strh r3, [r0, #6] 257 | strh r3, [r1, #6] 258 | 259 | add r0, r0, #0x34 260 | add r1, r1, #0x34 261 | mov r4, r0 262 | mov r5, r1 263 | 264 | ldr r0, [sp, #8] 265 | add r0, r0, #0x36 266 | add r0, r0, #4 267 | add r1, r4, #4 268 | ldr r1, [r1] 269 | bl parse_branch_thumb 270 | ldr r1, =arm9_nandredir_readcodefinal_jumpaddr 271 | str r0, [r1] 272 | 273 | ldr r0, [sp, #12] 274 | add r0, r0, #0x36 275 | add r0, r0, #4 276 | add r1, r5, #4 277 | ldr r1, [r1] 278 | bl parse_branch_thumb 279 | ldr r1, =arm9_nandredir_writecodefinal_jumpaddr 280 | str r0, [r1] 281 | 282 | mov r0, r4 283 | mov r1, r5 284 | adr r2, arm9_nandredir_stub2 285 | adr r3, arm9_nandredir_stub3 286 | ldrh r4, [r2, #0] 287 | strh r4, [r0, #0] 288 | ldrh r4, [r3, #0] 289 | strh r4, [r1, #0] 290 | ldrh r4, [r2, #2] 291 | strh r4, [r0, #2] 292 | ldrh r4, [r3, #2] 293 | strh r4, [r1, #2] 294 | ldrh r4, [r2, #4] 295 | strh r4, [r0, #4] 296 | ldrh r4, [r3, #4] 297 | strh r4, [r1, #4] 298 | ldrh r4, [r2, #6] 299 | strh r4, [r0, #6] 300 | ldrh r4, [r3, #6] 301 | strh r4, [r1, #6] 302 | 303 | mov r2, #0x44 304 | ldr r1, [sp, #0] 305 | ldr r0, =0xffff8001 306 | svc 0x54 @ svcFlushProcessDataCache 307 | 308 | mov r2, #0x44 309 | ldr r1, [sp, #4] 310 | ldr r0, =0xffff8001 311 | svc 0x54 @ svcFlushProcessDataCache 312 | pop {r0, r1, r2, r3, r4, r5, pc} 313 | .pool 314 | 315 | patch_nandredir_autolocate: 316 | push {r4, r5, r6, r7, lr} 317 | sub sp, sp, #8 318 | 319 | mov r5, #0 320 | ldr r4, =arm9_nandredir_patch_cmpdata 321 | mov r6, r2 322 | mov r7, r0 323 | 324 | patch_nandredir_autolocate_lp: 325 | ldrh r2, [r0, #0] 326 | ldrh r3, [r4, #0] 327 | cmp r2, r3 328 | bne patch_nandredir_autolocate_lpend 329 | ldrh r2, [r0, #2] 330 | ldrh r3, [r4, #2] 331 | cmp r2, r3 332 | bne patch_nandredir_autolocate_lpend 333 | ldrh r2, [r0, #4] 334 | ldrh r3, [r4, #4] 335 | cmp r2, r3 336 | bne patch_nandredir_autolocate_lpend 337 | ldrh r2, [r0, #6] 338 | ldrh r3, [r4, #6] 339 | cmp r2, r3 340 | bne patch_nandredir_autolocate_lpend 341 | ldrh r2, [r0, #8] 342 | ldrh r3, [r4, #8] 343 | cmp r2, r3 344 | bne patch_nandredir_autolocate_lpend 345 | ldrh r2, [r0, #0xa] 346 | ldrh r3, [r4, #0xa] 347 | cmp r2, r3 348 | bne patch_nandredir_autolocate_lpend 349 | ldrh r2, [r0, #0xc] 350 | ldrh r3, [r4, #0xc] 351 | cmp r2, r3 352 | bne patch_nandredir_autolocate_lpend 353 | 354 | str r0, [sp, r5] 355 | add r5, r5, #4 356 | cmp r5, #8 357 | beq patch_nandredir_autolocate_lpfinish 358 | 359 | patch_nandredir_autolocate_lpend: 360 | add r0, r0, #2 361 | subs r1, r1, #2 362 | bgt patch_nandredir_autolocate_lp 363 | 364 | mov r0, #1 365 | b patch_nandredir_autolocate_end 366 | 367 | patch_nandredir_autolocate_lpfinish: 368 | ldr r0, [sp, #4] 369 | ldr r1, [sp, #0] 370 | sub r2, r0, r7 371 | sub r3, r1, r7 372 | add r2, r2, r6 373 | add r3, r3, r6 374 | bl patch_nandredir 375 | 376 | mov r0, #0 377 | 378 | patch_nandredir_autolocate_end: 379 | add sp, sp, #8 380 | pop {r4, r5, r6, r7, pc} 381 | .pool 382 | 383 | arm9_nandredir_code_savaddr: 384 | .word 0 385 | arm9_nandredir_code_hookflag: 386 | .word 0 387 | arm9_nandredir_code_initflag: 388 | .word 0 389 | 390 | arm9_nandredir_readcodefinal_jumpaddr: 391 | .word 0 392 | arm9_nandredir_writecodefinal_jumpaddr: 393 | .word 0 394 | 395 | arm9_nandredir_patch_cmpdata: @ This is the first 0xe-bytes of the functions which are patched for nand-redir. 396 | .hword 0xb5fe, 0x0004, 0x000d, 0x0017, 0x001e, 0x05c8, 0xd001 397 | 398 | #endif 399 | 400 | -------------------------------------------------------------------------------- /3dshaxarm9/firmlaunch_hookpatches.s: -------------------------------------------------------------------------------- 1 | .arch armv5te 2 | .fpu softvfp 3 | .text 4 | .arm 5 | 6 | .global firmlaunch_hook0_stub 7 | .global init_firmlaunch_hook1 8 | //.global firmlaunch_swprintfhook 9 | .type firmlaunch_hook0_stub STT_FUNC 10 | .type init_firmlaunch_hook1 STT_FUNC 11 | //.type firmlaunch_swprintfhook STT_FUNC 12 | 13 | firmlaunch_hook0_stub: 14 | ldr r3, =firmlaunch_hook0 15 | blx r3 16 | .pool 17 | 18 | #ifndef DISABLE_FIRMLAUNCH_LOADSD 19 | firmlaunch_loadfirmsd: @ r0 = FIRM tidlow u16, r1 = u64* filesize out 20 | push {r0, r1, r2, r3, r4, lr} 21 | sub sp, sp, #12 22 | 23 | mov r4, #0 24 | 25 | ldr r0, =sdarchive_obj 26 | ldr r0, [r0] 27 | mov r3, #1 28 | str r3, [sp, #0] 29 | add r1, sp, #8 30 | str r1, [sp, #4] 31 | mov r1, #4 32 | 33 | //lower half word so it'll work on n3ds too 34 | ldrh r2, [sp, #12] 35 | mov r3, #0x100 36 | add r3, r3, #0x2 // TWL_FIRM tidlow 37 | cmp r2, r3 38 | ldreq r2, =twlfirmbin_filepath 39 | beq firmlaunch_loadfirmsd_openfile 40 | 41 | cmp r2, #0x2 42 | mvnne r4, #1 43 | bne firmlaunch_loadfirmsd_end 44 | 45 | ldr r2, =firmbin_filepath 46 | 47 | firmlaunch_loadfirmsd_openfile: 48 | mov r3, #0x14 49 | bl openfile 50 | mov r4, r0 51 | cmp r4, #0 52 | bne firmlaunch_loadfirmsd_end 53 | mvn r4, #0 54 | 55 | ldr r0, [sp, #8] 56 | cmp r0, #0 57 | beq firmlaunch_loadfirmsd_end 58 | bl getfilesize 59 | ldr r1, [sp, #16] 60 | str r0, [r1] 61 | mov r2, #0 62 | str r2, [r1, #4] 63 | 64 | mov r2, r0 65 | ldr r0, [sp, #8] 66 | ldr r1, =0x21000000 67 | mov r3, #0 68 | bl fileread 69 | mov r4, r0 70 | 71 | ldr r0, [sp, #8] 72 | bl closefile 73 | 74 | firmlaunch_loadfirmsd_end: 75 | mov r0, r4 76 | add sp, sp, #12 77 | add sp, sp, #16 78 | pop {r4, pc} 79 | .pool 80 | #endif 81 | 82 | #ifdef ENABLE_FIRMLAUNCH_LOADNAND 83 | firmlaunch_loadfirmnand: @ r0 = _this, r1 = u64* filesize out, r2 = getfilesize funcptr 84 | push {r0, r1, r2, r3, r4, lr} 85 | sub sp, sp, #12 86 | 87 | blx r2 @ Call the getfilesize vtable funcptr, then execute infinite loop if it fails. 88 | cmp r0, #0 89 | bne firmlaunch_loadfirmnand_end 90 | 91 | ldr r0, [sp, #12] @ _this 92 | mov r1, sp @ u32* total actual read data 93 | ldr r2, =0x21000000 @ outbuf 94 | ldr r3, [sp, #16] 95 | ldr r3, [r3] @ size 96 | ldr r4, [r0] 97 | ldr r4, [r4, #0x28] 98 | blx r4 99 | cmp r0, #0 100 | bne firmlaunch_loadfirmnand_end 101 | 102 | ldr r2, [sp, #0] @ read size 103 | ldr r3, [sp, #16] 104 | ldr r3, [r3] @ filesize 105 | cmp r2, r3 106 | mvnne r0, #0 107 | 108 | firmlaunch_loadfirmnand_end: 109 | add sp, sp, #12 110 | add sp, sp, #16 111 | pop {r4, pc} 112 | .pool 113 | 114 | /*firmlaunch_swprintfhook://This code was intended to have proc9 open "firm0:" instead of the exefs .firm, but that somehow breaks firmlaunch even when firmlaunch_loadfirmnand() wasn't even executed. 115 | mov r3, #0xe 116 | ldr r2, =firm0device 117 | 118 | firmlaunch_swprintfhook_cpylp: 119 | ldrh r1, [r2], #2 120 | strh r1, [r0], #2 121 | subs r3, r3, #2 122 | bgt firmlaunch_swprintfhook_cpylp 123 | bx lr 124 | .pool*/ 125 | #endif 126 | 127 | firmlaunch_hook0: 128 | push {r0, r1, r2, r3, r4, r5, lr} 129 | sub sp, sp, #12 130 | 131 | ldrh r2, [sp, #12+4*7] 132 | mov r3, #0x100 133 | add r3, r3, #0x2 // TWL_FIRM tidlow 134 | cmp r2, r3 135 | moveq r5, #1 136 | movne r5, #0 137 | add r3, r3, #0x100 @ AGB_FIRM 138 | cmp r2, r3 139 | moveq r5, #1 140 | 141 | ldr r3, =FIRMLAUNCH_CLEARPARAMS 142 | ldr r3, [r3] 143 | cmp r3, #1 144 | cmpeq r2, #0x3 145 | moveq r2, #0x2 146 | strh r2, [sp, #12+4*7] 147 | 148 | firmlaunch_hook0_firmload: 149 | #ifndef DISABLE_FIRMLAUNCH_LOADSD 150 | mov r0, r2 151 | ldr r1, [sp, #16] 152 | bl firmlaunch_loadfirmsd 153 | cmp r0, #0 154 | beq firmlaunch_hook0_copyheader 155 | #endif 156 | 157 | #ifdef ENABLE_FIRMLAUNCH_LOADNAND 158 | #ifdef ENABLENANDREDIR//Refuse to load from NAND for the second firmlaunch when nandredir is enabled, since that would mean loading FIRM from physnand with a potentially newer sd-nandimage which could fail to boot with older FIRM. 159 | ldr r3, =FIRMLAUNCH_CLEARPARAMS 160 | ldr r3, [r3] 161 | cmp r3, #1 162 | mvneq r0, #5 163 | beq firmlaunch_hook0_fail 164 | #endif 165 | 166 | ldr r0, [sp, #12] 167 | ldr r1, [sp, #16] 168 | ldr r2, [sp, #20] 169 | bl firmlaunch_loadfirmnand 170 | #endif 171 | 172 | cmp r0, #0 173 | bne firmlaunch_hook0_fail 174 | 175 | #ifdef DISABLE_FIRMLAUNCH_LOADSD 176 | #ifndef ENABLE_FIRMLAUNCH_LOADNAND 177 | #error "No FIRMLAUNCH load-type(SD/NAND) is enabled at all." 178 | #endif 179 | #endif 180 | 181 | firmlaunch_hook0_copyheader: 182 | ldr r0, =firmheader_address 183 | ldr r0, [r0] 184 | ldr r1, =0x21000000 185 | mov r2, #0x100 186 | bl memcpy 187 | 188 | cmp r5, #1 189 | beq firmlaunch_hook0_skip_paramsclear @ skip patches and clear param if twl_firm/agb_firm. 190 | 191 | #ifndef DISABLE_MATCHINGFIRM_HWCHECK 192 | ldr r0, =0x21000000 193 | bl firm_gethwtype 194 | mvn r1, #0 195 | cmp r0, r1 196 | beq firmlaunch_hook0_patchabort @ Check for error from firm_gethwtype(). 197 | 198 | ldr r1, =RUNNINGFWVER 199 | ldr r1, [r1] 200 | lsr r1, r1, #30 201 | and r1, r1, #1 202 | 203 | cmp r0, r1 204 | bne firmlaunch_hook0_patchabort @ Return error when the hw type returned by firm_gethwtype() doesn't match the current one from RUNNINGFWVER. 205 | #endif 206 | 207 | ldr r0, =0x21000000 208 | ldrh r1, [sp, #12+4*7] @ FIRM tidlow 209 | bl init_firmlaunch_fwver 210 | cmp r0, #0 211 | beq firmlaunch_hook0_beginpatch 212 | 213 | firmlaunch_hook0_patchabort: 214 | b firmlaunch_hook0_patchabort @ Halt firmlaunch when fwver init failed, or for fail with the above firm_gethwtype() code. 215 | 216 | firmlaunch_hook0_beginpatch: 217 | ldr r0, =0x21000000 @ Only execute this when init_firmlaunch_fwver() successfully determined the FWVER. 218 | bl patch_firm 219 | 220 | firmlaunch_hook0_patchfinish: 221 | /*ldr r0, =0x20000440 222 | ldr r1, =0x4B464445 223 | ldr r2, =0x00048004 224 | mov r3, #0 225 | str r1, [r0] 226 | str r2, [r0, #4] 227 | str r3, [r0, #8] 228 | mov r3, #1 229 | str r3, [r0, #0x20]*/ 230 | 231 | ldr r0, =FIRMLAUNCH_CLEARPARAMS 232 | ldr r0, [r0] 233 | cmp r0, #1 234 | bne firmlaunch_hook0_skip_paramsclear 235 | 236 | ldr r0, =0x20000000 @ Clear FIRM-launch params. 237 | mov r1, #0 238 | mov r2, #0x1000 239 | bl memset 240 | 241 | firmlaunch_hook0_skip_paramsclear: 242 | @ Enable the following block to have NS launch the gamecard title, which bypasses the region-lock. Note that the system will fail to boot with this enabled if no gamecard is inserted. 243 | /*ldr r0, =0x20000440 244 | mov r1, #0 245 | mov r2, #0 246 | mov r3, #2 247 | str r1, [r0, #0] 248 | str r2, [r0, #4] 249 | str r3, [r0, #8] 250 | add r0, r0, #0x20 251 | ldr r1, [r0] 252 | orr r1, r1, #1 253 | str r1, [r0] @ Set FIRMlaunch params so that NS launches the gamecard title. 254 | 255 | ldr r1, =0x20000438 256 | ldr r2, =0xffff 257 | str r2, [r1] 258 | 259 | ldr r1, =0x2000043c 260 | mov r0, #0 261 | str r0, [r1] 262 | 263 | ldr r0, =0x20000400 264 | mov r1, #0x140 265 | blx CalcCRC32 266 | ldr r1, =0x2000043c 267 | str r0, [r1]*/ 268 | 269 | mov r2, #0 270 | ldr r0, =0x01ffcd00 271 | ldr r1, [r0] 272 | cmp r1, #0 273 | strne r2, [r0, #0] 274 | strne r2, [r0, #4] 275 | strne r2, [r0, #8] 276 | strne r2, [r0, #12] 277 | 278 | #ifdef ENABLE_LOADSD_AESKEYS 279 | ldr r0, =0x20F00000 280 | bl loadsd_aeskeys 281 | #endif 282 | 283 | #ifdef LOADA9_NEW3DSMEM 284 | bl patchfirm_setup_tmpaddr_bincopy 285 | #endif 286 | 287 | add sp, sp, #12 288 | pop {r0, r1, r2, r3, r4, r5, lr} 289 | add lr, lr, #4 290 | bx lr 291 | firmlaunch_hook0_fail: 292 | b firmlaunch_hook0_fail 293 | .pool 294 | 295 | init_firmlaunch_hook1: 296 | push {r4, r5, r6, lr} 297 | 298 | mov r4, r0 299 | mov r6, r1 300 | 301 | mov r0, #2 302 | strb r0, [r2, r3] 303 | ldr r0, [r2, #8] 304 | mov r1, r0 305 | lsr r1, r1, #24 306 | cmp r1, #0x01 307 | bne init_firmlaunch_hook1_writefirmhdradr 308 | 309 | ldr r3, =RUNNINGFWVER @ When FIRM-header is located in ITCM(>=v9.5 running FIRM), change it to endofarm9mem-0x200. FIRM-launching with these hooks is broken when the FIRM-header is located in ITCM. 310 | ldr r3, [r3] 311 | lsr r3, r3, #30 312 | and r3, r3, #1 313 | cmp r3, #0 314 | ldreq r0, =0x08100000 315 | ldrne r0, =0x08180000 316 | sub r0, r0, #0x200 317 | 318 | str r0, [r2, #8] 319 | 320 | init_firmlaunch_hook1_writefirmhdradr: 321 | ldr r2, =firmheader_address 322 | str r0, [r2] 323 | 324 | mov r1, r6 325 | mov r5, #0 326 | ldr r2, =0xe5900048 327 | ldr r3, =0xe3500000 328 | 329 | init_firmlaunch_hook1_locatelp0: 330 | ldr r0, [r1, r5] 331 | cmp r0, r2 332 | bne init_firmlaunch_hook1_locatelp0next 333 | add r5, r5, #4 334 | ldr r0, [r1, r5] 335 | cmp r0, r3 336 | beq init_firmlaunch_hook1_locatelp0end 337 | 338 | init_firmlaunch_hook1_locatelp0next: 339 | add r5, r5, #4 340 | b init_firmlaunch_hook1_locatelp0 341 | 342 | init_firmlaunch_hook1_locatelp0end: 343 | add r5, r5, #4 344 | add r1, r1, r5 345 | mov r0, r1 346 | 347 | ldr r3, =0xe59d0000 348 | 349 | init_firmlaunch_hook1_locatelp1: 350 | ldr r2, [r1], #4 351 | cmp r2, r3 352 | bne init_firmlaunch_hook1_locatelp1 353 | sub r1, r1, #4 354 | 355 | ldr r2, =firmlaunch_hook1_finishjumpadr 356 | str r1, [r2] 357 | 358 | adr r1, firmlaunch_hook1 359 | adr r2, firmlaunch_hook1_end 360 | sub r2, r2, r1 361 | 362 | init_firmlaunch_hook1_cpy: 363 | ldr r3, [r1], #4 364 | str r3, [r0], #4 365 | subs r2, r2, #4 366 | bgt init_firmlaunch_hook1_cpy 367 | 368 | mov r0, r4 369 | mov r1, #0 370 | mov r2, #0x20 371 | bl memset 372 | 373 | ldr r0, =0xfff 374 | bic r4, r4, r0 375 | mov r0, r4 376 | ldr r1, =0xc00 377 | mov r2, r1 378 | mov r1, r0 379 | ldr r0, =0xffff8001 380 | bl svcFlushProcessDataCache 381 | 382 | mov r0, #0 383 | pop {r4, r5, r6, pc} 384 | .pool 385 | 386 | firmlaunch_hook1: 387 | /*ldr r2, [sp, #0] 388 | cmp r2, #0 389 | bne firmlaunch_hook1_handlesection 390 | 391 | ldr r0, =0x10146000 392 | firmlaunch_hook1_buttonwait: @ Wait for button X to be pressed. 393 | ldrh r1, [r0] 394 | tst r1, #0x400 395 | bne firmlaunch_hook1_buttonwait 396 | 397 | firmlaunch_hook1_handlesection:*/ 398 | ldr r1, =0x21000000 399 | ldr r2, [r7, #0] 400 | add r1, r1, r2 401 | ldr r0, [r7, #4] 402 | ldr r2, [r7, #8] 403 | cmp r2, #0 404 | cmpne r0, #0 405 | beq firmlaunch_hook1_copyend 406 | 407 | firmlaunch_hook1_copylp: 408 | ldr r3, [r1], #4 409 | str r3, [r0], #4 410 | subs r2, r2, #4 411 | bgt firmlaunch_hook1_copylp 412 | 413 | firmlaunch_hook1_copyend: 414 | ldr r0, =firmlaunch_hook1_finishjumpadr 415 | ldr r0, [r0] 416 | bx r0 417 | .pool 418 | 419 | firmlaunch_hook1_end: 420 | .word 0 421 | 422 | init_firmlaunch_fwver: 423 | push {r1, r4, r5, r6, r7, r8, lr} 424 | 425 | ldr r3, =RUNNINGFWVER 426 | ldr r3, [r3] 427 | lsr r3, r3, #30 428 | and r3, r3, #1 429 | mov r8, r3 430 | lsl r8, r8, #30 431 | 432 | bl firm_arm11kernel_getminorversion_firmimage 433 | mvn r1, #0 434 | cmp r0, r1 435 | beq init_firmlaunch_fwver_end 436 | 437 | orr r3, r0, r8 438 | ldrh r0, [sp] 439 | lsl r0, r0, #8 @ FIRM tidlow 440 | orr r3, r3, r0 441 | ldr r2, =FIRMLAUNCH_FWVER 442 | str r3, [r2] 443 | 444 | mov r0, #0 445 | 446 | init_firmlaunch_fwver_end: 447 | add sp, sp, #4 448 | pop {r4, r5, r6, r7, r8, pc} 449 | .pool 450 | 451 | firmbin_filepath: 452 | #ifndef ALTSD_FIRMPATH 453 | .hword 0x2F, 0x66, 0x69, 0x72, 0x6D, 0x2E, 0x62, 0x69, 0x6E, 0x00 //UTF-16 "/firm.bin" 454 | #else 455 | .string16 "/3dshax_firm.bin" 456 | #endif 457 | .align 2 458 | 459 | twlfirmbin_filepath: 460 | .hword 0x2F, 0x74, 0x77, 0x6C, 0x5F, 0x66, 0x69, 0x72, 0x6D, 0x2E, 0x62, 0x69, 0x6E, 0x00 //UTF-16 "/twl_firm.bin" 461 | .align 2 462 | 463 | firmlaunch_hook1_finishjumpadr: 464 | .word 0 465 | 466 | firmheader_address: 467 | .word 0 468 | 469 | #ifdef ENABLE_FIRMLAUNCH_LOADNAND 470 | .global proc9_swprintf_addr 471 | proc9_swprintf_addr: 472 | .word 0 473 | 474 | firm0device: 475 | .string16 "firm0:" 476 | #endif 477 | 478 | -------------------------------------------------------------------------------- /Makefile.arm9: -------------------------------------------------------------------------------- 1 | #--------------------------------------------------------------------------------- 2 | .SUFFIXES: 3 | #--------------------------------------------------------------------------------- 4 | 5 | ifeq ($(strip $(DEVKITARM)),) 6 | $(error "Please set DEVKITARM in your environment. export DEVKITARM=devkitARM") 7 | endif 8 | 9 | include $(DEVKITARM)/3ds_rules 10 | 11 | #--------------------------------------------------------------------------------- 12 | # TARGET is the name of the output 13 | # BUILD is the directory where object files & intermediate files will be placed 14 | # SOURCES is a list of directories containing source code 15 | # INCLUDES is a list of directories containing extra header files 16 | # DATA is a list of directories containing binary files embedded using bin2o 17 | # GRAPHICS is a list of directories containing image files to be converted with grit 18 | #--------------------------------------------------------------------------------- 19 | TARGET := 3dshax_arm9 20 | BUILD := build9 21 | SOURCES := 3dshaxarm9 3dshax_common 22 | INCLUDES := include 3dshaxarm9 3dshax_common 23 | DATA := data 24 | 25 | #--------------------------------------------------------------------------------- 26 | # options for code generation 27 | #--------------------------------------------------------------------------------- 28 | DEFINES := 29 | 30 | LDNAME := 3dshaxarm9.ld 31 | 32 | ARM9BINCPOUT_PATH := 33 | ifneq ($(strip $(ARM9BINCPOUT_PATH)),) 34 | ARM9BINCPOUT_PATH := $(ARM9BINCPOUT_PATH) 35 | endif 36 | 37 | BINCPCMD := 38 | ifneq ($(strip $(OUTPATH)),) 39 | BINCPCMD := @cp $(OUTPUT).bin $(OUTPATH)$(ARM9BINCPOUT_PATH) 40 | endif 41 | 42 | ifeq ($(strip $(DISABLEAES)),) 43 | DEFINES := $(DEFINES) -DENABLEAES 44 | endif 45 | 46 | ifeq ($(strip $(DISABLENANDREDIR)),) 47 | DEFINES := $(DEFINES) -DENABLENANDREDIR 48 | endif 49 | 50 | ifeq ($(strip $(DISABLE_ARM9DEBUGGING)),) 51 | DEFINES := $(DEFINES) -DENABLE_ARM9DEBUGGING 52 | endif 53 | 54 | ifeq ($(strip $(DISABLE_ARM11KERNEL_DEBUG)),) 55 | DEFINES := $(DEFINES) -DENABLE_ARM11KERNEL_DEBUG 56 | endif 57 | 58 | ifeq ($(strip $(DISABLE_ARM11KERNEL_PROCSTARTHOOK)),) 59 | DEFINES := $(DEFINES) -DENABLE_ARM11KERNEL_PROCSTARTHOOK 60 | endif 61 | 62 | ifneq ($(strip $(DISABLE_ARM11KERNEL_SVCHANDLER_PATCH)),) 63 | DEFINES := $(DEFINES) -DDISABLE_ARM11KERNEL_SVCHANDLER_PATCH 64 | endif 65 | 66 | ifneq ($(strip $(DISABLE_NETDEBUG)),) 67 | DEFINES := $(DEFINES) -DDISABLE_NETDEBUG=1 68 | endif 69 | 70 | ifneq ($(strip $(ENABLE_ARM11KERNEL_SVCBREAKPATCH)),) 71 | DEFINES := $(DEFINES) -DENABLE_ARM11KERNEL_SVCBREAKPATCH=1 72 | endif 73 | 74 | ifeq ($(strip $(DISABLE_GETEXHDRHOOK)),) 75 | DEFINES := $(DEFINES) -DENABLE_GETEXHDRHOOK 76 | endif 77 | 78 | ifneq ($(strip $(ENABLE_LOADA9_x01FFB800)),) 79 | DEFINES := $(DEFINES) -DENABLE_LOADA9_x01FFB800 80 | endif 81 | 82 | ifneq ($(strip $(LOADA9_x01FFB800_INCFILEPATH)),) 83 | DEFINES := $(DEFINES) -DLOADA9_x01FFB800_INCFILEPATH=\"$(LOADA9_x01FFB800_INCFILEPATH)\" 84 | endif 85 | 86 | ifneq ($(strip $(ENABLE_ARM11PROCLIST_OVERRIDE)),) 87 | DEFINES := $(DEFINES) -DENABLE_ARM11PROCLIST_OVERRIDE 88 | endif 89 | 90 | ifneq ($(strip $(ENABLE_REGIONFREE)),) 91 | DEFINES := $(DEFINES) -DENABLE_REGIONFREE=1 92 | endif 93 | 94 | ifneq ($(strip $(ENABLE_THEMECACHENAME)),) 95 | DEFINES := $(DEFINES) -DENABLE_THEMECACHENAME=1 96 | endif 97 | 98 | ifneq ($(strip $(DISABLE_GAMECARDUPDATE)),) 99 | DEFINES := $(DEFINES) -DDISABLE_GAMECARDUPDATE=1 100 | endif 101 | 102 | ifeq ($(strip $(ENABLE_REGIONFREE)),2) 103 | DEFINES := $(DEFINES) -DDISABLE_GAMECARDUPDATE=1 104 | endif 105 | 106 | ifneq ($(strip $(ADDEXHDR_SYSMODULE_DEPENDENCY)),) 107 | DEFINES := $(DEFINES) -DADDEXHDR_SYSMODULE_DEPENDENCY=$(ADDEXHDR_SYSMODULE_DEPENDENCY) 108 | endif 109 | 110 | ifneq ($(strip $(ADDEXHDR_SYSMODULE_DEPENDENCY_PADCHECK)),) 111 | DEFINES := $(DEFINES) -DADDEXHDR_SYSMODULE_DEPENDENCY_PADCHECK=$(ADDEXHDR_SYSMODULE_DEPENDENCY_PADCHECK) 112 | endif 113 | 114 | ifneq ($(strip $(ENABLE_BROWSER_APPMEM)),) 115 | DEFINES := $(DEFINES) -DENABLE_BROWSER_APPMEM 116 | endif 117 | 118 | ifneq ($(strip $(ENABLE_GAMECARD)),) 119 | DEFINES := $(DEFINES) -DENABLE_GAMECARD 120 | endif 121 | 122 | ifneq ($(strip $(ENABLE_ARM11CODELOAD_SERVACCESSCONTROL_OVERWRITE)),) 123 | DEFINES := $(DEFINES) -DENABLE_ARM11CODELOAD_SERVACCESSCONTROL_OVERWRITE=1 124 | endif 125 | 126 | ifneq ($(strip $(ENABLE_OLDFS_AUTOLOCATE)),) 127 | DEFINES := $(DEFINES) -DENABLE_OLDFS_AUTOLOCATE=1 128 | endif 129 | 130 | ifneq ($(strip $(ENABLE_DMA)),) 131 | DEFINES := $(DEFINES) -DENABLE_DMA=1 132 | endif 133 | 134 | ifneq ($(strip $(DISABLE_FSACCESSINFO_OVERWRITE)),) 135 | DEFINES := $(DEFINES) -DDISABLE_FSACCESSINFO_OVERWRITE 136 | endif 137 | 138 | ifneq ($(strip $(DISABLE_A9THREAD)),) 139 | DEFINES := $(DEFINES) -DDISABLE_A9THREAD=1 140 | endif 141 | 142 | ifneq ($(strip $(ENABLE_CONFIGMEM_DEVUNIT)),) 143 | DEFINES := $(DEFINES) -DENABLE_CONFIGMEM_DEVUNIT=1 144 | endif 145 | 146 | ifneq ($(strip $(ENABLE_FIRMLAUNCH_HOOK)),) 147 | DEFINES := $(DEFINES) -DENABLE_FIRMLAUNCH_HOOK=1 148 | endif 149 | 150 | ifneq ($(strip $(DISABLE_FIRMLAUNCH_LOADSD)),) 151 | DEFINES := $(DEFINES) -DDISABLE_FIRMLAUNCH_LOADSD=1 152 | endif 153 | 154 | ifneq ($(strip $(ENABLE_FIRMLAUNCH_LOADNAND)),) 155 | DEFINES := $(DEFINES) -DENABLE_FIRMLAUNCH_LOADNAND=1 156 | endif 157 | 158 | ifneq ($(strip $(ALTSD_FIRMPATH)),) 159 | DEFINES := $(DEFINES) -DALTSD_FIRMPATH=1 160 | endif 161 | 162 | ifneq ($(strip $(DISABLE_MATCHINGFIRM_HWCHECK)),) 163 | DEFINES := $(DEFINES) -DDISABLE_MATCHINGFIRM_HWCHECK=1 164 | endif 165 | 166 | ifneq ($(strip $(ENABLE_BOOTSAFEFIRM_STARTUP)),) 167 | DEFINES := $(DEFINES) -DENABLE_BOOTSAFEFIRM_STARTUP=1 168 | endif 169 | 170 | ifneq ($(strip $(ENABLE_CMDLOGGING)),) 171 | DEFINES := $(DEFINES) -DARM11KERNEL_ENABLECMDLOG 172 | endif 173 | 174 | ifneq ($(strip $(CMDLOGGING_PADCHECK)),) 175 | DEFINES := $(DEFINES) -DCMDLOGGING_PADCHECK=$(CMDLOGGING_PADCHECK) 176 | endif 177 | 178 | ifneq ($(strip $(CMDLOGGING_PROCNAME0)),) 179 | DEFINES := $(DEFINES) -DCMDLOGGING_PROCNAME0=$(CMDLOGGING_PROCNAME0) 180 | endif 181 | 182 | ifneq ($(strip $(CMDLOGGING_PROCNAME1)),) 183 | DEFINES := $(DEFINES) -DCMDLOGGING_PROCNAME1=$(CMDLOGGING_PROCNAME1) 184 | endif 185 | 186 | ifneq ($(strip $(CMDLOGGING_ALTPROCNAME)),) 187 | DEFINES := $(DEFINES) -DCMDLOGGING_ALTPROCNAME=$(CMDLOGGING_ALTPROCNAME) 188 | endif 189 | 190 | ifneq ($(strip $(CMDLOGGING_IGNORE_PROCNAME)),) 191 | DEFINES := $(DEFINES) -DCMDLOGGING_IGNORE_PROCNAME=$(CMDLOGGING_IGNORE_PROCNAME) 192 | endif 193 | 194 | ifneq ($(strip $(CMDLOGGING_CMDHDR_FILTER)),) 195 | DEFINES := $(DEFINES) -DCMDLOGGING_CMDHDR_FILTER=$(CMDLOGGING_CMDHDR_FILTER) 196 | endif 197 | 198 | ifneq ($(strip $(ENABLE_DUMP_NANDIMAGE)),) 199 | DEFINES := $(DEFINES) -DENABLE_DUMP_NANDIMAGE 200 | endif 201 | 202 | ifneq ($(strip $(NANDREDIR_SECTORNUM)),) 203 | DEFINES := $(DEFINES) -DNANDREDIR_SECTORNUM_=$(NANDREDIR_SECTORNUM) 204 | endif 205 | 206 | ifneq ($(strip $(NANDREDIR_SECTORNUM_PADCHECK0)),) 207 | DEFINES := $(DEFINES) -DNANDREDIR_SECTORNUM_PADCHECK0=$(NANDREDIR_SECTORNUM_PADCHECK0) 208 | endif 209 | 210 | ifneq ($(strip $(NANDREDIR_SECTORNUM_PADCHECK0VAL)),) 211 | DEFINES := $(DEFINES) -DNANDREDIR_SECTORNUM_PADCHECK0VAL=$(NANDREDIR_SECTORNUM_PADCHECK0VAL) 212 | endif 213 | 214 | ifneq ($(strip $(NANDREDIR_SECTORNUM_PADCHECK1)),) 215 | DEFINES := $(DEFINES) -DNANDREDIR_SECTORNUM_PADCHECK1=$(NANDREDIR_SECTORNUM_PADCHECK1) 216 | endif 217 | 218 | ifneq ($(strip $(NANDREDIR_SECTORNUM_PADCHECK1VAL)),) 219 | DEFINES := $(DEFINES) -DNANDREDIR_SECTORNUM_PADCHECK1VAL=$(NANDREDIR_SECTORNUM_PADCHECK1VAL) 220 | endif 221 | 222 | ifneq ($(strip $(LOADA9_NEW3DSMEM)),) 223 | DEFINES := $(DEFINES) -DLOADA9_NEW3DSMEM 224 | LDNAME := 3dshaxarm9new3dsmem.ld 225 | endif 226 | 227 | ifneq ($(strip $(LOADA9_FCRAM)),) 228 | DEFINES := $(DEFINES) -DLOADA9_FCRAM 229 | LDNAME := 3dshaxarm9fcram.ld 230 | endif 231 | 232 | ifneq ($(strip $(NEW3DS_MEMDUMPA9_ADR)),) 233 | DEFINES := $(DEFINES) -DNEW3DS_MEMDUMPA9_ADR=$(NEW3DS_MEMDUMPA9_ADR) 234 | endif 235 | 236 | ifneq ($(strip $(NEW3DS_MEMDUMPA9_SIZE)),) 237 | DEFINES := $(DEFINES) -DNEW3DS_MEMDUMPA9_SIZE=$(NEW3DS_MEMDUMPA9_SIZE) 238 | endif 239 | 240 | ifneq ($(strip $(NEW3DS_MEMDUMPA9_DISABLEVRAMCLR)),) 241 | DEFINES := $(DEFINES) -DNEW3DS_MEMDUMPA9_DISABLEVRAMCLR 242 | endif 243 | 244 | ifneq ($(strip $(NEW3DS_ARM9BINLDR_PATCHADDR0)),) 245 | DEFINES := $(DEFINES) -DNEW3DS_ARM9BINLDR_PATCHADDR0=$(NEW3DS_ARM9BINLDR_PATCHADDR0) 246 | endif 247 | 248 | ifneq ($(strip $(NEW3DS_ARM9BINLDR_PATCHADDR0_VAL)),) 249 | DEFINES := $(DEFINES) -DNEW3DS_ARM9BINLDR_PATCHADDR0_VAL=$(NEW3DS_ARM9BINLDR_PATCHADDR0_VAL) 250 | endif 251 | 252 | ifneq ($(strip $(NEW3DS_ARM9BINLDR_PATCHADDR1)),) 253 | DEFINES := $(DEFINES) -DNEW3DS_ARM9BINLDR_PATCHADDR1=$(NEW3DS_ARM9BINLDR_PATCHADDR1) 254 | endif 255 | 256 | ifneq ($(strip $(NEW3DS_ARM9BINLDR_PATCHADDR1_VAL)),) 257 | DEFINES := $(DEFINES) -DNEW3DS_ARM9BINLDR_PATCHADDR1_VAL=$(NEW3DS_ARM9BINLDR_PATCHADDR1_VAL) 258 | endif 259 | 260 | ifneq ($(strip $(NEW3DS_ARM9BINLDR_CLRMEM)),) 261 | DEFINES := $(DEFINES) -DNEW3DS_ARM9BINLDR_CLRMEM=$(NEW3DS_ARM9BINLDR_CLRMEM) 262 | endif 263 | 264 | ifneq ($(strip $(NEW3DS_ARM9BINLDR_CLRMEM_SIZE)),) 265 | DEFINES := $(DEFINES) -DNEW3DS_ARM9BINLDR_CLRMEM_SIZE=$(NEW3DS_ARM9BINLDR_CLRMEM_SIZE) 266 | endif 267 | 268 | ifneq ($(strip $(ENABLE_NIMURLS_PATCHES)),) 269 | DEFINES := $(DEFINES) -DENABLE_NIMURLS_PATCHES 270 | endif 271 | 272 | ifneq ($(strip $(NIMPATCHURL_UPDATE)),) 273 | DEFINES := $(DEFINES) -DNIMPATCHURL_UPDATE=\"$(NIMPATCHURL_UPDATE)\" 274 | endif 275 | 276 | ifneq ($(strip $(NIMPATCHURL_ECOMMERCE)),) 277 | DEFINES := $(DEFINES) -DNIMPATCHURL_ECOMMERCE=\"$(NIMPATCHURL_ECOMMERCE)\" 278 | endif 279 | 280 | ifneq ($(strip $(ENABLE_LOADSD_AESKEYS)),) 281 | DEFINES := $(DEFINES) -DENABLE_LOADSD_AESKEYS 282 | endif 283 | 284 | ifneq ($(strip $(MEMDUMPBOOT_SRCADDR)),) 285 | DEFINES := $(DEFINES) -DMEMDUMPBOOT_SRCADDR=$(MEMDUMPBOOT_SRCADDR) 286 | endif 287 | 288 | ifneq ($(strip $(MEMDUMPBOOT_DSTADDR)),) 289 | DEFINES := $(DEFINES) -DMEMDUMPBOOT_DSTADDR=$(MEMDUMPBOOT_DSTADDR) 290 | endif 291 | 292 | ifneq ($(strip $(MEMDUMPBOOT_SIZE)),) 293 | DEFINES := $(DEFINES) -DMEMDUMPBOOT_SIZE=$(MEMDUMPBOOT_SIZE) 294 | endif 295 | 296 | ARCH := -mthumb -mthumb-interwork 297 | 298 | CFLAGS := -g -Wall -Os\ 299 | -march=armv5te -mtune=arm946e-s -fomit-frame-pointer\ 300 | -ffast-math \ 301 | $(ARCH) 302 | 303 | CFLAGS += $(INCLUDE) -DARM9 $(DEFINES) 304 | CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions 305 | 306 | ASFLAGS := -g $(ARCH) $(DEFINES) 307 | LDFLAGS = -nostartfiles -T../$(LDNAME) -g $(ARCH) -Wl,-Map,$(notdir $*.map) 308 | 309 | #--------------------------------------------------------------------------------- 310 | # any extra libraries we wish to link with the project (order is important) 311 | #--------------------------------------------------------------------------------- 312 | LIBS := 313 | 314 | 315 | #--------------------------------------------------------------------------------- 316 | # list of directories containing libraries, this must be the top level containing 317 | # include and lib 318 | #--------------------------------------------------------------------------------- 319 | LIBDIRS := $(CTRULIB) 320 | 321 | #--------------------------------------------------------------------------------- 322 | # no real need to edit anything past this point unless you need to add additional 323 | # rules for different file extensions 324 | #--------------------------------------------------------------------------------- 325 | ifneq ($(BUILD),$(notdir $(CURDIR))) 326 | #--------------------------------------------------------------------------------- 327 | 328 | export OUTPUT := $(CURDIR)/$(TARGET) 329 | 330 | export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \ 331 | $(foreach dir,$(DATA),$(CURDIR)/$(dir)) \ 332 | $(foreach dir,$(GRAPHICS),$(CURDIR)/$(dir)) 333 | 334 | export DEPSDIR := $(CURDIR)/$(BUILD) 335 | 336 | CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) 337 | CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) 338 | SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) 339 | PNGFILES := $(foreach dir,$(GRAPHICS),$(notdir $(wildcard $(dir)/*.png))) 340 | BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) 341 | 342 | #--------------------------------------------------------------------------------- 343 | # use CXX for linking C++ projects, CC for standard C 344 | #--------------------------------------------------------------------------------- 345 | ifeq ($(strip $(CPPFILES)),) 346 | #--------------------------------------------------------------------------------- 347 | export LD := $(CC) 348 | #--------------------------------------------------------------------------------- 349 | else 350 | #--------------------------------------------------------------------------------- 351 | export LD := $(CXX) 352 | #--------------------------------------------------------------------------------- 353 | endif 354 | #--------------------------------------------------------------------------------- 355 | 356 | export OFILES := $(addsuffix .o,$(BINFILES)) \ 357 | $(PNGFILES:.png=.o) \ 358 | $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o) 359 | 360 | export INCLUDE := $(foreach dir,$(INCLUDES),-iquote $(CURDIR)/$(dir)) \ 361 | $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ 362 | -I$(CURDIR)/$(BUILD) 363 | 364 | export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) 365 | 366 | .PHONY: $(BUILD) clean 367 | 368 | #--------------------------------------------------------------------------------- 369 | $(BUILD): 370 | @[ -d $@ ] || mkdir -p $@ 371 | @make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile.arm9 372 | 373 | #--------------------------------------------------------------------------------- 374 | clean: 375 | @echo clean ... 376 | @rm -fr $(BUILD) $(TARGET).elf $(TARGET).bin 377 | 378 | #--------------------------------------------------------------------------------- 379 | else 380 | 381 | #--------------------------------------------------------------------------------- 382 | # main targets 383 | #--------------------------------------------------------------------------------- 384 | 385 | $(OUTPUT).bin : $(OUTPUT).elf 386 | @$(OBJCOPY) -O binary $< $@ 387 | $(BINCPCMD) 388 | @echo "ARM9BINCPOUT_PATH: $(ARM9BINCPOUT_PATH)" 389 | @echo built ... $(notdir $@) 390 | 391 | $(OUTPUT).elf : $(OFILES) 392 | 393 | #--------------------------------------------------------------------------------- 394 | %.bin.o : %.bin 395 | #--------------------------------------------------------------------------------- 396 | @echo $(notdir $<) 397 | $(bin2o) 398 | 399 | -include $(DEPSDIR)/*.d 400 | 401 | #--------------------------------------------------------------------------------------- 402 | endif 403 | #--------------------------------------------------------------------------------------- 404 | -------------------------------------------------------------------------------- /3dshax_parsedebug.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | FILE *fdebuginfo; 8 | int enable_hexdump = 0; 9 | unsigned int debuginfo_pos; 10 | 11 | char regnames[16][4] = {"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "sl", "fp", "ip", "sp", "lr", "pc"}; 12 | 13 | void hexdump(void *ptr, int buflen)//This is based on code from ctrtool. 14 | { 15 | unsigned char *buf = (unsigned char*)ptr; 16 | int i, j; 17 | 18 | for (i=0; i= 0x20 && buf[i+j] <= 0x7e) ? buf[i+j] : '.'); 40 | } 41 | } 42 | printf("\n"); 43 | } 44 | } 45 | 46 | void parse_debuginfo_exception(unsigned int *debuginfo, uint32_t new, uint32_t formatversion) 47 | { 48 | FILE *ftmp; 49 | int i; 50 | unsigned int regs[16]; 51 | unsigned int cpsr; 52 | unsigned int exceptiontype; 53 | unsigned char *ptr8; 54 | unsigned int RUNNINGFWVER; 55 | unsigned int tmp; 56 | uint32_t zeros_x20[0x20]; 57 | char processname[16]; 58 | char str[256]; 59 | 60 | memset(processname, 0, 16); 61 | strncpy(processname, (char*)&debuginfo[(0x50+4)>>2], 8); 62 | printf("Process name: %s\n", processname); 63 | 64 | memset(regs, 0, 16 * 4); 65 | for(i=0; i<13; i++)regs[i] = debuginfo[i]; 66 | regs[13] = debuginfo[14]; 67 | regs[14] = debuginfo[15]; 68 | regs[15] = debuginfo[17]; 69 | cpsr = debuginfo[19+1]; 70 | exceptiontype = debuginfo[16]; 71 | 72 | if((cpsr & 0x1f) != 0x10)regs[14] = debuginfo[18]; 73 | 74 | if(exceptiontype==0) 75 | { 76 | printf("Undefined instruction\n"); 77 | } 78 | else if(exceptiontype==1) 79 | { 80 | printf("Prefetch abort\n"); 81 | } 82 | else if(exceptiontype==2) 83 | { 84 | printf("Data abort\n"); 85 | } 86 | 87 | for(i=0; i<16; i+=4) 88 | { 89 | printf("%s = 0x%08x ", regnames[i], regs[i]); 90 | printf("%s = 0x%08x ", regnames[i+1], regs[i+1]); 91 | printf("%s = 0x%08x ", regnames[i+2], regs[i+2]); 92 | printf("%s = 0x%08x ", regnames[i+3], regs[i+3]); 93 | printf("\n"); 94 | } 95 | 96 | printf("cpsr: 0x%08x\n", cpsr); 97 | 98 | if(strncmp(processname, "Process9", 8))//Only print these for ARM11 processes. 99 | { 100 | printf("Process MMU table ptr: 0x%08x\n", debuginfo[(0x58+4)>>2]); 101 | printf("DFSR: 0x%08x\n", debuginfo[(0x5c+4)>>2]); 102 | printf("IFSR: 0x%08x\n", debuginfo[(0x60+4)>>2]); 103 | printf("FAR: 0x%08x\n", debuginfo[(0x64+4)>>2]); 104 | 105 | if(new && formatversion>=1) 106 | { 107 | printf("WFAR: 0x%08x\n", debuginfo[(0x90+0x164 + 0x0)>>2]); 108 | printf("c13 contextID register: 0x%08x\n", debuginfo[(0x90+0x164 + 0x4)>>2]); 109 | printf("c13 threadID register: 0x%08x\n", debuginfo[(0x90+0x164 + 0x8)>>2]); 110 | printf("CPUID register: 0x%08x\n", debuginfo[(0x90+0x164 + 0xc)>>2]); 111 | printf("KThread kernel VA: 0x%08x\n", debuginfo[(0x90+0x164 + 0x10)>>2]); 112 | printf("KProcess kernel VA: 0x%08x\n", debuginfo[(0x90+0x164 + 0x14)>>2]); 113 | 114 | if(formatversion>=2) 115 | { 116 | tmp = debuginfo[(0x90+0x164 + 0x18)>>2]; 117 | printf("DSCR: 0x%08x. ", tmp); 118 | 119 | tmp = (tmp & 0x3c) >> 2; 120 | printf("Method-of-entry: 0x%x, ", tmp); 121 | if(tmp==0) 122 | { 123 | printf("default setting.\n"); 124 | } 125 | else 126 | { 127 | switch(tmp) 128 | { 129 | case 1: 130 | printf("breakpoint"); 131 | break; 132 | 133 | case 2: 134 | printf("watchpoint"); 135 | break; 136 | 137 | case 3: 138 | printf("bkpt instruction"); 139 | break; 140 | 141 | case 4: 142 | printf("EDBGRQ signal"); 143 | break; 144 | 145 | case 5: 146 | printf("vector catch"); 147 | break; 148 | 149 | case 6: 150 | printf("data-side abort"); 151 | break; 152 | 153 | case 7: 154 | printf("instruction-side abort"); 155 | break; 156 | 157 | default: 158 | printf("invalid"); 159 | break; 160 | } 161 | 162 | printf(".\n"); 163 | } 164 | } 165 | } 166 | } 167 | 168 | if(enable_hexdump) 169 | { 170 | memset(zeros_x20, 0, 0x20); 171 | 172 | if(memcmp(&debuginfo[(0x68+4)>>2], zeros_x20, 0x20)!=0) 173 | { 174 | ftmp = fopen("3dshaxparsedebug_tmpcode.bin", "wb"); 175 | 176 | if(ftmp) 177 | { 178 | fwrite(&debuginfo[(0x68+4)>>2], 1, 0x20, ftmp); 179 | fclose(ftmp); 180 | 181 | snprintf(str, 255, "arm-none-eabi-objdump -D -b binary -m arm --adjust-vma=0x%0x", regs[15]-0x10); 182 | 183 | if(cpsr & 0x20)strncat(str, " -M force-thumb", 255); 184 | 185 | strncat(str, " 3dshaxparsedebug_tmpcode.bin", 255); 186 | 187 | printf("\nDisassembly from pc-0x10(0x%08x):\n", regs[15]-0x10); 188 | system(str); 189 | printf("\n"); 190 | 191 | unlink("3dshaxparsedebug_tmpcode.bin"); 192 | } 193 | else 194 | { 195 | printf("Failed to open file for writing: 3dshaxparsedebug_tmpcode.bin\n"); 196 | } 197 | } 198 | else 199 | { 200 | printf("Skippig disasm since the dumped code is all-zero(probably due to inaccessible memory / prefetch abort).\n"); 201 | } 202 | 203 | RUNNINGFWVER = debuginfo[(0x8c)>>2]; 204 | printf("RUNNINGFWVER = 0x%08x. Hardware type = %s. FIRM tidlow u16 = 0x%x. Actual FWVER = %u/0x%x.\n", RUNNINGFWVER, RUNNINGFWVER & 0x40000000 ? "New3DS":"Old3DS", (RUNNINGFWVER>>8) & 0xffff, RUNNINGFWVER & 0xff, RUNNINGFWVER & 0xff); 205 | 206 | tmp = debuginfo[(0x210)>>2]; 207 | if(tmp == 0x38) 208 | { 209 | printf("Stack dump:\n"); 210 | } 211 | else 212 | { 213 | printf("Memory dump from "); 214 | if(tmp < 13*4) 215 | { 216 | printf("%s", regnames[tmp>>2]); 217 | } 218 | else 219 | { 220 | if(tmp == 14*4) 221 | { 222 | printf("%s", regnames[13]); 223 | } 224 | else if(tmp == 15*4) 225 | { 226 | printf("%s", regnames[14]); 227 | } 228 | else if(tmp == 17*4) 229 | { 230 | printf("%s", regnames[15]); 231 | } 232 | else if(tmp == 18*4) 233 | { 234 | printf("%s", regnames[14]); 235 | } 236 | else 237 | { 238 | printf(""); 239 | } 240 | } 241 | printf(":\n"); 242 | } 243 | hexdump(&debuginfo[(0x90)>>2], 0x164); 244 | printf("\n"); 245 | } 246 | } 247 | 248 | void parse_debuginfo_command(unsigned int *debuginfo) 249 | { 250 | unsigned int i, pos, src_wordsize, dst_wordsize, tmp_wordsize, bufpos; 251 | unsigned int cmd_wordpos, cmdreply_wordpos, base_wordpos; 252 | unsigned int type; 253 | unsigned int srcbufdata_size = 0; 254 | unsigned int dstbufdata_size = 0; 255 | unsigned int addpos = 0; 256 | unsigned char *srcbufdata = NULL; 257 | unsigned char *dstbufdata = NULL; 258 | char processname_src[16]; 259 | char processname_dst[16]; 260 | 261 | type = debuginfo[0]; 262 | 263 | memset(processname_src, 0, 16); 264 | memset(processname_dst, 0, 16); 265 | strncpy(processname_src, (char*)&debuginfo[0x4>>2], 8); 266 | strncpy(processname_dst, (char*)&debuginfo[0xc>>2], 8); 267 | 268 | if(type==0)printf("%s->%s ", processname_src, processname_dst); 269 | if(type==1)printf("%s->%s ", processname_dst, processname_src); 270 | 271 | if(type==1) 272 | { 273 | cmd_wordpos = 5+0x40; 274 | cmdreply_wordpos = 5; 275 | } 276 | else 277 | { 278 | cmd_wordpos = 5; 279 | cmdreply_wordpos = 5+0x40; 280 | } 281 | 282 | printf("command: "); 283 | 284 | dst_wordsize = (debuginfo[cmd_wordpos] & 0x3f) + ((debuginfo[cmd_wordpos] & 0xfc0) >> 6) + 1; 285 | 286 | for(i=0; i> 6) + 1; 296 | 297 | if(type==1) 298 | { 299 | for(i=0; i>2); i<(0x314>>2); i+=2) 307 | { 308 | srcbufdata_size+= debuginfo[i]; 309 | } 310 | 311 | if(type==1) 312 | { 313 | for(i=(0x314>>2); i<(0x414>>2); i+=2) 314 | { 315 | dstbufdata_size+= debuginfo[i]; 316 | } 317 | } 318 | 319 | printf("\n"); 320 | //printf("srcbufdata_size=0x%lx dstbufdata_size=0x%lx\n", srcbufdata_size, dstbufdata_size); 321 | 322 | if(srcbufdata_size==0 && dstbufdata_size==0)return; 323 | 324 | if(srcbufdata_size)srcbufdata = (unsigned char*)malloc(srcbufdata_size); 325 | if(dstbufdata_size)dstbufdata = (unsigned char*)malloc(dstbufdata_size); 326 | if((srcbufdata==NULL && srcbufdata_size) || (dstbufdata==NULL && dstbufdata_size)) 327 | { 328 | if(srcbufdata)free(srcbufdata); 329 | if(dstbufdata)free(dstbufdata); 330 | printf("Failed to allocate memory for srcbufdata/dstbufdata."); 331 | return; 332 | } 333 | 334 | if(srcbufdata)memset(srcbufdata, 0, srcbufdata_size); 335 | if(dstbufdata)memset(dstbufdata, 0, dstbufdata_size); 336 | 337 | if(srcbufdata)fread(srcbufdata, 1, srcbufdata_size, fdebuginfo); 338 | if(dstbufdata)fread(dstbufdata, 1, dstbufdata_size, fdebuginfo); 339 | 340 | if(dstbufdata && type==1) 341 | { 342 | pos=0x314>>2; 343 | i = ((debuginfo[cmd_wordpos] & 0xfc0) >> 6) + 1; 344 | bufpos = 0; 345 | addpos = 0; 346 | 347 | for(; i> 26; 354 | continue; 355 | } 356 | printf("cmd [%u] = vaddr 0x%x / physaddr 0x%x filepos 0x%x size 0x%x", i, debuginfo[cmd_wordpos+i+1], debuginfo[pos+1], debuginfo_pos+srcbufdata_size+bufpos, debuginfo[pos]); 357 | if(enable_hexdump)printf(":"); 358 | printf("\n"); 359 | 360 | if(enable_hexdump)hexdump(&dstbufdata[bufpos], debuginfo[pos]); 361 | 362 | bufpos+= debuginfo[pos]; 363 | } 364 | 365 | for(; bufpos < dstbufdata_size && pos < (0x414>>2); pos+=2) 366 | { 367 | if(debuginfo[pos]==0 || debuginfo[pos+1]==0)continue; 368 | 369 | printf("cmd additional_buf[%u] = physaddr 0x%x filepos 0x%x size 0x%x", pos, debuginfo[pos+1], debuginfo_pos+srcbufdata_size+bufpos, debuginfo[pos]); 370 | if(enable_hexdump)printf(":"); 371 | printf("\n"); 372 | 373 | if(enable_hexdump)hexdump(&dstbufdata[bufpos], debuginfo[pos]); 374 | 375 | bufpos+= debuginfo[pos]; 376 | } 377 | } 378 | 379 | if(srcbufdata) 380 | { 381 | if(type==1) 382 | { 383 | base_wordpos = cmdreply_wordpos; 384 | tmp_wordsize = src_wordsize; 385 | } 386 | else if(type==0) 387 | { 388 | base_wordpos = cmd_wordpos; 389 | tmp_wordsize = dst_wordsize; 390 | } 391 | 392 | pos=0x214>>2; 393 | i = ((debuginfo[base_wordpos] & 0xfc0) >> 6) + 1; 394 | bufpos = 0; 395 | addpos = 0; 396 | 397 | for(; i> 26; 404 | continue; 405 | } 406 | printf("%s [%u] = vaddr 0x%x / physaddr 0x%x filepos 0x%x size 0x%x", type==1?"cmdreply":"cmd", i, debuginfo[base_wordpos+i+1], debuginfo[pos+1], debuginfo_pos+bufpos, debuginfo[pos]); 407 | if(enable_hexdump)printf(":"); 408 | printf("\n"); 409 | 410 | if(enable_hexdump)hexdump(&srcbufdata[bufpos], debuginfo[pos]); 411 | 412 | bufpos+= debuginfo[pos]; 413 | } 414 | 415 | for(; bufpos < srcbufdata_size && pos < (0x314>>2); pos+=2) 416 | { 417 | if(debuginfo[pos]==0 || debuginfo[pos+1]==0)continue; 418 | 419 | printf("%s additional_buf[%u] = physaddr 0x%x filepos 0x%x size 0x%x", type==1?"cmdreply":"cmd", pos, debuginfo[pos+1], debuginfo_pos+bufpos, debuginfo[pos]); 420 | if(enable_hexdump)printf(":"); 421 | printf("\n"); 422 | 423 | if(enable_hexdump)hexdump(&srcbufdata[bufpos], debuginfo[pos]); 424 | 425 | bufpos+= debuginfo[pos]; 426 | } 427 | } 428 | 429 | debuginfo_pos+= srcbufdata_size + dstbufdata_size; 430 | 431 | if(srcbufdata)free(srcbufdata); 432 | if(dstbufdata)free(dstbufdata); 433 | } 434 | 435 | FILE *fvid = NULL; 436 | 437 | void parse_debuginfo_gxcmd3(unsigned int *debuginfo) 438 | { 439 | unsigned char *buf; 440 | 441 | printf("gxcmd3\n"); 442 | 443 | buf = (unsigned char*)malloc(debuginfo[5]); 444 | memset(buf, 0, debuginfo[5]); 445 | 446 | fread(buf, 1, debuginfo[5], fdebuginfo); 447 | debuginfo_pos+=debuginfo[5]; 448 | 449 | if(fvid==NULL)fvid = fopen("videodump.bin", "wb"); 450 | if(debuginfo[0] == 0x1f000000)fwrite(buf, 1, debuginfo[5], fvid); 451 | 452 | free(buf); 453 | } 454 | 455 | int main(int argc, char **argv) 456 | { 457 | unsigned int *debuginfo_ptr = NULL; 458 | unsigned int debuginfo[0x200>>2]; 459 | unsigned int debuginfo_size; 460 | uint32_t formatversion, parser_formatversion = 0x3; 461 | struct stat filestat; 462 | 463 | if(argc<2)return 0; 464 | 465 | if(stat(argv[1], &filestat)==-1)return 0; 466 | 467 | if(argc>2) 468 | { 469 | if(strncmp(argv[2], "--hexdump", 9)==0)enable_hexdump = 1; 470 | } 471 | 472 | debuginfo_size = (unsigned long)filestat.st_size; 473 | if(debuginfo_size<0x200) 474 | { 475 | printf("Debuginfo size is invalid: 0x%x\n", debuginfo_size); 476 | return 2; 477 | } 478 | 479 | memset(debuginfo, 0, 0x200); 480 | 481 | fdebuginfo = fopen(argv[1], "rb"); 482 | if(fdebuginfo==NULL)return 2; 483 | 484 | debuginfo_pos = 0; 485 | while(debuginfo_pos < debuginfo_size) 486 | { 487 | fread(debuginfo, 1, 12, fdebuginfo); 488 | 489 | if(debuginfo[0] != 0x58584148) 490 | { 491 | printf("Invalid magic number.\n"); 492 | fclose(fdebuginfo); 493 | return 1; 494 | } 495 | 496 | debuginfo_ptr = (unsigned int*)malloc(debuginfo[2]); 497 | if(debuginfo_ptr==NULL) 498 | { 499 | printf("Failed to allocate debuginfo_buf with size 0x%x.\n", debuginfo[2]); 500 | fclose(fdebuginfo); 501 | return 1; 502 | } 503 | memcpy(debuginfo_ptr, debuginfo, 12); 504 | fread(&debuginfo_ptr[12>>2], 1, debuginfo[2]-12, fdebuginfo); 505 | 506 | printf("pos 0x%x: ", debuginfo_pos); 507 | debuginfo_pos+= debuginfo[2]; 508 | 509 | fseek(fdebuginfo, debuginfo_pos, SEEK_SET); 510 | 511 | if(debuginfo[1]==0x47424445) 512 | { 513 | printf("Exception(old format)\n"); 514 | parse_debuginfo_exception(&debuginfo_ptr[3], 0, 0); 515 | } 516 | else if(debuginfo[1]==0x4e474445) 517 | { 518 | formatversion = debuginfo_ptr[3]; 519 | 520 | printf("Exception(new format, version=0x%x)\n", formatversion); 521 | if(formatversion > parser_formatversion) 522 | { 523 | printf("The exception dump format version(0x%x) is newer than the version supported by this parser(0x%x). Skipping parsing.\n", formatversion, parser_formatversion); 524 | } 525 | parse_debuginfo_exception(&debuginfo_ptr[4], 1, formatversion); 526 | } 527 | else if(debuginfo[1]==0x444d4344) 528 | { 529 | parse_debuginfo_command(&debuginfo_ptr[3]); 530 | } 531 | else if(debuginfo[1]==0x33435847) 532 | { 533 | parse_debuginfo_gxcmd3(&debuginfo_ptr[3]); 534 | } 535 | else 536 | { 537 | printf("Skipping unknown debuginfo with type 0x%08x\n", debuginfo[1]); 538 | 539 | debuginfo_pos+= debuginfo[2]; 540 | 541 | /*printf("Old debuginfo(exception) pos 0x%lx:\n", debuginfo_pos); 542 | debuginfo_pos+= 0x200; 543 | 544 | parse_debuginfo_exception(&debuginfo[1]); 545 | printf("\n");*/ 546 | } 547 | 548 | fseek(fdebuginfo, debuginfo_pos, SEEK_SET); 549 | 550 | free(debuginfo_ptr); 551 | } 552 | 553 | fclose(fdebuginfo); 554 | if(fvid)fclose(fvid); 555 | 556 | return 0; 557 | } 558 | 559 | -------------------------------------------------------------------------------- /3dshaxarm11_ctrserverold/necir.c: -------------------------------------------------------------------------------- 1 | //This is based on the code from: http://openlgtv.org.ru/wiki/index.php/Using_a_generic_microcontroller_board_as_an_LG_service_remote 2 | 3 | // ==================================================================== 4 | // "NEC protocol" IR Remote implementation for the Atmel ATtiny2313 5 | // microcontroller. Originally made for a board with 8 red LEDs and 6 | // two momentary push buttons but only really requires a single LED 7 | // if you reduce the code down to its core. 8 | // -------------------------------------------------------------------- 9 | // This should be pretty easily portable to other microcontrollers 10 | // or similar low-end singletasking systems. You need to be able to 11 | // generate accurate delays in the microseconds range, though. 12 | // ==================================================================== 13 | // 14 | // Copyright (c) 2011 Jukka Aho 15 | // 16 | // Permission is hereby granted, free of charge, to any person 17 | // obtaining a copy of this software and associated documentation 18 | // files (the "Software"), to deal in the Software without restriction, 19 | // including without limitation the rights to use, copy, modify, merge, 20 | // publish, distribute, sublicense, and/or sell copies of the Software, 21 | // and to permit persons to whom the Software is furnished to do so, 22 | // subject to the following conditions: 23 | // 24 | // The above copyright notice and this permission notice shall be 25 | // included in all copies or substantial portions of the Software. 26 | // 27 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 28 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 29 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 30 | // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 31 | // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 32 | // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 33 | // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 34 | 35 | // The number in the F_CPU macro needs to match your Atmel 36 | // microcontroller CPU clock in Hz. If it doesn't, the delay functions 37 | // in delay.h will not work properly and you will not get proper timing. 38 | // I'm using a 10 MHz crystal with the ATtiny2313, hence 10000000UL. 39 | 40 | /*#define F_CPU 10000000UL 41 | 42 | #include 43 | #include 44 | #include */ 45 | 46 | #include 47 | #include 48 | #include 49 | #include 50 | #include 51 | #include 52 | #include 53 | 54 | // On the ATtiny2313 board I used (kudos to my little brother for 55 | // building it and lending it to me in the first place!) there is 56 | // a straight row of 8 red LEDs, looking like this: 57 | // 58 | // o o o o o o o o 59 | // 7 6 5 4 3 2 1 0 60 | // 61 | // Each LED is connected to the I/O lines of the port "B", which is 62 | // represented on the CPU side as an 8-bit, 8-line GPIO register. 63 | // The register that controls these lines is called "PORTB". The 64 | // individual bits of this register directly control whether the 65 | // individual LEDs are lit or not. 66 | // 67 | // The row of LEDs serves dual purposes in this implementation: 68 | // 69 | // 1) The LEDs are used as indicator lights for displaying the 70 | // currently selected, "active" IR command to the user. (The 71 | // user can cycle through a small set of predefined, hardcoded 72 | // IR commands with one push-button, then transmit the selected 73 | // IR command with a press of another button.) 74 | // 75 | // 2) The LEDs are also used as "IR" LEDs: for blinking/flashing 76 | // out the IR code when the user presses the "transmit" button. 77 | // 78 | // The latter part works because red LEDs, when lit, will emit some 79 | // energy also in the IR part of the spectrum: not much, but enough 80 | // to control the TV from a close distance. You just need to bring 81 | // the LEDs as near to the IR eye of the TV as possible (5...15 cm 82 | // would appear to be near enough.) 83 | // 84 | // Using a genuine IR LED would give you more range. And even a 85 | // single red LED would do for transmitting the IR commands - you 86 | // don't need 8 of them! But since the board I used was already 87 | // populated with 8 red LEDs and since they handily doubled as 88 | // both IR transmitters and indicator lights, the setup was good 89 | // enough for my purposes, "as is". 90 | // 91 | // Here's a function-like macro for setting the bits of the PORTB 92 | // register: in other words, the state of the indicator LEDs: 93 | 94 | //#define set_portb(value) (PORTB = value) 95 | 96 | // For quick porting, you can replace this with an actual function or 97 | // another macro definition which deals with the indicator lights in 98 | // a different way. Or if you don't use or need indicator LEDs at all, 99 | // simply redefine set_portb() as a no-op operation, such as a mere 100 | // semicolon. Note that the state of the LEDs connected to PORTB is 101 | // defined in inverse logic: 0 = on, 1 = off. 102 | 103 | // As for blinking out the IR commands, we actually set _all_ the 104 | // eight LEDs on and off "in unison": 105 | 106 | //#define set_ir_led_on() set_portb(0x00) 107 | //#define set_ir_led_off() set_portb(0xFF) 108 | #define set_ir_led_on() IRU_SetIRLEDState(1) 109 | #define set_ir_led_off() IRU_SetIRLEDState(0) 110 | 111 | #define _delay_us(val) svc_sleepThread((u64)(val*1000)) 112 | #define _delay_ms(val) svc_sleepThread((u64)(val*1000000)) 113 | 114 | // If you do not use this dual-purpose LED approach but have a 115 | // separate IR LED for blinking the code out, redefining the 116 | // macros set_ir_led_on() and set_ir_led_off() to something 117 | // sensible for your architecture would do the trick there. 118 | 119 | // The board I used has two push-buttons (momentary switches) for 120 | // user input: "SELECT" and "TRANSMIT". They could look like this: 121 | // 122 | // [o] SELECT 123 | // 124 | // [o] TRANSMIT 125 | // 126 | // In this implementation, we predefine 8 hardcoded IR command codes. 127 | // These will be stored in the flash memory our "remote". The user can 128 | // cycle through the available commands with the "SELECT" button (the 129 | // corresponding indicator LED will be lit) and then press the 130 | // "TRANSMIT" button in order to blink the selected command out. 131 | 132 | // The "SELECT" and the "TRANSMIT" buttons are connected to the input 133 | // lines on the ATtiny2313 GPIO port "D". The state of the "SELECT" 134 | // button is readable in the bit 2 of the PIND register. The "TRANSMIT" 135 | // button is the bit 3, respectively. Inverse logic applies here as 136 | // well: the state of the button bit is 0 when the button is depressed. 137 | // Here are the two helper functions which will be used for testing the 138 | // button states later on, you may want to redefine them for your 139 | // implementation: 140 | 141 | /*uint8_t get_select_button_state() { 142 | return ~PIND & (1 << 2); 143 | } 144 | 145 | uint8_t get_transmit_button_state() { 146 | return ~PIND & (1 << 3); 147 | }*/ 148 | 149 | // This IR Remote implementation was created primarily for getting 150 | // into the service menus of LG TVs. 151 | // 152 | // LG uses the so-called NEC IR protocol in their TVs. This protocol 153 | // transmits a device address byte followed by a bit-inverted 154 | // "checksum" and then a command byte followed by another bit-inverted 155 | // "checksum". That's about it: there are four bytes in all. 156 | // 157 | // The TVs manufactured by LG respond to the device address 0x04. The 158 | // IR command codes we are most interested in are 0xFB ("IN-START") 159 | // and 0xFF ("EZ_ADJUST"). Each one opens a different kind of service 160 | // menu on an LG TV. 161 | 162 | #define NEC_IR_ADDRESS_LG_TV 0x04 163 | 164 | // The actual remote key command codes we implement here are as 165 | // follows. (Of course, I didn't really _need_ any other than 166 | // the IN_START and the EZ_ADJUST codes, but the others were a 167 | // nice thing to have for initial testing.) 168 | 169 | #define IRKEY_CHANNEL_PLUS 0x00 170 | #define IRKEY_CHANNEL_MINUS 0x01 171 | #define IRKEY_VOLUME_PLUS 0x02 172 | #define IRKEY_VOLUME_MINUS 0x03 173 | #define IRKEY_MUTE 0x09 174 | #define IRKEY_Q_MENU 0x45 175 | #define IRKEY_IN_START 0xFB 176 | #define IRKEY_EZ_ADJUST 0xFF 177 | 178 | // The following array defines the order in which the command codes 179 | // cycle when browsing them by the "SELECT" button. If you do not 180 | // need this kind of selection mechanism, feel free to simplify it 181 | // as you see fit. 182 | 183 | uint8_t ir_commands[8] = { 184 | IRKEY_CHANNEL_PLUS, 185 | IRKEY_CHANNEL_MINUS, 186 | IRKEY_VOLUME_PLUS, 187 | IRKEY_VOLUME_MINUS, 188 | IRKEY_MUTE, 189 | IRKEY_Q_MENU, 190 | IRKEY_IN_START, 191 | IRKEY_EZ_ADJUST 192 | }; 193 | 194 | // Since the ATtiny2313 microcontroller only has 2K of flash and 195 | // 128 bytes of SRAM, using a ready-made IR library would 196 | // probably have been out of the question. I just decided to 197 | // implement the NEC protocol on my own, in the simplest possible 198 | // fashion. I found an excellent description of the protocol on 199 | // this page by San Bergmans: 200 | // 201 | // 202 | // 203 | // The carrier frequency for the NEC IR protocol is 38000 Hz. One 204 | // carrier pulse cycle takes 1/38000th of a second. According to 205 | // the page linked above, the recommended carrier duty-cycle for 206 | // this protocol is either 1/4 or 1/3. 207 | // 208 | // Let's figure out what that means in microseconds: 209 | // 210 | // 1/4 cycles takes 1/38000 * 1/4 seconds = 1/152000th of a second. 211 | // 212 | // 1/152000 seconds = 6 11/19 microseconds (=~ 6.58 microseconds) 213 | // 3/152000 seconds = 19 14/19 microseconds (=~ 19.74 microseconds) 214 | // 4/152000 seconds = 26 6/19 microseconds (=~ 26.32 microseconds) 215 | // 216 | // 1/3 cycles takes 1/38000 * 1/3 seconds = 1/114000th of a second. 217 | // 218 | // 1/114000 seconds = 8 44/57 microseconds (=~ 8.77 microseconds) 219 | // 2/114000 seconds = 17 31/57 microseconds (=~ 17.54 microseconds) 220 | // 3/114000 seconds = 26 6/19 microseconds (=~ 26.32 microseconds) 221 | // 222 | // Through some experimenting, I found out the 1/4 duty cycle works 223 | // noticeably better and appears to give a longer range than the 1/3 224 | // duty cycle - at least on my TV and with my LEDs. However, I present 225 | // both timings here in case you want to try them out with your IR 226 | // emitter and TV - maybe they behave differently. 227 | 228 | #define DUTY_CYCLE_1_3 229 | 230 | #ifdef DUTY_CYCLE_1_4 // 1:4 duty cycle 231 | #define NEC_IR_CARRIER_CYCLE_DURATION_HIGH 6.58f 232 | #define NEC_IR_CARRIER_CYCLE_DURATION_LOW 19.74f 233 | #define NEC_IR_CARRIER_CYCLE_DURATION_TOTAL 26.32f 234 | #endif 235 | 236 | #ifdef DUTY_CYCLE_1_3 // 1:3 duty cycle 237 | #define NEC_IR_CARRIER_CYCLE_DURATION_HIGH 8.77f 238 | #define NEC_IR_CARRIER_CYCLE_DURATION_LOW 17.55f // OK, I just rounded this one up to keep the timebase sane! 239 | #define NEC_IR_CARRIER_CYCLE_DURATION_TOTAL 26.32f 240 | #endif 241 | 242 | // The following is an enumeration and definition of the four different 243 | // types of mark/space codes (pulse types) found in the NEC IR protocol. 244 | // The first value is an index number, the two other values are the 245 | // "mark" and "space" duration in microseconds. 246 | // 247 | // We want to use these as literal constants so as not to mess up the 248 | // delay loops even on slower processors. Also, the delay.h routines 249 | // cannot be called with variables, only with constants, or they will 250 | // produce inaccurate delays. 251 | 252 | #define NEC_IR_LOGICAL_0 0 253 | #define NEC_IR_LOGICAL_0_MARK_DURATION 560 254 | #define NEC_IR_LOGICAL_0_SPACE_DURATION 560 255 | 256 | #define NEC_IR_LOGICAL_1 1 257 | #define NEC_IR_LOGICAL_1_MARK_DURATION 560 258 | #define NEC_IR_LOGICAL_1_SPACE_DURATION 1690 259 | 260 | #define NEC_IR_AGC_CALIBRATION 2 261 | #define NEC_IR_AGC_CALIBRATION_MARK_DURATION 9000 262 | #define NEC_IR_AGC_CALIBRATION_SPACE_DURATION 4500 263 | 264 | #define NEC_IR_END 3 265 | #define NEC_IR_END_MARK_DURATION 560 266 | #define NEC_IR_END_SPACE_DURATION 4708 267 | 268 | // The following function blinks a specific pulse type (as defined 269 | // above) at the 38 kHz carrier. Some nasty hardcoded values in there 270 | // but I hope this helps maintain accuracy with slower CPU speeds. I 271 | // could have used the fancier timer interrupt and pulse width modulator 272 | // features built-in to the microcontroller itself, of course, and 273 | // generate the carrier that way, but this was just a quick busy-loop 274 | // hack for getting into the service menu, anyway... so finer details 275 | // weren't that important. And maybe this kind of a simplistic, 276 | // hardware-independent approach will make it easier to port the same 277 | // code over to other platforms, if required. 278 | 279 | void transmit_nec_ir_pulse(uint8_t pulse_type_id) { 280 | 281 | // Calculate how many cycles of the 38 kHz carrier we need 282 | // for the duration of the "mark" time 283 | 284 | uint16_t num_cycles; 285 | uint16_t i; 286 | u64 start_tick, end_tick; 287 | 288 | if( pulse_type_id == NEC_IR_AGC_CALIBRATION ) 289 | num_cycles = 290 | (NEC_IR_AGC_CALIBRATION_MARK_DURATION 291 | / NEC_IR_CARRIER_CYCLE_DURATION_TOTAL); 292 | else 293 | // All other pulse types share an identical 560 us "mark" 294 | // duration 295 | num_cycles = 296 | (NEC_IR_LOGICAL_0_MARK_DURATION 297 | / NEC_IR_CARRIER_CYCLE_DURATION_TOTAL); 298 | 299 | // Blinking the 38 kHz carrier now! 300 | 301 | for( i = 0; i < num_cycles; i++) { 302 | start_tick = svc_getSystemTick(); 303 | end_tick = start_tick + ((268123480 / 1000000) * NEC_IR_CARRIER_CYCLE_DURATION_HIGH); 304 | 305 | while(svc_getSystemTick() < end_tick)set_ir_led_on(); 306 | 307 | //set_ir_led_on(); 308 | //_delay_us(NEC_IR_CARRIER_CYCLE_DURATION_HIGH); 309 | set_ir_led_off(); 310 | _delay_us(NEC_IR_CARRIER_CYCLE_DURATION_LOW); 311 | } 312 | 313 | // Wait for the duration of "space" for the given pulse. These 314 | // delays are hardcoded and split into a couple of separate calls 315 | // in the hopes they will remain accurate at least in the range 316 | // of 1...20 MHz CPU speed. See delay.h for details about the 317 | // allowed (accurate) delay ranges for different Atmel CPU speeds. 318 | 319 | switch( pulse_type_id ) { 320 | 321 | case NEC_IR_LOGICAL_0: 322 | // 560 us 323 | svc_sleepThread((u64)(560*1000)); 324 | /*_delay_ms(0.5); 325 | _delay_us(30); 326 | _delay_us(30);*/ 327 | break; 328 | case NEC_IR_LOGICAL_1: 329 | // 1690 us 330 | svc_sleepThread((u64)(1690*1000)); 331 | /*_delay_ms(1.6); 332 | _delay_us(30); 333 | _delay_us(30); 334 | _delay_us(30);*/ 335 | break; 336 | case NEC_IR_END: 337 | // 4708 us 338 | svc_sleepThread((u64)(4708*1000)); 339 | /*_delay_ms(4.7); 340 | _delay_us(8);*/ 341 | break; 342 | case NEC_IR_AGC_CALIBRATION: 343 | // 4500 us 344 | svc_sleepThread(4500LL*1000000LL); 345 | //_delay_ms(4.5); 346 | break; 347 | } 348 | 349 | } 350 | 351 | void transmit_nec_ir_command(uint8_t address, uint8_t command) { 352 | 353 | uint8_t i, j, value; 354 | uint8_t bytes[4] = {address, ~address, command, ~command}; 355 | 356 | transmit_nec_ir_pulse(NEC_IR_AGC_CALIBRATION); 357 | 358 | for( i = 0; i < 4; i++ ) { 359 | 360 | value = bytes[i]; 361 | 362 | for( j = 0; j < 8; j++ ) { 363 | 364 | if( value & (1<=FW18 503 | mov r3, #7 504 | bl locate_cmdhandler_code 505 | cmp r0, #0 506 | bne initializeptr_pxifsopenarchive_jumptablefound 507 | 508 | #ifdef ENABLE_OLDFS_AUTOLOCATE 509 | mov r0, #1 510 | str r0, [sp] 511 | 512 | ldr r0, =proc9_textstartaddr 513 | ldr r0, [r0] 514 | ldr r1, =0x080ff000 515 | sub r1, r1, r0 516 | 517 | adr r2, pxifs_cmdhandler_poolcmpdata_old0 518 | mov r3, #3 519 | bl locate_cmdhandler_code 520 | cmp r0, #0 521 | bne initializeptr_pxifsopenarchive_jumptablefound 522 | 523 | mov r0, #1 524 | str r0, [sp] 525 | 526 | ldr r0, =proc9_textstartaddr 527 | ldr r0, [r0] 528 | ldr r1, =0x080ff000 529 | sub r1, r1, r0 530 | 531 | adr r2, pxifs_cmdhandler_poolcmpdata_old1 532 | mov r3, #4 533 | bl locate_cmdhandler_code 534 | cmp r0, #0 535 | bne initializeptr_pxifsopenarchive_jumptablefound 536 | #endif 537 | 538 | b initializeptr_pxifsopenarchive_end 539 | 540 | initializeptr_pxifsopenarchive_jumptablefound: 541 | mov r1, #0x12 542 | lsl r1, r1, #2 543 | ldr r0, [r0, r1] @ r0 = jump-addr in the pxifs cmdhandler for cmd 0x12, OpenArchive. 544 | 545 | ldr r1, =0x080ff000 546 | 547 | initializeptr_pxifsopenarchive_lp: @ Locate the pxifs_openarchive blx instruction. 548 | ldr r2, [r0] 549 | lsr r2, r2, #24 550 | cmp r2, #0xfa 551 | bne initializeptr_pxifsopenarchive_lpnext 552 | b initializeptr_pxifsopenarchive_lpend 553 | 554 | initializeptr_pxifsopenarchive_lpnext: 555 | add r0, r0, #4 556 | cmp r0, r1 557 | blt initializeptr_pxifsopenarchive_lp 558 | 559 | mov r4, #1 560 | mvn r4, r4 561 | b initializeptr_pxifsopenarchive_end 562 | 563 | initializeptr_pxifsopenarchive_lpend: 564 | mov r1, #0 565 | blx parse_branch 566 | 567 | ldr r1, =pxifsopenarchive_adr 568 | mov r2, #1 569 | orr r0, r0, r2 570 | str r0, [r1] 571 | 572 | mov r4, #0 573 | 574 | initializeptr_pxifsopenarchive_end: 575 | mov r0, r4 576 | 577 | add sp, sp, #4 578 | pop {r4, pc} 579 | .pool 580 | 581 | initializeptr_getarchiveclass_something: 582 | push {r4, r5, lr} 583 | 584 | mov r4, #0 585 | mvn r4, r4 586 | 587 | ldr r0, =proc9_textstartaddr 588 | ldr r0, [r0] 589 | ldr r1, =0x080ff000 590 | ldr r2, =0x567890ae 591 | ldr r5, =0x0074002f 592 | 593 | initializeptr_getarchiveclass_something_lp0: 594 | ldr r3, [r0] 595 | cmp r3, r2 596 | bne initializeptr_getarchiveclass_something_lp0next 597 | ldr r3, [r0, #4] 598 | cmp r3, r5 599 | bne initializeptr_getarchiveclass_something_lp0next 600 | b initializeptr_getarchiveclass_something_lp1_begin 601 | 602 | initializeptr_getarchiveclass_something_lp0next: 603 | add r0, r0, #4 604 | cmp r0, r1 605 | blt initializeptr_getarchiveclass_something_lp0 606 | b initializeptr_getarchiveclass_something_end 607 | 608 | initializeptr_getarchiveclass_something_lp1_begin: 609 | ldr r2, =0x0280 610 | 611 | initializeptr_getarchiveclass_something_lp1: 612 | ldrh r3, [r0] 613 | cmp r3, r2 614 | beq initializeptr_getarchiveclass_something_lp1end 615 | 616 | initializeptr_getarchiveclass_something_lp1next: 617 | sub r0, r0, #2 618 | b initializeptr_getarchiveclass_something_lp1 619 | 620 | initializeptr_getarchiveclass_something_lp1end: 621 | sub r0, r0, #6 622 | mov r1, #0 623 | bl parse_branch_thumb 624 | 625 | mov r2, #1 626 | orr r0, r0, r2 627 | ldr r1, =getarchiveclass_something_adr 628 | str r0, [r1] 629 | 630 | mov r4, #0 631 | 632 | initializeptr_getarchiveclass_something_end: 633 | mov r0, r4 634 | pop {r4, r5, pc} 635 | .pool 636 | 637 | initializeptr_pxifs_state: 638 | push {r4, r5, lr} 639 | mov r4, #0 640 | mvn r4, r4 641 | 642 | bl proc9_locate_main_endaddr 643 | cmp r0, #0 644 | beq initializeptr_pxifs_state_end 645 | 646 | ldr r1, [r0] 647 | lsr r1, r1, #12 648 | ldr r2, =0xe8bd8 649 | cmp r1, r2 650 | bne initializeptr_pxifs_state_lp0_init_getfuncaddr 651 | ldr r0, [r0, #0x10] 652 | b initializeptr_pxifs_state_lp0_init @ >=v10.0 FIRM 653 | 654 | initializeptr_pxifs_state_lp0_init_getfuncaddr: 655 | sub r0, r0, #0x18 656 | mov r1, #0 657 | bl parse_branch 658 | 659 | initializeptr_pxifs_state_lp0_init: 660 | ldr r1, =0xe2800008 661 | ldr r4, =0x000ff000 662 | 663 | initializeptr_pxifs_state_lp0: @ Locate "add , , #8" 664 | ldr r3, [r0] 665 | mov r2, r3 666 | bic r2, r2, r4 667 | cmp r2, r1 668 | beq initializeptr_pxifs_state_lp0end 669 | 670 | initializeptr_pxifs_state_lp0next: 671 | add r0, r0, #4 672 | b initializeptr_pxifs_state_lp0 673 | 674 | initializeptr_pxifs_state_lp0end: 675 | mov r2, #16 676 | lsr r3, r3, r2 677 | mov r2, #0xf 678 | and r3, r3, r2 679 | 680 | ldr r1, =0xe59f0000 681 | lsl r3, r3, #12 682 | orr r1, r1, r3 683 | ldr r4, =0xfff 684 | 685 | initializeptr_pxifs_state_lp1: @ Locate the ldr instruction for pxifs state. 686 | ldr r3, [r0] 687 | mov r2, r3 688 | bic r2, r2, r4 689 | cmp r2, r1 690 | beq initializeptr_pxifs_state_lp1end 691 | 692 | initializeptr_pxifs_state_lp1next: 693 | sub r0, r0, #4 694 | b initializeptr_pxifs_state_lp1 695 | 696 | initializeptr_pxifs_state_lp1end: 697 | mov r2, #0xff 698 | and r3, r3, r2 699 | add r0, r0, #8 700 | add r0, r0, r3 701 | ldr r0, [r0] 702 | 703 | add r0, r0, #8 704 | ldr r1, =pxifs_state 705 | str r0, [r1] 706 | 707 | mov r4, #0 708 | 709 | initializeptr_pxifs_state_end: 710 | mov r0, r4 711 | pop {r4, r5, pc} 712 | .pool 713 | 714 | initializeptr_fsvtables: 715 | push {r4, r5, r6, r7, lr} 716 | mov r4, #0 717 | mvn r4, r4 718 | 719 | ldr r0, =proc9_textstartaddr 720 | ldr r0, [r0] 721 | ldr r1, =0x080ff000 722 | ldr r2, =0x4453434e 723 | 724 | initializeptr_fsvtables_lp0: @ Locate "NCSD" word in the target function's .pool. 725 | ldr r3, [r0] 726 | cmp r3, r2 727 | bne initializeptr_fsvtables_lp0next 728 | b initializeptr_fsvtables_lp0end 729 | 730 | initializeptr_fsvtables_lp0next: 731 | add r0, r0, #4 732 | cmp r0, r1 733 | blt initializeptr_fsvtables_lp0 734 | b initializeptr_fsvtables_end 735 | 736 | initializeptr_fsvtables_lp0end: 737 | sub r0, r0, #4 738 | ldr r5, [r0] 739 | ldr r2, =fs_vtableptr_fileread 740 | str r5, [r2] 741 | add r0, r0, #4 742 | 743 | ldr r7, =0xbdf0 @ "pop {r4, r5, r6, r7, pc}" 744 | 745 | initializeptr_fsvtables_lp1: @ Locate the fileread vtable ptr in a function's .pool, where the above instructions are immediately before it. 746 | ldr r6, =0xb005 @ "add sp, #20" 747 | 748 | ldr r3, [r0] 749 | cmp r3, r5 750 | bne initializeptr_fsvtables_lp1next 751 | 752 | sub r2, r0, #4 753 | ldrh r3, [r2, #0] 754 | cmp r3, r6 755 | #ifndef ENABLE_OLDFS_AUTOLOCATE 756 | bne initializeptr_fsvtables_lp1next 757 | #else 758 | beq initializeptr_fsvtables_lp1_l0 759 | 760 | add r6, r6, #4 761 | cmp r3, r6 762 | bne initializeptr_fsvtables_lp1next 763 | #endif 764 | 765 | initializeptr_fsvtables_lp1_l0: 766 | ldrh r3, [r2, #2] 767 | cmp r3, r7 768 | bne initializeptr_fsvtables_lp1next 769 | b initializeptr_fsvtables_lp1end 770 | 771 | initializeptr_fsvtables_lp1next: 772 | add r0, r0, #4 773 | cmp r0, r1 774 | blt initializeptr_fsvtables_lp1 775 | 776 | ldr r0, =fs_vtableptr_fileread @ When locating vtableptr_filewrite fails with the above, like with FIRM >=v10.0, just assume that it's at fs_vtableptr_fileread-0x38. 777 | ldr r0, [r0] 778 | sub r0, r0, #0x38 779 | b initializeptr_fsvtables_lp1end_stateinit 780 | 781 | initializeptr_fsvtables_lp1end: 782 | add r0, r0, #4 783 | ldr r0, [r0] 784 | 785 | initializeptr_fsvtables_lp1end_stateinit: 786 | ldr r1, =fs_vtableptr_filewrite 787 | str r0, [r1] 788 | 789 | mov r4, #0 790 | 791 | initializeptr_fsvtables_end: 792 | mov r0, r4 793 | pop {r4, r5, r6, r7, pc} 794 | .pool 795 | 796 | pxifs_cmdhandler_poolcmpdata: 797 | .word 0xd9001830, 0x000101c2, 0xe0e046be, 0x000100c1, 0x00020142, 0x00020041, 0x00030244 798 | 799 | pxifs_cmdhandler_poolcmpdata_old0: 800 | .word 0xd9001830, 0x000101c2, 0xc8a044dc 801 | 802 | pxifs_cmdhandler_poolcmpdata_old1: 803 | .word 0xd9001830, 0x000101c2, 0xe0e046be, 0xc8a044dc 804 | 805 | pxifsopenarchive_adr: 806 | .word 0 807 | 808 | getarchiveclass_something_adr: 809 | .word 0 810 | 811 | fs_vtableptr_fileread: 812 | .word 0 813 | 814 | fs_vtableptr_filewrite: 815 | .word 0 816 | 817 | -------------------------------------------------------------------------------- /3dshaxarm9/firmpatches.s: -------------------------------------------------------------------------------- 1 | .arch armv5te 2 | .fpu softvfp 3 | .text 4 | .arm 5 | 6 | .global patch_firm 7 | .global patchfirm_arm9section 8 | .global patchfirm_arm11section_kernel 9 | .global firm_arm11kernel_getminorversion_firmimage 10 | .global firm_gethwtype 11 | .global patchfirm_setup_tmpaddr_bincopy 12 | .type patch_firm STT_FUNC 13 | .type patchfirm_arm9section STT_FUNC 14 | .type patchfirm_arm11section_kernel STT_FUNC 15 | .type firm_arm11kernel_getminorversion_firmimage STT_FUNC 16 | .type firm_gethwtype STT_FUNC 17 | .type patchfirm_setup_tmpaddr_bincopy STT_FUNC 18 | 19 | #ifdef LOADA9_NEW3DSMEM 20 | #define NEW3DSMEM_TMPADDR_END 0x1ff80000 21 | #endif 22 | 23 | patch_firm: @ r0 = addr of entire FIRM 24 | push {r4, r5, r6, lr} 25 | mov r4, r0 26 | 27 | mov r5, #0 28 | patchfirm_sectionlp: 29 | mov r3, #0x30 30 | mul r1, r5, r3 31 | add r1, r1, #0x40 32 | add r1, r1, r4 33 | 34 | ldr r3, [r1, #0x8] 35 | cmp r3, #0 36 | beq patchfirm_sectionlp_end @ branch when sectionsize == 0 37 | 38 | ldr r3, [r1, #0x0] 39 | add r0, r4, r3 40 | mov r2, r4 41 | 42 | ldr r3, [r1, #0xc] 43 | cmp r3, #0 44 | bne patchfirm_sectionlp_checkarm11 @ branch when the section type is not arm9. 45 | 46 | ldr r1, [r1, #0x8] 47 | mov r2, r4 48 | mov r3, #1 49 | bl patchfirm_arm9section 50 | b patchfirm_sectionlp_end 51 | 52 | patchfirm_sectionlp_checkarm11: 53 | ldr r1, [r1, #0x8] 54 | cmp r5, #0 55 | bleq patchfirm_arm11section_modules 56 | cmp r5, #1 57 | bleq patchfirm_arm11section_kernel 58 | 59 | patchfirm_sectionlp_end: 60 | add r5, r5, #1 61 | cmp r5, #4 62 | blt patchfirm_sectionlp 63 | pop {r4, r5, r6, pc} 64 | 65 | patchfirm_arm9section: @ r0 = address of FIRM section in memory, in the FIRM binary. r1 = FIRM section size. r2 = FIRM header address(only used on New3DS when inr3 flag=1), r3 = flag. 66 | push {r4, r5, r6, r7, lr} 67 | sub sp, sp, #4 68 | 69 | mov r7, r0 70 | mov r4, r1 71 | 72 | cmp r3, #0 73 | beq patchfirm_arm9section_begin 74 | 75 | ldr r3, =RUNNINGFWVER 76 | ldr r3, [r3] 77 | lsr r3, r3, #30 78 | and r3, r3, #1 79 | cmp r3, #0 80 | beq patchfirm_arm9section_begin @ Branch when not running on new3ds. 81 | 82 | add r1, r1, r0 83 | ldr r3, [r2, #12] 84 | ldr r2, =0x08006000 85 | sub r3, r3, r2 86 | add r3, r3, r0 87 | ldr r4, =new3ds_hookloader_entrypoint 88 | blx r4 89 | 90 | b patchfirm_arm9section_finish 91 | 92 | patchfirm_arm9section_begin: 93 | #ifdef LOADA9_NEW3DSMEM 94 | mov r0, r7 95 | mov r1, r4 96 | bl patchfirm_arm9kernel_mpuconfig 97 | #endif 98 | 99 | ldr r1, =0x636f7250 @ "Process9" 100 | ldr r2, =0x39737365 101 | 102 | patchfirm_arm9section_locateprocess9: @ Locate the "Process9" exheader. 103 | ldr r3, [r7, #0] 104 | cmp r3, r1 105 | ldreq r3, [r7, #4] 106 | cmpeq r3, r2 107 | beq patchfirm_arm9section_locateprocess9_finish 108 | sub r4, r4, #8 109 | add r7, r7, #8 110 | cmp r4, #0 111 | bgt patchfirm_arm9section_locateprocess9 112 | b patchfirm_arm9section_finish 113 | 114 | patchfirm_arm9section_locateprocess9_finish: 115 | mov r0, r7 116 | ldr r4, [r0, #0x10] @ r4 = Process9 .text addr 117 | ldr r7, [r0, #0x18] @ r7 = Process9 .text size 118 | add r0, r0, #0xa00 @ r0/r5 = addr of Process9 .code 119 | mov r5, r0 120 | 121 | #ifdef LOADA9_NEW3DSMEM 122 | mov r0, r4 123 | mov r1, r5 124 | bl patchfirm_setup_proc9entryhook 125 | #endif 126 | 127 | #ifdef ENABLE_FIRMPARTINSTALL_STRS_PATCH 128 | mov r0, r4 129 | mov r1, r5 130 | mov r2, r7 131 | bl proc9_autolocate_patch_firminstallstrs 132 | b patchfirm_arm9section_finish 133 | #endif 134 | 135 | /*ldr r3, =0x08078a90 136 | sub r3, r3, r4 137 | add r3, r3, r0 138 | ldr r1, =arm9_nandredir_stub4 139 | ldr r2, [r1, #0] 140 | str r2, [r3, #0] 141 | ldr r2, [r1, #4] 142 | str r2, [r3, #4]*/ 143 | 144 | mov r0, r4 145 | mov r1, r5 146 | bl proc9_autolocate_hookpatchaddr 147 | 148 | ldr r1, =proc9_waitfirmevent_hook 149 | ldr r2, =0xe51ff004 150 | ldr r3, =proc9_waitfirmevent_hook_patchaddr 151 | str r0, [r3] 152 | sub r0, r0, r4 153 | add r0, r0, r5 154 | str r2, [r0] @ "ldr pc, [pc, #-4]" 155 | str r1, [r0, #4] 156 | 157 | patchfirm_arm9section_L0: 158 | /*#if FIRMLAUNCH_FWVER == 0x1F 159 | ldr r0, =0x08029004 160 | #elif FIRMLAUNCH_FWVER == 0x2E 161 | ldr r0, =0x080292b8 162 | #endif 163 | sub r0, r0, r4 164 | add r0, r0, r5 165 | ldr r1, =proc9_fsdeviceinit_hookstub 166 | ldr r2, [r1, #0] 167 | str r2, [r0, #0] 168 | ldr r2, [r1, #4] 169 | str r2, [r0, #4]*/ 170 | 171 | mov r0, r4 172 | mov r1, r5 173 | mov r2, r7 174 | bl proc9_autolocate_certsigcheck_patchaddr 175 | cmp r0, #0 176 | beq patchfirm_arm9section_L1 177 | 178 | ldr r1, =0x2000 @ Patch the RSA verification function used for certs(tmd/tik/cert-chain/...), so that it returns 0 instead of -2011 for invalid signature. 179 | sub r0, r0, r4 180 | add r0, r0, r5 181 | strh r1, [r0] @ "mov r0, #0" 182 | 183 | patchfirm_arm9section_L1: 184 | mov r0, r4 @ Patch rsa_verifysignature, so that the very beginning of it is just "return 0". This is used for all RSA sig verification except for the above cert stuff. 185 | mov r1, r5 186 | mov r2, r7 187 | bl proc9_autolocate_mainsigcheck_patchaddr 188 | 189 | cmp r0, #0 190 | beq patchfirm_arm9section_L2 191 | 192 | ldr r1, =0x2000 193 | ldr r2, =0x4770 194 | sub r0, r0, r4 195 | add r0, r0, r5 196 | strh r1, [r0] @ "mov r0, #0" 197 | strh r2, [r0, #2] @ "bx lr" 198 | 199 | patchfirm_arm9section_L2: 200 | /*#if FIRMLAUNCH_FWVER == 0x1F 201 | ldr r0, =0x08081e10 202 | ldr r1, =arm9_rsaengine_txtwrite_stub 203 | sub r0, r0, r4 204 | add r0, r0, r5 205 | 206 | ldrh r2, [r1, #0] 207 | strh r2, [r0, #0] 208 | ldrh r2, [r1, #2] 209 | strh r2, [r0, #2] 210 | ldrh r2, [r1, #4] 211 | strh r2, [r0, #4] 212 | ldrh r2, [r1, #6] 213 | strh r2, [r0, #6] 214 | #endif*/ 215 | 216 | /*ldr r0, =0x08085ee0 217 | sub r0, r0, r4 218 | add r0, r0, r5 219 | bl arm9general_debughook_writepatch*/ 220 | 221 | #ifdef ENABLENANDREDIR 222 | ldr r0, =FIRMLAUNCH_RUNNINGTYPE 223 | ldr r0, [r0] 224 | cmp r0, #3 225 | beq patchfirm_arm9section_L3 226 | 227 | #ifdef ENABLENANDREDIR 228 | #ifdef ENABLE_LOADA9_x01FFB800 229 | #ifndef LOADA9_x01FFB800_INCFILEPATH 230 | adr r0, filepath_x01ffb800 231 | ldr r1, =0x01ffb800 232 | ldr r2, =0x4800 233 | bl loadfile_charpath 234 | #else 235 | ldr r0, =0x01ffb800 236 | ldr r1, =LOADA9_x01FFB800_DATA 237 | mov r2, #0x100 238 | bl memcpy 239 | #endif 240 | #endif 241 | #endif 242 | 243 | mov r0, r5 244 | mov r1, r7 245 | mov r2, r4 246 | bl patch_nandredir_autolocate 247 | #if NANDREDIR_SECTORNUM_PADCHECK0 || NANDREDIR_SECTORNUM_PADCHECK1 248 | cmp r0, #0 249 | bne patchfirm_arm9section_L3 250 | 251 | #ifdef NANDREDIR_SECTORNUM_PADCHECK0 252 | #ifndef NANDREDIR_SECTORNUM_PADCHECK0VAL 253 | #error NANDREDIR_SECTORNUM_PADCHECK0VAL must be defined when NANDREDIR_SECTORNUM_PADCHECK0 is used. 254 | #endif 255 | #endif 256 | 257 | #ifdef NANDREDIR_SECTORNUM_PADCHECK1 258 | #ifndef NANDREDIR_SECTORNUM_PADCHECK1VAL 259 | #error NANDREDIR_SECTORNUM_PADCHECK1VAL must be defined when NANDREDIR_SECTORNUM_PADCHECK1 is used. 260 | #endif 261 | #endif 262 | 263 | ldr r0, =0x10146000 264 | ldrh r0, [r0] 265 | 266 | #ifdef NANDREDIR_SECTORNUM_PADCHECK0 267 | ldr r1, =NANDREDIR_SECTORNUM_PADCHECK0 268 | ldr r2, =NANDREDIR_SECTORNUM_PADCHECK0VAL 269 | mov r3, r0 270 | ands r3, r1 271 | bne patchfirm_arm9section_nandredir_padcheck1 272 | 273 | ldr r3, =NANDREDIR_SECTORNUM 274 | str r2, [r3] 275 | b patchfirm_arm9section_L3 276 | #endif 277 | 278 | patchfirm_arm9section_nandredir_padcheck1: 279 | #ifdef NANDREDIR_SECTORNUM_PADCHECK1 280 | ldr r1, =NANDREDIR_SECTORNUM_PADCHECK1 281 | ldr r2, =NANDREDIR_SECTORNUM_PADCHECK1VAL 282 | mov r3, r0 283 | ands r3, r1 284 | bne patchfirm_arm9section_L3 285 | 286 | ldr r3, =NANDREDIR_SECTORNUM 287 | str r2, [r3] 288 | #endif 289 | 290 | #endif 291 | #endif 292 | 293 | patchfirm_arm9section_L3: 294 | 295 | patchfirm_arm9section_finish: 296 | add sp, sp, #4 297 | pop {r4, r5, r6, r7, pc} 298 | .pool 299 | 300 | #ifdef LOADA9_NEW3DSMEM 301 | patchfirm_arm9kernel_mpuconfig: @ r0 = address of FIRM section in memory, in the FIRM binary. r1 = FIRM section size. 302 | push {r4, r5, r6, r7, lr} 303 | 304 | @ This patches the mpu region config setup by the arm9kernel in crt0. 305 | 306 | patchfirm_arm9kernel_mpuconfig_lpstart: 307 | ldr r2, [r0, #0x0] 308 | ldr r3, =0x10000000 309 | cmp r2, r3 310 | bne patchfirm_arm9kernel_mpuconfig_lpnext 311 | 312 | ldr r2, [r0, #0x4] 313 | mov r3, #0x1 314 | cmp r2, r3 315 | bne patchfirm_arm9kernel_mpuconfig_lpnext 316 | 317 | ldr r2, [r0, #0x8] 318 | ldr r3, =0x00240003 319 | cmp r2, r3 320 | bne patchfirm_arm9kernel_mpuconfig_lpnext 321 | 322 | ldr r2, [r0, #0xc] 323 | ldr r3, =0x10100000 324 | cmp r2, r3 325 | bne patchfirm_arm9kernel_mpuconfig_lpnext 326 | 327 | @ Disable the region for 0x10100000 in the kernel mpu-config. 328 | mov r2, #0 329 | strb r2, [r0, #0x4] 330 | 331 | @ Set the size of the mpuregion at 0x10000000 to 256MB, so that it covers 0x10000000 - 0x20000000. 332 | sub r0, r0, #0x8 333 | mov r2, #0x37 334 | strb r2, [r0, #6] 335 | 336 | @ Set the instruction permissions for the mpuregion at 0x10000000, to priv/usr = RO(executable). 337 | mov r2, #0x6 338 | strb r2, [r0, #5] 339 | b patchfirm_arm9kernel_mpuconfig_end 340 | 341 | patchfirm_arm9kernel_mpuconfig_lpnext: 342 | add r0, r0, #4 343 | sub r1, r1, #4 344 | cmp r1, #0 345 | bgt patchfirm_arm9kernel_mpuconfig_lpstart 346 | 347 | patchfirm_arm9kernel_mpuconfig_end: 348 | pop {r4, r5, r6, r7, pc} 349 | .pool 350 | 351 | patchfirm_setup_proc9entryhook: @ r0 = Process9 .text addr. r1 = addr of Process9 .code. 352 | push {r4, r5, r6, r7, lr} 353 | 354 | mov r4, r0 355 | mov r5, r1 356 | 357 | add r0, r5, #0x20 358 | 359 | @ Write the jump-stub into proc9 .text, with the jump-addr relocated into the binary based at NEW3DSMEM_TMPADDR_END - . 360 | ldr r1, =0xe51ff004 @ "ldr pc, [pc, #-4]" 361 | ldr r2, =firmpatches_proc9entryhook_codestub 362 | ldr r3, =__text_start 363 | sub r2, r2, r3 364 | ldr r6, =_end 365 | ldr r3, =__text_start 366 | sub r6, r6, r3 367 | ldr r3, =NEW3DSMEM_TMPADDR_END 368 | sub r3, r3, r6 369 | add r2, r2, r3 370 | str r1, [r0, #0x0] 371 | str r2, [r0, #0x4] 372 | 373 | add r0, r4, #0x28 374 | ldr r2, =firmpatches_proc9entryhook_codestub_retaddr 375 | str r0, [r2] 376 | 377 | pop {r4, r5, r6, r7, pc} 378 | .pool 379 | 380 | patchfirm_setup_tmpaddr_bincopy: 381 | @ Copy the running binary to NEW3DSMEM_TMPADDR_END - . Nothing should be changed anywhere in the binary after this, until firmpatches_proc9entryhook_codestub is executed. 382 | ldr r1, =_end 383 | ldr r0, =__text_start 384 | sub r1, r1, r0 385 | ldr r0, =NEW3DSMEM_TMPADDR_END 386 | sub r0, r0, r1 387 | 388 | ldr r1, =__text_start 389 | ldr r2, =_end 390 | sub r2, r2, r1 391 | b memcpy 392 | .pool 393 | #endif 394 | 395 | patchfirm_arm11section_modules: @ r0 = address of FIRM section in memory, in the FIRM binary. r1 = FIRM section size. r2 = FIRM header address. 396 | push {r4, r5, r6, r7, r8, lr} 397 | sub sp, sp, #20 398 | /*#ifdef FIRMLAUNCH_ENABLEFIRM_MODULELOAD 399 | #if FIRMLAUNCH_FWVER == 0x1F//This code itself is not nativefirm-version dependent, however this module will not get loaded without the below kernel patches. 400 | 401 | add r5, r0, r1 402 | mov r6, r2 403 | 404 | ldr r0, sdarchive_obj 405 | mov r3, #1 406 | str r3, [sp, #0] 407 | add r1, sp, #8 408 | str r1, [sp, #4] 409 | mov r1, #4 410 | ldr r2, =yls8proc_cxi_filepath 411 | mov r3, #0x1c 412 | bl openfile 413 | 414 | ldr r0, [sp, #8] 415 | cmp r0, #0 416 | beq patchfirm_arm11section_modules_end 417 | bl getfilesize 418 | adr r1, patchfirm_arm11section_additionalmodulesize 419 | str r0, [r1] 420 | mov r4, r0 421 | 422 | mov r7, #3 @ Move each FIRM section(excluding section0 containing the arm11 modules) forward(offset change + data-copy) by the size of the SD .cxi module. 423 | patchfirm_arm11section_modules_firmhdrlp: 424 | mov r3, #0x30 425 | mul r1, r7, r3 426 | add r1, r1, #0x40 427 | add r8, r1, r6 428 | 429 | ldr r2, [r8, #8] @ section size 430 | cmp r2, #0 431 | beq patchfirm_arm11section_modules_firmhdrlp_end 432 | 433 | ldr r0, [r8, #0] @ section offset 434 | mov r1, r0 435 | add r0, r0, r4 436 | str r0, [r8, #0] 437 | add r1, r1, r6 438 | ldr r0, =0x25000000 439 | bl memcpy 440 | 441 | ldr r1, =0x25000000 442 | ldr r0, [r8, #0] 443 | add r0, r0, r6 444 | ldr r2, [r8, #8] 445 | bl memcpy 446 | 447 | patchfirm_arm11section_modules_firmhdrlp_end: 448 | sub r7, r7, #1 449 | cmp r7, #0 450 | bgt patchfirm_arm11section_modules_firmhdrlp 451 | 452 | ldr r0, [r6, #0x48] @ section0 size 453 | add r0, r0, r4 454 | str r0, [r6, #0x48] 455 | 456 | mov r2, r4 457 | ldr r0, [sp, #8] 458 | mov r1, r5 459 | mov r3, #0 460 | bl fileread 461 | 462 | patchfirm_arm11section_modules_end: 463 | #endif 464 | #endif*/ 465 | add sp, sp, #20 466 | pop {r4, r5, r6, r7, r8, pc} 467 | .pool 468 | 469 | patchfirm_arm11section_kernel: @ r0 = address of FIRM section in memory, in the FIRM binary. r1 = FIRM section size. r2 = FIRM header address. 470 | push {r4, r5, r6, lr} 471 | /*#ifdef FIRMLAUNCH_ENABLEFIRM_MODULELOAD 472 | #if FIRMLAUNCH_FWVER == 0x1F 473 | 474 | ldr r3, patchfirm_arm11section_additionalmodulesize 475 | cmp r3, #0 476 | beq patchfirm_arm11section_kernel_end 477 | 478 | ldr r1, =0x8a08 @ Increase the FIRM module count returned by svcGetSystemInfo. 479 | ldr r2, [r0, r1] 480 | add r2, r2, #1 481 | str r2, [r0, r1] 482 | 483 | ldr r1, =0xdb8 @ Increase the module-count value in the cmp instruction in the start_firmprocesses() loop. 484 | ldr r2, [r0, r1] 485 | add r2, r2, #1 486 | str r2, [r0, r1] 487 | 488 | ldr r1, =0xde4 @ Increase the ncch module-data end-address field in the start_firmprocesses() .pool. 489 | ldr r2, [r0, r1] 490 | add r2, r2, r3 491 | str r2, [r0, r1] 492 | 493 | ldr r1, =0xdfc @ Increase the totalncchmodulesize field in the start_firmprocesses() .pool, used for clearing the ncch data once finished. 494 | ldr r2, [r0, r1] 495 | add r2, r2, r3 496 | str r2, [r0, r1] 497 | 498 | #endif 499 | #endif*/ 500 | 501 | #ifndef ENABLE_BOOTSAFEFIRM_STARTUP 502 | ldr r3, =FIRMLAUNCH_RUNNINGTYPE 503 | ldr r3, [r3] 504 | cmp r3, #3 505 | bne patchfirm_arm11section_kernel_end 506 | #else 507 | ldr r3, =RUNNINGFWVER @ Skip the below code if SAFE_MODE_FIRM is already running. 508 | ldr r3, [r3] 509 | lsr r3, r3, #8 510 | ldr r4, =0xffff 511 | and r3, r3, r4 512 | cmp r3, #0x3 513 | beq patchfirm_arm11section_kernel_end 514 | 515 | ldr r3, =FIRMLAUNCH_FWVER @ Skip the below code if SAFE_MODE_FIRM is being launched. 516 | ldr r3, [r3] 517 | lsr r3, r3, #8 518 | ldr r4, =0xffff 519 | and r3, r3, r4 520 | cmp r3, #0x3 521 | beq patchfirm_arm11section_kernel_end 522 | #endif 523 | 524 | bl firm_arm11kernel_locate_configmeminit 525 | cmp r0, #0 526 | beq patchfirm_arm11section_kernel_end 527 | 528 | sub r0, r0, #0x18 @ Patch the "mov , #0" instruction before the above code, to "mov , #1", so that the UPDATEFLAG always is set. Hence, this then triggers firmlaunch by NS later. 529 | ldr r1, [r0] 530 | orr r1, r1, #1 531 | str r1, [r0] 532 | 533 | patchfirm_arm11section_kernel_end: 534 | pop {r4, r5, r6, pc} 535 | .pool 536 | 537 | firm_arm11kernel_locate_configmeminit: @ r0 = address of FIRM section in memory, in the FIRM binary. r1 = FIRM section size. 538 | push {r4, lr} 539 | 540 | ldr r4, =0x000ff000 541 | 542 | firm_arm11kernel_locate_configmeminit_lp: @ Locate the padcheck code in the kernel configmem init func. 543 | ldr r3, [r0] 544 | bic r3, r3, r4 545 | ldr r2, =0xe2400b03 @ sub , , #0xc00 546 | cmp r3, r2 547 | bne firm_arm11kernel_locate_configmeminit_lpnext 548 | ldr r3, [r0, #4] 549 | bic r3, r3, r4 550 | ldr r2, =0xe25000be @ subs , , #0xbe 551 | cmp r3, r2 552 | bne firm_arm11kernel_locate_configmeminit_lpnext 553 | 554 | b firm_arm11kernel_locate_configmeminit_end 555 | 556 | firm_arm11kernel_locate_configmeminit_lpnext: 557 | add r0, r0, #4 558 | subs r1, r1, #4 559 | bgt firm_arm11kernel_locate_configmeminit_lp 560 | 561 | mov r0, #0 562 | 563 | firm_arm11kernel_locate_configmeminit_end: 564 | pop {r4, pc} 565 | .pool 566 | 567 | firm_arm11kernel_getminorversion: @ r0 = address of FIRM section in memory, in the FIRM binary. r1 = FIRM section size. 568 | push {r4, r5, lr} 569 | 570 | mvn r4, #0 571 | 572 | bl firm_arm11kernel_locate_configmeminit 573 | cmp r0, #0 574 | beq firm_arm11kernel_getminorversion_end 575 | 576 | ldr r5, =0xf000 577 | ldr r3, =0xe5c00002 578 | 579 | firm_arm11kernel_getminorversion_lp0: @ Locate the "strb , [r0, #2]" instruction. 580 | ldr r2, [r0] 581 | bic r1, r2, r5 582 | cmp r1, r3 583 | addne r0, r0, #4 584 | bne firm_arm11kernel_getminorversion_lp0 585 | 586 | sub r0, r0, #4 587 | and r2, r2, r5 588 | 589 | ldr r5, =0xe3a00000 590 | orr r5, r5, r2 591 | 592 | firm_arm11kernel_getminorversion_lp1: @ Locate the "mov , #" instruction, where matches the one located above, and is the minorversion. 593 | ldr r1, [r0] 594 | lsr r3, r1, #12 595 | lsl r3, r3, #12 596 | cmp r3, r5 597 | subne r0, r0, #4 598 | bne firm_arm11kernel_getminorversion_lp1 599 | 600 | and r4, r1, #0xff 601 | 602 | firm_arm11kernel_getminorversion_end: 603 | mov r0, r4 604 | pop {r4, r5, pc} 605 | .pool 606 | 607 | firm_arm11kernel_getminorversion_firmimage: @ r0 = addr of entire FIRM 608 | push {r4, lr} 609 | mov r1, #0 610 | mov r3, #0x40 611 | add r3, r3, r0 @ start of section headers 612 | 613 | ldr r4, =0x1FF80000 614 | 615 | firm_arm11kernel_getminorversion_firmimage_lp: @ Locate the section with address=0x1FF80000. 616 | ldr r2, [r3, #4] 617 | cmp r2, r4 618 | beq firm_arm11kernel_getminorversion_firmimage_lp_end 619 | add r3, r3, #0x30 620 | add r1, r1, #1 621 | cmp r1, #4 622 | blt firm_arm11kernel_getminorversion_firmimage_lp 623 | 624 | mvneq r0, #0 625 | popeq {r4, pc} 626 | 627 | firm_arm11kernel_getminorversion_firmimage_lp_end: 628 | ldr r2, [r3, #8] @ section size 629 | cmp r2, #0 630 | mvneq r0, #0 631 | popeq {r4, pc} 632 | 633 | ldr r2, [r3, #0xc] @ core 634 | cmp r2, #0 635 | mvneq r0, #0 636 | popeq {r4, pc} @ type must be arm11. 637 | 638 | ldr r1, [r3, #0] 639 | ldr r2, [r3, #8] 640 | add r0, r0, r1 @ section addr in firm image 641 | mov r1, r2 @ size 642 | pop {r4, lr} 643 | b firm_arm11kernel_getminorversion 644 | .pool 645 | 646 | #ifndef DISABLE_MATCHINGFIRM_HWCHECK 647 | firm_gethwtype: @ r0 = addr of entire FIRM. Returns 0 for Old3DS FIRM, 1 for New3DS. Returns ~0 for error. 648 | mov r1, #0 649 | add r2, r0, #0x40 650 | 651 | firm_gethwtype_hdrlp: 652 | ldr r3, [r2, #0xc] 653 | cmp r3, #0 654 | bne firm_gethwtype_hdrlpnext @ Look for the arm9 section. 655 | 656 | ldr r3, [r2, #0] 657 | add r0, r0, r3 @ r0 = addr of arm9 section start 658 | 659 | ldr r0, [r0, #0x40] @ Compare the new3ds control block data, on old3ds actual code is located here instead. 660 | ldr r1, =0x12a82efe 661 | cmp r0, r1 662 | moveq r0, #1 663 | movne r0, #0 664 | b firm_gethwtype_end 665 | 666 | firm_gethwtype_hdrlpnext: 667 | add r2, r2, #0x30 668 | add r1, r1, #1 669 | cmp r1, #4 670 | blt firm_gethwtype_hdrlp 671 | 672 | mvn r0, #0 673 | 674 | firm_gethwtype_end: 675 | bx lr 676 | .pool 677 | #endif 678 | 679 | /*@ Locate the two "firmX:" strings used for FIRM-partition installation. 680 | proc9_autolocate_patch_firminstallstrs: @ r0 = Process9 .text addr, r1 = addr of Process9 .code, r2 = Process9 .text size. 681 | push {r4, r5, r6, lr} 682 | mov r4, r1 683 | mov r5, r2 684 | add r4, r4, r5 685 | sub r5, r5, #0x1c 686 | sub r4, r4, #0x1c 687 | 688 | proc9_autolocate_patch_firminstallstrs_lp: 689 | mov r0, r4 690 | ldr r1, =proc9_autolocate_patch_firminstallstrs_patterndata 691 | mov r2, #0x1c 692 | bl memcmp 693 | cmp r0, #0 694 | bne proc9_autolocate_patch_firminstallstrs_lpnext 695 | 696 | @ Overwrite "firm0:" with "firm1:". 697 | mov r0, #0x31 698 | strb r0, [r4, #8] 699 | 700 | b proc9_autolocate_patch_firminstallstrs_end 701 | 702 | proc9_autolocate_patch_firminstallstrs_lpnext: 703 | sub r4, r4, #1 704 | sub r5, r5, #1 705 | cmp r5, #0 706 | bcs proc9_autolocate_patch_firminstallstrs_lp 707 | 708 | proc9_autolocate_patch_firminstallstrs_end: 709 | pop {r4, r5, r6, pc} 710 | 711 | proc9_autolocate_patch_firminstallstrs_patterndata: 712 | .byte 66 00 69 00 72 00 6D 00 30 00 3A 00 00 00 66 00 69 00 72 00 6D 00 31 00 3A 00 00 00*/ 713 | 714 | //patchfirm_arm11section_additionalmodulesize: 715 | //.word 0 716 | 717 | #ifdef LOADA9_NEW3DSMEM 718 | firmpatches_proc9entryhook_codestub: 719 | @ Executed from the proc9 .bss clearing func hook. This code is executed from the binary at NEW3DSMEM_TMPADDR_END - . 720 | @ Copy the binary from NEW3DSMEM_TMPADDR_END - to the original binary location, then return to proc9. 721 | 722 | ldr r0, =_end 723 | ldr r1, =__text_start 724 | sub r0, r0, r1 725 | ldr r1, =NEW3DSMEM_TMPADDR_END 726 | sub r1, r1, r0 727 | 728 | ldr r0, =__text_start 729 | ldr r2, =_end 730 | sub r2, r2, r0 731 | 732 | firmpatches_proc9entryhook_codestub_cpylp: 733 | ldr r3, [r1], #4 734 | str r3, [r0], #4 735 | sub r2, r2, #4 736 | cmp r2, #0 737 | bgt firmpatches_proc9entryhook_codestub_cpylp 738 | 739 | ldr r3, firmpatches_proc9entryhook_codestub_retaddr 740 | ldr r0, [r3, #0x14] 741 | ldr r1, [r3, #0x18] 742 | bx r3 743 | .pool 744 | 745 | firmpatches_proc9entryhook_codestub_retaddr: 746 | .word 0 747 | #endif 748 | 749 | filepath_x01ffb800: 750 | .string "/x01ffb800.bin" 751 | .align 2 752 | 753 | #ifdef LOADA9_x01FFB800_INCFILEPATH 754 | LOADA9_x01FFB800_DATA: 755 | .incbin LOADA9_x01FFB800_INCFILEPATH 756 | #endif 757 | 758 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Codebase for Nintendo 3DS modded-FIRM("CFW"), for both Old3DS/New3DS. This also includes ctrserver, which is a network server which runs on the 3DS. This codebase originally started at roughly December 2012 - January 2013, which was finally released in January 2017. 2 | 3 | You *must* build this yourself. This codebase is *only* intended for those that can build this codebase themselves. Built binaries will+should not be released(hence the below build options). Hence, this is mainly for developers. 4 | 5 | Kind of like other "CFW", use at your own risk if you do anything (semi-)dangerous on physnand without nandredir & without a way to restore a nandimage. 6 | 7 | # Building 8 | To build: make {optional makefile parameters listed below} 9 | You have to use various "DISABLE" build options if you don't use the "LOADA9_NEW3DSMEM=1" build option, otherwise 3dshax will fail to build. 10 | You will likely want to have your own script(s) for the default build command(s) you use. 11 | 12 | Building ctrserver requires "3dshaxarm11_ctrserver_data/auth.bin", this is the "auth.txt" which would be used on the client-side. This is a <=0x100-byte file, the contents can be anything(random data for example). 13 | 14 | The end result of building both of these is "3dshax_arm9.bin" and "3dshax_arm11_ctrserver.bin". After building, each .bin is copied to OUTPATH, for the latter .bin it's copied to OUTPATH/3dshax_arm11.bin. 15 | 16 | # Usage 17 | 18 | By default NAND-redir is enabled, see below for disabling it. When NAND-redir is enabled, the base sector-num must be specified via Makefile parameter NANDREDIR_SECTORNUM. 19 | 20 | By default the FIRM-launch code loads the plaintext FIRM from SD "/firm.bin", see the below *_FIRMLAUNCH_LOAD* options. The FWVER values used by the arm9code is automatically determined via the arm11kernel configmem init code in the FIRM being loaded. 21 | 22 | The arm9 codebase will handle launching the sdcard "/3dshax_arm11.bin", when enabled(which is the default). By default this arm11code is loaded into the "dlp" process, this can be overridden with "spider" by holding down the "Up" D-Pad button when main() is executed, or the "Down" D-Pad button there instead for running under the Miiverse applet. The server must not be running under dlp when trying to boot into \*hax payload with Old3DS. 23 | 24 | If you press buttons X, Select, and Start, while the arm9-thread is running, the thread will dump FCRAM+AXIWRAM to SD then terminate the thread. You should shutdown the system soon after using this. 25 | 26 | When DISABLE_ARM11KERNEL_DEBUG isn't(?) used, 3dshax may randomly fail to boot. When this happens just reboot and try again. This is probably related to the arm9<>arm11 IPC sync done by the arm9-thread/etc? 27 | 28 | # Makefile parameters 29 | * "OUTPATH={path to sdcard root}" Optional, this can be used to copy the built binaries to the specified path. 30 | * "ARM9BINCPOUT_PATH={path}" When OUTPATH is used, copy the built arm9bin to "$(OUTPATH)$(ARM9BINCPOUT_PATH)" instead of just "$(OUTPATH)". 31 | 32 | * "DISABLEAES=1" Disables all arm9 AES code. 33 | * "DISABLENANDREDIR=1" Disables NAND->SD redirection. 34 | * "NANDREDIR_SECTORNUM={sectornum}" Sector-num base for the SD nandimage, for NAND-redir when enabled. 35 | * "NANDREDIR_SECTORNUM_PADCHECK0={padbitmask}" When used with NANDREDIR_SECTORNUM_PADCHECK0VAL, the current NANDREDIR_SECTORNUM(during firmpatching @ firmlaunch) will be set to NANDREDIR_SECTORNUM_PADCHECK0VAL when all of the buttons specified by the NANDREDIR_SECTORNUM_PADCHECK0 bitmask are set. 36 | * "NANDREDIR_SECTORNUM_PADCHECK0VAL={sectornum}" Required when using NANDREDIR_SECTORNUM_PADCHECK0, see above. 37 | * "NANDREDIR_SECTORNUM_PADCHECK1={padbitmask}" "NANDREDIR_SECTORNUM_PADCHECK1VAL={sectornum}" Same as NANDREDIR_SECTORNUM_PADCHECK0* except for a different set of options, these are checked/used after NANDREDIR_SECTORNUM_PADCHECK0*. 38 | * "ENABLE_DUMP_NANDIMAGE=1" Enables nandimage dumping to SD "/3dshax_dump.bin", when button Y is pressed once from the arm9 thread. To dump the physical NAND, "DISABLENANDREDIR=1" should be used. 39 | * "LOADA9_NEW3DSMEM=1" Use the new3ds arm9 .ld for using new3ds arm9mem, for much more space. 40 | 41 | * "DISABLE_ARM9DEBUGGING=1" Disables ARM9 exception debugging, this is automatically disabled when DISABLE_ARM11KERNEL_DEBUG=1 is used. Note that ARM9 exception dumping currently only works with ctrserver, this doesn't work for writing the exception info to SD. 42 | * "DISABLE_ARM11KERNEL_DEBUG=1" Disables ARM11-kernel patches. 43 | * "DISABLE_ARM11KERNEL_PROCSTARTHOOK=1" Disables the ARM11-kernel process-start hook, used for loading arm11code(ctrserver) etc. This isn't needed when "DISABLE_ARM11KERNEL_DEBUG=1" is used. 44 | * "DISABLE_ARM11KERNEL_SVCHANDLER_PATCH=1" Disables the ARM11-kernel svc-handler patch, which when the patch is left enabled allows access to all SVCs. This option also disables patching the svc7b entry in the svc jumptable when that entry is 0x0, like with FIRM >=v11.0. 45 | * "DISABLE_NETDEBUG=1" Disable the loop in the arm11kernel debug exception handler(when procstarthook/arm11kernel_debug are enabled) which waits for a signal(terminate process / continue) from ctrserver. 46 | * "ENABLE_CMDLOGGING=1" Enables ARM11-kernel patches+code for logging commands. 47 | * "CMDLOGGING_PADCHECK=value" For cmd-logging, only do logging when any of the bits in the specified value is set for the current PAD register state. 48 | * "CMDLOGGING_PROCNAME0=value" u32 value to compare the src/dst process-name with for filtering. This is required for cmd-logging. 49 | * "CMDLOGGING_PROCNAME1=value" Optional extra u32 value to compare the src/dst process-name with for filtering, for cmd-logging. When this is set, only commands where the src and dst are CMDLOGGING_PROCNAME0 and CMDLOGGING_PROCNAME1 are logged(for example, for logging commands sent to a certain sysmodule sent by a certain process). 50 | * "CMDLOGGING_ALTPROCNAME=value" Optional extra u32 value to compare the src/dst process-name with for filtering, for cmd-logging. This can be used to log all service commands sent/received by the procnames specified by CMDLOGGING_PROCNAME0 and CMDLOGGING_ALTPROCNAME(not just commands sent to each other like with CMDLOGGING_PROCNAME1). CMDLOGGING_PROCNAME1 must not be used when this option is used. 51 | * "CMDLOGGING_IGNORE_PROCNAME=value" Optional u32 value to compare the src/dst process-name with, when it matches the cmd will not be logged. 52 | * "CMDLOGGING_CMDHDR_FILTER=value" Optional command-request header value, when used only comand requests with this header will be logged. 53 | * "ENABLE_ARM11KERNEL_SVCBREAKPATCH=1" This enables writing a bkpt instruction to the start of the ARM11-kernel code handling svcBreak. 54 | 55 | * "DISABLE_GETEXHDRHOOK=1" Disables the arm9 get-exheader hook. This option must be used when DISABLE_ARM11KERNEL_DEBUG or DISABLE_ARM11KERNEL_PROCSTARTHOOK is set. 56 | * "ENABLE_LOADA9_x01FFB800=1" This enables arm9 code which loads the 0x4800-byte SD file @ "/x01ffb800.bin" to arm9-mem 0x01ffb800. This should only be used when NAND-redir is enabled, and when the SD nandimage is originally from another 3ds, converted for usage on another 3ds. This is broken on New3DS(openfile() in loadfile_charpath() never returns), LOADA9_x01FFB800_INCFILEPATH must be used here due to this. 57 | * "LOADA9_x01FFB800_INCFILEPATH={filepath relative to the 3dshaxarm9 directory}" When ENABLE_LOADA9_x01FFB800 is specified, this does a 0x100-byte memcpy for writing to 0x01ffb800 with the specified file(which gets included in the 3dshax_arm9.bin), instead of loading from a file on SD. 58 | * "ENABLE_ARM11PROCLIST_OVERRIDE=1" This enables overriding the exheader and/or the loaded code binary at process-start, for any process(see 3dshax_arm9.c). 59 | * "ADDEXHDR_SYSMODULE_DEPENDENCY=hexvalue" This adds sysmodules to the specified process exheader, so that ctrserver under dlp module gets loaded + is accessible over the network(only needed for getting ctrserver to load eariler than normal). 60 | * "ADDEXHDR_SYSMODULE_DEPENDENCY_PADCHECK=hexvalue" When used the code for ADDEXHDR_SYSMODULE_DEPENDENCY only gets executed when the specified PAD button(s) are pressed. 61 | * "ENABLE_BROWSER_APPMEM=1" Patch the browser(spider/skater) exheader so that memregion=APPLICATION and reslimit=APPLICATION, this allows the process to allocate much more memory. The official browser code won't allocate additional memory with this. This was implemented for use with webkitdebug.s from here: https://github.com/yellows8/3ds_browserhax_common 62 | * "ENABLE_GAMECARD=1" Enables 3ds gamecard reading code(including ctrcard cmd 0xc6 code). 63 | * "ENABLE_ARM11CODELOAD_SERVACCESSCONTROL_OVERWRITE=1" Enable overwriting the exheader service-access-control for the arm11codeload with the get-exhdr-hook, with the list from 3dshax_arm9.c. This is only needed when the loaded arm11 binary is not the latest ctrserver binary which has access to all services. 64 | * "DISABLE_FSACCESSINFO_OVERWRITE=1" Disable exheader FS accessinfo overwrite with all 0xFF for the arm11code-load process. 65 | * "DISABLE_A9THREAD=1" Disables creation of the arm9 thread. 66 | * "ENABLE_CONFIGMEM_DEVUNIT=1" Enables writing val0 to configmem UNITINFO. This can be used to enable dev-mode for ErrDisp. This should not be used normally(breaks eShop for example). 67 | 68 | * "ENABLE_FIRMLAUNCH_HOOK=1" Enables hooking Process9 FIRM-launch once the system finishes fully booting after previous FIRM-launch(es). FIRM-launch parameters won't be cleared with this, so that launching titles with this works. 69 | * "DISABLE_FIRMLAUNCH_LOADSD=1" Disable loading FIRM from SD from the firmlaunch hook. If this is used, then the ENABLE_FIRMLAUNCH_LOADNAND=1 option must be used. 70 | * "ENABLE_FIRMLAUNCH_LOADNAND=1" Enable loading FIRM from NAND(from the default ExeFS filepath used by official firmlaunch) from the firmlaunch hook. This is only used when loading the FIRM from SD fails, the FIRM being launched isn't available on SD / isn't supported with SD loading, or when DISABLE_FIRMLAUNCH_LOADSD=1 is used. With the second NATIVE_FIRM firmlaunch, this will *only* load the FIRM from physnand, not the nandredir image. If this code gets executed in that case with nandredir enabled, it will abort(allowing the FIRM boot to continue would only result in boot failure due to nandimage incompatibility with the physnand FIRM, depending on the FIRM/nandimage versions). Therefore, with nandredir enabled this should only be used for non-nativefirm. 71 | * "ALTSD_FIRMPATH=1" Use SD FIRM filepath "/3dshax_firm.bin" instead of "/firm.bin". 72 | * "DISABLE_MATCHINGFIRM_HWCHECK=1" Disables the code which checks that the FIRM is for the currently running system: no booting Old3DS FIRM on New3DS when that code is enabled, likewise for New3DS FIRM on Old3DS. 73 | * "ENABLE_BOOTSAFEFIRM_STARTUP=1" Boot into SAFE_MODE_FIRM with the system-updater with nand-redir(if enabled), instead of nativefirm like normal. The FIRM code for Old3DS SAFE_MODE_FIRM is very old, hence the auto-locate code for nandredir+{proc9 hook for code executed from main()} doesn't work with safefirm atm. 74 | 75 | * "ENABLE_REGIONFREE={val}" Enables the homemenu SMDH icon region check patch. This does not affect the region-lock via gamecard sysupdates, see DISABLE_GAMECARDUPDATE. "ENABLE_REGIONFREE=2" is the same as "ENABLE_REGIONFREE=1", except this also uses the "DISABLE_GAMECARDUPDATE=1" option at the same time. Note that this(SMDH region patch) may cause SD titles which normally aren't displayed, to be shown as presents or black icons. 76 | * "DISABLE_GAMECARDUPDATE=1" Disables gamecard sysupdates, this is required for launching gamecards from other regions. 77 | 78 | * "ENABLE_OLDFS_AUTOLOCATE=1" Enable auto-locating FS code with very old FIRM. 79 | 80 | * "ENABLE_DMA=1" Enables the cmd for use via ctrserver for the DMA SVCs. 81 | 82 | * "ENABLE_NIMURLS_PATCHES=1" Enables patching NIM so that it uses custom URLs for the ECommerceSOAP and NetUpdateSOAP URLs, see NIMPATCHURL_UPDATE and NIMPATCHURL_ECOMMERCE. Both of those options are required when using this ENABLE_NIMURLS_PATCHES option. 83 | * NIMPATCHURL_UPDATE=URL Sets the NetUpdateSOAP URL to write to NIM with ENABLE_NIMURLS_PATCHES=1. The max length is 62 characters, not including the final null-terminator left in memory. 84 | * NIMPATCHURL_ECOMMERCE=URL Sets the ECommerceSOAP URL to write to NIM with ENABLE_NIMURLS_PATCHES=1. See NIMPATCHURL_UPDATE for max len. 85 | 86 | * "ENABLE_THEMECACHENAME=1" Enables patching home menu's theme cache filenames so that home menu uses its own theme cache under 3dshax. This is particularly useful when used with menuhax to a) avoid infinite boot loops and b) avoid ROP crashes in mismatching home menu versions. 87 | 88 | * "ENABLE_LOADSD_AESKEYS=1" During firmlaunch, enable loading AES keyslots keydata from SD, see 3dshax_arm9.c. 89 | 90 | * "NEW3DS_ARM9BINLDR_PATCHADDR0=address" Write NEW3DS_ARM9BINLDR_PATCHADDR0_VAL to {address}, from the new3ds arm9bin loader entrypoint hook. 91 | * "NEW3DS_ARM9BINLDR_PATCHADDR0_VAL=val" 92 | * "NEW3DS_ARM9BINLDR_PATCHADDR1=address" 93 | * "NEW3DS_ARM9BINLDR_PATCHADDR1_VAL=val" 94 | * "NEW3DS_ARM9BINLDR_CLRMEM=address" Clear the memory starting at address with size from NEW3DS_ARM9BINLDR_CLRMEM_SIZE, from the new3ds arm9bin loader entrypoint hook. 95 | * "NEW3DS_ARM9BINLDR_CLRMEM_SIZE=val" 96 | 97 | * "MEMDUMPBOOT_SRCADDR=address" Copies memory from the specified address to the dst with the configured size, the first time 3dshax runs with RUNNINGTYPE 3. This could be used to dump memory which would be overwritten / no longer available later in boot. Once 3dshax boots, you could then use 3dshaxclient to read the memory from the dst addr(see below). 98 | * "MEMDUMPBOOT_DSTADDR=address" Override the default(0x08001000) dst address used with the above. The dst memory starts with magicnum "DUMP" followed by the actual data. The dump code only runs with RUNNINGTYPE 3 when the data at dst+0 doesn't match this magicnum. 99 | * "MEMDUMPBOOT_SIZE=val" Override the default(0x200) size used with the above. 100 | 101 | # FIRM Compatibility 102 | Supported NATIVE_FIRM system-versions(versions where NATIVE_FIRM wasn't updated don't apply here): 103 | * v4.1 104 | * v5.x 105 | * v6.x 106 | * v7.x 107 | * v8.x 108 | * v9.0-v9.2 109 | * v9.3 110 | * v9.5 111 | * v9.6 112 | * v10.0 113 | * v10.4 114 | * v11.0 Something related to the svcBackdoor code might be broken or something?(The getdebuginfoblk network cmd works fine usually but sometimes returns nothing) 115 | * v11.1 116 | * v11.2 117 | * v11.3 118 | * v11.4 Broken 119 | * {Versions that work fine as-is due to auto-location} 120 | 121 | Basically all of the codebase automatically determines what addresses to patch/etc on-the-fly(besides some structure/etc stuff which use FWVER instead / minor stuff). 122 | 123 | The codebase also determines the version of the FIRM being loaded on-the-fly, hence the only time this codebase needs updated for newer FIRM is when auto-location breaks / certain structures change. 124 | 125 | Note: when using nandredir where you also want to use old NATIVE_FIRM, you should use ALTSD_FIRMPATH. The SD firm.bin should contain a FIRM compatible with physnand, while 3dshax_firm.bin should contain the actual FIRM you want to run under nandredir. 126 | 127 | # Debugging 128 | 129 | Debug data is always written to SD "/3dshax_debug.bin" unless "DISABLE_ARM11KERNEL_DEBUG=1" is used. The contents can be parsed with the 3dshax_parsedebug tool. This contains exception dumps, and cmdlog data if enabled via the build options. By default a process will not terminate at crash until a continue/kill command is used by 3dshaxclient, if the server is active(see the DISABLE_NETDEBUG option). 130 | 131 | The cmdlogs are logs of IPC commands' request and reply data, with dumps of the data buffers(when --hexdump is passed to 3dshax_parsedebug). Note that in some cases some of the dumped data is invalid: it just gets the physaddr of buf+0 then writes the whole buffer size with that to SD. The result is invalid data when the physmem for a buffer isn't linear, in particular 0x04000000+ memory after the first page. 132 | 133 | Cmdlogging will slow down the system, unless it's logging barely anything. 134 | 135 | # Networking 136 | 137 | This includes ctrserver and 3dshaxclient. The former is a RPC server which runs under dlp-sysmodule by default, see the Usage section. The protocol is based on [ctrclient](https://github.com/neimod/ctr/tree/master/ramtracer/ctrclient), some code is used from that as well. 3dshaxclient is built with that(unless you build with ctr-cryptotool for the CTRCLIENT build option from 3dscrypto-tools). Among other things, this allows doing debugging and AES-engine crypto over the network. 138 | 139 | You can use the running server with [3dscrypto-tools](https://github.com/yellows8/3dscrypto-tools). DO NOT use network AES crypto without nandredir / a way to restore a nandimage: it's known to cause NAND corruption. In some rare(?) cases the decrypted data may be junk, just rerun the tool if that happens. 140 | 141 | For accessing the server you can use 3dshaxclient. The commands for the client/server are not documented. See 3dshaxclient.c, network.c, and 3dshax_arm9.c. 142 | 143 | The network debugging is done with the custom client commands for 3dshaxclient. 144 | 145 | # Setup 146 | 147 | Note: this entire Setup section of the README didn't exist in the README until 3dshax release. 148 | 149 | ## sighax / Custom FIRM 150 | 151 | Remember, be *very* *careful* with this since NAND writing is done here. And of course, backup your NAND image first. 152 | 153 | This could(not tested) also be used with non-BootROM FIRM-boot methods(from "CFW"/whatever), in that case you can skip/ignore the NAND-related info in this section. 154 | 155 | Stage0, Building: 156 | 157 | 1. Build [bootldr9_rawdevice](https://github.com/yellows8/bootldr9_rawdevice). Use at least build options "ENABLE_RETURNFROMCRT0=1" and "ENABLE_CONTINUEWHEN_PAYLOADCALLFAILS=1". You can use whatever device/padcheck build options you want if any. 158 | 2. Build [firm_payload_bootstrap](https://github.com/yellows8/firm_payload_bootstrap) with the above built binary for bootldr9_rawdevice. Manually replace the signature in the built FIRM with your own signature. 159 | 3. Build [3dsbootldr_fatfs](https://github.com/yellows8/3dsbootldr_fatfs) with at least build option "ENABLE_RETURNFROMCRT0=1". 160 | 4. Build payloadbuilder from [bootldr9_rawdevice](https://github.com/yellows8/bootldr9_rawdevice), then run: payloadbuilder 3dsbootldr_fatfs.customfirmfmt 3dsbootldr_fatfs.bin 0x080F4000 161 | 5. Build [3dsbootldr_firm](https://github.com/yellows8/3dsbootldr_firm), with at least build option "ENABLE_RETURNFROMCRT0=1". Do not use the rawdevice/NAND build options. 162 | 163 | Stage1, SD Setup: 164 | 165 | 1. On the SD card, write "3dsbootldr_fatfs.customfirmfmt" to the raw sectors starting at sector 8. Make sure the area that would be written here is empty / not used. 166 | 2. Setup the built 3dsbootldr_firm on SD the same way described in the below arm9loaderhax section. 167 | 168 | Stage2, NAND Setup: 169 | 170 | 1. Rebuild 3dsbootldr_firm with at least the following build options: "ENABLE_RETURNFROMCRT0=1", "BINLOAD_DISABLE=1", "USE_RAWDEVICE=1", "USEDEVICE_NAND=1", "RAWDEVICE_STARTSECTOR={0x5A180}", and "RAWDEVICE_NUMSECTORS={0x800}". 171 | 2. Then run payloadbuilder from [bootldr9_rawdevice](https://github.com/yellows8/bootldr9_rawdevice): payloadbuilder 3dsbootldr_firm.customfirmfmt 3dsbootldr_firm.bin 0x080F4000 172 | 3. Write "3dsbootldr_firm.customfirmfmt" to the raw sectors in NAND starting at sector 8. 173 | 4. Write the official unmodified FIRM(ideally unmodified at least) that you want to boot from NAND, to NAND offset 0x0B430000(sector 0x5A180). 174 | 175 | Stage3, custom FIRM Setup: 176 | 177 | 1. Write the FIRM built from firm_payload_bootstrap with the previously updated signature, to your system's NAND firm0 partition, using whatever method you want. If writing it raw, remember to encrypt it properly. If you want to use it with non-NAND FIRM boot instead, you'll have to manually encrypt the FIRM sections following the FIRM header + use a signature for non-NAND. 178 | 179 | Note that "firm.bin" on SD is required with this, when booting 3dshax from SD with the above. 180 | 181 | After building 3dshax with OUTPATH={sd root}, you must run the build_hashedbin.sh script from 3dsbootldr_firm with 3dshax_arm9.bin on SD, unless you built 3dsbootldr_firm with "DISABLE_BINVERIFY=1". 182 | 183 | NOTE: Prior to broken attempts at using the 3dsbootldr repos mentioned in the arm9loaderhax section, from the beginning they(and others) were originally used with sighax. 184 | 185 | NOTE: You MUST avoid triggering any FIRM-partition-installation on physnand(downloadplay, sysupdate, ...). Otherwise, official FIRM will overwrite the FIRM installed to NAND firm0(system will still boot fine but you would have to reinstall the custom FIRM). 186 | 187 | ## Public arm9loaderhax 188 | 189 | Currently 3dshax can only be used with a9lh on Old3DS, not New3DS due to New3DS keys not being setup properly. If you run 3dsbootldr_fatfs as a Luma payload, your build of Luma *must* include [this](https://github.com/AuroraWright/Luma3DS/commit/f03e232b90ed3e2e8545c5abb4c489ca4f1e0b7d) commit. 190 | 191 | 3dshax was *never* used with any form of arm9loaderhax until some broken attempts in Jan-2017. 192 | 193 | 1. Setup [3dsbootldr_fatfs](https://github.com/yellows8/3dsbootldr_fatfs), where the output binary is used as your "arm9loaderhax.bin" or equivalent, on SD. "ALTARM11BOOT=1" must be used when building this. Do not use ENABLE_RETURNFROMCRT0. 194 | 2. Setup [3dsbootldr_firm](https://github.com/yellows8/3dsbootldr_firm). At offset 0x0 in 3dsbootldr_firm.bin, insert(not overwrite) raw bytes "00 80 0E 08" then write it to SD "/load9.bin". Likewise for 3dsbootldr_firm_arm11.bin, except use raw bytes "00 E7 FF 1F" then write to SD "/load11.bin". The binaries on SD must be run with the build_hashedbin.sh script from 3dsbootldr_fatfs, unless you used "DISABLE_BINVERIFY=1" for 3dsbootldr_fatfs. Do not use the rawdevice/NAND build options. 195 | 196 | After building 3dshax with OUTPATH={sd root}, you must run the build_hashedbin.sh script from 3dsbootldr_firm with 3dshax_arm9.bin on SD, unless you built 3dsbootldr_firm with "DISABLE_BINVERIFY=1". 197 | 198 | **NOTE: If you use this with DISABLENANDREDIR=1, you MUST avoid triggering any FIRM-partition-installation(downloadplay, sysupdate, ...). A brick(on New3DS at least) will occur otherwise. While there's some disabled code for some form of FIRM-protection, it was never really finished.** 199 | 200 | ## 3ds-totalcontrolhaxx 201 | 202 | If you are on a compatible FIRM version, you can also use [3ds-totalcontrolhaxx](https://github.com/yellows8/3ds-totalcontrolhaxx). Just setup the .3dsx on SD(or even use the payload binary directly if you want) + the actual 3dshax, and that's all. The firm.bin on SD should match the physnand version. If you want to boot a different FIRM version, use 3dshax build option ALTSD_FIRMPATH. 203 | 204 | --------------------------------------------------------------------------------