[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:
Maufeat 2025-11-27 19:46:41 +01:00 committed by crueter
parent 1efef85352
commit f58097e814
No known key found for this signature in database
GPG key ID: 425ACD2D4830EBC6
75 changed files with 1634 additions and 181 deletions

View file

@ -580,6 +580,21 @@ struct System::Impl {
gpu_dirty_memory_managers;
std::deque<std::vector<u8>> user_channel;
std::mutex general_channel_mutex;
std::deque<std::vector<u8>> general_channel;
std::unique_ptr<Service::KernelHelpers::ServiceContext> general_channel_context; // lazy
std::unique_ptr<Service::Event> general_channel_event; // lazy
bool general_channel_initialized{false};
void EnsureGeneralChannelInitialized(System& system) {
if (general_channel_initialized) {
return;
}
general_channel_context = std::make_unique<Service::KernelHelpers::ServiceContext>(system, "GeneralChannel");
general_channel_event = std::make_unique<Service::Event>(*general_channel_context);
general_channel_initialized = true;
}
};
System::System() : impl{std::make_unique<Impl>(*this)} {}
@ -993,6 +1008,39 @@ std::deque<std::vector<u8>>& System::GetUserChannel() {
return impl->user_channel;
}
std::deque<std::vector<u8>>& System::GetGeneralChannel() {
return impl->general_channel;
}
void System::PushGeneralChannelData(std::vector<u8>&& data) {
std::scoped_lock lk{impl->general_channel_mutex};
impl->EnsureGeneralChannelInitialized(*this);
const bool was_empty = impl->general_channel.empty();
impl->general_channel.push_back(std::move(data));
if (was_empty) {
impl->general_channel_event->Signal();
}
}
bool System::TryPopGeneralChannel(std::vector<u8>& out_data) {
std::scoped_lock lk{impl->general_channel_mutex};
if (!impl->general_channel_initialized || impl->general_channel.empty()) {
return false;
}
out_data = std::move(impl->general_channel.back());
impl->general_channel.pop_back();
if (impl->general_channel.empty()) {
impl->general_channel_event->Clear();
}
return true;
}
Service::Event& System::GetGeneralChannelEvent() {
std::scoped_lock lk{impl->general_channel_mutex};
impl->EnsureGeneralChannelInitialized(*this);
return *impl->general_channel_event;
}
void System::RegisterExitCallback(ExitCallback&& callback) {
impl->exit_callback = std::move(callback);
}