mirror of
https://git.eden-emu.dev/eden-emu/eden.git
synced 2026-08-15 13:16:43 +00:00
Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| faa771646c | |||
| de59fa1ab4 | |||
| b79295c528 | |||
| c47bae4c4e | |||
| ca0eebcfe8 | |||
| 4c65780f11 |
@@ -22,9 +22,11 @@ using namespace std::literals;
|
||||
constexpr auto INCREMENT_TIME{5ms};
|
||||
|
||||
DeviceSession::DeviceSession(Core::System& system_)
|
||||
: system{system_}, thread_event{Core::Timing::CreateEvent(
|
||||
"AudioOutSampleTick",
|
||||
[this](s64 time, std::chrono::nanoseconds) { return ThreadFunc(); })} {}
|
||||
: system{system_}
|
||||
, thread_event{system_.CreateTimingEvent("AudioOutSampleTick", [this](s64 time, std::chrono::nanoseconds) {
|
||||
return ThreadFunc();
|
||||
})}
|
||||
{}
|
||||
|
||||
DeviceSession::~DeviceSession() {
|
||||
Finalize();
|
||||
|
||||
@@ -5,7 +5,11 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include <string>
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <cstring>
|
||||
#endif
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include <fmt/ranges.h>
|
||||
|
||||
@@ -208,12 +208,4 @@ UUID UUID::MakeRandomRFC4122V4() {
|
||||
return uuid;
|
||||
}
|
||||
|
||||
UUID UUID::MakeRFC4122V5(std::span<u8, 20> sha1) {
|
||||
UUID uuid{};
|
||||
std::memcpy(&uuid.uuid, sha1.data(), sizeof(UUID));
|
||||
uuid.uuid[8] = 0x80 | (uuid.uuid[8] & 0x3F);
|
||||
uuid.uuid[6] = 0x50 | (uuid.uuid[6] & 0xF);
|
||||
return uuid;
|
||||
}
|
||||
|
||||
} // namespace Common
|
||||
|
||||
+20
-16
@@ -1,6 +1,3 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
@@ -8,7 +5,6 @@
|
||||
|
||||
#include <array>
|
||||
#include <functional>
|
||||
#include <span>
|
||||
#include <string>
|
||||
|
||||
#include "common/common_types.h"
|
||||
@@ -90,20 +86,28 @@ struct UUID {
|
||||
};
|
||||
}
|
||||
|
||||
/// @brief Creates a random UUID.
|
||||
/// @returns A random UUID.
|
||||
[[nodiscard]] static UUID MakeRandom();
|
||||
/**
|
||||
* Creates a random UUID.
|
||||
*
|
||||
* @returns A random UUID.
|
||||
*/
|
||||
static UUID MakeRandom();
|
||||
|
||||
/// @brief Creates a random UUID with a seed.
|
||||
/// @param seed A seed to initialize the Mersenne-Twister RNG
|
||||
/// @returns A random UUID.
|
||||
[[nodiscard]] static UUID MakeRandomWithSeed(u32 seed);
|
||||
/**
|
||||
* Creates a random UUID with a seed.
|
||||
*
|
||||
* @param seed A seed to initialize the Mersenne-Twister RNG
|
||||
*
|
||||
* @returns A random UUID.
|
||||
*/
|
||||
static UUID MakeRandomWithSeed(u32 seed);
|
||||
|
||||
/// @brief Creates a random UUID. The generated UUID is RFC 4122 Version 4 compliant.
|
||||
/// @returns A random UUID that is RFC 4122 Version 4 compliant.
|
||||
[[nodiscard]] static UUID MakeRandomRFC4122V4();
|
||||
|
||||
[[nodiscard]] static UUID MakeRFC4122V5(std::span<u8, 20> sha1);
|
||||
/**
|
||||
* Creates a random UUID. The generated UUID is RFC 4122 Version 4 compliant.
|
||||
*
|
||||
* @returns A random UUID that is RFC 4122 Version 4 compliant.
|
||||
*/
|
||||
static UUID MakeRandomRFC4122V4();
|
||||
|
||||
friend constexpr bool operator==(const UUID& lhs, const UUID& rhs) = default;
|
||||
};
|
||||
|
||||
@@ -969,4 +969,8 @@ void System::ApplySettings() {
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<Core::Timing::EventType> System::CreateTimingEvent(std::string name, Core::Timing::TimedCallback&& callback) {
|
||||
return std::make_shared<Core::Timing::EventType>(std::move(callback), std::move(name));
|
||||
}
|
||||
|
||||
} // namespace Core
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "core/file_sys/vfs/vfs_types.h"
|
||||
#include "core/hle/service/os/event.h"
|
||||
#include "core/hle/service/kernel_helpers.h"
|
||||
#include "core/core_timing.h"
|
||||
|
||||
namespace Core::Frontend {
|
||||
class EmuWindow;
|
||||
@@ -438,6 +439,9 @@ public:
|
||||
/// Applies any changes to settings to this core instance.
|
||||
void ApplySettings();
|
||||
|
||||
std::shared_ptr<Core::Timing::EventType> CreateTimingEvent(std::string name, Core::Timing::TimedCallback&& callback);
|
||||
|
||||
private:
|
||||
struct Impl;
|
||||
std::unique_ptr<Impl> impl;
|
||||
};
|
||||
|
||||
+14
-45
@@ -23,10 +23,6 @@ namespace Core::Timing {
|
||||
|
||||
constexpr s64 MAX_SLICE_LENGTH = 10000;
|
||||
|
||||
std::shared_ptr<EventType> CreateEvent(std::string name, TimedCallback&& callback) {
|
||||
return std::make_shared<EventType>(std::move(callback), std::move(name));
|
||||
}
|
||||
|
||||
struct CoreTiming::Event {
|
||||
s64 time;
|
||||
u64 fifo_order;
|
||||
@@ -36,11 +32,10 @@ struct CoreTiming::Event {
|
||||
|
||||
// Sort by time, unless the times are the same, in which case sort by
|
||||
// the order added to the queue
|
||||
friend bool operator>(const Event& left, const Event& right) {
|
||||
friend bool operator>(const Event& left, const Event& right) noexcept {
|
||||
return std::tie(left.time, left.fifo_order) > std::tie(right.time, right.fifo_order);
|
||||
}
|
||||
|
||||
friend bool operator<(const Event& left, const Event& right) {
|
||||
friend bool operator<(const Event& left, const Event& right) noexcept {
|
||||
return std::tie(left.time, left.fifo_order) < std::tie(right.time, right.fifo_order);
|
||||
}
|
||||
};
|
||||
@@ -60,8 +55,6 @@ void CoreTiming::Initialize(std::function<void()>&& on_thread_init_) {
|
||||
Common::SetCurrentThreadName("HostTiming");
|
||||
Common::SetCurrentThreadPriority(Common::ThreadPriority::High);
|
||||
on_thread_init();
|
||||
has_started = true;
|
||||
|
||||
// base frequency in MHz: 1ns (10^-9) = 1GHz (10^9)
|
||||
while (!stop_token.stop_requested()) {
|
||||
while (!paused && !stop_token.stop_requested()) {
|
||||
@@ -77,8 +70,8 @@ void CoreTiming::Initialize(std::function<void()>&& on_thread_init_) {
|
||||
// continue.
|
||||
wait_set = true;
|
||||
event.Wait();
|
||||
wait_set = false;
|
||||
}
|
||||
wait_set = false;
|
||||
}
|
||||
paused_set = true;
|
||||
pause_event.Wait();
|
||||
@@ -144,39 +137,28 @@ void CoreTiming::ScheduleEvent(std::chrono::nanoseconds ns_into_future,
|
||||
event.Set();
|
||||
}
|
||||
|
||||
void CoreTiming::ScheduleLoopingEvent(std::chrono::nanoseconds start_time,
|
||||
std::chrono::nanoseconds resched_time,
|
||||
const std::shared_ptr<EventType>& event_type,
|
||||
bool absolute_time) {
|
||||
void CoreTiming::ScheduleLoopingEvent(std::chrono::nanoseconds start_time, std::chrono::nanoseconds resched_time, const std::shared_ptr<EventType>& event_type, bool absolute_time) {
|
||||
{
|
||||
std::scoped_lock scope{basic_lock};
|
||||
const auto next_time{absolute_time ? start_time : GetGlobalTimeNs() + start_time};
|
||||
|
||||
auto h{event_queue.emplace(
|
||||
Event{next_time.count(), event_fifo_id++, event_type, resched_time.count()})};
|
||||
auto h = event_queue.emplace(Event{next_time.count(), event_fifo_id++, event_type, resched_time.count()});
|
||||
(*h).handle = h;
|
||||
}
|
||||
|
||||
event.Set();
|
||||
}
|
||||
|
||||
void CoreTiming::UnscheduleEvent(const std::shared_ptr<EventType>& event_type,
|
||||
UnscheduleEventType type) {
|
||||
void CoreTiming::UnscheduleEvent(const std::shared_ptr<EventType>& event_type, UnscheduleEventType type) {
|
||||
{
|
||||
std::scoped_lock lk{basic_lock};
|
||||
|
||||
std::vector<heap_t::handle_type> to_remove;
|
||||
for (auto itr = event_queue.begin(); itr != event_queue.end(); itr++) {
|
||||
const Event& e = *itr;
|
||||
for (auto it = event_queue.begin(); it != event_queue.end(); it++) {
|
||||
auto const& e = *it;
|
||||
if (e.type.lock().get() == event_type.get()) {
|
||||
to_remove.push_back(itr->handle);
|
||||
to_remove.push_back(it->handle);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& h : to_remove) {
|
||||
for (auto& h : to_remove)
|
||||
event_queue.erase(h);
|
||||
}
|
||||
|
||||
event_type->sequence_number++;
|
||||
}
|
||||
|
||||
@@ -187,16 +169,15 @@ void CoreTiming::UnscheduleEvent(const std::shared_ptr<EventType>& event_type,
|
||||
}
|
||||
|
||||
static u64 GetNextTickCount(u64 next_ticks) {
|
||||
if (Settings::values.use_custom_cpu_ticks.GetValue()) {
|
||||
if (Settings::values.use_custom_cpu_ticks.GetValue())
|
||||
return Settings::values.cpu_ticks.GetValue();
|
||||
}
|
||||
return next_ticks;
|
||||
}
|
||||
|
||||
void CoreTiming::AddTicks(u64 ticks_to_add) {
|
||||
const u64 ticks = GetNextTickCount(ticks_to_add);
|
||||
cpu_ticks += ticks;
|
||||
downcount -= static_cast<s64>(ticks);
|
||||
downcount -= s64(ticks);
|
||||
}
|
||||
|
||||
void CoreTiming::Idle() {
|
||||
@@ -270,19 +251,14 @@ std::optional<s64> CoreTiming::Advance() {
|
||||
next_time = pause_end_time + next_schedule_time;
|
||||
}
|
||||
|
||||
event_queue.update(evt.handle, Event{next_time, event_fifo_id++, evt.type,
|
||||
next_schedule_time, evt.handle});
|
||||
event_queue.update(evt.handle, Event{next_time, event_fifo_id++, evt.type, next_schedule_time, evt.handle});
|
||||
}
|
||||
}
|
||||
|
||||
global_timer = GetGlobalTimeNs().count();
|
||||
}
|
||||
|
||||
if (!event_queue.empty()) {
|
||||
return event_queue.top().time;
|
||||
} else {
|
||||
return std::nullopt;
|
||||
}
|
||||
return event_queue.empty() ? std::optional<s64>{} : event_queue.top().time;
|
||||
}
|
||||
|
||||
void CoreTiming::Reset() {
|
||||
@@ -293,7 +269,6 @@ void CoreTiming::Reset() {
|
||||
timer_thread.request_stop();
|
||||
timer_thread.join();
|
||||
}
|
||||
has_started = false;
|
||||
}
|
||||
|
||||
/// @brief Returns current time in nanoseconds.
|
||||
@@ -310,10 +285,4 @@ std::chrono::microseconds CoreTiming::GetGlobalTimeUs() const noexcept {
|
||||
: std::chrono::microseconds{Common::WallClock::CPUTickToUS(cpu_ticks)};
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
void CoreTiming::SetTimerResolutionNs(std::chrono::nanoseconds ns) {
|
||||
timer_resolution_ns = ns.count();
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace Core::Timing
|
||||
|
||||
+11
-33
@@ -29,8 +29,7 @@ using TimedCallback = std::function<std::optional<std::chrono::nanoseconds>(
|
||||
|
||||
/// Contains the characteristics of a particular event.
|
||||
struct EventType {
|
||||
explicit EventType(TimedCallback&& callback_, std::string&& name_)
|
||||
: callback{std::move(callback_)}, name{std::move(name_)}, sequence_number{0} {}
|
||||
explicit EventType(TimedCallback&& callback_, std::string&& name_) : callback{std::move(callback_)}, name{std::move(name_)}, sequence_number{0} {}
|
||||
|
||||
/// The event's callback function.
|
||||
TimedCallback callback;
|
||||
@@ -90,11 +89,6 @@ public:
|
||||
/// Checks if core timing is running.
|
||||
bool IsRunning() const;
|
||||
|
||||
/// Checks if the timer thread has started.
|
||||
bool HasStarted() const {
|
||||
return has_started;
|
||||
}
|
||||
|
||||
/// Checks if there are any pending time events.
|
||||
bool HasPendingEvents() const;
|
||||
|
||||
@@ -134,45 +128,29 @@ public:
|
||||
/// Checks for events manually and returns time in nanoseconds for next event, threadsafe.
|
||||
std::optional<s64> Advance();
|
||||
|
||||
#ifdef _WIN32
|
||||
void SetTimerResolutionNs(std::chrono::nanoseconds ns);
|
||||
#endif
|
||||
|
||||
struct Event;
|
||||
|
||||
void Reset();
|
||||
|
||||
using heap_t = boost::heap::fibonacci_heap<CoreTiming::Event, boost::heap::compare<std::greater<>>>;
|
||||
Common::Event event{};
|
||||
Common::Event pause_event{};
|
||||
|
||||
alignas(64) mutable std::mutex basic_lock;
|
||||
alignas(64) std::mutex advance_lock;
|
||||
alignas(64) std::atomic<bool> paused{};
|
||||
alignas(64) std::atomic<bool> paused_set{};
|
||||
alignas(64) std::atomic<bool> wait_set{};
|
||||
std::function<void()> on_thread_init{};
|
||||
heap_t event_queue;
|
||||
std::jthread timer_thread;
|
||||
s64 global_timer = 0;
|
||||
#ifdef _WIN32
|
||||
s64 timer_resolution_ns;
|
||||
#endif
|
||||
u64 event_fifo_id = 0;
|
||||
s64 pause_end_time{};
|
||||
/// Cycle timing
|
||||
u64 cpu_ticks{};
|
||||
s64 downcount{};
|
||||
Common::Event event{};
|
||||
Common::Event pause_event{};
|
||||
std::function<void()> on_thread_init{};
|
||||
std::jthread timer_thread;
|
||||
mutable std::mutex basic_lock;
|
||||
std::mutex advance_lock;
|
||||
std::atomic<bool> paused{};
|
||||
std::atomic<bool> paused_set{};
|
||||
std::atomic<bool> wait_set{};
|
||||
std::atomic<bool> has_started{};
|
||||
bool is_multicore{};
|
||||
};
|
||||
|
||||
/// Creates a core timing event with the given name and callback.
|
||||
///
|
||||
/// @param name The name of the core timing event to create.
|
||||
/// @param callback The callback to execute for the event.
|
||||
///
|
||||
/// @returns An EventType instance representing the created event.
|
||||
///
|
||||
std::shared_ptr<EventType> CreateEvent(std::string name, TimedCallback&& callback);
|
||||
|
||||
} // namespace Core::Timing
|
||||
|
||||
@@ -274,22 +274,23 @@ public:
|
||||
explicit NACP(VirtualFile file);
|
||||
~NACP();
|
||||
|
||||
[[nodiscard]] const LanguageEntry& GetLanguageEntry() const;
|
||||
[[nodiscard]] std::string GetApplicationName() const;
|
||||
[[nodiscard]] std::string GetDeveloperName() const;
|
||||
[[nodiscard]] u64 GetTitleId() const;
|
||||
[[nodiscard]] u64 GetDLCBaseTitleId() const;
|
||||
[[nodiscard]] std::string GetVersionString() const;
|
||||
[[nodiscard]] u64 GetDefaultNormalSaveSize() const;
|
||||
[[nodiscard]] u64 GetDefaultJournalSaveSize() const;
|
||||
[[nodiscard]] u32 GetSupportedLanguages() const;
|
||||
[[nodiscard]] std::vector<std::string> GetApplicationNames() const;
|
||||
[[nodiscard]] std::vector<u8> GetRawBytes() const;
|
||||
[[nodiscard]] bool GetUserAccountSwitchLock() const;
|
||||
[[nodiscard]] u64 GetDeviceSaveDataSize() const;
|
||||
[[nodiscard]] u32 GetParentalControlFlag() const;
|
||||
[[nodiscard]] const std::array<u8, 0x20>& GetRatingAge() const;
|
||||
const LanguageEntry& GetLanguageEntry() const;
|
||||
std::string GetApplicationName() const;
|
||||
std::string GetDeveloperName() const;
|
||||
u64 GetTitleId() const;
|
||||
u64 GetDLCBaseTitleId() const;
|
||||
std::string GetVersionString() const;
|
||||
u64 GetDefaultNormalSaveSize() const;
|
||||
u64 GetDefaultJournalSaveSize() const;
|
||||
u32 GetSupportedLanguages() const;
|
||||
std::vector<std::string> GetApplicationNames() const;
|
||||
std::vector<u8> GetRawBytes() const;
|
||||
bool GetUserAccountSwitchLock() const;
|
||||
u64 GetDeviceSaveDataSize() const;
|
||||
u32 GetParentalControlFlag() const;
|
||||
const std::array<u8, 0x20>& GetRatingAge() const;
|
||||
|
||||
private:
|
||||
RawNACP raw{};
|
||||
std::vector<LanguageEntry> language_entries;
|
||||
};
|
||||
|
||||
@@ -1156,14 +1156,4 @@ PatchManager::Metadata PatchManager::ParseControlNCA(const NCA& nca) const {
|
||||
|
||||
return {std::move(nacp), icon_file};
|
||||
}
|
||||
|
||||
[[nodiscard]] PatchManager::Metadata PatchManager::GetMetadataFromBaseOrUpdate(Core::System& system, u64 application_id) noexcept {
|
||||
const FileSys::PatchManager pm{application_id, system.GetFileSystemController(), system.GetContentProvider()};
|
||||
auto metadata = pm.GetControlMetadata();
|
||||
if (metadata.first != nullptr)
|
||||
return metadata;
|
||||
const FileSys::PatchManager pm_update{FileSys::GetUpdateTitleID(application_id), system.GetFileSystemController(), system.GetContentProvider()};
|
||||
return pm_update.GetControlMetadata();
|
||||
}
|
||||
|
||||
} // namespace FileSys
|
||||
|
||||
@@ -105,9 +105,6 @@ public:
|
||||
// Version of GetControlMetadata that takes an arbitrary NCA
|
||||
[[nodiscard]] Metadata ParseControlNCA(const NCA& nca) const;
|
||||
|
||||
/// @brief Gets NACP metadata (accounting for any patches or updates)
|
||||
[[nodiscard]] static PatchManager::Metadata GetMetadataFromBaseOrUpdate(Core::System& system, u64 application_id) noexcept;
|
||||
|
||||
private:
|
||||
[[nodiscard]] std::vector<VirtualFile> CollectPatches(const std::vector<VirtualDir>& patch_dirs,
|
||||
const std::string& build_id) const;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
|
||||
@@ -13,11 +13,10 @@ namespace Kernel {
|
||||
|
||||
void KHardwareTimer::Initialize() {
|
||||
// Create the timing callback to register with CoreTiming.
|
||||
m_event_type = Core::Timing::CreateEvent("KHardwareTimer::Callback",
|
||||
[this](s64, std::chrono::nanoseconds) {
|
||||
this->DoTask();
|
||||
return std::nullopt;
|
||||
});
|
||||
m_event_type = m_kernel.System().CreateTimingEvent("KHardwareTimer::Callback", [this](s64, std::chrono::nanoseconds) {
|
||||
this->DoTask();
|
||||
return std::nullopt;
|
||||
});
|
||||
}
|
||||
|
||||
void KHardwareTimer::Finalize() {
|
||||
|
||||
@@ -255,7 +255,7 @@ struct KernelCore::Impl {
|
||||
}
|
||||
|
||||
void InitializePreemption(KernelCore& kernel) {
|
||||
preemption_event = Core::Timing::CreateEvent("PreemptionCallback", [this, &kernel](s64 time, std::chrono::nanoseconds) -> std::optional<std::chrono::nanoseconds> {
|
||||
preemption_event = system.CreateTimingEvent("PreemptionCallback", [this, &kernel](s64 time, std::chrono::nanoseconds) -> std::optional<std::chrono::nanoseconds> {
|
||||
{
|
||||
KScopedSchedulerLock lock(kernel);
|
||||
global_scheduler_context->PreemptThreads(kernel);
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include <openssl/evp.h>
|
||||
|
||||
#include "common/settings.h"
|
||||
#include "common/uuid.h"
|
||||
#include "core/file_sys/control_metadata.h"
|
||||
@@ -156,7 +154,20 @@ Result IApplicationFunctions::GetDesiredLanguage(Out<u64> out_language_code) {
|
||||
// Default to 0 (all languages supported)
|
||||
u32 supported_languages = 0;
|
||||
|
||||
const auto res = FileSys::PatchManager::GetMetadataFromBaseOrUpdate(system, m_applet->program_id);
|
||||
const auto res = [this] {
|
||||
const FileSys::PatchManager pm{m_applet->program_id, system.GetFileSystemController(),
|
||||
system.GetContentProvider()};
|
||||
auto metadata = pm.GetControlMetadata();
|
||||
if (metadata.first != nullptr) {
|
||||
return metadata;
|
||||
}
|
||||
|
||||
const FileSys::PatchManager pm_update{FileSys::GetUpdateTitleID(m_applet->program_id),
|
||||
system.GetFileSystemController(),
|
||||
system.GetContentProvider()};
|
||||
return pm_update.GetControlMetadata();
|
||||
}();
|
||||
|
||||
if (res.first != nullptr) {
|
||||
supported_languages = res.first->GetSupportedLanguages();
|
||||
}
|
||||
@@ -194,7 +205,20 @@ Result IApplicationFunctions::SetTerminateResult(Result terminate_result) {
|
||||
Result IApplicationFunctions::GetDisplayVersion(Out<DisplayVersion> out_display_version) {
|
||||
LOG_DEBUG(Service_AM, "called");
|
||||
|
||||
const auto res = FileSys::PatchManager::GetMetadataFromBaseOrUpdate(system, m_applet->program_id);
|
||||
const auto res = [this] {
|
||||
const FileSys::PatchManager pm{m_applet->program_id, system.GetFileSystemController(),
|
||||
system.GetContentProvider()};
|
||||
auto metadata = pm.GetControlMetadata();
|
||||
if (metadata.first != nullptr) {
|
||||
return metadata;
|
||||
}
|
||||
|
||||
const FileSys::PatchManager pm_update{FileSys::GetUpdateTitleID(m_applet->program_id),
|
||||
system.GetFileSystemController(),
|
||||
system.GetContentProvider()};
|
||||
return pm_update.GetControlMetadata();
|
||||
}();
|
||||
|
||||
if (res.first != nullptr) {
|
||||
const auto& version = res.first->GetVersionString();
|
||||
std::memcpy(out_display_version->string.data(), version.data(),
|
||||
@@ -323,21 +347,8 @@ Result IApplicationFunctions::NotifyRunning(Out<bool> out_became_running) {
|
||||
}
|
||||
|
||||
Result IApplicationFunctions::GetPseudoDeviceId(Out<Common::UUID> out_pseudo_device_id) {
|
||||
LOG_WARNING(Service_AM, "(stubbed)");
|
||||
|
||||
// This should be hashed with the device specific hash
|
||||
// for now this will do
|
||||
const auto res = FileSys::PatchManager::GetMetadataFromBaseOrUpdate(system, m_applet->program_id);
|
||||
u8 hash[EVP_MAX_MD_SIZE];
|
||||
unsigned int hash_len = 0;
|
||||
auto const seed = res.first->raw.seed_for_pseudo_device_id;
|
||||
EVP_MD_CTX *ctx = EVP_MD_CTX_new();
|
||||
auto const algorithm = EVP_sha1();
|
||||
EVP_DigestInit_ex(ctx, algorithm, nullptr);
|
||||
EVP_DigestUpdate(ctx, &seed, sizeof(seed));
|
||||
EVP_DigestFinal_ex(ctx, hash, &hash_len);
|
||||
EVP_MD_CTX_free(ctx);
|
||||
*out_pseudo_device_id = Common::UUID::MakeRFC4122V5(std::span<u8, 20>{hash, std::size(hash)});
|
||||
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||
*out_pseudo_device_id = {};
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
|
||||
@@ -252,7 +252,19 @@ Result ILibraryAppletSelfAccessor::GetMainAppletApplicationDesiredLanguage(
|
||||
// Default to 0 (all languages supported)
|
||||
u32 supported_languages = 0;
|
||||
|
||||
const auto res = FileSys::PatchManager::GetMetadataFromBaseOrUpdate(system, identity.application_id);
|
||||
const auto res = [this, identity] {
|
||||
const FileSys::PatchManager pm{identity.application_id, system.GetFileSystemController(),
|
||||
system.GetContentProvider()};
|
||||
auto metadata = pm.GetControlMetadata();
|
||||
if (metadata.first != nullptr) {
|
||||
return metadata;
|
||||
}
|
||||
|
||||
const FileSys::PatchManager pm_update{FileSys::GetUpdateTitleID(identity.application_id),
|
||||
system.GetFileSystemController(),
|
||||
system.GetContentProvider()};
|
||||
return pm_update.GetControlMetadata();
|
||||
}();
|
||||
|
||||
if (res.first != nullptr) {
|
||||
supported_languages = res.first->GetSupportedLanguages();
|
||||
|
||||
@@ -25,16 +25,11 @@ AlarmWorker::~AlarmWorker() {
|
||||
|
||||
void AlarmWorker::Initialize(std::shared_ptr<Service::PSC::Time::ServiceManager> time_m) {
|
||||
m_time_m = std::move(time_m);
|
||||
|
||||
m_timer_event = m_ctx.CreateEvent("Glue:AlarmWorker:TimerEvent");
|
||||
m_timer_timing_event = Core::Timing::CreateEvent(
|
||||
"Glue:AlarmWorker::AlarmTimer",
|
||||
[this](s64 time,
|
||||
std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
|
||||
m_timer_event->Signal(m_system.Kernel());
|
||||
return std::nullopt;
|
||||
});
|
||||
|
||||
m_timer_timing_event = m_system.CreateTimingEvent("Glue:AlarmWorker::AlarmTimer", [this](s64 time, std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
|
||||
m_timer_event->Signal(m_system.Kernel());
|
||||
return std::nullopt;
|
||||
});
|
||||
AttachToClosestAlarmEvent();
|
||||
}
|
||||
|
||||
|
||||
@@ -22,28 +22,19 @@ namespace Service::Glue::Time {
|
||||
|
||||
TimeWorker::TimeWorker(Core::System& system, StandardSteadyClockResource& steady_clock_resource,
|
||||
FileTimestampWorker& file_timestamp_worker)
|
||||
: m_system{system}, m_ctx{m_system, "Glue:TimeWorker"}, m_event{m_ctx.CreateEvent(
|
||||
"Glue:TimeWorker:Event")},
|
||||
: m_system{system}, m_ctx{m_system, "Glue:TimeWorker"}, m_event{m_ctx.CreateEvent("Glue:TimeWorker:Event")},
|
||||
m_steady_clock_resource{steady_clock_resource},
|
||||
m_file_timestamp_worker{file_timestamp_worker}, m_timer_steady_clock{m_ctx.CreateEvent(
|
||||
"Glue:TimeWorker:SteadyClockTimerEvent")},
|
||||
m_file_timestamp_worker{file_timestamp_worker}, m_timer_steady_clock{m_ctx.CreateEvent("Glue:TimeWorker:SteadyClockTimerEvent")},
|
||||
m_timer_file_system{m_ctx.CreateEvent("Glue:TimeWorker:FileTimeTimerEvent")},
|
||||
m_alarm_worker{m_system, m_steady_clock_resource}, m_pm_state_change_handler{m_alarm_worker} {
|
||||
m_timer_steady_clock_timing_event = Core::Timing::CreateEvent(
|
||||
"Time::SteadyClockEvent",
|
||||
[this](s64 time,
|
||||
std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
|
||||
m_timer_steady_clock->Signal(m_system.Kernel());
|
||||
return std::nullopt;
|
||||
});
|
||||
|
||||
m_timer_file_system_timing_event = Core::Timing::CreateEvent(
|
||||
"Time::SteadyClockEvent",
|
||||
[this](s64 time,
|
||||
std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
|
||||
m_timer_file_system->Signal(m_system.Kernel());
|
||||
return std::nullopt;
|
||||
});
|
||||
m_timer_steady_clock_timing_event = m_system.CreateTimingEvent("Time::SteadyClockEvent", [this](s64 time, std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
|
||||
m_timer_steady_clock->Signal(m_system.Kernel());
|
||||
return std::nullopt;
|
||||
});
|
||||
m_timer_file_system_timing_event = m_system.CreateTimingEvent("Time::SteadyClockEvent", [this](s64 time, std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
|
||||
m_timer_file_system->Signal(m_system.Kernel());
|
||||
return std::nullopt;
|
||||
});
|
||||
}
|
||||
|
||||
TimeWorker::~TimeWorker() {
|
||||
|
||||
@@ -51,17 +51,12 @@ Hidbus::Hidbus(Core::System& system_)
|
||||
RegisterHandlers(functions);
|
||||
|
||||
// Register update callbacks
|
||||
hidbus_update_event = Core::Timing::CreateEvent(
|
||||
"Hidbus::UpdateCallback",
|
||||
[this](s64 time,
|
||||
std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
|
||||
const auto guard = LockService();
|
||||
UpdateHidbus(ns_late);
|
||||
return std::nullopt;
|
||||
});
|
||||
|
||||
system_.CoreTiming().ScheduleLoopingEvent(hidbus_update_ns, hidbus_update_ns,
|
||||
hidbus_update_event);
|
||||
hidbus_update_event = system_.CreateTimingEvent("Hidbus::UpdateCallback", [this](s64 time, std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
|
||||
const auto guard = LockService();
|
||||
UpdateHidbus(ns_late);
|
||||
return std::nullopt;
|
||||
});
|
||||
system_.CoreTiming().ScheduleLoopingEvent(hidbus_update_ns, hidbus_update_ns, hidbus_update_event);
|
||||
}
|
||||
|
||||
Hidbus::~Hidbus() {
|
||||
|
||||
@@ -23,25 +23,17 @@ Conductor::Conductor(Core::System& system, Container& container, DisplayList& di
|
||||
});
|
||||
|
||||
if (system.IsMulticore()) {
|
||||
m_event = Core::Timing::CreateEvent(
|
||||
"ScreenComposition",
|
||||
[this](s64 time,
|
||||
std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
|
||||
m_signal.Set();
|
||||
return std::chrono::nanoseconds(this->GetNextTicks());
|
||||
});
|
||||
|
||||
m_event = system.CreateTimingEvent("ScreenComposition", [this](s64 time, std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
|
||||
m_signal.Set();
|
||||
return std::chrono::nanoseconds(this->GetNextTicks());
|
||||
});
|
||||
system.CoreTiming().ScheduleLoopingEvent(FrameNs, FrameNs, m_event);
|
||||
m_thread = std::jthread([this](std::stop_token token) { this->VsyncThread(token); });
|
||||
} else {
|
||||
m_event = Core::Timing::CreateEvent(
|
||||
"ScreenComposition",
|
||||
[this](s64 time,
|
||||
std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
|
||||
this->ProcessVsync();
|
||||
return std::chrono::nanoseconds(this->GetNextTicks());
|
||||
});
|
||||
|
||||
m_event = system.CreateTimingEvent("ScreenComposition", [this](s64 time, std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
|
||||
this->ProcessVsync();
|
||||
return std::chrono::nanoseconds(this->GetNextTicks());
|
||||
});
|
||||
system.CoreTiming().ScheduleLoopingEvent(FrameNs, FrameNs, m_event);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -231,12 +231,10 @@ CheatEngine::~CheatEngine() {
|
||||
}
|
||||
|
||||
void CheatEngine::Initialize() {
|
||||
event = Core::Timing::CreateEvent(
|
||||
"CheatEngine::FrameCallback::" + Common::HexToString(metadata.main_nso_build_id),
|
||||
[this](s64 time, std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
|
||||
FrameCallback(ns_late);
|
||||
return std::nullopt;
|
||||
});
|
||||
event = system.CreateTimingEvent("CheatEngine::FrameCallback::" + Common::HexToString(metadata.main_nso_build_id), [this](s64 time, std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
|
||||
FrameCallback(ns_late);
|
||||
return std::nullopt;
|
||||
});
|
||||
core_timing.ScheduleLoopingEvent(CHEAT_ENGINE_NS, CHEAT_ENGINE_NS, event);
|
||||
|
||||
metadata.process_id = system.ApplicationProcess()->GetProcessId();
|
||||
|
||||
@@ -52,14 +52,12 @@ void MemoryWriteWidth(Core::Memory::Memory& memory, u32 width, VAddr addr, u64 v
|
||||
|
||||
} // Anonymous namespace
|
||||
|
||||
Freezer::Freezer(Core::Timing::CoreTiming& core_timing_, Core::Memory::Memory& memory_)
|
||||
Freezer::Freezer(Core::System& system_, Core::Timing::CoreTiming& core_timing_, Core::Memory::Memory& memory_)
|
||||
: core_timing{core_timing_}, memory{memory_} {
|
||||
event = Core::Timing::CreateEvent("MemoryFreezer::FrameCallback",
|
||||
[this](s64 time, std::chrono::nanoseconds ns_late)
|
||||
-> std::optional<std::chrono::nanoseconds> {
|
||||
FrameCallback(ns_late);
|
||||
return std::nullopt;
|
||||
});
|
||||
event = system_.CreateTimingEvent("MemoryFreezer::FrameCallback", [this](s64 time, std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
|
||||
FrameCallback(ns_late);
|
||||
return std::nullopt;
|
||||
});
|
||||
core_timing.ScheduleEvent(memory_freezer_ns, event);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
@@ -11,14 +14,16 @@
|
||||
#include <vector>
|
||||
#include "common/common_types.h"
|
||||
|
||||
namespace Core::Timing {
|
||||
namespace Core {
|
||||
class System;
|
||||
namespace Timing {
|
||||
class CoreTiming;
|
||||
struct EventType;
|
||||
} // namespace Core::Timing
|
||||
|
||||
namespace Core::Memory {
|
||||
namespace Memory {
|
||||
class Memory;
|
||||
}
|
||||
} //namespace Core::Memory
|
||||
} //namespace Core
|
||||
|
||||
namespace Tools {
|
||||
|
||||
@@ -38,7 +43,7 @@ public:
|
||||
u64 value;
|
||||
};
|
||||
|
||||
explicit Freezer(Core::Timing::CoreTiming& core_timing_, Core::Memory::Memory& memory_);
|
||||
explicit Freezer(Core::System& system_, Core::Timing::CoreTiming& core_timing_, Core::Memory::Memory& memory_);
|
||||
~Freezer();
|
||||
|
||||
// Enables or disables the entire memory freezer.
|
||||
|
||||
@@ -56,33 +56,22 @@ ResourceManager::ResourceManager(Core::System& system_,
|
||||
applet_resource = std::make_shared<AppletResource>(system);
|
||||
|
||||
// Register update callbacks
|
||||
npad_update_event = Core::Timing::CreateEvent("HID::UpdatePadCallback",
|
||||
[this](s64 time, std::chrono::nanoseconds ns_late)
|
||||
-> std::optional<std::chrono::nanoseconds> {
|
||||
UpdateNpad(ns_late);
|
||||
return std::nullopt;
|
||||
});
|
||||
default_update_event = Core::Timing::CreateEvent(
|
||||
"HID::UpdateDefaultCallback",
|
||||
[this](s64 time,
|
||||
std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
|
||||
UpdateControllers(ns_late);
|
||||
return std::nullopt;
|
||||
});
|
||||
mouse_keyboard_update_event = Core::Timing::CreateEvent(
|
||||
"HID::UpdateMouseKeyboardCallback",
|
||||
[this](s64 time,
|
||||
std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
|
||||
UpdateMouseKeyboard(ns_late);
|
||||
return std::nullopt;
|
||||
});
|
||||
motion_update_event = Core::Timing::CreateEvent(
|
||||
"HID::UpdateMotionCallback",
|
||||
[this](s64 time,
|
||||
std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
|
||||
UpdateMotion(ns_late);
|
||||
return std::nullopt;
|
||||
});
|
||||
npad_update_event = system.CreateTimingEvent("HID::UpdatePadCallback", [this](s64 time, std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
|
||||
UpdateNpad(ns_late);
|
||||
return std::nullopt;
|
||||
});
|
||||
default_update_event = system.CreateTimingEvent("HID::UpdateDefaultCallback", [this](s64 time, std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
|
||||
UpdateControllers(ns_late);
|
||||
return std::nullopt;
|
||||
});
|
||||
mouse_keyboard_update_event = system.CreateTimingEvent("HID::UpdateMouseKeyboardCallback", [this](s64 time, std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
|
||||
UpdateMouseKeyboard(ns_late);
|
||||
return std::nullopt;
|
||||
});
|
||||
motion_update_event = system.CreateTimingEvent("HID::UpdateMotionCallback", [this](s64 time, std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
|
||||
UpdateMotion(ns_late);
|
||||
return std::nullopt;
|
||||
});
|
||||
}
|
||||
|
||||
ResourceManager::~ResourceManager() {
|
||||
@@ -267,13 +256,10 @@ void ResourceManager::InitializeTouchScreenSampler() {
|
||||
touch_screen = std::make_shared<TouchScreen>(touch_resource);
|
||||
gesture = std::make_shared<Gesture>(touch_resource);
|
||||
|
||||
touch_update_event = Core::Timing::CreateEvent(
|
||||
"HID::TouchUpdateCallback",
|
||||
[this](s64 time,
|
||||
std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
|
||||
touch_resource->OnTouchUpdate(time);
|
||||
return std::nullopt;
|
||||
});
|
||||
touch_update_event = system.CreateTimingEvent("HID::TouchUpdateCallback", [this](s64 time, std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
|
||||
touch_resource->OnTouchUpdate(time);
|
||||
return std::nullopt;
|
||||
});
|
||||
|
||||
touch_resource->SetTouchDriver(touch_driver);
|
||||
touch_resource->SetAppletResource(applet_resource, &shared_mutex);
|
||||
|
||||
@@ -266,12 +266,7 @@ void Init(QWidget* root) {
|
||||
Common::GetMemInfo().TotalPhysicalMemory / f64{1_GiB});
|
||||
LOG_INFO(Frontend, "Host Swap: {:.2f} GiB", Common::GetMemInfo().TotalSwapMemory / f64{1_GiB});
|
||||
#ifdef _WIN32
|
||||
LOG_INFO(Frontend, "Host Timer Resolution: {:.4f} ms",
|
||||
std::chrono::duration_cast<std::chrono::duration<f64, std::milli>>(
|
||||
Common::Windows::SetCurrentTimerResolutionToMaximum())
|
||||
.count());
|
||||
QtCommon::system->CoreTiming().SetTimerResolutionNs(
|
||||
Common::Windows::GetCurrentTimerResolution());
|
||||
LOG_INFO(Frontend, "Host Timer Resolution: {:.4f} ms", std::chrono::duration_cast<std::chrono::duration<f64, std::milli>>(Common::Windows::SetCurrentTimerResolutionToMaximum()).count());
|
||||
#endif
|
||||
|
||||
// Remove cached contents generated during the previous session
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: 2016 Dolphin Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
@@ -53,14 +56,15 @@ u64 TestTimerSpeed(Core::Timing::CoreTiming& core_timing) {
|
||||
} // Anonymous namespace
|
||||
|
||||
TEST_CASE("CoreTiming[BasicOrder]", "[core]") {
|
||||
Core::System system{};
|
||||
ScopeInit guard;
|
||||
auto& core_timing = guard.core_timing;
|
||||
std::vector<std::shared_ptr<Core::Timing::EventType>> events{
|
||||
Core::Timing::CreateEvent("callbackA", HostCallbackTemplate<0>),
|
||||
Core::Timing::CreateEvent("callbackB", HostCallbackTemplate<1>),
|
||||
Core::Timing::CreateEvent("callbackC", HostCallbackTemplate<2>),
|
||||
Core::Timing::CreateEvent("callbackD", HostCallbackTemplate<3>),
|
||||
Core::Timing::CreateEvent("callbackE", HostCallbackTemplate<4>),
|
||||
system.CreateTimingEvent("callbackA", HostCallbackTemplate<0>),
|
||||
system.CreateTimingEvent("callbackB", HostCallbackTemplate<1>),
|
||||
system.CreateTimingEvent("callbackC", HostCallbackTemplate<2>),
|
||||
system.CreateTimingEvent("callbackD", HostCallbackTemplate<3>),
|
||||
system.CreateTimingEvent("callbackE", HostCallbackTemplate<4>),
|
||||
};
|
||||
|
||||
expected_callback = 0;
|
||||
@@ -93,14 +97,15 @@ TEST_CASE("CoreTiming[BasicOrder]", "[core]") {
|
||||
}
|
||||
|
||||
TEST_CASE("CoreTiming[BasicOrderNoPausing]", "[core]") {
|
||||
Core::System system{};
|
||||
ScopeInit guard;
|
||||
auto& core_timing = guard.core_timing;
|
||||
std::vector<std::shared_ptr<Core::Timing::EventType>> events{
|
||||
Core::Timing::CreateEvent("callbackA", HostCallbackTemplate<0>),
|
||||
Core::Timing::CreateEvent("callbackB", HostCallbackTemplate<1>),
|
||||
Core::Timing::CreateEvent("callbackC", HostCallbackTemplate<2>),
|
||||
Core::Timing::CreateEvent("callbackD", HostCallbackTemplate<3>),
|
||||
Core::Timing::CreateEvent("callbackE", HostCallbackTemplate<4>),
|
||||
system.CreateTimingEvent("callbackA", HostCallbackTemplate<0>),
|
||||
system.CreateTimingEvent("callbackB", HostCallbackTemplate<1>),
|
||||
system.CreateTimingEvent("callbackC", HostCallbackTemplate<2>),
|
||||
system.CreateTimingEvent("callbackD", HostCallbackTemplate<3>),
|
||||
system.CreateTimingEvent("callbackE", HostCallbackTemplate<4>),
|
||||
};
|
||||
|
||||
core_timing.SyncPause(true);
|
||||
|
||||
@@ -371,7 +371,6 @@ int main(int argc, char** argv) {
|
||||
|
||||
#ifdef _WIN32
|
||||
Common::Windows::SetCurrentTimerResolutionToMaximum();
|
||||
system.CoreTiming().SetTimerResolutionNs(Common::Windows::GetCurrentTimerResolution());
|
||||
#endif
|
||||
|
||||
system.SetContentProvider(std::make_unique<FileSys::ContentProviderUnion>());
|
||||
|
||||
Reference in New Issue
Block a user