Merge pull request #11473 from liamwhite/fix-launch-param
am: Implement UserChannel parameters
This commit is contained in:
commit
9a0ea90018
10 changed files with 70 additions and 35 deletions
|
@ -562,6 +562,8 @@ struct System::Impl {
|
|||
|
||||
std::array<Core::GPUDirtyMemoryManager, Core::Hardware::NUM_CPU_CORES>
|
||||
gpu_dirty_memory_write_manager{};
|
||||
|
||||
std::deque<std::vector<u8>> user_channel;
|
||||
};
|
||||
|
||||
System::System() : impl{std::make_unique<Impl>(*this)} {}
|
||||
|
@ -1036,6 +1038,10 @@ void System::ExecuteProgram(std::size_t program_index) {
|
|||
}
|
||||
}
|
||||
|
||||
std::deque<std::vector<u8>>& System::GetUserChannel() {
|
||||
return impl->user_channel;
|
||||
}
|
||||
|
||||
void System::RegisterExitCallback(ExitCallback&& callback) {
|
||||
impl->exit_callback = std::move(callback);
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
#include <deque>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
|
@ -459,6 +460,12 @@ public:
|
|||
*/
|
||||
void ExecuteProgram(std::size_t program_index);
|
||||
|
||||
/**
|
||||
* Gets a reference to the user channel stack.
|
||||
* It is used to transfer data between programs.
|
||||
*/
|
||||
[[nodiscard]] std::deque<std::vector<u8>>& GetUserChannel();
|
||||
|
||||
/// Type used for the frontend to designate a callback for System to exit the application.
|
||||
using ExitCallback = std::function<void()>;
|
||||
|
||||
|
|
|
@ -46,7 +46,7 @@ constexpr Result ResultNoMessages{ErrorModule::AM, 3};
|
|||
constexpr Result ResultInvalidOffset{ErrorModule::AM, 503};
|
||||
|
||||
enum class LaunchParameterKind : u32 {
|
||||
ApplicationSpecific = 1,
|
||||
UserChannel = 1,
|
||||
AccountPreselectedUser = 2,
|
||||
};
|
||||
|
||||
|
@ -1518,27 +1518,26 @@ void IApplicationFunctions::PopLaunchParameter(HLERequestContext& ctx) {
|
|||
IPC::RequestParser rp{ctx};
|
||||
const auto kind = rp.PopEnum<LaunchParameterKind>();
|
||||
|
||||
LOG_DEBUG(Service_AM, "called, kind={:08X}", kind);
|
||||
LOG_INFO(Service_AM, "called, kind={:08X}", kind);
|
||||
|
||||
if (kind == LaunchParameterKind::ApplicationSpecific && !launch_popped_application_specific) {
|
||||
const auto backend = BCAT::CreateBackendFromSettings(system, [this](u64 tid) {
|
||||
return system.GetFileSystemController().GetBCATDirectory(tid);
|
||||
});
|
||||
const auto build_id_full = system.GetApplicationProcessBuildID();
|
||||
u64 build_id{};
|
||||
std::memcpy(&build_id, build_id_full.data(), sizeof(u64));
|
||||
|
||||
auto data =
|
||||
backend->GetLaunchParameter({system.GetApplicationProcessProgramID(), build_id});
|
||||
if (data.has_value()) {
|
||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.PushIpcInterface<IStorage>(system, std::move(*data));
|
||||
launch_popped_application_specific = true;
|
||||
if (kind == LaunchParameterKind::UserChannel) {
|
||||
auto channel = system.GetUserChannel();
|
||||
if (channel.empty()) {
|
||||
LOG_ERROR(Service_AM, "Attempted to load launch parameter but none was found!");
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(AM::ResultNoDataInChannel);
|
||||
return;
|
||||
}
|
||||
|
||||
auto data = channel.back();
|
||||
channel.pop_back();
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.PushIpcInterface<IStorage>(system, std::move(data));
|
||||
} else if (kind == LaunchParameterKind::AccountPreselectedUser &&
|
||||
!launch_popped_account_preselect) {
|
||||
// TODO: Verify this is hw-accurate
|
||||
LaunchParameterAccountPreselectedUser params{};
|
||||
|
||||
params.magic = LAUNCH_PARAMETER_ACCOUNT_PRESELECTED_USER_MAGIC;
|
||||
|
@ -1550,7 +1549,6 @@ void IApplicationFunctions::PopLaunchParameter(HLERequestContext& ctx) {
|
|||
params.current_user = *uuid;
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||
|
||||
rb.Push(ResultSuccess);
|
||||
|
||||
std::vector<u8> buffer(sizeof(LaunchParameterAccountPreselectedUser));
|
||||
|
@ -1558,12 +1556,11 @@ void IApplicationFunctions::PopLaunchParameter(HLERequestContext& ctx) {
|
|||
|
||||
rb.PushIpcInterface<IStorage>(system, std::move(buffer));
|
||||
launch_popped_account_preselect = true;
|
||||
return;
|
||||
} else {
|
||||
LOG_ERROR(Service_AM, "Unknown launch parameter kind.");
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(AM::ResultNoDataInChannel);
|
||||
}
|
||||
|
||||
LOG_ERROR(Service_AM, "Attempted to load launch parameter but none was found!");
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(AM::ResultNoDataInChannel);
|
||||
}
|
||||
|
||||
void IApplicationFunctions::CreateApplicationAndRequestToStartForQuest(HLERequestContext& ctx) {
|
||||
|
@ -1855,14 +1852,22 @@ void IApplicationFunctions::ExecuteProgram(HLERequestContext& ctx) {
|
|||
}
|
||||
|
||||
void IApplicationFunctions::ClearUserChannel(HLERequestContext& ctx) {
|
||||
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||
LOG_DEBUG(Service_AM, "called");
|
||||
|
||||
system.GetUserChannel().clear();
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ResultSuccess);
|
||||
}
|
||||
|
||||
void IApplicationFunctions::UnpopToUserChannel(HLERequestContext& ctx) {
|
||||
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||
LOG_DEBUG(Service_AM, "called");
|
||||
|
||||
IPC::RequestParser rp{ctx};
|
||||
const auto storage = rp.PopIpcInterface<IStorage>().lock();
|
||||
if (storage) {
|
||||
system.GetUserChannel().push_back(storage->GetData());
|
||||
}
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ResultSuccess);
|
||||
|
|
|
@ -339,7 +339,6 @@ private:
|
|||
|
||||
KernelHelpers::ServiceContext service_context;
|
||||
|
||||
bool launch_popped_application_specific = false;
|
||||
bool launch_popped_account_preselect = false;
|
||||
s32 previous_program_index{-1};
|
||||
Kernel::KEvent* gpu_error_detected_event;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue