mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-11-03 23:28:48 +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
				
			
		| 
						 | 
				
			
			@ -87,8 +87,7 @@ Handler::Handler(Core::Timing& timing) : timing(timing) {
 | 
			
		|||
    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::GetSystemTime() const {
 | 
			
		||||
u64 Handler::GetSystemTimeSince2000() const {
 | 
			
		||||
    std::chrono::milliseconds now =
 | 
			
		||||
        init_time + std::chrono::duration_cast<std::chrono::milliseconds>(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;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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<Module> 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<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) {
 | 
			
		||||
    auto& service_manager = system.ServiceManager();
 | 
			
		||||
    auto act = std::make_shared<Module>();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -22,6 +22,33 @@ public:
 | 
			
		|||
 | 
			
		||||
    protected:
 | 
			
		||||
        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:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -11,9 +11,9 @@ ACT_A::ACT_A(std::shared_ptr<Module> 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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -10,9 +10,9 @@ namespace Service::ACT {
 | 
			
		|||
ACT_U::ACT_U(std::shared_ptr<Module> 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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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<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) {
 | 
			
		||||
    IPC::RequestParser rp(ctx, 0x0019, 1, 0); // 0x190040
 | 
			
		||||
    u8 media_type = rp.Pop<u8>();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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(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"},
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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(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"},
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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(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"},
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -271,6 +271,17 @@ void Module::Interface::SecureInfoGetRegion(Kernel::HLERequestContext& ctx, u16
 | 
			
		|||
    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) {
 | 
			
		||||
    IPC::RequestParser rp(ctx, 0x03, 1, 0);
 | 
			
		||||
    const u32 app_id_salt = rp.Pop<u32>() & 0x000FFFFF;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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(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<Module> 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
 | 
			
		||||
    };
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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(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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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<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) {
 | 
			
		||||
    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"},
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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<Module> ptm;
 | 
			
		||||
    };
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -30,7 +30,7 @@ PTM_Gets::PTM_Gets(std::shared_ptr<Module> 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);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue