summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--dist/qt_themes/qdarkstyle/style.qss8
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/style.qss3
-rw-r--r--src/audio_core/stream.cpp7
-rw-r--r--src/core/core.cpp2
-rw-r--r--src/core/core_timing.cpp16
-rw-r--r--src/core/core_timing.h7
-rw-r--r--src/core/device_memory.cpp5
-rw-r--r--src/core/device_memory.h8
-rw-r--r--src/core/file_sys/registered_cache.cpp101
-rw-r--r--src/core/file_sys/registered_cache.h6
-rw-r--r--src/core/file_sys/xts_archive.cpp14
-rw-r--r--src/core/hardware_interrupt_manager.cpp4
-rw-r--r--src/core/hle/kernel/kernel.cpp2
-rw-r--r--src/core/hle/kernel/server_session.cpp6
-rw-r--r--src/core/hle/kernel/time_manager.cpp10
-rw-r--r--src/core/hle/service/hid/hid.cpp8
-rw-r--r--src/core/hle/service/hid/hid.h2
-rw-r--r--src/core/hle/service/nvflinger/nvflinger.cpp2
-rw-r--r--src/core/memory/cheat_engine.cpp12
-rw-r--r--src/core/memory/cheat_engine.h2
-rw-r--r--src/core/settings.cpp1
-rw-r--r--src/core/settings.h1
-rw-r--r--src/core/tools/freezer.cpp11
-rw-r--r--src/core/tools/freezer.h2
-rw-r--r--src/tests/core/core_timing.cpp4
-rw-r--r--src/video_core/compatible_formats.h2
-rw-r--r--src/video_core/texture_cache/surface_params.cpp97
-rw-r--r--src/yuzu/configuration/config.cpp5
-rw-r--r--src/yuzu/configuration/configure_graphics_advanced.cpp10
-rw-r--r--src/yuzu/configuration/configure_graphics_advanced.h1
-rw-r--r--src/yuzu/configuration/configure_graphics_advanced.ui7
-rw-r--r--src/yuzu/game_list.cpp34
-rw-r--r--src/yuzu/game_list.h15
-rw-r--r--src/yuzu/main.cpp193
-rw-r--r--src/yuzu/main.h9
35 files changed, 413 insertions, 204 deletions
diff --git a/dist/qt_themes/qdarkstyle/style.qss b/dist/qt_themes/qdarkstyle/style.qss
index 2d5c9761f..2926a05fa 100644
--- a/dist/qt_themes/qdarkstyle/style.qss
+++ b/dist/qt_themes/qdarkstyle/style.qss
@@ -654,7 +654,11 @@ QAbstractSpinBox::down-arrow:hover {
654 image: url(:/qss_icons/rc/down_arrow.png); 654 image: url(:/qss_icons/rc/down_arrow.png);
655} 655}
656 656
657QLabel, 657QLabel {
658 border: 0;
659 background: transparent;
660}
661
658QTabWidget { 662QTabWidget {
659 border: 0; 663 border: 0;
660} 664}
@@ -1269,4 +1273,4 @@ QPushButton#RendererStatusBarButton:checked {
1269 1273
1270QPushButton#RendererStatusBarButton:!checked{ 1274QPushButton#RendererStatusBarButton:!checked{
1271 color: #00ccdd; 1275 color: #00ccdd;
1272} \ No newline at end of file 1276}
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/style.qss b/dist/qt_themes/qdarkstyle_midnight_blue/style.qss
index be645c907..9c24b0d07 100644
--- a/dist/qt_themes/qdarkstyle_midnight_blue/style.qss
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/style.qss
@@ -875,7 +875,7 @@ https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qframe
875 875
876--------------------------------------------------------------------------- */ 876--------------------------------------------------------------------------- */
877QLabel { 877QLabel {
878 background-color: #19232D; 878 background: transparent;
879 border: 0px solid #32414B; 879 border: 0px solid #32414B;
880 padding: 2px; 880 padding: 2px;
881 margin: 0px; 881 margin: 0px;
@@ -883,7 +883,6 @@ QLabel {
883} 883}
884 884
885QLabel:disabled { 885QLabel:disabled {
886 background-color: #19232D;
887 border: 0px solid #32414B; 886 border: 0px solid #32414B;
888 color: #787878; 887 color: #787878;
889} 888}
diff --git a/src/audio_core/stream.cpp b/src/audio_core/stream.cpp
index f80ab92e4..7be5d5087 100644
--- a/src/audio_core/stream.cpp
+++ b/src/audio_core/stream.cpp
@@ -36,9 +36,10 @@ Stream::Stream(Core::Timing::CoreTiming& core_timing, u32 sample_rate, Format fo
36 ReleaseCallback&& release_callback, SinkStream& sink_stream, std::string&& name_) 36 ReleaseCallback&& release_callback, SinkStream& sink_stream, std::string&& name_)
37 : sample_rate{sample_rate}, format{format}, release_callback{std::move(release_callback)}, 37 : sample_rate{sample_rate}, format{format}, release_callback{std::move(release_callback)},
38 sink_stream{sink_stream}, core_timing{core_timing}, name{std::move(name_)} { 38 sink_stream{sink_stream}, core_timing{core_timing}, name{std::move(name_)} {
39 39 release_event =
40 release_event = Core::Timing::CreateEvent( 40 Core::Timing::CreateEvent(name, [this](std::uintptr_t, std::chrono::nanoseconds ns_late) {
41 name, [this](u64, std::chrono::nanoseconds ns_late) { ReleaseActiveBuffer(ns_late); }); 41 ReleaseActiveBuffer(ns_late);
42 });
42} 43}
43 44
44void Stream::Play() { 45void Stream::Play() {
diff --git a/src/core/core.cpp b/src/core/core.cpp
index e598c0e2b..42277e2cd 100644
--- a/src/core/core.cpp
+++ b/src/core/core.cpp
@@ -146,7 +146,7 @@ struct System::Impl {
146 ResultStatus Init(System& system, Frontend::EmuWindow& emu_window) { 146 ResultStatus Init(System& system, Frontend::EmuWindow& emu_window) {
147 LOG_DEBUG(HW_Memory, "initialized OK"); 147 LOG_DEBUG(HW_Memory, "initialized OK");
148 148
149 device_memory = std::make_unique<Core::DeviceMemory>(system); 149 device_memory = std::make_unique<Core::DeviceMemory>();
150 150
151 is_multicore = Settings::values.use_multi_core.GetValue(); 151 is_multicore = Settings::values.use_multi_core.GetValue();
152 is_async_gpu = is_multicore || Settings::values.use_asynchronous_gpu_emulation.GetValue(); 152 is_async_gpu = is_multicore || Settings::values.use_asynchronous_gpu_emulation.GetValue();
diff --git a/src/core/core_timing.cpp b/src/core/core_timing.cpp
index b5feb3f24..71af26ec5 100644
--- a/src/core/core_timing.cpp
+++ b/src/core/core_timing.cpp
@@ -23,7 +23,7 @@ std::shared_ptr<EventType> CreateEvent(std::string name, TimedCallback&& callbac
23struct CoreTiming::Event { 23struct CoreTiming::Event {
24 u64 time; 24 u64 time;
25 u64 fifo_order; 25 u64 fifo_order;
26 u64 userdata; 26 std::uintptr_t user_data;
27 std::weak_ptr<EventType> type; 27 std::weak_ptr<EventType> type;
28 28
29 // Sort by time, unless the times are the same, in which case sort by 29 // Sort by time, unless the times are the same, in which case sort by
@@ -58,7 +58,7 @@ void CoreTiming::Initialize(std::function<void()>&& on_thread_init_) {
58 event_fifo_id = 0; 58 event_fifo_id = 0;
59 shutting_down = false; 59 shutting_down = false;
60 ticks = 0; 60 ticks = 0;
61 const auto empty_timed_callback = [](u64, std::chrono::nanoseconds) {}; 61 const auto empty_timed_callback = [](std::uintptr_t, std::chrono::nanoseconds) {};
62 ev_lost = CreateEvent("_lost_event", empty_timed_callback); 62 ev_lost = CreateEvent("_lost_event", empty_timed_callback);
63 if (is_multicore) { 63 if (is_multicore) {
64 timer_thread = std::make_unique<std::thread>(ThreadEntry, std::ref(*this)); 64 timer_thread = std::make_unique<std::thread>(ThreadEntry, std::ref(*this));
@@ -107,22 +107,24 @@ bool CoreTiming::HasPendingEvents() const {
107} 107}
108 108
109void CoreTiming::ScheduleEvent(std::chrono::nanoseconds ns_into_future, 109void CoreTiming::ScheduleEvent(std::chrono::nanoseconds ns_into_future,
110 const std::shared_ptr<EventType>& event_type, u64 userdata) { 110 const std::shared_ptr<EventType>& event_type,
111 std::uintptr_t user_data) {
111 { 112 {
112 std::scoped_lock scope{basic_lock}; 113 std::scoped_lock scope{basic_lock};
113 const u64 timeout = static_cast<u64>((GetGlobalTimeNs() + ns_into_future).count()); 114 const u64 timeout = static_cast<u64>((GetGlobalTimeNs() + ns_into_future).count());
114 115
115 event_queue.emplace_back(Event{timeout, event_fifo_id++, userdata, event_type}); 116 event_queue.emplace_back(Event{timeout, event_fifo_id++, user_data, event_type});
116 117
117 std::push_heap(event_queue.begin(), event_queue.end(), std::greater<>()); 118 std::push_heap(event_queue.begin(), event_queue.end(), std::greater<>());
118 } 119 }
119 event.Set(); 120 event.Set();
120} 121}
121 122
122void CoreTiming::UnscheduleEvent(const std::shared_ptr<EventType>& event_type, u64 userdata) { 123void CoreTiming::UnscheduleEvent(const std::shared_ptr<EventType>& event_type,
124 std::uintptr_t user_data) {
123 std::scoped_lock scope{basic_lock}; 125 std::scoped_lock scope{basic_lock};
124 const auto itr = std::remove_if(event_queue.begin(), event_queue.end(), [&](const Event& e) { 126 const auto itr = std::remove_if(event_queue.begin(), event_queue.end(), [&](const Event& e) {
125 return e.type.lock().get() == event_type.get() && e.userdata == userdata; 127 return e.type.lock().get() == event_type.get() && e.user_data == user_data;
126 }); 128 });
127 129
128 // Removing random items breaks the invariant so we have to re-establish it. 130 // Removing random items breaks the invariant so we have to re-establish it.
@@ -197,7 +199,7 @@ std::optional<s64> CoreTiming::Advance() {
197 199
198 if (const auto event_type{evt.type.lock()}) { 200 if (const auto event_type{evt.type.lock()}) {
199 event_type->callback( 201 event_type->callback(
200 evt.userdata, std::chrono::nanoseconds{static_cast<s64>(global_timer - evt.time)}); 202 evt.user_data, std::chrono::nanoseconds{static_cast<s64>(global_timer - evt.time)});
201 } 203 }
202 204
203 basic_lock.lock(); 205 basic_lock.lock();
diff --git a/src/core/core_timing.h b/src/core/core_timing.h
index 120c74e46..b0b6036e4 100644
--- a/src/core/core_timing.h
+++ b/src/core/core_timing.h
@@ -22,7 +22,8 @@
22namespace Core::Timing { 22namespace Core::Timing {
23 23
24/// A callback that may be scheduled for a particular core timing event. 24/// A callback that may be scheduled for a particular core timing event.
25using TimedCallback = std::function<void(u64 userdata, std::chrono::nanoseconds ns_late)>; 25using TimedCallback =
26 std::function<void(std::uintptr_t user_data, std::chrono::nanoseconds ns_late)>;
26 27
27/// Contains the characteristics of a particular event. 28/// Contains the characteristics of a particular event.
28struct EventType { 29struct EventType {
@@ -94,9 +95,9 @@ public:
94 95
95 /// Schedules an event in core timing 96 /// Schedules an event in core timing
96 void ScheduleEvent(std::chrono::nanoseconds ns_into_future, 97 void ScheduleEvent(std::chrono::nanoseconds ns_into_future,
97 const std::shared_ptr<EventType>& event_type, u64 userdata = 0); 98 const std::shared_ptr<EventType>& event_type, std::uintptr_t user_data = 0);
98 99
99 void UnscheduleEvent(const std::shared_ptr<EventType>& event_type, u64 userdata); 100 void UnscheduleEvent(const std::shared_ptr<EventType>& event_type, std::uintptr_t user_data);
100 101
101 /// We only permit one event of each type in the queue at a time. 102 /// We only permit one event of each type in the queue at a time.
102 void RemoveEvent(const std::shared_ptr<EventType>& event_type); 103 void RemoveEvent(const std::shared_ptr<EventType>& event_type);
diff --git a/src/core/device_memory.cpp b/src/core/device_memory.cpp
index 51097ced3..0c4b440ed 100644
--- a/src/core/device_memory.cpp
+++ b/src/core/device_memory.cpp
@@ -2,14 +2,11 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "core/core.h"
6#include "core/device_memory.h" 5#include "core/device_memory.h"
7#include "core/memory.h"
8 6
9namespace Core { 7namespace Core {
10 8
11DeviceMemory::DeviceMemory(System& system) : buffer{DramMemoryMap::Size}, system{system} {} 9DeviceMemory::DeviceMemory() : buffer{DramMemoryMap::Size} {}
12
13DeviceMemory::~DeviceMemory() = default; 10DeviceMemory::~DeviceMemory() = default;
14 11
15} // namespace Core 12} // namespace Core
diff --git a/src/core/device_memory.h b/src/core/device_memory.h
index 9efa088d0..5b1ae28f3 100644
--- a/src/core/device_memory.h
+++ b/src/core/device_memory.h
@@ -4,14 +4,11 @@
4 4
5#pragma once 5#pragma once
6 6
7#include "common/assert.h" 7#include "common/common_types.h"
8#include "common/common_funcs.h"
9#include "common/virtual_buffer.h" 8#include "common/virtual_buffer.h"
10 9
11namespace Core { 10namespace Core {
12 11
13class System;
14
15namespace DramMemoryMap { 12namespace DramMemoryMap {
16enum : u64 { 13enum : u64 {
17 Base = 0x80000000ULL, 14 Base = 0x80000000ULL,
@@ -26,7 +23,7 @@ enum : u64 {
26 23
27class DeviceMemory : NonCopyable { 24class DeviceMemory : NonCopyable {
28public: 25public:
29 explicit DeviceMemory(Core::System& system); 26 explicit DeviceMemory();
30 ~DeviceMemory(); 27 ~DeviceMemory();
31 28
32 template <typename T> 29 template <typename T>
@@ -45,7 +42,6 @@ public:
45 42
46private: 43private:
47 Common::VirtualBuffer<u8> buffer; 44 Common::VirtualBuffer<u8> buffer;
48 Core::System& system;
49}; 45};
50 46
51} // namespace Core 47} // namespace Core
diff --git a/src/core/file_sys/registered_cache.cpp b/src/core/file_sys/registered_cache.cpp
index 37351c561..e94eed3b6 100644
--- a/src/core/file_sys/registered_cache.cpp
+++ b/src/core/file_sys/registered_cache.cpp
@@ -547,56 +547,6 @@ InstallResult RegisteredCache::InstallEntry(const XCI& xci, bool overwrite_if_ex
547 return InstallEntry(*xci.GetSecurePartitionNSP(), overwrite_if_exists, copy); 547 return InstallEntry(*xci.GetSecurePartitionNSP(), overwrite_if_exists, copy);
548} 548}
549 549
550bool RegisteredCache::RemoveExistingEntry(u64 title_id) {
551 const auto delete_nca = [this](const NcaID& id) {
552 const auto path = GetRelativePathFromNcaID(id, false, true, false);
553
554 if (dir->GetFileRelative(path) == nullptr) {
555 return false;
556 }
557
558 Core::Crypto::SHA256Hash hash{};
559 mbedtls_sha256_ret(id.data(), id.size(), hash.data(), 0);
560 const auto dirname = fmt::format("000000{:02X}", hash[0]);
561
562 const auto dir2 = GetOrCreateDirectoryRelative(dir, dirname);
563
564 const auto res = dir2->DeleteFile(fmt::format("{}.nca", Common::HexToString(id, false)));
565
566 return res;
567 };
568
569 // If an entry exists in the registered cache, remove it
570 if (HasEntry(title_id, ContentRecordType::Meta)) {
571 LOG_INFO(Loader,
572 "Previously installed entry (v{}) for title_id={:016X} detected! "
573 "Attempting to remove...",
574 GetEntryVersion(title_id).value_or(0), title_id);
575 // Get all the ncas associated with the current CNMT and delete them
576 const auto meta_old_id =
577 GetNcaIDFromMetadata(title_id, ContentRecordType::Meta).value_or(NcaID{});
578 const auto program_id =
579 GetNcaIDFromMetadata(title_id, ContentRecordType::Program).value_or(NcaID{});
580 const auto data_id =
581 GetNcaIDFromMetadata(title_id, ContentRecordType::Data).value_or(NcaID{});
582 const auto control_id =
583 GetNcaIDFromMetadata(title_id, ContentRecordType::Control).value_or(NcaID{});
584 const auto html_id =
585 GetNcaIDFromMetadata(title_id, ContentRecordType::HtmlDocument).value_or(NcaID{});
586 const auto legal_id =
587 GetNcaIDFromMetadata(title_id, ContentRecordType::LegalInformation).value_or(NcaID{});
588
589 delete_nca(meta_old_id);
590 delete_nca(program_id);
591 delete_nca(data_id);
592 delete_nca(control_id);
593 delete_nca(html_id);
594 delete_nca(legal_id);
595 return true;
596 }
597 return false;
598}
599
600InstallResult RegisteredCache::InstallEntry(const NSP& nsp, bool overwrite_if_exists, 550InstallResult RegisteredCache::InstallEntry(const NSP& nsp, bool overwrite_if_exists,
601 const VfsCopyFunction& copy) { 551 const VfsCopyFunction& copy) {
602 const auto ncas = nsp.GetNCAsCollapsed(); 552 const auto ncas = nsp.GetNCAsCollapsed();
@@ -692,6 +642,57 @@ InstallResult RegisteredCache::InstallEntry(const NCA& nca, TitleType type,
692 return RawInstallNCA(nca, copy, overwrite_if_exists, c_rec.nca_id); 642 return RawInstallNCA(nca, copy, overwrite_if_exists, c_rec.nca_id);
693} 643}
694 644
645bool RegisteredCache::RemoveExistingEntry(u64 title_id) const {
646 const auto delete_nca = [this](const NcaID& id) {
647 const auto path = GetRelativePathFromNcaID(id, false, true, false);
648
649 const bool isFile = dir->GetFileRelative(path) != nullptr;
650 const bool isDir = dir->GetDirectoryRelative(path) != nullptr;
651
652 if (isFile) {
653 return dir->DeleteFile(path);
654 } else if (isDir) {
655 return dir->DeleteSubdirectoryRecursive(path);
656 }
657
658 return false;
659 };
660
661 // If an entry exists in the registered cache, remove it
662 if (HasEntry(title_id, ContentRecordType::Meta)) {
663 LOG_INFO(Loader,
664 "Previously installed entry (v{}) for title_id={:016X} detected! "
665 "Attempting to remove...",
666 GetEntryVersion(title_id).value_or(0), title_id);
667
668 // Get all the ncas associated with the current CNMT and delete them
669 const auto meta_old_id =
670 GetNcaIDFromMetadata(title_id, ContentRecordType::Meta).value_or(NcaID{});
671 const auto program_id =
672 GetNcaIDFromMetadata(title_id, ContentRecordType::Program).value_or(NcaID{});
673 const auto data_id =
674 GetNcaIDFromMetadata(title_id, ContentRecordType::Data).value_or(NcaID{});
675 const auto control_id =
676 GetNcaIDFromMetadata(title_id, ContentRecordType::Control).value_or(NcaID{});
677 const auto html_id =
678 GetNcaIDFromMetadata(title_id, ContentRecordType::HtmlDocument).value_or(NcaID{});
679 const auto legal_id =
680 GetNcaIDFromMetadata(title_id, ContentRecordType::LegalInformation).value_or(NcaID{});
681
682 const auto deleted_meta = delete_nca(meta_old_id);
683 const auto deleted_program = delete_nca(program_id);
684 const auto deleted_data = delete_nca(data_id);
685 const auto deleted_control = delete_nca(control_id);
686 const auto deleted_html = delete_nca(html_id);
687 const auto deleted_legal = delete_nca(legal_id);
688
689 return deleted_meta && (deleted_meta || deleted_program || deleted_data ||
690 deleted_control || deleted_html || deleted_legal);
691 }
692
693 return false;
694}
695
695InstallResult RegisteredCache::RawInstallNCA(const NCA& nca, const VfsCopyFunction& copy, 696InstallResult RegisteredCache::RawInstallNCA(const NCA& nca, const VfsCopyFunction& copy,
696 bool overwrite_if_exists, 697 bool overwrite_if_exists,
697 std::optional<NcaID> override_id) { 698 std::optional<NcaID> override_id) {
diff --git a/src/core/file_sys/registered_cache.h b/src/core/file_sys/registered_cache.h
index 29cf0d40c..ec1d54f27 100644
--- a/src/core/file_sys/registered_cache.h
+++ b/src/core/file_sys/registered_cache.h
@@ -155,9 +155,6 @@ public:
155 std::optional<TitleType> title_type = {}, std::optional<ContentRecordType> record_type = {}, 155 std::optional<TitleType> title_type = {}, std::optional<ContentRecordType> record_type = {},
156 std::optional<u64> title_id = {}) const override; 156 std::optional<u64> title_id = {}) const override;
157 157
158 // Removes an existing entry based on title id
159 bool RemoveExistingEntry(u64 title_id);
160
161 // Raw copies all the ncas from the xci/nsp to the csache. Does some quick checks to make sure 158 // Raw copies all the ncas from the xci/nsp to the csache. Does some quick checks to make sure
162 // there is a meta NCA and all of them are accessible. 159 // there is a meta NCA and all of them are accessible.
163 InstallResult InstallEntry(const XCI& xci, bool overwrite_if_exists = false, 160 InstallResult InstallEntry(const XCI& xci, bool overwrite_if_exists = false,
@@ -172,6 +169,9 @@ public:
172 InstallResult InstallEntry(const NCA& nca, TitleType type, bool overwrite_if_exists = false, 169 InstallResult InstallEntry(const NCA& nca, TitleType type, bool overwrite_if_exists = false,
173 const VfsCopyFunction& copy = &VfsRawCopy); 170 const VfsCopyFunction& copy = &VfsRawCopy);
174 171
172 // Removes an existing entry based on title id
173 bool RemoveExistingEntry(u64 title_id) const;
174
175private: 175private:
176 template <typename T> 176 template <typename T>
177 void IterateAllMetadata(std::vector<T>& out, 177 void IterateAllMetadata(std::vector<T>& out,
diff --git a/src/core/file_sys/xts_archive.cpp b/src/core/file_sys/xts_archive.cpp
index 86e06ccb9..81413c684 100644
--- a/src/core/file_sys/xts_archive.cpp
+++ b/src/core/file_sys/xts_archive.cpp
@@ -70,14 +70,18 @@ NAX::NAX(VirtualFile file_, std::array<u8, 0x10> nca_id)
70NAX::~NAX() = default; 70NAX::~NAX() = default;
71 71
72Loader::ResultStatus NAX::Parse(std::string_view path) { 72Loader::ResultStatus NAX::Parse(std::string_view path) {
73 if (file->ReadObject(header.get()) != sizeof(NAXHeader)) 73 if (file == nullptr) {
74 return Loader::ResultStatus::ErrorNullFile;
75 }
76 if (file->ReadObject(header.get()) != sizeof(NAXHeader)) {
74 return Loader::ResultStatus::ErrorBadNAXHeader; 77 return Loader::ResultStatus::ErrorBadNAXHeader;
75 78 }
76 if (header->magic != Common::MakeMagic('N', 'A', 'X', '0')) 79 if (header->magic != Common::MakeMagic('N', 'A', 'X', '0')) {
77 return Loader::ResultStatus::ErrorBadNAXHeader; 80 return Loader::ResultStatus::ErrorBadNAXHeader;
78 81 }
79 if (file->GetSize() < NAX_HEADER_PADDING_SIZE + header->file_size) 82 if (file->GetSize() < NAX_HEADER_PADDING_SIZE + header->file_size) {
80 return Loader::ResultStatus::ErrorIncorrectNAXFileSize; 83 return Loader::ResultStatus::ErrorIncorrectNAXFileSize;
84 }
81 85
82 keys.DeriveSDSeedLazy(); 86 keys.DeriveSDSeedLazy();
83 std::array<Core::Crypto::Key256, 2> sd_keys{}; 87 std::array<Core::Crypto::Key256, 2> sd_keys{};
diff --git a/src/core/hardware_interrupt_manager.cpp b/src/core/hardware_interrupt_manager.cpp
index efc1030c1..645f26e91 100644
--- a/src/core/hardware_interrupt_manager.cpp
+++ b/src/core/hardware_interrupt_manager.cpp
@@ -11,8 +11,8 @@
11namespace Core::Hardware { 11namespace Core::Hardware {
12 12
13InterruptManager::InterruptManager(Core::System& system_in) : system(system_in) { 13InterruptManager::InterruptManager(Core::System& system_in) : system(system_in) {
14 gpu_interrupt_event = 14 gpu_interrupt_event = Core::Timing::CreateEvent(
15 Core::Timing::CreateEvent("GPUInterrupt", [this](u64 message, std::chrono::nanoseconds) { 15 "GPUInterrupt", [this](std::uintptr_t message, std::chrono::nanoseconds) {
16 auto nvdrv = system.ServiceManager().GetService<Service::Nvidia::NVDRV>("nvdrv"); 16 auto nvdrv = system.ServiceManager().GetService<Service::Nvidia::NVDRV>("nvdrv");
17 const u32 syncpt = static_cast<u32>(message >> 32); 17 const u32 syncpt = static_cast<u32>(message >> 32);
18 const u32 value = static_cast<u32>(message); 18 const u32 value = static_cast<u32>(message);
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index 8dd4a2637..cabe8d418 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -145,7 +145,7 @@ struct KernelCore::Impl {
145 145
146 void InitializePreemption(KernelCore& kernel) { 146 void InitializePreemption(KernelCore& kernel) {
147 preemption_event = Core::Timing::CreateEvent( 147 preemption_event = Core::Timing::CreateEvent(
148 "PreemptionCallback", [this, &kernel](u64, std::chrono::nanoseconds) { 148 "PreemptionCallback", [this, &kernel](std::uintptr_t, std::chrono::nanoseconds) {
149 { 149 {
150 SchedulerLock lock(kernel); 150 SchedulerLock lock(kernel);
151 global_scheduler.PreemptThreads(); 151 global_scheduler.PreemptThreads();
diff --git a/src/core/hle/kernel/server_session.cpp b/src/core/hle/kernel/server_session.cpp
index af22f4c33..7e6391c6c 100644
--- a/src/core/hle/kernel/server_session.cpp
+++ b/src/core/hle/kernel/server_session.cpp
@@ -33,8 +33,10 @@ ResultVal<std::shared_ptr<ServerSession>> ServerSession::Create(KernelCore& kern
33 std::string name) { 33 std::string name) {
34 std::shared_ptr<ServerSession> session{std::make_shared<ServerSession>(kernel)}; 34 std::shared_ptr<ServerSession> session{std::make_shared<ServerSession>(kernel)};
35 35
36 session->request_event = Core::Timing::CreateEvent( 36 session->request_event =
37 name, [session](u64, std::chrono::nanoseconds) { session->CompleteSyncRequest(); }); 37 Core::Timing::CreateEvent(name, [session](std::uintptr_t, std::chrono::nanoseconds) {
38 session->CompleteSyncRequest();
39 });
38 session->name = std::move(name); 40 session->name = std::move(name);
39 session->parent = std::move(parent); 41 session->parent = std::move(parent);
40 42
diff --git a/src/core/hle/kernel/time_manager.cpp b/src/core/hle/kernel/time_manager.cpp
index 88b01b751..95f2446c9 100644
--- a/src/core/hle/kernel/time_manager.cpp
+++ b/src/core/hle/kernel/time_manager.cpp
@@ -16,14 +16,14 @@ namespace Kernel {
16 16
17TimeManager::TimeManager(Core::System& system_) : system{system_} { 17TimeManager::TimeManager(Core::System& system_) : system{system_} {
18 time_manager_event_type = Core::Timing::CreateEvent( 18 time_manager_event_type = Core::Timing::CreateEvent(
19 "Kernel::TimeManagerCallback", [this](u64 thread_handle, std::chrono::nanoseconds) { 19 "Kernel::TimeManagerCallback",
20 SchedulerLock lock(system.Kernel()); 20 [this](std::uintptr_t thread_handle, std::chrono::nanoseconds) {
21 Handle proper_handle = static_cast<Handle>(thread_handle); 21 const SchedulerLock lock(system.Kernel());
22 const auto proper_handle = static_cast<Handle>(thread_handle);
22 if (cancelled_events[proper_handle]) { 23 if (cancelled_events[proper_handle]) {
23 return; 24 return;
24 } 25 }
25 std::shared_ptr<Thread> thread = 26 auto thread = this->system.Kernel().RetrieveThreadFromGlobalHandleTable(proper_handle);
26 this->system.Kernel().RetrieveThreadFromGlobalHandleTable(proper_handle);
27 thread->OnWakeUp(); 27 thread->OnWakeUp();
28 }); 28 });
29} 29}
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp
index 680290cbd..1e95b7580 100644
--- a/src/core/hle/service/hid/hid.cpp
+++ b/src/core/hle/service/hid/hid.cpp
@@ -77,8 +77,9 @@ IAppletResource::IAppletResource(Core::System& system)
77 77
78 // Register update callbacks 78 // Register update callbacks
79 pad_update_event = Core::Timing::CreateEvent( 79 pad_update_event = Core::Timing::CreateEvent(
80 "HID::UpdatePadCallback", [this](u64 userdata, std::chrono::nanoseconds ns_late) { 80 "HID::UpdatePadCallback",
81 UpdateControllers(userdata, ns_late); 81 [this](std::uintptr_t user_data, std::chrono::nanoseconds ns_late) {
82 UpdateControllers(user_data, ns_late);
82 }); 83 });
83 84
84 // TODO(shinyquagsire23): Other update callbacks? (accel, gyro?) 85 // TODO(shinyquagsire23): Other update callbacks? (accel, gyro?)
@@ -108,7 +109,8 @@ void IAppletResource::GetSharedMemoryHandle(Kernel::HLERequestContext& ctx) {
108 rb.PushCopyObjects(shared_mem); 109 rb.PushCopyObjects(shared_mem);
109} 110}
110 111
111void IAppletResource::UpdateControllers(u64 userdata, std::chrono::nanoseconds ns_late) { 112void IAppletResource::UpdateControllers(std::uintptr_t user_data,
113 std::chrono::nanoseconds ns_late) {
112 auto& core_timing = system.CoreTiming(); 114 auto& core_timing = system.CoreTiming();
113 115
114 const bool should_reload = Settings::values.is_device_reload_pending.exchange(false); 116 const bool should_reload = Settings::values.is_device_reload_pending.exchange(false);
diff --git a/src/core/hle/service/hid/hid.h b/src/core/hle/service/hid/hid.h
index c6f0a2584..efb07547f 100644
--- a/src/core/hle/service/hid/hid.h
+++ b/src/core/hle/service/hid/hid.h
@@ -64,7 +64,7 @@ private:
64 } 64 }
65 65
66 void GetSharedMemoryHandle(Kernel::HLERequestContext& ctx); 66 void GetSharedMemoryHandle(Kernel::HLERequestContext& ctx);
67 void UpdateControllers(u64 userdata, std::chrono::nanoseconds ns_late); 67 void UpdateControllers(std::uintptr_t user_data, std::chrono::nanoseconds ns_late);
68 68
69 std::shared_ptr<Kernel::SharedMemory> shared_mem; 69 std::shared_ptr<Kernel::SharedMemory> shared_mem;
70 70
diff --git a/src/core/hle/service/nvflinger/nvflinger.cpp b/src/core/hle/service/nvflinger/nvflinger.cpp
index e561bf654..f644a460d 100644
--- a/src/core/hle/service/nvflinger/nvflinger.cpp
+++ b/src/core/hle/service/nvflinger/nvflinger.cpp
@@ -67,7 +67,7 @@ NVFlinger::NVFlinger(Core::System& system) : system(system) {
67 67
68 // Schedule the screen composition events 68 // Schedule the screen composition events
69 composition_event = Core::Timing::CreateEvent( 69 composition_event = Core::Timing::CreateEvent(
70 "ScreenComposition", [this](u64, std::chrono::nanoseconds ns_late) { 70 "ScreenComposition", [this](std::uintptr_t, std::chrono::nanoseconds ns_late) {
71 const auto guard = Lock(); 71 const auto guard = Lock();
72 Compose(); 72 Compose();
73 73
diff --git a/src/core/memory/cheat_engine.cpp b/src/core/memory/cheat_engine.cpp
index ced41b1fe..eeebdf02e 100644
--- a/src/core/memory/cheat_engine.cpp
+++ b/src/core/memory/cheat_engine.cpp
@@ -188,11 +188,11 @@ CheatEngine::~CheatEngine() {
188} 188}
189 189
190void CheatEngine::Initialize() { 190void CheatEngine::Initialize() {
191 event = Core::Timing::CreateEvent("CheatEngine::FrameCallback::" + 191 event = Core::Timing::CreateEvent(
192 Common::HexToString(metadata.main_nso_build_id), 192 "CheatEngine::FrameCallback::" + Common::HexToString(metadata.main_nso_build_id),
193 [this](u64 userdata, std::chrono::nanoseconds ns_late) { 193 [this](std::uintptr_t user_data, std::chrono::nanoseconds ns_late) {
194 FrameCallback(userdata, ns_late); 194 FrameCallback(user_data, ns_late);
195 }); 195 });
196 core_timing.ScheduleEvent(CHEAT_ENGINE_NS, event); 196 core_timing.ScheduleEvent(CHEAT_ENGINE_NS, event);
197 197
198 metadata.process_id = system.CurrentProcess()->GetProcessID(); 198 metadata.process_id = system.CurrentProcess()->GetProcessID();
@@ -219,7 +219,7 @@ void CheatEngine::Reload(std::vector<CheatEntry> cheats) {
219 219
220MICROPROFILE_DEFINE(Cheat_Engine, "Add-Ons", "Cheat Engine", MP_RGB(70, 200, 70)); 220MICROPROFILE_DEFINE(Cheat_Engine, "Add-Ons", "Cheat Engine", MP_RGB(70, 200, 70));
221 221
222void CheatEngine::FrameCallback(u64, std::chrono::nanoseconds ns_late) { 222void CheatEngine::FrameCallback(std::uintptr_t, std::chrono::nanoseconds ns_late) {
223 if (is_pending_reload.exchange(false)) { 223 if (is_pending_reload.exchange(false)) {
224 vm.LoadProgram(cheats); 224 vm.LoadProgram(cheats);
225 } 225 }
diff --git a/src/core/memory/cheat_engine.h b/src/core/memory/cheat_engine.h
index d4068cf84..fa039a831 100644
--- a/src/core/memory/cheat_engine.h
+++ b/src/core/memory/cheat_engine.h
@@ -72,7 +72,7 @@ public:
72 void Reload(std::vector<CheatEntry> cheats); 72 void Reload(std::vector<CheatEntry> cheats);
73 73
74private: 74private:
75 void FrameCallback(u64 userdata, std::chrono::nanoseconds ns_late); 75 void FrameCallback(std::uintptr_t user_data, std::chrono::nanoseconds ns_late);
76 76
77 DmntCheatVm vm; 77 DmntCheatVm vm;
78 CheatProcessMetadata metadata; 78 CheatProcessMetadata metadata;
diff --git a/src/core/settings.cpp b/src/core/settings.cpp
index 44252dd81..416b2d866 100644
--- a/src/core/settings.cpp
+++ b/src/core/settings.cpp
@@ -173,7 +173,6 @@ void RestoreGlobalState() {
173 values.use_assembly_shaders.SetGlobal(true); 173 values.use_assembly_shaders.SetGlobal(true);
174 values.use_asynchronous_shaders.SetGlobal(true); 174 values.use_asynchronous_shaders.SetGlobal(true);
175 values.use_fast_gpu_time.SetGlobal(true); 175 values.use_fast_gpu_time.SetGlobal(true);
176 values.force_30fps_mode.SetGlobal(true);
177 values.bg_red.SetGlobal(true); 176 values.bg_red.SetGlobal(true);
178 values.bg_green.SetGlobal(true); 177 values.bg_green.SetGlobal(true);
179 values.bg_blue.SetGlobal(true); 178 values.bg_blue.SetGlobal(true);
diff --git a/src/core/settings.h b/src/core/settings.h
index 386233fdf..bb145f193 100644
--- a/src/core/settings.h
+++ b/src/core/settings.h
@@ -435,7 +435,6 @@ struct Values {
435 Setting<bool> use_vsync; 435 Setting<bool> use_vsync;
436 Setting<bool> use_assembly_shaders; 436 Setting<bool> use_assembly_shaders;
437 Setting<bool> use_asynchronous_shaders; 437 Setting<bool> use_asynchronous_shaders;
438 Setting<bool> force_30fps_mode;
439 Setting<bool> use_fast_gpu_time; 438 Setting<bool> use_fast_gpu_time;
440 439
441 Setting<float> bg_red; 440 Setting<float> bg_red;
diff --git a/src/core/tools/freezer.cpp b/src/core/tools/freezer.cpp
index 27b894b51..2003e096f 100644
--- a/src/core/tools/freezer.cpp
+++ b/src/core/tools/freezer.cpp
@@ -55,10 +55,11 @@ void MemoryWriteWidth(Core::Memory::Memory& memory, u32 width, VAddr addr, u64 v
55 55
56Freezer::Freezer(Core::Timing::CoreTiming& core_timing_, Core::Memory::Memory& memory_) 56Freezer::Freezer(Core::Timing::CoreTiming& core_timing_, Core::Memory::Memory& memory_)
57 : core_timing{core_timing_}, memory{memory_} { 57 : core_timing{core_timing_}, memory{memory_} {
58 event = Core::Timing::CreateEvent("MemoryFreezer::FrameCallback", 58 event = Core::Timing::CreateEvent(
59 [this](u64 userdata, std::chrono::nanoseconds ns_late) { 59 "MemoryFreezer::FrameCallback",
60 FrameCallback(userdata, ns_late); 60 [this](std::uintptr_t user_data, std::chrono::nanoseconds ns_late) {
61 }); 61 FrameCallback(user_data, ns_late);
62 });
62 core_timing.ScheduleEvent(memory_freezer_ns, event); 63 core_timing.ScheduleEvent(memory_freezer_ns, event);
63} 64}
64 65
@@ -159,7 +160,7 @@ std::vector<Freezer::Entry> Freezer::GetEntries() const {
159 return entries; 160 return entries;
160} 161}
161 162
162void Freezer::FrameCallback(u64, std::chrono::nanoseconds ns_late) { 163void Freezer::FrameCallback(std::uintptr_t, std::chrono::nanoseconds ns_late) {
163 if (!IsActive()) { 164 if (!IsActive()) {
164 LOG_DEBUG(Common_Memory, "Memory freezer has been deactivated, ending callback events."); 165 LOG_DEBUG(Common_Memory, "Memory freezer has been deactivated, ending callback events.");
165 return; 166 return;
diff --git a/src/core/tools/freezer.h b/src/core/tools/freezer.h
index 8438783d5..2b2326bc4 100644
--- a/src/core/tools/freezer.h
+++ b/src/core/tools/freezer.h
@@ -73,7 +73,7 @@ public:
73 std::vector<Entry> GetEntries() const; 73 std::vector<Entry> GetEntries() const;
74 74
75private: 75private:
76 void FrameCallback(u64 userdata, std::chrono::nanoseconds ns_late); 76 void FrameCallback(std::uintptr_t user_data, std::chrono::nanoseconds ns_late);
77 void FillEntryReads(); 77 void FillEntryReads();
78 78
79 std::atomic_bool active{false}; 79 std::atomic_bool active{false};
diff --git a/src/tests/core/core_timing.cpp b/src/tests/core/core_timing.cpp
index 244463a47..022b26e6d 100644
--- a/src/tests/core/core_timing.cpp
+++ b/src/tests/core/core_timing.cpp
@@ -25,10 +25,10 @@ std::bitset<CB_IDS.size()> callbacks_ran_flags;
25u64 expected_callback = 0; 25u64 expected_callback = 0;
26 26
27template <unsigned int IDX> 27template <unsigned int IDX>
28void HostCallbackTemplate(u64 userdata, std::chrono::nanoseconds ns_late) { 28void HostCallbackTemplate(std::uintptr_t user_data, std::chrono::nanoseconds ns_late) {
29 static_assert(IDX < CB_IDS.size(), "IDX out of range"); 29 static_assert(IDX < CB_IDS.size(), "IDX out of range");
30 callbacks_ran_flags.set(IDX); 30 callbacks_ran_flags.set(IDX);
31 REQUIRE(CB_IDS[IDX] == userdata); 31 REQUIRE(CB_IDS[IDX] == user_data);
32 REQUIRE(CB_IDS[IDX] == CB_IDS[calls_order[expected_callback]]); 32 REQUIRE(CB_IDS[IDX] == CB_IDS[calls_order[expected_callback]]);
33 delays[IDX] = ns_late.count(); 33 delays[IDX] = ns_late.count();
34 ++expected_callback; 34 ++expected_callback;
diff --git a/src/video_core/compatible_formats.h b/src/video_core/compatible_formats.h
index d1082566d..51766349b 100644
--- a/src/video_core/compatible_formats.h
+++ b/src/video_core/compatible_formats.h
@@ -2,6 +2,8 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once
6
5#include <array> 7#include <array>
6#include <bitset> 8#include <bitset>
7#include <cstddef> 9#include <cstddef>
diff --git a/src/video_core/texture_cache/surface_params.cpp b/src/video_core/texture_cache/surface_params.cpp
index 9e5fe2374..9a98f0e98 100644
--- a/src/video_core/texture_cache/surface_params.cpp
+++ b/src/video_core/texture_cache/surface_params.cpp
@@ -74,9 +74,9 @@ SurfaceParams SurfaceParams::CreateForTexture(const FormatLookupTable& lookup_ta
74 SurfaceParams params; 74 SurfaceParams params;
75 params.is_tiled = tic.IsTiled(); 75 params.is_tiled = tic.IsTiled();
76 params.srgb_conversion = tic.IsSrgbConversionEnabled(); 76 params.srgb_conversion = tic.IsSrgbConversionEnabled();
77 params.block_width = params.is_tiled ? tic.BlockWidth() : 0, 77 params.block_width = params.is_tiled ? tic.BlockWidth() : 0;
78 params.block_height = params.is_tiled ? tic.BlockHeight() : 0, 78 params.block_height = params.is_tiled ? tic.BlockHeight() : 0;
79 params.block_depth = params.is_tiled ? tic.BlockDepth() : 0, 79 params.block_depth = params.is_tiled ? tic.BlockDepth() : 0;
80 params.tile_width_spacing = params.is_tiled ? (1 << tic.tile_width_spacing.Value()) : 1; 80 params.tile_width_spacing = params.is_tiled ? (1 << tic.tile_width_spacing.Value()) : 1;
81 params.pixel_format = lookup_table.GetPixelFormat( 81 params.pixel_format = lookup_table.GetPixelFormat(
82 tic.format, params.srgb_conversion, tic.r_type, tic.g_type, tic.b_type, tic.a_type); 82 tic.format, params.srgb_conversion, tic.r_type, tic.g_type, tic.b_type, tic.a_type);
@@ -130,14 +130,13 @@ SurfaceParams SurfaceParams::CreateForImage(const FormatLookupTable& lookup_tabl
130 SurfaceParams params; 130 SurfaceParams params;
131 params.is_tiled = tic.IsTiled(); 131 params.is_tiled = tic.IsTiled();
132 params.srgb_conversion = tic.IsSrgbConversionEnabled(); 132 params.srgb_conversion = tic.IsSrgbConversionEnabled();
133 params.block_width = params.is_tiled ? tic.BlockWidth() : 0, 133 params.block_width = params.is_tiled ? tic.BlockWidth() : 0;
134 params.block_height = params.is_tiled ? tic.BlockHeight() : 0, 134 params.block_height = params.is_tiled ? tic.BlockHeight() : 0;
135 params.block_depth = params.is_tiled ? tic.BlockDepth() : 0, 135 params.block_depth = params.is_tiled ? tic.BlockDepth() : 0;
136 params.tile_width_spacing = params.is_tiled ? (1 << tic.tile_width_spacing.Value()) : 1; 136 params.tile_width_spacing = params.is_tiled ? (1 << tic.tile_width_spacing.Value()) : 1;
137 params.pixel_format = lookup_table.GetPixelFormat( 137 params.pixel_format = lookup_table.GetPixelFormat(
138 tic.format, params.srgb_conversion, tic.r_type, tic.g_type, tic.b_type, tic.a_type); 138 tic.format, params.srgb_conversion, tic.r_type, tic.g_type, tic.b_type, tic.a_type);
139 params.type = GetFormatType(params.pixel_format); 139 params.type = GetFormatType(params.pixel_format);
140 params.type = GetFormatType(params.pixel_format);
141 params.target = ImageTypeToSurfaceTarget(entry.type); 140 params.target = ImageTypeToSurfaceTarget(entry.type);
142 // TODO: on 1DBuffer we should use the tic info. 141 // TODO: on 1DBuffer we should use the tic info.
143 if (tic.IsBuffer()) { 142 if (tic.IsBuffer()) {
@@ -167,27 +166,30 @@ SurfaceParams SurfaceParams::CreateForImage(const FormatLookupTable& lookup_tabl
167 166
168SurfaceParams SurfaceParams::CreateForDepthBuffer(Core::System& system) { 167SurfaceParams SurfaceParams::CreateForDepthBuffer(Core::System& system) {
169 const auto& regs = system.GPU().Maxwell3D().regs; 168 const auto& regs = system.GPU().Maxwell3D().regs;
170 SurfaceParams params;
171 params.is_tiled = regs.zeta.memory_layout.type ==
172 Tegra::Engines::Maxwell3D::Regs::InvMemoryLayout::BlockLinear;
173 params.srgb_conversion = false;
174 params.block_width = std::min(regs.zeta.memory_layout.block_width.Value(), 5U);
175 params.block_height = std::min(regs.zeta.memory_layout.block_height.Value(), 5U);
176 params.block_depth = std::min(regs.zeta.memory_layout.block_depth.Value(), 5U);
177 params.tile_width_spacing = 1;
178 params.pixel_format = PixelFormatFromDepthFormat(regs.zeta.format);
179 params.type = GetFormatType(params.pixel_format);
180 params.width = regs.zeta_width;
181 params.height = regs.zeta_height;
182 params.pitch = 0;
183 params.num_levels = 1;
184 params.emulated_levels = 1;
185 169
186 const bool is_layered = regs.zeta_layers > 1 && params.block_depth == 0; 170 const auto block_depth = std::min(regs.zeta.memory_layout.block_depth.Value(), 5U);
187 params.is_layered = is_layered; 171 const bool is_layered = regs.zeta_layers > 1 && block_depth == 0;
188 params.target = is_layered ? SurfaceTarget::Texture2DArray : SurfaceTarget::Texture2D; 172 const auto pixel_format = PixelFormatFromDepthFormat(regs.zeta.format);
189 params.depth = is_layered ? regs.zeta_layers.Value() : 1U; 173
190 return params; 174 return {
175 .is_tiled = regs.zeta.memory_layout.type ==
176 Tegra::Engines::Maxwell3D::Regs::InvMemoryLayout::BlockLinear,
177 .srgb_conversion = false,
178 .is_layered = is_layered,
179 .block_width = std::min(regs.zeta.memory_layout.block_width.Value(), 5U),
180 .block_height = std::min(regs.zeta.memory_layout.block_height.Value(), 5U),
181 .block_depth = block_depth,
182 .tile_width_spacing = 1,
183 .width = regs.zeta_width,
184 .height = regs.zeta_height,
185 .depth = is_layered ? regs.zeta_layers.Value() : 1U,
186 .pitch = 0,
187 .num_levels = 1,
188 .emulated_levels = 1,
189 .pixel_format = pixel_format,
190 .type = GetFormatType(pixel_format),
191 .target = is_layered ? SurfaceTarget::Texture2DArray : SurfaceTarget::Texture2D,
192 };
191} 193}
192 194
193SurfaceParams SurfaceParams::CreateForFramebuffer(Core::System& system, std::size_t index) { 195SurfaceParams SurfaceParams::CreateForFramebuffer(Core::System& system, std::size_t index) {
@@ -233,24 +235,29 @@ SurfaceParams SurfaceParams::CreateForFramebuffer(Core::System& system, std::siz
233 235
234SurfaceParams SurfaceParams::CreateForFermiCopySurface( 236SurfaceParams SurfaceParams::CreateForFermiCopySurface(
235 const Tegra::Engines::Fermi2D::Regs::Surface& config) { 237 const Tegra::Engines::Fermi2D::Regs::Surface& config) {
236 SurfaceParams params{}; 238 const bool is_tiled = !config.linear;
237 params.is_tiled = !config.linear; 239 const auto pixel_format = PixelFormatFromRenderTargetFormat(config.format);
238 params.srgb_conversion = config.format == Tegra::RenderTargetFormat::B8G8R8A8_SRGB || 240
239 config.format == Tegra::RenderTargetFormat::A8B8G8R8_SRGB; 241 SurfaceParams params{
240 params.block_width = params.is_tiled ? std::min(config.BlockWidth(), 5U) : 0, 242 .is_tiled = is_tiled,
241 params.block_height = params.is_tiled ? std::min(config.BlockHeight(), 5U) : 0, 243 .srgb_conversion = config.format == Tegra::RenderTargetFormat::B8G8R8A8_SRGB ||
242 params.block_depth = params.is_tiled ? std::min(config.BlockDepth(), 5U) : 0, 244 config.format == Tegra::RenderTargetFormat::A8B8G8R8_SRGB,
243 params.tile_width_spacing = 1; 245 .block_width = is_tiled ? std::min(config.BlockWidth(), 5U) : 0U,
244 params.pixel_format = PixelFormatFromRenderTargetFormat(config.format); 246 .block_height = is_tiled ? std::min(config.BlockHeight(), 5U) : 0U,
245 params.type = GetFormatType(params.pixel_format); 247 .block_depth = is_tiled ? std::min(config.BlockDepth(), 5U) : 0U,
246 params.width = config.width; 248 .tile_width_spacing = 1,
247 params.height = config.height; 249 .width = config.width,
248 params.pitch = config.pitch; 250 .height = config.height,
249 // TODO(Rodrigo): Try to guess texture arrays from parameters 251 .depth = 1,
250 params.target = SurfaceTarget::Texture2D; 252 .pitch = config.pitch,
251 params.depth = 1; 253 .num_levels = 1,
252 params.num_levels = 1; 254 .emulated_levels = 1,
253 params.emulated_levels = 1; 255 .pixel_format = pixel_format,
256 .type = GetFormatType(pixel_format),
257 // TODO(Rodrigo): Try to guess texture arrays from parameters
258 .target = SurfaceTarget::Texture2D,
259 };
260
254 params.is_layered = params.IsLayered(); 261 params.is_layered = params.IsLayered();
255 return params; 262 return params;
256} 263}
diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp
index 59a193edd..94b96afb4 100644
--- a/src/yuzu/configuration/config.cpp
+++ b/src/yuzu/configuration/config.cpp
@@ -666,8 +666,6 @@ void Config::ReadRendererValues() {
666 QStringLiteral("use_asynchronous_shaders"), false); 666 QStringLiteral("use_asynchronous_shaders"), false);
667 ReadSettingGlobal(Settings::values.use_fast_gpu_time, QStringLiteral("use_fast_gpu_time"), 667 ReadSettingGlobal(Settings::values.use_fast_gpu_time, QStringLiteral("use_fast_gpu_time"),
668 true); 668 true);
669 ReadSettingGlobal(Settings::values.force_30fps_mode, QStringLiteral("force_30fps_mode"), false);
670
671 ReadSettingGlobal(Settings::values.bg_red, QStringLiteral("bg_red"), 0.0); 669 ReadSettingGlobal(Settings::values.bg_red, QStringLiteral("bg_red"), 0.0);
672 ReadSettingGlobal(Settings::values.bg_green, QStringLiteral("bg_green"), 0.0); 670 ReadSettingGlobal(Settings::values.bg_green, QStringLiteral("bg_green"), 0.0);
673 ReadSettingGlobal(Settings::values.bg_blue, QStringLiteral("bg_blue"), 0.0); 671 ReadSettingGlobal(Settings::values.bg_blue, QStringLiteral("bg_blue"), 0.0);
@@ -1153,9 +1151,6 @@ void Config::SaveRendererValues() {
1153 Settings::values.use_asynchronous_shaders, false); 1151 Settings::values.use_asynchronous_shaders, false);
1154 WriteSettingGlobal(QStringLiteral("use_fast_gpu_time"), Settings::values.use_fast_gpu_time, 1152 WriteSettingGlobal(QStringLiteral("use_fast_gpu_time"), Settings::values.use_fast_gpu_time,
1155 true); 1153 true);
1156 WriteSettingGlobal(QStringLiteral("force_30fps_mode"), Settings::values.force_30fps_mode,
1157 false);
1158
1159 // Cast to double because Qt's written float values are not human-readable 1154 // Cast to double because Qt's written float values are not human-readable
1160 WriteSettingGlobal(QStringLiteral("bg_red"), Settings::values.bg_red, 0.0); 1155 WriteSettingGlobal(QStringLiteral("bg_red"), Settings::values.bg_red, 0.0);
1161 WriteSettingGlobal(QStringLiteral("bg_green"), Settings::values.bg_green, 0.0); 1156 WriteSettingGlobal(QStringLiteral("bg_green"), Settings::values.bg_green, 0.0);
diff --git a/src/yuzu/configuration/configure_graphics_advanced.cpp b/src/yuzu/configuration/configure_graphics_advanced.cpp
index 8b9180811..c5d1a778c 100644
--- a/src/yuzu/configuration/configure_graphics_advanced.cpp
+++ b/src/yuzu/configuration/configure_graphics_advanced.cpp
@@ -25,14 +25,12 @@ void ConfigureGraphicsAdvanced::SetConfiguration() {
25 ui->use_vsync->setEnabled(runtime_lock); 25 ui->use_vsync->setEnabled(runtime_lock);
26 ui->use_assembly_shaders->setEnabled(runtime_lock); 26 ui->use_assembly_shaders->setEnabled(runtime_lock);
27 ui->use_asynchronous_shaders->setEnabled(runtime_lock); 27 ui->use_asynchronous_shaders->setEnabled(runtime_lock);
28 ui->force_30fps_mode->setEnabled(runtime_lock);
29 ui->anisotropic_filtering_combobox->setEnabled(runtime_lock); 28 ui->anisotropic_filtering_combobox->setEnabled(runtime_lock);
30 29
31 ui->use_vsync->setChecked(Settings::values.use_vsync.GetValue()); 30 ui->use_vsync->setChecked(Settings::values.use_vsync.GetValue());
32 ui->use_assembly_shaders->setChecked(Settings::values.use_assembly_shaders.GetValue()); 31 ui->use_assembly_shaders->setChecked(Settings::values.use_assembly_shaders.GetValue());
33 ui->use_asynchronous_shaders->setChecked(Settings::values.use_asynchronous_shaders.GetValue()); 32 ui->use_asynchronous_shaders->setChecked(Settings::values.use_asynchronous_shaders.GetValue());
34 ui->use_fast_gpu_time->setChecked(Settings::values.use_fast_gpu_time.GetValue()); 33 ui->use_fast_gpu_time->setChecked(Settings::values.use_fast_gpu_time.GetValue());
35 ui->force_30fps_mode->setChecked(Settings::values.force_30fps_mode.GetValue());
36 34
37 if (Settings::configuring_global) { 35 if (Settings::configuring_global) {
38 ui->gpu_accuracy->setCurrentIndex( 36 ui->gpu_accuracy->setCurrentIndex(
@@ -78,9 +76,6 @@ void ConfigureGraphicsAdvanced::ApplyConfiguration() {
78 if (Settings::values.use_fast_gpu_time.UsingGlobal()) { 76 if (Settings::values.use_fast_gpu_time.UsingGlobal()) {
79 Settings::values.use_fast_gpu_time.SetValue(ui->use_fast_gpu_time->isChecked()); 77 Settings::values.use_fast_gpu_time.SetValue(ui->use_fast_gpu_time->isChecked());
80 } 78 }
81 if (Settings::values.force_30fps_mode.UsingGlobal()) {
82 Settings::values.force_30fps_mode.SetValue(ui->force_30fps_mode->isChecked());
83 }
84 if (Settings::values.max_anisotropy.UsingGlobal()) { 79 if (Settings::values.max_anisotropy.UsingGlobal()) {
85 Settings::values.max_anisotropy.SetValue( 80 Settings::values.max_anisotropy.SetValue(
86 ui->anisotropic_filtering_combobox->currentIndex()); 81 ui->anisotropic_filtering_combobox->currentIndex());
@@ -97,8 +92,6 @@ void ConfigureGraphicsAdvanced::ApplyConfiguration() {
97 use_asynchronous_shaders); 92 use_asynchronous_shaders);
98 ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_fast_gpu_time, 93 ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_fast_gpu_time,
99 ui->use_fast_gpu_time, use_fast_gpu_time); 94 ui->use_fast_gpu_time, use_fast_gpu_time);
100 ConfigurationShared::ApplyPerGameSetting(&Settings::values.force_30fps_mode,
101 ui->force_30fps_mode, force_30fps_mode);
102 ConfigurationShared::ApplyPerGameSetting(&Settings::values.max_anisotropy, 95 ConfigurationShared::ApplyPerGameSetting(&Settings::values.max_anisotropy,
103 ui->anisotropic_filtering_combobox); 96 ui->anisotropic_filtering_combobox);
104 97
@@ -132,7 +125,6 @@ void ConfigureGraphicsAdvanced::SetupPerGameUI() {
132 ui->use_asynchronous_shaders->setEnabled( 125 ui->use_asynchronous_shaders->setEnabled(
133 Settings::values.use_asynchronous_shaders.UsingGlobal()); 126 Settings::values.use_asynchronous_shaders.UsingGlobal());
134 ui->use_fast_gpu_time->setEnabled(Settings::values.use_fast_gpu_time.UsingGlobal()); 127 ui->use_fast_gpu_time->setEnabled(Settings::values.use_fast_gpu_time.UsingGlobal());
135 ui->force_30fps_mode->setEnabled(Settings::values.force_30fps_mode.UsingGlobal());
136 ui->anisotropic_filtering_combobox->setEnabled( 128 ui->anisotropic_filtering_combobox->setEnabled(
137 Settings::values.max_anisotropy.UsingGlobal()); 129 Settings::values.max_anisotropy.UsingGlobal());
138 130
@@ -149,8 +141,6 @@ void ConfigureGraphicsAdvanced::SetupPerGameUI() {
149 Settings::values.use_asynchronous_shaders, use_asynchronous_shaders); 141 Settings::values.use_asynchronous_shaders, use_asynchronous_shaders);
150 ConfigurationShared::SetColoredTristate(ui->use_fast_gpu_time, "use_fast_gpu_time", 142 ConfigurationShared::SetColoredTristate(ui->use_fast_gpu_time, "use_fast_gpu_time",
151 Settings::values.use_fast_gpu_time, use_fast_gpu_time); 143 Settings::values.use_fast_gpu_time, use_fast_gpu_time);
152 ConfigurationShared::SetColoredTristate(ui->force_30fps_mode, "force_30fps_mode",
153 Settings::values.force_30fps_mode, force_30fps_mode);
154 ConfigurationShared::SetColoredComboBox( 144 ConfigurationShared::SetColoredComboBox(
155 ui->gpu_accuracy, ui->label_gpu_accuracy, "label_gpu_accuracy", 145 ui->gpu_accuracy, ui->label_gpu_accuracy, "label_gpu_accuracy",
156 static_cast<int>(Settings::values.gpu_accuracy.GetValue(true))); 146 static_cast<int>(Settings::values.gpu_accuracy.GetValue(true)));
diff --git a/src/yuzu/configuration/configure_graphics_advanced.h b/src/yuzu/configuration/configure_graphics_advanced.h
index 3c4f6f7bb..e61b571c7 100644
--- a/src/yuzu/configuration/configure_graphics_advanced.h
+++ b/src/yuzu/configuration/configure_graphics_advanced.h
@@ -38,5 +38,4 @@ private:
38 ConfigurationShared::CheckState use_assembly_shaders; 38 ConfigurationShared::CheckState use_assembly_shaders;
39 ConfigurationShared::CheckState use_asynchronous_shaders; 39 ConfigurationShared::CheckState use_asynchronous_shaders;
40 ConfigurationShared::CheckState use_fast_gpu_time; 40 ConfigurationShared::CheckState use_fast_gpu_time;
41 ConfigurationShared::CheckState force_30fps_mode;
42}; 41};
diff --git a/src/yuzu/configuration/configure_graphics_advanced.ui b/src/yuzu/configuration/configure_graphics_advanced.ui
index 6a0d29c27..a793c803d 100644
--- a/src/yuzu/configuration/configure_graphics_advanced.ui
+++ b/src/yuzu/configuration/configure_graphics_advanced.ui
@@ -97,13 +97,6 @@
97 </widget> 97 </widget>
98 </item> 98 </item>
99 <item> 99 <item>
100 <widget class="QCheckBox" name="force_30fps_mode">
101 <property name="text">
102 <string>Force 30 FPS mode</string>
103 </property>
104 </widget>
105 </item>
106 <item>
107 <widget class="QCheckBox" name="use_fast_gpu_time"> 100 <widget class="QCheckBox" name="use_fast_gpu_time">
108 <property name="text"> 101 <property name="text">
109 <string>Use Fast GPU Time</string> 102 <string>Use Fast GPU Time</string>
diff --git a/src/yuzu/game_list.cpp b/src/yuzu/game_list.cpp
index ab7fc7a24..62acc3720 100644
--- a/src/yuzu/game_list.cpp
+++ b/src/yuzu/game_list.cpp
@@ -474,28 +474,56 @@ void GameList::PopupContextMenu(const QPoint& menu_location) {
474 474
475void GameList::AddGamePopup(QMenu& context_menu, u64 program_id, std::string path) { 475void GameList::AddGamePopup(QMenu& context_menu, u64 program_id, std::string path) {
476 QAction* open_save_location = context_menu.addAction(tr("Open Save Data Location")); 476 QAction* open_save_location = context_menu.addAction(tr("Open Save Data Location"));
477 QAction* open_lfs_location = context_menu.addAction(tr("Open Mod Data Location")); 477 QAction* open_mod_location = context_menu.addAction(tr("Open Mod Data Location"));
478 QAction* open_transferable_shader_cache = 478 QAction* open_transferable_shader_cache =
479 context_menu.addAction(tr("Open Transferable Shader Cache")); 479 context_menu.addAction(tr("Open Transferable Shader Cache"));
480 context_menu.addSeparator(); 480 context_menu.addSeparator();
481 QMenu* remove_menu = context_menu.addMenu(tr("Remove"));
482 QAction* remove_update = remove_menu->addAction(tr("Remove Installed Update"));
483 QAction* remove_dlc = remove_menu->addAction(tr("Remove All Installed DLC"));
484 QAction* remove_shader_cache = remove_menu->addAction(tr("Remove Shader Cache"));
485 QAction* remove_custom_config = remove_menu->addAction(tr("Remove Custom Configuration"));
486 remove_menu->addSeparator();
487 QAction* remove_all_content = remove_menu->addAction(tr("Remove All Installed Contents"));
481 QAction* dump_romfs = context_menu.addAction(tr("Dump RomFS")); 488 QAction* dump_romfs = context_menu.addAction(tr("Dump RomFS"));
482 QAction* copy_tid = context_menu.addAction(tr("Copy Title ID to Clipboard")); 489 QAction* copy_tid = context_menu.addAction(tr("Copy Title ID to Clipboard"));
483 QAction* navigate_to_gamedb_entry = context_menu.addAction(tr("Navigate to GameDB entry")); 490 QAction* navigate_to_gamedb_entry = context_menu.addAction(tr("Navigate to GameDB entry"));
484 context_menu.addSeparator(); 491 context_menu.addSeparator();
485 QAction* properties = context_menu.addAction(tr("Properties")); 492 QAction* properties = context_menu.addAction(tr("Properties"));
486 493
487 open_save_location->setEnabled(program_id != 0); 494 open_save_location->setVisible(program_id != 0);
495 open_mod_location->setVisible(program_id != 0);
496 open_transferable_shader_cache->setVisible(program_id != 0);
497 remove_update->setVisible(program_id != 0);
498 remove_dlc->setVisible(program_id != 0);
499 remove_shader_cache->setVisible(program_id != 0);
500 remove_all_content->setVisible(program_id != 0);
488 auto it = FindMatchingCompatibilityEntry(compatibility_list, program_id); 501 auto it = FindMatchingCompatibilityEntry(compatibility_list, program_id);
489 navigate_to_gamedb_entry->setVisible(it != compatibility_list.end() && program_id != 0); 502 navigate_to_gamedb_entry->setVisible(it != compatibility_list.end() && program_id != 0);
490 503
491 connect(open_save_location, &QAction::triggered, [this, program_id, path]() { 504 connect(open_save_location, &QAction::triggered, [this, program_id, path]() {
492 emit OpenFolderRequested(GameListOpenTarget::SaveData, path); 505 emit OpenFolderRequested(GameListOpenTarget::SaveData, path);
493 }); 506 });
494 connect(open_lfs_location, &QAction::triggered, [this, program_id, path]() { 507 connect(open_mod_location, &QAction::triggered, [this, program_id, path]() {
495 emit OpenFolderRequested(GameListOpenTarget::ModData, path); 508 emit OpenFolderRequested(GameListOpenTarget::ModData, path);
496 }); 509 });
497 connect(open_transferable_shader_cache, &QAction::triggered, 510 connect(open_transferable_shader_cache, &QAction::triggered,
498 [this, program_id]() { emit OpenTransferableShaderCacheRequested(program_id); }); 511 [this, program_id]() { emit OpenTransferableShaderCacheRequested(program_id); });
512 connect(remove_all_content, &QAction::triggered, [this, program_id]() {
513 emit RemoveInstalledEntryRequested(program_id, InstalledEntryType::Game);
514 });
515 connect(remove_update, &QAction::triggered, [this, program_id]() {
516 emit RemoveInstalledEntryRequested(program_id, InstalledEntryType::Update);
517 });
518 connect(remove_dlc, &QAction::triggered, [this, program_id]() {
519 emit RemoveInstalledEntryRequested(program_id, InstalledEntryType::AddOnContent);
520 });
521 connect(remove_shader_cache, &QAction::triggered, [this, program_id]() {
522 emit RemoveFileRequested(program_id, GameListRemoveTarget::ShaderCache);
523 });
524 connect(remove_custom_config, &QAction::triggered, [this, program_id]() {
525 emit RemoveFileRequested(program_id, GameListRemoveTarget::CustomConfiguration);
526 });
499 connect(dump_romfs, &QAction::triggered, 527 connect(dump_romfs, &QAction::triggered,
500 [this, program_id, path]() { emit DumpRomFSRequested(program_id, path); }); 528 [this, program_id, path]() { emit DumpRomFSRequested(program_id, path); });
501 connect(copy_tid, &QAction::triggered, 529 connect(copy_tid, &QAction::triggered,
diff --git a/src/yuzu/game_list.h b/src/yuzu/game_list.h
index a38cb2fc3..483835cce 100644
--- a/src/yuzu/game_list.h
+++ b/src/yuzu/game_list.h
@@ -39,6 +39,17 @@ enum class GameListOpenTarget {
39 ModData, 39 ModData,
40}; 40};
41 41
42enum class GameListRemoveTarget {
43 ShaderCache,
44 CustomConfiguration,
45};
46
47enum class InstalledEntryType {
48 Game,
49 Update,
50 AddOnContent,
51};
52
42class GameList : public QWidget { 53class GameList : public QWidget {
43 Q_OBJECT 54 Q_OBJECT
44 55
@@ -75,6 +86,8 @@ signals:
75 void ShouldCancelWorker(); 86 void ShouldCancelWorker();
76 void OpenFolderRequested(GameListOpenTarget target, const std::string& game_path); 87 void OpenFolderRequested(GameListOpenTarget target, const std::string& game_path);
77 void OpenTransferableShaderCacheRequested(u64 program_id); 88 void OpenTransferableShaderCacheRequested(u64 program_id);
89 void RemoveInstalledEntryRequested(u64 program_id, InstalledEntryType type);
90 void RemoveFileRequested(u64 program_id, GameListRemoveTarget target);
78 void DumpRomFSRequested(u64 program_id, const std::string& game_path); 91 void DumpRomFSRequested(u64 program_id, const std::string& game_path);
79 void CopyTIDRequested(u64 program_id); 92 void CopyTIDRequested(u64 program_id);
80 void NavigateToGamedbEntryRequested(u64 program_id, 93 void NavigateToGamedbEntryRequested(u64 program_id,
@@ -117,8 +130,6 @@ private:
117 friend class GameListSearchField; 130 friend class GameListSearchField;
118}; 131};
119 132
120Q_DECLARE_METATYPE(GameListOpenTarget);
121
122class GameListPlaceholder : public QWidget { 133class GameListPlaceholder : public QWidget {
123 Q_OBJECT 134 Q_OBJECT
124public: 135public:
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index 31a635176..2ff559746 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -847,6 +847,9 @@ void GMainWindow::ConnectWidgetEvents() {
847 connect(game_list, &GameList::OpenFolderRequested, this, &GMainWindow::OnGameListOpenFolder); 847 connect(game_list, &GameList::OpenFolderRequested, this, &GMainWindow::OnGameListOpenFolder);
848 connect(game_list, &GameList::OpenTransferableShaderCacheRequested, this, 848 connect(game_list, &GameList::OpenTransferableShaderCacheRequested, this,
849 &GMainWindow::OnTransferableShaderCacheOpenFile); 849 &GMainWindow::OnTransferableShaderCacheOpenFile);
850 connect(game_list, &GameList::RemoveInstalledEntryRequested, this,
851 &GMainWindow::OnGameListRemoveInstalledEntry);
852 connect(game_list, &GameList::RemoveFileRequested, this, &GMainWindow::OnGameListRemoveFile);
850 connect(game_list, &GameList::DumpRomFSRequested, this, &GMainWindow::OnGameListDumpRomFS); 853 connect(game_list, &GameList::DumpRomFSRequested, this, &GMainWindow::OnGameListDumpRomFS);
851 connect(game_list, &GameList::CopyTIDRequested, this, &GMainWindow::OnGameListCopyTID); 854 connect(game_list, &GameList::CopyTIDRequested, this, &GMainWindow::OnGameListCopyTID);
852 connect(game_list, &GameList::NavigateToGamedbEntryRequested, this, 855 connect(game_list, &GameList::NavigateToGamedbEntryRequested, this,
@@ -1257,7 +1260,6 @@ void GMainWindow::OnGameListOpenFolder(GameListOpenTarget target, const std::str
1257 case GameListOpenTarget::SaveData: { 1260 case GameListOpenTarget::SaveData: {
1258 open_target = tr("Save Data"); 1261 open_target = tr("Save Data");
1259 const std::string nand_dir = FileUtil::GetUserPath(FileUtil::UserPath::NANDDir); 1262 const std::string nand_dir = FileUtil::GetUserPath(FileUtil::UserPath::NANDDir);
1260 ASSERT(program_id != 0);
1261 1263
1262 if (has_user_save) { 1264 if (has_user_save) {
1263 // User save data 1265 // User save data
@@ -1322,14 +1324,12 @@ void GMainWindow::OnGameListOpenFolder(GameListOpenTarget target, const std::str
1322} 1324}
1323 1325
1324void GMainWindow::OnTransferableShaderCacheOpenFile(u64 program_id) { 1326void GMainWindow::OnTransferableShaderCacheOpenFile(u64 program_id) {
1325 ASSERT(program_id != 0);
1326
1327 const QString shader_dir = 1327 const QString shader_dir =
1328 QString::fromStdString(FileUtil::GetUserPath(FileUtil::UserPath::ShaderDir)); 1328 QString::fromStdString(FileUtil::GetUserPath(FileUtil::UserPath::ShaderDir));
1329 const QString tranferable_shader_cache_folder_path = 1329 const QString transferable_shader_cache_folder_path =
1330 shader_dir + QStringLiteral("opengl") + QDir::separator() + QStringLiteral("transferable"); 1330 shader_dir + QStringLiteral("opengl") + QDir::separator() + QStringLiteral("transferable");
1331 const QString transferable_shader_cache_file_path = 1331 const QString transferable_shader_cache_file_path =
1332 tranferable_shader_cache_folder_path + QDir::separator() + 1332 transferable_shader_cache_folder_path + QDir::separator() +
1333 QString::fromStdString(fmt::format("{:016X}.bin", program_id)); 1333 QString::fromStdString(fmt::format("{:016X}.bin", program_id));
1334 1334
1335 if (!QFile::exists(transferable_shader_cache_file_path)) { 1335 if (!QFile::exists(transferable_shader_cache_file_path)) {
@@ -1350,7 +1350,7 @@ void GMainWindow::OnTransferableShaderCacheOpenFile(u64 program_id) {
1350 param << QDir::toNativeSeparators(transferable_shader_cache_file_path); 1350 param << QDir::toNativeSeparators(transferable_shader_cache_file_path);
1351 QProcess::startDetached(explorer, param); 1351 QProcess::startDetached(explorer, param);
1352#else 1352#else
1353 QDesktopServices::openUrl(QUrl::fromLocalFile(tranferable_shader_cache_folder_path)); 1353 QDesktopServices::openUrl(QUrl::fromLocalFile(transferable_shader_cache_folder_path));
1354#endif 1354#endif
1355} 1355}
1356 1356
@@ -1394,6 +1394,174 @@ static bool RomFSRawCopy(QProgressDialog& dialog, const FileSys::VirtualDir& src
1394 return true; 1394 return true;
1395} 1395}
1396 1396
1397void GMainWindow::OnGameListRemoveInstalledEntry(u64 program_id, InstalledEntryType type) {
1398 const QString entry_type = [this, type] {
1399 switch (type) {
1400 case InstalledEntryType::Game:
1401 return tr("Contents");
1402 case InstalledEntryType::Update:
1403 return tr("Update");
1404 case InstalledEntryType::AddOnContent:
1405 return tr("DLC");
1406 default:
1407 return QString{};
1408 }
1409 }();
1410
1411 if (QMessageBox::question(
1412 this, tr("Remove Entry"), tr("Remove Installed Game %1?").arg(entry_type),
1413 QMessageBox::Yes | QMessageBox::No, QMessageBox::No) != QMessageBox::Yes) {
1414 return;
1415 }
1416
1417 switch (type) {
1418 case InstalledEntryType::Game:
1419 RemoveBaseContent(program_id, entry_type);
1420 [[fallthrough]];
1421 case InstalledEntryType::Update:
1422 RemoveUpdateContent(program_id, entry_type);
1423 if (type != InstalledEntryType::Game) {
1424 break;
1425 }
1426 [[fallthrough]];
1427 case InstalledEntryType::AddOnContent:
1428 RemoveAddOnContent(program_id, entry_type);
1429 break;
1430 }
1431 FileUtil::DeleteDirRecursively(FileUtil::GetUserPath(FileUtil::UserPath::CacheDir) + DIR_SEP +
1432 "game_list");
1433 game_list->PopulateAsync(UISettings::values.game_dirs);
1434}
1435
1436void GMainWindow::RemoveBaseContent(u64 program_id, const QString& entry_type) {
1437 const auto& fs_controller = Core::System::GetInstance().GetFileSystemController();
1438 const auto res = fs_controller.GetUserNANDContents()->RemoveExistingEntry(program_id) ||
1439 fs_controller.GetSDMCContents()->RemoveExistingEntry(program_id);
1440
1441 if (res) {
1442 QMessageBox::information(this, tr("Successfully Removed"),
1443 tr("Successfully removed the installed base game."));
1444 } else {
1445 QMessageBox::warning(
1446 this, tr("Error Removing %1").arg(entry_type),
1447 tr("The base game is not installed in the NAND and cannot be removed."));
1448 }
1449}
1450
1451void GMainWindow::RemoveUpdateContent(u64 program_id, const QString& entry_type) {
1452 const auto update_id = program_id | 0x800;
1453 const auto& fs_controller = Core::System::GetInstance().GetFileSystemController();
1454 const auto res = fs_controller.GetUserNANDContents()->RemoveExistingEntry(update_id) ||
1455 fs_controller.GetSDMCContents()->RemoveExistingEntry(update_id);
1456
1457 if (res) {
1458 QMessageBox::information(this, tr("Successfully Removed"),
1459 tr("Successfully removed the installed update."));
1460 } else {
1461 QMessageBox::warning(this, tr("Error Removing %1").arg(entry_type),
1462 tr("There is no update installed for this title."));
1463 }
1464}
1465
1466void GMainWindow::RemoveAddOnContent(u64 program_id, const QString& entry_type) {
1467 u32 count{};
1468 const auto& fs_controller = Core::System::GetInstance().GetFileSystemController();
1469 const auto dlc_entries = Core::System::GetInstance().GetContentProvider().ListEntriesFilter(
1470 FileSys::TitleType::AOC, FileSys::ContentRecordType::Data);
1471
1472 for (const auto& entry : dlc_entries) {
1473 if ((entry.title_id & DLC_BASE_TITLE_ID_MASK) == program_id) {
1474 const auto res =
1475 fs_controller.GetUserNANDContents()->RemoveExistingEntry(entry.title_id) ||
1476 fs_controller.GetSDMCContents()->RemoveExistingEntry(entry.title_id);
1477 if (res) {
1478 ++count;
1479 }
1480 }
1481 }
1482
1483 if (count == 0) {
1484 QMessageBox::warning(this, tr("Error Removing %1").arg(entry_type),
1485 tr("There are no DLC installed for this title."));
1486 return;
1487 }
1488
1489 QMessageBox::information(this, tr("Successfully Removed"),
1490 tr("Successfully removed %1 installed DLC.").arg(count));
1491}
1492
1493void GMainWindow::OnGameListRemoveFile(u64 program_id, GameListRemoveTarget target) {
1494 const QString question = [this, target] {
1495 switch (target) {
1496 case GameListRemoveTarget::ShaderCache:
1497 return tr("Delete Transferable Shader Cache?");
1498 case GameListRemoveTarget::CustomConfiguration:
1499 return tr("Remove Custom Game Configuration?");
1500 default:
1501 return QString{};
1502 }
1503 }();
1504
1505 if (QMessageBox::question(this, tr("Remove File"), question, QMessageBox::Yes | QMessageBox::No,
1506 QMessageBox::No) != QMessageBox::Yes) {
1507 return;
1508 }
1509
1510 switch (target) {
1511 case GameListRemoveTarget::ShaderCache:
1512 RemoveTransferableShaderCache(program_id);
1513 break;
1514 case GameListRemoveTarget::CustomConfiguration:
1515 RemoveCustomConfiguration(program_id);
1516 break;
1517 }
1518}
1519
1520void GMainWindow::RemoveTransferableShaderCache(u64 program_id) {
1521 const QString shader_dir =
1522 QString::fromStdString(FileUtil::GetUserPath(FileUtil::UserPath::ShaderDir));
1523 const QString transferable_shader_cache_folder_path =
1524 shader_dir + QStringLiteral("opengl") + QDir::separator() + QStringLiteral("transferable");
1525 const QString transferable_shader_cache_file_path =
1526 transferable_shader_cache_folder_path + QDir::separator() +
1527 QString::fromStdString(fmt::format("{:016X}.bin", program_id));
1528
1529 if (!QFile::exists(transferable_shader_cache_file_path)) {
1530 QMessageBox::warning(this, tr("Error Removing Transferable Shader Cache"),
1531 tr("A shader cache for this title does not exist."));
1532 return;
1533 }
1534
1535 if (QFile::remove(transferable_shader_cache_file_path)) {
1536 QMessageBox::information(this, tr("Successfully Removed"),
1537 tr("Successfully removed the transferable shader cache."));
1538 } else {
1539 QMessageBox::warning(this, tr("Error Removing Transferable Shader Cache"),
1540 tr("Failed to remove the transferable shader cache."));
1541 }
1542}
1543
1544void GMainWindow::RemoveCustomConfiguration(u64 program_id) {
1545 const QString config_dir =
1546 QString::fromStdString(FileUtil::GetUserPath(FileUtil::UserPath::ConfigDir));
1547 const QString custom_config_file_path =
1548 config_dir + QString::fromStdString(fmt::format("{:016X}.ini", program_id));
1549
1550 if (!QFile::exists(custom_config_file_path)) {
1551 QMessageBox::warning(this, tr("Error Removing Custom Configuration"),
1552 tr("A custom configuration for this title does not exist."));
1553 return;
1554 }
1555
1556 if (QFile::remove(custom_config_file_path)) {
1557 QMessageBox::information(this, tr("Successfully Removed"),
1558 tr("Successfully removed the custom game configuration."));
1559 } else {
1560 QMessageBox::warning(this, tr("Error Removing Custom Configuration"),
1561 tr("Failed to remove the custom game configuration."));
1562 }
1563}
1564
1397void GMainWindow::OnGameListDumpRomFS(u64 program_id, const std::string& game_path) { 1565void GMainWindow::OnGameListDumpRomFS(u64 program_id, const std::string& game_path) {
1398 const auto failed = [this] { 1566 const auto failed = [this] {
1399 QMessageBox::warning(this, tr("RomFS Extraction Failed!"), 1567 QMessageBox::warning(this, tr("RomFS Extraction Failed!"),
@@ -1655,7 +1823,7 @@ void GMainWindow::OnMenuInstallToNAND() {
1655 1823
1656 ui.action_Install_File_NAND->setEnabled(false); 1824 ui.action_Install_File_NAND->setEnabled(false);
1657 1825
1658 install_progress = new QProgressDialog(QStringLiteral(""), tr("Cancel"), 0, total_size, this); 1826 install_progress = new QProgressDialog(QString{}, tr("Cancel"), 0, total_size, this);
1659 install_progress->setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint & 1827 install_progress->setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint &
1660 ~Qt::WindowMaximizeButtonHint); 1828 ~Qt::WindowMaximizeButtonHint);
1661 install_progress->setAttribute(Qt::WA_DeleteOnClose, true); 1829 install_progress->setAttribute(Qt::WA_DeleteOnClose, true);
@@ -1705,18 +1873,18 @@ void GMainWindow::OnMenuInstallToNAND() {
1705 install_progress->close(); 1873 install_progress->close();
1706 1874
1707 const QString install_results = 1875 const QString install_results =
1708 (new_files.isEmpty() ? QStringLiteral("") 1876 (new_files.isEmpty() ? QString{}
1709 : tr("%n file(s) were newly installed\n", "", new_files.size())) + 1877 : tr("%n file(s) were newly installed\n", "", new_files.size())) +
1710 (overwritten_files.isEmpty() 1878 (overwritten_files.isEmpty()
1711 ? QStringLiteral("") 1879 ? QString{}
1712 : tr("%n file(s) were overwritten\n", "", overwritten_files.size())) + 1880 : tr("%n file(s) were overwritten\n", "", overwritten_files.size())) +
1713 (failed_files.isEmpty() ? QStringLiteral("") 1881 (failed_files.isEmpty() ? QString{}
1714 : tr("%n file(s) failed to install\n", "", failed_files.size())); 1882 : tr("%n file(s) failed to install\n", "", failed_files.size()));
1715 1883
1716 QMessageBox::information(this, tr("Install Results"), install_results); 1884 QMessageBox::information(this, tr("Install Results"), install_results);
1717 game_list->PopulateAsync(UISettings::values.game_dirs);
1718 FileUtil::DeleteDirRecursively(FileUtil::GetUserPath(FileUtil::UserPath::CacheDir) + DIR_SEP + 1885 FileUtil::DeleteDirRecursively(FileUtil::GetUserPath(FileUtil::UserPath::CacheDir) + DIR_SEP +
1719 "game_list"); 1886 "game_list");
1887 game_list->PopulateAsync(UISettings::values.game_dirs);
1720 ui.action_Install_File_NAND->setEnabled(true); 1888 ui.action_Install_File_NAND->setEnabled(true);
1721} 1889}
1722 1890
@@ -2202,8 +2370,7 @@ void GMainWindow::UpdateStatusBar() {
2202 2370
2203 if (shaders_building != 0) { 2371 if (shaders_building != 0) {
2204 shader_building_label->setText( 2372 shader_building_label->setText(
2205 tr("Building: %1 shader").arg(shaders_building) + 2373 tr("Building: %n shader(s)", "", static_cast<int>(shaders_building)));
2206 (shaders_building != 1 ? QString::fromStdString("s") : QString::fromStdString("")));
2207 shader_building_label->setVisible(true); 2374 shader_building_label->setVisible(true);
2208 } else { 2375 } else {
2209 shader_building_label->setVisible(false); 2376 shader_building_label->setVisible(false);
diff --git a/src/yuzu/main.h b/src/yuzu/main.h
index db573d606..73a44a3bf 100644
--- a/src/yuzu/main.h
+++ b/src/yuzu/main.h
@@ -32,6 +32,8 @@ class QPushButton;
32class QProgressDialog; 32class QProgressDialog;
33class WaitTreeWidget; 33class WaitTreeWidget;
34enum class GameListOpenTarget; 34enum class GameListOpenTarget;
35enum class GameListRemoveTarget;
36enum class InstalledEntryType;
35class GameListPlaceholder; 37class GameListPlaceholder;
36 38
37namespace Core::Frontend { 39namespace Core::Frontend {
@@ -198,6 +200,8 @@ private slots:
198 void OnGameListLoadFile(QString game_path); 200 void OnGameListLoadFile(QString game_path);
199 void OnGameListOpenFolder(GameListOpenTarget target, const std::string& game_path); 201 void OnGameListOpenFolder(GameListOpenTarget target, const std::string& game_path);
200 void OnTransferableShaderCacheOpenFile(u64 program_id); 202 void OnTransferableShaderCacheOpenFile(u64 program_id);
203 void OnGameListRemoveInstalledEntry(u64 program_id, InstalledEntryType type);
204 void OnGameListRemoveFile(u64 program_id, GameListRemoveTarget target);
201 void OnGameListDumpRomFS(u64 program_id, const std::string& game_path); 205 void OnGameListDumpRomFS(u64 program_id, const std::string& game_path);
202 void OnGameListCopyTID(u64 program_id); 206 void OnGameListCopyTID(u64 program_id);
203 void OnGameListNavigateToGamedbEntry(u64 program_id, 207 void OnGameListNavigateToGamedbEntry(u64 program_id,
@@ -229,6 +233,11 @@ private slots:
229 void OnLanguageChanged(const QString& locale); 233 void OnLanguageChanged(const QString& locale);
230 234
231private: 235private:
236 void RemoveBaseContent(u64 program_id, const QString& entry_type);
237 void RemoveUpdateContent(u64 program_id, const QString& entry_type);
238 void RemoveAddOnContent(u64 program_id, const QString& entry_type);
239 void RemoveTransferableShaderCache(u64 program_id);
240 void RemoveCustomConfiguration(u64 program_id);
232 std::optional<u64> SelectRomFSDumpTarget(const FileSys::ContentProvider&, u64 program_id); 241 std::optional<u64> SelectRomFSDumpTarget(const FileSys::ContentProvider&, u64 program_id);
233 InstallResult InstallNSPXCI(const QString& filename); 242 InstallResult InstallNSPXCI(const QString& filename);
234 InstallResult InstallNCA(const QString& filename); 243 InstallResult InstallNCA(const QString& filename);