2017-06-05 02:02:04 +02:00
/*
* This file is part of Luma3DS
2022-03-13 18:00:00 +00:00
* Copyright ( C ) 2016 - 2021 Aurora Wright , TuxSH
2017-06-05 02:02:04 +02:00
*
* 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 <3ds.h>
# include "menus/miscellaneous.h"
# include "input_redirection.h"
2019-06-03 00:43:44 +02:00
# include "ntp.h"
2017-06-05 02:02:04 +02:00
# include "memory.h"
# include "draw.h"
# include "fmt.h"
2020-04-25 13:17:23 +01:00
# include "utils.h" // for makeArmBranch
2017-06-05 02:02:04 +02:00
# include "minisoc.h"
2017-06-18 22:31:21 +02:00
# include "ifile.h"
2019-03-30 18:12:54 +01:00
# include "pmdbgext.h"
2021-01-16 21:16:32 +00:00
# include "process_patches.h"
2022-03-28 20:30:02 +01:00
# include "screen_filters.h"
# include "config_template_ini.h"
2021-01-16 21:16:32 +00:00
2022-03-28 20:30:02 +01:00
# define CONFIG(a) (((cfg->config >> (a)) & 1) != 0)
# define MULTICONFIG(a) ((cfg->multiConfig >> (2 * (a))) & 3)
# define BOOTCONFIG(a, b) ((cfg->bootConfig >> (a)) & (b))
enum singleOptions
{
AUTOBOOTEMU = 0 ,
USEEMUFIRM ,
LOADEXTFIRMSANDMODULES ,
PATCHGAMES ,
PATCHVERSTRING ,
SHOWGBABOOT ,
PATCHUNITINFO ,
DISABLEARM11EXCHANDLERS ,
ENABLESAFEFIRMROSALINA ,
} ;
enum multiOptions
{
DEFAULTEMU = 0 ,
BRIGHTNESS ,
SPLASH ,
PIN ,
2023-01-03 15:30:07 +01:00
NEWCPU ,
AUTOBOOTMODE ,
2022-03-28 20:30:02 +01:00
} ;
2021-01-16 21:16:32 +00:00
typedef struct DspFirmSegmentHeader {
u32 offset ;
u32 loadAddrHalfwords ;
u32 size ;
u8 _0x0C [ 3 ] ;
u8 memType ;
u8 hash [ 0x20 ] ;
} DspFirmSegmentHeader ;
typedef struct DspFirm {
u8 signature [ 0x100 ] ;
char magic [ 4 ] ;
u32 totalSize ; // no more than 0x10000
u16 layoutBitfield ;
u8 _0x10A [ 3 ] ;
u8 surroundSegmentMemType ;
u8 numSegments ; // no more than 10
u8 flags ;
u32 surroundSegmentLoadAddrHalfwords ;
u32 surroundSegmentSize ;
u8 _0x118 [ 8 ] ;
DspFirmSegmentHeader segmentHdrs [ 10 ] ;
u8 data [ ] ;
} DspFirm ;
2017-06-05 02:02:04 +02:00
2022-03-28 20:30:02 +01:00
typedef struct CfgData {
u16 formatVersionMajor , formatVersionMinor ;
u32 config , multiConfig , bootConfig ;
u32 splashDurationMsec ;
u64 hbldr3dsxTitleId ;
u32 rosalinaMenuCombo ;
u16 screenFiltersCct ;
s16 ntpTzOffetMinutes ;
2023-01-03 15:30:07 +01:00
u64 autobootTwlTitleId ;
u8 autobootCtrAppmemtype ;
2022-03-28 20:30:02 +01:00
} CfgData ;
2017-06-05 02:02:04 +02:00
Menu miscellaneousMenu = {
" Miscellaneous options menu " ,
{
{ " Switch the hb. title to the current app. " , METHOD , . method = & MiscellaneousMenu_SwitchBoot3dsxTargetTitle } ,
2019-06-03 00:43:44 +02:00
{ " Change the menu combo " , METHOD , . method = & MiscellaneousMenu_ChangeMenuCombo } ,
2017-06-05 02:02:04 +02:00
{ " Start InputRedirection " , METHOD , . method = & MiscellaneousMenu_InputRedirection } ,
2021-01-13 23:55:55 +00:00
{ " Update time and date via NTP " , METHOD , . method = & MiscellaneousMenu_UpdateTimeDateNtp } ,
{ " Nullify user time offset " , METHOD , . method = & MiscellaneousMenu_NullifyUserTimeOffset } ,
2021-01-16 21:16:32 +00:00
{ " Dump DSP firmware " , METHOD , . method = & MiscellaneousMenu_DumpDspFirm } ,
2017-07-23 22:44:14 -04:00
{ " Save settings " , METHOD , . method = & MiscellaneousMenu_SaveSettings } ,
2020-05-17 16:42:44 +01:00
{ } ,
2017-06-05 02:02:04 +02:00
}
} ;
2022-03-28 20:30:02 +01:00
int lastNtpTzOffset = 0 ;
2017-06-05 02:02:04 +02:00
2023-01-07 01:58:11 +00:00
static inline bool compareTids ( u64 tidA , u64 tidB )
{
// Just like p9 clears them, ignore platform/N3DS bits
return ( ( tidA ^ tidB ) & ~ 0xF0000000ull ) = = 0 ;
}
2017-06-05 02:02:04 +02:00
void MiscellaneousMenu_SwitchBoot3dsxTargetTitle ( void )
{
Result res ;
char failureReason [ 64 ] ;
2023-01-07 01:58:11 +00:00
u64 currentTid = Luma_SharedConfig - > hbldr_3dsx_tid ;
u64 newTid = currentTid ;
2017-06-05 02:02:04 +02:00
2023-01-07 01:58:11 +00:00
if ( compareTids ( currentTid , HBLDR_DEFAULT_3DSX_TID ) )
2017-06-05 02:02:04 +02:00
{
2020-05-10 02:58:21 +01:00
FS_ProgramInfo progInfo ;
2019-03-31 16:12:31 +02:00
u32 pid ;
2020-05-10 02:58:21 +01:00
u32 launchFlags ;
res = PMDBG_GetCurrentAppInfo ( & progInfo , & pid , & launchFlags ) ;
2017-06-05 02:02:04 +02:00
if ( R_SUCCEEDED ( res ) )
{
2023-01-07 01:58:11 +00:00
newTid = progInfo . programId ;
2020-07-12 19:36:18 +01:00
Luma_SharedConfig - > hbldr_3dsx_tid = progInfo . programId ;
2017-06-05 02:02:04 +02:00
}
else
{
res = - 1 ;
strcpy ( failureReason , " no suitable process found " ) ;
}
}
else
{
res = 0 ;
2023-01-07 01:58:11 +00:00
newTid = HBLDR_DEFAULT_3DSX_TID ;
2017-06-05 02:02:04 +02:00
}
2023-01-07 01:58:11 +00:00
Luma_SharedConfig - > hbldr_3dsx_tid = newTid ;
if ( compareTids ( newTid , HBLDR_DEFAULT_3DSX_TID ) )
miscellaneousMenu . items [ 0 ] . title = " Switch the hb. title to the current app. " ;
else
miscellaneousMenu . items [ 0 ] . title = " Switch the hb. title to " HBLDR_DEFAULT_3DSX_TITLE_NAME ;
2017-06-05 02:02:04 +02:00
Draw_Lock ( ) ;
Draw_ClearFramebuffer ( ) ;
Draw_FlushFramebuffer ( ) ;
Draw_Unlock ( ) ;
do
{
Draw_Lock ( ) ;
Draw_DrawString ( 10 , 10 , COLOR_TITLE , " Miscellaneous options menu " ) ;
if ( R_SUCCEEDED ( res ) )
Draw_DrawString ( 10 , 30 , COLOR_WHITE , " Operation succeeded. " ) ;
else
Draw_DrawFormattedString ( 10 , 30 , COLOR_WHITE , " Operation failed (%s). " , failureReason ) ;
Draw_FlushFramebuffer ( ) ;
Draw_Unlock ( ) ;
}
2020-05-15 20:00:13 +01:00
while ( ! ( waitInput ( ) & KEY_B ) & & ! menuShouldExit ) ;
2017-06-05 02:02:04 +02:00
}
static void MiscellaneousMenu_ConvertComboToString ( char * out , u32 combo )
{
2020-05-15 02:06:52 +01:00
static const char * keys [ ] = {
" A " , " B " , " Select " , " Start " , " Right " , " Left " , " Up " , " Down " , " R " , " L " , " X " , " Y " ,
" ? " , " ? " ,
" ZL " , " ZR " ,
" ? " , " ? " , " ? " , " ? " ,
" Touch " ,
" ? " , " ? " , " ? " ,
" CStick Right " , " CStick Left " , " CStick Up " , " CStick Down " ,
" CPad Right " , " CPad Left " , " CPad Up " , " CPad Down " ,
} ;
char * outOrig = out ;
out [ 0 ] = 0 ;
for ( s32 i = 31 ; i > = 0 ; i - - )
2017-06-05 02:02:04 +02:00
{
if ( combo & ( 1 < < i ) )
{
strcpy ( out , keys [ i ] ) ;
out + = strlen ( keys [ i ] ) ;
* out + + = ' + ' ;
}
}
2020-05-15 02:06:52 +01:00
if ( out ! = outOrig )
out [ - 1 ] = 0 ;
2017-06-05 02:02:04 +02:00
}
2017-07-04 23:13:48 -04:00
2017-06-05 02:02:04 +02:00
void MiscellaneousMenu_ChangeMenuCombo ( void )
{
2020-05-15 02:06:52 +01:00
char comboStrOrig [ 128 ] , comboStr [ 128 ] ;
2017-06-05 02:02:04 +02:00
u32 posY ;
Draw_Lock ( ) ;
Draw_ClearFramebuffer ( ) ;
Draw_FlushFramebuffer ( ) ;
Draw_Unlock ( ) ;
MiscellaneousMenu_ConvertComboToString ( comboStrOrig , menuCombo ) ;
Draw_Lock ( ) ;
Draw_DrawString ( 10 , 10 , COLOR_TITLE , " Miscellaneous options menu " ) ;
posY = Draw_DrawFormattedString ( 10 , 30 , COLOR_WHITE , " The current menu combo is: %s " , comboStrOrig ) ;
posY = Draw_DrawString ( 10 , posY + SPACING_Y , COLOR_WHITE , " Please enter the new combo: " ) ;
2017-06-06 01:21:52 +02:00
menuCombo = waitCombo ( ) ;
2017-06-05 02:02:04 +02:00
MiscellaneousMenu_ConvertComboToString ( comboStr , menuCombo ) ;
do
{
Draw_Lock ( ) ;
Draw_DrawString ( 10 , 10 , COLOR_TITLE , " Miscellaneous options menu " ) ;
posY = Draw_DrawFormattedString ( 10 , 30 , COLOR_WHITE , " The current menu combo is: %s " , comboStrOrig ) ;
posY = Draw_DrawFormattedString ( 10 , posY + SPACING_Y , COLOR_WHITE , " Please enter the new combo: %s " , comboStr ) + SPACING_Y ;
2017-06-18 22:31:21 +02:00
2017-06-05 02:02:04 +02:00
posY = Draw_DrawString ( 10 , posY + SPACING_Y , COLOR_WHITE , " Successfully changed the menu combo. " ) ;
Draw_FlushFramebuffer ( ) ;
Draw_Unlock ( ) ;
}
2020-05-15 20:00:13 +01:00
while ( ! ( waitInput ( ) & KEY_B ) & & ! menuShouldExit ) ;
2017-06-05 02:02:04 +02:00
}
2022-03-28 20:30:02 +01:00
static size_t saveLumaIniConfigToStr ( char * out , const CfgData * cfg )
{
char lumaVerStr [ 64 ] ;
char lumaRevSuffixStr [ 16 ] ;
char rosalinaMenuComboStr [ 128 ] ;
const char * splashPosStr ;
const char * n3dsCpuStr ;
s64 outInfo ;
svcGetSystemInfo ( & outInfo , 0x10000 , 0 ) ;
u32 version = ( u32 ) outInfo ;
svcGetSystemInfo ( & outInfo , 0x10000 , 1 ) ;
u32 commitHash = ( u32 ) outInfo ;
svcGetSystemInfo ( & outInfo , 0x10000 , 0x200 ) ;
bool isRelease = ( bool ) outInfo ;
switch ( MULTICONFIG ( SPLASH ) ) {
default : case 0 : splashPosStr = " off " ; break ;
case 1 : splashPosStr = " before payloads " ; break ;
case 2 : splashPosStr = " after payloads " ; break ;
}
switch ( MULTICONFIG ( NEWCPU ) ) {
default : case 0 : n3dsCpuStr = " off " ; break ;
case 1 : n3dsCpuStr = " clock " ; break ;
case 2 : n3dsCpuStr = " l2 " ; break ;
case 3 : n3dsCpuStr = " clock+l2 " ; break ;
}
if ( GET_VERSION_REVISION ( version ) ! = 0 ) {
sprintf ( lumaVerStr , " Luma3DS v%d.%d.%d " , ( int ) GET_VERSION_MAJOR ( version ) , ( int ) GET_VERSION_MINOR ( version ) , ( int ) GET_VERSION_REVISION ( version ) ) ;
} else {
sprintf ( lumaVerStr , " Luma3DS v%d.%d " , ( int ) GET_VERSION_MAJOR ( version ) , ( int ) GET_VERSION_MINOR ( version ) ) ;
}
if ( isRelease ) {
strcpy ( lumaRevSuffixStr , " " ) ;
} else {
sprintf ( lumaRevSuffixStr , " -%08lx " , ( u32 ) commitHash ) ;
}
MiscellaneousMenu_ConvertComboToString ( rosalinaMenuComboStr , cfg - > rosalinaMenuCombo ) ;
static const int pinOptionToDigits [ ] = { 0 , 4 , 6 , 8 } ;
int pinNumDigits = pinOptionToDigits [ MULTICONFIG ( PIN ) ] ;
int n = sprintf (
out , ( const char * ) config_template_ini ,
lumaVerStr , lumaRevSuffixStr ,
( int ) cfg - > formatVersionMajor , ( int ) cfg - > formatVersionMinor ,
( int ) CONFIG ( AUTOBOOTEMU ) , ( int ) CONFIG ( USEEMUFIRM ) ,
( int ) CONFIG ( LOADEXTFIRMSANDMODULES ) , ( int ) CONFIG ( PATCHGAMES ) ,
( int ) CONFIG ( PATCHVERSTRING ) , ( int ) CONFIG ( SHOWGBABOOT ) ,
1 + ( int ) MULTICONFIG ( DEFAULTEMU ) , 4 - ( int ) MULTICONFIG ( BRIGHTNESS ) ,
splashPosStr , ( unsigned int ) cfg - > splashDurationMsec ,
2023-01-03 15:30:07 +01:00
pinNumDigits , n3dsCpuStr , ( int ) MULTICONFIG ( AUTOBOOTMODE ) ,
2022-03-28 20:30:02 +01:00
cfg - > hbldr3dsxTitleId , rosalinaMenuComboStr ,
( int ) cfg - > screenFiltersCct , ( int ) cfg - > ntpTzOffetMinutes ,
2023-01-03 15:30:07 +01:00
cfg - > autobootTwlTitleId , ( int ) cfg - > autobootCtrAppmemtype ,
2022-03-28 20:30:02 +01:00
( int ) CONFIG ( PATCHUNITINFO ) , ( int ) CONFIG ( DISABLEARM11EXCHANDLERS ) ,
( int ) CONFIG ( ENABLESAFEFIRMROSALINA )
) ;
return n < 0 ? 0 : ( size_t ) n ;
}
2017-06-18 22:31:21 +02:00
void MiscellaneousMenu_SaveSettings ( void )
{
2022-03-28 20:30:02 +01:00
char inibuf [ 0x2000 ] ;
2017-06-18 22:31:21 +02:00
Result res ;
IFile file ;
u64 total ;
2022-03-28 20:30:02 +01:00
CfgData configData ;
2017-06-18 22:31:21 +02:00
u32 formatVersion ;
u32 config , multiConfig , bootConfig ;
2022-03-28 20:30:02 +01:00
u32 splashDurationMsec ;
2023-01-03 15:30:07 +01:00
u8 autobootCtrAppmemtype ;
u64 autobootTwlTitleId ;
2017-06-18 22:31:21 +02:00
s64 out ;
bool isSdMode ;
2023-01-03 15:30:07 +01:00
2022-03-28 20:30:02 +01:00
svcGetSystemInfo ( & out , 0x10000 , 2 ) ;
2017-06-18 22:31:21 +02:00
formatVersion = ( u32 ) out ;
2022-03-28 20:30:02 +01:00
svcGetSystemInfo ( & out , 0x10000 , 3 ) ;
2017-06-18 22:31:21 +02:00
config = ( u32 ) out ;
2022-03-28 20:30:02 +01:00
svcGetSystemInfo ( & out , 0x10000 , 4 ) ;
2017-06-18 22:31:21 +02:00
multiConfig = ( u32 ) out ;
2022-03-28 20:30:02 +01:00
svcGetSystemInfo ( & out , 0x10000 , 5 ) ;
2017-06-18 22:31:21 +02:00
bootConfig = ( u32 ) out ;
2022-03-28 20:30:02 +01:00
svcGetSystemInfo ( & out , 0x10000 , 6 ) ;
splashDurationMsec = ( u32 ) out ;
2023-01-03 15:30:07 +01:00
svcGetSystemInfo ( & out , 0x10000 , 0x10 ) ;
autobootTwlTitleId = ( u64 ) out ;
svcGetSystemInfo ( & out , 0x10000 , 0x11 ) ;
autobootCtrAppmemtype = ( u8 ) out ;
2022-03-28 20:30:02 +01:00
svcGetSystemInfo ( & out , 0x10000 , 0x203 ) ;
2017-06-18 22:31:21 +02:00
isSdMode = ( bool ) out ;
configData . formatVersionMajor = ( u16 ) ( formatVersion > > 16 ) ;
configData . formatVersionMinor = ( u16 ) formatVersion ;
configData . config = config ;
configData . multiConfig = multiConfig ;
configData . bootConfig = bootConfig ;
2022-03-28 20:30:02 +01:00
configData . splashDurationMsec = splashDurationMsec ;
2020-07-12 19:36:18 +01:00
configData . hbldr3dsxTitleId = Luma_SharedConfig - > hbldr_3dsx_tid ;
2017-06-18 22:31:21 +02:00
configData . rosalinaMenuCombo = menuCombo ;
2022-03-28 20:30:02 +01:00
configData . screenFiltersCct = ( u16 ) screenFiltersCurrentTemperature ;
configData . ntpTzOffetMinutes = ( s16 ) lastNtpTzOffset ;
2023-01-03 15:30:07 +01:00
configData . autobootTwlTitleId = autobootTwlTitleId ;
configData . autobootCtrAppmemtype = autobootCtrAppmemtype ;
2017-06-18 22:31:21 +02:00
2022-03-28 20:30:02 +01:00
size_t n = saveLumaIniConfigToStr ( inibuf , & configData ) ;
2017-06-18 22:31:21 +02:00
FS_ArchiveID archiveId = isSdMode ? ARCHIVE_SDMC : ARCHIVE_NAND_RW ;
2022-03-28 20:30:02 +01:00
if ( n > 0 )
res = IFile_Open ( & file , archiveId , fsMakePath ( PATH_EMPTY , " " ) , fsMakePath ( PATH_ASCII , " /luma/config.ini " ) , FS_OPEN_CREATE | FS_OPEN_WRITE ) ;
else
res = - 1 ;
2017-06-18 22:31:21 +02:00
2021-01-16 21:26:37 +00:00
if ( R_SUCCEEDED ( res ) )
2022-03-28 20:30:02 +01:00
res = IFile_SetSize ( & file , n ) ;
2017-06-18 22:31:21 +02:00
if ( R_SUCCEEDED ( res ) )
2022-03-28 20:30:02 +01:00
res = IFile_Write ( & file , & total , inibuf , n , 0 ) ;
2021-01-16 21:26:37 +00:00
IFile_Close ( & file ) ;
2017-06-18 22:31:21 +02:00
Draw_Lock ( ) ;
Draw_ClearFramebuffer ( ) ;
Draw_FlushFramebuffer ( ) ;
Draw_Unlock ( ) ;
do
{
Draw_Lock ( ) ;
2017-08-15 09:01:48 -04:00
Draw_DrawString ( 10 , 10 , COLOR_TITLE , " Miscellaneous options menu " ) ;
2017-06-18 22:31:21 +02:00
if ( R_SUCCEEDED ( res ) )
Draw_DrawString ( 10 , 30 , COLOR_WHITE , " Operation succeeded. " ) ;
else
2018-05-24 00:55:38 +02:00
Draw_DrawFormattedString ( 10 , 30 , COLOR_WHITE , " Operation failed (0x%08lx). " , res ) ;
2017-06-18 22:31:21 +02:00
Draw_FlushFramebuffer ( ) ;
Draw_Unlock ( ) ;
}
2020-05-15 20:00:13 +01:00
while ( ! ( waitInput ( ) & KEY_B ) & & ! menuShouldExit ) ;
2017-06-18 22:31:21 +02:00
}
2017-06-05 02:02:04 +02:00
void MiscellaneousMenu_InputRedirection ( void )
{
bool done = false ;
Result res ;
char buf [ 65 ] ;
bool wasEnabled = inputRedirectionEnabled ;
2017-06-06 21:04:13 +02:00
bool cantStart = false ;
2017-06-05 02:02:04 +02:00
if ( wasEnabled )
{
2020-04-28 01:31:29 +01:00
res = InputRedirection_Disable ( 5 * 1000 * 1000 * 1000LL ) ;
2017-06-05 02:02:04 +02:00
if ( res ! = 0 )
2018-05-24 00:55:38 +02:00
sprintf ( buf , " Failed to stop InputRedirection (0x%08lx). " , ( u32 ) res ) ;
2017-06-05 02:02:04 +02:00
else
2017-08-06 23:51:52 +03:00
miscellaneousMenu . items [ 2 ] . title = " Start InputRedirection " ;
2017-06-05 02:02:04 +02:00
}
else
{
2018-01-18 20:44:54 +01:00
s64 dummyInfo ;
bool isN3DS = svcGetSystemInfo ( & dummyInfo , 0x10001 , 0 ) = = 0 ;
bool isSocURegistered ;
2017-06-05 02:02:04 +02:00
2018-01-18 20:44:54 +01:00
res = srvIsServiceRegistered ( & isSocURegistered , " soc:U " ) ;
cantStart = R_FAILED ( res ) | | ! isSocURegistered ;
2017-06-05 02:02:04 +02:00
if ( ! cantStart & & isN3DS )
{
2018-01-18 20:44:54 +01:00
bool isIrRstRegistered ;
res = srvIsServiceRegistered ( & isIrRstRegistered , " ir:rst " ) ;
cantStart = R_FAILED ( res ) | | ! isIrRstRegistered ;
2017-06-05 02:02:04 +02:00
}
}
2017-06-18 22:31:21 +02:00
Draw_Lock ( ) ;
Draw_ClearFramebuffer ( ) ;
Draw_FlushFramebuffer ( ) ;
Draw_Unlock ( ) ;
2017-06-05 02:02:04 +02:00
do
{
Draw_Lock ( ) ;
Draw_DrawString ( 10 , 10 , COLOR_TITLE , " Miscellaneous options menu " ) ;
if ( ! wasEnabled & & cantStart )
2018-01-18 20:44:54 +01:00
Draw_DrawString ( 10 , 30 , COLOR_WHITE , " Can't start the input redirection before the system \n has finished loading. " ) ;
2017-06-05 02:02:04 +02:00
else if ( ! wasEnabled )
{
Draw_DrawString ( 10 , 30 , COLOR_WHITE , " Starting InputRedirection... " ) ;
if ( ! done )
{
res = InputRedirection_DoOrUndoPatches ( ) ;
if ( R_SUCCEEDED ( res ) )
{
res = svcCreateEvent ( & inputRedirectionThreadStartedEvent , RESET_STICKY ) ;
if ( R_SUCCEEDED ( res ) )
{
2020-04-28 01:31:29 +01:00
inputRedirectionCreateThread ( ) ;
2017-06-05 02:02:04 +02:00
res = svcWaitSynchronization ( inputRedirectionThreadStartedEvent , 10 * 1000 * 1000 * 1000LL ) ;
if ( res = = 0 )
res = ( Result ) inputRedirectionStartResult ;
if ( res ! = 0 )
2020-04-27 21:58:40 +01:00
{
svcCloseHandle ( inputRedirectionThreadStartedEvent ) ;
2017-06-05 02:02:04 +02:00
InputRedirection_DoOrUndoPatches ( ) ;
2020-04-27 21:58:40 +01:00
inputRedirectionEnabled = false ;
}
inputRedirectionStartResult = 0 ;
2017-06-05 02:02:04 +02:00
}
}
if ( res ! = 0 )
2018-05-24 00:55:38 +02:00
sprintf ( buf , " Starting InputRedirection... failed (0x%08lx). " , ( u32 ) res ) ;
2017-06-05 02:02:04 +02:00
else
2017-08-06 23:51:52 +03:00
miscellaneousMenu . items [ 2 ] . title = " Stop InputRedirection " ;
2017-06-05 02:02:04 +02:00
done = true ;
}
if ( res = = 0 )
Draw_DrawString ( 10 , 30 , COLOR_WHITE , " Starting InputRedirection... OK. " ) ;
else
Draw_DrawString ( 10 , 30 , COLOR_WHITE , buf ) ;
}
else
{
if ( res = = 0 )
2020-07-15 22:24:08 +01:00
{
u32 posY = 30 ;
posY = Draw_DrawString ( 10 , posY , COLOR_WHITE , " InputRedirection stopped successfully. \n \n " ) ;
if ( isN3DS )
{
posY = Draw_DrawString (
10 ,
posY ,
COLOR_WHITE ,
" This might cause a key press to be repeated in \n "
" Home Menu for no reason. \n \n "
" Just pressing ZL/ZR on the console is enough to fix \n this. \n "
) ;
}
}
2017-06-05 02:02:04 +02:00
else
Draw_DrawString ( 10 , 30 , COLOR_WHITE , buf ) ;
}
Draw_FlushFramebuffer ( ) ;
Draw_Unlock ( ) ;
}
2020-05-15 20:00:13 +01:00
while ( ! ( waitInput ( ) & KEY_B ) & & ! menuShouldExit ) ;
2017-06-05 02:02:04 +02:00
}
2019-06-03 00:43:44 +02:00
2021-01-13 23:55:55 +00:00
void MiscellaneousMenu_UpdateTimeDateNtp ( void )
2019-06-03 00:43:44 +02:00
{
u32 posY ;
u32 input = 0 ;
Result res ;
bool cantStart = false ;
bool isSocURegistered ;
2022-03-15 20:24:49 +00:00
u64 msSince1900 , samplingTick ;
2019-06-03 00:43:44 +02:00
res = srvIsServiceRegistered ( & isSocURegistered , " soc:U " ) ;
cantStart = R_FAILED ( res ) | | ! isSocURegistered ;
2022-03-28 20:30:02 +01:00
int dt = 12 * 60 + lastNtpTzOffset ;
int utcOffset = dt / 60 ;
int utcOffsetMinute = dt % 60 ;
2019-06-03 00:43:44 +02:00
int absOffset ;
do
{
Draw_Lock ( ) ;
Draw_DrawString ( 10 , 10 , COLOR_TITLE , " Miscellaneous options menu " ) ;
absOffset = utcOffset - 12 ;
absOffset = absOffset < 0 ? - absOffset : absOffset ;
2019-09-16 17:13:23 +09:30
posY = Draw_DrawFormattedString ( 10 , 30 , COLOR_WHITE , " Current UTC offset: %c%02d%02d " , utcOffset < 12 ? ' - ' : ' + ' , absOffset , utcOffsetMinute ) ;
posY = Draw_DrawFormattedString ( 10 , posY + SPACING_Y , COLOR_WHITE , " Use DPAD Left/Right to change hour offset. \n Use DPAD Up/Down to change minute offset. \n Press A when done. " ) + SPACING_Y ;
2019-06-03 00:43:44 +02:00
input = waitInput ( ) ;
2022-03-28 20:30:02 +01:00
if ( input & KEY_LEFT ) utcOffset = ( 27 + utcOffset - 1 ) % 27 ; // ensure utcOffset >= 0
if ( input & KEY_RIGHT ) utcOffset = ( utcOffset + 1 ) % 27 ;
2020-05-15 02:06:52 +01:00
if ( input & KEY_UP ) utcOffsetMinute = ( utcOffsetMinute + 1 ) % 60 ;
if ( input & KEY_DOWN ) utcOffsetMinute = ( 60 + utcOffsetMinute - 1 ) % 60 ;
2019-06-03 00:43:44 +02:00
Draw_FlushFramebuffer ( ) ;
Draw_Unlock ( ) ;
}
2020-05-15 20:00:13 +01:00
while ( ! ( input & ( KEY_A | KEY_B ) ) & & ! menuShouldExit ) ;
2019-06-03 00:43:44 +02:00
2020-05-15 02:06:52 +01:00
if ( input & KEY_B )
2019-06-03 00:43:44 +02:00
return ;
utcOffset - = 12 ;
2022-03-28 20:30:02 +01:00
lastNtpTzOffset = 60 * utcOffset + utcOffsetMinute ;
2019-06-03 00:43:44 +02:00
res = srvIsServiceRegistered ( & isSocURegistered , " soc:U " ) ;
cantStart = R_FAILED ( res ) | | ! isSocURegistered ;
res = 0 ;
if ( ! cantStart )
{
2022-03-15 20:24:49 +00:00
res = ntpGetTimeStamp ( & msSince1900 , & samplingTick ) ;
2019-06-03 00:43:44 +02:00
if ( R_SUCCEEDED ( res ) )
{
2022-03-15 20:24:49 +00:00
msSince1900 + = 1000 * ( 3600 * utcOffset + 60 * utcOffsetMinute ) ;
res = ntpSetTimeDate ( msSince1900 , samplingTick ) ;
2019-06-03 00:43:44 +02:00
}
}
do
{
Draw_Lock ( ) ;
Draw_DrawString ( 10 , 10 , COLOR_TITLE , " Miscellaneous options menu " ) ;
absOffset = utcOffset ;
absOffset = absOffset < 0 ? - absOffset : absOffset ;
Draw_DrawFormattedString ( 10 , 30 , COLOR_WHITE , " Current UTC offset: %c%02d " , utcOffset < 0 ? ' - ' : ' + ' , absOffset ) ;
if ( cantStart )
2019-06-29 17:05:43 +02:00
Draw_DrawFormattedString ( 10 , posY + 2 * SPACING_Y , COLOR_WHITE , " Can't sync time/date before the system \n has finished loading. " ) + SPACING_Y ;
2019-06-03 00:43:44 +02:00
else if ( R_FAILED ( res ) )
2019-06-29 17:05:43 +02:00
Draw_DrawFormattedString ( 10 , posY + 2 * SPACING_Y , COLOR_WHITE , " Operation failed (%08lx). " , ( u32 ) res ) + SPACING_Y ;
2019-06-03 00:43:44 +02:00
else
2021-01-13 23:55:55 +00:00
Draw_DrawFormattedString ( 10 , posY + 2 * SPACING_Y , COLOR_WHITE , " Time/date updated successfully. " ) + SPACING_Y ;
2019-06-03 00:43:44 +02:00
input = waitInput ( ) ;
Draw_FlushFramebuffer ( ) ;
Draw_Unlock ( ) ;
}
2020-05-15 20:00:13 +01:00
while ( ! ( input & KEY_B ) & & ! menuShouldExit ) ;
2019-06-03 00:43:44 +02:00
2020-04-18 00:29:37 +01:00
}
2021-01-13 23:55:55 +00:00
void MiscellaneousMenu_NullifyUserTimeOffset ( void )
{
Result res = ntpNullifyUserTimeOffset ( ) ;
Draw_Lock ( ) ;
Draw_ClearFramebuffer ( ) ;
Draw_FlushFramebuffer ( ) ;
Draw_Unlock ( ) ;
do
{
Draw_Lock ( ) ;
Draw_DrawString ( 10 , 10 , COLOR_TITLE , " Miscellaneous options menu " ) ;
if ( R_SUCCEEDED ( res ) )
Draw_DrawString ( 10 , 30 , COLOR_WHITE , " Operation succeeded. \n \n Please reboot to finalize the changes. " ) ;
else
Draw_DrawFormattedString ( 10 , 30 , COLOR_WHITE , " Operation failed (0x%08lx). " , res ) ;
Draw_FlushFramebuffer ( ) ;
Draw_Unlock ( ) ;
}
while ( ! ( waitInput ( ) & KEY_B ) & & ! menuShouldExit ) ;
}
2021-01-16 21:16:32 +00:00
static Result MiscellaneousMenu_DumpDspFirmCallback ( Handle procHandle , u32 textSz , u32 roSz , u32 rwSz )
{
( void ) procHandle ;
Result res = 0 ;
// NOTE: we suppose .text, .rodata, .data+.bss are contiguous & in that order
u32 rwStart = 0x00100000 + textSz + roSz ;
u32 rwEnd = rwStart + rwSz ;
// Locate the DSP firm (it's in .data, not .rodata, suprisingly)
u32 magic ;
memcpy ( & magic , " DSP1 " , 4 ) ;
const u32 * off = ( u32 * ) rwStart ;
for ( ; off < ( u32 * ) rwEnd & & * off ! = magic ; off + + ) ;
if ( off > = ( u32 * ) rwEnd | | off < ( u32 * ) ( rwStart + 0x100 ) )
return - 2 ;
// Do some sanity checks
const DspFirm * firm = ( const DspFirm * ) ( ( u32 ) off - 0x100 ) ;
if ( firm - > totalSize > 0x10000 | | firm - > numSegments > 10 )
return - 3 ;
if ( ( u32 ) firm + firm - > totalSize > = rwEnd )
return - 3 ;
// Dump to SD card (no point in dumping to CTRNAND as 3dsx stuff doesn't work there)
IFile file ;
res = IFile_Open (
& file , ARCHIVE_SDMC , fsMakePath ( PATH_EMPTY , " " ) ,
fsMakePath ( PATH_ASCII , " /3ds/dspfirm.cdc " ) , FS_OPEN_CREATE | FS_OPEN_WRITE
) ;
u64 total ;
if ( R_SUCCEEDED ( res ) )
res = IFile_Write ( & file , & total , firm , firm - > totalSize , 0 ) ;
if ( R_SUCCEEDED ( res ) )
res = IFile_SetSize ( & file , firm - > totalSize ) ; // truncate accordingly
IFile_Close ( & file ) ;
return res ;
}
void MiscellaneousMenu_DumpDspFirm ( void )
{
Result res = OperateOnProcessByName ( " menu " , MiscellaneousMenu_DumpDspFirmCallback ) ;
Draw_Lock ( ) ;
Draw_ClearFramebuffer ( ) ;
Draw_FlushFramebuffer ( ) ;
Draw_Unlock ( ) ;
do
{
Draw_Lock ( ) ;
Draw_DrawString ( 10 , 10 , COLOR_TITLE , " Miscellaneous options menu " ) ;
if ( R_SUCCEEDED ( res ) )
Draw_DrawString ( 10 , 30 , COLOR_WHITE , " DSP firm. successfully written to /3ds/dspfirm.cdc \n on the SD card. " ) ;
else
Draw_DrawFormattedString (
10 , 30 , COLOR_WHITE ,
" Operation failed (0x%08lx). \n \n Make sure that Home Menu is running and that your \n SD card is inserted. " ,
res
) ;
Draw_FlushFramebuffer ( ) ;
Draw_Unlock ( ) ;
}
while ( ! ( waitInput ( ) & KEY_B ) & & ! menuShouldExit ) ;
}