summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to '')
-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:
// We don't delete it because we want BitField to be trivially copyable.
constexpr BitField& operator=(const BitField&) = default;
- // StorageType is T for non-enum types and the underlying type of T if
+ // UnderlyingType is T for non-enum types and the underlying type of T if
// T is an enumeration. Note that T is wrapped within an enable_if in the
// former case to workaround compile errors which arise when using
// std::underlying_type<T>::type directly.
- using StorageType = typename std::conditional_t<std::is_enum<T>::value, std::underlying_type<T>,
- std::enable_if<true, T>>::type;
+ using UnderlyingType = typename std::conditional_t<std::is_enum_v<T>, std::underlying_type<T>,
+ std::enable_if<true, T>>::type;
- // Unsigned version of StorageType
- using StorageTypeU = std::make_unsigned_t<StorageType>;
+ // We store the value as the unsigned type to avoid undefined behaviour on value shifting
+ using StorageType = std::make_unsigned_t<UnderlyingType>;
public:
/// Constants to allow limited introspection of fields if needed
static constexpr std::size_t position = Position;
static constexpr std::size_t bits = Bits;
- static constexpr StorageType mask = (((StorageTypeU)~0) >> (8 * sizeof(T) - bits)) << position;
+ static constexpr StorageType mask = (((StorageType)~0) >> (8 * sizeof(T) - bits)) << position;
/**
* Formats a value by masking and shifting it according to the field parameters. A value
@@ -148,11 +148,12 @@ public:
* union in a constexpr context.
*/
static constexpr FORCE_INLINE T ExtractValue(const StorageType& storage) {
- if (std::numeric_limits<T>::is_signed) {
+ if constexpr (std::numeric_limits<UnderlyingType>::is_signed) {
std::size_t shift = 8 * sizeof(T) - bits;
- return (T)((storage << (shift - position)) >> shift);
+ return static_cast<T>(static_cast<UnderlyingType>(storage << (shift - position)) >>
+ shift);
} else {
- return (T)((storage & mask) >> position);
+ return static_cast<T>((storage & mask) >> position);
}
}
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) {
for (const VirtualFile& file : partitions[static_cast<std::size_t>(part)]->GetFiles()) {
if (file->GetExtension() != "nca")
continue;
- auto nca = std::make_shared<NCA>(file);
+ auto nca = std::make_shared<NCA>(file, nullptr, 0, keys);
// TODO(DarkLordZach): Add proper Rev1+ Support
if (nca->IsUpdate())
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 @@
#include <vector>
#include "common/common_types.h"
#include "common/swap.h"
+#include "core/crypto/key_manager.h"
#include "core/file_sys/vfs.h"
namespace Loader {
@@ -107,5 +108,7 @@ private:
std::shared_ptr<NSP> secure_partition;
std::shared_ptr<NCA> program;
std::vector<std::shared_ptr<NCA>> ncas;
+
+ Core::Crypto::KeyManager keys;
};
} // 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) {
return header.magic == Common::MakeMagic('N', 'C', 'A', '3');
}
-NCA::NCA(VirtualFile file_, VirtualFile bktr_base_romfs_, u64 bktr_base_ivfc_offset)
- : file(std::move(file_)), bktr_base_romfs(std::move(bktr_base_romfs_)) {
+NCA::NCA(VirtualFile file_, VirtualFile bktr_base_romfs_, u64 bktr_base_ivfc_offset,
+ Core::Crypto::KeyManager keys_)
+ : file(std::move(file_)), bktr_base_romfs(std::move(bktr_base_romfs_)), keys(std::move(keys_)) {
if (file == nullptr) {
status = Loader::ResultStatus::ErrorNullFile;
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) {
class NCA : public ReadOnlyVfsDirectory {
public:
explicit NCA(VirtualFile file, VirtualFile bktr_base_romfs = nullptr,
- u64 bktr_base_ivfc_offset = 0);
+ u64 bktr_base_ivfc_offset = 0,
+ Core::Crypto::KeyManager keys = Core::Crypto::KeyManager());
~NCA() override;
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 @@
namespace FileSys {
-namespace ErrCodes {
-enum {
- NotFound = 1,
- TitleNotFound = 1002,
- SdCardNotFound = 2001,
- RomFSNotFound = 2520,
-};
-}
-
-constexpr ResultCode ERROR_PATH_NOT_FOUND(ErrorModule::FS, ErrCodes::NotFound);
-
-// TODO(bunnei): Replace these with correct errors for Switch OS
-constexpr ResultCode ERROR_INVALID_PATH(-1);
-constexpr ResultCode ERROR_UNSUPPORTED_OPEN_FLAGS(-1);
-constexpr ResultCode ERROR_INVALID_OPEN_FLAGS(-1);
-constexpr ResultCode ERROR_FILE_NOT_FOUND(-1);
-constexpr ResultCode ERROR_UNEXPECTED_FILE_OR_DIRECTORY(-1);
-constexpr ResultCode ERROR_DIRECTORY_ALREADY_EXISTS(-1);
-constexpr ResultCode ERROR_FILE_ALREADY_EXISTS(-1);
-constexpr ResultCode ERROR_DIRECTORY_NOT_EMPTY(-1);
+constexpr ResultCode ERROR_PATH_NOT_FOUND{ErrorModule::FS, 1};
+constexpr ResultCode ERROR_ENTITY_NOT_FOUND{ErrorModule::FS, 1002};
+constexpr ResultCode ERROR_SD_CARD_NOT_FOUND{ErrorModule::FS, 2001};
+constexpr ResultCode ERROR_INVALID_OFFSET{ErrorModule::FS, 6061};
+constexpr ResultCode ERROR_INVALID_SIZE{ErrorModule::FS, 6062};
} // 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) {
VirtualFile RegisteredCache::OpenFileOrDirectoryConcat(const VirtualDir& dir,
std::string_view path) const {
- if (dir->GetFileRelative(path) != nullptr)
- return dir->GetFileRelative(path);
- if (dir->GetDirectoryRelative(path) != nullptr) {
+ const auto file = dir->GetFileRelative(path);
+ if (file != nullptr)
+ return file;
+
+ const auto nca_dir = dir->GetDirectoryRelative(path);
+ if (nca_dir != nullptr) {
const auto nca_dir = dir->GetDirectoryRelative(path);
VirtualFile file = nullptr;
@@ -225,7 +228,7 @@ void RegisteredCache::ProcessFiles(const std::vector<NcaID>& ids) {
if (file == nullptr)
continue;
- const auto nca = std::make_shared<NCA>(parser(file, id));
+ const auto nca = std::make_shared<NCA>(parser(file, id), nullptr, 0, keys);
if (nca->GetStatus() != Loader::ResultStatus::Success ||
nca->GetType() != NCAContentType::Meta) {
continue;
@@ -315,7 +318,7 @@ std::unique_ptr<NCA> RegisteredCache::GetEntry(u64 title_id, ContentRecordType t
const auto raw = GetEntryRaw(title_id, type);
if (raw == nullptr)
return nullptr;
- return std::make_unique<NCA>(raw);
+ return std::make_unique<NCA>(raw, nullptr, 0, keys);
}
std::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 @@
#include <vector>
#include <boost/container/flat_map.hpp>
#include "common/common_types.h"
+#include "core/crypto/key_manager.h"
#include "core/file_sys/vfs.h"
namespace FileSys {
@@ -133,6 +134,8 @@ private:
VirtualDir dir;
RegisteredCacheParsingFunction parser;
+ Core::Crypto::KeyManager keys;
+
// maps tid -> NcaID of meta
boost::container::flat_map<u64, NcaID> meta_id;
// 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) {
continue;
}
- auto next_nca = std::make_shared<NCA>(next_file);
+ auto next_nca = std::make_shared<NCA>(next_file, nullptr, 0, keys);
if (next_nca->GetType() == NCAContentType::Program)
program_status[cnmt.GetTitleID()] = next_nca->GetStatus();
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:
std::map<u64, std::map<ContentRecordType, std::shared_ptr<NCA>>> ncas;
std::vector<VirtualFile> ticket_files;
+ Core::Crypto::KeyManager keys;
+
VirtualFile romfs;
VirtualDir exefs;
};
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 @@
namespace Kernel {
-namespace ErrCodes {
-enum {
- // Confirmed Switch OS error codes
- MaxConnectionsReached = 7,
- InvalidSize = 101,
- InvalidAddress = 102,
- HandleTableFull = 105,
- InvalidMemoryState = 106,
- InvalidMemoryPermissions = 108,
- InvalidMemoryRange = 110,
- InvalidThreadPriority = 112,
- InvalidProcessorId = 113,
- InvalidHandle = 114,
- InvalidPointer = 115,
- InvalidCombination = 116,
- Timeout = 117,
- SynchronizationCanceled = 118,
- TooLarge = 119,
- InvalidEnumValue = 120,
- NoSuchEntry = 121,
- AlreadyRegistered = 122,
- SessionClosed = 123,
- InvalidState = 125,
- ResourceLimitExceeded = 132,
-};
-}
+// Confirmed Switch kernel error codes
-// WARNING: The kernel is quite inconsistent in it's usage of errors code. Make sure to always
-// double check that the code matches before re-using the constant.
-
-constexpr ResultCode ERR_HANDLE_TABLE_FULL(ErrorModule::Kernel, ErrCodes::HandleTableFull);
-constexpr ResultCode ERR_SESSION_CLOSED_BY_REMOTE(ErrorModule::Kernel, ErrCodes::SessionClosed);
-constexpr ResultCode ERR_PORT_NAME_TOO_LONG(ErrorModule::Kernel, ErrCodes::TooLarge);
-constexpr ResultCode ERR_MAX_CONNECTIONS_REACHED(ErrorModule::Kernel,
- ErrCodes::MaxConnectionsReached);
-constexpr ResultCode ERR_INVALID_ENUM_VALUE(ErrorModule::Kernel, ErrCodes::InvalidEnumValue);
-constexpr ResultCode ERR_INVALID_COMBINATION_KERNEL(ErrorModule::Kernel,
- ErrCodes::InvalidCombination);
-constexpr ResultCode ERR_INVALID_ADDRESS(ErrorModule::Kernel, ErrCodes::InvalidAddress);
-constexpr ResultCode ERR_INVALID_ADDRESS_STATE(ErrorModule::Kernel, ErrCodes::InvalidMemoryState);
-constexpr ResultCode ERR_INVALID_MEMORY_PERMISSIONS(ErrorModule::Kernel,
- ErrCodes::InvalidMemoryPermissions);
-constexpr ResultCode ERR_INVALID_MEMORY_RANGE(ErrorModule::Kernel, ErrCodes::InvalidMemoryRange);
-constexpr ResultCode ERR_INVALID_HANDLE(ErrorModule::Kernel, ErrCodes::InvalidHandle);
-constexpr ResultCode ERR_INVALID_PROCESSOR_ID(ErrorModule::Kernel, ErrCodes::InvalidProcessorId);
-constexpr ResultCode ERR_INVALID_SIZE(ErrorModule::Kernel, ErrCodes::InvalidSize);
-constexpr ResultCode ERR_ALREADY_REGISTERED(ErrorModule::Kernel, ErrCodes::AlreadyRegistered);
-constexpr ResultCode ERR_INVALID_STATE(ErrorModule::Kernel, ErrCodes::InvalidState);
-constexpr ResultCode ERR_INVALID_THREAD_PRIORITY(ErrorModule::Kernel,
- ErrCodes::InvalidThreadPriority);
-constexpr ResultCode ERR_INVALID_POINTER(ErrorModule::Kernel, ErrCodes::InvalidPointer);
-constexpr ResultCode ERR_NOT_FOUND(ErrorModule::Kernel, ErrCodes::NoSuchEntry);
-constexpr ResultCode RESULT_TIMEOUT(ErrorModule::Kernel, ErrCodes::Timeout);
+constexpr ResultCode ERR_MAX_CONNECTIONS_REACHED{ErrorModule::Kernel, 7};
+constexpr ResultCode ERR_INVALID_SIZE{ErrorModule::Kernel, 101};
+constexpr ResultCode ERR_INVALID_ADDRESS{ErrorModule::Kernel, 102};
+constexpr ResultCode ERR_HANDLE_TABLE_FULL{ErrorModule::Kernel, 105};
+constexpr ResultCode ERR_INVALID_ADDRESS_STATE{ErrorModule::Kernel, 106};
+constexpr ResultCode ERR_INVALID_MEMORY_PERMISSIONS{ErrorModule::Kernel, 108};
+constexpr ResultCode ERR_INVALID_MEMORY_RANGE{ErrorModule::Kernel, 110};
+constexpr ResultCode ERR_INVALID_PROCESSOR_ID{ErrorModule::Kernel, 113};
+constexpr ResultCode ERR_INVALID_THREAD_PRIORITY{ErrorModule::Kernel, 112};
+constexpr ResultCode ERR_INVALID_HANDLE{ErrorModule::Kernel, 114};
+constexpr ResultCode ERR_INVALID_POINTER{ErrorModule::Kernel, 115};
+constexpr ResultCode ERR_INVALID_COMBINATION{ErrorModule::Kernel, 116};
+constexpr ResultCode RESULT_TIMEOUT{ErrorModule::Kernel, 117};
+constexpr ResultCode ERR_SYNCHRONIZATION_CANCELED{ErrorModule::Kernel, 118};
+constexpr ResultCode ERR_OUT_OF_RANGE{ErrorModule::Kernel, 119};
+constexpr ResultCode ERR_INVALID_ENUM_VALUE{ErrorModule::Kernel, 120};
+constexpr ResultCode ERR_NOT_FOUND{ErrorModule::Kernel, 121};
+constexpr ResultCode ERR_ALREADY_REGISTERED{ErrorModule::Kernel, 122};
+constexpr ResultCode ERR_SESSION_CLOSED_BY_REMOTE{ErrorModule::Kernel, 123};
+constexpr ResultCode ERR_INVALID_STATE{ErrorModule::Kernel, 125};
+constexpr ResultCode ERR_RESOURCE_LIMIT_EXCEEDED{ErrorModule::Kernel, 132};
} // 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) {
return RESULT_SUCCESS;
}
+static ResultCode SetMemoryPermission(VAddr addr, u64 size, u32 prot) {
+ LOG_TRACE(Kernel_SVC, "called, addr=0x{:X}, size=0x{:X}, prot=0x{:X}", addr, size, prot);
+
+ if (!Common::Is4KBAligned(addr)) {
+ return ERR_INVALID_ADDRESS;
+ }
+
+ if (size == 0 || !Common::Is4KBAligned(size)) {
+ return ERR_INVALID_SIZE;
+ }
+
+ if (!IsValidAddressRange(addr, size)) {
+ return ERR_INVALID_ADDRESS_STATE;
+ }
+
+ const auto permission = static_cast<MemoryPermission>(prot);
+ if (permission != MemoryPermission::None && permission != MemoryPermission::Read &&
+ permission != MemoryPermission::ReadWrite) {
+ return ERR_INVALID_MEMORY_PERMISSIONS;
+ }
+
+ auto* const current_process = Core::CurrentProcess();
+ auto& vm_manager = current_process->VMManager();
+
+ if (!IsInsideAddressSpace(vm_manager, addr, size)) {
+ return ERR_INVALID_ADDRESS_STATE;
+ }
+
+ const VMManager::VMAHandle iter = vm_manager.FindVMA(addr);
+ if (iter == vm_manager.vma_map.end()) {
+ return ERR_INVALID_ADDRESS_STATE;
+ }
+
+ LOG_WARNING(Kernel_SVC, "Uniformity check on protected memory is not implemented.");
+ // TODO: Performs a uniformity check to make sure only protected memory is changed (it doesn't
+ // make sense to allow changing permissions on kernel memory itself, etc).
+
+ const auto converted_permissions = SharedMemory::ConvertPermissions(permission);
+
+ return vm_manager.ReprotectRange(addr, size, converted_permissions);
+}
+
static ResultCode SetMemoryAttribute(VAddr addr, u64 size, u32 state0, u32 state1) {
LOG_WARNING(Kernel_SVC,
"(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
// Read 1 char beyond the max allowed port name to detect names that are too long.
std::string port_name = Memory::ReadCString(port_name_address, PortNameMaxLength + 1);
if (port_name.size() > PortNameMaxLength) {
- return ERR_PORT_NAME_TOO_LONG;
+ return ERR_OUT_OF_RANGE;
}
LOG_TRACE(Kernel_SVC, "called port_name={}", port_name);
@@ -268,8 +310,9 @@ static ResultCode WaitSynchronization(Handle* index, VAddr handles_address, u64
static constexpr u64 MaxHandles = 0x40;
- if (handle_count > MaxHandles)
- return ResultCode(ErrorModule::Kernel, ErrCodes::TooLarge);
+ if (handle_count > MaxHandles) {
+ return ERR_OUT_OF_RANGE;
+ }
auto* const thread = GetCurrentThread();
@@ -334,8 +377,7 @@ static ResultCode CancelSynchronization(Handle thread_handle) {
}
ASSERT(thread->GetStatus() == ThreadStatus::WaitSynchAny);
- thread->SetWaitSynchronizationResult(
- ResultCode(ErrorModule::Kernel, ErrCodes::SynchronizationCanceled));
+ thread->SetWaitSynchronizationResult(ERR_SYNCHRONIZATION_CANCELED);
thread->ResumeFromWait();
return RESULT_SUCCESS;
}
@@ -564,7 +606,7 @@ static ResultCode GetInfo(u64* result, u64 info_id, u64 handle, u64 info_sub_id)
}
if (info_sub_id >= Process::RANDOM_ENTROPY_SIZE) {
- return ERR_INVALID_COMBINATION_KERNEL;
+ return ERR_INVALID_COMBINATION;
}
*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)
case GetInfoType::ThreadTickCount: {
constexpr u64 num_cpus = 4;
if (info_sub_id != 0xFFFFFFFFFFFFFFFF && info_sub_id >= num_cpus) {
- return ERR_INVALID_COMBINATION_KERNEL;
+ return ERR_INVALID_COMBINATION;
}
const auto thread =
@@ -1194,7 +1236,7 @@ static ResultCode SetThreadCoreMask(Handle thread_handle, u32 core, u64 mask) {
}
if (mask == 0) {
- return ResultCode(ErrorModule::Kernel, ErrCodes::InvalidCombination);
+ return ERR_INVALID_COMBINATION;
}
/// 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) {
if (core == OnlyChangeMask) {
core = thread->GetIdealCore();
} else if (core >= Core::NUM_CPU_CORES && core != static_cast<u32>(-1)) {
- return ResultCode(ErrorModule::Kernel, ErrCodes::InvalidProcessorId);
+ return ERR_INVALID_PROCESSOR_ID;
}
// Error out if the input core isn't enabled in the input mask.
if (core < Core::NUM_CPU_CORES && (mask & (1ull << core)) == 0) {
- return ResultCode(ErrorModule::Kernel, ErrCodes::InvalidCombination);
+ return ERR_INVALID_COMBINATION;
}
thread->ChangeCore(core, mask);
@@ -1297,7 +1339,7 @@ struct FunctionDef {
static const FunctionDef SVC_Table[] = {
{0x00, nullptr, "Unknown"},
{0x01, SvcWrap<SetHeapSize>, "SetHeapSize"},
- {0x02, nullptr, "SetMemoryPermission"},
+ {0x02, SvcWrap<SetMemoryPermission>, "SetMemoryPermission"},
{0x03, SvcWrap<SetMemoryAttribute>, "SetMemoryAttribute"},
{0x04, SvcWrap<MapMemory>, "MapMemory"},
{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() {
FuncReturn(func(Param(0), Param(1), Param(2)).raw);
}
+template <ResultCode func(u64, u64, u32)>
+void SvcWrap() {
+ FuncReturn(func(Param(0), Param(1), static_cast<u32>(Param(2))).raw);
+}
+
template <ResultCode func(u32, u64, u64, u32)>
void SvcWrap() {
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 @@
enum class ErrorDescription : u32 {
Success = 0,
RemoteProcessDead = 301,
- InvalidOffset = 6061,
- InvalidLength = 6062,
};
/**
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:
IPC::ResponseBuilder rb{ctx, 6};
rb.Push(RESULT_SUCCESS);
rb.Push<u32>(consumed);
- rb.Push<u64>(performance);
rb.Push<u32>(sample_count);
+ rb.Push<u64>(performance);
ctx.WriteBuffer(samples.data(), samples.size() * sizeof(s16));
}
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,
static_cast<u8>(space), save_struct.DebugInfo());
if (save_data_factory == nullptr) {
- return ResultCode(ErrorModule::FS, FileSys::ErrCodes::TitleNotFound);
+ return FileSys::ERROR_ENTITY_NOT_FOUND;
}
return save_data_factory->Open(space, save_struct);
@@ -313,7 +313,7 @@ ResultVal<FileSys::VirtualDir> OpenSaveDataSpace(FileSys::SaveDataSpaceId space)
LOG_TRACE(Service_FS, "Opening Save Data Space for space_id={:01X}", static_cast<u8>(space));
if (save_data_factory == nullptr) {
- return ResultCode(ErrorModule::FS, FileSys::ErrCodes::TitleNotFound);
+ return FileSys::ERROR_ENTITY_NOT_FOUND;
}
return MakeResult(save_data_factory->GetSaveDataSpaceDirectory(space));
@@ -323,15 +323,22 @@ ResultVal<FileSys::VirtualDir> OpenSDMC() {
LOG_TRACE(Service_FS, "Opening SDMC");
if (sdmc_factory == nullptr) {
- return ResultCode(ErrorModule::FS, FileSys::ErrCodes::SdCardNotFound);
+ return FileSys::ERROR_SD_CARD_NOT_FOUND;
}
return sdmc_factory->Open();
}
-std::unique_ptr<FileSys::RegisteredCacheUnion> GetUnionContents() {
- return std::make_unique<FileSys::RegisteredCacheUnion>(std::vector<FileSys::RegisteredCache*>{
- GetSystemNANDContents(), GetUserNANDContents(), GetSDMCContents()});
+std::shared_ptr<FileSys::RegisteredCacheUnion> registered_cache_union;
+
+std::shared_ptr<FileSys::RegisteredCacheUnion> GetUnionContents() {
+ if (registered_cache_union == nullptr) {
+ registered_cache_union =
+ std::make_shared<FileSys::RegisteredCacheUnion>(std::vector<FileSys::RegisteredCache*>{
+ GetSystemNANDContents(), GetUserNANDContents(), GetSDMCContents()});
+ }
+
+ return registered_cache_union;
}
FileSys::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,
ResultVal<FileSys::VirtualDir> OpenSaveDataSpace(FileSys::SaveDataSpaceId space);
ResultVal<FileSys::VirtualDir> OpenSDMC();
-std::unique_ptr<FileSys::RegisteredCacheUnion> GetUnionContents();
+std::shared_ptr<FileSys::RegisteredCacheUnion> GetUnionContents();
FileSys::RegisteredCache* GetSystemNANDContents();
FileSys::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:
// Error checking
if (length < 0) {
IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultCode(ErrorModule::FS, ErrorDescription::InvalidLength));
+ rb.Push(FileSys::ERROR_INVALID_SIZE);
return;
}
if (offset < 0) {
IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultCode(ErrorModule::FS, ErrorDescription::InvalidOffset));
+ rb.Push(FileSys::ERROR_INVALID_OFFSET);
return;
}
@@ -108,12 +108,12 @@ private:
// Error checking
if (length < 0) {
IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultCode(ErrorModule::FS, ErrorDescription::InvalidLength));
+ rb.Push(FileSys::ERROR_INVALID_SIZE);
return;
}
if (offset < 0) {
IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultCode(ErrorModule::FS, ErrorDescription::InvalidOffset));
+ rb.Push(FileSys::ERROR_INVALID_OFFSET);
return;
}
@@ -139,12 +139,12 @@ private:
// Error checking
if (length < 0) {
IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultCode(ErrorModule::FS, ErrorDescription::InvalidLength));
+ rb.Push(FileSys::ERROR_INVALID_SIZE);
return;
}
if (offset < 0) {
IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultCode(ErrorModule::FS, ErrorDescription::InvalidOffset));
+ rb.Push(FileSys::ERROR_INVALID_OFFSET);
return;
}
@@ -744,7 +744,7 @@ void FSP_SRV::MountSaveData(Kernel::HLERequestContext& ctx) {
if (dir.Failed()) {
IPC::ResponseBuilder rb{ctx, 2, 0, 0};
- rb.Push(ResultCode(ErrorModule::FS, FileSys::ErrCodes::TitleNotFound));
+ rb.Push(FileSys::ERROR_ENTITY_NOT_FOUND);
return;
}
@@ -836,7 +836,7 @@ void FSP_SRV::OpenRomStorage(Kernel::HLERequestContext& ctx) {
static_cast<u8>(storage_id), title_id);
IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultCode(ErrorModule::FS, FileSys::ErrCodes::TitleNotFound));
+ rb.Push(FileSys::ERROR_ENTITY_NOT_FOUND);
}
} // 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:
{519, nullptr, "GetPalmaOperationResult"},
{520, nullptr, "ReadPalmaPlayLog"},
{521, nullptr, "ResetPalmaPlayLog"},
- {522, nullptr, "SetIsPalmaAllConnectable"},
+ {522, &Hid::SetIsPalmaAllConnectable, "SetIsPalmaAllConnectable"},
{523, nullptr, "SetIsPalmaPairedConnectable"},
{524, nullptr, "PairPalma"},
- {525, nullptr, "SetPalmaBoostMode"},
+ {525, &Hid::SetPalmaBoostMode, "SetPalmaBoostMode"},
{1000, nullptr, "SetNpadCommunicationMode"},
{1001, nullptr, "GetNpadCommunicationMode"},
};
@@ -596,6 +596,18 @@ private:
rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service_HID, "(STUBBED) called");
}
+
+ void SetIsPalmaAllConnectable(Kernel::HLERequestContext& ctx) {
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(RESULT_SUCCESS);
+ LOG_WARNING(Service_HID, "(STUBBED) called");
+ }
+
+ void SetPalmaBoostMode(Kernel::HLERequestContext& ctx) {
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(RESULT_SUCCESS);
+ LOG_WARNING(Service_HID, "(STUBBED) called");
+ }
};
class 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
if (params.is_layered) {
u64 offset = params.GetMipmapLevelOffset(mip_level);
u64 offset_gl = 0;
- u64 layer_size = params.LayerMemorySize();
- u64 gl_size = params.LayerSizeGL(mip_level);
+ const u64 layer_size = params.LayerMemorySize();
+ const u64 gl_size = params.LayerSizeGL(mip_level);
for (u32 i = 0; i < params.depth; i++) {
functions[static_cast<std::size_t>(params.pixel_format)](
params.MipWidth(mip_level), params.MipBlockHeight(mip_level),
@@ -561,7 +561,7 @@ void SwizzleFunc(const GLConversionArray& functions, const SurfaceParams& params
offset_gl += gl_size;
}
} else {
- u64 offset = params.GetMipmapLevelOffset(mip_level);
+ const u64 offset = params.GetMipmapLevelOffset(mip_level);
functions[static_cast<std::size_t>(params.pixel_format)](
params.MipWidth(mip_level), params.MipBlockHeight(mip_level),
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 {
const auto& updated = viewports[0];
if (updated.x != current.x || updated.y != current.y || updated.width != current.width ||
updated.height != current.height) {
- glViewport(updated.x, updated.y, updated.width, updated.height);
+ glViewport(static_cast<GLint>(updated.x), static_cast<GLint>(updated.y),
+ static_cast<GLsizei>(updated.width), static_cast<GLsizei>(updated.height));
}
if (updated.depth_range_near != current.depth_range_near ||
updated.depth_range_far != current.depth_range_far) {
@@ -313,7 +314,7 @@ void OpenGLState::ApplyGlobalBlending() const {
}
}
-void OpenGLState::ApplyTargetBlending(int target, bool force) const {
+void OpenGLState::ApplyTargetBlending(std::size_t target, bool force) const {
const Blend& updated = blend[target];
const Blend& current = cur_state.blend[target];
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:
void ApplyPrimitiveRestart() const;
void ApplyStencilTest() const;
void ApplyViewport() const;
- void ApplyTargetBlending(int target, bool force) const;
+ void ApplyTargetBlending(std::size_t target, bool force) const;
void ApplyGlobalBlending() const;
void ApplyBlending() const;
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>();
* Instead of going gob by gob, we map the coordinates inside a block and manage from
* those. Block_Width is assumed to be 1.
*/
-void PreciseProcessBlock(u8* swizzled_data, u8* unswizzled_data, const bool unswizzle,
+void PreciseProcessBlock(u8* const swizzled_data, u8* const unswizzled_data, const bool unswizzle,
const u32 x_start, const u32 y_start, const u32 z_start, const u32 x_end,
const u32 y_end, const u32 z_end, const u32 tile_offset,
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
* Instead of going gob by gob, we map the coordinates inside a block and manage from
* those. Block_Width is assumed to be 1.
*/
-void FastProcessBlock(u8* swizzled_data, u8* unswizzled_data, const bool unswizzle,
+void FastProcessBlock(u8* const swizzled_data, u8* const unswizzled_data, const bool unswizzle,
const u32 x_start, const u32 y_start, const u32 z_start, const u32 x_end,
const u32 y_end, const u32 z_end, const u32 tile_offset,
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
u32 z_address = tile_offset;
const u32 x_startb = x_start * bytes_per_pixel;
const u32 x_endb = x_end * bytes_per_pixel;
- const u32 copy_size = 16;
- const u32 gob_size_x = 64;
- const u32 gob_size_y = 8;
- const u32 gob_size_z = 1;
+ constexpr u32 copy_size = 16;
+ constexpr u32 gob_size_x = 64;
+ constexpr u32 gob_size_y = 8;
+ constexpr u32 gob_size_z = 1;
const u32 gob_size = gob_size_x * gob_size_y * gob_size_z;
for (u32 z = z_start; z < z_end; z++) {
u32 y_address = z_address;
@@ -126,23 +126,23 @@ void FastProcessBlock(u8* swizzled_data, u8* unswizzled_data, const bool unswizz
* https://envytools.readthedocs.io/en/latest/hw/memory/g80-surface.html#blocklinear-surfaces
*/
template <bool fast>
-void SwizzledData(u8* swizzled_data, u8* unswizzled_data, const bool unswizzle, const u32 width,
- const u32 height, const u32 depth, const u32 bytes_per_pixel,
+void SwizzledData(u8* const swizzled_data, u8* const unswizzled_data, const bool unswizzle,
+ const u32 width, const u32 height, const u32 depth, const u32 bytes_per_pixel,
const u32 out_bytes_per_pixel, const u32 block_height, const u32 block_depth) {
auto div_ceil = [](const u32 x, const u32 y) { return ((x + y - 1) / y); };
const u32 stride_x = width * out_bytes_per_pixel;
const u32 layer_z = height * stride_x;
- const u32 gob_x_bytes = 64;
+ constexpr u32 gob_x_bytes = 64;
const u32 gob_elements_x = gob_x_bytes / bytes_per_pixel;
- const u32 gob_elements_y = 8;
- const u32 gob_elements_z = 1;
+ constexpr u32 gob_elements_y = 8;
+ constexpr u32 gob_elements_z = 1;
const u32 block_x_elements = gob_elements_x;
const u32 block_y_elements = gob_elements_y * block_height;
const u32 block_z_elements = gob_elements_z * block_depth;
const u32 blocks_on_x = div_ceil(width, block_x_elements);
const u32 blocks_on_y = div_ceil(height, block_y_elements);
const u32 blocks_on_z = div_ceil(depth, block_z_elements);
- const u32 gob_size = gob_x_bytes * gob_elements_y * gob_elements_z;
+ constexpr u32 gob_size = gob_x_bytes * gob_elements_y * gob_elements_z;
const u32 xy_block_size = gob_size * block_height;
const u32 block_size = xy_block_size * block_depth;
u32 tile_offset = 0;
@@ -171,7 +171,7 @@ void SwizzledData(u8* swizzled_data, u8* unswizzled_data, const bool unswizzle,
}
void CopySwizzledData(u32 width, u32 height, u32 depth, u32 bytes_per_pixel,
- u32 out_bytes_per_pixel, u8* swizzled_data, u8* unswizzled_data,
+ u32 out_bytes_per_pixel, u8* const swizzled_data, u8* const unswizzled_data,
bool unswizzle, u32 block_height, u32 block_depth) {
if (bytes_per_pixel % 3 != 0 && (width * bytes_per_pixel) % 16 == 0) {
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
std::size_t CalculateSize(bool tiled, u32 bytes_per_pixel, u32 width, u32 height, u32 depth,
u32 block_height, u32 block_depth) {
if (tiled) {
- const u32 gobs_in_x = 64;
- const u32 gobs_in_y = 8;
- const u32 gobs_in_z = 1;
+ constexpr u32 gobs_in_x = 64;
+ constexpr u32 gobs_in_y = 8;
+ constexpr u32 gobs_in_z = 1;
const u32 aligned_width = Common::AlignUp(width * bytes_per_pixel, gobs_in_x);
const u32 aligned_height = Common::AlignUp(height, gobs_in_y * block_height);
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() {
qt_config->beginGroup("UIGameList");
UISettings::values.show_unknown = qt_config->value("show_unknown", true).toBool();
+ UISettings::values.show_add_ons = qt_config->value("show_add_ons", true).toBool();
UISettings::values.icon_size = qt_config->value("icon_size", 64).toUInt();
UISettings::values.row_1_text_id = qt_config->value("row_1_text_id", 3).toUInt();
UISettings::values.row_2_text_id = qt_config->value("row_2_text_id", 2).toUInt();
@@ -312,6 +313,7 @@ void Config::SaveValues() {
qt_config->beginGroup("UIGameList");
qt_config->setValue("show_unknown", UISettings::values.show_unknown);
+ qt_config->setValue("show_add_ons", UISettings::values.show_add_ons);
qt_config->setValue("icon_size", UISettings::values.icon_size);
qt_config->setValue("row_1_text_id", UISettings::values.row_1_text_id);
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;
void ConfigureGameList::applyConfiguration() {
UISettings::values.show_unknown = ui->show_unknown->isChecked();
+ UISettings::values.show_add_ons = ui->show_add_ons->isChecked();
UISettings::values.icon_size = ui->icon_size_combobox->currentData().toUInt();
UISettings::values.row_1_text_id = ui->row_1_text_combobox->currentData().toUInt();
UISettings::values.row_2_text_id = ui->row_2_text_combobox->currentData().toUInt();
@@ -50,6 +51,7 @@ void ConfigureGameList::applyConfiguration() {
void ConfigureGameList::setConfiguration() {
ui->show_unknown->setChecked(UISettings::values.show_unknown);
+ ui->show_add_ons->setChecked(UISettings::values.show_add_ons);
ui->icon_size_combobox->setCurrentIndex(
ui->icon_size_combobox->findData(UISettings::values.icon_size));
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 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ConfigureGameList</class>
- <widget class="QWidget" name="ConfigureGeneral">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>300</width>
- <height>377</height>
- </rect>
- </property>
- <property name="windowTitle">
- <string>Form</string>
- </property>
- <layout class="QHBoxLayout" name="HorizontalLayout">
- <item>
- <layout class="QVBoxLayout" name="VerticalLayout">
+ <widget class="QWidget" name="ConfigureGameList">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>300</width>
+ <height>377</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Form</string>
+ </property>
+ <layout class="QHBoxLayout" name="HorizontalLayout">
+ <item>
+ <layout class="QVBoxLayout" name="VerticalLayout">
+ <item>
+ <widget class="QGroupBox" name="GeneralGroupBox">
+ <property name="title">
+ <string>General</string>
+ </property>
+ <layout class="QHBoxLayout" name="GeneralHorizontalLayout">
+ <item>
+ <layout class="QVBoxLayout" name="GeneralVerticalLayout">
<item>
- <widget class="QGroupBox" name="GeneralGroupBox">
- <property name="title">
- <string>General</string>
- </property>
- <layout class="QHBoxLayout" name="GeneralHorizontalLayout">
- <item>
- <layout class="QVBoxLayout" name="GeneralVerticalLayout">
- <item>
- <widget class="QCheckBox" name="show_unknown">
- <property name="text">
- <string>Show files with type 'Unknown'</string>
- </property>
- </widget>
- </item>
- </layout>
- </item>
- </layout>
- </widget>
+ <widget class="QCheckBox" name="show_unknown">
+ <property name="text">
+ <string>Show files with type 'Unknown'</string>
+ </property>
+ </widget>
</item>
<item>
- <widget class="QGroupBox" name="IconSizeGroupBox">
- <property name="title">
- <string>Icon Size</string>
- </property>
- <layout class="QHBoxLayout" name="icon_size_qhbox_layout">
- <item>
- <layout class="QVBoxLayout" name="icon_size_qvbox_layout">
- <item>
- <layout class="QHBoxLayout" name="icon_size_qhbox_layout_2">
- <item>
- <widget class="QLabel" name="icon_size_label">
- <property name="text">
- <string>Icon Size:</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QComboBox" name="icon_size_combobox"/>
- </item>
- </layout>
- </item>
- </layout>
- </item>
- </layout>
- </widget>
+ <widget class="QCheckBox" name="show_add_ons">
+ <property name="text">
+ <string>Show Add-Ons Column</string>
+ </property>
+ </widget>
</item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="IconSizeGroupBox">
+ <property name="title">
+ <string>Icon Size</string>
+ </property>
+ <layout class="QHBoxLayout" name="icon_size_qhbox_layout">
+ <item>
+ <layout class="QVBoxLayout" name="icon_size_qvbox_layout">
<item>
- <widget class="QGroupBox" name="RowGroupBox">
- <property name="title">
- <string>Row Text</string>
+ <layout class="QHBoxLayout" name="icon_size_qhbox_layout_2">
+ <item>
+ <widget class="QLabel" name="icon_size_label">
+ <property name="text">
+ <string>Icon Size:</string>
</property>
- <layout class="QHBoxLayout" name="RowHorizontalLayout">
- <item>
- <layout class="QVBoxLayout" name="RowVerticalLayout">
- <item>
- <layout class="QHBoxLayout" name="row_1_qhbox_layout">
- <item>
- <widget class="QLabel" name="row_1_label">
- <property name="text">
- <string>Row 1 Text:</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QComboBox" name="row_1_text_combobox"/>
- </item>
- </layout>
- </item>
- <item>
- <layout class="QHBoxLayout" name="row_2_qhbox_layout">
- <item>
- <widget class="QLabel" name="row_2_label">
- <property name="text">
- <string>Row 2 Text:</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QComboBox" name="row_2_text_combobox"/>
- </item>
- </layout>
- </item>
- </layout>
- </item>
- </layout>
- </widget>
+ </widget>
+ </item>
+ <item>
+ <widget class="QComboBox" name="icon_size_combobox"/>
+ </item>
+ </layout>
</item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="RowGroupBox">
+ <property name="title">
+ <string>Row Text</string>
+ </property>
+ <layout class="QHBoxLayout" name="RowHorizontalLayout">
+ <item>
+ <layout class="QVBoxLayout" name="RowVerticalLayout">
<item>
- <spacer name="verticalSpacer">
- <property name="orientation">
- <enum>Qt::Vertical</enum>
+ <layout class="QHBoxLayout" name="row_1_qhbox_layout">
+ <item>
+ <widget class="QLabel" name="row_1_label">
+ <property name="text">
+ <string>Row 1 Text:</string>
</property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>20</width>
- <height>40</height>
- </size>
+ </widget>
+ </item>
+ <item>
+ <widget class="QComboBox" name="row_1_text_combobox"/>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="row_2_qhbox_layout">
+ <item>
+ <widget class="QLabel" name="row_2_label">
+ <property name="text">
+ <string>Row 2 Text:</string>
</property>
- </spacer>
+ </widget>
+ </item>
+ <item>
+ <widget class="QComboBox" name="row_2_text_combobox"/>
+ </item>
+ </layout>
</item>
- </layout>
- </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
</layout>
- </widget>
+ </item>
+ </layout>
+ </widget>
<resources/>
<connections/>
</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)
tree_view->setUniformRowHeights(true);
tree_view->setContextMenuPolicy(Qt::CustomContextMenu);
- item_model->insertColumns(0, COLUMN_COUNT);
+ item_model->insertColumns(0, UISettings::values.show_add_ons ? COLUMN_COUNT : COLUMN_COUNT - 1);
item_model->setHeaderData(COLUMN_NAME, Qt::Horizontal, tr("Name"));
item_model->setHeaderData(COLUMN_COMPATIBILITY, Qt::Horizontal, tr("Compatibility"));
- item_model->setHeaderData(COLUMN_ADD_ONS, Qt::Horizontal, tr("Add-ons"));
- item_model->setHeaderData(COLUMN_FILE_TYPE, Qt::Horizontal, tr("File type"));
- item_model->setHeaderData(COLUMN_SIZE, Qt::Horizontal, tr("Size"));
+
+ if (UISettings::values.show_add_ons) {
+ item_model->setHeaderData(COLUMN_ADD_ONS, Qt::Horizontal, tr("Add-ons"));
+ item_model->setHeaderData(COLUMN_FILE_TYPE, Qt::Horizontal, tr("File type"));
+ item_model->setHeaderData(COLUMN_SIZE, Qt::Horizontal, tr("Size"));
+ } else {
+ item_model->setHeaderData(COLUMN_FILE_TYPE - 1, Qt::Horizontal, tr("File type"));
+ item_model->setHeaderData(COLUMN_SIZE - 1, Qt::Horizontal, tr("Size"));
+ }
connect(tree_view, &QTreeView::activated, this, &GameList::ValidateEntry);
connect(tree_view, &QTreeView::customContextMenuRequested, this, &GameList::PopupContextMenu);
@@ -394,6 +400,25 @@ void GameList::PopulateAsync(const QString& dir_path, bool deep_scan) {
}
tree_view->setEnabled(false);
+
+ // Update the columns in case UISettings has changed
+ item_model->removeColumns(0, item_model->columnCount());
+ item_model->insertColumns(0, UISettings::values.show_add_ons ? COLUMN_COUNT : COLUMN_COUNT - 1);
+ item_model->setHeaderData(COLUMN_NAME, Qt::Horizontal, tr("Name"));
+ item_model->setHeaderData(COLUMN_COMPATIBILITY, Qt::Horizontal, tr("Compatibility"));
+
+ if (UISettings::values.show_add_ons) {
+ item_model->setHeaderData(COLUMN_ADD_ONS, Qt::Horizontal, tr("Add-ons"));
+ item_model->setHeaderData(COLUMN_FILE_TYPE, Qt::Horizontal, tr("File type"));
+ item_model->setHeaderData(COLUMN_SIZE, Qt::Horizontal, tr("Size"));
+ } else {
+ item_model->setHeaderData(COLUMN_FILE_TYPE - 1, Qt::Horizontal, tr("File type"));
+ item_model->setHeaderData(COLUMN_SIZE - 1, Qt::Horizontal, tr("Size"));
+ item_model->removeColumns(COLUMN_COUNT - 1, 1);
+ }
+
+ LoadInterfaceLayout();
+
// Delete any rows that might already exist if we're repopulating
item_model->removeRows(0, item_model->rowCount());
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() {
if (it != compatibility_list.end())
compatibility = it->second.first;
- emit EntryReady({
+ QList<QStandardItem*> list{
new GameListItemPath(
FormatGameName(file->GetFullPath()), icon, QString::fromStdString(name),
QString::fromStdString(Loader::GetFileTypeString(loader->GetFileType())),
program_id),
new GameListItemCompat(compatibility),
- new GameListItem(FormatPatchNameVersions(patch, *loader)),
new GameListItem(
QString::fromStdString(Loader::GetFileTypeString(loader->GetFileType()))),
new GameListItemSize(file->GetSize()),
- });
+ };
+
+ if (UISettings::values.show_add_ons) {
+ list.insert(2, new GameListItem(FormatPatchNameVersions(patch, *loader)));
+ }
+
+ emit EntryReady(list);
}
const auto control_data = cache->ListEntriesFilter(FileSys::TitleType::Application,
@@ -216,18 +221,23 @@ void GameListWorker::AddFstEntriesToGameList(const std::string& dir_path, unsign
if (it != compatibility_list.end())
compatibility = it->second.first;
- emit EntryReady({
+ QList<QStandardItem*> list{
new GameListItemPath(
FormatGameName(physical_name), icon, QString::fromStdString(name),
QString::fromStdString(Loader::GetFileTypeString(loader->GetFileType())),
program_id),
new GameListItemCompat(compatibility),
new GameListItem(
- FormatPatchNameVersions(patch, *loader, loader->IsRomFSUpdatable())),
- new GameListItem(
QString::fromStdString(Loader::GetFileTypeString(loader->GetFileType()))),
new GameListItemSize(FileUtil::GetSize(physical_name)),
- });
+ };
+
+ if (UISettings::values.show_add_ons) {
+ list.insert(2, new GameListItem(FormatPatchNameVersions(
+ patch, *loader, loader->IsRomFSUpdatable())));
+ }
+
+ emit EntryReady(std::move(list));
} else if (is_dir && recursion > 0) {
watch_list.append(QString::fromStdString(physical_name));
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 {
// Game List
bool show_unknown;
+ bool show_add_ons;
uint32_t icon_size;
uint8_t row_1_text_id;
uint8_t row_2_text_id;