mirror of
https://git.eden-emu.dev/eden-emu/eden
synced 2026-07-01 17:55:23 +02:00
[hle,display,overlay,starter,hid] add overlay functions, starter applet (initially), HID handheld for system applets and fw21 stubs (#3080)
Adds fully functional overlay display. - Enable Overlay Applet via "View" -> "Enable Overlay Display Applet" - Open the overlay by pressing the home button for over 1s - Can adjust volume - Can toggle airplane mode (if on WiFi, maybe if overlay is enabled pretend to be on WiFi?) - Future TODO(?): Adjust Brightness implementation for host system - Inputs are properly registered. e.g. if overlay open, application does not register inputs. You can control volume and airplane mode outside of the emulator window Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3080 Reviewed-by: CamilleLaVey <camillelavey99@gmail.com> Reviewed-by: crueter <crueter@eden-emu.dev> Co-authored-by: Maufeat <sahyno1996@gmail.com> Co-committed-by: Maufeat <sahyno1996@gmail.com>
This commit is contained in:
parent
1efef85352
commit
f58097e814
75 changed files with 1634 additions and 181 deletions
|
|
@ -1,3 +1,6 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
|
|
@ -18,4 +21,13 @@ union MessageFlags {
|
|||
};
|
||||
static_assert(sizeof(MessageFlags) == 0x8, "MessageFlags has incorrect size");
|
||||
|
||||
struct SourceName {
|
||||
char name[0x16];
|
||||
|
||||
const char* GetString() const {
|
||||
return name;
|
||||
}
|
||||
};
|
||||
;
|
||||
|
||||
} // namespace Service::PSC
|
||||
|
|
|
|||
|
|
@ -1,24 +1,118 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "core/hle/service/psc/ovln/receiver.h"
|
||||
#include "core/hle/service/cmif_serialization.h"
|
||||
|
||||
namespace Service::PSC {
|
||||
|
||||
IReceiver::IReceiver(Core::System& system_) : ServiceFramework{system_, "IReceiver"} {
|
||||
IReceiver::IReceiver(Core::System& system_)
|
||||
: ServiceFramework{system_, "IReceiver"}, service_context{system_, "IReceiver"} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, nullptr, "AddSource"},
|
||||
{1, nullptr, "RemoveSource"},
|
||||
{2, nullptr, "GetReceiveEventHandle"},
|
||||
{3, nullptr, "Receive"},
|
||||
{4, nullptr, "ReceiveWithTick"},
|
||||
{0, D<&IReceiver::AddSource>, "AddSource"},
|
||||
{1, D<&IReceiver::RemoveSource>, "RemoveSource"},
|
||||
{2, D<&IReceiver::GetReceiveEventHandle>, "GetReceiveEventHandle"},
|
||||
{3, D<&IReceiver::Receive>, "Receive"},
|
||||
{4, D<&IReceiver::ReceiveWithTick>, "ReceiveWithTick"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
|
||||
receive_event = service_context.CreateEvent("IReceiver::ReceiveEvent");
|
||||
}
|
||||
|
||||
IReceiver::~IReceiver() = default;
|
||||
IReceiver::~IReceiver() {
|
||||
service_context.CloseEvent(receive_event);
|
||||
}
|
||||
|
||||
Result IReceiver::AddSource(SourceName source_name) {
|
||||
const std::string name = source_name.GetString();
|
||||
LOG_INFO(Service_PSC, "called: source_name={}", name);
|
||||
|
||||
// Add source if it doesn't already exist
|
||||
if (message_sources.find(name) == message_sources.end()) {
|
||||
message_sources[name] = {};
|
||||
}
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IReceiver::RemoveSource(SourceName source_name) {
|
||||
const std::string name = source_name.GetString();
|
||||
LOG_INFO(Service_PSC, "called: source_name={}", name);
|
||||
|
||||
// Remove source if it exists
|
||||
message_sources.erase(name);
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IReceiver::GetReceiveEventHandle(OutCopyHandle<Kernel::KReadableEvent> out_event) {
|
||||
LOG_INFO(Service_PSC, "called");
|
||||
*out_event = &receive_event->GetReadableEvent();
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IReceiver::Receive(Out<OverlayNotification> out_notification, Out<MessageFlags> out_flags) {
|
||||
u64 tick;
|
||||
return ReceiveWithTick(out_notification, out_flags, Out<u64>(&tick));
|
||||
}
|
||||
|
||||
Result IReceiver::ReceiveWithTick(Out<OverlayNotification> out_notification,
|
||||
Out<MessageFlags> out_flags, Out<u64> out_tick) {
|
||||
LOG_DEBUG(Service_PSC, "called");
|
||||
|
||||
// Find the message with the lowest ID across all sources
|
||||
const std::string* target_source = nullptr;
|
||||
size_t target_index = 0;
|
||||
|
||||
for (const auto& [source_name, messages] : message_sources) {
|
||||
if (!messages.empty()) {
|
||||
if (target_source == nullptr) {
|
||||
target_source = &source_name;
|
||||
target_index = 0;
|
||||
}
|
||||
// Note: In the real implementation, we would track message IDs
|
||||
// For now, just use FIFO order
|
||||
}
|
||||
}
|
||||
|
||||
if (target_source != nullptr) {
|
||||
auto& messages = message_sources[*target_source];
|
||||
*out_notification = messages[target_index].first;
|
||||
*out_flags = messages[target_index].second;
|
||||
*out_tick = 0; // TODO: Implement tick tracking
|
||||
|
||||
// Remove the message
|
||||
messages.erase(messages.begin() + target_index);
|
||||
|
||||
// Clear event if no more messages
|
||||
bool has_messages = false;
|
||||
for (const auto& [_, msgs] : message_sources) {
|
||||
if (!msgs.empty()) {
|
||||
has_messages = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!has_messages) {
|
||||
receive_event->Clear();
|
||||
}
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
// No messages available
|
||||
*out_notification = {};
|
||||
*out_flags = {};
|
||||
*out_tick = 0;
|
||||
|
||||
LOG_WARNING(Service_PSC, "No messages available");
|
||||
R_THROW(ResultUnknown); // TODO: Use proper OvlnResult::NoMessages when available
|
||||
}
|
||||
|
||||
} // namespace Service::PSC
|
||||
|
|
|
|||
|
|
@ -1,9 +1,23 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include "core/hle/result.h"
|
||||
#include "core/hle/service/cmif_types.h"
|
||||
#include "core/hle/service/kernel_helpers.h"
|
||||
#include "core/hle/service/service.h"
|
||||
#include "core/hle/service/psc/ovln/ovln_types.h"
|
||||
|
||||
namespace Kernel {
|
||||
class KReadableEvent;
|
||||
}
|
||||
|
||||
namespace Service::PSC {
|
||||
|
||||
|
|
@ -11,6 +25,22 @@ class IReceiver final : public ServiceFramework<IReceiver> {
|
|||
public:
|
||||
explicit IReceiver(Core::System& system_);
|
||||
~IReceiver() override;
|
||||
|
||||
IReceiver(const IReceiver&) = delete;
|
||||
IReceiver& operator=(const IReceiver&) = delete;
|
||||
|
||||
private:
|
||||
Result AddSource(SourceName source_name);
|
||||
Result RemoveSource(SourceName source_name);
|
||||
Result GetReceiveEventHandle(OutCopyHandle<Kernel::KReadableEvent> out_event);
|
||||
Result Receive(Out<OverlayNotification> out_notification, Out<MessageFlags> out_flags);
|
||||
Result ReceiveWithTick(Out<OverlayNotification> out_notification, Out<MessageFlags> out_flags,
|
||||
Out<u64> out_tick);
|
||||
|
||||
KernelHelpers::ServiceContext service_context;
|
||||
Kernel::KEvent* receive_event;
|
||||
|
||||
std::map<std::string, std::vector<std::pair<OverlayNotification, MessageFlags>>> message_sources;
|
||||
};
|
||||
|
||||
} // namespace Service::PSC
|
||||
|
|
|
|||
|
|
@ -1,3 +1,6 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
|
|
@ -21,7 +24,7 @@ IReceiverService::~IReceiverService() = default;
|
|||
|
||||
Result IReceiverService::OpenReceiver(Out<SharedPointer<IReceiver>> out_receiver) {
|
||||
LOG_DEBUG(Service_PSC, "called");
|
||||
*out_receiver = std::make_shared<IReceiver>(system);
|
||||
*out_receiver = std::shared_ptr<IReceiver>(new IReceiver(system));
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue