diff --git a/CMakeModules/GenerateSettingKeys.cmake b/CMakeModules/GenerateSettingKeys.cmake
index 005011dd8..15a28a5de 100644
--- a/CMakeModules/GenerateSettingKeys.cmake
+++ b/CMakeModules/GenerateSettingKeys.cmake
@@ -114,6 +114,7 @@ foreach(KEY IN ITEMS
"enable_rpc_server"
"log_filter"
"log_regex_filter"
+ "toggle_unique_data_console_type"
"use_integer_scaling"
"layouts_to_cycle"
"camera_inner_flip"
diff --git a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/SettingKeys.kt b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/SettingKeys.kt
index 636bc46f4..1d6e0dcee 100644
--- a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/SettingKeys.kt
+++ b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/SettingKeys.kt
@@ -102,6 +102,7 @@ object SettingKeys {
external fun gdbstub_port(): String
external fun instant_debug_log(): String
external fun enable_rpc_server(): String
+ external fun toggle_unique_data_console_type(): String
external fun log_filter(): String
external fun log_regex_filter(): String
external fun use_integer_scaling(): String
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 803a068d4..e12d87544 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
@@ -20,6 +20,7 @@ enum class BooleanSetting(
SWAP_SCREEN(SettingKeys.swap_screen(), Settings.SECTION_LAYOUT, false),
INSTANT_DEBUG_LOG(SettingKeys.instant_debug_log(), Settings.SECTION_DEBUG, false),
ENABLE_RPC_SERVER(SettingKeys.enable_rpc_server(), Settings.SECTION_DEBUG, false),
+ TOGGLE_UNIQUE_DATA_CONSOLE_TYPE(SettingKeys.toggle_unique_data_console_type(), Settings.SECTION_DEBUG, false),
SWAP_EYES_3D(SettingKeys.swap_eyes_3d(),Settings.SECTION_RENDERER, false),
PERF_OVERLAY_ENABLE(SettingKeys.performance_overlay_enable(), Settings.SECTION_LAYOUT, false),
PERF_OVERLAY_SHOW_FPS(SettingKeys.performance_overlay_show_fps(), Settings.SECTION_LAYOUT, true),
@@ -82,6 +83,7 @@ enum class BooleanSetting(
REQUIRED_ONLINE_LLE_MODULES,
NEW_3DS,
LLE_APPLETS,
+ TOGGLE_UNIQUE_DATA_CONSOLE_TYPE,
VSYNC,
DEBUG_RENDERER,
CPU_JIT,
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 1b7812342..0143ac804 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
@@ -1817,6 +1817,15 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView)
BooleanSetting.ENABLE_RPC_SERVER.defaultValue
)
)
+ add(
+ SwitchSetting(
+ BooleanSetting.TOGGLE_UNIQUE_DATA_CONSOLE_TYPE,
+ R.string.toggle_unique_data_console_type,
+ R.string.toggle_unique_data_console_type_desc,
+ BooleanSetting.TOGGLE_UNIQUE_DATA_CONSOLE_TYPE.key,
+ BooleanSetting.TOGGLE_UNIQUE_DATA_CONSOLE_TYPE.defaultValue
+ )
+ )
add(
SwitchSetting(
BooleanSetting.DELAY_START_LLE_MODULES,
diff --git a/src/android/app/src/main/jni/config.cpp b/src/android/app/src/main/jni/config.cpp
index 0a620f7ba..e0fa260c5 100644
--- a/src/android/app/src/main/jni/config.cpp
+++ b/src/android/app/src/main/jni/config.cpp
@@ -315,6 +315,7 @@ void Config::ReadValues() {
ReadSetting("Debugging", Settings::values.gdbstub_port);
ReadSetting("Debugging", Settings::values.instant_debug_log);
ReadSetting("Debugging", Settings::values.enable_rpc_server);
+ ReadSetting("Debugging", Settings::values.toggle_unique_data_console_type);
for (const auto& service_module : Service::service_module_map) {
bool use_lle =
diff --git a/src/android/app/src/main/jni/default_ini.h b/src/android/app/src/main/jni/default_ini.h
index 851ff33a7..5e2eab1d1 100644
--- a/src/android/app/src/main/jni/default_ini.h
+++ b/src/android/app/src/main/jni/default_ini.h
@@ -539,6 +539,10 @@ static const char* android_config_default_file_content = (BOOST_HANA_STRING(R"(
# 0 (default): Off, 1: On
)") DECLARE_KEY(enable_rpc_server) BOOST_HANA_STRING(R"(
+# Enables toggling the unique data console type (Old 3DS <-> New 3DS) to be able to download the opposite system firmware type from system settings.
+# 0 (default): Off, 1: On
+)") DECLARE_KEY(toggle_unique_data_console_type) BOOST_HANA_STRING(R"(
+
# Delay the start of apps when LLE modules are enabled
# 0: Off, 1 (default): On
)") DECLARE_KEY(delay_start_for_lle_modules) BOOST_HANA_STRING(R"(
diff --git a/src/android/app/src/main/res/values/strings.xml b/src/android/app/src/main/res/values/strings.xml
index fb8fbf8fd..46a2b0e47 100644
--- a/src/android/app/src/main/res/values/strings.xml
+++ b/src/android/app/src/main/res/values/strings.xml
@@ -357,6 +357,8 @@
Makes async operations deterministic for debugging. Enabling this may cause freezes.
Enable RPC Server
Enables the RPC server on port 45987. This allows remotely reading/writing guest memory.
+ Toggle unique data console type
+ Toggles the unique data console type (Old 3DS ↔ New 3DS) to be able to download the opposite system firmware type from system settings.
Enable Shader JIT
Use the JIT engine instead of the interpreter for software shader emulation.
diff --git a/src/citra_qt/configuration/config.cpp b/src/citra_qt/configuration/config.cpp
index 013054daa..fa6ff311d 100644
--- a/src/citra_qt/configuration/config.cpp
+++ b/src/citra_qt/configuration/config.cpp
@@ -504,6 +504,7 @@ void QtConfig::ReadDebuggingValues() {
ReadBasicSetting(Settings::values.dump_command_buffers);
ReadBasicSetting(Settings::values.instant_debug_log);
ReadBasicSetting(Settings::values.enable_rpc_server);
+ ReadBasicSetting(Settings::values.toggle_unique_data_console_type);
qt_config->beginGroup(QStringLiteral("LLE"));
for (const auto& service_module : Service::service_module_map) {
@@ -1084,6 +1085,7 @@ void QtConfig::SaveDebuggingValues() {
WriteBasicSetting(Settings::values.renderer_debug);
WriteBasicSetting(Settings::values.instant_debug_log);
WriteBasicSetting(Settings::values.enable_rpc_server);
+ WriteBasicSetting(Settings::values.toggle_unique_data_console_type);
qt_config->beginGroup(QStringLiteral("LLE"));
for (const auto& service_module : Settings::values.lle_modules) {
diff --git a/src/citra_qt/configuration/configure_debug.cpp b/src/citra_qt/configuration/configure_debug.cpp
index 33592081e..0fe4f49cf 100644
--- a/src/citra_qt/configuration/configure_debug.cpp
+++ b/src/citra_qt/configuration/configure_debug.cpp
@@ -74,6 +74,7 @@ ConfigureDebug::ConfigureDebug(bool is_powered_on_, QWidget* parent)
ui->toggle_renderer_debug->setEnabled(!is_powered_on);
ui->toggle_dump_command_buffers->setEnabled(!is_powered_on);
ui->enable_rpc_server->setEnabled(!is_powered_on);
+ ui->toggle_unique_data_console_type->setEnabled(!is_powered_on);
// Set a minimum width for the label to prevent the slider from changing size.
// This scales across DPIs. (This value should be enough for "xxx%")
@@ -109,6 +110,8 @@ void ConfigureDebug::SetConfiguration() {
#ifndef ENABLE_SCRIPTING
ui->enable_rpc_server->setVisible(false);
#endif // !ENABLE_SCRIPTING
+ ui->toggle_unique_data_console_type->setChecked(
+ Settings::values.toggle_unique_data_console_type.GetValue());
ui->toggle_renderer_debug->setChecked(Settings::values.renderer_debug.GetValue());
ui->toggle_dump_command_buffers->setChecked(Settings::values.dump_command_buffers.GetValue());
@@ -148,6 +151,8 @@ void ConfigureDebug::ApplyConfiguration() {
Settings::values.deterministic_async_operations =
ui->deterministic_async_operations->isChecked();
Settings::values.enable_rpc_server = ui->enable_rpc_server->isChecked();
+ Settings::values.toggle_unique_data_console_type =
+ ui->toggle_unique_data_console_type->isChecked();
Settings::values.renderer_debug = ui->toggle_renderer_debug->isChecked();
Settings::values.dump_command_buffers = ui->toggle_dump_command_buffers->isChecked();
Settings::values.instant_debug_log = ui->instant_debug_log->isChecked();
@@ -172,6 +177,7 @@ void ConfigureDebug::SetupPerGameUI() {
ui->groupBox->setVisible(false);
ui->groupBox_2->setVisible(false);
ui->enable_rpc_server->setVisible(false);
+ ui->toggle_unique_data_console_type->setVisible(false);
ui->toggle_cpu_jit->setVisible(false);
}
diff --git a/src/citra_qt/configuration/configure_debug.ui b/src/citra_qt/configuration/configure_debug.ui
index 3f8fe661c..990835a80 100644
--- a/src/citra_qt/configuration/configure_debug.ui
+++ b/src/citra_qt/configuration/configure_debug.ui
@@ -270,6 +270,16 @@
-
+
+
+ <html><head/><body><p>Toggles the unique data console type (Old 3DS ↔ New 3DS) to be able to download the opposite system firmware type from system settings.</p></body></html>
+
+
+ Toggle unique data console type
+
+
+
+ -
Force deterministic async operations
@@ -279,7 +289,7 @@
- -
+
-
Enable RPC server
diff --git a/src/common/settings.cpp b/src/common/settings.cpp
index eb8e9be3b..2ac231f50 100644
--- a/src/common/settings.cpp
+++ b/src/common/settings.cpp
@@ -163,6 +163,8 @@ void LogSettings() {
log_setting("Debugging_UseGdbstub", values.use_gdbstub.GetValue());
log_setting("Debugging_GdbstubPort", values.gdbstub_port.GetValue());
log_setting("Debugging_InstantDebugLog", values.instant_debug_log.GetValue());
+ log_setting("Debugging_ToggleUniqueDataConsoleType",
+ values.toggle_unique_data_console_type.GetValue());
}
bool IsConfiguringGlobal() {
diff --git a/src/common/settings.h b/src/common/settings.h
index b8826646f..e03c46961 100644
--- a/src/common/settings.h
+++ b/src/common/settings.h
@@ -635,6 +635,7 @@ struct Values {
Setting gdbstub_port{24689, Keys::gdbstub_port};
Setting instant_debug_log{false, Keys::instant_debug_log};
Setting enable_rpc_server{false, Keys::enable_rpc_server};
+ Setting toggle_unique_data_console_type{false, Keys::toggle_unique_data_console_type};
// Miscellaneous
Setting log_filter{"*:Info", Keys::log_filter};
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp
index af2739590..3ba4c61f0 100644
--- a/src/core/hle/service/am/am.cpp
+++ b/src/core/hle/service/am/am.cpp
@@ -2852,11 +2852,15 @@ void Module::Interface::GetDeviceID(Kernel::HLERequestContext& ctx) {
}
u32 deviceID = otp.GetDeviceID();
- if (am->force_new_device_id) {
- deviceID |= 0x80000000;
- }
- if (am->force_old_device_id) {
- deviceID &= ~0x80000000;
+ if (am->force_new_device_id || am->force_old_device_id) {
+ if (am->force_new_device_id) {
+ deviceID |= 0x80000000;
+ }
+ if (am->force_old_device_id) {
+ deviceID &= ~0x80000000;
+ }
+ } else if (Settings::values.toggle_unique_data_console_type) {
+ deviceID ^= 0x80000000;
}
IPC::RequestBuilder rb = rp.MakeBuilder(3, 0);