summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/android/app/src/main/jni/native.cpp2
-rw-r--r--src/common/demangle.cpp2
-rw-r--r--src/common/detached_tasks.cpp4
-rw-r--r--src/common/page_table.h12
-rw-r--r--src/common/settings.cpp3
-rw-r--r--src/common/time_zone.cpp47
-rw-r--r--src/core/arm/arm_interface.cpp4
-rw-r--r--src/core/arm/arm_interface.h2
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic_32.cpp6
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic_32.h6
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic_64.cpp6
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic_64.h6
-rw-r--r--src/core/arm/dynarmic/dynarmic_exclusive_monitor.h5
-rw-r--r--src/core/core.cpp8
-rw-r--r--src/core/core.h3
-rw-r--r--src/core/debugger/gdbstub.cpp13
-rw-r--r--src/core/hle/kernel/k_auto_object.cpp4
-rw-r--r--src/core/hle/kernel/k_auto_object.h5
-rw-r--r--src/core/hle/kernel/k_code_memory.cpp17
-rw-r--r--src/core/hle/kernel/k_page_table.h41
-rw-r--r--src/core/hle/kernel/k_process.cpp2
-rw-r--r--src/core/hle/kernel/k_process.h10
-rw-r--r--src/core/hle/kernel/k_scheduler.cpp3
-rw-r--r--src/core/hle/kernel/k_shared_memory.cpp6
-rw-r--r--src/core/hle/kernel/k_thread.cpp6
-rw-r--r--src/core/hle/kernel/k_thread_local_page.cpp10
-rw-r--r--src/core/hle/kernel/kernel.cpp6
-rw-r--r--src/core/hle/kernel/physical_core.cpp8
-rw-r--r--src/core/hle/kernel/svc/svc_cache.cpp2
-rw-r--r--src/core/hle/kernel/svc/svc_code_memory.cpp14
-rw-r--r--src/core/hle/kernel/svc/svc_device_address_space.cpp6
-rw-r--r--src/core/hle/kernel/svc/svc_info.cpp16
-rw-r--r--src/core/hle/kernel/svc/svc_ipc.cpp11
-rw-r--r--src/core/hle/kernel/svc/svc_memory.cpp33
-rw-r--r--src/core/hle/kernel/svc/svc_physical_memory.cpp14
-rw-r--r--src/core/hle/kernel/svc/svc_process.cpp4
-rw-r--r--src/core/hle/kernel/svc/svc_process_memory.cpp34
-rw-r--r--src/core/hle/kernel/svc/svc_query_memory.cpp2
-rw-r--r--src/core/hle/kernel/svc/svc_shared_memory.cpp4
-rw-r--r--src/core/hle/kernel/svc/svc_synchronization.cpp11
-rw-r--r--src/core/hle/kernel/svc/svc_thread.cpp2
-rw-r--r--src/core/hle/kernel/svc/svc_transfer_memory.cpp2
-rw-r--r--src/core/hle/service/acc/acc.cpp3
-rw-r--r--src/core/hle/service/am/am.cpp4
-rw-r--r--src/core/hle/service/glue/ectx.cpp43
-rw-r--r--src/core/hle/service/glue/ectx.h3
-rw-r--r--src/core/hle/service/ldr/ldr.cpp20
-rw-r--r--src/core/hle/service/nfc/common/amiibo_crypto.cpp2
-rw-r--r--src/core/hle/service/nfc/common/amiibo_crypto.h2
-rw-r--r--src/core/hle/service/nfc/common/device.cpp3
-rw-r--r--src/core/hle/service/nfc/common/device_manager.cpp135
-rw-r--r--src/core/hle/service/nfc/common/device_manager.h34
-rw-r--r--src/core/hle/service/nfc/nfc_interface.cpp18
-rw-r--r--src/core/hle/service/nfc/nfc_result.h3
-rw-r--r--src/core/hle/service/nvdrv/devices/nvmap.cpp4
-rw-r--r--src/core/hle/service/sockets/bsd.cpp2
-rw-r--r--src/core/hle/service/sockets/nsd.cpp27
-rw-r--r--src/core/hle/service/sockets/nsd.h2
-rw-r--r--src/core/hle/service/sockets/sfdnsres.cpp16
-rw-r--r--src/core/hle/service/sockets/sfdnsres.h1
-rw-r--r--src/core/hle/service/sockets/sockets_translate.cpp38
-rw-r--r--src/core/hle/service/sockets/sockets_translate.h3
-rw-r--r--src/core/loader/deconstructed_rom_directory.cpp2
-rw-r--r--src/core/loader/kip.cpp2
-rw-r--r--src/core/loader/nro.cpp2
-rw-r--r--src/core/loader/nso.cpp2
-rw-r--r--src/core/memory.cpp151
-rw-r--r--src/core/memory.h13
-rw-r--r--src/core/memory/cheat_engine.cpp2
-rw-r--r--src/core/reporter.cpp4
-rw-r--r--src/shader_recompiler/ir_opt/ssa_rewrite_pass.cpp11
-rw-r--r--src/video_core/buffer_cache/buffer_cache.h10
-rw-r--r--src/video_core/buffer_cache/buffer_cache_base.h2
-rw-r--r--src/video_core/query_cache.h4
-rw-r--r--src/video_core/rasterizer_accelerated.cpp5
-rw-r--r--src/video_core/rasterizer_accelerated.h3
-rw-r--r--src/video_core/renderer_base.cpp4
-rw-r--r--src/video_core/renderer_opengl/gl_graphics_pipeline.cpp15
-rw-r--r--src/video_core/renderer_opengl/gl_shader_cache.cpp8
-rw-r--r--src/video_core/renderer_vulkan/vk_buffer_cache.cpp33
-rw-r--r--src/video_core/renderer_vulkan/vk_pipeline_cache.cpp12
-rw-r--r--src/video_core/renderer_vulkan/vk_query_cache.cpp11
-rw-r--r--src/video_core/renderer_vulkan/vk_texture_cache.cpp6
-rw-r--r--src/web_service/announce_room_json.cpp10
-rw-r--r--src/yuzu/game_list_worker.cpp8
85 files changed, 625 insertions, 460 deletions
diff --git a/src/android/app/src/main/jni/native.cpp b/src/android/app/src/main/jni/native.cpp
index 8bc6a4a04..c23b2f19e 100644
--- a/src/android/app/src/main/jni/native.cpp
+++ b/src/android/app/src/main/jni/native.cpp
@@ -449,7 +449,7 @@ private:
449 loader->ReadTitle(entry.title); 449 loader->ReadTitle(entry.title);
450 loader->ReadIcon(entry.icon); 450 loader->ReadIcon(entry.icon);
451 if (loader->GetFileType() == Loader::FileType::NRO) { 451 if (loader->GetFileType() == Loader::FileType::NRO) {
452 jauto loader_nro = dynamic_cast<Loader::AppLoader_NRO*>(loader.get()); 452 jauto loader_nro = reinterpret_cast<Loader::AppLoader_NRO*>(loader.get());
453 entry.isHomebrew = loader_nro->IsHomebrew(); 453 entry.isHomebrew = loader_nro->IsHomebrew();
454 } else { 454 } else {
455 entry.isHomebrew = false; 455 entry.isHomebrew = false;
diff --git a/src/common/demangle.cpp b/src/common/demangle.cpp
index 3310faf86..6e117cb41 100644
--- a/src/common/demangle.cpp
+++ b/src/common/demangle.cpp
@@ -23,7 +23,7 @@ std::string DemangleSymbol(const std::string& mangled) {
23 SCOPE_EXIT({ std::free(demangled); }); 23 SCOPE_EXIT({ std::free(demangled); });
24 24
25 if (is_itanium(mangled)) { 25 if (is_itanium(mangled)) {
26 demangled = llvm::itaniumDemangle(mangled.c_str(), nullptr, nullptr, nullptr); 26 demangled = llvm::itaniumDemangle(mangled.c_str());
27 } 27 }
28 28
29 if (!demangled) { 29 if (!demangled) {
diff --git a/src/common/detached_tasks.cpp b/src/common/detached_tasks.cpp
index da64848da..f2ed795cc 100644
--- a/src/common/detached_tasks.cpp
+++ b/src/common/detached_tasks.cpp
@@ -30,8 +30,8 @@ DetachedTasks::~DetachedTasks() {
30void DetachedTasks::AddTask(std::function<void()> task) { 30void DetachedTasks::AddTask(std::function<void()> task) {
31 std::unique_lock lock{instance->mutex}; 31 std::unique_lock lock{instance->mutex};
32 ++instance->count; 32 ++instance->count;
33 std::thread([task{std::move(task)}]() { 33 std::thread([task_{std::move(task)}]() {
34 task(); 34 task_();
35 std::unique_lock thread_lock{instance->mutex}; 35 std::unique_lock thread_lock{instance->mutex};
36 --instance->count; 36 --instance->count;
37 std::notify_all_at_thread_exit(instance->cv, std::move(thread_lock)); 37 std::notify_all_at_thread_exit(instance->cv, std::move(thread_lock));
diff --git a/src/common/page_table.h b/src/common/page_table.h
index fec8378f3..e653d52ad 100644
--- a/src/common/page_table.h
+++ b/src/common/page_table.h
@@ -51,7 +51,7 @@ struct PageTable {
51 class PageInfo { 51 class PageInfo {
52 public: 52 public:
53 /// Returns the page pointer 53 /// Returns the page pointer
54 [[nodiscard]] u8* Pointer() const noexcept { 54 [[nodiscard]] uintptr_t Pointer() const noexcept {
55 return ExtractPointer(raw.load(std::memory_order_relaxed)); 55 return ExtractPointer(raw.load(std::memory_order_relaxed));
56 } 56 }
57 57
@@ -61,7 +61,7 @@ struct PageTable {
61 } 61 }
62 62
63 /// Returns the page pointer and attribute pair, extracted from the same atomic read 63 /// Returns the page pointer and attribute pair, extracted from the same atomic read
64 [[nodiscard]] std::pair<u8*, PageType> PointerType() const noexcept { 64 [[nodiscard]] std::pair<uintptr_t, PageType> PointerType() const noexcept {
65 const uintptr_t non_atomic_raw = raw.load(std::memory_order_relaxed); 65 const uintptr_t non_atomic_raw = raw.load(std::memory_order_relaxed);
66 return {ExtractPointer(non_atomic_raw), ExtractType(non_atomic_raw)}; 66 return {ExtractPointer(non_atomic_raw), ExtractType(non_atomic_raw)};
67 } 67 }
@@ -73,13 +73,13 @@ struct PageTable {
73 } 73 }
74 74
75 /// Write a page pointer and type pair atomically 75 /// Write a page pointer and type pair atomically
76 void Store(u8* pointer, PageType type) noexcept { 76 void Store(uintptr_t pointer, PageType type) noexcept {
77 raw.store(reinterpret_cast<uintptr_t>(pointer) | static_cast<uintptr_t>(type)); 77 raw.store(pointer | static_cast<uintptr_t>(type));
78 } 78 }
79 79
80 /// Unpack a pointer from a page info raw representation 80 /// Unpack a pointer from a page info raw representation
81 [[nodiscard]] static u8* ExtractPointer(uintptr_t raw) noexcept { 81 [[nodiscard]] static uintptr_t ExtractPointer(uintptr_t raw) noexcept {
82 return reinterpret_cast<u8*>(raw & (~uintptr_t{0} << ATTRIBUTE_BITS)); 82 return raw & (~uintptr_t{0} << ATTRIBUTE_BITS);
83 } 83 }
84 84
85 /// Unpack a page type from a page info raw representation 85 /// Unpack a page type from a page info raw representation
diff --git a/src/common/settings.cpp b/src/common/settings.cpp
index 5972480e5..d4e55f988 100644
--- a/src/common/settings.cpp
+++ b/src/common/settings.cpp
@@ -26,7 +26,8 @@ std::string GetTimeZoneString() {
26 26
27 std::string location_name; 27 std::string location_name;
28 if (time_zone_index == 0) { // Auto 28 if (time_zone_index == 0) { // Auto
29#if __cpp_lib_chrono >= 201907L 29#if __cpp_lib_chrono >= 201907L && !defined(MINGW)
30 // Disabled for MinGW -- tzdb always returns Etc/UTC
30 try { 31 try {
31 const struct std::chrono::tzdb& time_zone_data = std::chrono::get_tzdb(); 32 const struct std::chrono::tzdb& time_zone_data = std::chrono::get_tzdb();
32 const std::chrono::time_zone* current_zone = time_zone_data.current_zone(); 33 const std::chrono::time_zone* current_zone = time_zone_data.current_zone();
diff --git a/src/common/time_zone.cpp b/src/common/time_zone.cpp
index d8d7896c6..69e728a9d 100644
--- a/src/common/time_zone.cpp
+++ b/src/common/time_zone.cpp
@@ -4,13 +4,13 @@
4#include <chrono> 4#include <chrono>
5#include <exception> 5#include <exception>
6#include <iomanip> 6#include <iomanip>
7#include <map>
7#include <sstream> 8#include <sstream>
8#include <stdexcept> 9#include <stdexcept>
9#include <fmt/chrono.h> 10#include <fmt/chrono.h>
10#include <fmt/core.h> 11#include <fmt/core.h>
11 12
12#include "common/logging/log.h" 13#include "common/logging/log.h"
13#include "common/settings.h"
14#include "common/time_zone.h" 14#include "common/time_zone.h"
15 15
16namespace Common::TimeZone { 16namespace Common::TimeZone {
@@ -33,32 +33,29 @@ std::string GetDefaultTimeZone() {
33 return "GMT"; 33 return "GMT";
34} 34}
35 35
36static std::string GetOsTimeZoneOffset() { 36// Results are not comparable to seconds since Epoch
37 const std::time_t t{std::time(nullptr)}; 37static std::time_t TmSpecToSeconds(const struct std::tm& spec) {
38 const std::tm tm{*std::localtime(&t)}; 38 const int year = spec.tm_year - 1; // Years up to now
39 39 const int leap_years = year / 4 - year / 100;
40 return fmt::format("{:%z}", tm); 40 std::time_t cumulative = spec.tm_year;
41} 41 cumulative = cumulative * 365 + leap_years + spec.tm_yday; // Years to days
42 42 cumulative = cumulative * 24 + spec.tm_hour; // Days to hours
43static int ConvertOsTimeZoneOffsetToInt(const std::string& timezone) { 43 cumulative = cumulative * 60 + spec.tm_min; // Hours to minutes
44 try { 44 cumulative = cumulative * 60 + spec.tm_sec; // Minutes to seconds
45 return std::stoi(timezone); 45 return cumulative;
46 } catch (const std::invalid_argument&) {
47 LOG_CRITICAL(Common, "invalid_argument with {}!", timezone);
48 return 0;
49 } catch (const std::out_of_range&) {
50 LOG_CRITICAL(Common, "out_of_range with {}!", timezone);
51 return 0;
52 }
53} 46}
54 47
55std::chrono::seconds GetCurrentOffsetSeconds() { 48std::chrono::seconds GetCurrentOffsetSeconds() {
56 const int offset{ConvertOsTimeZoneOffsetToInt(GetOsTimeZoneOffset())}; 49 const std::time_t t{std::time(nullptr)};
50 const std::tm local{*std::localtime(&t)};
51 const std::tm gmt{*std::gmtime(&t)};
57 52
58 int seconds{(offset / 100) * 60 * 60}; // Convert hour component to seconds 53 // gmt_seconds is a different offset than time(nullptr)
59 seconds += (offset % 100) * 60; // Convert minute component to seconds 54 const auto gmt_seconds = TmSpecToSeconds(gmt);
55 const auto local_seconds = TmSpecToSeconds(local);
56 const auto seconds_offset = local_seconds - gmt_seconds;
60 57
61 return std::chrono::seconds{seconds}; 58 return std::chrono::seconds{seconds_offset};
62} 59}
63 60
64// Key is [Hours * 100 + Minutes], multiplied by 100 if DST 61// Key is [Hours * 100 + Minutes], multiplied by 100 if DST
@@ -71,11 +68,6 @@ const static std::map<s64, const char*> off_timezones = {
71}; 68};
72 69
73std::string FindSystemTimeZone() { 70std::string FindSystemTimeZone() {
74#if defined(MINGW)
75 // MinGW has broken strftime -- https://sourceforge.net/p/mingw-w64/bugs/793/
76 // e.g. fmt::format("{:%z}") -- returns "Eastern Daylight Time" when it should be "-0400"
77 return timezones[0];
78#else
79 const s64 seconds = static_cast<s64>(GetCurrentOffsetSeconds().count()); 71 const s64 seconds = static_cast<s64>(GetCurrentOffsetSeconds().count());
80 72
81 const s64 minutes = seconds / 60; 73 const s64 minutes = seconds / 60;
@@ -97,7 +89,6 @@ std::string FindSystemTimeZone() {
97 } 89 }
98 } 90 }
99 return fmt::format("Etc/GMT{:s}{:d}", hours > 0 ? "-" : "+", std::abs(hours)); 91 return fmt::format("Etc/GMT{:s}{:d}", hours > 0 ? "-" : "+", std::abs(hours));
100#endif
101} 92}
102 93
103} // namespace Common::TimeZone 94} // namespace Common::TimeZone
diff --git a/src/core/arm/arm_interface.cpp b/src/core/arm/arm_interface.cpp
index aa0eb9791..0c012f094 100644
--- a/src/core/arm/arm_interface.cpp
+++ b/src/core/arm/arm_interface.cpp
@@ -217,8 +217,8 @@ void ARM_Interface::Run() {
217 } 217 }
218} 218}
219 219
220void ARM_Interface::LoadWatchpointArray(const WatchpointArray& wp) { 220void ARM_Interface::LoadWatchpointArray(const WatchpointArray* wp) {
221 watchpoints = &wp; 221 watchpoints = wp;
222} 222}
223 223
224const Kernel::DebugWatchpoint* ARM_Interface::MatchingWatchpoint( 224const Kernel::DebugWatchpoint* ARM_Interface::MatchingWatchpoint(
diff --git a/src/core/arm/arm_interface.h b/src/core/arm/arm_interface.h
index d5f2fa09a..3d866ff6f 100644
--- a/src/core/arm/arm_interface.h
+++ b/src/core/arm/arm_interface.h
@@ -186,7 +186,7 @@ public:
186 virtual void SaveContext(ThreadContext64& ctx) const = 0; 186 virtual void SaveContext(ThreadContext64& ctx) const = 0;
187 virtual void LoadContext(const ThreadContext32& ctx) = 0; 187 virtual void LoadContext(const ThreadContext32& ctx) = 0;
188 virtual void LoadContext(const ThreadContext64& ctx) = 0; 188 virtual void LoadContext(const ThreadContext64& ctx) = 0;
189 void LoadWatchpointArray(const WatchpointArray& wp); 189 void LoadWatchpointArray(const WatchpointArray* wp);
190 190
191 /// Clears the exclusive monitor's state. 191 /// Clears the exclusive monitor's state.
192 virtual void ClearExclusiveState() = 0; 192 virtual void ClearExclusiveState() = 0;
diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.cpp b/src/core/arm/dynarmic/arm_dynarmic_32.cpp
index 3b82fb73c..c97158a71 100644
--- a/src/core/arm/dynarmic/arm_dynarmic_32.cpp
+++ b/src/core/arm/dynarmic/arm_dynarmic_32.cpp
@@ -346,11 +346,11 @@ void ARM_Dynarmic_32::RewindBreakpointInstruction() {
346} 346}
347 347
348ARM_Dynarmic_32::ARM_Dynarmic_32(System& system_, bool uses_wall_clock_, 348ARM_Dynarmic_32::ARM_Dynarmic_32(System& system_, bool uses_wall_clock_,
349 ExclusiveMonitor& exclusive_monitor_, std::size_t core_index_) 349 DynarmicExclusiveMonitor& exclusive_monitor_,
350 std::size_t core_index_)
350 : ARM_Interface{system_, uses_wall_clock_}, cb(std::make_unique<DynarmicCallbacks32>(*this)), 351 : ARM_Interface{system_, uses_wall_clock_}, cb(std::make_unique<DynarmicCallbacks32>(*this)),
351 cp15(std::make_shared<DynarmicCP15>(*this)), core_index{core_index_}, 352 cp15(std::make_shared<DynarmicCP15>(*this)), core_index{core_index_},
352 exclusive_monitor{dynamic_cast<DynarmicExclusiveMonitor&>(exclusive_monitor_)}, 353 exclusive_monitor{exclusive_monitor_}, null_jit{MakeJit(nullptr)}, jit{null_jit.get()} {}
353 null_jit{MakeJit(nullptr)}, jit{null_jit.get()} {}
354 354
355ARM_Dynarmic_32::~ARM_Dynarmic_32() = default; 355ARM_Dynarmic_32::~ARM_Dynarmic_32() = default;
356 356
diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.h b/src/core/arm/dynarmic/arm_dynarmic_32.h
index a990845cb..92fb3f836 100644
--- a/src/core/arm/dynarmic/arm_dynarmic_32.h
+++ b/src/core/arm/dynarmic/arm_dynarmic_32.h
@@ -12,7 +12,7 @@
12#include "common/common_types.h" 12#include "common/common_types.h"
13#include "common/hash.h" 13#include "common/hash.h"
14#include "core/arm/arm_interface.h" 14#include "core/arm/arm_interface.h"
15#include "core/arm/exclusive_monitor.h" 15#include "core/arm/dynarmic/dynarmic_exclusive_monitor.h"
16 16
17namespace Core::Memory { 17namespace Core::Memory {
18class Memory; 18class Memory;
@@ -28,8 +28,8 @@ class System;
28 28
29class ARM_Dynarmic_32 final : public ARM_Interface { 29class ARM_Dynarmic_32 final : public ARM_Interface {
30public: 30public:
31 ARM_Dynarmic_32(System& system_, bool uses_wall_clock_, ExclusiveMonitor& exclusive_monitor_, 31 ARM_Dynarmic_32(System& system_, bool uses_wall_clock_,
32 std::size_t core_index_); 32 DynarmicExclusiveMonitor& exclusive_monitor_, std::size_t core_index_);
33 ~ARM_Dynarmic_32() override; 33 ~ARM_Dynarmic_32() override;
34 34
35 void SetPC(u64 pc) override; 35 void SetPC(u64 pc) override;
diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.cpp b/src/core/arm/dynarmic/arm_dynarmic_64.cpp
index bb97ed5bc..791d466ca 100644
--- a/src/core/arm/dynarmic/arm_dynarmic_64.cpp
+++ b/src/core/arm/dynarmic/arm_dynarmic_64.cpp
@@ -405,11 +405,11 @@ void ARM_Dynarmic_64::RewindBreakpointInstruction() {
405} 405}
406 406
407ARM_Dynarmic_64::ARM_Dynarmic_64(System& system_, bool uses_wall_clock_, 407ARM_Dynarmic_64::ARM_Dynarmic_64(System& system_, bool uses_wall_clock_,
408 ExclusiveMonitor& exclusive_monitor_, std::size_t core_index_) 408 DynarmicExclusiveMonitor& exclusive_monitor_,
409 std::size_t core_index_)
409 : ARM_Interface{system_, uses_wall_clock_}, 410 : ARM_Interface{system_, uses_wall_clock_},
410 cb(std::make_unique<DynarmicCallbacks64>(*this)), core_index{core_index_}, 411 cb(std::make_unique<DynarmicCallbacks64>(*this)), core_index{core_index_},
411 exclusive_monitor{dynamic_cast<DynarmicExclusiveMonitor&>(exclusive_monitor_)}, 412 exclusive_monitor{exclusive_monitor_}, null_jit{MakeJit(nullptr, 48)}, jit{null_jit.get()} {}
412 null_jit{MakeJit(nullptr, 48)}, jit{null_jit.get()} {}
413 413
414ARM_Dynarmic_64::~ARM_Dynarmic_64() = default; 414ARM_Dynarmic_64::~ARM_Dynarmic_64() = default;
415 415
diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.h b/src/core/arm/dynarmic/arm_dynarmic_64.h
index af2aa1f1c..2b88a08e2 100644
--- a/src/core/arm/dynarmic/arm_dynarmic_64.h
+++ b/src/core/arm/dynarmic/arm_dynarmic_64.h
@@ -11,7 +11,7 @@
11#include "common/common_types.h" 11#include "common/common_types.h"
12#include "common/hash.h" 12#include "common/hash.h"
13#include "core/arm/arm_interface.h" 13#include "core/arm/arm_interface.h"
14#include "core/arm/exclusive_monitor.h" 14#include "core/arm/dynarmic/dynarmic_exclusive_monitor.h"
15 15
16namespace Core::Memory { 16namespace Core::Memory {
17class Memory; 17class Memory;
@@ -25,8 +25,8 @@ class System;
25 25
26class ARM_Dynarmic_64 final : public ARM_Interface { 26class ARM_Dynarmic_64 final : public ARM_Interface {
27public: 27public:
28 ARM_Dynarmic_64(System& system_, bool uses_wall_clock_, ExclusiveMonitor& exclusive_monitor_, 28 ARM_Dynarmic_64(System& system_, bool uses_wall_clock_,
29 std::size_t core_index_); 29 DynarmicExclusiveMonitor& exclusive_monitor_, std::size_t core_index_);
30 ~ARM_Dynarmic_64() override; 30 ~ARM_Dynarmic_64() override;
31 31
32 void SetPC(u64 pc) override; 32 void SetPC(u64 pc) override;
diff --git a/src/core/arm/dynarmic/dynarmic_exclusive_monitor.h b/src/core/arm/dynarmic/dynarmic_exclusive_monitor.h
index 57e6dd0d0..fbfcd8d95 100644
--- a/src/core/arm/dynarmic/dynarmic_exclusive_monitor.h
+++ b/src/core/arm/dynarmic/dynarmic_exclusive_monitor.h
@@ -6,8 +6,6 @@
6#include <dynarmic/interface/exclusive_monitor.h> 6#include <dynarmic/interface/exclusive_monitor.h>
7 7
8#include "common/common_types.h" 8#include "common/common_types.h"
9#include "core/arm/dynarmic/arm_dynarmic_32.h"
10#include "core/arm/dynarmic/arm_dynarmic_64.h"
11#include "core/arm/exclusive_monitor.h" 9#include "core/arm/exclusive_monitor.h"
12 10
13namespace Core::Memory { 11namespace Core::Memory {
@@ -16,6 +14,9 @@ class Memory;
16 14
17namespace Core { 15namespace Core {
18 16
17class ARM_Dynarmic_32;
18class ARM_Dynarmic_64;
19
19class DynarmicExclusiveMonitor final : public ExclusiveMonitor { 20class DynarmicExclusiveMonitor final : public ExclusiveMonitor {
20public: 21public:
21 explicit DynarmicExclusiveMonitor(Memory::Memory& memory_, std::size_t core_count_); 22 explicit DynarmicExclusiveMonitor(Memory::Memory& memory_, std::size_t core_count_);
diff --git a/src/core/core.cpp b/src/core/core.cpp
index 9e3eb3795..48233d7c8 100644
--- a/src/core/core.cpp
+++ b/src/core/core.cpp
@@ -880,6 +880,14 @@ const FileSys::ContentProvider& System::GetContentProvider() const {
880 return *impl->content_provider; 880 return *impl->content_provider;
881} 881}
882 882
883FileSys::ContentProviderUnion& System::GetContentProviderUnion() {
884 return *impl->content_provider;
885}
886
887const FileSys::ContentProviderUnion& System::GetContentProviderUnion() const {
888 return *impl->content_provider;
889}
890
883Service::FileSystem::FileSystemController& System::GetFileSystemController() { 891Service::FileSystem::FileSystemController& System::GetFileSystemController() {
884 return impl->fs_controller; 892 return impl->fs_controller;
885} 893}
diff --git a/src/core/core.h b/src/core/core.h
index 14b2f7785..c70ea1965 100644
--- a/src/core/core.h
+++ b/src/core/core.h
@@ -381,6 +381,9 @@ public:
381 [[nodiscard]] FileSys::ContentProvider& GetContentProvider(); 381 [[nodiscard]] FileSys::ContentProvider& GetContentProvider();
382 [[nodiscard]] const FileSys::ContentProvider& GetContentProvider() const; 382 [[nodiscard]] const FileSys::ContentProvider& GetContentProvider() const;
383 383
384 [[nodiscard]] FileSys::ContentProviderUnion& GetContentProviderUnion();
385 [[nodiscard]] const FileSys::ContentProviderUnion& GetContentProviderUnion() const;
386
384 [[nodiscard]] Service::FileSystem::FileSystemController& GetFileSystemController(); 387 [[nodiscard]] Service::FileSystem::FileSystemController& GetFileSystemController();
385 [[nodiscard]] const Service::FileSystem::FileSystemController& GetFileSystemController() const; 388 [[nodiscard]] const Service::FileSystem::FileSystemController& GetFileSystemController() const;
386 389
diff --git a/src/core/debugger/gdbstub.cpp b/src/core/debugger/gdbstub.cpp
index e2a13bbd2..0f839d5b4 100644
--- a/src/core/debugger/gdbstub.cpp
+++ b/src/core/debugger/gdbstub.cpp
@@ -261,10 +261,8 @@ void GDBStub::ExecuteCommand(std::string_view packet, std::vector<DebuggerAction
261 const size_t addr{static_cast<size_t>(strtoll(command.data(), nullptr, 16))}; 261 const size_t addr{static_cast<size_t>(strtoll(command.data(), nullptr, 16))};
262 const size_t size{static_cast<size_t>(strtoll(command.data() + sep, nullptr, 16))}; 262 const size_t size{static_cast<size_t>(strtoll(command.data() + sep, nullptr, 16))};
263 263
264 if (system.ApplicationMemory().IsValidVirtualAddressRange(addr, size)) { 264 std::vector<u8> mem(size);
265 std::vector<u8> mem(size); 265 if (system.ApplicationMemory().ReadBlock(addr, mem.data(), size)) {
266 system.ApplicationMemory().ReadBlock(addr, mem.data(), size);
267
268 SendReply(Common::HexToString(mem)); 266 SendReply(Common::HexToString(mem));
269 } else { 267 } else {
270 SendReply(GDB_STUB_REPLY_ERR); 268 SendReply(GDB_STUB_REPLY_ERR);
@@ -281,8 +279,7 @@ void GDBStub::ExecuteCommand(std::string_view packet, std::vector<DebuggerAction
281 const auto mem_substr{std::string_view(command).substr(mem_sep)}; 279 const auto mem_substr{std::string_view(command).substr(mem_sep)};
282 const auto mem{Common::HexStringToVector(mem_substr, false)}; 280 const auto mem{Common::HexStringToVector(mem_substr, false)};
283 281
284 if (system.ApplicationMemory().IsValidVirtualAddressRange(addr, size)) { 282 if (system.ApplicationMemory().WriteBlock(addr, mem.data(), size)) {
285 system.ApplicationMemory().WriteBlock(addr, mem.data(), size);
286 system.InvalidateCpuInstructionCacheRange(addr, size); 283 system.InvalidateCpuInstructionCacheRange(addr, size);
287 SendReply(GDB_STUB_REPLY_OK); 284 SendReply(GDB_STUB_REPLY_OK);
288 } else { 285 } else {
@@ -556,7 +553,7 @@ void GDBStub::HandleQuery(std::string_view command) {
556 } else { 553 } else {
557 SendReply(fmt::format( 554 SendReply(fmt::format(
558 "TextSeg={:x}", 555 "TextSeg={:x}",
559 GetInteger(system.ApplicationProcess()->PageTable().GetCodeRegionStart()))); 556 GetInteger(system.ApplicationProcess()->GetPageTable().GetCodeRegionStart())));
560 } 557 }
561 } else if (command.starts_with("Xfer:libraries:read::")) { 558 } else if (command.starts_with("Xfer:libraries:read::")) {
562 Loader::AppLoader::Modules modules; 559 Loader::AppLoader::Modules modules;
@@ -731,7 +728,7 @@ void GDBStub::HandleRcmd(const std::vector<u8>& command) {
731 std::string reply; 728 std::string reply;
732 729
733 auto* process = system.ApplicationProcess(); 730 auto* process = system.ApplicationProcess();
734 auto& page_table = process->PageTable(); 731 auto& page_table = process->GetPageTable();
735 732
736 const char* commands = "Commands:\n" 733 const char* commands = "Commands:\n"
737 " get fastmem\n" 734 " get fastmem\n"
diff --git a/src/core/hle/kernel/k_auto_object.cpp b/src/core/hle/kernel/k_auto_object.cpp
index 0ae42c95c..9cd7a9fd5 100644
--- a/src/core/hle/kernel/k_auto_object.cpp
+++ b/src/core/hle/kernel/k_auto_object.cpp
@@ -15,8 +15,8 @@ void KAutoObject::RegisterWithKernel() {
15 m_kernel.RegisterKernelObject(this); 15 m_kernel.RegisterKernelObject(this);
16} 16}
17 17
18void KAutoObject::UnregisterWithKernel() { 18void KAutoObject::UnregisterWithKernel(KernelCore& kernel, KAutoObject* self) {
19 m_kernel.UnregisterKernelObject(this); 19 kernel.UnregisterKernelObject(self);
20} 20}
21 21
22} // namespace Kernel 22} // namespace Kernel
diff --git a/src/core/hle/kernel/k_auto_object.h b/src/core/hle/kernel/k_auto_object.h
index f384b1568..8d4e0df44 100644
--- a/src/core/hle/kernel/k_auto_object.h
+++ b/src/core/hle/kernel/k_auto_object.h
@@ -159,14 +159,15 @@ public:
159 159
160 // If ref count hits zero, destroy the object. 160 // If ref count hits zero, destroy the object.
161 if (cur_ref_count - 1 == 0) { 161 if (cur_ref_count - 1 == 0) {
162 KernelCore& kernel = m_kernel;
162 this->Destroy(); 163 this->Destroy();
163 this->UnregisterWithKernel(); 164 KAutoObject::UnregisterWithKernel(kernel, this);
164 } 165 }
165 } 166 }
166 167
167private: 168private:
168 void RegisterWithKernel(); 169 void RegisterWithKernel();
169 void UnregisterWithKernel(); 170 static void UnregisterWithKernel(KernelCore& kernel, KAutoObject* self);
170 171
171protected: 172protected:
172 KernelCore& m_kernel; 173 KernelCore& m_kernel;
diff --git a/src/core/hle/kernel/k_code_memory.cpp b/src/core/hle/kernel/k_code_memory.cpp
index 3583bee44..7454be55c 100644
--- a/src/core/hle/kernel/k_code_memory.cpp
+++ b/src/core/hle/kernel/k_code_memory.cpp
@@ -25,7 +25,7 @@ Result KCodeMemory::Initialize(Core::DeviceMemory& device_memory, KProcessAddres
25 m_owner = GetCurrentProcessPointer(m_kernel); 25 m_owner = GetCurrentProcessPointer(m_kernel);
26 26
27 // Get the owner page table. 27 // Get the owner page table.
28 auto& page_table = m_owner->PageTable(); 28 auto& page_table = m_owner->GetPageTable();
29 29
30 // Construct the page group. 30 // Construct the page group.
31 m_page_group.emplace(m_kernel, page_table.GetBlockInfoManager()); 31 m_page_group.emplace(m_kernel, page_table.GetBlockInfoManager());
@@ -53,7 +53,7 @@ void KCodeMemory::Finalize() {
53 // Unlock. 53 // Unlock.
54 if (!m_is_mapped && !m_is_owner_mapped) { 54 if (!m_is_mapped && !m_is_owner_mapped) {
55 const size_t size = m_page_group->GetNumPages() * PageSize; 55 const size_t size = m_page_group->GetNumPages() * PageSize;
56 m_owner->PageTable().UnlockForCodeMemory(m_address, size, *m_page_group); 56 m_owner->GetPageTable().UnlockForCodeMemory(m_address, size, *m_page_group);
57 } 57 }
58 58
59 // Close the page group. 59 // Close the page group.
@@ -75,7 +75,7 @@ Result KCodeMemory::Map(KProcessAddress address, size_t size) {
75 R_UNLESS(!m_is_mapped, ResultInvalidState); 75 R_UNLESS(!m_is_mapped, ResultInvalidState);
76 76
77 // Map the memory. 77 // Map the memory.
78 R_TRY(GetCurrentProcess(m_kernel).PageTable().MapPageGroup( 78 R_TRY(GetCurrentProcess(m_kernel).GetPageTable().MapPageGroup(
79 address, *m_page_group, KMemoryState::CodeOut, KMemoryPermission::UserReadWrite)); 79 address, *m_page_group, KMemoryState::CodeOut, KMemoryPermission::UserReadWrite));
80 80
81 // Mark ourselves as mapped. 81 // Mark ourselves as mapped.
@@ -92,8 +92,8 @@ Result KCodeMemory::Unmap(KProcessAddress address, size_t size) {
92 KScopedLightLock lk(m_lock); 92 KScopedLightLock lk(m_lock);
93 93
94 // Unmap the memory. 94 // Unmap the memory.
95 R_TRY(GetCurrentProcess(m_kernel).PageTable().UnmapPageGroup(address, *m_page_group, 95 R_TRY(GetCurrentProcess(m_kernel).GetPageTable().UnmapPageGroup(address, *m_page_group,
96 KMemoryState::CodeOut)); 96 KMemoryState::CodeOut));
97 97
98 // Mark ourselves as unmapped. 98 // Mark ourselves as unmapped.
99 m_is_mapped = false; 99 m_is_mapped = false;
@@ -126,8 +126,8 @@ Result KCodeMemory::MapToOwner(KProcessAddress address, size_t size, Svc::Memory
126 } 126 }
127 127
128 // Map the memory. 128 // Map the memory.
129 R_TRY(m_owner->PageTable().MapPageGroup(address, *m_page_group, KMemoryState::GeneratedCode, 129 R_TRY(m_owner->GetPageTable().MapPageGroup(address, *m_page_group, KMemoryState::GeneratedCode,
130 k_perm)); 130 k_perm));
131 131
132 // Mark ourselves as mapped. 132 // Mark ourselves as mapped.
133 m_is_owner_mapped = true; 133 m_is_owner_mapped = true;
@@ -143,7 +143,8 @@ Result KCodeMemory::UnmapFromOwner(KProcessAddress address, size_t size) {
143 KScopedLightLock lk(m_lock); 143 KScopedLightLock lk(m_lock);
144 144
145 // Unmap the memory. 145 // Unmap the memory.
146 R_TRY(m_owner->PageTable().UnmapPageGroup(address, *m_page_group, KMemoryState::GeneratedCode)); 146 R_TRY(m_owner->GetPageTable().UnmapPageGroup(address, *m_page_group,
147 KMemoryState::GeneratedCode));
147 148
148 // Mark ourselves as unmapped. 149 // Mark ourselves as unmapped.
149 m_is_owner_mapped = false; 150 m_is_owner_mapped = false;
diff --git a/src/core/hle/kernel/k_page_table.h b/src/core/hle/kernel/k_page_table.h
index 022d15f35..b9e8c6042 100644
--- a/src/core/hle/kernel/k_page_table.h
+++ b/src/core/hle/kernel/k_page_table.h
@@ -388,39 +388,6 @@ public:
388 constexpr size_t GetHeapSize() const { 388 constexpr size_t GetHeapSize() const {
389 return m_current_heap_end - m_heap_region_start; 389 return m_current_heap_end - m_heap_region_start;
390 } 390 }
391 constexpr bool IsInsideAddressSpace(KProcessAddress address, size_t size) const {
392 return m_address_space_start <= address && address + size - 1 <= m_address_space_end - 1;
393 }
394 constexpr bool IsOutsideAliasRegion(KProcessAddress address, size_t size) const {
395 return m_alias_region_start > address || address + size - 1 > m_alias_region_end - 1;
396 }
397 constexpr bool IsOutsideStackRegion(KProcessAddress address, size_t size) const {
398 return m_stack_region_start > address || address + size - 1 > m_stack_region_end - 1;
399 }
400 constexpr bool IsInvalidRegion(KProcessAddress address, size_t size) const {
401 return address + size - 1 > GetAliasCodeRegionStart() + GetAliasCodeRegionSize() - 1;
402 }
403 constexpr bool IsInsideHeapRegion(KProcessAddress address, size_t size) const {
404 return address + size > m_heap_region_start && m_heap_region_end > address;
405 }
406 constexpr bool IsInsideAliasRegion(KProcessAddress address, size_t size) const {
407 return address + size > m_alias_region_start && m_alias_region_end > address;
408 }
409 constexpr bool IsOutsideASLRRegion(KProcessAddress address, size_t size) const {
410 if (IsInvalidRegion(address, size)) {
411 return true;
412 }
413 if (IsInsideHeapRegion(address, size)) {
414 return true;
415 }
416 if (IsInsideAliasRegion(address, size)) {
417 return true;
418 }
419 return {};
420 }
421 constexpr bool IsInsideASLRRegion(KProcessAddress address, size_t size) const {
422 return !IsOutsideASLRRegion(address, size);
423 }
424 constexpr size_t GetNumGuardPages() const { 391 constexpr size_t GetNumGuardPages() const {
425 return IsKernel() ? 1 : 4; 392 return IsKernel() ? 1 : 4;
426 } 393 }
@@ -436,6 +403,14 @@ public:
436 return m_address_space_start <= addr && addr < addr + size && 403 return m_address_space_start <= addr && addr < addr + size &&
437 addr + size - 1 <= m_address_space_end - 1; 404 addr + size - 1 <= m_address_space_end - 1;
438 } 405 }
406 constexpr bool IsInAliasRegion(KProcessAddress addr, size_t size) const {
407 return this->Contains(addr, size) && m_alias_region_start <= addr &&
408 addr + size - 1 <= m_alias_region_end - 1;
409 }
410 constexpr bool IsInHeapRegion(KProcessAddress addr, size_t size) const {
411 return this->Contains(addr, size) && m_heap_region_start <= addr &&
412 addr + size - 1 <= m_heap_region_end - 1;
413 }
439 414
440public: 415public:
441 static KVirtualAddress GetLinearMappedVirtualAddress(const KMemoryLayout& layout, 416 static KVirtualAddress GetLinearMappedVirtualAddress(const KMemoryLayout& layout,
diff --git a/src/core/hle/kernel/k_process.cpp b/src/core/hle/kernel/k_process.cpp
index efe86ad27..44c7cb22f 100644
--- a/src/core/hle/kernel/k_process.cpp
+++ b/src/core/hle/kernel/k_process.cpp
@@ -38,7 +38,7 @@ namespace {
38 */ 38 */
39void SetupMainThread(Core::System& system, KProcess& owner_process, u32 priority, 39void SetupMainThread(Core::System& system, KProcess& owner_process, u32 priority,
40 KProcessAddress stack_top) { 40 KProcessAddress stack_top) {
41 const KProcessAddress entry_point = owner_process.PageTable().GetCodeRegionStart(); 41 const KProcessAddress entry_point = owner_process.GetPageTable().GetCodeRegionStart();
42 ASSERT(owner_process.GetResourceLimit()->Reserve(LimitableResource::ThreadCountMax, 1)); 42 ASSERT(owner_process.GetResourceLimit()->Reserve(LimitableResource::ThreadCountMax, 1));
43 43
44 KThread* thread = KThread::Create(system.Kernel()); 44 KThread* thread = KThread::Create(system.Kernel());
diff --git a/src/core/hle/kernel/k_process.h b/src/core/hle/kernel/k_process.h
index 925981d06..c9b37e138 100644
--- a/src/core/hle/kernel/k_process.h
+++ b/src/core/hle/kernel/k_process.h
@@ -110,16 +110,6 @@ public:
110 ProcessType type, KResourceLimit* res_limit); 110 ProcessType type, KResourceLimit* res_limit);
111 111
112 /// Gets a reference to the process' page table. 112 /// Gets a reference to the process' page table.
113 KPageTable& PageTable() {
114 return m_page_table;
115 }
116
117 /// Gets const a reference to the process' page table.
118 const KPageTable& PageTable() const {
119 return m_page_table;
120 }
121
122 /// Gets a reference to the process' page table.
123 KPageTable& GetPageTable() { 113 KPageTable& GetPageTable() {
124 return m_page_table; 114 return m_page_table;
125 } 115 }
diff --git a/src/core/hle/kernel/k_scheduler.cpp b/src/core/hle/kernel/k_scheduler.cpp
index 75ce5a23c..d8143c650 100644
--- a/src/core/hle/kernel/k_scheduler.cpp
+++ b/src/core/hle/kernel/k_scheduler.cpp
@@ -510,11 +510,12 @@ void KScheduler::Unload(KThread* thread) {
510 510
511void KScheduler::Reload(KThread* thread) { 511void KScheduler::Reload(KThread* thread) {
512 auto& cpu_core = m_kernel.System().ArmInterface(m_core_id); 512 auto& cpu_core = m_kernel.System().ArmInterface(m_core_id);
513 auto* process = thread->GetOwnerProcess();
513 cpu_core.LoadContext(thread->GetContext32()); 514 cpu_core.LoadContext(thread->GetContext32());
514 cpu_core.LoadContext(thread->GetContext64()); 515 cpu_core.LoadContext(thread->GetContext64());
515 cpu_core.SetTlsAddress(GetInteger(thread->GetTlsAddress())); 516 cpu_core.SetTlsAddress(GetInteger(thread->GetTlsAddress()));
516 cpu_core.SetTPIDR_EL0(thread->GetTpidrEl0()); 517 cpu_core.SetTPIDR_EL0(thread->GetTpidrEl0());
517 cpu_core.LoadWatchpointArray(thread->GetOwnerProcess()->GetWatchpoints()); 518 cpu_core.LoadWatchpointArray(process ? &process->GetWatchpoints() : nullptr);
518 cpu_core.ClearExclusiveState(); 519 cpu_core.ClearExclusiveState();
519} 520}
520 521
diff --git a/src/core/hle/kernel/k_shared_memory.cpp b/src/core/hle/kernel/k_shared_memory.cpp
index efb5699de..f713968f6 100644
--- a/src/core/hle/kernel/k_shared_memory.cpp
+++ b/src/core/hle/kernel/k_shared_memory.cpp
@@ -90,8 +90,8 @@ Result KSharedMemory::Map(KProcess& target_process, KProcessAddress address, std
90 R_UNLESS(map_perm == test_perm, ResultInvalidNewMemoryPermission); 90 R_UNLESS(map_perm == test_perm, ResultInvalidNewMemoryPermission);
91 } 91 }
92 92
93 R_RETURN(target_process.PageTable().MapPageGroup(address, *m_page_group, KMemoryState::Shared, 93 R_RETURN(target_process.GetPageTable().MapPageGroup(
94 ConvertToKMemoryPermission(map_perm))); 94 address, *m_page_group, KMemoryState::Shared, ConvertToKMemoryPermission(map_perm)));
95} 95}
96 96
97Result KSharedMemory::Unmap(KProcess& target_process, KProcessAddress address, 97Result KSharedMemory::Unmap(KProcess& target_process, KProcessAddress address,
@@ -100,7 +100,7 @@ Result KSharedMemory::Unmap(KProcess& target_process, KProcessAddress address,
100 R_UNLESS(m_size == unmap_size, ResultInvalidSize); 100 R_UNLESS(m_size == unmap_size, ResultInvalidSize);
101 101
102 R_RETURN( 102 R_RETURN(
103 target_process.PageTable().UnmapPageGroup(address, *m_page_group, KMemoryState::Shared)); 103 target_process.GetPageTable().UnmapPageGroup(address, *m_page_group, KMemoryState::Shared));
104} 104}
105 105
106} // namespace Kernel 106} // namespace Kernel
diff --git a/src/core/hle/kernel/k_thread.cpp b/src/core/hle/kernel/k_thread.cpp
index adb6ec581..7df8fd7f7 100644
--- a/src/core/hle/kernel/k_thread.cpp
+++ b/src/core/hle/kernel/k_thread.cpp
@@ -129,7 +129,7 @@ Result KThread::Initialize(KThreadFunction func, uintptr_t arg, KProcessAddress
129 case ThreadType::User: 129 case ThreadType::User:
130 ASSERT(((owner == nullptr) || 130 ASSERT(((owner == nullptr) ||
131 (owner->GetCoreMask() | (1ULL << virt_core)) == owner->GetCoreMask())); 131 (owner->GetCoreMask() | (1ULL << virt_core)) == owner->GetCoreMask()));
132 ASSERT(((owner == nullptr) || 132 ASSERT(((owner == nullptr) || (prio > Svc::LowestThreadPriority) ||
133 (owner->GetPriorityMask() | (1ULL << prio)) == owner->GetPriorityMask())); 133 (owner->GetPriorityMask() | (1ULL << prio)) == owner->GetPriorityMask()));
134 break; 134 break;
135 case ThreadType::Kernel: 135 case ThreadType::Kernel:
@@ -302,12 +302,12 @@ Result KThread::InitializeServiceThread(Core::System& system, KThread* thread,
302 std::function<void()>&& func, s32 prio, s32 virt_core, 302 std::function<void()>&& func, s32 prio, s32 virt_core,
303 KProcess* owner) { 303 KProcess* owner) {
304 system.Kernel().GlobalSchedulerContext().AddThread(thread); 304 system.Kernel().GlobalSchedulerContext().AddThread(thread);
305 std::function<void()> func2{[&system, func{std::move(func)}] { 305 std::function<void()> func2{[&system, func_{std::move(func)}] {
306 // Similar to UserModeThreadStarter. 306 // Similar to UserModeThreadStarter.
307 system.Kernel().CurrentScheduler()->OnThreadStart(); 307 system.Kernel().CurrentScheduler()->OnThreadStart();
308 308
309 // Run the guest function. 309 // Run the guest function.
310 func(); 310 func_();
311 311
312 // Exit. 312 // Exit.
313 Svc::ExitThread(system); 313 Svc::ExitThread(system);
diff --git a/src/core/hle/kernel/k_thread_local_page.cpp b/src/core/hle/kernel/k_thread_local_page.cpp
index b4a1e3cdb..2c45b4232 100644
--- a/src/core/hle/kernel/k_thread_local_page.cpp
+++ b/src/core/hle/kernel/k_thread_local_page.cpp
@@ -25,9 +25,9 @@ Result KThreadLocalPage::Initialize(KernelCore& kernel, KProcess* process) {
25 25
26 // Map the address in. 26 // Map the address in.
27 const auto phys_addr = kernel.System().DeviceMemory().GetPhysicalAddr(page_buf); 27 const auto phys_addr = kernel.System().DeviceMemory().GetPhysicalAddr(page_buf);
28 R_TRY(m_owner->PageTable().MapPages(std::addressof(m_virt_addr), 1, PageSize, phys_addr, 28 R_TRY(m_owner->GetPageTable().MapPages(std::addressof(m_virt_addr), 1, PageSize, phys_addr,
29 KMemoryState::ThreadLocal, 29 KMemoryState::ThreadLocal,
30 KMemoryPermission::UserReadWrite)); 30 KMemoryPermission::UserReadWrite));
31 31
32 // We succeeded. 32 // We succeeded.
33 page_buf_guard.Cancel(); 33 page_buf_guard.Cancel();
@@ -37,11 +37,11 @@ Result KThreadLocalPage::Initialize(KernelCore& kernel, KProcess* process) {
37 37
38Result KThreadLocalPage::Finalize() { 38Result KThreadLocalPage::Finalize() {
39 // Get the physical address of the page. 39 // Get the physical address of the page.
40 const KPhysicalAddress phys_addr = m_owner->PageTable().GetPhysicalAddr(m_virt_addr); 40 const KPhysicalAddress phys_addr = m_owner->GetPageTable().GetPhysicalAddr(m_virt_addr);
41 ASSERT(phys_addr); 41 ASSERT(phys_addr);
42 42
43 // Unmap the page. 43 // Unmap the page.
44 R_TRY(m_owner->PageTable().UnmapPages(this->GetAddress(), 1, KMemoryState::ThreadLocal)); 44 R_TRY(m_owner->GetPageTable().UnmapPages(this->GetAddress(), 1, KMemoryState::ThreadLocal));
45 45
46 // Free the page. 46 // Free the page.
47 KPageBuffer::Free(*m_kernel, KPageBuffer::FromPhysicalAddress(m_kernel->System(), phys_addr)); 47 KPageBuffer::Free(*m_kernel, KPageBuffer::FromPhysicalAddress(m_kernel->System(), phys_addr));
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index f33600ca5..ebe7582c6 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -1089,15 +1089,15 @@ static std::jthread RunHostThreadFunc(KernelCore& kernel, KProcess* process,
1089 KThread::Register(kernel, thread); 1089 KThread::Register(kernel, thread);
1090 1090
1091 return std::jthread( 1091 return std::jthread(
1092 [&kernel, thread, thread_name{std::move(thread_name)}, func{std::move(func)}] { 1092 [&kernel, thread, thread_name_{std::move(thread_name)}, func_{std::move(func)}] {
1093 // Set the thread name. 1093 // Set the thread name.
1094 Common::SetCurrentThreadName(thread_name.c_str()); 1094 Common::SetCurrentThreadName(thread_name_.c_str());
1095 1095
1096 // Set the thread as current. 1096 // Set the thread as current.
1097 kernel.RegisterHostThread(thread); 1097 kernel.RegisterHostThread(thread);
1098 1098
1099 // Run the callback. 1099 // Run the callback.
1100 func(); 1100 func_();
1101 1101
1102 // Close the thread. 1102 // Close the thread.
1103 // This will free the process if it is the last reference. 1103 // This will free the process if it is the last reference.
diff --git a/src/core/hle/kernel/physical_core.cpp b/src/core/hle/kernel/physical_core.cpp
index 2e0c36129..5ee869fa2 100644
--- a/src/core/hle/kernel/physical_core.cpp
+++ b/src/core/hle/kernel/physical_core.cpp
@@ -17,7 +17,9 @@ PhysicalCore::PhysicalCore(std::size_t core_index, Core::System& system, KSchedu
17 // a 32-bit instance of Dynarmic. This should be abstracted out to a CPU manager. 17 // a 32-bit instance of Dynarmic. This should be abstracted out to a CPU manager.
18 auto& kernel = system.Kernel(); 18 auto& kernel = system.Kernel();
19 m_arm_interface = std::make_unique<Core::ARM_Dynarmic_64>( 19 m_arm_interface = std::make_unique<Core::ARM_Dynarmic_64>(
20 system, kernel.IsMulticore(), kernel.GetExclusiveMonitor(), m_core_index); 20 system, kernel.IsMulticore(),
21 reinterpret_cast<Core::DynarmicExclusiveMonitor&>(kernel.GetExclusiveMonitor()),
22 m_core_index);
21#else 23#else
22#error Platform not supported yet. 24#error Platform not supported yet.
23#endif 25#endif
@@ -31,7 +33,9 @@ void PhysicalCore::Initialize(bool is_64_bit) {
31 if (!is_64_bit) { 33 if (!is_64_bit) {
32 // We already initialized a 64-bit core, replace with a 32-bit one. 34 // We already initialized a 64-bit core, replace with a 32-bit one.
33 m_arm_interface = std::make_unique<Core::ARM_Dynarmic_32>( 35 m_arm_interface = std::make_unique<Core::ARM_Dynarmic_32>(
34 m_system, kernel.IsMulticore(), kernel.GetExclusiveMonitor(), m_core_index); 36 m_system, kernel.IsMulticore(),
37 reinterpret_cast<Core::DynarmicExclusiveMonitor&>(kernel.GetExclusiveMonitor()),
38 m_core_index);
35 } 39 }
36#else 40#else
37#error Platform not supported yet. 41#error Platform not supported yet.
diff --git a/src/core/hle/kernel/svc/svc_cache.cpp b/src/core/hle/kernel/svc/svc_cache.cpp
index 082942dab..c2c8be10f 100644
--- a/src/core/hle/kernel/svc/svc_cache.cpp
+++ b/src/core/hle/kernel/svc/svc_cache.cpp
@@ -42,7 +42,7 @@ Result FlushProcessDataCache(Core::System& system, Handle process_handle, u64 ad
42 R_UNLESS(process.IsNotNull(), ResultInvalidHandle); 42 R_UNLESS(process.IsNotNull(), ResultInvalidHandle);
43 43
44 // Verify the region is within range. 44 // Verify the region is within range.
45 auto& page_table = process->PageTable(); 45 auto& page_table = process->GetPageTable();
46 R_UNLESS(page_table.Contains(address, size), ResultInvalidCurrentMemory); 46 R_UNLESS(page_table.Contains(address, size), ResultInvalidCurrentMemory);
47 47
48 // Perform the operation. 48 // Perform the operation.
diff --git a/src/core/hle/kernel/svc/svc_code_memory.cpp b/src/core/hle/kernel/svc/svc_code_memory.cpp
index 687baff82..bae4cb0cd 100644
--- a/src/core/hle/kernel/svc/svc_code_memory.cpp
+++ b/src/core/hle/kernel/svc/svc_code_memory.cpp
@@ -48,7 +48,7 @@ Result CreateCodeMemory(Core::System& system, Handle* out, u64 address, uint64_t
48 SCOPE_EXIT({ code_mem->Close(); }); 48 SCOPE_EXIT({ code_mem->Close(); });
49 49
50 // Verify that the region is in range. 50 // Verify that the region is in range.
51 R_UNLESS(GetCurrentProcess(system.Kernel()).PageTable().Contains(address, size), 51 R_UNLESS(GetCurrentProcess(system.Kernel()).GetPageTable().Contains(address, size),
52 ResultInvalidCurrentMemory); 52 ResultInvalidCurrentMemory);
53 53
54 // Initialize the code memory. 54 // Initialize the code memory.
@@ -92,7 +92,7 @@ Result ControlCodeMemory(Core::System& system, Handle code_memory_handle,
92 case CodeMemoryOperation::Map: { 92 case CodeMemoryOperation::Map: {
93 // Check that the region is in range. 93 // Check that the region is in range.
94 R_UNLESS(GetCurrentProcess(system.Kernel()) 94 R_UNLESS(GetCurrentProcess(system.Kernel())
95 .PageTable() 95 .GetPageTable()
96 .CanContain(address, size, KMemoryState::CodeOut), 96 .CanContain(address, size, KMemoryState::CodeOut),
97 ResultInvalidMemoryRegion); 97 ResultInvalidMemoryRegion);
98 98
@@ -105,7 +105,7 @@ Result ControlCodeMemory(Core::System& system, Handle code_memory_handle,
105 case CodeMemoryOperation::Unmap: { 105 case CodeMemoryOperation::Unmap: {
106 // Check that the region is in range. 106 // Check that the region is in range.
107 R_UNLESS(GetCurrentProcess(system.Kernel()) 107 R_UNLESS(GetCurrentProcess(system.Kernel())
108 .PageTable() 108 .GetPageTable()
109 .CanContain(address, size, KMemoryState::CodeOut), 109 .CanContain(address, size, KMemoryState::CodeOut),
110 ResultInvalidMemoryRegion); 110 ResultInvalidMemoryRegion);
111 111
@@ -117,8 +117,8 @@ Result ControlCodeMemory(Core::System& system, Handle code_memory_handle,
117 } break; 117 } break;
118 case CodeMemoryOperation::MapToOwner: { 118 case CodeMemoryOperation::MapToOwner: {
119 // Check that the region is in range. 119 // Check that the region is in range.
120 R_UNLESS(code_mem->GetOwner()->PageTable().CanContain(address, size, 120 R_UNLESS(code_mem->GetOwner()->GetPageTable().CanContain(address, size,
121 KMemoryState::GeneratedCode), 121 KMemoryState::GeneratedCode),
122 ResultInvalidMemoryRegion); 122 ResultInvalidMemoryRegion);
123 123
124 // Check the memory permission. 124 // Check the memory permission.
@@ -129,8 +129,8 @@ Result ControlCodeMemory(Core::System& system, Handle code_memory_handle,
129 } break; 129 } break;
130 case CodeMemoryOperation::UnmapFromOwner: { 130 case CodeMemoryOperation::UnmapFromOwner: {
131 // Check that the region is in range. 131 // Check that the region is in range.
132 R_UNLESS(code_mem->GetOwner()->PageTable().CanContain(address, size, 132 R_UNLESS(code_mem->GetOwner()->GetPageTable().CanContain(address, size,
133 KMemoryState::GeneratedCode), 133 KMemoryState::GeneratedCode),
134 ResultInvalidMemoryRegion); 134 ResultInvalidMemoryRegion);
135 135
136 // Check the memory permission. 136 // Check the memory permission.
diff --git a/src/core/hle/kernel/svc/svc_device_address_space.cpp b/src/core/hle/kernel/svc/svc_device_address_space.cpp
index ec3143e67..42add9473 100644
--- a/src/core/hle/kernel/svc/svc_device_address_space.cpp
+++ b/src/core/hle/kernel/svc/svc_device_address_space.cpp
@@ -107,7 +107,7 @@ Result MapDeviceAddressSpaceByForce(Core::System& system, Handle das_handle, Han
107 R_UNLESS(process.IsNotNull(), ResultInvalidHandle); 107 R_UNLESS(process.IsNotNull(), ResultInvalidHandle);
108 108
109 // Validate that the process address is within range. 109 // Validate that the process address is within range.
110 auto& page_table = process->PageTable(); 110 auto& page_table = process->GetPageTable();
111 R_UNLESS(page_table.Contains(process_address, size), ResultInvalidCurrentMemory); 111 R_UNLESS(page_table.Contains(process_address, size), ResultInvalidCurrentMemory);
112 112
113 // Map. 113 // Map.
@@ -148,7 +148,7 @@ Result MapDeviceAddressSpaceAligned(Core::System& system, Handle das_handle, Han
148 R_UNLESS(process.IsNotNull(), ResultInvalidHandle); 148 R_UNLESS(process.IsNotNull(), ResultInvalidHandle);
149 149
150 // Validate that the process address is within range. 150 // Validate that the process address is within range.
151 auto& page_table = process->PageTable(); 151 auto& page_table = process->GetPageTable();
152 R_UNLESS(page_table.Contains(process_address, size), ResultInvalidCurrentMemory); 152 R_UNLESS(page_table.Contains(process_address, size), ResultInvalidCurrentMemory);
153 153
154 // Map. 154 // Map.
@@ -180,7 +180,7 @@ Result UnmapDeviceAddressSpace(Core::System& system, Handle das_handle, Handle p
180 R_UNLESS(process.IsNotNull(), ResultInvalidHandle); 180 R_UNLESS(process.IsNotNull(), ResultInvalidHandle);
181 181
182 // Validate that the process address is within range. 182 // Validate that the process address is within range.
183 auto& page_table = process->PageTable(); 183 auto& page_table = process->GetPageTable();
184 R_UNLESS(page_table.Contains(process_address, size), ResultInvalidCurrentMemory); 184 R_UNLESS(page_table.Contains(process_address, size), ResultInvalidCurrentMemory);
185 185
186 R_RETURN(das->Unmap(std::addressof(page_table), process_address, size, device_address)); 186 R_RETURN(das->Unmap(std::addressof(page_table), process_address, size, device_address));
diff --git a/src/core/hle/kernel/svc/svc_info.cpp b/src/core/hle/kernel/svc/svc_info.cpp
index 445cdd87b..f99964028 100644
--- a/src/core/hle/kernel/svc/svc_info.cpp
+++ b/src/core/hle/kernel/svc/svc_info.cpp
@@ -54,35 +54,35 @@ Result GetInfo(Core::System& system, u64* result, InfoType info_id_type, Handle
54 R_SUCCEED(); 54 R_SUCCEED();
55 55
56 case InfoType::AliasRegionAddress: 56 case InfoType::AliasRegionAddress:
57 *result = GetInteger(process->PageTable().GetAliasRegionStart()); 57 *result = GetInteger(process->GetPageTable().GetAliasRegionStart());
58 R_SUCCEED(); 58 R_SUCCEED();
59 59
60 case InfoType::AliasRegionSize: 60 case InfoType::AliasRegionSize:
61 *result = process->PageTable().GetAliasRegionSize(); 61 *result = process->GetPageTable().GetAliasRegionSize();
62 R_SUCCEED(); 62 R_SUCCEED();
63 63
64 case InfoType::HeapRegionAddress: 64 case InfoType::HeapRegionAddress:
65 *result = GetInteger(process->PageTable().GetHeapRegionStart()); 65 *result = GetInteger(process->GetPageTable().GetHeapRegionStart());
66 R_SUCCEED(); 66 R_SUCCEED();
67 67
68 case InfoType::HeapRegionSize: 68 case InfoType::HeapRegionSize:
69 *result = process->PageTable().GetHeapRegionSize(); 69 *result = process->GetPageTable().GetHeapRegionSize();
70 R_SUCCEED(); 70 R_SUCCEED();
71 71
72 case InfoType::AslrRegionAddress: 72 case InfoType::AslrRegionAddress:
73 *result = GetInteger(process->PageTable().GetAliasCodeRegionStart()); 73 *result = GetInteger(process->GetPageTable().GetAliasCodeRegionStart());
74 R_SUCCEED(); 74 R_SUCCEED();
75 75
76 case InfoType::AslrRegionSize: 76 case InfoType::AslrRegionSize:
77 *result = process->PageTable().GetAliasCodeRegionSize(); 77 *result = process->GetPageTable().GetAliasCodeRegionSize();
78 R_SUCCEED(); 78 R_SUCCEED();
79 79
80 case InfoType::StackRegionAddress: 80 case InfoType::StackRegionAddress:
81 *result = GetInteger(process->PageTable().GetStackRegionStart()); 81 *result = GetInteger(process->GetPageTable().GetStackRegionStart());
82 R_SUCCEED(); 82 R_SUCCEED();
83 83
84 case InfoType::StackRegionSize: 84 case InfoType::StackRegionSize:
85 *result = process->PageTable().GetStackRegionSize(); 85 *result = process->GetPageTable().GetStackRegionSize();
86 R_SUCCEED(); 86 R_SUCCEED();
87 87
88 case InfoType::TotalMemorySize: 88 case InfoType::TotalMemorySize:
diff --git a/src/core/hle/kernel/svc/svc_ipc.cpp b/src/core/hle/kernel/svc/svc_ipc.cpp
index bb94f6934..373ae7c8d 100644
--- a/src/core/hle/kernel/svc/svc_ipc.cpp
+++ b/src/core/hle/kernel/svc/svc_ipc.cpp
@@ -8,6 +8,7 @@
8#include "core/hle/kernel/k_process.h" 8#include "core/hle/kernel/k_process.h"
9#include "core/hle/kernel/k_server_session.h" 9#include "core/hle/kernel/k_server_session.h"
10#include "core/hle/kernel/svc.h" 10#include "core/hle/kernel/svc.h"
11#include "core/hle/kernel/svc_results.h"
11 12
12namespace Kernel::Svc { 13namespace Kernel::Svc {
13 14
@@ -49,14 +50,10 @@ Result ReplyAndReceive(Core::System& system, s32* out_index, uint64_t handles_ad
49 50
50 // Copy user handles. 51 // Copy user handles.
51 if (num_handles > 0) { 52 if (num_handles > 0) {
52 // Ensure we can try to get the handles.
53 R_UNLESS(GetCurrentMemory(kernel).IsValidVirtualAddressRange(
54 handles_addr, static_cast<u64>(sizeof(Handle) * num_handles)),
55 ResultInvalidPointer);
56
57 // Get the handles. 53 // Get the handles.
58 GetCurrentMemory(kernel).ReadBlock(handles_addr, handles.data(), 54 R_UNLESS(GetCurrentMemory(kernel).ReadBlock(handles_addr, handles.data(),
59 sizeof(Handle) * num_handles); 55 sizeof(Handle) * num_handles),
56 ResultInvalidPointer);
60 57
61 // Convert the handles to objects. 58 // Convert the handles to objects.
62 R_UNLESS(handle_table.GetMultipleObjects<KSynchronizationObject>( 59 R_UNLESS(handle_table.GetMultipleObjects<KSynchronizationObject>(
diff --git a/src/core/hle/kernel/svc/svc_memory.cpp b/src/core/hle/kernel/svc/svc_memory.cpp
index 5dcb7f045..2cab74127 100644
--- a/src/core/hle/kernel/svc/svc_memory.cpp
+++ b/src/core/hle/kernel/svc/svc_memory.cpp
@@ -63,36 +63,13 @@ Result MapUnmapMemorySanityChecks(const KPageTable& manager, u64 dst_addr, u64 s
63 R_THROW(ResultInvalidCurrentMemory); 63 R_THROW(ResultInvalidCurrentMemory);
64 } 64 }
65 65
66 if (!manager.IsInsideAddressSpace(src_addr, size)) { 66 if (!manager.Contains(src_addr, size)) {
67 LOG_ERROR(Kernel_SVC, 67 LOG_ERROR(Kernel_SVC,
68 "Source is not within the address space, addr=0x{:016X}, size=0x{:016X}", 68 "Source is not within the address space, addr=0x{:016X}, size=0x{:016X}",
69 src_addr, size); 69 src_addr, size);
70 R_THROW(ResultInvalidCurrentMemory); 70 R_THROW(ResultInvalidCurrentMemory);
71 } 71 }
72 72
73 if (manager.IsOutsideStackRegion(dst_addr, size)) {
74 LOG_ERROR(Kernel_SVC,
75 "Destination is not within the stack region, addr=0x{:016X}, size=0x{:016X}",
76 dst_addr, size);
77 R_THROW(ResultInvalidMemoryRegion);
78 }
79
80 if (manager.IsInsideHeapRegion(dst_addr, size)) {
81 LOG_ERROR(Kernel_SVC,
82 "Destination does not fit within the heap region, addr=0x{:016X}, "
83 "size=0x{:016X}",
84 dst_addr, size);
85 R_THROW(ResultInvalidMemoryRegion);
86 }
87
88 if (manager.IsInsideAliasRegion(dst_addr, size)) {
89 LOG_ERROR(Kernel_SVC,
90 "Destination does not fit within the map region, addr=0x{:016X}, "
91 "size=0x{:016X}",
92 dst_addr, size);
93 R_THROW(ResultInvalidMemoryRegion);
94 }
95
96 R_SUCCEED(); 73 R_SUCCEED();
97} 74}
98 75
@@ -112,7 +89,7 @@ Result SetMemoryPermission(Core::System& system, u64 address, u64 size, MemoryPe
112 R_UNLESS(IsValidSetMemoryPermission(perm), ResultInvalidNewMemoryPermission); 89 R_UNLESS(IsValidSetMemoryPermission(perm), ResultInvalidNewMemoryPermission);
113 90
114 // Validate that the region is in range for the current process. 91 // Validate that the region is in range for the current process.
115 auto& page_table = GetCurrentProcess(system.Kernel()).PageTable(); 92 auto& page_table = GetCurrentProcess(system.Kernel()).GetPageTable();
116 R_UNLESS(page_table.Contains(address, size), ResultInvalidCurrentMemory); 93 R_UNLESS(page_table.Contains(address, size), ResultInvalidCurrentMemory);
117 94
118 // Set the memory attribute. 95 // Set the memory attribute.
@@ -136,7 +113,7 @@ Result SetMemoryAttribute(Core::System& system, u64 address, u64 size, u32 mask,
136 R_UNLESS((mask | attr | SupportedMask) == SupportedMask, ResultInvalidCombination); 113 R_UNLESS((mask | attr | SupportedMask) == SupportedMask, ResultInvalidCombination);
137 114
138 // Validate that the region is in range for the current process. 115 // Validate that the region is in range for the current process.
139 auto& page_table{GetCurrentProcess(system.Kernel()).PageTable()}; 116 auto& page_table{GetCurrentProcess(system.Kernel()).GetPageTable()};
140 R_UNLESS(page_table.Contains(address, size), ResultInvalidCurrentMemory); 117 R_UNLESS(page_table.Contains(address, size), ResultInvalidCurrentMemory);
141 118
142 // Set the memory attribute. 119 // Set the memory attribute.
@@ -148,7 +125,7 @@ Result MapMemory(Core::System& system, u64 dst_addr, u64 src_addr, u64 size) {
148 LOG_TRACE(Kernel_SVC, "called, dst_addr=0x{:X}, src_addr=0x{:X}, size=0x{:X}", dst_addr, 125 LOG_TRACE(Kernel_SVC, "called, dst_addr=0x{:X}, src_addr=0x{:X}, size=0x{:X}", dst_addr,
149 src_addr, size); 126 src_addr, size);
150 127
151 auto& page_table{GetCurrentProcess(system.Kernel()).PageTable()}; 128 auto& page_table{GetCurrentProcess(system.Kernel()).GetPageTable()};
152 129
153 if (const Result result{MapUnmapMemorySanityChecks(page_table, dst_addr, src_addr, size)}; 130 if (const Result result{MapUnmapMemorySanityChecks(page_table, dst_addr, src_addr, size)};
154 result.IsError()) { 131 result.IsError()) {
@@ -163,7 +140,7 @@ Result UnmapMemory(Core::System& system, u64 dst_addr, u64 src_addr, u64 size) {
163 LOG_TRACE(Kernel_SVC, "called, dst_addr=0x{:X}, src_addr=0x{:X}, size=0x{:X}", dst_addr, 140 LOG_TRACE(Kernel_SVC, "called, dst_addr=0x{:X}, src_addr=0x{:X}, size=0x{:X}", dst_addr,
164 src_addr, size); 141 src_addr, size);
165 142
166 auto& page_table{GetCurrentProcess(system.Kernel()).PageTable()}; 143 auto& page_table{GetCurrentProcess(system.Kernel()).GetPageTable()};
167 144
168 if (const Result result{MapUnmapMemorySanityChecks(page_table, dst_addr, src_addr, size)}; 145 if (const Result result{MapUnmapMemorySanityChecks(page_table, dst_addr, src_addr, size)};
169 result.IsError()) { 146 result.IsError()) {
diff --git a/src/core/hle/kernel/svc/svc_physical_memory.cpp b/src/core/hle/kernel/svc/svc_physical_memory.cpp
index c2fbfb59a..d3545f232 100644
--- a/src/core/hle/kernel/svc/svc_physical_memory.cpp
+++ b/src/core/hle/kernel/svc/svc_physical_memory.cpp
@@ -16,7 +16,7 @@ Result SetHeapSize(Core::System& system, u64* out_address, u64 size) {
16 R_UNLESS(size < MainMemorySizeMax, ResultInvalidSize); 16 R_UNLESS(size < MainMemorySizeMax, ResultInvalidSize);
17 17
18 // Set the heap size. 18 // Set the heap size.
19 R_RETURN(GetCurrentProcess(system.Kernel()).PageTable().SetHeapSize(out_address, size)); 19 R_RETURN(GetCurrentProcess(system.Kernel()).GetPageTable().SetHeapSize(out_address, size));
20} 20}
21 21
22/// Maps memory at a desired address 22/// Maps memory at a desired address
@@ -44,21 +44,21 @@ Result MapPhysicalMemory(Core::System& system, u64 addr, u64 size) {
44 } 44 }
45 45
46 KProcess* const current_process{GetCurrentProcessPointer(system.Kernel())}; 46 KProcess* const current_process{GetCurrentProcessPointer(system.Kernel())};
47 auto& page_table{current_process->PageTable()}; 47 auto& page_table{current_process->GetPageTable()};
48 48
49 if (current_process->GetSystemResourceSize() == 0) { 49 if (current_process->GetSystemResourceSize() == 0) {
50 LOG_ERROR(Kernel_SVC, "System Resource Size is zero"); 50 LOG_ERROR(Kernel_SVC, "System Resource Size is zero");
51 R_THROW(ResultInvalidState); 51 R_THROW(ResultInvalidState);
52 } 52 }
53 53
54 if (!page_table.IsInsideAddressSpace(addr, size)) { 54 if (!page_table.Contains(addr, size)) {
55 LOG_ERROR(Kernel_SVC, 55 LOG_ERROR(Kernel_SVC,
56 "Address is not within the address space, addr=0x{:016X}, size=0x{:016X}", addr, 56 "Address is not within the address space, addr=0x{:016X}, size=0x{:016X}", addr,
57 size); 57 size);
58 R_THROW(ResultInvalidMemoryRegion); 58 R_THROW(ResultInvalidMemoryRegion);
59 } 59 }
60 60
61 if (page_table.IsOutsideAliasRegion(addr, size)) { 61 if (!page_table.IsInAliasRegion(addr, size)) {
62 LOG_ERROR(Kernel_SVC, 62 LOG_ERROR(Kernel_SVC,
63 "Address is not within the alias region, addr=0x{:016X}, size=0x{:016X}", addr, 63 "Address is not within the alias region, addr=0x{:016X}, size=0x{:016X}", addr,
64 size); 64 size);
@@ -93,21 +93,21 @@ Result UnmapPhysicalMemory(Core::System& system, u64 addr, u64 size) {
93 } 93 }
94 94
95 KProcess* const current_process{GetCurrentProcessPointer(system.Kernel())}; 95 KProcess* const current_process{GetCurrentProcessPointer(system.Kernel())};
96 auto& page_table{current_process->PageTable()}; 96 auto& page_table{current_process->GetPageTable()};
97 97
98 if (current_process->GetSystemResourceSize() == 0) { 98 if (current_process->GetSystemResourceSize() == 0) {
99 LOG_ERROR(Kernel_SVC, "System Resource Size is zero"); 99 LOG_ERROR(Kernel_SVC, "System Resource Size is zero");
100 R_THROW(ResultInvalidState); 100 R_THROW(ResultInvalidState);
101 } 101 }
102 102
103 if (!page_table.IsInsideAddressSpace(addr, size)) { 103 if (!page_table.Contains(addr, size)) {
104 LOG_ERROR(Kernel_SVC, 104 LOG_ERROR(Kernel_SVC,
105 "Address is not within the address space, addr=0x{:016X}, size=0x{:016X}", addr, 105 "Address is not within the address space, addr=0x{:016X}, size=0x{:016X}", addr,
106 size); 106 size);
107 R_THROW(ResultInvalidMemoryRegion); 107 R_THROW(ResultInvalidMemoryRegion);
108 } 108 }
109 109
110 if (page_table.IsOutsideAliasRegion(addr, size)) { 110 if (!page_table.IsInAliasRegion(addr, size)) {
111 LOG_ERROR(Kernel_SVC, 111 LOG_ERROR(Kernel_SVC,
112 "Address is not within the alias region, addr=0x{:016X}, size=0x{:016X}", addr, 112 "Address is not within the alias region, addr=0x{:016X}, size=0x{:016X}", addr,
113 size); 113 size);
diff --git a/src/core/hle/kernel/svc/svc_process.cpp b/src/core/hle/kernel/svc/svc_process.cpp
index 619ed16a3..caa8bee9a 100644
--- a/src/core/hle/kernel/svc/svc_process.cpp
+++ b/src/core/hle/kernel/svc/svc_process.cpp
@@ -66,8 +66,8 @@ Result GetProcessList(Core::System& system, s32* out_num_processes, u64 out_proc
66 auto& kernel = system.Kernel(); 66 auto& kernel = system.Kernel();
67 const auto total_copy_size = out_process_ids_size * sizeof(u64); 67 const auto total_copy_size = out_process_ids_size * sizeof(u64);
68 68
69 if (out_process_ids_size > 0 && !GetCurrentProcess(kernel).PageTable().IsInsideAddressSpace( 69 if (out_process_ids_size > 0 &&
70 out_process_ids, total_copy_size)) { 70 !GetCurrentProcess(kernel).GetPageTable().Contains(out_process_ids, total_copy_size)) {
71 LOG_ERROR(Kernel_SVC, "Address range outside address space. begin=0x{:016X}, end=0x{:016X}", 71 LOG_ERROR(Kernel_SVC, "Address range outside address space. begin=0x{:016X}, end=0x{:016X}",
72 out_process_ids, out_process_ids + total_copy_size); 72 out_process_ids, out_process_ids + total_copy_size);
73 R_THROW(ResultInvalidCurrentMemory); 73 R_THROW(ResultInvalidCurrentMemory);
diff --git a/src/core/hle/kernel/svc/svc_process_memory.cpp b/src/core/hle/kernel/svc/svc_process_memory.cpp
index aee0f2f36..07cd48175 100644
--- a/src/core/hle/kernel/svc/svc_process_memory.cpp
+++ b/src/core/hle/kernel/svc/svc_process_memory.cpp
@@ -49,7 +49,7 @@ Result SetProcessMemoryPermission(Core::System& system, Handle process_handle, u
49 R_UNLESS(process.IsNotNull(), ResultInvalidHandle); 49 R_UNLESS(process.IsNotNull(), ResultInvalidHandle);
50 50
51 // Validate that the address is in range. 51 // Validate that the address is in range.
52 auto& page_table = process->PageTable(); 52 auto& page_table = process->GetPageTable();
53 R_UNLESS(page_table.Contains(address, size), ResultInvalidCurrentMemory); 53 R_UNLESS(page_table.Contains(address, size), ResultInvalidCurrentMemory);
54 54
55 // Set the memory permission. 55 // Set the memory permission.
@@ -77,8 +77,8 @@ Result MapProcessMemory(Core::System& system, u64 dst_address, Handle process_ha
77 R_UNLESS(src_process.IsNotNull(), ResultInvalidHandle); 77 R_UNLESS(src_process.IsNotNull(), ResultInvalidHandle);
78 78
79 // Get the page tables. 79 // Get the page tables.
80 auto& dst_pt = dst_process->PageTable(); 80 auto& dst_pt = dst_process->GetPageTable();
81 auto& src_pt = src_process->PageTable(); 81 auto& src_pt = src_process->GetPageTable();
82 82
83 // Validate that the mapping is in range. 83 // Validate that the mapping is in range.
84 R_UNLESS(src_pt.Contains(src_address, size), ResultInvalidCurrentMemory); 84 R_UNLESS(src_pt.Contains(src_address, size), ResultInvalidCurrentMemory);
@@ -118,8 +118,8 @@ Result UnmapProcessMemory(Core::System& system, u64 dst_address, Handle process_
118 R_UNLESS(src_process.IsNotNull(), ResultInvalidHandle); 118 R_UNLESS(src_process.IsNotNull(), ResultInvalidHandle);
119 119
120 // Get the page tables. 120 // Get the page tables.
121 auto& dst_pt = dst_process->PageTable(); 121 auto& dst_pt = dst_process->GetPageTable();
122 auto& src_pt = src_process->PageTable(); 122 auto& src_pt = src_process->GetPageTable();
123 123
124 // Validate that the mapping is in range. 124 // Validate that the mapping is in range.
125 R_UNLESS(src_pt.Contains(src_address, size), ResultInvalidCurrentMemory); 125 R_UNLESS(src_pt.Contains(src_address, size), ResultInvalidCurrentMemory);
@@ -178,8 +178,8 @@ Result MapProcessCodeMemory(Core::System& system, Handle process_handle, u64 dst
178 R_THROW(ResultInvalidHandle); 178 R_THROW(ResultInvalidHandle);
179 } 179 }
180 180
181 auto& page_table = process->PageTable(); 181 auto& page_table = process->GetPageTable();
182 if (!page_table.IsInsideAddressSpace(src_address, size)) { 182 if (!page_table.Contains(src_address, size)) {
183 LOG_ERROR(Kernel_SVC, 183 LOG_ERROR(Kernel_SVC,
184 "Source address range is not within the address space (src_address=0x{:016X}, " 184 "Source address range is not within the address space (src_address=0x{:016X}, "
185 "size=0x{:016X}).", 185 "size=0x{:016X}).",
@@ -187,14 +187,6 @@ Result MapProcessCodeMemory(Core::System& system, Handle process_handle, u64 dst
187 R_THROW(ResultInvalidCurrentMemory); 187 R_THROW(ResultInvalidCurrentMemory);
188 } 188 }
189 189
190 if (!page_table.IsInsideASLRRegion(dst_address, size)) {
191 LOG_ERROR(Kernel_SVC,
192 "Destination address range is not within the ASLR region (dst_address=0x{:016X}, "
193 "size=0x{:016X}).",
194 dst_address, size);
195 R_THROW(ResultInvalidMemoryRegion);
196 }
197
198 R_RETURN(page_table.MapCodeMemory(dst_address, src_address, size)); 190 R_RETURN(page_table.MapCodeMemory(dst_address, src_address, size));
199} 191}
200 192
@@ -246,8 +238,8 @@ Result UnmapProcessCodeMemory(Core::System& system, Handle process_handle, u64 d
246 R_THROW(ResultInvalidHandle); 238 R_THROW(ResultInvalidHandle);
247 } 239 }
248 240
249 auto& page_table = process->PageTable(); 241 auto& page_table = process->GetPageTable();
250 if (!page_table.IsInsideAddressSpace(src_address, size)) { 242 if (!page_table.Contains(src_address, size)) {
251 LOG_ERROR(Kernel_SVC, 243 LOG_ERROR(Kernel_SVC,
252 "Source address range is not within the address space (src_address=0x{:016X}, " 244 "Source address range is not within the address space (src_address=0x{:016X}, "
253 "size=0x{:016X}).", 245 "size=0x{:016X}).",
@@ -255,14 +247,6 @@ Result UnmapProcessCodeMemory(Core::System& system, Handle process_handle, u64 d
255 R_THROW(ResultInvalidCurrentMemory); 247 R_THROW(ResultInvalidCurrentMemory);
256 } 248 }
257 249
258 if (!page_table.IsInsideASLRRegion(dst_address, size)) {
259 LOG_ERROR(Kernel_SVC,
260 "Destination address range is not within the ASLR region (dst_address=0x{:016X}, "
261 "size=0x{:016X}).",
262 dst_address, size);
263 R_THROW(ResultInvalidMemoryRegion);
264 }
265
266 R_RETURN(page_table.UnmapCodeMemory(dst_address, src_address, size, 250 R_RETURN(page_table.UnmapCodeMemory(dst_address, src_address, size,
267 KPageTable::ICacheInvalidationStrategy::InvalidateAll)); 251 KPageTable::ICacheInvalidationStrategy::InvalidateAll));
268} 252}
diff --git a/src/core/hle/kernel/svc/svc_query_memory.cpp b/src/core/hle/kernel/svc/svc_query_memory.cpp
index 4d9fcd25f..51af06e97 100644
--- a/src/core/hle/kernel/svc/svc_query_memory.cpp
+++ b/src/core/hle/kernel/svc/svc_query_memory.cpp
@@ -31,7 +31,7 @@ Result QueryProcessMemory(Core::System& system, uint64_t out_memory_info, PageIn
31 } 31 }
32 32
33 auto& current_memory{GetCurrentMemory(system.Kernel())}; 33 auto& current_memory{GetCurrentMemory(system.Kernel())};
34 const auto memory_info{process->PageTable().QueryInfo(address).GetSvcMemoryInfo()}; 34 const auto memory_info{process->GetPageTable().QueryInfo(address).GetSvcMemoryInfo()};
35 35
36 current_memory.WriteBlock(out_memory_info, std::addressof(memory_info), sizeof(memory_info)); 36 current_memory.WriteBlock(out_memory_info, std::addressof(memory_info), sizeof(memory_info));
37 37
diff --git a/src/core/hle/kernel/svc/svc_shared_memory.cpp b/src/core/hle/kernel/svc/svc_shared_memory.cpp
index a698596aa..012b1ae2b 100644
--- a/src/core/hle/kernel/svc/svc_shared_memory.cpp
+++ b/src/core/hle/kernel/svc/svc_shared_memory.cpp
@@ -43,7 +43,7 @@ Result MapSharedMemory(Core::System& system, Handle shmem_handle, u64 address, u
43 43
44 // Get the current process. 44 // Get the current process.
45 auto& process = GetCurrentProcess(system.Kernel()); 45 auto& process = GetCurrentProcess(system.Kernel());
46 auto& page_table = process.PageTable(); 46 auto& page_table = process.GetPageTable();
47 47
48 // Get the shared memory. 48 // Get the shared memory.
49 KScopedAutoObject shmem = process.GetHandleTable().GetObject<KSharedMemory>(shmem_handle); 49 KScopedAutoObject shmem = process.GetHandleTable().GetObject<KSharedMemory>(shmem_handle);
@@ -73,7 +73,7 @@ Result UnmapSharedMemory(Core::System& system, Handle shmem_handle, u64 address,
73 73
74 // Get the current process. 74 // Get the current process.
75 auto& process = GetCurrentProcess(system.Kernel()); 75 auto& process = GetCurrentProcess(system.Kernel());
76 auto& page_table = process.PageTable(); 76 auto& page_table = process.GetPageTable();
77 77
78 // Get the shared memory. 78 // Get the shared memory.
79 KScopedAutoObject shmem = process.GetHandleTable().GetObject<KSharedMemory>(shmem_handle); 79 KScopedAutoObject shmem = process.GetHandleTable().GetObject<KSharedMemory>(shmem_handle);
diff --git a/src/core/hle/kernel/svc/svc_synchronization.cpp b/src/core/hle/kernel/svc/svc_synchronization.cpp
index f02d03f30..366e8ed4a 100644
--- a/src/core/hle/kernel/svc/svc_synchronization.cpp
+++ b/src/core/hle/kernel/svc/svc_synchronization.cpp
@@ -7,6 +7,7 @@
7#include "core/hle/kernel/k_process.h" 7#include "core/hle/kernel/k_process.h"
8#include "core/hle/kernel/k_readable_event.h" 8#include "core/hle/kernel/k_readable_event.h"
9#include "core/hle/kernel/svc.h" 9#include "core/hle/kernel/svc.h"
10#include "core/hle/kernel/svc_results.h"
10 11
11namespace Kernel::Svc { 12namespace Kernel::Svc {
12 13
@@ -64,14 +65,10 @@ Result WaitSynchronization(Core::System& system, int32_t* out_index, u64 user_ha
64 65
65 // Copy user handles. 66 // Copy user handles.
66 if (num_handles > 0) { 67 if (num_handles > 0) {
67 // Ensure we can try to get the handles.
68 R_UNLESS(GetCurrentMemory(kernel).IsValidVirtualAddressRange(
69 user_handles, static_cast<u64>(sizeof(Handle) * num_handles)),
70 ResultInvalidPointer);
71
72 // Get the handles. 68 // Get the handles.
73 GetCurrentMemory(kernel).ReadBlock(user_handles, handles.data(), 69 R_UNLESS(GetCurrentMemory(kernel).ReadBlock(user_handles, handles.data(),
74 sizeof(Handle) * num_handles); 70 sizeof(Handle) * num_handles),
71 ResultInvalidPointer);
75 72
76 // Convert the handles to objects. 73 // Convert the handles to objects.
77 R_UNLESS(handle_table.GetMultipleObjects<KSynchronizationObject>( 74 R_UNLESS(handle_table.GetMultipleObjects<KSynchronizationObject>(
diff --git a/src/core/hle/kernel/svc/svc_thread.cpp b/src/core/hle/kernel/svc/svc_thread.cpp
index 36b94e6bf..92bcea72b 100644
--- a/src/core/hle/kernel/svc/svc_thread.cpp
+++ b/src/core/hle/kernel/svc/svc_thread.cpp
@@ -236,7 +236,7 @@ Result GetThreadList(Core::System& system, s32* out_num_threads, u64 out_thread_
236 const auto total_copy_size = out_thread_ids_size * sizeof(u64); 236 const auto total_copy_size = out_thread_ids_size * sizeof(u64);
237 237
238 if (out_thread_ids_size > 0 && 238 if (out_thread_ids_size > 0 &&
239 !current_process->PageTable().IsInsideAddressSpace(out_thread_ids, total_copy_size)) { 239 !current_process->GetPageTable().Contains(out_thread_ids, total_copy_size)) {
240 LOG_ERROR(Kernel_SVC, "Address range outside address space. begin=0x{:016X}, end=0x{:016X}", 240 LOG_ERROR(Kernel_SVC, "Address range outside address space. begin=0x{:016X}, end=0x{:016X}",
241 out_thread_ids, out_thread_ids + total_copy_size); 241 out_thread_ids, out_thread_ids + total_copy_size);
242 R_THROW(ResultInvalidCurrentMemory); 242 R_THROW(ResultInvalidCurrentMemory);
diff --git a/src/core/hle/kernel/svc/svc_transfer_memory.cpp b/src/core/hle/kernel/svc/svc_transfer_memory.cpp
index 82d469a37..7d94e7f09 100644
--- a/src/core/hle/kernel/svc/svc_transfer_memory.cpp
+++ b/src/core/hle/kernel/svc/svc_transfer_memory.cpp
@@ -55,7 +55,7 @@ Result CreateTransferMemory(Core::System& system, Handle* out, u64 address, u64
55 SCOPE_EXIT({ trmem->Close(); }); 55 SCOPE_EXIT({ trmem->Close(); });
56 56
57 // Ensure that the region is in range. 57 // Ensure that the region is in range.
58 R_UNLESS(process.PageTable().Contains(address, size), ResultInvalidCurrentMemory); 58 R_UNLESS(process.GetPageTable().Contains(address, size), ResultInvalidCurrentMemory);
59 59
60 // Initialize the transfer memory. 60 // Initialize the transfer memory.
61 R_TRY(trmem->Initialize(address, size, map_perm)); 61 R_TRY(trmem->Initialize(address, size, map_perm));
diff --git a/src/core/hle/service/acc/acc.cpp b/src/core/hle/service/acc/acc.cpp
index 6c29cb613..2632cd3ef 100644
--- a/src/core/hle/service/acc/acc.cpp
+++ b/src/core/hle/service/acc/acc.cpp
@@ -496,8 +496,9 @@ public:
496 void LoadIdTokenCache(HLERequestContext& ctx) { 496 void LoadIdTokenCache(HLERequestContext& ctx) {
497 LOG_WARNING(Service_ACC, "(STUBBED) called"); 497 LOG_WARNING(Service_ACC, "(STUBBED) called");
498 498
499 IPC::ResponseBuilder rb{ctx, 2}; 499 IPC::ResponseBuilder rb{ctx, 3};
500 rb.Push(ResultSuccess); 500 rb.Push(ResultSuccess);
501 rb.Push(0);
501 } 502 }
502 503
503protected: 504protected:
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp
index a2375508a..4f400d341 100644
--- a/src/core/hle/service/am/am.cpp
+++ b/src/core/hle/service/am/am.cpp
@@ -506,8 +506,8 @@ void ISelfController::SetHandlesRequestToDisplay(HLERequestContext& ctx) {
506void ISelfController::SetIdleTimeDetectionExtension(HLERequestContext& ctx) { 506void ISelfController::SetIdleTimeDetectionExtension(HLERequestContext& ctx) {
507 IPC::RequestParser rp{ctx}; 507 IPC::RequestParser rp{ctx};
508 idle_time_detection_extension = rp.Pop<u32>(); 508 idle_time_detection_extension = rp.Pop<u32>();
509 LOG_WARNING(Service_AM, "(STUBBED) called idle_time_detection_extension={}", 509 LOG_DEBUG(Service_AM, "(STUBBED) called idle_time_detection_extension={}",
510 idle_time_detection_extension); 510 idle_time_detection_extension);
511 511
512 IPC::ResponseBuilder rb{ctx, 2}; 512 IPC::ResponseBuilder rb{ctx, 2};
513 rb.Push(ResultSuccess); 513 rb.Push(ResultSuccess);
diff --git a/src/core/hle/service/glue/ectx.cpp b/src/core/hle/service/glue/ectx.cpp
index 1bd9314ae..6f71b62f3 100644
--- a/src/core/hle/service/glue/ectx.cpp
+++ b/src/core/hle/service/glue/ectx.cpp
@@ -2,13 +2,48 @@
2// SPDX-License-Identifier: GPL-2.0-or-later 2// SPDX-License-Identifier: GPL-2.0-or-later
3 3
4#include "core/hle/service/glue/ectx.h" 4#include "core/hle/service/glue/ectx.h"
5#include "core/hle/service/ipc_helpers.h"
5 6
6namespace Service::Glue { 7namespace Service::Glue {
7 8
9// This is nn::err::context::IContextRegistrar
10class IContextRegistrar : public ServiceFramework<IContextRegistrar> {
11public:
12 IContextRegistrar(Core::System& system_) : ServiceFramework{system_, "IContextRegistrar"} {
13 // clang-format off
14 static const FunctionInfo functions[] = {
15 {0, &IContextRegistrar::Complete, "Complete"},
16 };
17 // clang-format on
18
19 RegisterHandlers(functions);
20 }
21
22 ~IContextRegistrar() override = default;
23
24private:
25 void Complete(HLERequestContext& ctx) {
26 struct InputParameters {
27 u32 unk;
28 };
29 struct OutputParameters {
30 u32 unk;
31 };
32
33 IPC::RequestParser rp{ctx};
34 [[maybe_unused]] auto input = rp.PopRaw<InputParameters>();
35 [[maybe_unused]] auto value = ctx.ReadBuffer();
36
37 IPC::ResponseBuilder rb{ctx, 3};
38 rb.Push(ResultSuccess);
39 rb.Push(0);
40 }
41};
42
8ECTX_AW::ECTX_AW(Core::System& system_) : ServiceFramework{system_, "ectx:aw"} { 43ECTX_AW::ECTX_AW(Core::System& system_) : ServiceFramework{system_, "ectx:aw"} {
9 // clang-format off 44 // clang-format off
10 static const FunctionInfo functions[] = { 45 static const FunctionInfo functions[] = {
11 {0, nullptr, "CreateContextRegistrar"}, 46 {0, &ECTX_AW::CreateContextRegistrar, "CreateContextRegistrar"},
12 {1, nullptr, "CommitContext"}, 47 {1, nullptr, "CommitContext"},
13 }; 48 };
14 // clang-format on 49 // clang-format on
@@ -18,4 +53,10 @@ ECTX_AW::ECTX_AW(Core::System& system_) : ServiceFramework{system_, "ectx:aw"} {
18 53
19ECTX_AW::~ECTX_AW() = default; 54ECTX_AW::~ECTX_AW() = default;
20 55
56void ECTX_AW::CreateContextRegistrar(HLERequestContext& ctx) {
57 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
58 rb.Push(ResultSuccess);
59 rb.PushIpcInterface<IContextRegistrar>(std::make_shared<IContextRegistrar>(system));
60}
61
21} // namespace Service::Glue 62} // namespace Service::Glue
diff --git a/src/core/hle/service/glue/ectx.h b/src/core/hle/service/glue/ectx.h
index a608de053..ffa74d8d3 100644
--- a/src/core/hle/service/glue/ectx.h
+++ b/src/core/hle/service/glue/ectx.h
@@ -15,6 +15,9 @@ class ECTX_AW final : public ServiceFramework<ECTX_AW> {
15public: 15public:
16 explicit ECTX_AW(Core::System& system_); 16 explicit ECTX_AW(Core::System& system_);
17 ~ECTX_AW() override; 17 ~ECTX_AW() override;
18
19private:
20 void CreateContextRegistrar(HLERequestContext& ctx);
18}; 21};
19 22
20} // namespace Service::Glue 23} // namespace Service::Glue
diff --git a/src/core/hle/service/ldr/ldr.cpp b/src/core/hle/service/ldr/ldr.cpp
index c42489ff9..055c0a2db 100644
--- a/src/core/hle/service/ldr/ldr.cpp
+++ b/src/core/hle/service/ldr/ldr.cpp
@@ -318,15 +318,15 @@ public:
318 return false; 318 return false;
319 } 319 }
320 320
321 if (!page_table.IsInsideAddressSpace(out_addr, size)) { 321 if (!page_table.Contains(out_addr, size)) {
322 return false; 322 return false;
323 } 323 }
324 324
325 if (page_table.IsInsideHeapRegion(out_addr, size)) { 325 if (page_table.IsInHeapRegion(out_addr, size)) {
326 return false; 326 return false;
327 } 327 }
328 328
329 if (page_table.IsInsideAliasRegion(out_addr, size)) { 329 if (page_table.IsInAliasRegion(out_addr, size)) {
330 return false; 330 return false;
331 } 331 }
332 332
@@ -358,7 +358,7 @@ public:
358 } 358 }
359 359
360 ResultVal<VAddr> MapProcessCodeMemory(Kernel::KProcess* process, VAddr base_addr, u64 size) { 360 ResultVal<VAddr> MapProcessCodeMemory(Kernel::KProcess* process, VAddr base_addr, u64 size) {
361 auto& page_table{process->PageTable()}; 361 auto& page_table{process->GetPageTable()};
362 VAddr addr{}; 362 VAddr addr{};
363 363
364 for (std::size_t retry = 0; retry < MAXIMUM_MAP_RETRIES; retry++) { 364 for (std::size_t retry = 0; retry < MAXIMUM_MAP_RETRIES; retry++) {
@@ -382,7 +382,7 @@ public:
382 ResultVal<VAddr> MapNro(Kernel::KProcess* process, VAddr nro_addr, std::size_t nro_size, 382 ResultVal<VAddr> MapNro(Kernel::KProcess* process, VAddr nro_addr, std::size_t nro_size,
383 VAddr bss_addr, std::size_t bss_size, std::size_t size) { 383 VAddr bss_addr, std::size_t bss_size, std::size_t size) {
384 for (std::size_t retry = 0; retry < MAXIMUM_MAP_RETRIES; retry++) { 384 for (std::size_t retry = 0; retry < MAXIMUM_MAP_RETRIES; retry++) {
385 auto& page_table{process->PageTable()}; 385 auto& page_table{process->GetPageTable()};
386 VAddr addr{}; 386 VAddr addr{};
387 387
388 CASCADE_RESULT(addr, MapProcessCodeMemory(process, nro_addr, nro_size)); 388 CASCADE_RESULT(addr, MapProcessCodeMemory(process, nro_addr, nro_size));
@@ -437,12 +437,12 @@ public:
437 CopyCode(nro_addr + nro_header.segment_headers[DATA_INDEX].memory_offset, data_start, 437 CopyCode(nro_addr + nro_header.segment_headers[DATA_INDEX].memory_offset, data_start,
438 nro_header.segment_headers[DATA_INDEX].memory_size); 438 nro_header.segment_headers[DATA_INDEX].memory_size);
439 439
440 CASCADE_CODE(process->PageTable().SetProcessMemoryPermission( 440 CASCADE_CODE(process->GetPageTable().SetProcessMemoryPermission(
441 text_start, ro_start - text_start, Kernel::Svc::MemoryPermission::ReadExecute)); 441 text_start, ro_start - text_start, Kernel::Svc::MemoryPermission::ReadExecute));
442 CASCADE_CODE(process->PageTable().SetProcessMemoryPermission( 442 CASCADE_CODE(process->GetPageTable().SetProcessMemoryPermission(
443 ro_start, data_start - ro_start, Kernel::Svc::MemoryPermission::Read)); 443 ro_start, data_start - ro_start, Kernel::Svc::MemoryPermission::Read));
444 444
445 return process->PageTable().SetProcessMemoryPermission( 445 return process->GetPageTable().SetProcessMemoryPermission(
446 data_start, bss_end_addr - data_start, Kernel::Svc::MemoryPermission::ReadWrite); 446 data_start, bss_end_addr - data_start, Kernel::Svc::MemoryPermission::ReadWrite);
447 } 447 }
448 448
@@ -571,7 +571,7 @@ public:
571 571
572 Result UnmapNro(const NROInfo& info) { 572 Result UnmapNro(const NROInfo& info) {
573 // Each region must be unmapped separately to validate memory state 573 // Each region must be unmapped separately to validate memory state
574 auto& page_table{system.ApplicationProcess()->PageTable()}; 574 auto& page_table{system.ApplicationProcess()->GetPageTable()};
575 575
576 if (info.bss_size != 0) { 576 if (info.bss_size != 0) {
577 CASCADE_CODE(page_table.UnmapCodeMemory( 577 CASCADE_CODE(page_table.UnmapCodeMemory(
@@ -643,7 +643,7 @@ public:
643 643
644 initialized = true; 644 initialized = true;
645 current_map_addr = 645 current_map_addr =
646 GetInteger(system.ApplicationProcess()->PageTable().GetAliasCodeRegionStart()); 646 GetInteger(system.ApplicationProcess()->GetPageTable().GetAliasCodeRegionStart());
647 647
648 IPC::ResponseBuilder rb{ctx, 2}; 648 IPC::ResponseBuilder rb{ctx, 2};
649 rb.Push(ResultSuccess); 649 rb.Push(ResultSuccess);
diff --git a/src/core/hle/service/nfc/common/amiibo_crypto.cpp b/src/core/hle/service/nfc/common/amiibo_crypto.cpp
index bc232c334..9556e9193 100644
--- a/src/core/hle/service/nfc/common/amiibo_crypto.cpp
+++ b/src/core/hle/service/nfc/common/amiibo_crypto.cpp
@@ -180,7 +180,7 @@ std::vector<u8> GenerateInternalKey(const InternalKey& key, const HashSeed& seed
180} 180}
181 181
182void CryptoInit(CryptoCtx& ctx, mbedtls_md_context_t& hmac_ctx, const HmacKey& hmac_key, 182void CryptoInit(CryptoCtx& ctx, mbedtls_md_context_t& hmac_ctx, const HmacKey& hmac_key,
183 const std::vector<u8>& seed) { 183 std::span<const u8> seed) {
184 // Initialize context 184 // Initialize context
185 ctx.used = false; 185 ctx.used = false;
186 ctx.counter = 0; 186 ctx.counter = 0;
diff --git a/src/core/hle/service/nfc/common/amiibo_crypto.h b/src/core/hle/service/nfc/common/amiibo_crypto.h
index 6a3e0841e..2cc0e4d51 100644
--- a/src/core/hle/service/nfc/common/amiibo_crypto.h
+++ b/src/core/hle/service/nfc/common/amiibo_crypto.h
@@ -75,7 +75,7 @@ std::vector<u8> GenerateInternalKey(const InternalKey& key, const HashSeed& seed
75 75
76// Initializes mbedtls context 76// Initializes mbedtls context
77void CryptoInit(CryptoCtx& ctx, mbedtls_md_context_t& hmac_ctx, const HmacKey& hmac_key, 77void CryptoInit(CryptoCtx& ctx, mbedtls_md_context_t& hmac_ctx, const HmacKey& hmac_key,
78 const std::vector<u8>& seed); 78 std::span<const u8> seed);
79 79
80// Feeds data to mbedtls context to generate the derived key 80// Feeds data to mbedtls context to generate the derived key
81void CryptoStep(CryptoCtx& ctx, mbedtls_md_context_t& hmac_ctx, DrgbOutput& output); 81void CryptoStep(CryptoCtx& ctx, mbedtls_md_context_t& hmac_ctx, DrgbOutput& output);
diff --git a/src/core/hle/service/nfc/common/device.cpp b/src/core/hle/service/nfc/common/device.cpp
index 2d633b03f..49446bc42 100644
--- a/src/core/hle/service/nfc/common/device.cpp
+++ b/src/core/hle/service/nfc/common/device.cpp
@@ -34,8 +34,6 @@
34#include "core/hle/service/nfc/mifare_result.h" 34#include "core/hle/service/nfc/mifare_result.h"
35#include "core/hle/service/nfc/nfc_result.h" 35#include "core/hle/service/nfc/nfc_result.h"
36#include "core/hle/service/time/time_manager.h" 36#include "core/hle/service/time/time_manager.h"
37#include "core/hle/service/time/time_zone_content_manager.h"
38#include "core/hle/service/time/time_zone_types.h"
39 37
40namespace Service::NFC { 38namespace Service::NFC {
41NfcDevice::NfcDevice(Core::HID::NpadIdType npad_id_, Core::System& system_, 39NfcDevice::NfcDevice(Core::HID::NpadIdType npad_id_, Core::System& system_,
@@ -1486,6 +1484,7 @@ DeviceState NfcDevice::GetCurrentState() const {
1486} 1484}
1487 1485
1488Result NfcDevice::GetNpadId(Core::HID::NpadIdType& out_npad_id) const { 1486Result NfcDevice::GetNpadId(Core::HID::NpadIdType& out_npad_id) const {
1487 // TODO: This should get the npad id from nn::hid::system::GetXcdHandleForNpadWithNfc
1489 out_npad_id = npad_id; 1488 out_npad_id = npad_id;
1490 return ResultSuccess; 1489 return ResultSuccess;
1491} 1490}
diff --git a/src/core/hle/service/nfc/common/device_manager.cpp b/src/core/hle/service/nfc/common/device_manager.cpp
index 562f3a28e..a71d26157 100644
--- a/src/core/hle/service/nfc/common/device_manager.cpp
+++ b/src/core/hle/service/nfc/common/device_manager.cpp
@@ -1,6 +1,8 @@
1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project 1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-3.0-or-later 2// SPDX-License-Identifier: GPL-3.0-or-later
3 3
4#include <algorithm>
5
4#include "common/logging/log.h" 6#include "common/logging/log.h"
5#include "core/core.h" 7#include "core/core.h"
6#include "core/hid/hid_types.h" 8#include "core/hid/hid_types.h"
@@ -10,6 +12,7 @@
10#include "core/hle/service/nfc/common/device_manager.h" 12#include "core/hle/service/nfc/common/device_manager.h"
11#include "core/hle/service/nfc/nfc_result.h" 13#include "core/hle/service/nfc/nfc_result.h"
12#include "core/hle/service/time/clock_types.h" 14#include "core/hle/service/time/clock_types.h"
15#include "core/hle/service/time/time_manager.h"
13 16
14namespace Service::NFC { 17namespace Service::NFC {
15 18
@@ -51,22 +54,53 @@ Result DeviceManager::Finalize() {
51 return ResultSuccess; 54 return ResultSuccess;
52} 55}
53 56
54Result DeviceManager::ListDevices(std::vector<u64>& nfp_devices, 57Result DeviceManager::ListDevices(std::vector<u64>& nfp_devices, std::size_t max_allowed_devices,
55 std::size_t max_allowed_devices) const { 58 bool skip_fatal_errors) const {
59 std::scoped_lock lock{mutex};
60 if (max_allowed_devices < 1) {
61 return ResultInvalidArgument;
62 }
63
64 Result result = IsNfcParameterSet();
65 if (result.IsError()) {
66 return result;
67 }
68
69 result = IsNfcEnabled();
70 if (result.IsError()) {
71 return result;
72 }
73
74 result = IsNfcInitialized();
75 if (result.IsError()) {
76 return result;
77 }
78
56 for (auto& device : devices) { 79 for (auto& device : devices) {
57 if (nfp_devices.size() >= max_allowed_devices) { 80 if (nfp_devices.size() >= max_allowed_devices) {
58 continue; 81 continue;
59 } 82 }
60 if (device->GetCurrentState() != DeviceState::Unavailable) { 83 if (skip_fatal_errors) {
61 nfp_devices.push_back(device->GetHandle()); 84 constexpr u64 MinimumRecoveryTime = 60;
85 auto& standard_steady_clock{system.GetTimeManager().GetStandardSteadyClockCore()};
86 const u64 elapsed_time = standard_steady_clock.GetCurrentTimePoint(system).time_point -
87 time_since_last_error;
88
89 if (time_since_last_error != 0 && elapsed_time < MinimumRecoveryTime) {
90 continue;
91 }
62 } 92 }
93 if (device->GetCurrentState() == DeviceState::Unavailable) {
94 continue;
95 }
96 nfp_devices.push_back(device->GetHandle());
63 } 97 }
64 98
65 if (nfp_devices.empty()) { 99 if (nfp_devices.empty()) {
66 return ResultDeviceNotFound; 100 return ResultDeviceNotFound;
67 } 101 }
68 102
69 return ResultSuccess; 103 return result;
70} 104}
71 105
72DeviceState DeviceManager::GetDeviceState(u64 device_handle) const { 106DeviceState DeviceManager::GetDeviceState(u64 device_handle) const {
@@ -79,10 +113,10 @@ DeviceState DeviceManager::GetDeviceState(u64 device_handle) const {
79 return device->GetCurrentState(); 113 return device->GetCurrentState();
80 } 114 }
81 115
82 return DeviceState::Unavailable; 116 return DeviceState::Finalized;
83} 117}
84 118
85Result DeviceManager::GetNpadId(u64 device_handle, Core::HID::NpadIdType& npad_id) const { 119Result DeviceManager::GetNpadId(u64 device_handle, Core::HID::NpadIdType& npad_id) {
86 std::scoped_lock lock{mutex}; 120 std::scoped_lock lock{mutex};
87 121
88 std::shared_ptr<NfcDevice> device = nullptr; 122 std::shared_ptr<NfcDevice> device = nullptr;
@@ -128,7 +162,7 @@ Result DeviceManager::StopDetection(u64 device_handle) {
128 return result; 162 return result;
129} 163}
130 164
131Result DeviceManager::GetTagInfo(u64 device_handle, TagInfo& tag_info) const { 165Result DeviceManager::GetTagInfo(u64 device_handle, TagInfo& tag_info) {
132 std::scoped_lock lock{mutex}; 166 std::scoped_lock lock{mutex};
133 167
134 std::shared_ptr<NfcDevice> device = nullptr; 168 std::shared_ptr<NfcDevice> device = nullptr;
@@ -142,24 +176,46 @@ Result DeviceManager::GetTagInfo(u64 device_handle, TagInfo& tag_info) const {
142 return result; 176 return result;
143} 177}
144 178
145Kernel::KReadableEvent& DeviceManager::AttachActivateEvent(u64 device_handle) const { 179Result DeviceManager::AttachActivateEvent(Kernel::KReadableEvent** out_event,
146 std::scoped_lock lock{mutex}; 180 u64 device_handle) const {
147 181 std::vector<u64> nfp_devices;
148 std::shared_ptr<NfcDevice> device = nullptr; 182 std::shared_ptr<NfcDevice> device = nullptr;
149 GetDeviceFromHandle(device_handle, device, false); 183 Result result = ListDevices(nfp_devices, 9, false);
150 184
151 // TODO: Return proper error code on failure 185 if (result.IsSuccess()) {
152 return device->GetActivateEvent(); 186 result = CheckHandleOnList(device_handle, nfp_devices);
153} 187 }
154 188
155Kernel::KReadableEvent& DeviceManager::AttachDeactivateEvent(u64 device_handle) const { 189 if (result.IsSuccess()) {
156 std::scoped_lock lock{mutex}; 190 result = GetDeviceFromHandle(device_handle, device, false);
191 }
192
193 if (result.IsSuccess()) {
194 *out_event = &device->GetActivateEvent();
195 }
196
197 return result;
198}
157 199
200Result DeviceManager::AttachDeactivateEvent(Kernel::KReadableEvent** out_event,
201 u64 device_handle) const {
202 std::vector<u64> nfp_devices;
158 std::shared_ptr<NfcDevice> device = nullptr; 203 std::shared_ptr<NfcDevice> device = nullptr;
159 GetDeviceFromHandle(device_handle, device, false); 204 Result result = ListDevices(nfp_devices, 9, false);
160 205
161 // TODO: Return proper error code on failure 206 if (result.IsSuccess()) {
162 return device->GetDeactivateEvent(); 207 result = CheckHandleOnList(device_handle, nfp_devices);
208 }
209
210 if (result.IsSuccess()) {
211 result = GetDeviceFromHandle(device_handle, device, false);
212 }
213
214 if (result.IsSuccess()) {
215 *out_event = &device->GetDeactivateEvent();
216 }
217
218 return result;
163} 219}
164 220
165Result DeviceManager::ReadMifare(u64 device_handle, 221Result DeviceManager::ReadMifare(u64 device_handle,
@@ -253,7 +309,7 @@ Result DeviceManager::OpenApplicationArea(u64 device_handle, u32 access_id) {
253 return result; 309 return result;
254} 310}
255 311
256Result DeviceManager::GetApplicationArea(u64 device_handle, std::span<u8> data) const { 312Result DeviceManager::GetApplicationArea(u64 device_handle, std::span<u8> data) {
257 std::scoped_lock lock{mutex}; 313 std::scoped_lock lock{mutex};
258 314
259 std::shared_ptr<NfcDevice> device = nullptr; 315 std::shared_ptr<NfcDevice> device = nullptr;
@@ -324,7 +380,7 @@ Result DeviceManager::CreateApplicationArea(u64 device_handle, u32 access_id,
324 return result; 380 return result;
325} 381}
326 382
327Result DeviceManager::GetRegisterInfo(u64 device_handle, NFP::RegisterInfo& register_info) const { 383Result DeviceManager::GetRegisterInfo(u64 device_handle, NFP::RegisterInfo& register_info) {
328 std::scoped_lock lock{mutex}; 384 std::scoped_lock lock{mutex};
329 385
330 std::shared_ptr<NfcDevice> device = nullptr; 386 std::shared_ptr<NfcDevice> device = nullptr;
@@ -338,7 +394,7 @@ Result DeviceManager::GetRegisterInfo(u64 device_handle, NFP::RegisterInfo& regi
338 return result; 394 return result;
339} 395}
340 396
341Result DeviceManager::GetCommonInfo(u64 device_handle, NFP::CommonInfo& common_info) const { 397Result DeviceManager::GetCommonInfo(u64 device_handle, NFP::CommonInfo& common_info) {
342 std::scoped_lock lock{mutex}; 398 std::scoped_lock lock{mutex};
343 399
344 std::shared_ptr<NfcDevice> device = nullptr; 400 std::shared_ptr<NfcDevice> device = nullptr;
@@ -352,7 +408,7 @@ Result DeviceManager::GetCommonInfo(u64 device_handle, NFP::CommonInfo& common_i
352 return result; 408 return result;
353} 409}
354 410
355Result DeviceManager::GetModelInfo(u64 device_handle, NFP::ModelInfo& model_info) const { 411Result DeviceManager::GetModelInfo(u64 device_handle, NFP::ModelInfo& model_info) {
356 std::scoped_lock lock{mutex}; 412 std::scoped_lock lock{mutex};
357 413
358 std::shared_ptr<NfcDevice> device = nullptr; 414 std::shared_ptr<NfcDevice> device = nullptr;
@@ -399,7 +455,7 @@ Result DeviceManager::Format(u64 device_handle) {
399 return result; 455 return result;
400} 456}
401 457
402Result DeviceManager::GetAdminInfo(u64 device_handle, NFP::AdminInfo& admin_info) const { 458Result DeviceManager::GetAdminInfo(u64 device_handle, NFP::AdminInfo& admin_info) {
403 std::scoped_lock lock{mutex}; 459 std::scoped_lock lock{mutex};
404 460
405 std::shared_ptr<NfcDevice> device = nullptr; 461 std::shared_ptr<NfcDevice> device = nullptr;
@@ -414,7 +470,7 @@ Result DeviceManager::GetAdminInfo(u64 device_handle, NFP::AdminInfo& admin_info
414} 470}
415 471
416Result DeviceManager::GetRegisterInfoPrivate(u64 device_handle, 472Result DeviceManager::GetRegisterInfoPrivate(u64 device_handle,
417 NFP::RegisterInfoPrivate& register_info) const { 473 NFP::RegisterInfoPrivate& register_info) {
418 std::scoped_lock lock{mutex}; 474 std::scoped_lock lock{mutex};
419 475
420 std::shared_ptr<NfcDevice> device = nullptr; 476 std::shared_ptr<NfcDevice> device = nullptr;
@@ -471,7 +527,7 @@ Result DeviceManager::DeleteApplicationArea(u64 device_handle) {
471 return result; 527 return result;
472} 528}
473 529
474Result DeviceManager::ExistsApplicationArea(u64 device_handle, bool& has_application_area) const { 530Result DeviceManager::ExistsApplicationArea(u64 device_handle, bool& has_application_area) {
475 std::scoped_lock lock{mutex}; 531 std::scoped_lock lock{mutex};
476 532
477 std::shared_ptr<NfcDevice> device = nullptr; 533 std::shared_ptr<NfcDevice> device = nullptr;
@@ -485,7 +541,7 @@ Result DeviceManager::ExistsApplicationArea(u64 device_handle, bool& has_applica
485 return result; 541 return result;
486} 542}
487 543
488Result DeviceManager::GetAll(u64 device_handle, NFP::NfpData& nfp_data) const { 544Result DeviceManager::GetAll(u64 device_handle, NFP::NfpData& nfp_data) {
489 std::scoped_lock lock{mutex}; 545 std::scoped_lock lock{mutex};
490 546
491 std::shared_ptr<NfcDevice> device = nullptr; 547 std::shared_ptr<NfcDevice> device = nullptr;
@@ -541,7 +597,7 @@ Result DeviceManager::BreakTag(u64 device_handle, NFP::BreakType break_type) {
541 return result; 597 return result;
542} 598}
543 599
544Result DeviceManager::ReadBackupData(u64 device_handle, std::span<u8> data) const { 600Result DeviceManager::ReadBackupData(u64 device_handle, std::span<u8> data) {
545 std::scoped_lock lock{mutex}; 601 std::scoped_lock lock{mutex};
546 602
547 std::shared_ptr<NfcDevice> device = nullptr; 603 std::shared_ptr<NfcDevice> device = nullptr;
@@ -593,6 +649,19 @@ Result DeviceManager::WriteNtf(u64 device_handle, NFP::WriteType, std::span<cons
593 return result; 649 return result;
594} 650}
595 651
652Result DeviceManager::CheckHandleOnList(u64 device_handle,
653 const std::span<const u64> device_list) const {
654 if (device_list.size() < 1) {
655 return ResultDeviceNotFound;
656 }
657
658 if (std::find(device_list.begin(), device_list.end(), device_handle) != device_list.end()) {
659 return ResultSuccess;
660 }
661
662 return ResultDeviceNotFound;
663}
664
596Result DeviceManager::GetDeviceFromHandle(u64 handle, std::shared_ptr<NfcDevice>& nfc_device, 665Result DeviceManager::GetDeviceFromHandle(u64 handle, std::shared_ptr<NfcDevice>& nfc_device,
597 bool check_state) const { 666 bool check_state) const {
598 if (check_state) { 667 if (check_state) {
@@ -647,7 +716,7 @@ Result DeviceManager::GetDeviceHandle(u64 handle, std::shared_ptr<NfcDevice>& de
647} 716}
648 717
649Result DeviceManager::VerifyDeviceResult(std::shared_ptr<NfcDevice> device, 718Result DeviceManager::VerifyDeviceResult(std::shared_ptr<NfcDevice> device,
650 Result operation_result) const { 719 Result operation_result) {
651 if (operation_result.IsSuccess()) { 720 if (operation_result.IsSuccess()) {
652 return operation_result; 721 return operation_result;
653 } 722 }
@@ -669,6 +738,12 @@ Result DeviceManager::VerifyDeviceResult(std::shared_ptr<NfcDevice> device,
669 return device_state; 738 return device_state;
670 } 739 }
671 740
741 if (operation_result == ResultUnknown112 || operation_result == ResultUnknown114 ||
742 operation_result == ResultUnknown115) {
743 auto& standard_steady_clock{system.GetTimeManager().GetStandardSteadyClockCore()};
744 time_since_last_error = standard_steady_clock.GetCurrentTimePoint(system).time_point;
745 }
746
672 return operation_result; 747 return operation_result;
673} 748}
674 749
diff --git a/src/core/hle/service/nfc/common/device_manager.h b/src/core/hle/service/nfc/common/device_manager.h
index c61ba0cf3..c9f038e32 100644
--- a/src/core/hle/service/nfc/common/device_manager.h
+++ b/src/core/hle/service/nfc/common/device_manager.h
@@ -27,15 +27,16 @@ public:
27 // Nfc device manager 27 // Nfc device manager
28 Result Initialize(); 28 Result Initialize();
29 Result Finalize(); 29 Result Finalize();
30 Result ListDevices(std::vector<u64>& nfp_devices, std::size_t max_allowed_devices) const; 30 Result ListDevices(std::vector<u64>& nfp_devices, std::size_t max_allowed_devices,
31 bool skip_fatal_errors) const;
31 DeviceState GetDeviceState(u64 device_handle) const; 32 DeviceState GetDeviceState(u64 device_handle) const;
32 Result GetNpadId(u64 device_handle, Core::HID::NpadIdType& npad_id) const; 33 Result GetNpadId(u64 device_handle, Core::HID::NpadIdType& npad_id);
33 Kernel::KReadableEvent& AttachAvailabilityChangeEvent() const; 34 Kernel::KReadableEvent& AttachAvailabilityChangeEvent() const;
34 Result StartDetection(u64 device_handle, NfcProtocol tag_protocol); 35 Result StartDetection(u64 device_handle, NfcProtocol tag_protocol);
35 Result StopDetection(u64 device_handle); 36 Result StopDetection(u64 device_handle);
36 Result GetTagInfo(u64 device_handle, NFP::TagInfo& tag_info) const; 37 Result GetTagInfo(u64 device_handle, NFP::TagInfo& tag_info);
37 Kernel::KReadableEvent& AttachActivateEvent(u64 device_handle) const; 38 Result AttachActivateEvent(Kernel::KReadableEvent** event, u64 device_handle) const;
38 Kernel::KReadableEvent& AttachDeactivateEvent(u64 device_handle) const; 39 Result AttachDeactivateEvent(Kernel::KReadableEvent** event, u64 device_handle) const;
39 Result ReadMifare(u64 device_handle, 40 Result ReadMifare(u64 device_handle,
40 const std::span<const MifareReadBlockParameter> read_parameters, 41 const std::span<const MifareReadBlockParameter> read_parameters,
41 std::span<MifareReadBlockData> read_data); 42 std::span<MifareReadBlockData> read_data);
@@ -48,28 +49,28 @@ public:
48 Result Mount(u64 device_handle, NFP::ModelType model_type, NFP::MountTarget mount_target); 49 Result Mount(u64 device_handle, NFP::ModelType model_type, NFP::MountTarget mount_target);
49 Result Unmount(u64 device_handle); 50 Result Unmount(u64 device_handle);
50 Result OpenApplicationArea(u64 device_handle, u32 access_id); 51 Result OpenApplicationArea(u64 device_handle, u32 access_id);
51 Result GetApplicationArea(u64 device_handle, std::span<u8> data) const; 52 Result GetApplicationArea(u64 device_handle, std::span<u8> data);
52 Result SetApplicationArea(u64 device_handle, std::span<const u8> data); 53 Result SetApplicationArea(u64 device_handle, std::span<const u8> data);
53 Result Flush(u64 device_handle); 54 Result Flush(u64 device_handle);
54 Result Restore(u64 device_handle); 55 Result Restore(u64 device_handle);
55 Result CreateApplicationArea(u64 device_handle, u32 access_id, std::span<const u8> data); 56 Result CreateApplicationArea(u64 device_handle, u32 access_id, std::span<const u8> data);
56 Result GetRegisterInfo(u64 device_handle, NFP::RegisterInfo& register_info) const; 57 Result GetRegisterInfo(u64 device_handle, NFP::RegisterInfo& register_info);
57 Result GetCommonInfo(u64 device_handle, NFP::CommonInfo& common_info) const; 58 Result GetCommonInfo(u64 device_handle, NFP::CommonInfo& common_info);
58 Result GetModelInfo(u64 device_handle, NFP::ModelInfo& model_info) const; 59 Result GetModelInfo(u64 device_handle, NFP::ModelInfo& model_info);
59 u32 GetApplicationAreaSize() const; 60 u32 GetApplicationAreaSize() const;
60 Result RecreateApplicationArea(u64 device_handle, u32 access_id, std::span<const u8> data); 61 Result RecreateApplicationArea(u64 device_handle, u32 access_id, std::span<const u8> data);
61 Result Format(u64 device_handle); 62 Result Format(u64 device_handle);
62 Result GetAdminInfo(u64 device_handle, NFP::AdminInfo& admin_info) const; 63 Result GetAdminInfo(u64 device_handle, NFP::AdminInfo& admin_info);
63 Result GetRegisterInfoPrivate(u64 device_handle, NFP::RegisterInfoPrivate& register_info) const; 64 Result GetRegisterInfoPrivate(u64 device_handle, NFP::RegisterInfoPrivate& register_info);
64 Result SetRegisterInfoPrivate(u64 device_handle, const NFP::RegisterInfoPrivate& register_info); 65 Result SetRegisterInfoPrivate(u64 device_handle, const NFP::RegisterInfoPrivate& register_info);
65 Result DeleteRegisterInfo(u64 device_handle); 66 Result DeleteRegisterInfo(u64 device_handle);
66 Result DeleteApplicationArea(u64 device_handle); 67 Result DeleteApplicationArea(u64 device_handle);
67 Result ExistsApplicationArea(u64 device_handle, bool& has_application_area) const; 68 Result ExistsApplicationArea(u64 device_handle, bool& has_application_area);
68 Result GetAll(u64 device_handle, NFP::NfpData& nfp_data) const; 69 Result GetAll(u64 device_handle, NFP::NfpData& nfp_data);
69 Result SetAll(u64 device_handle, const NFP::NfpData& nfp_data); 70 Result SetAll(u64 device_handle, const NFP::NfpData& nfp_data);
70 Result FlushDebug(u64 device_handle); 71 Result FlushDebug(u64 device_handle);
71 Result BreakTag(u64 device_handle, NFP::BreakType break_type); 72 Result BreakTag(u64 device_handle, NFP::BreakType break_type);
72 Result ReadBackupData(u64 device_handle, std::span<u8> data) const; 73 Result ReadBackupData(u64 device_handle, std::span<u8> data);
73 Result WriteBackupData(u64 device_handle, std::span<const u8> data); 74 Result WriteBackupData(u64 device_handle, std::span<const u8> data);
74 Result WriteNtf(u64 device_handle, NFP::WriteType, std::span<const u8> data); 75 Result WriteNtf(u64 device_handle, NFP::WriteType, std::span<const u8> data);
75 76
@@ -78,17 +79,20 @@ private:
78 Result IsNfcParameterSet() const; 79 Result IsNfcParameterSet() const;
79 Result IsNfcInitialized() const; 80 Result IsNfcInitialized() const;
80 81
82 Result CheckHandleOnList(u64 device_handle, std::span<const u64> device_list) const;
83
81 Result GetDeviceFromHandle(u64 handle, std::shared_ptr<NfcDevice>& device, 84 Result GetDeviceFromHandle(u64 handle, std::shared_ptr<NfcDevice>& device,
82 bool check_state) const; 85 bool check_state) const;
83 86
84 Result GetDeviceHandle(u64 handle, std::shared_ptr<NfcDevice>& device) const; 87 Result GetDeviceHandle(u64 handle, std::shared_ptr<NfcDevice>& device) const;
85 Result VerifyDeviceResult(std::shared_ptr<NfcDevice> device, Result operation_result) const; 88 Result VerifyDeviceResult(std::shared_ptr<NfcDevice> device, Result operation_result);
86 Result CheckDeviceState(std::shared_ptr<NfcDevice> device) const; 89 Result CheckDeviceState(std::shared_ptr<NfcDevice> device) const;
87 90
88 std::optional<std::shared_ptr<NfcDevice>> GetNfcDevice(u64 handle); 91 std::optional<std::shared_ptr<NfcDevice>> GetNfcDevice(u64 handle);
89 const std::optional<std::shared_ptr<NfcDevice>> GetNfcDevice(u64 handle) const; 92 const std::optional<std::shared_ptr<NfcDevice>> GetNfcDevice(u64 handle) const;
90 93
91 bool is_initialized = false; 94 bool is_initialized = false;
95 u64 time_since_last_error = 0;
92 mutable std::mutex mutex; 96 mutable std::mutex mutex;
93 std::array<std::shared_ptr<NfcDevice>, 10> devices{}; 97 std::array<std::shared_ptr<NfcDevice>, 10> devices{};
94 98
diff --git a/src/core/hle/service/nfc/nfc_interface.cpp b/src/core/hle/service/nfc/nfc_interface.cpp
index e7ca7582e..179c7ba2c 100644
--- a/src/core/hle/service/nfc/nfc_interface.cpp
+++ b/src/core/hle/service/nfc/nfc_interface.cpp
@@ -79,7 +79,7 @@ void NfcInterface::ListDevices(HLERequestContext& ctx) {
79 const std::size_t max_allowed_devices = ctx.GetWriteBufferNumElements<u64>(); 79 const std::size_t max_allowed_devices = ctx.GetWriteBufferNumElements<u64>();
80 LOG_DEBUG(Service_NFC, "called"); 80 LOG_DEBUG(Service_NFC, "called");
81 81
82 auto result = GetManager()->ListDevices(nfp_devices, max_allowed_devices); 82 auto result = GetManager()->ListDevices(nfp_devices, max_allowed_devices, true);
83 result = TranslateResultToServiceError(result); 83 result = TranslateResultToServiceError(result);
84 84
85 if (result.IsError()) { 85 if (result.IsError()) {
@@ -190,9 +190,13 @@ void NfcInterface::AttachActivateEvent(HLERequestContext& ctx) {
190 const auto device_handle{rp.Pop<u64>()}; 190 const auto device_handle{rp.Pop<u64>()};
191 LOG_DEBUG(Service_NFC, "called, device_handle={}", device_handle); 191 LOG_DEBUG(Service_NFC, "called, device_handle={}", device_handle);
192 192
193 Kernel::KReadableEvent* out_event = nullptr;
194 auto result = GetManager()->AttachActivateEvent(&out_event, device_handle);
195 result = TranslateResultToServiceError(result);
196
193 IPC::ResponseBuilder rb{ctx, 2, 1}; 197 IPC::ResponseBuilder rb{ctx, 2, 1};
194 rb.Push(ResultSuccess); 198 rb.Push(result);
195 rb.PushCopyObjects(GetManager()->AttachActivateEvent(device_handle)); 199 rb.PushCopyObjects(out_event);
196} 200}
197 201
198void NfcInterface::AttachDeactivateEvent(HLERequestContext& ctx) { 202void NfcInterface::AttachDeactivateEvent(HLERequestContext& ctx) {
@@ -200,9 +204,13 @@ void NfcInterface::AttachDeactivateEvent(HLERequestContext& ctx) {
200 const auto device_handle{rp.Pop<u64>()}; 204 const auto device_handle{rp.Pop<u64>()};
201 LOG_DEBUG(Service_NFC, "called, device_handle={}", device_handle); 205 LOG_DEBUG(Service_NFC, "called, device_handle={}", device_handle);
202 206
207 Kernel::KReadableEvent* out_event = nullptr;
208 auto result = GetManager()->AttachDeactivateEvent(&out_event, device_handle);
209 result = TranslateResultToServiceError(result);
210
203 IPC::ResponseBuilder rb{ctx, 2, 1}; 211 IPC::ResponseBuilder rb{ctx, 2, 1};
204 rb.Push(ResultSuccess); 212 rb.Push(result);
205 rb.PushCopyObjects(GetManager()->AttachDeactivateEvent(device_handle)); 213 rb.PushCopyObjects(out_event);
206} 214}
207 215
208void NfcInterface::ReadMifare(HLERequestContext& ctx) { 216void NfcInterface::ReadMifare(HLERequestContext& ctx) {
diff --git a/src/core/hle/service/nfc/nfc_result.h b/src/core/hle/service/nfc/nfc_result.h
index 715c0e80c..464b5fd69 100644
--- a/src/core/hle/service/nfc/nfc_result.h
+++ b/src/core/hle/service/nfc/nfc_result.h
@@ -17,7 +17,10 @@ constexpr Result ResultNfcNotInitialized(ErrorModule::NFC, 77);
17constexpr Result ResultNfcDisabled(ErrorModule::NFC, 80); 17constexpr Result ResultNfcDisabled(ErrorModule::NFC, 80);
18constexpr Result ResultWriteAmiiboFailed(ErrorModule::NFC, 88); 18constexpr Result ResultWriteAmiiboFailed(ErrorModule::NFC, 88);
19constexpr Result ResultTagRemoved(ErrorModule::NFC, 97); 19constexpr Result ResultTagRemoved(ErrorModule::NFC, 97);
20constexpr Result ResultUnknown112(ErrorModule::NFC, 112);
20constexpr Result ResultUnableToAccessBackupFile(ErrorModule::NFC, 113); 21constexpr Result ResultUnableToAccessBackupFile(ErrorModule::NFC, 113);
22constexpr Result ResultUnknown114(ErrorModule::NFC, 114);
23constexpr Result ResultUnknown115(ErrorModule::NFC, 115);
21constexpr Result ResultRegistrationIsNotInitialized(ErrorModule::NFC, 120); 24constexpr Result ResultRegistrationIsNotInitialized(ErrorModule::NFC, 120);
22constexpr Result ResultApplicationAreaIsNotInitialized(ErrorModule::NFC, 128); 25constexpr Result ResultApplicationAreaIsNotInitialized(ErrorModule::NFC, 128);
23constexpr Result ResultCorruptedDataWithBackup(ErrorModule::NFC, 136); 26constexpr Result ResultCorruptedDataWithBackup(ErrorModule::NFC, 136);
diff --git a/src/core/hle/service/nvdrv/devices/nvmap.cpp b/src/core/hle/service/nvdrv/devices/nvmap.cpp
index e7f7e273b..968eaa175 100644
--- a/src/core/hle/service/nvdrv/devices/nvmap.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvmap.cpp
@@ -128,7 +128,7 @@ NvResult nvmap::IocAlloc(std::span<const u8> input, std::span<u8> output) {
128 } 128 }
129 bool is_out_io{}; 129 bool is_out_io{};
130 ASSERT(system.ApplicationProcess() 130 ASSERT(system.ApplicationProcess()
131 ->PageTable() 131 ->GetPageTable()
132 .LockForMapDeviceAddressSpace(&is_out_io, handle_description->address, 132 .LockForMapDeviceAddressSpace(&is_out_io, handle_description->address,
133 handle_description->size, 133 handle_description->size,
134 Kernel::KMemoryPermission::None, true, false) 134 Kernel::KMemoryPermission::None, true, false)
@@ -255,7 +255,7 @@ NvResult nvmap::IocFree(std::span<const u8> input, std::span<u8> output) {
255 if (auto freeInfo{file.FreeHandle(params.handle, false)}) { 255 if (auto freeInfo{file.FreeHandle(params.handle, false)}) {
256 if (freeInfo->can_unlock) { 256 if (freeInfo->can_unlock) {
257 ASSERT(system.ApplicationProcess() 257 ASSERT(system.ApplicationProcess()
258 ->PageTable() 258 ->GetPageTable()
259 .UnlockForDeviceAddressSpace(freeInfo->address, freeInfo->size) 259 .UnlockForDeviceAddressSpace(freeInfo->address, freeInfo->size)
260 .IsSuccess()); 260 .IsSuccess());
261 } 261 }
diff --git a/src/core/hle/service/sockets/bsd.cpp b/src/core/hle/service/sockets/bsd.cpp
index e63b0a357..11f8efbac 100644
--- a/src/core/hle/service/sockets/bsd.cpp
+++ b/src/core/hle/service/sockets/bsd.cpp
@@ -559,7 +559,7 @@ std::pair<s32, Errno> BSD::PollImpl(std::vector<u8>& write_buffer, std::span<con
559 559
560 const std::optional<FileDescriptor>& descriptor = file_descriptors[pollfd.fd]; 560 const std::optional<FileDescriptor>& descriptor = file_descriptors[pollfd.fd];
561 if (!descriptor) { 561 if (!descriptor) {
562 LOG_ERROR(Service, "File descriptor handle={} is not allocated", pollfd.fd); 562 LOG_TRACE(Service, "File descriptor handle={} is not allocated", pollfd.fd);
563 pollfd.revents = PollEvents::Nval; 563 pollfd.revents = PollEvents::Nval;
564 return {0, Errno::SUCCESS}; 564 return {0, Errno::SUCCESS};
565 } 565 }
diff --git a/src/core/hle/service/sockets/nsd.cpp b/src/core/hle/service/sockets/nsd.cpp
index 0dfb0f166..5dfcaabb1 100644
--- a/src/core/hle/service/sockets/nsd.cpp
+++ b/src/core/hle/service/sockets/nsd.cpp
@@ -10,12 +10,21 @@ namespace Service::Sockets {
10 10
11constexpr Result ResultOverflow{ErrorModule::NSD, 6}; 11constexpr Result ResultOverflow{ErrorModule::NSD, 6};
12 12
13// This is nn::oe::ServerEnvironmentType
14enum class ServerEnvironmentType : u8 {
15 Dd,
16 Lp,
17 Sd,
18 Sp,
19 Dp,
20};
21
13NSD::NSD(Core::System& system_, const char* name) : ServiceFramework{system_, name} { 22NSD::NSD(Core::System& system_, const char* name) : ServiceFramework{system_, name} {
14 // clang-format off 23 // clang-format off
15 static const FunctionInfo functions[] = { 24 static const FunctionInfo functions[] = {
16 {5, nullptr, "GetSettingUrl"}, 25 {5, nullptr, "GetSettingUrl"},
17 {10, nullptr, "GetSettingName"}, 26 {10, nullptr, "GetSettingName"},
18 {11, nullptr, "GetEnvironmentIdentifier"}, 27 {11, &NSD::GetEnvironmentIdentifier, "GetEnvironmentIdentifier"},
19 {12, nullptr, "GetDeviceId"}, 28 {12, nullptr, "GetDeviceId"},
20 {13, nullptr, "DeleteSettings"}, 29 {13, nullptr, "DeleteSettings"},
21 {14, nullptr, "ImportSettings"}, 30 {14, nullptr, "ImportSettings"},
@@ -36,7 +45,7 @@ NSD::NSD(Core::System& system_, const char* name) : ServiceFramework{system_, na
36 {62, nullptr, "DeleteSaveDataOfFsForTest"}, 45 {62, nullptr, "DeleteSaveDataOfFsForTest"},
37 {63, nullptr, "IsChangeEnvironmentIdentifierDisabled"}, 46 {63, nullptr, "IsChangeEnvironmentIdentifierDisabled"},
38 {64, nullptr, "SetWithoutDomainExchangeFqdns"}, 47 {64, nullptr, "SetWithoutDomainExchangeFqdns"},
39 {100, nullptr, "GetApplicationServerEnvironmentType"}, 48 {100, &NSD::GetApplicationServerEnvironmentType, "GetApplicationServerEnvironmentType"},
40 {101, nullptr, "SetApplicationServerEnvironmentType"}, 49 {101, nullptr, "SetApplicationServerEnvironmentType"},
41 {102, nullptr, "DeleteApplicationServerEnvironmentType"}, 50 {102, nullptr, "DeleteApplicationServerEnvironmentType"},
42 }; 51 };
@@ -94,6 +103,20 @@ void NSD::ResolveEx(HLERequestContext& ctx) {
94 rb.Push(ResultSuccess); 103 rb.Push(ResultSuccess);
95} 104}
96 105
106void NSD::GetEnvironmentIdentifier(HLERequestContext& ctx) {
107 const std::string environment_identifier = "lp1";
108 ctx.WriteBuffer(environment_identifier);
109
110 IPC::ResponseBuilder rb{ctx, 2};
111 rb.Push(ResultSuccess);
112}
113
114void NSD::GetApplicationServerEnvironmentType(HLERequestContext& ctx) {
115 IPC::ResponseBuilder rb{ctx, 3};
116 rb.Push(ResultSuccess);
117 rb.Push(static_cast<u32>(ServerEnvironmentType::Lp));
118}
119
97NSD::~NSD() = default; 120NSD::~NSD() = default;
98 121
99} // namespace Service::Sockets 122} // namespace Service::Sockets
diff --git a/src/core/hle/service/sockets/nsd.h b/src/core/hle/service/sockets/nsd.h
index a7379a8a9..b0cfec507 100644
--- a/src/core/hle/service/sockets/nsd.h
+++ b/src/core/hle/service/sockets/nsd.h
@@ -19,6 +19,8 @@ public:
19private: 19private:
20 void Resolve(HLERequestContext& ctx); 20 void Resolve(HLERequestContext& ctx);
21 void ResolveEx(HLERequestContext& ctx); 21 void ResolveEx(HLERequestContext& ctx);
22 void GetEnvironmentIdentifier(HLERequestContext& ctx);
23 void GetApplicationServerEnvironmentType(HLERequestContext& ctx);
22}; 24};
23 25
24} // namespace Service::Sockets 26} // namespace Service::Sockets
diff --git a/src/core/hle/service/sockets/sfdnsres.cpp b/src/core/hle/service/sockets/sfdnsres.cpp
index 84cc79de8..22e4a6f49 100644
--- a/src/core/hle/service/sockets/sfdnsres.cpp
+++ b/src/core/hle/service/sockets/sfdnsres.cpp
@@ -24,7 +24,7 @@ SFDNSRES::SFDNSRES(Core::System& system_) : ServiceFramework{system_, "sfdnsres"
24 {2, &SFDNSRES::GetHostByNameRequest, "GetHostByNameRequest"}, 24 {2, &SFDNSRES::GetHostByNameRequest, "GetHostByNameRequest"},
25 {3, nullptr, "GetHostByAddrRequest"}, 25 {3, nullptr, "GetHostByAddrRequest"},
26 {4, nullptr, "GetHostStringErrorRequest"}, 26 {4, nullptr, "GetHostStringErrorRequest"},
27 {5, nullptr, "GetGaiStringErrorRequest"}, 27 {5, &SFDNSRES::GetGaiStringErrorRequest, "GetGaiStringErrorRequest"},
28 {6, &SFDNSRES::GetAddrInfoRequest, "GetAddrInfoRequest"}, 28 {6, &SFDNSRES::GetAddrInfoRequest, "GetAddrInfoRequest"},
29 {7, nullptr, "GetNameInfoRequest"}, 29 {7, nullptr, "GetNameInfoRequest"},
30 {8, nullptr, "RequestCancelHandleRequest"}, 30 {8, nullptr, "RequestCancelHandleRequest"},
@@ -300,6 +300,20 @@ void SFDNSRES::GetAddrInfoRequest(HLERequestContext& ctx) {
300 }); 300 });
301} 301}
302 302
303void SFDNSRES::GetGaiStringErrorRequest(HLERequestContext& ctx) {
304 struct InputParameters {
305 GetAddrInfoError gai_errno;
306 };
307 IPC::RequestParser rp{ctx};
308 auto input = rp.PopRaw<InputParameters>();
309
310 const std::string result = Translate(input.gai_errno);
311 ctx.WriteBuffer(result);
312
313 IPC::ResponseBuilder rb{ctx, 2};
314 rb.Push(ResultSuccess);
315}
316
303void SFDNSRES::GetAddrInfoRequestWithOptions(HLERequestContext& ctx) { 317void SFDNSRES::GetAddrInfoRequestWithOptions(HLERequestContext& ctx) {
304 // Additional options are ignored 318 // Additional options are ignored
305 auto [data_size, emu_gai_err] = GetAddrInfoRequestImpl(ctx); 319 auto [data_size, emu_gai_err] = GetAddrInfoRequestImpl(ctx);
diff --git a/src/core/hle/service/sockets/sfdnsres.h b/src/core/hle/service/sockets/sfdnsres.h
index d99a9d560..282ef9071 100644
--- a/src/core/hle/service/sockets/sfdnsres.h
+++ b/src/core/hle/service/sockets/sfdnsres.h
@@ -18,6 +18,7 @@ public:
18 18
19private: 19private:
20 void GetHostByNameRequest(HLERequestContext& ctx); 20 void GetHostByNameRequest(HLERequestContext& ctx);
21 void GetGaiStringErrorRequest(HLERequestContext& ctx);
21 void GetHostByNameRequestWithOptions(HLERequestContext& ctx); 22 void GetHostByNameRequestWithOptions(HLERequestContext& ctx);
22 void GetAddrInfoRequest(HLERequestContext& ctx); 23 void GetAddrInfoRequest(HLERequestContext& ctx);
23 void GetAddrInfoRequestWithOptions(HLERequestContext& ctx); 24 void GetAddrInfoRequestWithOptions(HLERequestContext& ctx);
diff --git a/src/core/hle/service/sockets/sockets_translate.cpp b/src/core/hle/service/sockets/sockets_translate.cpp
index 2f9a0e39c..c1187209f 100644
--- a/src/core/hle/service/sockets/sockets_translate.cpp
+++ b/src/core/hle/service/sockets/sockets_translate.cpp
@@ -81,6 +81,44 @@ GetAddrInfoError Translate(Network::GetAddrInfoError error) {
81 } 81 }
82} 82}
83 83
84const char* Translate(GetAddrInfoError error) {
85 // https://android.googlesource.com/platform/bionic/+/085543106/libc/dns/net/getaddrinfo.c#254
86 switch (error) {
87 case GetAddrInfoError::SUCCESS:
88 return "Success";
89 case GetAddrInfoError::ADDRFAMILY:
90 return "Address family for hostname not supported";
91 case GetAddrInfoError::AGAIN:
92 return "Temporary failure in name resolution";
93 case GetAddrInfoError::BADFLAGS:
94 return "Invalid value for ai_flags";
95 case GetAddrInfoError::FAIL:
96 return "Non-recoverable failure in name resolution";
97 case GetAddrInfoError::FAMILY:
98 return "ai_family not supported";
99 case GetAddrInfoError::MEMORY:
100 return "Memory allocation failure";
101 case GetAddrInfoError::NODATA:
102 return "No address associated with hostname";
103 case GetAddrInfoError::NONAME:
104 return "hostname nor servname provided, or not known";
105 case GetAddrInfoError::SERVICE:
106 return "servname not supported for ai_socktype";
107 case GetAddrInfoError::SOCKTYPE:
108 return "ai_socktype not supported";
109 case GetAddrInfoError::SYSTEM:
110 return "System error returned in errno";
111 case GetAddrInfoError::BADHINTS:
112 return "Invalid value for hints";
113 case GetAddrInfoError::PROTOCOL:
114 return "Resolved protocol is unknown";
115 case GetAddrInfoError::OVERFLOW_:
116 return "Argument buffer overflow";
117 default:
118 return "Unknown error";
119 }
120}
121
84Network::Domain Translate(Domain domain) { 122Network::Domain Translate(Domain domain) {
85 switch (domain) { 123 switch (domain) {
86 case Domain::Unspecified: 124 case Domain::Unspecified:
diff --git a/src/core/hle/service/sockets/sockets_translate.h b/src/core/hle/service/sockets/sockets_translate.h
index 694868b37..bd6721fd3 100644
--- a/src/core/hle/service/sockets/sockets_translate.h
+++ b/src/core/hle/service/sockets/sockets_translate.h
@@ -20,6 +20,9 @@ std::pair<s32, Errno> Translate(std::pair<s32, Network::Errno> value);
20/// Translate abstract getaddrinfo error to guest getaddrinfo error 20/// Translate abstract getaddrinfo error to guest getaddrinfo error
21GetAddrInfoError Translate(Network::GetAddrInfoError value); 21GetAddrInfoError Translate(Network::GetAddrInfoError value);
22 22
23/// Translate guest error to string
24const char* Translate(GetAddrInfoError value);
25
23/// Translate guest domain to abstract domain 26/// Translate guest domain to abstract domain
24Network::Domain Translate(Domain domain); 27Network::Domain Translate(Domain domain);
25 28
diff --git a/src/core/loader/deconstructed_rom_directory.cpp b/src/core/loader/deconstructed_rom_directory.cpp
index 3be9b71cf..e04ad19db 100644
--- a/src/core/loader/deconstructed_rom_directory.cpp
+++ b/src/core/loader/deconstructed_rom_directory.cpp
@@ -153,7 +153,7 @@ AppLoader_DeconstructedRomDirectory::LoadResult AppLoader_DeconstructedRomDirect
153 153
154 // Load NSO modules 154 // Load NSO modules
155 modules.clear(); 155 modules.clear();
156 const VAddr base_address{GetInteger(process.PageTable().GetCodeRegionStart())}; 156 const VAddr base_address{GetInteger(process.GetPageTable().GetCodeRegionStart())};
157 VAddr next_load_addr{base_address}; 157 VAddr next_load_addr{base_address};
158 const FileSys::PatchManager pm{metadata.GetTitleID(), system.GetFileSystemController(), 158 const FileSys::PatchManager pm{metadata.GetTitleID(), system.GetFileSystemController(),
159 system.GetContentProvider()}; 159 system.GetContentProvider()};
diff --git a/src/core/loader/kip.cpp b/src/core/loader/kip.cpp
index 709e2564f..ffe976b94 100644
--- a/src/core/loader/kip.cpp
+++ b/src/core/loader/kip.cpp
@@ -96,7 +96,7 @@ AppLoader::LoadResult AppLoader_KIP::Load(Kernel::KProcess& process,
96 } 96 }
97 97
98 codeset.memory = std::move(program_image); 98 codeset.memory = std::move(program_image);
99 const VAddr base_address = GetInteger(process.PageTable().GetCodeRegionStart()); 99 const VAddr base_address = GetInteger(process.GetPageTable().GetCodeRegionStart());
100 process.LoadModule(std::move(codeset), base_address); 100 process.LoadModule(std::move(codeset), base_address);
101 101
102 LOG_DEBUG(Loader, "loaded module {} @ 0x{:X}", kip->GetName(), base_address); 102 LOG_DEBUG(Loader, "loaded module {} @ 0x{:X}", kip->GetName(), base_address);
diff --git a/src/core/loader/nro.cpp b/src/core/loader/nro.cpp
index 7be6cf5f3..506808b5d 100644
--- a/src/core/loader/nro.cpp
+++ b/src/core/loader/nro.cpp
@@ -203,7 +203,7 @@ static bool LoadNroImpl(Kernel::KProcess& process, const std::vector<u8>& data)
203 203
204 // Load codeset for current process 204 // Load codeset for current process
205 codeset.memory = std::move(program_image); 205 codeset.memory = std::move(program_image);
206 process.LoadModule(std::move(codeset), process.PageTable().GetCodeRegionStart()); 206 process.LoadModule(std::move(codeset), process.GetPageTable().GetCodeRegionStart());
207 207
208 return true; 208 return true;
209} 209}
diff --git a/src/core/loader/nso.cpp b/src/core/loader/nso.cpp
index 79639f5e4..74cc9579f 100644
--- a/src/core/loader/nso.cpp
+++ b/src/core/loader/nso.cpp
@@ -167,7 +167,7 @@ AppLoader_NSO::LoadResult AppLoader_NSO::Load(Kernel::KProcess& process, Core::S
167 modules.clear(); 167 modules.clear();
168 168
169 // Load module 169 // Load module
170 const VAddr base_address = GetInteger(process.PageTable().GetCodeRegionStart()); 170 const VAddr base_address = GetInteger(process.GetPageTable().GetCodeRegionStart());
171 if (!LoadModule(process, system, *file, base_address, true, true)) { 171 if (!LoadModule(process, system, *file, base_address, true, true)) {
172 return {ResultStatus::ErrorLoadingNSO, {}}; 172 return {ResultStatus::ErrorLoadingNSO, {}};
173 } 173 }
diff --git a/src/core/memory.cpp b/src/core/memory.cpp
index 805963178..513bc4edb 100644
--- a/src/core/memory.cpp
+++ b/src/core/memory.cpp
@@ -31,10 +31,10 @@ struct Memory::Impl {
31 explicit Impl(Core::System& system_) : system{system_} {} 31 explicit Impl(Core::System& system_) : system{system_} {}
32 32
33 void SetCurrentPageTable(Kernel::KProcess& process, u32 core_id) { 33 void SetCurrentPageTable(Kernel::KProcess& process, u32 core_id) {
34 current_page_table = &process.PageTable().PageTableImpl(); 34 current_page_table = &process.GetPageTable().PageTableImpl();
35 current_page_table->fastmem_arena = system.DeviceMemory().buffer.VirtualBasePointer(); 35 current_page_table->fastmem_arena = system.DeviceMemory().buffer.VirtualBasePointer();
36 36
37 const std::size_t address_space_width = process.PageTable().GetAddressSpaceWidth(); 37 const std::size_t address_space_width = process.GetPageTable().GetAddressSpaceWidth();
38 38
39 system.ArmInterface(core_id).PageTableChanged(*current_page_table, address_space_width); 39 system.ArmInterface(core_id).PageTableChanged(*current_page_table, address_space_width);
40 } 40 }
@@ -73,7 +73,7 @@ struct Memory::Impl {
73 return {}; 73 return {};
74 } 74 }
75 75
76 return system.DeviceMemory().GetPointer<u8>(paddr) + vaddr; 76 return system.DeviceMemory().GetPointer<u8>(paddr + vaddr);
77 } 77 }
78 78
79 [[nodiscard]] u8* GetPointerFromDebugMemory(u64 vaddr) const { 79 [[nodiscard]] u8* GetPointerFromDebugMemory(u64 vaddr) const {
@@ -84,7 +84,7 @@ struct Memory::Impl {
84 return {}; 84 return {};
85 } 85 }
86 86
87 return system.DeviceMemory().GetPointer<u8>(paddr) + vaddr; 87 return system.DeviceMemory().GetPointer<u8>(paddr + vaddr);
88 } 88 }
89 89
90 u8 Read8(const Common::ProcessAddress addr) { 90 u8 Read8(const Common::ProcessAddress addr) {
@@ -183,13 +183,13 @@ struct Memory::Impl {
183 return string; 183 return string;
184 } 184 }
185 185
186 void WalkBlock(const Kernel::KProcess& process, const Common::ProcessAddress addr, 186 bool WalkBlock(const Common::ProcessAddress addr, const std::size_t size, auto on_unmapped,
187 const std::size_t size, auto on_unmapped, auto on_memory, auto on_rasterizer, 187 auto on_memory, auto on_rasterizer, auto increment) {
188 auto increment) { 188 const auto& page_table = system.ApplicationProcess()->GetPageTable().PageTableImpl();
189 const auto& page_table = process.PageTable().PageTableImpl();
190 std::size_t remaining_size = size; 189 std::size_t remaining_size = size;
191 std::size_t page_index = addr >> YUZU_PAGEBITS; 190 std::size_t page_index = addr >> YUZU_PAGEBITS;
192 std::size_t page_offset = addr & YUZU_PAGEMASK; 191 std::size_t page_offset = addr & YUZU_PAGEMASK;
192 bool user_accessible = true;
193 193
194 while (remaining_size) { 194 while (remaining_size) {
195 const std::size_t copy_amount = 195 const std::size_t copy_amount =
@@ -200,11 +200,13 @@ struct Memory::Impl {
200 const auto [pointer, type] = page_table.pointers[page_index].PointerType(); 200 const auto [pointer, type] = page_table.pointers[page_index].PointerType();
201 switch (type) { 201 switch (type) {
202 case Common::PageType::Unmapped: { 202 case Common::PageType::Unmapped: {
203 user_accessible = false;
203 on_unmapped(copy_amount, current_vaddr); 204 on_unmapped(copy_amount, current_vaddr);
204 break; 205 break;
205 } 206 }
206 case Common::PageType::Memory: { 207 case Common::PageType::Memory: {
207 u8* mem_ptr = pointer + page_offset + (page_index << YUZU_PAGEBITS); 208 u8* mem_ptr =
209 reinterpret_cast<u8*>(pointer + page_offset + (page_index << YUZU_PAGEBITS));
208 on_memory(copy_amount, mem_ptr); 210 on_memory(copy_amount, mem_ptr);
209 break; 211 break;
210 } 212 }
@@ -227,13 +229,15 @@ struct Memory::Impl {
227 increment(copy_amount); 229 increment(copy_amount);
228 remaining_size -= copy_amount; 230 remaining_size -= copy_amount;
229 } 231 }
232
233 return user_accessible;
230 } 234 }
231 235
232 template <bool UNSAFE> 236 template <bool UNSAFE>
233 void ReadBlockImpl(const Kernel::KProcess& process, const Common::ProcessAddress src_addr, 237 bool ReadBlockImpl(const Common::ProcessAddress src_addr, void* dest_buffer,
234 void* dest_buffer, const std::size_t size) { 238 const std::size_t size) {
235 WalkBlock( 239 return WalkBlock(
236 process, src_addr, size, 240 src_addr, size,
237 [src_addr, size, &dest_buffer](const std::size_t copy_amount, 241 [src_addr, size, &dest_buffer](const std::size_t copy_amount,
238 const Common::ProcessAddress current_vaddr) { 242 const Common::ProcessAddress current_vaddr) {
239 LOG_ERROR(HW_Memory, 243 LOG_ERROR(HW_Memory,
@@ -256,14 +260,14 @@ struct Memory::Impl {
256 }); 260 });
257 } 261 }
258 262
259 void ReadBlock(const Common::ProcessAddress src_addr, void* dest_buffer, 263 bool ReadBlock(const Common::ProcessAddress src_addr, void* dest_buffer,
260 const std::size_t size) { 264 const std::size_t size) {
261 ReadBlockImpl<false>(*system.ApplicationProcess(), src_addr, dest_buffer, size); 265 return ReadBlockImpl<false>(src_addr, dest_buffer, size);
262 } 266 }
263 267
264 void ReadBlockUnsafe(const Common::ProcessAddress src_addr, void* dest_buffer, 268 bool ReadBlockUnsafe(const Common::ProcessAddress src_addr, void* dest_buffer,
265 const std::size_t size) { 269 const std::size_t size) {
266 ReadBlockImpl<true>(*system.ApplicationProcess(), src_addr, dest_buffer, size); 270 return ReadBlockImpl<true>(src_addr, dest_buffer, size);
267 } 271 }
268 272
269 const u8* GetSpan(const VAddr src_addr, const std::size_t size) const { 273 const u8* GetSpan(const VAddr src_addr, const std::size_t size) const {
@@ -283,10 +287,10 @@ struct Memory::Impl {
283 } 287 }
284 288
285 template <bool UNSAFE> 289 template <bool UNSAFE>
286 void WriteBlockImpl(const Kernel::KProcess& process, const Common::ProcessAddress dest_addr, 290 bool WriteBlockImpl(const Common::ProcessAddress dest_addr, const void* src_buffer,
287 const void* src_buffer, const std::size_t size) { 291 const std::size_t size) {
288 WalkBlock( 292 return WalkBlock(
289 process, dest_addr, size, 293 dest_addr, size,
290 [dest_addr, size](const std::size_t copy_amount, 294 [dest_addr, size](const std::size_t copy_amount,
291 const Common::ProcessAddress current_vaddr) { 295 const Common::ProcessAddress current_vaddr) {
292 LOG_ERROR(HW_Memory, 296 LOG_ERROR(HW_Memory,
@@ -308,20 +312,19 @@ struct Memory::Impl {
308 }); 312 });
309 } 313 }
310 314
311 void WriteBlock(const Common::ProcessAddress dest_addr, const void* src_buffer, 315 bool WriteBlock(const Common::ProcessAddress dest_addr, const void* src_buffer,
312 const std::size_t size) { 316 const std::size_t size) {
313 WriteBlockImpl<false>(*system.ApplicationProcess(), dest_addr, src_buffer, size); 317 return WriteBlockImpl<false>(dest_addr, src_buffer, size);
314 } 318 }
315 319
316 void WriteBlockUnsafe(const Common::ProcessAddress dest_addr, const void* src_buffer, 320 bool WriteBlockUnsafe(const Common::ProcessAddress dest_addr, const void* src_buffer,
317 const std::size_t size) { 321 const std::size_t size) {
318 WriteBlockImpl<true>(*system.ApplicationProcess(), dest_addr, src_buffer, size); 322 return WriteBlockImpl<true>(dest_addr, src_buffer, size);
319 } 323 }
320 324
321 void ZeroBlock(const Kernel::KProcess& process, const Common::ProcessAddress dest_addr, 325 bool ZeroBlock(const Common::ProcessAddress dest_addr, const std::size_t size) {
322 const std::size_t size) { 326 return WalkBlock(
323 WalkBlock( 327 dest_addr, size,
324 process, dest_addr, size,
325 [dest_addr, size](const std::size_t copy_amount, 328 [dest_addr, size](const std::size_t copy_amount,
326 const Common::ProcessAddress current_vaddr) { 329 const Common::ProcessAddress current_vaddr) {
327 LOG_ERROR(HW_Memory, 330 LOG_ERROR(HW_Memory,
@@ -339,23 +342,23 @@ struct Memory::Impl {
339 [](const std::size_t copy_amount) {}); 342 [](const std::size_t copy_amount) {});
340 } 343 }
341 344
342 void CopyBlock(const Kernel::KProcess& process, Common::ProcessAddress dest_addr, 345 bool CopyBlock(Common::ProcessAddress dest_addr, Common::ProcessAddress src_addr,
343 Common::ProcessAddress src_addr, const std::size_t size) { 346 const std::size_t size) {
344 WalkBlock( 347 return WalkBlock(
345 process, dest_addr, size, 348 dest_addr, size,
346 [&](const std::size_t copy_amount, const Common::ProcessAddress current_vaddr) { 349 [&](const std::size_t copy_amount, const Common::ProcessAddress current_vaddr) {
347 LOG_ERROR(HW_Memory, 350 LOG_ERROR(HW_Memory,
348 "Unmapped CopyBlock @ 0x{:016X} (start address = 0x{:016X}, size = {})", 351 "Unmapped CopyBlock @ 0x{:016X} (start address = 0x{:016X}, size = {})",
349 GetInteger(current_vaddr), GetInteger(src_addr), size); 352 GetInteger(current_vaddr), GetInteger(src_addr), size);
350 ZeroBlock(process, dest_addr, copy_amount); 353 ZeroBlock(dest_addr, copy_amount);
351 }, 354 },
352 [&](const std::size_t copy_amount, const u8* const src_ptr) { 355 [&](const std::size_t copy_amount, const u8* const src_ptr) {
353 WriteBlockImpl<false>(process, dest_addr, src_ptr, copy_amount); 356 WriteBlockImpl<false>(dest_addr, src_ptr, copy_amount);
354 }, 357 },
355 [&](const Common::ProcessAddress current_vaddr, const std::size_t copy_amount, 358 [&](const Common::ProcessAddress current_vaddr, const std::size_t copy_amount,
356 u8* const host_ptr) { 359 u8* const host_ptr) {
357 HandleRasterizerDownload(GetInteger(current_vaddr), copy_amount); 360 HandleRasterizerDownload(GetInteger(current_vaddr), copy_amount);
358 WriteBlockImpl<false>(process, dest_addr, host_ptr, copy_amount); 361 WriteBlockImpl<false>(dest_addr, host_ptr, copy_amount);
359 }, 362 },
360 [&](const std::size_t copy_amount) { 363 [&](const std::size_t copy_amount) {
361 dest_addr += copy_amount; 364 dest_addr += copy_amount;
@@ -364,13 +367,13 @@ struct Memory::Impl {
364 } 367 }
365 368
366 template <typename Callback> 369 template <typename Callback>
367 Result PerformCacheOperation(const Kernel::KProcess& process, Common::ProcessAddress dest_addr, 370 Result PerformCacheOperation(Common::ProcessAddress dest_addr, std::size_t size,
368 std::size_t size, Callback&& cb) { 371 Callback&& cb) {
369 class InvalidMemoryException : public std::exception {}; 372 class InvalidMemoryException : public std::exception {};
370 373
371 try { 374 try {
372 WalkBlock( 375 WalkBlock(
373 process, dest_addr, size, 376 dest_addr, size,
374 [&](const std::size_t block_size, const Common::ProcessAddress current_vaddr) { 377 [&](const std::size_t block_size, const Common::ProcessAddress current_vaddr) {
375 LOG_ERROR(HW_Memory, "Unmapped cache maintenance @ {:#018X}", 378 LOG_ERROR(HW_Memory, "Unmapped cache maintenance @ {:#018X}",
376 GetInteger(current_vaddr)); 379 GetInteger(current_vaddr));
@@ -387,37 +390,34 @@ struct Memory::Impl {
387 return ResultSuccess; 390 return ResultSuccess;
388 } 391 }
389 392
390 Result InvalidateDataCache(const Kernel::KProcess& process, Common::ProcessAddress dest_addr, 393 Result InvalidateDataCache(Common::ProcessAddress dest_addr, std::size_t size) {
391 std::size_t size) {
392 auto on_rasterizer = [&](const Common::ProcessAddress current_vaddr, 394 auto on_rasterizer = [&](const Common::ProcessAddress current_vaddr,
393 const std::size_t block_size) { 395 const std::size_t block_size) {
394 // dc ivac: Invalidate to point of coherency 396 // dc ivac: Invalidate to point of coherency
395 // GPU flush -> CPU invalidate 397 // GPU flush -> CPU invalidate
396 HandleRasterizerDownload(GetInteger(current_vaddr), block_size); 398 HandleRasterizerDownload(GetInteger(current_vaddr), block_size);
397 }; 399 };
398 return PerformCacheOperation(process, dest_addr, size, on_rasterizer); 400 return PerformCacheOperation(dest_addr, size, on_rasterizer);
399 } 401 }
400 402
401 Result StoreDataCache(const Kernel::KProcess& process, Common::ProcessAddress dest_addr, 403 Result StoreDataCache(Common::ProcessAddress dest_addr, std::size_t size) {
402 std::size_t size) {
403 auto on_rasterizer = [&](const Common::ProcessAddress current_vaddr, 404 auto on_rasterizer = [&](const Common::ProcessAddress current_vaddr,
404 const std::size_t block_size) { 405 const std::size_t block_size) {
405 // dc cvac: Store to point of coherency 406 // dc cvac: Store to point of coherency
406 // CPU flush -> GPU invalidate 407 // CPU flush -> GPU invalidate
407 system.GPU().InvalidateRegion(GetInteger(current_vaddr), block_size); 408 system.GPU().InvalidateRegion(GetInteger(current_vaddr), block_size);
408 }; 409 };
409 return PerformCacheOperation(process, dest_addr, size, on_rasterizer); 410 return PerformCacheOperation(dest_addr, size, on_rasterizer);
410 } 411 }
411 412
412 Result FlushDataCache(const Kernel::KProcess& process, Common::ProcessAddress dest_addr, 413 Result FlushDataCache(Common::ProcessAddress dest_addr, std::size_t size) {
413 std::size_t size) {
414 auto on_rasterizer = [&](const Common::ProcessAddress current_vaddr, 414 auto on_rasterizer = [&](const Common::ProcessAddress current_vaddr,
415 const std::size_t block_size) { 415 const std::size_t block_size) {
416 // dc civac: Store to point of coherency, and invalidate from cache 416 // dc civac: Store to point of coherency, and invalidate from cache
417 // CPU flush -> GPU invalidate 417 // CPU flush -> GPU invalidate
418 system.GPU().InvalidateRegion(GetInteger(current_vaddr), block_size); 418 system.GPU().InvalidateRegion(GetInteger(current_vaddr), block_size);
419 }; 419 };
420 return PerformCacheOperation(process, dest_addr, size, on_rasterizer); 420 return PerformCacheOperation(dest_addr, size, on_rasterizer);
421 } 421 }
422 422
423 void MarkRegionDebug(u64 vaddr, u64 size, bool debug) { 423 void MarkRegionDebug(u64 vaddr, u64 size, bool debug) {
@@ -448,7 +448,7 @@ struct Memory::Impl {
448 break; 448 break;
449 case Common::PageType::Memory: 449 case Common::PageType::Memory:
450 current_page_table->pointers[vaddr >> YUZU_PAGEBITS].Store( 450 current_page_table->pointers[vaddr >> YUZU_PAGEBITS].Store(
451 nullptr, Common::PageType::DebugMemory); 451 0, Common::PageType::DebugMemory);
452 break; 452 break;
453 default: 453 default:
454 UNREACHABLE(); 454 UNREACHABLE();
@@ -466,7 +466,8 @@ struct Memory::Impl {
466 case Common::PageType::DebugMemory: { 466 case Common::PageType::DebugMemory: {
467 u8* const pointer{GetPointerFromDebugMemory(vaddr & ~YUZU_PAGEMASK)}; 467 u8* const pointer{GetPointerFromDebugMemory(vaddr & ~YUZU_PAGEMASK)};
468 current_page_table->pointers[vaddr >> YUZU_PAGEBITS].Store( 468 current_page_table->pointers[vaddr >> YUZU_PAGEBITS].Store(
469 pointer - (vaddr & ~YUZU_PAGEMASK), Common::PageType::Memory); 469 reinterpret_cast<uintptr_t>(pointer) - (vaddr & ~YUZU_PAGEMASK),
470 Common::PageType::Memory);
470 break; 471 break;
471 } 472 }
472 default: 473 default:
@@ -506,7 +507,7 @@ struct Memory::Impl {
506 case Common::PageType::DebugMemory: 507 case Common::PageType::DebugMemory:
507 case Common::PageType::Memory: 508 case Common::PageType::Memory:
508 current_page_table->pointers[vaddr >> YUZU_PAGEBITS].Store( 509 current_page_table->pointers[vaddr >> YUZU_PAGEBITS].Store(
509 nullptr, Common::PageType::RasterizerCachedMemory); 510 0, Common::PageType::RasterizerCachedMemory);
510 break; 511 break;
511 case Common::PageType::RasterizerCachedMemory: 512 case Common::PageType::RasterizerCachedMemory:
512 // There can be more than one GPU region mapped per CPU region, so it's common 513 // There can be more than one GPU region mapped per CPU region, so it's common
@@ -534,10 +535,11 @@ struct Memory::Impl {
534 // pagetable after unmapping a VMA. In that case the underlying VMA will no 535 // pagetable after unmapping a VMA. In that case the underlying VMA will no
535 // longer exist, and we should just leave the pagetable entry blank. 536 // longer exist, and we should just leave the pagetable entry blank.
536 current_page_table->pointers[vaddr >> YUZU_PAGEBITS].Store( 537 current_page_table->pointers[vaddr >> YUZU_PAGEBITS].Store(
537 nullptr, Common::PageType::Unmapped); 538 0, Common::PageType::Unmapped);
538 } else { 539 } else {
539 current_page_table->pointers[vaddr >> YUZU_PAGEBITS].Store( 540 current_page_table->pointers[vaddr >> YUZU_PAGEBITS].Store(
540 pointer - (vaddr & ~YUZU_PAGEMASK), Common::PageType::Memory); 541 reinterpret_cast<uintptr_t>(pointer) - (vaddr & ~YUZU_PAGEMASK),
542 Common::PageType::Memory);
541 } 543 }
542 break; 544 break;
543 } 545 }
@@ -584,7 +586,7 @@ struct Memory::Impl {
584 "Mapping memory page without a pointer @ {:016x}", base * YUZU_PAGESIZE); 586 "Mapping memory page without a pointer @ {:016x}", base * YUZU_PAGESIZE);
585 587
586 while (base != end) { 588 while (base != end) {
587 page_table.pointers[base].Store(nullptr, type); 589 page_table.pointers[base].Store(0, type);
588 page_table.backing_addr[base] = 0; 590 page_table.backing_addr[base] = 0;
589 page_table.blocks[base] = 0; 591 page_table.blocks[base] = 0;
590 base += 1; 592 base += 1;
@@ -593,7 +595,8 @@ struct Memory::Impl {
593 auto orig_base = base; 595 auto orig_base = base;
594 while (base != end) { 596 while (base != end) {
595 auto host_ptr = 597 auto host_ptr =
596 system.DeviceMemory().GetPointer<u8>(target) - (base << YUZU_PAGEBITS); 598 reinterpret_cast<uintptr_t>(system.DeviceMemory().GetPointer<u8>(target)) -
599 (base << YUZU_PAGEBITS);
597 auto backing = GetInteger(target) - (base << YUZU_PAGEBITS); 600 auto backing = GetInteger(target) - (base << YUZU_PAGEBITS);
598 page_table.pointers[base].Store(host_ptr, type); 601 page_table.pointers[base].Store(host_ptr, type);
599 page_table.backing_addr[base] = backing; 602 page_table.backing_addr[base] = backing;
@@ -619,8 +622,8 @@ struct Memory::Impl {
619 622
620 // Avoid adding any extra logic to this fast-path block 623 // Avoid adding any extra logic to this fast-path block
621 const uintptr_t raw_pointer = current_page_table->pointers[vaddr >> YUZU_PAGEBITS].Raw(); 624 const uintptr_t raw_pointer = current_page_table->pointers[vaddr >> YUZU_PAGEBITS].Raw();
622 if (u8* const pointer = Common::PageTable::PageInfo::ExtractPointer(raw_pointer)) { 625 if (const uintptr_t pointer = Common::PageTable::PageInfo::ExtractPointer(raw_pointer)) {
623 return &pointer[vaddr]; 626 return reinterpret_cast<u8*>(pointer + vaddr);
624 } 627 }
625 switch (Common::PageTable::PageInfo::ExtractType(raw_pointer)) { 628 switch (Common::PageTable::PageInfo::ExtractType(raw_pointer)) {
626 case Common::PageType::Unmapped: 629 case Common::PageType::Unmapped:
@@ -808,13 +811,13 @@ void Memory::UnmapRegion(Common::PageTable& page_table, Common::ProcessAddress b
808 811
809bool Memory::IsValidVirtualAddress(const Common::ProcessAddress vaddr) const { 812bool Memory::IsValidVirtualAddress(const Common::ProcessAddress vaddr) const {
810 const Kernel::KProcess& process = *system.ApplicationProcess(); 813 const Kernel::KProcess& process = *system.ApplicationProcess();
811 const auto& page_table = process.PageTable().PageTableImpl(); 814 const auto& page_table = process.GetPageTable().PageTableImpl();
812 const size_t page = vaddr >> YUZU_PAGEBITS; 815 const size_t page = vaddr >> YUZU_PAGEBITS;
813 if (page >= page_table.pointers.size()) { 816 if (page >= page_table.pointers.size()) {
814 return false; 817 return false;
815 } 818 }
816 const auto [pointer, type] = page_table.pointers[page].PointerType(); 819 const auto [pointer, type] = page_table.pointers[page].PointerType();
817 return pointer != nullptr || type == Common::PageType::RasterizerCachedMemory || 820 return pointer != 0 || type == Common::PageType::RasterizerCachedMemory ||
818 type == Common::PageType::DebugMemory; 821 type == Common::PageType::DebugMemory;
819} 822}
820 823
@@ -899,14 +902,14 @@ std::string Memory::ReadCString(Common::ProcessAddress vaddr, std::size_t max_le
899 return impl->ReadCString(vaddr, max_length); 902 return impl->ReadCString(vaddr, max_length);
900} 903}
901 904
902void Memory::ReadBlock(const Common::ProcessAddress src_addr, void* dest_buffer, 905bool Memory::ReadBlock(const Common::ProcessAddress src_addr, void* dest_buffer,
903 const std::size_t size) { 906 const std::size_t size) {
904 impl->ReadBlock(src_addr, dest_buffer, size); 907 return impl->ReadBlock(src_addr, dest_buffer, size);
905} 908}
906 909
907void Memory::ReadBlockUnsafe(const Common::ProcessAddress src_addr, void* dest_buffer, 910bool Memory::ReadBlockUnsafe(const Common::ProcessAddress src_addr, void* dest_buffer,
908 const std::size_t size) { 911 const std::size_t size) {
909 impl->ReadBlockUnsafe(src_addr, dest_buffer, size); 912 return impl->ReadBlockUnsafe(src_addr, dest_buffer, size);
910} 913}
911 914
912const u8* Memory::GetSpan(const VAddr src_addr, const std::size_t size) const { 915const u8* Memory::GetSpan(const VAddr src_addr, const std::size_t size) const {
@@ -917,23 +920,23 @@ u8* Memory::GetSpan(const VAddr src_addr, const std::size_t size) {
917 return impl->GetSpan(src_addr, size); 920 return impl->GetSpan(src_addr, size);
918} 921}
919 922
920void Memory::WriteBlock(const Common::ProcessAddress dest_addr, const void* src_buffer, 923bool Memory::WriteBlock(const Common::ProcessAddress dest_addr, const void* src_buffer,
921 const std::size_t size) { 924 const std::size_t size) {
922 impl->WriteBlock(dest_addr, src_buffer, size); 925 return impl->WriteBlock(dest_addr, src_buffer, size);
923} 926}
924 927
925void Memory::WriteBlockUnsafe(const Common::ProcessAddress dest_addr, const void* src_buffer, 928bool Memory::WriteBlockUnsafe(const Common::ProcessAddress dest_addr, const void* src_buffer,
926 const std::size_t size) { 929 const std::size_t size) {
927 impl->WriteBlockUnsafe(dest_addr, src_buffer, size); 930 return impl->WriteBlockUnsafe(dest_addr, src_buffer, size);
928} 931}
929 932
930void Memory::CopyBlock(Common::ProcessAddress dest_addr, Common::ProcessAddress src_addr, 933bool Memory::CopyBlock(Common::ProcessAddress dest_addr, Common::ProcessAddress src_addr,
931 const std::size_t size) { 934 const std::size_t size) {
932 impl->CopyBlock(*system.ApplicationProcess(), dest_addr, src_addr, size); 935 return impl->CopyBlock(dest_addr, src_addr, size);
933} 936}
934 937
935void Memory::ZeroBlock(Common::ProcessAddress dest_addr, const std::size_t size) { 938bool Memory::ZeroBlock(Common::ProcessAddress dest_addr, const std::size_t size) {
936 impl->ZeroBlock(*system.ApplicationProcess(), dest_addr, size); 939 return impl->ZeroBlock(dest_addr, size);
937} 940}
938 941
939void Memory::SetGPUDirtyManagers(std::span<Core::GPUDirtyMemoryManager> managers) { 942void Memory::SetGPUDirtyManagers(std::span<Core::GPUDirtyMemoryManager> managers) {
@@ -941,15 +944,15 @@ void Memory::SetGPUDirtyManagers(std::span<Core::GPUDirtyMemoryManager> managers
941} 944}
942 945
943Result Memory::InvalidateDataCache(Common::ProcessAddress dest_addr, const std::size_t size) { 946Result Memory::InvalidateDataCache(Common::ProcessAddress dest_addr, const std::size_t size) {
944 return impl->InvalidateDataCache(*system.ApplicationProcess(), dest_addr, size); 947 return impl->InvalidateDataCache(dest_addr, size);
945} 948}
946 949
947Result Memory::StoreDataCache(Common::ProcessAddress dest_addr, const std::size_t size) { 950Result Memory::StoreDataCache(Common::ProcessAddress dest_addr, const std::size_t size) {
948 return impl->StoreDataCache(*system.ApplicationProcess(), dest_addr, size); 951 return impl->StoreDataCache(dest_addr, size);
949} 952}
950 953
951Result Memory::FlushDataCache(Common::ProcessAddress dest_addr, const std::size_t size) { 954Result Memory::FlushDataCache(Common::ProcessAddress dest_addr, const std::size_t size) {
952 return impl->FlushDataCache(*system.ApplicationProcess(), dest_addr, size); 955 return impl->FlushDataCache(dest_addr, size);
953} 956}
954 957
955void Memory::RasterizerMarkRegionCached(Common::ProcessAddress vaddr, u64 size, bool cached) { 958void Memory::RasterizerMarkRegionCached(Common::ProcessAddress vaddr, u64 size, bool cached) {
diff --git a/src/core/memory.h b/src/core/memory.h
index ea33c769c..2eb61ffd3 100644
--- a/src/core/memory.h
+++ b/src/core/memory.h
@@ -24,7 +24,6 @@ class GPUDirtyMemoryManager;
24} // namespace Core 24} // namespace Core
25 25
26namespace Kernel { 26namespace Kernel {
27class PhysicalMemory;
28class KProcess; 27class KProcess;
29} // namespace Kernel 28} // namespace Kernel
30 29
@@ -330,7 +329,7 @@ public:
330 * @post The range [dest_buffer, size) contains the read bytes from the 329 * @post The range [dest_buffer, size) contains the read bytes from the
331 * current process' address space. 330 * current process' address space.
332 */ 331 */
333 void ReadBlock(Common::ProcessAddress src_addr, void* dest_buffer, std::size_t size); 332 bool ReadBlock(Common::ProcessAddress src_addr, void* dest_buffer, std::size_t size);
334 333
335 /** 334 /**
336 * Reads a contiguous block of bytes from the current process' address space. 335 * Reads a contiguous block of bytes from the current process' address space.
@@ -349,7 +348,7 @@ public:
349 * @post The range [dest_buffer, size) contains the read bytes from the 348 * @post The range [dest_buffer, size) contains the read bytes from the
350 * current process' address space. 349 * current process' address space.
351 */ 350 */
352 void ReadBlockUnsafe(Common::ProcessAddress src_addr, void* dest_buffer, std::size_t size); 351 bool ReadBlockUnsafe(Common::ProcessAddress src_addr, void* dest_buffer, std::size_t size);
353 352
354 const u8* GetSpan(const VAddr src_addr, const std::size_t size) const; 353 const u8* GetSpan(const VAddr src_addr, const std::size_t size) const;
355 u8* GetSpan(const VAddr src_addr, const std::size_t size); 354 u8* GetSpan(const VAddr src_addr, const std::size_t size);
@@ -373,7 +372,7 @@ public:
373 * and will mark that region as invalidated to caches that the active 372 * and will mark that region as invalidated to caches that the active
374 * graphics backend may be maintaining over the course of execution. 373 * graphics backend may be maintaining over the course of execution.
375 */ 374 */
376 void WriteBlock(Common::ProcessAddress dest_addr, const void* src_buffer, std::size_t size); 375 bool WriteBlock(Common::ProcessAddress dest_addr, const void* src_buffer, std::size_t size);
377 376
378 /** 377 /**
379 * Writes a range of bytes into the current process' address space at the specified 378 * Writes a range of bytes into the current process' address space at the specified
@@ -391,7 +390,7 @@ public:
391 * will be ignored and an error will be logged. 390 * will be ignored and an error will be logged.
392 * 391 *
393 */ 392 */
394 void WriteBlockUnsafe(Common::ProcessAddress dest_addr, const void* src_buffer, 393 bool WriteBlockUnsafe(Common::ProcessAddress dest_addr, const void* src_buffer,
395 std::size_t size); 394 std::size_t size);
396 395
397 /** 396 /**
@@ -405,7 +404,7 @@ public:
405 * @post The range [dest_addr, size) within the process' address space contains the 404 * @post The range [dest_addr, size) within the process' address space contains the
406 * same data within the range [src_addr, size). 405 * same data within the range [src_addr, size).
407 */ 406 */
408 void CopyBlock(Common::ProcessAddress dest_addr, Common::ProcessAddress src_addr, 407 bool CopyBlock(Common::ProcessAddress dest_addr, Common::ProcessAddress src_addr,
409 std::size_t size); 408 std::size_t size);
410 409
411 /** 410 /**
@@ -418,7 +417,7 @@ public:
418 * @post The range [dest_addr, size) within the process' address space contains the 417 * @post The range [dest_addr, size) within the process' address space contains the
419 * value 0. 418 * value 0.
420 */ 419 */
421 void ZeroBlock(Common::ProcessAddress dest_addr, std::size_t size); 420 bool ZeroBlock(Common::ProcessAddress dest_addr, std::size_t size);
422 421
423 /** 422 /**
424 * Invalidates a range of bytes within the current process' address space at the specified 423 * Invalidates a range of bytes within the current process' address space at the specified
diff --git a/src/core/memory/cheat_engine.cpp b/src/core/memory/cheat_engine.cpp
index 8742dd164..7b52f61a7 100644
--- a/src/core/memory/cheat_engine.cpp
+++ b/src/core/memory/cheat_engine.cpp
@@ -199,7 +199,7 @@ void CheatEngine::Initialize() {
199 metadata.process_id = system.ApplicationProcess()->GetProcessId(); 199 metadata.process_id = system.ApplicationProcess()->GetProcessId();
200 metadata.title_id = system.GetApplicationProcessProgramID(); 200 metadata.title_id = system.GetApplicationProcessProgramID();
201 201
202 const auto& page_table = system.ApplicationProcess()->PageTable(); 202 const auto& page_table = system.ApplicationProcess()->GetPageTable();
203 metadata.heap_extents = { 203 metadata.heap_extents = {
204 .base = GetInteger(page_table.GetHeapRegionStart()), 204 .base = GetInteger(page_table.GetHeapRegionStart()),
205 .size = page_table.GetHeapRegionSize(), 205 .size = page_table.GetHeapRegionSize(),
diff --git a/src/core/reporter.cpp b/src/core/reporter.cpp
index 6c3dc7369..b5b3e7eda 100644
--- a/src/core/reporter.cpp
+++ b/src/core/reporter.cpp
@@ -117,8 +117,8 @@ json GetProcessorStateDataAuto(Core::System& system) {
117 arm.SaveContext(context); 117 arm.SaveContext(context);
118 118
119 return GetProcessorStateData(process->Is64BitProcess() ? "AArch64" : "AArch32", 119 return GetProcessorStateData(process->Is64BitProcess() ? "AArch64" : "AArch32",
120 GetInteger(process->PageTable().GetCodeRegionStart()), context.sp, 120 GetInteger(process->GetPageTable().GetCodeRegionStart()),
121 context.pc, context.pstate, context.cpu_registers); 121 context.sp, context.pc, context.pstate, context.cpu_registers);
122} 122}
123 123
124json GetBacktraceData(Core::System& system) { 124json GetBacktraceData(Core::System& system) {
diff --git a/src/shader_recompiler/ir_opt/ssa_rewrite_pass.cpp b/src/shader_recompiler/ir_opt/ssa_rewrite_pass.cpp
index d0b145860..07cabca43 100644
--- a/src/shader_recompiler/ir_opt/ssa_rewrite_pass.cpp
+++ b/src/shader_recompiler/ir_opt/ssa_rewrite_pass.cpp
@@ -14,12 +14,12 @@
14// 14//
15 15
16#include <deque> 16#include <deque>
17#include <map>
17#include <span> 18#include <span>
19#include <unordered_map>
18#include <variant> 20#include <variant>
19#include <vector> 21#include <vector>
20 22
21#include <boost/container/flat_map.hpp>
22
23#include "shader_recompiler/frontend/ir/basic_block.h" 23#include "shader_recompiler/frontend/ir/basic_block.h"
24#include "shader_recompiler/frontend/ir/opcodes.h" 24#include "shader_recompiler/frontend/ir/opcodes.h"
25#include "shader_recompiler/frontend/ir/pred.h" 25#include "shader_recompiler/frontend/ir/pred.h"
@@ -52,7 +52,7 @@ struct IndirectBranchVariable {
52 52
53using Variant = std::variant<IR::Reg, IR::Pred, ZeroFlagTag, SignFlagTag, CarryFlagTag, 53using Variant = std::variant<IR::Reg, IR::Pred, ZeroFlagTag, SignFlagTag, CarryFlagTag,
54 OverflowFlagTag, GotoVariable, IndirectBranchVariable>; 54 OverflowFlagTag, GotoVariable, IndirectBranchVariable>;
55using ValueMap = boost::container::flat_map<IR::Block*, IR::Value>; 55using ValueMap = std::unordered_map<IR::Block*, IR::Value>;
56 56
57struct DefTable { 57struct DefTable {
58 const IR::Value& Def(IR::Block* block, IR::Reg variable) { 58 const IR::Value& Def(IR::Block* block, IR::Reg variable) {
@@ -112,7 +112,7 @@ struct DefTable {
112 } 112 }
113 113
114 std::array<ValueMap, IR::NUM_USER_PREDS> preds; 114 std::array<ValueMap, IR::NUM_USER_PREDS> preds;
115 boost::container::flat_map<u32, ValueMap> goto_vars; 115 std::unordered_map<u32, ValueMap> goto_vars;
116 ValueMap indirect_branch_var; 116 ValueMap indirect_branch_var;
117 ValueMap zero_flag; 117 ValueMap zero_flag;
118 ValueMap sign_flag; 118 ValueMap sign_flag;
@@ -295,8 +295,7 @@ private:
295 return same; 295 return same;
296 } 296 }
297 297
298 boost::container::flat_map<IR::Block*, boost::container::flat_map<Variant, IR::Inst*>> 298 std::unordered_map<IR::Block*, std::map<Variant, IR::Inst*>> incomplete_phis;
299 incomplete_phis;
300 DefTable current_def; 299 DefTable current_def;
301}; 300};
302 301
diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h
index 6ed4b78f2..f0f450edb 100644
--- a/src/video_core/buffer_cache/buffer_cache.h
+++ b/src/video_core/buffer_cache/buffer_cache.h
@@ -442,6 +442,11 @@ void BufferCache<P>::UnbindComputeStorageBuffers() {
442template <class P> 442template <class P>
443void BufferCache<P>::BindComputeStorageBuffer(size_t ssbo_index, u32 cbuf_index, u32 cbuf_offset, 443void BufferCache<P>::BindComputeStorageBuffer(size_t ssbo_index, u32 cbuf_index, u32 cbuf_offset,
444 bool is_written) { 444 bool is_written) {
445 if (ssbo_index >= channel_state->compute_storage_buffers.size()) [[unlikely]] {
446 LOG_ERROR(HW_GPU, "Storage buffer index {} exceeds maximum storage buffer count",
447 ssbo_index);
448 return;
449 }
445 channel_state->enabled_compute_storage_buffers |= 1U << ssbo_index; 450 channel_state->enabled_compute_storage_buffers |= 1U << ssbo_index;
446 channel_state->written_compute_storage_buffers |= (is_written ? 1U : 0U) << ssbo_index; 451 channel_state->written_compute_storage_buffers |= (is_written ? 1U : 0U) << ssbo_index;
447 452
@@ -464,6 +469,11 @@ void BufferCache<P>::UnbindComputeTextureBuffers() {
464template <class P> 469template <class P>
465void BufferCache<P>::BindComputeTextureBuffer(size_t tbo_index, GPUVAddr gpu_addr, u32 size, 470void BufferCache<P>::BindComputeTextureBuffer(size_t tbo_index, GPUVAddr gpu_addr, u32 size,
466 PixelFormat format, bool is_written, bool is_image) { 471 PixelFormat format, bool is_written, bool is_image) {
472 if (tbo_index >= channel_state->compute_texture_buffers.size()) [[unlikely]] {
473 LOG_ERROR(HW_GPU, "Texture buffer index {} exceeds maximum texture buffer count",
474 tbo_index);
475 return;
476 }
467 channel_state->enabled_compute_texture_buffers |= 1U << tbo_index; 477 channel_state->enabled_compute_texture_buffers |= 1U << tbo_index;
468 channel_state->written_compute_texture_buffers |= (is_written ? 1U : 0U) << tbo_index; 478 channel_state->written_compute_texture_buffers |= (is_written ? 1U : 0U) << tbo_index;
469 if constexpr (SEPARATE_IMAGE_BUFFERS_BINDINGS) { 479 if constexpr (SEPARATE_IMAGE_BUFFERS_BINDINGS) {
diff --git a/src/video_core/buffer_cache/buffer_cache_base.h b/src/video_core/buffer_cache/buffer_cache_base.h
index 460fc7551..0b7135d49 100644
--- a/src/video_core/buffer_cache/buffer_cache_base.h
+++ b/src/video_core/buffer_cache/buffer_cache_base.h
@@ -67,7 +67,7 @@ constexpr u32 NUM_TRANSFORM_FEEDBACK_BUFFERS = 4;
67constexpr u32 NUM_GRAPHICS_UNIFORM_BUFFERS = 18; 67constexpr u32 NUM_GRAPHICS_UNIFORM_BUFFERS = 18;
68constexpr u32 NUM_COMPUTE_UNIFORM_BUFFERS = 8; 68constexpr u32 NUM_COMPUTE_UNIFORM_BUFFERS = 8;
69constexpr u32 NUM_STORAGE_BUFFERS = 16; 69constexpr u32 NUM_STORAGE_BUFFERS = 16;
70constexpr u32 NUM_TEXTURE_BUFFERS = 16; 70constexpr u32 NUM_TEXTURE_BUFFERS = 32;
71constexpr u32 NUM_STAGES = 5; 71constexpr u32 NUM_STAGES = 5;
72 72
73using UniformBufferSizes = std::array<std::array<u32, NUM_GRAPHICS_UNIFORM_BUFFERS>, NUM_STAGES>; 73using UniformBufferSizes = std::array<std::array<u32, NUM_GRAPHICS_UNIFORM_BUFFERS>, NUM_STAGES>;
diff --git a/src/video_core/query_cache.h b/src/video_core/query_cache.h
index 1528cc1dd..7047e2e63 100644
--- a/src/video_core/query_cache.h
+++ b/src/video_core/query_cache.h
@@ -103,7 +103,9 @@ public:
103 explicit QueryCacheBase(VideoCore::RasterizerInterface& rasterizer_, 103 explicit QueryCacheBase(VideoCore::RasterizerInterface& rasterizer_,
104 Core::Memory::Memory& cpu_memory_) 104 Core::Memory::Memory& cpu_memory_)
105 : rasterizer{rasterizer_}, 105 : rasterizer{rasterizer_},
106 cpu_memory{cpu_memory_}, streams{{CounterStream{static_cast<QueryCache&>(*this), 106 // Use reinterpret_cast instead of static_cast as workaround for
107 // UBSan bug (https://github.com/llvm/llvm-project/issues/59060)
108 cpu_memory{cpu_memory_}, streams{{CounterStream{reinterpret_cast<QueryCache&>(*this),
107 VideoCore::QueryType::SamplesPassed}}} { 109 VideoCore::QueryType::SamplesPassed}}} {
108 (void)slot_async_jobs.insert(); // Null value 110 (void)slot_async_jobs.insert(); // Null value
109 } 111 }
diff --git a/src/video_core/rasterizer_accelerated.cpp b/src/video_core/rasterizer_accelerated.cpp
index 4a197d65d..f200a650f 100644
--- a/src/video_core/rasterizer_accelerated.cpp
+++ b/src/video_core/rasterizer_accelerated.cpp
@@ -13,7 +13,8 @@ namespace VideoCore {
13 13
14using namespace Core::Memory; 14using namespace Core::Memory;
15 15
16RasterizerAccelerated::RasterizerAccelerated(Memory& cpu_memory_) : cpu_memory{cpu_memory_} {} 16RasterizerAccelerated::RasterizerAccelerated(Memory& cpu_memory_)
17 : cached_pages(std::make_unique<CachedPages>()), cpu_memory{cpu_memory_} {}
17 18
18RasterizerAccelerated::~RasterizerAccelerated() = default; 19RasterizerAccelerated::~RasterizerAccelerated() = default;
19 20
@@ -26,7 +27,7 @@ void RasterizerAccelerated::UpdatePagesCachedCount(VAddr addr, u64 size, int del
26 std::atomic_thread_fence(std::memory_order_acquire); 27 std::atomic_thread_fence(std::memory_order_acquire);
27 const u64 page_end = Common::DivCeil(addr + size, YUZU_PAGESIZE); 28 const u64 page_end = Common::DivCeil(addr + size, YUZU_PAGESIZE);
28 for (u64 page = addr >> YUZU_PAGEBITS; page != page_end; ++page) { 29 for (u64 page = addr >> YUZU_PAGEBITS; page != page_end; ++page) {
29 std::atomic_uint16_t& count = cached_pages.at(page >> 2).Count(page); 30 std::atomic_uint16_t& count = cached_pages->at(page >> 2).Count(page);
30 31
31 if (delta > 0) { 32 if (delta > 0) {
32 ASSERT_MSG(count.load(std::memory_order::relaxed) < UINT16_MAX, "Count may overflow!"); 33 ASSERT_MSG(count.load(std::memory_order::relaxed) < UINT16_MAX, "Count may overflow!");
diff --git a/src/video_core/rasterizer_accelerated.h b/src/video_core/rasterizer_accelerated.h
index 7118b8aff..e6c0ea87a 100644
--- a/src/video_core/rasterizer_accelerated.h
+++ b/src/video_core/rasterizer_accelerated.h
@@ -41,7 +41,8 @@ private:
41 }; 41 };
42 static_assert(sizeof(CacheEntry) == 8, "CacheEntry should be 8 bytes!"); 42 static_assert(sizeof(CacheEntry) == 8, "CacheEntry should be 8 bytes!");
43 43
44 std::array<CacheEntry, 0x2000000> cached_pages; 44 using CachedPages = std::array<CacheEntry, 0x2000000>;
45 std::unique_ptr<CachedPages> cached_pages;
45 Core::Memory::Memory& cpu_memory; 46 Core::Memory::Memory& cpu_memory;
46}; 47};
47 48
diff --git a/src/video_core/renderer_base.cpp b/src/video_core/renderer_base.cpp
index 2d3f58201..4002fa72b 100644
--- a/src/video_core/renderer_base.cpp
+++ b/src/video_core/renderer_base.cpp
@@ -38,8 +38,8 @@ void RendererBase::RequestScreenshot(void* data, std::function<void(bool)> callb
38 LOG_ERROR(Render, "A screenshot is already requested or in progress, ignoring the request"); 38 LOG_ERROR(Render, "A screenshot is already requested or in progress, ignoring the request");
39 return; 39 return;
40 } 40 }
41 auto async_callback{[callback = std::move(callback)](bool invert_y) { 41 auto async_callback{[callback_ = std::move(callback)](bool invert_y) {
42 std::thread t{callback, invert_y}; 42 std::thread t{callback_, invert_y};
43 t.detach(); 43 t.detach();
44 }}; 44 }};
45 renderer_settings.screenshot_bits = data; 45 renderer_settings.screenshot_bits = data;
diff --git a/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp b/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp
index 23a48c6fe..71f720c63 100644
--- a/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp
+++ b/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp
@@ -231,24 +231,25 @@ GraphicsPipeline::GraphicsPipeline(const Device& device, TextureCache& texture_c
231 } 231 }
232 const bool in_parallel = thread_worker != nullptr; 232 const bool in_parallel = thread_worker != nullptr;
233 const auto backend = device.GetShaderBackend(); 233 const auto backend = device.GetShaderBackend();
234 auto func{[this, sources = std::move(sources), sources_spirv = std::move(sources_spirv), 234 auto func{[this, sources_ = std::move(sources), sources_spirv_ = std::move(sources_spirv),
235 shader_notify, backend, in_parallel, 235 shader_notify, backend, in_parallel,
236 force_context_flush](ShaderContext::Context*) mutable { 236 force_context_flush](ShaderContext::Context*) mutable {
237 for (size_t stage = 0; stage < 5; ++stage) { 237 for (size_t stage = 0; stage < 5; ++stage) {
238 switch (backend) { 238 switch (backend) {
239 case Settings::ShaderBackend::GLSL: 239 case Settings::ShaderBackend::GLSL:
240 if (!sources[stage].empty()) { 240 if (!sources_[stage].empty()) {
241 source_programs[stage] = CreateProgram(sources[stage], Stage(stage)); 241 source_programs[stage] = CreateProgram(sources_[stage], Stage(stage));
242 } 242 }
243 break; 243 break;
244 case Settings::ShaderBackend::GLASM: 244 case Settings::ShaderBackend::GLASM:
245 if (!sources[stage].empty()) { 245 if (!sources_[stage].empty()) {
246 assembly_programs[stage] = CompileProgram(sources[stage], AssemblyStage(stage)); 246 assembly_programs[stage] =
247 CompileProgram(sources_[stage], AssemblyStage(stage));
247 } 248 }
248 break; 249 break;
249 case Settings::ShaderBackend::SPIRV: 250 case Settings::ShaderBackend::SPIRV:
250 if (!sources_spirv[stage].empty()) { 251 if (!sources_spirv_[stage].empty()) {
251 source_programs[stage] = CreateProgram(sources_spirv[stage], Stage(stage)); 252 source_programs[stage] = CreateProgram(sources_spirv_[stage], Stage(stage));
252 } 253 }
253 break; 254 break;
254 } 255 }
diff --git a/src/video_core/renderer_opengl/gl_shader_cache.cpp b/src/video_core/renderer_opengl/gl_shader_cache.cpp
index 0329ed820..7e1d7f92e 100644
--- a/src/video_core/renderer_opengl/gl_shader_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_cache.cpp
@@ -288,9 +288,9 @@ void ShaderCache::LoadDiskResources(u64 title_id, std::stop_token stop_loading,
288 const auto load_compute{[&](std::ifstream& file, FileEnvironment env) { 288 const auto load_compute{[&](std::ifstream& file, FileEnvironment env) {
289 ComputePipelineKey key; 289 ComputePipelineKey key;
290 file.read(reinterpret_cast<char*>(&key), sizeof(key)); 290 file.read(reinterpret_cast<char*>(&key), sizeof(key));
291 queue_work([this, key, env = std::move(env), &state, &callback](Context* ctx) mutable { 291 queue_work([this, key, env_ = std::move(env), &state, &callback](Context* ctx) mutable {
292 ctx->pools.ReleaseContents(); 292 ctx->pools.ReleaseContents();
293 auto pipeline{CreateComputePipeline(ctx->pools, key, env, true)}; 293 auto pipeline{CreateComputePipeline(ctx->pools, key, env_, true)};
294 std::scoped_lock lock{state.mutex}; 294 std::scoped_lock lock{state.mutex};
295 if (pipeline) { 295 if (pipeline) {
296 compute_cache.emplace(key, std::move(pipeline)); 296 compute_cache.emplace(key, std::move(pipeline));
@@ -305,9 +305,9 @@ void ShaderCache::LoadDiskResources(u64 title_id, std::stop_token stop_loading,
305 const auto load_graphics{[&](std::ifstream& file, std::vector<FileEnvironment> envs) { 305 const auto load_graphics{[&](std::ifstream& file, std::vector<FileEnvironment> envs) {
306 GraphicsPipelineKey key; 306 GraphicsPipelineKey key;
307 file.read(reinterpret_cast<char*>(&key), sizeof(key)); 307 file.read(reinterpret_cast<char*>(&key), sizeof(key));
308 queue_work([this, key, envs = std::move(envs), &state, &callback](Context* ctx) mutable { 308 queue_work([this, key, envs_ = std::move(envs), &state, &callback](Context* ctx) mutable {
309 boost::container::static_vector<Shader::Environment*, 5> env_ptrs; 309 boost::container::static_vector<Shader::Environment*, 5> env_ptrs;
310 for (auto& env : envs) { 310 for (auto& env : envs_) {
311 env_ptrs.push_back(&env); 311 env_ptrs.push_back(&env);
312 } 312 }
313 ctx->pools.ReleaseContents(); 313 ctx->pools.ReleaseContents();
diff --git a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp
index 51df18ec3..f8cd2a5d8 100644
--- a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp
+++ b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp
@@ -206,8 +206,8 @@ public:
206 const size_t sub_first_offset = static_cast<size_t>(first % 4) * GetQuadsNum(num_indices); 206 const size_t sub_first_offset = static_cast<size_t>(first % 4) * GetQuadsNum(num_indices);
207 const size_t offset = 207 const size_t offset =
208 (sub_first_offset + GetQuadsNum(first)) * 6ULL * BytesPerIndex(index_type); 208 (sub_first_offset + GetQuadsNum(first)) * 6ULL * BytesPerIndex(index_type);
209 scheduler.Record([buffer = *buffer, index_type_, offset](vk::CommandBuffer cmdbuf) { 209 scheduler.Record([buffer_ = *buffer, index_type_, offset](vk::CommandBuffer cmdbuf) {
210 cmdbuf.BindIndexBuffer(buffer, offset, index_type_); 210 cmdbuf.BindIndexBuffer(buffer_, offset, index_type_);
211 }); 211 });
212 } 212 }
213 213
@@ -528,17 +528,18 @@ void BufferCacheRuntime::BindVertexBuffers(VideoCommon::HostBindings<Buffer>& bi
528 buffer_handles.push_back(handle); 528 buffer_handles.push_back(handle);
529 } 529 }
530 if (device.IsExtExtendedDynamicStateSupported()) { 530 if (device.IsExtExtendedDynamicStateSupported()) {
531 scheduler.Record([bindings = std::move(bindings), 531 scheduler.Record([bindings_ = std::move(bindings),
532 buffer_handles = std::move(buffer_handles)](vk::CommandBuffer cmdbuf) { 532 buffer_handles_ = std::move(buffer_handles)](vk::CommandBuffer cmdbuf) {
533 cmdbuf.BindVertexBuffers2EXT( 533 cmdbuf.BindVertexBuffers2EXT(bindings_.min_index,
534 bindings.min_index, bindings.max_index - bindings.min_index, buffer_handles.data(), 534 bindings_.max_index - bindings_.min_index,
535 bindings.offsets.data(), bindings.sizes.data(), bindings.strides.data()); 535 buffer_handles_.data(), bindings_.offsets.data(),
536 bindings_.sizes.data(), bindings_.strides.data());
536 }); 537 });
537 } else { 538 } else {
538 scheduler.Record([bindings = std::move(bindings), 539 scheduler.Record([bindings_ = std::move(bindings),
539 buffer_handles = std::move(buffer_handles)](vk::CommandBuffer cmdbuf) { 540 buffer_handles_ = std::move(buffer_handles)](vk::CommandBuffer cmdbuf) {
540 cmdbuf.BindVertexBuffers(bindings.min_index, bindings.max_index - bindings.min_index, 541 cmdbuf.BindVertexBuffers(bindings_.min_index, bindings_.max_index - bindings_.min_index,
541 buffer_handles.data(), bindings.offsets.data()); 542 buffer_handles_.data(), bindings_.offsets.data());
542 }); 543 });
543 } 544 }
544} 545}
@@ -573,11 +574,11 @@ void BufferCacheRuntime::BindTransformFeedbackBuffers(VideoCommon::HostBindings<
573 for (u32 index = 0; index < bindings.buffers.size(); ++index) { 574 for (u32 index = 0; index < bindings.buffers.size(); ++index) {
574 buffer_handles.push_back(bindings.buffers[index]->Handle()); 575 buffer_handles.push_back(bindings.buffers[index]->Handle());
575 } 576 }
576 scheduler.Record([bindings = std::move(bindings), 577 scheduler.Record([bindings_ = std::move(bindings),
577 buffer_handles = std::move(buffer_handles)](vk::CommandBuffer cmdbuf) { 578 buffer_handles_ = std::move(buffer_handles)](vk::CommandBuffer cmdbuf) {
578 cmdbuf.BindTransformFeedbackBuffersEXT(0, static_cast<u32>(buffer_handles.size()), 579 cmdbuf.BindTransformFeedbackBuffersEXT(0, static_cast<u32>(buffer_handles_.size()),
579 buffer_handles.data(), bindings.offsets.data(), 580 buffer_handles_.data(), bindings_.offsets.data(),
580 bindings.sizes.data()); 581 bindings_.sizes.data());
581 }); 582 });
582} 583}
583 584
diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
index d600c4e61..4f84d8497 100644
--- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
+++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
@@ -469,9 +469,9 @@ void PipelineCache::LoadDiskResources(u64 title_id, std::stop_token stop_loading
469 ComputePipelineCacheKey key; 469 ComputePipelineCacheKey key;
470 file.read(reinterpret_cast<char*>(&key), sizeof(key)); 470 file.read(reinterpret_cast<char*>(&key), sizeof(key));
471 471
472 workers.QueueWork([this, key, env = std::move(env), &state, &callback]() mutable { 472 workers.QueueWork([this, key, env_ = std::move(env), &state, &callback]() mutable {
473 ShaderPools pools; 473 ShaderPools pools;
474 auto pipeline{CreateComputePipeline(pools, key, env, state.statistics.get(), false)}; 474 auto pipeline{CreateComputePipeline(pools, key, env_, state.statistics.get(), false)};
475 std::scoped_lock lock{state.mutex}; 475 std::scoped_lock lock{state.mutex};
476 if (pipeline) { 476 if (pipeline) {
477 compute_cache.emplace(key, std::move(pipeline)); 477 compute_cache.emplace(key, std::move(pipeline));
@@ -500,10 +500,10 @@ void PipelineCache::LoadDiskResources(u64 title_id, std::stop_token stop_loading
500 (key.state.dynamic_vertex_input != 0) != dynamic_features.has_dynamic_vertex_input) { 500 (key.state.dynamic_vertex_input != 0) != dynamic_features.has_dynamic_vertex_input) {
501 return; 501 return;
502 } 502 }
503 workers.QueueWork([this, key, envs = std::move(envs), &state, &callback]() mutable { 503 workers.QueueWork([this, key, envs_ = std::move(envs), &state, &callback]() mutable {
504 ShaderPools pools; 504 ShaderPools pools;
505 boost::container::static_vector<Shader::Environment*, 5> env_ptrs; 505 boost::container::static_vector<Shader::Environment*, 5> env_ptrs;
506 for (auto& env : envs) { 506 for (auto& env : envs_) {
507 env_ptrs.push_back(&env); 507 env_ptrs.push_back(&env);
508 } 508 }
509 auto pipeline{CreateGraphicsPipeline(pools, key, MakeSpan(env_ptrs), 509 auto pipeline{CreateGraphicsPipeline(pools, key, MakeSpan(env_ptrs),
@@ -702,8 +702,8 @@ std::unique_ptr<ComputePipeline> PipelineCache::CreateComputePipeline(
702 if (!pipeline || pipeline_cache_filename.empty()) { 702 if (!pipeline || pipeline_cache_filename.empty()) {
703 return pipeline; 703 return pipeline;
704 } 704 }
705 serialization_thread.QueueWork([this, key, env = std::move(env)] { 705 serialization_thread.QueueWork([this, key, env_ = std::move(env)] {
706 SerializePipeline(key, std::array<const GenericEnvironment*, 1>{&env}, 706 SerializePipeline(key, std::array<const GenericEnvironment*, 1>{&env_},
707 pipeline_cache_filename, CACHE_VERSION); 707 pipeline_cache_filename, CACHE_VERSION);
708 }); 708 });
709 return pipeline; 709 return pipeline;
diff --git a/src/video_core/renderer_vulkan/vk_query_cache.cpp b/src/video_core/renderer_vulkan/vk_query_cache.cpp
index d67490449..29e0b797b 100644
--- a/src/video_core/renderer_vulkan/vk_query_cache.cpp
+++ b/src/video_core/renderer_vulkan/vk_query_cache.cpp
@@ -98,10 +98,10 @@ HostCounter::HostCounter(QueryCache& cache_, std::shared_ptr<HostCounter> depend
98 : HostCounterBase{std::move(dependency_)}, cache{cache_}, type{type_}, 98 : HostCounterBase{std::move(dependency_)}, cache{cache_}, type{type_},
99 query{cache_.AllocateQuery(type_)}, tick{cache_.GetScheduler().CurrentTick()} { 99 query{cache_.AllocateQuery(type_)}, tick{cache_.GetScheduler().CurrentTick()} {
100 const vk::Device* logical = &cache.GetDevice().GetLogical(); 100 const vk::Device* logical = &cache.GetDevice().GetLogical();
101 cache.GetScheduler().Record([logical, query = query](vk::CommandBuffer cmdbuf) { 101 cache.GetScheduler().Record([logical, query_ = query](vk::CommandBuffer cmdbuf) {
102 const bool use_precise = Settings::IsGPULevelHigh(); 102 const bool use_precise = Settings::IsGPULevelHigh();
103 logical->ResetQueryPool(query.first, query.second, 1); 103 logical->ResetQueryPool(query_.first, query_.second, 1);
104 cmdbuf.BeginQuery(query.first, query.second, 104 cmdbuf.BeginQuery(query_.first, query_.second,
105 use_precise ? VK_QUERY_CONTROL_PRECISE_BIT : 0); 105 use_precise ? VK_QUERY_CONTROL_PRECISE_BIT : 0);
106 }); 106 });
107} 107}
@@ -111,8 +111,9 @@ HostCounter::~HostCounter() {
111} 111}
112 112
113void HostCounter::EndQuery() { 113void HostCounter::EndQuery() {
114 cache.GetScheduler().Record( 114 cache.GetScheduler().Record([query_ = query](vk::CommandBuffer cmdbuf) {
115 [query = query](vk::CommandBuffer cmdbuf) { cmdbuf.EndQuery(query.first, query.second); }); 115 cmdbuf.EndQuery(query_.first, query_.second);
116 });
116} 117}
117 118
118u64 HostCounter::BlockingQuery(bool async) const { 119u64 HostCounter::BlockingQuery(bool async) const {
diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp
index 3aac3cfab..bf6ad6c79 100644
--- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp
+++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp
@@ -1412,7 +1412,7 @@ void Image::DownloadMemory(std::span<VkBuffer> buffers_span, std::span<VkDeviceS
1412 } 1412 }
1413 scheduler->RequestOutsideRenderPassOperationContext(); 1413 scheduler->RequestOutsideRenderPassOperationContext();
1414 scheduler->Record([buffers = std::move(buffers_vector), image = *original_image, 1414 scheduler->Record([buffers = std::move(buffers_vector), image = *original_image,
1415 aspect_mask = aspect_mask, vk_copies](vk::CommandBuffer cmdbuf) { 1415 aspect_mask_ = aspect_mask, vk_copies](vk::CommandBuffer cmdbuf) {
1416 const VkImageMemoryBarrier read_barrier{ 1416 const VkImageMemoryBarrier read_barrier{
1417 .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, 1417 .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
1418 .pNext = nullptr, 1418 .pNext = nullptr,
@@ -1424,7 +1424,7 @@ void Image::DownloadMemory(std::span<VkBuffer> buffers_span, std::span<VkDeviceS
1424 .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, 1424 .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
1425 .image = image, 1425 .image = image,
1426 .subresourceRange{ 1426 .subresourceRange{
1427 .aspectMask = aspect_mask, 1427 .aspectMask = aspect_mask_,
1428 .baseMipLevel = 0, 1428 .baseMipLevel = 0,
1429 .levelCount = VK_REMAINING_MIP_LEVELS, 1429 .levelCount = VK_REMAINING_MIP_LEVELS,
1430 .baseArrayLayer = 0, 1430 .baseArrayLayer = 0,
@@ -1456,7 +1456,7 @@ void Image::DownloadMemory(std::span<VkBuffer> buffers_span, std::span<VkDeviceS
1456 .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, 1456 .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
1457 .image = image, 1457 .image = image,
1458 .subresourceRange{ 1458 .subresourceRange{
1459 .aspectMask = aspect_mask, 1459 .aspectMask = aspect_mask_,
1460 .baseMipLevel = 0, 1460 .baseMipLevel = 0,
1461 .levelCount = VK_REMAINING_MIP_LEVELS, 1461 .levelCount = VK_REMAINING_MIP_LEVELS,
1462 .baseArrayLayer = 0, 1462 .baseArrayLayer = 0,
diff --git a/src/web_service/announce_room_json.cpp b/src/web_service/announce_room_json.cpp
index 4c3195efd..f1020a5b8 100644
--- a/src/web_service/announce_room_json.cpp
+++ b/src/web_service/announce_room_json.cpp
@@ -135,11 +135,11 @@ void RoomJson::Delete() {
135 LOG_ERROR(WebService, "Room must be registered to be deleted"); 135 LOG_ERROR(WebService, "Room must be registered to be deleted");
136 return; 136 return;
137 } 137 }
138 Common::DetachedTasks::AddTask( 138 Common::DetachedTasks::AddTask([host_{this->host}, username_{this->username},
139 [host{this->host}, username{this->username}, token{this->token}, room_id{this->room_id}]() { 139 token_{this->token}, room_id_{this->room_id}]() {
140 // create a new client here because the this->client might be destroyed. 140 // create a new client here because the this->client might be destroyed.
141 Client{host, username, token}.DeleteJson(fmt::format("/lobby/{}", room_id), "", false); 141 Client{host_, username_, token_}.DeleteJson(fmt::format("/lobby/{}", room_id_), "", false);
142 }); 142 });
143} 143}
144 144
145} // namespace WebService 145} // namespace WebService
diff --git a/src/yuzu/game_list_worker.cpp b/src/yuzu/game_list_worker.cpp
index 63326968b..9404365b4 100644
--- a/src/yuzu/game_list_worker.cpp
+++ b/src/yuzu/game_list_worker.cpp
@@ -235,7 +235,7 @@ GameListWorker::~GameListWorker() = default;
235void GameListWorker::AddTitlesToGameList(GameListDir* parent_dir) { 235void GameListWorker::AddTitlesToGameList(GameListDir* parent_dir) {
236 using namespace FileSys; 236 using namespace FileSys;
237 237
238 const auto& cache = dynamic_cast<ContentProviderUnion&>(system.GetContentProvider()); 238 const auto& cache = system.GetContentProviderUnion();
239 239
240 auto installed_games = cache.ListEntriesFilterOrigin(std::nullopt, TitleType::Application, 240 auto installed_games = cache.ListEntriesFilterOrigin(std::nullopt, TitleType::Application,
241 ContentRecordType::Program); 241 ContentRecordType::Program);
@@ -265,7 +265,11 @@ void GameListWorker::AddTitlesToGameList(GameListDir* parent_dir) {
265 std::vector<u8> icon; 265 std::vector<u8> icon;
266 std::string name; 266 std::string name;
267 u64 program_id = 0; 267 u64 program_id = 0;
268 loader->ReadProgramId(program_id); 268 const auto result = loader->ReadProgramId(program_id);
269
270 if (result != Loader::ResultStatus::Success) {
271 continue;
272 }
269 273
270 const PatchManager patch{program_id, system.GetFileSystemController(), 274 const PatchManager patch{program_id, system.GetFileSystemController(),
271 system.GetContentProvider()}; 275 system.GetContentProvider()};