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:
parent
6d3113c8c3
commit
c83edea7ad
@ -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)
|
||||
#define MENU_BUTTONS (DPAD_BUTTONS | BUTTON_A | BUTTON_START)
|
||||
#define PIN_BUTTONS (BUTTON_A | BUTTON_B | BUTTON_X | BUTTON_Y | DPAD_BUTTONS | BUTTON_START)
|
@ -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);
|
||||
}
|
@ -56,7 +56,8 @@ bool loadSplash(void)
|
||||
{
|
||||
swapFramebuffers(true);
|
||||
|
||||
chrono(3);
|
||||
startChrono();
|
||||
while(chrono(false) < 3);
|
||||
|
||||
ret = true;
|
||||
}
|
||||
|
@ -204,7 +204,7 @@ void detectAndProcessExceptionDumps(void)
|
||||
|
||||
memset32((void *)dumpHeader, 0, dumpHeader->totalSize);
|
||||
|
||||
waitInput();
|
||||
waitInput(false);
|
||||
mcuPowerOff();
|
||||
}
|
||||
}
|
24
source/fs.c
24
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,16 +258,23 @@ 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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
25
source/i2c.c
25
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),
|
||||
|
@ -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);
|
@ -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;
|
||||
|
@ -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));
|
||||
|
||||
|
@ -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);
|
||||
|
||||
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();
|
||||
|
@ -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);
|
Reference in New Issue
Block a user