diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/common/file_util.cpp | 49 | ||||
| -rw-r--r-- | src/common/file_util.h | 15 | ||||
| -rw-r--r-- | src/core/hle/service/aoc/aoc_u.cpp | 69 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_device.cpp | 1 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_cache.cpp | 3 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_gen.cpp | 9 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/utils.cpp | 16 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/utils.h | 4 | ||||
| -rw-r--r-- | src/yuzu/configuration/configure_dialog.cpp | 3 | ||||
| -rw-r--r-- | src/yuzu/configuration/configure_hotkeys.cpp | 38 | ||||
| -rw-r--r-- | src/yuzu/configuration/configure_hotkeys.h | 6 | ||||
| -rw-r--r-- | src/yuzu/util/sequence_dialog/sequence_dialog.cpp | 13 | ||||
| -rw-r--r-- | src/yuzu_cmd/config.cpp | 4 |
13 files changed, 114 insertions, 116 deletions
diff --git a/src/common/file_util.cpp b/src/common/file_util.cpp index aecb66c32..2d9374783 100644 --- a/src/common/file_util.cpp +++ b/src/common/file_util.cpp | |||
| @@ -78,16 +78,17 @@ namespace FileUtil { | |||
| 78 | // Remove any ending forward slashes from directory paths | 78 | // Remove any ending forward slashes from directory paths |
| 79 | // Modifies argument. | 79 | // Modifies argument. |
| 80 | static void StripTailDirSlashes(std::string& fname) { | 80 | static void StripTailDirSlashes(std::string& fname) { |
| 81 | if (fname.length() > 1) { | 81 | if (fname.length() <= 1) { |
| 82 | std::size_t i = fname.length(); | 82 | return; |
| 83 | while (i > 0 && fname[i - 1] == DIR_SEP_CHR) | 83 | } |
| 84 | --i; | 84 | |
| 85 | fname.resize(i); | 85 | std::size_t i = fname.length(); |
| 86 | while (i > 0 && fname[i - 1] == DIR_SEP_CHR) { | ||
| 87 | --i; | ||
| 86 | } | 88 | } |
| 87 | return; | 89 | fname.resize(i); |
| 88 | } | 90 | } |
| 89 | 91 | ||
| 90 | // Returns true if file filename exists | ||
| 91 | bool Exists(const std::string& filename) { | 92 | bool Exists(const std::string& filename) { |
| 92 | struct stat file_info; | 93 | struct stat file_info; |
| 93 | 94 | ||
| @@ -107,7 +108,6 @@ bool Exists(const std::string& filename) { | |||
| 107 | return (result == 0); | 108 | return (result == 0); |
| 108 | } | 109 | } |
| 109 | 110 | ||
| 110 | // Returns true if filename is a directory | ||
| 111 | bool IsDirectory(const std::string& filename) { | 111 | bool IsDirectory(const std::string& filename) { |
| 112 | struct stat file_info; | 112 | struct stat file_info; |
| 113 | 113 | ||
| @@ -132,8 +132,6 @@ bool IsDirectory(const std::string& filename) { | |||
| 132 | return S_ISDIR(file_info.st_mode); | 132 | return S_ISDIR(file_info.st_mode); |
| 133 | } | 133 | } |
| 134 | 134 | ||
| 135 | // Deletes a given filename, return true on success | ||
| 136 | // Doesn't supports deleting a directory | ||
| 137 | bool Delete(const std::string& filename) { | 135 | bool Delete(const std::string& filename) { |
| 138 | LOG_TRACE(Common_Filesystem, "file {}", filename); | 136 | LOG_TRACE(Common_Filesystem, "file {}", filename); |
| 139 | 137 | ||
| @@ -165,7 +163,6 @@ bool Delete(const std::string& filename) { | |||
| 165 | return true; | 163 | return true; |
| 166 | } | 164 | } |
| 167 | 165 | ||
| 168 | // Returns true if successful, or path already exists. | ||
| 169 | bool CreateDir(const std::string& path) { | 166 | bool CreateDir(const std::string& path) { |
| 170 | LOG_TRACE(Common_Filesystem, "directory {}", path); | 167 | LOG_TRACE(Common_Filesystem, "directory {}", path); |
| 171 | #ifdef _WIN32 | 168 | #ifdef _WIN32 |
| @@ -194,7 +191,6 @@ bool CreateDir(const std::string& path) { | |||
| 194 | #endif | 191 | #endif |
| 195 | } | 192 | } |
| 196 | 193 | ||
| 197 | // Creates the full path of fullPath returns true on success | ||
| 198 | bool CreateFullPath(const std::string& fullPath) { | 194 | bool CreateFullPath(const std::string& fullPath) { |
| 199 | int panicCounter = 100; | 195 | int panicCounter = 100; |
| 200 | LOG_TRACE(Common_Filesystem, "path {}", fullPath); | 196 | LOG_TRACE(Common_Filesystem, "path {}", fullPath); |
| @@ -230,7 +226,6 @@ bool CreateFullPath(const std::string& fullPath) { | |||
| 230 | } | 226 | } |
| 231 | } | 227 | } |
| 232 | 228 | ||
| 233 | // Deletes a directory filename, returns true on success | ||
| 234 | bool DeleteDir(const std::string& filename) { | 229 | bool DeleteDir(const std::string& filename) { |
| 235 | LOG_TRACE(Common_Filesystem, "directory {}", filename); | 230 | LOG_TRACE(Common_Filesystem, "directory {}", filename); |
| 236 | 231 | ||
| @@ -252,7 +247,6 @@ bool DeleteDir(const std::string& filename) { | |||
| 252 | return false; | 247 | return false; |
| 253 | } | 248 | } |
| 254 | 249 | ||
| 255 | // renames file srcFilename to destFilename, returns true on success | ||
| 256 | bool Rename(const std::string& srcFilename, const std::string& destFilename) { | 250 | bool Rename(const std::string& srcFilename, const std::string& destFilename) { |
| 257 | LOG_TRACE(Common_Filesystem, "{} --> {}", srcFilename, destFilename); | 251 | LOG_TRACE(Common_Filesystem, "{} --> {}", srcFilename, destFilename); |
| 258 | #ifdef _WIN32 | 252 | #ifdef _WIN32 |
| @@ -268,7 +262,6 @@ bool Rename(const std::string& srcFilename, const std::string& destFilename) { | |||
| 268 | return false; | 262 | return false; |
| 269 | } | 263 | } |
| 270 | 264 | ||
| 271 | // copies file srcFilename to destFilename, returns true on success | ||
| 272 | bool Copy(const std::string& srcFilename, const std::string& destFilename) { | 265 | bool Copy(const std::string& srcFilename, const std::string& destFilename) { |
| 273 | LOG_TRACE(Common_Filesystem, "{} --> {}", srcFilename, destFilename); | 266 | LOG_TRACE(Common_Filesystem, "{} --> {}", srcFilename, destFilename); |
| 274 | #ifdef _WIN32 | 267 | #ifdef _WIN32 |
| @@ -324,7 +317,6 @@ bool Copy(const std::string& srcFilename, const std::string& destFilename) { | |||
| 324 | #endif | 317 | #endif |
| 325 | } | 318 | } |
| 326 | 319 | ||
| 327 | // Returns the size of filename (64bit) | ||
| 328 | u64 GetSize(const std::string& filename) { | 320 | u64 GetSize(const std::string& filename) { |
| 329 | if (!Exists(filename)) { | 321 | if (!Exists(filename)) { |
| 330 | LOG_ERROR(Common_Filesystem, "failed {}: No such file", filename); | 322 | LOG_ERROR(Common_Filesystem, "failed {}: No such file", filename); |
| @@ -351,7 +343,6 @@ u64 GetSize(const std::string& filename) { | |||
| 351 | return 0; | 343 | return 0; |
| 352 | } | 344 | } |
| 353 | 345 | ||
| 354 | // Overloaded GetSize, accepts file descriptor | ||
| 355 | u64 GetSize(const int fd) { | 346 | u64 GetSize(const int fd) { |
| 356 | struct stat buf; | 347 | struct stat buf; |
| 357 | if (fstat(fd, &buf) != 0) { | 348 | if (fstat(fd, &buf) != 0) { |
| @@ -361,7 +352,6 @@ u64 GetSize(const int fd) { | |||
| 361 | return buf.st_size; | 352 | return buf.st_size; |
| 362 | } | 353 | } |
| 363 | 354 | ||
| 364 | // Overloaded GetSize, accepts FILE* | ||
| 365 | u64 GetSize(FILE* f) { | 355 | u64 GetSize(FILE* f) { |
| 366 | // can't use off_t here because it can be 32-bit | 356 | // can't use off_t here because it can be 32-bit |
| 367 | u64 pos = ftello(f); | 357 | u64 pos = ftello(f); |
| @@ -377,7 +367,6 @@ u64 GetSize(FILE* f) { | |||
| 377 | return size; | 367 | return size; |
| 378 | } | 368 | } |
| 379 | 369 | ||
| 380 | // creates an empty file filename, returns true on success | ||
| 381 | bool CreateEmptyFile(const std::string& filename) { | 370 | bool CreateEmptyFile(const std::string& filename) { |
| 382 | LOG_TRACE(Common_Filesystem, "{}", filename); | 371 | LOG_TRACE(Common_Filesystem, "{}", filename); |
| 383 | 372 | ||
| @@ -502,7 +491,6 @@ bool DeleteDirRecursively(const std::string& directory, unsigned int recursion) | |||
| 502 | return true; | 491 | return true; |
| 503 | } | 492 | } |
| 504 | 493 | ||
| 505 | // Create directory and copy contents (does not overwrite existing files) | ||
| 506 | void CopyDir(const std::string& source_path, const std::string& dest_path) { | 494 | void CopyDir(const std::string& source_path, const std::string& dest_path) { |
| 507 | #ifndef _WIN32 | 495 | #ifndef _WIN32 |
| 508 | if (source_path == dest_path) | 496 | if (source_path == dest_path) |
| @@ -539,8 +527,7 @@ void CopyDir(const std::string& source_path, const std::string& dest_path) { | |||
| 539 | #endif | 527 | #endif |
| 540 | } | 528 | } |
| 541 | 529 | ||
| 542 | // Returns the current directory | 530 | std::optional<std::string> GetCurrentDir() { |
| 543 | std::string GetCurrentDir() { | ||
| 544 | // Get the current working directory (getcwd uses malloc) | 531 | // Get the current working directory (getcwd uses malloc) |
| 545 | #ifdef _WIN32 | 532 | #ifdef _WIN32 |
| 546 | wchar_t* dir; | 533 | wchar_t* dir; |
| @@ -550,7 +537,7 @@ std::string GetCurrentDir() { | |||
| 550 | if (!(dir = getcwd(nullptr, 0))) { | 537 | if (!(dir = getcwd(nullptr, 0))) { |
| 551 | #endif | 538 | #endif |
| 552 | LOG_ERROR(Common_Filesystem, "GetCurrentDirectory failed: {}", GetLastErrorMsg()); | 539 | LOG_ERROR(Common_Filesystem, "GetCurrentDirectory failed: {}", GetLastErrorMsg()); |
| 553 | return nullptr; | 540 | return {}; |
| 554 | } | 541 | } |
| 555 | #ifdef _WIN32 | 542 | #ifdef _WIN32 |
| 556 | std::string strDir = Common::UTF16ToUTF8(dir); | 543 | std::string strDir = Common::UTF16ToUTF8(dir); |
| @@ -561,7 +548,6 @@ std::string GetCurrentDir() { | |||
| 561 | return strDir; | 548 | return strDir; |
| 562 | } | 549 | } |
| 563 | 550 | ||
| 564 | // Sets the current directory to the given directory | ||
| 565 | bool SetCurrentDir(const std::string& directory) { | 551 | bool SetCurrentDir(const std::string& directory) { |
| 566 | #ifdef _WIN32 | 552 | #ifdef _WIN32 |
| 567 | return _wchdir(Common::UTF8ToUTF16W(directory).c_str()) == 0; | 553 | return _wchdir(Common::UTF8ToUTF16W(directory).c_str()) == 0; |
| @@ -673,8 +659,6 @@ std::string GetSysDirectory() { | |||
| 673 | return sysDir; | 659 | return sysDir; |
| 674 | } | 660 | } |
| 675 | 661 | ||
| 676 | // Returns a string with a yuzu data dir or file in the user's home | ||
| 677 | // directory. To be used in "multi-user" mode (that is, installed). | ||
| 678 | const std::string& GetUserPath(UserPath path, const std::string& new_path) { | 662 | const std::string& GetUserPath(UserPath path, const std::string& new_path) { |
| 679 | static std::unordered_map<UserPath, std::string> paths; | 663 | static std::unordered_map<UserPath, std::string> paths; |
| 680 | auto& user_path = paths[UserPath::UserDir]; | 664 | auto& user_path = paths[UserPath::UserDir]; |
| @@ -762,11 +746,11 @@ std::string GetNANDRegistrationDir(bool system) { | |||
| 762 | return GetUserPath(UserPath::NANDDir) + "user/Contents/registered/"; | 746 | return GetUserPath(UserPath::NANDDir) + "user/Contents/registered/"; |
| 763 | } | 747 | } |
| 764 | 748 | ||
| 765 | std::size_t WriteStringToFile(bool text_file, const std::string& str, const char* filename) { | 749 | std::size_t WriteStringToFile(bool text_file, const std::string& filename, std::string_view str) { |
| 766 | return FileUtil::IOFile(filename, text_file ? "w" : "wb").WriteBytes(str.data(), str.size()); | 750 | return IOFile(filename, text_file ? "w" : "wb").WriteString(str); |
| 767 | } | 751 | } |
| 768 | 752 | ||
| 769 | std::size_t ReadFileToString(bool text_file, const char* filename, std::string& str) { | 753 | std::size_t ReadFileToString(bool text_file, const std::string& filename, std::string& str) { |
| 770 | IOFile file(filename, text_file ? "r" : "rb"); | 754 | IOFile file(filename, text_file ? "r" : "rb"); |
| 771 | 755 | ||
| 772 | if (!file.IsOpen()) | 756 | if (!file.IsOpen()) |
| @@ -776,13 +760,6 @@ std::size_t ReadFileToString(bool text_file, const char* filename, std::string& | |||
| 776 | return file.ReadArray(&str[0], str.size()); | 760 | return file.ReadArray(&str[0], str.size()); |
| 777 | } | 761 | } |
| 778 | 762 | ||
| 779 | /** | ||
| 780 | * Splits the filename into 8.3 format | ||
| 781 | * Loosely implemented following https://en.wikipedia.org/wiki/8.3_filename | ||
| 782 | * @param filename The normal filename to use | ||
| 783 | * @param short_name A 9-char array in which the short name will be written | ||
| 784 | * @param extension A 4-char array in which the extension will be written | ||
| 785 | */ | ||
| 786 | void SplitFilename83(const std::string& filename, std::array<char, 9>& short_name, | 763 | void SplitFilename83(const std::string& filename, std::array<char, 9>& short_name, |
| 787 | std::array<char, 4>& extension) { | 764 | std::array<char, 4>& extension) { |
| 788 | const std::string forbidden_characters = ".\"/\\[]:;=, "; | 765 | const std::string forbidden_characters = ".\"/\\[]:;=, "; |
diff --git a/src/common/file_util.h b/src/common/file_util.h index 38cc7f059..cde7ddf2d 100644 --- a/src/common/file_util.h +++ b/src/common/file_util.h | |||
| @@ -9,6 +9,7 @@ | |||
| 9 | #include <fstream> | 9 | #include <fstream> |
| 10 | #include <functional> | 10 | #include <functional> |
| 11 | #include <limits> | 11 | #include <limits> |
| 12 | #include <optional> | ||
| 12 | #include <string> | 13 | #include <string> |
| 13 | #include <string_view> | 14 | #include <string_view> |
| 14 | #include <type_traits> | 15 | #include <type_traits> |
| @@ -118,7 +119,7 @@ u64 ScanDirectoryTree(const std::string& directory, FSTEntry& parent_entry, | |||
| 118 | bool DeleteDirRecursively(const std::string& directory, unsigned int recursion = 256); | 119 | bool DeleteDirRecursively(const std::string& directory, unsigned int recursion = 256); |
| 119 | 120 | ||
| 120 | // Returns the current directory | 121 | // Returns the current directory |
| 121 | std::string GetCurrentDir(); | 122 | std::optional<std::string> GetCurrentDir(); |
| 122 | 123 | ||
| 123 | // Create directory and copy contents (does not overwrite existing files) | 124 | // Create directory and copy contents (does not overwrite existing files) |
| 124 | void CopyDir(const std::string& source_path, const std::string& dest_path); | 125 | void CopyDir(const std::string& source_path, const std::string& dest_path); |
| @@ -146,9 +147,9 @@ const std::string& GetExeDirectory(); | |||
| 146 | std::string AppDataRoamingDirectory(); | 147 | std::string AppDataRoamingDirectory(); |
| 147 | #endif | 148 | #endif |
| 148 | 149 | ||
| 149 | std::size_t WriteStringToFile(bool text_file, const std::string& str, const char* filename); | 150 | std::size_t WriteStringToFile(bool text_file, const std::string& filename, std::string_view str); |
| 150 | 151 | ||
| 151 | std::size_t ReadFileToString(bool text_file, const char* filename, std::string& str); | 152 | std::size_t ReadFileToString(bool text_file, const std::string& filename, std::string& str); |
| 152 | 153 | ||
| 153 | /** | 154 | /** |
| 154 | * Splits the filename into 8.3 format | 155 | * Splits the filename into 8.3 format |
| @@ -257,8 +258,8 @@ public: | |||
| 257 | return WriteArray(&object, 1); | 258 | return WriteArray(&object, 1); |
| 258 | } | 259 | } |
| 259 | 260 | ||
| 260 | std::size_t WriteString(const std::string& str) { | 261 | std::size_t WriteString(std::string_view str) { |
| 261 | return WriteArray(str.c_str(), str.length()); | 262 | return WriteArray(str.data(), str.length()); |
| 262 | } | 263 | } |
| 263 | 264 | ||
| 264 | bool IsOpen() const { | 265 | bool IsOpen() const { |
| @@ -286,8 +287,8 @@ private: | |||
| 286 | template <typename T> | 287 | template <typename T> |
| 287 | void OpenFStream(T& fstream, const std::string& filename, std::ios_base::openmode openmode) { | 288 | void OpenFStream(T& fstream, const std::string& filename, std::ios_base::openmode openmode) { |
| 288 | #ifdef _MSC_VER | 289 | #ifdef _MSC_VER |
| 289 | fstream.open(Common::UTF8ToUTF16W(filename).c_str(), openmode); | 290 | fstream.open(Common::UTF8ToUTF16W(filename), openmode); |
| 290 | #else | 291 | #else |
| 291 | fstream.open(filename.c_str(), openmode); | 292 | fstream.open(filename, openmode); |
| 292 | #endif | 293 | #endif |
| 293 | } | 294 | } |
diff --git a/src/core/hle/service/aoc/aoc_u.cpp b/src/core/hle/service/aoc/aoc_u.cpp index bd4e38461..d3e97776b 100644 --- a/src/core/hle/service/aoc/aoc_u.cpp +++ b/src/core/hle/service/aoc/aoc_u.cpp | |||
| @@ -9,7 +9,6 @@ | |||
| 9 | #include "core/file_sys/content_archive.h" | 9 | #include "core/file_sys/content_archive.h" |
| 10 | #include "core/file_sys/control_metadata.h" | 10 | #include "core/file_sys/control_metadata.h" |
| 11 | #include "core/file_sys/nca_metadata.h" | 11 | #include "core/file_sys/nca_metadata.h" |
| 12 | #include "core/file_sys/partition_filesystem.h" | ||
| 13 | #include "core/file_sys/patch_manager.h" | 12 | #include "core/file_sys/patch_manager.h" |
| 14 | #include "core/file_sys/registered_cache.h" | 13 | #include "core/file_sys/registered_cache.h" |
| 15 | #include "core/hle/ipc_helpers.h" | 14 | #include "core/hle/ipc_helpers.h" |
| @@ -18,7 +17,6 @@ | |||
| 18 | #include "core/hle/kernel/readable_event.h" | 17 | #include "core/hle/kernel/readable_event.h" |
| 19 | #include "core/hle/kernel/writable_event.h" | 18 | #include "core/hle/kernel/writable_event.h" |
| 20 | #include "core/hle/service/aoc/aoc_u.h" | 19 | #include "core/hle/service/aoc/aoc_u.h" |
| 21 | #include "core/hle/service/filesystem/filesystem.h" | ||
| 22 | #include "core/loader/loader.h" | 20 | #include "core/loader/loader.h" |
| 23 | #include "core/settings.h" | 21 | #include "core/settings.h" |
| 24 | 22 | ||
| @@ -75,7 +73,15 @@ AOC_U::AOC_U() : ServiceFramework("aoc:u"), add_on_content(AccumulateAOCTitleIDs | |||
| 75 | AOC_U::~AOC_U() = default; | 73 | AOC_U::~AOC_U() = default; |
| 76 | 74 | ||
| 77 | void AOC_U::CountAddOnContent(Kernel::HLERequestContext& ctx) { | 75 | void AOC_U::CountAddOnContent(Kernel::HLERequestContext& ctx) { |
| 78 | LOG_DEBUG(Service_AOC, "called"); | 76 | struct Parameters { |
| 77 | u64 process_id; | ||
| 78 | }; | ||
| 79 | static_assert(sizeof(Parameters) == 8); | ||
| 80 | |||
| 81 | IPC::RequestParser rp{ctx}; | ||
| 82 | const auto params = rp.PopRaw<Parameters>(); | ||
| 83 | |||
| 84 | LOG_DEBUG(Service_AOC, "called. process_id={}", params.process_id); | ||
| 79 | 85 | ||
| 80 | IPC::ResponseBuilder rb{ctx, 3}; | 86 | IPC::ResponseBuilder rb{ctx, 3}; |
| 81 | rb.Push(RESULT_SUCCESS); | 87 | rb.Push(RESULT_SUCCESS); |
| @@ -94,23 +100,32 @@ void AOC_U::CountAddOnContent(Kernel::HLERequestContext& ctx) { | |||
| 94 | } | 100 | } |
| 95 | 101 | ||
| 96 | void AOC_U::ListAddOnContent(Kernel::HLERequestContext& ctx) { | 102 | void AOC_U::ListAddOnContent(Kernel::HLERequestContext& ctx) { |
| 103 | struct Parameters { | ||
| 104 | u32 offset; | ||
| 105 | u32 count; | ||
| 106 | u64 process_id; | ||
| 107 | }; | ||
| 108 | static_assert(sizeof(Parameters) == 16); | ||
| 109 | |||
| 97 | IPC::RequestParser rp{ctx}; | 110 | IPC::RequestParser rp{ctx}; |
| 111 | const auto [offset, count, process_id] = rp.PopRaw<Parameters>(); | ||
| 98 | 112 | ||
| 99 | const auto offset = rp.PopRaw<u32>(); | 113 | LOG_DEBUG(Service_AOC, "called with offset={}, count={}, process_id={}", offset, count, |
| 100 | auto count = rp.PopRaw<u32>(); | 114 | process_id); |
| 101 | LOG_DEBUG(Service_AOC, "called with offset={}, count={}", offset, count); | ||
| 102 | 115 | ||
| 103 | const auto current = Core::System::GetInstance().CurrentProcess()->GetTitleID(); | 116 | const auto current = Core::System::GetInstance().CurrentProcess()->GetTitleID(); |
| 104 | 117 | ||
| 105 | std::vector<u32> out; | 118 | std::vector<u32> out; |
| 106 | for (size_t i = 0; i < add_on_content.size(); ++i) { | ||
| 107 | if ((add_on_content[i] & DLC_BASE_TITLE_ID_MASK) == current) | ||
| 108 | out.push_back(static_cast<u32>(add_on_content[i] & 0x7FF)); | ||
| 109 | } | ||
| 110 | |||
| 111 | const auto& disabled = Settings::values.disabled_addons[current]; | 119 | const auto& disabled = Settings::values.disabled_addons[current]; |
| 112 | if (std::find(disabled.begin(), disabled.end(), "DLC") != disabled.end()) | 120 | if (std::find(disabled.begin(), disabled.end(), "DLC") == disabled.end()) { |
| 113 | out = {}; | 121 | for (u64 content_id : add_on_content) { |
| 122 | if ((content_id & DLC_BASE_TITLE_ID_MASK) != current) { | ||
| 123 | continue; | ||
| 124 | } | ||
| 125 | |||
| 126 | out.push_back(static_cast<u32>(content_id & 0x7FF)); | ||
| 127 | } | ||
| 128 | } | ||
| 114 | 129 | ||
| 115 | if (out.size() < offset) { | 130 | if (out.size() < offset) { |
| 116 | IPC::ResponseBuilder rb{ctx, 2}; | 131 | IPC::ResponseBuilder rb{ctx, 2}; |
| @@ -119,22 +134,31 @@ void AOC_U::ListAddOnContent(Kernel::HLERequestContext& ctx) { | |||
| 119 | return; | 134 | return; |
| 120 | } | 135 | } |
| 121 | 136 | ||
| 122 | count = static_cast<u32>(std::min<size_t>(out.size() - offset, count)); | 137 | const auto out_count = static_cast<u32>(std::min<size_t>(out.size() - offset, count)); |
| 123 | std::rotate(out.begin(), out.begin() + offset, out.end()); | 138 | std::rotate(out.begin(), out.begin() + offset, out.end()); |
| 124 | out.resize(count); | 139 | out.resize(out_count); |
| 125 | 140 | ||
| 126 | ctx.WriteBuffer(out); | 141 | ctx.WriteBuffer(out); |
| 127 | 142 | ||
| 128 | IPC::ResponseBuilder rb{ctx, 3}; | 143 | IPC::ResponseBuilder rb{ctx, 3}; |
| 129 | rb.Push(RESULT_SUCCESS); | 144 | rb.Push(RESULT_SUCCESS); |
| 130 | rb.Push(count); | 145 | rb.Push(out_count); |
| 131 | } | 146 | } |
| 132 | 147 | ||
| 133 | void AOC_U::GetAddOnContentBaseId(Kernel::HLERequestContext& ctx) { | 148 | void AOC_U::GetAddOnContentBaseId(Kernel::HLERequestContext& ctx) { |
| 134 | LOG_DEBUG(Service_AOC, "called"); | 149 | struct Parameters { |
| 150 | u64 process_id; | ||
| 151 | }; | ||
| 152 | static_assert(sizeof(Parameters) == 8); | ||
| 153 | |||
| 154 | IPC::RequestParser rp{ctx}; | ||
| 155 | const auto params = rp.PopRaw<Parameters>(); | ||
| 156 | |||
| 157 | LOG_DEBUG(Service_AOC, "called. process_id={}", params.process_id); | ||
| 135 | 158 | ||
| 136 | IPC::ResponseBuilder rb{ctx, 4}; | 159 | IPC::ResponseBuilder rb{ctx, 4}; |
| 137 | rb.Push(RESULT_SUCCESS); | 160 | rb.Push(RESULT_SUCCESS); |
| 161 | |||
| 138 | const auto title_id = Core::System::GetInstance().CurrentProcess()->GetTitleID(); | 162 | const auto title_id = Core::System::GetInstance().CurrentProcess()->GetTitleID(); |
| 139 | FileSys::PatchManager pm{title_id}; | 163 | FileSys::PatchManager pm{title_id}; |
| 140 | 164 | ||
| @@ -148,10 +172,17 @@ void AOC_U::GetAddOnContentBaseId(Kernel::HLERequestContext& ctx) { | |||
| 148 | } | 172 | } |
| 149 | 173 | ||
| 150 | void AOC_U::PrepareAddOnContent(Kernel::HLERequestContext& ctx) { | 174 | void AOC_U::PrepareAddOnContent(Kernel::HLERequestContext& ctx) { |
| 175 | struct Parameters { | ||
| 176 | s32 addon_index; | ||
| 177 | u64 process_id; | ||
| 178 | }; | ||
| 179 | static_assert(sizeof(Parameters) == 16); | ||
| 180 | |||
| 151 | IPC::RequestParser rp{ctx}; | 181 | IPC::RequestParser rp{ctx}; |
| 182 | const auto [addon_index, process_id] = rp.PopRaw<Parameters>(); | ||
| 152 | 183 | ||
| 153 | const auto aoc_id = rp.PopRaw<u32>(); | 184 | LOG_WARNING(Service_AOC, "(STUBBED) called with addon_index={}, process_id={}", addon_index, |
| 154 | LOG_WARNING(Service_AOC, "(STUBBED) called with aoc_id={:08X}", aoc_id); | 185 | process_id); |
| 155 | 186 | ||
| 156 | IPC::ResponseBuilder rb{ctx, 2}; | 187 | IPC::ResponseBuilder rb{ctx, 2}; |
| 157 | rb.Push(RESULT_SUCCESS); | 188 | rb.Push(RESULT_SUCCESS); |
diff --git a/src/video_core/renderer_opengl/gl_device.cpp b/src/video_core/renderer_opengl/gl_device.cpp index 38497678a..1d1581f49 100644 --- a/src/video_core/renderer_opengl/gl_device.cpp +++ b/src/video_core/renderer_opengl/gl_device.cpp | |||
| @@ -35,6 +35,7 @@ Device::Device(std::nullptr_t) { | |||
| 35 | 35 | ||
| 36 | bool Device::TestVariableAoffi() { | 36 | bool Device::TestVariableAoffi() { |
| 37 | const GLchar* AOFFI_TEST = R"(#version 430 core | 37 | const GLchar* AOFFI_TEST = R"(#version 430 core |
| 38 | // This is a unit test, please ignore me on apitrace bug reports. | ||
| 38 | uniform sampler2D tex; | 39 | uniform sampler2D tex; |
| 39 | uniform ivec2 variable_offset; | 40 | uniform ivec2 variable_offset; |
| 40 | void main() { | 41 | void main() { |
diff --git a/src/video_core/renderer_opengl/gl_shader_cache.cpp b/src/video_core/renderer_opengl/gl_shader_cache.cpp index 7ee1c99c0..d66252224 100644 --- a/src/video_core/renderer_opengl/gl_shader_cache.cpp +++ b/src/video_core/renderer_opengl/gl_shader_cache.cpp | |||
| @@ -170,7 +170,8 @@ GLShader::ProgramResult CreateProgram(const Device& device, Maxwell::ShaderProgr | |||
| 170 | CachedProgram SpecializeShader(const std::string& code, const GLShader::ShaderEntries& entries, | 170 | CachedProgram SpecializeShader(const std::string& code, const GLShader::ShaderEntries& entries, |
| 171 | Maxwell::ShaderProgram program_type, BaseBindings base_bindings, | 171 | Maxwell::ShaderProgram program_type, BaseBindings base_bindings, |
| 172 | GLenum primitive_mode, bool hint_retrievable = false) { | 172 | GLenum primitive_mode, bool hint_retrievable = false) { |
| 173 | std::string source = "#version 430 core\n"; | 173 | std::string source = "#version 430 core\n" |
| 174 | "#extension GL_ARB_separate_shader_objects : enable\n\n"; | ||
| 174 | source += fmt::format("#define EMULATION_UBO_BINDING {}\n", base_bindings.cbuf++); | 175 | source += fmt::format("#define EMULATION_UBO_BINDING {}\n", base_bindings.cbuf++); |
| 175 | 176 | ||
| 176 | for (const auto& cbuf : entries.const_buffers) { | 177 | for (const auto& cbuf : entries.const_buffers) { |
diff --git a/src/video_core/renderer_opengl/gl_shader_gen.cpp b/src/video_core/renderer_opengl/gl_shader_gen.cpp index 7ab0b4553..d2bb705a9 100644 --- a/src/video_core/renderer_opengl/gl_shader_gen.cpp +++ b/src/video_core/renderer_opengl/gl_shader_gen.cpp | |||
| @@ -19,8 +19,7 @@ static constexpr u32 PROGRAM_OFFSET{10}; | |||
| 19 | ProgramResult GenerateVertexShader(const Device& device, const ShaderSetup& setup) { | 19 | ProgramResult GenerateVertexShader(const Device& device, const ShaderSetup& setup) { |
| 20 | const std::string id = fmt::format("{:016x}", setup.program.unique_identifier); | 20 | const std::string id = fmt::format("{:016x}", setup.program.unique_identifier); |
| 21 | 21 | ||
| 22 | std::string out = "#extension GL_ARB_separate_shader_objects : enable\n\n"; | 22 | std::string out = "// Shader Unique Id: VS" + id + "\n\n"; |
| 23 | out += "// Shader Unique Id: VS" + id + "\n\n"; | ||
| 24 | out += GetCommonDeclarations(); | 23 | out += GetCommonDeclarations(); |
| 25 | 24 | ||
| 26 | out += R"( | 25 | out += R"( |
| @@ -82,8 +81,7 @@ void main() { | |||
| 82 | ProgramResult GenerateGeometryShader(const Device& device, const ShaderSetup& setup) { | 81 | ProgramResult GenerateGeometryShader(const Device& device, const ShaderSetup& setup) { |
| 83 | const std::string id = fmt::format("{:016x}", setup.program.unique_identifier); | 82 | const std::string id = fmt::format("{:016x}", setup.program.unique_identifier); |
| 84 | 83 | ||
| 85 | std::string out = "#extension GL_ARB_separate_shader_objects : enable\n\n"; | 84 | std::string out = "// Shader Unique Id: GS" + id + "\n\n"; |
| 86 | out += "// Shader Unique Id: GS" + id + "\n\n"; | ||
| 87 | out += GetCommonDeclarations(); | 85 | out += GetCommonDeclarations(); |
| 88 | 86 | ||
| 89 | out += R"( | 87 | out += R"( |
| @@ -113,8 +111,7 @@ void main() { | |||
| 113 | ProgramResult GenerateFragmentShader(const Device& device, const ShaderSetup& setup) { | 111 | ProgramResult GenerateFragmentShader(const Device& device, const ShaderSetup& setup) { |
| 114 | const std::string id = fmt::format("{:016x}", setup.program.unique_identifier); | 112 | const std::string id = fmt::format("{:016x}", setup.program.unique_identifier); |
| 115 | 113 | ||
| 116 | std::string out = "#extension GL_ARB_separate_shader_objects : enable\n\n"; | 114 | std::string out = "// Shader Unique Id: FS" + id + "\n\n"; |
| 117 | out += "// Shader Unique Id: FS" + id + "\n\n"; | ||
| 118 | out += GetCommonDeclarations(); | 115 | out += GetCommonDeclarations(); |
| 119 | 116 | ||
| 120 | out += R"( | 117 | out += R"( |
diff --git a/src/video_core/renderer_opengl/utils.cpp b/src/video_core/renderer_opengl/utils.cpp index 84a987371..f23fc9f9d 100644 --- a/src/video_core/renderer_opengl/utils.cpp +++ b/src/video_core/renderer_opengl/utils.cpp | |||
| @@ -38,27 +38,27 @@ void BindBuffersRangePushBuffer::Bind() const { | |||
| 38 | sizes.data()); | 38 | sizes.data()); |
| 39 | } | 39 | } |
| 40 | 40 | ||
| 41 | void LabelGLObject(GLenum identifier, GLuint handle, VAddr addr, std::string extra_info) { | 41 | void LabelGLObject(GLenum identifier, GLuint handle, VAddr addr, std::string_view extra_info) { |
| 42 | if (!GLAD_GL_KHR_debug) { | 42 | if (!GLAD_GL_KHR_debug) { |
| 43 | return; // We don't need to throw an error as this is just for debugging | 43 | // We don't need to throw an error as this is just for debugging |
| 44 | return; | ||
| 44 | } | 45 | } |
| 45 | const std::string nice_addr = fmt::format("0x{:016x}", addr); | ||
| 46 | std::string object_label; | ||
| 47 | 46 | ||
| 47 | std::string object_label; | ||
| 48 | if (extra_info.empty()) { | 48 | if (extra_info.empty()) { |
| 49 | switch (identifier) { | 49 | switch (identifier) { |
| 50 | case GL_TEXTURE: | 50 | case GL_TEXTURE: |
| 51 | object_label = "Texture@" + nice_addr; | 51 | object_label = fmt::format("Texture@0x{:016X}", addr); |
| 52 | break; | 52 | break; |
| 53 | case GL_PROGRAM: | 53 | case GL_PROGRAM: |
| 54 | object_label = "Shader@" + nice_addr; | 54 | object_label = fmt::format("Shader@0x{:016X}", addr); |
| 55 | break; | 55 | break; |
| 56 | default: | 56 | default: |
| 57 | object_label = fmt::format("Object(0x{:x})@{}", identifier, nice_addr); | 57 | object_label = fmt::format("Object(0x{:X})@0x{:016X}", identifier, addr); |
| 58 | break; | 58 | break; |
| 59 | } | 59 | } |
| 60 | } else { | 60 | } else { |
| 61 | object_label = extra_info + '@' + nice_addr; | 61 | object_label = fmt::format("{}@0x{:016X}", extra_info, addr); |
| 62 | } | 62 | } |
| 63 | glObjectLabel(identifier, handle, -1, static_cast<const GLchar*>(object_label.c_str())); | 63 | glObjectLabel(identifier, handle, -1, static_cast<const GLchar*>(object_label.c_str())); |
| 64 | } | 64 | } |
diff --git a/src/video_core/renderer_opengl/utils.h b/src/video_core/renderer_opengl/utils.h index aef45c9dc..b3e9fc499 100644 --- a/src/video_core/renderer_opengl/utils.h +++ b/src/video_core/renderer_opengl/utils.h | |||
| @@ -4,7 +4,7 @@ | |||
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <string> | 7 | #include <string_view> |
| 8 | #include <vector> | 8 | #include <vector> |
| 9 | #include <glad/glad.h> | 9 | #include <glad/glad.h> |
| 10 | #include "common/common_types.h" | 10 | #include "common/common_types.h" |
| @@ -30,6 +30,6 @@ private: | |||
| 30 | std::vector<GLsizeiptr> sizes; | 30 | std::vector<GLsizeiptr> sizes; |
| 31 | }; | 31 | }; |
| 32 | 32 | ||
| 33 | void LabelGLObject(GLenum identifier, GLuint handle, VAddr addr, std::string extra_info = ""); | 33 | void LabelGLObject(GLenum identifier, GLuint handle, VAddr addr, std::string_view extra_info = {}); |
| 34 | 34 | ||
| 35 | } // namespace OpenGL \ No newline at end of file | 35 | } // namespace OpenGL \ No newline at end of file |
diff --git a/src/yuzu/configuration/configure_dialog.cpp b/src/yuzu/configuration/configure_dialog.cpp index 32c05b797..8086f9d6b 100644 --- a/src/yuzu/configuration/configure_dialog.cpp +++ b/src/yuzu/configuration/configure_dialog.cpp | |||
| @@ -25,9 +25,6 @@ ConfigureDialog::ConfigureDialog(QWidget* parent, HotkeyRegistry& registry) | |||
| 25 | 25 | ||
| 26 | adjustSize(); | 26 | adjustSize(); |
| 27 | ui->selectorList->setCurrentRow(0); | 27 | ui->selectorList->setCurrentRow(0); |
| 28 | |||
| 29 | // Synchronise lists upon initialisation | ||
| 30 | ui->hotkeysTab->EmitHotkeysChanged(); | ||
| 31 | } | 28 | } |
| 32 | 29 | ||
| 33 | ConfigureDialog::~ConfigureDialog() = default; | 30 | ConfigureDialog::~ConfigureDialog() = default; |
diff --git a/src/yuzu/configuration/configure_hotkeys.cpp b/src/yuzu/configuration/configure_hotkeys.cpp index a7a8752e5..9fb970c21 100644 --- a/src/yuzu/configuration/configure_hotkeys.cpp +++ b/src/yuzu/configuration/configure_hotkeys.cpp | |||
| @@ -31,22 +31,6 @@ ConfigureHotkeys::ConfigureHotkeys(QWidget* parent) | |||
| 31 | 31 | ||
| 32 | ConfigureHotkeys::~ConfigureHotkeys() = default; | 32 | ConfigureHotkeys::~ConfigureHotkeys() = default; |
| 33 | 33 | ||
| 34 | void ConfigureHotkeys::EmitHotkeysChanged() { | ||
| 35 | emit HotkeysChanged(GetUsedKeyList()); | ||
| 36 | } | ||
| 37 | |||
| 38 | QList<QKeySequence> ConfigureHotkeys::GetUsedKeyList() const { | ||
| 39 | QList<QKeySequence> list; | ||
| 40 | for (int r = 0; r < model->rowCount(); r++) { | ||
| 41 | const QStandardItem* parent = model->item(r, 0); | ||
| 42 | for (int r2 = 0; r2 < parent->rowCount(); r2++) { | ||
| 43 | const QStandardItem* keyseq = parent->child(r2, 1); | ||
| 44 | list << QKeySequence::fromString(keyseq->text(), QKeySequence::NativeText); | ||
| 45 | } | ||
| 46 | } | ||
| 47 | return list; | ||
| 48 | } | ||
| 49 | |||
| 50 | void ConfigureHotkeys::Populate(const HotkeyRegistry& registry) { | 34 | void ConfigureHotkeys::Populate(const HotkeyRegistry& registry) { |
| 51 | for (const auto& group : registry.hotkey_groups) { | 35 | for (const auto& group : registry.hotkey_groups) { |
| 52 | auto* parent_item = new QStandardItem(group.first); | 36 | auto* parent_item = new QStandardItem(group.first); |
| @@ -83,16 +67,29 @@ void ConfigureHotkeys::Configure(QModelIndex index) { | |||
| 83 | } | 67 | } |
| 84 | 68 | ||
| 85 | if (IsUsedKey(key_sequence) && key_sequence != QKeySequence(previous_key.toString())) { | 69 | if (IsUsedKey(key_sequence) && key_sequence != QKeySequence(previous_key.toString())) { |
| 86 | QMessageBox::critical(this, tr("Error in inputted key"), | 70 | QMessageBox::warning(this, tr("Conflicting Key Sequence"), |
| 87 | tr("You're using a key that's already bound.")); | 71 | tr("The entered key sequence is already assigned to another hotkey.")); |
| 88 | } else { | 72 | } else { |
| 89 | model->setData(index, key_sequence.toString(QKeySequence::NativeText)); | 73 | model->setData(index, key_sequence.toString(QKeySequence::NativeText)); |
| 90 | EmitHotkeysChanged(); | ||
| 91 | } | 74 | } |
| 92 | } | 75 | } |
| 93 | 76 | ||
| 94 | bool ConfigureHotkeys::IsUsedKey(QKeySequence key_sequence) const { | 77 | bool ConfigureHotkeys::IsUsedKey(QKeySequence key_sequence) const { |
| 95 | return GetUsedKeyList().contains(key_sequence); | 78 | for (int r = 0; r < model->rowCount(); r++) { |
| 79 | const QStandardItem* const parent = model->item(r, 0); | ||
| 80 | |||
| 81 | for (int r2 = 0; r2 < parent->rowCount(); r2++) { | ||
| 82 | const QStandardItem* const key_seq_item = parent->child(r2, 1); | ||
| 83 | const auto key_seq_str = key_seq_item->text(); | ||
| 84 | const auto key_seq = QKeySequence::fromString(key_seq_str, QKeySequence::NativeText); | ||
| 85 | |||
| 86 | if (key_sequence == key_seq) { | ||
| 87 | return true; | ||
| 88 | } | ||
| 89 | } | ||
| 90 | } | ||
| 91 | |||
| 92 | return false; | ||
| 96 | } | 93 | } |
| 97 | 94 | ||
| 98 | void ConfigureHotkeys::applyConfiguration(HotkeyRegistry& registry) { | 95 | void ConfigureHotkeys::applyConfiguration(HotkeyRegistry& registry) { |
| @@ -114,7 +111,6 @@ void ConfigureHotkeys::applyConfiguration(HotkeyRegistry& registry) { | |||
| 114 | } | 111 | } |
| 115 | 112 | ||
| 116 | registry.SaveHotkeys(); | 113 | registry.SaveHotkeys(); |
| 117 | Settings::Apply(); | ||
| 118 | } | 114 | } |
| 119 | 115 | ||
| 120 | void ConfigureHotkeys::retranslateUi() { | 116 | void ConfigureHotkeys::retranslateUi() { |
diff --git a/src/yuzu/configuration/configure_hotkeys.h b/src/yuzu/configuration/configure_hotkeys.h index 73fb8a175..e77d73c35 100644 --- a/src/yuzu/configuration/configure_hotkeys.h +++ b/src/yuzu/configuration/configure_hotkeys.h | |||
| @@ -24,8 +24,6 @@ public: | |||
| 24 | void applyConfiguration(HotkeyRegistry& registry); | 24 | void applyConfiguration(HotkeyRegistry& registry); |
| 25 | void retranslateUi(); | 25 | void retranslateUi(); |
| 26 | 26 | ||
| 27 | void EmitHotkeysChanged(); | ||
| 28 | |||
| 29 | /** | 27 | /** |
| 30 | * Populates the hotkey list widget using data from the provided registry. | 28 | * Populates the hotkey list widget using data from the provided registry. |
| 31 | * Called everytime the Configure dialog is opened. | 29 | * Called everytime the Configure dialog is opened. |
| @@ -33,13 +31,9 @@ public: | |||
| 33 | */ | 31 | */ |
| 34 | void Populate(const HotkeyRegistry& registry); | 32 | void Populate(const HotkeyRegistry& registry); |
| 35 | 33 | ||
| 36 | signals: | ||
| 37 | void HotkeysChanged(QList<QKeySequence> new_key_list); | ||
| 38 | |||
| 39 | private: | 34 | private: |
| 40 | void Configure(QModelIndex index); | 35 | void Configure(QModelIndex index); |
| 41 | bool IsUsedKey(QKeySequence key_sequence) const; | 36 | bool IsUsedKey(QKeySequence key_sequence) const; |
| 42 | QList<QKeySequence> GetUsedKeyList() const; | ||
| 43 | 37 | ||
| 44 | std::unique_ptr<Ui::ConfigureHotkeys> ui; | 38 | std::unique_ptr<Ui::ConfigureHotkeys> ui; |
| 45 | 39 | ||
diff --git a/src/yuzu/util/sequence_dialog/sequence_dialog.cpp b/src/yuzu/util/sequence_dialog/sequence_dialog.cpp index d3edf6ec3..bb5f74ec4 100644 --- a/src/yuzu/util/sequence_dialog/sequence_dialog.cpp +++ b/src/yuzu/util/sequence_dialog/sequence_dialog.cpp | |||
| @@ -9,16 +9,19 @@ | |||
| 9 | 9 | ||
| 10 | SequenceDialog::SequenceDialog(QWidget* parent) : QDialog(parent) { | 10 | SequenceDialog::SequenceDialog(QWidget* parent) : QDialog(parent) { |
| 11 | setWindowTitle(tr("Enter a hotkey")); | 11 | setWindowTitle(tr("Enter a hotkey")); |
| 12 | auto* layout = new QVBoxLayout(this); | 12 | setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); |
| 13 | |||
| 13 | key_sequence = new QKeySequenceEdit; | 14 | key_sequence = new QKeySequenceEdit; |
| 14 | layout->addWidget(key_sequence); | 15 | |
| 15 | auto* buttons = | 16 | auto* const buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); |
| 16 | new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal); | ||
| 17 | buttons->setCenterButtons(true); | 17 | buttons->setCenterButtons(true); |
| 18 | |||
| 19 | auto* const layout = new QVBoxLayout(this); | ||
| 20 | layout->addWidget(key_sequence); | ||
| 18 | layout->addWidget(buttons); | 21 | layout->addWidget(buttons); |
| 22 | |||
| 19 | connect(buttons, &QDialogButtonBox::accepted, this, &QDialog::accept); | 23 | connect(buttons, &QDialogButtonBox::accepted, this, &QDialog::accept); |
| 20 | connect(buttons, &QDialogButtonBox::rejected, this, &QDialog::reject); | 24 | connect(buttons, &QDialogButtonBox::rejected, this, &QDialog::reject); |
| 21 | setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); | ||
| 22 | } | 25 | } |
| 23 | 26 | ||
| 24 | SequenceDialog::~SequenceDialog() = default; | 27 | SequenceDialog::~SequenceDialog() = default; |
diff --git a/src/yuzu_cmd/config.cpp b/src/yuzu_cmd/config.cpp index d0ae058fd..730956427 100644 --- a/src/yuzu_cmd/config.cpp +++ b/src/yuzu_cmd/config.cpp | |||
| @@ -26,12 +26,12 @@ Config::Config() { | |||
| 26 | Config::~Config() = default; | 26 | Config::~Config() = default; |
| 27 | 27 | ||
| 28 | bool Config::LoadINI(const std::string& default_contents, bool retry) { | 28 | bool Config::LoadINI(const std::string& default_contents, bool retry) { |
| 29 | const char* location = this->sdl2_config_loc.c_str(); | 29 | const std::string& location = this->sdl2_config_loc; |
| 30 | if (sdl2_config->ParseError() < 0) { | 30 | if (sdl2_config->ParseError() < 0) { |
| 31 | if (retry) { | 31 | if (retry) { |
| 32 | LOG_WARNING(Config, "Failed to load {}. Creating file from defaults...", location); | 32 | LOG_WARNING(Config, "Failed to load {}. Creating file from defaults...", location); |
| 33 | FileUtil::CreateFullPath(location); | 33 | FileUtil::CreateFullPath(location); |
| 34 | FileUtil::WriteStringToFile(true, default_contents, location); | 34 | FileUtil::WriteStringToFile(true, location, default_contents); |
| 35 | sdl2_config = std::make_unique<INIReader>(location); // Reopen file | 35 | sdl2_config = std::make_unique<INIReader>(location); // Reopen file |
| 36 | 36 | ||
| 37 | return LoadINI(default_contents, false); | 37 | return LoadINI(default_contents, false); |