diff options
Diffstat (limited to 'src/common')
| -rw-r--r-- | src/common/common_funcs.h | 6 | ||||
| -rw-r--r-- | src/common/fs/path_util.cpp | 44 | ||||
| -rw-r--r-- | src/common/fs/path_util.h | 8 | ||||
| -rw-r--r-- | src/common/host_memory.cpp | 38 | ||||
| -rw-r--r-- | src/common/host_memory.h | 2 | ||||
| -rw-r--r-- | src/common/settings.cpp | 2 | ||||
| -rw-r--r-- | src/common/settings.h | 10 | ||||
| -rw-r--r-- | src/common/settings_common.h | 1 | ||||
| -rw-r--r-- | src/common/settings_setting.h | 5 |
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. |
| 127 | template <class C> | 133 | template <class C> |
| 128 | constexpr auto Size(const C& c) -> decltype(c.size()) { | 134 | constexpr 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 | ||
| 357 | std::vector<std::string> SplitPathComponents(std::string_view filename) { | 357 | template <typename F> |
| 358 | std::string copy(filename); | 358 | static 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 | |||
| 375 | std::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 | |||
| 382 | std::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 | ||
| 371 | std::string SanitizePath(std::string_view path_, DirectorySeparator directory_separator) { | 389 | std::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 | ||
| 403 | std::string_view GetParentPath(std::string_view path) { | 421 | std::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 | ||
| 427 | std::string_view GetPathWithoutTop(std::string_view path) { | 445 | std::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 | ||
| 715 | void 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 | |||
| 701 | void HostMemory::EnableDirectMappedAddress() { | 721 | void 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 | } |