Implement CheckNew3DS and CheckNew3DSApp
Append an item[is_new3ds] to config file[System] group Implement APT::SetNSStateField,it will update the unknown NS_state_field
This commit is contained in:
parent
a4c5d8fd50
commit
7129611e65
11 changed files with 145 additions and 14 deletions
|
@ -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");
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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"},
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
Loading…
Reference in a new issue