summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/common/bit_field.h19
-rw-r--r--src/core/file_sys/card_image.cpp2
-rw-r--r--src/core/file_sys/card_image.h3
-rw-r--r--src/core/file_sys/content_archive.cpp5
-rw-r--r--src/core/file_sys/content_archive.h3
-rw-r--r--src/core/file_sys/errors.h25
-rw-r--r--src/core/file_sys/registered_cache.cpp13
-rw-r--r--src/core/file_sys/registered_cache.h3
-rw-r--r--src/core/file_sys/submission_package.cpp2
-rw-r--r--src/core/file_sys/submission_package.h2
-rw-r--r--src/core/hle/kernel/errors.h74
-rw-r--r--src/core/hle/kernel/svc.cpp64
-rw-r--r--src/core/hle/kernel/svc_wrap.h5
-rw-r--r--src/core/hle/result.h2
-rw-r--r--src/core/hle/service/audio/hwopus.cpp2
-rw-r--r--src/core/hle/service/filesystem/filesystem.cpp19
-rw-r--r--src/core/hle/service/filesystem/filesystem.h2
-rw-r--r--src/core/hle/service/filesystem/fsp_srv.cpp16
-rw-r--r--src/core/hle/service/hid/hid.cpp16
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer_cache.cpp6
-rw-r--r--src/video_core/renderer_opengl/gl_state.cpp5
-rw-r--r--src/video_core/renderer_opengl/gl_state.h2
-rw-r--r--src/video_core/textures/decoders.cpp32
-rw-r--r--src/yuzu/configuration/config.cpp2
-rw-r--r--src/yuzu/configuration/configure_gamelist.cpp2
-rw-r--r--src/yuzu/configuration/configure_gamelist.ui223
-rw-r--r--src/yuzu/game_list.cpp33
-rw-r--r--src/yuzu/game_list_worker.cpp24
-rw-r--r--src/yuzu/ui_settings.h1
29 files changed, 344 insertions, 263 deletions
diff --git a/src/common/bit_field.h b/src/common/bit_field.h
index bf803da8d..21e07925d 100644
--- a/src/common/bit_field.h
+++ b/src/common/bit_field.h
@@ -117,21 +117,21 @@ private:
117 // We don't delete it because we want BitField to be trivially copyable. 117 // We don't delete it because we want BitField to be trivially copyable.
118 constexpr BitField& operator=(const BitField&) = default; 118 constexpr BitField& operator=(const BitField&) = default;
119 119
120 // StorageType is T for non-enum types and the underlying type of T if 120 // UnderlyingType is T for non-enum types and the underlying type of T if
121 // T is an enumeration. Note that T is wrapped within an enable_if in the 121 // T is an enumeration. Note that T is wrapped within an enable_if in the
122 // former case to workaround compile errors which arise when using 122 // former case to workaround compile errors which arise when using
123 // std::underlying_type<T>::type directly. 123 // std::underlying_type<T>::type directly.
124 using StorageType = typename std::conditional_t<std::is_enum<T>::value, std::underlying_type<T>, 124 using UnderlyingType = typename std::conditional_t<std::is_enum_v<T>, std::underlying_type<T>,
125 std::enable_if<true, T>>::type; 125 std::enable_if<true, T>>::type;
126 126
127 // Unsigned version of StorageType 127 // We store the value as the unsigned type to avoid undefined behaviour on value shifting
128 using StorageTypeU = std::make_unsigned_t<StorageType>; 128 using StorageType = std::make_unsigned_t<UnderlyingType>;
129 129
130public: 130public:
131 /// Constants to allow limited introspection of fields if needed 131 /// Constants to allow limited introspection of fields if needed
132 static constexpr std::size_t position = Position; 132 static constexpr std::size_t position = Position;
133 static constexpr std::size_t bits = Bits; 133 static constexpr std::size_t bits = Bits;
134 static constexpr StorageType mask = (((StorageTypeU)~0) >> (8 * sizeof(T) - bits)) << position; 134 static constexpr StorageType mask = (((StorageType)~0) >> (8 * sizeof(T) - bits)) << position;
135 135
136 /** 136 /**
137 * Formats a value by masking and shifting it according to the field parameters. A value 137 * Formats a value by masking and shifting it according to the field parameters. A value
@@ -148,11 +148,12 @@ public:
148 * union in a constexpr context. 148 * union in a constexpr context.
149 */ 149 */
150 static constexpr FORCE_INLINE T ExtractValue(const StorageType& storage) { 150 static constexpr FORCE_INLINE T ExtractValue(const StorageType& storage) {
151 if (std::numeric_limits<T>::is_signed) { 151 if constexpr (std::numeric_limits<UnderlyingType>::is_signed) {
152 std::size_t shift = 8 * sizeof(T) - bits; 152 std::size_t shift = 8 * sizeof(T) - bits;
153 return (T)((storage << (shift - position)) >> shift); 153 return static_cast<T>(static_cast<UnderlyingType>(storage << (shift - position)) >>
154 shift);
154 } else { 155 } else {
155 return (T)((storage & mask) >> position); 156 return static_cast<T>((storage & mask) >> position);
156 } 157 }
157 } 158 }
158 159
diff --git a/src/core/file_sys/card_image.cpp b/src/core/file_sys/card_image.cpp
index 1ece55731..2c145bd09 100644
--- a/src/core/file_sys/card_image.cpp
+++ b/src/core/file_sys/card_image.cpp
@@ -176,7 +176,7 @@ Loader::ResultStatus XCI::AddNCAFromPartition(XCIPartition part) {
176 for (const VirtualFile& file : partitions[static_cast<std::size_t>(part)]->GetFiles()) { 176 for (const VirtualFile& file : partitions[static_cast<std::size_t>(part)]->GetFiles()) {
177 if (file->GetExtension() != "nca") 177 if (file->GetExtension() != "nca")
178 continue; 178 continue;
179 auto nca = std::make_shared<NCA>(file); 179 auto nca = std::make_shared<NCA>(file, nullptr, 0, keys);
180 // TODO(DarkLordZach): Add proper Rev1+ Support 180 // TODO(DarkLordZach): Add proper Rev1+ Support
181 if (nca->IsUpdate()) 181 if (nca->IsUpdate())
182 continue; 182 continue;
diff --git a/src/core/file_sys/card_image.h b/src/core/file_sys/card_image.h
index 8f62571cf..25f5914b6 100644
--- a/src/core/file_sys/card_image.h
+++ b/src/core/file_sys/card_image.h
@@ -9,6 +9,7 @@
9#include <vector> 9#include <vector>
10#include "common/common_types.h" 10#include "common/common_types.h"
11#include "common/swap.h" 11#include "common/swap.h"
12#include "core/crypto/key_manager.h"
12#include "core/file_sys/vfs.h" 13#include "core/file_sys/vfs.h"
13 14
14namespace Loader { 15namespace Loader {
@@ -107,5 +108,7 @@ private:
107 std::shared_ptr<NSP> secure_partition; 108 std::shared_ptr<NSP> secure_partition;
108 std::shared_ptr<NCA> program; 109 std::shared_ptr<NCA> program;
109 std::vector<std::shared_ptr<NCA>> ncas; 110 std::vector<std::shared_ptr<NCA>> ncas;
111
112 Core::Crypto::KeyManager keys;
110}; 113};
111} // namespace FileSys 114} // namespace FileSys
diff --git a/src/core/file_sys/content_archive.cpp b/src/core/file_sys/content_archive.cpp
index b46fe893c..19b6f8600 100644
--- a/src/core/file_sys/content_archive.cpp
+++ b/src/core/file_sys/content_archive.cpp
@@ -101,8 +101,9 @@ static bool IsValidNCA(const NCAHeader& header) {
101 return header.magic == Common::MakeMagic('N', 'C', 'A', '3'); 101 return header.magic == Common::MakeMagic('N', 'C', 'A', '3');
102} 102}
103 103
104NCA::NCA(VirtualFile file_, VirtualFile bktr_base_romfs_, u64 bktr_base_ivfc_offset) 104NCA::NCA(VirtualFile file_, VirtualFile bktr_base_romfs_, u64 bktr_base_ivfc_offset,
105 : file(std::move(file_)), bktr_base_romfs(std::move(bktr_base_romfs_)) { 105 Core::Crypto::KeyManager keys_)
106 : file(std::move(file_)), bktr_base_romfs(std::move(bktr_base_romfs_)), keys(std::move(keys_)) {
106 if (file == nullptr) { 107 if (file == nullptr) {
107 status = Loader::ResultStatus::ErrorNullFile; 108 status = Loader::ResultStatus::ErrorNullFile;
108 return; 109 return;
diff --git a/src/core/file_sys/content_archive.h b/src/core/file_sys/content_archive.h
index 4bba55607..99294cbb4 100644
--- a/src/core/file_sys/content_archive.h
+++ b/src/core/file_sys/content_archive.h
@@ -79,7 +79,8 @@ inline bool IsDirectoryExeFS(const std::shared_ptr<VfsDirectory>& pfs) {
79class NCA : public ReadOnlyVfsDirectory { 79class NCA : public ReadOnlyVfsDirectory {
80public: 80public:
81 explicit NCA(VirtualFile file, VirtualFile bktr_base_romfs = nullptr, 81 explicit NCA(VirtualFile file, VirtualFile bktr_base_romfs = nullptr,
82 u64 bktr_base_ivfc_offset = 0); 82 u64 bktr_base_ivfc_offset = 0,
83 Core::Crypto::KeyManager keys = Core::Crypto::KeyManager());
83 ~NCA() override; 84 ~NCA() override;
84 85
85 Loader::ResultStatus GetStatus() const; 86 Loader::ResultStatus GetStatus() const;
diff --git a/src/core/file_sys/errors.h b/src/core/file_sys/errors.h
index fea0593c7..e4a4ee4ab 100644
--- a/src/core/file_sys/errors.h
+++ b/src/core/file_sys/errors.h
@@ -8,25 +8,10 @@
8 8
9namespace FileSys { 9namespace FileSys {
10 10
11namespace ErrCodes { 11constexpr ResultCode ERROR_PATH_NOT_FOUND{ErrorModule::FS, 1};
12enum { 12constexpr ResultCode ERROR_ENTITY_NOT_FOUND{ErrorModule::FS, 1002};
13 NotFound = 1, 13constexpr ResultCode ERROR_SD_CARD_NOT_FOUND{ErrorModule::FS, 2001};
14 TitleNotFound = 1002, 14constexpr ResultCode ERROR_INVALID_OFFSET{ErrorModule::FS, 6061};
15 SdCardNotFound = 2001, 15constexpr ResultCode ERROR_INVALID_SIZE{ErrorModule::FS, 6062};
16 RomFSNotFound = 2520,
17};
18}
19
20constexpr ResultCode ERROR_PATH_NOT_FOUND(ErrorModule::FS, ErrCodes::NotFound);
21
22// TODO(bunnei): Replace these with correct errors for Switch OS
23constexpr ResultCode ERROR_INVALID_PATH(-1);
24constexpr ResultCode ERROR_UNSUPPORTED_OPEN_FLAGS(-1);
25constexpr ResultCode ERROR_INVALID_OPEN_FLAGS(-1);
26constexpr ResultCode ERROR_FILE_NOT_FOUND(-1);
27constexpr ResultCode ERROR_UNEXPECTED_FILE_OR_DIRECTORY(-1);
28constexpr ResultCode ERROR_DIRECTORY_ALREADY_EXISTS(-1);
29constexpr ResultCode ERROR_FILE_ALREADY_EXISTS(-1);
30constexpr ResultCode ERROR_DIRECTORY_NOT_EMPTY(-1);
31 16
32} // namespace FileSys 17} // namespace FileSys
diff --git a/src/core/file_sys/registered_cache.cpp b/src/core/file_sys/registered_cache.cpp
index 96302a241..a3f8f2f73 100644
--- a/src/core/file_sys/registered_cache.cpp
+++ b/src/core/file_sys/registered_cache.cpp
@@ -106,9 +106,12 @@ static ContentRecordType GetCRTypeFromNCAType(NCAContentType type) {
106 106
107VirtualFile RegisteredCache::OpenFileOrDirectoryConcat(const VirtualDir& dir, 107VirtualFile RegisteredCache::OpenFileOrDirectoryConcat(const VirtualDir& dir,
108 std::string_view path) const { 108 std::string_view path) const {
109 if (dir->GetFileRelative(path) != nullptr) 109 const auto file = dir->GetFileRelative(path);
110 return dir->GetFileRelative(path); 110 if (file != nullptr)
111 if (dir->GetDirectoryRelative(path) != nullptr) { 111 return file;
112
113 const auto nca_dir = dir->GetDirectoryRelative(path);
114 if (nca_dir != nullptr) {
112 const auto nca_dir = dir->GetDirectoryRelative(path); 115 const auto nca_dir = dir->GetDirectoryRelative(path);
113 VirtualFile file = nullptr; 116 VirtualFile file = nullptr;
114 117
@@ -225,7 +228,7 @@ void RegisteredCache::ProcessFiles(const std::vector<NcaID>& ids) {
225 228
226 if (file == nullptr) 229 if (file == nullptr)
227 continue; 230 continue;
228 const auto nca = std::make_shared<NCA>(parser(file, id)); 231 const auto nca = std::make_shared<NCA>(parser(file, id), nullptr, 0, keys);
229 if (nca->GetStatus() != Loader::ResultStatus::Success || 232 if (nca->GetStatus() != Loader::ResultStatus::Success ||
230 nca->GetType() != NCAContentType::Meta) { 233 nca->GetType() != NCAContentType::Meta) {
231 continue; 234 continue;
@@ -315,7 +318,7 @@ std::unique_ptr<NCA> RegisteredCache::GetEntry(u64 title_id, ContentRecordType t
315 const auto raw = GetEntryRaw(title_id, type); 318 const auto raw = GetEntryRaw(title_id, type);
316 if (raw == nullptr) 319 if (raw == nullptr)
317 return nullptr; 320 return nullptr;
318 return std::make_unique<NCA>(raw); 321 return std::make_unique<NCA>(raw, nullptr, 0, keys);
319} 322}
320 323
321std::unique_ptr<NCA> RegisteredCache::GetEntry(RegisteredCacheEntry entry) const { 324std::unique_ptr<NCA> RegisteredCache::GetEntry(RegisteredCacheEntry entry) const {
diff --git a/src/core/file_sys/registered_cache.h b/src/core/file_sys/registered_cache.h
index 6cfb16017..6b89db8de 100644
--- a/src/core/file_sys/registered_cache.h
+++ b/src/core/file_sys/registered_cache.h
@@ -12,6 +12,7 @@
12#include <vector> 12#include <vector>
13#include <boost/container/flat_map.hpp> 13#include <boost/container/flat_map.hpp>
14#include "common/common_types.h" 14#include "common/common_types.h"
15#include "core/crypto/key_manager.h"
15#include "core/file_sys/vfs.h" 16#include "core/file_sys/vfs.h"
16 17
17namespace FileSys { 18namespace FileSys {
@@ -133,6 +134,8 @@ private:
133 134
134 VirtualDir dir; 135 VirtualDir dir;
135 RegisteredCacheParsingFunction parser; 136 RegisteredCacheParsingFunction parser;
137 Core::Crypto::KeyManager keys;
138
136 // maps tid -> NcaID of meta 139 // maps tid -> NcaID of meta
137 boost::container::flat_map<u64, NcaID> meta_id; 140 boost::container::flat_map<u64, NcaID> meta_id;
138 // maps tid -> meta 141 // maps tid -> meta
diff --git a/src/core/file_sys/submission_package.cpp b/src/core/file_sys/submission_package.cpp
index 2aaba4179..e1a4210db 100644
--- a/src/core/file_sys/submission_package.cpp
+++ b/src/core/file_sys/submission_package.cpp
@@ -252,7 +252,7 @@ void NSP::ReadNCAs(const std::vector<VirtualFile>& files) {
252 continue; 252 continue;
253 } 253 }
254 254
255 auto next_nca = std::make_shared<NCA>(next_file); 255 auto next_nca = std::make_shared<NCA>(next_file, nullptr, 0, keys);
256 if (next_nca->GetType() == NCAContentType::Program) 256 if (next_nca->GetType() == NCAContentType::Program)
257 program_status[cnmt.GetTitleID()] = next_nca->GetStatus(); 257 program_status[cnmt.GetTitleID()] = next_nca->GetStatus();
258 if (next_nca->GetStatus() == Loader::ResultStatus::Success || 258 if (next_nca->GetStatus() == Loader::ResultStatus::Success ||
diff --git a/src/core/file_sys/submission_package.h b/src/core/file_sys/submission_package.h
index 338080b7e..9a28ed5bb 100644
--- a/src/core/file_sys/submission_package.h
+++ b/src/core/file_sys/submission_package.h
@@ -70,6 +70,8 @@ private:
70 std::map<u64, std::map<ContentRecordType, std::shared_ptr<NCA>>> ncas; 70 std::map<u64, std::map<ContentRecordType, std::shared_ptr<NCA>>> ncas;
71 std::vector<VirtualFile> ticket_files; 71 std::vector<VirtualFile> ticket_files;
72 72
73 Core::Crypto::KeyManager keys;
74
73 VirtualFile romfs; 75 VirtualFile romfs;
74 VirtualDir exefs; 76 VirtualDir exefs;
75}; 77};
diff --git a/src/core/hle/kernel/errors.h b/src/core/hle/kernel/errors.h
index ee698c8a7..8b58d701d 100644
--- a/src/core/hle/kernel/errors.h
+++ b/src/core/hle/kernel/errors.h
@@ -8,58 +8,28 @@
8 8
9namespace Kernel { 9namespace Kernel {
10 10
11namespace ErrCodes { 11// Confirmed Switch kernel error codes
12enum {
13 // Confirmed Switch OS error codes
14 MaxConnectionsReached = 7,
15 InvalidSize = 101,
16 InvalidAddress = 102,
17 HandleTableFull = 105,
18 InvalidMemoryState = 106,
19 InvalidMemoryPermissions = 108,
20 InvalidMemoryRange = 110,
21 InvalidThreadPriority = 112,
22 InvalidProcessorId = 113,
23 InvalidHandle = 114,
24 InvalidPointer = 115,
25 InvalidCombination = 116,
26 Timeout = 117,
27 SynchronizationCanceled = 118,
28 TooLarge = 119,
29 InvalidEnumValue = 120,
30 NoSuchEntry = 121,
31 AlreadyRegistered = 122,
32 SessionClosed = 123,
33 InvalidState = 125,
34 ResourceLimitExceeded = 132,
35};
36}
37 12
38// WARNING: The kernel is quite inconsistent in it's usage of errors code. Make sure to always 13constexpr ResultCode ERR_MAX_CONNECTIONS_REACHED{ErrorModule::Kernel, 7};
39// double check that the code matches before re-using the constant. 14constexpr ResultCode ERR_INVALID_SIZE{ErrorModule::Kernel, 101};
40 15constexpr ResultCode ERR_INVALID_ADDRESS{ErrorModule::Kernel, 102};
41constexpr ResultCode ERR_HANDLE_TABLE_FULL(ErrorModule::Kernel, ErrCodes::HandleTableFull); 16constexpr ResultCode ERR_HANDLE_TABLE_FULL{ErrorModule::Kernel, 105};
42constexpr ResultCode ERR_SESSION_CLOSED_BY_REMOTE(ErrorModule::Kernel, ErrCodes::SessionClosed); 17constexpr ResultCode ERR_INVALID_ADDRESS_STATE{ErrorModule::Kernel, 106};
43constexpr ResultCode ERR_PORT_NAME_TOO_LONG(ErrorModule::Kernel, ErrCodes::TooLarge); 18constexpr ResultCode ERR_INVALID_MEMORY_PERMISSIONS{ErrorModule::Kernel, 108};
44constexpr ResultCode ERR_MAX_CONNECTIONS_REACHED(ErrorModule::Kernel, 19constexpr ResultCode ERR_INVALID_MEMORY_RANGE{ErrorModule::Kernel, 110};
45 ErrCodes::MaxConnectionsReached); 20constexpr ResultCode ERR_INVALID_PROCESSOR_ID{ErrorModule::Kernel, 113};
46constexpr ResultCode ERR_INVALID_ENUM_VALUE(ErrorModule::Kernel, ErrCodes::InvalidEnumValue); 21constexpr ResultCode ERR_INVALID_THREAD_PRIORITY{ErrorModule::Kernel, 112};
47constexpr ResultCode ERR_INVALID_COMBINATION_KERNEL(ErrorModule::Kernel, 22constexpr ResultCode ERR_INVALID_HANDLE{ErrorModule::Kernel, 114};
48 ErrCodes::InvalidCombination); 23constexpr ResultCode ERR_INVALID_POINTER{ErrorModule::Kernel, 115};
49constexpr ResultCode ERR_INVALID_ADDRESS(ErrorModule::Kernel, ErrCodes::InvalidAddress); 24constexpr ResultCode ERR_INVALID_COMBINATION{ErrorModule::Kernel, 116};
50constexpr ResultCode ERR_INVALID_ADDRESS_STATE(ErrorModule::Kernel, ErrCodes::InvalidMemoryState); 25constexpr ResultCode RESULT_TIMEOUT{ErrorModule::Kernel, 117};
51constexpr ResultCode ERR_INVALID_MEMORY_PERMISSIONS(ErrorModule::Kernel, 26constexpr ResultCode ERR_SYNCHRONIZATION_CANCELED{ErrorModule::Kernel, 118};
52 ErrCodes::InvalidMemoryPermissions); 27constexpr ResultCode ERR_OUT_OF_RANGE{ErrorModule::Kernel, 119};
53constexpr ResultCode ERR_INVALID_MEMORY_RANGE(ErrorModule::Kernel, ErrCodes::InvalidMemoryRange); 28constexpr ResultCode ERR_INVALID_ENUM_VALUE{ErrorModule::Kernel, 120};
54constexpr ResultCode ERR_INVALID_HANDLE(ErrorModule::Kernel, ErrCodes::InvalidHandle); 29constexpr ResultCode ERR_NOT_FOUND{ErrorModule::Kernel, 121};
55constexpr ResultCode ERR_INVALID_PROCESSOR_ID(ErrorModule::Kernel, ErrCodes::InvalidProcessorId); 30constexpr ResultCode ERR_ALREADY_REGISTERED{ErrorModule::Kernel, 122};
56constexpr ResultCode ERR_INVALID_SIZE(ErrorModule::Kernel, ErrCodes::InvalidSize); 31constexpr ResultCode ERR_SESSION_CLOSED_BY_REMOTE{ErrorModule::Kernel, 123};
57constexpr ResultCode ERR_ALREADY_REGISTERED(ErrorModule::Kernel, ErrCodes::AlreadyRegistered); 32constexpr ResultCode ERR_INVALID_STATE{ErrorModule::Kernel, 125};
58constexpr ResultCode ERR_INVALID_STATE(ErrorModule::Kernel, ErrCodes::InvalidState); 33constexpr ResultCode ERR_RESOURCE_LIMIT_EXCEEDED{ErrorModule::Kernel, 132};
59constexpr ResultCode ERR_INVALID_THREAD_PRIORITY(ErrorModule::Kernel,
60 ErrCodes::InvalidThreadPriority);
61constexpr ResultCode ERR_INVALID_POINTER(ErrorModule::Kernel, ErrCodes::InvalidPointer);
62constexpr ResultCode ERR_NOT_FOUND(ErrorModule::Kernel, ErrCodes::NoSuchEntry);
63constexpr ResultCode RESULT_TIMEOUT(ErrorModule::Kernel, ErrCodes::Timeout);
64 34
65} // namespace Kernel 35} // namespace Kernel
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index b0b6508d9..2e7c9d094 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -123,6 +123,48 @@ static ResultCode SetHeapSize(VAddr* heap_addr, u64 heap_size) {
123 return RESULT_SUCCESS; 123 return RESULT_SUCCESS;
124} 124}
125 125
126static ResultCode SetMemoryPermission(VAddr addr, u64 size, u32 prot) {
127 LOG_TRACE(Kernel_SVC, "called, addr=0x{:X}, size=0x{:X}, prot=0x{:X}", addr, size, prot);
128
129 if (!Common::Is4KBAligned(addr)) {
130 return ERR_INVALID_ADDRESS;
131 }
132
133 if (size == 0 || !Common::Is4KBAligned(size)) {
134 return ERR_INVALID_SIZE;
135 }
136
137 if (!IsValidAddressRange(addr, size)) {
138 return ERR_INVALID_ADDRESS_STATE;
139 }
140
141 const auto permission = static_cast<MemoryPermission>(prot);
142 if (permission != MemoryPermission::None && permission != MemoryPermission::Read &&
143 permission != MemoryPermission::ReadWrite) {
144 return ERR_INVALID_MEMORY_PERMISSIONS;
145 }
146
147 auto* const current_process = Core::CurrentProcess();
148 auto& vm_manager = current_process->VMManager();
149
150 if (!IsInsideAddressSpace(vm_manager, addr, size)) {
151 return ERR_INVALID_ADDRESS_STATE;
152 }
153
154 const VMManager::VMAHandle iter = vm_manager.FindVMA(addr);
155 if (iter == vm_manager.vma_map.end()) {
156 return ERR_INVALID_ADDRESS_STATE;
157 }
158
159 LOG_WARNING(Kernel_SVC, "Uniformity check on protected memory is not implemented.");
160 // TODO: Performs a uniformity check to make sure only protected memory is changed (it doesn't
161 // make sense to allow changing permissions on kernel memory itself, etc).
162
163 const auto converted_permissions = SharedMemory::ConvertPermissions(permission);
164
165 return vm_manager.ReprotectRange(addr, size, converted_permissions);
166}
167
126static ResultCode SetMemoryAttribute(VAddr addr, u64 size, u32 state0, u32 state1) { 168static ResultCode SetMemoryAttribute(VAddr addr, u64 size, u32 state0, u32 state1) {
127 LOG_WARNING(Kernel_SVC, 169 LOG_WARNING(Kernel_SVC,
128 "(STUBBED) called, addr=0x{:X}, size=0x{:X}, state0=0x{:X}, state1=0x{:X}", addr, 170 "(STUBBED) called, addr=0x{:X}, size=0x{:X}, state0=0x{:X}, state1=0x{:X}", addr,
@@ -172,7 +214,7 @@ static ResultCode ConnectToNamedPort(Handle* out_handle, VAddr port_name_address
172 // Read 1 char beyond the max allowed port name to detect names that are too long. 214 // Read 1 char beyond the max allowed port name to detect names that are too long.
173 std::string port_name = Memory::ReadCString(port_name_address, PortNameMaxLength + 1); 215 std::string port_name = Memory::ReadCString(port_name_address, PortNameMaxLength + 1);
174 if (port_name.size() > PortNameMaxLength) { 216 if (port_name.size() > PortNameMaxLength) {
175 return ERR_PORT_NAME_TOO_LONG; 217 return ERR_OUT_OF_RANGE;
176 } 218 }
177 219
178 LOG_TRACE(Kernel_SVC, "called port_name={}", port_name); 220 LOG_TRACE(Kernel_SVC, "called port_name={}", port_name);
@@ -268,8 +310,9 @@ static ResultCode WaitSynchronization(Handle* index, VAddr handles_address, u64
268 310
269 static constexpr u64 MaxHandles = 0x40; 311 static constexpr u64 MaxHandles = 0x40;
270 312
271 if (handle_count > MaxHandles) 313 if (handle_count > MaxHandles) {
272 return ResultCode(ErrorModule::Kernel, ErrCodes::TooLarge); 314 return ERR_OUT_OF_RANGE;
315 }
273 316
274 auto* const thread = GetCurrentThread(); 317 auto* const thread = GetCurrentThread();
275 318
@@ -334,8 +377,7 @@ static ResultCode CancelSynchronization(Handle thread_handle) {
334 } 377 }
335 378
336 ASSERT(thread->GetStatus() == ThreadStatus::WaitSynchAny); 379 ASSERT(thread->GetStatus() == ThreadStatus::WaitSynchAny);
337 thread->SetWaitSynchronizationResult( 380 thread->SetWaitSynchronizationResult(ERR_SYNCHRONIZATION_CANCELED);
338 ResultCode(ErrorModule::Kernel, ErrCodes::SynchronizationCanceled));
339 thread->ResumeFromWait(); 381 thread->ResumeFromWait();
340 return RESULT_SUCCESS; 382 return RESULT_SUCCESS;
341} 383}
@@ -564,7 +606,7 @@ static ResultCode GetInfo(u64* result, u64 info_id, u64 handle, u64 info_sub_id)
564 } 606 }
565 607
566 if (info_sub_id >= Process::RANDOM_ENTROPY_SIZE) { 608 if (info_sub_id >= Process::RANDOM_ENTROPY_SIZE) {
567 return ERR_INVALID_COMBINATION_KERNEL; 609 return ERR_INVALID_COMBINATION;
568 } 610 }
569 611
570 *result = current_process->GetRandomEntropy(info_sub_id); 612 *result = current_process->GetRandomEntropy(info_sub_id);
@@ -601,7 +643,7 @@ static ResultCode GetInfo(u64* result, u64 info_id, u64 handle, u64 info_sub_id)
601 case GetInfoType::ThreadTickCount: { 643 case GetInfoType::ThreadTickCount: {
602 constexpr u64 num_cpus = 4; 644 constexpr u64 num_cpus = 4;
603 if (info_sub_id != 0xFFFFFFFFFFFFFFFF && info_sub_id >= num_cpus) { 645 if (info_sub_id != 0xFFFFFFFFFFFFFFFF && info_sub_id >= num_cpus) {
604 return ERR_INVALID_COMBINATION_KERNEL; 646 return ERR_INVALID_COMBINATION;
605 } 647 }
606 648
607 const auto thread = 649 const auto thread =
@@ -1194,7 +1236,7 @@ static ResultCode SetThreadCoreMask(Handle thread_handle, u32 core, u64 mask) {
1194 } 1236 }
1195 1237
1196 if (mask == 0) { 1238 if (mask == 0) {
1197 return ResultCode(ErrorModule::Kernel, ErrCodes::InvalidCombination); 1239 return ERR_INVALID_COMBINATION;
1198 } 1240 }
1199 1241
1200 /// This value is used to only change the affinity mask without changing the current ideal core. 1242 /// This value is used to only change the affinity mask without changing the current ideal core.
@@ -1203,12 +1245,12 @@ static ResultCode SetThreadCoreMask(Handle thread_handle, u32 core, u64 mask) {
1203 if (core == OnlyChangeMask) { 1245 if (core == OnlyChangeMask) {
1204 core = thread->GetIdealCore(); 1246 core = thread->GetIdealCore();
1205 } else if (core >= Core::NUM_CPU_CORES && core != static_cast<u32>(-1)) { 1247 } else if (core >= Core::NUM_CPU_CORES && core != static_cast<u32>(-1)) {
1206 return ResultCode(ErrorModule::Kernel, ErrCodes::InvalidProcessorId); 1248 return ERR_INVALID_PROCESSOR_ID;
1207 } 1249 }
1208 1250
1209 // Error out if the input core isn't enabled in the input mask. 1251 // Error out if the input core isn't enabled in the input mask.
1210 if (core < Core::NUM_CPU_CORES && (mask & (1ull << core)) == 0) { 1252 if (core < Core::NUM_CPU_CORES && (mask & (1ull << core)) == 0) {
1211 return ResultCode(ErrorModule::Kernel, ErrCodes::InvalidCombination); 1253 return ERR_INVALID_COMBINATION;
1212 } 1254 }
1213 1255
1214 thread->ChangeCore(core, mask); 1256 thread->ChangeCore(core, mask);
@@ -1297,7 +1339,7 @@ struct FunctionDef {
1297static const FunctionDef SVC_Table[] = { 1339static const FunctionDef SVC_Table[] = {
1298 {0x00, nullptr, "Unknown"}, 1340 {0x00, nullptr, "Unknown"},
1299 {0x01, SvcWrap<SetHeapSize>, "SetHeapSize"}, 1341 {0x01, SvcWrap<SetHeapSize>, "SetHeapSize"},
1300 {0x02, nullptr, "SetMemoryPermission"}, 1342 {0x02, SvcWrap<SetMemoryPermission>, "SetMemoryPermission"},
1301 {0x03, SvcWrap<SetMemoryAttribute>, "SetMemoryAttribute"}, 1343 {0x03, SvcWrap<SetMemoryAttribute>, "SetMemoryAttribute"},
1302 {0x04, SvcWrap<MapMemory>, "MapMemory"}, 1344 {0x04, SvcWrap<MapMemory>, "MapMemory"},
1303 {0x05, SvcWrap<UnmapMemory>, "UnmapMemory"}, 1345 {0x05, SvcWrap<UnmapMemory>, "UnmapMemory"},
diff --git a/src/core/hle/kernel/svc_wrap.h b/src/core/hle/kernel/svc_wrap.h
index b09753c80..233a99fb0 100644
--- a/src/core/hle/kernel/svc_wrap.h
+++ b/src/core/hle/kernel/svc_wrap.h
@@ -121,6 +121,11 @@ void SvcWrap() {
121 FuncReturn(func(Param(0), Param(1), Param(2)).raw); 121 FuncReturn(func(Param(0), Param(1), Param(2)).raw);
122} 122}
123 123
124template <ResultCode func(u64, u64, u32)>
125void SvcWrap() {
126 FuncReturn(func(Param(0), Param(1), static_cast<u32>(Param(2))).raw);
127}
128
124template <ResultCode func(u32, u64, u64, u32)> 129template <ResultCode func(u32, u64, u64, u32)>
125void SvcWrap() { 130void SvcWrap() {
126 FuncReturn( 131 FuncReturn(
diff --git a/src/core/hle/result.h b/src/core/hle/result.h
index c6b18cfba..bfb77cc31 100644
--- a/src/core/hle/result.h
+++ b/src/core/hle/result.h
@@ -19,8 +19,6 @@
19enum class ErrorDescription : u32 { 19enum class ErrorDescription : u32 {
20 Success = 0, 20 Success = 0,
21 RemoteProcessDead = 301, 21 RemoteProcessDead = 301,
22 InvalidOffset = 6061,
23 InvalidLength = 6062,
24}; 22};
25 23
26/** 24/**
diff --git a/src/core/hle/service/audio/hwopus.cpp b/src/core/hle/service/audio/hwopus.cpp
index 783c39503..763e619a4 100644
--- a/src/core/hle/service/audio/hwopus.cpp
+++ b/src/core/hle/service/audio/hwopus.cpp
@@ -77,8 +77,8 @@ private:
77 IPC::ResponseBuilder rb{ctx, 6}; 77 IPC::ResponseBuilder rb{ctx, 6};
78 rb.Push(RESULT_SUCCESS); 78 rb.Push(RESULT_SUCCESS);
79 rb.Push<u32>(consumed); 79 rb.Push<u32>(consumed);
80 rb.Push<u64>(performance);
81 rb.Push<u32>(sample_count); 80 rb.Push<u32>(sample_count);
81 rb.Push<u64>(performance);
82 ctx.WriteBuffer(samples.data(), samples.size() * sizeof(s16)); 82 ctx.WriteBuffer(samples.data(), samples.size() * sizeof(s16));
83 } 83 }
84 84
diff --git a/src/core/hle/service/filesystem/filesystem.cpp b/src/core/hle/service/filesystem/filesystem.cpp
index a92cf7815..5d6294016 100644
--- a/src/core/hle/service/filesystem/filesystem.cpp
+++ b/src/core/hle/service/filesystem/filesystem.cpp
@@ -303,7 +303,7 @@ ResultVal<FileSys::VirtualDir> OpenSaveData(FileSys::SaveDataSpaceId space,
303 static_cast<u8>(space), save_struct.DebugInfo()); 303 static_cast<u8>(space), save_struct.DebugInfo());
304 304
305 if (save_data_factory == nullptr) { 305 if (save_data_factory == nullptr) {
306 return ResultCode(ErrorModule::FS, FileSys::ErrCodes::TitleNotFound); 306 return FileSys::ERROR_ENTITY_NOT_FOUND;
307 } 307 }
308 308
309 return save_data_factory->Open(space, save_struct); 309 return save_data_factory->Open(space, save_struct);
@@ -313,7 +313,7 @@ ResultVal<FileSys::VirtualDir> OpenSaveDataSpace(FileSys::SaveDataSpaceId space)
313 LOG_TRACE(Service_FS, "Opening Save Data Space for space_id={:01X}", static_cast<u8>(space)); 313 LOG_TRACE(Service_FS, "Opening Save Data Space for space_id={:01X}", static_cast<u8>(space));
314 314
315 if (save_data_factory == nullptr) { 315 if (save_data_factory == nullptr) {
316 return ResultCode(ErrorModule::FS, FileSys::ErrCodes::TitleNotFound); 316 return FileSys::ERROR_ENTITY_NOT_FOUND;
317 } 317 }
318 318
319 return MakeResult(save_data_factory->GetSaveDataSpaceDirectory(space)); 319 return MakeResult(save_data_factory->GetSaveDataSpaceDirectory(space));
@@ -323,15 +323,22 @@ ResultVal<FileSys::VirtualDir> OpenSDMC() {
323 LOG_TRACE(Service_FS, "Opening SDMC"); 323 LOG_TRACE(Service_FS, "Opening SDMC");
324 324
325 if (sdmc_factory == nullptr) { 325 if (sdmc_factory == nullptr) {
326 return ResultCode(ErrorModule::FS, FileSys::ErrCodes::SdCardNotFound); 326 return FileSys::ERROR_SD_CARD_NOT_FOUND;
327 } 327 }
328 328
329 return sdmc_factory->Open(); 329 return sdmc_factory->Open();
330} 330}
331 331
332std::unique_ptr<FileSys::RegisteredCacheUnion> GetUnionContents() { 332std::shared_ptr<FileSys::RegisteredCacheUnion> registered_cache_union;
333 return std::make_unique<FileSys::RegisteredCacheUnion>(std::vector<FileSys::RegisteredCache*>{ 333
334 GetSystemNANDContents(), GetUserNANDContents(), GetSDMCContents()}); 334std::shared_ptr<FileSys::RegisteredCacheUnion> GetUnionContents() {
335 if (registered_cache_union == nullptr) {
336 registered_cache_union =
337 std::make_shared<FileSys::RegisteredCacheUnion>(std::vector<FileSys::RegisteredCache*>{
338 GetSystemNANDContents(), GetUserNANDContents(), GetSDMCContents()});
339 }
340
341 return registered_cache_union;
335} 342}
336 343
337FileSys::RegisteredCache* GetSystemNANDContents() { 344FileSys::RegisteredCache* GetSystemNANDContents() {
diff --git a/src/core/hle/service/filesystem/filesystem.h b/src/core/hle/service/filesystem/filesystem.h
index e38f02869..ff9182e84 100644
--- a/src/core/hle/service/filesystem/filesystem.h
+++ b/src/core/hle/service/filesystem/filesystem.h
@@ -48,7 +48,7 @@ ResultVal<FileSys::VirtualDir> OpenSaveData(FileSys::SaveDataSpaceId space,
48ResultVal<FileSys::VirtualDir> OpenSaveDataSpace(FileSys::SaveDataSpaceId space); 48ResultVal<FileSys::VirtualDir> OpenSaveDataSpace(FileSys::SaveDataSpaceId space);
49ResultVal<FileSys::VirtualDir> OpenSDMC(); 49ResultVal<FileSys::VirtualDir> OpenSDMC();
50 50
51std::unique_ptr<FileSys::RegisteredCacheUnion> GetUnionContents(); 51std::shared_ptr<FileSys::RegisteredCacheUnion> GetUnionContents();
52 52
53FileSys::RegisteredCache* GetSystemNANDContents(); 53FileSys::RegisteredCache* GetSystemNANDContents();
54FileSys::RegisteredCache* GetUserNANDContents(); 54FileSys::RegisteredCache* GetUserNANDContents();
diff --git a/src/core/hle/service/filesystem/fsp_srv.cpp b/src/core/hle/service/filesystem/fsp_srv.cpp
index b9a1d5105..038dc80b1 100644
--- a/src/core/hle/service/filesystem/fsp_srv.cpp
+++ b/src/core/hle/service/filesystem/fsp_srv.cpp
@@ -63,12 +63,12 @@ private:
63 // Error checking 63 // Error checking
64 if (length < 0) { 64 if (length < 0) {
65 IPC::ResponseBuilder rb{ctx, 2}; 65 IPC::ResponseBuilder rb{ctx, 2};
66 rb.Push(ResultCode(ErrorModule::FS, ErrorDescription::InvalidLength)); 66 rb.Push(FileSys::ERROR_INVALID_SIZE);
67 return; 67 return;
68 } 68 }
69 if (offset < 0) { 69 if (offset < 0) {
70 IPC::ResponseBuilder rb{ctx, 2}; 70 IPC::ResponseBuilder rb{ctx, 2};
71 rb.Push(ResultCode(ErrorModule::FS, ErrorDescription::InvalidOffset)); 71 rb.Push(FileSys::ERROR_INVALID_OFFSET);
72 return; 72 return;
73 } 73 }
74 74
@@ -108,12 +108,12 @@ private:
108 // Error checking 108 // Error checking
109 if (length < 0) { 109 if (length < 0) {
110 IPC::ResponseBuilder rb{ctx, 2}; 110 IPC::ResponseBuilder rb{ctx, 2};
111 rb.Push(ResultCode(ErrorModule::FS, ErrorDescription::InvalidLength)); 111 rb.Push(FileSys::ERROR_INVALID_SIZE);
112 return; 112 return;
113 } 113 }
114 if (offset < 0) { 114 if (offset < 0) {
115 IPC::ResponseBuilder rb{ctx, 2}; 115 IPC::ResponseBuilder rb{ctx, 2};
116 rb.Push(ResultCode(ErrorModule::FS, ErrorDescription::InvalidOffset)); 116 rb.Push(FileSys::ERROR_INVALID_OFFSET);
117 return; 117 return;
118 } 118 }
119 119
@@ -139,12 +139,12 @@ private:
139 // Error checking 139 // Error checking
140 if (length < 0) { 140 if (length < 0) {
141 IPC::ResponseBuilder rb{ctx, 2}; 141 IPC::ResponseBuilder rb{ctx, 2};
142 rb.Push(ResultCode(ErrorModule::FS, ErrorDescription::InvalidLength)); 142 rb.Push(FileSys::ERROR_INVALID_SIZE);
143 return; 143 return;
144 } 144 }
145 if (offset < 0) { 145 if (offset < 0) {
146 IPC::ResponseBuilder rb{ctx, 2}; 146 IPC::ResponseBuilder rb{ctx, 2};
147 rb.Push(ResultCode(ErrorModule::FS, ErrorDescription::InvalidOffset)); 147 rb.Push(FileSys::ERROR_INVALID_OFFSET);
148 return; 148 return;
149 } 149 }
150 150
@@ -744,7 +744,7 @@ void FSP_SRV::MountSaveData(Kernel::HLERequestContext& ctx) {
744 744
745 if (dir.Failed()) { 745 if (dir.Failed()) {
746 IPC::ResponseBuilder rb{ctx, 2, 0, 0}; 746 IPC::ResponseBuilder rb{ctx, 2, 0, 0};
747 rb.Push(ResultCode(ErrorModule::FS, FileSys::ErrCodes::TitleNotFound)); 747 rb.Push(FileSys::ERROR_ENTITY_NOT_FOUND);
748 return; 748 return;
749 } 749 }
750 750
@@ -836,7 +836,7 @@ void FSP_SRV::OpenRomStorage(Kernel::HLERequestContext& ctx) {
836 static_cast<u8>(storage_id), title_id); 836 static_cast<u8>(storage_id), title_id);
837 837
838 IPC::ResponseBuilder rb{ctx, 2}; 838 IPC::ResponseBuilder rb{ctx, 2};
839 rb.Push(ResultCode(ErrorModule::FS, FileSys::ErrCodes::TitleNotFound)); 839 rb.Push(FileSys::ERROR_ENTITY_NOT_FOUND);
840} 840}
841 841
842} // namespace Service::FileSystem 842} // namespace Service::FileSystem
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp
index a45fd4954..39631b14f 100644
--- a/src/core/hle/service/hid/hid.cpp
+++ b/src/core/hle/service/hid/hid.cpp
@@ -286,10 +286,10 @@ public:
286 {519, nullptr, "GetPalmaOperationResult"}, 286 {519, nullptr, "GetPalmaOperationResult"},
287 {520, nullptr, "ReadPalmaPlayLog"}, 287 {520, nullptr, "ReadPalmaPlayLog"},
288 {521, nullptr, "ResetPalmaPlayLog"}, 288 {521, nullptr, "ResetPalmaPlayLog"},
289 {522, nullptr, "SetIsPalmaAllConnectable"}, 289 {522, &Hid::SetIsPalmaAllConnectable, "SetIsPalmaAllConnectable"},
290 {523, nullptr, "SetIsPalmaPairedConnectable"}, 290 {523, nullptr, "SetIsPalmaPairedConnectable"},
291 {524, nullptr, "PairPalma"}, 291 {524, nullptr, "PairPalma"},
292 {525, nullptr, "SetPalmaBoostMode"}, 292 {525, &Hid::SetPalmaBoostMode, "SetPalmaBoostMode"},
293 {1000, nullptr, "SetNpadCommunicationMode"}, 293 {1000, nullptr, "SetNpadCommunicationMode"},
294 {1001, nullptr, "GetNpadCommunicationMode"}, 294 {1001, nullptr, "GetNpadCommunicationMode"},
295 }; 295 };
@@ -596,6 +596,18 @@ private:
596 rb.Push(RESULT_SUCCESS); 596 rb.Push(RESULT_SUCCESS);
597 LOG_WARNING(Service_HID, "(STUBBED) called"); 597 LOG_WARNING(Service_HID, "(STUBBED) called");
598 } 598 }
599
600 void SetIsPalmaAllConnectable(Kernel::HLERequestContext& ctx) {
601 IPC::ResponseBuilder rb{ctx, 2};
602 rb.Push(RESULT_SUCCESS);
603 LOG_WARNING(Service_HID, "(STUBBED) called");
604 }
605
606 void SetPalmaBoostMode(Kernel::HLERequestContext& ctx) {
607 IPC::ResponseBuilder rb{ctx, 2};
608 rb.Push(RESULT_SUCCESS);
609 LOG_WARNING(Service_HID, "(STUBBED) called");
610 }
599}; 611};
600 612
601class HidDbg final : public ServiceFramework<HidDbg> { 613class HidDbg final : public ServiceFramework<HidDbg> {
diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
index 26711e6f7..b44ecfa1c 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
@@ -550,8 +550,8 @@ void SwizzleFunc(const GLConversionArray& functions, const SurfaceParams& params
550 if (params.is_layered) { 550 if (params.is_layered) {
551 u64 offset = params.GetMipmapLevelOffset(mip_level); 551 u64 offset = params.GetMipmapLevelOffset(mip_level);
552 u64 offset_gl = 0; 552 u64 offset_gl = 0;
553 u64 layer_size = params.LayerMemorySize(); 553 const u64 layer_size = params.LayerMemorySize();
554 u64 gl_size = params.LayerSizeGL(mip_level); 554 const u64 gl_size = params.LayerSizeGL(mip_level);
555 for (u32 i = 0; i < params.depth; i++) { 555 for (u32 i = 0; i < params.depth; i++) {
556 functions[static_cast<std::size_t>(params.pixel_format)]( 556 functions[static_cast<std::size_t>(params.pixel_format)](
557 params.MipWidth(mip_level), params.MipBlockHeight(mip_level), 557 params.MipWidth(mip_level), params.MipBlockHeight(mip_level),
@@ -561,7 +561,7 @@ void SwizzleFunc(const GLConversionArray& functions, const SurfaceParams& params
561 offset_gl += gl_size; 561 offset_gl += gl_size;
562 } 562 }
563 } else { 563 } else {
564 u64 offset = params.GetMipmapLevelOffset(mip_level); 564 const u64 offset = params.GetMipmapLevelOffset(mip_level);
565 functions[static_cast<std::size_t>(params.pixel_format)]( 565 functions[static_cast<std::size_t>(params.pixel_format)](
566 params.MipWidth(mip_level), params.MipBlockHeight(mip_level), 566 params.MipWidth(mip_level), params.MipBlockHeight(mip_level),
567 params.MipHeight(mip_level), params.MipBlockDepth(mip_level), depth, gl_buffer.data(), 567 params.MipHeight(mip_level), params.MipBlockDepth(mip_level), depth, gl_buffer.data(),
diff --git a/src/video_core/renderer_opengl/gl_state.cpp b/src/video_core/renderer_opengl/gl_state.cpp
index 2635f2b0c..98622a058 100644
--- a/src/video_core/renderer_opengl/gl_state.cpp
+++ b/src/video_core/renderer_opengl/gl_state.cpp
@@ -266,7 +266,8 @@ void OpenGLState::ApplyViewport() const {
266 const auto& updated = viewports[0]; 266 const auto& updated = viewports[0];
267 if (updated.x != current.x || updated.y != current.y || updated.width != current.width || 267 if (updated.x != current.x || updated.y != current.y || updated.width != current.width ||
268 updated.height != current.height) { 268 updated.height != current.height) {
269 glViewport(updated.x, updated.y, updated.width, updated.height); 269 glViewport(static_cast<GLint>(updated.x), static_cast<GLint>(updated.y),
270 static_cast<GLsizei>(updated.width), static_cast<GLsizei>(updated.height));
270 } 271 }
271 if (updated.depth_range_near != current.depth_range_near || 272 if (updated.depth_range_near != current.depth_range_near ||
272 updated.depth_range_far != current.depth_range_far) { 273 updated.depth_range_far != current.depth_range_far) {
@@ -313,7 +314,7 @@ void OpenGLState::ApplyGlobalBlending() const {
313 } 314 }
314} 315}
315 316
316void OpenGLState::ApplyTargetBlending(int target, bool force) const { 317void OpenGLState::ApplyTargetBlending(std::size_t target, bool force) const {
317 const Blend& updated = blend[target]; 318 const Blend& updated = blend[target];
318 const Blend& current = cur_state.blend[target]; 319 const Blend& current = cur_state.blend[target];
319 const bool blend_changed = updated.enabled != current.enabled || force; 320 const bool blend_changed = updated.enabled != current.enabled || force;
diff --git a/src/video_core/renderer_opengl/gl_state.h b/src/video_core/renderer_opengl/gl_state.h
index eacca0b9c..e5d1baae6 100644
--- a/src/video_core/renderer_opengl/gl_state.h
+++ b/src/video_core/renderer_opengl/gl_state.h
@@ -208,7 +208,7 @@ private:
208 void ApplyPrimitiveRestart() const; 208 void ApplyPrimitiveRestart() const;
209 void ApplyStencilTest() const; 209 void ApplyStencilTest() const;
210 void ApplyViewport() const; 210 void ApplyViewport() const;
211 void ApplyTargetBlending(int target, bool force) const; 211 void ApplyTargetBlending(std::size_t target, bool force) const;
212 void ApplyGlobalBlending() const; 212 void ApplyGlobalBlending() const;
213 void ApplyBlending() const; 213 void ApplyBlending() const;
214 void ApplyLogicOp() const; 214 void ApplyLogicOp() const;
diff --git a/src/video_core/textures/decoders.cpp b/src/video_core/textures/decoders.cpp
index a9d134d14..19f30b1b5 100644
--- a/src/video_core/textures/decoders.cpp
+++ b/src/video_core/textures/decoders.cpp
@@ -45,7 +45,7 @@ constexpr auto fast_swizzle_table = SwizzleTable<8, 4, 16>();
45 * Instead of going gob by gob, we map the coordinates inside a block and manage from 45 * Instead of going gob by gob, we map the coordinates inside a block and manage from
46 * those. Block_Width is assumed to be 1. 46 * those. Block_Width is assumed to be 1.
47 */ 47 */
48void PreciseProcessBlock(u8* swizzled_data, u8* unswizzled_data, const bool unswizzle, 48void PreciseProcessBlock(u8* const swizzled_data, u8* const unswizzled_data, const bool unswizzle,
49 const u32 x_start, const u32 y_start, const u32 z_start, const u32 x_end, 49 const u32 x_start, const u32 y_start, const u32 z_start, const u32 x_end,
50 const u32 y_end, const u32 z_end, const u32 tile_offset, 50 const u32 y_end, const u32 z_end, const u32 tile_offset,
51 const u32 xy_block_size, const u32 layer_z, const u32 stride_x, 51 const u32 xy_block_size, const u32 layer_z, const u32 stride_x,
@@ -81,7 +81,7 @@ void PreciseProcessBlock(u8* swizzled_data, u8* unswizzled_data, const bool unsw
81 * Instead of going gob by gob, we map the coordinates inside a block and manage from 81 * Instead of going gob by gob, we map the coordinates inside a block and manage from
82 * those. Block_Width is assumed to be 1. 82 * those. Block_Width is assumed to be 1.
83 */ 83 */
84void FastProcessBlock(u8* swizzled_data, u8* unswizzled_data, const bool unswizzle, 84void FastProcessBlock(u8* const swizzled_data, u8* const unswizzled_data, const bool unswizzle,
85 const u32 x_start, const u32 y_start, const u32 z_start, const u32 x_end, 85 const u32 x_start, const u32 y_start, const u32 z_start, const u32 x_end,
86 const u32 y_end, const u32 z_end, const u32 tile_offset, 86 const u32 y_end, const u32 z_end, const u32 tile_offset,
87 const u32 xy_block_size, const u32 layer_z, const u32 stride_x, 87 const u32 xy_block_size, const u32 layer_z, const u32 stride_x,
@@ -90,10 +90,10 @@ void FastProcessBlock(u8* swizzled_data, u8* unswizzled_data, const bool unswizz
90 u32 z_address = tile_offset; 90 u32 z_address = tile_offset;
91 const u32 x_startb = x_start * bytes_per_pixel; 91 const u32 x_startb = x_start * bytes_per_pixel;
92 const u32 x_endb = x_end * bytes_per_pixel; 92 const u32 x_endb = x_end * bytes_per_pixel;
93 const u32 copy_size = 16; 93 constexpr u32 copy_size = 16;
94 const u32 gob_size_x = 64; 94 constexpr u32 gob_size_x = 64;
95 const u32 gob_size_y = 8; 95 constexpr u32 gob_size_y = 8;
96 const u32 gob_size_z = 1; 96 constexpr u32 gob_size_z = 1;
97 const u32 gob_size = gob_size_x * gob_size_y * gob_size_z; 97 const u32 gob_size = gob_size_x * gob_size_y * gob_size_z;
98 for (u32 z = z_start; z < z_end; z++) { 98 for (u32 z = z_start; z < z_end; z++) {
99 u32 y_address = z_address; 99 u32 y_address = z_address;
@@ -126,23 +126,23 @@ void FastProcessBlock(u8* swizzled_data, u8* unswizzled_data, const bool unswizz
126 * https://envytools.readthedocs.io/en/latest/hw/memory/g80-surface.html#blocklinear-surfaces 126 * https://envytools.readthedocs.io/en/latest/hw/memory/g80-surface.html#blocklinear-surfaces
127 */ 127 */
128template <bool fast> 128template <bool fast>
129void SwizzledData(u8* swizzled_data, u8* unswizzled_data, const bool unswizzle, const u32 width, 129void SwizzledData(u8* const swizzled_data, u8* const unswizzled_data, const bool unswizzle,
130 const u32 height, const u32 depth, const u32 bytes_per_pixel, 130 const u32 width, const u32 height, const u32 depth, const u32 bytes_per_pixel,
131 const u32 out_bytes_per_pixel, const u32 block_height, const u32 block_depth) { 131 const u32 out_bytes_per_pixel, const u32 block_height, const u32 block_depth) {
132 auto div_ceil = [](const u32 x, const u32 y) { return ((x + y - 1) / y); }; 132 auto div_ceil = [](const u32 x, const u32 y) { return ((x + y - 1) / y); };
133 const u32 stride_x = width * out_bytes_per_pixel; 133 const u32 stride_x = width * out_bytes_per_pixel;
134 const u32 layer_z = height * stride_x; 134 const u32 layer_z = height * stride_x;
135 const u32 gob_x_bytes = 64; 135 constexpr u32 gob_x_bytes = 64;
136 const u32 gob_elements_x = gob_x_bytes / bytes_per_pixel; 136 const u32 gob_elements_x = gob_x_bytes / bytes_per_pixel;
137 const u32 gob_elements_y = 8; 137 constexpr u32 gob_elements_y = 8;
138 const u32 gob_elements_z = 1; 138 constexpr u32 gob_elements_z = 1;
139 const u32 block_x_elements = gob_elements_x; 139 const u32 block_x_elements = gob_elements_x;
140 const u32 block_y_elements = gob_elements_y * block_height; 140 const u32 block_y_elements = gob_elements_y * block_height;
141 const u32 block_z_elements = gob_elements_z * block_depth; 141 const u32 block_z_elements = gob_elements_z * block_depth;
142 const u32 blocks_on_x = div_ceil(width, block_x_elements); 142 const u32 blocks_on_x = div_ceil(width, block_x_elements);
143 const u32 blocks_on_y = div_ceil(height, block_y_elements); 143 const u32 blocks_on_y = div_ceil(height, block_y_elements);
144 const u32 blocks_on_z = div_ceil(depth, block_z_elements); 144 const u32 blocks_on_z = div_ceil(depth, block_z_elements);
145 const u32 gob_size = gob_x_bytes * gob_elements_y * gob_elements_z; 145 constexpr u32 gob_size = gob_x_bytes * gob_elements_y * gob_elements_z;
146 const u32 xy_block_size = gob_size * block_height; 146 const u32 xy_block_size = gob_size * block_height;
147 const u32 block_size = xy_block_size * block_depth; 147 const u32 block_size = xy_block_size * block_depth;
148 u32 tile_offset = 0; 148 u32 tile_offset = 0;
@@ -171,7 +171,7 @@ void SwizzledData(u8* swizzled_data, u8* unswizzled_data, const bool unswizzle,
171} 171}
172 172
173void CopySwizzledData(u32 width, u32 height, u32 depth, u32 bytes_per_pixel, 173void CopySwizzledData(u32 width, u32 height, u32 depth, u32 bytes_per_pixel,
174 u32 out_bytes_per_pixel, u8* swizzled_data, u8* unswizzled_data, 174 u32 out_bytes_per_pixel, u8* const swizzled_data, u8* const unswizzled_data,
175 bool unswizzle, u32 block_height, u32 block_depth) { 175 bool unswizzle, u32 block_height, u32 block_depth) {
176 if (bytes_per_pixel % 3 != 0 && (width * bytes_per_pixel) % 16 == 0) { 176 if (bytes_per_pixel % 3 != 0 && (width * bytes_per_pixel) % 16 == 0) {
177 SwizzledData<true>(swizzled_data, unswizzled_data, unswizzle, width, height, depth, 177 SwizzledData<true>(swizzled_data, unswizzled_data, unswizzle, width, height, depth,
@@ -325,9 +325,9 @@ std::vector<u8> DecodeTexture(const std::vector<u8>& texture_data, TextureFormat
325std::size_t CalculateSize(bool tiled, u32 bytes_per_pixel, u32 width, u32 height, u32 depth, 325std::size_t CalculateSize(bool tiled, u32 bytes_per_pixel, u32 width, u32 height, u32 depth,
326 u32 block_height, u32 block_depth) { 326 u32 block_height, u32 block_depth) {
327 if (tiled) { 327 if (tiled) {
328 const u32 gobs_in_x = 64; 328 constexpr u32 gobs_in_x = 64;
329 const u32 gobs_in_y = 8; 329 constexpr u32 gobs_in_y = 8;
330 const u32 gobs_in_z = 1; 330 constexpr u32 gobs_in_z = 1;
331 const u32 aligned_width = Common::AlignUp(width * bytes_per_pixel, gobs_in_x); 331 const u32 aligned_width = Common::AlignUp(width * bytes_per_pixel, gobs_in_x);
332 const u32 aligned_height = Common::AlignUp(height, gobs_in_y * block_height); 332 const u32 aligned_height = Common::AlignUp(height, gobs_in_y * block_height);
333 const u32 aligned_depth = Common::AlignUp(depth, gobs_in_z * block_depth); 333 const u32 aligned_depth = Common::AlignUp(depth, gobs_in_z * block_depth);
diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp
index 60606bb33..be69fb831 100644
--- a/src/yuzu/configuration/config.cpp
+++ b/src/yuzu/configuration/config.cpp
@@ -171,6 +171,7 @@ void Config::ReadValues() {
171 171
172 qt_config->beginGroup("UIGameList"); 172 qt_config->beginGroup("UIGameList");
173 UISettings::values.show_unknown = qt_config->value("show_unknown", true).toBool(); 173 UISettings::values.show_unknown = qt_config->value("show_unknown", true).toBool();
174 UISettings::values.show_add_ons = qt_config->value("show_add_ons", true).toBool();
174 UISettings::values.icon_size = qt_config->value("icon_size", 64).toUInt(); 175 UISettings::values.icon_size = qt_config->value("icon_size", 64).toUInt();
175 UISettings::values.row_1_text_id = qt_config->value("row_1_text_id", 3).toUInt(); 176 UISettings::values.row_1_text_id = qt_config->value("row_1_text_id", 3).toUInt();
176 UISettings::values.row_2_text_id = qt_config->value("row_2_text_id", 2).toUInt(); 177 UISettings::values.row_2_text_id = qt_config->value("row_2_text_id", 2).toUInt();
@@ -312,6 +313,7 @@ void Config::SaveValues() {
312 313
313 qt_config->beginGroup("UIGameList"); 314 qt_config->beginGroup("UIGameList");
314 qt_config->setValue("show_unknown", UISettings::values.show_unknown); 315 qt_config->setValue("show_unknown", UISettings::values.show_unknown);
316 qt_config->setValue("show_add_ons", UISettings::values.show_add_ons);
315 qt_config->setValue("icon_size", UISettings::values.icon_size); 317 qt_config->setValue("icon_size", UISettings::values.icon_size);
316 qt_config->setValue("row_1_text_id", UISettings::values.row_1_text_id); 318 qt_config->setValue("row_1_text_id", UISettings::values.row_1_text_id);
317 qt_config->setValue("row_2_text_id", UISettings::values.row_2_text_id); 319 qt_config->setValue("row_2_text_id", UISettings::values.row_2_text_id);
diff --git a/src/yuzu/configuration/configure_gamelist.cpp b/src/yuzu/configuration/configure_gamelist.cpp
index 8743ce982..639d5df0f 100644
--- a/src/yuzu/configuration/configure_gamelist.cpp
+++ b/src/yuzu/configuration/configure_gamelist.cpp
@@ -42,6 +42,7 @@ ConfigureGameList::~ConfigureGameList() = default;
42 42
43void ConfigureGameList::applyConfiguration() { 43void ConfigureGameList::applyConfiguration() {
44 UISettings::values.show_unknown = ui->show_unknown->isChecked(); 44 UISettings::values.show_unknown = ui->show_unknown->isChecked();
45 UISettings::values.show_add_ons = ui->show_add_ons->isChecked();
45 UISettings::values.icon_size = ui->icon_size_combobox->currentData().toUInt(); 46 UISettings::values.icon_size = ui->icon_size_combobox->currentData().toUInt();
46 UISettings::values.row_1_text_id = ui->row_1_text_combobox->currentData().toUInt(); 47 UISettings::values.row_1_text_id = ui->row_1_text_combobox->currentData().toUInt();
47 UISettings::values.row_2_text_id = ui->row_2_text_combobox->currentData().toUInt(); 48 UISettings::values.row_2_text_id = ui->row_2_text_combobox->currentData().toUInt();
@@ -50,6 +51,7 @@ void ConfigureGameList::applyConfiguration() {
50 51
51void ConfigureGameList::setConfiguration() { 52void ConfigureGameList::setConfiguration() {
52 ui->show_unknown->setChecked(UISettings::values.show_unknown); 53 ui->show_unknown->setChecked(UISettings::values.show_unknown);
54 ui->show_add_ons->setChecked(UISettings::values.show_add_ons);
53 ui->icon_size_combobox->setCurrentIndex( 55 ui->icon_size_combobox->setCurrentIndex(
54 ui->icon_size_combobox->findData(UISettings::values.icon_size)); 56 ui->icon_size_combobox->findData(UISettings::values.icon_size));
55 ui->row_1_text_combobox->setCurrentIndex( 57 ui->row_1_text_combobox->setCurrentIndex(
diff --git a/src/yuzu/configuration/configure_gamelist.ui b/src/yuzu/configuration/configure_gamelist.ui
index 7471fdb60..7a69377e7 100644
--- a/src/yuzu/configuration/configure_gamelist.ui
+++ b/src/yuzu/configuration/configure_gamelist.ui
@@ -1,126 +1,133 @@
1<?xml version="1.0" encoding="UTF-8"?> 1<?xml version="1.0" encoding="UTF-8"?>
2<ui version="4.0"> 2<ui version="4.0">
3 <class>ConfigureGameList</class> 3 <class>ConfigureGameList</class>
4 <widget class="QWidget" name="ConfigureGeneral"> 4 <widget class="QWidget" name="ConfigureGameList">
5 <property name="geometry"> 5 <property name="geometry">
6 <rect> 6 <rect>
7 <x>0</x> 7 <x>0</x>
8 <y>0</y> 8 <y>0</y>
9 <width>300</width> 9 <width>300</width>
10 <height>377</height> 10 <height>377</height>
11 </rect> 11 </rect>
12 </property> 12 </property>
13 <property name="windowTitle"> 13 <property name="windowTitle">
14 <string>Form</string> 14 <string>Form</string>
15 </property> 15 </property>
16 <layout class="QHBoxLayout" name="HorizontalLayout"> 16 <layout class="QHBoxLayout" name="HorizontalLayout">
17 <item> 17 <item>
18 <layout class="QVBoxLayout" name="VerticalLayout"> 18 <layout class="QVBoxLayout" name="VerticalLayout">
19 <item>
20 <widget class="QGroupBox" name="GeneralGroupBox">
21 <property name="title">
22 <string>General</string>
23 </property>
24 <layout class="QHBoxLayout" name="GeneralHorizontalLayout">
25 <item>
26 <layout class="QVBoxLayout" name="GeneralVerticalLayout">
19 <item> 27 <item>
20 <widget class="QGroupBox" name="GeneralGroupBox"> 28 <widget class="QCheckBox" name="show_unknown">
21 <property name="title"> 29 <property name="text">
22 <string>General</string> 30 <string>Show files with type 'Unknown'</string>
23 </property> 31 </property>
24 <layout class="QHBoxLayout" name="GeneralHorizontalLayout"> 32 </widget>
25 <item>
26 <layout class="QVBoxLayout" name="GeneralVerticalLayout">
27 <item>
28 <widget class="QCheckBox" name="show_unknown">
29 <property name="text">
30 <string>Show files with type 'Unknown'</string>
31 </property>
32 </widget>
33 </item>
34 </layout>
35 </item>
36 </layout>
37 </widget>
38 </item> 33 </item>
39 <item> 34 <item>
40 <widget class="QGroupBox" name="IconSizeGroupBox"> 35 <widget class="QCheckBox" name="show_add_ons">
41 <property name="title"> 36 <property name="text">
42 <string>Icon Size</string> 37 <string>Show Add-Ons Column</string>
43 </property> 38 </property>
44 <layout class="QHBoxLayout" name="icon_size_qhbox_layout"> 39 </widget>
45 <item>
46 <layout class="QVBoxLayout" name="icon_size_qvbox_layout">
47 <item>
48 <layout class="QHBoxLayout" name="icon_size_qhbox_layout_2">
49 <item>
50 <widget class="QLabel" name="icon_size_label">
51 <property name="text">
52 <string>Icon Size:</string>
53 </property>
54 </widget>
55 </item>
56 <item>
57 <widget class="QComboBox" name="icon_size_combobox"/>
58 </item>
59 </layout>
60 </item>
61 </layout>
62 </item>
63 </layout>
64 </widget>
65 </item> 40 </item>
41 </layout>
42 </item>
43 </layout>
44 </widget>
45 </item>
46 <item>
47 <widget class="QGroupBox" name="IconSizeGroupBox">
48 <property name="title">
49 <string>Icon Size</string>
50 </property>
51 <layout class="QHBoxLayout" name="icon_size_qhbox_layout">
52 <item>
53 <layout class="QVBoxLayout" name="icon_size_qvbox_layout">
66 <item> 54 <item>
67 <widget class="QGroupBox" name="RowGroupBox"> 55 <layout class="QHBoxLayout" name="icon_size_qhbox_layout_2">
68 <property name="title"> 56 <item>
69 <string>Row Text</string> 57 <widget class="QLabel" name="icon_size_label">
58 <property name="text">
59 <string>Icon Size:</string>
70 </property> 60 </property>
71 <layout class="QHBoxLayout" name="RowHorizontalLayout"> 61 </widget>
72 <item> 62 </item>
73 <layout class="QVBoxLayout" name="RowVerticalLayout"> 63 <item>
74 <item> 64 <widget class="QComboBox" name="icon_size_combobox"/>
75 <layout class="QHBoxLayout" name="row_1_qhbox_layout"> 65 </item>
76 <item> 66 </layout>
77 <widget class="QLabel" name="row_1_label">
78 <property name="text">
79 <string>Row 1 Text:</string>
80 </property>
81 </widget>
82 </item>
83 <item>
84 <widget class="QComboBox" name="row_1_text_combobox"/>
85 </item>
86 </layout>
87 </item>
88 <item>
89 <layout class="QHBoxLayout" name="row_2_qhbox_layout">
90 <item>
91 <widget class="QLabel" name="row_2_label">
92 <property name="text">
93 <string>Row 2 Text:</string>
94 </property>
95 </widget>
96 </item>
97 <item>
98 <widget class="QComboBox" name="row_2_text_combobox"/>
99 </item>
100 </layout>
101 </item>
102 </layout>
103 </item>
104 </layout>
105 </widget>
106 </item> 67 </item>
68 </layout>
69 </item>
70 </layout>
71 </widget>
72 </item>
73 <item>
74 <widget class="QGroupBox" name="RowGroupBox">
75 <property name="title">
76 <string>Row Text</string>
77 </property>
78 <layout class="QHBoxLayout" name="RowHorizontalLayout">
79 <item>
80 <layout class="QVBoxLayout" name="RowVerticalLayout">
107 <item> 81 <item>
108 <spacer name="verticalSpacer"> 82 <layout class="QHBoxLayout" name="row_1_qhbox_layout">
109 <property name="orientation"> 83 <item>
110 <enum>Qt::Vertical</enum> 84 <widget class="QLabel" name="row_1_label">
85 <property name="text">
86 <string>Row 1 Text:</string>
111 </property> 87 </property>
112 <property name="sizeHint" stdset="0"> 88 </widget>
113 <size> 89 </item>
114 <width>20</width> 90 <item>
115 <height>40</height> 91 <widget class="QComboBox" name="row_1_text_combobox"/>
116 </size> 92 </item>
93 </layout>
94 </item>
95 <item>
96 <layout class="QHBoxLayout" name="row_2_qhbox_layout">
97 <item>
98 <widget class="QLabel" name="row_2_label">
99 <property name="text">
100 <string>Row 2 Text:</string>
117 </property> 101 </property>
118 </spacer> 102 </widget>
103 </item>
104 <item>
105 <widget class="QComboBox" name="row_2_text_combobox"/>
106 </item>
107 </layout>
119 </item> 108 </item>
120 </layout> 109 </layout>
121 </item> 110 </item>
111 </layout>
112 </widget>
113 </item>
114 <item>
115 <spacer name="verticalSpacer">
116 <property name="orientation">
117 <enum>Qt::Vertical</enum>
118 </property>
119 <property name="sizeHint" stdset="0">
120 <size>
121 <width>20</width>
122 <height>40</height>
123 </size>
124 </property>
125 </spacer>
126 </item>
122 </layout> 127 </layout>
123 </widget> 128 </item>
129 </layout>
130 </widget>
124 <resources/> 131 <resources/>
125 <connections/> 132 <connections/>
126</ui> 133</ui>
diff --git a/src/yuzu/game_list.cpp b/src/yuzu/game_list.cpp
index a5a4aa432..11a8c390b 100644
--- a/src/yuzu/game_list.cpp
+++ b/src/yuzu/game_list.cpp
@@ -215,12 +215,18 @@ GameList::GameList(FileSys::VirtualFilesystem vfs, GMainWindow* parent)
215 tree_view->setUniformRowHeights(true); 215 tree_view->setUniformRowHeights(true);
216 tree_view->setContextMenuPolicy(Qt::CustomContextMenu); 216 tree_view->setContextMenuPolicy(Qt::CustomContextMenu);
217 217
218 item_model->insertColumns(0, COLUMN_COUNT); 218 item_model->insertColumns(0, UISettings::values.show_add_ons ? COLUMN_COUNT : COLUMN_COUNT - 1);
219 item_model->setHeaderData(COLUMN_NAME, Qt::Horizontal, tr("Name")); 219 item_model->setHeaderData(COLUMN_NAME, Qt::Horizontal, tr("Name"));
220 item_model->setHeaderData(COLUMN_COMPATIBILITY, Qt::Horizontal, tr("Compatibility")); 220 item_model->setHeaderData(COLUMN_COMPATIBILITY, Qt::Horizontal, tr("Compatibility"));
221 item_model->setHeaderData(COLUMN_ADD_ONS, Qt::Horizontal, tr("Add-ons")); 221
222 item_model->setHeaderData(COLUMN_FILE_TYPE, Qt::Horizontal, tr("File type")); 222 if (UISettings::values.show_add_ons) {
223 item_model->setHeaderData(COLUMN_SIZE, Qt::Horizontal, tr("Size")); 223 item_model->setHeaderData(COLUMN_ADD_ONS, Qt::Horizontal, tr("Add-ons"));
224 item_model->setHeaderData(COLUMN_FILE_TYPE, Qt::Horizontal, tr("File type"));
225 item_model->setHeaderData(COLUMN_SIZE, Qt::Horizontal, tr("Size"));
226 } else {
227 item_model->setHeaderData(COLUMN_FILE_TYPE - 1, Qt::Horizontal, tr("File type"));
228 item_model->setHeaderData(COLUMN_SIZE - 1, Qt::Horizontal, tr("Size"));
229 }
224 230
225 connect(tree_view, &QTreeView::activated, this, &GameList::ValidateEntry); 231 connect(tree_view, &QTreeView::activated, this, &GameList::ValidateEntry);
226 connect(tree_view, &QTreeView::customContextMenuRequested, this, &GameList::PopupContextMenu); 232 connect(tree_view, &QTreeView::customContextMenuRequested, this, &GameList::PopupContextMenu);
@@ -394,6 +400,25 @@ void GameList::PopulateAsync(const QString& dir_path, bool deep_scan) {
394 } 400 }
395 401
396 tree_view->setEnabled(false); 402 tree_view->setEnabled(false);
403
404 // Update the columns in case UISettings has changed
405 item_model->removeColumns(0, item_model->columnCount());
406 item_model->insertColumns(0, UISettings::values.show_add_ons ? COLUMN_COUNT : COLUMN_COUNT - 1);
407 item_model->setHeaderData(COLUMN_NAME, Qt::Horizontal, tr("Name"));
408 item_model->setHeaderData(COLUMN_COMPATIBILITY, Qt::Horizontal, tr("Compatibility"));
409
410 if (UISettings::values.show_add_ons) {
411 item_model->setHeaderData(COLUMN_ADD_ONS, Qt::Horizontal, tr("Add-ons"));
412 item_model->setHeaderData(COLUMN_FILE_TYPE, Qt::Horizontal, tr("File type"));
413 item_model->setHeaderData(COLUMN_SIZE, Qt::Horizontal, tr("Size"));
414 } else {
415 item_model->setHeaderData(COLUMN_FILE_TYPE - 1, Qt::Horizontal, tr("File type"));
416 item_model->setHeaderData(COLUMN_SIZE - 1, Qt::Horizontal, tr("Size"));
417 item_model->removeColumns(COLUMN_COUNT - 1, 1);
418 }
419
420 LoadInterfaceLayout();
421
397 // Delete any rows that might already exist if we're repopulating 422 // Delete any rows that might already exist if we're repopulating
398 item_model->removeRows(0, item_model->rowCount()); 423 item_model->removeRows(0, item_model->rowCount());
399 424
diff --git a/src/yuzu/game_list_worker.cpp b/src/yuzu/game_list_worker.cpp
index 3d865a12d..362902e46 100644
--- a/src/yuzu/game_list_worker.cpp
+++ b/src/yuzu/game_list_worker.cpp
@@ -123,17 +123,22 @@ void GameListWorker::AddInstalledTitlesToGameList() {
123 if (it != compatibility_list.end()) 123 if (it != compatibility_list.end())
124 compatibility = it->second.first; 124 compatibility = it->second.first;
125 125
126 emit EntryReady({ 126 QList<QStandardItem*> list{
127 new GameListItemPath( 127 new GameListItemPath(
128 FormatGameName(file->GetFullPath()), icon, QString::fromStdString(name), 128 FormatGameName(file->GetFullPath()), icon, QString::fromStdString(name),
129 QString::fromStdString(Loader::GetFileTypeString(loader->GetFileType())), 129 QString::fromStdString(Loader::GetFileTypeString(loader->GetFileType())),
130 program_id), 130 program_id),
131 new GameListItemCompat(compatibility), 131 new GameListItemCompat(compatibility),
132 new GameListItem(FormatPatchNameVersions(patch, *loader)),
133 new GameListItem( 132 new GameListItem(
134 QString::fromStdString(Loader::GetFileTypeString(loader->GetFileType()))), 133 QString::fromStdString(Loader::GetFileTypeString(loader->GetFileType()))),
135 new GameListItemSize(file->GetSize()), 134 new GameListItemSize(file->GetSize()),
136 }); 135 };
136
137 if (UISettings::values.show_add_ons) {
138 list.insert(2, new GameListItem(FormatPatchNameVersions(patch, *loader)));
139 }
140
141 emit EntryReady(list);
137 } 142 }
138 143
139 const auto control_data = cache->ListEntriesFilter(FileSys::TitleType::Application, 144 const auto control_data = cache->ListEntriesFilter(FileSys::TitleType::Application,
@@ -216,18 +221,23 @@ void GameListWorker::AddFstEntriesToGameList(const std::string& dir_path, unsign
216 if (it != compatibility_list.end()) 221 if (it != compatibility_list.end())
217 compatibility = it->second.first; 222 compatibility = it->second.first;
218 223
219 emit EntryReady({ 224 QList<QStandardItem*> list{
220 new GameListItemPath( 225 new GameListItemPath(
221 FormatGameName(physical_name), icon, QString::fromStdString(name), 226 FormatGameName(physical_name), icon, QString::fromStdString(name),
222 QString::fromStdString(Loader::GetFileTypeString(loader->GetFileType())), 227 QString::fromStdString(Loader::GetFileTypeString(loader->GetFileType())),
223 program_id), 228 program_id),
224 new GameListItemCompat(compatibility), 229 new GameListItemCompat(compatibility),
225 new GameListItem( 230 new GameListItem(
226 FormatPatchNameVersions(patch, *loader, loader->IsRomFSUpdatable())),
227 new GameListItem(
228 QString::fromStdString(Loader::GetFileTypeString(loader->GetFileType()))), 231 QString::fromStdString(Loader::GetFileTypeString(loader->GetFileType()))),
229 new GameListItemSize(FileUtil::GetSize(physical_name)), 232 new GameListItemSize(FileUtil::GetSize(physical_name)),
230 }); 233 };
234
235 if (UISettings::values.show_add_ons) {
236 list.insert(2, new GameListItem(FormatPatchNameVersions(
237 patch, *loader, loader->IsRomFSUpdatable())));
238 }
239
240 emit EntryReady(std::move(list));
231 } else if (is_dir && recursion > 0) { 241 } else if (is_dir && recursion > 0) {
232 watch_list.append(QString::fromStdString(physical_name)); 242 watch_list.append(QString::fromStdString(physical_name));
233 AddFstEntriesToGameList(physical_name, recursion - 1); 243 AddFstEntriesToGameList(physical_name, recursion - 1);
diff --git a/src/yuzu/ui_settings.h b/src/yuzu/ui_settings.h
index 2e617d52a..32a0d813c 100644
--- a/src/yuzu/ui_settings.h
+++ b/src/yuzu/ui_settings.h
@@ -59,6 +59,7 @@ struct Values {
59 59
60 // Game List 60 // Game List
61 bool show_unknown; 61 bool show_unknown;
62 bool show_add_ons;
62 uint32_t icon_size; 63 uint32_t icon_size;
63 uint8_t row_1_text_id; 64 uint8_t row_1_text_id;
64 uint8_t row_2_text_id; 65 uint8_t row_2_text_id;