summaryrefslogtreecommitdiffstats
path: root/src/core
diff options
context:
space:
mode:
Diffstat (limited to 'src/core')
-rw-r--r--src/core/core.cpp6
-rw-r--r--src/core/core.h7
-rw-r--r--src/core/hle/service/am/am.cpp57
-rw-r--r--src/core/hle/service/am/am.h1
4 files changed, 44 insertions, 27 deletions
diff --git a/src/core/core.cpp b/src/core/core.cpp
index e95ae80da..f075ae7fa 100644
--- a/src/core/core.cpp
+++ b/src/core/core.cpp
@@ -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);
}
diff --git a/src/core/core.h b/src/core/core.h
index a9ff9315e..fba312125 100644
--- a/src/core/core.h
+++ b/src/core/core.h
@@ -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()>;
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp
index e92f400de..f9c4f9678 100644
--- a/src/core/hle/service/am/am.cpp
+++ b/src/core/hle/service/am/am.cpp
@@ -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);
-
- 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;
+ LOG_INFO(Service_AM, "called, kind={:08X}", kind);
+
+ 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);
diff --git a/src/core/hle/service/am/am.h b/src/core/hle/service/am/am.h
index d68998f04..f75a665b2 100644
--- a/src/core/hle/service/am/am.h
+++ b/src/core/hle/service/am/am.h
@@ -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;