summaryrefslogtreecommitdiff
path: root/src/common
diff options
context:
space:
mode:
Diffstat (limited to 'src/common')
-rw-r--r--src/common/common_funcs.h6
-rw-r--r--src/common/fs/path_util.cpp44
-rw-r--r--src/common/fs/path_util.h8
-rw-r--r--src/common/host_memory.cpp38
-rw-r--r--src/common/host_memory.h2
-rw-r--r--src/common/settings.cpp2
-rw-r--r--src/common/settings.h10
-rw-r--r--src/common/settings_common.h1
-rw-r--r--src/common/settings_setting.h5
9 files changed, 86 insertions, 30 deletions
diff --git a/src/common/common_funcs.h b/src/common/common_funcs.h
index 47d028d48..ba3081efb 100644
--- a/src/common/common_funcs.h
+++ b/src/common/common_funcs.h
@@ -123,6 +123,12 @@ namespace Common {
123 return u32(a) | u32(b) << 8 | u32(c) << 16 | u32(d) << 24; 123 return u32(a) | u32(b) << 8 | u32(c) << 16 | u32(d) << 24;
124} 124}
125 125
126[[nodiscard]] constexpr u64 MakeMagic(char a, char b, char c, char d, char e, char f, char g,
127 char h) {
128 return u64(a) << 0 | u64(b) << 8 | u64(c) << 16 | u64(d) << 24 | u64(e) << 32 | u64(f) << 40 |
129 u64(g) << 48 | u64(h) << 56;
130}
131
126// std::size() does not support zero-size C arrays. We're fixing that. 132// std::size() does not support zero-size C arrays. We're fixing that.
127template <class C> 133template <class C>
128constexpr auto Size(const C& c) -> decltype(c.size()) { 134constexpr auto Size(const C& c) -> decltype(c.size()) {
diff --git a/src/common/fs/path_util.cpp b/src/common/fs/path_util.cpp
index c3a81f9a9..4f69db6f5 100644
--- a/src/common/fs/path_util.cpp
+++ b/src/common/fs/path_util.cpp
@@ -354,18 +354,36 @@ std::string_view RemoveTrailingSlash(std::string_view path) {
354 return path; 354 return path;
355} 355}
356 356
357std::vector<std::string> SplitPathComponents(std::string_view filename) { 357template <typename F>
358 std::string copy(filename); 358static void ForEachPathComponent(std::string_view filename, F&& cb) {
359 std::replace(copy.begin(), copy.end(), '\\', '/'); 359 const char* component_begin = filename.data();
360 std::vector<std::string> out; 360 const char* const end = component_begin + filename.size();
361 361 for (const char* it = component_begin; it != end; ++it) {
362 std::stringstream stream(copy); 362 const char c = *it;
363 std::string item; 363 if (c == '\\' || c == '/') {
364 while (std::getline(stream, item, '/')) { 364 if (component_begin != it) {
365 out.push_back(std::move(item)); 365 cb(std::string_view{component_begin, it});
366 }
367 component_begin = it + 1;
368 }
369 }
370 if (component_begin != end) {
371 cb(std::string_view{component_begin, end});
366 } 372 }
373}
374
375std::vector<std::string_view> SplitPathComponents(std::string_view filename) {
376 std::vector<std::string_view> components;
377 ForEachPathComponent(filename, [&](auto component) { components.emplace_back(component); });
367 378
368 return out; 379 return components;
380}
381
382std::vector<std::string> SplitPathComponentsCopy(std::string_view filename) {
383 std::vector<std::string> components;
384 ForEachPathComponent(filename, [&](auto component) { components.emplace_back(component); });
385
386 return components;
369} 387}
370 388
371std::string SanitizePath(std::string_view path_, DirectorySeparator directory_separator) { 389std::string SanitizePath(std::string_view path_, DirectorySeparator directory_separator) {
@@ -400,9 +418,9 @@ std::string SanitizePath(std::string_view path_, DirectorySeparator directory_se
400 return std::string(RemoveTrailingSlash(path)); 418 return std::string(RemoveTrailingSlash(path));
401} 419}
402 420
403std::string_view GetParentPath(std::string_view path) { 421std::string GetParentPath(std::string_view path) {
404 if (path.empty()) { 422 if (path.empty()) {
405 return path; 423 return std::string(path);
406 } 424 }
407 425
408#ifdef ANDROID 426#ifdef ANDROID
@@ -421,7 +439,7 @@ std::string_view GetParentPath(std::string_view path) {
421 name_index = std::max(name_bck_index, name_fwd_index); 439 name_index = std::max(name_bck_index, name_fwd_index);
422 } 440 }
423 441
424 return path.substr(0, name_index); 442 return std::string(path.substr(0, name_index));
425} 443}
426 444
427std::string_view GetPathWithoutTop(std::string_view path) { 445std::string_view GetPathWithoutTop(std::string_view path) {
diff --git a/src/common/fs/path_util.h b/src/common/fs/path_util.h
index 2874ea738..59301e7ed 100644
--- a/src/common/fs/path_util.h
+++ b/src/common/fs/path_util.h
@@ -289,7 +289,11 @@ enum class DirectorySeparator {
289 289
290// Splits the path on '/' or '\' and put the components into a vector 290// Splits the path on '/' or '\' and put the components into a vector
291// i.e. "C:\Users\Yuzu\Documents\save.bin" becomes {"C:", "Users", "Yuzu", "Documents", "save.bin" } 291// i.e. "C:\Users\Yuzu\Documents\save.bin" becomes {"C:", "Users", "Yuzu", "Documents", "save.bin" }
292[[nodiscard]] std::vector<std::string> SplitPathComponents(std::string_view filename); 292[[nodiscard]] std::vector<std::string_view> SplitPathComponents(std::string_view filename);
293
294// Splits the path on '/' or '\' and put the components into a vector
295// i.e. "C:\Users\Yuzu\Documents\save.bin" becomes {"C:", "Users", "Yuzu", "Documents", "save.bin" }
296[[nodiscard]] std::vector<std::string> SplitPathComponentsCopy(std::string_view filename);
293 297
294// Removes trailing slash, makes all '\\' into '/', and removes duplicate '/'. Makes '/' into '\\' 298// Removes trailing slash, makes all '\\' into '/', and removes duplicate '/'. Makes '/' into '\\'
295// depending if directory_separator is BackwardSlash or PlatformDefault and running on windows 299// depending if directory_separator is BackwardSlash or PlatformDefault and running on windows
@@ -298,7 +302,7 @@ enum class DirectorySeparator {
298 DirectorySeparator directory_separator = DirectorySeparator::ForwardSlash); 302 DirectorySeparator directory_separator = DirectorySeparator::ForwardSlash);
299 303
300// Gets all of the text up to the last '/' or '\' in the path. 304// Gets all of the text up to the last '/' or '\' in the path.
301[[nodiscard]] std::string_view GetParentPath(std::string_view path); 305[[nodiscard]] std::string GetParentPath(std::string_view path);
302 306
303// Gets all of the text after the first '/' or '\' in the path. 307// Gets all of the text after the first '/' or '\' in the path.
304[[nodiscard]] std::string_view GetPathWithoutTop(std::string_view path); 308[[nodiscard]] std::string_view GetPathWithoutTop(std::string_view path);
diff --git a/src/common/host_memory.cpp b/src/common/host_memory.cpp
index 4bfc64f2d..e540375b8 100644
--- a/src/common/host_memory.cpp
+++ b/src/common/host_memory.cpp
@@ -11,10 +11,6 @@
11 11
12#elif defined(__linux__) || defined(__FreeBSD__) // ^^^ Windows ^^^ vvv Linux vvv 12#elif defined(__linux__) || defined(__FreeBSD__) // ^^^ Windows ^^^ vvv Linux vvv
13 13
14#ifdef ANDROID
15#include <android/sharedmem.h>
16#endif
17
18#ifndef _GNU_SOURCE 14#ifndef _GNU_SOURCE
19#define _GNU_SOURCE 15#define _GNU_SOURCE
20#endif 16#endif
@@ -193,6 +189,11 @@ public:
193 } 189 }
194 } 190 }
195 191
192 bool ClearBackingRegion(size_t physical_offset, size_t length) {
193 // TODO: This does not seem to be possible on Windows.
194 return false;
195 }
196
196 void EnableDirectMappedAddress() { 197 void EnableDirectMappedAddress() {
197 // TODO 198 // TODO
198 UNREACHABLE(); 199 UNREACHABLE();
@@ -442,9 +443,7 @@ public:
442 } 443 }
443 444
444 // Backing memory initialization 445 // Backing memory initialization
445#ifdef ANDROID 446#if defined(__FreeBSD__) && __FreeBSD__ < 13
446 fd = ASharedMemory_create("HostMemory", backing_size);
447#elif defined(__FreeBSD__) && __FreeBSD__ < 13
448 // XXX Drop after FreeBSD 12.* reaches EOL on 2024-06-30 447 // XXX Drop after FreeBSD 12.* reaches EOL on 2024-06-30
449 fd = shm_open(SHM_ANON, O_RDWR, 0600); 448 fd = shm_open(SHM_ANON, O_RDWR, 0600);
450#else 449#else
@@ -455,7 +454,6 @@ public:
455 throw std::bad_alloc{}; 454 throw std::bad_alloc{};
456 } 455 }
457 456
458#ifndef ANDROID
459 // Defined to extend the file with zeros 457 // Defined to extend the file with zeros
460 int ret = ftruncate(fd, backing_size); 458 int ret = ftruncate(fd, backing_size);
461 if (ret != 0) { 459 if (ret != 0) {
@@ -463,7 +461,6 @@ public:
463 strerror(errno)); 461 strerror(errno));
464 throw std::bad_alloc{}; 462 throw std::bad_alloc{};
465 } 463 }
466#endif
467 464
468 backing_base = static_cast<u8*>( 465 backing_base = static_cast<u8*>(
469 mmap(nullptr, backing_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)); 466 mmap(nullptr, backing_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0));
@@ -552,6 +549,19 @@ public:
552 ASSERT_MSG(ret == 0, "mprotect failed: {}", strerror(errno)); 549 ASSERT_MSG(ret == 0, "mprotect failed: {}", strerror(errno));
553 } 550 }
554 551
552 bool ClearBackingRegion(size_t physical_offset, size_t length) {
553#ifdef __linux__
554 // Set MADV_REMOVE on backing map to destroy it instantly.
555 // This also deletes the area from the backing file.
556 int ret = madvise(backing_base + physical_offset, length, MADV_REMOVE);
557 ASSERT_MSG(ret == 0, "madvise failed: {}", strerror(errno));
558
559 return true;
560#else
561 return false;
562#endif
563 }
564
555 void EnableDirectMappedAddress() { 565 void EnableDirectMappedAddress() {
556 virtual_base = nullptr; 566 virtual_base = nullptr;
557 } 567 }
@@ -623,6 +633,10 @@ public:
623 633
624 void Protect(size_t virtual_offset, size_t length, bool read, bool write, bool execute) {} 634 void Protect(size_t virtual_offset, size_t length, bool read, bool write, bool execute) {}
625 635
636 bool ClearBackingRegion(size_t physical_offset, size_t length) {
637 return false;
638 }
639
626 void EnableDirectMappedAddress() {} 640 void EnableDirectMappedAddress() {}
627 641
628 u8* backing_base{nullptr}; 642 u8* backing_base{nullptr};
@@ -698,6 +712,12 @@ void HostMemory::Protect(size_t virtual_offset, size_t length, bool read, bool w
698 impl->Protect(virtual_offset + virtual_base_offset, length, read, write, execute); 712 impl->Protect(virtual_offset + virtual_base_offset, length, read, write, execute);
699} 713}
700 714
715void HostMemory::ClearBackingRegion(size_t physical_offset, size_t length, u32 fill_value) {
716 if (!impl || fill_value != 0 || !impl->ClearBackingRegion(physical_offset, length)) {
717 std::memset(backing_base + physical_offset, fill_value, length);
718 }
719}
720
701void HostMemory::EnableDirectMappedAddress() { 721void HostMemory::EnableDirectMappedAddress() {
702 if (impl) { 722 if (impl) {
703 impl->EnableDirectMappedAddress(); 723 impl->EnableDirectMappedAddress();
diff --git a/src/common/host_memory.h b/src/common/host_memory.h
index cebfacab2..747c5850c 100644
--- a/src/common/host_memory.h
+++ b/src/common/host_memory.h
@@ -48,6 +48,8 @@ public:
48 48
49 void EnableDirectMappedAddress(); 49 void EnableDirectMappedAddress();
50 50
51 void ClearBackingRegion(size_t physical_offset, size_t length, u32 fill_value);
52
51 [[nodiscard]] u8* BackingBasePointer() noexcept { 53 [[nodiscard]] u8* BackingBasePointer() noexcept {
52 return backing_base; 54 return backing_base;
53 } 55 }
diff --git a/src/common/settings.cpp b/src/common/settings.cpp
index 88f509ba7..ea52bbfa6 100644
--- a/src/common/settings.cpp
+++ b/src/common/settings.cpp
@@ -211,6 +211,8 @@ const char* TranslateCategory(Category category) {
211 case Category::Debugging: 211 case Category::Debugging:
212 case Category::DebuggingGraphics: 212 case Category::DebuggingGraphics:
213 return "Debugging"; 213 return "Debugging";
214 case Category::GpuDriver:
215 return "GpuDriver";
214 case Category::Miscellaneous: 216 case Category::Miscellaneous:
215 return "Miscellaneous"; 217 return "Miscellaneous";
216 case Category::Network: 218 case Category::Network:
diff --git a/src/common/settings.h b/src/common/settings.h
index 7dc18fffe..07dba53ab 100644
--- a/src/common/settings.h
+++ b/src/common/settings.h
@@ -197,7 +197,7 @@ struct Values {
197 SwitchableSetting<CpuAccuracy, true> cpu_accuracy{linkage, CpuAccuracy::Auto, 197 SwitchableSetting<CpuAccuracy, true> cpu_accuracy{linkage, CpuAccuracy::Auto,
198 CpuAccuracy::Auto, CpuAccuracy::Paranoid, 198 CpuAccuracy::Auto, CpuAccuracy::Paranoid,
199 "cpu_accuracy", Category::Cpu}; 199 "cpu_accuracy", Category::Cpu};
200 Setting<bool> cpu_debug_mode{linkage, false, "cpu_debug_mode", Category::CpuDebug}; 200 SwitchableSetting<bool> cpu_debug_mode{linkage, false, "cpu_debug_mode", Category::CpuDebug};
201 201
202 Setting<bool> cpuopt_page_tables{linkage, true, "cpuopt_page_tables", Category::CpuDebug}; 202 Setting<bool> cpuopt_page_tables{linkage, true, "cpuopt_page_tables", Category::CpuDebug};
203 Setting<bool> cpuopt_block_linking{linkage, true, "cpuopt_block_linking", Category::CpuDebug}; 203 Setting<bool> cpuopt_block_linking{linkage, true, "cpuopt_block_linking", Category::CpuDebug};
@@ -211,9 +211,9 @@ struct Values {
211 Setting<bool> cpuopt_misc_ir{linkage, true, "cpuopt_misc_ir", Category::CpuDebug}; 211 Setting<bool> cpuopt_misc_ir{linkage, true, "cpuopt_misc_ir", Category::CpuDebug};
212 Setting<bool> cpuopt_reduce_misalign_checks{linkage, true, "cpuopt_reduce_misalign_checks", 212 Setting<bool> cpuopt_reduce_misalign_checks{linkage, true, "cpuopt_reduce_misalign_checks",
213 Category::CpuDebug}; 213 Category::CpuDebug};
214 Setting<bool> cpuopt_fastmem{linkage, true, "cpuopt_fastmem", Category::CpuDebug}; 214 SwitchableSetting<bool> cpuopt_fastmem{linkage, true, "cpuopt_fastmem", Category::CpuDebug};
215 Setting<bool> cpuopt_fastmem_exclusives{linkage, true, "cpuopt_fastmem_exclusives", 215 SwitchableSetting<bool> cpuopt_fastmem_exclusives{linkage, true, "cpuopt_fastmem_exclusives",
216 Category::CpuDebug}; 216 Category::CpuDebug};
217 Setting<bool> cpuopt_recompile_exclusives{linkage, true, "cpuopt_recompile_exclusives", 217 Setting<bool> cpuopt_recompile_exclusives{linkage, true, "cpuopt_recompile_exclusives",
218 Category::CpuDebug}; 218 Category::CpuDebug};
219 Setting<bool> cpuopt_ignore_memory_aborts{linkage, true, "cpuopt_ignore_memory_aborts", 219 Setting<bool> cpuopt_ignore_memory_aborts{linkage, true, "cpuopt_ignore_memory_aborts",
@@ -256,7 +256,7 @@ struct Values {
256 AstcDecodeMode::CpuAsynchronous, 256 AstcDecodeMode::CpuAsynchronous,
257 "accelerate_astc", 257 "accelerate_astc",
258 Category::Renderer}; 258 Category::Renderer};
259 Setting<VSyncMode, true> vsync_mode{ 259 SwitchableSetting<VSyncMode, true> vsync_mode{
260 linkage, VSyncMode::Fifo, VSyncMode::Immediate, VSyncMode::FifoRelaxed, 260 linkage, VSyncMode::Fifo, VSyncMode::Immediate, VSyncMode::FifoRelaxed,
261 "use_vsync", Category::Renderer, Specialization::RuntimeList, true, 261 "use_vsync", Category::Renderer, Specialization::RuntimeList, true,
262 true}; 262 true};
diff --git a/src/common/settings_common.h b/src/common/settings_common.h
index 344c04439..c82e17495 100644
--- a/src/common/settings_common.h
+++ b/src/common/settings_common.h
@@ -26,6 +26,7 @@ enum class Category : u32 {
26 DataStorage, 26 DataStorage,
27 Debugging, 27 Debugging,
28 DebuggingGraphics, 28 DebuggingGraphics,
29 GpuDriver,
29 Miscellaneous, 30 Miscellaneous,
30 Network, 31 Network,
31 WebService, 32 WebService,
diff --git a/src/common/settings_setting.h b/src/common/settings_setting.h
index 3175ab07d..0b18ca5ec 100644
--- a/src/common/settings_setting.h
+++ b/src/common/settings_setting.h
@@ -81,6 +81,9 @@ public:
81 [[nodiscard]] virtual const Type& GetValue() const { 81 [[nodiscard]] virtual const Type& GetValue() const {
82 return value; 82 return value;
83 } 83 }
84 [[nodiscard]] virtual const Type& GetValue(bool need_global) const {
85 return value;
86 }
84 87
85 /** 88 /**
86 * Sets the setting to the given value. 89 * Sets the setting to the given value.
@@ -353,7 +356,7 @@ public:
353 } 356 }
354 return custom; 357 return custom;
355 } 358 }
356 [[nodiscard]] const Type& GetValue(bool need_global) const { 359 [[nodiscard]] const Type& GetValue(bool need_global) const override final {
357 if (use_global || need_global) { 360 if (use_global || need_global) {
358 return this->value; 361 return this->value;
359 } 362 }