summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic.cpp1
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic.h4
-rw-r--r--src/core/arm/unicorn/arm_unicorn.cpp5
-rw-r--r--src/core/arm/unicorn/arm_unicorn.h4
-rw-r--r--src/core/file_sys/fsmitm_romfsbuild.cpp4
-rw-r--r--src/core/file_sys/nca_metadata.cpp8
-rw-r--r--src/core/file_sys/nca_metadata.h3
-rw-r--r--src/core/file_sys/program_metadata.cpp27
-rw-r--r--src/core/file_sys/program_metadata.h2
-rw-r--r--src/core/file_sys/savedata_factory.cpp8
-rw-r--r--src/core/file_sys/savedata_factory.h11
-rw-r--r--src/core/gdbstub/gdbstub.cpp2
-rw-r--r--src/core/hle/kernel/svc.cpp14
-rw-r--r--src/core/hle/result.h4
-rw-r--r--src/core/hle/service/audio/audin_u.cpp4
-rw-r--r--src/core/hle/service/audio/audrec_u.cpp4
-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.cpp19
-rw-r--r--src/core/hle/service/nvdrv/devices/nvdisp_disp0.h2
-rw-r--r--src/core/hle/service/nvdrv/interface.h2
-rw-r--r--src/core/hle/service/nvdrv/nvmemp.h2
-rw-r--r--src/core/hle/service/service.h2
-rw-r--r--src/core/hle/service/set/set_cal.h2
-rw-r--r--src/core/hle/service/ssl/ssl.cpp1
-rw-r--r--src/core/hle/service/vi/vi.cpp4
-rw-r--r--src/core/loader/xci.h2
-rw-r--r--src/video_core/engines/fermi_2d.cpp3
-rw-r--r--src/video_core/engines/fermi_2d.h8
-rw-r--r--src/video_core/engines/kepler_compute.h10
-rw-r--r--src/video_core/engines/kepler_memory.cpp4
-rw-r--r--src/video_core/engines/kepler_memory.h7
-rw-r--r--src/video_core/engines/maxwell_3d.cpp7
-rw-r--r--src/video_core/engines/maxwell_3d.h8
-rw-r--r--src/video_core/engines/maxwell_dma.cpp4
-rw-r--r--src/video_core/engines/maxwell_dma.h9
-rw-r--r--src/video_core/gpu_thread.cpp2
-rw-r--r--src/video_core/macro_interpreter.cpp20
-rw-r--r--src/video_core/memory_manager.cpp51
-rw-r--r--src/video_core/memory_manager.h9
-rw-r--r--src/video_core/renderer_opengl/gl_shader_decompiler.cpp31
-rw-r--r--src/video_core/renderer_vulkan/vk_buffer_cache.cpp1
-rw-r--r--src/yuzu/debugger/graphics/graphics_surface.cpp206
43 files changed, 316 insertions, 226 deletions
diff --git a/src/core/arm/dynarmic/arm_dynarmic.cpp b/src/core/arm/dynarmic/arm_dynarmic.cpp
index 4fdc12f11..f64e4c6a6 100644
--- a/src/core/arm/dynarmic/arm_dynarmic.cpp
+++ b/src/core/arm/dynarmic/arm_dynarmic.cpp
@@ -26,7 +26,6 @@ using Vector = Dynarmic::A64::Vector;
26class ARM_Dynarmic_Callbacks : public Dynarmic::A64::UserCallbacks { 26class ARM_Dynarmic_Callbacks : public Dynarmic::A64::UserCallbacks {
27public: 27public:
28 explicit ARM_Dynarmic_Callbacks(ARM_Dynarmic& parent) : parent(parent) {} 28 explicit ARM_Dynarmic_Callbacks(ARM_Dynarmic& parent) : parent(parent) {}
29 ~ARM_Dynarmic_Callbacks() = default;
30 29
31 u8 MemoryRead8(u64 vaddr) override { 30 u8 MemoryRead8(u64 vaddr) override {
32 return Memory::Read8(vaddr); 31 return Memory::Read8(vaddr);
diff --git a/src/core/arm/dynarmic/arm_dynarmic.h b/src/core/arm/dynarmic/arm_dynarmic.h
index aada1e862..81e0b4ac0 100644
--- a/src/core/arm/dynarmic/arm_dynarmic.h
+++ b/src/core/arm/dynarmic/arm_dynarmic.h
@@ -29,7 +29,7 @@ class ARM_Dynarmic final : public ARM_Interface {
29public: 29public:
30 ARM_Dynarmic(Timing::CoreTiming& core_timing, ExclusiveMonitor& exclusive_monitor, 30 ARM_Dynarmic(Timing::CoreTiming& core_timing, ExclusiveMonitor& exclusive_monitor,
31 std::size_t core_index); 31 std::size_t core_index);
32 ~ARM_Dynarmic(); 32 ~ARM_Dynarmic() override;
33 33
34 void MapBackingMemory(VAddr address, std::size_t size, u8* memory, 34 void MapBackingMemory(VAddr address, std::size_t size, u8* memory,
35 Kernel::VMAPermission perms) override; 35 Kernel::VMAPermission perms) override;
@@ -76,7 +76,7 @@ private:
76class DynarmicExclusiveMonitor final : public ExclusiveMonitor { 76class DynarmicExclusiveMonitor final : public ExclusiveMonitor {
77public: 77public:
78 explicit DynarmicExclusiveMonitor(std::size_t core_count); 78 explicit DynarmicExclusiveMonitor(std::size_t core_count);
79 ~DynarmicExclusiveMonitor(); 79 ~DynarmicExclusiveMonitor() override;
80 80
81 void SetExclusive(std::size_t core_index, VAddr addr) override; 81 void SetExclusive(std::size_t core_index, VAddr addr) override;
82 void ClearExclusive() override; 82 void ClearExclusive() override;
diff --git a/src/core/arm/unicorn/arm_unicorn.cpp b/src/core/arm/unicorn/arm_unicorn.cpp
index a542a098b..27309280c 100644
--- a/src/core/arm/unicorn/arm_unicorn.cpp
+++ b/src/core/arm/unicorn/arm_unicorn.cpp
@@ -192,12 +192,13 @@ void ARM_Unicorn::ExecuteInstructions(int num_instructions) {
192 CHECKED(uc_emu_start(uc, GetPC(), 1ULL << 63, 0, num_instructions)); 192 CHECKED(uc_emu_start(uc, GetPC(), 1ULL << 63, 0, num_instructions));
193 core_timing.AddTicks(num_instructions); 193 core_timing.AddTicks(num_instructions);
194 if (GDBStub::IsServerEnabled()) { 194 if (GDBStub::IsServerEnabled()) {
195 if (last_bkpt_hit) { 195 if (last_bkpt_hit && last_bkpt.type == GDBStub::BreakpointType::Execute) {
196 uc_reg_write(uc, UC_ARM64_REG_PC, &last_bkpt.address); 196 uc_reg_write(uc, UC_ARM64_REG_PC, &last_bkpt.address);
197 } 197 }
198
198 Kernel::Thread* thread = Kernel::GetCurrentThread(); 199 Kernel::Thread* thread = Kernel::GetCurrentThread();
199 SaveContext(thread->GetContext()); 200 SaveContext(thread->GetContext());
200 if (last_bkpt_hit || GDBStub::GetCpuStepFlag()) { 201 if (last_bkpt_hit || GDBStub::IsMemoryBreak() || GDBStub::GetCpuStepFlag()) {
201 last_bkpt_hit = false; 202 last_bkpt_hit = false;
202 GDBStub::Break(); 203 GDBStub::Break();
203 GDBStub::SendTrap(thread, 5); 204 GDBStub::SendTrap(thread, 5);
diff --git a/src/core/arm/unicorn/arm_unicorn.h b/src/core/arm/unicorn/arm_unicorn.h
index dbd6955ea..1e44f0736 100644
--- a/src/core/arm/unicorn/arm_unicorn.h
+++ b/src/core/arm/unicorn/arm_unicorn.h
@@ -18,7 +18,7 @@ namespace Core {
18class ARM_Unicorn final : public ARM_Interface { 18class ARM_Unicorn final : public ARM_Interface {
19public: 19public:
20 explicit ARM_Unicorn(Timing::CoreTiming& core_timing); 20 explicit ARM_Unicorn(Timing::CoreTiming& core_timing);
21 ~ARM_Unicorn(); 21 ~ARM_Unicorn() override;
22 22
23 void MapBackingMemory(VAddr address, std::size_t size, u8* memory, 23 void MapBackingMemory(VAddr address, std::size_t size, u8* memory,
24 Kernel::VMAPermission perms) override; 24 Kernel::VMAPermission perms) override;
@@ -50,7 +50,7 @@ private:
50 uc_engine* uc{}; 50 uc_engine* uc{};
51 Timing::CoreTiming& core_timing; 51 Timing::CoreTiming& core_timing;
52 GDBStub::BreakpointAddress last_bkpt{}; 52 GDBStub::BreakpointAddress last_bkpt{};
53 bool last_bkpt_hit; 53 bool last_bkpt_hit = false;
54}; 54};
55 55
56} // namespace Core 56} // namespace Core
diff --git a/src/core/file_sys/fsmitm_romfsbuild.cpp b/src/core/file_sys/fsmitm_romfsbuild.cpp
index 47b7526c7..d126ae8dd 100644
--- a/src/core/file_sys/fsmitm_romfsbuild.cpp
+++ b/src/core/file_sys/fsmitm_romfsbuild.cpp
@@ -23,6 +23,7 @@
23 */ 23 */
24 24
25#include <cstring> 25#include <cstring>
26#include <string_view>
26#include "common/alignment.h" 27#include "common/alignment.h"
27#include "common/assert.h" 28#include "common/assert.h"
28#include "core/file_sys/fsmitm_romfsbuild.h" 29#include "core/file_sys/fsmitm_romfsbuild.h"
@@ -97,7 +98,8 @@ struct RomFSBuildFileContext {
97 VirtualFile source; 98 VirtualFile source;
98}; 99};
99 100
100static u32 romfs_calc_path_hash(u32 parent, std::string path, u32 start, std::size_t path_len) { 101static u32 romfs_calc_path_hash(u32 parent, std::string_view path, u32 start,
102 std::size_t path_len) {
101 u32 hash = parent ^ 123456789; 103 u32 hash = parent ^ 123456789;
102 for (u32 i = 0; i < path_len; i++) { 104 for (u32 i = 0; i < path_len; i++) {
103 hash = (hash >> 5) | (hash << 27); 105 hash = (hash >> 5) | (hash << 27);
diff --git a/src/core/file_sys/nca_metadata.cpp b/src/core/file_sys/nca_metadata.cpp
index 6f34b7836..93d0df6b9 100644
--- a/src/core/file_sys/nca_metadata.cpp
+++ b/src/core/file_sys/nca_metadata.cpp
@@ -10,14 +10,6 @@
10 10
11namespace FileSys { 11namespace FileSys {
12 12
13bool operator>=(TitleType lhs, TitleType rhs) {
14 return static_cast<std::size_t>(lhs) >= static_cast<std::size_t>(rhs);
15}
16
17bool operator<=(TitleType lhs, TitleType rhs) {
18 return static_cast<std::size_t>(lhs) <= static_cast<std::size_t>(rhs);
19}
20
21CNMT::CNMT(VirtualFile file) { 13CNMT::CNMT(VirtualFile file) {
22 if (file->ReadObject(&header) != sizeof(CNMTHeader)) 14 if (file->ReadObject(&header) != sizeof(CNMTHeader))
23 return; 15 return;
diff --git a/src/core/file_sys/nca_metadata.h b/src/core/file_sys/nca_metadata.h
index a05d155f4..50bf38471 100644
--- a/src/core/file_sys/nca_metadata.h
+++ b/src/core/file_sys/nca_metadata.h
@@ -29,9 +29,6 @@ enum class TitleType : u8 {
29 DeltaTitle = 0x83, 29 DeltaTitle = 0x83,
30}; 30};
31 31
32bool operator>=(TitleType lhs, TitleType rhs);
33bool operator<=(TitleType lhs, TitleType rhs);
34
35enum class ContentRecordType : u8 { 32enum class ContentRecordType : u8 {
36 Meta = 0, 33 Meta = 0,
37 Program = 1, 34 Program = 1,
diff --git a/src/core/file_sys/program_metadata.cpp b/src/core/file_sys/program_metadata.cpp
index d3e00437f..d863253f8 100644
--- a/src/core/file_sys/program_metadata.cpp
+++ b/src/core/file_sys/program_metadata.cpp
@@ -3,7 +3,6 @@
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <cstddef> 5#include <cstddef>
6#include <cstring>
7#include <vector> 6#include <vector>
8 7
9#include "common/logging/log.h" 8#include "common/logging/log.h"
@@ -17,28 +16,30 @@ ProgramMetadata::ProgramMetadata() = default;
17ProgramMetadata::~ProgramMetadata() = default; 16ProgramMetadata::~ProgramMetadata() = default;
18 17
19Loader::ResultStatus ProgramMetadata::Load(VirtualFile file) { 18Loader::ResultStatus ProgramMetadata::Load(VirtualFile file) {
20 std::size_t total_size = static_cast<std::size_t>(file->GetSize()); 19 const std::size_t total_size = file->GetSize();
21 if (total_size < sizeof(Header)) 20 if (total_size < sizeof(Header)) {
22 return Loader::ResultStatus::ErrorBadNPDMHeader; 21 return Loader::ResultStatus::ErrorBadNPDMHeader;
22 }
23 23
24 // TODO(DarkLordZach): Use ReadObject when Header/AcidHeader becomes trivially copyable. 24 if (sizeof(Header) != file->ReadObject(&npdm_header)) {
25 std::vector<u8> npdm_header_data = file->ReadBytes(sizeof(Header));
26 if (sizeof(Header) != npdm_header_data.size())
27 return Loader::ResultStatus::ErrorBadNPDMHeader; 25 return Loader::ResultStatus::ErrorBadNPDMHeader;
28 std::memcpy(&npdm_header, npdm_header_data.data(), sizeof(Header)); 26 }
29 27
30 std::vector<u8> acid_header_data = file->ReadBytes(sizeof(AcidHeader), npdm_header.acid_offset); 28 if (sizeof(AcidHeader) != file->ReadObject(&acid_header, npdm_header.acid_offset)) {
31 if (sizeof(AcidHeader) != acid_header_data.size())
32 return Loader::ResultStatus::ErrorBadACIDHeader; 29 return Loader::ResultStatus::ErrorBadACIDHeader;
33 std::memcpy(&acid_header, acid_header_data.data(), sizeof(AcidHeader)); 30 }
34 31
35 if (sizeof(AciHeader) != file->ReadObject(&aci_header, npdm_header.aci_offset)) 32 if (sizeof(AciHeader) != file->ReadObject(&aci_header, npdm_header.aci_offset)) {
36 return Loader::ResultStatus::ErrorBadACIHeader; 33 return Loader::ResultStatus::ErrorBadACIHeader;
34 }
37 35
38 if (sizeof(FileAccessControl) != file->ReadObject(&acid_file_access, acid_header.fac_offset)) 36 if (sizeof(FileAccessControl) != file->ReadObject(&acid_file_access, acid_header.fac_offset)) {
39 return Loader::ResultStatus::ErrorBadFileAccessControl; 37 return Loader::ResultStatus::ErrorBadFileAccessControl;
40 if (sizeof(FileAccessHeader) != file->ReadObject(&aci_file_access, aci_header.fah_offset)) 38 }
39
40 if (sizeof(FileAccessHeader) != file->ReadObject(&aci_file_access, aci_header.fah_offset)) {
41 return Loader::ResultStatus::ErrorBadFileAccessHeader; 41 return Loader::ResultStatus::ErrorBadFileAccessHeader;
42 }
42 43
43 aci_kernel_capabilities.resize(aci_header.kac_size / sizeof(u32)); 44 aci_kernel_capabilities.resize(aci_header.kac_size / sizeof(u32));
44 const u64 read_size = aci_header.kac_size; 45 const u64 read_size = aci_header.kac_size;
diff --git a/src/core/file_sys/program_metadata.h b/src/core/file_sys/program_metadata.h
index 0033ba347..7de5b9cf9 100644
--- a/src/core/file_sys/program_metadata.h
+++ b/src/core/file_sys/program_metadata.h
@@ -58,7 +58,6 @@ public:
58 void Print() const; 58 void Print() const;
59 59
60private: 60private:
61 // TODO(DarkLordZach): BitField is not trivially copyable.
62 struct Header { 61 struct Header {
63 std::array<char, 4> magic; 62 std::array<char, 4> magic;
64 std::array<u8, 8> reserved; 63 std::array<u8, 8> reserved;
@@ -85,7 +84,6 @@ private:
85 84
86 static_assert(sizeof(Header) == 0x80, "NPDM header structure size is wrong"); 85 static_assert(sizeof(Header) == 0x80, "NPDM header structure size is wrong");
87 86
88 // TODO(DarkLordZach): BitField is not trivially copyable.
89 struct AcidHeader { 87 struct AcidHeader {
90 std::array<u8, 0x100> signature; 88 std::array<u8, 0x100> signature;
91 std::array<u8, 0x100> nca_modulus; 89 std::array<u8, 0x100> nca_modulus;
diff --git a/src/core/file_sys/savedata_factory.cpp b/src/core/file_sys/savedata_factory.cpp
index 1913dc956..7974b031d 100644
--- a/src/core/file_sys/savedata_factory.cpp
+++ b/src/core/file_sys/savedata_factory.cpp
@@ -16,8 +16,10 @@ namespace FileSys {
16constexpr char SAVE_DATA_SIZE_FILENAME[] = ".yuzu_save_size"; 16constexpr char SAVE_DATA_SIZE_FILENAME[] = ".yuzu_save_size";
17 17
18std::string SaveDataDescriptor::DebugInfo() const { 18std::string SaveDataDescriptor::DebugInfo() const {
19 return fmt::format("[type={:02X}, title_id={:016X}, user_id={:016X}{:016X}, save_id={:016X}]", 19 return fmt::format("[type={:02X}, title_id={:016X}, user_id={:016X}{:016X}, save_id={:016X}, "
20 static_cast<u8>(type), title_id, user_id[1], user_id[0], save_id); 20 "rank={}, index={}]",
21 static_cast<u8>(type), title_id, user_id[1], user_id[0], save_id,
22 static_cast<u8>(rank), index);
21} 23}
22 24
23SaveDataFactory::SaveDataFactory(VirtualDir save_directory) : dir(std::move(save_directory)) { 25SaveDataFactory::SaveDataFactory(VirtualDir save_directory) : dir(std::move(save_directory)) {
@@ -28,7 +30,7 @@ SaveDataFactory::SaveDataFactory(VirtualDir save_directory) : dir(std::move(save
28 30
29SaveDataFactory::~SaveDataFactory() = default; 31SaveDataFactory::~SaveDataFactory() = default;
30 32
31ResultVal<VirtualDir> SaveDataFactory::Open(SaveDataSpaceId space, SaveDataDescriptor meta) { 33ResultVal<VirtualDir> SaveDataFactory::Open(SaveDataSpaceId space, const SaveDataDescriptor& meta) {
32 if (meta.type == SaveDataType::SystemSaveData || meta.type == SaveDataType::SaveData) { 34 if (meta.type == SaveDataType::SystemSaveData || meta.type == SaveDataType::SaveData) {
33 if (meta.zero_1 != 0) { 35 if (meta.zero_1 != 0) {
34 LOG_WARNING(Service_FS, 36 LOG_WARNING(Service_FS,
diff --git a/src/core/file_sys/savedata_factory.h b/src/core/file_sys/savedata_factory.h
index 3a1caf292..b73654571 100644
--- a/src/core/file_sys/savedata_factory.h
+++ b/src/core/file_sys/savedata_factory.h
@@ -32,12 +32,19 @@ enum class SaveDataType : u8 {
32 CacheStorage = 5, 32 CacheStorage = 5,
33}; 33};
34 34
35enum class SaveDataRank : u8 {
36 Primary,
37 Secondary,
38};
39
35struct SaveDataDescriptor { 40struct SaveDataDescriptor {
36 u64_le title_id; 41 u64_le title_id;
37 u128 user_id; 42 u128 user_id;
38 u64_le save_id; 43 u64_le save_id;
39 SaveDataType type; 44 SaveDataType type;
40 INSERT_PADDING_BYTES(7); 45 SaveDataRank rank;
46 u16_le index;
47 INSERT_PADDING_BYTES(4);
41 u64_le zero_1; 48 u64_le zero_1;
42 u64_le zero_2; 49 u64_le zero_2;
43 u64_le zero_3; 50 u64_le zero_3;
@@ -57,7 +64,7 @@ public:
57 explicit SaveDataFactory(VirtualDir dir); 64 explicit SaveDataFactory(VirtualDir dir);
58 ~SaveDataFactory(); 65 ~SaveDataFactory();
59 66
60 ResultVal<VirtualDir> Open(SaveDataSpaceId space, SaveDataDescriptor meta); 67 ResultVal<VirtualDir> Open(SaveDataSpaceId space, const SaveDataDescriptor& meta);
61 68
62 VirtualDir GetSaveDataSpaceDirectory(SaveDataSpaceId space) const; 69 VirtualDir GetSaveDataSpaceDirectory(SaveDataSpaceId space) const;
63 70
diff --git a/src/core/gdbstub/gdbstub.cpp b/src/core/gdbstub/gdbstub.cpp
index dafb32aae..afa812598 100644
--- a/src/core/gdbstub/gdbstub.cpp
+++ b/src/core/gdbstub/gdbstub.cpp
@@ -1030,7 +1030,7 @@ static void Step() {
1030 1030
1031/// Tell the CPU if we hit a memory breakpoint. 1031/// Tell the CPU if we hit a memory breakpoint.
1032bool IsMemoryBreak() { 1032bool IsMemoryBreak() {
1033 if (IsConnected()) { 1033 if (!IsConnected()) {
1034 return false; 1034 return false;
1035 } 1035 }
1036 1036
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index ab10db3df..2fd07ab34 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -1339,6 +1339,20 @@ static ResultCode WaitProcessWideKeyAtomic(VAddr mutex_addr, VAddr condition_var
1339 "called mutex_addr={:X}, condition_variable_addr={:X}, thread_handle=0x{:08X}, timeout={}", 1339 "called mutex_addr={:X}, condition_variable_addr={:X}, thread_handle=0x{:08X}, timeout={}",
1340 mutex_addr, condition_variable_addr, thread_handle, nano_seconds); 1340 mutex_addr, condition_variable_addr, thread_handle, nano_seconds);
1341 1341
1342 if (Memory::IsKernelVirtualAddress(mutex_addr)) {
1343 LOG_ERROR(
1344 Kernel_SVC,
1345 "Given mutex address must not be within the kernel address space. address=0x{:016X}",
1346 mutex_addr);
1347 return ERR_INVALID_ADDRESS_STATE;
1348 }
1349
1350 if (!Common::IsWordAligned(mutex_addr)) {
1351 LOG_ERROR(Kernel_SVC, "Given mutex address must be word-aligned. address=0x{:016X}",
1352 mutex_addr);
1353 return ERR_INVALID_ADDRESS;
1354 }
1355
1342 auto* const current_process = Core::System::GetInstance().Kernel().CurrentProcess(); 1356 auto* const current_process = Core::System::GetInstance().Kernel().CurrentProcess();
1343 const auto& handle_table = current_process->GetHandleTable(); 1357 const auto& handle_table = current_process->GetHandleTable();
1344 SharedPtr<Thread> thread = handle_table.Get<Thread>(thread_handle); 1358 SharedPtr<Thread> thread = handle_table.Get<Thread>(thread_handle);
diff --git a/src/core/hle/result.h b/src/core/hle/result.h
index ab84f5ddc..8a3701151 100644
--- a/src/core/hle/result.h
+++ b/src/core/hle/result.h
@@ -119,10 +119,6 @@ union ResultCode {
119 BitField<0, 9, ErrorModule> module; 119 BitField<0, 9, ErrorModule> module;
120 BitField<9, 13, u32> description; 120 BitField<9, 13, u32> description;
121 121
122 // The last bit of `level` is checked by apps and the kernel to determine if a result code is an
123 // error
124 BitField<31, 1, u32> is_error;
125
126 constexpr explicit ResultCode(u32 raw) : raw(raw) {} 122 constexpr explicit ResultCode(u32 raw) : raw(raw) {}
127 123
128 constexpr ResultCode(ErrorModule module_, u32 description_) 124 constexpr ResultCode(ErrorModule module_, u32 description_)
diff --git a/src/core/hle/service/audio/audin_u.cpp b/src/core/hle/service/audio/audin_u.cpp
index 088410564..e5daefdde 100644
--- a/src/core/hle/service/audio/audin_u.cpp
+++ b/src/core/hle/service/audio/audin_u.cpp
@@ -2,9 +2,6 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "common/logging/log.h"
6#include "core/hle/ipc_helpers.h"
7#include "core/hle/kernel/hle_ipc.h"
8#include "core/hle/service/audio/audin_u.h" 5#include "core/hle/service/audio/audin_u.h"
9 6
10namespace Service::Audio { 7namespace Service::Audio {
@@ -33,7 +30,6 @@ public:
33 30
34 RegisterHandlers(functions); 31 RegisterHandlers(functions);
35 } 32 }
36 ~IAudioIn() = default;
37}; 33};
38 34
39AudInU::AudInU() : ServiceFramework("audin:u") { 35AudInU::AudInU() : ServiceFramework("audin:u") {
diff --git a/src/core/hle/service/audio/audrec_u.cpp b/src/core/hle/service/audio/audrec_u.cpp
index 6956a2e64..1a5aed9ed 100644
--- a/src/core/hle/service/audio/audrec_u.cpp
+++ b/src/core/hle/service/audio/audrec_u.cpp
@@ -2,9 +2,6 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "common/logging/log.h"
6#include "core/hle/ipc_helpers.h"
7#include "core/hle/kernel/hle_ipc.h"
8#include "core/hle/service/audio/audrec_u.h" 5#include "core/hle/service/audio/audrec_u.h"
9 6
10namespace Service::Audio { 7namespace Service::Audio {
@@ -30,7 +27,6 @@ public:
30 27
31 RegisterHandlers(functions); 28 RegisterHandlers(functions);
32 } 29 }
33 ~IFinalOutputRecorder() = default;
34}; 30};
35 31
36AudRecU::AudRecU() : ServiceFramework("audrec:u") { 32AudRecU::AudRecU() : ServiceFramework("audrec:u") {
diff --git a/src/core/hle/service/filesystem/filesystem.cpp b/src/core/hle/service/filesystem/filesystem.cpp
index c6da2df43..4c2b371c3 100644
--- a/src/core/hle/service/filesystem/filesystem.cpp
+++ b/src/core/hle/service/filesystem/filesystem.cpp
@@ -197,13 +197,16 @@ ResultCode VfsDirectoryServiceWrapper::RenameDirectory(const std::string& src_pa
197 197
198ResultVal<FileSys::VirtualFile> VfsDirectoryServiceWrapper::OpenFile(const std::string& path_, 198ResultVal<FileSys::VirtualFile> VfsDirectoryServiceWrapper::OpenFile(const std::string& path_,
199 FileSys::Mode mode) const { 199 FileSys::Mode mode) const {
200 std::string path(FileUtil::SanitizePath(path_)); 200 const std::string path(FileUtil::SanitizePath(path_));
201 auto npath = path; 201 std::string_view npath = path;
202 while (npath.size() > 0 && (npath[0] == '/' || npath[0] == '\\')) 202 while (!npath.empty() && (npath[0] == '/' || npath[0] == '\\')) {
203 npath = npath.substr(1); 203 npath.remove_prefix(1);
204 }
205
204 auto file = backing->GetFileRelative(npath); 206 auto file = backing->GetFileRelative(npath);
205 if (file == nullptr) 207 if (file == nullptr) {
206 return FileSys::ERROR_PATH_NOT_FOUND; 208 return FileSys::ERROR_PATH_NOT_FOUND;
209 }
207 210
208 if (mode == FileSys::Mode::Append) { 211 if (mode == FileSys::Mode::Append) {
209 return MakeResult<FileSys::VirtualFile>( 212 return MakeResult<FileSys::VirtualFile>(
@@ -319,15 +322,15 @@ ResultVal<FileSys::VirtualFile> OpenRomFS(u64 title_id, FileSys::StorageId stora
319} 322}
320 323
321ResultVal<FileSys::VirtualDir> OpenSaveData(FileSys::SaveDataSpaceId space, 324ResultVal<FileSys::VirtualDir> OpenSaveData(FileSys::SaveDataSpaceId space,
322 FileSys::SaveDataDescriptor save_struct) { 325 const FileSys::SaveDataDescriptor& descriptor) {
323 LOG_TRACE(Service_FS, "Opening Save Data for space_id={:01X}, save_struct={}", 326 LOG_TRACE(Service_FS, "Opening Save Data for space_id={:01X}, save_struct={}",
324 static_cast<u8>(space), save_struct.DebugInfo()); 327 static_cast<u8>(space), descriptor.DebugInfo());
325 328
326 if (save_data_factory == nullptr) { 329 if (save_data_factory == nullptr) {
327 return FileSys::ERROR_ENTITY_NOT_FOUND; 330 return FileSys::ERROR_ENTITY_NOT_FOUND;
328 } 331 }
329 332
330 return save_data_factory->Open(space, save_struct); 333 return save_data_factory->Open(space, descriptor);
331} 334}
332 335
333ResultVal<FileSys::VirtualDir> OpenSaveDataSpace(FileSys::SaveDataSpaceId space) { 336ResultVal<FileSys::VirtualDir> OpenSaveDataSpace(FileSys::SaveDataSpaceId space) {
diff --git a/src/core/hle/service/filesystem/filesystem.h b/src/core/hle/service/filesystem/filesystem.h
index 6fd5e7b23..7cfc0d902 100644
--- a/src/core/hle/service/filesystem/filesystem.h
+++ b/src/core/hle/service/filesystem/filesystem.h
@@ -46,7 +46,7 @@ ResultVal<FileSys::VirtualFile> OpenRomFSCurrentProcess();
46ResultVal<FileSys::VirtualFile> OpenRomFS(u64 title_id, FileSys::StorageId storage_id, 46ResultVal<FileSys::VirtualFile> OpenRomFS(u64 title_id, FileSys::StorageId storage_id,
47 FileSys::ContentRecordType type); 47 FileSys::ContentRecordType type);
48ResultVal<FileSys::VirtualDir> OpenSaveData(FileSys::SaveDataSpaceId space, 48ResultVal<FileSys::VirtualDir> OpenSaveData(FileSys::SaveDataSpaceId space,
49 FileSys::SaveDataDescriptor save_struct); 49 const FileSys::SaveDataDescriptor& descriptor);
50ResultVal<FileSys::VirtualDir> OpenSaveDataSpace(FileSys::SaveDataSpaceId space); 50ResultVal<FileSys::VirtualDir> OpenSaveDataSpace(FileSys::SaveDataSpaceId space);
51ResultVal<FileSys::VirtualDir> OpenSDMC(); 51ResultVal<FileSys::VirtualDir> OpenSDMC();
52 52
diff --git a/src/core/hle/service/filesystem/fsp_srv.cpp b/src/core/hle/service/filesystem/fsp_srv.cpp
index 592dce31a..657baddb8 100644
--- a/src/core/hle/service/filesystem/fsp_srv.cpp
+++ b/src/core/hle/service/filesystem/fsp_srv.cpp
@@ -604,7 +604,9 @@ private:
604 u64_le save_id; 604 u64_le save_id;
605 u64_le title_id; 605 u64_le title_id;
606 u64_le save_image_size; 606 u64_le save_image_size;
607 INSERT_PADDING_BYTES(0x28); 607 u16_le index;
608 FileSys::SaveDataRank rank;
609 INSERT_PADDING_BYTES(0x25);
608 }; 610 };
609 static_assert(sizeof(SaveDataInfo) == 0x60, "SaveDataInfo has incorrect size."); 611 static_assert(sizeof(SaveDataInfo) == 0x60, "SaveDataInfo has incorrect size.");
610 612
@@ -767,16 +769,17 @@ void FSP_SRV::CreateSaveDataFileSystem(Kernel::HLERequestContext& ctx) {
767} 769}
768 770
769void FSP_SRV::OpenSaveDataFileSystem(Kernel::HLERequestContext& ctx) { 771void FSP_SRV::OpenSaveDataFileSystem(Kernel::HLERequestContext& ctx) {
770 IPC::RequestParser rp{ctx}; 772 LOG_INFO(Service_FS, "called.");
771
772 auto space_id = rp.PopRaw<FileSys::SaveDataSpaceId>();
773 auto unk = rp.Pop<u32>();
774 LOG_INFO(Service_FS, "called with unknown={:08X}", unk);
775 773
776 auto save_struct = rp.PopRaw<FileSys::SaveDataDescriptor>(); 774 struct Parameters {
775 FileSys::SaveDataSpaceId save_data_space_id;
776 FileSys::SaveDataDescriptor descriptor;
777 };
777 778
778 auto dir = OpenSaveData(space_id, save_struct); 779 IPC::RequestParser rp{ctx};
780 const auto parameters = rp.PopRaw<Parameters>();
779 781
782 auto dir = OpenSaveData(parameters.save_data_space_id, parameters.descriptor);
780 if (dir.Failed()) { 783 if (dir.Failed()) {
781 IPC::ResponseBuilder rb{ctx, 2, 0, 0}; 784 IPC::ResponseBuilder rb{ctx, 2, 0, 0};
782 rb.Push(FileSys::ERROR_ENTITY_NOT_FOUND); 785 rb.Push(FileSys::ERROR_ENTITY_NOT_FOUND);
diff --git a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.h b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.h
index ace71169f..12f3ef825 100644
--- a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.h
+++ b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.h
@@ -18,7 +18,7 @@ class nvmap;
18class nvdisp_disp0 final : public nvdevice { 18class nvdisp_disp0 final : public nvdevice {
19public: 19public:
20 explicit nvdisp_disp0(std::shared_ptr<nvmap> nvmap_dev); 20 explicit nvdisp_disp0(std::shared_ptr<nvmap> nvmap_dev);
21 ~nvdisp_disp0(); 21 ~nvdisp_disp0() override;
22 22
23 u32 ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) override; 23 u32 ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) override;
24 24
diff --git a/src/core/hle/service/nvdrv/interface.h b/src/core/hle/service/nvdrv/interface.h
index fe311b069..5b4889910 100644
--- a/src/core/hle/service/nvdrv/interface.h
+++ b/src/core/hle/service/nvdrv/interface.h
@@ -17,7 +17,7 @@ namespace Service::Nvidia {
17class NVDRV final : public ServiceFramework<NVDRV> { 17class NVDRV final : public ServiceFramework<NVDRV> {
18public: 18public:
19 NVDRV(std::shared_ptr<Module> nvdrv, const char* name); 19 NVDRV(std::shared_ptr<Module> nvdrv, const char* name);
20 ~NVDRV(); 20 ~NVDRV() override;
21 21
22private: 22private:
23 void Open(Kernel::HLERequestContext& ctx); 23 void Open(Kernel::HLERequestContext& ctx);
diff --git a/src/core/hle/service/nvdrv/nvmemp.h b/src/core/hle/service/nvdrv/nvmemp.h
index 5a4dfc1f9..6eafb1346 100644
--- a/src/core/hle/service/nvdrv/nvmemp.h
+++ b/src/core/hle/service/nvdrv/nvmemp.h
@@ -11,7 +11,7 @@ namespace Service::Nvidia {
11class NVMEMP final : public ServiceFramework<NVMEMP> { 11class NVMEMP final : public ServiceFramework<NVMEMP> {
12public: 12public:
13 NVMEMP(); 13 NVMEMP();
14 ~NVMEMP(); 14 ~NVMEMP() override;
15 15
16private: 16private:
17 void Cmd0(Kernel::HLERequestContext& ctx); 17 void Cmd0(Kernel::HLERequestContext& ctx);
diff --git a/src/core/hle/service/service.h b/src/core/hle/service/service.h
index 830790269..abbfe5524 100644
--- a/src/core/hle/service/service.h
+++ b/src/core/hle/service/service.h
@@ -90,7 +90,7 @@ private:
90 Kernel::HLERequestContext& ctx); 90 Kernel::HLERequestContext& ctx);
91 91
92 ServiceFrameworkBase(const char* service_name, u32 max_sessions, InvokerFn* handler_invoker); 92 ServiceFrameworkBase(const char* service_name, u32 max_sessions, InvokerFn* handler_invoker);
93 ~ServiceFrameworkBase(); 93 ~ServiceFrameworkBase() override;
94 94
95 void RegisterHandlersBase(const FunctionInfoBase* functions, std::size_t n); 95 void RegisterHandlersBase(const FunctionInfoBase* functions, std::size_t n);
96 void ReportUnimplementedFunction(Kernel::HLERequestContext& ctx, const FunctionInfoBase* info); 96 void ReportUnimplementedFunction(Kernel::HLERequestContext& ctx, const FunctionInfoBase* info);
diff --git a/src/core/hle/service/set/set_cal.h b/src/core/hle/service/set/set_cal.h
index 583036eac..a0677e815 100644
--- a/src/core/hle/service/set/set_cal.h
+++ b/src/core/hle/service/set/set_cal.h
@@ -11,7 +11,7 @@ namespace Service::Set {
11class SET_CAL final : public ServiceFramework<SET_CAL> { 11class SET_CAL final : public ServiceFramework<SET_CAL> {
12public: 12public:
13 explicit SET_CAL(); 13 explicit SET_CAL();
14 ~SET_CAL(); 14 ~SET_CAL() override;
15}; 15};
16 16
17} // namespace Service::Set 17} // namespace Service::Set
diff --git a/src/core/hle/service/ssl/ssl.cpp b/src/core/hle/service/ssl/ssl.cpp
index f671f355e..f7f87a958 100644
--- a/src/core/hle/service/ssl/ssl.cpp
+++ b/src/core/hle/service/ssl/ssl.cpp
@@ -64,7 +64,6 @@ public:
64 }; 64 };
65 RegisterHandlers(functions); 65 RegisterHandlers(functions);
66 } 66 }
67 ~ISslContext() = default;
68 67
69private: 68private:
70 void SetOption(Kernel::HLERequestContext& ctx) { 69 void SetOption(Kernel::HLERequestContext& ctx) {
diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp
index b77cb495d..4e17249a9 100644
--- a/src/core/hle/service/vi/vi.cpp
+++ b/src/core/hle/service/vi/vi.cpp
@@ -498,7 +498,6 @@ public:
498 }; 498 };
499 RegisterHandlers(functions); 499 RegisterHandlers(functions);
500 } 500 }
501 ~IHOSBinderDriver() = default;
502 501
503private: 502private:
504 enum class TransactionId { 503 enum class TransactionId {
@@ -692,7 +691,6 @@ public:
692 }; 691 };
693 RegisterHandlers(functions); 692 RegisterHandlers(functions);
694 } 693 }
695 ~ISystemDisplayService() = default;
696 694
697private: 695private:
698 void SetLayerZ(Kernel::HLERequestContext& ctx) { 696 void SetLayerZ(Kernel::HLERequestContext& ctx) {
@@ -818,7 +816,6 @@ public:
818 }; 816 };
819 RegisterHandlers(functions); 817 RegisterHandlers(functions);
820 } 818 }
821 ~IManagerDisplayService() = default;
822 819
823private: 820private:
824 void CloseDisplay(Kernel::HLERequestContext& ctx) { 821 void CloseDisplay(Kernel::HLERequestContext& ctx) {
@@ -884,7 +881,6 @@ private:
884class IApplicationDisplayService final : public ServiceFramework<IApplicationDisplayService> { 881class IApplicationDisplayService final : public ServiceFramework<IApplicationDisplayService> {
885public: 882public:
886 explicit IApplicationDisplayService(std::shared_ptr<NVFlinger::NVFlinger> nv_flinger); 883 explicit IApplicationDisplayService(std::shared_ptr<NVFlinger::NVFlinger> nv_flinger);
887 ~IApplicationDisplayService() = default;
888 884
889private: 885private:
890 enum class ConvertedScaleMode : u64 { 886 enum class ConvertedScaleMode : u64 {
diff --git a/src/core/loader/xci.h b/src/core/loader/xci.h
index d6995b61e..436f7387c 100644
--- a/src/core/loader/xci.h
+++ b/src/core/loader/xci.h
@@ -22,7 +22,7 @@ class AppLoader_NCA;
22class AppLoader_XCI final : public AppLoader { 22class AppLoader_XCI final : public AppLoader {
23public: 23public:
24 explicit AppLoader_XCI(FileSys::VirtualFile file); 24 explicit AppLoader_XCI(FileSys::VirtualFile file);
25 ~AppLoader_XCI(); 25 ~AppLoader_XCI() override;
26 26
27 /** 27 /**
28 * Returns the type of the file 28 * Returns the type of the file
diff --git a/src/video_core/engines/fermi_2d.cpp b/src/video_core/engines/fermi_2d.cpp
index 03b7ee5d8..55966eef1 100644
--- a/src/video_core/engines/fermi_2d.cpp
+++ b/src/video_core/engines/fermi_2d.cpp
@@ -6,12 +6,13 @@
6#include "common/logging/log.h" 6#include "common/logging/log.h"
7#include "common/math_util.h" 7#include "common/math_util.h"
8#include "video_core/engines/fermi_2d.h" 8#include "video_core/engines/fermi_2d.h"
9#include "video_core/memory_manager.h"
9#include "video_core/rasterizer_interface.h" 10#include "video_core/rasterizer_interface.h"
10 11
11namespace Tegra::Engines { 12namespace Tegra::Engines {
12 13
13Fermi2D::Fermi2D(VideoCore::RasterizerInterface& rasterizer, MemoryManager& memory_manager) 14Fermi2D::Fermi2D(VideoCore::RasterizerInterface& rasterizer, MemoryManager& memory_manager)
14 : memory_manager(memory_manager), rasterizer{rasterizer} {} 15 : rasterizer{rasterizer}, memory_manager{memory_manager} {}
15 16
16void Fermi2D::CallMethod(const GPU::MethodCall& method_call) { 17void Fermi2D::CallMethod(const GPU::MethodCall& method_call) {
17 ASSERT_MSG(method_call.method < Regs::NUM_REGS, 18 ASSERT_MSG(method_call.method < Regs::NUM_REGS,
diff --git a/src/video_core/engines/fermi_2d.h b/src/video_core/engines/fermi_2d.h
index 80523e320..2e51b7f13 100644
--- a/src/video_core/engines/fermi_2d.h
+++ b/src/video_core/engines/fermi_2d.h
@@ -10,7 +10,10 @@
10#include "common/common_funcs.h" 10#include "common/common_funcs.h"
11#include "common/common_types.h" 11#include "common/common_types.h"
12#include "video_core/gpu.h" 12#include "video_core/gpu.h"
13#include "video_core/memory_manager.h" 13
14namespace Tegra {
15class MemoryManager;
16}
14 17
15namespace VideoCore { 18namespace VideoCore {
16class RasterizerInterface; 19class RasterizerInterface;
@@ -115,10 +118,9 @@ public:
115 }; 118 };
116 } regs{}; 119 } regs{};
117 120
118 MemoryManager& memory_manager;
119
120private: 121private:
121 VideoCore::RasterizerInterface& rasterizer; 122 VideoCore::RasterizerInterface& rasterizer;
123 MemoryManager& memory_manager;
122 124
123 /// Performs the copy from the source surface to the destination surface as configured in the 125 /// Performs the copy from the source surface to the destination surface as configured in the
124 /// registers. 126 /// registers.
diff --git a/src/video_core/engines/kepler_compute.h b/src/video_core/engines/kepler_compute.h
index 6575afd0f..fb6cdf432 100644
--- a/src/video_core/engines/kepler_compute.h
+++ b/src/video_core/engines/kepler_compute.h
@@ -9,7 +9,10 @@
9#include "common/common_funcs.h" 9#include "common/common_funcs.h"
10#include "common/common_types.h" 10#include "common/common_types.h"
11#include "video_core/gpu.h" 11#include "video_core/gpu.h"
12#include "video_core/memory_manager.h" 12
13namespace Tegra {
14class MemoryManager;
15}
13 16
14namespace Tegra::Engines { 17namespace Tegra::Engines {
15 18
@@ -40,10 +43,11 @@ public:
40 static_assert(sizeof(Regs) == Regs::NUM_REGS * sizeof(u32), 43 static_assert(sizeof(Regs) == Regs::NUM_REGS * sizeof(u32),
41 "KeplerCompute Regs has wrong size"); 44 "KeplerCompute Regs has wrong size");
42 45
43 MemoryManager& memory_manager;
44
45 /// Write the value to the register identified by method. 46 /// Write the value to the register identified by method.
46 void CallMethod(const GPU::MethodCall& method_call); 47 void CallMethod(const GPU::MethodCall& method_call);
48
49private:
50 MemoryManager& memory_manager;
47}; 51};
48 52
49#define ASSERT_REG_POSITION(field_name, position) \ 53#define ASSERT_REG_POSITION(field_name, position) \
diff --git a/src/video_core/engines/kepler_memory.cpp b/src/video_core/engines/kepler_memory.cpp
index e259bf46b..cd51a31d7 100644
--- a/src/video_core/engines/kepler_memory.cpp
+++ b/src/video_core/engines/kepler_memory.cpp
@@ -5,9 +5,9 @@
5#include "common/assert.h" 5#include "common/assert.h"
6#include "common/logging/log.h" 6#include "common/logging/log.h"
7#include "core/core.h" 7#include "core/core.h"
8#include "core/memory.h"
9#include "video_core/engines/kepler_memory.h" 8#include "video_core/engines/kepler_memory.h"
10#include "video_core/engines/maxwell_3d.h" 9#include "video_core/engines/maxwell_3d.h"
10#include "video_core/memory_manager.h"
11#include "video_core/rasterizer_interface.h" 11#include "video_core/rasterizer_interface.h"
12#include "video_core/renderer_base.h" 12#include "video_core/renderer_base.h"
13 13
@@ -15,7 +15,7 @@ namespace Tegra::Engines {
15 15
16KeplerMemory::KeplerMemory(Core::System& system, VideoCore::RasterizerInterface& rasterizer, 16KeplerMemory::KeplerMemory(Core::System& system, VideoCore::RasterizerInterface& rasterizer,
17 MemoryManager& memory_manager) 17 MemoryManager& memory_manager)
18 : system{system}, memory_manager(memory_manager), rasterizer{rasterizer} {} 18 : system{system}, rasterizer{rasterizer}, memory_manager{memory_manager} {}
19 19
20KeplerMemory::~KeplerMemory() = default; 20KeplerMemory::~KeplerMemory() = default;
21 21
diff --git a/src/video_core/engines/kepler_memory.h b/src/video_core/engines/kepler_memory.h
index 9181e9d80..78b6c3e45 100644
--- a/src/video_core/engines/kepler_memory.h
+++ b/src/video_core/engines/kepler_memory.h
@@ -10,12 +10,15 @@
10#include "common/common_funcs.h" 10#include "common/common_funcs.h"
11#include "common/common_types.h" 11#include "common/common_types.h"
12#include "video_core/gpu.h" 12#include "video_core/gpu.h"
13#include "video_core/memory_manager.h"
14 13
15namespace Core { 14namespace Core {
16class System; 15class System;
17} 16}
18 17
18namespace Tegra {
19class MemoryManager;
20}
21
19namespace VideoCore { 22namespace VideoCore {
20class RasterizerInterface; 23class RasterizerInterface;
21} 24}
@@ -82,8 +85,8 @@ public:
82 85
83private: 86private:
84 Core::System& system; 87 Core::System& system;
85 MemoryManager& memory_manager;
86 VideoCore::RasterizerInterface& rasterizer; 88 VideoCore::RasterizerInterface& rasterizer;
89 MemoryManager& memory_manager;
87 90
88 void ProcessData(u32 data); 91 void ProcessData(u32 data);
89}; 92};
diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp
index defcfbd3f..3c3ac8f81 100644
--- a/src/video_core/engines/maxwell_3d.cpp
+++ b/src/video_core/engines/maxwell_3d.cpp
@@ -7,11 +7,10 @@
7#include "common/assert.h" 7#include "common/assert.h"
8#include "core/core.h" 8#include "core/core.h"
9#include "core/core_timing.h" 9#include "core/core_timing.h"
10#include "core/memory.h"
11#include "video_core/debug_utils/debug_utils.h" 10#include "video_core/debug_utils/debug_utils.h"
12#include "video_core/engines/maxwell_3d.h" 11#include "video_core/engines/maxwell_3d.h"
12#include "video_core/memory_manager.h"
13#include "video_core/rasterizer_interface.h" 13#include "video_core/rasterizer_interface.h"
14#include "video_core/renderer_base.h"
15#include "video_core/textures/texture.h" 14#include "video_core/textures/texture.h"
16 15
17namespace Tegra::Engines { 16namespace Tegra::Engines {
@@ -21,8 +20,8 @@ constexpr u32 MacroRegistersStart = 0xE00;
21 20
22Maxwell3D::Maxwell3D(Core::System& system, VideoCore::RasterizerInterface& rasterizer, 21Maxwell3D::Maxwell3D(Core::System& system, VideoCore::RasterizerInterface& rasterizer,
23 MemoryManager& memory_manager) 22 MemoryManager& memory_manager)
24 : memory_manager(memory_manager), system{system}, rasterizer{rasterizer}, 23 : system{system}, rasterizer{rasterizer}, memory_manager{memory_manager}, macro_interpreter{
25 macro_interpreter(*this) { 24 *this} {
26 InitializeRegisterDefaults(); 25 InitializeRegisterDefaults();
27} 26}
28 27
diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h
index 7fbf1026e..b352060a1 100644
--- a/src/video_core/engines/maxwell_3d.h
+++ b/src/video_core/engines/maxwell_3d.h
@@ -16,13 +16,16 @@
16#include "common/math_util.h" 16#include "common/math_util.h"
17#include "video_core/gpu.h" 17#include "video_core/gpu.h"
18#include "video_core/macro_interpreter.h" 18#include "video_core/macro_interpreter.h"
19#include "video_core/memory_manager.h"
20#include "video_core/textures/texture.h" 19#include "video_core/textures/texture.h"
21 20
22namespace Core { 21namespace Core {
23class System; 22class System;
24} 23}
25 24
25namespace Tegra {
26class MemoryManager;
27}
28
26namespace VideoCore { 29namespace VideoCore {
27class RasterizerInterface; 30class RasterizerInterface;
28} 31}
@@ -1093,7 +1096,6 @@ public:
1093 }; 1096 };
1094 1097
1095 State state{}; 1098 State state{};
1096 MemoryManager& memory_manager;
1097 1099
1098 struct DirtyFlags { 1100 struct DirtyFlags {
1099 std::bitset<8> color_buffer{0xFF}; 1101 std::bitset<8> color_buffer{0xFF};
@@ -1141,6 +1143,8 @@ private:
1141 1143
1142 VideoCore::RasterizerInterface& rasterizer; 1144 VideoCore::RasterizerInterface& rasterizer;
1143 1145
1146 MemoryManager& memory_manager;
1147
1144 /// Start offsets of each macro in macro_memory 1148 /// Start offsets of each macro in macro_memory
1145 std::unordered_map<u32, u32> macro_offsets; 1149 std::unordered_map<u32, u32> macro_offsets;
1146 1150
diff --git a/src/video_core/engines/maxwell_dma.cpp b/src/video_core/engines/maxwell_dma.cpp
index 5cca5c29a..2426d0067 100644
--- a/src/video_core/engines/maxwell_dma.cpp
+++ b/src/video_core/engines/maxwell_dma.cpp
@@ -5,9 +5,9 @@
5#include "common/assert.h" 5#include "common/assert.h"
6#include "common/logging/log.h" 6#include "common/logging/log.h"
7#include "core/core.h" 7#include "core/core.h"
8#include "core/memory.h"
9#include "video_core/engines/maxwell_3d.h" 8#include "video_core/engines/maxwell_3d.h"
10#include "video_core/engines/maxwell_dma.h" 9#include "video_core/engines/maxwell_dma.h"
10#include "video_core/memory_manager.h"
11#include "video_core/rasterizer_interface.h" 11#include "video_core/rasterizer_interface.h"
12#include "video_core/renderer_base.h" 12#include "video_core/renderer_base.h"
13#include "video_core/textures/decoders.h" 13#include "video_core/textures/decoders.h"
@@ -16,7 +16,7 @@ namespace Tegra::Engines {
16 16
17MaxwellDMA::MaxwellDMA(Core::System& system, VideoCore::RasterizerInterface& rasterizer, 17MaxwellDMA::MaxwellDMA(Core::System& system, VideoCore::RasterizerInterface& rasterizer,
18 MemoryManager& memory_manager) 18 MemoryManager& memory_manager)
19 : memory_manager(memory_manager), system{system}, rasterizer{rasterizer} {} 19 : system{system}, rasterizer{rasterizer}, memory_manager{memory_manager} {}
20 20
21void MaxwellDMA::CallMethod(const GPU::MethodCall& method_call) { 21void MaxwellDMA::CallMethod(const GPU::MethodCall& method_call) {
22 ASSERT_MSG(method_call.method < Regs::NUM_REGS, 22 ASSERT_MSG(method_call.method < Regs::NUM_REGS,
diff --git a/src/video_core/engines/maxwell_dma.h b/src/video_core/engines/maxwell_dma.h
index 34c369320..c6b649842 100644
--- a/src/video_core/engines/maxwell_dma.h
+++ b/src/video_core/engines/maxwell_dma.h
@@ -10,12 +10,15 @@
10#include "common/common_funcs.h" 10#include "common/common_funcs.h"
11#include "common/common_types.h" 11#include "common/common_types.h"
12#include "video_core/gpu.h" 12#include "video_core/gpu.h"
13#include "video_core/memory_manager.h"
14 13
15namespace Core { 14namespace Core {
16class System; 15class System;
17} 16}
18 17
18namespace Tegra {
19class MemoryManager;
20}
21
19namespace VideoCore { 22namespace VideoCore {
20class RasterizerInterface; 23class RasterizerInterface;
21} 24}
@@ -139,13 +142,13 @@ public:
139 }; 142 };
140 } regs{}; 143 } regs{};
141 144
142 MemoryManager& memory_manager;
143
144private: 145private:
145 Core::System& system; 146 Core::System& system;
146 147
147 VideoCore::RasterizerInterface& rasterizer; 148 VideoCore::RasterizerInterface& rasterizer;
148 149
150 MemoryManager& memory_manager;
151
149 /// Performs the copy from the source buffer to the destination buffer as configured in the 152 /// Performs the copy from the source buffer to the destination buffer as configured in the
150 /// registers. 153 /// registers.
151 void HandleCopy(); 154 void HandleCopy();
diff --git a/src/video_core/gpu_thread.cpp b/src/video_core/gpu_thread.cpp
index 23f9bd422..cc56cf467 100644
--- a/src/video_core/gpu_thread.cpp
+++ b/src/video_core/gpu_thread.cpp
@@ -59,7 +59,7 @@ ThreadManager::ThreadManager(Core::System& system, VideoCore::RendererBase& rend
59 Tegra::DmaPusher& dma_pusher) 59 Tegra::DmaPusher& dma_pusher)
60 : system{system}, thread{RunThread, std::ref(renderer), std::ref(dma_pusher), std::ref(state)} { 60 : system{system}, thread{RunThread, std::ref(renderer), std::ref(dma_pusher), std::ref(state)} {
61 synchronization_event = system.CoreTiming().RegisterEvent( 61 synchronization_event = system.CoreTiming().RegisterEvent(
62 "GPUThreadSynch", [this](u64 fence, int) { state.WaitForSynchronization(fence); }); 62 "GPUThreadSynch", [this](u64 fence, s64) { state.WaitForSynchronization(fence); });
63} 63}
64 64
65ThreadManager::~ThreadManager() { 65ThreadManager::~ThreadManager() {
diff --git a/src/video_core/macro_interpreter.cpp b/src/video_core/macro_interpreter.cpp
index 64f75db43..524d9ea5a 100644
--- a/src/video_core/macro_interpreter.cpp
+++ b/src/video_core/macro_interpreter.cpp
@@ -223,27 +223,21 @@ void MacroInterpreter::ProcessResult(ResultOperation operation, u32 reg, u32 res
223} 223}
224 224
225u32 MacroInterpreter::FetchParameter() { 225u32 MacroInterpreter::FetchParameter() {
226 ASSERT(next_parameter_index < parameters.size()); 226 return parameters.at(next_parameter_index++);
227 return parameters[next_parameter_index++];
228} 227}
229 228
230u32 MacroInterpreter::GetRegister(u32 register_id) const { 229u32 MacroInterpreter::GetRegister(u32 register_id) const {
231 // Register 0 is supposed to always return 0. 230 return registers.at(register_id);
232 if (register_id == 0)
233 return 0;
234
235 ASSERT(register_id < registers.size());
236 return registers[register_id];
237} 231}
238 232
239void MacroInterpreter::SetRegister(u32 register_id, u32 value) { 233void MacroInterpreter::SetRegister(u32 register_id, u32 value) {
240 // Register 0 is supposed to always return 0. NOP is implemented as a store to the zero 234 // Register 0 is hardwired as the zero register.
241 // register. 235 // Ensure no writes to it actually occur.
242 if (register_id == 0) 236 if (register_id == 0) {
243 return; 237 return;
238 }
244 239
245 ASSERT(register_id < registers.size()); 240 registers.at(register_id) = value;
246 registers[register_id] = value;
247} 241}
248 242
249void MacroInterpreter::SetMethodAddress(u32 address) { 243void MacroInterpreter::SetMethodAddress(u32 address) {
diff --git a/src/video_core/memory_manager.cpp b/src/video_core/memory_manager.cpp
index e76b59842..8417324ff 100644
--- a/src/video_core/memory_manager.cpp
+++ b/src/video_core/memory_manager.cpp
@@ -77,16 +77,17 @@ GPUVAddr MemoryManager::UnmapBuffer(GPUVAddr gpu_addr, u64 size) {
77 return gpu_addr; 77 return gpu_addr;
78} 78}
79 79
80GPUVAddr MemoryManager::FindFreeRegion(GPUVAddr region_start, u64 size) { 80GPUVAddr MemoryManager::FindFreeRegion(GPUVAddr region_start, u64 size) const {
81 // Find the first Free VMA. 81 // Find the first Free VMA.
82 const VMAHandle vma_handle{std::find_if(vma_map.begin(), vma_map.end(), [&](const auto& vma) { 82 const VMAHandle vma_handle{
83 if (vma.second.type != VirtualMemoryArea::Type::Unmapped) { 83 std::find_if(vma_map.begin(), vma_map.end(), [region_start, size](const auto& vma) {
84 return false; 84 if (vma.second.type != VirtualMemoryArea::Type::Unmapped) {
85 } 85 return false;
86 }
86 87
87 const VAddr vma_end{vma.second.base + vma.second.size}; 88 const VAddr vma_end{vma.second.base + vma.second.size};
88 return vma_end > region_start && vma_end >= region_start + size; 89 return vma_end > region_start && vma_end >= region_start + size;
89 })}; 90 })};
90 91
91 if (vma_handle == vma_map.end()) { 92 if (vma_handle == vma_map.end()) {
92 return {}; 93 return {};
@@ -99,12 +100,12 @@ bool MemoryManager::IsAddressValid(GPUVAddr addr) const {
99 return (addr >> page_bits) < page_table.pointers.size(); 100 return (addr >> page_bits) < page_table.pointers.size();
100} 101}
101 102
102std::optional<VAddr> MemoryManager::GpuToCpuAddress(GPUVAddr addr) { 103std::optional<VAddr> MemoryManager::GpuToCpuAddress(GPUVAddr addr) const {
103 if (!IsAddressValid(addr)) { 104 if (!IsAddressValid(addr)) {
104 return {}; 105 return {};
105 } 106 }
106 107
107 VAddr cpu_addr{page_table.backing_addr[addr >> page_bits]}; 108 const VAddr cpu_addr{page_table.backing_addr[addr >> page_bits]};
108 if (cpu_addr) { 109 if (cpu_addr) {
109 return cpu_addr + (addr & page_mask); 110 return cpu_addr + (addr & page_mask);
110 } 111 }
@@ -113,7 +114,7 @@ std::optional<VAddr> MemoryManager::GpuToCpuAddress(GPUVAddr addr) {
113} 114}
114 115
115template <typename T> 116template <typename T>
116T MemoryManager::Read(GPUVAddr addr) { 117T MemoryManager::Read(GPUVAddr addr) const {
117 if (!IsAddressValid(addr)) { 118 if (!IsAddressValid(addr)) {
118 return {}; 119 return {};
119 } 120 }
@@ -165,10 +166,10 @@ void MemoryManager::Write(GPUVAddr addr, T data) {
165 } 166 }
166} 167}
167 168
168template u8 MemoryManager::Read<u8>(GPUVAddr addr); 169template u8 MemoryManager::Read<u8>(GPUVAddr addr) const;
169template u16 MemoryManager::Read<u16>(GPUVAddr addr); 170template u16 MemoryManager::Read<u16>(GPUVAddr addr) const;
170template u32 MemoryManager::Read<u32>(GPUVAddr addr); 171template u32 MemoryManager::Read<u32>(GPUVAddr addr) const;
171template u64 MemoryManager::Read<u64>(GPUVAddr addr); 172template u64 MemoryManager::Read<u64>(GPUVAddr addr) const;
172template void MemoryManager::Write<u8>(GPUVAddr addr, u8 data); 173template void MemoryManager::Write<u8>(GPUVAddr addr, u8 data);
173template void MemoryManager::Write<u16>(GPUVAddr addr, u16 data); 174template void MemoryManager::Write<u16>(GPUVAddr addr, u16 data);
174template void MemoryManager::Write<u32>(GPUVAddr addr, u32 data); 175template void MemoryManager::Write<u32>(GPUVAddr addr, u32 data);
@@ -179,8 +180,22 @@ u8* MemoryManager::GetPointer(GPUVAddr addr) {
179 return {}; 180 return {};
180 } 181 }
181 182
182 u8* page_pointer{page_table.pointers[addr >> page_bits]}; 183 u8* const page_pointer{page_table.pointers[addr >> page_bits]};
183 if (page_pointer) { 184 if (page_pointer != nullptr) {
185 return page_pointer + (addr & page_mask);
186 }
187
188 LOG_ERROR(HW_GPU, "Unknown GetPointer @ 0x{:016X}", addr);
189 return {};
190}
191
192const u8* MemoryManager::GetPointer(GPUVAddr addr) const {
193 if (!IsAddressValid(addr)) {
194 return {};
195 }
196
197 const u8* const page_pointer{page_table.pointers[addr >> page_bits]};
198 if (page_pointer != nullptr) {
184 return page_pointer + (addr & page_mask); 199 return page_pointer + (addr & page_mask);
185 } 200 }
186 201
@@ -188,7 +203,7 @@ u8* MemoryManager::GetPointer(GPUVAddr addr) {
188 return {}; 203 return {};
189} 204}
190 205
191void MemoryManager::ReadBlock(GPUVAddr src_addr, void* dest_buffer, std::size_t size) { 206void MemoryManager::ReadBlock(GPUVAddr src_addr, void* dest_buffer, std::size_t size) const {
192 std::memcpy(dest_buffer, GetPointer(src_addr), size); 207 std::memcpy(dest_buffer, GetPointer(src_addr), size);
193} 208}
194void MemoryManager::WriteBlock(GPUVAddr dest_addr, const void* src_buffer, std::size_t size) { 209void MemoryManager::WriteBlock(GPUVAddr dest_addr, const void* src_buffer, std::size_t size) {
diff --git a/src/video_core/memory_manager.h b/src/video_core/memory_manager.h
index 34744bb27..178e2f655 100644
--- a/src/video_core/memory_manager.h
+++ b/src/video_core/memory_manager.h
@@ -50,17 +50,18 @@ public:
50 GPUVAddr MapBufferEx(VAddr cpu_addr, u64 size); 50 GPUVAddr MapBufferEx(VAddr cpu_addr, u64 size);
51 GPUVAddr MapBufferEx(VAddr cpu_addr, GPUVAddr addr, u64 size); 51 GPUVAddr MapBufferEx(VAddr cpu_addr, GPUVAddr addr, u64 size);
52 GPUVAddr UnmapBuffer(GPUVAddr addr, u64 size); 52 GPUVAddr UnmapBuffer(GPUVAddr addr, u64 size);
53 std::optional<VAddr> GpuToCpuAddress(GPUVAddr addr); 53 std::optional<VAddr> GpuToCpuAddress(GPUVAddr addr) const;
54 54
55 template <typename T> 55 template <typename T>
56 T Read(GPUVAddr addr); 56 T Read(GPUVAddr addr) const;
57 57
58 template <typename T> 58 template <typename T>
59 void Write(GPUVAddr addr, T data); 59 void Write(GPUVAddr addr, T data);
60 60
61 u8* GetPointer(GPUVAddr addr); 61 u8* GetPointer(GPUVAddr addr);
62 const u8* GetPointer(GPUVAddr addr) const;
62 63
63 void ReadBlock(GPUVAddr src_addr, void* dest_buffer, std::size_t size); 64 void ReadBlock(GPUVAddr src_addr, void* dest_buffer, std::size_t size) const;
64 void WriteBlock(GPUVAddr dest_addr, const void* src_buffer, std::size_t size); 65 void WriteBlock(GPUVAddr dest_addr, const void* src_buffer, std::size_t size);
65 void CopyBlock(GPUVAddr dest_addr, GPUVAddr src_addr, std::size_t size); 66 void CopyBlock(GPUVAddr dest_addr, GPUVAddr src_addr, std::size_t size);
66 67
@@ -127,7 +128,7 @@ private:
127 void UpdatePageTableForVMA(const VirtualMemoryArea& vma); 128 void UpdatePageTableForVMA(const VirtualMemoryArea& vma);
128 129
129 /// Finds a free (unmapped region) of the specified size starting at the specified address. 130 /// Finds a free (unmapped region) of the specified size starting at the specified address.
130 GPUVAddr FindFreeRegion(GPUVAddr region_start, u64 size); 131 GPUVAddr FindFreeRegion(GPUVAddr region_start, u64 size) const;
131 132
132private: 133private:
133 static constexpr u64 page_bits{16}; 134 static constexpr u64 page_bits{16};
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
index 7300a4037..a1a51f226 100644
--- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
@@ -69,10 +69,10 @@ public:
69 shader_source += '\n'; 69 shader_source += '\n';
70 } 70 }
71 71
72 std::string GenerateTemporal() { 72 std::string GenerateTemporary() {
73 std::string temporal = "tmp"; 73 std::string temporary = "tmp";
74 temporal += std::to_string(temporal_index++); 74 temporary += std::to_string(temporary_index++);
75 return temporal; 75 return temporary;
76 } 76 }
77 77
78 std::string GetResult() { 78 std::string GetResult() {
@@ -87,7 +87,7 @@ private:
87 } 87 }
88 88
89 std::string shader_source; 89 std::string shader_source;
90 u32 temporal_index = 1; 90 u32 temporary_index = 1;
91}; 91};
92 92
93/// Generates code to use for a swizzle operation. 93/// Generates code to use for a swizzle operation.
@@ -426,9 +426,14 @@ private:
426 std::string Visit(Node node) { 426 std::string Visit(Node node) {
427 if (const auto operation = std::get_if<OperationNode>(node)) { 427 if (const auto operation = std::get_if<OperationNode>(node)) {
428 const auto operation_index = static_cast<std::size_t>(operation->GetCode()); 428 const auto operation_index = static_cast<std::size_t>(operation->GetCode());
429 if (operation_index >= operation_decompilers.size()) {
430 UNREACHABLE_MSG("Out of bounds operation: {}", operation_index);
431 return {};
432 }
429 const auto decompiler = operation_decompilers[operation_index]; 433 const auto decompiler = operation_decompilers[operation_index];
430 if (decompiler == nullptr) { 434 if (decompiler == nullptr) {
431 UNREACHABLE_MSG("Operation decompiler {} not defined", operation_index); 435 UNREACHABLE_MSG("Undefined operation: {}", operation_index);
436 return {};
432 } 437 }
433 return (this->*decompiler)(*operation); 438 return (this->*decompiler)(*operation);
434 439
@@ -540,7 +545,7 @@ private:
540 545
541 } else if (std::holds_alternative<OperationNode>(*offset)) { 546 } else if (std::holds_alternative<OperationNode>(*offset)) {
542 // Indirect access 547 // Indirect access
543 const std::string final_offset = code.GenerateTemporal(); 548 const std::string final_offset = code.GenerateTemporary();
544 code.AddLine("uint " + final_offset + " = (ftou(" + Visit(offset) + ") / 4) & " + 549 code.AddLine("uint " + final_offset + " = (ftou(" + Visit(offset) + ") / 4) & " +
545 std::to_string(MAX_CONSTBUFFER_ELEMENTS - 1) + ';'); 550 std::to_string(MAX_CONSTBUFFER_ELEMENTS - 1) + ';');
546 return fmt::format("{}[{} / 4][{} % 4]", GetConstBuffer(cbuf->GetIndex()), 551 return fmt::format("{}[{} / 4][{} % 4]", GetConstBuffer(cbuf->GetIndex()),
@@ -587,9 +592,9 @@ private:
587 // There's a bug in NVidia's proprietary drivers that makes precise fail on fragment shaders 592 // There's a bug in NVidia's proprietary drivers that makes precise fail on fragment shaders
588 const std::string precise = stage != ShaderStage::Fragment ? "precise " : ""; 593 const std::string precise = stage != ShaderStage::Fragment ? "precise " : "";
589 594
590 const std::string temporal = code.GenerateTemporal(); 595 const std::string temporary = code.GenerateTemporary();
591 code.AddLine(precise + "float " + temporal + " = " + value + ';'); 596 code.AddLine(precise + "float " + temporary + " = " + value + ';');
592 return temporal; 597 return temporary;
593 } 598 }
594 599
595 std::string VisitOperand(Operation operation, std::size_t operand_index) { 600 std::string VisitOperand(Operation operation, std::size_t operand_index) {
@@ -601,9 +606,9 @@ private:
601 return Visit(operand); 606 return Visit(operand);
602 } 607 }
603 608
604 const std::string temporal = code.GenerateTemporal(); 609 const std::string temporary = code.GenerateTemporary();
605 code.AddLine("float " + temporal + " = " + Visit(operand) + ';'); 610 code.AddLine("float " + temporary + " = " + Visit(operand) + ';');
606 return temporal; 611 return temporary;
607 } 612 }
608 613
609 std::string VisitOperand(Operation operation, std::size_t operand_index, Type type) { 614 std::string VisitOperand(Operation operation, std::size_t operand_index, Type type) {
diff --git a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp
index 388b5ffd5..02a9f5ecb 100644
--- a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp
+++ b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp
@@ -10,6 +10,7 @@
10#include "common/alignment.h" 10#include "common/alignment.h"
11#include "common/assert.h" 11#include "common/assert.h"
12#include "core/memory.h" 12#include "core/memory.h"
13#include "video_core/memory_manager.h"
13#include "video_core/renderer_vulkan/declarations.h" 14#include "video_core/renderer_vulkan/declarations.h"
14#include "video_core/renderer_vulkan/vk_buffer_cache.h" 15#include "video_core/renderer_vulkan/vk_buffer_cache.h"
15#include "video_core/renderer_vulkan/vk_scheduler.h" 16#include "video_core/renderer_vulkan/vk_scheduler.h"
diff --git a/src/yuzu/debugger/graphics/graphics_surface.cpp b/src/yuzu/debugger/graphics/graphics_surface.cpp
index 11023ed63..f2d14becf 100644
--- a/src/yuzu/debugger/graphics/graphics_surface.cpp
+++ b/src/yuzu/debugger/graphics/graphics_surface.cpp
@@ -7,6 +7,7 @@
7#include <QDebug> 7#include <QDebug>
8#include <QFileDialog> 8#include <QFileDialog>
9#include <QLabel> 9#include <QLabel>
10#include <QMessageBox>
10#include <QMouseEvent> 11#include <QMouseEvent>
11#include <QPushButton> 12#include <QPushButton>
12#include <QScrollArea> 13#include <QScrollArea>
@@ -95,50 +96,91 @@ GraphicsSurfaceWidget::GraphicsSurfaceWidget(std::shared_ptr<Tegra::DebugContext
95 surface_picker_y_control = new QSpinBox; 96 surface_picker_y_control = new QSpinBox;
96 surface_picker_y_control->setRange(0, max_dimension - 1); 97 surface_picker_y_control->setRange(0, max_dimension - 1);
97 98
98 surface_format_control = new QComboBox; 99 // clang-format off
99
100 // Color formats sorted by Maxwell texture format index 100 // Color formats sorted by Maxwell texture format index
101 surface_format_control->addItem(tr("None")); 101 const QStringList surface_formats{
102 surface_format_control->addItem(tr("Unknown")); 102 tr("None"),
103 surface_format_control->addItem(tr("Unknown")); 103 QStringLiteral("R32_G32_B32_A32"),
104 surface_format_control->addItem(tr("Unknown")); 104 QStringLiteral("R32_G32_B32"),
105 surface_format_control->addItem(tr("Unknown")); 105 QStringLiteral("R16_G16_B16_A16"),
106 surface_format_control->addItem(tr("Unknown")); 106 QStringLiteral("R32_G32"),
107 surface_format_control->addItem(tr("Unknown")); 107 QStringLiteral("R32_B24G8"),
108 surface_format_control->addItem(tr("Unknown")); 108 QStringLiteral("ETC2_RGB"),
109 surface_format_control->addItem(tr("A8R8G8B8")); 109 QStringLiteral("X8B8G8R8"),
110 surface_format_control->addItem(tr("Unknown")); 110 QStringLiteral("A8R8G8B8"),
111 surface_format_control->addItem(tr("Unknown")); 111 QStringLiteral("A2B10G10R10"),
112 surface_format_control->addItem(tr("Unknown")); 112 QStringLiteral("ETC2_RGB_PTA"),
113 surface_format_control->addItem(tr("Unknown")); 113 QStringLiteral("ETC2_RGBA"),
114 surface_format_control->addItem(tr("Unknown")); 114 QStringLiteral("R16_G16"),
115 surface_format_control->addItem(tr("Unknown")); 115 QStringLiteral("G8R24"),
116 surface_format_control->addItem(tr("Unknown")); 116 QStringLiteral("G24R8"),
117 surface_format_control->addItem(tr("Unknown")); 117 QStringLiteral("R32"),
118 surface_format_control->addItem(tr("Unknown")); 118 QStringLiteral("BC6H_SF16"),
119 surface_format_control->addItem(tr("Unknown")); 119 QStringLiteral("BC6H_UF16"),
120 surface_format_control->addItem(tr("Unknown")); 120 QStringLiteral("A4B4G4R4"),
121 surface_format_control->addItem(tr("Unknown")); 121 QStringLiteral("A5B5G5R1"),
122 surface_format_control->addItem(tr("Unknown")); 122 QStringLiteral("A1B5G5R5"),
123 surface_format_control->addItem(tr("Unknown")); 123 QStringLiteral("B5G6R5"),
124 surface_format_control->addItem(tr("Unknown")); 124 QStringLiteral("B6G5R5"),
125 surface_format_control->addItem(tr("Unknown")); 125 QStringLiteral("BC7U"),
126 surface_format_control->addItem(tr("Unknown")); 126 QStringLiteral("G8R8"),
127 surface_format_control->addItem(tr("Unknown")); 127 QStringLiteral("EAC"),
128 surface_format_control->addItem(tr("Unknown")); 128 QStringLiteral("EACX2"),
129 surface_format_control->addItem(tr("Unknown")); 129 QStringLiteral("R16"),
130 surface_format_control->addItem(tr("Unknown")); 130 QStringLiteral("Y8_VIDEO"),
131 surface_format_control->addItem(tr("Unknown")); 131 QStringLiteral("R8"),
132 surface_format_control->addItem(tr("Unknown")); 132 QStringLiteral("G4R4"),
133 surface_format_control->addItem(tr("Unknown")); 133 QStringLiteral("R1"),
134 surface_format_control->addItem(tr("Unknown")); 134 QStringLiteral("E5B9G9R9_SHAREDEXP"),
135 surface_format_control->addItem(tr("Unknown")); 135 QStringLiteral("BF10GF11RF11"),
136 surface_format_control->addItem(tr("Unknown")); 136 QStringLiteral("G8B8G8R8"),
137 surface_format_control->addItem(tr("DXT1")); 137 QStringLiteral("B8G8R8G8"),
138 surface_format_control->addItem(tr("DXT23")); 138 QStringLiteral("DXT1"),
139 surface_format_control->addItem(tr("DXT45")); 139 QStringLiteral("DXT23"),
140 surface_format_control->addItem(tr("DXN1")); 140 QStringLiteral("DXT45"),
141 surface_format_control->addItem(tr("DXN2")); 141 QStringLiteral("DXN1"),
142 QStringLiteral("DXN2"),
143 QStringLiteral("Z24S8"),
144 QStringLiteral("X8Z24"),
145 QStringLiteral("S8Z24"),
146 QStringLiteral("X4V4Z24__COV4R4V"),
147 QStringLiteral("X4V4Z24__COV8R8V"),
148 QStringLiteral("V8Z24__COV4R12V"),
149 QStringLiteral("ZF32"),
150 QStringLiteral("ZF32_X24S8"),
151 QStringLiteral("X8Z24_X20V4S8__COV4R4V"),
152 QStringLiteral("X8Z24_X20V4S8__COV8R8V"),
153 QStringLiteral("ZF32_X20V4X8__COV4R4V"),
154 QStringLiteral("ZF32_X20V4X8__COV8R8V"),
155 QStringLiteral("ZF32_X20V4S8__COV4R4V"),
156 QStringLiteral("ZF32_X20V4S8__COV8R8V"),
157 QStringLiteral("X8Z24_X16V8S8__COV4R12V"),
158 QStringLiteral("ZF32_X16V8X8__COV4R12V"),
159 QStringLiteral("ZF32_X16V8S8__COV4R12V"),
160 QStringLiteral("Z16"),
161 QStringLiteral("V8Z24__COV8R24V"),
162 QStringLiteral("X8Z24_X16V8S8__COV8R24V"),
163 QStringLiteral("ZF32_X16V8X8__COV8R24V"),
164 QStringLiteral("ZF32_X16V8S8__COV8R24V"),
165 QStringLiteral("ASTC_2D_4X4"),
166 QStringLiteral("ASTC_2D_5X5"),
167 QStringLiteral("ASTC_2D_6X6"),
168 QStringLiteral("ASTC_2D_8X8"),
169 QStringLiteral("ASTC_2D_10X10"),
170 QStringLiteral("ASTC_2D_12X12"),
171 QStringLiteral("ASTC_2D_5X4"),
172 QStringLiteral("ASTC_2D_6X5"),
173 QStringLiteral("ASTC_2D_8X6"),
174 QStringLiteral("ASTC_2D_10X8"),
175 QStringLiteral("ASTC_2D_12X10"),
176 QStringLiteral("ASTC_2D_8X5"),
177 QStringLiteral("ASTC_2D_10X5"),
178 QStringLiteral("ASTC_2D_10X6"),
179 };
180 // clang-format on
181
182 surface_format_control = new QComboBox;
183 surface_format_control->addItems(surface_formats);
142 184
143 surface_info_label = new QLabel(); 185 surface_info_label = new QLabel();
144 surface_info_label->setWordWrap(true); 186 surface_info_label->setWordWrap(true);
@@ -157,22 +199,20 @@ GraphicsSurfaceWidget::GraphicsSurfaceWidget(std::shared_ptr<Tegra::DebugContext
157 199
158 // Connections 200 // Connections
159 connect(this, &GraphicsSurfaceWidget::Update, this, &GraphicsSurfaceWidget::OnUpdate); 201 connect(this, &GraphicsSurfaceWidget::Update, this, &GraphicsSurfaceWidget::OnUpdate);
160 connect(surface_source_list, 202 connect(surface_source_list, qOverload<int>(&QComboBox::currentIndexChanged), this,
161 static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this,
162 &GraphicsSurfaceWidget::OnSurfaceSourceChanged); 203 &GraphicsSurfaceWidget::OnSurfaceSourceChanged);
163 connect(surface_address_control, &CSpinBox::ValueChanged, this, 204 connect(surface_address_control, &CSpinBox::ValueChanged, this,
164 &GraphicsSurfaceWidget::OnSurfaceAddressChanged); 205 &GraphicsSurfaceWidget::OnSurfaceAddressChanged);
165 connect(surface_width_control, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), 206 connect(surface_width_control, qOverload<int>(&QSpinBox::valueChanged), this,
166 this, &GraphicsSurfaceWidget::OnSurfaceWidthChanged); 207 &GraphicsSurfaceWidget::OnSurfaceWidthChanged);
167 connect(surface_height_control, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), 208 connect(surface_height_control, qOverload<int>(&QSpinBox::valueChanged), this,
168 this, &GraphicsSurfaceWidget::OnSurfaceHeightChanged); 209 &GraphicsSurfaceWidget::OnSurfaceHeightChanged);
169 connect(surface_format_control, 210 connect(surface_format_control, qOverload<int>(&QComboBox::currentIndexChanged), this,
170 static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this,
171 &GraphicsSurfaceWidget::OnSurfaceFormatChanged); 211 &GraphicsSurfaceWidget::OnSurfaceFormatChanged);
172 connect(surface_picker_x_control, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), 212 connect(surface_picker_x_control, qOverload<int>(&QSpinBox::valueChanged), this,
173 this, &GraphicsSurfaceWidget::OnSurfacePickerXChanged); 213 &GraphicsSurfaceWidget::OnSurfacePickerXChanged);
174 connect(surface_picker_y_control, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), 214 connect(surface_picker_y_control, qOverload<int>(&QSpinBox::valueChanged), this,
175 this, &GraphicsSurfaceWidget::OnSurfacePickerYChanged); 215 &GraphicsSurfaceWidget::OnSurfacePickerYChanged);
176 connect(save_surface, &QPushButton::clicked, this, &GraphicsSurfaceWidget::SaveSurface); 216 connect(save_surface, &QPushButton::clicked, this, &GraphicsSurfaceWidget::SaveSurface);
177 217
178 auto main_widget = new QWidget; 218 auto main_widget = new QWidget;
@@ -420,40 +460,56 @@ void GraphicsSurfaceWidget::OnUpdate() {
420} 460}
421 461
422void GraphicsSurfaceWidget::SaveSurface() { 462void GraphicsSurfaceWidget::SaveSurface() {
423 QString png_filter = tr("Portable Network Graphic (*.png)"); 463 const QString png_filter = tr("Portable Network Graphic (*.png)");
424 QString bin_filter = tr("Binary data (*.bin)"); 464 const QString bin_filter = tr("Binary data (*.bin)");
425 465
426 QString selectedFilter; 466 QString selected_filter;
427 QString filename = QFileDialog::getSaveFileName( 467 const QString filename = QFileDialog::getSaveFileName(
428 this, tr("Save Surface"), 468 this, tr("Save Surface"),
429 QString("texture-0x%1.png").arg(QString::number(surface_address, 16)), 469 QStringLiteral("texture-0x%1.png").arg(QString::number(surface_address, 16)),
430 QString("%1;;%2").arg(png_filter, bin_filter), &selectedFilter); 470 QStringLiteral("%1;;%2").arg(png_filter, bin_filter), &selected_filter);
431 471
432 if (filename.isEmpty()) { 472 if (filename.isEmpty()) {
433 // If the user canceled the dialog, don't save anything. 473 // If the user canceled the dialog, don't save anything.
434 return; 474 return;
435 } 475 }
436 476
437 if (selectedFilter == png_filter) { 477 if (selected_filter == png_filter) {
438 const QPixmap* pixmap = surface_picture_label->pixmap(); 478 const QPixmap* const pixmap = surface_picture_label->pixmap();
439 ASSERT_MSG(pixmap != nullptr, "No pixmap set"); 479 ASSERT_MSG(pixmap != nullptr, "No pixmap set");
440 480
441 QFile file(filename); 481 QFile file{filename};
442 file.open(QIODevice::WriteOnly); 482 if (!file.open(QIODevice::WriteOnly)) {
443 if (pixmap) 483 QMessageBox::warning(this, tr("Error"), tr("Failed to open file '%1'").arg(filename));
444 pixmap->save(&file, "PNG"); 484 return;
445 } else if (selectedFilter == bin_filter) { 485 }
486
487 if (!pixmap->save(&file, "PNG")) {
488 QMessageBox::warning(this, tr("Error"),
489 tr("Failed to save surface data to file '%1'").arg(filename));
490 }
491 } else if (selected_filter == bin_filter) {
446 auto& gpu = Core::System::GetInstance().GPU(); 492 auto& gpu = Core::System::GetInstance().GPU();
447 std::optional<VAddr> address = gpu.MemoryManager().GpuToCpuAddress(surface_address); 493 const std::optional<VAddr> address = gpu.MemoryManager().GpuToCpuAddress(surface_address);
448 494
449 const u8* buffer = Memory::GetPointer(*address); 495 const u8* const buffer = Memory::GetPointer(*address);
450 ASSERT_MSG(buffer != nullptr, "Memory not accessible"); 496 ASSERT_MSG(buffer != nullptr, "Memory not accessible");
451 497
452 QFile file(filename); 498 QFile file{filename};
453 file.open(QIODevice::WriteOnly); 499 if (!file.open(QIODevice::WriteOnly)) {
454 int size = surface_width * surface_height * Tegra::Texture::BytesPerPixel(surface_format); 500 QMessageBox::warning(this, tr("Error"), tr("Failed to open file '%1'").arg(filename));
455 QByteArray data(reinterpret_cast<const char*>(buffer), size); 501 return;
456 file.write(data); 502 }
503
504 const int size =
505 surface_width * surface_height * Tegra::Texture::BytesPerPixel(surface_format);
506 const QByteArray data(reinterpret_cast<const char*>(buffer), size);
507 if (file.write(data) != data.size()) {
508 QMessageBox::warning(
509 this, tr("Error"),
510 tr("Failed to completely write surface data to file. The saved data will "
511 "likely be corrupt."));
512 }
457 } else { 513 } else {
458 UNREACHABLE_MSG("Unhandled filter selected"); 514 UNREACHABLE_MSG("Unhandled filter selected");
459 } 515 }