From 662bb9ba7787dd580b922c6a9962a10ccc6ab77d Mon Sep 17 00:00:00 2001 From: Steveice10 <1269164+Steveice10@users.noreply.github.com> Date: Fri, 7 Jul 2023 22:05:38 -0700 Subject: [PATCH] hle: Stub some service calls used by the home menu. (#6675) --- src/common/logging/filter.cpp | 1 + src/common/logging/types.h | 1 + src/core/hle/kernel/shared_page.cpp | 19 +++++++++-------- src/core/hle/kernel/shared_page.h | 7 ++++++- src/core/hle/service/act/act.cpp | 30 +++++++++++++++++++++++++++ src/core/hle/service/act/act.h | 27 ++++++++++++++++++++++++ src/core/hle/service/act/act_a.cpp | 4 ++-- src/core/hle/service/act/act_u.cpp | 4 ++-- src/core/hle/service/am/am.cpp | 11 ++++++++++ src/core/hle/service/am/am.h | 10 +++++++++ src/core/hle/service/am/am_net.cpp | 2 +- src/core/hle/service/am/am_sys.cpp | 2 +- src/core/hle/service/am/am_u.cpp | 2 +- src/core/hle/service/cfg/cfg.cpp | 11 ++++++++++ src/core/hle/service/cfg/cfg.h | 11 ++++++++++ src/core/hle/service/cfg/cfg_i.cpp | 4 ++-- src/core/hle/service/cfg/cfg_s.cpp | 2 +- src/core/hle/service/news/news_s.cpp | 25 +++++++++++++++++++++- src/core/hle/service/news/news_s.h | 14 +++++++++++++ src/core/hle/service/ptm/ptm.cpp | 12 +++++++++++ src/core/hle/service/ptm/ptm.h | 8 +++++++ src/core/hle/service/ptm/ptm_gets.cpp | 2 +- 22 files changed, 187 insertions(+), 22 deletions(-) diff --git a/src/common/logging/filter.cpp b/src/common/logging/filter.cpp index c469993e8..2a2b85e84 100644 --- a/src/common/logging/filter.cpp +++ b/src/common/logging/filter.cpp @@ -88,6 +88,7 @@ bool ParseFilterRule(Filter& instance, Iterator begin, Iterator end) { SUB(Service, FRD) \ SUB(Service, FS) \ SUB(Service, ERR) \ + SUB(Service, ACT) \ SUB(Service, APT) \ SUB(Service, BOSS) \ SUB(Service, GSP) \ diff --git a/src/common/logging/types.h b/src/common/logging/types.h index f4db2dc42..8d27c18c2 100644 --- a/src/common/logging/types.h +++ b/src/common/logging/types.h @@ -55,6 +55,7 @@ enum class Class : u8 { Service_FRD, ///< The FRD (Friends) service Service_FS, ///< The FS (Filesystem) service implementation Service_ERR, ///< The ERR (Error) port implementation + Service_ACT, ///< The ACT (Account) service Service_APT, ///< The APT (Applets) service Service_BOSS, ///< The BOSS (SpotPass) service Service_GSP, ///< The GSP (GPU control) service diff --git a/src/core/hle/kernel/shared_page.cpp b/src/core/hle/kernel/shared_page.cpp index f1e59416f..249c912d9 100644 --- a/src/core/hle/kernel/shared_page.cpp +++ b/src/core/hle/kernel/shared_page.cpp @@ -87,8 +87,7 @@ Handler::Handler(Core::Timing& timing) : timing(timing) { shared_page.sliderstate_3d = static_cast(slidestate); } -/// Gets system time in 3DS format. The epoch is Jan 1900, and the unit is millisecond. -u64 Handler::GetSystemTime() const { +u64 Handler::GetSystemTimeSince2000() const { std::chrono::milliseconds now = init_time + std::chrono::duration_cast(timing.GetGlobalTimeUs()); @@ -104,23 +103,25 @@ u64 Handler::GetSystemTime() const { epoch_tm.tm_isdst = 0; s64 epoch = std::mktime(&epoch_tm) * 1000; - // 3DS console time uses Jan 1 1900 as internal epoch, - // so we use the milliseconds between 1900 and 2000 as base console time - u64 console_time = 3155673600000ULL; - // Only when system time is after 2000, we set it as 3DS system time if (now.count() > epoch) { - console_time += (now.count() - epoch); + return now.count() - epoch; + } else { + return 0; } +} - return console_time; +u64 Handler::GetSystemTimeSince1900() const { + // 3DS console time uses Jan 1 1900 as internal epoch, + // so we use the milliseconds between 1900 and 2000 as base console time + return 3155673600000ULL + GetSystemTimeSince2000(); } void Handler::UpdateTimeCallback(std::uintptr_t user_data, int cycles_late) { DateTime& date_time = shared_page.date_time_counter % 2 ? shared_page.date_time_0 : shared_page.date_time_1; - date_time.date_time = GetSystemTime(); + date_time.date_time = GetSystemTimeSince1900(); date_time.update_tick = timing.GetTicks(); date_time.tick_to_second_coefficient = BASE_CLOCK_RATE_ARM11; date_time.tick_offset = 0; diff --git a/src/core/hle/kernel/shared_page.h b/src/core/hle/kernel/shared_page.h index 505a89ec4..ef7b86e5c 100644 --- a/src/core/hle/kernel/shared_page.h +++ b/src/core/hle/kernel/shared_page.h @@ -110,8 +110,13 @@ public: return sizeof(shared_page); } + /// Gets the system time in milliseconds since the year 2000. + u64 GetSystemTimeSince2000() const; + + /// Gets the system time in milliseconds since the year 1900. + u64 GetSystemTimeSince1900() const; + private: - u64 GetSystemTime() const; void UpdateTimeCallback(std::uintptr_t user_data, int cycles_late); Core::Timing& timing; Core::TimingEventType* update_time_event; diff --git a/src/core/hle/service/act/act.cpp b/src/core/hle/service/act/act.cpp index 3b74c6d5f..9a42d733e 100644 --- a/src/core/hle/service/act/act.cpp +++ b/src/core/hle/service/act/act.cpp @@ -3,6 +3,7 @@ // Refer to the license.txt file included. #include "core/core.h" +#include "core/hle/ipc_helpers.h" #include "core/hle/service/act/act.h" #include "core/hle/service/act/act_a.h" #include "core/hle/service/act/act_u.h" @@ -14,6 +15,35 @@ Module::Interface::Interface(std::shared_ptr act, const char* name) Module::Interface::~Interface() = default; +void Module::Interface::Initialize(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp(ctx, 0x1, 2, 4); // 0x10084 + const auto sdk_version = rp.Pop(); + const auto shared_memory_size = rp.Pop(); + const auto caller_pid = rp.PopPID(); + [[maybe_unused]] const auto shared_memory = rp.PopObject(); + + LOG_DEBUG(Service_ACT, + "(STUBBED) called sdk_version={:08X}, shared_memory_size={:08X}, caller_pid={}", + sdk_version, shared_memory_size, caller_pid); + + IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); + rb.Push(RESULT_SUCCESS); +} + +void Module::Interface::GetAccountDataBlock(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp(ctx, 0x6, 3, 2); // 0x600C2 + const auto unknown = rp.Pop(); + const auto size = rp.Pop(); + const auto block_id = rp.Pop(); + [[maybe_unused]] auto output_buffer = rp.PopMappedBuffer(); + + LOG_DEBUG(Service_ACT, "(STUBBED) called unknown={:02X}, size={:08X}, block_id={:08X}", unknown, + size, block_id); + + IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); + rb.Push(RESULT_SUCCESS); +} + void InstallInterfaces(Core::System& system) { auto& service_manager = system.ServiceManager(); auto act = std::make_shared(); diff --git a/src/core/hle/service/act/act.h b/src/core/hle/service/act/act.h index e5c2cf7ae..cbd5e6eb1 100644 --- a/src/core/hle/service/act/act.h +++ b/src/core/hle/service/act/act.h @@ -22,6 +22,33 @@ public: protected: std::shared_ptr act; + + /** + * ACT::Initialize service function. + * Inputs: + * 1 : SDK version + * 2 : Shared Memory Size + * 3 : PID Translation Header (0x20) + * 4 : Caller PID + * 5 : Handle Translation Header (0x0) + * 6 : Shared Memory Handle + * Outputs: + * 1 : Result of function, 0 on success, otherwise error code + */ + void Initialize(Kernel::HLERequestContext& ctx); + + /** + * ACT::GetAccountDataBlock service function. + * Inputs: + * 1 : u8 Unknown + * 2 : Size + * 3 : Block ID + * 4 : Output Buffer Mapping Translation Header ((Size << 4) | 0xC) + * 5 : Output Buffer Pointer + * Outputs: + * 1 : Result of function, 0 on success, otherwise error code + */ + void GetAccountDataBlock(Kernel::HLERequestContext& ctx); }; private: diff --git a/src/core/hle/service/act/act_a.cpp b/src/core/hle/service/act/act_a.cpp index c249bb509..e75ef0908 100644 --- a/src/core/hle/service/act/act_a.cpp +++ b/src/core/hle/service/act/act_a.cpp @@ -11,9 +11,9 @@ ACT_A::ACT_A(std::shared_ptr act) : Module::Interface(std::move(act), "a const FunctionInfo functions[] = { // act:u shared commands // clang-format off - {IPC::MakeHeader(0x0001, 2, 4), nullptr, "Initialize"}, + {IPC::MakeHeader(0x0001, 2, 4), &ACT_A::Initialize, "Initialize"}, {IPC::MakeHeader(0x0002, 1, 0), nullptr, "GetErrorCode"}, - {IPC::MakeHeader(0x0006, 3, 2), nullptr, "GetAccountDataBlock"}, + {IPC::MakeHeader(0x0006, 3, 2), &ACT_A::GetAccountDataBlock, "GetAccountDataBlock"}, {IPC::MakeHeader(0x000B, 1, 2), nullptr, "AcquireEulaList"}, {IPC::MakeHeader(0x000D, 1, 0), nullptr, "GenerateUuid"}, // act:a diff --git a/src/core/hle/service/act/act_u.cpp b/src/core/hle/service/act/act_u.cpp index ae9d08526..42ca849f3 100644 --- a/src/core/hle/service/act/act_u.cpp +++ b/src/core/hle/service/act/act_u.cpp @@ -10,9 +10,9 @@ namespace Service::ACT { ACT_U::ACT_U(std::shared_ptr act) : Module::Interface(std::move(act), "act:u") { static const FunctionInfo functions[] = { // clang-format off - {IPC::MakeHeader(0x0001, 2, 4), nullptr, "Initialize"}, + {IPC::MakeHeader(0x0001, 2, 4), &ACT_U::Initialize, "Initialize"}, {IPC::MakeHeader(0x0002, 1, 0), nullptr, "GetErrorCode"}, - {IPC::MakeHeader(0x0006, 3, 2), nullptr, "GetAccountDataBlock"}, + {IPC::MakeHeader(0x0006, 3, 2), &ACT_U::GetAccountDataBlock, "GetAccountDataBlock"}, {IPC::MakeHeader(0x000B, 1, 2), nullptr, "AcquireEulaList"}, {IPC::MakeHeader(0x000D, 1, 0), nullptr, "GenerateUuid"}, // clang-format on diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index 05aaaf24a..124253578 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp @@ -1121,6 +1121,17 @@ void Module::Interface::GetTicketList(Kernel::HLERequestContext& ctx) { ticket_list_count, ticket_index); } +void Module::Interface::NeedsCleanup(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp(ctx, 0x0013, 1, 0); // 0x00130040 + const auto media_type = rp.Pop(); + + LOG_DEBUG(Service_AM, "(STUBBED) media_type=0x{:02x}", media_type); + + IPC::RequestBuilder rb = rp.MakeBuilder(2, 0); + rb.Push(RESULT_SUCCESS); + rb.Push(false); +} + void Module::Interface::QueryAvailableTitleDatabase(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp(ctx, 0x0019, 1, 0); // 0x190040 u8 media_type = rp.Pop(); diff --git a/src/core/hle/service/am/am.h b/src/core/hle/service/am/am.h index 3ea266a0a..674f6616b 100644 --- a/src/core/hle/service/am/am.h +++ b/src/core/hle/service/am/am.h @@ -357,6 +357,16 @@ public: */ void GetTicketList(Kernel::HLERequestContext& ctx); + /** + * AM::NeedsCleanup service function + * Inputs: + * 1 : Media Type + * Outputs: + * 1 : Result, 0 on success, otherwise error code + * 2 : bool, Needs Cleanup + */ + void NeedsCleanup(Kernel::HLERequestContext& ctx); + /** * AM::QueryAvailableTitleDatabase service function * Inputs: diff --git a/src/core/hle/service/am/am_net.cpp b/src/core/hle/service/am/am_net.cpp index 7cf06f8e9..bb4c68f09 100644 --- a/src/core/hle/service/am/am_net.cpp +++ b/src/core/hle/service/am/am_net.cpp @@ -28,7 +28,7 @@ AM_NET::AM_NET(std::shared_ptr am) : Module::Interface(std::move(am), "a {IPC::MakeHeader(0x0010, 4, 2), nullptr, "GetImportContentContextList"}, {IPC::MakeHeader(0x0011, 4, 4), nullptr, "GetImportContentContexts"}, {IPC::MakeHeader(0x0012, 4, 2), nullptr, "DeleteImportContentContexts"}, - {IPC::MakeHeader(0x0013, 1, 0), nullptr, "NeedsCleanup"}, + {IPC::MakeHeader(0x0013, 1, 0), &AM_NET::NeedsCleanup, "NeedsCleanup"}, {IPC::MakeHeader(0x0014, 1, 0), nullptr, "DoCleanup"}, {IPC::MakeHeader(0x0015, 1, 0), nullptr, "DeleteAllImportContexts"}, {IPC::MakeHeader(0x0016, 0, 0), nullptr, "DeleteAllTemporaryPrograms"}, diff --git a/src/core/hle/service/am/am_sys.cpp b/src/core/hle/service/am/am_sys.cpp index c5f04d12d..248e8d4a5 100644 --- a/src/core/hle/service/am/am_sys.cpp +++ b/src/core/hle/service/am/am_sys.cpp @@ -28,7 +28,7 @@ AM_SYS::AM_SYS(std::shared_ptr am) : Module::Interface(std::move(am), "a {IPC::MakeHeader(0x0010, 4, 2), nullptr, "GetImportContentContextList"}, {IPC::MakeHeader(0x0011, 4, 4), nullptr, "GetImportContentContexts"}, {IPC::MakeHeader(0x0012, 4, 2), nullptr, "DeleteImportContentContexts"}, - {IPC::MakeHeader(0x0013, 1, 0), nullptr, "NeedsCleanup"}, + {IPC::MakeHeader(0x0013, 1, 0), &AM_SYS::NeedsCleanup, "NeedsCleanup"}, {IPC::MakeHeader(0x0014, 1, 0), nullptr, "DoCleanup"}, {IPC::MakeHeader(0x0015, 1, 0), nullptr, "DeleteAllImportContexts"}, {IPC::MakeHeader(0x0016, 0, 0), nullptr, "DeleteAllTemporaryPrograms"}, diff --git a/src/core/hle/service/am/am_u.cpp b/src/core/hle/service/am/am_u.cpp index 44ba50a2f..a60408aee 100644 --- a/src/core/hle/service/am/am_u.cpp +++ b/src/core/hle/service/am/am_u.cpp @@ -28,7 +28,7 @@ AM_U::AM_U(std::shared_ptr am) : Module::Interface(std::move(am), "am:u" {IPC::MakeHeader(0x0010, 4, 2), nullptr, "GetImportContentContextList"}, {IPC::MakeHeader(0x0011, 4, 4), nullptr, "GetImportContentContexts"}, {IPC::MakeHeader(0x0012, 4, 2), nullptr, "DeleteImportContentContexts"}, - {IPC::MakeHeader(0x0013, 1, 0), nullptr, "NeedsCleanup"}, + {IPC::MakeHeader(0x0013, 1, 0), &AM_U::NeedsCleanup, "NeedsCleanup"}, {IPC::MakeHeader(0x0014, 1, 0), nullptr, "DoCleanup"}, {IPC::MakeHeader(0x0015, 1, 0), nullptr, "DeleteAllImportContexts"}, {IPC::MakeHeader(0x0016, 0, 0), nullptr, "DeleteAllTemporaryPrograms"}, diff --git a/src/core/hle/service/cfg/cfg.cpp b/src/core/hle/service/cfg/cfg.cpp index c67827b88..06556fbaf 100644 --- a/src/core/hle/service/cfg/cfg.cpp +++ b/src/core/hle/service/cfg/cfg.cpp @@ -271,6 +271,17 @@ void Module::Interface::SecureInfoGetRegion(Kernel::HLERequestContext& ctx, u16 rb.Push(static_cast(cfg->GetRegionValue())); } +void Module::Interface::SecureInfoGetByte101(Kernel::HLERequestContext& ctx, u16 id) { + IPC::RequestParser rp(ctx, id, 0, 0); + + LOG_DEBUG(Service_CFG, "(STUBBED) called"); + + IPC::RequestBuilder rb = rp.MakeBuilder(2, 0); + rb.Push(RESULT_SUCCESS); + // According to 3dbrew this is normally 0. + rb.Push(0); +} + void Module::Interface::GenHashConsoleUnique(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp(ctx, 0x03, 1, 0); const u32 app_id_salt = rp.Pop() & 0x000FFFFF; diff --git a/src/core/hle/service/cfg/cfg.h b/src/core/hle/service/cfg/cfg.h index 63f383879..371ce8228 100644 --- a/src/core/hle/service/cfg/cfg.h +++ b/src/core/hle/service/cfg/cfg.h @@ -165,6 +165,17 @@ public: */ void SecureInfoGetRegion(Kernel::HLERequestContext& ctx, u16 id); + /** + * CFG::SecureInfoGetByte101 service function + * Inputs: + * 1 : None + * Outputs: + * 0 : Result Header code + * 1 : Result of function, 0 on success, otherwise error code + * 2 : Value loaded from SecureInfo offset 0x101 + */ + void SecureInfoGetByte101(Kernel::HLERequestContext& ctx, u16 id); + /** * CFG::GenHashConsoleUnique service function * Inputs: diff --git a/src/core/hle/service/cfg/cfg_i.cpp b/src/core/hle/service/cfg/cfg_i.cpp index 1248db268..61a151128 100644 --- a/src/core/hle/service/cfg/cfg_i.cpp +++ b/src/core/hle/service/cfg/cfg_i.cpp @@ -31,7 +31,7 @@ CFG_I::CFG_I(std::shared_ptr cfg) : Module::Interface(std::move(cfg), "c {IPC::MakeHeader(0x0404, 1, 2), nullptr, "GetLocalFriendCodeSeedData"}, {IPC::MakeHeader(0x0405, 0, 0), nullptr, "GetLocalFriendCodeSeed"}, {IPC::MakeHeader(0x0406, 0, 0), &CFG_I::D<&CFG_I::SecureInfoGetRegion, 0x0406>, "SecureInfoGetRegion"}, - {IPC::MakeHeader(0x0407, 0, 0), nullptr, "SecureInfoGetByte101"}, + {IPC::MakeHeader(0x0407, 0, 0), &CFG_I::D<&CFG_I::SecureInfoGetByte101, 0x0407>, "SecureInfoGetByte101"}, {IPC::MakeHeader(0x0408, 1, 2), nullptr, "SecureInfoGetSerialNo"}, {IPC::MakeHeader(0x0409, 0, 0), nullptr, "UpdateConfigBlk00040003"}, {IPC::MakeHeader(0x0801, 2, 2), &CFG_I::D<&CFG_I::GetConfigInfoBlk8, 0x0801>, "GetConfigInfoBlk8"}, @@ -55,7 +55,7 @@ CFG_I::CFG_I(std::shared_ptr cfg) : Module::Interface(std::move(cfg), "c {IPC::MakeHeader(0x0814, 1, 2), nullptr, "SecureInfoGetData"}, {IPC::MakeHeader(0x0815, 1, 2), nullptr, "SecureInfoGetSignature"}, {IPC::MakeHeader(0x0816, 0, 0), &CFG_I::D<&CFG_I::SecureInfoGetRegion, 0x0816>, "SecureInfoGetRegion"}, - {IPC::MakeHeader(0x0817, 0, 0), nullptr, "SecureInfoGetByte101"}, + {IPC::MakeHeader(0x0817, 0, 0), &CFG_I::D<&CFG_I::SecureInfoGetByte101, 0x0817>, "SecureInfoGetByte101"}, {IPC::MakeHeader(0x0818, 1, 2), nullptr, "SecureInfoGetSerialNo"}, // clang-format on }; diff --git a/src/core/hle/service/cfg/cfg_s.cpp b/src/core/hle/service/cfg/cfg_s.cpp index de2fbfec8..eafe4076f 100644 --- a/src/core/hle/service/cfg/cfg_s.cpp +++ b/src/core/hle/service/cfg/cfg_s.cpp @@ -31,7 +31,7 @@ CFG_S::CFG_S(std::shared_ptr cfg) : Module::Interface(std::move(cfg), "c {IPC::MakeHeader(0x0404, 1, 2), nullptr, "GetLocalFriendCodeSeedData"}, {IPC::MakeHeader(0x0405, 0, 0), nullptr, "GetLocalFriendCodeSeed"}, {IPC::MakeHeader(0x0406, 0, 0), &CFG_S::D<&CFG_S::SecureInfoGetRegion, 0x0406>, "SecureInfoGetRegion"}, - {IPC::MakeHeader(0x0407, 0, 0), nullptr, "SecureInfoGetByte101"}, + {IPC::MakeHeader(0x0407, 0, 0), &CFG_S::D<&CFG_S::SecureInfoGetByte101, 0x0407>, "SecureInfoGetByte101"}, {IPC::MakeHeader(0x0408, 1, 2), nullptr, "SecureInfoGetSerialNo"}, {IPC::MakeHeader(0x0409, 0, 0), nullptr, "UpdateConfigBlk00040003"}, // clang-format on diff --git a/src/core/hle/service/news/news_s.cpp b/src/core/hle/service/news/news_s.cpp index 42de3f780..1d4ecf677 100644 --- a/src/core/hle/service/news/news_s.cpp +++ b/src/core/hle/service/news/news_s.cpp @@ -10,6 +10,13 @@ SERIALIZE_EXPORT_IMPL(Service::NEWS::NEWS_S) namespace Service::NEWS { +struct NewsDbHeader { + u8 unknown_one; + u8 flags; + INSERT_PADDING_BYTES(0xE); +}; +static_assert(sizeof(NewsDbHeader) == 0x10, "News DB Header structure size is wrong"); + void NEWS_S::GetTotalNotifications(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp(ctx, 0x5, 0, 0); @@ -21,6 +28,22 @@ void NEWS_S::GetTotalNotifications(Kernel::HLERequestContext& ctx) { rb.Push(0); } +void NEWS_S::GetNewsDBHeader(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp(ctx, 0xA, 1, 2); + const auto size = rp.Pop(); + auto output_buffer = rp.PopMappedBuffer(); + + LOG_WARNING(Service, "(STUBBED) called size={}", size); + + NewsDbHeader dummy = {.unknown_one = 1, .flags = 0}; + output_buffer.Write(&dummy, 0, std::min(sizeof(NewsDbHeader), static_cast(size))); + + IPC::RequestBuilder rb = rp.MakeBuilder(2, 0); + + rb.Push(RESULT_SUCCESS); + rb.Push(size); +} + NEWS_S::NEWS_S() : ServiceFramework("news:s", 2) { const FunctionInfo functions[] = { // clang-format off @@ -30,7 +53,7 @@ NEWS_S::NEWS_S() : ServiceFramework("news:s", 2) { {IPC::MakeHeader(0x0007, 2, 2), nullptr, "SetNotificationHeader"}, {IPC::MakeHeader(0x0008, 2, 2), nullptr, "SetNotificationMessage"}, {IPC::MakeHeader(0x0009, 2, 2), nullptr, "SetNotificationImage"}, - {IPC::MakeHeader(0x000A, 1, 2), nullptr, "GetNewsDBHeader"}, + {IPC::MakeHeader(0x000A, 1, 2), &NEWS_S::GetNewsDBHeader, "GetNewsDBHeader"}, {IPC::MakeHeader(0x000B, 2, 2), nullptr, "GetNotificationHeader"}, {IPC::MakeHeader(0x000C, 2, 2), nullptr, "GetNotificationMessage"}, {IPC::MakeHeader(0x000D, 2, 2), nullptr, "GetNotificationImage"}, diff --git a/src/core/hle/service/news/news_s.h b/src/core/hle/service/news/news_s.h index 9d1ce829f..a12d496c1 100644 --- a/src/core/hle/service/news/news_s.h +++ b/src/core/hle/service/news/news_s.h @@ -25,6 +25,20 @@ private: */ void GetTotalNotifications(Kernel::HLERequestContext& ctx); + /** + * GetNewsDBHeader service function. + * Inputs: + * 0 : 0x000A0042 + * 1 : Size + * 2 : Output Buffer Mapping Translation Header ((Size << 4) | 0xC) + * 3 : Output Buffer Pointer + * Outputs: + * 0 : 0x000A0080 + * 1 : Result of function, 0 on success, otherwise error code + * 2 : Actual Size + */ + void GetNewsDBHeader(Kernel::HLERequestContext& ctx); + SERVICE_SERIALIZATION_SIMPLE }; diff --git a/src/core/hle/service/ptm/ptm.cpp b/src/core/hle/service/ptm/ptm.cpp index c68f0095c..120af5276 100644 --- a/src/core/hle/service/ptm/ptm.cpp +++ b/src/core/hle/service/ptm/ptm.cpp @@ -11,6 +11,7 @@ #include "core/file_sys/archive_extsavedata.h" #include "core/file_sys/errors.h" #include "core/file_sys/file_backend.h" +#include "core/hle/kernel/shared_page.h" #include "core/hle/service/ptm/ptm.h" #include "core/hle/service/ptm/ptm_gets.h" #include "core/hle/service/ptm/ptm_play.h" @@ -132,6 +133,17 @@ void Module::Interface::CheckNew3DS(Kernel::HLERequestContext& ctx) { Service::PTM::CheckNew3DS(rb); } +void Module::Interface::GetSystemTime(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp(ctx, 0x401, 0, 0); + + auto& share_page = Core::System::GetInstance().Kernel().GetSharedPageHandler(); + const u64 console_time = share_page.GetSystemTimeSince2000(); + + IPC::RequestBuilder rb = rp.MakeBuilder(3, 0); + rb.Push(RESULT_SUCCESS); + rb.Push(console_time); +} + static void WriteGameCoinData(GameCoin gamecoin_data) { const std::string& nand_directory = FileUtil::GetUserPath(FileUtil::UserPath::NANDDir); FileSys::ArchiveFactory_ExtSaveData extdata_archive_factory(nand_directory, true); diff --git a/src/core/hle/service/ptm/ptm.h b/src/core/hle/service/ptm/ptm.h index ba23224d7..83298f02a 100644 --- a/src/core/hle/service/ptm/ptm.h +++ b/src/core/hle/service/ptm/ptm.h @@ -137,6 +137,14 @@ public: */ void CheckNew3DS(Kernel::HLERequestContext& ctx); + /** + * PTM::GetSystemTime service function + * Outputs: + * 1: Result code, 0 on success, otherwise error code + * 2-3: Time since 01/01/2020. + */ + void GetSystemTime(Kernel::HLERequestContext& ctx); + protected: std::shared_ptr ptm; }; diff --git a/src/core/hle/service/ptm/ptm_gets.cpp b/src/core/hle/service/ptm/ptm_gets.cpp index 28169fde2..717b49748 100644 --- a/src/core/hle/service/ptm/ptm_gets.cpp +++ b/src/core/hle/service/ptm/ptm_gets.cpp @@ -30,7 +30,7 @@ PTM_Gets::PTM_Gets(std::shared_ptr ptm) {IPC::MakeHeader(0x000E, 0, 0), nullptr, "GetPedometerRecordingMode"}, {IPC::MakeHeader(0x000F, 2, 4), nullptr, "GetStepHistoryAll"}, // ptm:gets - {IPC::MakeHeader(0x0401, 0, 0), nullptr, "GetSystemTime"}, + {IPC::MakeHeader(0x0401, 0, 0), &PTM_Gets::GetSystemTime, "GetSystemTime"}, // clang-format on }; RegisterHandlers(functions);