Improved the waitInput function basing on code from @d0k3, added support for the power button, added possibiity to quit the payload loader menu with START

This commit is contained in:
Aurora 2016-11-13 22:13:24 +01:00
parent 6d3113c8c3
commit c83edea7ad
11 changed files with 110 additions and 69 deletions

View File

@ -39,9 +39,9 @@
#define BUTTON_UP (1 << 6) #define BUTTON_UP (1 << 6)
#define BUTTON_DOWN (1 << 7) #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 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 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 (DPAD_BUTTONS | BUTTON_A | BUTTON_START)
#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 | DPAD_BUTTONS | BUTTON_START)
#define PIN_BUTTONS (BUTTON_A | BUTTON_B | BUTTON_X | BUTTON_Y | BUTTON_LEFT | BUTTON_RIGHT | BUTTON_UP | BUTTON_DOWN | BUTTON_START)

View File

@ -239,12 +239,12 @@ void configMenu(bool isSdMode, bool oldPinStatus, u32 oldPinMode)
initScreens(); initScreens();
drawString(CONFIG_TITLE, true, 10, 10, COLOR_TITLE); 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 //Character to display a selected option
char selected = 'x'; char selected = 'x';
u32 endPos = 42; u32 endPos = 10 + 2 * SPACING_Y;
//Display all the multiple choice options in white //Display all the multiple choice options in white
for(u32 i = 0; i < multiOptionsAmount; i++) for(u32 i = 0; i < multiOptionsAmount; i++)
@ -286,7 +286,7 @@ void configMenu(bool isSdMode, bool oldPinStatus, u32 oldPinMode)
{ {
do do
{ {
pressed = waitInput(); pressed = waitInput(true);
} }
while(!(pressed & MENU_BUTTONS)); while(!(pressed & MENU_BUTTONS));
@ -394,8 +394,7 @@ void configMenu(bool isSdMode, bool oldPinStatus, u32 oldPinMode)
if(newPinMode != 0) newPin(oldPinStatus && newPinMode == oldPinMode, newPinMode); if(newPinMode != 0) newPin(oldPinStatus && newPinMode == oldPinMode, newPinMode);
else if(oldPinStatus) fileDelete(PIN_FILE); else if(oldPinStatus) fileDelete(PIN_FILE);
//Wait for the pressed buttons to change
while(HID_PAD & PIN_BUTTONS); while(HID_PAD & PIN_BUTTONS);
startChrono();
chrono(2); while(chrono(false) < 2);
} }

View File

@ -56,7 +56,8 @@ bool loadSplash(void)
{ {
swapFramebuffers(true); swapFramebuffers(true);
chrono(3); startChrono();
while(chrono(false) < 3);
ret = true; ret = true;
} }

View File

@ -204,7 +204,7 @@ void detectAndProcessExceptionDumps(void)
memset32((void *)dumpHeader, 0, dumpHeader->totalSize); memset32((void *)dumpHeader, 0, dumpHeader->totalSize);
waitInput(); waitInput(false);
mcuPowerOff(); mcuPowerOff();
} }
} }

View File

@ -196,9 +196,9 @@ void payloadMenu(void)
{ {
FILINFO info; FILINFO info;
u32 payloadNum = 0; 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) if(info.fname[0] != '.' && memcmp(info.altname + 8, ".BIN", 4) == 0)
{ {
u32 nameLength = strlen(info.fname) - 4; u32 nameLength = strlen(info.fname) - 4;
@ -216,9 +216,10 @@ void payloadMenu(void)
{ {
initScreens(); 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); drawString(payloadList[i], true, 10, posY, color);
if(color == COLOR_RED) color = COLOR_WHITE; if(color == COLOR_RED) color = COLOR_WHITE;
@ -227,11 +228,11 @@ void payloadMenu(void)
u32 pressed = 0, u32 pressed = 0,
selectedPayload = 0; selectedPayload = 0;
while(pressed != BUTTON_A) while(!(pressed & (BUTTON_A | BUTTON_START)))
{ {
do do
{ {
pressed = waitInput(); pressed = waitInput(true);
} }
while(!(pressed & MENU_BUTTONS)); while(!(pressed & MENU_BUTTONS));
@ -257,15 +258,22 @@ void payloadMenu(void)
if(oldSelectedPayload == selectedPayload) continue; if(oldSelectedPayload == selectedPayload) continue;
drawString(payloadList[oldSelectedPayload], true, 10, 30 + oldSelectedPayload * SPACING_Y, COLOR_WHITE); drawString(payloadList[oldSelectedPayload], true, 10, 10 + (3 + oldSelectedPayload) * SPACING_Y, COLOR_WHITE);
drawString(payloadList[selectedPayload], true, 10, 30 + selectedPayload * SPACING_Y, COLOR_RED); drawString(payloadList[selectedPayload], true, 10, 10 + (3 + selectedPayload) * SPACING_Y, COLOR_RED);
} }
concatenateStrings(path, "/"); if(pressed == BUTTON_A)
concatenateStrings(path, payloadList[selectedPayload]); {
concatenateStrings(path, ".bin"); concatenateStrings(path, "/");
loadPayload(0, path); concatenateStrings(path, payloadList[selectedPayload]);
error("The payload is too large or corrupted."); concatenateStrings(path, ".bin");
loadPayload(0, path);
error("The payload is too large or corrupted.");
}
while(HID_PAD & MENU_BUTTONS);
startChrono();
while(chrono(false) < 2);
} }
} }
} }

View File

@ -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) bool i2cWriteRegister(u8 dev_id, u8 reg, u8 data)
{ {
u8 bus_id = i2cGetDeviceBusId(dev_id), u8 bus_id = i2cGetDeviceBusId(dev_id),

View File

@ -41,4 +41,5 @@
#define I2C_DEV_GYRO 10 #define I2C_DEV_GYRO 10
#define I2C_DEV_IR 13 #define I2C_DEV_IR 13
u8 i2cReadRegister(u8 dev_id, u8 reg);
bool i2cWriteRegister(u8 dev_id, u8 reg, u8 data); bool i2cWriteRegister(u8 dev_id, u8 reg, u8 data);

View File

@ -148,7 +148,8 @@ void main(void)
if(pinExists && !shouldLoadConfigMenu) if(pinExists && !shouldLoadConfigMenu)
{ {
while(HID_PAD & PIN_BUTTONS); while(HID_PAD & PIN_BUTTONS);
chrono(2); startChrono();
while(chrono(false) < 2);
} }
} }
else else
@ -157,10 +158,11 @@ void main(void)
if(splashMode == 1 && loadSplash()) pressed = HID_PAD; if(splashMode == 1 && loadSplash()) pressed = HID_PAD;
if((pressed & (BUTTON_START | BUTTON_L1)) == BUTTON_START) payloadMenu(); if((pressed & (BUTTON_START | BUTTON_L1)) == BUTTON_START)
{
/* If L and R/A/Select or one of the single payload buttons are pressed, payloadMenu();
chainload an external payload */ pressed = HID_PAD;
}
else if(((pressed & SINGLE_PAYLOAD_BUTTONS) && !(pressed & (BUTTON_L1 | BUTTON_R1 | BUTTON_A))) || else if(((pressed & SINGLE_PAYLOAD_BUTTONS) && !(pressed & (BUTTON_L1 | BUTTON_R1 | BUTTON_A))) ||
((pressed & L_PAYLOAD_BUTTONS) && (pressed & BUTTON_L1))) loadPayload(pressed, NULL); ((pressed & L_PAYLOAD_BUTTONS) && (pressed & BUTTON_L1))) loadPayload(pressed, NULL);
@ -192,7 +194,7 @@ void main(void)
if(nandType == FIRMWARE_EMUNAND || firmSource == FIRMWARE_EMUNAND) if(nandType == FIRMWARE_EMUNAND || firmSource == FIRMWARE_EMUNAND)
{ {
FirmwareSource tempNand; FirmwareSource tempNand;
switch(pressed & EMUNAND_BUTTONS) switch(pressed & DPAD_BUTTONS)
{ {
case BUTTON_UP: case BUTTON_UP:
tempNand = FIRMWARE_EMUNAND; tempNand = FIRMWARE_EMUNAND;

View File

@ -66,7 +66,7 @@ void newPin(bool allowSkipping, u32 pinMode)
u32 pressed; u32 pressed;
do do
{ {
pressed = waitInput(); pressed = waitInput(false);
} }
while(!(pressed & PIN_BUTTONS)); while(!(pressed & PIN_BUTTONS));
@ -156,7 +156,7 @@ bool verifyPin(u32 pinMode)
u32 pressed; u32 pressed;
do do
{ {
pressed = waitInput(); pressed = waitInput(false);
} }
while(!(pressed & PIN_BUTTONS)); while(!(pressed & PIN_BUTTONS));

View File

@ -20,6 +20,10 @@
* Notices displayed by works containing it. * 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 "utils.h"
#include "i2c.h" #include "i2c.h"
#include "buttons.h" #include "buttons.h"
@ -27,29 +31,37 @@
#include "draw.h" #include "draw.h"
#include "cache.h" #include "cache.h"
u32 waitInput(void) u32 waitInput(bool isMenu)
{ {
static u64 dPadDelay = 0;
bool pressedKey = false; bool pressedKey = false;
u32 key; u32 key,
oldKey = HID_PAD;
//Wait for no keys to be pressed if(isMenu)
while(HID_PAD);
do
{ {
//Wait for a key to be pressed dPadDelay = dPadDelay > 0 ? 87 : 143;
while(!HID_PAD); startChrono();
}
while(!pressedKey)
{
key = HID_PAD; key = HID_PAD;
//Make sure it's pressed if(!key)
for(u32 i = 0x13000; i > 0; i--)
{ {
if(key != HID_PAD) break; if(i2cReadRegister(I2C_DEV_MCU, 0x10) == 1) mcuPowerOff();
if(i == 1) pressedKey = true; 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; return key;
} }
@ -65,38 +77,26 @@ void mcuPowerOff(void)
while(true); while(true);
} }
static inline void startChrono(u64 initialTicks) void startChrono(void)
{ {
REG_TIMER_CNT(0) = 0; //67MHz REG_TIMER_CNT(0) = 0; //67MHz
for(u32 i = 1; i < 4; i++) REG_TIMER_CNT(i) = 4; //Count-up 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 REG_TIMER_CNT(0) = 0x80; //67MHz; enabled
for(u32 i = 1; i < 4; i++) REG_TIMER_CNT(i) = 0x84; //Count-up; 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; u64 res;
do for(u32 i = 0; i < 4; i++) res |= REG_TIMER_VAL(i) << (16 * i);
{
res = 0;
for(u32 i = 0; i < 4; i++) res |= REG_TIMER_VAL(i) << (16 * i);
}
while(res - startingTicks < seconds * TICKS_PER_SEC);
stopChrono(); if(isMilliseconds) res /= (TICKS_PER_SEC / 1000);
else res /= TICKS_PER_SEC;
return res;
} }
void error(const char *message) void error(const char *message)
@ -109,7 +109,7 @@ void error(const char *message)
u32 posY = drawString(message, true, 10, 30, COLOR_WHITE); u32 posY = drawString(message, true, 10, 30, COLOR_WHITE);
drawString("Press any button to shutdown", true, 10, posY + 2 * SPACING_Y, COLOR_WHITE); drawString("Press any button to shutdown", true, 10, posY + 2 * SPACING_Y, COLOR_WHITE);
waitInput(); waitInput(false);
} }
mcuPowerOff(); mcuPowerOff();

View File

@ -20,6 +20,10 @@
* Notices displayed by works containing it. * 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 #pragma once
#include "types.h" #include "types.h"
@ -28,7 +32,8 @@
#define REG_TIMER_CNT(i) *(vu16 *)(0x10003002 + 4 * i) #define REG_TIMER_CNT(i) *(vu16 *)(0x10003002 + 4 * i)
#define REG_TIMER_VAL(i) *(vu16 *)(0x10003000 + 4 * i) #define REG_TIMER_VAL(i) *(vu16 *)(0x10003000 + 4 * i)
u32 waitInput(void); u32 waitInput(bool isMenu);
void mcuPowerOff(void); void mcuPowerOff(void);
void chrono(u32 seconds); void startChrono(void);
u64 chrono(bool isMilliseconds);
void error(const char *message); void error(const char *message);