Skip to content

Commit

Permalink
Merge branch 'LumaTeam:master' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
Popax21 authored Apr 17, 2024
2 parents 1de852b + 35a7ca2 commit 90491af
Show file tree
Hide file tree
Showing 14 changed files with 201 additions and 38 deletions.
52 changes: 28 additions & 24 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,36 +1,40 @@
# Luma3DS
*Noob-proof (N)3DS "Custom Firmware"*

### 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.
*Nintendo 3DS "Custom Firmware"*

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.
## What it is
**Luma3DS** is a program patching and reimplementing significant parts of the software running on all models of the Nintendo 3DS family of consoles.

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 aims at greatly improving the user experience and at supporting the 3DS far beyond its end-of-life. Features include:

#
### 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`.
* First class support of 3DSX homebrew
* An overlay menu called "Rosalina" (triggerable by <kbd>L+Down+Select</kbd> by default), allowing amongst many thing to take screenshots while in-game
* Removal of restrictions such as the region lock
* Per-game language settings, asset content path redirection (LayeredFS), game plugins...
* A fully-fledged GDB stub allowing to debug software (homebrew and system software alike)
* ... and much more!

The produced `boot.firm` is meant to be copied to the root of your SD card for usage with Boot9Strap.
Luma3DS requires a full-system persisent exploit such as [boot9strap](https://github.com/SciresM/boot9strap) to run.

#
### Setup / Usage / Features
See https://github.com/LumaTeam/Luma3DS/wiki
## Compiling

#
### Credits
See https://github.com/LumaTeam/Luma3DS/wiki/Credits
To build Luma3DS, the following is needed:
* git
* up-to-date devkitARM and libctru
* [makerom](https://github.com/jakcron/Project_CTR) in PATH
* [firmtool](https://github.com/TuxSH/firmtool) installed

#
### Licensing
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 (needs rework)

## Credits
See https://github.com/LumaTeam/Luma3DS/wiki/Credits (needs rework)

## Licensing
This software is licensed under the terms of the GPLv3. You can find a copy of the license in the LICENSE.txt file.

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.

By contributing to this repository, you agree to license your changes to the project's owners.
Binary file modified arm9/data/config_template.ini
Binary file not shown.
23 changes: 20 additions & 3 deletions arm9/source/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
#include "pin.h"
#include "i2c.h"
#include "ini.h"
#include "firm.h"

#include "config_template_ini.h" // note that it has an extra NUL byte inserted

Expand Down Expand Up @@ -566,6 +567,11 @@ static int configIniHandler(void* user, const char* section, const char* name, c
} else {
CHECK_PARSE_OPTION(-1);
}
} else if (strcmp(name, "volume_slider_override") == 0) {
s64 opt;
CHECK_PARSE_OPTION(parseDecIntOption(&opt, value, -1, 100));
cfg->volumeSliderOverride = (s8)opt;
return 1;
} else {
CHECK_PARSE_OPTION(-1);
}
Expand Down Expand Up @@ -670,6 +676,7 @@ static size_t saveLumaIniConfigToStr(char *out)
cfg->autobootTwlTitleId, (int)cfg->autobootCtrAppmemtype,

forceAudioOutputStr,
cfg->volumeSliderOverride,

(int)CONFIG(PATCHUNITINFO), (int)CONFIG(DISABLEARM11EXCHANDLERS),
(int)CONFIG(ENABLESAFEFIRMROSALINA)
Expand Down Expand Up @@ -774,6 +781,7 @@ bool readConfig(void)
configData.formatVersionMinor = CONFIG_VERSIONMINOR;
configData.config |= 1u << PATCHVERSTRING;
configData.splashDurationMsec = 3000;
configData.volumeSliderOverride = -1;
configData.hbldr3dsxTitleId = HBLDR_DEFAULT_3DSX_TID;
configData.rosalinaMenuCombo = 1u << 9 | 1u << 7 | 1u << 2; // L+Start+Select
configData.topScreenFilter.cct = 6500; // default temp, no-op
Expand Down Expand Up @@ -834,8 +842,9 @@ void configMenu(bool oldPinStatus, u32 oldPinMode)
"( ) Enable custom upscaling filters for DSi",
"( ) Allow Left+Right / Up+Down combos for DSi",

// Should always be the last entry
"\nSave and exit"
// Should always be the last 2 entries
"\nBoot chainloader",
"Save and exit"
};

static const char *optionsDescription[] = { "Select the default EmuNAND.\n\n"
Expand Down Expand Up @@ -933,7 +942,10 @@ void configMenu(bool oldPinStatus, u32 oldPinMode)
"Commercial software filter these\n"
"combos on their own too, though.",

// Should always be the last entry

// Should always be the last 2 entries
"Boot to the Luma3DS chainloader menu.",

"Save the changes and exit. To discard\n"
"any changes press the POWER button.\n"
"Use START as a shortcut to this entry."
Expand Down Expand Up @@ -977,6 +989,7 @@ void configMenu(bool oldPinStatus, u32 oldPinMode)
{ .visible = true },
{ .visible = true },
{ .visible = true },
{ .visible = true },
};

//Calculate the amount of the various kinds of options and pre-select the first single one
Expand Down Expand Up @@ -1154,6 +1167,10 @@ void configMenu(bool oldPinStatus, u32 oldPinMode)
startPressed = false;
break;
}
else if (singleSelected == singleOptionsAmount - 2) {
loadHomebrewFirm(0);
break;
}
else
{
bool oldEnabled = singleOptions[singleSelected].enabled;
Expand Down
2 changes: 1 addition & 1 deletion arm9/source/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@

#define CONFIG_FILE "config.ini"
#define CONFIG_VERSIONMAJOR 3
#define CONFIG_VERSIONMINOR 10
#define CONFIG_VERSIONMINOR 11

#define BOOTCFG_NAND BOOTCONFIG(0, 1)
#define BOOTCFG_EMUINDEX BOOTCONFIG(1, 3)
Expand Down
2 changes: 2 additions & 0 deletions arm9/source/patches.c
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ u32 installK11Extension(u8 *pos, u32 size, bool needToInitSd, u32 baseK11VA, u32
u16 configFormatVersionMajor, configFormatVersionMinor;
u32 config, multiConfig, bootConfig;
u32 splashDurationMsec;
s8 volumeSliderOverride;
u64 hbldr3dsxTitleId;
u32 rosalinaMenuCombo;
u32 pluginLoaderFlags;
Expand Down Expand Up @@ -215,6 +216,7 @@ u32 installK11Extension(u8 *pos, u32 size, bool needToInitSd, u32 baseK11VA, u32
info->multiConfig = configData.multiConfig;
info->bootConfig = configData.bootConfig;
info->splashDurationMsec = configData.splashDurationMsec;
info->volumeSliderOverride = configData.volumeSliderOverride;
info->hbldr3dsxTitleId = configData.hbldr3dsxTitleId;
info->rosalinaMenuCombo = configData.rosalinaMenuCombo;
info->pluginLoaderFlags = configData.pluginLoaderFlags;
Expand Down
1 change: 1 addition & 0 deletions arm9/source/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ typedef struct CfgData {

u32 config, multiConfig, bootConfig;
u32 splashDurationMsec;
s8 volumeSliderOverride;

u64 hbldr3dsxTitleId;
u32 rosalinaMenuCombo;
Expand Down
1 change: 1 addition & 0 deletions k11_extension/include/globals.h
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ typedef struct CfwInfo
u16 configFormatVersionMajor, configFormatVersionMinor;
u32 config, multiConfig, bootConfig;
u32 splashDurationMsec;
s8 volumeSliderOverride;
u64 hbldr3dsxTitleId;
u32 rosalinaMenuCombo;
u32 pluginLoaderFlags;
Expand Down
3 changes: 3 additions & 0 deletions k11_extension/source/svc/GetSystemInfo.c
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,9 @@ Result GetSystemInfoHook(s64 *out, s32 type, s32 param)
case 6:
*out = cfwInfo.splashDurationMsec;
break;
case 7:
*out = (s64)cfwInfo.volumeSliderOverride;
break;
case 0x10:
*out = (s64)cfwInfo.autobootTwlTitleId;
break;
Expand Down
40 changes: 30 additions & 10 deletions sysmodules/loader/source/patcher.c
Original file line number Diff line number Diff line change
Expand Up @@ -579,21 +579,41 @@ static inline bool patchLayeredFs(u64 progId, u8 *code, u32 size, u32 textSize,
if(!findLayeredFsSymbols(code, textSize, &fsMountArchive, &fsRegisterArchive, &fsTryOpenFile, &fsOpenFileDirectly) ||
!findLayeredFsPayloadOffset(code, textSize, roSize, dataSize, roAddress, dataAddress, &payloadOffset, &pathOffset, &pathAddress)) return false;

static const char *updateRomFsMounts[] = { "rom2:",
static const char *updateRomFsMounts[] = { "ro2:",
"rom2:",
"rex:",
"patch:",
"ext:",
"rom:" };
u32 updateRomFsIndex;

//Locate update RomFSes
for(updateRomFsIndex = 0; updateRomFsIndex < sizeof(updateRomFsMounts) / sizeof(char *) - 1; updateRomFsIndex++)
bool isMarioKart7 = (u32)progId == 0x00030600 || //JPN MK7
(u32)progId == 0x00030700 || //EUR MK7
(u32)progId == 0x00030800 || //USA MK7
(u32)progId == 0x00030A00 || //KOR MK7
(u32)progId == 0x0008B400; //TWN MK7
// Exclude CHN as it never got updates

const char *updateRomFsMount;

if (isMarioKart7)
{
updateRomFsMount = "pat1"; // Isolated to prevent false-positives
}

else
{
u32 patternSize = strlen(updateRomFsMounts[updateRomFsIndex]);
u8 temp[7];
temp[0] = 0;
memcpy(temp + 1, updateRomFsMounts[updateRomFsIndex], patternSize);
if(memsearch(code, temp, size, patternSize + 1) != NULL) break;
u32 updateRomFsIndex;

//Locate update RomFS
for(updateRomFsIndex = 0; updateRomFsIndex < sizeof(updateRomFsMounts) / sizeof(char *) - 1; updateRomFsIndex++)
{
u32 patternSize = strlen(updateRomFsMounts[updateRomFsIndex]);
u8 temp[7];
temp[0] = 0;
memcpy(temp + 1, updateRomFsMounts[updateRomFsIndex], patternSize);
if(memsearch(code, temp, size, patternSize + 1) != NULL) break;
}
updateRomFsMount = updateRomFsMounts[updateRomFsIndex];
}

//Setup the payload
Expand All @@ -607,7 +627,7 @@ static inline bool patchLayeredFs(u64 progId, u8 *code, u32 size, u32 textSize,
romfsRedirPatchFsMountArchive = 0x100000 + fsMountArchive;
romfsRedirPatchFsRegisterArchive = 0x100000 + fsRegisterArchive;
romfsRedirPatchArchiveId = archiveId;
memcpy(&romfsRedirPatchUpdateRomFsMount, updateRomFsMounts[updateRomFsIndex], 4);
memcpy(&romfsRedirPatchUpdateRomFsMount, updateRomFsMount, 4);

memcpy(payload, romfsRedirPatch, romfsRedirPatchSize);

Expand Down
Binary file modified sysmodules/rosalina/data/config_template.ini
Binary file not shown.
3 changes: 3 additions & 0 deletions sysmodules/rosalina/include/menus/sysconfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@

extern Menu sysconfigMenu;
extern bool isConnectionForced;
extern s8 currVolumeSliderOverride;

void SysConfigMenu_UpdateStatus(bool control);

Expand All @@ -40,3 +41,5 @@ void SysConfigMenu_TogglePowerButton(void);
void SysConfigMenu_ControlWifi(void);
void SysConfigMenu_DisableForcedWifiConnection(void);
void SysConfigMenu_ToggleCardIfPower(void);
void SysConfigMenu_LoadConfig(void);
void SysConfigMenu_AdjustVolume(void);
4 changes: 4 additions & 0 deletions sysmodules/rosalina/source/luma_config.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,15 @@
#include "config_template_ini.h"
#include "ifile.h"
#include "menus/miscellaneous.h"
#include "menus/sysconfig.h"
#include "plugin/plgloader.h"

typedef struct CfgData {
u16 formatVersionMajor, formatVersionMinor;

u32 config, multiConfig, bootConfig;
u32 splashDurationMsec;
s8 volumeSliderOverride;

u64 hbldr3dsxTitleId;
u32 rosalinaMenuCombo;
Expand Down Expand Up @@ -187,6 +189,7 @@ static size_t LumaConfig_SaveLumaIniConfigToStr(char *out, const CfgData *cfg)
cfg->autobootTwlTitleId, (int)cfg->autobootCtrAppmemtype,

forceAudioOutputStr,
cfg->volumeSliderOverride,

(int)CONFIG(PATCHUNITINFO), (int)CONFIG(DISABLEARM11EXCHANDLERS),
(int)CONFIG(ENABLESAFEFIRMROSALINA)
Expand Down Expand Up @@ -245,6 +248,7 @@ Result LumaConfig_SaveSettings(void)
configData.multiConfig = multiConfig;
configData.bootConfig = bootConfig;
configData.splashDurationMsec = splashDurationMsec;
configData.volumeSliderOverride = currVolumeSliderOverride;
configData.hbldr3dsxTitleId = Luma_SharedConfig->selected_hbldr_3dsx_tid;
configData.rosalinaMenuCombo = menuCombo;
configData.pluginLoaderFlags = PluginLoader__IsEnabled();
Expand Down
1 change: 1 addition & 0 deletions sysmodules/rosalina/source/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,7 @@ int main(void)
Draw_Init();
Cheat_SeedRng(svcGetSystemTick());
ScreenFiltersMenu_LoadConfig();
SysConfigMenu_LoadConfig();

MyThread *menuThread = menuCreateThread();
MyThread *taskRunnerThread = taskRunnerCreateThread();
Expand Down
Loading

0 comments on commit 90491af

Please sign in to comment.