From 913bc867b7e69d1ac66155017805cbb2e44e0188 Mon Sep 17 00:00:00 2001 From: Gabriel Marcano Date: Tue, 7 Jun 2016 02:30:30 -0400 Subject: [PATCH] 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