Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Timelock system #1727

Open
wants to merge 17 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 24 additions & 27 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,36 +1,33 @@
# Luma3DS
*Noob-proof (N)3DS "Custom Firmware"*
# Luma3DS with Timelock

### What it is
**Luma3DS** is a program to patch the system software of (New) Nintendo (2)3DS handheld consoles "on the fly", adding features such as per-game language settings, debugging capabilities for developers, and removing restrictions enforced by Nintendo such as the region lock.
This modified build (available on the `timelock` branch) contains a Timelock system.
It enables Rosalina (Luma3DS's custom sysmodule) to lock the console after a certain time with a PIN code.
Something which is missing from the original parental control, in my opinion.
The main use is for parents not wanting their kids to use the console for too long.

It also allows you to run unauthorized ("homebrew") content by removing signature checks.
To use it, you will need a console capable of running homebrew software on the Arm9 processor.
It provides a new config menu in Rosalina letting the user handle the following options:
- Enabling/Disabling the timelock system
- Set the time limit
- Set the PIN code

Since v8.0, Luma3DS has its own in-game menu, triggerable by <kbd>L+Down+Select</kbd> (see the [release notes](https://github.com/LumaTeam/Luma3DS/releases/tag/v8.0)).
It uses a config file storing the properties listed above, as well as an elapsed time value to keep track of the time spent using the console. This lets us keep track of the usage time even after a reboot.

#
### Compiling
* Prerequisites
1. git
2. [makerom](https://github.com/jakcron/Project_CTR) in PATH
3. [firmtool](https://github.com/TuxSH/firmtool)
4. Up-to-date devkitARM+libctru
1. Clone the repository with `git clone https://github.com/LumaTeam/Luma3DS.git`
2. Run `make`.
**Default PIN: 0000**

The produced `boot.firm` is meant to be copied to the root of your SD card for usage with Boot9Strap.

#
### Setup / Usage / Features
See https://github.com/LumaTeam/Luma3DS/wiki
Here are some screenshots:

#
### Credits
See https://github.com/LumaTeam/Luma3DS/wiki/Credits
1. Rosalina menu
![1-RosalinaMenu](https://user-images.githubusercontent.com/1681898/159120680-ad2e813b-1337-4744-afab-d9f224620058.jpg)

#
### Licensing
This software is licensed under the terms of the GPLv3. You can find a copy of the license in the LICENSE.txt file.
2. Locked timelock menu
![2-LockedTimelockMenu](https://user-images.githubusercontent.com/1681898/159120683-0a4eccdb-2af9-48a7-95f1-362e3be3ce1c.jpg)

Files in the GDB stub are instead triple-licensed as MIT or "GPLv2 or any later version", in which case it's specified in the file header.
3. Unlocking timelock menu
![3-UnlockingTimelockMenu](https://user-images.githubusercontent.com/1681898/159120687-010fb016-0e05-4bc2-895a-e37400cc0428.jpg)

4. Unlocked timelock menu
![4-UnlockedTimelockMenu](https://user-images.githubusercontent.com/1681898/159120691-b2a78805-6dab-4ad9-9ca5-4b6b4e0f82ba.jpg)

5. Timelocked console
![5-Timelocked](https://user-images.githubusercontent.com/1681898/159120695-cddaba00-8644-4d8c-876a-02518a878cba.jpg)
1 change: 1 addition & 0 deletions sysmodules/rosalina/include/menu.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,3 +90,4 @@ void menuEnter(void);
void menuLeave(void);
void menuThreadMain(void);
void menuShow(Menu *root);
void menuResetSelectedItem(void);
56 changes: 56 additions & 0 deletions sysmodules/rosalina/include/menus/timelock_config.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
* This file is part of Luma3DS
* Copyright (C) 2016-2020 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 "menu.h"
#include "../timelock_shared_config.h"

#define PIN_ZERO "0000"


typedef enum
{
TL_MENU_TOGGLE,
TL_MENU_DELAY,
TL_MENU_PIN
} TIMELOCK_CONFIG_MENU;

extern Menu timelockMenu;

bool TimelockMenu_IsMenuLocked(void);
bool TimelockMenu_IsMenuUnlocked(void);
void TimelockMenu_LockMenu(void);
void TimelockMenu_UnlockMenu(void);
bool TimelockMenu_CheckPIN(char *enteredPIN);

void TimelockMenu_LoadData(void);
void TimelockMenu_UpdateAll(void);
void TimelockMenu_UpdateStatus(TIMELOCK_CONFIG_MENU menuItem);
void TimelockMenu_ToggleTimelock(void);
void TimelockMenu_Delay(void);
void TimelockMenu_PIN(void);
void TimelockMenu_SaveSettings(void);
56 changes: 56 additions & 0 deletions sysmodules/rosalina/include/timelock.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
* This file is part of Luma3DS
* Copyright (C) 2016-2021 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 <3ds/types.h>
#include "MyThread.h"
#include "timelock_shared_config.h"


#define MINUTES_TO_CHECK 1

#define CORE_APPLICATION 0
#define CORE_SYSTEM 1


// From main.c
extern bool menuShouldExit;
extern bool preTerminationRequested;
extern Handle preTerminationEvent;


MyThread *timelockCreateThread(void);
void timelockThreadMain(void);
void timelockLoadData(void);
void timelockEnter(void);
void timelockLeave(void);
void timelockShow(void);
void saveElapsedTime(void);

bool checkPIN(void);
void resetEnteredPIN(void);
void timelockInput(void);
35 changes: 35 additions & 0 deletions sysmodules/rosalina/include/timelock_shared_config.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/* This paricular file is licensed under the following terms: */

/*
* This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable
* for any damages arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it
* and redistribute it freely, subject to the following restrictions:
*
* The origin of this software must not be misrepresented; you must not claim that you wrote the original software.
* If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
*
* Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
* This notice may not be removed or altered from any source distribution.
*/

#pragma once

#include <3ds/types.h>

#define PIN_LENGTH 4
#define CONFIG_FILE_PATH "/luma/timelock_config.bin"


typedef struct PACKED ALIGN(4) timelockConfig
{
bool isEnabled;
u16 minutes;
char pin[PIN_LENGTH];
u16 elapsedMinutes;
} timelockConfig;


extern bool isRosalinaMenuOpened;
extern bool isTimeLocked;
5 changes: 5 additions & 0 deletions sysmodules/rosalina/source/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include <3ds.h>
#include "memory.h"
#include "menu.h"
#include "timelock.h"
#include "service_manager.h"
#include "errdisp.h"
#include "utils.h"
Expand All @@ -36,6 +37,7 @@
#include "menus/screen_filters.h"
#include "menus/cheats.h"
#include "menus/sysconfig.h"
#include "menus/timelock_config.h"
#include "input_redirection.h"
#include "minisoc.h"
#include "draw.h"
Expand Down Expand Up @@ -249,10 +251,12 @@ int main(void)

Draw_Init();
Cheat_SeedRng(svcGetSystemTick());
TimelockMenu_LoadData();

MyThread *menuThread = menuCreateThread();
MyThread *taskRunnerThread = taskRunnerCreateThread();
MyThread *errDispThread = errDispCreateThread();
MyThread *timelockThread = timelockCreateThread();
bootdiagCreateThread();

if (R_FAILED(ServiceManager_Run(services, notifications, NULL)))
Expand All @@ -264,6 +268,7 @@ int main(void)

MyThread_Join(taskRunnerThread, -1LL);
MyThread_Join(errDispThread, -1LL);
MyThread_Join(timelockThread, -1LL);

return 0;
}
54 changes: 47 additions & 7 deletions sysmodules/rosalina/source/menu.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,13 @@
#include "minisoc.h"
#include "menus/screen_filters.h"
#include "shell.h"
#include "timelock_shared_config.h"

u32 menuCombo = 0;
bool isHidInitialized = false;
u32 mcuFwVersion = 0;
bool needsResetSelectedItem = false;
bool isRosalinaMenuOpened = false;

// libctru redefinition:

Expand Down Expand Up @@ -250,6 +253,24 @@ u32 menuCountItems(const Menu *menu)
return n;
}

static inline u32 menuAdvanceCursorWithVisibilityHandling(const Menu* menu, u32 pos, u32 numItems, s32 displ)
{
u32 menuIter = 0;
u32 selectedItem = pos;

do
{
// If everything is hidden in the menu, we return index 0 to avoid an infinite loop
if (menuIter >= numItems)
return 0;

selectedItem = menuAdvanceCursor(selectedItem, numItems, displ);
menuIter++;
} while (menuItemIsHidden(&menu->items[selectedItem]));

return selectedItem;
}

MyThread *menuCreateThread(void)
{
if(R_FAILED(MyThread_Create(&menuThread, menuThreadMain, menuThreadStack, 0x3000, 52, CORE_SYSTEM)))
Expand Down Expand Up @@ -279,8 +300,10 @@ void menuThreadMain(void)

Cheat_ApplyCheats();

if((scanHeldKeys() & menuCombo) == menuCombo)
if ((scanHeldKeys() & menuCombo) == menuCombo && !isTimeLocked)
{
isRosalinaMenuOpened = true;

menuEnter();
if(isN3DS) N3DSMenu_UpdateStatus();
menuShow(&rosalinaMenu);
Expand All @@ -303,6 +326,7 @@ void menuEnter(void)
// Oops
menuRefCount = 0;
svcKernelSetState(0x10000, 2 | 1);
isRosalinaMenuOpened = false;
svcSleepThread(5 * 1000 * 100LL);
}
else
Expand All @@ -321,6 +345,8 @@ void menuLeave(void)
Draw_RestoreFramebuffer();
Draw_FreeFramebufferCache();
svcKernelSetState(0x10000, 2 | 1);

isRosalinaMenuOpened = false;
}
Draw_Unlock();
}
Expand Down Expand Up @@ -409,7 +435,7 @@ void menuShow(Menu *root)

u32 numItems = menuCountItems(currentMenu);
if (menuItemIsHidden(&currentMenu->items[selectedItem]))
selectedItem = menuAdvanceCursor(selectedItem, numItems, 1);
selectedItem = menuAdvanceCursorWithVisibilityHandling(currentMenu, selectedItem, numItems, 1);

Draw_Lock();
Draw_ClearFramebuffer();
Expand Down Expand Up @@ -450,7 +476,10 @@ void menuShow(Menu *root)
previousSelectedItems[nbPreviousMenus] = selectedItem;
previousMenus[nbPreviousMenus++] = currentMenu;
currentMenu = currentMenu->items[selectedItem].menu;

selectedItem = 0;
if (menuItemIsHidden(&currentMenu->items[selectedItem]))
selectedItem = menuAdvanceCursorWithVisibilityHandling(currentMenu, selectedItem, numItems, 1);
break;
default:
__builtin_trap(); // oops
Expand Down Expand Up @@ -481,15 +510,21 @@ void menuShow(Menu *root)
}
else if(pressed & KEY_DOWN)
{
selectedItem = menuAdvanceCursor(selectedItem, numItems, 1);
if (menuItemIsHidden(&currentMenu->items[selectedItem]))
selectedItem = menuAdvanceCursor(selectedItem, numItems, 1);
selectedItem = menuAdvanceCursorWithVisibilityHandling(currentMenu, selectedItem, numItems, 1);
}
else if(pressed & KEY_UP)
{
selectedItem = menuAdvanceCursor(selectedItem, numItems, -1);
selectedItem = menuAdvanceCursorWithVisibilityHandling(currentMenu, selectedItem, numItems, -1);
}

if (needsResetSelectedItem)
{
selectedItem = 0;

if (menuItemIsHidden(&currentMenu->items[selectedItem]))
selectedItem = menuAdvanceCursor(selectedItem, numItems, -1);
selectedItem = menuAdvanceCursorWithVisibilityHandling(currentMenu, selectedItem, numItems, 1);

needsResetSelectedItem = false;
}

Draw_Lock();
Expand All @@ -498,3 +533,8 @@ void menuShow(Menu *root)
}
while(!menuShouldExit);
}

void menuResetSelectedItem(void)
{
needsResetSelectedItem = true;
}
2 changes: 2 additions & 0 deletions sysmodules/rosalina/source/menus.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
#include "menus/miscellaneous.h"
#include "menus/sysconfig.h"
#include "menus/screen_filters.h"
#include "menus/timelock_config.h"
#include "ifile.h"
#include "memory.h"
#include "fmt.h"
Expand All @@ -54,6 +55,7 @@ Menu rosalinaMenu = {
{ "Screen filters...", MENU, .menu = &screenFiltersMenu },
{ "New 3DS menu...", MENU, .menu = &N3DSMenu, .visibility = &menuCheckN3ds },
{ "Miscellaneous options...", MENU, .menu = &miscellaneousMenu },
{ "Timelock options...", MENU, .menu = &timelockMenu },
{ "Save settings", METHOD, .method = &RosalinaMenu_SaveSettings },
{ "Power off", METHOD, .method = &RosalinaMenu_PowerOff },
{ "Reboot", METHOD, .method = &RosalinaMenu_Reboot },
Expand Down
Loading