summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/common/file_util.cpp49
-rw-r--r--src/common/file_util.h15
-rw-r--r--src/core/hle/service/aoc/aoc_u.cpp69
-rw-r--r--src/video_core/renderer_opengl/gl_device.cpp1
-rw-r--r--src/video_core/renderer_opengl/gl_shader_cache.cpp3
-rw-r--r--src/video_core/renderer_opengl/gl_shader_gen.cpp9
-rw-r--r--src/video_core/renderer_opengl/utils.cpp16
-rw-r--r--src/video_core/renderer_opengl/utils.h4
-rw-r--r--src/yuzu/configuration/configure_dialog.cpp3
-rw-r--r--src/yuzu/configuration/configure_hotkeys.cpp38
-rw-r--r--src/yuzu/configuration/configure_hotkeys.h6
-rw-r--r--src/yuzu/util/sequence_dialog/sequence_dialog.cpp13
-rw-r--r--src/yuzu_cmd/config.cpp4
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.
80static void StripTailDirSlashes(std::string& fname) { 80static 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
91bool Exists(const std::string& filename) { 92bool 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
111bool IsDirectory(const std::string& filename) { 111bool 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
137bool Delete(const std::string& filename) { 135bool 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.
169bool CreateDir(const std::string& path) { 166bool 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
198bool CreateFullPath(const std::string& fullPath) { 194bool 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
234bool DeleteDir(const std::string& filename) { 229bool 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
256bool Rename(const std::string& srcFilename, const std::string& destFilename) { 250bool 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
272bool Copy(const std::string& srcFilename, const std::string& destFilename) { 265bool 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)
328u64 GetSize(const std::string& filename) { 320u64 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
355u64 GetSize(const int fd) { 346u64 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*
365u64 GetSize(FILE* f) { 355u64 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
381bool CreateEmptyFile(const std::string& filename) { 370bool 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)
506void CopyDir(const std::string& source_path, const std::string& dest_path) { 494void 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 530std::optional<std::string> GetCurrentDir() {
543std::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
565bool SetCurrentDir(const std::string& directory) { 551bool 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).
678const std::string& GetUserPath(UserPath path, const std::string& new_path) { 662const 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
765std::size_t WriteStringToFile(bool text_file, const std::string& str, const char* filename) { 749std::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
769std::size_t ReadFileToString(bool text_file, const char* filename, std::string& str) { 753std::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 */
786void SplitFilename83(const std::string& filename, std::array<char, 9>& short_name, 763void 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,
118bool DeleteDirRecursively(const std::string& directory, unsigned int recursion = 256); 119bool DeleteDirRecursively(const std::string& directory, unsigned int recursion = 256);
119 120
120// Returns the current directory 121// Returns the current directory
121std::string GetCurrentDir(); 122std::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)
124void CopyDir(const std::string& source_path, const std::string& dest_path); 125void CopyDir(const std::string& source_path, const std::string& dest_path);
@@ -146,9 +147,9 @@ const std::string& GetExeDirectory();
146std::string AppDataRoamingDirectory(); 147std::string AppDataRoamingDirectory();
147#endif 148#endif
148 149
149std::size_t WriteStringToFile(bool text_file, const std::string& str, const char* filename); 150std::size_t WriteStringToFile(bool text_file, const std::string& filename, std::string_view str);
150 151
151std::size_t ReadFileToString(bool text_file, const char* filename, std::string& str); 152std::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:
286template <typename T> 287template <typename T>
287void OpenFStream(T& fstream, const std::string& filename, std::ios_base::openmode openmode) { 288void 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
75AOC_U::~AOC_U() = default; 73AOC_U::~AOC_U() = default;
76 74
77void AOC_U::CountAddOnContent(Kernel::HLERequestContext& ctx) { 75void 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
96void AOC_U::ListAddOnContent(Kernel::HLERequestContext& ctx) { 102void 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
133void AOC_U::GetAddOnContentBaseId(Kernel::HLERequestContext& ctx) { 148void 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
150void AOC_U::PrepareAddOnContent(Kernel::HLERequestContext& ctx) { 174void 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
36bool Device::TestVariableAoffi() { 36bool 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.
38uniform sampler2D tex; 39uniform sampler2D tex;
39uniform ivec2 variable_offset; 40uniform ivec2 variable_offset;
40void main() { 41void 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
170CachedProgram SpecializeShader(const std::string& code, const GLShader::ShaderEntries& entries, 170CachedProgram 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};
19ProgramResult GenerateVertexShader(const Device& device, const ShaderSetup& setup) { 19ProgramResult 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() {
82ProgramResult GenerateGeometryShader(const Device& device, const ShaderSetup& setup) { 81ProgramResult 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() {
113ProgramResult GenerateFragmentShader(const Device& device, const ShaderSetup& setup) { 111ProgramResult 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
41void LabelGLObject(GLenum identifier, GLuint handle, VAddr addr, std::string extra_info) { 41void 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
33void LabelGLObject(GLenum identifier, GLuint handle, VAddr addr, std::string extra_info = ""); 33void 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
33ConfigureDialog::~ConfigureDialog() = default; 30ConfigureDialog::~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
32ConfigureHotkeys::~ConfigureHotkeys() = default; 32ConfigureHotkeys::~ConfigureHotkeys() = default;
33 33
34void ConfigureHotkeys::EmitHotkeysChanged() {
35 emit HotkeysChanged(GetUsedKeyList());
36}
37
38QList<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
50void ConfigureHotkeys::Populate(const HotkeyRegistry& registry) { 34void 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
94bool ConfigureHotkeys::IsUsedKey(QKeySequence key_sequence) const { 77bool 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
98void ConfigureHotkeys::applyConfiguration(HotkeyRegistry& registry) { 95void 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
120void ConfigureHotkeys::retranslateUi() { 116void 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
36signals:
37 void HotkeysChanged(QList<QKeySequence> new_key_list);
38
39private: 34private:
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
10SequenceDialog::SequenceDialog(QWidget* parent) : QDialog(parent) { 10SequenceDialog::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
24SequenceDialog::~SequenceDialog() = default; 27SequenceDialog::~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() {
26Config::~Config() = default; 26Config::~Config() = default;
27 27
28bool Config::LoadINI(const std::string& default_contents, bool retry) { 28bool 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);