Merge branch suyu:dev into features/qol-changes
This commit is contained in:
commit
1157a4c1f9
128 changed files with 1530 additions and 499 deletions
2
externals/xbyak
vendored
2
externals/xbyak
vendored
|
@ -1 +1 @@
|
||||||
Subproject commit 9c0f5d3ecb06d2c93c2b59becb9b3b763213e74e
|
Subproject commit a1ac3750f9a639b5a6c6d6c7da4259b8d6790989
|
|
@ -8,8 +8,8 @@
|
||||||
namespace AudioCore::AudioIn {
|
namespace AudioCore::AudioIn {
|
||||||
|
|
||||||
In::In(Core::System& system_, Manager& manager_, Kernel::KEvent* event_, size_t session_id_)
|
In::In(Core::System& system_, Manager& manager_, Kernel::KEvent* event_, size_t session_id_)
|
||||||
: manager{manager_}, parent_mutex{manager.mutex}, event{event_},
|
: manager{manager_}, parent_mutex{manager.mutex}, event{event_}, system{system_, event,
|
||||||
system{system_, event, session_id_} {}
|
session_id_} {}
|
||||||
|
|
||||||
void In::Free() {
|
void In::Free() {
|
||||||
std::scoped_lock l{parent_mutex};
|
std::scoped_lock l{parent_mutex};
|
||||||
|
|
|
@ -14,8 +14,8 @@
|
||||||
namespace AudioCore::AudioIn {
|
namespace AudioCore::AudioIn {
|
||||||
|
|
||||||
System::System(Core::System& system_, Kernel::KEvent* event_, const size_t session_id_)
|
System::System(Core::System& system_, Kernel::KEvent* event_, const size_t session_id_)
|
||||||
: system{system_}, buffer_event{event_}, session_id{session_id_},
|
: system{system_}, buffer_event{event_},
|
||||||
session{std::make_unique<DeviceSession>(system_)} {}
|
session_id{session_id_}, session{std::make_unique<DeviceSession>(system_)} {}
|
||||||
|
|
||||||
System::~System() {
|
System::~System() {
|
||||||
Finalize();
|
Finalize();
|
||||||
|
|
|
@ -8,8 +8,8 @@
|
||||||
namespace AudioCore::AudioOut {
|
namespace AudioCore::AudioOut {
|
||||||
|
|
||||||
Out::Out(Core::System& system_, Manager& manager_, Kernel::KEvent* event_, size_t session_id_)
|
Out::Out(Core::System& system_, Manager& manager_, Kernel::KEvent* event_, size_t session_id_)
|
||||||
: manager{manager_}, parent_mutex{manager.mutex}, event{event_},
|
: manager{manager_}, parent_mutex{manager.mutex}, event{event_}, system{system_, event,
|
||||||
system{system_, event, session_id_} {}
|
session_id_} {}
|
||||||
|
|
||||||
void Out::Free() {
|
void Out::Free() {
|
||||||
std::scoped_lock l{parent_mutex};
|
std::scoped_lock l{parent_mutex};
|
||||||
|
|
|
@ -14,8 +14,8 @@
|
||||||
namespace AudioCore::AudioOut {
|
namespace AudioCore::AudioOut {
|
||||||
|
|
||||||
System::System(Core::System& system_, Kernel::KEvent* event_, size_t session_id_)
|
System::System(Core::System& system_, Kernel::KEvent* event_, size_t session_id_)
|
||||||
: system{system_}, buffer_event{event_}, session_id{session_id_},
|
: system{system_}, buffer_event{event_},
|
||||||
session{std::make_unique<DeviceSession>(system_)} {}
|
session_id{session_id_}, session{std::make_unique<DeviceSession>(system_)} {}
|
||||||
|
|
||||||
System::~System() {
|
System::~System() {
|
||||||
Finalize();
|
Finalize();
|
||||||
|
|
|
@ -19,9 +19,10 @@ namespace AudioCore::Renderer {
|
||||||
|
|
||||||
InfoUpdater::InfoUpdater(std::span<const u8> input_, std::span<u8> output_,
|
InfoUpdater::InfoUpdater(std::span<const u8> input_, std::span<u8> output_,
|
||||||
Kernel::KProcess* process_handle_, BehaviorInfo& behaviour_)
|
Kernel::KProcess* process_handle_, BehaviorInfo& behaviour_)
|
||||||
: input{input_.data() + sizeof(UpdateDataHeader)}, input_origin{input_},
|
: input{input_.data() + sizeof(UpdateDataHeader)},
|
||||||
output{output_.data() + sizeof(UpdateDataHeader)}, output_origin{output_},
|
input_origin{input_}, output{output_.data() + sizeof(UpdateDataHeader)},
|
||||||
in_header{reinterpret_cast<const UpdateDataHeader*>(input_origin.data())},
|
output_origin{output_}, in_header{reinterpret_cast<const UpdateDataHeader*>(
|
||||||
|
input_origin.data())},
|
||||||
out_header{reinterpret_cast<UpdateDataHeader*>(output_origin.data())},
|
out_header{reinterpret_cast<UpdateDataHeader*>(output_origin.data())},
|
||||||
expected_input_size{input_.size()}, expected_output_size{output_.size()},
|
expected_input_size{input_.size()}, expected_output_size{output_.size()},
|
||||||
process_handle{process_handle_}, behaviour{behaviour_} {
|
process_handle{process_handle_}, behaviour{behaviour_} {
|
||||||
|
|
|
@ -13,8 +13,8 @@ PoolMapper::PoolMapper(Kernel::KProcess* process_handle_, bool force_map_)
|
||||||
|
|
||||||
PoolMapper::PoolMapper(Kernel::KProcess* process_handle_, std::span<MemoryPoolInfo> pool_infos_,
|
PoolMapper::PoolMapper(Kernel::KProcess* process_handle_, std::span<MemoryPoolInfo> pool_infos_,
|
||||||
u32 pool_count_, bool force_map_)
|
u32 pool_count_, bool force_map_)
|
||||||
: process_handle{process_handle_}, pool_infos{pool_infos_.data()}, pool_count{pool_count_},
|
: process_handle{process_handle_}, pool_infos{pool_infos_.data()},
|
||||||
force_map{force_map_} {}
|
pool_count{pool_count_}, force_map{force_map_} {}
|
||||||
|
|
||||||
void PoolMapper::ClearUseState(std::span<MemoryPoolInfo> pools, const u32 count) {
|
void PoolMapper::ClearUseState(std::span<MemoryPoolInfo> pools, const u32 count) {
|
||||||
for (u32 i = 0; i < count; i++) {
|
for (u32 i = 0; i < count; i++) {
|
||||||
|
|
|
@ -136,6 +136,8 @@ add_library(common STATIC
|
||||||
string_util.cpp
|
string_util.cpp
|
||||||
string_util.h
|
string_util.h
|
||||||
swap.h
|
swap.h
|
||||||
|
telemetry.cpp
|
||||||
|
telemetry.h
|
||||||
thread.cpp
|
thread.cpp
|
||||||
thread.h
|
thread.h
|
||||||
thread_queue_list.h
|
thread_queue_list.h
|
||||||
|
|
|
@ -12,7 +12,8 @@
|
||||||
|
|
||||||
namespace Common {
|
namespace Common {
|
||||||
template <typename VaType, size_t AddressSpaceBits>
|
template <typename VaType, size_t AddressSpaceBits>
|
||||||
concept AddressSpaceValid = std::is_unsigned_v<VaType> && sizeof(VaType) * 8 >= AddressSpaceBits;
|
concept AddressSpaceValid = std::is_unsigned_v<VaType> && sizeof(VaType) * 8 >=
|
||||||
|
AddressSpaceBits;
|
||||||
|
|
||||||
struct EmptyStruct {};
|
struct EmptyStruct {};
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@ template <typename Derived, typename Base>
|
||||||
concept DerivedFrom = requires {
|
concept DerivedFrom = requires {
|
||||||
std::is_base_of_v<Base, Derived>;
|
std::is_base_of_v<Base, Derived>;
|
||||||
std::is_convertible_v<const volatile Derived*, const volatile Base*>;
|
std::is_convertible_v<const volatile Derived*, const volatile Base*>;
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: Replace with std::convertible_to when libc++ implements it.
|
// TODO: Replace with std::convertible_to when libc++ implements it.
|
||||||
template <typename From, typename To>
|
template <typename From, typename To>
|
||||||
|
|
|
@ -598,14 +598,14 @@ public:
|
||||||
template <typename G = E, std::enable_if_t<std::is_constructible_v<E, G&&>>* = nullptr,
|
template <typename G = E, std::enable_if_t<std::is_constructible_v<E, G&&>>* = nullptr,
|
||||||
std::enable_if_t<!std::is_convertible_v<G&&, E>>* = nullptr>
|
std::enable_if_t<!std::is_convertible_v<G&&, E>>* = nullptr>
|
||||||
constexpr explicit Expected(Unexpected<G>&& e) noexcept(std::is_nothrow_constructible_v<E, G&&>)
|
constexpr explicit Expected(Unexpected<G>&& e) noexcept(std::is_nothrow_constructible_v<E, G&&>)
|
||||||
: impl_base{unexpect_t{}, std::move(e.value())},
|
: impl_base{unexpect_t{}, std::move(e.value())}, ctor_base{
|
||||||
ctor_base{detail::default_constructor_tag{}} {}
|
detail::default_constructor_tag{}} {}
|
||||||
|
|
||||||
template <typename G = E, std::enable_if_t<std::is_constructible_v<E, G&&>>* = nullptr,
|
template <typename G = E, std::enable_if_t<std::is_constructible_v<E, G&&>>* = nullptr,
|
||||||
std::enable_if_t<std::is_convertible_v<G&&, E>>* = nullptr>
|
std::enable_if_t<std::is_convertible_v<G&&, E>>* = nullptr>
|
||||||
constexpr Expected(Unexpected<G>&& e) noexcept(std::is_nothrow_constructible_v<E, G&&>)
|
constexpr Expected(Unexpected<G>&& e) noexcept(std::is_nothrow_constructible_v<E, G&&>)
|
||||||
: impl_base{unexpect_t{}, std::move(e.value())},
|
: impl_base{unexpect_t{}, std::move(e.value())}, ctor_base{
|
||||||
ctor_base{detail::default_constructor_tag{}} {}
|
detail::default_constructor_tag{}} {}
|
||||||
|
|
||||||
template <typename... Args, std::enable_if_t<std::is_constructible_v<E, Args&&...>>* = nullptr>
|
template <typename... Args, std::enable_if_t<std::is_constructible_v<E, Args&&...>>* = nullptr>
|
||||||
constexpr explicit Expected(unexpect_t, Args&&... args)
|
constexpr explicit Expected(unexpect_t, Args&&... args)
|
||||||
|
|
|
@ -238,8 +238,10 @@ public:
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
concept HasRedBlackKeyType = requires {
|
concept HasRedBlackKeyType = requires {
|
||||||
{ std::is_same<typename T::RedBlackKeyType, void>::value } -> std::convertible_to<bool>;
|
{
|
||||||
};
|
std::is_same<typename T::RedBlackKeyType, void>::value
|
||||||
|
} -> std::convertible_to<bool>;
|
||||||
|
};
|
||||||
|
|
||||||
namespace impl {
|
namespace impl {
|
||||||
|
|
||||||
|
|
|
@ -25,12 +25,12 @@ public:
|
||||||
|
|
||||||
MultiLevelPageTable(MultiLevelPageTable&& other) noexcept
|
MultiLevelPageTable(MultiLevelPageTable&& other) noexcept
|
||||||
: address_space_bits{std::exchange(other.address_space_bits, 0)},
|
: address_space_bits{std::exchange(other.address_space_bits, 0)},
|
||||||
first_level_bits{std::exchange(other.first_level_bits, 0)},
|
first_level_bits{std::exchange(other.first_level_bits, 0)}, page_bits{std::exchange(
|
||||||
page_bits{std::exchange(other.page_bits, 0)},
|
other.page_bits, 0)},
|
||||||
first_level_shift{std::exchange(other.first_level_shift, 0)},
|
first_level_shift{std::exchange(other.first_level_shift, 0)},
|
||||||
first_level_chunk_size{std::exchange(other.first_level_chunk_size, 0)},
|
first_level_chunk_size{std::exchange(other.first_level_chunk_size, 0)},
|
||||||
first_level_map{std::move(other.first_level_map)},
|
first_level_map{std::move(other.first_level_map)}, base_ptr{std::exchange(other.base_ptr,
|
||||||
base_ptr{std::exchange(other.base_ptr, nullptr)} {}
|
nullptr)} {}
|
||||||
|
|
||||||
MultiLevelPageTable& operator=(MultiLevelPageTable&& other) noexcept {
|
MultiLevelPageTable& operator=(MultiLevelPageTable&& other) noexcept {
|
||||||
address_space_bits = std::exchange(other.address_space_bits, 0);
|
address_space_bits = std::exchange(other.address_space_bits, 0);
|
||||||
|
|
|
@ -20,7 +20,7 @@ template <typename T>
|
||||||
concept range = requires(T& t) {
|
concept range = requires(T& t) {
|
||||||
begin(t);
|
begin(t);
|
||||||
end(t);
|
end(t);
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
concept input_range = range<T>;
|
concept input_range = range<T>;
|
||||||
|
|
|
@ -530,9 +530,9 @@ struct Values {
|
||||||
Setting<bool> mouse_enabled{linkage, false, "mouse_enabled", Category::Controls};
|
Setting<bool> mouse_enabled{linkage, false, "mouse_enabled", Category::Controls};
|
||||||
|
|
||||||
Setting<u8, true> mouse_panning_x_sensitivity{
|
Setting<u8, true> mouse_panning_x_sensitivity{
|
||||||
linkage, 50, 1, 200, "mouse_panning_x_sensitivity", Category::Controls};
|
linkage, 50, 1, 100, "mouse_panning_x_sensitivity", Category::Controls};
|
||||||
Setting<u8, true> mouse_panning_y_sensitivity{
|
Setting<u8, true> mouse_panning_y_sensitivity{
|
||||||
linkage, 50, 1, 200, "mouse_panning_y_sensitivity", Category::Controls};
|
linkage, 50, 1, 100, "mouse_panning_y_sensitivity", Category::Controls};
|
||||||
Setting<u8, true> mouse_panning_deadzone_counterweight{
|
Setting<u8, true> mouse_panning_deadzone_counterweight{
|
||||||
linkage, 20, 0, 100, "mouse_panning_deadzone_counterweight", Category::Controls};
|
linkage, 20, 0, 100, "mouse_panning_deadzone_counterweight", Category::Controls};
|
||||||
Setting<u8, true> mouse_panning_decay_strength{
|
Setting<u8, true> mouse_panning_decay_strength{
|
||||||
|
@ -611,6 +611,7 @@ struct Values {
|
||||||
Category::Network};
|
Category::Network};
|
||||||
|
|
||||||
// WebService
|
// WebService
|
||||||
|
Setting<bool> enable_telemetry{linkage, false, "enable_telemetry", Category::WebService};
|
||||||
Setting<std::string> web_api_url{linkage, "http://74.113.97.71:3000", "web_api_url",
|
Setting<std::string> web_api_url{linkage, "http://74.113.97.71:3000", "web_api_url",
|
||||||
Category::WebService};
|
Category::WebService};
|
||||||
Setting<std::string> suyu_username{linkage, std::string(), "suyu_username",
|
Setting<std::string> suyu_username{linkage, std::string(), "suyu_username",
|
||||||
|
|
119
src/common/telemetry.cpp
Normal file
119
src/common/telemetry.cpp
Normal file
|
@ -0,0 +1,119 @@
|
||||||
|
// SPDX-FileCopyrightText: 2017 Citra Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <cstring>
|
||||||
|
#include "common/scm_rev.h"
|
||||||
|
#include "common/telemetry.h"
|
||||||
|
|
||||||
|
#ifdef ARCHITECTURE_x86_64
|
||||||
|
#include "common/x64/cpu_detect.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace Common::Telemetry {
|
||||||
|
|
||||||
|
void FieldCollection::Accept(VisitorInterface& visitor) const {
|
||||||
|
for (const auto& field : fields) {
|
||||||
|
field.second->Accept(visitor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FieldCollection::AddField(std::unique_ptr<FieldInterface> field) {
|
||||||
|
fields[field->GetName()] = std::move(field);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
void Field<T>::Accept(VisitorInterface& visitor) const {
|
||||||
|
visitor.Visit(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
template class Field<bool>;
|
||||||
|
template class Field<double>;
|
||||||
|
template class Field<float>;
|
||||||
|
template class Field<u8>;
|
||||||
|
template class Field<u16>;
|
||||||
|
template class Field<u32>;
|
||||||
|
template class Field<u64>;
|
||||||
|
template class Field<s8>;
|
||||||
|
template class Field<s16>;
|
||||||
|
template class Field<s32>;
|
||||||
|
template class Field<s64>;
|
||||||
|
template class Field<std::string>;
|
||||||
|
template class Field<const char*>;
|
||||||
|
template class Field<std::chrono::microseconds>;
|
||||||
|
|
||||||
|
void AppendBuildInfo(FieldCollection& fc) {
|
||||||
|
const bool is_git_dirty{std::strstr(Common::g_scm_desc, "dirty") != nullptr};
|
||||||
|
fc.AddField(FieldType::App, "Git_IsDirty", is_git_dirty);
|
||||||
|
fc.AddField(FieldType::App, "Git_Branch", Common::g_scm_branch);
|
||||||
|
fc.AddField(FieldType::App, "Git_Revision", Common::g_scm_rev);
|
||||||
|
fc.AddField(FieldType::App, "BuildDate", Common::g_build_date);
|
||||||
|
fc.AddField(FieldType::App, "BuildName", Common::g_build_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AppendCPUInfo(FieldCollection& fc) {
|
||||||
|
#ifdef ARCHITECTURE_x86_64
|
||||||
|
|
||||||
|
const auto& caps = Common::GetCPUCaps();
|
||||||
|
const auto add_field = [&fc](std::string_view field_name, const auto& field_value) {
|
||||||
|
fc.AddField(FieldType::UserSystem, field_name, field_value);
|
||||||
|
};
|
||||||
|
add_field("CPU_Model", caps.cpu_string);
|
||||||
|
add_field("CPU_BrandString", caps.brand_string);
|
||||||
|
|
||||||
|
add_field("CPU_Extension_x64_SSE", caps.sse);
|
||||||
|
add_field("CPU_Extension_x64_SSE2", caps.sse2);
|
||||||
|
add_field("CPU_Extension_x64_SSE3", caps.sse3);
|
||||||
|
add_field("CPU_Extension_x64_SSSE3", caps.ssse3);
|
||||||
|
add_field("CPU_Extension_x64_SSE41", caps.sse4_1);
|
||||||
|
add_field("CPU_Extension_x64_SSE42", caps.sse4_2);
|
||||||
|
|
||||||
|
add_field("CPU_Extension_x64_AVX", caps.avx);
|
||||||
|
add_field("CPU_Extension_x64_AVX_VNNI", caps.avx_vnni);
|
||||||
|
add_field("CPU_Extension_x64_AVX2", caps.avx2);
|
||||||
|
|
||||||
|
// Skylake-X/SP level AVX512, for compatibility with the previous telemetry field
|
||||||
|
add_field("CPU_Extension_x64_AVX512",
|
||||||
|
caps.avx512f && caps.avx512cd && caps.avx512vl && caps.avx512dq && caps.avx512bw);
|
||||||
|
|
||||||
|
add_field("CPU_Extension_x64_AVX512F", caps.avx512f);
|
||||||
|
add_field("CPU_Extension_x64_AVX512CD", caps.avx512cd);
|
||||||
|
add_field("CPU_Extension_x64_AVX512VL", caps.avx512vl);
|
||||||
|
add_field("CPU_Extension_x64_AVX512DQ", caps.avx512dq);
|
||||||
|
add_field("CPU_Extension_x64_AVX512BW", caps.avx512bw);
|
||||||
|
add_field("CPU_Extension_x64_AVX512BITALG", caps.avx512bitalg);
|
||||||
|
add_field("CPU_Extension_x64_AVX512VBMI", caps.avx512vbmi);
|
||||||
|
|
||||||
|
add_field("CPU_Extension_x64_AES", caps.aes);
|
||||||
|
add_field("CPU_Extension_x64_BMI1", caps.bmi1);
|
||||||
|
add_field("CPU_Extension_x64_BMI2", caps.bmi2);
|
||||||
|
add_field("CPU_Extension_x64_F16C", caps.f16c);
|
||||||
|
add_field("CPU_Extension_x64_FMA", caps.fma);
|
||||||
|
add_field("CPU_Extension_x64_FMA4", caps.fma4);
|
||||||
|
add_field("CPU_Extension_x64_GFNI", caps.gfni);
|
||||||
|
add_field("CPU_Extension_x64_INVARIANT_TSC", caps.invariant_tsc);
|
||||||
|
add_field("CPU_Extension_x64_LZCNT", caps.lzcnt);
|
||||||
|
add_field("CPU_Extension_x64_MONITORX", caps.monitorx);
|
||||||
|
add_field("CPU_Extension_x64_MOVBE", caps.movbe);
|
||||||
|
add_field("CPU_Extension_x64_PCLMULQDQ", caps.pclmulqdq);
|
||||||
|
add_field("CPU_Extension_x64_POPCNT", caps.popcnt);
|
||||||
|
add_field("CPU_Extension_x64_SHA", caps.sha);
|
||||||
|
add_field("CPU_Extension_x64_WAITPKG", caps.waitpkg);
|
||||||
|
#else
|
||||||
|
fc.AddField(FieldType::UserSystem, "CPU_Model", "Other");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void AppendOSInfo(FieldCollection& fc) {
|
||||||
|
#ifdef __APPLE__
|
||||||
|
fc.AddField(FieldType::UserSystem, "OsPlatform", "Apple");
|
||||||
|
#elif defined(_WIN32)
|
||||||
|
fc.AddField(FieldType::UserSystem, "OsPlatform", "Windows");
|
||||||
|
#elif defined(__linux__) || defined(linux) || defined(__linux)
|
||||||
|
fc.AddField(FieldType::UserSystem, "OsPlatform", "Linux");
|
||||||
|
#else
|
||||||
|
fc.AddField(FieldType::UserSystem, "OsPlatform", "Unknown");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Common::Telemetry
|
209
src/common/telemetry.h
Normal file
209
src/common/telemetry.h
Normal file
|
@ -0,0 +1,209 @@
|
||||||
|
// SPDX-FileCopyrightText: 2017 Citra Emulator Project & 2024 suyu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <chrono>
|
||||||
|
#include <map>
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
#include "common/common_funcs.h"
|
||||||
|
#include "common/common_types.h"
|
||||||
|
|
||||||
|
namespace Common::Telemetry {
|
||||||
|
|
||||||
|
/// Field type, used for grouping fields together in the final submitted telemetry log
|
||||||
|
enum class FieldType : u8 {
|
||||||
|
None = 0, ///< No specified field group
|
||||||
|
App, ///< suyu application fields (e.g. version, branch, etc.)
|
||||||
|
Session, ///< Emulated session fields (e.g. title ID, log, etc.)
|
||||||
|
Performance, ///< Emulated performance (e.g. fps, emulated CPU speed, etc.)
|
||||||
|
UserFeedback, ///< User submitted feedback (e.g. star rating, user notes, etc.)
|
||||||
|
UserConfig, ///< User configuration fields (e.g. emulated CPU core, renderer, etc.)
|
||||||
|
UserSystem, ///< User system information (e.g. host CPU type, RAM, etc.)
|
||||||
|
};
|
||||||
|
|
||||||
|
struct VisitorInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface class for telemetry data fields.
|
||||||
|
*/
|
||||||
|
class FieldInterface {
|
||||||
|
public:
|
||||||
|
virtual ~FieldInterface() = default;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Accept method for the visitor pattern.
|
||||||
|
* @param visitor Reference to the visitor that will visit this field.
|
||||||
|
*/
|
||||||
|
virtual void Accept(VisitorInterface& visitor) const = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the name of this field.
|
||||||
|
* @returns Name of this field as a string.
|
||||||
|
*/
|
||||||
|
virtual const std::string& GetName() const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a telemetry data field, i.e. a unit of data that gets logged and submitted to our
|
||||||
|
* telemetry web service.
|
||||||
|
*/
|
||||||
|
template <typename T>
|
||||||
|
class Field : public FieldInterface {
|
||||||
|
public:
|
||||||
|
SUYU_NON_COPYABLE(Field);
|
||||||
|
|
||||||
|
Field(FieldType type_, std::string_view name_, T value_)
|
||||||
|
: name(name_), type(type_), value(std::move(value_)) {}
|
||||||
|
|
||||||
|
~Field() override = default;
|
||||||
|
|
||||||
|
Field(Field&&) noexcept = default;
|
||||||
|
Field& operator=(Field&& other) noexcept = default;
|
||||||
|
|
||||||
|
void Accept(VisitorInterface& visitor) const override;
|
||||||
|
|
||||||
|
[[nodiscard]] const std::string& GetName() const override {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the type of the field.
|
||||||
|
*/
|
||||||
|
[[nodiscard]] FieldType GetType() const {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the value of the field.
|
||||||
|
*/
|
||||||
|
[[nodiscard]] const T& GetValue() const {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] bool operator==(const Field& other) const {
|
||||||
|
return (type == other.type) && (name == other.name) && (value == other.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] bool operator!=(const Field& other) const {
|
||||||
|
return !operator==(other);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string name; ///< Field name, must be unique
|
||||||
|
FieldType type{}; ///< Field type, used for grouping fields together
|
||||||
|
T value; ///< Field value
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Collection of data fields that have been logged.
|
||||||
|
*/
|
||||||
|
class FieldCollection final {
|
||||||
|
public:
|
||||||
|
SUYU_NON_COPYABLE(FieldCollection);
|
||||||
|
|
||||||
|
FieldCollection() = default;
|
||||||
|
~FieldCollection() = default;
|
||||||
|
|
||||||
|
FieldCollection(FieldCollection&&) noexcept = default;
|
||||||
|
FieldCollection& operator=(FieldCollection&&) noexcept = default;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Accept method for the visitor pattern, visits each field in the collection.
|
||||||
|
* @param visitor Reference to the visitor that will visit each field.
|
||||||
|
*/
|
||||||
|
void Accept(VisitorInterface& visitor) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new field and adds it to the field collection.
|
||||||
|
* @param type Type of the field to add.
|
||||||
|
* @param name Name of the field to add.
|
||||||
|
* @param value Value for the field to add.
|
||||||
|
*/
|
||||||
|
template <typename T>
|
||||||
|
void AddField(FieldType type, std::string_view name, T value) {
|
||||||
|
return AddField(std::make_unique<Field<T>>(type, name, std::move(value)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a new field to the field collection.
|
||||||
|
* @param field Field to add to the field collection.
|
||||||
|
*/
|
||||||
|
void AddField(std::unique_ptr<FieldInterface> field);
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::map<std::string, std::unique_ptr<FieldInterface>> fields;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Telemetry fields visitor interface class. A backend to log to a web service should implement
|
||||||
|
* this interface.
|
||||||
|
*/
|
||||||
|
struct VisitorInterface {
|
||||||
|
virtual ~VisitorInterface() = default;
|
||||||
|
|
||||||
|
virtual void Visit(const Field<bool>& field) = 0;
|
||||||
|
virtual void Visit(const Field<double>& field) = 0;
|
||||||
|
virtual void Visit(const Field<float>& field) = 0;
|
||||||
|
virtual void Visit(const Field<u8>& field) = 0;
|
||||||
|
virtual void Visit(const Field<u16>& field) = 0;
|
||||||
|
virtual void Visit(const Field<u32>& field) = 0;
|
||||||
|
virtual void Visit(const Field<u64>& field) = 0;
|
||||||
|
virtual void Visit(const Field<s8>& field) = 0;
|
||||||
|
virtual void Visit(const Field<s16>& field) = 0;
|
||||||
|
virtual void Visit(const Field<s32>& field) = 0;
|
||||||
|
virtual void Visit(const Field<s64>& field) = 0;
|
||||||
|
virtual void Visit(const Field<std::string>& field) = 0;
|
||||||
|
virtual void Visit(const Field<const char*>& field) = 0;
|
||||||
|
virtual void Visit(const Field<std::chrono::microseconds>& field) = 0;
|
||||||
|
|
||||||
|
/// Completion method, called once all fields have been visited
|
||||||
|
virtual void Complete() = 0;
|
||||||
|
virtual bool SubmitTestcase() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Empty implementation of VisitorInterface that drops all fields. Used when a functional
|
||||||
|
* backend implementation is not available.
|
||||||
|
*/
|
||||||
|
struct NullVisitor final : public VisitorInterface {
|
||||||
|
SUYU_NON_COPYABLE(NullVisitor);
|
||||||
|
|
||||||
|
NullVisitor() = default;
|
||||||
|
~NullVisitor() override = default;
|
||||||
|
|
||||||
|
void Visit(const Field<bool>& /*field*/) override {}
|
||||||
|
void Visit(const Field<double>& /*field*/) override {}
|
||||||
|
void Visit(const Field<float>& /*field*/) override {}
|
||||||
|
void Visit(const Field<u8>& /*field*/) override {}
|
||||||
|
void Visit(const Field<u16>& /*field*/) override {}
|
||||||
|
void Visit(const Field<u32>& /*field*/) override {}
|
||||||
|
void Visit(const Field<u64>& /*field*/) override {}
|
||||||
|
void Visit(const Field<s8>& /*field*/) override {}
|
||||||
|
void Visit(const Field<s16>& /*field*/) override {}
|
||||||
|
void Visit(const Field<s32>& /*field*/) override {}
|
||||||
|
void Visit(const Field<s64>& /*field*/) override {}
|
||||||
|
void Visit(const Field<std::string>& /*field*/) override {}
|
||||||
|
void Visit(const Field<const char*>& /*field*/) override {}
|
||||||
|
void Visit(const Field<std::chrono::microseconds>& /*field*/) override {}
|
||||||
|
|
||||||
|
void Complete() override {}
|
||||||
|
bool SubmitTestcase() override {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Appends build-specific information to the given FieldCollection,
|
||||||
|
/// such as branch name, revision hash, etc.
|
||||||
|
void AppendBuildInfo(FieldCollection& fc);
|
||||||
|
|
||||||
|
/// Appends CPU-specific information to the given FieldCollection,
|
||||||
|
/// such as instruction set extensions, etc.
|
||||||
|
void AppendCPUInfo(FieldCollection& fc);
|
||||||
|
|
||||||
|
/// Appends OS-specific information to the given FieldCollection,
|
||||||
|
/// such as platform name, etc.
|
||||||
|
void AppendOSInfo(FieldCollection& fc);
|
||||||
|
|
||||||
|
} // namespace Common::Telemetry
|
|
@ -105,7 +105,7 @@ template <typename T>
|
||||||
concept HasRBEntry = requires(T& t, const T& ct) {
|
concept HasRBEntry = requires(T& t, const T& ct) {
|
||||||
{ t.GetRBEntry() } -> std::same_as<RBEntry<T>&>;
|
{ t.GetRBEntry() } -> std::same_as<RBEntry<T>&>;
|
||||||
{ ct.GetRBEntry() } -> std::same_as<const RBEntry<T>&>;
|
{ ct.GetRBEntry() } -> std::same_as<const RBEntry<T>&>;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
requires HasRBEntry<T>
|
requires HasRBEntry<T>
|
||||||
|
|
|
@ -362,9 +362,7 @@ public:
|
||||||
// _DEFINE_SWIZZLER2 defines a single such function, DEFINE_SWIZZLER2 defines all of them for all
|
// _DEFINE_SWIZZLER2 defines a single such function, DEFINE_SWIZZLER2 defines all of them for all
|
||||||
// component names (x<->r) and permutations (xy<->yx)
|
// component names (x<->r) and permutations (xy<->yx)
|
||||||
#define _DEFINE_SWIZZLER2(a, b, name) \
|
#define _DEFINE_SWIZZLER2(a, b, name) \
|
||||||
[[nodiscard]] constexpr Vec2<T> name() const { \
|
[[nodiscard]] constexpr Vec2<T> name() const { return Vec2<T>(a, b); }
|
||||||
return Vec2<T>(a, b); \
|
|
||||||
}
|
|
||||||
#define DEFINE_SWIZZLER2(a, b, a2, b2, a3, b3, a4, b4) \
|
#define DEFINE_SWIZZLER2(a, b, a2, b2, a3, b3, a4, b4) \
|
||||||
_DEFINE_SWIZZLER2(a, b, a##b); \
|
_DEFINE_SWIZZLER2(a, b, a##b); \
|
||||||
_DEFINE_SWIZZLER2(a, b, a2##b2); \
|
_DEFINE_SWIZZLER2(a, b, a2##b2); \
|
||||||
|
@ -557,9 +555,7 @@ public:
|
||||||
// DEFINE_SWIZZLER2_COMP2 defines two component functions for all component names (x<->r) and
|
// DEFINE_SWIZZLER2_COMP2 defines two component functions for all component names (x<->r) and
|
||||||
// permutations (xy<->yx)
|
// permutations (xy<->yx)
|
||||||
#define _DEFINE_SWIZZLER2(a, b, name) \
|
#define _DEFINE_SWIZZLER2(a, b, name) \
|
||||||
[[nodiscard]] constexpr Vec2<T> name() const { \
|
[[nodiscard]] constexpr Vec2<T> name() const { return Vec2<T>(a, b); }
|
||||||
return Vec2<T>(a, b); \
|
|
||||||
}
|
|
||||||
#define DEFINE_SWIZZLER2_COMP1(a, a2) \
|
#define DEFINE_SWIZZLER2_COMP1(a, a2) \
|
||||||
_DEFINE_SWIZZLER2(a, a, a##a); \
|
_DEFINE_SWIZZLER2(a, a, a##a); \
|
||||||
_DEFINE_SWIZZLER2(a, a, a2##a2)
|
_DEFINE_SWIZZLER2(a, a, a2##a2)
|
||||||
|
@ -584,9 +580,7 @@ public:
|
||||||
#undef _DEFINE_SWIZZLER2
|
#undef _DEFINE_SWIZZLER2
|
||||||
|
|
||||||
#define _DEFINE_SWIZZLER3(a, b, c, name) \
|
#define _DEFINE_SWIZZLER3(a, b, c, name) \
|
||||||
[[nodiscard]] constexpr Vec3<T> name() const { \
|
[[nodiscard]] constexpr Vec3<T> name() const { return Vec3<T>(a, b, c); }
|
||||||
return Vec3<T>(a, b, c); \
|
|
||||||
}
|
|
||||||
#define DEFINE_SWIZZLER3_COMP1(a, a2) \
|
#define DEFINE_SWIZZLER3_COMP1(a, a2) \
|
||||||
_DEFINE_SWIZZLER3(a, a, a, a##a##a); \
|
_DEFINE_SWIZZLER3(a, a, a, a##a##a); \
|
||||||
_DEFINE_SWIZZLER3(a, a, a, a2##a2##a2)
|
_DEFINE_SWIZZLER3(a, a, a, a2##a2##a2)
|
||||||
|
|
|
@ -33,8 +33,8 @@ public:
|
||||||
VirtualBuffer& operator=(const VirtualBuffer&) = delete;
|
VirtualBuffer& operator=(const VirtualBuffer&) = delete;
|
||||||
|
|
||||||
VirtualBuffer(VirtualBuffer&& other) noexcept
|
VirtualBuffer(VirtualBuffer&& other) noexcept
|
||||||
: alloc_size{std::exchange(other.alloc_size, 0)},
|
: alloc_size{std::exchange(other.alloc_size, 0)}, base_ptr{std::exchange(other.base_ptr),
|
||||||
base_ptr{std::exchange(other.base_ptr), nullptr} {}
|
nullptr} {}
|
||||||
|
|
||||||
VirtualBuffer& operator=(VirtualBuffer&& other) noexcept {
|
VirtualBuffer& operator=(VirtualBuffer&& other) noexcept {
|
||||||
alloc_size = std::exchange(other.alloc_size, 0);
|
alloc_size = std::exchange(other.alloc_size, 0);
|
||||||
|
|
|
@ -8,8 +8,8 @@
|
||||||
namespace Common::X64 {
|
namespace Common::X64 {
|
||||||
|
|
||||||
NativeClock::NativeClock(u64 rdtsc_frequency_)
|
NativeClock::NativeClock(u64 rdtsc_frequency_)
|
||||||
: rdtsc_frequency{rdtsc_frequency_},
|
: rdtsc_frequency{rdtsc_frequency_}, ns_rdtsc_factor{GetFixedPoint64Factor(NsRatio::den,
|
||||||
ns_rdtsc_factor{GetFixedPoint64Factor(NsRatio::den, rdtsc_frequency)},
|
rdtsc_frequency)},
|
||||||
us_rdtsc_factor{GetFixedPoint64Factor(UsRatio::den, rdtsc_frequency)},
|
us_rdtsc_factor{GetFixedPoint64Factor(UsRatio::den, rdtsc_frequency)},
|
||||||
ms_rdtsc_factor{GetFixedPoint64Factor(MsRatio::den, rdtsc_frequency)},
|
ms_rdtsc_factor{GetFixedPoint64Factor(MsRatio::den, rdtsc_frequency)},
|
||||||
cntpct_rdtsc_factor{GetFixedPoint64Factor(CNTFRQ, rdtsc_frequency)},
|
cntpct_rdtsc_factor{GetFixedPoint64Factor(CNTFRQ, rdtsc_frequency)},
|
||||||
|
|
|
@ -1136,6 +1136,8 @@ add_library(core STATIC
|
||||||
precompiled_headers.h
|
precompiled_headers.h
|
||||||
reporter.cpp
|
reporter.cpp
|
||||||
reporter.h
|
reporter.h
|
||||||
|
telemetry_session.cpp
|
||||||
|
telemetry_session.h
|
||||||
tools/freezer.cpp
|
tools/freezer.cpp
|
||||||
tools/freezer.h
|
tools/freezer.h
|
||||||
tools/renderdoc.cpp
|
tools/renderdoc.cpp
|
||||||
|
|
|
@ -16,8 +16,8 @@ using namespace Common::Literals;
|
||||||
class DynarmicCallbacks32 : public Dynarmic::A32::UserCallbacks {
|
class DynarmicCallbacks32 : public Dynarmic::A32::UserCallbacks {
|
||||||
public:
|
public:
|
||||||
explicit DynarmicCallbacks32(ArmDynarmic32& parent, Kernel::KProcess* process)
|
explicit DynarmicCallbacks32(ArmDynarmic32& parent, Kernel::KProcess* process)
|
||||||
: m_parent{parent}, m_memory(process->GetMemory()), m_process(process),
|
: m_parent{parent}, m_memory(process->GetMemory()),
|
||||||
m_debugger_enabled{parent.m_system.DebuggerEnabled()},
|
m_process(process), m_debugger_enabled{parent.m_system.DebuggerEnabled()},
|
||||||
m_check_memory_access{m_debugger_enabled ||
|
m_check_memory_access{m_debugger_enabled ||
|
||||||
!Settings::values.cpuopt_ignore_memory_aborts.GetValue()} {}
|
!Settings::values.cpuopt_ignore_memory_aborts.GetValue()} {}
|
||||||
|
|
||||||
|
|
|
@ -16,8 +16,8 @@ using namespace Common::Literals;
|
||||||
class DynarmicCallbacks64 : public Dynarmic::A64::UserCallbacks {
|
class DynarmicCallbacks64 : public Dynarmic::A64::UserCallbacks {
|
||||||
public:
|
public:
|
||||||
explicit DynarmicCallbacks64(ArmDynarmic64& parent, Kernel::KProcess* process)
|
explicit DynarmicCallbacks64(ArmDynarmic64& parent, Kernel::KProcess* process)
|
||||||
: m_parent{parent}, m_memory(process->GetMemory()), m_process(process),
|
: m_parent{parent}, m_memory(process->GetMemory()),
|
||||||
m_debugger_enabled{parent.m_system.DebuggerEnabled()},
|
m_process(process), m_debugger_enabled{parent.m_system.DebuggerEnabled()},
|
||||||
m_check_memory_access{m_debugger_enabled ||
|
m_check_memory_access{m_debugger_enabled ||
|
||||||
!Settings::values.cpuopt_ignore_memory_aborts.GetValue()} {}
|
!Settings::values.cpuopt_ignore_memory_aborts.GetValue()} {}
|
||||||
|
|
||||||
|
|
|
@ -55,6 +55,7 @@
|
||||||
#include "core/memory/cheat_engine.h"
|
#include "core/memory/cheat_engine.h"
|
||||||
#include "core/perf_stats.h"
|
#include "core/perf_stats.h"
|
||||||
#include "core/reporter.h"
|
#include "core/reporter.h"
|
||||||
|
#include "core/telemetry_session.h"
|
||||||
#include "core/tools/freezer.h"
|
#include "core/tools/freezer.h"
|
||||||
#include "core/tools/renderdoc.h"
|
#include "core/tools/renderdoc.h"
|
||||||
#include "hid_core/hid_core.h"
|
#include "hid_core/hid_core.h"
|
||||||
|
@ -271,6 +272,8 @@ struct System::Impl {
|
||||||
}
|
}
|
||||||
|
|
||||||
SystemResultStatus SetupForApplicationProcess(System& system, Frontend::EmuWindow& emu_window) {
|
SystemResultStatus SetupForApplicationProcess(System& system, Frontend::EmuWindow& emu_window) {
|
||||||
|
telemetry_session = std::make_unique<Core::TelemetrySession>();
|
||||||
|
|
||||||
host1x_core = std::make_unique<Tegra::Host1x::Host1x>(system);
|
host1x_core = std::make_unique<Tegra::Host1x::Host1x>(system);
|
||||||
gpu_core = VideoCore::CreateGPU(emu_window, system);
|
gpu_core = VideoCore::CreateGPU(emu_window, system);
|
||||||
if (!gpu_core) {
|
if (!gpu_core) {
|
||||||
|
@ -351,6 +354,8 @@ struct System::Impl {
|
||||||
return init_result;
|
return init_result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
telemetry_session->AddInitialInfo(*app_loader, fs_controller, *content_provider);
|
||||||
|
|
||||||
// Initialize cheat engine
|
// Initialize cheat engine
|
||||||
if (cheat_engine) {
|
if (cheat_engine) {
|
||||||
cheat_engine->Initialize();
|
cheat_engine->Initialize();
|
||||||
|
@ -396,6 +401,21 @@ struct System::Impl {
|
||||||
void ShutdownMainProcess() {
|
void ShutdownMainProcess() {
|
||||||
SetShuttingDown(true);
|
SetShuttingDown(true);
|
||||||
|
|
||||||
|
// Log last frame performance stats if game was loaded
|
||||||
|
if (perf_stats) {
|
||||||
|
const auto perf_results = GetAndResetPerfStats();
|
||||||
|
constexpr auto performance = Common::Telemetry::FieldType::Performance;
|
||||||
|
|
||||||
|
telemetry_session->AddField(performance, "Shutdown_EmulationSpeed",
|
||||||
|
perf_results.emulation_speed * 100.0);
|
||||||
|
telemetry_session->AddField(performance, "Shutdown_Framerate",
|
||||||
|
perf_results.average_game_fps);
|
||||||
|
telemetry_session->AddField(performance, "Shutdown_Frametime",
|
||||||
|
perf_results.frametime * 1000.0);
|
||||||
|
telemetry_session->AddField(performance, "Mean_Frametime_MS",
|
||||||
|
perf_stats->GetMeanFrametime());
|
||||||
|
}
|
||||||
|
|
||||||
is_powered_on = false;
|
is_powered_on = false;
|
||||||
exit_locked = false;
|
exit_locked = false;
|
||||||
exit_requested = false;
|
exit_requested = false;
|
||||||
|
@ -414,6 +434,7 @@ struct System::Impl {
|
||||||
service_manager.reset();
|
service_manager.reset();
|
||||||
fs_controller.Reset();
|
fs_controller.Reset();
|
||||||
cheat_engine.reset();
|
cheat_engine.reset();
|
||||||
|
telemetry_session.reset();
|
||||||
core_timing.ClearPendingEvents();
|
core_timing.ClearPendingEvents();
|
||||||
app_loader.reset();
|
app_loader.reset();
|
||||||
audio_core.reset();
|
audio_core.reset();
|
||||||
|
@ -513,6 +534,9 @@ struct System::Impl {
|
||||||
/// Services
|
/// Services
|
||||||
std::unique_ptr<Service::Services> services;
|
std::unique_ptr<Service::Services> services;
|
||||||
|
|
||||||
|
/// Telemetry session for this emulation session
|
||||||
|
std::unique_ptr<Core::TelemetrySession> telemetry_session;
|
||||||
|
|
||||||
/// Network instance
|
/// Network instance
|
||||||
Network::NetworkInstance network_instance;
|
Network::NetworkInstance network_instance;
|
||||||
|
|
||||||
|
@ -639,6 +663,14 @@ PerfStatsResults System::GetAndResetPerfStats() {
|
||||||
return impl->GetAndResetPerfStats();
|
return impl->GetAndResetPerfStats();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TelemetrySession& System::TelemetrySession() {
|
||||||
|
return *impl->telemetry_session;
|
||||||
|
}
|
||||||
|
|
||||||
|
const TelemetrySession& System::TelemetrySession() const {
|
||||||
|
return *impl->telemetry_session;
|
||||||
|
}
|
||||||
|
|
||||||
Kernel::PhysicalCore& System::CurrentPhysicalCore() {
|
Kernel::PhysicalCore& System::CurrentPhysicalCore() {
|
||||||
return impl->kernel.CurrentPhysicalCore();
|
return impl->kernel.CurrentPhysicalCore();
|
||||||
}
|
}
|
||||||
|
|
|
@ -122,6 +122,7 @@ class GPUDirtyMemoryManager;
|
||||||
class PerfStats;
|
class PerfStats;
|
||||||
class Reporter;
|
class Reporter;
|
||||||
class SpeedLimiter;
|
class SpeedLimiter;
|
||||||
|
class TelemetrySession;
|
||||||
|
|
||||||
struct PerfStatsResults;
|
struct PerfStatsResults;
|
||||||
|
|
||||||
|
@ -217,6 +218,12 @@ public:
|
||||||
*/
|
*/
|
||||||
[[nodiscard]] bool IsPoweredOn() const;
|
[[nodiscard]] bool IsPoweredOn() const;
|
||||||
|
|
||||||
|
/// Gets a reference to the telemetry session for this emulation session.
|
||||||
|
[[nodiscard]] Core::TelemetrySession& TelemetrySession();
|
||||||
|
|
||||||
|
/// Gets a reference to the telemetry session for this emulation session.
|
||||||
|
[[nodiscard]] const Core::TelemetrySession& TelemetrySession() const;
|
||||||
|
|
||||||
/// Prepare the core emulation for a reschedule
|
/// Prepare the core emulation for a reschedule
|
||||||
void PrepareReschedule(u32 core_index);
|
void PrepareReschedule(u32 core_index);
|
||||||
|
|
||||||
|
|
|
@ -29,8 +29,8 @@ constexpr std::array partition_names{
|
||||||
|
|
||||||
XCI::XCI(VirtualFile file_, u64 program_id, size_t program_index)
|
XCI::XCI(VirtualFile file_, u64 program_id, size_t program_index)
|
||||||
: file(std::move(file_)), program_nca_status{Loader::ResultStatus::ErrorXCIMissingProgramNCA},
|
: file(std::move(file_)), program_nca_status{Loader::ResultStatus::ErrorXCIMissingProgramNCA},
|
||||||
partitions(partition_names.size()), partitions_raw(partition_names.size()),
|
partitions(partition_names.size()),
|
||||||
keys{Core::Crypto::KeyManager::Instance()} {
|
partitions_raw(partition_names.size()), keys{Core::Crypto::KeyManager::Instance()} {
|
||||||
const auto header_status = TryReadHeader();
|
const auto header_status = TryReadHeader();
|
||||||
if (header_status != Loader::ResultStatus::Success) {
|
if (header_status != Loader::ResultStatus::Success) {
|
||||||
status = header_status;
|
status = header_status;
|
||||||
|
|
|
@ -91,12 +91,8 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
#define DECLARE_PATH_FLAG_HANDLER(__WHICH__) \
|
#define DECLARE_PATH_FLAG_HANDLER(__WHICH__) \
|
||||||
constexpr bool Is##__WHICH__##Allowed() const { \
|
constexpr bool Is##__WHICH__##Allowed() const { return (m_value & __WHICH__##Flag) != 0; } \
|
||||||
return (m_value & __WHICH__##Flag) != 0; \
|
constexpr void Allow##__WHICH__() { m_value |= __WHICH__##Flag; }
|
||||||
} \
|
|
||||||
constexpr void Allow##__WHICH__() { \
|
|
||||||
m_value |= __WHICH__##Flag; \
|
|
||||||
}
|
|
||||||
|
|
||||||
DECLARE_PATH_FLAG_HANDLER(WindowsPath)
|
DECLARE_PATH_FLAG_HANDLER(WindowsPath)
|
||||||
DECLARE_PATH_FLAG_HANDLER(RelativePath)
|
DECLARE_PATH_FLAG_HANDLER(RelativePath)
|
||||||
|
|
|
@ -19,9 +19,9 @@
|
||||||
namespace FileSys {
|
namespace FileSys {
|
||||||
|
|
||||||
NSP::NSP(VirtualFile file_, u64 title_id_, std::size_t program_index_)
|
NSP::NSP(VirtualFile file_, u64 title_id_, std::size_t program_index_)
|
||||||
: file(std::move(file_)), expected_program_id(title_id_), program_index(program_index_),
|
: file(std::move(file_)), expected_program_id(title_id_),
|
||||||
status{Loader::ResultStatus::Success}, pfs(std::make_shared<PartitionFilesystem>(file)),
|
program_index(program_index_), status{Loader::ResultStatus::Success},
|
||||||
keys{Core::Crypto::KeyManager::Instance()} {
|
pfs(std::make_shared<PartitionFilesystem>(file)), keys{Core::Crypto::KeyManager::Instance()} {
|
||||||
if (pfs->GetStatus() != Loader::ResultStatus::Success) {
|
if (pfs->GetStatus() != Loader::ResultStatus::Success) {
|
||||||
status = pfs->GetStatus();
|
status = pfs->GetStatus();
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -44,8 +44,8 @@ static bool CalculateHMAC256(Destination* out, const SourceKey* key, std::size_t
|
||||||
}
|
}
|
||||||
|
|
||||||
NAX::NAX(VirtualFile file_)
|
NAX::NAX(VirtualFile file_)
|
||||||
: header(std::make_unique<NAXHeader>()), file(std::move(file_)),
|
: header(std::make_unique<NAXHeader>()),
|
||||||
keys{Core::Crypto::KeyManager::Instance()} {
|
file(std::move(file_)), keys{Core::Crypto::KeyManager::Instance()} {
|
||||||
std::string path = Common::FS::SanitizePath(file->GetFullPath());
|
std::string path = Common::FS::SanitizePath(file->GetFullPath());
|
||||||
static const std::regex nax_path_regex("/registered/(000000[0-9A-F]{2})/([0-9A-F]{32})\\.nca",
|
static const std::regex nax_path_regex("/registered/(000000[0-9A-F]{2})/([0-9A-F]{32})\\.nca",
|
||||||
std::regex_constants::ECMAScript |
|
std::regex_constants::ECMAScript |
|
||||||
|
@ -62,8 +62,8 @@ NAX::NAX(VirtualFile file_)
|
||||||
}
|
}
|
||||||
|
|
||||||
NAX::NAX(VirtualFile file_, std::array<u8, 0x10> nca_id)
|
NAX::NAX(VirtualFile file_, std::array<u8, 0x10> nca_id)
|
||||||
: header(std::make_unique<NAXHeader>()), file(std::move(file_)),
|
: header(std::make_unique<NAXHeader>()),
|
||||||
keys{Core::Crypto::KeyManager::Instance()} {
|
file(std::move(file_)), keys{Core::Crypto::KeyManager::Instance()} {
|
||||||
Core::Crypto::SHA256Hash hash{};
|
Core::Crypto::SHA256Hash hash{};
|
||||||
mbedtls_sha256_ret(nca_id.data(), nca_id.size(), hash.data(), 0);
|
mbedtls_sha256_ret(nca_id.data(), nca_id.size(), hash.data(), 0);
|
||||||
status = Parse(fmt::format("/registered/000000{:02X}/{}.nca", hash[0],
|
status = Parse(fmt::format("/registered/000000{:02X}/{}.nca", hash[0],
|
||||||
|
|
|
@ -24,9 +24,7 @@ private:
|
||||||
friend class ::Kernel::KClassTokenGenerator; \
|
friend class ::Kernel::KClassTokenGenerator; \
|
||||||
static constexpr inline auto ObjectType = ::Kernel::KClassTokenGenerator::ObjectType::CLASS; \
|
static constexpr inline auto ObjectType = ::Kernel::KClassTokenGenerator::ObjectType::CLASS; \
|
||||||
static constexpr inline const char* const TypeName = #CLASS; \
|
static constexpr inline const char* const TypeName = #CLASS; \
|
||||||
static constexpr inline ClassTokenType ClassToken() { \
|
static constexpr inline ClassTokenType ClassToken() { return ::Kernel::ClassToken<CLASS>; } \
|
||||||
return ::Kernel::ClassToken<CLASS>; \
|
|
||||||
} \
|
|
||||||
\
|
\
|
||||||
public: \
|
public: \
|
||||||
SUYU_NON_COPYABLE(CLASS); \
|
SUYU_NON_COPYABLE(CLASS); \
|
||||||
|
@ -37,15 +35,9 @@ public:
|
||||||
constexpr ClassTokenType Token = ClassToken(); \
|
constexpr ClassTokenType Token = ClassToken(); \
|
||||||
return TypeObj(TypeName, Token); \
|
return TypeObj(TypeName, Token); \
|
||||||
} \
|
} \
|
||||||
static constexpr const char* GetStaticTypeName() { \
|
static constexpr const char* GetStaticTypeName() { return TypeName; } \
|
||||||
return TypeName; \
|
virtual TypeObj GetTypeObj() ATTRIBUTE { return GetStaticTypeObj(); } \
|
||||||
} \
|
virtual const char* GetTypeName() ATTRIBUTE { return GetStaticTypeName(); } \
|
||||||
virtual TypeObj GetTypeObj() ATTRIBUTE { \
|
|
||||||
return GetStaticTypeObj(); \
|
|
||||||
} \
|
|
||||||
virtual const char* GetTypeName() ATTRIBUTE { \
|
|
||||||
return GetStaticTypeName(); \
|
|
||||||
} \
|
|
||||||
\
|
\
|
||||||
private: \
|
private: \
|
||||||
constexpr bool operator!=(const TypeObj& rhs)
|
constexpr bool operator!=(const TypeObj& rhs)
|
||||||
|
|
|
@ -128,8 +128,8 @@ KVirtualAddress KMemoryRegionTree::GetRandomAlignedRegion(size_t size, size_t al
|
||||||
|
|
||||||
KMemoryLayout::KMemoryLayout()
|
KMemoryLayout::KMemoryLayout()
|
||||||
: m_virtual_tree{m_memory_region_allocator}, m_physical_tree{m_memory_region_allocator},
|
: m_virtual_tree{m_memory_region_allocator}, m_physical_tree{m_memory_region_allocator},
|
||||||
m_virtual_linear_tree{m_memory_region_allocator},
|
m_virtual_linear_tree{m_memory_region_allocator}, m_physical_linear_tree{
|
||||||
m_physical_linear_tree{m_memory_region_allocator} {}
|
m_memory_region_allocator} {}
|
||||||
|
|
||||||
void KMemoryLayout::InitializeLinearMemoryRegionTrees(KPhysicalAddress aligned_linear_phys_start,
|
void KMemoryLayout::InitializeLinearMemoryRegionTrees(KPhysicalAddress aligned_linear_phys_start,
|
||||||
KVirtualAddress linear_virtual_start) {
|
KVirtualAddress linear_virtual_start) {
|
||||||
|
|
|
@ -17,32 +17,38 @@ namespace Kernel {
|
||||||
class KThread;
|
class KThread;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
concept KPriorityQueueAffinityMask = !std::is_reference_v<T> && requires(T& t) {
|
concept KPriorityQueueAffinityMask = !
|
||||||
|
std::is_reference_v<T>&& requires(T& t) {
|
||||||
{ t.GetAffinityMask() } -> Common::ConvertibleTo<u64>;
|
{ t.GetAffinityMask() } -> Common::ConvertibleTo<u64>;
|
||||||
{ t.SetAffinityMask(0) };
|
{ t.SetAffinityMask(0) };
|
||||||
|
|
||||||
{ t.GetAffinity(0) } -> std::same_as<bool>;
|
{ t.GetAffinity(0) } -> std::same_as<bool>;
|
||||||
{ t.SetAffinity(0, false) };
|
{ t.SetAffinity(0, false) };
|
||||||
{ t.SetAll() };
|
{ t.SetAll() };
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
concept KPriorityQueueMember = !std::is_reference_v<T> && requires(T& t) {
|
concept KPriorityQueueMember = !
|
||||||
|
std::is_reference_v<T>&& requires(T& t) {
|
||||||
{ typename T::QueueEntry() };
|
{ typename T::QueueEntry() };
|
||||||
{ (typename T::QueueEntry()).Initialize() };
|
{ (typename T::QueueEntry()).Initialize() };
|
||||||
{ (typename T::QueueEntry()).SetPrev(std::addressof(t)) };
|
{ (typename T::QueueEntry()).SetPrev(std::addressof(t)) };
|
||||||
{ (typename T::QueueEntry()).SetNext(std::addressof(t)) };
|
{ (typename T::QueueEntry()).SetNext(std::addressof(t)) };
|
||||||
{ (typename T::QueueEntry()).GetNext() } -> std::same_as<T*>;
|
{ (typename T::QueueEntry()).GetNext() } -> std::same_as<T*>;
|
||||||
{ (typename T::QueueEntry()).GetPrev() } -> std::same_as<T*>;
|
{ (typename T::QueueEntry()).GetPrev() } -> std::same_as<T*>;
|
||||||
{ t.GetPriorityQueueEntry(0) } -> std::same_as<typename T::QueueEntry&>;
|
{
|
||||||
|
t.GetPriorityQueueEntry(0)
|
||||||
|
} -> std::same_as<typename T::QueueEntry&>;
|
||||||
|
|
||||||
{ t.GetAffinityMask() };
|
{ t.GetAffinityMask() };
|
||||||
{ std::remove_cvref_t<decltype(t.GetAffinityMask())>() } -> KPriorityQueueAffinityMask;
|
{
|
||||||
|
std::remove_cvref_t<decltype(t.GetAffinityMask())>()
|
||||||
|
} -> KPriorityQueueAffinityMask;
|
||||||
|
|
||||||
{ t.GetActiveCore() } -> Common::ConvertibleTo<s32>;
|
{ t.GetActiveCore() } -> Common::ConvertibleTo<s32>;
|
||||||
{ t.GetPriority() } -> Common::ConvertibleTo<s32>;
|
{ t.GetPriority() } -> Common::ConvertibleTo<s32>;
|
||||||
{ t.IsDummyThread() } -> Common::ConvertibleTo<bool>;
|
{ t.IsDummyThread() } -> Common::ConvertibleTo<bool>;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Member, size_t NumCores_, int LowestPriority, int HighestPriority>
|
template <typename Member, size_t NumCores_, int LowestPriority, int HighestPriority>
|
||||||
requires KPriorityQueueMember<Member>
|
requires KPriorityQueueMember<Member>
|
||||||
|
|
|
@ -10,10 +10,11 @@
|
||||||
namespace Kernel {
|
namespace Kernel {
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
concept KLockable = !std::is_reference_v<T> && requires(T& t) {
|
concept KLockable = !
|
||||||
|
std::is_reference_v<T>&& requires(T& t) {
|
||||||
{ t.Lock() } -> std::same_as<void>;
|
{ t.Lock() } -> std::same_as<void>;
|
||||||
{ t.Unlock() } -> std::same_as<void>;
|
{ t.Unlock() } -> std::same_as<void>;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
requires KLockable<T>
|
requires KLockable<T>
|
||||||
|
|
|
@ -458,13 +458,9 @@ constexpr inline Result __TmpCurrentResultReference = ResultSuccess;
|
||||||
if (true)
|
if (true)
|
||||||
|
|
||||||
#define R_CONVERT(catch_type, convert_type) \
|
#define R_CONVERT(catch_type, convert_type) \
|
||||||
R_CATCH(catch_type) { \
|
R_CATCH(catch_type) { R_THROW(static_cast<Result>(convert_type)); }
|
||||||
R_THROW(static_cast<Result>(convert_type)); \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define R_CONVERT_ALL(convert_type) \
|
#define R_CONVERT_ALL(convert_type) \
|
||||||
R_CATCH_ALL() { \
|
R_CATCH_ALL() { R_THROW(static_cast<Result>(convert_type)); }
|
||||||
R_THROW(static_cast<Result>(convert_type)); \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define R_ASSERT(res_expr) ASSERT(R_SUCCEEDED(res_expr))
|
#define R_ASSERT(res_expr) ASSERT(R_SUCCEEDED(res_expr))
|
||||||
|
|
|
@ -1028,8 +1028,8 @@ void Module::Interface::TrySelectUserWithoutInteraction(HLERequestContext& ctx)
|
||||||
Module::Interface::Interface(std::shared_ptr<Module> module_,
|
Module::Interface::Interface(std::shared_ptr<Module> module_,
|
||||||
std::shared_ptr<ProfileManager> profile_manager_,
|
std::shared_ptr<ProfileManager> profile_manager_,
|
||||||
Core::System& system_, const char* name)
|
Core::System& system_, const char* name)
|
||||||
: ServiceFramework{system_, name}, module{std::move(module_)},
|
: ServiceFramework{system_, name}, module{std::move(module_)}, profile_manager{std::move(
|
||||||
profile_manager{std::move(profile_manager_)} {}
|
profile_manager_)} {}
|
||||||
|
|
||||||
Module::Interface::~Interface() = default;
|
Module::Interface::~Interface() = default;
|
||||||
|
|
||||||
|
|
|
@ -18,8 +18,9 @@ namespace Service::AM::Frontend {
|
||||||
|
|
||||||
Cabinet::Cabinet(Core::System& system_, std::shared_ptr<Applet> applet_,
|
Cabinet::Cabinet(Core::System& system_, std::shared_ptr<Applet> applet_,
|
||||||
LibraryAppletMode applet_mode_, const Core::Frontend::CabinetApplet& frontend_)
|
LibraryAppletMode applet_mode_, const Core::Frontend::CabinetApplet& frontend_)
|
||||||
: FrontendApplet{system_, applet_, applet_mode_}, frontend{frontend_},
|
: FrontendApplet{system_, applet_, applet_mode_}, frontend{frontend_}, service_context{
|
||||||
service_context{system_, "CabinetApplet"} {
|
system_,
|
||||||
|
"CabinetApplet"} {
|
||||||
|
|
||||||
availability_change_event =
|
availability_change_event =
|
||||||
service_context.CreateEvent("CabinetApplet:AvailabilityChangeEvent");
|
service_context.CreateEvent("CabinetApplet:AvailabilityChangeEvent");
|
||||||
|
|
|
@ -18,8 +18,8 @@ namespace Service::AM {
|
||||||
|
|
||||||
IApplicationProxy::IApplicationProxy(Core::System& system_, std::shared_ptr<Applet> applet,
|
IApplicationProxy::IApplicationProxy(Core::System& system_, std::shared_ptr<Applet> applet,
|
||||||
Kernel::KProcess* process, WindowSystem& window_system)
|
Kernel::KProcess* process, WindowSystem& window_system)
|
||||||
: ServiceFramework{system_, "IApplicationProxy"}, m_window_system{window_system},
|
: ServiceFramework{system_, "IApplicationProxy"},
|
||||||
m_process{process}, m_applet{std::move(applet)} {
|
m_window_system{window_system}, m_process{process}, m_applet{std::move(applet)} {
|
||||||
// clang-format off
|
// clang-format off
|
||||||
static const FunctionInfo functions[] = {
|
static const FunctionInfo functions[] = {
|
||||||
{0, D<&IApplicationProxy::GetCommonStateGetter>, "GetCommonStateGetter"},
|
{0, D<&IApplicationProxy::GetCommonStateGetter>, "GetCommonStateGetter"},
|
||||||
|
|
|
@ -165,8 +165,8 @@ std::shared_ptr<ILibraryAppletAccessor> CreateFrontendApplet(Core::System& syste
|
||||||
|
|
||||||
ILibraryAppletCreator::ILibraryAppletCreator(Core::System& system_, std::shared_ptr<Applet> applet,
|
ILibraryAppletCreator::ILibraryAppletCreator(Core::System& system_, std::shared_ptr<Applet> applet,
|
||||||
WindowSystem& window_system)
|
WindowSystem& window_system)
|
||||||
: ServiceFramework{system_, "ILibraryAppletCreator"}, m_window_system{window_system},
|
: ServiceFramework{system_, "ILibraryAppletCreator"},
|
||||||
m_applet{std::move(applet)} {
|
m_window_system{window_system}, m_applet{std::move(applet)} {
|
||||||
static const FunctionInfo functions[] = {
|
static const FunctionInfo functions[] = {
|
||||||
{0, D<&ILibraryAppletCreator::CreateLibraryApplet>, "CreateLibraryApplet"},
|
{0, D<&ILibraryAppletCreator::CreateLibraryApplet>, "CreateLibraryApplet"},
|
||||||
{1, nullptr, "TerminateAllLibraryApplets"},
|
{1, nullptr, "TerminateAllLibraryApplets"},
|
||||||
|
|
|
@ -20,8 +20,8 @@ namespace Service::AM {
|
||||||
|
|
||||||
ILibraryAppletProxy::ILibraryAppletProxy(Core::System& system_, std::shared_ptr<Applet> applet,
|
ILibraryAppletProxy::ILibraryAppletProxy(Core::System& system_, std::shared_ptr<Applet> applet,
|
||||||
Kernel::KProcess* process, WindowSystem& window_system)
|
Kernel::KProcess* process, WindowSystem& window_system)
|
||||||
: ServiceFramework{system_, "ILibraryAppletProxy"}, m_window_system{window_system},
|
: ServiceFramework{system_, "ILibraryAppletProxy"},
|
||||||
m_process{process}, m_applet{std::move(applet)} {
|
m_window_system{window_system}, m_process{process}, m_applet{std::move(applet)} {
|
||||||
// clang-format off
|
// clang-format off
|
||||||
static const FunctionInfo functions[] = {
|
static const FunctionInfo functions[] = {
|
||||||
{0, D<&ILibraryAppletProxy::GetCommonStateGetter>, "GetCommonStateGetter"},
|
{0, D<&ILibraryAppletProxy::GetCommonStateGetter>, "GetCommonStateGetter"},
|
||||||
|
|
|
@ -16,8 +16,8 @@ namespace Service::AM {
|
||||||
|
|
||||||
ISelfController::ISelfController(Core::System& system_, std::shared_ptr<Applet> applet,
|
ISelfController::ISelfController(Core::System& system_, std::shared_ptr<Applet> applet,
|
||||||
Kernel::KProcess* process)
|
Kernel::KProcess* process)
|
||||||
: ServiceFramework{system_, "ISelfController"}, m_process{process},
|
: ServiceFramework{system_, "ISelfController"}, m_process{process}, m_applet{
|
||||||
m_applet{std::move(applet)} {
|
std::move(applet)} {
|
||||||
// clang-format off
|
// clang-format off
|
||||||
static const FunctionInfo functions[] = {
|
static const FunctionInfo functions[] = {
|
||||||
{0, D<&ISelfController::Exit>, "Exit"},
|
{0, D<&ISelfController::Exit>, "Exit"},
|
||||||
|
|
|
@ -20,8 +20,8 @@ namespace Service::AM {
|
||||||
|
|
||||||
ISystemAppletProxy::ISystemAppletProxy(Core::System& system_, std::shared_ptr<Applet> applet,
|
ISystemAppletProxy::ISystemAppletProxy(Core::System& system_, std::shared_ptr<Applet> applet,
|
||||||
Kernel::KProcess* process, WindowSystem& window_system)
|
Kernel::KProcess* process, WindowSystem& window_system)
|
||||||
: ServiceFramework{system_, "ISystemAppletProxy"}, m_window_system{window_system},
|
: ServiceFramework{system_, "ISystemAppletProxy"},
|
||||||
m_process{process}, m_applet{std::move(applet)} {
|
m_window_system{window_system}, m_process{process}, m_applet{std::move(applet)} {
|
||||||
// clang-format off
|
// clang-format off
|
||||||
static const FunctionInfo functions[] = {
|
static const FunctionInfo functions[] = {
|
||||||
{0, D<&ISystemAppletProxy::GetCommonStateGetter>, "GetCommonStateGetter"},
|
{0, D<&ISystemAppletProxy::GetCommonStateGetter>, "GetCommonStateGetter"},
|
||||||
|
|
|
@ -11,8 +11,8 @@ namespace Service::AM {
|
||||||
|
|
||||||
IWindowController::IWindowController(Core::System& system_, std::shared_ptr<Applet> applet,
|
IWindowController::IWindowController(Core::System& system_, std::shared_ptr<Applet> applet,
|
||||||
WindowSystem& window_system)
|
WindowSystem& window_system)
|
||||||
: ServiceFramework{system_, "IWindowController"}, m_window_system{window_system},
|
: ServiceFramework{system_, "IWindowController"},
|
||||||
m_applet{std::move(applet)} {
|
m_window_system{window_system}, m_applet{std::move(applet)} {
|
||||||
// clang-format off
|
// clang-format off
|
||||||
static const FunctionInfo functions[] = {
|
static const FunctionInfo functions[] = {
|
||||||
{0, nullptr, "CreateWindow"},
|
{0, nullptr, "CreateWindow"},
|
||||||
|
|
|
@ -9,8 +9,8 @@ namespace Service::AOC {
|
||||||
constexpr Result ResultNoPurchasedProductInfoAvailable{ErrorModule::NIMShop, 400};
|
constexpr Result ResultNoPurchasedProductInfoAvailable{ErrorModule::NIMShop, 400};
|
||||||
|
|
||||||
IPurchaseEventManager::IPurchaseEventManager(Core::System& system_)
|
IPurchaseEventManager::IPurchaseEventManager(Core::System& system_)
|
||||||
: ServiceFramework{system_, "IPurchaseEventManager"},
|
: ServiceFramework{system_, "IPurchaseEventManager"}, service_context{system,
|
||||||
service_context{system, "IPurchaseEventManager"} {
|
"IPurchaseEventManager"} {
|
||||||
// clang-format off
|
// clang-format off
|
||||||
static const FunctionInfo functions[] = {
|
static const FunctionInfo functions[] = {
|
||||||
{0, D<&IPurchaseEventManager::SetDefaultDeliveryTarget>, "SetDefaultDeliveryTarget"},
|
{0, D<&IPurchaseEventManager::SetDefaultDeliveryTarget>, "SetDefaultDeliveryTarget"},
|
||||||
|
|
|
@ -12,8 +12,9 @@ IAudioIn::IAudioIn(Core::System& system_, Manager& manager, size_t session_id,
|
||||||
const std::string& device_name, const AudioInParameter& in_params,
|
const std::string& device_name, const AudioInParameter& in_params,
|
||||||
Kernel::KProcess* handle, u64 applet_resource_user_id)
|
Kernel::KProcess* handle, u64 applet_resource_user_id)
|
||||||
: ServiceFramework{system_, "IAudioIn"}, process{handle}, service_context{system_, "IAudioIn"},
|
: ServiceFramework{system_, "IAudioIn"}, process{handle}, service_context{system_, "IAudioIn"},
|
||||||
event{service_context.CreateEvent("AudioInEvent")},
|
event{service_context.CreateEvent("AudioInEvent")}, impl{std::make_shared<In>(system_,
|
||||||
impl{std::make_shared<In>(system_, manager, event, session_id)} {
|
manager, event,
|
||||||
|
session_id)} {
|
||||||
// clang-format off
|
// clang-format off
|
||||||
static const FunctionInfo functions[] = {
|
static const FunctionInfo functions[] = {
|
||||||
{0, D<&IAudioIn::GetAudioInState>, "GetAudioInState"},
|
{0, D<&IAudioIn::GetAudioInState>, "GetAudioInState"},
|
||||||
|
|
|
@ -10,8 +10,8 @@ namespace Service::Audio {
|
||||||
using namespace AudioCore::AudioIn;
|
using namespace AudioCore::AudioIn;
|
||||||
|
|
||||||
IAudioInManager::IAudioInManager(Core::System& system_)
|
IAudioInManager::IAudioInManager(Core::System& system_)
|
||||||
: ServiceFramework{system_, "audin:u"},
|
: ServiceFramework{system_, "audin:u"}, impl{std::make_unique<AudioCore::AudioIn::Manager>(
|
||||||
impl{std::make_unique<AudioCore::AudioIn::Manager>(system_)} {
|
system_)} {
|
||||||
// clang-format off
|
// clang-format off
|
||||||
static const FunctionInfo functions[] = {
|
static const FunctionInfo functions[] = {
|
||||||
{0, D<&IAudioInManager::ListAudioIns>, "ListAudioIns"},
|
{0, D<&IAudioInManager::ListAudioIns>, "ListAudioIns"},
|
||||||
|
|
|
@ -14,8 +14,8 @@ IAudioRenderer::IAudioRenderer(Core::System& system_, Manager& manager_,
|
||||||
s32 session_id)
|
s32 session_id)
|
||||||
: ServiceFramework{system_, "IAudioRenderer"}, service_context{system_, "IAudioRenderer"},
|
: ServiceFramework{system_, "IAudioRenderer"}, service_context{system_, "IAudioRenderer"},
|
||||||
rendered_event{service_context.CreateEvent("IAudioRendererEvent")}, manager{manager_},
|
rendered_event{service_context.CreateEvent("IAudioRendererEvent")}, manager{manager_},
|
||||||
impl{std::make_unique<Renderer>(system_, manager, rendered_event)},
|
impl{std::make_unique<Renderer>(system_, manager, rendered_event)}, process_handle{
|
||||||
process_handle{process_handle_} {
|
process_handle_} {
|
||||||
// clang-format off
|
// clang-format off
|
||||||
static const FunctionInfo functions[] = {
|
static const FunctionInfo functions[] = {
|
||||||
{0, D<&IAudioRenderer::GetSampleRate>, "GetSampleRate"},
|
{0, D<&IAudioRenderer::GetSampleRate>, "GetSampleRate"},
|
||||||
|
|
|
@ -7,8 +7,9 @@
|
||||||
namespace Service::News {
|
namespace Service::News {
|
||||||
|
|
||||||
INewlyArrivedEventHolder::INewlyArrivedEventHolder(Core::System& system_)
|
INewlyArrivedEventHolder::INewlyArrivedEventHolder(Core::System& system_)
|
||||||
: ServiceFramework{system_, "INewlyArrivedEventHolder"},
|
: ServiceFramework{system_, "INewlyArrivedEventHolder"}, service_context{
|
||||||
service_context{system_, "INewlyArrivedEventHolder"} {
|
system_,
|
||||||
|
"INewlyArrivedEventHolder"} {
|
||||||
// clang-format off
|
// clang-format off
|
||||||
static const FunctionInfo functions[] = {
|
static const FunctionInfo functions[] = {
|
||||||
{0, D<&INewlyArrivedEventHolder::Get>, "Get"},
|
{0, D<&INewlyArrivedEventHolder::Get>, "Get"},
|
||||||
|
|
|
@ -7,8 +7,8 @@
|
||||||
namespace Service::News {
|
namespace Service::News {
|
||||||
|
|
||||||
IOverwriteEventHolder::IOverwriteEventHolder(Core::System& system_)
|
IOverwriteEventHolder::IOverwriteEventHolder(Core::System& system_)
|
||||||
: ServiceFramework{system_, "IOverwriteEventHolder"},
|
: ServiceFramework{system_, "IOverwriteEventHolder"}, service_context{system_,
|
||||||
service_context{system_, "IOverwriteEventHolder"} {
|
"IOverwriteEventHolder"} {
|
||||||
// clang-format off
|
// clang-format off
|
||||||
static const FunctionInfo functions[] = {
|
static const FunctionInfo functions[] = {
|
||||||
{0, D<&IOverwriteEventHolder::Get>, "Get"},
|
{0, D<&IOverwriteEventHolder::Get>, "Get"},
|
||||||
|
|
|
@ -11,8 +11,8 @@
|
||||||
namespace Service::FileSystem {
|
namespace Service::FileSystem {
|
||||||
|
|
||||||
IFileSystem::IFileSystem(Core::System& system_, FileSys::VirtualDir dir_, SizeGetter size_getter_)
|
IFileSystem::IFileSystem(Core::System& system_, FileSys::VirtualDir dir_, SizeGetter size_getter_)
|
||||||
: ServiceFramework{system_, "IFileSystem"},
|
: ServiceFramework{system_, "IFileSystem"}, backend{std::make_unique<FileSys::Fsa::IFileSystem>(
|
||||||
backend{std::make_unique<FileSys::Fsa::IFileSystem>(dir_)},
|
dir_)},
|
||||||
size_getter{std::move(size_getter_)} {
|
size_getter{std::move(size_getter_)} {
|
||||||
static const FunctionInfo functions[] = {
|
static const FunctionInfo functions[] = {
|
||||||
{0, D<&IFileSystem::CreateFile>, "CreateFile"},
|
{0, D<&IFileSystem::CreateFile>, "CreateFile"},
|
||||||
|
|
|
@ -12,8 +12,8 @@ namespace Service::FileSystem {
|
||||||
ISaveDataInfoReader::ISaveDataInfoReader(Core::System& system_,
|
ISaveDataInfoReader::ISaveDataInfoReader(Core::System& system_,
|
||||||
std::shared_ptr<SaveDataController> save_data_controller_,
|
std::shared_ptr<SaveDataController> save_data_controller_,
|
||||||
FileSys::SaveDataSpaceId space)
|
FileSys::SaveDataSpaceId space)
|
||||||
: ServiceFramework{system_, "ISaveDataInfoReader"},
|
: ServiceFramework{system_, "ISaveDataInfoReader"}, save_data_controller{
|
||||||
save_data_controller{save_data_controller_} {
|
save_data_controller_} {
|
||||||
static const FunctionInfo functions[] = {
|
static const FunctionInfo functions[] = {
|
||||||
{0, D<&ISaveDataInfoReader::ReadSaveDataInfo>, "ReadSaveDataInfo"},
|
{0, D<&ISaveDataInfoReader::ReadSaveDataInfo>, "ReadSaveDataInfo"},
|
||||||
};
|
};
|
||||||
|
|
|
@ -11,8 +11,8 @@
|
||||||
namespace Service::Glue::Time {
|
namespace Service::Glue::Time {
|
||||||
|
|
||||||
AlarmWorker::AlarmWorker(Core::System& system, StandardSteadyClockResource& steady_clock_resource)
|
AlarmWorker::AlarmWorker(Core::System& system, StandardSteadyClockResource& steady_clock_resource)
|
||||||
: m_system{system}, m_ctx{system, "Glue:AlarmWorker"},
|
: m_system{system}, m_ctx{system, "Glue:AlarmWorker"}, m_steady_clock_resource{
|
||||||
m_steady_clock_resource{steady_clock_resource} {}
|
steady_clock_resource} {}
|
||||||
|
|
||||||
AlarmWorker::~AlarmWorker() {
|
AlarmWorker::~AlarmWorker() {
|
||||||
m_system.CoreTiming().UnscheduleEvent(m_timer_timing_event);
|
m_system.CoreTiming().UnscheduleEvent(m_timer_timing_event);
|
||||||
|
|
|
@ -87,8 +87,10 @@ static Service::PSC::Time::LocationName GetTimeZoneString(
|
||||||
}
|
}
|
||||||
|
|
||||||
TimeManager::TimeManager(Core::System& system)
|
TimeManager::TimeManager(Core::System& system)
|
||||||
: m_steady_clock_resource{system}, m_time_zone_binary{system},
|
: m_steady_clock_resource{system}, m_time_zone_binary{system}, m_worker{
|
||||||
m_worker{system, m_steady_clock_resource, m_file_timestamp_worker} {
|
system,
|
||||||
|
m_steady_clock_resource,
|
||||||
|
m_file_timestamp_worker} {
|
||||||
m_time_m =
|
m_time_m =
|
||||||
system.ServiceManager().GetService<Service::PSC::Time::ServiceManager>("time:m", true);
|
system.ServiceManager().GetService<Service::PSC::Time::ServiceManager>("time:m", true);
|
||||||
|
|
||||||
|
|
|
@ -22,9 +22,9 @@ TimeZoneService::TimeZoneService(
|
||||||
std::shared_ptr<Service::PSC::Time::TimeZoneService> time_zone_service)
|
std::shared_ptr<Service::PSC::Time::TimeZoneService> time_zone_service)
|
||||||
: ServiceFramework{system_, "ITimeZoneService"}, m_system{system},
|
: ServiceFramework{system_, "ITimeZoneService"}, m_system{system},
|
||||||
m_can_write_timezone_device_location{can_write_timezone_device_location},
|
m_can_write_timezone_device_location{can_write_timezone_device_location},
|
||||||
m_file_timestamp_worker{file_timestamp_worker},
|
m_file_timestamp_worker{file_timestamp_worker}, m_wrapped_service{std::move(
|
||||||
m_wrapped_service{std::move(time_zone_service)}, m_operation_event{m_system},
|
time_zone_service)},
|
||||||
m_time_zone_binary{time_zone_binary} {
|
m_operation_event{m_system}, m_time_zone_binary{time_zone_binary} {
|
||||||
// clang-format off
|
// clang-format off
|
||||||
static const FunctionInfo functions[] = {
|
static const FunctionInfo functions[] = {
|
||||||
{0, D<&TimeZoneService::GetDeviceLocationName>, "GetDeviceLocationName"},
|
{0, D<&TimeZoneService::GetDeviceLocationName>, "GetDeviceLocationName"},
|
||||||
|
|
|
@ -19,11 +19,11 @@ namespace Service::Glue::Time {
|
||||||
|
|
||||||
TimeWorker::TimeWorker(Core::System& system, StandardSteadyClockResource& steady_clock_resource,
|
TimeWorker::TimeWorker(Core::System& system, StandardSteadyClockResource& steady_clock_resource,
|
||||||
FileTimestampWorker& file_timestamp_worker)
|
FileTimestampWorker& file_timestamp_worker)
|
||||||
: m_system{system}, m_ctx{m_system, "Glue:TimeWorker"},
|
: m_system{system}, m_ctx{m_system, "Glue:TimeWorker"}, m_event{m_ctx.CreateEvent(
|
||||||
m_event{m_ctx.CreateEvent("Glue:TimeWorker:Event")},
|
"Glue:TimeWorker:Event")},
|
||||||
m_steady_clock_resource{steady_clock_resource},
|
m_steady_clock_resource{steady_clock_resource},
|
||||||
m_file_timestamp_worker{file_timestamp_worker},
|
m_file_timestamp_worker{file_timestamp_worker}, m_timer_steady_clock{m_ctx.CreateEvent(
|
||||||
m_timer_steady_clock{m_ctx.CreateEvent("Glue:TimeWorker:SteadyClockTimerEvent")},
|
"Glue:TimeWorker:SteadyClockTimerEvent")},
|
||||||
m_timer_file_system{m_ctx.CreateEvent("Glue:TimeWorker:FileTimeTimerEvent")},
|
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_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(
|
m_timer_steady_clock_timing_event = Core::Timing::CreateEvent(
|
||||||
|
|
|
@ -17,8 +17,8 @@ namespace Service::HID {
|
||||||
|
|
||||||
IHidDebugServer::IHidDebugServer(Core::System& system_, std::shared_ptr<ResourceManager> resource,
|
IHidDebugServer::IHidDebugServer(Core::System& system_, std::shared_ptr<ResourceManager> resource,
|
||||||
std::shared_ptr<HidFirmwareSettings> settings)
|
std::shared_ptr<HidFirmwareSettings> settings)
|
||||||
: ServiceFramework{system_, "hid:dbg"}, resource_manager{resource},
|
: ServiceFramework{system_, "hid:dbg"}, resource_manager{resource}, firmware_settings{
|
||||||
firmware_settings{settings} {
|
settings} {
|
||||||
// clang-format off
|
// clang-format off
|
||||||
static const FunctionInfo functions[] = {
|
static const FunctionInfo functions[] = {
|
||||||
{0, nullptr, "DeactivateDebugPad"},
|
{0, nullptr, "DeactivateDebugPad"},
|
||||||
|
|
|
@ -72,8 +72,8 @@ public:
|
||||||
u32 num_handles_to_copy_ = 0, u32 num_objects_to_move_ = 0,
|
u32 num_handles_to_copy_ = 0, u32 num_objects_to_move_ = 0,
|
||||||
Flags flags = Flags::None)
|
Flags flags = Flags::None)
|
||||||
: RequestHelperBase(ctx), normal_params_size(normal_params_size_),
|
: RequestHelperBase(ctx), normal_params_size(normal_params_size_),
|
||||||
num_handles_to_copy(num_handles_to_copy_), num_objects_to_move(num_objects_to_move_),
|
num_handles_to_copy(num_handles_to_copy_),
|
||||||
kernel{ctx.kernel} {
|
num_objects_to_move(num_objects_to_move_), kernel{ctx.kernel} {
|
||||||
|
|
||||||
memset(cmdbuf, 0, sizeof(u32) * IPC::COMMAND_BUFFER_LENGTH);
|
memset(cmdbuf, 0, sizeof(u32) * IPC::COMMAND_BUFFER_LENGTH);
|
||||||
|
|
||||||
|
|
|
@ -40,8 +40,8 @@ class DynarmicCallbacks64 : public Dynarmic::A64::UserCallbacks {
|
||||||
public:
|
public:
|
||||||
explicit DynarmicCallbacks64(Core::Memory::Memory& memory_, std::vector<u8>& local_memory_,
|
explicit DynarmicCallbacks64(Core::Memory::Memory& memory_, std::vector<u8>& local_memory_,
|
||||||
IntervalSet& mapped_ranges_, JITContextImpl& parent_)
|
IntervalSet& mapped_ranges_, JITContextImpl& parent_)
|
||||||
: memory{memory_}, local_memory{local_memory_}, mapped_ranges{mapped_ranges_},
|
: memory{memory_}, local_memory{local_memory_},
|
||||||
parent{parent_} {}
|
mapped_ranges{mapped_ranges_}, parent{parent_} {}
|
||||||
|
|
||||||
u8 MemoryRead8(u64 vaddr) override {
|
u8 MemoryRead8(u64 vaddr) override {
|
||||||
return ReadMemory<u8>(vaddr);
|
return ReadMemory<u8>(vaddr);
|
||||||
|
|
|
@ -23,8 +23,8 @@ class IDatabaseService final : public ServiceFramework<IDatabaseService> {
|
||||||
public:
|
public:
|
||||||
explicit IDatabaseService(Core::System& system_, std::shared_ptr<MiiManager> mii_manager,
|
explicit IDatabaseService(Core::System& system_, std::shared_ptr<MiiManager> mii_manager,
|
||||||
bool is_system_)
|
bool is_system_)
|
||||||
: ServiceFramework{system_, "IDatabaseService"}, manager{mii_manager},
|
: ServiceFramework{system_, "IDatabaseService"}, manager{mii_manager}, is_system{
|
||||||
is_system{is_system_} {
|
is_system_} {
|
||||||
// clang-format off
|
// clang-format off
|
||||||
static const FunctionInfo functions[] = {
|
static const FunctionInfo functions[] = {
|
||||||
{0, D<&IDatabaseService::IsUpdated>, "IsUpdated"},
|
{0, D<&IDatabaseService::IsUpdated>, "IsUpdated"},
|
||||||
|
|
|
@ -30,8 +30,8 @@ Alarm::~Alarm() {
|
||||||
Alarms::Alarms(Core::System& system, StandardSteadyClockCore& steady_clock,
|
Alarms::Alarms(Core::System& system, StandardSteadyClockCore& steady_clock,
|
||||||
PowerStateRequestManager& power_state_request_manager)
|
PowerStateRequestManager& power_state_request_manager)
|
||||||
: m_system{system}, m_ctx{system, "Psc:Alarms"}, m_steady_clock{steady_clock},
|
: m_system{system}, m_ctx{system, "Psc:Alarms"}, m_steady_clock{steady_clock},
|
||||||
m_power_state_request_manager{power_state_request_manager},
|
m_power_state_request_manager{power_state_request_manager}, m_event{m_ctx.CreateEvent(
|
||||||
m_event{m_ctx.CreateEvent("Psc:Alarms:Event")} {}
|
"Psc:Alarms:Event")} {}
|
||||||
|
|
||||||
Alarms::~Alarms() {
|
Alarms::~Alarms() {
|
||||||
m_ctx.CloseEvent(m_event);
|
m_ctx.CloseEvent(m_event);
|
||||||
|
|
|
@ -11,8 +11,8 @@ StandardUserSystemClockCore::StandardUserSystemClockCore(
|
||||||
StandardNetworkSystemClockCore& network_clock)
|
StandardNetworkSystemClockCore& network_clock)
|
||||||
: SystemClockCore{local_clock.GetSteadyClock()}, m_system{system},
|
: SystemClockCore{local_clock.GetSteadyClock()}, m_system{system},
|
||||||
m_ctx{m_system, "Psc:StandardUserSystemClockCore"}, m_local_system_clock{local_clock},
|
m_ctx{m_system, "Psc:StandardUserSystemClockCore"}, m_local_system_clock{local_clock},
|
||||||
m_network_system_clock{network_clock},
|
m_network_system_clock{network_clock}, m_event{m_ctx.CreateEvent(
|
||||||
m_event{m_ctx.CreateEvent("Psc:StandardUserSystemClockCore:Event")} {}
|
"Psc:StandardUserSystemClockCore:Event")} {}
|
||||||
|
|
||||||
StandardUserSystemClockCore::~StandardUserSystemClockCore() {
|
StandardUserSystemClockCore::~StandardUserSystemClockCore() {
|
||||||
m_ctx.CloseEvent(m_event);
|
m_ctx.CloseEvent(m_event);
|
||||||
|
|
|
@ -6,8 +6,8 @@
|
||||||
|
|
||||||
namespace Service::PSC::Time {
|
namespace Service::PSC::Time {
|
||||||
OperationEvent::OperationEvent(Core::System& system)
|
OperationEvent::OperationEvent(Core::System& system)
|
||||||
: m_ctx{system, "Time:OperationEvent"},
|
: m_ctx{system, "Time:OperationEvent"}, m_event{
|
||||||
m_event{m_ctx.CreateEvent("Time:OperationEvent:Event")} {}
|
m_ctx.CreateEvent("Time:OperationEvent:Event")} {}
|
||||||
|
|
||||||
OperationEvent::~OperationEvent() {
|
OperationEvent::~OperationEvent() {
|
||||||
m_ctx.CloseEvent(m_event);
|
m_ctx.CloseEvent(m_event);
|
||||||
|
|
|
@ -29,8 +29,8 @@ public:
|
||||||
m_standard_user_system_clock{m_system, m_standard_local_system_clock,
|
m_standard_user_system_clock{m_system, m_standard_local_system_clock,
|
||||||
m_standard_network_system_clock},
|
m_standard_network_system_clock},
|
||||||
m_ephemeral_network_clock{m_tick_based_steady_clock}, m_shared_memory{m_system},
|
m_ephemeral_network_clock{m_tick_based_steady_clock}, m_shared_memory{m_system},
|
||||||
m_power_state_request_manager{m_system},
|
m_power_state_request_manager{m_system}, m_alarms{m_system, m_standard_steady_clock,
|
||||||
m_alarms{m_system, m_standard_steady_clock, m_power_state_request_manager},
|
m_power_state_request_manager},
|
||||||
m_local_system_clock_context_writer{m_system, m_shared_memory},
|
m_local_system_clock_context_writer{m_system, m_shared_memory},
|
||||||
m_network_system_clock_context_writer{m_system, m_shared_memory,
|
m_network_system_clock_context_writer{m_system, m_shared_memory,
|
||||||
m_standard_user_system_clock},
|
m_standard_user_system_clock},
|
||||||
|
|
|
@ -8,8 +8,8 @@ namespace Service::PSC::Time {
|
||||||
|
|
||||||
IPowerStateRequestHandler::IPowerStateRequestHandler(
|
IPowerStateRequestHandler::IPowerStateRequestHandler(
|
||||||
Core::System& system_, PowerStateRequestManager& power_state_request_manager)
|
Core::System& system_, PowerStateRequestManager& power_state_request_manager)
|
||||||
: ServiceFramework{system_, "time:p"}, m_system{system},
|
: ServiceFramework{system_, "time:p"}, m_system{system}, m_power_state_request_manager{
|
||||||
m_power_state_request_manager{power_state_request_manager} {
|
power_state_request_manager} {
|
||||||
// clang-format off
|
// clang-format off
|
||||||
static const FunctionInfo functions[] = {
|
static const FunctionInfo functions[] = {
|
||||||
{0, D<&IPowerStateRequestHandler::GetPowerStateRequestEventReadableHandle>, "GetPowerStateRequestEventReadableHandle"},
|
{0, D<&IPowerStateRequestHandler::GetPowerStateRequestEventReadableHandle>, "GetPowerStateRequestEventReadableHandle"},
|
||||||
|
|
|
@ -37,8 +37,8 @@ StaticService::StaticService(Core::System& system_, StaticServiceSetupInfo setup
|
||||||
m_user_system_clock{m_time->m_standard_user_system_clock},
|
m_user_system_clock{m_time->m_standard_user_system_clock},
|
||||||
m_network_system_clock{m_time->m_standard_network_system_clock},
|
m_network_system_clock{m_time->m_standard_network_system_clock},
|
||||||
m_time_zone{m_time->m_time_zone},
|
m_time_zone{m_time->m_time_zone},
|
||||||
m_ephemeral_network_clock{m_time->m_ephemeral_network_clock},
|
m_ephemeral_network_clock{m_time->m_ephemeral_network_clock}, m_shared_memory{
|
||||||
m_shared_memory{m_time->m_shared_memory} {
|
m_time->m_shared_memory} {
|
||||||
// clang-format off
|
// clang-format off
|
||||||
static const FunctionInfo functions[] = {
|
static const FunctionInfo functions[] = {
|
||||||
{0, D<&StaticService::GetStandardUserSystemClock>, "GetStandardUserSystemClock"},
|
{0, D<&StaticService::GetStandardUserSystemClock>, "GetStandardUserSystemClock"},
|
||||||
|
|
|
@ -12,8 +12,8 @@ SteadyClock::SteadyClock(Core::System& system_, std::shared_ptr<TimeManager> man
|
||||||
bool can_write_steady_clock, bool can_write_uninitialized_clock)
|
bool can_write_steady_clock, bool can_write_uninitialized_clock)
|
||||||
: ServiceFramework{system_, "ISteadyClock"}, m_system{system},
|
: ServiceFramework{system_, "ISteadyClock"}, m_system{system},
|
||||||
m_clock_core{manager->m_standard_steady_clock},
|
m_clock_core{manager->m_standard_steady_clock},
|
||||||
m_can_write_steady_clock{can_write_steady_clock},
|
m_can_write_steady_clock{can_write_steady_clock}, m_can_write_uninitialized_clock{
|
||||||
m_can_write_uninitialized_clock{can_write_uninitialized_clock} {
|
can_write_uninitialized_clock} {
|
||||||
// clang-format off
|
// clang-format off
|
||||||
static const FunctionInfo functions[] = {
|
static const FunctionInfo functions[] = {
|
||||||
{0, D<&SteadyClock::GetCurrentTimePoint>, "GetCurrentTimePoint"},
|
{0, D<&SteadyClock::GetCurrentTimePoint>, "GetCurrentTimePoint"},
|
||||||
|
|
|
@ -11,8 +11,8 @@ namespace Service::PSC::Time {
|
||||||
SystemClock::SystemClock(Core::System& system_, SystemClockCore& clock_core, bool can_write_clock,
|
SystemClock::SystemClock(Core::System& system_, SystemClockCore& clock_core, bool can_write_clock,
|
||||||
bool can_write_uninitialized_clock)
|
bool can_write_uninitialized_clock)
|
||||||
: ServiceFramework{system_, "ISystemClock"}, m_system{system}, m_clock_core{clock_core},
|
: ServiceFramework{system_, "ISystemClock"}, m_system{system}, m_clock_core{clock_core},
|
||||||
m_can_write_clock{can_write_clock},
|
m_can_write_clock{can_write_clock}, m_can_write_uninitialized_clock{
|
||||||
m_can_write_uninitialized_clock{can_write_uninitialized_clock} {
|
can_write_uninitialized_clock} {
|
||||||
// clang-format off
|
// clang-format off
|
||||||
static const FunctionInfo functions[] = {
|
static const FunctionInfo functions[] = {
|
||||||
{0, D<&SystemClock::GetCurrentTime>, "GetCurrentTime"},
|
{0, D<&SystemClock::GetCurrentTime>, "GetCurrentTime"},
|
||||||
|
|
|
@ -13,8 +13,8 @@ namespace Service::PSC::Time {
|
||||||
TimeZoneService::TimeZoneService(Core::System& system_, StandardSteadyClockCore& clock_core,
|
TimeZoneService::TimeZoneService(Core::System& system_, StandardSteadyClockCore& clock_core,
|
||||||
TimeZone& time_zone, bool can_write_timezone_device_location)
|
TimeZone& time_zone, bool can_write_timezone_device_location)
|
||||||
: ServiceFramework{system_, "ITimeZoneService"}, m_system{system}, m_clock_core{clock_core},
|
: ServiceFramework{system_, "ITimeZoneService"}, m_system{system}, m_clock_core{clock_core},
|
||||||
m_time_zone{time_zone},
|
m_time_zone{time_zone}, m_can_write_timezone_device_location{
|
||||||
m_can_write_timezone_device_location{can_write_timezone_device_location} {
|
can_write_timezone_device_location} {
|
||||||
// clang-format off
|
// clang-format off
|
||||||
static const FunctionInfo functions[] = {
|
static const FunctionInfo functions[] = {
|
||||||
{0, D<&TimeZoneService::GetDeviceLocationName>, "GetDeviceLocationName"},
|
{0, D<&TimeZoneService::GetDeviceLocationName>, "GetDeviceLocationName"},
|
||||||
|
|
|
@ -251,8 +251,8 @@ void SM::UnregisterService(HLERequestContext& ctx) {
|
||||||
}
|
}
|
||||||
|
|
||||||
SM::SM(ServiceManager& service_manager_, Core::System& system_)
|
SM::SM(ServiceManager& service_manager_, Core::System& system_)
|
||||||
: ServiceFramework{system_, "sm:", 4}, service_manager{service_manager_},
|
: ServiceFramework{system_, "sm:", 4},
|
||||||
kernel{system_.Kernel()} {
|
service_manager{service_manager_}, kernel{system_.Kernel()} {
|
||||||
RegisterHandlers({
|
RegisterHandlers({
|
||||||
{0, &SM::Initialize, "Initialize"},
|
{0, &SM::Initialize, "Initialize"},
|
||||||
{1, &SM::GetServiceCmif, "GetService"},
|
{1, &SM::GetServiceCmif, "GetService"},
|
||||||
|
|
|
@ -15,8 +15,8 @@ namespace Service::VI {
|
||||||
|
|
||||||
IApplicationDisplayService::IApplicationDisplayService(Core::System& system_,
|
IApplicationDisplayService::IApplicationDisplayService(Core::System& system_,
|
||||||
std::shared_ptr<Container> container)
|
std::shared_ptr<Container> container)
|
||||||
: ServiceFramework{system_, "IApplicationDisplayService"}, m_container{std::move(container)},
|
: ServiceFramework{system_, "IApplicationDisplayService"},
|
||||||
m_context{system, "IApplicationDisplayService"} {
|
m_container{std::move(container)}, m_context{system, "IApplicationDisplayService"} {
|
||||||
// clang-format off
|
// clang-format off
|
||||||
static const FunctionInfo functions[] = {
|
static const FunctionInfo functions[] = {
|
||||||
{100, C<&IApplicationDisplayService::GetRelayService>, "GetRelayService"},
|
{100, C<&IApplicationDisplayService::GetRelayService>, "GetRelayService"},
|
||||||
|
|
|
@ -218,8 +218,8 @@ std::vector<CheatEntry> TextCheatParser::Parse(std::string_view data) const {
|
||||||
|
|
||||||
CheatEngine::CheatEngine(System& system_, std::vector<CheatEntry> cheats_,
|
CheatEngine::CheatEngine(System& system_, std::vector<CheatEntry> cheats_,
|
||||||
const std::array<u8, 0x20>& build_id_)
|
const std::array<u8, 0x20>& build_id_)
|
||||||
: vm{std::make_unique<StandardVmCallbacks>(system_, metadata)}, cheats(std::move(cheats_)),
|
: vm{std::make_unique<StandardVmCallbacks>(system_, metadata)},
|
||||||
core_timing{system_.CoreTiming()}, system{system_} {
|
cheats(std::move(cheats_)), core_timing{system_.CoreTiming()}, system{system_} {
|
||||||
metadata.main_nso_build_id = build_id_;
|
metadata.main_nso_build_id = build_id_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
294
src/core/telemetry_session.cpp
Normal file
294
src/core/telemetry_session.cpp
Normal file
|
@ -0,0 +1,294 @@
|
||||||
|
// SPDX-FileCopyrightText: 2017 Citra Emulator Project & 2024 suyu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
|
||||||
|
#include <mbedtls/ctr_drbg.h>
|
||||||
|
#include <mbedtls/entropy.h>
|
||||||
|
|
||||||
|
#include "common/assert.h"
|
||||||
|
#include "common/common_types.h"
|
||||||
|
#include "common/fs/file.h"
|
||||||
|
#include "common/fs/fs.h"
|
||||||
|
#include "common/fs/path_util.h"
|
||||||
|
#include "common/logging/log.h"
|
||||||
|
|
||||||
|
#include "common/settings.h"
|
||||||
|
#include "common/settings_enums.h"
|
||||||
|
#include "core/file_sys/control_metadata.h"
|
||||||
|
#include "core/file_sys/patch_manager.h"
|
||||||
|
#include "core/loader/loader.h"
|
||||||
|
#include "core/telemetry_session.h"
|
||||||
|
|
||||||
|
#ifdef ENABLE_WEB_SERVICE
|
||||||
|
#include "web_service/telemetry_json.h"
|
||||||
|
#include "web_service/verify_login.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace Core {
|
||||||
|
|
||||||
|
namespace Telemetry = Common::Telemetry;
|
||||||
|
|
||||||
|
static u64 GenerateTelemetryId() {
|
||||||
|
u64 telemetry_id{};
|
||||||
|
|
||||||
|
mbedtls_entropy_context entropy;
|
||||||
|
mbedtls_entropy_init(&entropy);
|
||||||
|
mbedtls_ctr_drbg_context ctr_drbg;
|
||||||
|
static constexpr std::array<char, 18> personalization{{"suyu Telemetry ID"}};
|
||||||
|
|
||||||
|
mbedtls_ctr_drbg_init(&ctr_drbg);
|
||||||
|
ASSERT(mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy,
|
||||||
|
reinterpret_cast<const unsigned char*>(personalization.data()),
|
||||||
|
personalization.size()) == 0);
|
||||||
|
ASSERT(mbedtls_ctr_drbg_random(&ctr_drbg, reinterpret_cast<unsigned char*>(&telemetry_id),
|
||||||
|
sizeof(u64)) == 0);
|
||||||
|
|
||||||
|
mbedtls_ctr_drbg_free(&ctr_drbg);
|
||||||
|
mbedtls_entropy_free(&entropy);
|
||||||
|
|
||||||
|
return telemetry_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char* TranslateRenderer(Settings::RendererBackend backend) {
|
||||||
|
switch (backend) {
|
||||||
|
case Settings::RendererBackend::OpenGL:
|
||||||
|
return "OpenGL";
|
||||||
|
case Settings::RendererBackend::Vulkan:
|
||||||
|
return "Vulkan";
|
||||||
|
case Settings::RendererBackend::Null:
|
||||||
|
return "Null";
|
||||||
|
}
|
||||||
|
return "Unknown";
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char* TranslateGPUAccuracyLevel(Settings::GpuAccuracy backend) {
|
||||||
|
switch (backend) {
|
||||||
|
case Settings::GpuAccuracy::Normal:
|
||||||
|
return "Normal";
|
||||||
|
case Settings::GpuAccuracy::High:
|
||||||
|
return "High";
|
||||||
|
case Settings::GpuAccuracy::Extreme:
|
||||||
|
return "Extreme";
|
||||||
|
}
|
||||||
|
return "Unknown";
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char* TranslateNvdecEmulation(Settings::NvdecEmulation backend) {
|
||||||
|
switch (backend) {
|
||||||
|
case Settings::NvdecEmulation::Off:
|
||||||
|
return "Off";
|
||||||
|
case Settings::NvdecEmulation::Cpu:
|
||||||
|
return "CPU";
|
||||||
|
case Settings::NvdecEmulation::Gpu:
|
||||||
|
return "GPU";
|
||||||
|
}
|
||||||
|
return "Unknown";
|
||||||
|
}
|
||||||
|
|
||||||
|
static constexpr const char* TranslateVSyncMode(Settings::VSyncMode mode) {
|
||||||
|
switch (mode) {
|
||||||
|
case Settings::VSyncMode::Immediate:
|
||||||
|
return "Immediate";
|
||||||
|
case Settings::VSyncMode::Mailbox:
|
||||||
|
return "Mailbox";
|
||||||
|
case Settings::VSyncMode::Fifo:
|
||||||
|
return "FIFO";
|
||||||
|
case Settings::VSyncMode::FifoRelaxed:
|
||||||
|
return "FIFO Relaxed";
|
||||||
|
}
|
||||||
|
return "Unknown";
|
||||||
|
}
|
||||||
|
|
||||||
|
static constexpr const char* TranslateASTCDecodeMode(Settings::AstcDecodeMode mode) {
|
||||||
|
switch (mode) {
|
||||||
|
case Settings::AstcDecodeMode::Cpu:
|
||||||
|
return "CPU";
|
||||||
|
case Settings::AstcDecodeMode::Gpu:
|
||||||
|
return "GPU";
|
||||||
|
case Settings::AstcDecodeMode::CpuAsynchronous:
|
||||||
|
return "CPU Asynchronous";
|
||||||
|
}
|
||||||
|
return "Unknown";
|
||||||
|
}
|
||||||
|
|
||||||
|
u64 GetTelemetryId() {
|
||||||
|
u64 telemetry_id{};
|
||||||
|
const auto filename = Common::FS::GetSuyuPath(Common::FS::SuyuPath::ConfigDir) / "telemetry_id";
|
||||||
|
|
||||||
|
bool generate_new_id = !Common::FS::Exists(filename);
|
||||||
|
|
||||||
|
if (!generate_new_id) {
|
||||||
|
Common::FS::IOFile file{filename, Common::FS::FileAccessMode::Read,
|
||||||
|
Common::FS::FileType::BinaryFile};
|
||||||
|
|
||||||
|
if (!file.IsOpen()) {
|
||||||
|
LOG_ERROR(Core, "failed to open telemetry_id: {}",
|
||||||
|
Common::FS::PathToUTF8String(filename));
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!file.ReadObject(telemetry_id) || telemetry_id == 0) {
|
||||||
|
LOG_ERROR(Frontend, "telemetry_id is 0. Generating a new one.", telemetry_id);
|
||||||
|
generate_new_id = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (generate_new_id) {
|
||||||
|
Common::FS::IOFile file{filename, Common::FS::FileAccessMode::Write,
|
||||||
|
Common::FS::FileType::BinaryFile};
|
||||||
|
|
||||||
|
if (!file.IsOpen()) {
|
||||||
|
LOG_ERROR(Core, "failed to open telemetry_id: {}",
|
||||||
|
Common::FS::PathToUTF8String(filename));
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
telemetry_id = GenerateTelemetryId();
|
||||||
|
|
||||||
|
if (!file.WriteObject(telemetry_id)) {
|
||||||
|
LOG_ERROR(Core, "Failed to write telemetry_id to file.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return telemetry_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
u64 RegenerateTelemetryId() {
|
||||||
|
const u64 new_telemetry_id{GenerateTelemetryId()};
|
||||||
|
const auto filename = Common::FS::GetSuyuPath(Common::FS::SuyuPath::ConfigDir) / "telemetry_id";
|
||||||
|
|
||||||
|
Common::FS::IOFile file{filename, Common::FS::FileAccessMode::Write,
|
||||||
|
Common::FS::FileType::BinaryFile};
|
||||||
|
|
||||||
|
if (!file.IsOpen()) {
|
||||||
|
LOG_ERROR(Core, "failed to open telemetry_id: {}", Common::FS::PathToUTF8String(filename));
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!file.WriteObject(new_telemetry_id)) {
|
||||||
|
LOG_ERROR(Core, "Failed to write telemetry_id to file.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return new_telemetry_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool VerifyLogin(const std::string& username, const std::string& token) {
|
||||||
|
#ifdef ENABLE_WEB_SERVICE
|
||||||
|
return WebService::VerifyLogin(Settings::values.web_api_url.GetValue(), username, token);
|
||||||
|
#else
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
TelemetrySession::TelemetrySession() = default;
|
||||||
|
|
||||||
|
TelemetrySession::~TelemetrySession() {
|
||||||
|
// Log one-time session end information
|
||||||
|
const s64 shutdown_time{std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||||
|
std::chrono::system_clock::now().time_since_epoch())
|
||||||
|
.count()};
|
||||||
|
AddField(Telemetry::FieldType::Session, "Shutdown_Time", shutdown_time);
|
||||||
|
|
||||||
|
#ifdef ENABLE_WEB_SERVICE
|
||||||
|
auto backend = std::make_unique<WebService::TelemetryJson>(
|
||||||
|
Settings::values.web_api_url.GetValue(), Settings::values.suyu_username.GetValue(),
|
||||||
|
Settings::values.suyu_token.GetValue());
|
||||||
|
#else
|
||||||
|
auto backend = std::make_unique<Telemetry::NullVisitor>();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Complete the session, submitting to the web service backend if necessary
|
||||||
|
field_collection.Accept(*backend);
|
||||||
|
if (Settings::values.enable_telemetry) {
|
||||||
|
backend->Complete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TelemetrySession::AddInitialInfo(Loader::AppLoader& app_loader,
|
||||||
|
const Service::FileSystem::FileSystemController& fsc,
|
||||||
|
const FileSys::ContentProvider& content_provider) {
|
||||||
|
// Log one-time top-level information
|
||||||
|
AddField(Telemetry::FieldType::None, "TelemetryId", GetTelemetryId());
|
||||||
|
|
||||||
|
// Log one-time session start information
|
||||||
|
const s64 init_time{std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||||
|
std::chrono::system_clock::now().time_since_epoch())
|
||||||
|
.count()};
|
||||||
|
AddField(Telemetry::FieldType::Session, "Init_Time", init_time);
|
||||||
|
|
||||||
|
u64 program_id{};
|
||||||
|
const Loader::ResultStatus res{app_loader.ReadProgramId(program_id)};
|
||||||
|
if (res == Loader::ResultStatus::Success) {
|
||||||
|
const std::string formatted_program_id{fmt::format("{:016X}", program_id)};
|
||||||
|
AddField(Telemetry::FieldType::Session, "ProgramId", formatted_program_id);
|
||||||
|
|
||||||
|
std::string name;
|
||||||
|
app_loader.ReadTitle(name);
|
||||||
|
|
||||||
|
if (name.empty()) {
|
||||||
|
const auto metadata = [&content_provider, &fsc, program_id] {
|
||||||
|
const FileSys::PatchManager pm{program_id, fsc, content_provider};
|
||||||
|
return pm.GetControlMetadata();
|
||||||
|
}();
|
||||||
|
if (metadata.first != nullptr) {
|
||||||
|
name = metadata.first->GetApplicationName();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!name.empty()) {
|
||||||
|
AddField(Telemetry::FieldType::Session, "ProgramName", name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AddField(Telemetry::FieldType::Session, "ProgramFormat",
|
||||||
|
static_cast<u8>(app_loader.GetFileType()));
|
||||||
|
|
||||||
|
// Log application information
|
||||||
|
Telemetry::AppendBuildInfo(field_collection);
|
||||||
|
|
||||||
|
// Log user system information
|
||||||
|
Telemetry::AppendCPUInfo(field_collection);
|
||||||
|
Telemetry::AppendOSInfo(field_collection);
|
||||||
|
|
||||||
|
// Log user configuration information
|
||||||
|
constexpr auto field_type = Telemetry::FieldType::UserConfig;
|
||||||
|
AddField(field_type, "Audio_SinkId",
|
||||||
|
Settings::CanonicalizeEnum(Settings::values.sink_id.GetValue()));
|
||||||
|
AddField(field_type, "Core_UseMultiCore", Settings::values.use_multi_core.GetValue());
|
||||||
|
AddField(field_type, "Renderer_Backend",
|
||||||
|
TranslateRenderer(Settings::values.renderer_backend.GetValue()));
|
||||||
|
AddField(field_type, "Renderer_UseSpeedLimit", Settings::values.use_speed_limit.GetValue());
|
||||||
|
AddField(field_type, "Renderer_SpeedLimit", Settings::values.speed_limit.GetValue());
|
||||||
|
AddField(field_type, "Renderer_UseDiskShaderCache",
|
||||||
|
Settings::values.use_disk_shader_cache.GetValue());
|
||||||
|
AddField(field_type, "Renderer_GPUAccuracyLevel",
|
||||||
|
TranslateGPUAccuracyLevel(Settings::values.gpu_accuracy.GetValue()));
|
||||||
|
AddField(field_type, "Renderer_UseAsynchronousGpuEmulation",
|
||||||
|
Settings::values.use_asynchronous_gpu_emulation.GetValue());
|
||||||
|
AddField(field_type, "Renderer_NvdecEmulation",
|
||||||
|
TranslateNvdecEmulation(Settings::values.nvdec_emulation.GetValue()));
|
||||||
|
AddField(field_type, "Renderer_AccelerateASTC",
|
||||||
|
TranslateASTCDecodeMode(Settings::values.accelerate_astc.GetValue()));
|
||||||
|
AddField(field_type, "Renderer_UseVsync",
|
||||||
|
TranslateVSyncMode(Settings::values.vsync_mode.GetValue()));
|
||||||
|
AddField(field_type, "Renderer_ShaderBackend",
|
||||||
|
static_cast<u32>(Settings::values.shader_backend.GetValue()));
|
||||||
|
AddField(field_type, "Renderer_UseAsynchronousShaders",
|
||||||
|
Settings::values.use_asynchronous_shaders.GetValue());
|
||||||
|
AddField(field_type, "System_UseDockedMode", Settings::IsDockedMode());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TelemetrySession::SubmitTestcase() {
|
||||||
|
#ifdef ENABLE_WEB_SERVICE
|
||||||
|
auto backend = std::make_unique<WebService::TelemetryJson>(
|
||||||
|
Settings::values.web_api_url.GetValue(), Settings::values.suyu_username.GetValue(),
|
||||||
|
Settings::values.suyu_token.GetValue());
|
||||||
|
field_collection.Accept(*backend);
|
||||||
|
return backend->SubmitTestcase();
|
||||||
|
#else
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Core
|
101
src/core/telemetry_session.h
Normal file
101
src/core/telemetry_session.h
Normal file
|
@ -0,0 +1,101 @@
|
||||||
|
// SPDX-FileCopyrightText: 2017 Citra Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include "common/telemetry.h"
|
||||||
|
|
||||||
|
namespace FileSys {
|
||||||
|
class ContentProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Loader {
|
||||||
|
class AppLoader;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Service::FileSystem {
|
||||||
|
class FileSystemController;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Core {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instruments telemetry for this emulation session. Creates a new set of telemetry fields on each
|
||||||
|
* session, logging any one-time fields. Interfaces with the telemetry backend used for submitting
|
||||||
|
* data to the web service. Submits session data on close.
|
||||||
|
*/
|
||||||
|
class TelemetrySession {
|
||||||
|
public:
|
||||||
|
explicit TelemetrySession();
|
||||||
|
~TelemetrySession();
|
||||||
|
|
||||||
|
TelemetrySession(const TelemetrySession&) = delete;
|
||||||
|
TelemetrySession& operator=(const TelemetrySession&) = delete;
|
||||||
|
|
||||||
|
TelemetrySession(TelemetrySession&&) = delete;
|
||||||
|
TelemetrySession& operator=(TelemetrySession&&) = delete;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds the initial telemetry info necessary when starting up a title.
|
||||||
|
*
|
||||||
|
* This includes information such as:
|
||||||
|
* - Telemetry ID
|
||||||
|
* - Initialization time
|
||||||
|
* - Title ID
|
||||||
|
* - Title name
|
||||||
|
* - Title file format
|
||||||
|
* - Miscellaneous settings values.
|
||||||
|
*
|
||||||
|
* @param app_loader The application loader to use to retrieve
|
||||||
|
* title-specific information.
|
||||||
|
* @param fsc Filesystem controller to use to retrieve info.
|
||||||
|
* @param content_provider Content provider to use to retrieve info.
|
||||||
|
*/
|
||||||
|
void AddInitialInfo(Loader::AppLoader& app_loader,
|
||||||
|
const Service::FileSystem::FileSystemController& fsc,
|
||||||
|
const FileSys::ContentProvider& content_provider);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrapper around the Telemetry::FieldCollection::AddField method.
|
||||||
|
* @param type Type of the field to add.
|
||||||
|
* @param name Name of the field to add.
|
||||||
|
* @param value Value for the field to add.
|
||||||
|
*/
|
||||||
|
template <typename T>
|
||||||
|
void AddField(Common::Telemetry::FieldType type, const char* name, T value) {
|
||||||
|
field_collection.AddField(type, name, std::move(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Submits a Testcase.
|
||||||
|
* @returns A bool indicating whether the submission succeeded
|
||||||
|
*/
|
||||||
|
bool SubmitTestcase();
|
||||||
|
|
||||||
|
private:
|
||||||
|
/// Tracks all added fields for the session
|
||||||
|
Common::Telemetry::FieldCollection field_collection;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets TelemetryId, a unique identifier used for the user's telemetry sessions.
|
||||||
|
* @returns The current TelemetryId for the session.
|
||||||
|
*/
|
||||||
|
u64 GetTelemetryId();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Regenerates TelemetryId, a unique identifier used for the user's telemetry sessions.
|
||||||
|
* @returns The new TelemetryId that was generated.
|
||||||
|
*/
|
||||||
|
u64 RegenerateTelemetryId();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verifies the username and token.
|
||||||
|
* @param username suyu username to use for authentication.
|
||||||
|
* @param token suyu token to use for authentication.
|
||||||
|
* @returns Future with bool indicating whether the verification succeeded
|
||||||
|
*/
|
||||||
|
bool VerifyLogin(const std::string& username, const std::string& token);
|
||||||
|
|
||||||
|
} // namespace Core
|
|
@ -148,8 +148,8 @@ public:
|
||||||
Common::Input::AnalogProperties properties_y_,
|
Common::Input::AnalogProperties properties_y_,
|
||||||
InputEngine* input_engine_)
|
InputEngine* input_engine_)
|
||||||
: identifier(identifier_), axis_x(axis_x_), axis_y(axis_y_), properties_x(properties_x_),
|
: identifier(identifier_), axis_x(axis_x_), axis_y(axis_y_), properties_x(properties_x_),
|
||||||
properties_y(properties_y_), input_engine(input_engine_),
|
properties_y(properties_y_),
|
||||||
invert_axis_y{input_engine_->GetEngineName() == "sdl"} {
|
input_engine(input_engine_), invert_axis_y{input_engine_->GetEngineName() == "sdl"} {
|
||||||
UpdateCallback engine_callback{[this]() { OnChange(); }};
|
UpdateCallback engine_callback{[this]() { OnChange(); }};
|
||||||
const InputIdentifier x_input_identifier{
|
const InputIdentifier x_input_identifier{
|
||||||
.identifier = identifier,
|
.identifier = identifier,
|
||||||
|
|
|
@ -186,8 +186,8 @@ Function::Function(ObjectPool<Block>& block_pool, Location start_address)
|
||||||
|
|
||||||
CFG::CFG(Environment& env_, ObjectPool<Block>& block_pool_, Location start_address,
|
CFG::CFG(Environment& env_, ObjectPool<Block>& block_pool_, Location start_address,
|
||||||
bool exits_to_dispatcher_)
|
bool exits_to_dispatcher_)
|
||||||
: env{env_}, block_pool{block_pool_}, program_start{start_address},
|
: env{env_}, block_pool{block_pool_}, program_start{start_address}, exits_to_dispatcher{
|
||||||
exits_to_dispatcher{exits_to_dispatcher_} {
|
exits_to_dispatcher_} {
|
||||||
if (exits_to_dispatcher) {
|
if (exits_to_dispatcher) {
|
||||||
dispatch_block = block_pool.Create(Block{});
|
dispatch_block = block_pool.Create(Block{});
|
||||||
dispatch_block->begin = {};
|
dispatch_block->begin = {};
|
||||||
|
|
|
@ -112,8 +112,8 @@ struct Statement : ListBaseHook {
|
||||||
Statement(SetVariable, u32 id_, Statement* op_, Statement* up_)
|
Statement(SetVariable, u32 id_, Statement* op_, Statement* up_)
|
||||||
: op{op_}, id{id_}, up{up_}, type{StatementType::SetVariable} {}
|
: op{op_}, id{id_}, up{up_}, type{StatementType::SetVariable} {}
|
||||||
Statement(SetIndirectBranchVariable, IR::Reg branch_reg_, s32 branch_offset_, Statement* up_)
|
Statement(SetIndirectBranchVariable, IR::Reg branch_reg_, s32 branch_offset_, Statement* up_)
|
||||||
: branch_offset{branch_offset_}, branch_reg{branch_reg_}, up{up_},
|
: branch_offset{branch_offset_},
|
||||||
type{StatementType::SetIndirectBranchVariable} {}
|
branch_reg{branch_reg_}, up{up_}, type{StatementType::SetIndirectBranchVariable} {}
|
||||||
Statement(Variable, u32 id_, Statement* up_)
|
Statement(Variable, u32 id_, Statement* up_)
|
||||||
: id{id_}, up{up_}, type{StatementType::Variable} {}
|
: id{id_}, up{up_}, type{StatementType::Variable} {}
|
||||||
Statement(IndirectBranchCond, u32 location_, Statement* up_)
|
Statement(IndirectBranchCond, u32 location_, Statement* up_)
|
||||||
|
|
|
@ -54,8 +54,8 @@ QtNXWebEngineView::QtNXWebEngineView(QWidget* parent, Core::System& system,
|
||||||
: QWebEngineView(parent), input_subsystem{input_subsystem_},
|
: QWebEngineView(parent), input_subsystem{input_subsystem_},
|
||||||
url_interceptor(std::make_unique<UrlRequestInterceptor>()),
|
url_interceptor(std::make_unique<UrlRequestInterceptor>()),
|
||||||
input_interpreter(std::make_unique<InputInterpreter>(system)),
|
input_interpreter(std::make_unique<InputInterpreter>(system)),
|
||||||
default_profile{QWebEngineProfile::defaultProfile()},
|
default_profile{QWebEngineProfile::defaultProfile()}, global_settings{
|
||||||
global_settings{default_profile->settings()} {
|
default_profile->settings()} {
|
||||||
default_profile->setPersistentStoragePath(QString::fromStdString(Common::FS::PathToUTF8String(
|
default_profile->setPersistentStoragePath(QString::fromStdString(Common::FS::PathToUTF8String(
|
||||||
Common::FS::GetSuyuPath(Common::FS::SuyuPath::SuyuDir) / "qtwebengine")));
|
Common::FS::GetSuyuPath(Common::FS::SuyuPath::SuyuDir) / "qtwebengine")));
|
||||||
|
|
||||||
|
|
|
@ -284,8 +284,8 @@ struct NullRenderWidget : public RenderWidget {
|
||||||
GRenderWindow::GRenderWindow(GMainWindow* parent, EmuThread* emu_thread_,
|
GRenderWindow::GRenderWindow(GMainWindow* parent, EmuThread* emu_thread_,
|
||||||
std::shared_ptr<InputCommon::InputSubsystem> input_subsystem_,
|
std::shared_ptr<InputCommon::InputSubsystem> input_subsystem_,
|
||||||
Core::System& system_)
|
Core::System& system_)
|
||||||
: QWidget(parent), emu_thread(emu_thread_), input_subsystem{std::move(input_subsystem_)},
|
: QWidget(parent),
|
||||||
system{system_} {
|
emu_thread(emu_thread_), input_subsystem{std::move(input_subsystem_)}, system{system_} {
|
||||||
setWindowTitle(QStringLiteral("suyu %1 | %2-%3")
|
setWindowTitle(QStringLiteral("suyu %1 | %2-%3")
|
||||||
.arg(QString::fromUtf8(Common::g_build_name),
|
.arg(QString::fromUtf8(Common::g_build_name),
|
||||||
QString::fromUtf8(Common::g_scm_branch),
|
QString::fromUtf8(Common::g_scm_branch),
|
||||||
|
|
|
@ -6,12 +6,14 @@
|
||||||
#include <QPushButton>
|
#include <QPushButton>
|
||||||
#include <QtConcurrent/qtconcurrentrun.h>
|
#include <QtConcurrent/qtconcurrentrun.h>
|
||||||
#include "common/logging/log.h"
|
#include "common/logging/log.h"
|
||||||
|
#include "common/telemetry.h"
|
||||||
|
#include "core/telemetry_session.h"
|
||||||
#include "suyu/compatdb.h"
|
#include "suyu/compatdb.h"
|
||||||
#include "ui_compatdb.h"
|
#include "ui_compatdb.h"
|
||||||
|
|
||||||
CompatDB::CompatDB(QWidget* parent)
|
CompatDB::CompatDB(Core::TelemetrySession& telemetry_session_, QWidget* parent)
|
||||||
: QWizard(parent, Qt::WindowTitleHint | Qt::WindowCloseButtonHint | Qt::WindowSystemMenuHint),
|
: QWizard(parent, Qt::WindowTitleHint | Qt::WindowCloseButtonHint | Qt::WindowSystemMenuHint),
|
||||||
ui{std::make_unique<Ui::CompatDB>()} {
|
ui{std::make_unique<Ui::CompatDB>()}, telemetry_session{telemetry_session_} {
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
|
|
||||||
connect(ui->radioButton_GameBoot_Yes, &QRadioButton::clicked, this, &CompatDB::EnableNext);
|
connect(ui->radioButton_GameBoot_Yes, &QRadioButton::clicked, this, &CompatDB::EnableNext);
|
||||||
|
@ -112,10 +114,15 @@ void CompatDB::Submit() {
|
||||||
case CompatDBPage::Final:
|
case CompatDBPage::Final:
|
||||||
back();
|
back();
|
||||||
LOG_INFO(Frontend, "Compatibility Rating: {}", compatibility);
|
LOG_INFO(Frontend, "Compatibility Rating: {}", compatibility);
|
||||||
|
telemetry_session.AddField(Common::Telemetry::FieldType::UserFeedback, "Compatibility",
|
||||||
|
compatibility);
|
||||||
|
|
||||||
button(NextButton)->setEnabled(false);
|
button(NextButton)->setEnabled(false);
|
||||||
button(NextButton)->setText(tr("Submitting"));
|
button(NextButton)->setText(tr("Submitting"));
|
||||||
button(CancelButton)->setVisible(false);
|
button(CancelButton)->setVisible(false);
|
||||||
|
|
||||||
|
testcase_watcher.setFuture(
|
||||||
|
QtConcurrent::run([this] { return telemetry_session.SubmitTestcase(); }));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
LOG_ERROR(Frontend, "Unexpected page: {}", currentId());
|
LOG_ERROR(Frontend, "Unexpected page: {}", currentId());
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <QFutureWatcher>
|
#include <QFutureWatcher>
|
||||||
#include <QWizard>
|
#include <QWizard>
|
||||||
|
#include "core/telemetry_session.h"
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
class CompatDB;
|
class CompatDB;
|
||||||
|
@ -24,7 +25,7 @@ class CompatDB : public QWizard {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit CompatDB(QWidget* parent = nullptr);
|
explicit CompatDB(Core::TelemetrySession& telemetry_session_, QWidget* parent = nullptr);
|
||||||
~CompatDB();
|
~CompatDB();
|
||||||
int nextId() const override;
|
int nextId() const override;
|
||||||
|
|
||||||
|
@ -37,4 +38,6 @@ private:
|
||||||
CompatibilityStatus CalculateCompatibility() const;
|
CompatibilityStatus CalculateCompatibility() const;
|
||||||
void OnTestcaseSubmitted();
|
void OnTestcaseSubmitted();
|
||||||
void EnableNext();
|
void EnableNext();
|
||||||
|
|
||||||
|
Core::TelemetrySession& telemetry_session;
|
||||||
};
|
};
|
||||||
|
|
|
@ -32,9 +32,9 @@ ConfigureDialog::ConfigureDialog(QWidget* parent, HotkeyRegistry& registry_,
|
||||||
InputCommon::InputSubsystem* input_subsystem,
|
InputCommon::InputSubsystem* input_subsystem,
|
||||||
std::vector<VkDeviceInfo::Record>& vk_device_records,
|
std::vector<VkDeviceInfo::Record>& vk_device_records,
|
||||||
Core::System& system_, bool enable_web_config)
|
Core::System& system_, bool enable_web_config)
|
||||||
: QDialog(parent), ui{std::make_unique<Ui::ConfigureDialog>()}, registry(registry_),
|
: QDialog(parent), ui{std::make_unique<Ui::ConfigureDialog>()},
|
||||||
system{system_},
|
registry(registry_), system{system_}, builder{std::make_unique<ConfigurationShared::Builder>(
|
||||||
builder{std::make_unique<ConfigurationShared::Builder>(this, !system_.IsPoweredOn())},
|
this, !system_.IsPoweredOn())},
|
||||||
applets_tab{std::make_unique<ConfigureApplets>(system_, nullptr, *builder, this)},
|
applets_tab{std::make_unique<ConfigureApplets>(system_, nullptr, *builder, this)},
|
||||||
audio_tab{std::make_unique<ConfigureAudio>(system_, nullptr, *builder, this)},
|
audio_tab{std::make_unique<ConfigureAudio>(system_, nullptr, *builder, this)},
|
||||||
cpu_tab{std::make_unique<ConfigureCpu>(system_, nullptr, *builder, this)},
|
cpu_tab{std::make_unique<ConfigureCpu>(system_, nullptr, *builder, this)},
|
||||||
|
|
|
@ -293,11 +293,11 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
|
||||||
InputCommon::InputSubsystem* input_subsystem_,
|
InputCommon::InputSubsystem* input_subsystem_,
|
||||||
InputProfiles* profiles_, Core::HID::HIDCore& hid_core_,
|
InputProfiles* profiles_, Core::HID::HIDCore& hid_core_,
|
||||||
bool is_powered_on_, bool debug_)
|
bool is_powered_on_, bool debug_)
|
||||||
: QWidget(parent), ui(std::make_unique<Ui::ConfigureInputPlayer>()),
|
: QWidget(parent),
|
||||||
player_index{player_index_}, debug{debug_}, is_powered_on{is_powered_on_},
|
ui(std::make_unique<Ui::ConfigureInputPlayer>()), player_index{player_index_}, debug{debug_},
|
||||||
input_subsystem{input_subsystem_}, profiles(profiles_),
|
is_powered_on{is_powered_on_}, input_subsystem{input_subsystem_}, profiles(profiles_),
|
||||||
timeout_timer(std::make_unique<QTimer>()), poll_timer(std::make_unique<QTimer>()),
|
timeout_timer(std::make_unique<QTimer>()),
|
||||||
bottom_row{bottom_row_}, hid_core{hid_core_} {
|
poll_timer(std::make_unique<QTimer>()), bottom_row{bottom_row_}, hid_core{hid_core_} {
|
||||||
if (player_index == 0) {
|
if (player_index == 0) {
|
||||||
auto* emulated_controller_p1 =
|
auto* emulated_controller_p1 =
|
||||||
hid_core.GetEmulatedController(Core::HID::NpadIdType::Player1);
|
hid_core.GetEmulatedController(Core::HID::NpadIdType::Player1);
|
||||||
|
|
|
@ -43,7 +43,7 @@
|
||||||
<number>1</number>
|
<number>1</number>
|
||||||
</property>
|
</property>
|
||||||
<property name="maximum">
|
<property name="maximum">
|
||||||
<number>200</number>
|
<number>100</number>
|
||||||
</property>
|
</property>
|
||||||
<property name="value">
|
<property name="value">
|
||||||
<number>50</number>
|
<number>50</number>
|
||||||
|
@ -69,7 +69,7 @@
|
||||||
<number>1</number>
|
<number>1</number>
|
||||||
</property>
|
</property>
|
||||||
<property name="maximum">
|
<property name="maximum">
|
||||||
<number>200</number>
|
<number>100</number>
|
||||||
</property>
|
</property>
|
||||||
<property name="value">
|
<property name="value">
|
||||||
<number>50</number>
|
<number>50</number>
|
||||||
|
|
|
@ -17,17 +17,14 @@
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
|
|
||||||
#include "common/fs/fs_util.h"
|
#include "common/fs/fs_util.h"
|
||||||
#include "common/hex_util.h"
|
|
||||||
#include "common/settings_enums.h"
|
#include "common/settings_enums.h"
|
||||||
#include "common/settings_input.h"
|
#include "common/settings_input.h"
|
||||||
#include "configuration/shared_widget.h"
|
#include "configuration/shared_widget.h"
|
||||||
#include "core/core.h"
|
#include "core/core.h"
|
||||||
#include "core/file_sys/control_metadata.h"
|
#include "core/file_sys/control_metadata.h"
|
||||||
#include "core/file_sys/ips_layer.h"
|
|
||||||
#include "core/file_sys/patch_manager.h"
|
#include "core/file_sys/patch_manager.h"
|
||||||
#include "core/file_sys/xts_archive.h"
|
#include "core/file_sys/xts_archive.h"
|
||||||
#include "core/loader/loader.h"
|
#include "core/loader/loader.h"
|
||||||
#include "core/loader/nso.h"
|
|
||||||
#include "frontend_common/config.h"
|
#include "frontend_common/config.h"
|
||||||
#include "suyu/configuration/configuration_shared.h"
|
#include "suyu/configuration/configuration_shared.h"
|
||||||
#include "suyu/configuration/configure_audio.h"
|
#include "suyu/configuration/configure_audio.h"
|
||||||
|
@ -47,12 +44,10 @@
|
||||||
ConfigurePerGame::ConfigurePerGame(QWidget* parent, u64 title_id_, const std::string& file_name,
|
ConfigurePerGame::ConfigurePerGame(QWidget* parent, u64 title_id_, const std::string& file_name,
|
||||||
std::vector<VkDeviceInfo::Record>& vk_device_records,
|
std::vector<VkDeviceInfo::Record>& vk_device_records,
|
||||||
Core::System& system_)
|
Core::System& system_)
|
||||||
: QDialog(parent), ui(std::make_unique<Ui::ConfigurePerGame>()),
|
: QDialog(parent),
|
||||||
pm{title_id_, system_.GetFileSystemController(), system_.GetContentProvider()},
|
ui(std::make_unique<Ui::ConfigurePerGame>()), title_id{title_id_}, system{system_},
|
||||||
title_id{title_id_}, system{system_},
|
|
||||||
builder{std::make_unique<ConfigurationShared::Builder>(this, !system_.IsPoweredOn())},
|
builder{std::make_unique<ConfigurationShared::Builder>(this, !system_.IsPoweredOn())},
|
||||||
tab_group{std::make_shared<std::vector<ConfigurationShared::Tab*>>()} {
|
tab_group{std::make_shared<std::vector<ConfigurationShared::Tab*>>()} {
|
||||||
|
|
||||||
const auto file_path = std::filesystem::path(Common::FS::ToU8String(file_name));
|
const auto file_path = std::filesystem::path(Common::FS::ToU8String(file_name));
|
||||||
const auto config_file_name = title_id == 0 ? Common::FS::PathToUTF8String(file_path.filename())
|
const auto config_file_name = title_id == 0 ? Common::FS::PathToUTF8String(file_path.filename())
|
||||||
: fmt::format("{:016X}", title_id);
|
: fmt::format("{:016X}", title_id);
|
||||||
|
@ -146,14 +141,6 @@ void ConfigurePerGame::LoadFromFile(FileSys::VirtualFile file_) {
|
||||||
LoadConfiguration();
|
LoadConfiguration();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string ConfigurePerGame::GetBuildID() {
|
|
||||||
LOG_INFO(Core, "{}", file->GetExtension());
|
|
||||||
|
|
||||||
// https://github.com/Ryujinx/Ryujinx/blob/master/src/Ryujinx.UI.Common/App/ApplicationData.cs#L71
|
|
||||||
|
|
||||||
return "Invalid File";
|
|
||||||
}
|
|
||||||
|
|
||||||
void ConfigurePerGame::LoadConfiguration() {
|
void ConfigurePerGame::LoadConfiguration() {
|
||||||
if (file == nullptr) {
|
if (file == nullptr) {
|
||||||
return;
|
return;
|
||||||
|
@ -161,14 +148,13 @@ void ConfigurePerGame::LoadConfiguration() {
|
||||||
|
|
||||||
addons_tab->LoadFromFile(file);
|
addons_tab->LoadFromFile(file);
|
||||||
|
|
||||||
const auto control = pm.GetControlMetadata();
|
|
||||||
const auto loader = Loader::GetLoader(system, file);
|
|
||||||
|
|
||||||
ui->display_title_id->setText(
|
ui->display_title_id->setText(
|
||||||
QStringLiteral("%1").arg(title_id, 16, 16, QLatin1Char{'0'}).toUpper());
|
QStringLiteral("%1").arg(title_id, 16, 16, QLatin1Char{'0'}).toUpper());
|
||||||
|
|
||||||
// TODO: Should get proper build id for UI
|
const FileSys::PatchManager pm{title_id, system.GetFileSystemController(),
|
||||||
// ui->display_build_id->setText(QString::fromStdString(GetBuildID()));
|
system.GetContentProvider()};
|
||||||
|
const auto control = pm.GetControlMetadata();
|
||||||
|
const auto loader = Loader::GetLoader(system, file);
|
||||||
|
|
||||||
if (control.first != nullptr) {
|
if (control.first != nullptr) {
|
||||||
ui->display_version->setText(QString::fromStdString(control.first->GetVersionString()));
|
ui->display_version->setText(QString::fromStdString(control.first->GetVersionString()));
|
||||||
|
|
|
@ -11,7 +11,6 @@
|
||||||
#include <QList>
|
#include <QList>
|
||||||
|
|
||||||
#include "configuration/shared_widget.h"
|
#include "configuration/shared_widget.h"
|
||||||
#include "core/file_sys/patch_manager.h"
|
|
||||||
#include "core/file_sys/vfs/vfs_types.h"
|
#include "core/file_sys/vfs/vfs_types.h"
|
||||||
#include "frontend_common/config.h"
|
#include "frontend_common/config.h"
|
||||||
#include "suyu/configuration/configuration_shared.h"
|
#include "suyu/configuration/configuration_shared.h"
|
||||||
|
@ -69,11 +68,8 @@ private:
|
||||||
|
|
||||||
void LoadConfiguration();
|
void LoadConfiguration();
|
||||||
|
|
||||||
std::string GetBuildID();
|
|
||||||
|
|
||||||
std::unique_ptr<Ui::ConfigurePerGame> ui;
|
std::unique_ptr<Ui::ConfigurePerGame> ui;
|
||||||
FileSys::VirtualFile file;
|
FileSys::VirtualFile file;
|
||||||
FileSys::PatchManager pm;
|
|
||||||
u64 title_id;
|
u64 title_id;
|
||||||
|
|
||||||
QGraphicsScene* scene;
|
QGraphicsScene* scene;
|
||||||
|
|
|
@ -67,18 +67,8 @@
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<layout class="QGridLayout" name="gridLayout_2">
|
<layout class="QGridLayout" name="gridLayout_2">
|
||||||
<item row="2" column="1">
|
|
||||||
<widget class="QLineEdit" name="display_developer">
|
|
||||||
<property name="enabled">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
<property name="readOnly">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="6" column="1">
|
<item row="6" column="1">
|
||||||
<widget class="QLineEdit" name="display_format">
|
<widget class="QLineEdit" name="display_size">
|
||||||
<property name="enabled">
|
<property name="enabled">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
|
@ -87,58 +77,6 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="7" column="0">
|
|
||||||
<widget class="QLabel" name="label_6">
|
|
||||||
<property name="text">
|
|
||||||
<string>Size</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="8" column="0">
|
|
||||||
<widget class="QLabel" name="label_7">
|
|
||||||
<property name="text">
|
|
||||||
<string>Filename</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="4" column="0">
|
|
||||||
<widget class="QLabel" name="label_4">
|
|
||||||
<property name="text">
|
|
||||||
<string>Title ID</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="0">
|
|
||||||
<widget class="QLabel" name="label">
|
|
||||||
<property name="text">
|
|
||||||
<string>Name</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="4" column="1">
|
|
||||||
<widget class="QLineEdit" name="display_title_id">
|
|
||||||
<property name="enabled">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
<property name="readOnly">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="0">
|
|
||||||
<widget class="QLabel" name="label_2">
|
|
||||||
<property name="text">
|
|
||||||
<string>Developer</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="6" column="0">
|
|
||||||
<widget class="QLabel" name="label_5">
|
|
||||||
<property name="text">
|
|
||||||
<string>Format</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="3" column="1">
|
<item row="3" column="1">
|
||||||
<widget class="QLineEdit" name="display_version">
|
<widget class="QLineEdit" name="display_version">
|
||||||
<property name="enabled">
|
<property name="enabled">
|
||||||
|
@ -149,14 +87,31 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="3" column="0">
|
<item row="1" column="0">
|
||||||
<widget class="QLabel" name="label_3">
|
<widget class="QLabel" name="label">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Version</string>
|
<string>Name</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="8" column="1">
|
<item row="4" column="0">
|
||||||
|
<widget class="QLabel" name="label_4">
|
||||||
|
<property name="text">
|
||||||
|
<string>Title ID</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="4" column="1">
|
||||||
|
<widget class="QLineEdit" name="display_title_id">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="readOnly">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="7" column="1">
|
||||||
<widget class="QLineEdit" name="display_filename">
|
<widget class="QLineEdit" name="display_filename">
|
||||||
<property name="enabled">
|
<property name="enabled">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
|
@ -166,6 +121,23 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="5" column="1">
|
||||||
|
<widget class="QLineEdit" name="display_format">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="readOnly">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="7" column="0">
|
||||||
|
<widget class="QLabel" name="label_7">
|
||||||
|
<property name="text">
|
||||||
|
<string>Filename</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item row="1" column="1">
|
<item row="1" column="1">
|
||||||
<widget class="QLineEdit" name="display_name">
|
<widget class="QLineEdit" name="display_name">
|
||||||
<property name="enabled">
|
<property name="enabled">
|
||||||
|
@ -176,8 +148,8 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="7" column="1">
|
<item row="2" column="1">
|
||||||
<widget class="QLineEdit" name="display_size">
|
<widget class="QLineEdit" name="display_developer">
|
||||||
<property name="enabled">
|
<property name="enabled">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
|
@ -186,21 +158,34 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<!-- TODO: Gotta implement proper working build id -->
|
<item row="5" column="0">
|
||||||
<!--item row="5" column="1">
|
<widget class="QLabel" name="label_5">
|
||||||
<widget class="QLineEdit" name="display_build_id">
|
<property name="text">
|
||||||
<property name="readOnly">
|
<string>Format</string>
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="5" column="0">
|
<item row="3" column="0">
|
||||||
<widget class="QLabel" name="label_9">
|
<widget class="QLabel" name="label_3">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Build ID</string>
|
<string>Version</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item-->
|
</item>
|
||||||
|
<item row="6" column="0">
|
||||||
|
<widget class="QLabel" name="label_6">
|
||||||
|
<property name="text">
|
||||||
|
<string>Size</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="0">
|
||||||
|
<widget class="QLabel" name="label_2">
|
||||||
|
<property name="text">
|
||||||
|
<string>Developer</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
#include <QtConcurrent/QtConcurrentRun>
|
#include <QtConcurrent/QtConcurrentRun>
|
||||||
#include "common/settings.h"
|
#include "common/settings.h"
|
||||||
|
#include "core/telemetry_session.h"
|
||||||
#include "suyu/configuration/configure_web.h"
|
#include "suyu/configuration/configure_web.h"
|
||||||
#include "suyu/uisettings.h"
|
#include "suyu/uisettings.h"
|
||||||
#include "ui_configure_web.h"
|
#include "ui_configure_web.h"
|
||||||
|
@ -37,6 +38,8 @@ static std::string TokenFromDisplayToken(const std::string& display_token) {
|
||||||
ConfigureWeb::ConfigureWeb(QWidget* parent)
|
ConfigureWeb::ConfigureWeb(QWidget* parent)
|
||||||
: QWidget(parent), ui(std::make_unique<Ui::ConfigureWeb>()) {
|
: QWidget(parent), ui(std::make_unique<Ui::ConfigureWeb>()) {
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
|
connect(ui->button_regenerate_telemetry_id, &QPushButton::clicked, this,
|
||||||
|
&ConfigureWeb::RefreshTelemetryID);
|
||||||
connect(ui->button_verify_login, &QPushButton::clicked, this, &ConfigureWeb::VerifyLogin);
|
connect(ui->button_verify_login, &QPushButton::clicked, this, &ConfigureWeb::VerifyLogin);
|
||||||
connect(&verify_watcher, &QFutureWatcher<bool>::finished, this, &ConfigureWeb::OnLoginVerified);
|
connect(&verify_watcher, &QFutureWatcher<bool>::finished, this, &ConfigureWeb::OnLoginVerified);
|
||||||
|
|
||||||
|
@ -61,6 +64,10 @@ void ConfigureWeb::changeEvent(QEvent* event) {
|
||||||
void ConfigureWeb::RetranslateUI() {
|
void ConfigureWeb::RetranslateUI() {
|
||||||
ui->retranslateUi(this);
|
ui->retranslateUi(this);
|
||||||
|
|
||||||
|
ui->telemetry_learn_more->setText(
|
||||||
|
tr("<a href='https://suyu.dev/help/feature/telemetry/'><span style=\"text-decoration: "
|
||||||
|
"underline; color:#039be5;\">Learn more</span></a>"));
|
||||||
|
|
||||||
ui->web_signup_link->setText(
|
ui->web_signup_link->setText(
|
||||||
tr("<a href='https://profile.suyu.dev/'><span style=\"text-decoration: underline; "
|
tr("<a href='https://profile.suyu.dev/'><span style=\"text-decoration: underline; "
|
||||||
"color:#039be5;\">Sign up</span></a>"));
|
"color:#039be5;\">Sign up</span></a>"));
|
||||||
|
@ -68,11 +75,15 @@ void ConfigureWeb::RetranslateUI() {
|
||||||
ui->web_token_info_link->setText(
|
ui->web_token_info_link->setText(
|
||||||
tr("<a href='https://suyu.dev/wiki/suyu-web-service/'><span style=\"text-decoration: "
|
tr("<a href='https://suyu.dev/wiki/suyu-web-service/'><span style=\"text-decoration: "
|
||||||
"underline; color:#039be5;\">What is my token?</span></a>"));
|
"underline; color:#039be5;\">What is my token?</span></a>"));
|
||||||
|
|
||||||
|
ui->label_telemetry_id->setText(
|
||||||
|
tr("Telemetry ID: 0x%1").arg(QString::number(Core::GetTelemetryId(), 16).toUpper()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConfigureWeb::SetConfiguration() {
|
void ConfigureWeb::SetConfiguration() {
|
||||||
ui->web_credentials_disclaimer->setWordWrap(true);
|
ui->web_credentials_disclaimer->setWordWrap(true);
|
||||||
|
|
||||||
|
ui->telemetry_learn_more->setOpenExternalLinks(true);
|
||||||
ui->web_signup_link->setOpenExternalLinks(true);
|
ui->web_signup_link->setOpenExternalLinks(true);
|
||||||
ui->web_token_info_link->setOpenExternalLinks(true);
|
ui->web_token_info_link->setOpenExternalLinks(true);
|
||||||
|
|
||||||
|
@ -82,6 +93,7 @@ void ConfigureWeb::SetConfiguration() {
|
||||||
ui->username->setText(QString::fromStdString(Settings::values.suyu_username.GetValue()));
|
ui->username->setText(QString::fromStdString(Settings::values.suyu_username.GetValue()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ui->toggle_telemetry->setChecked(Settings::values.enable_telemetry.GetValue());
|
||||||
ui->edit_token->setText(QString::fromStdString(GenerateDisplayToken(
|
ui->edit_token->setText(QString::fromStdString(GenerateDisplayToken(
|
||||||
Settings::values.suyu_username.GetValue(), Settings::values.suyu_token.GetValue())));
|
Settings::values.suyu_username.GetValue(), Settings::values.suyu_token.GetValue())));
|
||||||
|
|
||||||
|
@ -94,6 +106,7 @@ void ConfigureWeb::SetConfiguration() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConfigureWeb::ApplyConfiguration() {
|
void ConfigureWeb::ApplyConfiguration() {
|
||||||
|
Settings::values.enable_telemetry = ui->toggle_telemetry->isChecked();
|
||||||
UISettings::values.enable_discord_presence = ui->toggle_discordrpc->isChecked();
|
UISettings::values.enable_discord_presence = ui->toggle_discordrpc->isChecked();
|
||||||
if (user_verified) {
|
if (user_verified) {
|
||||||
Settings::values.suyu_username =
|
Settings::values.suyu_username =
|
||||||
|
@ -106,6 +119,12 @@ void ConfigureWeb::ApplyConfiguration() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ConfigureWeb::RefreshTelemetryID() {
|
||||||
|
const u64 new_telemetry_id{Core::RegenerateTelemetryId()};
|
||||||
|
ui->label_telemetry_id->setText(
|
||||||
|
tr("Telemetry ID: 0x%1").arg(QString::number(new_telemetry_id, 16).toUpper()));
|
||||||
|
}
|
||||||
|
|
||||||
void ConfigureWeb::OnLoginChanged() {
|
void ConfigureWeb::OnLoginChanged() {
|
||||||
if (ui->edit_token->text().isEmpty()) {
|
if (ui->edit_token->text().isEmpty()) {
|
||||||
user_verified = true;
|
user_verified = true;
|
||||||
|
@ -131,12 +150,7 @@ void ConfigureWeb::VerifyLogin() {
|
||||||
verify_watcher.setFuture(QtConcurrent::run(
|
verify_watcher.setFuture(QtConcurrent::run(
|
||||||
[username = UsernameFromDisplayToken(ui->edit_token->text().toStdString()),
|
[username = UsernameFromDisplayToken(ui->edit_token->text().toStdString()),
|
||||||
token = TokenFromDisplayToken(ui->edit_token->text().toStdString())] {
|
token = TokenFromDisplayToken(ui->edit_token->text().toStdString())] {
|
||||||
#ifdef ENABLE_WEB_SERVICE
|
return Core::VerifyLogin(username, token);
|
||||||
return WebService::VerifyLogin(Settings::values.web_api_url.GetValue(), username,
|
|
||||||
token);
|
|
||||||
#else
|
|
||||||
return false;
|
|
||||||
#endif
|
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,7 @@ private:
|
||||||
void changeEvent(QEvent* event) override;
|
void changeEvent(QEvent* event) override;
|
||||||
void RetranslateUI();
|
void RetranslateUI();
|
||||||
|
|
||||||
|
void RefreshTelemetryID();
|
||||||
void OnLoginChanged();
|
void OnLoginChanged();
|
||||||
void VerifyLogin();
|
void VerifyLogin();
|
||||||
void OnLoginVerified();
|
void OnLoginVerified();
|
||||||
|
|
|
@ -125,6 +125,56 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QGroupBox" name="groupBox">
|
||||||
|
<property name="title">
|
||||||
|
<string>Telemetry</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||||
|
<item>
|
||||||
|
<widget class="QCheckBox" name="toggle_telemetry">
|
||||||
|
<property name="text">
|
||||||
|
<string>Share anonymous usage data with the suyu team</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="telemetry_learn_more">
|
||||||
|
<property name="text">
|
||||||
|
<string>Learn more</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QGridLayout" name="gridLayoutTelemetryId">
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QLabel" name="label_telemetry_id">
|
||||||
|
<property name="text">
|
||||||
|
<string>Telemetry ID:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="1">
|
||||||
|
<widget class="QPushButton" name="button_regenerate_telemetry_id">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="layoutDirection">
|
||||||
|
<enum>Qt::RightToLeft</enum>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Regenerate</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
|
|
|
@ -766,8 +766,8 @@ Widget::Widget(Settings::BasicSetting* setting_, const TranslationMap& translati
|
||||||
|
|
||||||
Builder::Builder(QWidget* parent_, bool runtime_lock_)
|
Builder::Builder(QWidget* parent_, bool runtime_lock_)
|
||||||
: translations{InitializeTranslations(parent_)},
|
: translations{InitializeTranslations(parent_)},
|
||||||
combobox_translations{ComboboxEnumeration(parent_)}, parent{parent_},
|
combobox_translations{ComboboxEnumeration(parent_)}, parent{parent_}, runtime_lock{
|
||||||
runtime_lock{runtime_lock_} {}
|
runtime_lock_} {}
|
||||||
|
|
||||||
Builder::~Builder() = default;
|
Builder::~Builder() = default;
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
// Modified by palfaiate on <2024/03/07>
|
// Modified by palfaiate on <2024/03/07>
|
||||||
|
|
||||||
|
#include <regex>
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QFileInfo>
|
#include <QFileInfo>
|
||||||
|
@ -383,17 +384,6 @@ GameList::~GameList() {
|
||||||
UnloadController();
|
UnloadController();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameList::ClearList() {
|
|
||||||
// Clear all items
|
|
||||||
item_model->setRowCount(0);
|
|
||||||
|
|
||||||
// Notify a reload is pending
|
|
||||||
UISettings::values.is_game_list_reload_pending.exchange(true);
|
|
||||||
UISettings::values.is_game_list_reload_pending.notify_all();
|
|
||||||
|
|
||||||
// Load stuff back up
|
|
||||||
}
|
|
||||||
|
|
||||||
void GameList::SetFilterFocus() {
|
void GameList::SetFilterFocus() {
|
||||||
if (tree_view->model()->rowCount() > 0) {
|
if (tree_view->model()->rowCount() > 0) {
|
||||||
search_field->setFocus();
|
search_field->setFocus();
|
||||||
|
@ -423,10 +413,6 @@ void GameList::AddEntry(const QList<QStandardItem*>& entry_items, GameListDir* p
|
||||||
parent->appendRow(entry_items);
|
parent->appendRow(entry_items);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameList::AddRootEntry(const QList<QStandardItem*>& entry_items) {
|
|
||||||
item_model->invisibleRootItem()->appendRow(entry_items);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GameList::ValidateEntry(const QModelIndex& item) {
|
void GameList::ValidateEntry(const QModelIndex& item) {
|
||||||
const auto selected = item.sibling(item.row(), 0);
|
const auto selected = item.sibling(item.row(), 0);
|
||||||
|
|
||||||
|
@ -482,9 +468,7 @@ bool GameList::IsEmpty() const {
|
||||||
void GameList::DonePopulating(const QStringList& watch_list) {
|
void GameList::DonePopulating(const QStringList& watch_list) {
|
||||||
emit ShowList(!IsEmpty());
|
emit ShowList(!IsEmpty());
|
||||||
|
|
||||||
if (UISettings::values.show_folders_in_list) {
|
|
||||||
item_model->invisibleRootItem()->appendRow(new GameListAddDir());
|
item_model->invisibleRootItem()->appendRow(new GameListAddDir());
|
||||||
}
|
|
||||||
|
|
||||||
// Add favorites row
|
// Add favorites row
|
||||||
item_model->invisibleRootItem()->insertRow(0, new GameListFavorites());
|
item_model->invisibleRootItem()->insertRow(0, new GameListFavorites());
|
||||||
|
@ -501,7 +485,6 @@ void GameList::DonePopulating(const QStringList& watch_list) {
|
||||||
if (!watch_dirs.isEmpty()) {
|
if (!watch_dirs.isEmpty()) {
|
||||||
watcher->removePaths(watch_dirs);
|
watcher->removePaths(watch_dirs);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Workaround: Add the watch paths in chunks to allow the gui to refresh
|
// Workaround: Add the watch paths in chunks to allow the gui to refresh
|
||||||
// This prevents the UI from stalling when a large number of watch paths are added
|
// This prevents the UI from stalling when a large number of watch paths are added
|
||||||
// Also artificially caps the watcher to a certain number of directories
|
// Also artificially caps the watcher to a certain number of directories
|
||||||
|
@ -903,8 +886,7 @@ void GameList::ToggleFavorite(u64 program_id) {
|
||||||
void GameList::AddFavorite(u64 program_id) {
|
void GameList::AddFavorite(u64 program_id) {
|
||||||
auto* favorites_row = item_model->item(0);
|
auto* favorites_row = item_model->item(0);
|
||||||
|
|
||||||
if (UISettings::values.show_folders_in_list) {
|
for (int i = 1; i < item_model->rowCount() - 1; i++) {
|
||||||
for (int i = 0; i < item_model->rowCount(); i++) {
|
|
||||||
const auto* folder = item_model->item(i);
|
const auto* folder = item_model->item(i);
|
||||||
for (int j = 0; j < folder->rowCount(); j++) {
|
for (int j = 0; j < folder->rowCount(); j++) {
|
||||||
if (folder->child(j)->data(GameListItemPath::ProgramIdRole).toULongLong() ==
|
if (folder->child(j)->data(GameListItemPath::ProgramIdRole).toULongLong() ==
|
||||||
|
@ -922,26 +904,6 @@ void GameList::AddFavorite(u64 program_id) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
for (int i = 0; i < item_model->rowCount(); i++) {
|
|
||||||
const auto* game = item_model->item(i);
|
|
||||||
if (game->data(GameListItemPath::ProgramIdRole).toULongLong() != program_id) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
QList<QStandardItem*> list;
|
|
||||||
for (int j = 0; j < COLUMN_COUNT; j++) {
|
|
||||||
list.append(item_model->item(i, j)->clone());
|
|
||||||
}
|
|
||||||
|
|
||||||
list[0]->setData(game->data(GameListItem::SortRole), GameListItem::SortRole);
|
|
||||||
list[0]->setText(game->data(Qt::DisplayRole).toString());
|
|
||||||
|
|
||||||
favorites_row->appendRow(list);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameList::RemoveFavorite(u64 program_id) {
|
void GameList::RemoveFavorite(u64 program_id) {
|
||||||
|
|
|
@ -84,7 +84,6 @@ public:
|
||||||
~GameList() override;
|
~GameList() override;
|
||||||
|
|
||||||
QString GetLastFilterResultItem() const;
|
QString GetLastFilterResultItem() const;
|
||||||
void ClearList();
|
|
||||||
void ClearFilter();
|
void ClearFilter();
|
||||||
void SetFilterFocus();
|
void SetFilterFocus();
|
||||||
void SetFilterVisible(bool visibility);
|
void SetFilterVisible(bool visibility);
|
||||||
|
@ -138,7 +137,6 @@ private:
|
||||||
|
|
||||||
void AddDirEntry(GameListDir* entry_items);
|
void AddDirEntry(GameListDir* entry_items);
|
||||||
void AddEntry(const QList<QStandardItem*>& entry_items, GameListDir* parent);
|
void AddEntry(const QList<QStandardItem*>& entry_items, GameListDir* parent);
|
||||||
void AddRootEntry(const QList<QStandardItem*>& entry_items);
|
|
||||||
void DonePopulating(const QStringList& watch_list);
|
void DonePopulating(const QStringList& watch_list);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -234,8 +234,8 @@ GameListWorker::GameListWorker(FileSys::VirtualFilesystem vfs_,
|
||||||
const PlayTime::PlayTimeManager& play_time_manager_,
|
const PlayTime::PlayTimeManager& play_time_manager_,
|
||||||
Core::System& system_)
|
Core::System& system_)
|
||||||
: vfs{std::move(vfs_)}, provider{provider_}, game_dirs{game_dirs_},
|
: vfs{std::move(vfs_)}, provider{provider_}, game_dirs{game_dirs_},
|
||||||
compatibility_list{compatibility_list_}, play_time_manager{play_time_manager_},
|
compatibility_list{compatibility_list_}, play_time_manager{play_time_manager_}, system{
|
||||||
system{system_} {
|
system_} {
|
||||||
// We want the game list to manage our lifetime.
|
// We want the game list to manage our lifetime.
|
||||||
setAutoDelete(false);
|
setAutoDelete(false);
|
||||||
}
|
}
|
||||||
|
@ -330,13 +330,7 @@ void GameListWorker::AddTitlesToGameList(GameListDir* parent_dir) {
|
||||||
|
|
||||||
auto entry = MakeGameListEntry(file->GetFullPath(), name, file->GetSize(), icon, *loader,
|
auto entry = MakeGameListEntry(file->GetFullPath(), name, file->GetSize(), icon, *loader,
|
||||||
program_id, compatibility_list, play_time_manager, patch);
|
program_id, compatibility_list, play_time_manager, patch);
|
||||||
RecordEvent([=](GameList* game_list) {
|
RecordEvent([=](GameList* game_list) { game_list->AddEntry(entry, parent_dir); });
|
||||||
if (UISettings::values.show_folders_in_list) {
|
|
||||||
game_list->AddEntry(entry, parent_dir);
|
|
||||||
} else {
|
|
||||||
game_list->AddRootEntry(entry);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -414,7 +408,8 @@ void GameListWorker::ScanFileSystem(ScanTarget target, const std::string& dir_pa
|
||||||
physical_name, name, Common::FS::GetSize(physical_name), icon, *loader,
|
physical_name, name, Common::FS::GetSize(physical_name), icon, *loader,
|
||||||
id, compatibility_list, play_time_manager, patch);
|
id, compatibility_list, play_time_manager, patch);
|
||||||
|
|
||||||
RecordEvent([=](GameList* game_list) { game_list->AddRootEntry(entry); });
|
RecordEvent(
|
||||||
|
[=](GameList* game_list) { game_list->AddEntry(entry, parent_dir); });
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
std::vector<u8> icon;
|
std::vector<u8> icon;
|
||||||
|
@ -430,13 +425,8 @@ void GameListWorker::ScanFileSystem(ScanTarget target, const std::string& dir_pa
|
||||||
physical_name, name, Common::FS::GetSize(physical_name), icon, *loader,
|
physical_name, name, Common::FS::GetSize(physical_name), icon, *loader,
|
||||||
program_id, compatibility_list, play_time_manager, patch);
|
program_id, compatibility_list, play_time_manager, patch);
|
||||||
|
|
||||||
RecordEvent([=](GameList* game_list) {
|
RecordEvent(
|
||||||
if (UISettings::values.show_folders_in_list) {
|
[=](GameList* game_list) { game_list->AddEntry(entry, parent_dir); });
|
||||||
game_list->AddEntry(entry, parent_dir);
|
|
||||||
} else {
|
|
||||||
game_list->AddRootEntry(entry);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (is_dir) {
|
} else if (is_dir) {
|
||||||
|
@ -469,32 +459,20 @@ void GameListWorker::run() {
|
||||||
|
|
||||||
if (game_dir.path == std::string("SDMC")) {
|
if (game_dir.path == std::string("SDMC")) {
|
||||||
auto* const game_list_dir = new GameListDir(game_dir, GameListItemType::SdmcDir);
|
auto* const game_list_dir = new GameListDir(game_dir, GameListItemType::SdmcDir);
|
||||||
|
|
||||||
if (UISettings::values.show_folders_in_list)
|
|
||||||
DirEntryReady(game_list_dir);
|
DirEntryReady(game_list_dir);
|
||||||
|
|
||||||
AddTitlesToGameList(game_list_dir);
|
AddTitlesToGameList(game_list_dir);
|
||||||
} else if (game_dir.path == std::string("UserNAND")) {
|
} else if (game_dir.path == std::string("UserNAND")) {
|
||||||
auto* const game_list_dir = new GameListDir(game_dir, GameListItemType::UserNandDir);
|
auto* const game_list_dir = new GameListDir(game_dir, GameListItemType::UserNandDir);
|
||||||
|
|
||||||
if (UISettings::values.show_folders_in_list)
|
|
||||||
DirEntryReady(game_list_dir);
|
DirEntryReady(game_list_dir);
|
||||||
|
|
||||||
AddTitlesToGameList(game_list_dir);
|
AddTitlesToGameList(game_list_dir);
|
||||||
} else if (game_dir.path == std::string("SysNAND")) {
|
} else if (game_dir.path == std::string("SysNAND")) {
|
||||||
auto* const game_list_dir = new GameListDir(game_dir, GameListItemType::SysNandDir);
|
auto* const game_list_dir = new GameListDir(game_dir, GameListItemType::SysNandDir);
|
||||||
|
|
||||||
if (UISettings::values.show_folders_in_list)
|
|
||||||
DirEntryReady(game_list_dir);
|
DirEntryReady(game_list_dir);
|
||||||
|
|
||||||
AddTitlesToGameList(game_list_dir);
|
AddTitlesToGameList(game_list_dir);
|
||||||
} else {
|
} else {
|
||||||
watch_list.append(QString::fromStdString(game_dir.path));
|
watch_list.append(QString::fromStdString(game_dir.path));
|
||||||
auto* const game_list_dir = new GameListDir(game_dir);
|
auto* const game_list_dir = new GameListDir(game_dir);
|
||||||
|
|
||||||
if (UISettings::values.show_folders_in_list)
|
|
||||||
DirEntryReady(game_list_dir);
|
DirEntryReady(game_list_dir);
|
||||||
|
|
||||||
ScanFileSystem(ScanTarget::FillManualContentProvider, game_dir.path, game_dir.deep_scan,
|
ScanFileSystem(ScanTarget::FillManualContentProvider, game_dir.path, game_dir.deep_scan,
|
||||||
game_list_dir);
|
game_list_dir);
|
||||||
ScanFileSystem(ScanTarget::PopulateGameList, game_dir.path, game_dir.deep_scan,
|
ScanFileSystem(ScanTarget::PopulateGameList, game_dir.path, game_dir.deep_scan,
|
||||||
|
|
|
@ -100,6 +100,7 @@
|
||||||
#include "common/x64/cpu_detect.h"
|
#include "common/x64/cpu_detect.h"
|
||||||
#endif
|
#endif
|
||||||
#include "common/settings.h"
|
#include "common/settings.h"
|
||||||
|
#include "common/telemetry.h"
|
||||||
#include "core/core.h"
|
#include "core/core.h"
|
||||||
#include "core/core_timing.h"
|
#include "core/core_timing.h"
|
||||||
#include "core/crypto/key_manager.h"
|
#include "core/crypto/key_manager.h"
|
||||||
|
@ -118,6 +119,7 @@
|
||||||
#include "core/hle/service/sm/sm.h"
|
#include "core/hle/service/sm/sm.h"
|
||||||
#include "core/loader/loader.h"
|
#include "core/loader/loader.h"
|
||||||
#include "core/perf_stats.h"
|
#include "core/perf_stats.h"
|
||||||
|
#include "core/telemetry_session.h"
|
||||||
#include "frontend_common/config.h"
|
#include "frontend_common/config.h"
|
||||||
#include "input_common/drivers/tas_input.h"
|
#include "input_common/drivers/tas_input.h"
|
||||||
#include "input_common/drivers/virtual_amiibo.h"
|
#include "input_common/drivers/virtual_amiibo.h"
|
||||||
|
@ -186,9 +188,28 @@ constexpr size_t CopyBufferSize = 1_MiB;
|
||||||
* user. This is 32-bits - if we have more than 32 callouts, we should retire and recycle old ones.
|
* user. This is 32-bits - if we have more than 32 callouts, we should retire and recycle old ones.
|
||||||
*/
|
*/
|
||||||
enum class CalloutFlag : uint32_t {
|
enum class CalloutFlag : uint32_t {
|
||||||
|
Telemetry = 0x1,
|
||||||
DRDDeprecation = 0x2,
|
DRDDeprecation = 0x2,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void GMainWindow::ShowTelemetryCallout() {
|
||||||
|
if (UISettings::values.callout_flags.GetValue() &
|
||||||
|
static_cast<uint32_t>(CalloutFlag::Telemetry)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
UISettings::values.callout_flags =
|
||||||
|
UISettings::values.callout_flags.GetValue() | static_cast<uint32_t>(CalloutFlag::Telemetry);
|
||||||
|
const QString telemetry_message =
|
||||||
|
tr("<a href='https://suyu.dev/help/feature/telemetry/'>Anonymous "
|
||||||
|
"data is collected</a> to help improve suyu. "
|
||||||
|
"<br/><br/>Would you like to share your usage data with us?");
|
||||||
|
if (!question(this, tr("Telemetry"), telemetry_message)) {
|
||||||
|
Settings::values.enable_telemetry = false;
|
||||||
|
system->ApplySettings();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const int GMainWindow::max_recent_files_item;
|
const int GMainWindow::max_recent_files_item;
|
||||||
|
|
||||||
static void RemoveCachedContents() {
|
static void RemoveCachedContents() {
|
||||||
|
@ -396,6 +417,9 @@ GMainWindow::GMainWindow(std::unique_ptr<QtConfig> config_, bool has_broken_vulk
|
||||||
game_list->LoadCompatibilityList();
|
game_list->LoadCompatibilityList();
|
||||||
game_list->PopulateAsync(UISettings::values.game_dirs);
|
game_list->PopulateAsync(UISettings::values.game_dirs);
|
||||||
|
|
||||||
|
// Show one-time "callout" messages to the user
|
||||||
|
ShowTelemetryCallout();
|
||||||
|
|
||||||
// make sure menubar has the arrow cursor instead of inheriting from this
|
// make sure menubar has the arrow cursor instead of inheriting from this
|
||||||
ui->menubar->setCursor(QCursor());
|
ui->menubar->setCursor(QCursor());
|
||||||
statusBar()->setCursor(QCursor());
|
statusBar()->setCursor(QCursor());
|
||||||
|
@ -1416,7 +1440,6 @@ void GMainWindow::RestoreUIState() {
|
||||||
game_list->SetFilterVisible(ui->action_Show_Filter_Bar->isChecked());
|
game_list->SetFilterVisible(ui->action_Show_Filter_Bar->isChecked());
|
||||||
|
|
||||||
ui->action_Show_Status_Bar->setChecked(UISettings::values.show_status_bar.GetValue());
|
ui->action_Show_Status_Bar->setChecked(UISettings::values.show_status_bar.GetValue());
|
||||||
ui->action_Show_Folders_In_List->setChecked(UISettings::values.show_folders_in_list.GetValue());
|
|
||||||
statusBar()->setVisible(ui->action_Show_Status_Bar->isChecked());
|
statusBar()->setVisible(ui->action_Show_Status_Bar->isChecked());
|
||||||
Debugger::ToggleConsole();
|
Debugger::ToggleConsole();
|
||||||
}
|
}
|
||||||
|
@ -1532,7 +1555,6 @@ void GMainWindow::ConnectMenuEvents() {
|
||||||
connect_menu(ui->action_Display_Dock_Widget_Headers, &GMainWindow::OnDisplayTitleBars);
|
connect_menu(ui->action_Display_Dock_Widget_Headers, &GMainWindow::OnDisplayTitleBars);
|
||||||
connect_menu(ui->action_Show_Filter_Bar, &GMainWindow::OnToggleFilterBar);
|
connect_menu(ui->action_Show_Filter_Bar, &GMainWindow::OnToggleFilterBar);
|
||||||
connect_menu(ui->action_Show_Status_Bar, &GMainWindow::OnToggleStatusBar);
|
connect_menu(ui->action_Show_Status_Bar, &GMainWindow::OnToggleStatusBar);
|
||||||
connect_menu(ui->action_Show_Folders_In_List, &GMainWindow::OnToggleFoldersInList);
|
|
||||||
|
|
||||||
connect_menu(ui->action_Reset_Window_Size_720, &GMainWindow::ResetWindowSize720);
|
connect_menu(ui->action_Reset_Window_Size_720, &GMainWindow::ResetWindowSize720);
|
||||||
connect_menu(ui->action_Reset_Window_Size_900, &GMainWindow::ResetWindowSize900);
|
connect_menu(ui->action_Reset_Window_Size_900, &GMainWindow::ResetWindowSize900);
|
||||||
|
@ -1848,6 +1870,8 @@ bool GMainWindow::LoadROM(const QString& filename, Service::AM::FrontendAppletPa
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
current_game_path = filename;
|
current_game_path = filename;
|
||||||
|
|
||||||
|
system->TelemetrySession().AddField(Common::Telemetry::FieldType::App, "Frontend", "Qt");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3356,7 +3380,7 @@ void GMainWindow::OnMenuReportCompatibility() {
|
||||||
|
|
||||||
if (!Settings::values.suyu_token.GetValue().empty() &&
|
if (!Settings::values.suyu_token.GetValue().empty() &&
|
||||||
!Settings::values.suyu_username.GetValue().empty()) {
|
!Settings::values.suyu_username.GetValue().empty()) {
|
||||||
CompatDB compatdb{this};
|
CompatDB compatdb{system->TelemetrySession(), this};
|
||||||
compatdb.exec();
|
compatdb.exec();
|
||||||
} else {
|
} else {
|
||||||
QMessageBox::critical(
|
QMessageBox::critical(
|
||||||
|
@ -3586,6 +3610,8 @@ void GMainWindow::OnConfigure() {
|
||||||
|
|
||||||
SetDefaultUIGeometry();
|
SetDefaultUIGeometry();
|
||||||
RestoreUIState();
|
RestoreUIState();
|
||||||
|
|
||||||
|
ShowTelemetryCallout();
|
||||||
}
|
}
|
||||||
InitializeHotkeys();
|
InitializeHotkeys();
|
||||||
|
|
||||||
|
@ -4187,14 +4213,6 @@ void GMainWindow::OnToggleStatusBar() {
|
||||||
statusBar()->setVisible(ui->action_Show_Status_Bar->isChecked());
|
statusBar()->setVisible(ui->action_Show_Status_Bar->isChecked());
|
||||||
}
|
}
|
||||||
|
|
||||||
void GMainWindow::OnToggleFoldersInList() {
|
|
||||||
UISettings::values.show_folders_in_list = ui->action_Show_Folders_In_List->isChecked();
|
|
||||||
|
|
||||||
game_list->ClearList();
|
|
||||||
game_list->LoadCompatibilityList();
|
|
||||||
game_list->PopulateAsync(UISettings::values.game_dirs);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GMainWindow::OnAlbum() {
|
void GMainWindow::OnAlbum() {
|
||||||
constexpr u64 AlbumId = static_cast<u64>(Service::AM::AppletProgramId::PhotoViewer);
|
constexpr u64 AlbumId = static_cast<u64>(Service::AM::AppletProgramId::PhotoViewer);
|
||||||
auto bis_system = system->GetFileSystemController().GetSystemNANDContents();
|
auto bis_system = system->GetFileSystemController().GetSystemNANDContents();
|
||||||
|
@ -4583,7 +4601,6 @@ void GMainWindow::UpdateUISettings() {
|
||||||
UISettings::values.display_titlebar = ui->action_Display_Dock_Widget_Headers->isChecked();
|
UISettings::values.display_titlebar = ui->action_Display_Dock_Widget_Headers->isChecked();
|
||||||
UISettings::values.show_filter_bar = ui->action_Show_Filter_Bar->isChecked();
|
UISettings::values.show_filter_bar = ui->action_Show_Filter_Bar->isChecked();
|
||||||
UISettings::values.show_status_bar = ui->action_Show_Status_Bar->isChecked();
|
UISettings::values.show_status_bar = ui->action_Show_Status_Bar->isChecked();
|
||||||
UISettings::values.show_folders_in_list = ui->action_Show_Folders_In_List->isChecked();
|
|
||||||
UISettings::values.first_start = false;
|
UISettings::values.first_start = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -275,6 +275,7 @@ private:
|
||||||
void BootGameFromList(const QString& filename, StartGameType with_config);
|
void BootGameFromList(const QString& filename, StartGameType with_config);
|
||||||
void ShutdownGame();
|
void ShutdownGame();
|
||||||
|
|
||||||
|
void ShowTelemetryCallout();
|
||||||
void SetDiscordEnabled(bool state);
|
void SetDiscordEnabled(bool state);
|
||||||
void LoadAmiibo(const QString& filename);
|
void LoadAmiibo(const QString& filename);
|
||||||
|
|
||||||
|
@ -383,7 +384,6 @@ private slots:
|
||||||
void OnAbout();
|
void OnAbout();
|
||||||
void OnToggleFilterBar();
|
void OnToggleFilterBar();
|
||||||
void OnToggleStatusBar();
|
void OnToggleStatusBar();
|
||||||
void OnToggleFoldersInList();
|
|
||||||
void OnDisplayTitleBars(bool);
|
void OnDisplayTitleBars(bool);
|
||||||
void InitializeHotkeys();
|
void InitializeHotkeys();
|
||||||
void ToggleFullscreen();
|
void ToggleFullscreen();
|
||||||
|
|
|
@ -45,7 +45,7 @@
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>1280</width>
|
<width>1280</width>
|
||||||
<height>21</height>
|
<height>22</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<widget class="QMenu" name="menu_File">
|
<widget class="QMenu" name="menu_File">
|
||||||
|
@ -124,7 +124,6 @@
|
||||||
<addaction name="action_Display_Dock_Widget_Headers"/>
|
<addaction name="action_Display_Dock_Widget_Headers"/>
|
||||||
<addaction name="action_Show_Filter_Bar"/>
|
<addaction name="action_Show_Filter_Bar"/>
|
||||||
<addaction name="action_Show_Status_Bar"/>
|
<addaction name="action_Show_Status_Bar"/>
|
||||||
<addaction name="action_Show_Folders_In_List" />
|
|
||||||
<addaction name="separator"/>
|
<addaction name="separator"/>
|
||||||
<addaction name="menu_Reset_Window_Size"/>
|
<addaction name="menu_Reset_Window_Size"/>
|
||||||
<addaction name="menu_View_Debugging"/>
|
<addaction name="menu_View_Debugging"/>
|
||||||
|
@ -289,17 +288,6 @@
|
||||||
<string>Show Status Bar</string>
|
<string>Show Status Bar</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
<action name="action_Show_Folders_In_List">
|
|
||||||
<property name="checkable">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Show Folders in List</string>
|
|
||||||
</property>
|
|
||||||
<property name="iconText">
|
|
||||||
<string>Show Status Bar</string>
|
|
||||||
</property>
|
|
||||||
</action>
|
|
||||||
<action name="action_View_Lobby">
|
<action name="action_View_Lobby">
|
||||||
<property name="enabled">
|
<property name="enabled">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
|
|
|
@ -24,8 +24,8 @@ enum class ConnectionType : u8 { TraversalServer, IP };
|
||||||
|
|
||||||
DirectConnectWindow::DirectConnectWindow(Core::System& system_, QWidget* parent)
|
DirectConnectWindow::DirectConnectWindow(Core::System& system_, QWidget* parent)
|
||||||
: QDialog(parent, Qt::WindowTitleHint | Qt::WindowCloseButtonHint | Qt::WindowSystemMenuHint),
|
: QDialog(parent, Qt::WindowTitleHint | Qt::WindowCloseButtonHint | Qt::WindowSystemMenuHint),
|
||||||
ui(std::make_unique<Ui::DirectConnect>()), system{system_},
|
ui(std::make_unique<Ui::DirectConnect>()), system{system_}, room_network{
|
||||||
room_network{system.GetRoomNetwork()} {
|
system.GetRoomNetwork()} {
|
||||||
|
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
|
|
||||||
|
|
|
@ -31,8 +31,9 @@ HostRoomWindow::HostRoomWindow(QWidget* parent, QStandardItemModel* list,
|
||||||
std::shared_ptr<Core::AnnounceMultiplayerSession> session,
|
std::shared_ptr<Core::AnnounceMultiplayerSession> session,
|
||||||
Core::System& system_)
|
Core::System& system_)
|
||||||
: QDialog(parent, Qt::WindowTitleHint | Qt::WindowCloseButtonHint | Qt::WindowSystemMenuHint),
|
: QDialog(parent, Qt::WindowTitleHint | Qt::WindowCloseButtonHint | Qt::WindowSystemMenuHint),
|
||||||
ui(std::make_unique<Ui::HostRoom>()), announce_multiplayer_session(session), system{system_},
|
ui(std::make_unique<Ui::HostRoom>()),
|
||||||
room_network{system.GetRoomNetwork()} {
|
announce_multiplayer_session(session), system{system_}, room_network{
|
||||||
|
system.GetRoomNetwork()} {
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
|
|
||||||
// set up validation for all of the fields
|
// set up validation for all of the fields
|
||||||
|
|
|
@ -27,8 +27,9 @@
|
||||||
Lobby::Lobby(QWidget* parent, QStandardItemModel* list,
|
Lobby::Lobby(QWidget* parent, QStandardItemModel* list,
|
||||||
std::shared_ptr<Core::AnnounceMultiplayerSession> session, Core::System& system_)
|
std::shared_ptr<Core::AnnounceMultiplayerSession> session, Core::System& system_)
|
||||||
: QDialog(parent, Qt::WindowTitleHint | Qt::WindowCloseButtonHint | Qt::WindowSystemMenuHint),
|
: QDialog(parent, Qt::WindowTitleHint | Qt::WindowCloseButtonHint | Qt::WindowSystemMenuHint),
|
||||||
ui(std::make_unique<Ui::Lobby>()), announce_multiplayer_session(session), system{system_},
|
ui(std::make_unique<Ui::Lobby>()),
|
||||||
room_network{system.GetRoomNetwork()} {
|
announce_multiplayer_session(session), system{system_}, room_network{
|
||||||
|
system.GetRoomNetwork()} {
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
|
|
||||||
// setup the watcher for background connections
|
// setup the watcher for background connections
|
||||||
|
|
|
@ -200,7 +200,6 @@ struct Values {
|
||||||
std::atomic_bool is_game_list_reload_pending{false};
|
std::atomic_bool is_game_list_reload_pending{false};
|
||||||
Setting<bool> cache_game_list{linkage, true, "cache_game_list", Category::UiGameList};
|
Setting<bool> cache_game_list{linkage, true, "cache_game_list", Category::UiGameList};
|
||||||
Setting<bool> favorites_expanded{linkage, true, "favorites_expanded", Category::UiGameList};
|
Setting<bool> favorites_expanded{linkage, true, "favorites_expanded", Category::UiGameList};
|
||||||
Setting<bool> show_folders_in_list{linkage, true, "show_folders_in_list", Category::UiGameList};
|
|
||||||
QVector<u64> favorited_ids;
|
QVector<u64> favorited_ids;
|
||||||
|
|
||||||
// Compatibility List
|
// Compatibility List
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue