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:
parent
02f8f1bb3e
commit
fe8c7e66e2
2 changed files with 52 additions and 16 deletions
|
@ -31,6 +31,7 @@
|
||||||
#include "core/hle/service/am/tcap.h"
|
#include "core/hle/service/am/tcap.h"
|
||||||
#include "core/hle/service/apm/controller.h"
|
#include "core/hle/service/apm/controller.h"
|
||||||
#include "core/hle/service/apm/interface.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/filesystem/filesystem.h"
|
||||||
#include "core/hle/service/ns/ns.h"
|
#include "core/hle/service/ns/ns.h"
|
||||||
#include "core/hle/service/nvflinger/nvflinger.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_NO_MESSAGES{ErrorModule::AM, 0x3};
|
||||||
constexpr ResultCode ERR_SIZE_OUT_OF_BOUNDS{ErrorModule::AM, 0x1F7};
|
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 magic;
|
||||||
u32_le is_account_selected;
|
u32_le is_account_selected;
|
||||||
u128 current_user;
|
u128 current_user;
|
||||||
INSERT_PADDING_BYTES(0x70);
|
INSERT_PADDING_BYTES(0x70);
|
||||||
};
|
};
|
||||||
static_assert(sizeof(LaunchParameters) == 0x88);
|
static_assert(sizeof(LaunchParameterAccountPreselectedUser) == 0x88);
|
||||||
|
|
||||||
IWindowController::IWindowController(Core::System& system_)
|
IWindowController::IWindowController(Core::System& system_)
|
||||||
: ServiceFramework("IWindowController"), system{system_} {
|
: ServiceFramework("IWindowController"), system{system_} {
|
||||||
|
@ -1128,11 +1134,32 @@ void IApplicationFunctions::EndBlockingHomeButton(Kernel::HLERequestContext& ctx
|
||||||
}
|
}
|
||||||
|
|
||||||
void IApplicationFunctions::PopLaunchParameter(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;
|
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));
|
||||||
|
|
||||||
|
const auto data =
|
||||||
|
backend->GetLaunchParameter({Core::CurrentProcess()->GetTitleID(), build_id});
|
||||||
|
|
||||||
|
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{};
|
||||||
|
|
||||||
|
params.magic = LAUNCH_PARAMETER_ACCOUNT_PRESELECTED_USER_MAGIC;
|
||||||
params.is_account_selected = 1;
|
params.is_account_selected = 1;
|
||||||
|
|
||||||
Account::ProfileManager profile_manager{};
|
Account::ProfileManager profile_manager{};
|
||||||
|
@ -1144,10 +1171,17 @@ void IApplicationFunctions::PopLaunchParameter(Kernel::HLERequestContext& ctx) {
|
||||||
|
|
||||||
rb.Push(RESULT_SUCCESS);
|
rb.Push(RESULT_SUCCESS);
|
||||||
|
|
||||||
std::vector<u8> buffer(sizeof(LaunchParameters));
|
std::vector<u8> buffer(sizeof(LaunchParameterAccountPreselectedUser));
|
||||||
std::memcpy(buffer.data(), ¶ms, buffer.size());
|
std::memcpy(buffer.data(), ¶ms, buffer.size());
|
||||||
|
|
||||||
rb.PushIpcInterface<AM::IStorage>(buffer);
|
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(
|
void IApplicationFunctions::CreateApplicationAndRequestToStartForQuest(
|
||||||
|
|
|
@ -255,6 +255,8 @@ private:
|
||||||
void EnableApplicationCrashReport(Kernel::HLERequestContext& ctx);
|
void EnableApplicationCrashReport(Kernel::HLERequestContext& ctx);
|
||||||
void GetGpuErrorDetectedSystemEvent(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;
|
Kernel::EventPair gpu_error_detected_event;
|
||||||
Core::System& system;
|
Core::System& system;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue