Browse Source

some improvements :)

pull/2953/head
Maufeat 4 months ago
parent
commit
b2328abe93
  1. 1
      src/core/file_sys/control_metadata.h
  2. 2
      src/core/file_sys/savedata_factory.cpp
  3. 2
      src/core/hle/service/am/am.cpp
  4. 63
      src/core/hle/service/am/button_poller.cpp
  5. 14
      src/core/hle/service/am/button_poller.h
  6. 16
      src/core/hle/service/ns/application_manager_interface.cpp
  7. 3
      src/core/hle/service/ns/application_manager_interface.h
  8. 95
      src/core/hle/service/ns/read_only_application_control_data_interface.cpp
  9. 8
      src/core/hle/service/ns/read_only_application_control_data_interface.h
  10. 1
      src/qt_common/config/shared_translation.cpp

1
src/core/file_sys/control_metadata.h

@ -5,6 +5,7 @@
#include <array>
#include <string>
#include <vector>
#include "common/common_funcs.h"
#include "common/common_types.h"
#include "common/swap.h"

2
src/core/file_sys/savedata_factory.cpp

@ -98,6 +98,8 @@ std::string SaveDataFactory::GetSaveDataSpaceIdPath(SaveDataSpaceId space) {
return "/user/";
case SaveDataSpaceId::Temporary:
return "/temp/";
case SaveDataSpaceId::SdUser:
return "/user/";
default:
ASSERT_MSG(false, "Unrecognized SaveDataSpaceId: {:02X}", static_cast<u8>(space));
return "/unrecognized/"; ///< To prevent corruption when ignoring asserts.

2
src/core/hle/service/am/am.cpp

@ -13,8 +13,8 @@ namespace Service::AM {
void LoopProcess(Core::System& system) {
WindowSystem window_system(system);
ButtonPoller button_poller(system, window_system);
EventObserver event_observer(system, window_system);
ButtonPoller button_poller(system, window_system);
auto server_manager = std::make_unique<ServerManager>(system);

63
src/core/hle/service/am/button_poller.cpp

@ -48,14 +48,22 @@ ButtonPoller::ButtonPoller(Core::System& system, WindowSystem& window_system)
m_handheld_key = m_handheld->SetCallback(engine_callback);
m_player1 = system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Player1);
m_player1_key = m_player1->SetCallback(engine_callback);
m_thread = std::thread([this] { this->ThreadLoop(); });
}
ButtonPoller::~ButtonPoller() {
m_handheld->DeleteCallback(m_handheld_key);
m_player1->DeleteCallback(m_player1_key);
m_stop = true;
m_cv.notify_all();
if (m_thread.joinable()) {
m_thread.join();
}
}
void ButtonPoller::OnButtonStateChanged() {
std::lock_guard lk{m_mutex};
const bool home_button =
m_handheld->GetHomeButtons().home.Value() || m_player1->GetHomeButtons().home.Value();
const bool capture_button = m_handheld->GetCaptureButtons().capture.Value() ||
@ -64,28 +72,53 @@ void ButtonPoller::OnButtonStateChanged() {
// Buttons pressed which were not previously pressed
if (home_button && !m_home_button_press_start) {
m_home_button_press_start = std::chrono::steady_clock::now();
m_home_button_long_sent = false;
}
if (capture_button && !m_capture_button_press_start) {
m_capture_button_press_start = std::chrono::steady_clock::now();
m_capture_button_long_sent = false;
}
// if (power_button && !m_power_button_press_start) {
// m_power_button_press_start = std::chrono::steady_clock::now();
// }
// Buttons released which were previously held
if (!home_button && m_home_button_press_start) {
// While buttons are held, check whether they have crossed the long-press
// threshold and, if so, send the long-press action immediately (only once).
if (home_button && m_home_button_press_start && !m_home_button_long_sent) {
const auto duration = ClassifyPressDuration(*m_home_button_press_start);
m_window_system.OnSystemButtonPress(
duration == ButtonPressDuration::ShortPressing ? SystemButtonType::HomeButtonShortPressing
: SystemButtonType::HomeButtonLongPressing);
if (duration != ButtonPressDuration::ShortPressing) {
m_window_system.OnSystemButtonPress(SystemButtonType::HomeButtonLongPressing);
m_home_button_long_sent = true;
}
}
if (capture_button && m_capture_button_press_start && !m_capture_button_long_sent) {
const auto duration = ClassifyPressDuration(*m_capture_button_press_start);
if (duration != ButtonPressDuration::ShortPressing) {
m_window_system.OnSystemButtonPress(SystemButtonType::CaptureButtonLongPressing);
m_capture_button_long_sent = true;
}
}
// Buttons released which were previously held
if (!home_button && m_home_button_press_start) { (!m_home_button_long_sent) {
const auto duration = ClassifyPressDuration(*m_home_button_press_start);
m_window_system.OnSystemButtonPress(
duration == ButtonPressDuration::ShortPressing ? SystemButtonType::HomeButtonShortPressing
: SystemButtonType::HomeButtonLongPressing);
}
m_home_button_press_start = std::nullopt;
m_home_button_long_sent = false;
}
if (!capture_button && m_capture_button_press_start) {
const auto duration = ClassifyPressDuration(*m_capture_button_press_start);
m_window_system.OnSystemButtonPress(
duration == ButtonPressDuration::ShortPressing ? SystemButtonType::CaptureButtonShortPressing
: SystemButtonType::CaptureButtonLongPressing);
if (!m_capture_button_long_sent) {
const auto duration = ClassifyPressDuration(*m_capture_button_press_start);
m_window_system.OnSystemButtonPress(
duration == ButtonPressDuration::ShortPressing ? SystemButtonType::CaptureButtonShortPressing
: SystemButtonType::CaptureButtonLongPressing);
}
m_capture_button_press_start = std::nullopt;
m_capture_button_long_sent = false;
}
// if (!power_button && m_power_button_press_start) {
// // TODO
@ -93,4 +126,16 @@ void ButtonPoller::OnButtonStateChanged() {
// }
}
void ButtonPoller::ThreadLoop() {
using namespace std::chrono_literals;
std::unique_lock<std::mutex> lk{m_mutex};
while (!m_stop) {
m_cv.wait_for(lk, 50ms);
if (m_stop) break;
lk.unlock();
OnButtonStateChanged();
lk.lock();
}
}
} // namespace Service::AM

14
src/core/hle/service/am/button_poller.h

@ -3,8 +3,12 @@
#pragma once
#include <atomic>
#include <chrono>
#include <condition_variable>
#include <mutex>
#include <optional>
#include <thread>
#include "hid_core/frontend/emulated_controller.h"
namespace Core {
@ -26,6 +30,7 @@ public:
private:
void OnButtonStateChanged();
void ThreadLoop();
private:
WindowSystem& m_window_system;
@ -38,6 +43,15 @@ private:
std::optional<std::chrono::steady_clock::time_point> m_home_button_press_start{};
std::optional<std::chrono::steady_clock::time_point> m_capture_button_press_start{};
std::optional<std::chrono::steady_clock::time_point> m_power_button_press_start{};
bool m_home_button_long_sent{};
bool m_capture_button_long_sent{};
bool m_power_button_long_sent{};
std::thread m_thread;
std::atomic<bool> m_stop{false};
std::condition_variable m_cv;
std::mutex m_mutex;
};
} // namespace Service::AM

16
src/core/hle/service/ns/application_manager_interface.cpp

@ -4,6 +4,7 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "core/file_sys/control_metadata.h"
#include "core/file_sys/nca_metadata.h"
#include "core/file_sys/registered_cache.h"
#include "core/hle/service/cmif_serialization.h"
@ -11,6 +12,7 @@
#include "core/hle/service/ns/application_manager_interface.h"
#include "core/hle/service/ns/content_management_interface.h"
#include "core/hle/service/ns/read_only_application_control_data_interface.h"
#include "core/file_sys/patch_manager.h"
namespace Service::NS {
@ -19,7 +21,7 @@ IApplicationManagerInterface::IApplicationManagerInterface(Core::System& system_
service_context{system, "IApplicationManagerInterface"},
record_update_system_event{service_context}, sd_card_mount_status_event{service_context},
gamecard_update_detection_event{service_context},
gamecard_mount_status_event{service_context}, gamecard_mount_failure_event{service_context}, gamecard_waken_ready_event{service_context} {
gamecard_mount_status_event{service_context}, gamecard_mount_failure_event{service_context}, gamecard_waken_ready_event{service_context}, unknown_event{service_context} {
// clang-format off
static const FunctionInfo functions[] = {
{0, D<&IApplicationManagerInterface::ListApplicationRecord>, "ListApplicationRecord"},
@ -331,7 +333,7 @@ Result IApplicationManagerInterface::GetApplicationControlData(
OutBuffer<BufferAttr_HipcMapAlias> out_buffer, Out<u32> out_actual_size,
ApplicationControlSource application_control_source, u64 application_id) {
LOG_DEBUG(Service_NS, "called");
R_RETURN(IReadOnlyApplicationControlDataInterface(system).GetApplicationControlDataOld(
R_RETURN(IReadOnlyApplicationControlDataInterface(system).GetApplicationControlData(
out_buffer, out_actual_size, application_control_source, application_id));
}
@ -563,15 +565,19 @@ Result IApplicationManagerInterface::GetApplicationTerminateResult(Out<Result> o
}
Result IApplicationManagerInterface::RequestDownloadApplicationControlDataInBackground(
u64 unk, u64 application_id) {
LOG_WARNING(Service_NS, "(STUBBED), app={:016X} unk={}", application_id, unk);
u64 control_source, u64 application_id) {
LOG_INFO(Service_NS, "called, control_source={} app={:016X}",
control_source, application_id);
unknown_event.Signal();
R_SUCCEED();
}
Result IApplicationManagerInterface::Unknown4022(
OutCopyHandle<Kernel::KReadableEvent> out_event) {
LOG_WARNING(Service_NS, "(STUBBED) called");
*out_event = gamecard_update_detection_event.GetHandle();
unknown_event.Signal();
*out_event = unknown_event.GetHandle();
R_SUCCEED();
}

3
src/core/hle/service/ns/application_manager_interface.h

@ -62,7 +62,7 @@ public:
Result Unknown4023(Out<u64> out_result);
Result Unknown4053();
Result RequestDownloadApplicationControlDataInBackground(u64 unk,
Result RequestDownloadApplicationControlDataInBackground(u64 control_source,
u64 application_id);
private:
@ -73,6 +73,7 @@ private:
Event gamecard_mount_status_event;
Event gamecard_mount_failure_event;
Event gamecard_waken_ready_event;
Event unknown_event;
};
} // namespace Service::NS

95
src/core/hle/service/ns/read_only_application_control_data_interface.cpp

@ -22,12 +22,12 @@ IReadOnlyApplicationControlDataInterface::IReadOnlyApplicationControlDataInterfa
: ServiceFramework{system_, "IReadOnlyApplicationControlDataInterface"} {
// clang-format off
static const FunctionInfo functions[] = {
{0, D<&IReadOnlyApplicationControlDataInterface::GetApplicationControlDataOld>, "GetApplicationControlDataOld"},
{0, D<&IReadOnlyApplicationControlDataInterface::GetApplicationControlData>, "GetApplicationControlData"},
{1, D<&IReadOnlyApplicationControlDataInterface::GetApplicationDesiredLanguage>, "GetApplicationDesiredLanguage"},
{2, D<&IReadOnlyApplicationControlDataInterface::ConvertApplicationLanguageToLanguageCode>, "ConvertApplicationLanguageToLanguageCode"},
{3, nullptr, "ConvertLanguageCodeToApplicationLanguage"},
{4, nullptr, "SelectApplicationDesiredLanguage"},
{5, D<&IReadOnlyApplicationControlDataInterface::GetApplicationControlDataWithIconSize>, "GetApplicationControlDataWithIconSize"},
{5, D<&IReadOnlyApplicationControlDataInterface::GetApplicationControlDataWithoutIcon>, "GetApplicationControlDataWithoutIcon"},
};
// clang-format on
@ -36,7 +36,7 @@ IReadOnlyApplicationControlDataInterface::IReadOnlyApplicationControlDataInterfa
IReadOnlyApplicationControlDataInterface::~IReadOnlyApplicationControlDataInterface() = default;
Result IReadOnlyApplicationControlDataInterface::GetApplicationControlDataOld(
Result IReadOnlyApplicationControlDataInterface::GetApplicationControlData(
OutBuffer<BufferAttr_HipcMapAlias> out_buffer, Out<u32> out_actual_size,
ApplicationControlSource application_control_source, u64 application_id) {
LOG_INFO(Service_NS, "called with control_source={}, application_id={:016X}",
@ -124,8 +124,8 @@ Result IReadOnlyApplicationControlDataInterface::ConvertApplicationLanguageToLan
R_SUCCEED();
}
Result IReadOnlyApplicationControlDataInterface::GetApplicationControlData(
OutBuffer<BufferAttr_HipcMapAlias> out_buffer, Out<u32> out_actual_size,
Result IReadOnlyApplicationControlDataInterface::GetApplicationControlDataWithoutIcon(
OutBuffer<BufferAttr_HipcMapAlias> out_buffer, Out<u64> out_total_size,
ApplicationControlSource application_control_source, u64 application_id) {
LOG_INFO(Service_NS, "called with control_source={}, application_id={:016X}",
application_control_source, application_id);
@ -135,76 +135,47 @@ Result IReadOnlyApplicationControlDataInterface::GetApplicationControlData(
const auto control = pm.GetControlMetadata();
const auto size = out_buffer.size();
const auto icon_size = control.second ? control.second->GetSize() : 0;
const auto total_size = sizeof(FileSys::RawNACP) + icon_size;
// Use the caller-provided buffer capacity as the total size to return. This
// matches behavior where the caller expects a fixed-size package (NACP + icon
// area) and the icon area may be zero-padded up to the buffer size.
const auto nacp_size = sizeof(FileSys::RawNACP);
if (size < total_size) {
LOG_ERROR(Service_NS, "output buffer is too small! (actual={:016X}, expected_min=0x4000)",
size);
if (size < nacp_size) {
LOG_ERROR(Service_NS, "output buffer is too small! (actual={:016X}, expected_min={:08X})",
size, nacp_size);
R_THROW(ResultUnknown);
}
if (control.first != nullptr) {
const auto bytes = control.first->GetRawBytes();
std::memcpy(out_buffer.data(), bytes.data(), bytes.size());
const auto copy_len = (std::min)(static_cast<size_t>(bytes.size()), static_cast<size_t>(nacp_size));
std::memcpy(out_buffer.data(), bytes.data(), copy_len);
if (copy_len < nacp_size) {
std::memset(out_buffer.data() + copy_len, 0, nacp_size - copy_len);
}
} else {
LOG_WARNING(Service_NS, "missing NACP data for application_id={:016X}, defaulting to zero",
application_id);
std::memset(out_buffer.data(), 0, sizeof(FileSys::RawNACP));
}
if (control.second != nullptr) {
control.second->Read(out_buffer.data() + sizeof(FileSys::RawNACP), icon_size);
} else {
LOG_WARNING(Service_NS, "missing icon data for application_id={:016X}", application_id);
}
*out_actual_size = static_cast<u32>(total_size);
R_SUCCEED();
}
Result IReadOnlyApplicationControlDataInterface::GetApplicationControlDataWithIconSize(
OutBuffer<BufferAttr_HipcMapAlias> out_buffer,
Out<u64> out_total_size,
ApplicationControlSource application_control_source,
u64 application_id) {
LOG_INFO(Service_NS, "called with control_source={}, application_id={:016X}",
application_control_source, application_id);
constexpr size_t kExpectedBufferSize = 0x14000;
constexpr size_t kNACPSize = sizeof(FileSys::RawNACP);
constexpr size_t kMaxIconSize = kExpectedBufferSize - kNACPSize;
const FileSys::PatchManager pm{application_id, system.GetFileSystemController(),
system.GetContentProvider()};
const auto control = pm.GetControlMetadata();
const auto size = out_buffer.size();
if (size < kExpectedBufferSize) {
LOG_ERROR(Service_NS, "output buffer is too small! (actual={:016X}, required={:016X})", size, kExpectedBufferSize);
R_THROW(ResultUnknown);
}
// Copy NACP
if (control.first != nullptr) {
const auto bytes = control.first->GetRawBytes();
std::memcpy(out_buffer.data(), bytes.data(), bytes.size());
} else {
std::memset(out_buffer.data(), 0, kNACPSize);
std::memset(out_buffer.data(), 0, nacp_size);
}
// Copy icon, pad with zeros if needed
size_t icon_size = control.second ? control.second->GetSize() : 0;
if (icon_size > kMaxIconSize) {
icon_size = kMaxIconSize; // Truncate if too large
}
if (control.second != nullptr && icon_size > 0) {
control.second->Read(out_buffer.data() + kNACPSize, icon_size);
} else {
std::memset(out_buffer.data() + kNACPSize, 0, kMaxIconSize);
const auto icon_area_size = size - nacp_size;
if (icon_area_size > 0) {
if (control.second != nullptr) {
const auto icon_size = control.second->GetSize();
const auto to_copy = static_cast<size_t>((std::min)(icon_size, icon_area_size));
control.second->Read(out_buffer.data() + nacp_size, to_copy);
if (to_copy < icon_area_size) {
std::memset(out_buffer.data() + nacp_size + to_copy, 0, icon_area_size - to_copy);
}
} else {
std::memset(out_buffer.data() + nacp_size, 0, icon_area_size);
LOG_WARNING(Service_NS, "missing icon data for application_id={:016X}, zero-filling icon area",
application_id);
}
}
*out_total_size = kExpectedBufferSize;
*out_total_size = static_cast<u64>(size);
R_SUCCEED();
}

8
src/core/hle/service/ns/read_only_application_control_data_interface.h

@ -19,7 +19,7 @@ public:
explicit IReadOnlyApplicationControlDataInterface(Core::System& system_);
~IReadOnlyApplicationControlDataInterface() override;
Result GetApplicationControlDataOld(OutBuffer<BufferAttr_HipcMapAlias> out_buffer,
Result GetApplicationControlData(OutBuffer<BufferAttr_HipcMapAlias> out_buffer,
Out<u32> out_actual_size,
ApplicationControlSource application_control_source,
u64 application_id);
@ -27,11 +27,7 @@ public:
u32 supported_languages);
Result ConvertApplicationLanguageToLanguageCode(Out<u64> out_language_code,
ApplicationLanguage application_language);
Result GetApplicationControlData(OutBuffer<BufferAttr_HipcMapAlias> out_buffer,
Out<u32> out_actual_size,
ApplicationControlSource application_control_source,
u64 application_id);
Result GetApplicationControlDataWithIconSize(
Result GetApplicationControlDataWithoutIcon(
OutBuffer<BufferAttr_HipcMapAlias> out_buffer,
Out<u64> out_total_size,
ApplicationControlSource application_control_source,

1
src/qt_common/config/shared_translation.cpp

@ -47,6 +47,7 @@ std::unique_ptr<TranslationMap> InitializeTranslations(QObject* parent)
INSERT(Settings, login_share_applet_mode, tr("Login share"), QString());
INSERT(Settings, wifi_web_auth_applet_mode, tr("Wifi web auth"), QString());
INSERT(Settings, my_page_applet_mode, tr("My page"), QString());
INSERT(Settings, enable_overlay, tr("Enable Overlay Applet"), QString());
// Audio
INSERT(Settings, sink_id, tr("Output Engine:"), QString());

Loading…
Cancel
Save