diff --git a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/BooleanSetting.kt b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/BooleanSetting.kt
index 93259c66c..e486a4d96 100644
--- a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/BooleanSetting.kt
+++ b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/BooleanSetting.kt
@@ -51,7 +51,8 @@ enum class BooleanSetting(
USE_ARTIC_BASE_CONTROLLER("use_artic_base_controller", Settings.SECTION_CONTROLS, false),
UPRIGHT_SCREEN("upright_screen", Settings.SECTION_LAYOUT, false),
COMPRESS_INSTALLED_CIA_CONTENT("compress_cia_installs", Settings.SECTION_STORAGE, false),
- ANDROID_HIDE_IMAGES("android_hide_images", Settings.SECTION_CORE, false);
+ ANDROID_HIDE_IMAGES("android_hide_images", Settings.SECTION_CORE, false),
+ APPLY_REGION_FREE_PATCH("apply_region_free_patch", Settings.SECTION_SYSTEM, true);
override var boolean: Boolean = defaultValue
diff --git a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsFragmentPresenter.kt b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsFragmentPresenter.kt
index d4baf6166..2b823986a 100644
--- a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsFragmentPresenter.kt
+++ b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsFragmentPresenter.kt
@@ -354,6 +354,15 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView)
R.array.regionValues,
)
)
+ add(
+ SwitchSetting(
+ BooleanSetting.APPLY_REGION_FREE_PATCH,
+ R.string.apply_region_free_patch,
+ R.string.apply_region_free_patch_desc,
+ BooleanSetting.APPLY_REGION_FREE_PATCH.key,
+ BooleanSetting.APPLY_REGION_FREE_PATCH.defaultValue
+ )
+ )
val systemCountrySetting = object : AbstractShortSetting {
override var short: Short
get() {
diff --git a/src/android/app/src/main/jni/config.cpp b/src/android/app/src/main/jni/config.cpp
index 1659dc3d6..7cdfe9960 100644
--- a/src/android/app/src/main/jni/config.cpp
+++ b/src/android/app/src/main/jni/config.cpp
@@ -262,6 +262,7 @@ void Config::ReadValues() {
ReadSetting("System", Settings::values.plugin_loader_enabled);
ReadSetting("System", Settings::values.allow_plugin_loader);
ReadSetting("System", Settings::values.steps_per_hour);
+ ReadSetting("System", Settings::values.apply_region_free_patch);
// Camera
using namespace Service::CAM;
diff --git a/src/android/app/src/main/jni/default_ini.h b/src/android/app/src/main/jni/default_ini.h
index 26688a708..c7185f107 100644
--- a/src/android/app/src/main/jni/default_ini.h
+++ b/src/android/app/src/main/jni/default_ini.h
@@ -413,6 +413,11 @@ steps_per_hour =
plugin_loader =
allow_plugin_loader =
+# Apply region free patch to installed applications
+# Patches the region of installed applications to be region free, so that they always appear on the home menu.
+# 0: Disabled, 1 (default): Enabled
+apply_region_free_patch =
+
[Camera]
# Which camera engine to use for the right outer camera
# blank: a dummy camera that always returns black image
diff --git a/src/android/app/src/main/res/values/strings.xml b/src/android/app/src/main/res/values/strings.xml
index d3e5d958d..11c4943c8 100644
--- a/src/android/app/src/main/res/values/strings.xml
+++ b/src/android/app/src/main/res/values/strings.xml
@@ -190,6 +190,8 @@
Username
New 3DS Mode
Use LLE Applets (if installed)
+ Apply region free patch to installed applications
+ Patches the region of installed applications to be region free, so that they always appear on the home menu.
Enable required LLE modules for online features (if installed)
Enables the LLE modules required for online multiplayer, eShop access, etc.
Clock
diff --git a/src/citra_qt/configuration/config.cpp b/src/citra_qt/configuration/config.cpp
index cdb86c4c5..b793a6042 100644
--- a/src/citra_qt/configuration/config.cpp
+++ b/src/citra_qt/configuration/config.cpp
@@ -745,6 +745,7 @@ void QtConfig::ReadSystemValues() {
ReadBasicSetting(Settings::values.steps_per_hour);
ReadBasicSetting(Settings::values.plugin_loader_enabled);
ReadBasicSetting(Settings::values.allow_plugin_loader);
+ ReadBasicSetting(Settings::values.apply_region_free_patch);
}
qt_config->endGroup();
@@ -1276,6 +1277,7 @@ void QtConfig::SaveSystemValues() {
WriteBasicSetting(Settings::values.steps_per_hour);
WriteBasicSetting(Settings::values.plugin_loader_enabled);
WriteBasicSetting(Settings::values.allow_plugin_loader);
+ WriteBasicSetting(Settings::values.apply_region_free_patch);
}
qt_config->endGroup();
diff --git a/src/citra_qt/configuration/configure_system.cpp b/src/citra_qt/configuration/configure_system.cpp
index fb9f6d7bb..9ed8bebfa 100644
--- a/src/citra_qt/configuration/configure_system.cpp
+++ b/src/citra_qt/configuration/configure_system.cpp
@@ -313,6 +313,8 @@ void ConfigureSystem::SetConfiguration() {
ui->region_combobox->setCurrentIndex(Settings::values.region_value.GetValue() + 1);
}
+ ui->apply_region_free_patch->setChecked(Settings::values.apply_region_free_patch.GetValue());
+
ui->combo_init_clock->setCurrentIndex(static_cast(Settings::values.init_clock.GetValue()));
QDateTime date_time;
date_time.setSecsSinceEpoch(Settings::values.init_time.GetValue());
@@ -488,6 +490,7 @@ void ConfigureSystem::ApplyConfiguration() {
Settings::values.lle_applets = ui->toggle_lle_applets->isChecked();
Settings::values.enable_required_online_lle_modules =
ui->enable_required_online_lle_modules->isChecked();
+ Settings::values.apply_region_free_patch.SetValue(ui->apply_region_free_patch->isChecked());
Settings::values.plugin_loader_enabled.SetValue(ui->plugin_loader->isChecked());
Settings::values.allow_plugin_loader.SetValue(ui->allow_plugin_loader->isChecked());
@@ -710,6 +713,7 @@ void ConfigureSystem::SetupPerGameUI() {
}
// Hide most settings for now, we can implement them later
+ ui->apply_region_free_patch->setVisible(false);
ui->label_username->setVisible(false);
ui->label_birthday->setVisible(false);
ui->label_init_clock->setVisible(false);
diff --git a/src/citra_qt/configuration/configure_system.ui b/src/citra_qt/configuration/configure_system.ui
index 080ee139a..7327223d6 100644
--- a/src/citra_qt/configuration/configure_system.ui
+++ b/src/citra_qt/configuration/configure_system.ui
@@ -140,7 +140,18 @@ online features (if installed)
- -
+
-
+
+
+ Apply region free patch to
+installed applications.
+
+
+ Patches the region of installed applications to be region free, so that they always appear on the home menu.
+
+
+
+ -
@@ -153,21 +164,21 @@ online features (if installed)
- -
+
-
Username
- -
+
-
Birthday
- -
+
-
-
@@ -238,14 +249,14 @@ online features (if installed)
- -
+
-
Language
- -
+
-
Note: this can be overridden when region setting is auto-select
@@ -312,14 +323,14 @@ online features (if installed)
- -
+
-
Sound output mode
- -
+
-
-
@@ -338,31 +349,31 @@ online features (if installed)
- -
+
-
Country
- -
+
-
- -
+
-
- -
+
-
Clock
- -
+
-
-
@@ -376,28 +387,28 @@ online features (if installed)
- -
+
-
Startup time
- -
+
-
yyyy-MM-ddTHH:mm:ss
- -
+
-
Offset time
- -
+
-
-
@@ -421,14 +432,14 @@ online features (if installed)
- -
+
-
Initial System Ticks
- -
+
-
-
@@ -442,14 +453,14 @@ online features (if installed)
- -
+
-
Initial System Ticks Override
- -
+
-
@@ -462,21 +473,21 @@ online features (if installed)
- -
+
-
Play Coins
- -
+
-
300
- -
+
-
<html><head/><body><p>Number of steps per hour reported by the pedometer. Range from 0 to 65,535.</p></body></html>
@@ -486,28 +497,28 @@ online features (if installed)
- -
+
-
9999
- -
+
-
Run System Setup when Home Menu is launched
- -
+
-
Console ID:
- -
+
-
@@ -523,14 +534,14 @@ online features (if installed)
- -
+
-
MAC:
- -
+
-
@@ -546,21 +557,21 @@ online features (if installed)
- -
+
-
3GX Plugin Loader
- -
+
-
Enable 3GX plugin loader
- -
+
-
Allow applications to change plugin loader state
diff --git a/src/citra_sdl/config.cpp b/src/citra_sdl/config.cpp
index 58ac46e3c..a504dd3aa 100644
--- a/src/citra_sdl/config.cpp
+++ b/src/citra_sdl/config.cpp
@@ -253,6 +253,7 @@ void SdlConfig::ReadValues() {
ReadSetting("System", Settings::values.plugin_loader_enabled);
ReadSetting("System", Settings::values.allow_plugin_loader);
ReadSetting("System", Settings::values.steps_per_hour);
+ ReadSetting("System", Settings::values.apply_region_free_patch);
{
constexpr const char* default_init_time_offset = "0 00:00:00";
diff --git a/src/common/settings.cpp b/src/common/settings.cpp
index cd604e34a..0af00c2bf 100644
--- a/src/common/settings.cpp
+++ b/src/common/settings.cpp
@@ -153,6 +153,7 @@ void LogSettings() {
log_setting("System_RegionValue", values.region_value.GetValue());
log_setting("System_PluginLoader", values.plugin_loader_enabled.GetValue());
log_setting("System_PluginLoaderAllowed", values.allow_plugin_loader.GetValue());
+ log_setting("System_ApplyRegionFreePatch", values.apply_region_free_patch.GetValue());
log_setting("Debugging_DelayStartForLLEModules", values.delay_start_for_lle_modules.GetValue());
log_setting("Debugging_UseGdbstub", values.use_gdbstub.GetValue());
log_setting("Debugging_GdbstubPort", values.gdbstub_port.GetValue());
diff --git a/src/common/settings.h b/src/common/settings.h
index 589de0057..ee65c984e 100644
--- a/src/common/settings.h
+++ b/src/common/settings.h
@@ -481,6 +481,7 @@ struct Values {
Setting plugin_loader_enabled{false, "plugin_loader"};
Setting allow_plugin_loader{true, "allow_plugin_loader"};
Setting steps_per_hour{0, "steps_per_hour"};
+ Setting apply_region_free_patch{true, "apply_region_free_patch"};
// Renderer
SwitchableSetting graphics_api{
diff --git a/src/core/file_sys/archive_ncch.cpp b/src/core/file_sys/archive_ncch.cpp
index fb0be5640..345ba6a0f 100644
--- a/src/core/file_sys/archive_ncch.cpp
+++ b/src/core/file_sys/archive_ncch.cpp
@@ -116,6 +116,15 @@ ResultVal> NCCHArchive::OpenFile(const Path& path,
// Load NCCH .code or icon/banner/logo
result = ncch_container.LoadSectionExeFS(openfile_path.exefs_filepath.data(), buffer);
+ if (result == Loader::ResultStatus::Success && Settings::values.apply_region_free_patch &&
+ std::memcmp(openfile_path.exefs_filepath.data(), "icon", 4) == 0 &&
+ buffer.size() >= sizeof(Loader::SMDH)) {
+ // Change the SMDH region lockout value to be region free
+ Loader::SMDH* smdh = reinterpret_cast(buffer.data());
+ constexpr u32 REGION_LOCKOUT_REGION_FREE = 0x7FFFFFFF;
+
+ smdh->region_lockout = REGION_LOCKOUT_REGION_FREE;
+ }
std::unique_ptr delay_generator = std::make_unique();
file = std::make_unique(std::move(buffer), std::move(delay_generator));
} else {