am: Unstub PopLaunchParameter and add bcat connection for app-specific data
Previously we were simply returning the account-preselect structure all times but if passed with a different mode the game expects application-specific data. This also adds a hook for BCAT into this allowing us to send the launch parameter through bcat,
This commit is contained in:
		@@ -31,6 +31,7 @@
 | 
			
		||||
#include "core/hle/service/am/tcap.h"
 | 
			
		||||
#include "core/hle/service/apm/controller.h"
 | 
			
		||||
#include "core/hle/service/apm/interface.h"
 | 
			
		||||
#include "core/hle/service/bcat/backend/backend.h"
 | 
			
		||||
#include "core/hle/service/filesystem/filesystem.h"
 | 
			
		||||
#include "core/hle/service/ns/ns.h"
 | 
			
		||||
#include "core/hle/service/nvflinger/nvflinger.h"
 | 
			
		||||
@@ -46,15 +47,20 @@ constexpr ResultCode ERR_NO_DATA_IN_CHANNEL{ErrorModule::AM, 0x2};
 | 
			
		||||
constexpr ResultCode ERR_NO_MESSAGES{ErrorModule::AM, 0x3};
 | 
			
		||||
constexpr ResultCode ERR_SIZE_OUT_OF_BOUNDS{ErrorModule::AM, 0x1F7};
 | 
			
		||||
 | 
			
		||||
constexpr u32 POP_LAUNCH_PARAMETER_MAGIC = 0xC79497CA;
 | 
			
		||||
enum class LaunchParameterKind : u32 {
 | 
			
		||||
    ApplicationSpecific = 1,
 | 
			
		||||
    AccountPreselectedUser = 2,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct LaunchParameters {
 | 
			
		||||
constexpr u32 LAUNCH_PARAMETER_ACCOUNT_PRESELECTED_USER_MAGIC = 0xC79497CA;
 | 
			
		||||
 | 
			
		||||
struct LaunchParameterAccountPreselectedUser {
 | 
			
		||||
    u32_le magic;
 | 
			
		||||
    u32_le is_account_selected;
 | 
			
		||||
    u128 current_user;
 | 
			
		||||
    INSERT_PADDING_BYTES(0x70);
 | 
			
		||||
};
 | 
			
		||||
static_assert(sizeof(LaunchParameters) == 0x88);
 | 
			
		||||
static_assert(sizeof(LaunchParameterAccountPreselectedUser) == 0x88);
 | 
			
		||||
 | 
			
		||||
IWindowController::IWindowController(Core::System& system_)
 | 
			
		||||
    : ServiceFramework("IWindowController"), system{system_} {
 | 
			
		||||
@@ -1128,26 +1134,54 @@ void IApplicationFunctions::EndBlockingHomeButton(Kernel::HLERequestContext& ctx
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void IApplicationFunctions::PopLaunchParameter(Kernel::HLERequestContext& ctx) {
 | 
			
		||||
    LOG_DEBUG(Service_AM, "called");
 | 
			
		||||
    IPC::RequestParser rp{ctx};
 | 
			
		||||
    const auto kind = rp.PopEnum<LaunchParameterKind>();
 | 
			
		||||
 | 
			
		||||
    LaunchParameters params{};
 | 
			
		||||
    LOG_DEBUG(Service_AM, "called, kind={:08X}", static_cast<u8>(kind));
 | 
			
		||||
 | 
			
		||||
    params.magic = POP_LAUNCH_PARAMETER_MAGIC;
 | 
			
		||||
    params.is_account_selected = 1;
 | 
			
		||||
    if (kind == LaunchParameterKind::ApplicationSpecific && !launch_popped_application_specific) {
 | 
			
		||||
        const auto backend = BCAT::CreateBackendFromSettings(&FileSystem::GetBCATDirectory);
 | 
			
		||||
        const auto build_id_full = Core::System::GetInstance().GetCurrentProcessBuildID();
 | 
			
		||||
        u64 build_id{};
 | 
			
		||||
        std::memcpy(&build_id, build_id_full.data(), sizeof(u64));
 | 
			
		||||
 | 
			
		||||
    Account::ProfileManager profile_manager{};
 | 
			
		||||
    const auto uuid = profile_manager.GetUser(Settings::values.current_user);
 | 
			
		||||
    ASSERT(uuid);
 | 
			
		||||
    params.current_user = uuid->uuid;
 | 
			
		||||
        const auto data =
 | 
			
		||||
            backend->GetLaunchParameter({Core::CurrentProcess()->GetTitleID(), build_id});
 | 
			
		||||
 | 
			
		||||
    IPC::ResponseBuilder rb{ctx, 2, 0, 1};
 | 
			
		||||
        if (data.has_value()) {
 | 
			
		||||
            IPC::ResponseBuilder rb{ctx, 2, 0, 1};
 | 
			
		||||
            rb.Push(RESULT_SUCCESS);
 | 
			
		||||
            rb.PushIpcInterface<AM::IStorage>(*data);
 | 
			
		||||
            launch_popped_application_specific = true;
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
    } else if (kind == LaunchParameterKind::AccountPreselectedUser &&
 | 
			
		||||
               !launch_popped_account_preselect) {
 | 
			
		||||
        LaunchParameterAccountPreselectedUser params{};
 | 
			
		||||
 | 
			
		||||
    rb.Push(RESULT_SUCCESS);
 | 
			
		||||
        params.magic = LAUNCH_PARAMETER_ACCOUNT_PRESELECTED_USER_MAGIC;
 | 
			
		||||
        params.is_account_selected = 1;
 | 
			
		||||
 | 
			
		||||
    std::vector<u8> buffer(sizeof(LaunchParameters));
 | 
			
		||||
    std::memcpy(buffer.data(), ¶ms, buffer.size());
 | 
			
		||||
        Account::ProfileManager profile_manager{};
 | 
			
		||||
        const auto uuid = profile_manager.GetUser(Settings::values.current_user);
 | 
			
		||||
        ASSERT(uuid);
 | 
			
		||||
        params.current_user = uuid->uuid;
 | 
			
		||||
 | 
			
		||||
    rb.PushIpcInterface<AM::IStorage>(buffer);
 | 
			
		||||
        IPC::ResponseBuilder rb{ctx, 2, 0, 1};
 | 
			
		||||
 | 
			
		||||
        rb.Push(RESULT_SUCCESS);
 | 
			
		||||
 | 
			
		||||
        std::vector<u8> buffer(sizeof(LaunchParameterAccountPreselectedUser));
 | 
			
		||||
        std::memcpy(buffer.data(), ¶ms, buffer.size());
 | 
			
		||||
 | 
			
		||||
        rb.PushIpcInterface<AM::IStorage>(buffer);
 | 
			
		||||
        launch_popped_account_preselect = true;
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    LOG_ERROR(Service_AM, "Attempted to load launch parameter but none was found!");
 | 
			
		||||
    IPC::ResponseBuilder rb{ctx, 2};
 | 
			
		||||
    rb.Push(ERR_NO_DATA_IN_CHANNEL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void IApplicationFunctions::CreateApplicationAndRequestToStartForQuest(
 | 
			
		||||
 
 | 
			
		||||
@@ -255,6 +255,8 @@ private:
 | 
			
		||||
    void EnableApplicationCrashReport(Kernel::HLERequestContext& ctx);
 | 
			
		||||
    void GetGpuErrorDetectedSystemEvent(Kernel::HLERequestContext& ctx);
 | 
			
		||||
 | 
			
		||||
    bool launch_popped_application_specific = false;
 | 
			
		||||
    bool launch_popped_account_preselect = false;
 | 
			
		||||
    Kernel::EventPair gpu_error_detected_event;
 | 
			
		||||
    Core::System& system;
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user