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:
JamePeng 2016-04-20 18:12:05 +08:00
parent a4c5d8fd50
commit 7129611e65
11 changed files with 145 additions and 14 deletions

View file

@ -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");

View file

@ -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();

View file

@ -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");

View file

@ -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();

View file

@ -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() {

View file

@ -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() {

View file

@ -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() {

View file

@ -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);

View file

@ -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();

View file

@ -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"},

View file

@ -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;