From 913bc867b7e69d1ac66155017805cbb2e44e0188 Mon Sep 17 00:00:00 2001 From: Gabriel Marcano Date: Tue, 7 Jun 2016 02:30:30 -0400 Subject: [PATCH 1/6] No longer saves more than the ROM size, cleanup Using some header information from rom_tool, it was possible to implement something that will accurately determine the real ROM size. With that information, uncart no longer dumps in 2GB chunks, but to the actual size of ROM (all 8 partitions). Warnings were cleaned up as much as possible for now (2 remain). i2c support was added in order to be able to shut down uncart when it is over (it isn't clear that the ASM in start.s is right for returning control to brahma, if that's even possible). More warnings were enabled in the Makefile, and lto was enabled. Currently, the Makefile and the draw.h are configured for a9lh support. --- Makefile | 11 +++-- source/aes.h | 48 +++++++++---------- source/draw.c | 35 +++++++------- source/draw.h | 25 ++++++---- source/fatfs/ff.c | 32 ++++++------- source/fatfs/ff.h | 2 +- source/fatfs/sdmmc.c | 75 +++++++++++++++++------------ source/fatfs/sdmmc.h | 8 ++-- source/gamecart/command_ctr.c | 2 +- source/gamecart/command_ntr.c | 2 +- source/gamecart/command_ntr.h | 2 +- source/gamecart/protocol.c | 4 +- source/gamecart/protocol.h | 10 ++-- source/gamecart/protocol_ctr.c | 2 + source/gamecart/protocol_ctr.h | 36 +++++++------- source/gamecart/protocol_ntr.c | 2 + source/gamecart/protocol_ntr.h | 70 +++++++++++++-------------- source/headers.h | 75 +++++++++++++++++++++++++++++ source/i2c.c | 16 +++---- source/i2c.h | 9 ++-- source/main.c | 87 ++++++++++++++++++++++------------ source/start.s | 14 ++++++ 22 files changed, 355 insertions(+), 212 deletions(-) create mode 100644 source/headers.h diff --git a/Makefile b/Makefile index 7af4adb..50ee857 100644 --- a/Makefile +++ b/Makefile @@ -31,17 +31,18 @@ INCLUDES := source #--------------------------------------------------------------------------------- ARCH := -march=armv5te -mtune=arm946e-s -mthumb -mthumb-interwork -CFLAGS := -g -Wall -O2\ +CFLAGS := -g -Wall -Wextra -Wpedantic -O2 -flto\ -fomit-frame-pointer\ - -ffast-math -std=c99\ + -ffast-math -std=c11\ $(ARCH) -CFLAGS += $(INCLUDE) -DARM9 -Werror-implicit-function-declaration +CFLAGS += $(INCLUDE) -DARM9 -Werror-implicit-function-declaration -Wcast-align -Wcast-qual -Wdisabled-optimization -Wformat=2 -Winit-self -Wlogical-op -Wmissing-declarations -Wmissing-include-dirs -Wredundant-decls -Wshadow -Wsign-conversion -Wstrict-overflow=5 -Wswitch-default -Wundef -Wno-unused CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions ASFLAGS := -g $(ARCH) LDFLAGS = -nostartfiles -g --specs=../stub.specs $(ARCH) -Wl,-Map,$(TARGET).map +OCFLAGS=--set-section-flags .bss=alloc,load,contents LIBS := @@ -101,7 +102,7 @@ all: $(BUILD) $(BUILD): @[ -d $@ ] || mkdir -p $@ @make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile - cp $(OUTPUT).bin arm9payload.bin + cp $(OUTPUT).bin arm9loaderhax.bin #--------------------------------------------------------------------------------- clean: @@ -123,7 +124,7 @@ $(OUTPUT).elf : $(OFILES) #--------------------------------------------------------------------------------- %.bin: %.elf - @$(OBJCOPY) -O binary $< $@ + @$(OBJCOPY) $(OCFLAGS) -O binary $< $@ @echo built ... $(notdir $@) diff --git a/source/aes.h b/source/aes.h index 5192127..417ea38 100644 --- a/source/aes.h +++ b/source/aes.h @@ -26,29 +26,29 @@ #define AES_WRITE_FIFO_COUNT ((REG_AESCNT>>0) & 0x1F) #define AES_READ_FIFO_COUNT ((REG_AESCNT>>5) & 0x1F) -#define AES_BUSY (1<<31) +#define AES_BUSY (1u<<31) -#define AES_FLUSH_READ_FIFO (1<<10) -#define AES_FLUSH_WRITE_FIFO (1<<11) -#define AES_BIT12 (1<<12) -#define AES_BIT13 (1<<13) -#define AES_MAC_SIZE(n) ((n&7)<<16) -#define AES_MAC_REGISTER_SOURCE (1<<20) -#define AES_UNKNOWN_21 (1<<21) -#define AES_OUTPUT_BIG_ENDIAN (1<<22) -#define AES_INPUT_BIG_ENDIAN (1<<23) -#define AES_OUTPUT_NORMAL_ORDER (1<<24) -#define AES_INPUT_NORMAL_ORDER (1<<25) -#define AES_UNKNOWN_26 (1<<26) -#define AES_MODE(n) ((n&7)<<27) -#define AES_INTERRUPT_ENABLE (1<<30) -#define AES_ENABLE (1<<31) +#define AES_FLUSH_READ_FIFO (1u<<10) +#define AES_FLUSH_WRITE_FIFO (1u<<11) +#define AES_BIT12 (1u<<12) +#define AES_BIT13 (1u<<13) +#define AES_MAC_SIZE(n) ((n&7u)<<16) +#define AES_MAC_REGISTER_SOURCE (1u<<20) +#define AES_UNKNOWN_21 (1u<<21) +#define AES_OUTPUT_BIG_ENDIAN (1u<<22) +#define AES_INPUT_BIG_ENDIAN (1u<<23) +#define AES_OUTPUT_NORMAL_ORDER (1u<<24) +#define AES_INPUT_NORMAL_ORDER (1u<<25) +#define AES_UNKNOWN_26 (1u<<26) +#define AES_MODE(n) ((n&7u)<<27) +#define AES_INTERRUPT_ENABLE (1u<<30) +#define AES_ENABLE (1u<<31) -#define AES_MODE_CCM_DECRYPT 0 -#define AES_MODE_CCM_ENCRYPT 1 -#define AES_MODE_CTR 2 -#define AES_MODE_UNK3 3 -#define AES_MODE_CBC_DECRYPT 4 -#define AES_MODE_CBC_ENCRYPT 5 -#define AES_MODE_UNK6 6 -#define AES_MODE_UNK7 7 +#define AES_MODE_CCM_DECRYPT 0u +#define AES_MODE_CCM_ENCRYPT 1u +#define AES_MODE_CTR 2u +#define AES_MODE_UNK3 3u +#define AES_MODE_CBC_DECRYPT 4u +#define AES_MODE_CBC_ENCRYPT 5u +#define AES_MODE_UNK6 6u +#define AES_MODE_UNK7 7u diff --git a/source/draw.c b/source/draw.c index 1e82cac..fac8512 100644 --- a/source/draw.c +++ b/source/draw.c @@ -10,7 +10,7 @@ #include "font.h" #include "draw.h" -int current_y = 0; +size_t current_y = 0; void ClearScreen(unsigned char *screen, int color) { @@ -23,16 +23,15 @@ void ClearScreen(unsigned char *screen, int color) } } -void DrawCharacter(unsigned char *screen, int character, int x, int y, int color, int bgcolor) +void DrawCharacter(unsigned char *screen, int character, size_t x, size_t y, int color, int bgcolor) { - int yy, xx; - for (yy = 0; yy < 8; yy++) { - int xDisplacement = (x * BYTES_PER_PIXEL * SCREEN_WIDTH); - int yDisplacement = ((SCREEN_WIDTH - (y + yy) - 1) * BYTES_PER_PIXEL); - unsigned char *screenPos = screen + xDisplacement + yDisplacement; - - unsigned char charPos = font[character * 8 + yy]; - for (xx = 7; xx >= 0; xx--) { + for (size_t yy = 0; yy < 8; yy++) { + size_t xDisplacement = (x * BYTES_PER_PIXEL * SCREEN_WIDTH); + size_t yDisplacement = ((SCREEN_WIDTH - (y + yy) - 1) * BYTES_PER_PIXEL); + + unsigned char *screenPos = screen + xDisplacement + yDisplacement; + unsigned char charPos = font[(size_t)character * 8 + yy]; + for (int xx = 7; xx >= 0; xx--) { if ((charPos >> xx) & 1) { *(screenPos + 0) = color >> 16; // B *(screenPos + 1) = color >> 8; // G @@ -47,7 +46,7 @@ void DrawCharacter(unsigned char *screen, int character, int x, int y, int color } } -void DrawString(unsigned char *screen, const char *str, int x, int y, int color, int bgcolor) +void DrawString(unsigned char *screen, const char *str, size_t x, size_t y, int color, int bgcolor) { const size_t string_len = strlen(str); @@ -55,7 +54,7 @@ void DrawString(unsigned char *screen, const char *str, int x, int y, int color, DrawCharacter(screen, str[i], x + i * 8, y, color, bgcolor); } -void DrawStringF(int x, int y, const char *format, ...) +void DrawStringF(size_t x, size_t y, const char *format, ...) { char str[256]; va_list va; @@ -70,8 +69,8 @@ void DrawStringF(int x, int y, const char *format, ...) void Debug(const char *format, ...) { - char str[50]; - const char* spaces = " X"; + char str[51]; + const char* spaces = " X"; va_list va; va_start(va, format); @@ -79,10 +78,10 @@ void Debug(const char *format, ...) va_end(va); snprintf(str, sizeof(str), "%s%s", str, spaces); - DrawString(TOP_SCREEN0, str, 10, current_y, RGB(255, 0, 0), RGB(255, 255, 255)); - DrawString(TOP_SCREEN0, spaces, 10, current_y + 10, RGB(255, 0, 0), RGB(255, 255, 255)); - DrawString(TOP_SCREEN1, str, 10, current_y, RGB(255, 0, 0), RGB(255, 255, 255)); - DrawString(TOP_SCREEN1, spaces, 10, current_y + 10, RGB(255, 0, 0), RGB(255, 255, 255)); + DrawString(TOP_SCREEN0, str, 0u, current_y, RGB(255, 0, 0), RGB(255, 255, 255)); + DrawString(TOP_SCREEN0, spaces, 0u, current_y + 10, RGB(255, 0, 0), RGB(255, 255, 255)); + DrawString(TOP_SCREEN1, str, 0u, current_y, RGB(255, 0, 0), RGB(255, 255, 255)); + DrawString(TOP_SCREEN1, spaces, 0u, current_y + 10, RGB(255, 0, 0), RGB(255, 255, 255)); current_y += 10; if (current_y >= 240) { diff --git a/source/draw.h b/source/draw.h index 5f55ea0..c39c6cf 100644 --- a/source/draw.h +++ b/source/draw.h @@ -14,17 +14,22 @@ #define RGB(r,g,b) (r<<24|b<<16|g<<8|r) -#define TOP_SCREEN0 (u8*)(0x20000000) -#define TOP_SCREEN1 (u8*)(0x20046500) -#define BOT_SCREEN0 (u8*)(0x2008CA00) -#define BOT_SCREEN1 (u8*)(0x200C4E00) -extern int current_y; +//#define TOP_SCREEN0 (u8*)(0x20000000) +//#define TOP_SCREEN1 (u8*)(0x20046500) +//#define BOT_SCREEN0 (u8*)(0x2008CA00) +//#define BOT_SCREEN1 (u8*)(0x200C4E00) + +#define TOP_SCREEN0 (u8*)(0x18300000) +#define TOP_SCREEN1 (u8*)(0x18300000) +#define BOT_SCREEN0 (u8*)(0x18346500) +#define BOT_SCREEN1 (u8*)(0x18346500) +extern size_t current_y; void ClearScreen(unsigned char *screen, int color); -void DrawCharacter(unsigned char *screen, int character, int x, int y, int color, int bgcolor); -void DrawHex(unsigned char *screen, unsigned int hex, int x, int y, int color, int bgcolor); -void DrawString(unsigned char *screen, const char *str, int x, int y, int color, int bgcolor); -void DrawStringF(int x, int y, const char *format, ...); -void DrawHexWithName(unsigned char *screen, const char *str, unsigned int hex, int x, int y, int color, int bgcolor); +void DrawCharacter(unsigned char *screen, int character, size_t x, size_t y, int color, int bgcolor); +void DrawHex(unsigned char *screen, unsigned int hex, size_t x, size_t y, int color, int bgcolor); +void DrawString(unsigned char *screen, const char *str, size_t x, size_t y, int color, int bgcolor); +void DrawStringF(size_t x, size_t y, const char *format, ...); +void DrawHexWithName(unsigned char *screen, const char *str, unsigned int hex, size_t x, size_t y, int color, int bgcolor); void Debug(const char *format, ...); diff --git a/source/fatfs/ff.c b/source/fatfs/ff.c index f5547ae..e2b72f5 100644 --- a/source/fatfs/ff.c +++ b/source/fatfs/ff.c @@ -139,8 +139,8 @@ const unsigned short Tbl[] = { /* CP437(0x80-0xFF) to Unicode conversion table }; DWORD get_fattime (void) { - //NO - return 0; + // fixed valid time of 1980-01-01 00:00:00 + return 0x210000; } WCHAR ff_convert ( /* Converted character, Returns zero on error */ @@ -908,7 +908,7 @@ FRESULT sync_fs ( /* FR_OK: successful, FR_DISK_ERR: failed */ /*-----------------------------------------------------------------------*/ -DWORD clust2sect ( /* !=0: Sector number, 0: Failed - invalid cluster# */ +static DWORD clust2sect ( /* !=0: Sector number, 0: Failed - invalid cluster# */ FATFS* fs, /* File system object */ DWORD clst /* Cluster# to be converted */ ) @@ -926,7 +926,7 @@ DWORD clust2sect ( /* !=0: Sector number, 0: Failed - invalid cluster# */ /*-----------------------------------------------------------------------*/ -DWORD get_fat ( /* 0xFFFFFFFF:Disk error, 1:Internal error, Else:Cluster status */ +static DWORD get_fat ( /* 0xFFFFFFFF:Disk error, 1:Internal error, Else:Cluster status */ FATFS* fs, /* File system object */ DWORD clst /* Cluster# to get the link information */ ) @@ -946,7 +946,7 @@ DWORD get_fat ( /* 0xFFFFFFFF:Disk error, 1:Internal error, Else:Cluster status wc = fs->win[bc % SS(fs)]; bc++; if (move_window(fs, fs->fatbase + (bc / SS(fs)))) break; - wc |= fs->win[bc % SS(fs)] << 8; + wc |= (UINT)fs->win[bc % SS(fs)] << 8; return clst & 1 ? wc >> 4 : (wc & 0xFFF); case FS_FAT16 : @@ -974,7 +974,7 @@ DWORD get_fat ( /* 0xFFFFFFFF:Disk error, 1:Internal error, Else:Cluster status /*-----------------------------------------------------------------------*/ #if !_FS_READONLY -FRESULT put_fat ( +static FRESULT put_fat ( FATFS* fs, /* File system object */ DWORD clst, /* Cluster# to be changed in range of 2 to fs->n_fatent - 1 */ DWORD val /* New value to mark the cluster */ @@ -1245,7 +1245,7 @@ FRESULT dir_next ( /* FR_OK:Succeeded, FR_NO_FILE:End of table, FR_DENIED:Could UINT i; - i = dp->index + 1; + i = dp->index + 1u; if (!(i & 0xFFFF) || !dp->sect) /* Report EOT when index has reached 65535 */ return FR_NO_FILE; @@ -1257,7 +1257,7 @@ FRESULT dir_next ( /* FR_OK:Succeeded, FR_NO_FILE:End of table, FR_DENIED:Could return FR_NO_FILE; } else { /* Dynamic table */ - if (((i / (SS(dp->fs) / SZ_DIR)) & (dp->fs->csize - 1)) == 0) { /* Cluster changed? */ + if (((i / (SS(dp->fs) / SZ_DIR)) & (dp->fs->csize - 1u)) == 0) { /* Cluster changed? */ clst = get_fat(dp->fs, dp->clust); /* Get next cluster */ if (clst <= 1) return FR_INT_ERR; if (clst == 0xFFFFFFFF) return FR_DISK_ERR; @@ -1389,7 +1389,7 @@ int cmp_lfn ( /* 1:Matched, 0:Not matched */ WCHAR wc, uc; - i = ((dir[LDIR_Ord] & ~LLE) - 1) * 13; /* Get offset in the LFN buffer */ + i = ((UINT)(dir[LDIR_Ord] & ~LLE) - 1u) * 13u; /* Get offset in the LFN buffer */ s = 0; wc = 1; do { @@ -1421,7 +1421,7 @@ int pick_lfn ( /* 1:Succeeded, 0:Buffer overflow */ WCHAR wc, uc; - i = ((dir[LDIR_Ord] & 0x3F) - 1) * 13; /* Offset in the LFN buffer */ + i = ((dir[LDIR_Ord] & 0x3F) - 1u) * 13u; /* Offset in the LFN buffer */ s = 0; wc = 1; @@ -1462,7 +1462,7 @@ void fit_lfn ( dir[LDIR_Type] = 0; ST_WORD(dir+LDIR_FstClusLO, 0); - i = (ord - 1) * 13; /* Get offset in the LFN buffer */ + i = (ord - 1u) * 13u; /* Get offset in the LFN buffer */ s = wc = 0; do { if (wc != 0xFFFF) wc = lfnbuf[i++]; /* Get an effective character */ @@ -2200,7 +2200,7 @@ int get_ldnumber ( /* Returns logical drive number (-1:invalid drive) */ for (tt = *path; (UINT)*tt >= (_USE_LFN ? ' ' : '!') && *tt != ':'; tt++) ; /* Find ':' in the path */ if (*tt == ':') { /* If a ':' is exist in the path name */ tp = *path; - i = *tp++ - '0'; + i = (UINT)(*tp++ - '0'); if (i < 10 && tp == tt) { /* Is there a numeric drive id? */ if (i < _VOLUMES) { /* If a drive id is found, get the value and strip it */ vol = (int)i; @@ -2696,7 +2696,7 @@ FRESULT f_read ( for ( ; btr; /* Repeat until all data read */ rbuff += rcnt, fp->fptr += rcnt, *br += rcnt, btr -= rcnt) { if ((fp->fptr % SS(fp->fs)) == 0) { /* On the sector boundary? */ - csect = (BYTE)(fp->fptr / SS(fp->fs) & (fp->fs->csize - 1)); /* Sector offset in the cluster */ + csect = (BYTE)(fp->fptr / SS(fp->fs) & (fp->fs->csize - 1u)); /* Sector offset in the cluster */ if (!csect) { /* On the cluster boundary? */ if (fp->fptr == 0) { /* On the top of the file? */ clst = fp->sclust; /* Follow from the origin */ @@ -2718,7 +2718,7 @@ FRESULT f_read ( cc = btr / SS(fp->fs); /* When remaining bytes >= sector size, */ if (cc) { /* Read maximum contiguous sectors directly */ if (csect + cc > fp->fs->csize) /* Clip at cluster boundary */ - cc = fp->fs->csize - csect; + cc = (UINT)fp->fs->csize - csect; if (disk_read(fp->fs->drv, rbuff, sect, cc)) ABORT(fp->fs, FR_DISK_ERR); #if !_FS_READONLY && _FS_MINIMIZE <= 2 /* Replace one of the read sectors with cached data if it contains a dirty sector */ @@ -2797,7 +2797,7 @@ FRESULT f_write ( for ( ; btw; /* Repeat until all data written */ wbuff += wcnt, fp->fptr += wcnt, *bw += wcnt, btw -= wcnt) { if ((fp->fptr % SS(fp->fs)) == 0) { /* On the sector boundary? */ - csect = (BYTE)(fp->fptr / SS(fp->fs) & (fp->fs->csize - 1)); /* Sector offset in the cluster */ + csect = (BYTE)(fp->fptr / SS(fp->fs) & (fp->fs->csize - 1u)); /* Sector offset in the cluster */ if (!csect) { /* On the cluster boundary? */ if (fp->fptr == 0) { /* On the top of the file? */ clst = fp->sclust; /* Follow from the origin */ @@ -2832,7 +2832,7 @@ FRESULT f_write ( cc = btw / SS(fp->fs); /* When remaining bytes >= sector size, */ if (cc) { /* Write maximum contiguous sectors directly */ if (csect + cc > fp->fs->csize) /* Clip at cluster boundary */ - cc = fp->fs->csize - csect; + cc = (UINT)fp->fs->csize - csect; if (disk_write(fp->fs->drv, wbuff, sect, cc)) ABORT(fp->fs, FR_DISK_ERR); #if _FS_MINIMIZE <= 2 diff --git a/source/fatfs/ff.h b/source/fatfs/ff.h index c0d742f..a35b12c 100644 --- a/source/fatfs/ff.h +++ b/source/fatfs/ff.h @@ -330,7 +330,7 @@ int ff_del_syncobj (_SYNC_t sobj); /* Delete a sync object */ #define ST_DWORD(ptr,val) *(DWORD*)(BYTE*)(ptr)=(DWORD)(val) #else /* Use byte-by-byte access to the FAT structure */ #define LD_WORD(ptr) (WORD)(((WORD)*((BYTE*)(ptr)+1)<<8)|(WORD)*(BYTE*)(ptr)) -#define LD_DWORD(ptr) (DWORD)(((DWORD)*((BYTE*)(ptr)+3)<<24)|((DWORD)*((BYTE*)(ptr)+2)<<16)|((WORD)*((BYTE*)(ptr)+1)<<8)|*(BYTE*)(ptr)) +#define LD_DWORD(ptr) (DWORD)(((DWORD)*((BYTE*)(ptr)+3)<<24)|((DWORD)*((BYTE*)(ptr)+2)<<16)|(DWORD)((WORD)*((BYTE*)(ptr)+1)<<8)|*(BYTE*)(ptr)) #define ST_WORD(ptr,val) *(BYTE*)(ptr)=(BYTE)(val); *((BYTE*)(ptr)+1)=(BYTE)((WORD)(val)>>8) #define ST_DWORD(ptr,val) *(BYTE*)(ptr)=(BYTE)(val); *((BYTE*)(ptr)+1)=(BYTE)((WORD)(val)>>8); *((BYTE*)(ptr)+2)=(BYTE)((DWORD)(val)>>16); *((BYTE*)(ptr)+3)=(BYTE)((DWORD)(val)>>24) #endif diff --git a/source/fatfs/sdmmc.c b/source/fatfs/sdmmc.c index ab45589..8ba1ea4 100644 --- a/source/fatfs/sdmmc.c +++ b/source/fatfs/sdmmc.c @@ -20,15 +20,15 @@ mmcdevice *getMMCDevice(int drive) return &handleSD; } -int __attribute__((noinline)) geterror(struct mmcdevice *ctx) +static int __attribute__((noinline)) geterror(struct mmcdevice *ctx) { //if(ctx->error == 0x4) return -1; //else return 0; - return (ctx->error << 29) >> 31; + return (int)((ctx->error << 29) >> 31); } -void __attribute__((noinline)) inittarget(struct mmcdevice *ctx) +static void __attribute__((noinline)) inittarget(struct mmcdevice *ctx) { sdmmc_mask16(REG_SDPORTSEL,0x3,(u16)ctx->devicenumber); setckl(ctx->clk); @@ -41,7 +41,7 @@ void __attribute__((noinline)) inittarget(struct mmcdevice *ctx) } -void __attribute__((noinline)) sdmmc_send_command(struct mmcdevice *ctx, u32 cmd, u32 args) +static void __attribute__((noinline)) sdmmc_send_command(struct mmcdevice *ctx, u32 cmd, u32 args) { bool getSDRESP = (cmd << 15) >> 31; u16 flags = (cmd << 15) >> 31; @@ -72,8 +72,7 @@ void __attribute__((noinline)) sdmmc_send_command(struct mmcdevice *ctx, u32 cmd sdmmc_write16(REG_SDCMD,cmd &0xFFFF); u32 size = ctx->size; - u16 *dataPtr = (u16*)ctx->data; - u32 *dataPtr32 = (u32*)ctx->data; + u8 *dataPtr = ctx->data; bool useBuf = ( NULL != dataPtr ); bool useBuf32 = (useBuf && (0 == (3 & ((u32)dataPtr)))); @@ -88,12 +87,20 @@ void __attribute__((noinline)) sdmmc_send_command(struct mmcdevice *ctx, u32 cmd if (size > 0x1FF) { #ifdef DATA32_SUPPORT if (useBuf32) { - for(int i = 0; i<0x200; i+=4) - *dataPtr32++ = sdmmc_read32(REG_SDFIFO32); + for(int i = 0; i<0x200; i+=4) { + u32 data = sdmmc_read32(REG_SDFIFO32); + *dataPtr++ = data; + *dataPtr++ = data >> 8; + *dataPtr++ = data >> 16; + *dataPtr++ = data >> 24; + } } else { #endif - for(int i = 0; i<0x200; i+=2) - *dataPtr++ = sdmmc_read16(REG_SDFIFO); + for(int i = 0; i<0x200; i+=2) { + u16 data = sdmmc_read16(REG_SDFIFO); + *dataPtr++ = data; + *dataPtr++ = data >> 8; + } #ifdef DATA32_SUPPORT } #endif @@ -108,11 +115,20 @@ void __attribute__((noinline)) sdmmc_send_command(struct mmcdevice *ctx, u32 cmd //sdmmc_write16(REG_SDSTATUS1,~TMIO_STAT1_TXRQ); if (size > 0x1FF) { #ifdef DATA32_SUPPORT - for (int i = 0; i<0x200; i+=4) - sdmmc_write32(REG_SDFIFO32,*dataPtr32++); + for (int i = 0; i<0x200; i+=4) { + u32 data = *dataPtr++; + data |= *dataPtr++ << 8; + data |= *dataPtr++ << 16; + data |= *dataPtr++ << 24; + sdmmc_write32(REG_SDFIFO32,data); + } #else - for (int i = 0; i<0x200; i+=2) - sdmmc_write16(REG_SDFIFO,*dataPtr++); + for (int i = 0; i<0x200; i+=2) { + u16 data = *dataPtr++; + data |= *dataPtr++ << 8; + sdmmc_write16(REG_SDFIFO,data); + + } #endif size -= 0x200; } @@ -140,14 +156,14 @@ void __attribute__((noinline)) sdmmc_send_command(struct mmcdevice *ctx, u32 cmd sdmmc_write16(REG_SDSTATUS1,0); if (getSDRESP != 0) { - ctx->ret[0] = sdmmc_read16(REG_SDRESP0) | (sdmmc_read16(REG_SDRESP1) << 16); - ctx->ret[1] = sdmmc_read16(REG_SDRESP2) | (sdmmc_read16(REG_SDRESP3) << 16); - ctx->ret[2] = sdmmc_read16(REG_SDRESP4) | (sdmmc_read16(REG_SDRESP5) << 16); - ctx->ret[3] = sdmmc_read16(REG_SDRESP6) | (sdmmc_read16(REG_SDRESP7) << 16); + ctx->ret[0] = (u32)sdmmc_read16(REG_SDRESP0) | ((u32)sdmmc_read16(REG_SDRESP1) << 16); + ctx->ret[1] = (u32)sdmmc_read16(REG_SDRESP2) | ((u32)sdmmc_read16(REG_SDRESP3) << 16); + ctx->ret[2] = (u32)sdmmc_read16(REG_SDRESP4) | ((u32)sdmmc_read16(REG_SDRESP5) << 16); + ctx->ret[3] = (u32)sdmmc_read16(REG_SDRESP6) | ((u32)sdmmc_read16(REG_SDRESP7) << 16); } } -int __attribute__((noinline)) sdmmc_sdcard_writesectors(u32 sector_no, u32 numsectors, u8 *in) +int __attribute__((noinline)) sdmmc_sdcard_writesectors(u32 sector_no, u32 numsectors, const u8 *in) { if (handleSD.isSDHC == 0) sector_no <<= 9; @@ -206,7 +222,7 @@ int __attribute__((noinline)) sdmmc_nand_readsectors(u32 sector_no, u32 numsecto return geterror(&handleNAND); } -int __attribute__((noinline)) sdmmc_nand_writesectors(u32 sector_no, u32 numsectors, u8 *in) //experimental +int __attribute__((noinline)) sdmmc_nand_writesectors(u32 sector_no, u32 numsectors, const u8 *in) //experimental { if (handleNAND.isSDHC == 0) sector_no <<= 9; @@ -226,7 +242,7 @@ int __attribute__((noinline)) sdmmc_nand_writesectors(u32 sector_no, u32 numsect return geterror(&handleNAND); } -u32 calcSDSize(u8* csd, int type) +static u32 calcSDSize(u8* csd, int type) { u32 result = 0; u8 temp = csd[0xE]; @@ -238,14 +254,14 @@ u32 calcSDSize(u8* csd, int type) break; case 0: { - u32 temp = (csd[0x7] << 0x2 | csd[0x8] << 0xA | csd[0x6] >> 0x6 | (csd[0x9] & 0xF) << 0x10) & 0xFFF; - u32 temp2 = temp * (1 << (csd[0x9] & 0xF)); - u32 retval = temp2 * (1 << (((csd[0x4] >> 7 | csd[0x5] << 1) & 7) + 2)); + u32 temp2 = (csd[0x7] << 0x2 | csd[0x8] << 0xA | csd[0x6] >> 0x6 | (csd[0x9] & 0xF) << 0x10) & 0xFFF; + u32 temp3 = temp2 * (1u << (csd[0x9] & 0xF)); + u32 retval = temp3 * (1u << (((csd[0x4] >> 7 | csd[0x5] << 1) & 7) + 2)); result = retval >> 9; break; } case 1: - result = (((csd[0x7] & 0x3F) << 0x10 | csd[0x6] << 8 | csd[0x5]) + 1) << 0xA; + result = (u32)(((csd[0x7] & 0x3F) << 0x10 | csd[0x6] << 8 | csd[0x5]) + 1) << 0xA; break; default: result = 0; @@ -255,7 +271,7 @@ u32 calcSDSize(u8* csd, int type) return result; } -void InitSD() +static void InitSD() { //NAND handleNAND.isSDHC = 0; @@ -453,9 +469,10 @@ int SD_Init() return 0; } -void sdmmc_sdcard_init() +int sdmmc_sdcard_init() { InitSD(); - u32 nand_res = Nand_Init(); - u32 sd_res = SD_Init(); + int nand_res = Nand_Init(); + int sd_res = SD_Init(); + return nand_res | sd_res; } diff --git a/source/fatfs/sdmmc.h b/source/fatfs/sdmmc.h index bc067cb..9578503 100644 --- a/source/fatfs/sdmmc.h +++ b/source/fatfs/sdmmc.h @@ -125,14 +125,14 @@ void sdmmc_sdcard_writesector(uint32_t sector_no, void *in); void sdmmc_sdcard_writesectors(uint32_t sector_no, uint32_t numsectors, void *in); void sdmmc_blktransferinit();*/ -void sdmmc_sdcard_init(); +int sdmmc_sdcard_init(); int sdmmc_sdcard_readsector(u32 sector_no, u8 *out); int sdmmc_sdcard_readsectors(u32 sector_no, u32 numsectors, u8 *out); -int sdmmc_sdcard_writesector(u32 sector_no, u8 *in); -int sdmmc_sdcard_writesectors(u32 sector_no, u32 numsectors, u8 *in); +int sdmmc_sdcard_writesector(u32 sector_no, const u8 *in); +int sdmmc_sdcard_writesectors(u32 sector_no, u32 numsectors, const u8 *in); int sdmmc_nand_readsectors(u32 sector_no, u32 numsectors, u8 *out); -int sdmmc_nand_writesectors(u32 sector_no, u32 numsectors, u8 *in); +int sdmmc_nand_writesectors(u32 sector_no, u32 numsectors, const u8 *in); mmcdevice *getMMCDevice(int drive); diff --git a/source/gamecart/command_ctr.c b/source/gamecart/command_ctr.c index 517c679..020fbe7 100644 --- a/source/gamecart/command_ctr.c +++ b/source/gamecart/command_ctr.c @@ -9,7 +9,7 @@ static int read_count = 0; -void CTR_CmdC5() +static inline void CTR_CmdC5() { static const u32 c5_cmd[4] = { 0xC5000000, 0x00000000, 0x00000000, 0x00000000 }; CTR_SendCommand(c5_cmd, 0, 1, 0x100002C, NULL); diff --git a/source/gamecart/command_ntr.c b/source/gamecart/command_ntr.c index f0f66f0..e63ae22 100644 --- a/source/gamecart/command_ntr.c +++ b/source/gamecart/command_ntr.c @@ -12,7 +12,7 @@ void NTR_CmdReset(void) NTR_SendCommand(reset_cmd, 0x2000, NTRCARD_CLK_SLOW | NTRCARD_DELAY1(0x1FFF) | NTRCARD_DELAY2(0x18), NULL); } -int NTR_CmdGetCartId(void) +u32 NTR_CmdGetCartId(void) { u32 id; static const u32 getid_cmd[2] = { 0x90000000, 0x00000000 }; diff --git a/source/gamecart/command_ntr.h b/source/gamecart/command_ntr.h index 7c5459f..1e7162a 100644 --- a/source/gamecart/command_ntr.h +++ b/source/gamecart/command_ntr.h @@ -7,5 +7,5 @@ #include "common.h" void NTR_CmdReset(void); -int NTR_CmdGetCartId(void); +u32 NTR_CmdGetCartId(void); void NTR_CmdEnter16ByteMode(void); diff --git a/source/gamecart/protocol.c b/source/gamecart/protocol.c index 86b1147..ee36292 100644 --- a/source/gamecart/protocol.c +++ b/source/gamecart/protocol.c @@ -19,10 +19,10 @@ extern u8* bottomScreen; -u32 CartID = -1; +u32 CartID = 0xFFFFFFFFu; u32 CartType = 0; -static int A0_Response = -1; +static u32 A0_Response = 0xFFFFFFFFu; static u32 rand1 = 0; static u32 rand2 = 0; diff --git a/source/gamecart/protocol.h b/source/gamecart/protocol.h index 1f43ba1..75418aa 100644 --- a/source/gamecart/protocol.h +++ b/source/gamecart/protocol.h @@ -9,12 +9,12 @@ #define REG_CARDCONF2 (*(vu8*)0x10000010) //REG_AUXSPICNT -#define CARD_ENABLE (1<<15) -#define CARD_SPI_ENABLE (1<<13) -#define CARD_SPI_BUSY (1<<7) -#define CARD_SPI_HOLD (1<<6) +#define CARD_ENABLE (1u<<15) +#define CARD_SPI_ENABLE (1u<<13) +#define CARD_SPI_BUSY (1u<<7) +#define CARD_SPI_HOLD (1u<<6) -#define LATENCY 0x822C +#define LATENCY 0x822Cu u32 BSWAP32(u32 val); diff --git a/source/gamecart/protocol_ctr.c b/source/gamecart/protocol_ctr.c index 3fdea64..9799bde 100644 --- a/source/gamecart/protocol_ctr.c +++ b/source/gamecart/protocol_ctr.c @@ -74,6 +74,8 @@ void CTR_SendCommand(const u32 command[4], u32 pageSize, u32 blocks, u32 latency transferLength = 4096; pageParam = CTRCARD_PAGESIZE_4K; break; + default: + break; //Defaults already set } REG_CTRCARDBLKCNT = blocks - 1; diff --git a/source/gamecart/protocol_ctr.h b/source/gamecart/protocol_ctr.h index 67c902c..cba469e 100644 --- a/source/gamecart/protocol_ctr.h +++ b/source/gamecart/protocol_ctr.h @@ -14,27 +14,27 @@ #define REG_CTRCARDFIFO (*(vu32*)0x10004030) #define CTRCARD_PAGESIZE_0 (0<<16) -#define CTRCARD_PAGESIZE_4 (1<<16) -#define CTRCARD_PAGESIZE_16 (2<<16) -#define CTRCARD_PAGESIZE_64 (3<<16) -#define CTRCARD_PAGESIZE_512 (4<<16) -#define CTRCARD_PAGESIZE_1K (5<<16) -#define CTRCARD_PAGESIZE_2K (6<<16) -#define CTRCARD_PAGESIZE_4K (7<<16) -#define CTRCARD_PAGESIZE_16K (8<<16) -#define CTRCARD_PAGESIZE_64K (9<<16) +#define CTRCARD_PAGESIZE_4 (1u<<16) +#define CTRCARD_PAGESIZE_16 (2u<<16) +#define CTRCARD_PAGESIZE_64 (3u<<16) +#define CTRCARD_PAGESIZE_512 (4u<<16) +#define CTRCARD_PAGESIZE_1K (5u<<16) +#define CTRCARD_PAGESIZE_2K (6u<<16) +#define CTRCARD_PAGESIZE_4K (7u<<16) +#define CTRCARD_PAGESIZE_16K (8u<<16) +#define CTRCARD_PAGESIZE_64K (9u<<16) -#define CTRCARD_CRC_ERROR (1<<4) -#define CTRCARD_ACTIVATE (1<<31) // when writing, get the ball rolling -#define CTRCARD_IE (1<<30) // Interrupt enable -#define CTRCARD_WR (1<<29) // Card write enable -#define CTRCARD_nRESET (1<<28) // value on the /reset pin (1 = high out, not a reset state, 0 = low out = in reset) -#define CTRCARD_BLK_SIZE(n) (((n)&0xF)<<16) // Transfer block size +#define CTRCARD_CRC_ERROR (1u<<4) +#define CTRCARD_ACTIVATE (1u<<31) // when writing, get the ball rolling +#define CTRCARD_IE (1u<<30) // Interrupt enable +#define CTRCARD_WR (1u<<29) // Card write enable +#define CTRCARD_nRESET (1u<<28) // value on the /reset pin (1 = high out, not a reset state, 0 = low out = in reset) +#define CTRCARD_BLK_SIZE(n) (((n)&0xFu)<<16) // Transfer block size -#define CTRCARD_BUSY (1<<31) // when reading, still expecting incomming data? -#define CTRCARD_DATA_READY (1<<27) // when reading, REG_CTRCARDFIFO has another word of data and is good to go +#define CTRCARD_BUSY (1u<<31) // when reading, still expecting incomming data? +#define CTRCARD_DATA_READY (1u<<27) // when reading, REG_CTRCARDFIFO has another word of data and is good to go -#define CTRKEY_PARAM 0x1000000 +#define CTRKEY_PARAM 0x1000000u void CTR_SetSecKey(u32 value); void CTR_SetSecSeed(const u32* seed, bool flag); diff --git a/source/gamecart/protocol_ntr.c b/source/gamecart/protocol_ntr.c index 0781fdf..9888307 100644 --- a/source/gamecart/protocol_ntr.c +++ b/source/gamecart/protocol_ntr.c @@ -44,6 +44,8 @@ void NTR_SendCommand(const u32 command[2], u32 pageSize, u32 latency, void* buff transferLength = 8192; pageParam = NTRCARD_PAGESIZE_8K; break; + default: + break; //Using 4K pagesize and transfer length by default } // go diff --git a/source/gamecart/protocol_ntr.h b/source/gamecart/protocol_ntr.h index 2bb3113..069ed61 100644 --- a/source/gamecart/protocol_ntr.h +++ b/source/gamecart/protocol_ntr.h @@ -17,48 +17,48 @@ #define REG_NTRCARDFIFO (*(vu32*)0x1016401C) #define NTRCARD_PAGESIZE_0 (0<<24) -#define NTRCARD_PAGESIZE_4 (7<<24) -#define NTRCARD_PAGESIZE_512 (1<<24) -#define NTRCARD_PAGESIZE_1K (2<<24) -#define NTRCARD_PAGESIZE_2K (3<<24) -#define NTRCARD_PAGESIZE_4K (4<<24) -#define NTRCARD_PAGESIZE_8K (5<<24) -#define NTRCARD_PAGESIZE_16K (6<<24) +#define NTRCARD_PAGESIZE_4 (7u<<24) +#define NTRCARD_PAGESIZE_512 (1u<<24) +#define NTRCARD_PAGESIZE_1K (2u<<24) +#define NTRCARD_PAGESIZE_2K (3u<<24) +#define NTRCARD_PAGESIZE_4K (4u<<24) +#define NTRCARD_PAGESIZE_8K (5u<<24) +#define NTRCARD_PAGESIZE_16K (6u<<24) -#define NTRCARD_ACTIVATE (1<<31) // when writing, get the ball rolling -#define NTRCARD_WR (1<<30) // Card write enable -#define NTRCARD_nRESET (1<<29) // value on the /reset pin (1 = high out, not a reset state, 0 = low out = in reset) -#define NTRCARD_SEC_LARGE (1<<28) // Use "other" secure area mode, which tranfers blocks of 0x1000 bytes at a time -#define NTRCARD_CLK_SLOW (1<<27) // Transfer clock rate (0 = 6.7MHz, 1 = 4.2MHz) -#define NTRCARD_BLK_SIZE(n) (((n)&0x7)<<24) // Transfer block size, (0 = None, 1..6 = (0x100 << n) bytes, 7 = 4 bytes) -#define NTRCARD_SEC_CMD (1<<22) // The command transfer will be hardware encrypted (KEY2) -#define NTRCARD_DELAY2(n) (((n)&0x3F)<<16) // Transfer delay length part 2 -#define NTRCARD_SEC_SEED (1<<15) // Apply encryption (KEY2) seed to hardware registers -#define NTRCARD_SEC_EN (1<<14) // Security enable -#define NTRCARD_SEC_DAT (1<<13) // The data transfer will be hardware encrypted (KEY2) -#define NTRCARD_DELAY1(n) ((n)&0x1FFF) // Transfer delay length part 1 +#define NTRCARD_ACTIVATE (1u<<31) // when writing, get the ball rolling +#define NTRCARD_WR (1u<<30) // Card write enable +#define NTRCARD_nRESET (1u<<29) // value on the /reset pin (1 = high out, not a reset state, 0 = low out = in reset) +#define NTRCARD_SEC_LARGE (1u<<28) // Use "other" secure area mode, which tranfers blocks of 0x1000 bytes at a time +#define NTRCARD_CLK_SLOW (1u<<27) // Transfer clock rate (0 = 6.7MHz, 1 = 4.2MHz) +#define NTRCARD_BLK_SIZE(n) (((n)&0x7u)<<24) // Transfer block size, (0 = None, 1..6 = (0x100 << n) bytes, 7 = 4 bytes) +#define NTRCARD_SEC_CMD (1u<<22) // The command transfer will be hardware encrypted (KEY2) +#define NTRCARD_DELAY2(n) (((n)&0x3Fu)<<16) // Transfer delay length part 2 +#define NTRCARD_SEC_SEED (1u<<15) // Apply encryption (KEY2) seed to hardware registers +#define NTRCARD_SEC_EN (1u<<14) // Security enable +#define NTRCARD_SEC_DAT (1u<<13) // The data transfer will be hardware encrypted (KEY2) +#define NTRCARD_DELAY1(n) ((n)&0x1FFFu) // Transfer delay length part 1 // 3 bits in b10..b8 indicate something // read bits -#define NTRCARD_BUSY (1<<31) // when reading, still expecting incomming data? -#define NTRCARD_DATA_READY (1<<23) // when reading, REG_NTRCARDFIFO has another word of data and is good to go +#define NTRCARD_BUSY (1u<<31) // when reading, still expecting incomming data? +#define NTRCARD_DATA_READY (1u<<23) // when reading, REG_NTRCARDFIFO has another word of data and is good to go // Card commands -#define NTRCARD_CMD_DUMMY 0x9F -#define NTRCARD_CMD_HEADER_READ 0x00 -#define NTRCARD_CMD_HEADER_CHIPID 0x90 -#define NTRCARD_CMD_ACTIVATE_BF 0x3C // Go into blowfish (KEY1) encryption mode -#define NTRCARD_CMD_ACTIVATE_SEC 0x40 // Go into hardware (KEY2) encryption mode -#define NTRCARD_CMD_SECURE_CHIPID 0x10 -#define NTRCARD_CMD_SECURE_READ 0x20 -#define NTRCARD_CMD_DISABLE_SEC 0x60 // Leave hardware (KEY2) encryption mode -#define NTRCARD_CMD_DATA_MODE 0xA0 -#define NTRCARD_CMD_DATA_READ 0xB7 -#define NTRCARD_CMD_DATA_CHIPID 0xB8 +#define NTRCARD_CMD_DUMMY 0x9Fu +#define NTRCARD_CMD_HEADER_READ 0x00u +#define NTRCARD_CMD_HEADER_CHIPID 0x90u +#define NTRCARD_CMD_ACTIVATE_BF 0x3Cu // Go into blowfish (KEY1) encryption mode +#define NTRCARD_CMD_ACTIVATE_SEC 0x40u // Go into hardware (KEY2) encryption mode +#define NTRCARD_CMD_SECURE_CHIPID 0x10u +#define NTRCARD_CMD_SECURE_READ 0x20u +#define NTRCARD_CMD_DISABLE_SEC 0x60u // Leave hardware (KEY2) encryption mode +#define NTRCARD_CMD_DATA_MODE 0xA0u +#define NTRCARD_CMD_DATA_READ 0xB7u +#define NTRCARD_CMD_DATA_CHIPID 0xB8u -#define NTRCARD_CR1_ENABLE 0x8000 -#define NTRCARD_CR1_IRQ 0x4000 +#define NTRCARD_CR1_ENABLE 0x8000u +#define NTRCARD_CR1_IRQ 0x4000u -#define NTRKEY_PARAM 0x3F1FFF +#define NTRKEY_PARAM 0x3F1FFFu void NTR_SendCommand(const u32 command[2], u32 pageSize, u32 latency, void* buffer); diff --git a/source/headers.h b/source/headers.h new file mode 100644 index 0000000..a350083 --- /dev/null +++ b/source/headers.h @@ -0,0 +1,75 @@ +#ifndef UNCART_HEADERS_H_ +#define UNCART_HEADERS_H_ + +#include "common.h" + +typedef enum +{ + MEDIA_6X_SAVE_CRYPTO = 1, + MEDIA_CARD_DEVICE = 3, + MEDIA_PLATFORM_INDEX = 4, + MEDIA_TYPE_INDEX = 5, + MEDIA_UNIT_SIZE = 6, + MEDIA_CARD_DEVICE_OLD = 7 +} NcsdFlagIndex; + +typedef struct +{ + u32 offset; + u32 size; +} partition_offsetsize; + +typedef struct +{ + u8 sha256[0x100]; + u8 magic[4]; + u32 media_size; + u8 title_id[8]; + u8 partitions_fs_type[8]; + u8 partitions_crypto_type[8]; + partition_offsetsize offsetsize_table[8]; + u8 exheader_hash[0x20]; + u8 additional_header_size[0x4]; + u8 sector_zero_offset[0x4]; + u8 partition_flags[8]; + u8 partition_id_table[8][8]; + u8 reserved[0x30]; +} NCSD_HEADER; + +typedef struct +{ + u8 sha256[0x100]; + u8 magic[4]; + u32 content_size; + u8 title_id[8]; + u8 maker_code[2]; + u8 version[2]; + u8 reserved_0[4]; + u8 program_id[8]; + u8 temp_flag; + u8 reserved_1[0xF]; + u8 logo_sha_256_hash[0x20]; + u8 product_code[0x10]; + u8 extended_header_sha_256_hash[0x20]; + u8 extended_header_size[4]; + u8 reserved_2[4]; + u8 flags[8]; + u8 plain_region_offset[4]; + u8 plain_region_size[4]; + u8 logo_region_offset[4]; + u8 logo_region_size[4]; + u8 exefs_offset[4]; + u8 exefs_size[4]; + u8 exefs_hash_size[4]; + u8 reserved_4[4]; + u8 romfs_offset[4]; + u8 romfs_size[4]; + u8 romfs_hash_size[4]; + u8 reserved_5[4]; + u8 exefs_sha_256_hash[0x20]; + u8 romfs_sha_256_hash[0x20]; +} __attribute__((__packed__)) +NCCH_HEADER; + +#endif//UNCART_HEADERS_H_ + diff --git a/source/i2c.c b/source/i2c.c index cd4d597..0e34042 100644 --- a/source/i2c.c +++ b/source/i2c.c @@ -3,7 +3,7 @@ //----------------------------------------------------------------------------- -static const struct { u8 bus_id, reg_addr } dev_data[] = { +static const struct { u8 bus_id, reg_addr; } dev_data[] = { {0, 0x4A}, {0, 0x7A}, {0, 0x78}, {1, 0x4A}, {1, 0x78}, {1, 0x2C}, {1, 0x2E}, {1, 0x40}, {1, 0x44}, @@ -11,35 +11,35 @@ static const struct { u8 bus_id, reg_addr } dev_data[] = { {2, 0xA4}, {2, 0x9A}, {2, 0xA0}, }; -const inline u8 i2cGetDeviceBusId(u8 device_id) { +inline u8 i2cGetDeviceBusId(u8 device_id) { return dev_data[device_id].bus_id; } -const inline u8 i2cGetDeviceRegAddr(u8 device_id) { +inline u8 i2cGetDeviceRegAddr(u8 device_id) { return dev_data[device_id].reg_addr; } //----------------------------------------------------------------------------- -static vu8* const reg_data_addrs[] = { +static vu8* reg_data_addrs[] = { (vu8*)(I2C1_REG_OFF + I2C_REG_DATA), (vu8*)(I2C2_REG_OFF + I2C_REG_DATA), (vu8*)(I2C3_REG_OFF + I2C_REG_DATA), }; -inline vu8* const i2cGetDataReg(u8 bus_id) { +inline vu8* i2cGetDataReg(u8 bus_id) { return reg_data_addrs[bus_id]; } //----------------------------------------------------------------------------- -static vu8* const reg_cnt_addrs[] = { +static vu8* reg_cnt_addrs[] = { (vu8*)(I2C1_REG_OFF + I2C_REG_CNT), (vu8*)(I2C2_REG_OFF + I2C_REG_CNT), (vu8*)(I2C3_REG_OFF + I2C_REG_CNT), }; -inline vu8* const i2cGetCntReg(u8 bus_id) { +inline vu8* i2cGetCntReg(u8 bus_id) { return reg_cnt_addrs[bus_id]; } @@ -114,7 +114,7 @@ bool i2cReadRegisterBuffer(unsigned int dev_id, int reg, u8* buffer, size_t buf_ } if (buf_size != 1) { - for (int i = 0; i < buf_size - 1; i++) { + for (size_t i = 0; i < buf_size - 1; i++) { i2cWaitBusy(bus_id); *i2cGetCntReg(bus_id) = 0xF0; i2cWaitBusy(bus_id); diff --git a/source/i2c.h b/source/i2c.h index f8511f6..4adeb1b 100644 --- a/source/i2c.h +++ b/source/i2c.h @@ -15,11 +15,11 @@ #define I2C_DEV_GYRO 10 #define I2C_DEV_IR 13 -const u8 i2cGetDeviceBusId(u8 device_id); -const u8 i2cGetDeviceRegAddr(u8 device_id); +u8 i2cGetDeviceBusId(u8 device_id); +u8 i2cGetDeviceRegAddr(u8 device_id); -vu8* const i2cGetDataReg(u8 bus_id); -vu8* const i2cGetCntReg(u8 bus_id); +vu8* i2cGetDataReg(u8 bus_id); +vu8* i2cGetCntReg(u8 bus_id); void i2cWaitBusy(u8 bus_id); bool i2cGetResult(u8 bus_id); @@ -33,3 +33,4 @@ u8 i2cReadRegister(u8 dev_id, u8 reg); bool i2cWriteRegister(u8 dev_id, u8 reg, u8 data); bool i2cReadRegisterBuffer(unsigned int dev_id, int reg, u8* buffer, size_t buf_size); + diff --git a/source/main.c b/source/main.c index d7f3db7..82b1bb3 100644 --- a/source/main.c +++ b/source/main.c @@ -1,13 +1,14 @@ -#include -#include -#include - #include "draw.h" #include "hid.h" #include "i2c.h" #include "fatfs/ff.h" #include "gamecart/protocol.h" #include "gamecart/command_ctr.h" +#include "headers.h" +#include "i2c.h" + +#include +#include extern s32 CartID; extern s32 CartID2; @@ -17,7 +18,6 @@ static FATFS fs; static FIL file; static void ClearTop(void) { - ClearScreen(TOP_SCREEN0, RGB(255, 255, 255)); ClearScreen(TOP_SCREEN1, RGB(255, 255, 255)); current_y = 0; } @@ -27,7 +27,7 @@ static void wait_key(void) { InputWait(); } -void Reboot() +static void Reboot() { i2cWriteRegister(I2C_DEV_MCU, 0x20, 1 << 2); while(true); @@ -41,8 +41,8 @@ struct Context { u32 media_unit; }; -int dump_cart_region(u32 start_sector, u32 end_sector, FIL* output_file, struct Context* ctx) { - const u32 read_size = 1 * 1024 * 1024 / ctx->media_unit; // 1MB +static int dump_cart_region(u32 start_sector, u32 end_sector, FIL* output_file, struct Context* ctx) { + u32 read_size = 1u * 1024 * 1024 / ctx->media_unit; // 1MiB default // Dump remaining data u32 current_sector = start_sector; @@ -54,6 +54,12 @@ int dump_cart_region(u32 start_sector, u32 end_sector, FIL* output_file, struct while (read_ptr < ctx->buffer + ctx->buffer_size && current_sector < end_sector) { Cart_Dummy(); Cart_Dummy(); + + //If there is less data to read than the curren read_size, fix it + if (end_sector - current_sector < read_size) + { + read_size = end_sector - current_sector; + } CTR_CmdReadData(current_sector, ctx->media_unit, read_size, read_ptr); read_ptr += ctx->media_unit * read_size; current_sector += read_size; @@ -62,8 +68,8 @@ int dump_cart_region(u32 start_sector, u32 end_sector, FIL* output_file, struct u8* write_ptr = ctx->buffer; while (write_ptr < read_ptr) { unsigned int bytes_written = 0; - f_write(output_file, write_ptr, read_ptr - write_ptr, &bytes_written); - Debug("Wrote 0x%x bytes, e.g. %08x", bytes_written, *(u32*)write_ptr); + f_write(output_file, write_ptr, (size_t)(read_ptr - write_ptr), &bytes_written); + Debug("Wrote 0x%x bytes...", bytes_written); if (bytes_written == 0) { Debug("Writing failed! :( SD full?"); @@ -82,16 +88,20 @@ int main() { restart_program: // Setup boring stuff - clear the screen, initialize SD output, etc... ClearTop(); - Debug("ROM dump tool v0.2"); + + Debug("Uncart: ROM dump tool v0.2"); Debug("Insert your game cart now."); wait_key(); // Arbitrary target buffer // TODO: This should be done in a nicer way ;) - u8* target = (u8*)0x22000000; + u32* target = (u32*)0x22000000; + NCSD_HEADER *ncsdHeader = (NCSD_HEADER*)target; u32 target_buf_size = 16u * 1024u * 1024u; // 16MB - u8* header = (u8*)0x23000000; memset(target, 0, target_buf_size); // Clear our buffer + + u32* ncchHeaderData = (u32*)0x23000000; + NCCH_HEADER *ncchHeader = (NCCH_HEADER*)ncchHeaderData; *(vu32*)0x10000020 = 0; // InitFS stuff *(vu32*)0x10000020 = 0x340; // InitFS stuff @@ -100,45 +110,62 @@ restart_program: Cart_Init(); Debug("Cart id is %08x", Cart_GetID()); - CTR_CmdReadHeader(header); - Debug("Done reading header: %08X :)...", *(u32*)&header[0x100]); + Debug("Reading NCCH header..."); + CTR_CmdReadHeader(ncchHeader); + Debug("Done reading NCCH header."); + + if (strncmp((const char*)(ncchHeader->magic), "NCCH", 4)) + { + Debug("NCCH magic not found in header!!!"); + Debug("Press A to continue anyway."); + if (!(InputWait() & BUTTON_A)) + goto restart_prompt; + } - // TODO: Check first header bytes for "NCCH" or other magic words u32 sec_keys[4]; - Cart_Secure_Init((u32*)header,sec_keys); - - const u32 mediaUnit = 0x200; // TODO: Read from cart + Cart_Secure_Init(ncchHeaderData, sec_keys); + // Guess 0x200 first for the media size. this will be set correctly once the cart header is read // Read out the header 0x0000-0x1000 Cart_Dummy(); - CTR_CmdReadData(0, mediaUnit, 0x1000 / mediaUnit, target); - - u32 NCSD_magic = *(u32*)(&target[0x100]); - u32 cartSize = *(u32*)(&target[0x104]); - Debug("Cart size: %llu MB", (u64)cartSize * (u64)mediaUnit / 1024ull / 1024ull); - if (NCSD_magic != 0x4453434E) { + Debug("Reading NCSD header..."); + CTR_CmdReadData(0, 0x200, 0x1000 / 0x200, target); + Debug("Done reading NCSD header."); + + if (strncmp((const char*)(ncsdHeader->magic), "NCSD", 4)) { Debug("NCSD magic not found in header!!!"); Debug("Press A to continue anyway."); if (!(InputWait() & BUTTON_A)) goto restart_prompt; } + const u32 mediaUnit = 0x200 * (1u << ncsdHeader->partition_flags[MEDIA_UNIT_SIZE]); //Correctly set the media unit size + + //Calculate the actual size by counting the adding the size of each partition, plus the initial offset + //size is in media units + u32 cartSize = ncsdHeader->offsetsize_table[0].offset; + for(int i = 0; i < 8; i++){ + cartSize += ncsdHeader->offsetsize_table[i].size; + } + + Debug("Cart data size: %llu MB", (u64)cartSize * (u64)mediaUnit / 1024ull / 1024ull); + struct Context context = { - .buffer = target, + .buffer = (u8*)target, .buffer_size = target_buf_size, .cart_size = cartSize, .media_unit = mediaUnit, }; // Maximum number of blocks in a single file - u32 file_max_blocks = 2u * 1024u * 1024u * 1024u / mediaUnit; // 2GB + u32 file_max_blocks = 0xFFFFFFFFu / mediaUnit; // 4GiB - 1 u32 current_part = 0; while (current_part * file_max_blocks < cartSize) { // Create output file char filename_buf[32]; char extension_digit = cartSize <= file_max_blocks ? 's' : '0' + current_part; - snprintf(filename_buf, sizeof(filename_buf), "/%.16s.3d%c", &header[0x150], extension_digit); + snprintf(filename_buf, sizeof(filename_buf), "/%.16s.3d%c", ncchHeader->product_code, extension_digit); Debug("Writing to file: \"%s\"", filename_buf); Debug("Change the SD card now and/or press a key."); Debug("(Or SELECT to cancel)"); @@ -172,8 +199,8 @@ restart_program: f_lseek(&file, 0x1000); unsigned int written = 0; // Fill the 0x1200-0x4000 unused area with 0xFF instead of random garbage. - memset(header + 0x200, 0xFF, 0x3000 - 0x200); - f_write(&file, header, 0x3000, &written); + memset((u8*)ncchHeaderData + 0x200, 0xFF, 0x3000 - 0x200); + f_write(&file, ncchHeader, 0x3000, &written); } Debug("Done!"); diff --git a/source/start.s b/source/start.s index cfbfba4..d0e30f7 100644 --- a/source/start.s +++ b/source/start.s @@ -90,6 +90,20 @@ _init: push {r0-r12, lr} bl _enable_caches + + @@ Initialize .bss + @ ldr r0, =__bss_start__ + @ ldr r1, =__bss_end__ + @ ldr r2, =__bss_end__ + @ sbc r2, r0 + @ eor r4, r4 + + +@zero_bss: +@ strb r4, [r0], #1 +@ subs r2, r2, #1 +@ bne zero_bss + bl main mrc p15, 0, r4, c1, c0, 0 From 2c3870dbadae5c263225f4c2faa274393e0130de Mon Sep 17 00:00:00 2001 From: Gabriel Marcano Date: Tue, 7 Jun 2016 02:34:07 -0400 Subject: [PATCH 2/6] Memory management cleaning, dump options -newlib handles allocations, in the default case, by starting to allocate memory right after the end of the program in memory, and will continue to allocate memory as requested until it hits the stack. As a result, it is safe to use memory allocation function to get memory for usage. Changed some of the memory management in the application to use memalign (memory needs to be aligned to at least 16 bits if sdmmc.c is to work, preferably 32 bits). -Added an option for the user to either dump the full ROM, or just the partitions. --- Makefile | 5 ++- source/main.c | 82 +++++++++++++++++++++++++++++++++++--------------- source/start.s | 20 +++++------- 3 files changed, 70 insertions(+), 37 deletions(-) diff --git a/Makefile b/Makefile index 50ee857..51afdda 100644 --- a/Makefile +++ b/Makefile @@ -36,7 +36,10 @@ CFLAGS := -g -Wall -Wextra -Wpedantic -O2 -flto\ -ffast-math -std=c11\ $(ARCH) -CFLAGS += $(INCLUDE) -DARM9 -Werror-implicit-function-declaration -Wcast-align -Wcast-qual -Wdisabled-optimization -Wformat=2 -Winit-self -Wlogical-op -Wmissing-declarations -Wmissing-include-dirs -Wredundant-decls -Wshadow -Wsign-conversion -Wstrict-overflow=5 -Wswitch-default -Wundef -Wno-unused +CFLAGS += $(INCLUDE) -DARM9 -Werror-implicit-function-declaration -Wcast-align\ + -Wcast-qual -Wdisabled-optimization -Wformat=2 -Winit-self -Wlogical-op \ + -Wmissing-declarations -Wmissing-include-dirs -Wredundant-decls -Wshadow \ + -Wsign-conversion -Wstrict-overflow=5 -Wswitch-default -Wundef -Wno-unused CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions diff --git a/source/main.c b/source/main.c index 82b1bb3..a9800e4 100644 --- a/source/main.c +++ b/source/main.c @@ -9,6 +9,8 @@ #include #include +#include +#include //For memalign extern s32 CartID; extern s32 CartID2; @@ -54,9 +56,9 @@ static int dump_cart_region(u32 start_sector, u32 end_sector, FIL* output_file, while (read_ptr < ctx->buffer + ctx->buffer_size && current_sector < end_sector) { Cart_Dummy(); Cart_Dummy(); - - //If there is less data to read than the curren read_size, fix it - if (end_sector - current_sector < read_size) + + //If there is less data to read than the current read_size, fix it + if (end_sector - current_sector < read_size) { read_size = end_sector - current_sector; } @@ -84,27 +86,25 @@ static int dump_cart_region(u32 start_sector, u32 end_sector, FIL* output_file, } int main() { + // Arbitrary target buffer + // aligning to 32 bits in case other parts of the software assume alignment + const u32 target_buf_size = 16u * 1024u * 1024u; // 16MB + u32 * const target = memalign(32, target_buf_size); + + u32 * const ncchHeaderData = memalign(32, sizeof(NCCH_HEADER)); + NCCH_HEADER * const ncchHeader = (NCCH_HEADER*)ncchHeaderData; + + NCSD_HEADER * const ncsdHeader = (NCSD_HEADER*)target; restart_program: // Setup boring stuff - clear the screen, initialize SD output, etc... ClearTop(); - + Debug("Uncart: ROM dump tool v0.2"); Debug("Insert your game cart now."); wait_key(); - // Arbitrary target buffer - // TODO: This should be done in a nicer way ;) - u32* target = (u32*)0x22000000; - NCSD_HEADER *ncsdHeader = (NCSD_HEADER*)target; - u32 target_buf_size = 16u * 1024u * 1024u; // 16MB memset(target, 0, target_buf_size); // Clear our buffer - - u32* ncchHeaderData = (u32*)0x23000000; - NCCH_HEADER *ncchHeader = (NCCH_HEADER*)ncchHeaderData; - - *(vu32*)0x10000020 = 0; // InitFS stuff - *(vu32*)0x10000020 = 0x340; // InitFS stuff // ROM DUMPING CODE STARTS HERE @@ -114,6 +114,7 @@ restart_program: CTR_CmdReadHeader(ncchHeader); Debug("Done reading NCCH header."); + // Check that the NCCH header magic is there if (strncmp((const char*)(ncchHeader->magic), "NCCH", 4)) { Debug("NCCH magic not found in header!!!"); @@ -125,13 +126,14 @@ restart_program: u32 sec_keys[4]; Cart_Secure_Init(ncchHeaderData, sec_keys); - // Guess 0x200 first for the media size. this will be set correctly once the cart header is read + // Guess 0x200 first for the media size. this will be set correctly once the cart header is read // Read out the header 0x0000-0x1000 Cart_Dummy(); Debug("Reading NCSD header..."); CTR_CmdReadData(0, 0x200, 0x1000 / 0x200, target); Debug("Done reading NCSD header."); - + + // Check for NCSD magic if (strncmp((const char*)(ncsdHeader->magic), "NCSD", 4)) { Debug("NCSD magic not found in header!!!"); Debug("Press A to continue anyway."); @@ -139,16 +141,47 @@ restart_program: goto restart_prompt; } + Debug("Uncart can either dump the entire ROM (including"); + Debug("empty space), or a trimmed version based on the"); + Debug("size of the cart partitions."); + Debug(""); + + u32 input; + do + { + Debug("Press A to dump all of ROM, B for only the"); + Debug("trimmed version."); + input = InputWait(); + } + while (!(input & BUTTON_A) && !(input & BUTTON_B)); + + const u32 mediaUnit = 0x200 * (1u << ncsdHeader->partition_flags[MEDIA_UNIT_SIZE]); //Correctly set the media unit size //Calculate the actual size by counting the adding the size of each partition, plus the initial offset //size is in media units - u32 cartSize = ncsdHeader->offsetsize_table[0].offset; - for(int i = 0; i < 8; i++){ - cartSize += ncsdHeader->offsetsize_table[i].size; - } + u32 cartSize; + // Maximum number of blocks in a single file + u32 file_max_blocks; - Debug("Cart data size: %llu MB", (u64)cartSize * (u64)mediaUnit / 1024ull / 1024ull); + if (input & BUTTON_B) + { + cartSize = ncsdHeader->offsetsize_table[0].offset; + for(int i = 0; i < 8; i++){ + cartSize += ncsdHeader->offsetsize_table[i].size; + } + + Debug("Cart data size: %llu MB", (u64)cartSize * (u64)mediaUnit / 1024ull / 1024ull); + // Maximum number of blocks in a single file + file_max_blocks = 0xFFFFFFFFu / mediaUnit; // 4GiB - 513 + + } + else + { + cartSize = ncsdHeader->media_size; + // Maximum number of blocks in a single file + file_max_blocks = 0x80000000u / mediaUnit; // 2GiB + } struct Context context = { .buffer = (u8*)target, @@ -157,8 +190,6 @@ restart_program: .media_unit = mediaUnit, }; - // Maximum number of blocks in a single file - u32 file_max_blocks = 0xFFFFFFFFu / mediaUnit; // 4GiB - 1 u32 current_part = 0; while (current_part * file_max_blocks < cartSize) { @@ -221,6 +252,9 @@ restart_prompt: if (!(InputWait() & BUTTON_B)) goto restart_program; + free(ncchHeaderData); + free(target); + Reboot(); return 0; } diff --git a/source/start.s b/source/start.s index d0e30f7..264565b 100644 --- a/source/start.s +++ b/source/start.s @@ -86,23 +86,19 @@ _enable_caches: pop {r4-r5, pc} +_fix_sdmc_mount: + @ Fix mounting of SDMC + ldr r0, =0x10000020 + mov r1, #0x340 + str r1, [r0] + mov pc, lr + _init: push {r0-r12, lr} bl _enable_caches - - @@ Initialize .bss - @ ldr r0, =__bss_start__ - @ ldr r1, =__bss_end__ - @ ldr r2, =__bss_end__ - @ sbc r2, r0 - @ eor r4, r4 - -@zero_bss: -@ strb r4, [r0], #1 -@ subs r2, r2, #1 -@ bne zero_bss + bl _fix_sdmc_mount bl main From 4f1fd1a32bd9738749a620c0bf62e25476ebfff4 Mon Sep 17 00:00:00 2001 From: Gabriel Marcano Date: Mon, 7 Mar 2016 23:12:22 -0500 Subject: [PATCH 3/6] Added support to compile for both brahma and a9lh --- Makefile | 41 +++- source/aes.h | 108 ++++----- source/draw.h | 21 +- source/gamecart/protocol.c | 452 ++++++++++++++++++------------------- source/gamecart/protocol.h | 50 ++-- 5 files changed, 348 insertions(+), 324 deletions(-) diff --git a/Makefile b/Makefile index 51afdda..85d0331 100644 --- a/Makefile +++ b/Makefile @@ -36,19 +36,26 @@ CFLAGS := -g -Wall -Wextra -Wpedantic -O2 -flto\ -ffast-math -std=c11\ $(ARCH) -CFLAGS += $(INCLUDE) -DARM9 -Werror-implicit-function-declaration -Wcast-align\ - -Wcast-qual -Wdisabled-optimization -Wformat=2 -Winit-self -Wlogical-op \ - -Wmissing-declarations -Wmissing-include-dirs -Wredundant-decls -Wshadow \ - -Wsign-conversion -Wstrict-overflow=5 -Wswitch-default -Wundef -Wno-unused +CFLAGS += $(INCLUDE) -DARM9 -Werror-implicit-function-declaration -Wcast-align \ + -Wcast-qual -Wdisabled-optimization -Wformat=2 -Winit-self \ + -Wlogical-op -Wmissing-declarations -Wmissing-include-dirs \ + -Wredundant-decls -Wshadow -Wsign-conversion -Wstrict-overflow=5 \ + -Wswitch-default -Wundef -Wno-unused CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions ASFLAGS := -g $(ARCH) LDFLAGS = -nostartfiles -g --specs=../stub.specs $(ARCH) -Wl,-Map,$(TARGET).map -OCFLAGS=--set-section-flags .bss=alloc,load,contents +OCFLAGS= --set-section-flags .bss=alloc,load,contents LIBS := +ifeq ($(EXEC_METHOD),BRAHMA) + CFLAGS += -DBRAHMA #can't use CPPFLAGS because 3ds_rules doesn't use them +else ifeq ($(EXEC_METHOD), A9LH) + CFLAGS += -DA9LH #can't use CPPFLAGS because 3ds_rules doesn't use them +endif + #--------------------------------------------------------------------------------- # list of directories containing libraries, this must be the top level containing # include and lib @@ -97,20 +104,32 @@ export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \ export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) -.PHONY: $(BUILD) clean all +.PHONY: common clean all brahma a9lh release #--------------------------------------------------------------------------------- -all: $(BUILD) +all: release -$(BUILD): - @[ -d $@ ] || mkdir -p $@ - @make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile +common: + @[ -d $(BUILD) ] || mkdir -p $(BUILD) + +a9lh: common + @make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile EXEC_METHOD=A9LH cp $(OUTPUT).bin arm9loaderhax.bin +brahma: common + @make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile EXEC_METHOD=BRAHMA + cp $(OUTPUT).bin uncart_brahma.bin + +release: + @rm -fr $(BUILD) $(OUTPUT).bin $(OUTPUT).elf + @make --no-print-directory a9lh + @rm -fr $(BUILD) $(OUTPUT).bin $(OUTPUT).elf + @make --no-print-directory brahma + #--------------------------------------------------------------------------------- clean: @echo clean ... - @rm -fr $(BUILD) $(OUTPUT).elf $(OUTPUT).bin arm9payload.bin + @rm -fr $(BUILD) $(OUTPUT).elf $(OUTPUT).bin arm9payload.bin uncart_brahma.bin #--------------------------------------------------------------------------------- diff --git a/source/aes.h b/source/aes.h index 417ea38..1c951e7 100644 --- a/source/aes.h +++ b/source/aes.h @@ -1,54 +1,54 @@ -// Copyright 2014 Normmatt -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include "common.h" - -#define REG_AESCNT (*(vu32*)0x10009000) -#define REG_AESBLKCNT (*(vu32*)0x10009004) -#define REG_AESBLKCNTH1 (*(vu16*)0x10009004) -#define REG_AESBLKCNTH2 (*(vu16*)0x10009006) -#define REG_AESWRFIFO (*(vu32*)0x10009008) -#define REG_AESRDFIFO (*(vu32*)0x1000900C) -#define REG_AESKEYSEL (*(vu8*)0x10009010) -#define REG_AESKEYCNT (*(vu8*)0x10009011) -#define REG_AESCTR ((vu32*)0x10009020) // 16 -#define REG_AESMAC ((vu32*)0x10009030) // 16 -#define REG_AESKEY0 ((vu32*)0x10009040) // 48 -#define REG_AESKEY1 ((vu32*)0x10009070) // 48 -#define REG_AESKEY2 ((vu32*)0x100090A0) // 48 -#define REG_AESKEY3 ((vu32*)0x100090D0) // 48 -#define REG_AESKEYFIFO (*(vu32*)0x10009100) -#define REG_AESKEYXFIFO (*(vu32*)0x10009104) -#define REG_AESKEYYFIFO (*(vu32*)0x10009108) - -#define AES_WRITE_FIFO_COUNT ((REG_AESCNT>>0) & 0x1F) -#define AES_READ_FIFO_COUNT ((REG_AESCNT>>5) & 0x1F) -#define AES_BUSY (1u<<31) - -#define AES_FLUSH_READ_FIFO (1u<<10) -#define AES_FLUSH_WRITE_FIFO (1u<<11) -#define AES_BIT12 (1u<<12) -#define AES_BIT13 (1u<<13) -#define AES_MAC_SIZE(n) ((n&7u)<<16) -#define AES_MAC_REGISTER_SOURCE (1u<<20) -#define AES_UNKNOWN_21 (1u<<21) -#define AES_OUTPUT_BIG_ENDIAN (1u<<22) -#define AES_INPUT_BIG_ENDIAN (1u<<23) -#define AES_OUTPUT_NORMAL_ORDER (1u<<24) -#define AES_INPUT_NORMAL_ORDER (1u<<25) -#define AES_UNKNOWN_26 (1u<<26) -#define AES_MODE(n) ((n&7u)<<27) -#define AES_INTERRUPT_ENABLE (1u<<30) -#define AES_ENABLE (1u<<31) - -#define AES_MODE_CCM_DECRYPT 0u -#define AES_MODE_CCM_ENCRYPT 1u -#define AES_MODE_CTR 2u -#define AES_MODE_UNK3 3u -#define AES_MODE_CBC_DECRYPT 4u -#define AES_MODE_CBC_ENCRYPT 5u -#define AES_MODE_UNK6 6u -#define AES_MODE_UNK7 7u +// Copyright 2014 Normmatt +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include "common.h" + +#define REG_AESCNT (*(vu32*)0x10009000) +#define REG_AESBLKCNT (*(vu32*)0x10009004) +#define REG_AESBLKCNTH1 (*(vu16*)0x10009004) +#define REG_AESBLKCNTH2 (*(vu16*)0x10009006) +#define REG_AESWRFIFO (*(vu32*)0x10009008) +#define REG_AESRDFIFO (*(vu32*)0x1000900C) +#define REG_AESKEYSEL (*(vu8*)0x10009010) +#define REG_AESKEYCNT (*(vu8*)0x10009011) +#define REG_AESCTR ((vu32*)0x10009020) // 16 +#define REG_AESMAC ((vu32*)0x10009030) // 16 +#define REG_AESKEY0 ((vu32*)0x10009040) // 48 +#define REG_AESKEY1 ((vu32*)0x10009070) // 48 +#define REG_AESKEY2 ((vu32*)0x100090A0) // 48 +#define REG_AESKEY3 ((vu32*)0x100090D0) // 48 +#define REG_AESKEYFIFO (*(vu32*)0x10009100) +#define REG_AESKEYXFIFO (*(vu32*)0x10009104) +#define REG_AESKEYYFIFO (*(vu32*)0x10009108) + +#define AES_WRITE_FIFO_COUNT ((REG_AESCNT>>0) & 0x1F) +#define AES_READ_FIFO_COUNT ((REG_AESCNT>>5) & 0x1F) +#define AES_BUSY (1u<<31) + +#define AES_FLUSH_READ_FIFO (1u<<10) +#define AES_FLUSH_WRITE_FIFO (1u<<11) +#define AES_BIT12 (1u<<12) +#define AES_BIT13 (1u<<13) +#define AES_MAC_SIZE(n) ((n&7u)<<16) +#define AES_MAC_REGISTER_SOURCE (1u<<20) +#define AES_UNKNOWN_21 (1u<<21) +#define AES_OUTPUT_BIG_ENDIAN (1u<<22) +#define AES_INPUT_BIG_ENDIAN (1u<<23) +#define AES_OUTPUT_NORMAL_ORDER (1u<<24) +#define AES_INPUT_NORMAL_ORDER (1u<<25) +#define AES_UNKNOWN_26 (1u<<26) +#define AES_MODE(n) ((n&7u)<<27) +#define AES_INTERRUPT_ENABLE (1u<<30) +#define AES_ENABLE (1u<<31) + +#define AES_MODE_CCM_DECRYPT 0u +#define AES_MODE_CCM_ENCRYPT 1u +#define AES_MODE_CTR 2u +#define AES_MODE_UNK3 3u +#define AES_MODE_CBC_DECRYPT 4u +#define AES_MODE_CBC_ENCRYPT 5u +#define AES_MODE_UNK6 6u +#define AES_MODE_UNK7 7u diff --git a/source/draw.h b/source/draw.h index c39c6cf..99bba9c 100644 --- a/source/draw.h +++ b/source/draw.h @@ -14,15 +14,20 @@ #define RGB(r,g,b) (r<<24|b<<16|g<<8|r) -//#define TOP_SCREEN0 (u8*)(0x20000000) -//#define TOP_SCREEN1 (u8*)(0x20046500) -//#define BOT_SCREEN0 (u8*)(0x2008CA00) -//#define BOT_SCREEN1 (u8*)(0x200C4E00) +#ifdef BRAHMA + #define TOP_SCREEN0 (u8*)(0x20000000) + #define TOP_SCREEN1 (u8*)(0x20046500) + #define BOT_SCREEN0 (u8*)(0x2008CA00) + #define BOT_SCREEN1 (u8*)(0x200C4E00) +#endif + +#ifdef A9LH + #define TOP_SCREEN0 (u8*)(*(u32*)0x23FFFE00) + #define TOP_SCREEN1 (u8*)(*(u32*)0x23FFFE00) + #define BOT_SCREEN0 (u8*)(*(u32*)0x23FFFE08) + #define BOT_SCREEN1 (u8*)(*(u32*)0x23FFFE08) +#endif -#define TOP_SCREEN0 (u8*)(0x18300000) -#define TOP_SCREEN1 (u8*)(0x18300000) -#define BOT_SCREEN0 (u8*)(0x18346500) -#define BOT_SCREEN1 (u8*)(0x18346500) extern size_t current_y; void ClearScreen(unsigned char *screen, int color); diff --git a/source/gamecart/protocol.c b/source/gamecart/protocol.c index ee36292..fdfb7ec 100644 --- a/source/gamecart/protocol.c +++ b/source/gamecart/protocol.c @@ -1,226 +1,226 @@ -// Copyright 2014 Normmatt -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include "protocol.h" - -#include -#include -#include - -#include "draw.h" -#include "common.h" -#include "aes.h" -#include "protocol_ctr.h" -#include "protocol_ntr.h" -#include "command_ctr.h" -#include "command_ntr.h" -#include "delay.h" - -extern u8* bottomScreen; - -u32 CartID = 0xFFFFFFFFu; -u32 CartType = 0; - -static u32 A0_Response = 0xFFFFFFFFu; -static u32 rand1 = 0; -static u32 rand2 = 0; - -u32 BSWAP32(u32 val) { - return (((val >> 24) & 0xFF)) | - (((val >> 16) & 0xFF) << 8) | - (((val >> 8) & 0xFF) << 16) | - ((val & 0xFF) << 24); -} - -// TODO: Verify -static void ResetCartSlot(void) -{ - REG_CARDCONF2 = 0x0C; - REG_CARDCONF &= ~3; - - if (REG_CARDCONF2 == 0xC) { - while (REG_CARDCONF2 != 0); - } - - if (REG_CARDCONF2 != 0) - return; - - REG_CARDCONF2 = 0x4; - while(REG_CARDCONF2 != 0x4); - - REG_CARDCONF2 = 0x8; - while(REG_CARDCONF2 != 0x8); -} - -static void SwitchToNTRCARD(void) -{ - REG_NTRCARDROMCNT = 0x20000000; - REG_CARDCONF &= ~3; - REG_CARDCONF &= ~0x100; - REG_NTRCARDMCNT = NTRCARD_CR1_ENABLE; -} - -static void SwitchToCTRCARD(void) -{ - REG_CTRCARDCNT = 0x10000000; - REG_CARDCONF = (REG_CARDCONF & ~3) | 2; -} - -int Cart_IsInserted(void) -{ - return (0x9000E2C2 == CTR_CmdGetSecureId(rand1, rand2) ); -} - -u32 Cart_GetID(void) -{ - return CartID; -} - -void Cart_Init(void) -{ - ResetCartSlot(); //Seems to reset the cart slot? - - REG_CTRCARDSECCNT &= 0xFFFFFFFB; - ioDelay(0x30000); - - SwitchToNTRCARD(); - ioDelay(0x30000); - - REG_NTRCARDROMCNT = 0; - REG_NTRCARDMCNT &= 0xFF; - ioDelay(0x40000); - - REG_NTRCARDMCNT |= (NTRCARD_CR1_ENABLE | NTRCARD_CR1_IRQ); - REG_NTRCARDROMCNT = NTRCARD_nRESET | NTRCARD_SEC_SEED; - while (REG_NTRCARDROMCNT & NTRCARD_BUSY); - - // Reset - NTR_CmdReset(); - CartID = NTR_CmdGetCartId(); - - // 3ds - if (CartID & 0x10000000) { - u32 unknowna0_cmd[2] = { 0xA0000000, 0x00000000 }; - NTR_SendCommand(unknowna0_cmd, 0x4, 0, &A0_Response); - - NTR_CmdEnter16ByteMode(); - SwitchToCTRCARD(); - ioDelay(0xF000); - - REG_CTRCARDBLKCNT = 0; - } -} - -static void AES_SetKeyControl(u32 a) { - REG_AESKEYCNT = (REG_AESKEYCNT & 0xC0) | a | 0x80; -} - -//returns 1 if MAC valid otherwise 0 -static u8 card_aes(u32 *out, u32 *buff, size_t size) { // note size param ignored - u8 tmp = REG_AESKEYCNT; - REG_AESCNT = 0x10C00; //flush r/w fifo macsize = 001 - - (*(vu8*)0x10000008) |= 0x0C; //??? - - REG_AESCNT |= 0x2800000; - - //const u8 is_dev_unit = *(vu8*)0x10010010; - //if(is_dev_unit) //Dev unit - const u8 is_dev_cart = (A0_Response&3)==3; - if(is_dev_cart) //Dev unit - { - AES_SetKeyControl(0x11); - REG_AESKEYFIFO = 0; - REG_AESKEYFIFO = 0; - REG_AESKEYFIFO = 0; - REG_AESKEYFIFO = 0; - REG_AESKEYSEL = 0x11; - } - else - { - AES_SetKeyControl(0x3B); - REG_AESKEYYFIFO = buff[0]; - REG_AESKEYYFIFO = buff[1]; - REG_AESKEYYFIFO = buff[2]; - REG_AESKEYYFIFO = buff[3]; - REG_AESKEYSEL = 0x3B; - } - - REG_AESCNT = 0x4000000; - REG_AESCNT &= 0xFFF7FFFF; - REG_AESCNT |= 0x2970000; - REG_AESMAC[0] = buff[11]; - REG_AESMAC[1] = buff[10]; - REG_AESMAC[2] = buff[9]; - REG_AESMAC[3] = buff[8]; - REG_AESCNT |= 0x2800000; - REG_AESCTR[0] = buff[14]; - REG_AESCTR[1] = buff[13]; - REG_AESCTR[2] = buff[12]; - REG_AESBLKCNT = 0x10000; - - u32 v11 = ((REG_AESCNT | 0x80000000) & 0xC7FFFFFF); //Start and clear mode (ccm decrypt) - u32 v12 = v11 & 0xBFFFFFFF; //Disable Interrupt - REG_AESCNT = ((((v12 | 0x3000) & 0xFD7F3FFF) | (5 << 23)) & 0xFEBFFFFF) | (5 << 22); - - //REG_AESCNT = 0x83D73C00; - REG_AESWRFIFO = buff[4]; - REG_AESWRFIFO = buff[5]; - REG_AESWRFIFO = buff[6]; - REG_AESWRFIFO = buff[7]; - while (((REG_AESCNT >> 5) & 0x1F) <= 3); - out[0] = REG_AESRDFIFO; - out[1] = REG_AESRDFIFO; - out[2] = REG_AESRDFIFO; - out[3] = REG_AESRDFIFO; - return ((REG_AESCNT >> 21) & 1); -} - -void Cart_Secure_Init(u32 *buf, u32 *out) -{ - u8 mac_valid = card_aes(out, buf, 0x200); - -// if (!mac_valid) -// ClearScreen(bottomScreen, RGB(255, 0, 0)); - - ioDelay(0xF0000); - - CTR_SetSecKey(A0_Response); - CTR_SetSecSeed(out, true); - - rand1 = 0x42434445;//*((vu32*)0x10011000); - rand2 = 0x46474849;//*((vu32*)0x10011010); - - CTR_CmdSeed(rand1, rand2); - - out[3] = BSWAP32(rand2); - out[2] = BSWAP32(rand1); - CTR_SetSecSeed(out, false); - - u32 test = 0; - const u32 A2_cmd[4] = { 0xA2000000, 0x00000000, rand1, rand2 }; - CTR_SendCommand(A2_cmd, 4, 1, 0x701002C, &test); - - u32 test2 = 0; - const u32 A3_cmd[4] = { 0xA3000000, 0x00000000, rand1, rand2 }; - CTR_SendCommand(A3_cmd, 4, 1, 0x701002C, &test2); - - if(test==CartID && test2==A0_Response) - { - const u32 C5_cmd[4] = { 0xC5000000, 0x00000000, rand1, rand2 }; - CTR_SendCommand(C5_cmd, 0, 1, 0x100002C, NULL); - } - - for (int i = 0; i < 5; ++i) { - CTR_SendCommand(A2_cmd, 4, 1, 0x701002C, &test); - ioDelay(0xF0000); - } -} - -void Cart_Dummy(void) { - // Sends a dummy command to skip encrypted responses some problematic carts send. - u32 test; - const u32 A2_cmd[4] = { 0xA2000000, 0x00000000, rand1, rand2 }; - CTR_SendCommand(A2_cmd, 4, 1, 0x701002C, &test); -} +// Copyright 2014 Normmatt +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "protocol.h" + +#include +#include +#include + +#include "draw.h" +#include "common.h" +#include "aes.h" +#include "protocol_ctr.h" +#include "protocol_ntr.h" +#include "command_ctr.h" +#include "command_ntr.h" +#include "delay.h" + +extern u8* bottomScreen; + +u32 CartID = 0xFFFFFFFFu; +u32 CartType = 0; + +static u32 A0_Response = 0xFFFFFFFFu; +static u32 rand1 = 0; +static u32 rand2 = 0; + +u32 BSWAP32(u32 val) { + return (((val >> 24) & 0xFF)) | + (((val >> 16) & 0xFF) << 8) | + (((val >> 8) & 0xFF) << 16) | + ((val & 0xFF) << 24); +} + +// TODO: Verify +static void ResetCartSlot(void) +{ + REG_CARDCONF2 = 0x0C; + REG_CARDCONF &= ~3; + + if (REG_CARDCONF2 == 0xC) { + while (REG_CARDCONF2 != 0); + } + + if (REG_CARDCONF2 != 0) + return; + + REG_CARDCONF2 = 0x4; + while(REG_CARDCONF2 != 0x4); + + REG_CARDCONF2 = 0x8; + while(REG_CARDCONF2 != 0x8); +} + +static void SwitchToNTRCARD(void) +{ + REG_NTRCARDROMCNT = 0x20000000; + REG_CARDCONF &= ~3; + REG_CARDCONF &= ~0x100; + REG_NTRCARDMCNT = NTRCARD_CR1_ENABLE; +} + +static void SwitchToCTRCARD(void) +{ + REG_CTRCARDCNT = 0x10000000; + REG_CARDCONF = (REG_CARDCONF & ~3) | 2; +} + +int Cart_IsInserted(void) +{ + return (0x9000E2C2 == CTR_CmdGetSecureId(rand1, rand2) ); +} + +u32 Cart_GetID(void) +{ + return CartID; +} + +void Cart_Init(void) +{ + ResetCartSlot(); //Seems to reset the cart slot? + + REG_CTRCARDSECCNT &= 0xFFFFFFFB; + ioDelay(0x30000); + + SwitchToNTRCARD(); + ioDelay(0x30000); + + REG_NTRCARDROMCNT = 0; + REG_NTRCARDMCNT &= 0xFF; + ioDelay(0x40000); + + REG_NTRCARDMCNT |= (NTRCARD_CR1_ENABLE | NTRCARD_CR1_IRQ); + REG_NTRCARDROMCNT = NTRCARD_nRESET | NTRCARD_SEC_SEED; + while (REG_NTRCARDROMCNT & NTRCARD_BUSY); + + // Reset + NTR_CmdReset(); + CartID = NTR_CmdGetCartId(); + + // 3ds + if (CartID & 0x10000000) { + u32 unknowna0_cmd[2] = { 0xA0000000, 0x00000000 }; + NTR_SendCommand(unknowna0_cmd, 0x4, 0, &A0_Response); + + NTR_CmdEnter16ByteMode(); + SwitchToCTRCARD(); + ioDelay(0xF000); + + REG_CTRCARDBLKCNT = 0; + } +} + +static void AES_SetKeyControl(u32 a) { + REG_AESKEYCNT = (REG_AESKEYCNT & 0xC0) | a | 0x80; +} + +//returns 1 if MAC valid otherwise 0 +static u8 card_aes(u32 *out, u32 *buff, size_t size) { // note size param ignored + u8 tmp = REG_AESKEYCNT; + REG_AESCNT = 0x10C00; //flush r/w fifo macsize = 001 + + (*(vu8*)0x10000008) |= 0x0C; //??? + + REG_AESCNT |= 0x2800000; + + //const u8 is_dev_unit = *(vu8*)0x10010010; + //if(is_dev_unit) //Dev unit + const u8 is_dev_cart = (A0_Response&3)==3; + if(is_dev_cart) //Dev unit + { + AES_SetKeyControl(0x11); + REG_AESKEYFIFO = 0; + REG_AESKEYFIFO = 0; + REG_AESKEYFIFO = 0; + REG_AESKEYFIFO = 0; + REG_AESKEYSEL = 0x11; + } + else + { + AES_SetKeyControl(0x3B); + REG_AESKEYYFIFO = buff[0]; + REG_AESKEYYFIFO = buff[1]; + REG_AESKEYYFIFO = buff[2]; + REG_AESKEYYFIFO = buff[3]; + REG_AESKEYSEL = 0x3B; + } + + REG_AESCNT = 0x4000000; + REG_AESCNT &= 0xFFF7FFFF; + REG_AESCNT |= 0x2970000; + REG_AESMAC[0] = buff[11]; + REG_AESMAC[1] = buff[10]; + REG_AESMAC[2] = buff[9]; + REG_AESMAC[3] = buff[8]; + REG_AESCNT |= 0x2800000; + REG_AESCTR[0] = buff[14]; + REG_AESCTR[1] = buff[13]; + REG_AESCTR[2] = buff[12]; + REG_AESBLKCNT = 0x10000; + + u32 v11 = ((REG_AESCNT | 0x80000000) & 0xC7FFFFFF); //Start and clear mode (ccm decrypt) + u32 v12 = v11 & 0xBFFFFFFF; //Disable Interrupt + REG_AESCNT = ((((v12 | 0x3000) & 0xFD7F3FFF) | (5 << 23)) & 0xFEBFFFFF) | (5 << 22); + + //REG_AESCNT = 0x83D73C00; + REG_AESWRFIFO = buff[4]; + REG_AESWRFIFO = buff[5]; + REG_AESWRFIFO = buff[6]; + REG_AESWRFIFO = buff[7]; + while (((REG_AESCNT >> 5) & 0x1F) <= 3); + out[0] = REG_AESRDFIFO; + out[1] = REG_AESRDFIFO; + out[2] = REG_AESRDFIFO; + out[3] = REG_AESRDFIFO; + return ((REG_AESCNT >> 21) & 1); +} + +void Cart_Secure_Init(u32 *buf, u32 *out) +{ + u8 mac_valid = card_aes(out, buf, 0x200); + +// if (!mac_valid) +// ClearScreen(bottomScreen, RGB(255, 0, 0)); + + ioDelay(0xF0000); + + CTR_SetSecKey(A0_Response); + CTR_SetSecSeed(out, true); + + rand1 = 0x42434445;//*((vu32*)0x10011000); + rand2 = 0x46474849;//*((vu32*)0x10011010); + + CTR_CmdSeed(rand1, rand2); + + out[3] = BSWAP32(rand2); + out[2] = BSWAP32(rand1); + CTR_SetSecSeed(out, false); + + u32 test = 0; + const u32 A2_cmd[4] = { 0xA2000000, 0x00000000, rand1, rand2 }; + CTR_SendCommand(A2_cmd, 4, 1, 0x701002C, &test); + + u32 test2 = 0; + const u32 A3_cmd[4] = { 0xA3000000, 0x00000000, rand1, rand2 }; + CTR_SendCommand(A3_cmd, 4, 1, 0x701002C, &test2); + + if(test==CartID && test2==A0_Response) + { + const u32 C5_cmd[4] = { 0xC5000000, 0x00000000, rand1, rand2 }; + CTR_SendCommand(C5_cmd, 0, 1, 0x100002C, NULL); + } + + for (int i = 0; i < 5; ++i) { + CTR_SendCommand(A2_cmd, 4, 1, 0x701002C, &test); + ioDelay(0xF0000); + } +} + +void Cart_Dummy(void) { + // Sends a dummy command to skip encrypted responses some problematic carts send. + u32 test; + const u32 A2_cmd[4] = { 0xA2000000, 0x00000000, rand1, rand2 }; + CTR_SendCommand(A2_cmd, 4, 1, 0x701002C, &test); +} diff --git a/source/gamecart/protocol.h b/source/gamecart/protocol.h index 75418aa..7a12407 100644 --- a/source/gamecart/protocol.h +++ b/source/gamecart/protocol.h @@ -1,25 +1,25 @@ -// Copyright 2014 Normmatt -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once -#include "common.h" - -#define REG_CARDCONF (*(vu16*)0x1000000C) -#define REG_CARDCONF2 (*(vu8*)0x10000010) - -//REG_AUXSPICNT -#define CARD_ENABLE (1u<<15) -#define CARD_SPI_ENABLE (1u<<13) -#define CARD_SPI_BUSY (1u<<7) -#define CARD_SPI_HOLD (1u<<6) - -#define LATENCY 0x822Cu - -u32 BSWAP32(u32 val); - -void Cart_Init(void); -int Cart_IsInserted(void); -u32 Cart_GetID(void); -void Cart_Secure_Init(u32* buf, u32* out); -void Cart_Dummy(void); +// Copyright 2014 Normmatt +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once +#include "common.h" + +#define REG_CARDCONF (*(vu16*)0x1000000C) +#define REG_CARDCONF2 (*(vu8*)0x10000010) + +//REG_AUXSPICNT +#define CARD_ENABLE (1u<<15) +#define CARD_SPI_ENABLE (1u<<13) +#define CARD_SPI_BUSY (1u<<7) +#define CARD_SPI_HOLD (1u<<6) + +#define LATENCY 0x822Cu + +u32 BSWAP32(u32 val); + +void Cart_Init(void); +int Cart_IsInserted(void); +u32 Cart_GetID(void); +void Cart_Secure_Init(u32* buf, u32* out); +void Cart_Dummy(void); From a471b28cd513480ac747a33819e11af2be90e76c Mon Sep 17 00:00:00 2001 From: Gabriel Marcano Date: Tue, 7 Jun 2016 23:15:14 -0400 Subject: [PATCH 4/6] Styling fixes, framebuffer fix -Fixed a lot of styling problems related to indentation and spacing. -Fixed a bug where the cakehax framebuffer structure was being overwritten by the heap. --- Makefile | 9 +++++---- source/draw.c | 26 +++++++++++++++++++++++-- source/draw.h | 18 +++++------------- source/fatfs/sdmmc.c | 33 ++++++++++++++++---------------- source/gamecart/command_ctr.c | 2 +- source/gamecart/protocol.c | 2 +- source/main.c | 36 ++++++++++++++++++----------------- 7 files changed, 71 insertions(+), 55 deletions(-) diff --git a/Makefile b/Makefile index 85d0331..0ab7aa7 100644 --- a/Makefile +++ b/Makefile @@ -46,7 +46,7 @@ CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions ASFLAGS := -g $(ARCH) LDFLAGS = -nostartfiles -g --specs=../stub.specs $(ARCH) -Wl,-Map,$(TARGET).map -OCFLAGS= --set-section-flags .bss=alloc,load,contents +OCFLAGS = --set-section-flags .bss=alloc,load,contents LIBS := @@ -114,11 +114,11 @@ common: a9lh: common @make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile EXEC_METHOD=A9LH - cp $(OUTPUT).bin arm9loaderhax.bin + @mv $(OUTPUT).bin uncart_arm9loaderhax.bin brahma: common @make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile EXEC_METHOD=BRAHMA - cp $(OUTPUT).bin uncart_brahma.bin + @mv $(OUTPUT).bin uncart_brahma.bin release: @rm -fr $(BUILD) $(OUTPUT).bin $(OUTPUT).elf @@ -129,7 +129,8 @@ release: #--------------------------------------------------------------------------------- clean: @echo clean ... - @rm -fr $(BUILD) $(OUTPUT).elf $(OUTPUT).bin arm9payload.bin uncart_brahma.bin + @rm -fr $(BUILD) $(OUTPUT).elf $(OUTPUT).bin uncart_arm9loaderhax.bin \ + uncart_brahma.bin #--------------------------------------------------------------------------------- diff --git a/source/draw.c b/source/draw.c index fac8512..d4f397d 100644 --- a/source/draw.c +++ b/source/draw.c @@ -10,8 +10,30 @@ #include "font.h" #include "draw.h" +u8 *TOP_SCREEN0; +u8 *TOP_SCREEN1; +u8 *BOT_SCREEN0; +u8 *BOT_SCREEN1; + size_t current_y = 0; +void DrawInit(void) +{ +#ifdef BRAHMA + TOP_SCREEN0 = (u8*)(0x20000000); + TOP_SCREEN1 = (u8*)(0x20046500); + BOT_SCREEN0 = (u8*)(0x2008CA00); + BOT_SCREEN1 = (u8*)(0x200C4E00); +#elif A9LH + TOP_SCREEN0 = (u8*)(*(u32*)0x23FFFE00); + TOP_SCREEN1 = (u8*)(*(u32*)0x23FFFE00); + BOT_SCREEN0 = (u8*)(*(u32*)0x23FFFE08); + BOT_SCREEN1 = (u8*)(*(u32*)0x23FFFE08); +#else + #error "BRAHMA or A9LH must be defined!" +#endif +} + void ClearScreen(unsigned char *screen, int color) { int i; @@ -28,8 +50,8 @@ void DrawCharacter(unsigned char *screen, int character, size_t x, size_t y, int for (size_t yy = 0; yy < 8; yy++) { size_t xDisplacement = (x * BYTES_PER_PIXEL * SCREEN_WIDTH); size_t yDisplacement = ((SCREEN_WIDTH - (y + yy) - 1) * BYTES_PER_PIXEL); - - unsigned char *screenPos = screen + xDisplacement + yDisplacement; + + unsigned char *screenPos = screen + xDisplacement + yDisplacement; unsigned char charPos = font[(size_t)character * 8 + yy]; for (int xx = 7; xx >= 0; xx--) { if ((charPos >> xx) & 1) { diff --git a/source/draw.h b/source/draw.h index 99bba9c..d8a4013 100644 --- a/source/draw.h +++ b/source/draw.h @@ -14,22 +14,14 @@ #define RGB(r,g,b) (r<<24|b<<16|g<<8|r) -#ifdef BRAHMA - #define TOP_SCREEN0 (u8*)(0x20000000) - #define TOP_SCREEN1 (u8*)(0x20046500) - #define BOT_SCREEN0 (u8*)(0x2008CA00) - #define BOT_SCREEN1 (u8*)(0x200C4E00) -#endif - -#ifdef A9LH - #define TOP_SCREEN0 (u8*)(*(u32*)0x23FFFE00) - #define TOP_SCREEN1 (u8*)(*(u32*)0x23FFFE00) - #define BOT_SCREEN0 (u8*)(*(u32*)0x23FFFE08) - #define BOT_SCREEN1 (u8*)(*(u32*)0x23FFFE08) -#endif +extern u8 *TOP_SCREEN0; +extern u8 *TOP_SCREEN1; +extern u8 *BOT_SCREEN0; +extern u8 *BOT_SCREEN1; extern size_t current_y; +void DrawInit(void); void ClearScreen(unsigned char *screen, int color); void DrawCharacter(unsigned char *screen, int character, size_t x, size_t y, int color, int bgcolor); void DrawHex(unsigned char *screen, unsigned int hex, size_t x, size_t y, int color, int bgcolor); diff --git a/source/fatfs/sdmmc.c b/source/fatfs/sdmmc.c index 8ba1ea4..458fd0d 100644 --- a/source/fatfs/sdmmc.c +++ b/source/fatfs/sdmmc.c @@ -89,18 +89,18 @@ static void __attribute__((noinline)) sdmmc_send_command(struct mmcdevice *ctx, if (useBuf32) { for(int i = 0; i<0x200; i+=4) { u32 data = sdmmc_read32(REG_SDFIFO32); - *dataPtr++ = data; - *dataPtr++ = data >> 8; - *dataPtr++ = data >> 16; - *dataPtr++ = data >> 24; - } + *dataPtr++ = data; + *dataPtr++ = data >> 8; + *dataPtr++ = data >> 16; + *dataPtr++ = data >> 24; + } } else { #endif for(int i = 0; i<0x200; i+=2) { - u16 data = sdmmc_read16(REG_SDFIFO); + u16 data = sdmmc_read16(REG_SDFIFO); *dataPtr++ = data; - *dataPtr++ = data >> 8; - } + *dataPtr++ = data >> 8; + } #ifdef DATA32_SUPPORT } #endif @@ -117,18 +117,17 @@ static void __attribute__((noinline)) sdmmc_send_command(struct mmcdevice *ctx, #ifdef DATA32_SUPPORT for (int i = 0; i<0x200; i+=4) { u32 data = *dataPtr++; - data |= *dataPtr++ << 8; - data |= *dataPtr++ << 16; - data |= *dataPtr++ << 24; - sdmmc_write32(REG_SDFIFO32,data); - } + data |= *dataPtr++ << 8; + data |= *dataPtr++ << 16; + data |= *dataPtr++ << 24; + sdmmc_write32(REG_SDFIFO32,data); + } #else for (int i = 0; i<0x200; i+=2) { - u16 data = *dataPtr++; - data |= *dataPtr++ << 8; + u16 data = *dataPtr++; + data |= *dataPtr++ << 8; sdmmc_write16(REG_SDFIFO,data); - - } + } #endif size -= 0x200; } diff --git a/source/gamecart/command_ctr.c b/source/gamecart/command_ctr.c index 020fbe7..8e9ae75 100644 --- a/source/gamecart/command_ctr.c +++ b/source/gamecart/command_ctr.c @@ -9,7 +9,7 @@ static int read_count = 0; -static inline void CTR_CmdC5() +static void CTR_CmdC5() { static const u32 c5_cmd[4] = { 0xC5000000, 0x00000000, 0x00000000, 0x00000000 }; CTR_SendCommand(c5_cmd, 0, 1, 0x100002C, NULL); diff --git a/source/gamecart/protocol.c b/source/gamecart/protocol.c index fdfb7ec..70f4dac 100644 --- a/source/gamecart/protocol.c +++ b/source/gamecart/protocol.c @@ -205,7 +205,7 @@ void Cart_Secure_Init(u32 *buf, u32 *out) u32 test2 = 0; const u32 A3_cmd[4] = { 0xA3000000, 0x00000000, rand1, rand2 }; CTR_SendCommand(A3_cmd, 4, 1, 0x701002C, &test2); - + if(test==CartID && test2==A0_Response) { const u32 C5_cmd[4] = { 0xC5000000, 0x00000000, rand1, rand2 }; diff --git a/source/main.c b/source/main.c index a9800e4..c00bf84 100644 --- a/source/main.c +++ b/source/main.c @@ -20,6 +20,7 @@ static FATFS fs; static FIL file; static void ClearTop(void) { + ClearScreen(TOP_SCREEN0, RGB(255, 255, 255)); ClearScreen(TOP_SCREEN1, RGB(255, 255, 255)); current_y = 0; } @@ -57,8 +58,8 @@ static int dump_cart_region(u32 start_sector, u32 end_sector, FIL* output_file, Cart_Dummy(); Cart_Dummy(); - //If there is less data to read than the current read_size, fix it - if (end_sector - current_sector < read_size) + // If there is less data to read than the current read_size, fix it + if (end_sector - current_sector < read_size) { read_size = end_sector - current_sector; } @@ -86,15 +87,18 @@ static int dump_cart_region(u32 start_sector, u32 end_sector, FIL* output_file, } int main() { + // Saves the framebuffer information somewhere safe. + DrawInit(); + // Arbitrary target buffer // aligning to 32 bits in case other parts of the software assume alignment const u32 target_buf_size = 16u * 1024u * 1024u; // 16MB - u32 * const target = memalign(32, target_buf_size); + u32* const target = memalign(4, target_buf_size); - u32 * const ncchHeaderData = memalign(32, sizeof(NCCH_HEADER)); - NCCH_HEADER * const ncchHeader = (NCCH_HEADER*)ncchHeaderData; + u32* const ncchHeaderData = memalign(4, sizeof(NCCH_HEADER)); + NCCH_HEADER* const ncchHeader = (NCCH_HEADER*)ncchHeaderData; - NCSD_HEADER * const ncsdHeader = (NCSD_HEADER*)target; + NCSD_HEADER* const ncsdHeader = (NCSD_HEADER*)target; restart_program: // Setup boring stuff - clear the screen, initialize SD output, etc... @@ -115,8 +119,7 @@ restart_program: Debug("Done reading NCCH header."); // Check that the NCCH header magic is there - if (strncmp((const char*)(ncchHeader->magic), "NCCH", 4)) - { + if (strncmp((const char*)(ncchHeader->magic), "NCCH", 4)) { Debug("NCCH magic not found in header!!!"); Debug("Press A to continue anyway."); if (!(InputWait() & BUTTON_A)) @@ -147,8 +150,7 @@ restart_program: Debug(""); u32 input; - do - { + do { Debug("Press A to dump all of ROM, B for only the"); Debug("trimmed version."); input = InputWait(); @@ -158,23 +160,23 @@ restart_program: const u32 mediaUnit = 0x200 * (1u << ncsdHeader->partition_flags[MEDIA_UNIT_SIZE]); //Correctly set the media unit size - //Calculate the actual size by counting the adding the size of each partition, plus the initial offset - //size is in media units u32 cartSize; // Maximum number of blocks in a single file u32 file_max_blocks; - if (input & BUTTON_B) - { + if (input & BUTTON_B) { + // Calculate the actual size by counting the adding the size of each + // partition, plus the initial offset size is in media units + + // The 3DS carts have up to 8 partitions in their carts cartSize = ncsdHeader->offsetsize_table[0].offset; - for(int i = 0; i < 8; i++){ + for(size_t i = 0; i < 8; i++) { cartSize += ncsdHeader->offsetsize_table[i].size; } Debug("Cart data size: %llu MB", (u64)cartSize * (u64)mediaUnit / 1024ull / 1024ull); // Maximum number of blocks in a single file - file_max_blocks = 0xFFFFFFFFu / mediaUnit; // 4GiB - 513 - + file_max_blocks = 0xFFFFFFFFu / mediaUnit + mediaUnit; // 4GiB - 512 } else { From 4c0559bc1afe612aef17b2e98f3ab80a155dfc79 Mon Sep 17 00:00:00 2001 From: Gabriel Marcano Date: Wed, 8 Jun 2016 19:48:42 -0400 Subject: [PATCH 5/6] Explicitly setup heap, fixes brahma. Since brahma has its stack (unless it is changed) in ARM9 memory, the default logic for setting up the heap breaks, since it assumes the heap is in lower memory than the stack. This commit uses a hook used by newlib to setup the heap at any random location in memory. This commit just allocates a 32MB heap, although it could certainly be larger. --- source/start.s | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/source/start.s b/source/start.s index 264565b..c143ddf 100644 --- a/source/start.s +++ b/source/start.s @@ -3,6 +3,7 @@ .extern main .align 4 .arm +.extern fake_heap_end @ used for heap setup by newlib used by devKitARM #define SIZE_32KB 0b01110 #define SIZE_128KB 0b10000 @@ -93,6 +94,14 @@ _fix_sdmc_mount: str r1, [r0] mov pc, lr +_setup_heap: + mov r0, #0x2000000 @ Setup a 32MiB heap + ldr r1, =__end__ @ grab the location of the end of the binary + add r0, r0, r1 + ldr r1, =fake_heap_end @ heap goes from end of program to this variable + str r0, [r1] + mov pc, lr + _init: push {r0-r12, lr} @@ -100,6 +109,8 @@ _init: bl _fix_sdmc_mount + bl _setup_heap + bl main mrc p15, 0, r4, c1, c0, 0 From ce23df7d9bb893c6520b292126350aebde707096 Mon Sep 17 00:00:00 2001 From: Gabriel Marcano Date: Wed, 8 Jun 2016 20:00:31 -0400 Subject: [PATCH 6/6] Forgot to remove typo, extra i2c.h include. --- source/main.c | 1 - 1 file changed, 1 deletion(-) diff --git a/source/main.c b/source/main.c index c00bf84..494250f 100644 --- a/source/main.c +++ b/source/main.c @@ -5,7 +5,6 @@ #include "gamecart/protocol.h" #include "gamecart/command_ctr.h" #include "headers.h" -#include "i2c.h" #include #include