diff --git a/source/buttons.h b/source/buttons.h index 543fa25..3d034c1 100644 --- a/source/buttons.h +++ b/source/buttons.h @@ -39,9 +39,9 @@ #define BUTTON_UP (1 << 6) #define BUTTON_DOWN (1 << 7) +#define DPAD_BUTTONS (BUTTON_LEFT | BUTTON_RIGHT | BUTTON_UP | BUTTON_DOWN) #define SAFE_MODE (BUTTON_R1 | BUTTON_L1 | BUTTON_A | BUTTON_UP) -#define SINGLE_PAYLOAD_BUTTONS (BUTTON_LEFT | BUTTON_RIGHT | BUTTON_UP | BUTTON_DOWN | BUTTON_B | BUTTON_X | BUTTON_Y) +#define SINGLE_PAYLOAD_BUTTONS (DPAD_BUTTONS | BUTTON_B | BUTTON_X | BUTTON_Y) #define L_PAYLOAD_BUTTONS (BUTTON_R1 | BUTTON_A | BUTTON_START | BUTTON_SELECT) -#define EMUNAND_BUTTONS (BUTTON_LEFT | BUTTON_RIGHT | BUTTON_UP | BUTTON_DOWN) -#define MENU_BUTTONS (BUTTON_LEFT | BUTTON_RIGHT | BUTTON_UP | BUTTON_DOWN | BUTTON_A | BUTTON_START) -#define PIN_BUTTONS (BUTTON_A | BUTTON_B | BUTTON_X | BUTTON_Y | BUTTON_LEFT | BUTTON_RIGHT | BUTTON_UP | BUTTON_DOWN | BUTTON_START) \ No newline at end of file +#define MENU_BUTTONS (DPAD_BUTTONS | BUTTON_A | BUTTON_START) +#define PIN_BUTTONS (BUTTON_A | BUTTON_B | BUTTON_X | BUTTON_Y | DPAD_BUTTONS | BUTTON_START) \ No newline at end of file diff --git a/source/config.c b/source/config.c index fd8c3b4..935ccdb 100644 --- a/source/config.c +++ b/source/config.c @@ -239,12 +239,12 @@ void configMenu(bool isSdMode, bool oldPinStatus, u32 oldPinMode) initScreens(); drawString(CONFIG_TITLE, true, 10, 10, COLOR_TITLE); - drawString("Press A to select, START to save", true, 10, 30, COLOR_WHITE); + drawString("Press A to select, START to save", true, 10, 10 + SPACING_Y, COLOR_TITLE); //Character to display a selected option char selected = 'x'; - u32 endPos = 42; + u32 endPos = 10 + 2 * SPACING_Y; //Display all the multiple choice options in white for(u32 i = 0; i < multiOptionsAmount; i++) @@ -286,7 +286,7 @@ void configMenu(bool isSdMode, bool oldPinStatus, u32 oldPinMode) { do { - pressed = waitInput(); + pressed = waitInput(true); } while(!(pressed & MENU_BUTTONS)); @@ -394,8 +394,7 @@ void configMenu(bool isSdMode, bool oldPinStatus, u32 oldPinMode) if(newPinMode != 0) newPin(oldPinStatus && newPinMode == oldPinMode, newPinMode); else if(oldPinStatus) fileDelete(PIN_FILE); - //Wait for the pressed buttons to change while(HID_PAD & PIN_BUTTONS); - - chrono(2); + startChrono(); + while(chrono(false) < 2); } \ No newline at end of file diff --git a/source/draw.c b/source/draw.c index df0c0ee..edcf582 100644 --- a/source/draw.c +++ b/source/draw.c @@ -56,7 +56,8 @@ bool loadSplash(void) { swapFramebuffers(true); - chrono(3); + startChrono(); + while(chrono(false) < 3); ret = true; } diff --git a/source/exceptions.c b/source/exceptions.c index ff295f8..ee53f08 100644 --- a/source/exceptions.c +++ b/source/exceptions.c @@ -204,7 +204,7 @@ void detectAndProcessExceptionDumps(void) memset32((void *)dumpHeader, 0, dumpHeader->totalSize); - waitInput(); + waitInput(false); mcuPowerOff(); } } \ No newline at end of file diff --git a/source/fs.c b/source/fs.c index 866b23e..9641bbd 100644 --- a/source/fs.c +++ b/source/fs.c @@ -196,9 +196,9 @@ void payloadMenu(void) { FILINFO info; u32 payloadNum = 0; - char payloadList[21][49]; + char payloadList[20][49]; - while(f_readdir(&dir, &info) == FR_OK && info.fname[0] != 0 && payloadNum < 21) + while(f_readdir(&dir, &info) == FR_OK && info.fname[0] != 0 && payloadNum < 20) if(info.fname[0] != '.' && memcmp(info.altname + 8, ".BIN", 4) == 0) { u32 nameLength = strlen(info.fname) - 4; @@ -216,9 +216,10 @@ void payloadMenu(void) { initScreens(); - drawString("Luma3DS chainloader - Press A to select", true, 10, 10, COLOR_TITLE); + drawString("Luma3DS chainloader", true, 10, 10, COLOR_TITLE); + drawString("Press A to select, START to quit", true, 10, 10 + SPACING_Y, COLOR_TITLE); - for(u32 i = 0, posY = 30, color = COLOR_RED; i < payloadNum; i++, posY += SPACING_Y) + for(u32 i = 0, posY = 10 + 3 * SPACING_Y, color = COLOR_RED; i < payloadNum; i++, posY += SPACING_Y) { drawString(payloadList[i], true, 10, posY, color); if(color == COLOR_RED) color = COLOR_WHITE; @@ -227,11 +228,11 @@ void payloadMenu(void) u32 pressed = 0, selectedPayload = 0; - while(pressed != BUTTON_A) + while(!(pressed & (BUTTON_A | BUTTON_START))) { do { - pressed = waitInput(); + pressed = waitInput(true); } while(!(pressed & MENU_BUTTONS)); @@ -257,15 +258,22 @@ void payloadMenu(void) if(oldSelectedPayload == selectedPayload) continue; - drawString(payloadList[oldSelectedPayload], true, 10, 30 + oldSelectedPayload * SPACING_Y, COLOR_WHITE); - drawString(payloadList[selectedPayload], true, 10, 30 + selectedPayload * SPACING_Y, COLOR_RED); + drawString(payloadList[oldSelectedPayload], true, 10, 10 + (3 + oldSelectedPayload) * SPACING_Y, COLOR_WHITE); + drawString(payloadList[selectedPayload], true, 10, 10 + (3 + selectedPayload) * SPACING_Y, COLOR_RED); } - concatenateStrings(path, "/"); - concatenateStrings(path, payloadList[selectedPayload]); - concatenateStrings(path, ".bin"); - loadPayload(0, path); - error("The payload is too large or corrupted."); + if(pressed == BUTTON_A) + { + concatenateStrings(path, "/"); + concatenateStrings(path, payloadList[selectedPayload]); + concatenateStrings(path, ".bin"); + loadPayload(0, path); + error("The payload is too large or corrupted."); + } + + while(HID_PAD & MENU_BUTTONS); + startChrono(); + while(chrono(false) < 2); } } } diff --git a/source/i2c.c b/source/i2c.c index 3367034..8b7c250 100644 --- a/source/i2c.c +++ b/source/i2c.c @@ -115,6 +115,31 @@ static bool i2cSelectRegister(u8 bus_id, u8 reg) //----------------------------------------------------------------------------- +u8 i2cReadRegister(u8 dev_id, u8 reg) +{ + u8 bus_id = i2cGetDeviceBusId(dev_id), + dev_addr = i2cGetDeviceRegAddr(dev_id); + + for(u32 i = 0; i < 8; i++) + { + if(i2cSelectDevice(bus_id, dev_addr) && i2cSelectRegister(bus_id, reg)) + { + if(i2cSelectDevice(bus_id, dev_addr | 1)) + { + i2cWaitBusy(bus_id); + i2cStop(bus_id, 1); + i2cWaitBusy(bus_id); + + return *i2cGetDataReg(bus_id); + } + } + *i2cGetCntReg(bus_id) = 0xC5; + i2cWaitBusy(bus_id); + } + + return 0xFF; +} + bool i2cWriteRegister(u8 dev_id, u8 reg, u8 data) { u8 bus_id = i2cGetDeviceBusId(dev_id), diff --git a/source/i2c.h b/source/i2c.h index 0099d61..f00a301 100644 --- a/source/i2c.h +++ b/source/i2c.h @@ -41,4 +41,5 @@ #define I2C_DEV_GYRO 10 #define I2C_DEV_IR 13 +u8 i2cReadRegister(u8 dev_id, u8 reg); bool i2cWriteRegister(u8 dev_id, u8 reg, u8 data); \ No newline at end of file diff --git a/source/main.c b/source/main.c index 9ea3831..4280361 100644 --- a/source/main.c +++ b/source/main.c @@ -148,7 +148,8 @@ void main(void) if(pinExists && !shouldLoadConfigMenu) { while(HID_PAD & PIN_BUTTONS); - chrono(2); + startChrono(); + while(chrono(false) < 2); } } else @@ -157,10 +158,11 @@ void main(void) if(splashMode == 1 && loadSplash()) pressed = HID_PAD; - if((pressed & (BUTTON_START | BUTTON_L1)) == BUTTON_START) payloadMenu(); - - /* If L and R/A/Select or one of the single payload buttons are pressed, - chainload an external payload */ + if((pressed & (BUTTON_START | BUTTON_L1)) == BUTTON_START) + { + payloadMenu(); + pressed = HID_PAD; + } else if(((pressed & SINGLE_PAYLOAD_BUTTONS) && !(pressed & (BUTTON_L1 | BUTTON_R1 | BUTTON_A))) || ((pressed & L_PAYLOAD_BUTTONS) && (pressed & BUTTON_L1))) loadPayload(pressed, NULL); @@ -192,7 +194,7 @@ void main(void) if(nandType == FIRMWARE_EMUNAND || firmSource == FIRMWARE_EMUNAND) { FirmwareSource tempNand; - switch(pressed & EMUNAND_BUTTONS) + switch(pressed & DPAD_BUTTONS) { case BUTTON_UP: tempNand = FIRMWARE_EMUNAND; diff --git a/source/pin.c b/source/pin.c index 3b56a2f..2c380e5 100644 --- a/source/pin.c +++ b/source/pin.c @@ -66,7 +66,7 @@ void newPin(bool allowSkipping, u32 pinMode) u32 pressed; do { - pressed = waitInput(); + pressed = waitInput(false); } while(!(pressed & PIN_BUTTONS)); @@ -156,7 +156,7 @@ bool verifyPin(u32 pinMode) u32 pressed; do { - pressed = waitInput(); + pressed = waitInput(false); } while(!(pressed & PIN_BUTTONS)); diff --git a/source/utils.c b/source/utils.c index a210d6f..60af492 100644 --- a/source/utils.c +++ b/source/utils.c @@ -20,6 +20,10 @@ * Notices displayed by works containing it. */ +/* +* waitInput function based on code by d0k3 https://github.com/d0k3/Decrypt9WIP/blob/master/source/hid.c +*/ + #include "utils.h" #include "i2c.h" #include "buttons.h" @@ -27,29 +31,37 @@ #include "draw.h" #include "cache.h" -u32 waitInput(void) +u32 waitInput(bool isMenu) { + static u64 dPadDelay = 0; bool pressedKey = false; - u32 key; + u32 key, + oldKey = HID_PAD; - //Wait for no keys to be pressed - while(HID_PAD); - - do + if(isMenu) { - //Wait for a key to be pressed - while(!HID_PAD); + dPadDelay = dPadDelay > 0 ? 87 : 143; + startChrono(); + } + while(!pressedKey) + { key = HID_PAD; - //Make sure it's pressed - for(u32 i = 0x13000; i > 0; i--) + if(!key) { - if(key != HID_PAD) break; - if(i == 1) pressedKey = true; + if(i2cReadRegister(I2C_DEV_MCU, 0x10) == 1) mcuPowerOff(); + oldKey = key; + dPadDelay = 0; + } + else if((key != oldKey) || (isMenu && (key & DPAD_BUTTONS) != 0 && (chrono(true) >= dPadDelay))) + { + //Make sure the key is pressed + u32 i; + for(i = 0; i < 0x13000 && key == HID_PAD; i++); + if(i == 0x13000) pressedKey = true; } } - while(!pressedKey); return key; } @@ -65,38 +77,26 @@ void mcuPowerOff(void) while(true); } -static inline void startChrono(u64 initialTicks) +void startChrono(void) { REG_TIMER_CNT(0) = 0; //67MHz for(u32 i = 1; i < 4; i++) REG_TIMER_CNT(i) = 4; //Count-up - for(u32 i = 0; i < 4; i++) REG_TIMER_VAL(i) = (u16)(initialTicks >> (16 * i)); + for(u32 i = 0; i < 4; i++) REG_TIMER_VAL(i) = 0; REG_TIMER_CNT(0) = 0x80; //67MHz; enabled for(u32 i = 1; i < 4; i++) REG_TIMER_CNT(i) = 0x84; //Count-up; enabled } -static inline void stopChrono(void) +u64 chrono(bool isMilliseconds) { - for(u32 i = 0; i < 4; i++) REG_TIMER_CNT(i) &= ~0x80; -} - -void chrono(u32 seconds) -{ - startChrono(0); - - u64 startingTicks = 0; - for(u32 i = 0; i < 4; i++) startingTicks |= REG_TIMER_VAL(i) << (16 * i); - u64 res; - do - { - res = 0; - for(u32 i = 0; i < 4; i++) res |= REG_TIMER_VAL(i) << (16 * i); - } - while(res - startingTicks < seconds * TICKS_PER_SEC); + for(u32 i = 0; i < 4; i++) res |= REG_TIMER_VAL(i) << (16 * i); - stopChrono(); + if(isMilliseconds) res /= (TICKS_PER_SEC / 1000); + else res /= TICKS_PER_SEC; + + return res; } void error(const char *message) @@ -109,7 +109,7 @@ void error(const char *message) u32 posY = drawString(message, true, 10, 30, COLOR_WHITE); drawString("Press any button to shutdown", true, 10, posY + 2 * SPACING_Y, COLOR_WHITE); - waitInput(); + waitInput(false); } mcuPowerOff(); diff --git a/source/utils.h b/source/utils.h index 501de67..1504ffe 100644 --- a/source/utils.h +++ b/source/utils.h @@ -20,6 +20,10 @@ * Notices displayed by works containing it. */ +/* +* waitInput function based on code by d0k3 https://github.com/d0k3/Decrypt9WIP/blob/master/source/hid.c +*/ + #pragma once #include "types.h" @@ -28,7 +32,8 @@ #define REG_TIMER_CNT(i) *(vu16 *)(0x10003002 + 4 * i) #define REG_TIMER_VAL(i) *(vu16 *)(0x10003000 + 4 * i) -u32 waitInput(void); +u32 waitInput(bool isMenu); void mcuPowerOff(void); -void chrono(u32 seconds); +void startChrono(void); +u64 chrono(bool isMilliseconds); void error(const char *message); \ No newline at end of file