Implement autobooting into homebrew (3DS and DSi modes)
Add config option to autoboot into 3DS and DSi homebrew menu, without going through Home Menu (nor launching it). For 3DS homebrew, this requires homebrew built with libctru v2.0.0 or later (v2.0.0 was released 2.5y ago). We simulate a "reboot into title" to achieve this. This being said, when launching stuff like Pokemon US/UM on O3DS, Home Menu reboots into itself and not the game directly. This will cause Home Menu to crash if you use this feature and configure it to use a non-default memory layout (but if you don't, Home Menu will work just fine).
This commit is contained in:
parent
0a6b6865ca
commit
fe4bb0857b
Binary file not shown.
@ -319,8 +319,14 @@ static int configIniHandler(void* user, const char* section, const char* name, c
|
||||
} else {
|
||||
CHECK_PARSE_OPTION(-1);
|
||||
}
|
||||
} else if (strcmp(name, "autoboot_mode") == 0) {
|
||||
s64 opt;
|
||||
CHECK_PARSE_OPTION(parseDecIntOption(&opt, value, 0, 2));
|
||||
cfg->multiConfig |= (u32)opt << (2 * (u32)AUTOBOOTMODE);
|
||||
return 1;
|
||||
} else {
|
||||
CHECK_PARSE_OPTION(-1);
|
||||
}
|
||||
CHECK_PARSE_OPTION(-1);
|
||||
} else if (strcmp(section, "rosalina") == 0) {
|
||||
// Rosalina options
|
||||
if (strcmp(name, "hbldr_3dsx_titleid") == 0) {
|
||||
@ -347,6 +353,20 @@ static int configIniHandler(void* user, const char* section, const char* name, c
|
||||
else {
|
||||
CHECK_PARSE_OPTION(-1);
|
||||
}
|
||||
} else if (strcmp(section, "autoboot") == 0) {
|
||||
if (strcmp(name, "autoboot_dsi_titleid") == 0) {
|
||||
u64 opt;
|
||||
CHECK_PARSE_OPTION(parseHexIntOption(&opt, value, 0, 0xFFFFFFFFFFFFFFFFull));
|
||||
cfg->autobootTwlTitleId = opt;
|
||||
return 1;
|
||||
} else if (strcmp(name, "autoboot_3ds_app_mem_type") == 0) {
|
||||
s64 opt;
|
||||
CHECK_PARSE_OPTION(parseDecIntOption(&opt, value, 0, 4));
|
||||
cfg->autobootCtrAppmemtype = (u8)opt;
|
||||
return 1;
|
||||
} else {
|
||||
CHECK_PARSE_OPTION(-1);
|
||||
}
|
||||
} else if (strcmp(section, "misc") == 0) {
|
||||
for (size_t i = 0; i < sizeof(singleOptionIniNamesMisc)/sizeof(singleOptionIniNamesMisc[0]); i++) {
|
||||
if (strcmp(name, singleOptionIniNamesMisc[i]) == 0) {
|
||||
@ -414,11 +434,13 @@ static size_t saveLumaIniConfigToStr(char *out)
|
||||
|
||||
1 + (int)MULTICONFIG(DEFAULTEMU), 4 - (int)MULTICONFIG(BRIGHTNESS),
|
||||
splashPosStr, (unsigned int)cfg->splashDurationMsec,
|
||||
pinNumDigits, n3dsCpuStr,
|
||||
pinNumDigits, n3dsCpuStr, (int)MULTICONFIG(AUTOBOOTMODE),
|
||||
|
||||
cfg->hbldr3dsxTitleId, rosalinaMenuComboStr,
|
||||
(int)cfg->screenFiltersCct, (int)cfg->ntpTzOffetMinutes,
|
||||
|
||||
cfg->autobootTwlTitleId, (int)cfg->autobootCtrAppmemtype,
|
||||
|
||||
(int)CONFIG(PATCHUNITINFO), (int)CONFIG(DISABLEARM11EXCHANDLERS),
|
||||
(int)CONFIG(ENABLESAFEFIRMROSALINA)
|
||||
);
|
||||
@ -522,9 +544,10 @@ bool readConfig(void)
|
||||
configData.formatVersionMinor = CONFIG_VERSIONMINOR;
|
||||
configData.config |= 1u << PATCHVERSTRING;
|
||||
configData.splashDurationMsec = 3000;
|
||||
configData.hbldr3dsxTitleId = 0x000400000D921E00ull;
|
||||
configData.hbldr3dsxTitleId = HBLDR_DEFAULT_3DSX_TID;
|
||||
configData.rosalinaMenuCombo = 1u << 9 | 1u << 7 | 1u << 2; // L+Start+Select
|
||||
configData.screenFiltersCct = 6500; // default temp, no-op
|
||||
configData.autobootTwlTitleId = AUTOBOOT_DEFAULT_TWL_TID;
|
||||
ret = false;
|
||||
}
|
||||
else
|
||||
@ -566,6 +589,7 @@ void configMenu(bool oldPinStatus, u32 oldPinMode)
|
||||
"Splash: Off( ) Before( ) After( ) payloads",
|
||||
"PIN lock: Off( ) 4( ) 6( ) 8( ) digits",
|
||||
"New 3DS CPU: Off( ) Clock( ) L2( ) Clock+L2( )",
|
||||
"Homebrew autoboot: Off( ) 3DS( ) DSi( )",
|
||||
};
|
||||
|
||||
static const char *singleOptionsText[] = { "( ) Autoboot EmuNAND",
|
||||
@ -607,6 +631,14 @@ void configMenu(bool oldPinStatus, u32 oldPinMode)
|
||||
"'Clock+L2' can cause issues with some\n"
|
||||
"games.",
|
||||
|
||||
"Enable autobooting into homebrew,\n"
|
||||
"either into 3DS or DSi mode.\n\n"
|
||||
"Autobooting into a gamecard title is\n"
|
||||
"not supported.\n\n"
|
||||
"Refer to the \"autoboot\" section in the\n"
|
||||
"configuration file to configure\n"
|
||||
"this feature.",
|
||||
|
||||
"If enabled, an EmuNAND\n"
|
||||
"will be launched on boot.\n\n"
|
||||
"Otherwise, SysNAND will.\n\n"
|
||||
@ -675,6 +707,7 @@ void configMenu(bool oldPinStatus, u32 oldPinMode)
|
||||
{ .visible = true },
|
||||
{ .visible = true },
|
||||
{ .visible = ISN3DS },
|
||||
{ .visible = true },
|
||||
};
|
||||
|
||||
struct singleOption {
|
||||
|
@ -28,13 +28,16 @@
|
||||
|
||||
#include "types.h"
|
||||
|
||||
#define HBLDR_DEFAULT_3DSX_TID 0x000400000D921E00ull
|
||||
#define AUTOBOOT_DEFAULT_TWL_TID 0x0003000448424C41ull
|
||||
|
||||
#define CONFIG(a) (((configData.config >> (a)) & 1) != 0)
|
||||
#define MULTICONFIG(a) ((configData.multiConfig >> (2 * (a))) & 3)
|
||||
#define BOOTCONFIG(a, b) ((configData.bootConfig >> (a)) & (b))
|
||||
|
||||
#define CONFIG_FILE "config.bin"
|
||||
#define CONFIG_VERSIONMAJOR 3
|
||||
#define CONFIG_VERSIONMINOR 0
|
||||
#define CONFIG_VERSIONMINOR 1
|
||||
|
||||
#define BOOTCFG_NAND BOOTCONFIG(0, 7)
|
||||
#define BOOTCFG_FIRM BOOTCONFIG(3, 7)
|
||||
@ -47,7 +50,8 @@ enum multiOptions
|
||||
BRIGHTNESS,
|
||||
SPLASH,
|
||||
PIN,
|
||||
NEWCPU
|
||||
NEWCPU,
|
||||
AUTOBOOTMODE,
|
||||
};
|
||||
|
||||
enum singleOptions
|
||||
|
209
arm9/source/deliver_arg.c
Normal file
209
arm9/source/deliver_arg.c
Normal file
@ -0,0 +1,209 @@
|
||||
/*
|
||||
* This file is part of Luma3DS
|
||||
* Copyright (C) 2022 Aurora Wright, TuxSH
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Additional Terms 7.b and 7.c of GPLv3 apply to this file:
|
||||
* * Requiring preservation of specified reasonable legal notices or
|
||||
* author attributions in that material or in the Appropriate Legal
|
||||
* Notices displayed by works containing it.
|
||||
* * Prohibiting misrepresentation of the origin of that material,
|
||||
* or requiring that modified versions of such material be marked in
|
||||
* reasonable ways as different from the original version.
|
||||
*/
|
||||
|
||||
#include "deliver_arg.h"
|
||||
#include "utils.h"
|
||||
#include "memory.h"
|
||||
#include "config.h"
|
||||
|
||||
u8 *loadDeliverArg(void)
|
||||
{
|
||||
static u8 deliverArg[0x1000] = {0};
|
||||
static bool deliverArgLoaded = false;
|
||||
|
||||
if (!deliverArgLoaded)
|
||||
{
|
||||
u32 bootenv = CFG_BOOTENV; // this register is preserved across reboots
|
||||
if ((bootenv & 1) == 0) // true coldboot
|
||||
{
|
||||
memset(deliverArg, 0, 0x1000);
|
||||
}
|
||||
else
|
||||
{
|
||||
u32 mode = bootenv >> 1;
|
||||
if (mode == 0) // CTR mode
|
||||
{
|
||||
memcpy(deliverArg, (const void *)0x20000000, 0x1000);
|
||||
|
||||
// Validate deliver arg
|
||||
u32 testPattern = *(u32 *)(deliverArg + 0x438);
|
||||
u32 crc = *(u32 *)(deliverArg + 0x43C);
|
||||
u32 expectedCrc = crc32(deliverArg + 0x400, 0x140, 0xFFFFFFFF);
|
||||
if (testPattern != 0xFFFF || crc != expectedCrc)
|
||||
memset(deliverArg, 0, 0x1000);
|
||||
}
|
||||
else // Legacy modes
|
||||
{
|
||||
// Copy TWL deliver arg stuff as-is (0...0x300)
|
||||
copyFromLegacyModeFcram(deliverArg, (const void *)0x20000000, 0x400);
|
||||
|
||||
// Validate TLNC (TWL launcher params) block
|
||||
// Note: Nintendo doesn't do crcLen bound check
|
||||
u8 *tlnc = deliverArg + 0x300;
|
||||
bool hasMagic = memcmp(tlnc, "TLNC", 4) == 0;
|
||||
u8 crcLen = tlnc[5];
|
||||
u16 crc = *(u16 *)(tlnc + 6);
|
||||
if (!hasMagic || crcLen <= 248 || crc != crc16(tlnc + 8, crcLen, 0xFFFF))
|
||||
memset(tlnc, 0, 0x100);
|
||||
|
||||
memset(deliverArg + 0x400, 0, 0xC00);
|
||||
}
|
||||
}
|
||||
deliverArgLoaded = true;
|
||||
}
|
||||
|
||||
return deliverArg;
|
||||
}
|
||||
|
||||
void commitDeliverArg(void)
|
||||
{
|
||||
u8 *deliverArg = loadDeliverArg();
|
||||
u32 bootenv = CFG_BOOTENV;
|
||||
|
||||
if ((bootenv & 1) == 0) // if true coldboot, set bootenv to "CTR mode reboot"
|
||||
{
|
||||
bootenv = 1;
|
||||
CFG_BOOTENV = 1;
|
||||
}
|
||||
|
||||
u32 mode = bootenv >> 1;
|
||||
if (mode == 0) // CTR mode
|
||||
{
|
||||
*(u32 *)(deliverArg + 0x438) = 0xFFFF;
|
||||
*(u32 *)(deliverArg + 0x43C) = crc32(deliverArg + 0x400, 0x140, 0xFFFFFFFF);
|
||||
memcpy((void *)0x20000000, deliverArg, 0x1000);
|
||||
}
|
||||
else // Legacy modes (just TWL mode, really)
|
||||
{
|
||||
copyToLegacyModeFcram((void *)0x20000000, deliverArg, 0x400);
|
||||
}
|
||||
}
|
||||
|
||||
bool hasValidTlncAutobootParams(void)
|
||||
{
|
||||
u8 *tlnc = loadDeliverArg() + 0x300; // loadDeliverArg clears invalid TLNC blocks
|
||||
return memcmp(tlnc, "TLNC", 4) == 0 && (*(u16 *)(tlnc + 0x18) & 1) != 0;
|
||||
}
|
||||
|
||||
bool isTwlToCtrLaunch(void)
|
||||
{
|
||||
// assumes TLNC block is valid
|
||||
u8 *tlnc = loadDeliverArg() + 0x300; // loadDeliverArg clears invalid TLNC blocks
|
||||
u64 twlTid = *(u64 *)(tlnc + 0x10);
|
||||
|
||||
switch (twlTid & ~0xFFull)
|
||||
{
|
||||
case 0x0000000000000000ull: // TWL Launcher -> Home menu (note: NS checks full TID)
|
||||
case 0x00030015484E4200ull: // TWL System Settings -> CTR System Settings (mset)
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static bool configureHomebrewAutobootCtr(u8 *deliverArg)
|
||||
{
|
||||
static const u8 appmemtypesO3ds[] = { 0, 2, 3, 4, 5 };
|
||||
static const u8 appmemtypesN3ds[] = { 6, 7, 7, 7, 7 };
|
||||
|
||||
u64 hbldrTid = configData.hbldr3dsxTitleId;
|
||||
hbldrTid = hbldrTid == 0 ? HBLDR_DEFAULT_3DSX_TID : hbldrTid; // replicate Loader's behavior
|
||||
if ((hbldrTid >> 46) != 0x10) // Not a CTR titleId. Bail out
|
||||
return false;
|
||||
|
||||
u8 memtype = configData.autobootCtrAppmemtype;
|
||||
deliverArg[0x400] = ISN3DS ? appmemtypesN3ds[memtype] : appmemtypesO3ds[memtype];
|
||||
|
||||
// Determine whether to load from the SD card or from NAND. We don't support gamecards for this
|
||||
u32 category = (hbldrTid >> 32) & 0xFFFF;
|
||||
bool isSdApp = (category & 0x10) == 0 && category != 1; // not a system app nor a DLP child
|
||||
*(u64 *)(deliverArg + 0x440) = hbldrTid;
|
||||
*(u64 *)(deliverArg + 0x448) = isSdApp ? 1 : 0;
|
||||
|
||||
// Tell NS to run the title, and that it's not a title jump from legacy mode
|
||||
*(u32 *)(deliverArg + 0x460) = (0 << 1) | (1 << 0);
|
||||
|
||||
CFG_BOOTENV = 1;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool configureHomebrewAutobootTwl(u8 *deliverArg)
|
||||
{
|
||||
// Here, we pretend to be a TWL app rebooting into another TWL app.
|
||||
// We get NS to do all the heavy lifting (starting NWM and AM, etc.) this way.
|
||||
|
||||
memset(deliverArg + 0x000, 0, 0x300); // zero TWL deliver arg params
|
||||
|
||||
// Now onto TLNC (launcher params):
|
||||
u8 *tlnc = deliverArg + 0x300;
|
||||
memset(tlnc, 0, 0x100);
|
||||
memcpy(tlnc, "TLNC", 4);
|
||||
tlnc[4] = 1; // version
|
||||
tlnc[5] = 0x18; // length of data to calculate CRC over
|
||||
|
||||
*(u64 *)(tlnc + 8) = 0; // old title ID
|
||||
*(u64 *)(tlnc + 0x10) = configData.autobootTwlTitleId; // new title ID
|
||||
// bit4: "skip logo" ; bits2:1: NAND boot ; bit0: valid
|
||||
*(u16 *)(tlnc + 0x18) = (1 << 4) | (3 << 1) | (1 << 0);
|
||||
|
||||
*(u16 *)(tlnc + 6) = crc16(tlnc + 8, 0x18, 0xFFFF);
|
||||
|
||||
CFG_BOOTENV = 3;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool configureHomebrewAutoboot(void)
|
||||
{
|
||||
bool ret;
|
||||
u8 *deliverArg = loadDeliverArg();
|
||||
|
||||
u32 bootenv = CFG_BOOTENV;
|
||||
u32 mode = bootenv >> 1;
|
||||
|
||||
u32 testPattern = *(u32 *)(deliverArg + 0x438);
|
||||
if (mode != 0 || testPattern == 0xFFFF)
|
||||
return false; // bail out if this isn't a coldboot/plain reboot
|
||||
|
||||
switch (MULTICONFIG(AUTOBOOTMODE))
|
||||
{
|
||||
case 1:
|
||||
ret = configureHomebrewAutobootCtr(deliverArg);
|
||||
break;
|
||||
case 2:
|
||||
ret = configureHomebrewAutobootTwl(deliverArg);
|
||||
break;
|
||||
case 0:
|
||||
default:
|
||||
ret = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (ret)
|
||||
commitDeliverArg();
|
||||
return ret;
|
||||
}
|
37
arm9/source/deliver_arg.h
Normal file
37
arm9/source/deliver_arg.h
Normal file
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* This file is part of Luma3DS
|
||||
* Copyright (C) 2022 Aurora Wright, TuxSH
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Additional Terms 7.b and 7.c of GPLv3 apply to this file:
|
||||
* * Requiring preservation of specified reasonable legal notices or
|
||||
* author attributions in that material or in the Appropriate Legal
|
||||
* Notices displayed by works containing it.
|
||||
* * Prohibiting misrepresentation of the origin of that material,
|
||||
* or requiring that modified versions of such material be marked in
|
||||
* reasonable ways as different from the original version.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "types.h"
|
||||
|
||||
u8 *loadDeliverArg(void);
|
||||
void commitDeliverArg(void);
|
||||
|
||||
bool hasValidTlncAutobootParams(void);
|
||||
bool isTwlToCtrLaunch(void); // assumes TLNC block is valid
|
||||
|
||||
bool configureHomebrewAutoboot(void);
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of Luma3DS
|
||||
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||
* Copyright (C) 2016-2022 Aurora Wright, TuxSH
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -35,6 +35,7 @@
|
||||
#include "pin.h"
|
||||
#include "crypto.h"
|
||||
#include "memory.h"
|
||||
#include "deliver_arg.h"
|
||||
#include "screen.h"
|
||||
#include "i2c.h"
|
||||
#include "fmt.h"
|
||||
@ -216,8 +217,15 @@ void main(int argc, char **argv, u32 magicWord)
|
||||
//If it's a MCU reboot, try to force boot options
|
||||
if(CFG_BOOTENV && needConfig != CREATE_CONFIGURATION)
|
||||
{
|
||||
//Always force a SysNAND boot when quitting AGB_FIRM
|
||||
if(CFG_BOOTENV == 7)
|
||||
u32 bootenv = CFG_BOOTENV;
|
||||
bool validTlnc = bootenv == 3 && hasValidTlncAutobootParams();
|
||||
bool twlIntoCtr = validTlnc && isTwlToCtrLaunch();
|
||||
|
||||
if (validTlnc)
|
||||
needToInitSd = true;
|
||||
|
||||
//Always force a SysNAND boot when quitting AGB_FIRM, or when doing a TWL -> (ns ->) TWL reboot
|
||||
if(bootenv == 7 || (validTlnc && !twlIntoCtr))
|
||||
{
|
||||
nandType = FIRMWARE_SYSNAND;
|
||||
firmSource = (BOOTCFG_NAND != 0) == (BOOTCFG_FIRM != 0) ? FIRMWARE_SYSNAND : (FirmwareSource)BOOTCFG_FIRM;
|
||||
@ -228,16 +236,9 @@ void main(int argc, char **argv, u32 magicWord)
|
||||
goto boot;
|
||||
}
|
||||
|
||||
//Account for DSiWare soft resets if exiting TWL_FIRM
|
||||
if(CFG_BOOTENV == 3)
|
||||
{
|
||||
static const u8 TLNC[] = {0x54, 0x4C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4E, 0x43};
|
||||
if(memcmp((void *)0x20000C00, TLNC, 10) == 0) needToInitSd = true;
|
||||
}
|
||||
|
||||
/* Force the last used boot options if autobooting a TWL title, or unless a button is pressed
|
||||
/* Force the last used boot options if doing TWL->CTR, or unless a button is pressed
|
||||
or the no-forcing flag is set */
|
||||
if(needToInitSd || memcmp((void *)0x20000300, "TLNC", 4) == 0 || (!pressed && !BOOTCFG_NOFORCEFLAG))
|
||||
if(twlIntoCtr || !(pressed || BOOTCFG_NOFORCEFLAG))
|
||||
{
|
||||
nandType = (FirmwareSource)BOOTCFG_NAND;
|
||||
firmSource = (FirmwareSource)BOOTCFG_FIRM;
|
||||
@ -309,6 +310,17 @@ void main(int argc, char **argv, u32 magicWord)
|
||||
goto boot;
|
||||
}
|
||||
|
||||
// Set-up autoboot, and if we're booting into TWL mode, always use SysNAND
|
||||
if (MULTICONFIG(AUTOBOOTMODE) != 0)
|
||||
{
|
||||
bool ok = configureHomebrewAutoboot();
|
||||
if (ok && MULTICONFIG(AUTOBOOTMODE) == 2)
|
||||
{
|
||||
nandType = FIRMWARE_SYSNAND;
|
||||
firmSource = FIRMWARE_SYSNAND;
|
||||
}
|
||||
}
|
||||
|
||||
//If booting from CTRNAND, always use SysNAND
|
||||
if(!isSdMode) nandType = FIRMWARE_SYSNAND;
|
||||
|
||||
@ -387,8 +399,10 @@ boot:
|
||||
switch(firmType)
|
||||
{
|
||||
case NATIVE_FIRM:
|
||||
{
|
||||
res = patchNativeFirm(firmVersion, nandType, loadFromStorage, isFirmProtEnabled, needToInitSd, doUnitinfoPatch);
|
||||
break;
|
||||
}
|
||||
case TWL_FIRM:
|
||||
res = patchTwlFirm(firmVersion, loadFromStorage, doUnitinfoPatch);
|
||||
break;
|
||||
|
@ -54,3 +54,27 @@ u8 *memsearch(u8 *startPos, const void *pattern, u32 size, u32 patternSize)
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void *copyFromLegacyModeFcram(void *dst, const void *src, size_t size)
|
||||
{
|
||||
// Copy 2 bytes with a stride of 8
|
||||
const u16 *src16 = (const u16 *)src;
|
||||
u16 *dst16 = (u16 *)dst;
|
||||
|
||||
for (size_t i = 0; i < size / 2; i++)
|
||||
dst16[i] = src16[4 * i];
|
||||
|
||||
return dst;
|
||||
}
|
||||
|
||||
void *copyToLegacyModeFcram(void *dst, const void *src, size_t size)
|
||||
{
|
||||
// Copy 2 bytes with a stride of 8
|
||||
const u16 *src16 = (const u16 *)src;
|
||||
u16 *dst16 = (u16 *)dst;
|
||||
|
||||
for (size_t i = 0; i < size / 2; i++)
|
||||
dst16[4 * i] = src16[i];
|
||||
|
||||
return dst;
|
||||
}
|
||||
|
@ -34,3 +34,5 @@
|
||||
#include "types.h"
|
||||
|
||||
u8 *memsearch(u8 *startPos, const void *pattern, u32 size, u32 patternSize);
|
||||
void *copyFromLegacyModeFcram(void *dst, const void *src, size_t size);
|
||||
void *copyToLegacyModeFcram(void *dst, const void *src, size_t size);
|
||||
|
@ -134,6 +134,8 @@ u32 installK11Extension(u8 *pos, u32 size, bool needToInitSd, u32 baseK11VA, u32
|
||||
u32 rosalinaMenuCombo;
|
||||
u16 screenFiltersCct;
|
||||
s16 ntpTzOffetMinutes;
|
||||
u64 autobootTwlTitleId;
|
||||
u8 autobootCtrAppmemtype;
|
||||
} info;
|
||||
};
|
||||
|
||||
@ -209,6 +211,8 @@ u32 installK11Extension(u8 *pos, u32 size, bool needToInitSd, u32 baseK11VA, u32
|
||||
info->rosalinaMenuCombo = configData.rosalinaMenuCombo;
|
||||
info->screenFiltersCct = configData.screenFiltersCct;
|
||||
info->ntpTzOffetMinutes = configData.ntpTzOffetMinutes;
|
||||
info->autobootTwlTitleId = configData.autobootTwlTitleId;
|
||||
info->autobootCtrAppmemtype = configData.autobootCtrAppmemtype;
|
||||
info->versionMajor = VERSION_MAJOR;
|
||||
info->versionMinor = VERSION_MINOR;
|
||||
info->versionBuild = VERSION_BUILD;
|
||||
|
@ -71,6 +71,9 @@ typedef struct {
|
||||
u32 rosalinaMenuCombo;
|
||||
u16 screenFiltersCct;
|
||||
s16 ntpTzOffetMinutes;
|
||||
|
||||
u64 autobootTwlTitleId;
|
||||
u8 autobootCtrAppmemtype;
|
||||
} CfgData;
|
||||
|
||||
typedef struct
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of Luma3DS
|
||||
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||
* Copyright (C) 2016-2022 Aurora Wright, TuxSH
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -154,3 +154,55 @@ void error(const char *fmt, ...)
|
||||
|
||||
mcuPowerOff();
|
||||
}
|
||||
|
||||
u16 crc16(const void *data, size_t size, u16 initialValue)
|
||||
{
|
||||
static u16 lut[256] = {0};
|
||||
static bool lutInitialized = false;
|
||||
|
||||
if (!lutInitialized)
|
||||
{
|
||||
static const u16 poly = 0xA001;
|
||||
for (u32 i = 0; i < 256; i++)
|
||||
{
|
||||
u16 r = i;
|
||||
for (u32 j = 0; j < 8; j++)
|
||||
r = (r >> 1) ^ ((r & 1) != 0 ? poly : 0);
|
||||
lut[i] = r;
|
||||
}
|
||||
lutInitialized = true;
|
||||
}
|
||||
|
||||
u16 r = initialValue;
|
||||
const u8 *data8 = (const u8 *)data;
|
||||
for (size_t i = 0; i < size; i++)
|
||||
r = (r >> 8) ^ lut[(r ^ data8[i]) & 0xFF];
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
u32 crc32(const void *data, size_t size, u32 initialValue)
|
||||
{
|
||||
static u32 lut[256] = {0};
|
||||
static bool lutInitialized = false;
|
||||
|
||||
if (!lutInitialized)
|
||||
{
|
||||
static const u32 poly = 0xEDB88320;
|
||||
for (u32 i = 0; i < 256; i++)
|
||||
{
|
||||
u32 r = i;
|
||||
for (u32 j = 0; j < 8; j++)
|
||||
r = (r >> 1) ^ ((r & 1) != 0 ? poly : 0);
|
||||
lut[i] = r;
|
||||
}
|
||||
lutInitialized = true;
|
||||
}
|
||||
|
||||
u32 r = initialValue;
|
||||
const u8 *data8 = (const u8 *)data;
|
||||
for (size_t i = 0; i < size; i++)
|
||||
r = (r >> 8) ^ lut[(r ^ data8[i]) & 0xFF];
|
||||
|
||||
return ~r;
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of Luma3DS
|
||||
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||
* Copyright (C) 2016-2022 Aurora Wright, TuxSH
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -46,3 +46,6 @@ u32 waitInput(bool isMenu);
|
||||
void mcuPowerOff(void);
|
||||
void wait(u64 amount);
|
||||
void error(const char *fmt, ...);
|
||||
|
||||
u16 crc16(const void *data, size_t size, u16 initialValue);
|
||||
u32 crc32(const void *data, size_t size, u32 initialValue);
|
||||
|
@ -20,7 +20,8 @@ enum multiOptions
|
||||
BRIGHTNESS,
|
||||
SPLASH,
|
||||
PIN,
|
||||
NEWCPU
|
||||
NEWCPU,
|
||||
AUTOBOOTMODE,
|
||||
};
|
||||
|
||||
enum singleOptions
|
||||
|
@ -132,6 +132,8 @@ typedef struct CfwInfo
|
||||
u32 rosalinaMenuCombo;
|
||||
u16 screenFiltersCct;
|
||||
s16 ntpTzOffetMinutes;
|
||||
u64 autobootTwlTitleId;
|
||||
u8 autobootCtrAppmemtype;
|
||||
} CfwInfo;
|
||||
|
||||
extern CfwInfo cfwInfo;
|
||||
|
@ -61,6 +61,13 @@ Result GetSystemInfoHook(s64 *out, s32 type, s32 param)
|
||||
*out = cfwInfo.splashDurationMsec;
|
||||
break;
|
||||
|
||||
case 0x10:
|
||||
*out = (s64)cfwInfo.autobootTwlTitleId;
|
||||
break;
|
||||
case 0x11:
|
||||
*out = cfwInfo.autobootCtrAppmemtype;
|
||||
break;
|
||||
|
||||
case 0x100:
|
||||
*out = (s64)cfwInfo.hbldr3dsxTitleId;
|
||||
break;
|
||||
|
@ -22,7 +22,8 @@ enum multiOptions
|
||||
BRIGHTNESS,
|
||||
SPLASH,
|
||||
PIN,
|
||||
NEWCPU
|
||||
NEWCPU,
|
||||
AUTOBOOTMODE,
|
||||
};
|
||||
|
||||
enum singleOptions
|
||||
|
Binary file not shown.
@ -88,13 +88,6 @@ void RosalinaMenu_ShowDebugInfo(void)
|
||||
u32 kernelVer = osGetKernelVersion();
|
||||
FS_SdMmcSpeedInfo speedInfo;
|
||||
|
||||
Handle hm = 0;
|
||||
OpenProcessByName("menu", &hm);
|
||||
s64 out = 0;
|
||||
svcGetHandleInfo(&out, hm, 0);
|
||||
svcCloseHandle(hm);
|
||||
u64 timeToBootHm = 1000u * out / SYSCLOCK_ARM11;
|
||||
|
||||
do
|
||||
{
|
||||
Draw_Lock();
|
||||
@ -130,11 +123,10 @@ void RosalinaMenu_ShowDebugInfo(void)
|
||||
(int)speedInfo.highSpeedModeEnabled, SYSCLOCK_SDMMC / (1000 * clkDiv)
|
||||
);
|
||||
}
|
||||
if (timeToBootHm != 0)
|
||||
{
|
||||
posY = Draw_DrawFormattedString(
|
||||
10, posY, COLOR_WHITE, "Time to boot to Home Menu: %llums\n",
|
||||
timeToBootHm
|
||||
10, posY, COLOR_WHITE, "APPMEMTYPE: %lu\n",
|
||||
OS_KernelConfig->app_memtype
|
||||
);
|
||||
}
|
||||
Draw_FlushFramebuffer();
|
||||
|
@ -62,7 +62,8 @@ enum multiOptions
|
||||
BRIGHTNESS,
|
||||
SPLASH,
|
||||
PIN,
|
||||
NEWCPU
|
||||
NEWCPU,
|
||||
AUTOBOOTMODE,
|
||||
};
|
||||
typedef struct DspFirmSegmentHeader {
|
||||
u32 offset;
|
||||
@ -99,6 +100,9 @@ typedef struct CfgData {
|
||||
u32 rosalinaMenuCombo;
|
||||
u16 screenFiltersCct;
|
||||
s16 ntpTzOffetMinutes;
|
||||
|
||||
u64 autobootTwlTitleId;
|
||||
u8 autobootCtrAppmemtype;
|
||||
} CfgData;
|
||||
|
||||
Menu miscellaneousMenu = {
|
||||
@ -291,11 +295,13 @@ static size_t saveLumaIniConfigToStr(char *out, const CfgData *cfg)
|
||||
|
||||
1 + (int)MULTICONFIG(DEFAULTEMU), 4 - (int)MULTICONFIG(BRIGHTNESS),
|
||||
splashPosStr, (unsigned int)cfg->splashDurationMsec,
|
||||
pinNumDigits, n3dsCpuStr,
|
||||
pinNumDigits, n3dsCpuStr, (int)MULTICONFIG(AUTOBOOTMODE),
|
||||
|
||||
cfg->hbldr3dsxTitleId, rosalinaMenuComboStr,
|
||||
(int)cfg->screenFiltersCct, (int)cfg->ntpTzOffetMinutes,
|
||||
|
||||
cfg->autobootTwlTitleId, (int)cfg->autobootCtrAppmemtype,
|
||||
|
||||
(int)CONFIG(PATCHUNITINFO), (int)CONFIG(DISABLEARM11EXCHANDLERS),
|
||||
(int)CONFIG(ENABLESAFEFIRMROSALINA)
|
||||
);
|
||||
@ -318,8 +324,12 @@ void MiscellaneousMenu_SaveSettings(void)
|
||||
u32 config, multiConfig, bootConfig;
|
||||
u32 splashDurationMsec;
|
||||
|
||||
u8 autobootCtrAppmemtype;
|
||||
u64 autobootTwlTitleId;
|
||||
|
||||
s64 out;
|
||||
bool isSdMode;
|
||||
|
||||
svcGetSystemInfo(&out, 0x10000, 2);
|
||||
formatVersion = (u32)out;
|
||||
svcGetSystemInfo(&out, 0x10000, 3);
|
||||
@ -330,6 +340,12 @@ void MiscellaneousMenu_SaveSettings(void)
|
||||
bootConfig = (u32)out;
|
||||
svcGetSystemInfo(&out, 0x10000, 6);
|
||||
splashDurationMsec = (u32)out;
|
||||
|
||||
svcGetSystemInfo(&out, 0x10000, 0x10);
|
||||
autobootTwlTitleId = (u64)out;
|
||||
svcGetSystemInfo(&out, 0x10000, 0x11);
|
||||
autobootCtrAppmemtype = (u8)out;
|
||||
|
||||
svcGetSystemInfo(&out, 0x10000, 0x203);
|
||||
isSdMode = (bool)out;
|
||||
|
||||
@ -343,6 +359,8 @@ void MiscellaneousMenu_SaveSettings(void)
|
||||
configData.rosalinaMenuCombo = menuCombo;
|
||||
configData.screenFiltersCct = (u16)screenFiltersCurrentTemperature;
|
||||
configData.ntpTzOffetMinutes = (s16)lastNtpTzOffset;
|
||||
configData.autobootTwlTitleId = autobootTwlTitleId;
|
||||
configData.autobootCtrAppmemtype = autobootCtrAppmemtype;
|
||||
|
||||
size_t n = saveLumaIniConfigToStr(inibuf, &configData);
|
||||
FS_ArchiveID archiveId = isSdMode ? ARCHIVE_SDMC : ARCHIVE_NAND_RW;
|
||||
|
Loading…
x
Reference in New Issue
Block a user