diff --git a/src/core/hle/service/ptm/ptm.cpp b/src/core/hle/service/ptm/ptm.cpp index 6e6b63329..162988535 100644 --- a/src/core/hle/service/ptm/ptm.cpp +++ b/src/core/hle/service/ptm/ptm.cpp @@ -10,11 +10,11 @@ #include "core/hle/service/ptm/ptm_sysm.h" #include "core/hle/service/ptm/ptm_u.h" #include "core/hle/service/service.h" +#include "core/hle/svc.h" #include "core/settings.h" namespace Service { namespace PTM { - /// Values for the default gamecoin.dat file static const GameCoin default_game_coin = {0x4F00, 42, 0, 0, 0, 2014, 12, 29}; @@ -99,12 +99,25 @@ void CheckNew3DS(Service::Interface* self) { "settings. Citra does not fully support New 3DS emulation yet!"); } + cmd_buff[0] = IPC::MakeHeader(0x40A, 0x2, 0); 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(is_new_3ds)); } +void ConfigureNew3DSCPU(Interface* self) { + u32* cmd_buff = Kernel::GetCommandBuffer(); + u32 value = cmd_buff[1] & 0xF; + + cmd_buff[0] = IPC::MakeHeader(0x818, 0x1, 0); + cmd_buff[1] = SVC::KernelSetState(static_cast(SVC::KernelSetStateType::ConfigureNew3DSCPU), + value, 0, 0) + .raw; + + LOG_WARNING(Service_PTM, "(STUBBED) called"); +} + 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 6e163a6f9..552b12541 100644 --- a/src/core/hle/service/ptm/ptm.h +++ b/src/core/hle/service/ptm/ptm.h @@ -91,12 +91,31 @@ void IsLegacyPowerOff(Interface* self); /** * PTM::CheckNew3DS service function + * Inputs: + * 0 : Header code [0x040A0000] * Outputs: - * 1: Result code, 0 on success, otherwise error code - * 2: u8 output: 0 = Old3DS, 1 = New3DS. + * 0 : Header code + * 1 : Result code, 0 on success, otherwise error code + * 2 : u8 output: 0 = Old3DS, 1 = New3DS. */ void CheckNew3DS(Interface* self); +/* + * PTM::ConfigureNew3DSCPU service function + * Inputs: + * 0 : Header code [0x08180040] + * 1 : u8 value, only bit0-1 are used here. + * Bit 0 enables higher core clock, and bit 1 enables additional (L2) cache. + * Outputs: + * 0 : Header code + * 1 : Result code + * Note: + * This just uses svcKernelSetState with Type10 where Param0=. + * This command is implemented in the Old3DS PTM sysmodule too, + * but the above type is only implemented in the New3DS ARM11-kernel. + */ +void ConfigureNew3DSCPU(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 693158dbf..c8bdf424a 100644 --- a/src/core/hle/service/ptm/ptm_sysm.cpp +++ b/src/core/hle/service/ptm/ptm_sysm.cpp @@ -39,7 +39,7 @@ const Interface::FunctionInfo FunctionTable[] = { {0x08120000, nullptr, "IsShutdownByBatteryEmpty"}, {0x08130000, nullptr, "FormatSavedata"}, {0x08140000, nullptr, "GetLegacyJumpProhibitedFlag"}, - {0x08180040, nullptr, "ConfigureNew3DSCPU"}, + {0x08180040, ConfigureNew3DSCPU, "ConfigureNew3DSCPU"}, }; PTM_Sysm_Interface::PTM_Sysm_Interface() { diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp index 02b397eba..4d6ccdc29 100644 --- a/src/core/hle/svc.cpp +++ b/src/core/hle/svc.cpp @@ -26,6 +26,7 @@ #include "core/hle/kernel/vm_manager.h" #include "core/hle/result.h" #include "core/hle/service/service.h" +#include "core/settings.h" //////////////////////////////////////////////////////////////////////////////////////////////////// // Namespace SVC @@ -34,6 +35,8 @@ using Kernel::SharedPtr; using Kernel::ERR_INVALID_HANDLE; namespace SVC { +static bool enable_higher_core_clock = false; +static bool enable_additional_cache = false; const ResultCode ERR_NOT_FOUND(ErrorDescription::NotFound, ErrorModule::Kernel, ErrorSummary::NotFound, ErrorLevel::Permanent); // 0xD88007FA @@ -988,6 +991,39 @@ static ResultCode GetProcessInfo(s64* out, Handle process_handle, u32 type) { return RESULT_SUCCESS; } +ResultCode KernelSetState(u32 type, u32 param0, u32 param1, u32 param2) { + const bool is_new_3ds = Settings::values.is_new_3ds; + + switch (static_cast(type)) { + case KernelSetStateType::Type0: + case KernelSetStateType::Type1: + case KernelSetStateType::Type2: + case KernelSetStateType::Type3: + case KernelSetStateType::Type4: + case KernelSetStateType::Type5: + case KernelSetStateType::Type6: + case KernelSetStateType::Type7: + case KernelSetStateType::Type8: + case KernelSetStateType::Type9: + LOG_ERROR(Kernel_SVC, "unimplemented KernelSetState type=%u", type); + UNIMPLEMENTED(); + break; + case KernelSetStateType::ConfigureNew3DSCPU: + enable_higher_core_clock = (is_new_3ds && param0 & 0x00000001); + enable_additional_cache = (is_new_3ds && (param0 >> 1) & 0x00000001); + LOG_WARNING(Kernel_SVC, + "ConfigureNew3DSCPU enables_higher_core_clock=%u, enables_additional_cache=%u", + enable_higher_core_clock, enable_additional_cache); + break; + default: + return ResultCode( // 0xF8C007F4 + ErrorDescription::InvalidEnumValue, ErrorModule::Kernel, ErrorSummary::InvalidArgument, + ErrorLevel::Permanent); + break; + } + return RESULT_SUCCESS; +} + namespace { struct FunctionDef { using Func = void(); @@ -1123,7 +1159,7 @@ static const FunctionDef SVC_Table[] = { {0x79, nullptr, "SetResourceLimitValues"}, {0x7A, nullptr, "AddCodeSegment"}, {0x7B, nullptr, "Backdoor"}, - {0x7C, nullptr, "KernelSetState"}, + {0x7C, HLE::Wrap, "KernelSetState"}, {0x7D, HLE::Wrap, "QueryProcessMemory"}, }; diff --git a/src/core/hle/svc.h b/src/core/hle/svc.h index 818973eb6..e43980c06 100644 --- a/src/core/hle/svc.h +++ b/src/core/hle/svc.h @@ -9,6 +9,8 @@ //////////////////////////////////////////////////////////////////////////////////////////////////// // SVC types +union ResultCode; + struct MemoryInfo { u32 base_address; u32 size; @@ -54,6 +56,28 @@ enum class SystemInfoMemUsageRegion { BASE = 3, }; +enum class KernelSetStateType : u32 { + Type0 = 0, + Type1 = 1, + Type2 = 2, + Type3 = 3, + Type4 = 4, + Type5 = 5, + Type6 = 6, + Type7 = 7, + Type8 = 8, + Type9 = 9, + ConfigureNew3DSCPU = 10 +}; + void CallSVC(u32 immediate); +/** + * SVC::KernelSetState + * Note: The type determines the meaning of each param + * 0xF8C007F4 Invalid type/param0-param3 input for svcKernelSetState. + * This is also returned for those syscalls marked as stubs. + */ +ResultCode KernelSetState(u32 type, u32 param0, u32 param1, u32 param2); + } // namespace