mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-11-03 23:28:48 +00:00 
			
		
		
		
	service/apt: Implement Deliver Args (#5611)
* service/apt: Add GetModule and GetAppletManager These will be used to retrieve and set deliver args across system resets (which are currently implemented as complete restarts) * applet_manager: Implement DeliverArg `flags` was added to `ApplicationJumpParameters` as flags 0x2 is handled differently from 0x0. * service/apt: Add ReceiveDeliverArg, implement GetStartupArgument Some based on guesses. * Address review comments
This commit is contained in:
		
							parent
							
								
									182ffa4243
								
							
						
					
					
						commit
						21fb9d63f4
					
				
					 7 changed files with 177 additions and 20 deletions
				
			
		| 
						 | 
					@ -31,6 +31,8 @@
 | 
				
			||||||
#include "core/hle/kernel/kernel.h"
 | 
					#include "core/hle/kernel/kernel.h"
 | 
				
			||||||
#include "core/hle/kernel/process.h"
 | 
					#include "core/hle/kernel/process.h"
 | 
				
			||||||
#include "core/hle/kernel/thread.h"
 | 
					#include "core/hle/kernel/thread.h"
 | 
				
			||||||
 | 
					#include "core/hle/service/apt/applet_manager.h"
 | 
				
			||||||
 | 
					#include "core/hle/service/apt/apt.h"
 | 
				
			||||||
#include "core/hle/service/fs/archive.h"
 | 
					#include "core/hle/service/fs/archive.h"
 | 
				
			||||||
#include "core/hle/service/gsp/gsp.h"
 | 
					#include "core/hle/service/gsp/gsp.h"
 | 
				
			||||||
#include "core/hle/service/pm/pm_app.h"
 | 
					#include "core/hle/service/pm/pm_app.h"
 | 
				
			||||||
| 
						 | 
					@ -561,9 +563,20 @@ void System::Reset() {
 | 
				
			||||||
    // reloading.
 | 
					    // reloading.
 | 
				
			||||||
    // TODO: Properly implement the reset
 | 
					    // TODO: Properly implement the reset
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Since the system is completely reinitialized, we'll have to store the deliver arg manually.
 | 
				
			||||||
 | 
					    boost::optional<Service::APT::AppletManager::DeliverArg> deliver_arg;
 | 
				
			||||||
 | 
					    if (auto apt = Service::APT::GetModule(*this)) {
 | 
				
			||||||
 | 
					        deliver_arg = apt->GetAppletManager()->ReceiveDeliverArg();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Shutdown();
 | 
					    Shutdown();
 | 
				
			||||||
    // Reload the system with the same setting
 | 
					    // Reload the system with the same setting
 | 
				
			||||||
    Load(*m_emu_window, m_filepath);
 | 
					    Load(*m_emu_window, m_filepath);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Restore the deliver arg.
 | 
				
			||||||
 | 
					    if (auto apt = Service::APT::GetModule(*this)) {
 | 
				
			||||||
 | 
					        apt->GetAppletManager()->SetDeliverArg(std::move(deliver_arg));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
template <class Archive>
 | 
					template <class Archive>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -498,6 +498,7 @@ ResultCode AppletManager::PrepareToDoApplicationJump(u64 title_id, FS::MediaType
 | 
				
			||||||
    app_jump_parameters.current_media_type = FS::MediaType::NAND;
 | 
					    app_jump_parameters.current_media_type = FS::MediaType::NAND;
 | 
				
			||||||
    app_jump_parameters.next_title_id = title_id;
 | 
					    app_jump_parameters.next_title_id = title_id;
 | 
				
			||||||
    app_jump_parameters.next_media_type = media_type;
 | 
					    app_jump_parameters.next_media_type = media_type;
 | 
				
			||||||
 | 
					    app_jump_parameters.flags = flags;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Note: The real console uses the Home Menu to perform the application jump, therefore the menu
 | 
					    // Note: The real console uses the Home Menu to perform the application jump, therefore the menu
 | 
				
			||||||
    // needs to be running. The real APT module starts the Home Menu here if it's not already
 | 
					    // needs to be running. The real APT module starts the Home Menu here if it's not already
 | 
				
			||||||
| 
						 | 
					@ -505,16 +506,23 @@ ResultCode AppletManager::PrepareToDoApplicationJump(u64 title_id, FS::MediaType
 | 
				
			||||||
    return RESULT_SUCCESS;
 | 
					    return RESULT_SUCCESS;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ResultCode AppletManager::DoApplicationJump() {
 | 
					ResultCode AppletManager::DoApplicationJump(DeliverArg arg) {
 | 
				
			||||||
    // Note: The real console uses the Home Menu to perform the application jump, it goes
 | 
					    // Note: The real console uses the Home Menu to perform the application jump, it goes
 | 
				
			||||||
    // OldApplication->Home Menu->NewApplication. We do not need to use the Home Menu to do this so
 | 
					    // OldApplication->Home Menu->NewApplication. We do not need to use the Home Menu to do this so
 | 
				
			||||||
    // we launch the new application directly. In the real APT service, the Home Menu must be
 | 
					    // we launch the new application directly. In the real APT service, the Home Menu must be
 | 
				
			||||||
    // running to do this, otherwise error 0xC8A0CFF0 is returned.
 | 
					    // running to do this, otherwise error 0xC8A0CFF0 is returned.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    auto& application_slot = applet_slots[static_cast<size_t>(AppletSlot::Application)];
 | 
					    auto& application_slot = applet_slots[static_cast<size_t>(AppletSlot::Application)];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (app_jump_parameters.flags != ApplicationJumpFlags::UseCurrentParameters) {
 | 
				
			||||||
 | 
					        // The source program ID is not updated when using flags 0x2.
 | 
				
			||||||
 | 
					        arg.source_program_id = application_slot.title_id;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    application_slot.Reset();
 | 
					    application_slot.Reset();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // TODO(Subv): Set the delivery parameters.
 | 
					    // Set the delivery parameters.
 | 
				
			||||||
 | 
					    deliver_arg = std::move(arg);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // TODO(Subv): Terminate the current Application.
 | 
					    // TODO(Subv): Terminate the current Application.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -5,7 +5,9 @@
 | 
				
			||||||
#pragma once
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <array>
 | 
					#include <array>
 | 
				
			||||||
 | 
					#include <limits>
 | 
				
			||||||
#include <memory>
 | 
					#include <memory>
 | 
				
			||||||
 | 
					#include <optional>
 | 
				
			||||||
#include <vector>
 | 
					#include <vector>
 | 
				
			||||||
#include <boost/serialization/array.hpp>
 | 
					#include <boost/serialization/array.hpp>
 | 
				
			||||||
#include <boost/serialization/optional.hpp>
 | 
					#include <boost/serialization/optional.hpp>
 | 
				
			||||||
| 
						 | 
					@ -158,7 +160,30 @@ public:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ResultCode PrepareToDoApplicationJump(u64 title_id, FS::MediaType media_type,
 | 
					    ResultCode PrepareToDoApplicationJump(u64 title_id, FS::MediaType media_type,
 | 
				
			||||||
                                          ApplicationJumpFlags flags);
 | 
					                                          ApplicationJumpFlags flags);
 | 
				
			||||||
    ResultCode DoApplicationJump();
 | 
					
 | 
				
			||||||
 | 
					    struct DeliverArg {
 | 
				
			||||||
 | 
					        std::vector<u8> param;
 | 
				
			||||||
 | 
					        std::vector<u8> hmac;
 | 
				
			||||||
 | 
					        u64 source_program_id = std::numeric_limits<u64>::max();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private:
 | 
				
			||||||
 | 
					        template <class Archive>
 | 
				
			||||||
 | 
					        void serialize(Archive& ar, const unsigned int) {
 | 
				
			||||||
 | 
					            ar& param;
 | 
				
			||||||
 | 
					            ar& hmac;
 | 
				
			||||||
 | 
					            ar& source_program_id;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        friend class boost::serialization::access;
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ResultCode DoApplicationJump(DeliverArg arg);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    boost::optional<DeliverArg> ReceiveDeliverArg() const {
 | 
				
			||||||
 | 
					        return deliver_arg;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    void SetDeliverArg(boost::optional<DeliverArg> arg) {
 | 
				
			||||||
 | 
					        deliver_arg = std::move(arg);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    struct AppletInfo {
 | 
					    struct AppletInfo {
 | 
				
			||||||
        u64 title_id;
 | 
					        u64 title_id;
 | 
				
			||||||
| 
						 | 
					@ -173,15 +198,19 @@ public:
 | 
				
			||||||
    struct ApplicationJumpParameters {
 | 
					    struct ApplicationJumpParameters {
 | 
				
			||||||
        u64 next_title_id;
 | 
					        u64 next_title_id;
 | 
				
			||||||
        FS::MediaType next_media_type;
 | 
					        FS::MediaType next_media_type;
 | 
				
			||||||
 | 
					        ApplicationJumpFlags flags;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        u64 current_title_id;
 | 
					        u64 current_title_id;
 | 
				
			||||||
        FS::MediaType current_media_type;
 | 
					        FS::MediaType current_media_type;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private:
 | 
					    private:
 | 
				
			||||||
        template <class Archive>
 | 
					        template <class Archive>
 | 
				
			||||||
        void serialize(Archive& ar, const unsigned int) {
 | 
					        void serialize(Archive& ar, const unsigned int file_version) {
 | 
				
			||||||
            ar& next_title_id;
 | 
					            ar& next_title_id;
 | 
				
			||||||
            ar& next_media_type;
 | 
					            ar& next_media_type;
 | 
				
			||||||
 | 
					            if (file_version > 0) {
 | 
				
			||||||
 | 
					                ar& flags;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
            ar& current_title_id;
 | 
					            ar& current_title_id;
 | 
				
			||||||
            ar& current_media_type;
 | 
					            ar& current_media_type;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					@ -242,6 +271,7 @@ private:
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ApplicationJumpParameters app_jump_parameters{};
 | 
					    ApplicationJumpParameters app_jump_parameters{};
 | 
				
			||||||
 | 
					    boost::optional<DeliverArg> deliver_arg{};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Holds data about the concurrently running applets in the system.
 | 
					    // Holds data about the concurrently running applets in the system.
 | 
				
			||||||
    std::array<AppletSlotData, NumAppletSlot> applet_slots = {};
 | 
					    std::array<AppletSlotData, NumAppletSlot> applet_slots = {};
 | 
				
			||||||
| 
						 | 
					@ -259,9 +289,12 @@ private:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
    template <class Archive>
 | 
					    template <class Archive>
 | 
				
			||||||
    void serialize(Archive& ar, const unsigned int) {
 | 
					    void serialize(Archive& ar, const unsigned int file_version) {
 | 
				
			||||||
        ar& next_parameter;
 | 
					        ar& next_parameter;
 | 
				
			||||||
        ar& app_jump_parameters;
 | 
					        ar& app_jump_parameters;
 | 
				
			||||||
 | 
					        if (file_version > 0) {
 | 
				
			||||||
 | 
					            ar& deliver_arg;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
        ar& applet_slots;
 | 
					        ar& applet_slots;
 | 
				
			||||||
        ar& library_applet_closing_command;
 | 
					        ar& library_applet_closing_command;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					@ -270,4 +303,7 @@ private:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
} // namespace Service::APT
 | 
					} // namespace Service::APT
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_CLASS_VERSION(Service::APT::AppletManager::ApplicationJumpParameters, 1)
 | 
				
			||||||
 | 
					BOOST_CLASS_VERSION(Service::APT::AppletManager, 1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
SERVICE_CONSTRUCT(Service::APT::AppletManager)
 | 
					SERVICE_CONSTRUCT(Service::APT::AppletManager)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -56,6 +56,10 @@ Module::NSInterface::NSInterface(std::shared_ptr<Module> apt, const char* name,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Module::NSInterface::~NSInterface() = default;
 | 
					Module::NSInterface::~NSInterface() = default;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					std::shared_ptr<Module> Module::NSInterface::GetModule() const {
 | 
				
			||||||
 | 
					    return apt;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void Module::NSInterface::SetWirelessRebootInfo(Kernel::HLERequestContext& ctx) {
 | 
					void Module::NSInterface::SetWirelessRebootInfo(Kernel::HLERequestContext& ctx) {
 | 
				
			||||||
    IPC::RequestParser rp(ctx, 0x06, 1, 2); // 0x00060042
 | 
					    IPC::RequestParser rp(ctx, 0x06, 1, 2); // 0x00060042
 | 
				
			||||||
    u32 size = rp.Pop<u32>();
 | 
					    u32 size = rp.Pop<u32>();
 | 
				
			||||||
| 
						 | 
					@ -476,19 +480,32 @@ void Module::APTInterface::PrepareToDoApplicationJump(Kernel::HLERequestContext&
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void Module::APTInterface::DoApplicationJump(Kernel::HLERequestContext& ctx) {
 | 
					void Module::APTInterface::DoApplicationJump(Kernel::HLERequestContext& ctx) {
 | 
				
			||||||
    IPC::RequestParser rp(ctx, 0x32, 2, 4); // 0x00320084
 | 
					    IPC::RequestParser rp(ctx, 0x32, 2, 4); // 0x00320084
 | 
				
			||||||
    const auto param_size = rp.Pop<u32>();
 | 
					    auto param_size = rp.Pop<u32>();
 | 
				
			||||||
    const auto hmac_size = rp.Pop<u32>();
 | 
					    auto hmac_size = rp.Pop<u32>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    [[maybe_unused]] const auto param = rp.PopStaticBuffer();
 | 
					    constexpr u32 max_param_size{0x300};
 | 
				
			||||||
    [[maybe_unused]] const auto hmac = rp.PopStaticBuffer();
 | 
					    constexpr u32 max_hmac_size{0x20};
 | 
				
			||||||
 | 
					    if (param_size > max_param_size) {
 | 
				
			||||||
 | 
					        LOG_ERROR(Service_APT,
 | 
				
			||||||
 | 
					                  "Param size is outside the valid range (capped to {:#010X}): param_size={:#010X}",
 | 
				
			||||||
 | 
					                  max_param_size, param_size);
 | 
				
			||||||
 | 
					        param_size = max_param_size;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (hmac_size > max_hmac_size) {
 | 
				
			||||||
 | 
					        LOG_ERROR(Service_APT,
 | 
				
			||||||
 | 
					                  "HMAC size is outside the valid range (capped to {:#010X}): hmac_size={:#010X}",
 | 
				
			||||||
 | 
					                  max_hmac_size, hmac_size);
 | 
				
			||||||
 | 
					        hmac_size = max_hmac_size;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    LOG_WARNING(Service_APT, "(STUBBED) called param_size={:08X}, hmac_size={:08X}", param_size,
 | 
					    auto param = rp.PopStaticBuffer();
 | 
				
			||||||
                hmac_size);
 | 
					    auto hmac = rp.PopStaticBuffer();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // TODO(Subv): Set the delivery parameters before starting the new application.
 | 
					    LOG_INFO(Service_APT, "called param_size={:08X}, hmac_size={:08X}", param_size, hmac_size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
 | 
					    IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
 | 
				
			||||||
    rb.Push(apt->applet_manager->DoApplicationJump());
 | 
					    rb.Push(apt->applet_manager->DoApplicationJump(
 | 
				
			||||||
 | 
					        AppletManager::DeliverArg{std::move(param), std::move(hmac)}));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void Module::APTInterface::GetProgramIdOnApplicationJump(Kernel::HLERequestContext& ctx) {
 | 
					void Module::APTInterface::GetProgramIdOnApplicationJump(Kernel::HLERequestContext& ctx) {
 | 
				
			||||||
| 
						 | 
					@ -506,6 +523,25 @@ void Module::APTInterface::GetProgramIdOnApplicationJump(Kernel::HLERequestConte
 | 
				
			||||||
    rb.Push(static_cast<u8>(parameters.next_media_type));
 | 
					    rb.Push(static_cast<u8>(parameters.next_media_type));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void Module::APTInterface::ReceiveDeliverArg(Kernel::HLERequestContext& ctx) {
 | 
				
			||||||
 | 
					    IPC::RequestParser rp(ctx, 0x35, 2, 4); // 0x00350080
 | 
				
			||||||
 | 
					    const auto param_size = rp.Pop<u32>();
 | 
				
			||||||
 | 
					    const auto hmac_size = rp.Pop<u32>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    LOG_DEBUG(Service_APT, "called param_size={:08X}, hmac_size={:08X}", param_size, hmac_size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    auto arg = apt->applet_manager->ReceiveDeliverArg().value_or(AppletManager::DeliverArg{});
 | 
				
			||||||
 | 
					    arg.param.resize(param_size);
 | 
				
			||||||
 | 
					    arg.hmac.resize(std::max<std::size_t>(hmac_size, 0x20));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    IPC::RequestBuilder rb = rp.MakeBuilder(4, 4);
 | 
				
			||||||
 | 
					    rb.Push(RESULT_SUCCESS);
 | 
				
			||||||
 | 
					    rb.Push(arg.source_program_id);
 | 
				
			||||||
 | 
					    rb.Push<u8>(1);
 | 
				
			||||||
 | 
					    rb.PushStaticBuffer(std::move(arg.param), 0);
 | 
				
			||||||
 | 
					    rb.PushStaticBuffer(std::move(arg.hmac), 1);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void Module::APTInterface::PrepareToStartApplication(Kernel::HLERequestContext& ctx) {
 | 
					void Module::APTInterface::PrepareToStartApplication(Kernel::HLERequestContext& ctx) {
 | 
				
			||||||
    IPC::RequestParser rp(ctx, 0x15, 5, 0); // 0x00150140
 | 
					    IPC::RequestParser rp(ctx, 0x15, 5, 0); // 0x00150140
 | 
				
			||||||
    u32 title_info1 = rp.Pop<u32>();
 | 
					    u32 title_info1 = rp.Pop<u32>();
 | 
				
			||||||
| 
						 | 
					@ -809,6 +845,9 @@ void Module::APTInterface::GetStartupArgument(Kernel::HLERequestContext& ctx) {
 | 
				
			||||||
    constexpr u32 max_parameter_size{0x1000};
 | 
					    constexpr u32 max_parameter_size{0x1000};
 | 
				
			||||||
    const auto startup_argument_type = static_cast<StartupArgumentType>(rp.Pop<u8>());
 | 
					    const auto startup_argument_type = static_cast<StartupArgumentType>(rp.Pop<u8>());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    LOG_WARNING(Service_APT, "called, startup_argument_type={}, parameter_size={:#010X}",
 | 
				
			||||||
 | 
					                static_cast<u32>(startup_argument_type), parameter_size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (parameter_size > max_parameter_size) {
 | 
					    if (parameter_size > max_parameter_size) {
 | 
				
			||||||
        LOG_ERROR(Service_APT,
 | 
					        LOG_ERROR(Service_APT,
 | 
				
			||||||
                  "Parameter size is outside the valid range (capped to {:#010X}): "
 | 
					                  "Parameter size is outside the valid range (capped to {:#010X}): "
 | 
				
			||||||
| 
						 | 
					@ -817,15 +856,36 @@ void Module::APTInterface::GetStartupArgument(Kernel::HLERequestContext& ctx) {
 | 
				
			||||||
        parameter_size = max_parameter_size;
 | 
					        parameter_size = max_parameter_size;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    std::vector<u8> parameter(parameter_size);
 | 
					    std::vector<u8> param;
 | 
				
			||||||
 | 
					    bool exists = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    LOG_WARNING(Service_APT, "(STUBBED) called, startup_argument_type={}, parameter_size={:#010X}",
 | 
					    if (auto arg = apt->applet_manager->ReceiveDeliverArg()) {
 | 
				
			||||||
                static_cast<u32>(startup_argument_type), parameter_size);
 | 
					        param = std::move(arg->param);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // TODO: This is a complete guess based on observations. It is unknown how the OtherMedia
 | 
				
			||||||
 | 
					        // type is handled and how it interacts with the OtherApp type, and it is unknown if
 | 
				
			||||||
 | 
					        // this (checking the jump parameters) is indeed the way the 3DS checks the types.
 | 
				
			||||||
 | 
					        const auto& jump_parameters = apt->applet_manager->GetApplicationJumpParameters();
 | 
				
			||||||
 | 
					        switch (startup_argument_type) {
 | 
				
			||||||
 | 
					        case StartupArgumentType::OtherApp:
 | 
				
			||||||
 | 
					            exists = jump_parameters.current_title_id != jump_parameters.next_title_id &&
 | 
				
			||||||
 | 
					                     jump_parameters.current_media_type == jump_parameters.next_media_type;
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        case StartupArgumentType::Restart:
 | 
				
			||||||
 | 
					            exists = jump_parameters.current_title_id == jump_parameters.next_title_id;
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        case StartupArgumentType::OtherMedia:
 | 
				
			||||||
 | 
					            exists = jump_parameters.current_media_type != jump_parameters.next_media_type;
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    param.resize(parameter_size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    IPC::RequestBuilder rb = rp.MakeBuilder(2, 2);
 | 
					    IPC::RequestBuilder rb = rp.MakeBuilder(2, 2);
 | 
				
			||||||
    rb.Push(RESULT_SUCCESS);
 | 
					    rb.Push(RESULT_SUCCESS);
 | 
				
			||||||
    rb.Push<u32>(0);
 | 
					    rb.Push(exists);
 | 
				
			||||||
    rb.PushStaticBuffer(std::move(parameter), 0);
 | 
					    rb.PushStaticBuffer(std::move(param), 0);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void Module::APTInterface::Wrap(Kernel::HLERequestContext& ctx) {
 | 
					void Module::APTInterface::Wrap(Kernel::HLERequestContext& ctx) {
 | 
				
			||||||
| 
						 | 
					@ -967,6 +1027,10 @@ Module::APTInterface::APTInterface(std::shared_ptr<Module> apt, const char* name
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Module::APTInterface::~APTInterface() = default;
 | 
					Module::APTInterface::~APTInterface() = default;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					std::shared_ptr<Module> Module::APTInterface::GetModule() const {
 | 
				
			||||||
 | 
					    return apt;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Module::Module(Core::System& system) : system(system) {
 | 
					Module::Module(Core::System& system) : system(system) {
 | 
				
			||||||
    applet_manager = std::make_shared<AppletManager>(system);
 | 
					    applet_manager = std::make_shared<AppletManager>(system);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -982,6 +1046,17 @@ Module::Module(Core::System& system) : system(system) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Module::~Module() {}
 | 
					Module::~Module() {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					std::shared_ptr<AppletManager> Module::GetAppletManager() const {
 | 
				
			||||||
 | 
					    return applet_manager;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					std::shared_ptr<Module> GetModule(Core::System& system) {
 | 
				
			||||||
 | 
					    auto apt = system.ServiceManager().GetService<Service::APT::Module::APTInterface>("APT:A");
 | 
				
			||||||
 | 
					    if (!apt)
 | 
				
			||||||
 | 
					        return nullptr;
 | 
				
			||||||
 | 
					    return apt->GetModule();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void InstallInterfaces(Core::System& system) {
 | 
					void InstallInterfaces(Core::System& system) {
 | 
				
			||||||
    auto& service_manager = system.ServiceManager();
 | 
					    auto& service_manager = system.ServiceManager();
 | 
				
			||||||
    auto apt = std::make_shared<Module>(system);
 | 
					    auto apt = std::make_shared<Module>(system);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -65,11 +65,15 @@ public:
 | 
				
			||||||
    explicit Module(Core::System& system);
 | 
					    explicit Module(Core::System& system);
 | 
				
			||||||
    ~Module();
 | 
					    ~Module();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::shared_ptr<AppletManager> GetAppletManager() const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    class NSInterface : public ServiceFramework<NSInterface> {
 | 
					    class NSInterface : public ServiceFramework<NSInterface> {
 | 
				
			||||||
    public:
 | 
					    public:
 | 
				
			||||||
        NSInterface(std::shared_ptr<Module> apt, const char* name, u32 max_session);
 | 
					        NSInterface(std::shared_ptr<Module> apt, const char* name, u32 max_session);
 | 
				
			||||||
        ~NSInterface();
 | 
					        ~NSInterface();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        std::shared_ptr<Module> GetModule() const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected:
 | 
					    protected:
 | 
				
			||||||
        std::shared_ptr<Module> apt;
 | 
					        std::shared_ptr<Module> apt;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -90,6 +94,8 @@ public:
 | 
				
			||||||
        APTInterface(std::shared_ptr<Module> apt, const char* name, u32 max_session);
 | 
					        APTInterface(std::shared_ptr<Module> apt, const char* name, u32 max_session);
 | 
				
			||||||
        ~APTInterface();
 | 
					        ~APTInterface();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        std::shared_ptr<Module> GetModule() const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected:
 | 
					    protected:
 | 
				
			||||||
        /**
 | 
					        /**
 | 
				
			||||||
         * APT::Initialize service function
 | 
					         * APT::Initialize service function
 | 
				
			||||||
| 
						 | 
					@ -505,6 +511,23 @@ public:
 | 
				
			||||||
         */
 | 
					         */
 | 
				
			||||||
        void GetProgramIdOnApplicationJump(Kernel::HLERequestContext& ctx);
 | 
					        void GetProgramIdOnApplicationJump(Kernel::HLERequestContext& ctx);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /**
 | 
				
			||||||
 | 
					         * APT::ReceiveDeliverArg service function
 | 
				
			||||||
 | 
					         *  Inputs:
 | 
				
			||||||
 | 
					         *      0 : Command header [0x00350080]
 | 
				
			||||||
 | 
					         *      1 : Parameter Size (capped to 0x300)
 | 
				
			||||||
 | 
					         *      2 : HMAC Size (capped to 0x20)
 | 
				
			||||||
 | 
					         *     64 : (Parameter Size << 14) | 2
 | 
				
			||||||
 | 
					         *     65 : Output buffer for Parameter
 | 
				
			||||||
 | 
					         *     66 : (HMAC Size << 14) | 0x802
 | 
				
			||||||
 | 
					         *     67 : Output buffer for HMAC
 | 
				
			||||||
 | 
					         *  Outputs:
 | 
				
			||||||
 | 
					         *      1 : Result of function, 0 on success, otherwise error code
 | 
				
			||||||
 | 
					         *    2-3 : Source program id
 | 
				
			||||||
 | 
					         *      4 : u8, whether the arg is received (0 = not received, 1 = received)
 | 
				
			||||||
 | 
					         */
 | 
				
			||||||
 | 
					        void ReceiveDeliverArg(Kernel::HLERequestContext& ctx);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /**
 | 
					        /**
 | 
				
			||||||
         * APT::CancelLibraryApplet service function
 | 
					         * APT::CancelLibraryApplet service function
 | 
				
			||||||
         *  Inputs:
 | 
					         *  Inputs:
 | 
				
			||||||
| 
						 | 
					@ -725,6 +748,8 @@ private:
 | 
				
			||||||
    friend class boost::serialization::access;
 | 
					    friend class boost::serialization::access;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					std::shared_ptr<Module> GetModule(Core::System& system);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void InstallInterfaces(Core::System& system);
 | 
					void InstallInterfaces(Core::System& system);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
} // namespace Service::APT
 | 
					} // namespace Service::APT
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -62,7 +62,7 @@ APT_A::APT_A(std::shared_ptr<Module> apt)
 | 
				
			||||||
        {0x00320084, &APT_A::DoApplicationJump, "DoApplicationJump"},
 | 
					        {0x00320084, &APT_A::DoApplicationJump, "DoApplicationJump"},
 | 
				
			||||||
        {0x00330000, &APT_A::GetProgramIdOnApplicationJump, "GetProgramIdOnApplicationJump"},
 | 
					        {0x00330000, &APT_A::GetProgramIdOnApplicationJump, "GetProgramIdOnApplicationJump"},
 | 
				
			||||||
        {0x00340084, nullptr, "SendDeliverArg"},
 | 
					        {0x00340084, nullptr, "SendDeliverArg"},
 | 
				
			||||||
        {0x00350080, nullptr, "ReceiveDeliverArg"},
 | 
					        {0x00350080, &APT_A::ReceiveDeliverArg, "ReceiveDeliverArg"},
 | 
				
			||||||
        {0x00360040, nullptr, "LoadSysMenuArg"},
 | 
					        {0x00360040, nullptr, "LoadSysMenuArg"},
 | 
				
			||||||
        {0x00370042, nullptr, "StoreSysMenuArg"},
 | 
					        {0x00370042, nullptr, "StoreSysMenuArg"},
 | 
				
			||||||
        {0x00380040, nullptr, "PreloadResidentApplet"},
 | 
					        {0x00380040, nullptr, "PreloadResidentApplet"},
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -62,7 +62,7 @@ APT_U::APT_U(std::shared_ptr<Module> apt)
 | 
				
			||||||
        {0x00320084, &APT_U::DoApplicationJump, "DoApplicationJump"},
 | 
					        {0x00320084, &APT_U::DoApplicationJump, "DoApplicationJump"},
 | 
				
			||||||
        {0x00330000, &APT_U::GetProgramIdOnApplicationJump, "GetProgramIdOnApplicationJump"},
 | 
					        {0x00330000, &APT_U::GetProgramIdOnApplicationJump, "GetProgramIdOnApplicationJump"},
 | 
				
			||||||
        {0x00340084, nullptr, "SendDeliverArg"},
 | 
					        {0x00340084, nullptr, "SendDeliverArg"},
 | 
				
			||||||
        {0x00350080, nullptr, "ReceiveDeliverArg"},
 | 
					        {0x00350080, &APT_U::ReceiveDeliverArg, "ReceiveDeliverArg"},
 | 
				
			||||||
        {0x00360040, &APT_U::LoadSysMenuArg, "LoadSysMenuArg"},
 | 
					        {0x00360040, &APT_U::LoadSysMenuArg, "LoadSysMenuArg"},
 | 
				
			||||||
        {0x00370042, &APT_U::StoreSysMenuArg, "StoreSysMenuArg"},
 | 
					        {0x00370042, &APT_U::StoreSysMenuArg, "StoreSysMenuArg"},
 | 
				
			||||||
        {0x00380040, nullptr, "PreloadResidentApplet"},
 | 
					        {0x00380040, nullptr, "PreloadResidentApplet"},
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue