diff --git a/README.md b/README.md index c5f792f..09cdd76 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ For usage instructions, refer to [Plailect's guide](https://3ds.guide/). * **Normmatt**, for sdmmc.c / sdmmc.h * **Cha(N)**, **Kane49**, and all other FatFS contributors for FatFS * **SciresM** for being the first fearless person to test this -* **TuxSH** for FIRM research and usefule hints +* **TuxSH** for FIRM research and useful hints * **hedgeberg** for dumping the bootrom (when it's done) * **Plailect** for providing the guide and making this accessible to the common user * **stuckpixel** for his tireless behind-the-scenes work diff --git a/source/common/hid.c b/source/common/hid.c index d5e9414..2ea6396 100644 --- a/source/common/hid.c +++ b/source/common/hid.c @@ -6,6 +6,7 @@ u32 InputWait() { static u64 delay = 0; u32 pad_state_old = HID_STATE; u32 cart_state_old = CART_STATE; + u32 sd_state_old = SD_STATE; delay = (delay) ? 72 : 128; timer_start(); while (true) { @@ -14,6 +15,9 @@ u32 InputWait() { u32 cart_state = CART_STATE; if (cart_state != cart_state_old) return cart_state ? CART_INSERT : CART_EJECT; + u32 sd_state = SD_STATE; + if (sd_state != sd_state_old) + return sd_state ? SD_INSERT : SD_EJECT; u32 special_key = i2cReadRegister(I2C_DEV_MCU, 0x10); if (special_key == 0x01) return pad_state | BUTTON_POWER; diff --git a/source/common/hid.h b/source/common/hid.h index 2825ad7..3cb3a2e 100644 --- a/source/common/hid.h +++ b/source/common/hid.h @@ -2,8 +2,11 @@ #include "common.h" +// see: http://3dbrew.org/wiki/CONFIG9_Registers +// see: http://3dbrew.org/wiki/EMMC_Registers #define HID_STATE (~(*(volatile u32*)0x10146000) & BUTTON_ANY) #define CART_STATE (~(*(volatile u8*)0x10000010) & 0x1) +#define SD_STATE ((*(volatile u16*)0x1000601C) & (0x1<<5)) #define BUTTON_A (1 << 0) @@ -21,11 +24,13 @@ #define BUTTON_ANY 0x00000FFF #define BUTTON_ARROW (BUTTON_RIGHT|BUTTON_LEFT|BUTTON_UP|BUTTON_DOWN) -// special buttons / cart handling +// special buttons / cart / sd #define BUTTON_POWER (1 << 12) #define BUTTON_HOME (1 << 13) #define CART_INSERT (1 << 14) #define CART_EJECT (1 << 15) +#define SD_INSERT (1 << 16) +#define SD_EJECT (1 << 17) u32 InputWait(); bool CheckButton(u32 button); diff --git a/source/common/ui.c b/source/common/ui.c index b466963..2aac7d7 100644 --- a/source/common/ui.c +++ b/source/common/ui.c @@ -71,7 +71,9 @@ void DrawCharacter(u8* screen, int character, int x, int y, int color, int bgcol void DrawString(u8* screen, const char *str, int x, int y, int color, int bgcolor) { - for (size_t i = 0; i < strlen(str); i++) + size_t max_len = (((screen == TOP_SCREEN) ? SCREEN_WIDTH_TOP : SCREEN_WIDTH_BOT) - x) / FONT_WIDTH; + size_t len = (strlen(str) > max_len) ? max_len : strlen(str); + for (size_t i = 0; i < len; i++) DrawCharacter(screen, str[i], x + i * FONT_WIDTH, y, color, bgcolor); } @@ -94,10 +96,10 @@ u32 GetDrawStringHeight(const char* str) { return height; } -u32 GetDrawStringWidth(char* str) { +u32 GetDrawStringWidth(const char* str) { u32 width = 0; - char* old_lf = str; - char* str_end = str + strnlen(str, STRBUF_SIZE); + char* old_lf = (char*) str; + char* str_end = (char*) str + strnlen(str, STRBUF_SIZE); for (char* lf = strchr(str, '\n'); lf != NULL; lf = strchr(lf + 1, '\n')) { if ((u32) (lf - old_lf) > width) width = lf - old_lf; old_lf = lf; @@ -236,6 +238,11 @@ bool ShowUnlockSequence(u32 seqlvl, const char *format, ...) { { '\x18', '\x19', '\x1B', '\x1A', 'A' } }; const u32 len = 5; + + u32 color_bg = COLOR_STD_BG; + u32 color_font = COLOR_STD_FONT; + u32 color_off = COLOR_GREY; + u32 color_on = seqcolors[seqlvl]; u32 lvl = 0; u32 str_width, str_height; @@ -253,14 +260,21 @@ bool ShowUnlockSequence(u32 seqlvl, const char *format, ...) { x = (str_width >= SCREEN_WIDTH_TOP) ? 0 : (SCREEN_WIDTH_TOP - str_width) / 2; y = (str_height >= SCREEN_HEIGHT) ? 0 : (SCREEN_HEIGHT - str_height) / 2; - ClearScreenF(true, false, COLOR_STD_BG); - DrawStringF(TOP_SCREEN, x, y, COLOR_STD_FONT, COLOR_STD_BG, str); - DrawStringF(TOP_SCREEN, x, y + str_height - 28, COLOR_STD_FONT, COLOR_STD_BG, "To proceed, enter this:"); + if (seqlvl >= 6) { // special handling + color_bg = seqcolors[seqlvl]; + color_font = COLOR_BLACK; + color_off = COLOR_BLACK; + color_on = COLOR_DARKGREY; + } + + ClearScreenF(true, false, color_bg); + DrawStringF(TOP_SCREEN, x, y, color_font, color_bg, str); + DrawStringF(TOP_SCREEN, x, y + str_height - 28, color_font, color_bg, "To proceed, enter this:"); while (true) { for (u32 n = 0; n < len; n++) { DrawStringF(TOP_SCREEN, x + (n*4*8), y + str_height - 18, - (lvl > n) ? seqcolors[seqlvl] : COLOR_GREY, COLOR_STD_BG, "<%c>", seqsymbols[seqlvl][n]); + (lvl > n) ? color_on : color_off, color_bg, "<%c>", seqsymbols[seqlvl][n]); } if (lvl == len) break; diff --git a/source/common/ui.h b/source/common/ui.h index 45203c5..60b78e0 100644 --- a/source/common/ui.h +++ b/source/common/ui.h @@ -64,7 +64,7 @@ void DrawString(unsigned char *screen, const char *str, int x, int y, int color, void DrawStringF(unsigned char *screen, int x, int y, int color, int bgcolor, const char *format, ...); u32 GetDrawStringHeight(const char* str); -u32 GetDrawStringWidth(char* str); +u32 GetDrawStringWidth(const char* str); void ResizeString(char* dest, const char* orig, int nsize, int tpos, bool align_right); void TruncateString(char* dest, const char* orig, int nsize, int tpos); diff --git a/source/fatfs/diskio.c b/source/fatfs/diskio.c index 6e27fb1..a9f36b9 100644 --- a/source/fatfs/diskio.c +++ b/source/fatfs/diskio.c @@ -11,9 +11,12 @@ #include "nand.h" #include "sdmmc.h" +#define PART_TYPE(pdrv) (DriveInfo[pdrv].type) +#define PART_SUBTYPE(pdrv) (DriveInfo[pdrv].subtype) + #define TYPE_NONE 0 #define TYPE_SYSNAND NAND_SYSNAND -#define TYPE_SDCARD (1<<4) +#define TYPE_SDCARD (1UL<<4) #define SUBTYPE_CTRN 0 #define SUBTYPE_CTRN_N 1 @@ -41,42 +44,27 @@ FATpartition DriveInfo[4] = { }; SubtypeDesc SubTypes[5] = { - { 0x05C980, 0x17AE80, 0x4 }, // O3DS CTRNAND - { 0x05C980, 0x20F680, 0x5 }, // N3DS CTRNAND - { 0x05C980, 0x20F680, 0x4 }, // N3DS CTRNAND (downgraded) - { 0x000097, 0x047DA9, 0x3 }, // TWLN - { 0x04808D, 0x0105B3, 0x3 } // TWLP + { 0x05C980, 0x17AE80, 0x04 }, // O3DS CTRNAND + { 0x05C980, 0x20F680, 0x05 }, // N3DS CTRNAND + { 0x05C980, 0x20F680, 0x04 }, // N3DS CTRNAND (downgraded) + { 0x000097, 0x047DA9, 0x03 }, // TWLN + { 0x04808D, 0x0105B3, 0x03 } // TWLP }; static BYTE nand_type_sys = 0; -/*-----------------------------------------------------------------------*/ -/* Get actual FAT partition type helper */ -/*-----------------------------------------------------------------------*/ - -static inline BYTE get_partition_type( - __attribute__((unused)) - BYTE pdrv /* Physical drive number to identify the drive */ -) -{ - return DriveInfo[pdrv].type; -} - - - /*-----------------------------------------------------------------------*/ /* Get Drive Subtype helper */ /*-----------------------------------------------------------------------*/ static inline SubtypeDesc* get_subtype_desc( __attribute__((unused)) - BYTE pdrv /* Physical drive number to identify the drive */ + BYTE pdrv /* Physical drive number to identify the drive */ ) { - BYTE type = get_partition_type(pdrv); - BYTE subtype = (type) ? DriveInfo[pdrv].subtype : SUBTYPE_NONE; + BYTE subtype = PART_SUBTYPE(pdrv); if (subtype == SUBTYPE_NONE) { return NULL; @@ -95,8 +83,8 @@ static inline SubtypeDesc* get_subtype_desc( /*-----------------------------------------------------------------------*/ DSTATUS disk_status ( - __attribute__((unused)) - BYTE pdrv /* Physical drive number to identify the drive */ + __attribute__((unused)) + BYTE pdrv /* Physical drive number to identify the drive */ ) { return RES_OK; @@ -109,8 +97,8 @@ DSTATUS disk_status ( /*-----------------------------------------------------------------------*/ DSTATUS disk_initialize ( - __attribute__((unused)) - BYTE pdrv /* Physical drive number to identify the drive */ + __attribute__((unused)) + BYTE pdrv /* Physical drive number to identify the drive */ ) { if (pdrv == 0) { // a mounted SD card is the preriquisite for everything else @@ -119,7 +107,7 @@ DSTATUS disk_initialize ( nand_type_sys = CheckNandType(); if (!nand_type_sys) return STA_NOINIT|STA_NODISK; } - return RES_OK; + return RES_OK; } @@ -129,14 +117,14 @@ DSTATUS disk_initialize ( /*-----------------------------------------------------------------------*/ DRESULT disk_read ( - __attribute__((unused)) - BYTE pdrv, /* Physical drive number to identify the drive */ - BYTE *buff, /* Data buffer to store read data */ - DWORD sector, /* Sector address in LBA */ - UINT count /* Number of sectors to read */ + __attribute__((unused)) + BYTE pdrv, /* Physical drive number to identify the drive */ + BYTE *buff, /* Data buffer to store read data */ + DWORD sector, /* Sector address in LBA */ + UINT count /* Number of sectors to read */ ) { - BYTE type = get_partition_type(pdrv); + BYTE type = PART_TYPE(pdrv); if (type == TYPE_NONE) { return RES_PARERR; @@ -152,7 +140,7 @@ DRESULT disk_read ( return RES_PARERR; } - return RES_OK; + return RES_OK; } @@ -163,14 +151,14 @@ DRESULT disk_read ( #if _USE_WRITE DRESULT disk_write ( - __attribute__((unused)) - BYTE pdrv, /* Physical drive number to identify the drive */ - const BYTE *buff, /* Data to be written */ - DWORD sector, /* Sector address in LBA */ - UINT count /* Number of sectors to write */ + __attribute__((unused)) + BYTE pdrv, /* Physical drive number to identify the drive */ + const BYTE *buff, /* Data to be written */ + DWORD sector, /* Sector address in LBA */ + UINT count /* Number of sectors to write */ ) { - BYTE type = get_partition_type(pdrv); + BYTE type = PART_TYPE(pdrv); if (type == TYPE_NONE) { return RES_PARERR; @@ -186,7 +174,7 @@ DRESULT disk_write ( return RES_PARERR; // unstubbed! } - return RES_OK; + return RES_OK; } #endif @@ -198,15 +186,15 @@ DRESULT disk_write ( #if _USE_IOCTL DRESULT disk_ioctl ( - __attribute__((unused)) - BYTE pdrv, /* Physical drive number (0..) */ - __attribute__((unused)) - BYTE cmd, /* Control code */ - __attribute__((unused)) - void *buff /* Buffer to send/receive control data */ + __attribute__((unused)) + BYTE pdrv, /* Physical drive number (0..) */ + __attribute__((unused)) + BYTE cmd, /* Control code */ + __attribute__((unused)) + void *buff /* Buffer to send/receive control data */ ) { - BYTE type = get_partition_type(pdrv); + BYTE type = PART_TYPE(pdrv); switch (cmd) { case GET_SECTOR_SIZE: @@ -227,6 +215,6 @@ DRESULT disk_ioctl ( return RES_OK; } - return RES_PARERR; + return RES_PARERR; } #endif diff --git a/source/fatfs/ff.c b/source/fatfs/ff.c index b398e87..0c735e0 100644 --- a/source/fatfs/ff.c +++ b/source/fatfs/ff.c @@ -4941,7 +4941,7 @@ FRESULT f_setlabel ( dj.obj.fs = fs; /* Get length of given volume label */ - for (slen = 0; (UINT)label[slen] >= ' '; slen++) ; /* Get name length */ + for (slen = 0; (UINT)label[slen] >= ' '; slen++) {} /* Get name length */ #if _FS_EXFAT if (fs->fs_type == FS_EXFAT) { /* On the exFAT volume */ diff --git a/source/fatfs/ffconf.h b/source/fatfs/ffconf.h index 9ab7e88..4dfaa3e 100644 --- a/source/fatfs/ffconf.h +++ b/source/fatfs/ffconf.h @@ -229,7 +229,7 @@ / These options have no effect at read-only configuration (_FS_READONLY = 1). */ -#define _FS_LOCK 8 +#define _FS_LOCK 32 /* The option _FS_LOCK switches file lock function to control duplicated file open / and illegal operation to open objects. This option must be 0 when _FS_READONLY / is 1. diff --git a/source/fatfs/qff.c b/source/fatfs/qff.c index 3cf2ba5..110f939 100644 --- a/source/fatfs/qff.c +++ b/source/fatfs/qff.c @@ -6,7 +6,7 @@ static FATFS* fs = (FATFS*) 0x20316000; // currently open file systems -static FRESULT fs_mounted[NUM_FS] = { FR_NOT_READY }; +static FRESULT fs_mounted[NUM_FS]; FRESULT f_qread (const TCHAR* path, void* buff, FSIZE_t ofs, UINT btr, UINT* br) { FIL fp; @@ -50,7 +50,7 @@ FRESULT f_qwrite (const TCHAR* path, const void* buff, FSIZE_t ofs, UINT btw, UI return res; } -FATFS* fs_getobj(const TCHAR* path) { +FATFS* fs_getobj (const TCHAR* path) { UINT fsnum = (path[1] == ':') ? *path - '0' : -1; return ((fsnum < NUM_FS) && (fs_mounted[fsnum] == FR_OK)) ? &fs[fsnum] : (FATFS*) 0; } @@ -80,7 +80,6 @@ FRESULT fs_init(void) { for (UINT i = 0; i < NUM_FS; i++) { TCHAR* fsname = "X:"; *fsname = (TCHAR) ('0' + i); - if (fs_mounted[i] == FR_OK) continue; fs_mounted[i] = f_mount(fs + i, fsname, 1); if ((fs_mounted[i] != FR_OK) && (i == 0)) return fs_mounted[i]; // SD can't fail } diff --git a/source/main.c b/source/main.c index 3f80a39..fa1e92d 100644 --- a/source/main.c +++ b/source/main.c @@ -3,6 +3,7 @@ #include "i2c.h" #include "qff.h" + void Reboot() { i2cWriteRegister(I2C_DEV_MCU, 0x20, 1 << 2);