summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/common/file_util.h12
-rw-r--r--src/common/vector_math.h362
-rw-r--r--src/core/CMakeLists.txt2
-rw-r--r--src/core/file_sys/card_image.cpp1
-rw-r--r--src/core/file_sys/content_archive.cpp4
-rw-r--r--src/core/file_sys/content_archive.h1
-rw-r--r--src/core/file_sys/control_metadata.h7
-rw-r--r--src/core/hle/romfs.cpp102
-rw-r--r--src/core/hle/romfs.h22
-rw-r--r--src/core/hle/service/acc/acc.cpp7
-rw-r--r--src/core/hle/service/acc/acc.h1
-rw-r--r--src/core/hle/service/acc/acc_su.cpp2
-rw-r--r--src/core/hle/service/acc/acc_u0.cpp2
-rw-r--r--src/core/hle/service/acc/acc_u1.cpp2
-rw-r--r--src/core/hle/service/hid/hid.cpp2
-rw-r--r--src/core/hle/service/nvdrv/nvdrv.cpp7
-rw-r--r--src/core/hle/service/nvdrv/nvdrv.h8
-rw-r--r--src/core/hle/service/nvflinger/nvflinger.cpp7
-rw-r--r--src/core/hle/service/nvflinger/nvflinger.h9
-rw-r--r--src/core/hle/service/service.cpp2
-rw-r--r--src/core/loader/deconstructed_rom_directory.cpp68
-rw-r--r--src/core/loader/deconstructed_rom_directory.h7
-rw-r--r--src/core/loader/loader.cpp2
-rw-r--r--src/core/loader/loader.h2
-rw-r--r--src/core/loader/nca.cpp4
-rw-r--r--src/core/loader/nca.h2
-rw-r--r--src/core/loader/xci.cpp33
-rw-r--r--src/core/loader/xci.h5
-rw-r--r--src/tests/common/param_package.cpp2
-rw-r--r--src/tests/core/core_timing.cpp2
-rw-r--r--src/tests/glad.cpp2
-rw-r--r--src/tests/tests.cpp2
-rw-r--r--src/yuzu/CMakeLists.txt3
-rw-r--r--src/yuzu/configuration/config.cpp14
-rw-r--r--src/yuzu/configuration/configure.ui11
-rw-r--r--src/yuzu/configuration/configure_dialog.cpp1
-rw-r--r--src/yuzu/configuration/configure_gamelist.cpp63
-rw-r--r--src/yuzu/configuration/configure_gamelist.h28
-rw-r--r--src/yuzu/configuration/configure_gamelist.ui126
-rw-r--r--src/yuzu/game_list.cpp78
-rw-r--r--src/yuzu/game_list_p.h38
-rw-r--r--src/yuzu/main.cpp1
-rw-r--r--src/yuzu/ui_settings.h6
43 files changed, 712 insertions, 350 deletions
diff --git a/src/common/file_util.h b/src/common/file_util.h
index 7f2a5cb63..d0987fb57 100644
--- a/src/common/file_util.h
+++ b/src/common/file_util.h
@@ -8,6 +8,7 @@
8#include <cstdio> 8#include <cstdio>
9#include <fstream> 9#include <fstream>
10#include <functional> 10#include <functional>
11#include <limits>
11#include <string> 12#include <string>
12#include <string_view> 13#include <string_view>
13#include <type_traits> 14#include <type_traits>
@@ -210,8 +211,9 @@ public:
210 static_assert(std::is_trivially_copyable_v<T>, 211 static_assert(std::is_trivially_copyable_v<T>,
211 "Given array does not consist of trivially copyable objects"); 212 "Given array does not consist of trivially copyable objects");
212 213
213 if (!IsOpen()) 214 if (!IsOpen()) {
214 return -1; 215 return std::numeric_limits<size_t>::max();
216 }
215 217
216 return std::fread(data, sizeof(T), length, m_file); 218 return std::fread(data, sizeof(T), length, m_file);
217 } 219 }
@@ -220,8 +222,10 @@ public:
220 size_t WriteArray(const T* data, size_t length) { 222 size_t WriteArray(const T* data, size_t length) {
221 static_assert(std::is_trivially_copyable_v<T>, 223 static_assert(std::is_trivially_copyable_v<T>,
222 "Given array does not consist of trivially copyable objects"); 224 "Given array does not consist of trivially copyable objects");
223 if (!IsOpen()) 225 if (!IsOpen()) {
224 return -1; 226 return std::numeric_limits<size_t>::max();
227 }
228
225 return std::fwrite(data, sizeof(T), length, m_file); 229 return std::fwrite(data, sizeof(T), length, m_file);
226 } 230 }
227 231
diff --git a/src/common/vector_math.h b/src/common/vector_math.h
index cca43bd4c..5c94fcda3 100644
--- a/src/common/vector_math.h
+++ b/src/common/vector_math.h
@@ -43,139 +43,135 @@ template <typename T>
43class Vec4; 43class Vec4;
44 44
45template <typename T> 45template <typename T>
46static inline Vec2<T> MakeVec(const T& x, const T& y);
47template <typename T>
48static inline Vec3<T> MakeVec(const T& x, const T& y, const T& z);
49template <typename T>
50static inline Vec4<T> MakeVec(const T& x, const T& y, const T& z, const T& w);
51
52template <typename T>
53class Vec2 { 46class Vec2 {
54public: 47public:
55 T x{}; 48 T x{};
56 T y{}; 49 T y{};
57 50
58 Vec2() = default; 51 constexpr Vec2() = default;
59 Vec2(const T& _x, const T& _y) : x(_x), y(_y) {} 52 constexpr Vec2(const T& x_, const T& y_) : x(x_), y(y_) {}
60 53
61 template <typename T2> 54 template <typename T2>
62 Vec2<T2> Cast() const { 55 constexpr Vec2<T2> Cast() const {
63 return Vec2<T2>((T2)x, (T2)y); 56 return Vec2<T2>(static_cast<T2>(x), static_cast<T2>(y));
64 } 57 }
65 58
66 static Vec2 AssignToAll(const T& f) { 59 static constexpr Vec2 AssignToAll(const T& f) {
67 return Vec2<T>(f, f); 60 return Vec2{f, f};
68 } 61 }
69 62
70 Vec2<decltype(T{} + T{})> operator+(const Vec2& other) const { 63 constexpr Vec2<decltype(T{} + T{})> operator+(const Vec2& other) const {
71 return MakeVec(x + other.x, y + other.y); 64 return {x + other.x, y + other.y};
72 } 65 }
73 void operator+=(const Vec2& other) { 66 constexpr Vec2& operator+=(const Vec2& other) {
74 x += other.x; 67 x += other.x;
75 y += other.y; 68 y += other.y;
69 return *this;
76 } 70 }
77 Vec2<decltype(T{} - T{})> operator-(const Vec2& other) const { 71 constexpr Vec2<decltype(T{} - T{})> operator-(const Vec2& other) const {
78 return MakeVec(x - other.x, y - other.y); 72 return {x - other.x, y - other.y};
79 } 73 }
80 void operator-=(const Vec2& other) { 74 constexpr Vec2& operator-=(const Vec2& other) {
81 x -= other.x; 75 x -= other.x;
82 y -= other.y; 76 y -= other.y;
77 return *this;
83 } 78 }
84 79
85 template <typename U = T> 80 template <typename U = T>
86 Vec2<std::enable_if_t<std::is_signed<U>::value, U>> operator-() const { 81 constexpr Vec2<std::enable_if_t<std::is_signed<U>::value, U>> operator-() const {
87 return MakeVec(-x, -y); 82 return {-x, -y};
88 } 83 }
89 Vec2<decltype(T{} * T{})> operator*(const Vec2& other) const { 84 constexpr Vec2<decltype(T{} * T{})> operator*(const Vec2& other) const {
90 return MakeVec(x * other.x, y * other.y); 85 return {x * other.x, y * other.y};
91 } 86 }
87
92 template <typename V> 88 template <typename V>
93 Vec2<decltype(T{} * V{})> operator*(const V& f) const { 89 constexpr Vec2<decltype(T{} * V{})> operator*(const V& f) const {
94 return MakeVec(x * f, y * f); 90 return {x * f, y * f};
95 } 91 }
92
96 template <typename V> 93 template <typename V>
97 void operator*=(const V& f) { 94 constexpr Vec2& operator*=(const V& f) {
98 *this = *this * f; 95 *this = *this * f;
96 return *this;
99 } 97 }
98
100 template <typename V> 99 template <typename V>
101 Vec2<decltype(T{} / V{})> operator/(const V& f) const { 100 constexpr Vec2<decltype(T{} / V{})> operator/(const V& f) const {
102 return MakeVec(x / f, y / f); 101 return {x / f, y / f};
103 } 102 }
103
104 template <typename V> 104 template <typename V>
105 void operator/=(const V& f) { 105 constexpr Vec2& operator/=(const V& f) {
106 *this = *this / f; 106 *this = *this / f;
107 return *this;
107 } 108 }
108 109
109 T Length2() const { 110 constexpr T Length2() const {
110 return x * x + y * y; 111 return x * x + y * y;
111 } 112 }
112 113
113 // Only implemented for T=float 114 // Only implemented for T=float
114 float Length() const; 115 float Length() const;
115 void SetLength(const float l);
116 Vec2 WithLength(const float l) const;
117 float Distance2To(Vec2& other);
118 Vec2 Normalized() const;
119 float Normalize(); // returns the previous length, which is often useful 116 float Normalize(); // returns the previous length, which is often useful
120 117
121 T& operator[](int i) // allow vector[1] = 3 (vector.y=3) 118 constexpr T& operator[](std::size_t i) {
122 {
123 return *((&x) + i); 119 return *((&x) + i);
124 } 120 }
125 T operator[](const int i) const { 121 constexpr const T& operator[](std::size_t i) const {
126 return *((&x) + i); 122 return *((&x) + i);
127 } 123 }
128 124
129 void SetZero() { 125 constexpr void SetZero() {
130 x = 0; 126 x = 0;
131 y = 0; 127 y = 0;
132 } 128 }
133 129
134 // Common aliases: UV (texel coordinates), ST (texture coordinates) 130 // Common aliases: UV (texel coordinates), ST (texture coordinates)
135 T& u() { 131 constexpr T& u() {
136 return x; 132 return x;
137 } 133 }
138 T& v() { 134 constexpr T& v() {
139 return y; 135 return y;
140 } 136 }
141 T& s() { 137 constexpr T& s() {
142 return x; 138 return x;
143 } 139 }
144 T& t() { 140 constexpr T& t() {
145 return y; 141 return y;
146 } 142 }
147 143
148 const T& u() const { 144 constexpr const T& u() const {
149 return x; 145 return x;
150 } 146 }
151 const T& v() const { 147 constexpr const T& v() const {
152 return y; 148 return y;
153 } 149 }
154 const T& s() const { 150 constexpr const T& s() const {
155 return x; 151 return x;
156 } 152 }
157 const T& t() const { 153 constexpr const T& t() const {
158 return y; 154 return y;
159 } 155 }
160 156
161 // swizzlers - create a subvector of specific components 157 // swizzlers - create a subvector of specific components
162 const Vec2 yx() const { 158 constexpr Vec2 yx() const {
163 return Vec2(y, x); 159 return Vec2(y, x);
164 } 160 }
165 const Vec2 vu() const { 161 constexpr Vec2 vu() const {
166 return Vec2(y, x); 162 return Vec2(y, x);
167 } 163 }
168 const Vec2 ts() const { 164 constexpr Vec2 ts() const {
169 return Vec2(y, x); 165 return Vec2(y, x);
170 } 166 }
171}; 167};
172 168
173template <typename T, typename V> 169template <typename T, typename V>
174Vec2<T> operator*(const V& f, const Vec2<T>& vec) { 170constexpr Vec2<T> operator*(const V& f, const Vec2<T>& vec) {
175 return Vec2<T>(f * vec.x, f * vec.y); 171 return Vec2<T>(f * vec.x, f * vec.y);
176} 172}
177 173
178typedef Vec2<float> Vec2f; 174using Vec2f = Vec2<float>;
179 175
180template <> 176template <>
181inline float Vec2<float>::Length() const { 177inline float Vec2<float>::Length() const {
@@ -196,147 +192,151 @@ public:
196 T y{}; 192 T y{};
197 T z{}; 193 T z{};
198 194
199 Vec3() = default; 195 constexpr Vec3() = default;
200 Vec3(const T& _x, const T& _y, const T& _z) : x(_x), y(_y), z(_z) {} 196 constexpr Vec3(const T& x_, const T& y_, const T& z_) : x(x_), y(y_), z(z_) {}
201 197
202 template <typename T2> 198 template <typename T2>
203 Vec3<T2> Cast() const { 199 constexpr Vec3<T2> Cast() const {
204 return MakeVec<T2>((T2)x, (T2)y, (T2)z); 200 return Vec3<T2>(static_cast<T2>(x), static_cast<T2>(y), static_cast<T2>(z));
205 } 201 }
206 202
207 // Only implemented for T=int and T=float 203 static constexpr Vec3 AssignToAll(const T& f) {
208 static Vec3 FromRGB(unsigned int rgb); 204 return Vec3(f, f, f);
209 unsigned int ToRGB() const; // alpha bits set to zero
210
211 static Vec3 AssignToAll(const T& f) {
212 return MakeVec(f, f, f);
213 } 205 }
214 206
215 Vec3<decltype(T{} + T{})> operator+(const Vec3& other) const { 207 constexpr Vec3<decltype(T{} + T{})> operator+(const Vec3& other) const {
216 return MakeVec(x + other.x, y + other.y, z + other.z); 208 return {x + other.x, y + other.y, z + other.z};
217 } 209 }
218 void operator+=(const Vec3& other) { 210
211 constexpr Vec3& operator+=(const Vec3& other) {
219 x += other.x; 212 x += other.x;
220 y += other.y; 213 y += other.y;
221 z += other.z; 214 z += other.z;
215 return *this;
222 } 216 }
223 Vec3<decltype(T{} - T{})> operator-(const Vec3& other) const { 217
224 return MakeVec(x - other.x, y - other.y, z - other.z); 218 constexpr Vec3<decltype(T{} - T{})> operator-(const Vec3& other) const {
219 return {x - other.x, y - other.y, z - other.z};
225 } 220 }
226 void operator-=(const Vec3& other) { 221
222 constexpr Vec3& operator-=(const Vec3& other) {
227 x -= other.x; 223 x -= other.x;
228 y -= other.y; 224 y -= other.y;
229 z -= other.z; 225 z -= other.z;
226 return *this;
230 } 227 }
231 228
232 template <typename U = T> 229 template <typename U = T>
233 Vec3<std::enable_if_t<std::is_signed<U>::value, U>> operator-() const { 230 constexpr Vec3<std::enable_if_t<std::is_signed<U>::value, U>> operator-() const {
234 return MakeVec(-x, -y, -z); 231 return {-x, -y, -z};
235 } 232 }
236 Vec3<decltype(T{} * T{})> operator*(const Vec3& other) const { 233
237 return MakeVec(x * other.x, y * other.y, z * other.z); 234 constexpr Vec3<decltype(T{} * T{})> operator*(const Vec3& other) const {
235 return {x * other.x, y * other.y, z * other.z};
238 } 236 }
237
239 template <typename V> 238 template <typename V>
240 Vec3<decltype(T{} * V{})> operator*(const V& f) const { 239 constexpr Vec3<decltype(T{} * V{})> operator*(const V& f) const {
241 return MakeVec(x * f, y * f, z * f); 240 return {x * f, y * f, z * f};
242 } 241 }
242
243 template <typename V> 243 template <typename V>
244 void operator*=(const V& f) { 244 constexpr Vec3& operator*=(const V& f) {
245 *this = *this * f; 245 *this = *this * f;
246 return *this;
246 } 247 }
247 template <typename V> 248 template <typename V>
248 Vec3<decltype(T{} / V{})> operator/(const V& f) const { 249 constexpr Vec3<decltype(T{} / V{})> operator/(const V& f) const {
249 return MakeVec(x / f, y / f, z / f); 250 return {x / f, y / f, z / f};
250 } 251 }
252
251 template <typename V> 253 template <typename V>
252 void operator/=(const V& f) { 254 constexpr Vec3& operator/=(const V& f) {
253 *this = *this / f; 255 *this = *this / f;
256 return *this;
254 } 257 }
255 258
256 T Length2() const { 259 constexpr T Length2() const {
257 return x * x + y * y + z * z; 260 return x * x + y * y + z * z;
258 } 261 }
259 262
260 // Only implemented for T=float 263 // Only implemented for T=float
261 float Length() const; 264 float Length() const;
262 void SetLength(const float l);
263 Vec3 WithLength(const float l) const;
264 float Distance2To(Vec3& other);
265 Vec3 Normalized() const; 265 Vec3 Normalized() const;
266 float Normalize(); // returns the previous length, which is often useful 266 float Normalize(); // returns the previous length, which is often useful
267 267
268 T& operator[](int i) // allow vector[2] = 3 (vector.z=3) 268 constexpr T& operator[](std::size_t i) {
269 {
270 return *((&x) + i); 269 return *((&x) + i);
271 } 270 }
272 T operator[](const int i) const { 271
272 constexpr const T& operator[](std::size_t i) const {
273 return *((&x) + i); 273 return *((&x) + i);
274 } 274 }
275 275
276 void SetZero() { 276 constexpr void SetZero() {
277 x = 0; 277 x = 0;
278 y = 0; 278 y = 0;
279 z = 0; 279 z = 0;
280 } 280 }
281 281
282 // Common aliases: UVW (texel coordinates), RGB (colors), STQ (texture coordinates) 282 // Common aliases: UVW (texel coordinates), RGB (colors), STQ (texture coordinates)
283 T& u() { 283 constexpr T& u() {
284 return x; 284 return x;
285 } 285 }
286 T& v() { 286 constexpr T& v() {
287 return y; 287 return y;
288 } 288 }
289 T& w() { 289 constexpr T& w() {
290 return z; 290 return z;
291 } 291 }
292 292
293 T& r() { 293 constexpr T& r() {
294 return x; 294 return x;
295 } 295 }
296 T& g() { 296 constexpr T& g() {
297 return y; 297 return y;
298 } 298 }
299 T& b() { 299 constexpr T& b() {
300 return z; 300 return z;
301 } 301 }
302 302
303 T& s() { 303 constexpr T& s() {
304 return x; 304 return x;
305 } 305 }
306 T& t() { 306 constexpr T& t() {
307 return y; 307 return y;
308 } 308 }
309 T& q() { 309 constexpr T& q() {
310 return z; 310 return z;
311 } 311 }
312 312
313 const T& u() const { 313 constexpr const T& u() const {
314 return x; 314 return x;
315 } 315 }
316 const T& v() const { 316 constexpr const T& v() const {
317 return y; 317 return y;
318 } 318 }
319 const T& w() const { 319 constexpr const T& w() const {
320 return z; 320 return z;
321 } 321 }
322 322
323 const T& r() const { 323 constexpr const T& r() const {
324 return x; 324 return x;
325 } 325 }
326 const T& g() const { 326 constexpr const T& g() const {
327 return y; 327 return y;
328 } 328 }
329 const T& b() const { 329 constexpr const T& b() const {
330 return z; 330 return z;
331 } 331 }
332 332
333 const T& s() const { 333 constexpr const T& s() const {
334 return x; 334 return x;
335 } 335 }
336 const T& t() const { 336 constexpr const T& t() const {
337 return y; 337 return y;
338 } 338 }
339 const T& q() const { 339 constexpr const T& q() const {
340 return z; 340 return z;
341 } 341 }
342 342
@@ -345,7 +345,7 @@ public:
345// _DEFINE_SWIZZLER2 defines a single such function, DEFINE_SWIZZLER2 defines all of them for all 345// _DEFINE_SWIZZLER2 defines a single such function, DEFINE_SWIZZLER2 defines all of them for all
346// component names (x<->r) and permutations (xy<->yx) 346// component names (x<->r) and permutations (xy<->yx)
347#define _DEFINE_SWIZZLER2(a, b, name) \ 347#define _DEFINE_SWIZZLER2(a, b, name) \
348 const Vec2<T> name() const { \ 348 constexpr Vec2<T> name() const { \
349 return Vec2<T>(a, b); \ 349 return Vec2<T>(a, b); \
350 } 350 }
351#define DEFINE_SWIZZLER2(a, b, a2, b2, a3, b3, a4, b4) \ 351#define DEFINE_SWIZZLER2(a, b, a2, b2, a3, b3, a4, b4) \
@@ -366,7 +366,7 @@ public:
366}; 366};
367 367
368template <typename T, typename V> 368template <typename T, typename V>
369Vec3<T> operator*(const V& f, const Vec3<T>& vec) { 369constexpr Vec3<T> operator*(const V& f, const Vec3<T>& vec) {
370 return Vec3<T>(f * vec.x, f * vec.y, f * vec.z); 370 return Vec3<T>(f * vec.x, f * vec.y, f * vec.z);
371} 371}
372 372
@@ -387,7 +387,7 @@ inline float Vec3<float>::Normalize() {
387 return length; 387 return length;
388} 388}
389 389
390typedef Vec3<float> Vec3f; 390using Vec3f = Vec3<float>;
391 391
392template <typename T> 392template <typename T>
393class Vec4 { 393class Vec4 {
@@ -397,86 +397,88 @@ public:
397 T z{}; 397 T z{};
398 T w{}; 398 T w{};
399 399
400 Vec4() = default; 400 constexpr Vec4() = default;
401 Vec4(const T& _x, const T& _y, const T& _z, const T& _w) : x(_x), y(_y), z(_z), w(_w) {} 401 constexpr Vec4(const T& x_, const T& y_, const T& z_, const T& w_)
402 : x(x_), y(y_), z(z_), w(w_) {}
402 403
403 template <typename T2> 404 template <typename T2>
404 Vec4<T2> Cast() const { 405 constexpr Vec4<T2> Cast() const {
405 return Vec4<T2>((T2)x, (T2)y, (T2)z, (T2)w); 406 return Vec4<T2>(static_cast<T2>(x), static_cast<T2>(y), static_cast<T2>(z),
407 static_cast<T2>(w));
406 } 408 }
407 409
408 // Only implemented for T=int and T=float 410 static constexpr Vec4 AssignToAll(const T& f) {
409 static Vec4 FromRGBA(unsigned int rgba); 411 return Vec4(f, f, f, f);
410 unsigned int ToRGBA() const;
411
412 static Vec4 AssignToAll(const T& f) {
413 return Vec4<T>(f, f, f, f);
414 } 412 }
415 413
416 Vec4<decltype(T{} + T{})> operator+(const Vec4& other) const { 414 constexpr Vec4<decltype(T{} + T{})> operator+(const Vec4& other) const {
417 return MakeVec(x + other.x, y + other.y, z + other.z, w + other.w); 415 return {x + other.x, y + other.y, z + other.z, w + other.w};
418 } 416 }
419 void operator+=(const Vec4& other) { 417
418 constexpr Vec4& operator+=(const Vec4& other) {
420 x += other.x; 419 x += other.x;
421 y += other.y; 420 y += other.y;
422 z += other.z; 421 z += other.z;
423 w += other.w; 422 w += other.w;
423 return *this;
424 } 424 }
425 Vec4<decltype(T{} - T{})> operator-(const Vec4& other) const { 425
426 return MakeVec(x - other.x, y - other.y, z - other.z, w - other.w); 426 constexpr Vec4<decltype(T{} - T{})> operator-(const Vec4& other) const {
427 return {x - other.x, y - other.y, z - other.z, w - other.w};
427 } 428 }
428 void operator-=(const Vec4& other) { 429
430 constexpr Vec4& operator-=(const Vec4& other) {
429 x -= other.x; 431 x -= other.x;
430 y -= other.y; 432 y -= other.y;
431 z -= other.z; 433 z -= other.z;
432 w -= other.w; 434 w -= other.w;
435 return *this;
433 } 436 }
434 437
435 template <typename U = T> 438 template <typename U = T>
436 Vec4<std::enable_if_t<std::is_signed<U>::value, U>> operator-() const { 439 constexpr Vec4<std::enable_if_t<std::is_signed<U>::value, U>> operator-() const {
437 return MakeVec(-x, -y, -z, -w); 440 return {-x, -y, -z, -w};
438 } 441 }
439 Vec4<decltype(T{} * T{})> operator*(const Vec4& other) const { 442
440 return MakeVec(x * other.x, y * other.y, z * other.z, w * other.w); 443 constexpr Vec4<decltype(T{} * T{})> operator*(const Vec4& other) const {
444 return {x * other.x, y * other.y, z * other.z, w * other.w};
441 } 445 }
446
442 template <typename V> 447 template <typename V>
443 Vec4<decltype(T{} * V{})> operator*(const V& f) const { 448 constexpr Vec4<decltype(T{} * V{})> operator*(const V& f) const {
444 return MakeVec(x * f, y * f, z * f, w * f); 449 return {x * f, y * f, z * f, w * f};
445 } 450 }
451
446 template <typename V> 452 template <typename V>
447 void operator*=(const V& f) { 453 constexpr Vec4& operator*=(const V& f) {
448 *this = *this * f; 454 *this = *this * f;
455 return *this;
449 } 456 }
457
450 template <typename V> 458 template <typename V>
451 Vec4<decltype(T{} / V{})> operator/(const V& f) const { 459 constexpr Vec4<decltype(T{} / V{})> operator/(const V& f) const {
452 return MakeVec(x / f, y / f, z / f, w / f); 460 return {x / f, y / f, z / f, w / f};
453 } 461 }
462
454 template <typename V> 463 template <typename V>
455 void operator/=(const V& f) { 464 constexpr Vec4& operator/=(const V& f) {
456 *this = *this / f; 465 *this = *this / f;
466 return *this;
457 } 467 }
458 468
459 T Length2() const { 469 constexpr T Length2() const {
460 return x * x + y * y + z * z + w * w; 470 return x * x + y * y + z * z + w * w;
461 } 471 }
462 472
463 // Only implemented for T=float 473 constexpr T& operator[](std::size_t i) {
464 float Length() const;
465 void SetLength(const float l);
466 Vec4 WithLength(const float l) const;
467 float Distance2To(Vec4& other);
468 Vec4 Normalized() const;
469 float Normalize(); // returns the previous length, which is often useful
470
471 T& operator[](int i) // allow vector[2] = 3 (vector.z=3)
472 {
473 return *((&x) + i); 474 return *((&x) + i);
474 } 475 }
475 T operator[](const int i) const { 476
477 constexpr const T& operator[](std::size_t i) const {
476 return *((&x) + i); 478 return *((&x) + i);
477 } 479 }
478 480
479 void SetZero() { 481 constexpr void SetZero() {
480 x = 0; 482 x = 0;
481 y = 0; 483 y = 0;
482 z = 0; 484 z = 0;
@@ -484,29 +486,29 @@ public:
484 } 486 }
485 487
486 // Common alias: RGBA (colors) 488 // Common alias: RGBA (colors)
487 T& r() { 489 constexpr T& r() {
488 return x; 490 return x;
489 } 491 }
490 T& g() { 492 constexpr T& g() {
491 return y; 493 return y;
492 } 494 }
493 T& b() { 495 constexpr T& b() {
494 return z; 496 return z;
495 } 497 }
496 T& a() { 498 constexpr T& a() {
497 return w; 499 return w;
498 } 500 }
499 501
500 const T& r() const { 502 constexpr const T& r() const {
501 return x; 503 return x;
502 } 504 }
503 const T& g() const { 505 constexpr const T& g() const {
504 return y; 506 return y;
505 } 507 }
506 const T& b() const { 508 constexpr const T& b() const {
507 return z; 509 return z;
508 } 510 }
509 const T& a() const { 511 constexpr const T& a() const {
510 return w; 512 return w;
511 } 513 }
512 514
@@ -518,7 +520,7 @@ public:
518// DEFINE_SWIZZLER2_COMP2 defines two component functions for all component names (x<->r) and 520// DEFINE_SWIZZLER2_COMP2 defines two component functions for all component names (x<->r) and
519// permutations (xy<->yx) 521// permutations (xy<->yx)
520#define _DEFINE_SWIZZLER2(a, b, name) \ 522#define _DEFINE_SWIZZLER2(a, b, name) \
521 const Vec2<T> name() const { \ 523 constexpr Vec2<T> name() const { \
522 return Vec2<T>(a, b); \ 524 return Vec2<T>(a, b); \
523 } 525 }
524#define DEFINE_SWIZZLER2_COMP1(a, a2) \ 526#define DEFINE_SWIZZLER2_COMP1(a, a2) \
@@ -545,7 +547,7 @@ public:
545#undef _DEFINE_SWIZZLER2 547#undef _DEFINE_SWIZZLER2
546 548
547#define _DEFINE_SWIZZLER3(a, b, c, name) \ 549#define _DEFINE_SWIZZLER3(a, b, c, name) \
548 const Vec3<T> name() const { \ 550 constexpr Vec3<T> name() const { \
549 return Vec3<T>(a, b, c); \ 551 return Vec3<T>(a, b, c); \
550 } 552 }
551#define DEFINE_SWIZZLER3_COMP1(a, a2) \ 553#define DEFINE_SWIZZLER3_COMP1(a, a2) \
@@ -579,51 +581,51 @@ public:
579}; 581};
580 582
581template <typename T, typename V> 583template <typename T, typename V>
582Vec4<decltype(V{} * T{})> operator*(const V& f, const Vec4<T>& vec) { 584constexpr Vec4<decltype(V{} * T{})> operator*(const V& f, const Vec4<T>& vec) {
583 return MakeVec(f * vec.x, f * vec.y, f * vec.z, f * vec.w); 585 return {f * vec.x, f * vec.y, f * vec.z, f * vec.w};
584} 586}
585 587
586typedef Vec4<float> Vec4f; 588using Vec4f = Vec4<float>;
587 589
588template <typename T> 590template <typename T>
589static inline decltype(T{} * T{} + T{} * T{}) Dot(const Vec2<T>& a, const Vec2<T>& b) { 591constexpr decltype(T{} * T{} + T{} * T{}) Dot(const Vec2<T>& a, const Vec2<T>& b) {
590 return a.x * b.x + a.y * b.y; 592 return a.x * b.x + a.y * b.y;
591} 593}
592 594
593template <typename T> 595template <typename T>
594static inline decltype(T{} * T{} + T{} * T{}) Dot(const Vec3<T>& a, const Vec3<T>& b) { 596constexpr decltype(T{} * T{} + T{} * T{}) Dot(const Vec3<T>& a, const Vec3<T>& b) {
595 return a.x * b.x + a.y * b.y + a.z * b.z; 597 return a.x * b.x + a.y * b.y + a.z * b.z;
596} 598}
597 599
598template <typename T> 600template <typename T>
599static inline decltype(T{} * T{} + T{} * T{}) Dot(const Vec4<T>& a, const Vec4<T>& b) { 601constexpr decltype(T{} * T{} + T{} * T{}) Dot(const Vec4<T>& a, const Vec4<T>& b) {
600 return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w; 602 return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w;
601} 603}
602 604
603template <typename T> 605template <typename T>
604static inline Vec3<decltype(T{} * T{} - T{} * T{})> Cross(const Vec3<T>& a, const Vec3<T>& b) { 606constexpr Vec3<decltype(T{} * T{} - T{} * T{})> Cross(const Vec3<T>& a, const Vec3<T>& b) {
605 return MakeVec(a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y - a.y * b.x); 607 return {a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y - a.y * b.x};
606} 608}
607 609
608// linear interpolation via float: 0.0=begin, 1.0=end 610// linear interpolation via float: 0.0=begin, 1.0=end
609template <typename X> 611template <typename X>
610static inline decltype(X{} * float{} + X{} * float{}) Lerp(const X& begin, const X& end, 612constexpr decltype(X{} * float{} + X{} * float{}) Lerp(const X& begin, const X& end,
611 const float t) { 613 const float t) {
612 return begin * (1.f - t) + end * t; 614 return begin * (1.f - t) + end * t;
613} 615}
614 616
615// linear interpolation via int: 0=begin, base=end 617// linear interpolation via int: 0=begin, base=end
616template <typename X, int base> 618template <typename X, int base>
617static inline decltype((X{} * int{} + X{} * int{}) / base) LerpInt(const X& begin, const X& end, 619constexpr decltype((X{} * int{} + X{} * int{}) / base) LerpInt(const X& begin, const X& end,
618 const int t) { 620 const int t) {
619 return (begin * (base - t) + end * t) / base; 621 return (begin * (base - t) + end * t) / base;
620} 622}
621 623
622// bilinear interpolation. s is for interpolating x00-x01 and x10-x11, and t is for the second 624// bilinear interpolation. s is for interpolating x00-x01 and x10-x11, and t is for the second
623// interpolation. 625// interpolation.
624template <typename X> 626template <typename X>
625inline auto BilinearInterp(const X& x00, const X& x01, const X& x10, const X& x11, const float s, 627constexpr auto BilinearInterp(const X& x00, const X& x01, const X& x10, const X& x11, const float s,
626 const float t) { 628 const float t) {
627 auto y0 = Lerp(x00, x01, s); 629 auto y0 = Lerp(x00, x01, s);
628 auto y1 = Lerp(x10, x11, s); 630 auto y1 = Lerp(x10, x11, s);
629 return Lerp(y0, y1, t); 631 return Lerp(y0, y1, t);
@@ -631,42 +633,42 @@ inline auto BilinearInterp(const X& x00, const X& x01, const X& x10, const X& x1
631 633
632// Utility vector factories 634// Utility vector factories
633template <typename T> 635template <typename T>
634static inline Vec2<T> MakeVec(const T& x, const T& y) { 636constexpr Vec2<T> MakeVec(const T& x, const T& y) {
635 return Vec2<T>{x, y}; 637 return Vec2<T>{x, y};
636} 638}
637 639
638template <typename T> 640template <typename T>
639static inline Vec3<T> MakeVec(const T& x, const T& y, const T& z) { 641constexpr Vec3<T> MakeVec(const T& x, const T& y, const T& z) {
640 return Vec3<T>{x, y, z}; 642 return Vec3<T>{x, y, z};
641} 643}
642 644
643template <typename T> 645template <typename T>
644static inline Vec4<T> MakeVec(const T& x, const T& y, const Vec2<T>& zw) { 646constexpr Vec4<T> MakeVec(const T& x, const T& y, const Vec2<T>& zw) {
645 return MakeVec(x, y, zw[0], zw[1]); 647 return MakeVec(x, y, zw[0], zw[1]);
646} 648}
647 649
648template <typename T> 650template <typename T>
649static inline Vec3<T> MakeVec(const Vec2<T>& xy, const T& z) { 651constexpr Vec3<T> MakeVec(const Vec2<T>& xy, const T& z) {
650 return MakeVec(xy[0], xy[1], z); 652 return MakeVec(xy[0], xy[1], z);
651} 653}
652 654
653template <typename T> 655template <typename T>
654static inline Vec3<T> MakeVec(const T& x, const Vec2<T>& yz) { 656constexpr Vec3<T> MakeVec(const T& x, const Vec2<T>& yz) {
655 return MakeVec(x, yz[0], yz[1]); 657 return MakeVec(x, yz[0], yz[1]);
656} 658}
657 659
658template <typename T> 660template <typename T>
659static inline Vec4<T> MakeVec(const T& x, const T& y, const T& z, const T& w) { 661constexpr Vec4<T> MakeVec(const T& x, const T& y, const T& z, const T& w) {
660 return Vec4<T>{x, y, z, w}; 662 return Vec4<T>{x, y, z, w};
661} 663}
662 664
663template <typename T> 665template <typename T>
664static inline Vec4<T> MakeVec(const Vec2<T>& xy, const T& z, const T& w) { 666constexpr Vec4<T> MakeVec(const Vec2<T>& xy, const T& z, const T& w) {
665 return MakeVec(xy[0], xy[1], z, w); 667 return MakeVec(xy[0], xy[1], z, w);
666} 668}
667 669
668template <typename T> 670template <typename T>
669static inline Vec4<T> MakeVec(const T& x, const Vec2<T>& yz, const T& w) { 671constexpr Vec4<T> MakeVec(const T& x, const Vec2<T>& yz, const T& w) {
670 return MakeVec(x, yz[0], yz[1], w); 672 return MakeVec(x, yz[0], yz[1], w);
671} 673}
672 674
@@ -674,17 +676,17 @@ static inline Vec4<T> MakeVec(const T& x, const Vec2<T>& yz, const T& w) {
674// Even if someone wanted to use an odd object like Vec2<Vec2<T>>, the compiler would error 676// Even if someone wanted to use an odd object like Vec2<Vec2<T>>, the compiler would error
675// out soon enough due to misuse of the returned structure. 677// out soon enough due to misuse of the returned structure.
676template <typename T> 678template <typename T>
677static inline Vec4<T> MakeVec(const Vec2<T>& xy, const Vec2<T>& zw) { 679constexpr Vec4<T> MakeVec(const Vec2<T>& xy, const Vec2<T>& zw) {
678 return MakeVec(xy[0], xy[1], zw[0], zw[1]); 680 return MakeVec(xy[0], xy[1], zw[0], zw[1]);
679} 681}
680 682
681template <typename T> 683template <typename T>
682static inline Vec4<T> MakeVec(const Vec3<T>& xyz, const T& w) { 684constexpr Vec4<T> MakeVec(const Vec3<T>& xyz, const T& w) {
683 return MakeVec(xyz[0], xyz[1], xyz[2], w); 685 return MakeVec(xyz[0], xyz[1], xyz[2], w);
684} 686}
685 687
686template <typename T> 688template <typename T>
687static inline Vec4<T> MakeVec(const T& x, const Vec3<T>& yzw) { 689constexpr Vec4<T> MakeVec(const T& x, const Vec3<T>& yzw) {
688 return MakeVec(x, yzw[0], yzw[1], yzw[2]); 690 return MakeVec(x, yzw[0], yzw[1], yzw[2]);
689} 691}
690 692
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 0abf7edc1..cceb1564b 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -104,8 +104,6 @@ add_library(core STATIC
104 hle/lock.cpp 104 hle/lock.cpp
105 hle/lock.h 105 hle/lock.h
106 hle/result.h 106 hle/result.h
107 hle/romfs.cpp
108 hle/romfs.h
109 hle/service/acc/acc.cpp 107 hle/service/acc/acc.cpp
110 hle/service/acc/acc.h 108 hle/service/acc/acc.h
111 hle/service/acc/acc_aa.cpp 109 hle/service/acc/acc_aa.cpp
diff --git a/src/core/file_sys/card_image.cpp b/src/core/file_sys/card_image.cpp
index 395eea8ae..e897d9913 100644
--- a/src/core/file_sys/card_image.cpp
+++ b/src/core/file_sys/card_image.cpp
@@ -5,6 +5,7 @@
5#include <array> 5#include <array>
6#include <string> 6#include <string>
7#include <core/loader/loader.h> 7#include <core/loader/loader.h>
8#include "common/logging/log.h"
8#include "core/file_sys/card_image.h" 9#include "core/file_sys/card_image.h"
9#include "core/file_sys/partition_filesystem.h" 10#include "core/file_sys/partition_filesystem.h"
10#include "core/file_sys/vfs_offset.h" 11#include "core/file_sys/vfs_offset.h"
diff --git a/src/core/file_sys/content_archive.cpp b/src/core/file_sys/content_archive.cpp
index 3529166ac..d3007d981 100644
--- a/src/core/file_sys/content_archive.cpp
+++ b/src/core/file_sys/content_archive.cpp
@@ -170,6 +170,10 @@ VirtualFile NCA::Decrypt(NCASectionHeader s_header, VirtualFile in, u64 starting
170} 170}
171 171
172NCA::NCA(VirtualFile file_) : file(std::move(file_)) { 172NCA::NCA(VirtualFile file_) : file(std::move(file_)) {
173 if (file == nullptr) {
174 status = Loader::ResultStatus::ErrorInvalidFormat;
175 return;
176 }
173 if (sizeof(NCAHeader) != file->ReadObject(&header)) 177 if (sizeof(NCAHeader) != file->ReadObject(&header))
174 LOG_ERROR(Loader, "File reader errored out during header read."); 178 LOG_ERROR(Loader, "File reader errored out during header read.");
175 179
diff --git a/src/core/file_sys/content_archive.h b/src/core/file_sys/content_archive.h
index a8879d9a8..5cfd5031a 100644
--- a/src/core/file_sys/content_archive.h
+++ b/src/core/file_sys/content_archive.h
@@ -12,6 +12,7 @@
12#include "common/common_funcs.h" 12#include "common/common_funcs.h"
13#include "common/common_types.h" 13#include "common/common_types.h"
14#include "common/swap.h" 14#include "common/swap.h"
15#include "control_metadata.h"
15#include "core/crypto/key_manager.h" 16#include "core/crypto/key_manager.h"
16#include "core/file_sys/partition_filesystem.h" 17#include "core/file_sys/partition_filesystem.h"
17#include "core/loader/loader.h" 18#include "core/loader/loader.h"
diff --git a/src/core/file_sys/control_metadata.h b/src/core/file_sys/control_metadata.h
index cc3b745f7..6582cc240 100644
--- a/src/core/file_sys/control_metadata.h
+++ b/src/core/file_sys/control_metadata.h
@@ -62,6 +62,13 @@ enum class Language : u8 {
62 Chinese = 14, 62 Chinese = 14,
63}; 63};
64 64
65static constexpr std::array<const char*, 15> LANGUAGE_NAMES = {
66 "AmericanEnglish", "BritishEnglish", "Japanese",
67 "French", "German", "LatinAmericanSpanish",
68 "Spanish", "Italian", "Dutch",
69 "CanadianFrench", "Portugese", "Russian",
70 "Korean", "Taiwanese", "Chinese"};
71
65// A class representing the format used by NX metadata files, typically named Control.nacp. 72// A class representing the format used by NX metadata files, typically named Control.nacp.
66// These store application name, dev name, title id, and other miscellaneous data. 73// These store application name, dev name, title id, and other miscellaneous data.
67class NACP { 74class NACP {
diff --git a/src/core/hle/romfs.cpp b/src/core/hle/romfs.cpp
deleted file mode 100644
index 3157df71d..000000000
--- a/src/core/hle/romfs.cpp
+++ /dev/null
@@ -1,102 +0,0 @@
1// Copyright 2017 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include <cstring>
6#include "common/swap.h"
7#include "core/hle/romfs.h"
8
9namespace RomFS {
10
11struct Header {
12 u32_le header_length;
13 u32_le dir_hash_table_offset;
14 u32_le dir_hash_table_length;
15 u32_le dir_table_offset;
16 u32_le dir_table_length;
17 u32_le file_hash_table_offset;
18 u32_le file_hash_table_length;
19 u32_le file_table_offset;
20 u32_le file_table_length;
21 u32_le data_offset;
22};
23
24static_assert(sizeof(Header) == 0x28, "Header has incorrect size");
25
26struct DirectoryMetadata {
27 u32_le parent_dir_offset;
28 u32_le next_dir_offset;
29 u32_le first_child_dir_offset;
30 u32_le first_file_offset;
31 u32_le same_hash_next_dir_offset;
32 u32_le name_length; // in bytes
33 // followed by directory name
34};
35
36static_assert(sizeof(DirectoryMetadata) == 0x18, "DirectoryMetadata has incorrect size");
37
38struct FileMetadata {
39 u32_le parent_dir_offset;
40 u32_le next_file_offset;
41 u64_le data_offset;
42 u64_le data_length;
43 u32_le same_hash_next_file_offset;
44 u32_le name_length; // in bytes
45 // followed by file name
46};
47
48static_assert(sizeof(FileMetadata) == 0x20, "FileMetadata has incorrect size");
49
50static bool MatchName(const u8* buffer, u32 name_length, const std::u16string& name) {
51 std::vector<char16_t> name_buffer(name_length / sizeof(char16_t));
52 std::memcpy(name_buffer.data(), buffer, name_length);
53 return name == std::u16string(name_buffer.begin(), name_buffer.end());
54}
55
56const u8* GetFilePointer(const u8* romfs, const std::vector<std::u16string>& path) {
57 constexpr u32 INVALID_FIELD = 0xFFFFFFFF;
58
59 // Split path into directory names and file name
60 std::vector<std::u16string> dir_names = path;
61 dir_names.pop_back();
62 const std::u16string& file_name = path.back();
63
64 Header header;
65 std::memcpy(&header, romfs, sizeof(header));
66
67 // Find directories of each level
68 DirectoryMetadata dir;
69 const u8* current_dir = romfs + header.dir_table_offset;
70 std::memcpy(&dir, current_dir, sizeof(dir));
71 for (const std::u16string& dir_name : dir_names) {
72 u32 child_dir_offset;
73 child_dir_offset = dir.first_child_dir_offset;
74 while (true) {
75 if (child_dir_offset == INVALID_FIELD) {
76 return nullptr;
77 }
78 const u8* current_child_dir = romfs + header.dir_table_offset + child_dir_offset;
79 std::memcpy(&dir, current_child_dir, sizeof(dir));
80 if (MatchName(current_child_dir + sizeof(dir), dir.name_length, dir_name)) {
81 current_dir = current_child_dir;
82 break;
83 }
84 child_dir_offset = dir.next_dir_offset;
85 }
86 }
87
88 // Find the file
89 FileMetadata file;
90 u32 file_offset = dir.first_file_offset;
91 while (file_offset != INVALID_FIELD) {
92 const u8* current_file = romfs + header.file_table_offset + file_offset;
93 std::memcpy(&file, current_file, sizeof(file));
94 if (MatchName(current_file + sizeof(file), file.name_length, file_name)) {
95 return romfs + header.data_offset + file.data_offset;
96 }
97 file_offset = file.next_file_offset;
98 }
99 return nullptr;
100}
101
102} // namespace RomFS
diff --git a/src/core/hle/romfs.h b/src/core/hle/romfs.h
deleted file mode 100644
index ee9f29760..000000000
--- a/src/core/hle/romfs.h
+++ /dev/null
@@ -1,22 +0,0 @@
1// Copyright 2017 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include <string>
8#include <vector>
9#include "common/common_types.h"
10
11namespace RomFS {
12
13/**
14 * Gets the pointer to a file in a RomFS image.
15 * @param romfs The pointer to the RomFS image
16 * @param path A vector containing the directory names and file name of the path to the file
17 * @return the pointer to the file
18 * @todo reimplement this with a full RomFS manager
19 */
20const u8* GetFilePointer(const u8* romfs, const std::vector<std::u16string>& path);
21
22} // namespace RomFS
diff --git a/src/core/hle/service/acc/acc.cpp b/src/core/hle/service/acc/acc.cpp
index 6d15b46ed..e952b0518 100644
--- a/src/core/hle/service/acc/acc.cpp
+++ b/src/core/hle/service/acc/acc.cpp
@@ -119,6 +119,13 @@ private:
119 } 119 }
120}; 120};
121 121
122void Module::Interface::GetUserCount(Kernel::HLERequestContext& ctx) {
123 LOG_WARNING(Service_ACC, "(STUBBED) called");
124 IPC::ResponseBuilder rb{ctx, 3};
125 rb.Push(RESULT_SUCCESS);
126 rb.Push<u32>(1);
127}
128
122void Module::Interface::GetUserExistence(Kernel::HLERequestContext& ctx) { 129void Module::Interface::GetUserExistence(Kernel::HLERequestContext& ctx) {
123 LOG_WARNING(Service_ACC, "(STUBBED) called"); 130 LOG_WARNING(Service_ACC, "(STUBBED) called");
124 IPC::ResponseBuilder rb{ctx, 3}; 131 IPC::ResponseBuilder rb{ctx, 3};
diff --git a/src/core/hle/service/acc/acc.h b/src/core/hle/service/acc/acc.h
index 0a01d954c..88cabaa01 100644
--- a/src/core/hle/service/acc/acc.h
+++ b/src/core/hle/service/acc/acc.h
@@ -14,6 +14,7 @@ public:
14 public: 14 public:
15 explicit Interface(std::shared_ptr<Module> module, const char* name); 15 explicit Interface(std::shared_ptr<Module> module, const char* name);
16 16
17 void GetUserCount(Kernel::HLERequestContext& ctx);
17 void GetUserExistence(Kernel::HLERequestContext& ctx); 18 void GetUserExistence(Kernel::HLERequestContext& ctx);
18 void ListAllUsers(Kernel::HLERequestContext& ctx); 19 void ListAllUsers(Kernel::HLERequestContext& ctx);
19 void ListOpenUsers(Kernel::HLERequestContext& ctx); 20 void ListOpenUsers(Kernel::HLERequestContext& ctx);
diff --git a/src/core/hle/service/acc/acc_su.cpp b/src/core/hle/service/acc/acc_su.cpp
index 9ffb40b22..8b2a71f37 100644
--- a/src/core/hle/service/acc/acc_su.cpp
+++ b/src/core/hle/service/acc/acc_su.cpp
@@ -8,7 +8,7 @@ namespace Service::Account {
8 8
9ACC_SU::ACC_SU(std::shared_ptr<Module> module) : Module::Interface(std::move(module), "acc:su") { 9ACC_SU::ACC_SU(std::shared_ptr<Module> module) : Module::Interface(std::move(module), "acc:su") {
10 static const FunctionInfo functions[] = { 10 static const FunctionInfo functions[] = {
11 {0, nullptr, "GetUserCount"}, 11 {0, &ACC_SU::GetUserCount, "GetUserCount"},
12 {1, &ACC_SU::GetUserExistence, "GetUserExistence"}, 12 {1, &ACC_SU::GetUserExistence, "GetUserExistence"},
13 {2, &ACC_SU::ListAllUsers, "ListAllUsers"}, 13 {2, &ACC_SU::ListAllUsers, "ListAllUsers"},
14 {3, &ACC_SU::ListOpenUsers, "ListOpenUsers"}, 14 {3, &ACC_SU::ListOpenUsers, "ListOpenUsers"},
diff --git a/src/core/hle/service/acc/acc_u0.cpp b/src/core/hle/service/acc/acc_u0.cpp
index 44e21ac09..d84c8b2e1 100644
--- a/src/core/hle/service/acc/acc_u0.cpp
+++ b/src/core/hle/service/acc/acc_u0.cpp
@@ -8,7 +8,7 @@ namespace Service::Account {
8 8
9ACC_U0::ACC_U0(std::shared_ptr<Module> module) : Module::Interface(std::move(module), "acc:u0") { 9ACC_U0::ACC_U0(std::shared_ptr<Module> module) : Module::Interface(std::move(module), "acc:u0") {
10 static const FunctionInfo functions[] = { 10 static const FunctionInfo functions[] = {
11 {0, nullptr, "GetUserCount"}, 11 {0, &ACC_U0::GetUserCount, "GetUserCount"},
12 {1, &ACC_U0::GetUserExistence, "GetUserExistence"}, 12 {1, &ACC_U0::GetUserExistence, "GetUserExistence"},
13 {2, &ACC_U0::ListAllUsers, "ListAllUsers"}, 13 {2, &ACC_U0::ListAllUsers, "ListAllUsers"},
14 {3, &ACC_U0::ListOpenUsers, "ListOpenUsers"}, 14 {3, &ACC_U0::ListOpenUsers, "ListOpenUsers"},
diff --git a/src/core/hle/service/acc/acc_u1.cpp b/src/core/hle/service/acc/acc_u1.cpp
index d101d4e0d..0ceaf06b5 100644
--- a/src/core/hle/service/acc/acc_u1.cpp
+++ b/src/core/hle/service/acc/acc_u1.cpp
@@ -8,7 +8,7 @@ namespace Service::Account {
8 8
9ACC_U1::ACC_U1(std::shared_ptr<Module> module) : Module::Interface(std::move(module), "acc:u1") { 9ACC_U1::ACC_U1(std::shared_ptr<Module> module) : Module::Interface(std::move(module), "acc:u1") {
10 static const FunctionInfo functions[] = { 10 static const FunctionInfo functions[] = {
11 {0, nullptr, "GetUserCount"}, 11 {0, &ACC_U1::GetUserCount, "GetUserCount"},
12 {1, &ACC_U1::GetUserExistence, "GetUserExistence"}, 12 {1, &ACC_U1::GetUserExistence, "GetUserExistence"},
13 {2, &ACC_U1::ListAllUsers, "ListAllUsers"}, 13 {2, &ACC_U1::ListAllUsers, "ListAllUsers"},
14 {3, &ACC_U1::ListOpenUsers, "ListOpenUsers"}, 14 {3, &ACC_U1::ListOpenUsers, "ListOpenUsers"},
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp
index 8f0262e34..dcdfa0e19 100644
--- a/src/core/hle/service/hid/hid.cpp
+++ b/src/core/hle/service/hid/hid.cpp
@@ -457,7 +457,7 @@ private:
457 } 457 }
458 458
459 void IsSixAxisSensorAtRest(Kernel::HLERequestContext& ctx) { 459 void IsSixAxisSensorAtRest(Kernel::HLERequestContext& ctx) {
460 IPC::ResponseBuilder rb{ctx, 2}; 460 IPC::ResponseBuilder rb{ctx, 3};
461 rb.Push(RESULT_SUCCESS); 461 rb.Push(RESULT_SUCCESS);
462 // TODO (Hexagon12): Properly implement reading gyroscope values from controllers. 462 // TODO (Hexagon12): Properly implement reading gyroscope values from controllers.
463 rb.Push(true); 463 rb.Push(true);
diff --git a/src/core/hle/service/nvdrv/nvdrv.cpp b/src/core/hle/service/nvdrv/nvdrv.cpp
index e8b30921a..427f4b574 100644
--- a/src/core/hle/service/nvdrv/nvdrv.cpp
+++ b/src/core/hle/service/nvdrv/nvdrv.cpp
@@ -16,19 +16,18 @@
16#include "core/hle/service/nvdrv/interface.h" 16#include "core/hle/service/nvdrv/interface.h"
17#include "core/hle/service/nvdrv/nvdrv.h" 17#include "core/hle/service/nvdrv/nvdrv.h"
18#include "core/hle/service/nvdrv/nvmemp.h" 18#include "core/hle/service/nvdrv/nvmemp.h"
19#include "core/hle/service/nvflinger/nvflinger.h"
19 20
20namespace Service::Nvidia { 21namespace Service::Nvidia {
21 22
22std::weak_ptr<Module> nvdrv; 23void InstallInterfaces(SM::ServiceManager& service_manager, NVFlinger::NVFlinger& nvflinger) {
23
24void InstallInterfaces(SM::ServiceManager& service_manager) {
25 auto module_ = std::make_shared<Module>(); 24 auto module_ = std::make_shared<Module>();
26 std::make_shared<NVDRV>(module_, "nvdrv")->InstallAsService(service_manager); 25 std::make_shared<NVDRV>(module_, "nvdrv")->InstallAsService(service_manager);
27 std::make_shared<NVDRV>(module_, "nvdrv:a")->InstallAsService(service_manager); 26 std::make_shared<NVDRV>(module_, "nvdrv:a")->InstallAsService(service_manager);
28 std::make_shared<NVDRV>(module_, "nvdrv:s")->InstallAsService(service_manager); 27 std::make_shared<NVDRV>(module_, "nvdrv:s")->InstallAsService(service_manager);
29 std::make_shared<NVDRV>(module_, "nvdrv:t")->InstallAsService(service_manager); 28 std::make_shared<NVDRV>(module_, "nvdrv:t")->InstallAsService(service_manager);
30 std::make_shared<NVMEMP>()->InstallAsService(service_manager); 29 std::make_shared<NVMEMP>()->InstallAsService(service_manager);
31 nvdrv = module_; 30 nvflinger.SetNVDrvInstance(module_);
32} 31}
33 32
34Module::Module() { 33Module::Module() {
diff --git a/src/core/hle/service/nvdrv/nvdrv.h b/src/core/hle/service/nvdrv/nvdrv.h
index 184f3c9fc..99eb1128a 100644
--- a/src/core/hle/service/nvdrv/nvdrv.h
+++ b/src/core/hle/service/nvdrv/nvdrv.h
@@ -10,6 +10,10 @@
10#include "common/common_types.h" 10#include "common/common_types.h"
11#include "core/hle/service/service.h" 11#include "core/hle/service/service.h"
12 12
13namespace Service::NVFlinger {
14class NVFlinger;
15}
16
13namespace Service::Nvidia { 17namespace Service::Nvidia {
14 18
15namespace Devices { 19namespace Devices {
@@ -56,8 +60,6 @@ private:
56}; 60};
57 61
58/// Registers all NVDRV services with the specified service manager. 62/// Registers all NVDRV services with the specified service manager.
59void InstallInterfaces(SM::ServiceManager& service_manager); 63void InstallInterfaces(SM::ServiceManager& service_manager, NVFlinger::NVFlinger& nvflinger);
60
61extern std::weak_ptr<Module> nvdrv;
62 64
63} // namespace Service::Nvidia 65} // namespace Service::Nvidia
diff --git a/src/core/hle/service/nvflinger/nvflinger.cpp b/src/core/hle/service/nvflinger/nvflinger.cpp
index 570aa8493..a26a5f812 100644
--- a/src/core/hle/service/nvflinger/nvflinger.cpp
+++ b/src/core/hle/service/nvflinger/nvflinger.cpp
@@ -46,6 +46,10 @@ NVFlinger::~NVFlinger() {
46 CoreTiming::UnscheduleEvent(composition_event, 0); 46 CoreTiming::UnscheduleEvent(composition_event, 0);
47} 47}
48 48
49void NVFlinger::SetNVDrvInstance(std::shared_ptr<Nvidia::Module> instance) {
50 nvdrv = std::move(instance);
51}
52
49u64 NVFlinger::OpenDisplay(std::string_view name) { 53u64 NVFlinger::OpenDisplay(std::string_view name) {
50 LOG_WARNING(Service, "Opening display {}", name); 54 LOG_WARNING(Service, "Opening display {}", name);
51 55
@@ -141,9 +145,6 @@ void NVFlinger::Compose() {
141 auto& igbp_buffer = buffer->igbp_buffer; 145 auto& igbp_buffer = buffer->igbp_buffer;
142 146
143 // Now send the buffer to the GPU for drawing. 147 // Now send the buffer to the GPU for drawing.
144 auto nvdrv = Nvidia::nvdrv.lock();
145 ASSERT(nvdrv);
146
147 // TODO(Subv): Support more than just disp0. The display device selection is probably based 148 // TODO(Subv): Support more than just disp0. The display device selection is probably based
148 // on which display we're drawing (Default, Internal, External, etc) 149 // on which display we're drawing (Default, Internal, External, etc)
149 auto nvdisp = nvdrv->GetDevice<Nvidia::Devices::nvdisp_disp0>("/dev/nvdisp_disp0"); 150 auto nvdisp = nvdrv->GetDevice<Nvidia::Devices::nvdisp_disp0>("/dev/nvdisp_disp0");
diff --git a/src/core/hle/service/nvflinger/nvflinger.h b/src/core/hle/service/nvflinger/nvflinger.h
index 5374df175..f7112949f 100644
--- a/src/core/hle/service/nvflinger/nvflinger.h
+++ b/src/core/hle/service/nvflinger/nvflinger.h
@@ -16,6 +16,10 @@ namespace CoreTiming {
16struct EventType; 16struct EventType;
17} 17}
18 18
19namespace Service::Nvidia {
20class Module;
21}
22
19namespace Service::NVFlinger { 23namespace Service::NVFlinger {
20 24
21class BufferQueue; 25class BufferQueue;
@@ -44,6 +48,9 @@ public:
44 NVFlinger(); 48 NVFlinger();
45 ~NVFlinger(); 49 ~NVFlinger();
46 50
51 /// Sets the NVDrv module instance to use to send buffers to the GPU.
52 void SetNVDrvInstance(std::shared_ptr<Nvidia::Module> instance);
53
47 /// Opens the specified display and returns the id. 54 /// Opens the specified display and returns the id.
48 u64 OpenDisplay(std::string_view name); 55 u64 OpenDisplay(std::string_view name);
49 56
@@ -70,6 +77,8 @@ private:
70 /// Returns the layer identified by the specified id in the desired display. 77 /// Returns the layer identified by the specified id in the desired display.
71 Layer& GetLayer(u64 display_id, u64 layer_id); 78 Layer& GetLayer(u64 display_id, u64 layer_id);
72 79
80 std::shared_ptr<Nvidia::Module> nvdrv;
81
73 std::vector<Display> displays; 82 std::vector<Display> displays;
74 std::vector<std::shared_ptr<BufferQueue>> buffer_queues; 83 std::vector<std::shared_ptr<BufferQueue>> buffer_queues;
75 84
diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp
index 889cdd41a..6f286ea74 100644
--- a/src/core/hle/service/service.cpp
+++ b/src/core/hle/service/service.cpp
@@ -238,7 +238,7 @@ void Init(std::shared_ptr<SM::ServiceManager>& sm) {
238 NIFM::InstallInterfaces(*sm); 238 NIFM::InstallInterfaces(*sm);
239 NIM::InstallInterfaces(*sm); 239 NIM::InstallInterfaces(*sm);
240 NS::InstallInterfaces(*sm); 240 NS::InstallInterfaces(*sm);
241 Nvidia::InstallInterfaces(*sm); 241 Nvidia::InstallInterfaces(*sm, *nv_flinger);
242 PCIe::InstallInterfaces(*sm); 242 PCIe::InstallInterfaces(*sm);
243 PCTL::InstallInterfaces(*sm); 243 PCTL::InstallInterfaces(*sm);
244 PCV::InstallInterfaces(*sm); 244 PCV::InstallInterfaces(*sm);
diff --git a/src/core/loader/deconstructed_rom_directory.cpp b/src/core/loader/deconstructed_rom_directory.cpp
index 9a8cdd0ff..915d525b0 100644
--- a/src/core/loader/deconstructed_rom_directory.cpp
+++ b/src/core/loader/deconstructed_rom_directory.cpp
@@ -7,6 +7,7 @@
7#include "common/file_util.h" 7#include "common/file_util.h"
8#include "common/logging/log.h" 8#include "common/logging/log.h"
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/gdbstub/gdbstub.h" 11#include "core/gdbstub/gdbstub.h"
11#include "core/hle/kernel/process.h" 12#include "core/hle/kernel/process.h"
12#include "core/hle/kernel/resource_limit.h" 13#include "core/hle/kernel/resource_limit.h"
@@ -17,8 +18,50 @@
17 18
18namespace Loader { 19namespace Loader {
19 20
20AppLoader_DeconstructedRomDirectory::AppLoader_DeconstructedRomDirectory(FileSys::VirtualFile file) 21AppLoader_DeconstructedRomDirectory::AppLoader_DeconstructedRomDirectory(FileSys::VirtualFile file_)
21 : AppLoader(std::move(file)) {} 22 : AppLoader(std::move(file_)) {
23 const auto dir = file->GetContainingDirectory();
24
25 // Icon
26 FileSys::VirtualFile icon_file = nullptr;
27 for (const auto& language : FileSys::LANGUAGE_NAMES) {
28 icon_file = dir->GetFile("icon_" + std::string(language) + ".dat");
29 if (icon_file != nullptr) {
30 icon_data = icon_file->ReadAllBytes();
31 break;
32 }
33 }
34
35 if (icon_data.empty()) {
36 // Any png, jpeg, or bmp file
37 const auto& files = dir->GetFiles();
38 const auto icon_iter =
39 std::find_if(files.begin(), files.end(), [](const FileSys::VirtualFile& file) {
40 return file->GetExtension() == "png" || file->GetExtension() == "jpg" ||
41 file->GetExtension() == "bmp" || file->GetExtension() == "jpeg";
42 });
43 if (icon_iter != files.end())
44 icon_data = (*icon_iter)->ReadAllBytes();
45 }
46
47 // Metadata
48 FileSys::VirtualFile nacp_file = dir->GetFile("control.nacp");
49 if (nacp_file == nullptr) {
50 const auto& files = dir->GetFiles();
51 const auto nacp_iter =
52 std::find_if(files.begin(), files.end(), [](const FileSys::VirtualFile& file) {
53 return file->GetExtension() == "nacp";
54 });
55 if (nacp_iter != files.end())
56 nacp_file = *nacp_iter;
57 }
58
59 if (nacp_file != nullptr) {
60 FileSys::NACP nacp(nacp_file);
61 title_id = nacp.GetTitleId();
62 name = nacp.GetApplicationName();
63 }
64}
22 65
23AppLoader_DeconstructedRomDirectory::AppLoader_DeconstructedRomDirectory( 66AppLoader_DeconstructedRomDirectory::AppLoader_DeconstructedRomDirectory(
24 FileSys::VirtualDir directory) 67 FileSys::VirtualDir directory)
@@ -105,4 +148,25 @@ ResultStatus AppLoader_DeconstructedRomDirectory::ReadRomFS(FileSys::VirtualFile
105 return ResultStatus::Success; 148 return ResultStatus::Success;
106} 149}
107 150
151ResultStatus AppLoader_DeconstructedRomDirectory::ReadIcon(std::vector<u8>& buffer) {
152 if (icon_data.empty())
153 return ResultStatus::ErrorNotUsed;
154 buffer = icon_data;
155 return ResultStatus::Success;
156}
157
158ResultStatus AppLoader_DeconstructedRomDirectory::ReadProgramId(u64& out_program_id) {
159 if (name.empty())
160 return ResultStatus::ErrorNotUsed;
161 out_program_id = title_id;
162 return ResultStatus::Success;
163}
164
165ResultStatus AppLoader_DeconstructedRomDirectory::ReadTitle(std::string& title) {
166 if (name.empty())
167 return ResultStatus::ErrorNotUsed;
168 title = name;
169 return ResultStatus::Success;
170}
171
108} // namespace Loader 172} // namespace Loader
diff --git a/src/core/loader/deconstructed_rom_directory.h b/src/core/loader/deconstructed_rom_directory.h
index 7d5433563..b20804f75 100644
--- a/src/core/loader/deconstructed_rom_directory.h
+++ b/src/core/loader/deconstructed_rom_directory.h
@@ -39,11 +39,18 @@ public:
39 ResultStatus Load(Kernel::SharedPtr<Kernel::Process>& process) override; 39 ResultStatus Load(Kernel::SharedPtr<Kernel::Process>& process) override;
40 40
41 ResultStatus ReadRomFS(FileSys::VirtualFile& dir) override; 41 ResultStatus ReadRomFS(FileSys::VirtualFile& dir) override;
42 ResultStatus ReadIcon(std::vector<u8>& buffer) override;
43 ResultStatus ReadProgramId(u64& out_program_id) override;
44 ResultStatus ReadTitle(std::string& title) override;
42 45
43private: 46private:
44 FileSys::ProgramMetadata metadata; 47 FileSys::ProgramMetadata metadata;
45 FileSys::VirtualFile romfs; 48 FileSys::VirtualFile romfs;
46 FileSys::VirtualDir dir; 49 FileSys::VirtualDir dir;
50
51 std::vector<u8> icon_data;
52 std::string name;
53 u64 title_id{};
47}; 54};
48 55
49} // namespace Loader 56} // namespace Loader
diff --git a/src/core/loader/loader.cpp b/src/core/loader/loader.cpp
index 57e6c0365..0781fb8c1 100644
--- a/src/core/loader/loader.cpp
+++ b/src/core/loader/loader.cpp
@@ -68,7 +68,7 @@ FileType GuessFromFilename(const std::string& name) {
68 return FileType::Unknown; 68 return FileType::Unknown;
69} 69}
70 70
71const char* GetFileTypeString(FileType type) { 71std::string GetFileTypeString(FileType type) {
72 switch (type) { 72 switch (type) {
73 case FileType::ELF: 73 case FileType::ELF:
74 return "ELF"; 74 return "ELF";
diff --git a/src/core/loader/loader.h b/src/core/loader/loader.h
index e69ab85ef..7bd0adedb 100644
--- a/src/core/loader/loader.h
+++ b/src/core/loader/loader.h
@@ -61,7 +61,7 @@ FileType GuessFromFilename(const std::string& name);
61/** 61/**
62 * Convert a FileType into a string which can be displayed to the user. 62 * Convert a FileType into a string which can be displayed to the user.
63 */ 63 */
64const char* GetFileTypeString(FileType type); 64std::string GetFileTypeString(FileType type);
65 65
66/// Return type for functions in Loader namespace 66/// Return type for functions in Loader namespace
67enum class ResultStatus { 67enum class ResultStatus {
diff --git a/src/core/loader/nca.cpp b/src/core/loader/nca.cpp
index dbc67c0b5..46f5cd393 100644
--- a/src/core/loader/nca.cpp
+++ b/src/core/loader/nca.cpp
@@ -77,8 +77,8 @@ ResultStatus AppLoader_NCA::ReadRomFS(FileSys::VirtualFile& dir) {
77} 77}
78 78
79ResultStatus AppLoader_NCA::ReadProgramId(u64& out_program_id) { 79ResultStatus AppLoader_NCA::ReadProgramId(u64& out_program_id) {
80 if (nca == nullptr) 80 if (nca == nullptr || nca->GetStatus() != ResultStatus::Success)
81 return ResultStatus::ErrorNotLoaded; 81 return ResultStatus::ErrorInvalidFormat;
82 out_program_id = nca->GetTitleId(); 82 out_program_id = nca->GetTitleId();
83 return ResultStatus::Success; 83 return ResultStatus::Success;
84} 84}
diff --git a/src/core/loader/nca.h b/src/core/loader/nca.h
index 0fd2d0417..7f7d8ea0b 100644
--- a/src/core/loader/nca.h
+++ b/src/core/loader/nca.h
@@ -33,7 +33,6 @@ public:
33 ResultStatus Load(Kernel::SharedPtr<Kernel::Process>& process) override; 33 ResultStatus Load(Kernel::SharedPtr<Kernel::Process>& process) override;
34 34
35 ResultStatus ReadRomFS(FileSys::VirtualFile& dir) override; 35 ResultStatus ReadRomFS(FileSys::VirtualFile& dir) override;
36
37 ResultStatus ReadProgramId(u64& out_program_id) override; 36 ResultStatus ReadProgramId(u64& out_program_id) override;
38 37
39 ~AppLoader_NCA(); 38 ~AppLoader_NCA();
@@ -41,6 +40,7 @@ public:
41private: 40private:
42 FileSys::ProgramMetadata metadata; 41 FileSys::ProgramMetadata metadata;
43 42
43 FileSys::NCAHeader header;
44 std::unique_ptr<FileSys::NCA> nca; 44 std::unique_ptr<FileSys::NCA> nca;
45 std::unique_ptr<AppLoader_DeconstructedRomDirectory> directory_loader; 45 std::unique_ptr<AppLoader_DeconstructedRomDirectory> directory_loader;
46}; 46};
diff --git a/src/core/loader/xci.cpp b/src/core/loader/xci.cpp
index eb4dee2c2..d3fe24419 100644
--- a/src/core/loader/xci.cpp
+++ b/src/core/loader/xci.cpp
@@ -26,7 +26,25 @@ namespace Loader {
26AppLoader_XCI::AppLoader_XCI(FileSys::VirtualFile file) 26AppLoader_XCI::AppLoader_XCI(FileSys::VirtualFile file)
27 : AppLoader(file), xci(std::make_unique<FileSys::XCI>(file)), 27 : AppLoader(file), xci(std::make_unique<FileSys::XCI>(file)),
28 nca_loader(std::make_unique<AppLoader_NCA>( 28 nca_loader(std::make_unique<AppLoader_NCA>(
29 xci->GetNCAFileByType(FileSys::NCAContentType::Program))) {} 29 xci->GetNCAFileByType(FileSys::NCAContentType::Program))) {
30 if (xci->GetStatus() != ResultStatus::Success)
31 return;
32 const auto control_nca = xci->GetNCAByType(FileSys::NCAContentType::Control);
33 if (control_nca == nullptr || control_nca->GetStatus() != ResultStatus::Success)
34 return;
35 const auto romfs = FileSys::ExtractRomFS(control_nca->GetRomFS());
36 if (romfs == nullptr)
37 return;
38 for (const auto& language : FileSys::LANGUAGE_NAMES) {
39 icon_file = romfs->GetFile("icon_" + std::string(language) + ".dat");
40 if (icon_file != nullptr)
41 break;
42 }
43 const auto nacp_raw = romfs->GetFile("control.nacp");
44 if (nacp_raw == nullptr)
45 return;
46 nacp_file = std::make_shared<FileSys::NACP>(nacp_raw);
47}
30 48
31AppLoader_XCI::~AppLoader_XCI() = default; 49AppLoader_XCI::~AppLoader_XCI() = default;
32 50
@@ -71,4 +89,17 @@ ResultStatus AppLoader_XCI::ReadProgramId(u64& out_program_id) {
71 return nca_loader->ReadProgramId(out_program_id); 89 return nca_loader->ReadProgramId(out_program_id);
72} 90}
73 91
92ResultStatus AppLoader_XCI::ReadIcon(std::vector<u8>& buffer) {
93 if (icon_file == nullptr)
94 return ResultStatus::ErrorInvalidFormat;
95 buffer = icon_file->ReadAllBytes();
96 return ResultStatus::Success;
97}
98
99ResultStatus AppLoader_XCI::ReadTitle(std::string& title) {
100 if (nacp_file == nullptr)
101 return ResultStatus::ErrorInvalidFormat;
102 title = nacp_file->GetApplicationName();
103 return ResultStatus::Success;
104}
74} // namespace Loader 105} // namespace Loader
diff --git a/src/core/loader/xci.h b/src/core/loader/xci.h
index 0dbcfbdf8..973833050 100644
--- a/src/core/loader/xci.h
+++ b/src/core/loader/xci.h
@@ -33,12 +33,17 @@ public:
33 33
34 ResultStatus ReadRomFS(FileSys::VirtualFile& dir) override; 34 ResultStatus ReadRomFS(FileSys::VirtualFile& dir) override;
35 ResultStatus ReadProgramId(u64& out_program_id) override; 35 ResultStatus ReadProgramId(u64& out_program_id) override;
36 ResultStatus ReadIcon(std::vector<u8>& buffer) override;
37 ResultStatus ReadTitle(std::string& title) override;
36 38
37private: 39private:
38 FileSys::ProgramMetadata metadata; 40 FileSys::ProgramMetadata metadata;
39 41
40 std::unique_ptr<FileSys::XCI> xci; 42 std::unique_ptr<FileSys::XCI> xci;
41 std::unique_ptr<AppLoader_NCA> nca_loader; 43 std::unique_ptr<AppLoader_NCA> nca_loader;
44
45 FileSys::VirtualFile icon_file;
46 std::shared_ptr<FileSys::NACP> nacp_file;
42}; 47};
43 48
44} // namespace Loader 49} // namespace Loader
diff --git a/src/tests/common/param_package.cpp b/src/tests/common/param_package.cpp
index 19d372236..4c0f9654f 100644
--- a/src/tests/common/param_package.cpp
+++ b/src/tests/common/param_package.cpp
@@ -2,7 +2,7 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <catch.hpp> 5#include <catch2/catch.hpp>
6#include <math.h> 6#include <math.h>
7#include "common/param_package.h" 7#include "common/param_package.h"
8 8
diff --git a/src/tests/core/core_timing.cpp b/src/tests/core/core_timing.cpp
index fcaa30990..2242c14cf 100644
--- a/src/tests/core/core_timing.cpp
+++ b/src/tests/core/core_timing.cpp
@@ -2,7 +2,7 @@
2// Licensed under GPLv2+ 2// Licensed under GPLv2+
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <catch.hpp> 5#include <catch2/catch.hpp>
6 6
7#include <array> 7#include <array>
8#include <bitset> 8#include <bitset>
diff --git a/src/tests/glad.cpp b/src/tests/glad.cpp
index b0b016440..1797c0e3d 100644
--- a/src/tests/glad.cpp
+++ b/src/tests/glad.cpp
@@ -2,7 +2,7 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <catch.hpp> 5#include <catch2/catch.hpp>
6#include <glad/glad.h> 6#include <glad/glad.h>
7 7
8// This is not an actual test, but a work-around for issue #2183. 8// This is not an actual test, but a work-around for issue #2183.
diff --git a/src/tests/tests.cpp b/src/tests/tests.cpp
index 73978676f..275b430d9 100644
--- a/src/tests/tests.cpp
+++ b/src/tests/tests.cpp
@@ -3,7 +3,7 @@
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#define CATCH_CONFIG_MAIN 5#define CATCH_CONFIG_MAIN
6#include <catch.hpp> 6#include <catch2/catch.hpp>
7 7
8// Catch provides the main function since we've given it the 8// Catch provides the main function since we've given it the
9// CATCH_CONFIG_MAIN preprocessor directive. 9// CATCH_CONFIG_MAIN preprocessor directive.
diff --git a/src/yuzu/CMakeLists.txt b/src/yuzu/CMakeLists.txt
index 475556806..46ed232d8 100644
--- a/src/yuzu/CMakeLists.txt
+++ b/src/yuzu/CMakeLists.txt
@@ -17,6 +17,8 @@ add_executable(yuzu
17 configuration/configure_debug.h 17 configuration/configure_debug.h
18 configuration/configure_dialog.cpp 18 configuration/configure_dialog.cpp
19 configuration/configure_dialog.h 19 configuration/configure_dialog.h
20 configuration/configure_gamelist.cpp
21 configuration/configure_gamelist.h
20 configuration/configure_general.cpp 22 configuration/configure_general.cpp
21 configuration/configure_general.h 23 configuration/configure_general.h
22 configuration/configure_graphics.cpp 24 configuration/configure_graphics.cpp
@@ -59,6 +61,7 @@ set(UIS
59 configuration/configure.ui 61 configuration/configure.ui
60 configuration/configure_audio.ui 62 configuration/configure_audio.ui
61 configuration/configure_debug.ui 63 configuration/configure_debug.ui
64 configuration/configure_gamelist.ui
62 configuration/configure_general.ui 65 configuration/configure_general.ui
63 configuration/configure_graphics.ui 66 configuration/configure_graphics.ui
64 configuration/configure_input.ui 67 configuration/configure_input.ui
diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp
index bf469ee73..0bd46dbac 100644
--- a/src/yuzu/configuration/config.cpp
+++ b/src/yuzu/configuration/config.cpp
@@ -122,6 +122,13 @@ void Config::ReadValues() {
122 qt_config->beginGroup("UI"); 122 qt_config->beginGroup("UI");
123 UISettings::values.theme = qt_config->value("theme", UISettings::themes[0].second).toString(); 123 UISettings::values.theme = qt_config->value("theme", UISettings::themes[0].second).toString();
124 124
125 qt_config->beginGroup("UIGameList");
126 UISettings::values.show_unknown = qt_config->value("show_unknown", true).toBool();
127 UISettings::values.icon_size = qt_config->value("icon_size", 48).toUInt();
128 UISettings::values.row_1_text_id = qt_config->value("row_1_text_id", 0).toUInt();
129 UISettings::values.row_2_text_id = qt_config->value("row_2_text_id", 3).toUInt();
130 qt_config->endGroup();
131
125 qt_config->beginGroup("UILayout"); 132 qt_config->beginGroup("UILayout");
126 UISettings::values.geometry = qt_config->value("geometry").toByteArray(); 133 UISettings::values.geometry = qt_config->value("geometry").toByteArray();
127 UISettings::values.state = qt_config->value("state").toByteArray(); 134 UISettings::values.state = qt_config->value("state").toByteArray();
@@ -234,6 +241,13 @@ void Config::SaveValues() {
234 qt_config->beginGroup("UI"); 241 qt_config->beginGroup("UI");
235 qt_config->setValue("theme", UISettings::values.theme); 242 qt_config->setValue("theme", UISettings::values.theme);
236 243
244 qt_config->beginGroup("UIGameList");
245 qt_config->setValue("show_unknown", UISettings::values.show_unknown);
246 qt_config->setValue("icon_size", UISettings::values.icon_size);
247 qt_config->setValue("row_1_text_id", UISettings::values.row_1_text_id);
248 qt_config->setValue("row_2_text_id", UISettings::values.row_2_text_id);
249 qt_config->endGroup();
250
237 qt_config->beginGroup("UILayout"); 251 qt_config->beginGroup("UILayout");
238 qt_config->setValue("geometry", UISettings::values.geometry); 252 qt_config->setValue("geometry", UISettings::values.geometry);
239 qt_config->setValue("state", UISettings::values.state); 253 qt_config->setValue("state", UISettings::values.state);
diff --git a/src/yuzu/configuration/configure.ui b/src/yuzu/configuration/configure.ui
index c8e0b88af..20f120134 100644
--- a/src/yuzu/configuration/configure.ui
+++ b/src/yuzu/configuration/configure.ui
@@ -24,6 +24,11 @@
24 <string>General</string> 24 <string>General</string>
25 </attribute> 25 </attribute>
26 </widget> 26 </widget>
27 <widget class="ConfigureGameList" name="gameListTab">
28 <attribute name="title">
29 <string>Game List</string>
30 </attribute>
31 </widget>
27 <widget class="ConfigureSystem" name="systemTab"> 32 <widget class="ConfigureSystem" name="systemTab">
28 <attribute name="title"> 33 <attribute name="title">
29 <string>System</string> 34 <string>System</string>
@@ -67,6 +72,12 @@
67 <header>configuration/configure_general.h</header> 72 <header>configuration/configure_general.h</header>
68 <container>1</container> 73 <container>1</container>
69 </customwidget> 74 </customwidget>
75 <customwidget>
76 <class>ConfigureGameList</class>
77 <extends>QWidget</extends>
78 <header>configuration/configure_gamelist.h</header>
79 <container>1</container>
80 </customwidget>
70 <customwidget> 81 <customwidget>
71 <class>ConfigureSystem</class> 82 <class>ConfigureSystem</class>
72 <extends>QWidget</extends> 83 <extends>QWidget</extends>
diff --git a/src/yuzu/configuration/configure_dialog.cpp b/src/yuzu/configuration/configure_dialog.cpp
index cc4b326ae..daa4cc0d9 100644
--- a/src/yuzu/configuration/configure_dialog.cpp
+++ b/src/yuzu/configuration/configure_dialog.cpp
@@ -21,6 +21,7 @@ void ConfigureDialog::setConfiguration() {}
21 21
22void ConfigureDialog::applyConfiguration() { 22void ConfigureDialog::applyConfiguration() {
23 ui->generalTab->applyConfiguration(); 23 ui->generalTab->applyConfiguration();
24 ui->gameListTab->applyConfiguration();
24 ui->systemTab->applyConfiguration(); 25 ui->systemTab->applyConfiguration();
25 ui->inputTab->applyConfiguration(); 26 ui->inputTab->applyConfiguration();
26 ui->graphicsTab->applyConfiguration(); 27 ui->graphicsTab->applyConfiguration();
diff --git a/src/yuzu/configuration/configure_gamelist.cpp b/src/yuzu/configuration/configure_gamelist.cpp
new file mode 100644
index 000000000..1ae3423cf
--- /dev/null
+++ b/src/yuzu/configuration/configure_gamelist.cpp
@@ -0,0 +1,63 @@
1// Copyright 2016 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include "core/core.h"
6#include "core/settings.h"
7#include "ui_configure_gamelist.h"
8#include "ui_settings.h"
9#include "yuzu/configuration/configure_gamelist.h"
10
11ConfigureGameList::ConfigureGameList(QWidget* parent)
12 : QWidget(parent), ui(new Ui::ConfigureGameList) {
13 ui->setupUi(this);
14
15 static const std::vector<std::pair<u32, std::string>> default_icon_sizes{
16 std::make_pair(0, "None"), std::make_pair(32, "Small"),
17 std::make_pair(64, "Standard"), std::make_pair(128, "Large"),
18 std::make_pair(256, "Full Size"),
19 };
20
21 for (const auto& size : default_icon_sizes) {
22 ui->icon_size_combobox->addItem(QString::fromStdString(size.second + " (" +
23 std::to_string(size.first) + "x" +
24 std::to_string(size.first) + ")"),
25 size.first);
26 }
27
28 static const std::vector<std::string> row_text_names{
29 "Filename",
30 "Filetype",
31 "Title ID",
32 "Title Name",
33 };
34
35 for (size_t i = 0; i < row_text_names.size(); ++i) {
36 ui->row_1_text_combobox->addItem(QString::fromStdString(row_text_names[i]),
37 QVariant::fromValue(i));
38 ui->row_2_text_combobox->addItem(QString::fromStdString(row_text_names[i]),
39 QVariant::fromValue(i));
40 }
41
42 this->setConfiguration();
43}
44
45ConfigureGameList::~ConfigureGameList() {}
46
47void ConfigureGameList::setConfiguration() {
48 ui->show_unknown->setChecked(UISettings::values.show_unknown);
49 ui->icon_size_combobox->setCurrentIndex(
50 ui->icon_size_combobox->findData(UISettings::values.icon_size));
51 ui->row_1_text_combobox->setCurrentIndex(
52 ui->row_1_text_combobox->findData(UISettings::values.row_1_text_id));
53 ui->row_2_text_combobox->setCurrentIndex(
54 ui->row_2_text_combobox->findData(UISettings::values.row_2_text_id));
55}
56
57void ConfigureGameList::applyConfiguration() {
58 UISettings::values.show_unknown = ui->show_unknown->isChecked();
59 UISettings::values.icon_size = ui->icon_size_combobox->currentData().toUInt();
60 UISettings::values.row_1_text_id = ui->row_1_text_combobox->currentData().toUInt();
61 UISettings::values.row_2_text_id = ui->row_2_text_combobox->currentData().toUInt();
62 Settings::Apply();
63}
diff --git a/src/yuzu/configuration/configure_gamelist.h b/src/yuzu/configuration/configure_gamelist.h
new file mode 100644
index 000000000..94fba6373
--- /dev/null
+++ b/src/yuzu/configuration/configure_gamelist.h
@@ -0,0 +1,28 @@
1// Copyright 2016 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include <memory>
8#include <QWidget>
9
10namespace Ui {
11class ConfigureGameList;
12}
13
14class ConfigureGameList : public QWidget {
15 Q_OBJECT
16
17public:
18 explicit ConfigureGameList(QWidget* parent = nullptr);
19 ~ConfigureGameList();
20
21 void applyConfiguration();
22
23private:
24 void setConfiguration();
25
26private:
27 std::unique_ptr<Ui::ConfigureGameList> ui;
28};
diff --git a/src/yuzu/configuration/configure_gamelist.ui b/src/yuzu/configuration/configure_gamelist.ui
new file mode 100644
index 000000000..7471fdb60
--- /dev/null
+++ b/src/yuzu/configuration/configure_gamelist.ui
@@ -0,0 +1,126 @@
1<?xml version="1.0" encoding="UTF-8"?>
2<ui version="4.0">
3 <class>ConfigureGameList</class>
4 <widget class="QWidget" name="ConfigureGeneral">
5 <property name="geometry">
6 <rect>
7 <x>0</x>
8 <y>0</y>
9 <width>300</width>
10 <height>377</height>
11 </rect>
12 </property>
13 <property name="windowTitle">
14 <string>Form</string>
15 </property>
16 <layout class="QHBoxLayout" name="HorizontalLayout">
17 <item>
18 <layout class="QVBoxLayout" name="VerticalLayout">
19 <item>
20 <widget class="QGroupBox" name="GeneralGroupBox">
21 <property name="title">
22 <string>General</string>
23 </property>
24 <layout class="QHBoxLayout" name="GeneralHorizontalLayout">
25 <item>
26 <layout class="QVBoxLayout" name="GeneralVerticalLayout">
27 <item>
28 <widget class="QCheckBox" name="show_unknown">
29 <property name="text">
30 <string>Show files with type 'Unknown'</string>
31 </property>
32 </widget>
33 </item>
34 </layout>
35 </item>
36 </layout>
37 </widget>
38 </item>
39 <item>
40 <widget class="QGroupBox" name="IconSizeGroupBox">
41 <property name="title">
42 <string>Icon Size</string>
43 </property>
44 <layout class="QHBoxLayout" name="icon_size_qhbox_layout">
45 <item>
46 <layout class="QVBoxLayout" name="icon_size_qvbox_layout">
47 <item>
48 <layout class="QHBoxLayout" name="icon_size_qhbox_layout_2">
49 <item>
50 <widget class="QLabel" name="icon_size_label">
51 <property name="text">
52 <string>Icon Size:</string>
53 </property>
54 </widget>
55 </item>
56 <item>
57 <widget class="QComboBox" name="icon_size_combobox"/>
58 </item>
59 </layout>
60 </item>
61 </layout>
62 </item>
63 </layout>
64 </widget>
65 </item>
66 <item>
67 <widget class="QGroupBox" name="RowGroupBox">
68 <property name="title">
69 <string>Row Text</string>
70 </property>
71 <layout class="QHBoxLayout" name="RowHorizontalLayout">
72 <item>
73 <layout class="QVBoxLayout" name="RowVerticalLayout">
74 <item>
75 <layout class="QHBoxLayout" name="row_1_qhbox_layout">
76 <item>
77 <widget class="QLabel" name="row_1_label">
78 <property name="text">
79 <string>Row 1 Text:</string>
80 </property>
81 </widget>
82 </item>
83 <item>
84 <widget class="QComboBox" name="row_1_text_combobox"/>
85 </item>
86 </layout>
87 </item>
88 <item>
89 <layout class="QHBoxLayout" name="row_2_qhbox_layout">
90 <item>
91 <widget class="QLabel" name="row_2_label">
92 <property name="text">
93 <string>Row 2 Text:</string>
94 </property>
95 </widget>
96 </item>
97 <item>
98 <widget class="QComboBox" name="row_2_text_combobox"/>
99 </item>
100 </layout>
101 </item>
102 </layout>
103 </item>
104 </layout>
105 </widget>
106 </item>
107 <item>
108 <spacer name="verticalSpacer">
109 <property name="orientation">
110 <enum>Qt::Vertical</enum>
111 </property>
112 <property name="sizeHint" stdset="0">
113 <size>
114 <width>20</width>
115 <height>40</height>
116 </size>
117 </property>
118 </spacer>
119 </item>
120 </layout>
121 </item>
122 </layout>
123 </widget>
124 <resources/>
125 <connections/>
126</ui>
diff --git a/src/yuzu/game_list.cpp b/src/yuzu/game_list.cpp
index 24f38a3c7..5f47f5a2b 100644
--- a/src/yuzu/game_list.cpp
+++ b/src/yuzu/game_list.cpp
@@ -9,9 +9,12 @@
9#include <QKeyEvent> 9#include <QKeyEvent>
10#include <QMenu> 10#include <QMenu>
11#include <QThreadPool> 11#include <QThreadPool>
12#include <boost/container/flat_map.hpp>
12#include "common/common_paths.h" 13#include "common/common_paths.h"
13#include "common/logging/log.h" 14#include "common/logging/log.h"
14#include "common/string_util.h" 15#include "common/string_util.h"
16#include "core/file_sys/content_archive.h"
17#include "core/file_sys/control_metadata.h"
15#include "core/file_sys/vfs_real.h" 18#include "core/file_sys/vfs_real.h"
16#include "core/loader/loader.h" 19#include "core/loader/loader.h"
17#include "game_list.h" 20#include "game_list.h"
@@ -398,8 +401,32 @@ void GameList::RefreshGameDirectory() {
398} 401}
399 402
400void GameListWorker::AddFstEntriesToGameList(const std::string& dir_path, unsigned int recursion) { 403void GameListWorker::AddFstEntriesToGameList(const std::string& dir_path, unsigned int recursion) {
401 const auto callback = [this, recursion](u64* num_entries_out, const std::string& directory, 404 boost::container::flat_map<u64, std::shared_ptr<FileSys::NCA>> nca_control_map;
402 const std::string& virtual_name) -> bool { 405
406 const auto nca_control_callback =
407 [this, &nca_control_map](u64* num_entries_out, const std::string& directory,
408 const std::string& virtual_name) -> bool {
409 std::string physical_name = directory + DIR_SEP + virtual_name;
410
411 if (stop_processing)
412 return false; // Breaks the callback loop.
413
414 bool is_dir = FileUtil::IsDirectory(physical_name);
415 QFileInfo file_info(physical_name.c_str());
416 if (!is_dir && file_info.suffix().toStdString() == "nca") {
417 auto nca = std::make_shared<FileSys::NCA>(
418 std::make_shared<FileSys::RealVfsFile>(physical_name));
419 if (nca->GetType() == FileSys::NCAContentType::Control)
420 nca_control_map.insert_or_assign(nca->GetTitleId(), nca);
421 }
422 return true;
423 };
424
425 FileUtil::ForeachDirectoryEntry(nullptr, dir_path, nca_control_callback);
426
427 const auto callback = [this, recursion,
428 &nca_control_map](u64* num_entries_out, const std::string& directory,
429 const std::string& virtual_name) -> bool {
403 std::string physical_name = directory + DIR_SEP + virtual_name; 430 std::string physical_name = directory + DIR_SEP + virtual_name;
404 431
405 if (stop_processing) 432 if (stop_processing)
@@ -410,17 +437,50 @@ void GameListWorker::AddFstEntriesToGameList(const std::string& dir_path, unsign
410 (HasSupportedFileExtension(physical_name) || IsExtractedNCAMain(physical_name))) { 437 (HasSupportedFileExtension(physical_name) || IsExtractedNCAMain(physical_name))) {
411 std::unique_ptr<Loader::AppLoader> loader = 438 std::unique_ptr<Loader::AppLoader> loader =
412 Loader::GetLoader(std::make_shared<FileSys::RealVfsFile>(physical_name)); 439 Loader::GetLoader(std::make_shared<FileSys::RealVfsFile>(physical_name));
413 if (!loader) 440 if (!loader || ((loader->GetFileType() == Loader::FileType::Unknown ||
441 loader->GetFileType() == Loader::FileType::Error) &&
442 !UISettings::values.show_unknown))
414 return true; 443 return true;
415 444
416 std::vector<u8> smdh; 445 std::vector<u8> icon;
417 loader->ReadIcon(smdh); 446 const auto res1 = loader->ReadIcon(icon);
418 447
419 u64 program_id = 0; 448 u64 program_id;
420 loader->ReadProgramId(program_id); 449 const auto res2 = loader->ReadProgramId(program_id);
450
451 std::string name = " ";
452 const auto res3 = loader->ReadTitle(name);
453
454 if ((res1 == Loader::ResultStatus::ErrorNotUsed ||
455 res1 == Loader::ResultStatus::ErrorNotImplemented) &&
456 (res3 == Loader::ResultStatus::ErrorNotUsed ||
457 res3 == Loader::ResultStatus::ErrorNotImplemented) &&
458 res2 == Loader::ResultStatus::Success) {
459 // Use from metadata pool.
460 if (nca_control_map.find(program_id) != nca_control_map.end()) {
461 const auto nca = nca_control_map[program_id];
462 const auto control_dir = nca->GetSubdirectories()[0];
463
464 const auto nacp_file = control_dir->GetFile("control.nacp");
465 FileSys::NACP nacp(nacp_file);
466 name = nacp.GetApplicationName();
467
468 FileSys::VirtualFile icon_file = nullptr;
469 for (const auto& language : FileSys::LANGUAGE_NAMES) {
470 icon_file = control_dir->GetFile("icon_" + std::string(language) + ".dat");
471 if (icon_file != nullptr) {
472 icon = icon_file->ReadAllBytes();
473 break;
474 }
475 }
476 }
477 }
421 478
422 emit EntryReady({ 479 emit EntryReady({
423 new GameListItemPath(FormatGameName(physical_name), smdh, program_id), 480 new GameListItemPath(
481 FormatGameName(physical_name), icon, QString::fromStdString(name),
482 QString::fromStdString(Loader::GetFileTypeString(loader->GetFileType())),
483 program_id),
424 new GameListItem( 484 new GameListItem(
425 QString::fromStdString(Loader::GetFileTypeString(loader->GetFileType()))), 485 QString::fromStdString(Loader::GetFileTypeString(loader->GetFileType()))),
426 new GameListItemSize(FileUtil::GetSize(physical_name)), 486 new GameListItemSize(FileUtil::GetSize(physical_name)),
diff --git a/src/yuzu/game_list_p.h b/src/yuzu/game_list_p.h
index aa69a098f..a22025e67 100644
--- a/src/yuzu/game_list_p.h
+++ b/src/yuzu/game_list_p.h
@@ -11,6 +11,7 @@
11#include <QStandardItem> 11#include <QStandardItem>
12#include <QString> 12#include <QString>
13#include "common/string_util.h" 13#include "common/string_util.h"
14#include "ui_settings.h"
14#include "yuzu/util/util.h" 15#include "yuzu/util/util.h"
15 16
16/** 17/**
@@ -18,8 +19,7 @@
18 * @param large If true, returns large icon (48x48), otherwise returns small icon (24x24) 19 * @param large If true, returns large icon (48x48), otherwise returns small icon (24x24)
19 * @return QPixmap default icon 20 * @return QPixmap default icon
20 */ 21 */
21static QPixmap GetDefaultIcon(bool large) { 22static QPixmap GetDefaultIcon(u32 size) {
22 int size = large ? 48 : 24;
23 QPixmap icon(size, size); 23 QPixmap icon(size, size);
24 icon.fill(Qt::transparent); 24 icon.fill(Qt::transparent);
25 return icon; 25 return icon;
@@ -44,11 +44,25 @@ public:
44 static const int FullPathRole = Qt::UserRole + 1; 44 static const int FullPathRole = Qt::UserRole + 1;
45 static const int TitleRole = Qt::UserRole + 2; 45 static const int TitleRole = Qt::UserRole + 2;
46 static const int ProgramIdRole = Qt::UserRole + 3; 46 static const int ProgramIdRole = Qt::UserRole + 3;
47 static const int FileTypeRole = Qt::UserRole + 4;
47 48
48 GameListItemPath() = default; 49 GameListItemPath() = default;
49 GameListItemPath(const QString& game_path, const std::vector<u8>& smdh_data, u64 program_id) { 50 GameListItemPath(const QString& game_path, const std::vector<u8>& picture_data,
51 const QString& game_name, const QString& game_type, u64 program_id)
52 : GameListItem() {
50 setData(game_path, FullPathRole); 53 setData(game_path, FullPathRole);
54 setData(game_name, TitleRole);
51 setData(qulonglong(program_id), ProgramIdRole); 55 setData(qulonglong(program_id), ProgramIdRole);
56 setData(game_type, FileTypeRole);
57
58 QPixmap picture;
59 u32 size = UISettings::values.icon_size;
60 if (!picture.loadFromData(picture_data.data(), picture_data.size()))
61 picture = GetDefaultIcon(size);
62
63 picture = picture.scaled(size, size);
64
65 setData(picture, Qt::DecorationRole);
52 } 66 }
53 67
54 QVariant data(int role) const override { 68 QVariant data(int role) const override {
@@ -57,7 +71,23 @@ public:
57 Common::SplitPath(data(FullPathRole).toString().toStdString(), nullptr, &filename, 71 Common::SplitPath(data(FullPathRole).toString().toStdString(), nullptr, &filename,
58 nullptr); 72 nullptr);
59 QString title = data(TitleRole).toString(); 73 QString title = data(TitleRole).toString();
60 return QString::fromStdString(filename) + (title.isEmpty() ? "" : "\n " + title); 74
75 std::vector<QString> row_data{
76 QString::fromStdString(filename),
77 data(FileTypeRole).toString(),
78 QString::fromStdString(fmt::format("0x{:016X}", data(ProgramIdRole).toULongLong())),
79 data(TitleRole).toString(),
80 };
81
82 auto row1 = row_data.at(UISettings::values.row_1_text_id);
83 auto row2 = row_data.at(UISettings::values.row_2_text_id);
84
85 if (row1.isEmpty() || row1 == row2)
86 return row2;
87 if (row2.isEmpty())
88 return row1;
89
90 return row1 + "\n " + row2;
61 } else { 91 } else {
62 return GameListItem::data(role); 92 return GameListItem::data(role);
63 } 93 }
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index 17ed62c72..a6241e63e 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -768,6 +768,7 @@ void GMainWindow::OnConfigure() {
768 configureDialog.applyConfiguration(); 768 configureDialog.applyConfiguration();
769 if (UISettings::values.theme != old_theme) 769 if (UISettings::values.theme != old_theme)
770 UpdateUITheme(); 770 UpdateUITheme();
771 game_list->PopulateAsync(UISettings::values.gamedir, UISettings::values.gamedir_deepscan);
771 config->Save(); 772 config->Save();
772 } 773 }
773} 774}
diff --git a/src/yuzu/ui_settings.h b/src/yuzu/ui_settings.h
index 2286c2559..051494bc5 100644
--- a/src/yuzu/ui_settings.h
+++ b/src/yuzu/ui_settings.h
@@ -54,6 +54,12 @@ struct Values {
54 54
55 // logging 55 // logging
56 bool show_console; 56 bool show_console;
57
58 // Game List
59 bool show_unknown;
60 uint32_t icon_size;
61 uint8_t row_1_text_id;
62 uint8_t row_2_text_id;
57}; 63};
58 64
59extern Values values; 65extern Values values;