mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 13:50:03 +00:00 
			
		
		
		
	hle: Stub some service calls used by the home menu. (#6675)
This commit is contained in:
		
							parent
							
								
									26e3f96983
								
							
						
					
					
						commit
						662bb9ba77
					
				
					 22 changed files with 187 additions and 22 deletions
				
			
		|  | @ -88,6 +88,7 @@ bool ParseFilterRule(Filter& instance, Iterator begin, Iterator end) { | ||||||
|     SUB(Service, FRD)                                                                              \ |     SUB(Service, FRD)                                                                              \ | ||||||
|     SUB(Service, FS)                                                                               \ |     SUB(Service, FS)                                                                               \ | ||||||
|     SUB(Service, ERR)                                                                              \ |     SUB(Service, ERR)                                                                              \ | ||||||
|  |     SUB(Service, ACT)                                                                              \ | ||||||
|     SUB(Service, APT)                                                                              \ |     SUB(Service, APT)                                                                              \ | ||||||
|     SUB(Service, BOSS)                                                                             \ |     SUB(Service, BOSS)                                                                             \ | ||||||
|     SUB(Service, GSP)                                                                              \ |     SUB(Service, GSP)                                                                              \ | ||||||
|  |  | ||||||
|  | @ -55,6 +55,7 @@ enum class Class : u8 { | ||||||
|     Service_FRD,     ///< The FRD (Friends) service
 |     Service_FRD,     ///< The FRD (Friends) service
 | ||||||
|     Service_FS,      ///< The FS (Filesystem) service implementation
 |     Service_FS,      ///< The FS (Filesystem) service implementation
 | ||||||
|     Service_ERR,     ///< The ERR (Error) port implementation
 |     Service_ERR,     ///< The ERR (Error) port implementation
 | ||||||
|  |     Service_ACT,     ///< The ACT (Account) service
 | ||||||
|     Service_APT,     ///< The APT (Applets) service
 |     Service_APT,     ///< The APT (Applets) service
 | ||||||
|     Service_BOSS,    ///< The BOSS (SpotPass) service
 |     Service_BOSS,    ///< The BOSS (SpotPass) service
 | ||||||
|     Service_GSP,     ///< The GSP (GPU control) service
 |     Service_GSP,     ///< The GSP (GPU control) service
 | ||||||
|  |  | ||||||
|  | @ -87,8 +87,7 @@ Handler::Handler(Core::Timing& timing) : timing(timing) { | ||||||
|     shared_page.sliderstate_3d = static_cast<float_le>(slidestate); |     shared_page.sliderstate_3d = static_cast<float_le>(slidestate); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /// Gets system time in 3DS format. The epoch is Jan 1900, and the unit is millisecond.
 | u64 Handler::GetSystemTimeSince2000() const { | ||||||
| u64 Handler::GetSystemTime() const { |  | ||||||
|     std::chrono::milliseconds now = |     std::chrono::milliseconds now = | ||||||
|         init_time + std::chrono::duration_cast<std::chrono::milliseconds>(timing.GetGlobalTimeUs()); |         init_time + std::chrono::duration_cast<std::chrono::milliseconds>(timing.GetGlobalTimeUs()); | ||||||
| 
 | 
 | ||||||
|  | @ -104,23 +103,25 @@ u64 Handler::GetSystemTime() const { | ||||||
|     epoch_tm.tm_isdst = 0; |     epoch_tm.tm_isdst = 0; | ||||||
|     s64 epoch = std::mktime(&epoch_tm) * 1000; |     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
 |     // Only when system time is after 2000, we set it as 3DS system time
 | ||||||
|     if (now.count() > epoch) { |     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) { | void Handler::UpdateTimeCallback(std::uintptr_t user_data, int cycles_late) { | ||||||
|     DateTime& date_time = |     DateTime& date_time = | ||||||
|         shared_page.date_time_counter % 2 ? shared_page.date_time_0 : shared_page.date_time_1; |         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.update_tick = timing.GetTicks(); | ||||||
|     date_time.tick_to_second_coefficient = BASE_CLOCK_RATE_ARM11; |     date_time.tick_to_second_coefficient = BASE_CLOCK_RATE_ARM11; | ||||||
|     date_time.tick_offset = 0; |     date_time.tick_offset = 0; | ||||||
|  |  | ||||||
|  | @ -110,8 +110,13 @@ public: | ||||||
|         return sizeof(shared_page); |         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: | private: | ||||||
|     u64 GetSystemTime() const; |  | ||||||
|     void UpdateTimeCallback(std::uintptr_t user_data, int cycles_late); |     void UpdateTimeCallback(std::uintptr_t user_data, int cycles_late); | ||||||
|     Core::Timing& timing; |     Core::Timing& timing; | ||||||
|     Core::TimingEventType* update_time_event; |     Core::TimingEventType* update_time_event; | ||||||
|  |  | ||||||
|  | @ -3,6 +3,7 @@ | ||||||
| // Refer to the license.txt file included.
 | // Refer to the license.txt file included.
 | ||||||
| 
 | 
 | ||||||
| #include "core/core.h" | #include "core/core.h" | ||||||
|  | #include "core/hle/ipc_helpers.h" | ||||||
| #include "core/hle/service/act/act.h" | #include "core/hle/service/act/act.h" | ||||||
| #include "core/hle/service/act/act_a.h" | #include "core/hle/service/act/act_a.h" | ||||||
| #include "core/hle/service/act/act_u.h" | #include "core/hle/service/act/act_u.h" | ||||||
|  | @ -14,6 +15,35 @@ Module::Interface::Interface(std::shared_ptr<Module> act, const char* name) | ||||||
| 
 | 
 | ||||||
| Module::Interface::~Interface() = default; | 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<u32>(); | ||||||
|  |     const auto shared_memory_size = rp.Pop<u32>(); | ||||||
|  |     const auto caller_pid = rp.PopPID(); | ||||||
|  |     [[maybe_unused]] const auto shared_memory = rp.PopObject<Kernel::SharedMemory>(); | ||||||
|  | 
 | ||||||
|  |     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<u8>(); | ||||||
|  |     const auto size = rp.Pop<u32>(); | ||||||
|  |     const auto block_id = rp.Pop<u32>(); | ||||||
|  |     [[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) { | void InstallInterfaces(Core::System& system) { | ||||||
|     auto& service_manager = system.ServiceManager(); |     auto& service_manager = system.ServiceManager(); | ||||||
|     auto act = std::make_shared<Module>(); |     auto act = std::make_shared<Module>(); | ||||||
|  |  | ||||||
|  | @ -22,6 +22,33 @@ public: | ||||||
| 
 | 
 | ||||||
|     protected: |     protected: | ||||||
|         std::shared_ptr<Module> act; |         std::shared_ptr<Module> 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: | private: | ||||||
|  |  | ||||||
|  | @ -11,9 +11,9 @@ ACT_A::ACT_A(std::shared_ptr<Module> act) : Module::Interface(std::move(act), "a | ||||||
|     const FunctionInfo functions[] = { |     const FunctionInfo functions[] = { | ||||||
|         // act:u shared commands
 |         // act:u shared commands
 | ||||||
|         // clang-format off
 |         // 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(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(0x000B, 1, 2), nullptr, "AcquireEulaList"}, | ||||||
|         {IPC::MakeHeader(0x000D, 1, 0), nullptr, "GenerateUuid"}, |         {IPC::MakeHeader(0x000D, 1, 0), nullptr, "GenerateUuid"}, | ||||||
|         // act:a
 |         // act:a
 | ||||||
|  |  | ||||||
|  | @ -10,9 +10,9 @@ namespace Service::ACT { | ||||||
| ACT_U::ACT_U(std::shared_ptr<Module> act) : Module::Interface(std::move(act), "act:u") { | ACT_U::ACT_U(std::shared_ptr<Module> act) : Module::Interface(std::move(act), "act:u") { | ||||||
|     static const FunctionInfo functions[] = { |     static const FunctionInfo functions[] = { | ||||||
|         // clang-format off
 |         // 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(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(0x000B, 1, 2), nullptr, "AcquireEulaList"}, | ||||||
|         {IPC::MakeHeader(0x000D, 1, 0), nullptr, "GenerateUuid"}, |         {IPC::MakeHeader(0x000D, 1, 0), nullptr, "GenerateUuid"}, | ||||||
|         // clang-format on
 |         // clang-format on
 | ||||||
|  |  | ||||||
|  | @ -1121,6 +1121,17 @@ void Module::Interface::GetTicketList(Kernel::HLERequestContext& ctx) { | ||||||
|                 ticket_list_count, ticket_index); |                 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<u8>(); | ||||||
|  | 
 | ||||||
|  |     LOG_DEBUG(Service_AM, "(STUBBED) media_type=0x{:02x}", media_type); | ||||||
|  | 
 | ||||||
|  |     IPC::RequestBuilder rb = rp.MakeBuilder(2, 0); | ||||||
|  |     rb.Push(RESULT_SUCCESS); | ||||||
|  |     rb.Push<bool>(false); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void Module::Interface::QueryAvailableTitleDatabase(Kernel::HLERequestContext& ctx) { | void Module::Interface::QueryAvailableTitleDatabase(Kernel::HLERequestContext& ctx) { | ||||||
|     IPC::RequestParser rp(ctx, 0x0019, 1, 0); // 0x190040
 |     IPC::RequestParser rp(ctx, 0x0019, 1, 0); // 0x190040
 | ||||||
|     u8 media_type = rp.Pop<u8>(); |     u8 media_type = rp.Pop<u8>(); | ||||||
|  |  | ||||||
|  | @ -357,6 +357,16 @@ public: | ||||||
|          */ |          */ | ||||||
|         void GetTicketList(Kernel::HLERequestContext& ctx); |         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 |          * AM::QueryAvailableTitleDatabase service function | ||||||
|          *  Inputs: |          *  Inputs: | ||||||
|  |  | ||||||
|  | @ -28,7 +28,7 @@ AM_NET::AM_NET(std::shared_ptr<Module> am) : Module::Interface(std::move(am), "a | ||||||
|         {IPC::MakeHeader(0x0010, 4, 2), nullptr, "GetImportContentContextList"}, |         {IPC::MakeHeader(0x0010, 4, 2), nullptr, "GetImportContentContextList"}, | ||||||
|         {IPC::MakeHeader(0x0011, 4, 4), nullptr, "GetImportContentContexts"}, |         {IPC::MakeHeader(0x0011, 4, 4), nullptr, "GetImportContentContexts"}, | ||||||
|         {IPC::MakeHeader(0x0012, 4, 2), nullptr, "DeleteImportContentContexts"}, |         {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(0x0014, 1, 0), nullptr, "DoCleanup"}, | ||||||
|         {IPC::MakeHeader(0x0015, 1, 0), nullptr, "DeleteAllImportContexts"}, |         {IPC::MakeHeader(0x0015, 1, 0), nullptr, "DeleteAllImportContexts"}, | ||||||
|         {IPC::MakeHeader(0x0016, 0, 0), nullptr, "DeleteAllTemporaryPrograms"}, |         {IPC::MakeHeader(0x0016, 0, 0), nullptr, "DeleteAllTemporaryPrograms"}, | ||||||
|  |  | ||||||
|  | @ -28,7 +28,7 @@ AM_SYS::AM_SYS(std::shared_ptr<Module> am) : Module::Interface(std::move(am), "a | ||||||
|         {IPC::MakeHeader(0x0010, 4, 2), nullptr, "GetImportContentContextList"}, |         {IPC::MakeHeader(0x0010, 4, 2), nullptr, "GetImportContentContextList"}, | ||||||
|         {IPC::MakeHeader(0x0011, 4, 4), nullptr, "GetImportContentContexts"}, |         {IPC::MakeHeader(0x0011, 4, 4), nullptr, "GetImportContentContexts"}, | ||||||
|         {IPC::MakeHeader(0x0012, 4, 2), nullptr, "DeleteImportContentContexts"}, |         {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(0x0014, 1, 0), nullptr, "DoCleanup"}, | ||||||
|         {IPC::MakeHeader(0x0015, 1, 0), nullptr, "DeleteAllImportContexts"}, |         {IPC::MakeHeader(0x0015, 1, 0), nullptr, "DeleteAllImportContexts"}, | ||||||
|         {IPC::MakeHeader(0x0016, 0, 0), nullptr, "DeleteAllTemporaryPrograms"}, |         {IPC::MakeHeader(0x0016, 0, 0), nullptr, "DeleteAllTemporaryPrograms"}, | ||||||
|  |  | ||||||
|  | @ -28,7 +28,7 @@ AM_U::AM_U(std::shared_ptr<Module> am) : Module::Interface(std::move(am), "am:u" | ||||||
|         {IPC::MakeHeader(0x0010, 4, 2), nullptr, "GetImportContentContextList"}, |         {IPC::MakeHeader(0x0010, 4, 2), nullptr, "GetImportContentContextList"}, | ||||||
|         {IPC::MakeHeader(0x0011, 4, 4), nullptr, "GetImportContentContexts"}, |         {IPC::MakeHeader(0x0011, 4, 4), nullptr, "GetImportContentContexts"}, | ||||||
|         {IPC::MakeHeader(0x0012, 4, 2), nullptr, "DeleteImportContentContexts"}, |         {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(0x0014, 1, 0), nullptr, "DoCleanup"}, | ||||||
|         {IPC::MakeHeader(0x0015, 1, 0), nullptr, "DeleteAllImportContexts"}, |         {IPC::MakeHeader(0x0015, 1, 0), nullptr, "DeleteAllImportContexts"}, | ||||||
|         {IPC::MakeHeader(0x0016, 0, 0), nullptr, "DeleteAllTemporaryPrograms"}, |         {IPC::MakeHeader(0x0016, 0, 0), nullptr, "DeleteAllTemporaryPrograms"}, | ||||||
|  |  | ||||||
|  | @ -271,6 +271,17 @@ void Module::Interface::SecureInfoGetRegion(Kernel::HLERequestContext& ctx, u16 | ||||||
|     rb.Push<u8>(static_cast<u8>(cfg->GetRegionValue())); |     rb.Push<u8>(static_cast<u8>(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<u8>(0); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void Module::Interface::GenHashConsoleUnique(Kernel::HLERequestContext& ctx) { | void Module::Interface::GenHashConsoleUnique(Kernel::HLERequestContext& ctx) { | ||||||
|     IPC::RequestParser rp(ctx, 0x03, 1, 0); |     IPC::RequestParser rp(ctx, 0x03, 1, 0); | ||||||
|     const u32 app_id_salt = rp.Pop<u32>() & 0x000FFFFF; |     const u32 app_id_salt = rp.Pop<u32>() & 0x000FFFFF; | ||||||
|  |  | ||||||
|  | @ -165,6 +165,17 @@ public: | ||||||
|          */ |          */ | ||||||
|         void SecureInfoGetRegion(Kernel::HLERequestContext& ctx, u16 id); |         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 |          * CFG::GenHashConsoleUnique service function | ||||||
|          *  Inputs: |          *  Inputs: | ||||||
|  |  | ||||||
|  | @ -31,7 +31,7 @@ CFG_I::CFG_I(std::shared_ptr<Module> cfg) : Module::Interface(std::move(cfg), "c | ||||||
|         {IPC::MakeHeader(0x0404, 1, 2), nullptr, "GetLocalFriendCodeSeedData"}, |         {IPC::MakeHeader(0x0404, 1, 2), nullptr, "GetLocalFriendCodeSeedData"}, | ||||||
|         {IPC::MakeHeader(0x0405, 0, 0), nullptr, "GetLocalFriendCodeSeed"}, |         {IPC::MakeHeader(0x0405, 0, 0), nullptr, "GetLocalFriendCodeSeed"}, | ||||||
|         {IPC::MakeHeader(0x0406, 0, 0), &CFG_I::D<&CFG_I::SecureInfoGetRegion, 0x0406>, "SecureInfoGetRegion"}, |         {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(0x0408, 1, 2), nullptr, "SecureInfoGetSerialNo"}, | ||||||
|         {IPC::MakeHeader(0x0409, 0, 0), nullptr, "UpdateConfigBlk00040003"}, |         {IPC::MakeHeader(0x0409, 0, 0), nullptr, "UpdateConfigBlk00040003"}, | ||||||
|         {IPC::MakeHeader(0x0801, 2, 2), &CFG_I::D<&CFG_I::GetConfigInfoBlk8, 0x0801>, "GetConfigInfoBlk8"}, |         {IPC::MakeHeader(0x0801, 2, 2), &CFG_I::D<&CFG_I::GetConfigInfoBlk8, 0x0801>, "GetConfigInfoBlk8"}, | ||||||
|  | @ -55,7 +55,7 @@ CFG_I::CFG_I(std::shared_ptr<Module> cfg) : Module::Interface(std::move(cfg), "c | ||||||
|         {IPC::MakeHeader(0x0814, 1, 2), nullptr, "SecureInfoGetData"}, |         {IPC::MakeHeader(0x0814, 1, 2), nullptr, "SecureInfoGetData"}, | ||||||
|         {IPC::MakeHeader(0x0815, 1, 2), nullptr, "SecureInfoGetSignature"}, |         {IPC::MakeHeader(0x0815, 1, 2), nullptr, "SecureInfoGetSignature"}, | ||||||
|         {IPC::MakeHeader(0x0816, 0, 0), &CFG_I::D<&CFG_I::SecureInfoGetRegion, 0x0816>, "SecureInfoGetRegion"}, |         {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"}, |         {IPC::MakeHeader(0x0818, 1, 2), nullptr, "SecureInfoGetSerialNo"}, | ||||||
|         // clang-format on
 |         // clang-format on
 | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|  | @ -31,7 +31,7 @@ CFG_S::CFG_S(std::shared_ptr<Module> cfg) : Module::Interface(std::move(cfg), "c | ||||||
|         {IPC::MakeHeader(0x0404, 1, 2), nullptr, "GetLocalFriendCodeSeedData"}, |         {IPC::MakeHeader(0x0404, 1, 2), nullptr, "GetLocalFriendCodeSeedData"}, | ||||||
|         {IPC::MakeHeader(0x0405, 0, 0), nullptr, "GetLocalFriendCodeSeed"}, |         {IPC::MakeHeader(0x0405, 0, 0), nullptr, "GetLocalFriendCodeSeed"}, | ||||||
|         {IPC::MakeHeader(0x0406, 0, 0), &CFG_S::D<&CFG_S::SecureInfoGetRegion, 0x0406>, "SecureInfoGetRegion"}, |         {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(0x0408, 1, 2), nullptr, "SecureInfoGetSerialNo"}, | ||||||
|         {IPC::MakeHeader(0x0409, 0, 0), nullptr, "UpdateConfigBlk00040003"}, |         {IPC::MakeHeader(0x0409, 0, 0), nullptr, "UpdateConfigBlk00040003"}, | ||||||
|         // clang-format on
 |         // clang-format on
 | ||||||
|  |  | ||||||
|  | @ -10,6 +10,13 @@ SERIALIZE_EXPORT_IMPL(Service::NEWS::NEWS_S) | ||||||
| 
 | 
 | ||||||
| namespace Service::NEWS { | 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) { | void NEWS_S::GetTotalNotifications(Kernel::HLERequestContext& ctx) { | ||||||
|     IPC::RequestParser rp(ctx, 0x5, 0, 0); |     IPC::RequestParser rp(ctx, 0x5, 0, 0); | ||||||
| 
 | 
 | ||||||
|  | @ -21,6 +28,22 @@ void NEWS_S::GetTotalNotifications(Kernel::HLERequestContext& ctx) { | ||||||
|     rb.Push<u32>(0); |     rb.Push<u32>(0); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void NEWS_S::GetNewsDBHeader(Kernel::HLERequestContext& ctx) { | ||||||
|  |     IPC::RequestParser rp(ctx, 0xA, 1, 2); | ||||||
|  |     const auto size = rp.Pop<u32>(); | ||||||
|  |     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<std::size_t>(size))); | ||||||
|  | 
 | ||||||
|  |     IPC::RequestBuilder rb = rp.MakeBuilder(2, 0); | ||||||
|  | 
 | ||||||
|  |     rb.Push(RESULT_SUCCESS); | ||||||
|  |     rb.Push<u32>(size); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| NEWS_S::NEWS_S() : ServiceFramework("news:s", 2) { | NEWS_S::NEWS_S() : ServiceFramework("news:s", 2) { | ||||||
|     const FunctionInfo functions[] = { |     const FunctionInfo functions[] = { | ||||||
|         // clang-format off
 |         // clang-format off
 | ||||||
|  | @ -30,7 +53,7 @@ NEWS_S::NEWS_S() : ServiceFramework("news:s", 2) { | ||||||
|         {IPC::MakeHeader(0x0007, 2, 2), nullptr, "SetNotificationHeader"}, |         {IPC::MakeHeader(0x0007, 2, 2), nullptr, "SetNotificationHeader"}, | ||||||
|         {IPC::MakeHeader(0x0008, 2, 2), nullptr, "SetNotificationMessage"}, |         {IPC::MakeHeader(0x0008, 2, 2), nullptr, "SetNotificationMessage"}, | ||||||
|         {IPC::MakeHeader(0x0009, 2, 2), nullptr, "SetNotificationImage"}, |         {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(0x000B, 2, 2), nullptr, "GetNotificationHeader"}, | ||||||
|         {IPC::MakeHeader(0x000C, 2, 2), nullptr, "GetNotificationMessage"}, |         {IPC::MakeHeader(0x000C, 2, 2), nullptr, "GetNotificationMessage"}, | ||||||
|         {IPC::MakeHeader(0x000D, 2, 2), nullptr, "GetNotificationImage"}, |         {IPC::MakeHeader(0x000D, 2, 2), nullptr, "GetNotificationImage"}, | ||||||
|  |  | ||||||
|  | @ -25,6 +25,20 @@ private: | ||||||
|      */ |      */ | ||||||
|     void GetTotalNotifications(Kernel::HLERequestContext& ctx); |     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 |     SERVICE_SERIALIZATION_SIMPLE | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -11,6 +11,7 @@ | ||||||
| #include "core/file_sys/archive_extsavedata.h" | #include "core/file_sys/archive_extsavedata.h" | ||||||
| #include "core/file_sys/errors.h" | #include "core/file_sys/errors.h" | ||||||
| #include "core/file_sys/file_backend.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.h" | ||||||
| #include "core/hle/service/ptm/ptm_gets.h" | #include "core/hle/service/ptm/ptm_gets.h" | ||||||
| #include "core/hle/service/ptm/ptm_play.h" | #include "core/hle/service/ptm/ptm_play.h" | ||||||
|  | @ -132,6 +133,17 @@ void Module::Interface::CheckNew3DS(Kernel::HLERequestContext& ctx) { | ||||||
|     Service::PTM::CheckNew3DS(rb); |     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) { | static void WriteGameCoinData(GameCoin gamecoin_data) { | ||||||
|     const std::string& nand_directory = FileUtil::GetUserPath(FileUtil::UserPath::NANDDir); |     const std::string& nand_directory = FileUtil::GetUserPath(FileUtil::UserPath::NANDDir); | ||||||
|     FileSys::ArchiveFactory_ExtSaveData extdata_archive_factory(nand_directory, true); |     FileSys::ArchiveFactory_ExtSaveData extdata_archive_factory(nand_directory, true); | ||||||
|  |  | ||||||
|  | @ -137,6 +137,14 @@ public: | ||||||
|          */ |          */ | ||||||
|         void CheckNew3DS(Kernel::HLERequestContext& ctx); |         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: |     protected: | ||||||
|         std::shared_ptr<Module> ptm; |         std::shared_ptr<Module> ptm; | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|  | @ -30,7 +30,7 @@ PTM_Gets::PTM_Gets(std::shared_ptr<Module> ptm) | ||||||
|         {IPC::MakeHeader(0x000E, 0, 0), nullptr, "GetPedometerRecordingMode"}, |         {IPC::MakeHeader(0x000E, 0, 0), nullptr, "GetPedometerRecordingMode"}, | ||||||
|         {IPC::MakeHeader(0x000F, 2, 4), nullptr, "GetStepHistoryAll"}, |         {IPC::MakeHeader(0x000F, 2, 4), nullptr, "GetStepHistoryAll"}, | ||||||
|         // ptm:gets
 |         // ptm:gets
 | ||||||
|         {IPC::MakeHeader(0x0401, 0, 0), nullptr, "GetSystemTime"}, |         {IPC::MakeHeader(0x0401, 0, 0), &PTM_Gets::GetSystemTime, "GetSystemTime"}, | ||||||
|         // clang-format on
 |         // clang-format on
 | ||||||
|     }; |     }; | ||||||
|     RegisterHandlers(functions); |     RegisterHandlers(functions); | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue