diff --git a/src/citra/config.cpp b/src/citra/config.cpp
index 6b6617352f..ebea5f8409 100644
--- a/src/citra/config.cpp
+++ b/src/citra/config.cpp
@@ -73,8 +73,9 @@ void Config::ReadValues() {
     // Data Storage
     Settings::values.use_virtual_sd = sdl2_config->GetBoolean("Data Storage", "use_virtual_sd", true);
 
-    // System Region
-    Settings::values.region_value = sdl2_config->GetInteger("System Region", "region_value", 1);
+    // System
+    Settings::values.is_new3ds = sdl2_config->GetBoolean("System", "is_new3ds", false);
+    Settings::values.region_value = sdl2_config->GetInteger("System", "region_value", 1);
 
     // Miscellaneous
     Settings::values.log_filter = sdl2_config->Get("Miscellaneous", "log_filter", "*:Info");
diff --git a/src/citra_qt/config.cpp b/src/citra_qt/config.cpp
index 8e247ff5c0..66271aa7b0 100644
--- a/src/citra_qt/config.cpp
+++ b/src/citra_qt/config.cpp
@@ -55,7 +55,8 @@ void Config::ReadValues() {
     Settings::values.use_virtual_sd = qt_config->value("use_virtual_sd", true).toBool();
     qt_config->endGroup();
 
-    qt_config->beginGroup("System Region");
+    qt_config->beginGroup("System");
+    Settings::values.is_new3ds = qt_config->value("is_new3ds", false).toBool();
     Settings::values.region_value = qt_config->value("region_value", 1).toInt();
     qt_config->endGroup();
 
@@ -95,7 +96,8 @@ void Config::SaveValues() {
     qt_config->setValue("use_virtual_sd", Settings::values.use_virtual_sd);
     qt_config->endGroup();
 
-    qt_config->beginGroup("System Region");
+    qt_config->beginGroup("System");
+    qt_config->setValue("is_new3ds", Settings::values.is_new3ds);
     qt_config->setValue("region_value", Settings::values.region_value);
     qt_config->endGroup();
 
diff --git a/src/core/hle/service/apt/apt.cpp b/src/core/hle/service/apt/apt.cpp
index 6d72e81887..e6fcbc7144 100644
--- a/src/core/hle/service/apt/apt.cpp
+++ b/src/core/hle/service/apt/apt.cpp
@@ -13,6 +13,7 @@
 #include "core/hle/service/apt/apt_s.h"
 #include "core/hle/service/apt/apt_u.h"
 #include "core/hle/service/fs/archive.h"
+#include "core/hle/service/ptm/ptm.h"
 
 #include "core/hle/kernel/event.h"
 #include "core/hle/kernel/mutex.h"
@@ -41,6 +42,9 @@ static std::shared_ptr<std::vector<u8>> shared_font;
 
 static u32 cpu_percent; ///< CPU time available to the running application
 
+// APT::CheckNew3DSApp will check this unknown_ns_state_field to determine processing mode
+static u8 unknown_ns_state_field;
+
 /// Parameter data to be returned in the next call to Glance/ReceiveParameter
 static MessageParameter next_parameter;
 
@@ -264,6 +268,10 @@ void PrepareToStartApplication(Service::Interface* self) {
     u32 title_info4  = cmd_buff[4];
     u32 flags        = cmd_buff[5];
 
+    if (flags & 0x00000100) {
+        unknown_ns_state_field = 1;
+    }
+
     cmd_buff[1] = RESULT_SUCCESS.raw; // No error
 
     LOG_WARNING(Service_APT, "(STUBBED) called title_info1=0x%08X, title_info2=0x%08X, title_info3=0x%08X,"
@@ -379,6 +387,25 @@ void StartLibraryApplet(Service::Interface* self) {
     cmd_buff[1] = applet->Start(parameter).raw;
 }
 
+void SetNSStateField(Service::Interface* self) {
+    u32* cmd_buff = Kernel::GetCommandBuffer();
+
+    unknown_ns_state_field = cmd_buff[1];
+
+    cmd_buff[0] = IPC::MakeHeader(0x55, 1, 0);
+    cmd_buff[1] = RESULT_SUCCESS.raw;
+    LOG_WARNING(Service_APT, "(STUBBED) unknown_ns_state_field=%u", unknown_ns_state_field);
+}
+
+void GetNSStateField(Service::Interface* self) {
+    u32* cmd_buff = Kernel::GetCommandBuffer();
+
+    cmd_buff[0] = IPC::MakeHeader(0x56, 2, 0);
+    cmd_buff[1] = RESULT_SUCCESS.raw;
+    cmd_buff[8] = unknown_ns_state_field;
+    LOG_WARNING(Service_APT, "(STUBBED) unknown_ns_state_field=%u", unknown_ns_state_field);
+}
+
 void GetAppletInfo(Service::Interface* self) {
     u32* cmd_buff = Kernel::GetCommandBuffer();
     auto app_id = static_cast<AppletId>(cmd_buff[1]);
@@ -414,6 +441,29 @@ void GetStartupArgument(Service::Interface* self) {
     cmd_buff[2] = (parameter_size > 0) ? 1 : 0;
 }
 
+void CheckNew3DSApp(Service::Interface* self) {
+    u32* cmd_buff = Kernel::GetCommandBuffer();
+
+    if (unknown_ns_state_field) {
+        cmd_buff[1] = RESULT_SUCCESS.raw;
+        cmd_buff[2] = 0;
+    } else {
+        PTM::CheckNew3DS(self);
+    }
+
+    cmd_buff[0] = IPC::MakeHeader(0x101, 2, 0);
+    LOG_WARNING(Service_APT, "(STUBBED) called");
+}
+
+void CheckNew3DS(Service::Interface* self) {
+    u32* cmd_buff = Kernel::GetCommandBuffer();
+
+    PTM::CheckNew3DS(self);
+
+    cmd_buff[0] = IPC::MakeHeader(0x102, 2, 0);
+    LOG_WARNING(Service_APT, "(STUBBED) called");
+}
+
 void Init() {
     AddService(new APT_A_Interface);
     AddService(new APT_S_Interface);
@@ -449,6 +499,7 @@ void Init() {
     lock = Kernel::Mutex::Create(false, "APT_U:Lock");
 
     cpu_percent = 0;
+    unknown_ns_state_field = 0;
 
     // TODO(bunnei): Check if these are created in Initialize or on APT process startup.
     notification_event = Kernel::Event::Create(Kernel::ResetType::OneShot, "APT_U:Notification");
diff --git a/src/core/hle/service/apt/apt.h b/src/core/hle/service/apt/apt.h
index 668b4a66f2..fd3c2bd37c 100644
--- a/src/core/hle/service/apt/apt.h
+++ b/src/core/hle/service/apt/apt.h
@@ -361,6 +361,50 @@ void StartLibraryApplet(Service::Interface* self);
  */
 void GetStartupArgument(Service::Interface* self);
 
+/**
+ * APT::SetNSStateField service function
+ *  Inputs:
+ *      1 : u8 NS state field
+ *  Outputs:
+ *      1 : Result of function, 0 on success, otherwise error code
+ *  Note:
+ *      This writes the input u8 to a NS state field.
+ */
+void SetNSStateField(Service::Interface* self);
+
+/**
+ * APT::GetNSStateField service function
+ *  Outputs:
+ *      1 : Result of function, 0 on success, otherwise error code
+ *      8 : u8 NS state field
+ *  Note:
+ *      This returns a u8 NS state field(which can be set by cmd 0x00550040), at cmdreply+8.
+ */
+void GetNSStateField(Service::Interface* self);
+
+/**
+ * APT::CheckNew3DSApp service function
+ *  Outputs:
+ *      1: Result code, 0 on success, otherwise error code
+ *      2: u8 output: 0 = Old3DS, 1 = New3DS.
+ *  Note:
+ *  This uses PTMSYSM:CheckNew3DS.
+ *  When a certain NS state field is non-zero, the output value is zero,
+ *  Otherwise the output is from PTMSYSM:CheckNew3DS.
+ *  Normally this NS state field is zero, however this state field is set to 1
+ *  when APT:PrepareToStartApplication is used with flags bit8 is set.
+ */
+void CheckNew3DSApp(Service::Interface* self);
+
+/**
+ * Wrapper for PTMSYSM:CheckNew3DS
+ * APT::CheckNew3DS service function
+ *  Outputs:
+ *      1: Result code, 0 on success, otherwise error code
+ *      2: u8 output: 0 = Old3DS, 1 = New3DS.
+ */
+void CheckNew3DS(Service::Interface* self);
+
 /// Initialize the APT service
 void Init();
 
diff --git a/src/core/hle/service/apt/apt_a.cpp b/src/core/hle/service/apt/apt_a.cpp
index 9ff47701a9..223c0a8bd4 100644
--- a/src/core/hle/service/apt/apt_a.cpp
+++ b/src/core/hle/service/apt/apt_a.cpp
@@ -21,6 +21,7 @@ const Interface::FunctionInfo FunctionTable[] = {
     {0x000D0080, ReceiveParameter,             "ReceiveParameter"},
     {0x000E0080, GlanceParameter,              "GlanceParameter"},
     {0x000F0100, CancelParameter,              "CancelParameter"},
+    {0x00150140, PrepareToStartApplication,    "PrepareToStartApplication"},
     {0x00160040, PreloadLibraryApplet,         "PreloadLibraryApplet"},
     {0x00180040, PrepareToStartLibraryApplet,  "PrepareToStartLibraryApplet"},
     {0x001E0084, StartLibraryApplet,           "StartLibraryApplet"},
@@ -32,7 +33,10 @@ const Interface::FunctionInfo FunctionTable[] = {
     {0x004F0080, SetAppCpuTimeLimit,           "SetAppCpuTimeLimit"},
     {0x00500040, GetAppCpuTimeLimit,           "GetAppCpuTimeLimit"},
     {0x00510080, GetStartupArgument,           "GetStartupArgument"},
-    {0x00550040, nullptr,                      "WriteInputToNsState?"},
+    {0x00550040, SetNSStateField,              "SetNSStateField?"},
+    {0x00560000, GetNSStateField,              "GetNSStateField?"},
+    {0x01010000, CheckNew3DSApp,               "CheckNew3DSApp"},
+    {0x01020000, CheckNew3DS,                  "CheckNew3DS"}
 };
 
 APT_A_Interface::APT_A_Interface() {
diff --git a/src/core/hle/service/apt/apt_s.cpp b/src/core/hle/service/apt/apt_s.cpp
index ca54e593c0..f5c52fa3db 100644
--- a/src/core/hle/service/apt/apt_s.cpp
+++ b/src/core/hle/service/apt/apt_s.cpp
@@ -29,7 +29,7 @@ const Interface::FunctionInfo FunctionTable[] = {
     {0x00120040, nullptr,               "SetHomeMenuAppletIdForDebug"},
     {0x00130000, nullptr,               "GetPreparationState"},
     {0x00140040, nullptr,               "SetPreparationState"},
-    {0x00150140, nullptr,               "PrepareToStartApplication"},
+    {0x00150140, PrepareToStartApplication, "PrepareToStartApplication"},
     {0x00160040, PreloadLibraryApplet,  "PreloadLibraryApplet"},
     {0x00170040, nullptr,               "FinishPreloadingLibraryApplet"},
     {0x00180040, PrepareToStartLibraryApplet,"PrepareToStartLibraryApplet"},
@@ -92,9 +92,11 @@ const Interface::FunctionInfo FunctionTable[] = {
     {0x00510080, GetStartupArgument,    "GetStartupArgument"},
     {0x00520104, nullptr,               "Wrap1"},
     {0x00530104, nullptr,               "Unwrap1"},
+    {0x00550040, SetNSStateField,       "SetNSStateField?" },
+    {0x00560000, GetNSStateField,       "GetNSStateField?" },
     {0x00580002, nullptr,               "GetProgramID"},
-    {0x01010000, nullptr,               "CheckNew3DSApp"},
-    {0x01020000, nullptr,               "CheckNew3DS"}
+    {0x01010000, CheckNew3DSApp,        "CheckNew3DSApp"},
+    {0x01020000, CheckNew3DS,           "CheckNew3DS"}
 };
 
 APT_S_Interface::APT_S_Interface() {
diff --git a/src/core/hle/service/apt/apt_u.cpp b/src/core/hle/service/apt/apt_u.cpp
index 0e85c6d08f..0e60bd34f9 100644
--- a/src/core/hle/service/apt/apt_u.cpp
+++ b/src/core/hle/service/apt/apt_u.cpp
@@ -29,7 +29,7 @@ const Interface::FunctionInfo FunctionTable[] = {
     {0x00120040, nullptr,                         "SetHomeMenuAppletIdForDebug"},
     {0x00130000, nullptr,                         "GetPreparationState"},
     {0x00140040, nullptr,                         "SetPreparationState"},
-    {0x00150140, nullptr,                         "PrepareToStartApplication"},
+    {0x00150140, PrepareToStartApplication,       "PrepareToStartApplication"},
     {0x00160040, PreloadLibraryApplet,            "PreloadLibraryApplet"},
     {0x00170040, nullptr,                         "FinishPreloadingLibraryApplet"},
     {0x00180040, PrepareToStartLibraryApplet,     "PrepareToStartLibraryApplet"},
@@ -92,9 +92,11 @@ const Interface::FunctionInfo FunctionTable[] = {
     {0x00510080, GetStartupArgument,              "GetStartupArgument"},
     {0x00520104, nullptr,                         "Wrap1"},
     {0x00530104, nullptr,                         "Unwrap1"},
+    {0x00550040, SetNSStateField,                 "SetNSStateField?"},
+    {0x00560000, GetNSStateField,                 "GetNSStateField?"},
     {0x00580002, nullptr,                         "GetProgramID"},
-    {0x01010000, nullptr,                         "CheckNew3DSApp"},
-    {0x01020000, nullptr,                         "CheckNew3DS"}
+    {0x01010000, CheckNew3DSApp,                  "CheckNew3DSApp"},
+    {0x01020000, CheckNew3DS,                     "CheckNew3DS"}
 };
 
 APT_U_Interface::APT_U_Interface() {
diff --git a/src/core/hle/service/ptm/ptm.cpp b/src/core/hle/service/ptm/ptm.cpp
index 94f4946906..3a0331ee19 100644
--- a/src/core/hle/service/ptm/ptm.cpp
+++ b/src/core/hle/service/ptm/ptm.cpp
@@ -3,7 +3,7 @@
 // Refer to the license.txt file included.
 
 #include "common/logging/log.h"
-
+#include "core/settings.h"
 #include "core/file_sys/file_backend.h"
 #include "core/hle/service/fs/archive.h"
 #include "core/hle/service/ptm/ptm.h"
@@ -89,6 +89,20 @@ void IsLegacyPowerOff(Service::Interface* self) {
     LOG_WARNING(Service_PTM, "(STUBBED) called");
 }
 
+void CheckNew3DS(Service::Interface* self) {
+    u32* cmd_buff = Kernel::GetCommandBuffer();
+    const bool is_new_3ds = Settings::values.is_new3ds;
+
+    if (is_new_3ds) {
+        LOG_CRITICAL(Service_PTM, "The option 'is_new3ds' is enabled as part of the 'System' settings. Citra does not fully support New3DS emulation yet!");
+    }
+
+    cmd_buff[1] = RESULT_SUCCESS.raw;
+    cmd_buff[2] = is_new_3ds ? 1 : 0;
+
+    LOG_WARNING(Service_PTM, "(STUBBED) called isNew3DS = 0x%08x", static_cast<u32>(is_new_3ds));
+}
+
 void Init() {
     AddService(new PTM_Play_Interface);
     AddService(new PTM_Sysm_Interface);
diff --git a/src/core/hle/service/ptm/ptm.h b/src/core/hle/service/ptm/ptm.h
index 4cf7383d10..7ef8877c71 100644
--- a/src/core/hle/service/ptm/ptm.h
+++ b/src/core/hle/service/ptm/ptm.h
@@ -88,6 +88,14 @@ void GetTotalStepCount(Interface* self);
  */
 void IsLegacyPowerOff(Interface* self);
 
+/**
+ * PTM::CheckNew3DS service function
+ *  Outputs:
+ *      1: Result code, 0 on success, otherwise error code
+ *      2: u8 output: 0 = Old3DS, 1 = New3DS.
+ */
+void CheckNew3DS(Interface* self);
+
 /// Initialize the PTM service
 void Init();
 
diff --git a/src/core/hle/service/ptm/ptm_sysm.cpp b/src/core/hle/service/ptm/ptm_sysm.cpp
index fe76dd1084..cc4ef11010 100644
--- a/src/core/hle/service/ptm/ptm_sysm.cpp
+++ b/src/core/hle/service/ptm/ptm_sysm.cpp
@@ -18,7 +18,7 @@ const Interface::FunctionInfo FunctionTable[] = {
     {0x040700C0, nullptr,             "ShutdownAsync"},
     {0x04080000, nullptr,             "Awake"},
     {0x04090080, nullptr,             "RebootAsync"},
-    {0x040A0000, nullptr,             "CheckNew3DS"},
+    {0x040A0000, CheckNew3DS,         "CheckNew3DS"},
     {0x08010640, nullptr,             "SetInfoLEDPattern"},
     {0x08020040, nullptr,             "SetInfoLEDPatternHeader"},
     {0x08030000, nullptr,             "GetInfoLEDStatus"},
@@ -35,7 +35,7 @@ const Interface::FunctionInfo FunctionTable[] = {
     {0x080E0140, nullptr,             "NotifyPlayEvent"},
     {0x080F0000, IsLegacyPowerOff,    "IsLegacyPowerOff"},
     {0x08100000, nullptr,             "ClearLegacyPowerOff"},
-    {0x08110000, nullptr,             "GetShellStatus"},
+    {0x08110000, GetShellState,       "GetShellState"},
     {0x08120000, nullptr,             "IsShutdownByBatteryEmpty"},
     {0x08130000, nullptr,             "FormatSavedata"},
     {0x08140000, nullptr,             "GetLegacyJumpProhibitedFlag"},
diff --git a/src/core/settings.h b/src/core/settings.h
index 97ddcdff9d..4034b795a4 100644
--- a/src/core/settings.h
+++ b/src/core/settings.h
@@ -40,6 +40,9 @@ static const std::array<Values, NUM_INPUTS> All = {{
 
 
 struct Values {
+    // CheckNew3DS
+    bool is_new3ds;
+
     // Controls
     std::array<int, NativeInput::NUM_INPUTS> input_mappings;