diff options
62 files changed, 757 insertions, 369 deletions
diff --git a/CMakeModules/CopyYuzuQt5Deps.cmake b/CMakeModules/CopyYuzuQt5Deps.cmake index e4a9796c8..aaf80b77b 100644 --- a/CMakeModules/CopyYuzuQt5Deps.cmake +++ b/CMakeModules/CopyYuzuQt5Deps.cmake | |||
| @@ -4,8 +4,10 @@ function(copy_yuzu_Qt5_deps target_dir) | |||
| 4 | set(Qt5_DLL_DIR "${Qt5_DIR}/../../../bin") | 4 | set(Qt5_DLL_DIR "${Qt5_DIR}/../../../bin") |
| 5 | set(Qt5_PLATFORMS_DIR "${Qt5_DIR}/../../../plugins/platforms/") | 5 | set(Qt5_PLATFORMS_DIR "${Qt5_DIR}/../../../plugins/platforms/") |
| 6 | set(Qt5_STYLES_DIR "${Qt5_DIR}/../../../plugins/styles/") | 6 | set(Qt5_STYLES_DIR "${Qt5_DIR}/../../../plugins/styles/") |
| 7 | set(Qt5_IMAGEFORMATS_DIR "${Qt5_DIR}/../../../plugins/imageformats/") | ||
| 7 | set(PLATFORMS ${DLL_DEST}platforms/) | 8 | set(PLATFORMS ${DLL_DEST}platforms/) |
| 8 | set(STYLES ${DLL_DEST}styles/) | 9 | set(STYLES ${DLL_DEST}styles/) |
| 10 | set(IMAGEFORMATS ${DLL_DEST}imageformats/) | ||
| 9 | windows_copy_files(${target_dir} ${Qt5_DLL_DIR} ${DLL_DEST} | 11 | windows_copy_files(${target_dir} ${Qt5_DLL_DIR} ${DLL_DEST} |
| 10 | icudt*.dll | 12 | icudt*.dll |
| 11 | icuin*.dll | 13 | icuin*.dll |
| @@ -17,4 +19,5 @@ function(copy_yuzu_Qt5_deps target_dir) | |||
| 17 | ) | 19 | ) |
| 18 | windows_copy_files(yuzu ${Qt5_PLATFORMS_DIR} ${PLATFORMS} qwindows$<$<CONFIG:Debug>:d>.*) | 20 | windows_copy_files(yuzu ${Qt5_PLATFORMS_DIR} ${PLATFORMS} qwindows$<$<CONFIG:Debug>:d>.*) |
| 19 | windows_copy_files(yuzu ${Qt5_STYLES_DIR} ${STYLES} qwindowsvistastyle$<$<CONFIG:Debug>:d>.*) | 21 | windows_copy_files(yuzu ${Qt5_STYLES_DIR} ${STYLES} qwindowsvistastyle$<$<CONFIG:Debug>:d>.*) |
| 22 | windows_copy_files(yuzu ${Qt5_IMAGEFORMATS_DIR} ${IMAGEFORMATS} qjpeg$<$<CONFIG:Debug>:d>.*) | ||
| 20 | endfunction(copy_yuzu_Qt5_deps) | 23 | endfunction(copy_yuzu_Qt5_deps) |
diff --git a/appveyor.yml b/appveyor.yml index 17d1b5fee..a6f12b267 100644 --- a/appveyor.yml +++ b/appveyor.yml | |||
| @@ -117,6 +117,7 @@ after_build: | |||
| 117 | mkdir $RELEASE_DIST | 117 | mkdir $RELEASE_DIST |
| 118 | mkdir $RELEASE_DIST/platforms | 118 | mkdir $RELEASE_DIST/platforms |
| 119 | mkdir $RELEASE_DIST/styles | 119 | mkdir $RELEASE_DIST/styles |
| 120 | mkdir $RELEASE_DIST/imageformats | ||
| 120 | 121 | ||
| 121 | # copy the compiled binaries and other release files to the release folder | 122 | # copy the compiled binaries and other release files to the release folder |
| 122 | Get-ChildItem "$CMAKE_BINARY_DIR" -Filter "yuzu*.exe" | Copy-Item -destination $RELEASE_DIST | 123 | Get-ChildItem "$CMAKE_BINARY_DIR" -Filter "yuzu*.exe" | Copy-Item -destination $RELEASE_DIST |
| @@ -140,6 +141,9 @@ after_build: | |||
| 140 | # copy the qt windows vista style dll to platforms | 141 | # copy the qt windows vista style dll to platforms |
| 141 | Copy-Item -path "C:/msys64/mingw64/share/qt5/plugins/styles/qwindowsvistastyle.dll" -force -destination "$RELEASE_DIST/styles" | 142 | Copy-Item -path "C:/msys64/mingw64/share/qt5/plugins/styles/qwindowsvistastyle.dll" -force -destination "$RELEASE_DIST/styles" |
| 142 | 143 | ||
| 144 | # copy the qt jpeg imageformat dll to platforms | ||
| 145 | Copy-Item -path "C:/msys64/mingw64/share/qt5/plugins/imageformats/qjpeg.dll" -force -destination "$RELEASE_DIST/imageformats" | ||
| 146 | |||
| 143 | 7z a -tzip $MINGW_BUILD_ZIP $RELEASE_DIST\* | 147 | 7z a -tzip $MINGW_BUILD_ZIP $RELEASE_DIST\* |
| 144 | 7z a $MINGW_SEVENZIP $RELEASE_DIST | 148 | 7z a $MINGW_SEVENZIP $RELEASE_DIST |
| 145 | } | 149 | } |
diff --git a/externals/CMakeLists.txt b/externals/CMakeLists.txt index db21f3d50..b6eb36f20 100644 --- a/externals/CMakeLists.txt +++ b/externals/CMakeLists.txt | |||
| @@ -32,7 +32,7 @@ add_subdirectory(inih) | |||
| 32 | 32 | ||
| 33 | # lz4 | 33 | # lz4 |
| 34 | set(LZ4_BUNDLED_MODE ON) | 34 | set(LZ4_BUNDLED_MODE ON) |
| 35 | add_subdirectory(lz4/contrib/cmake_unofficial) | 35 | add_subdirectory(lz4/contrib/cmake_unofficial EXCLUDE_FROM_ALL) |
| 36 | target_include_directories(lz4_static INTERFACE ./lz4/lib) | 36 | target_include_directories(lz4_static INTERFACE ./lz4/lib) |
| 37 | 37 | ||
| 38 | # mbedtls | 38 | # mbedtls |
diff --git a/externals/catch b/externals/catch | |||
| Subproject d2a130f2433aeaca070e3e4d6298a80049d21cf | Subproject 15cf3caaceb21172ea42a24e595a2eb58c3ec96 | ||
diff --git a/externals/mbedtls b/externals/mbedtls | |||
| Subproject 06b1b55434dd5d821e911583d629cff39a04b38 | Subproject d409b75a4cf75a5b358b352c75826ddbca44db5 | ||
diff --git a/src/common/alignment.h b/src/common/alignment.h index b77da4a92..b9dd38746 100644 --- a/src/common/alignment.h +++ b/src/common/alignment.h | |||
| @@ -9,13 +9,13 @@ namespace Common { | |||
| 9 | 9 | ||
| 10 | template <typename T> | 10 | template <typename T> |
| 11 | constexpr T AlignUp(T value, size_t size) { | 11 | constexpr T AlignUp(T value, size_t size) { |
| 12 | static_assert(std::is_unsigned<T>::value, "T must be an unsigned value."); | 12 | static_assert(std::is_unsigned_v<T>, "T must be an unsigned value."); |
| 13 | return static_cast<T>(value + (size - value % size) % size); | 13 | return static_cast<T>(value + (size - value % size) % size); |
| 14 | } | 14 | } |
| 15 | 15 | ||
| 16 | template <typename T> | 16 | template <typename T> |
| 17 | constexpr T AlignDown(T value, size_t size) { | 17 | constexpr T AlignDown(T value, size_t size) { |
| 18 | static_assert(std::is_unsigned<T>::value, "T must be an unsigned value."); | 18 | static_assert(std::is_unsigned_v<T>, "T must be an unsigned value."); |
| 19 | return static_cast<T>(value - value % size); | 19 | return static_cast<T>(value - value % size); |
| 20 | } | 20 | } |
| 21 | 21 | ||
diff --git a/src/common/bit_set.h b/src/common/bit_set.h index 84e3cbe58..5a197d8c1 100644 --- a/src/common/bit_set.h +++ b/src/common/bit_set.h | |||
| @@ -96,7 +96,7 @@ static inline int LeastSignificantSetBit(u64 val) { | |||
| 96 | 96 | ||
| 97 | template <typename IntTy> | 97 | template <typename IntTy> |
| 98 | class BitSet { | 98 | class BitSet { |
| 99 | static_assert(!std::is_signed<IntTy>::value, "BitSet should not be used with signed types"); | 99 | static_assert(!std::is_signed_v<IntTy>, "BitSet should not be used with signed types"); |
| 100 | 100 | ||
| 101 | public: | 101 | public: |
| 102 | // A reference to a particular bit, returned from operator[]. | 102 | // A reference to a particular bit, returned from operator[]. |
diff --git a/src/common/file_util.h b/src/common/file_util.h index 28697d527..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> |
| @@ -207,39 +208,42 @@ public: | |||
| 207 | 208 | ||
| 208 | template <typename T> | 209 | template <typename T> |
| 209 | size_t ReadArray(T* data, size_t length) const { | 210 | size_t ReadArray(T* data, size_t length) const { |
| 210 | static_assert(std::is_trivially_copyable<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 | } |
| 218 | 220 | ||
| 219 | template <typename T> | 221 | template <typename T> |
| 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<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 | ||
| 228 | template <typename T> | 232 | template <typename T> |
| 229 | size_t ReadBytes(T* data, size_t length) const { | 233 | size_t ReadBytes(T* data, size_t length) const { |
| 230 | static_assert(std::is_trivially_copyable<T>(), "T must be trivially copyable"); | 234 | static_assert(std::is_trivially_copyable_v<T>, "T must be trivially copyable"); |
| 231 | return ReadArray(reinterpret_cast<char*>(data), length); | 235 | return ReadArray(reinterpret_cast<char*>(data), length); |
| 232 | } | 236 | } |
| 233 | 237 | ||
| 234 | template <typename T> | 238 | template <typename T> |
| 235 | size_t WriteBytes(const T* data, size_t length) { | 239 | size_t WriteBytes(const T* data, size_t length) { |
| 236 | static_assert(std::is_trivially_copyable<T>(), "T must be trivially copyable"); | 240 | static_assert(std::is_trivially_copyable_v<T>, "T must be trivially copyable"); |
| 237 | return WriteArray(reinterpret_cast<const char*>(data), length); | 241 | return WriteArray(reinterpret_cast<const char*>(data), length); |
| 238 | } | 242 | } |
| 239 | 243 | ||
| 240 | template <typename T> | 244 | template <typename T> |
| 241 | size_t WriteObject(const T& object) { | 245 | size_t WriteObject(const T& object) { |
| 242 | static_assert(!std::is_pointer<T>::value, "Given object is a pointer"); | 246 | static_assert(!std::is_pointer_v<T>, "WriteObject arguments must not be a pointer"); |
| 243 | return WriteArray(&object, 1); | 247 | return WriteArray(&object, 1); |
| 244 | } | 248 | } |
| 245 | 249 | ||
diff --git a/src/common/hash.h b/src/common/hash.h index 73c326980..2c761e545 100644 --- a/src/common/hash.h +++ b/src/common/hash.h | |||
| @@ -28,7 +28,7 @@ static inline u64 ComputeHash64(const void* data, size_t len) { | |||
| 28 | */ | 28 | */ |
| 29 | template <typename T> | 29 | template <typename T> |
| 30 | static inline u64 ComputeStructHash64(const T& data) { | 30 | static inline u64 ComputeStructHash64(const T& data) { |
| 31 | static_assert(std::is_trivially_copyable<T>(), | 31 | static_assert(std::is_trivially_copyable_v<T>, |
| 32 | "Type passed to ComputeStructHash64 must be trivially copyable"); | 32 | "Type passed to ComputeStructHash64 must be trivially copyable"); |
| 33 | return ComputeHash64(&data, sizeof(data)); | 33 | return ComputeHash64(&data, sizeof(data)); |
| 34 | } | 34 | } |
| @@ -38,7 +38,7 @@ template <typename T> | |||
| 38 | struct HashableStruct { | 38 | struct HashableStruct { |
| 39 | // In addition to being trivially copyable, T must also have a trivial default constructor, | 39 | // In addition to being trivially copyable, T must also have a trivial default constructor, |
| 40 | // because any member initialization would be overridden by memset | 40 | // because any member initialization would be overridden by memset |
| 41 | static_assert(std::is_trivial<T>(), "Type passed to HashableStruct must be trivial"); | 41 | static_assert(std::is_trivial_v<T>, "Type passed to HashableStruct must be trivial"); |
| 42 | /* | 42 | /* |
| 43 | * We use a union because "implicitly-defined copy/move constructor for a union X copies the | 43 | * We use a union because "implicitly-defined copy/move constructor for a union X copies the |
| 44 | * object representation of X." and "implicitly-defined copy assignment operator for a union X | 44 | * object representation of X." and "implicitly-defined copy assignment operator for a union X |
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> | |||
| 43 | class Vec4; | 43 | class Vec4; |
| 44 | 44 | ||
| 45 | template <typename T> | 45 | template <typename T> |
| 46 | static inline Vec2<T> MakeVec(const T& x, const T& y); | ||
| 47 | template <typename T> | ||
| 48 | static inline Vec3<T> MakeVec(const T& x, const T& y, const T& z); | ||
| 49 | template <typename T> | ||
| 50 | static inline Vec4<T> MakeVec(const T& x, const T& y, const T& z, const T& w); | ||
| 51 | |||
| 52 | template <typename T> | ||
| 53 | class Vec2 { | 46 | class Vec2 { |
| 54 | public: | 47 | public: |
| 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 | ||
| 173 | template <typename T, typename V> | 169 | template <typename T, typename V> |
| 174 | Vec2<T> operator*(const V& f, const Vec2<T>& vec) { | 170 | constexpr 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 | ||
| 178 | typedef Vec2<float> Vec2f; | 174 | using Vec2f = Vec2<float>; |
| 179 | 175 | ||
| 180 | template <> | 176 | template <> |
| 181 | inline float Vec2<float>::Length() const { | 177 | inline 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 | ||
| 368 | template <typename T, typename V> | 368 | template <typename T, typename V> |
| 369 | Vec3<T> operator*(const V& f, const Vec3<T>& vec) { | 369 | constexpr 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 | ||
| 390 | typedef Vec3<float> Vec3f; | 390 | using Vec3f = Vec3<float>; |
| 391 | 391 | ||
| 392 | template <typename T> | 392 | template <typename T> |
| 393 | class Vec4 { | 393 | class 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 | ||
| 581 | template <typename T, typename V> | 583 | template <typename T, typename V> |
| 582 | Vec4<decltype(V{} * T{})> operator*(const V& f, const Vec4<T>& vec) { | 584 | constexpr 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 | ||
| 586 | typedef Vec4<float> Vec4f; | 588 | using Vec4f = Vec4<float>; |
| 587 | 589 | ||
| 588 | template <typename T> | 590 | template <typename T> |
| 589 | static inline decltype(T{} * T{} + T{} * T{}) Dot(const Vec2<T>& a, const Vec2<T>& b) { | 591 | constexpr 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 | ||
| 593 | template <typename T> | 595 | template <typename T> |
| 594 | static inline decltype(T{} * T{} + T{} * T{}) Dot(const Vec3<T>& a, const Vec3<T>& b) { | 596 | constexpr 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 | ||
| 598 | template <typename T> | 600 | template <typename T> |
| 599 | static inline decltype(T{} * T{} + T{} * T{}) Dot(const Vec4<T>& a, const Vec4<T>& b) { | 601 | constexpr 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 | ||
| 603 | template <typename T> | 605 | template <typename T> |
| 604 | static inline Vec3<decltype(T{} * T{} - T{} * T{})> Cross(const Vec3<T>& a, const Vec3<T>& b) { | 606 | constexpr 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 |
| 609 | template <typename X> | 611 | template <typename X> |
| 610 | static inline decltype(X{} * float{} + X{} * float{}) Lerp(const X& begin, const X& end, | 612 | constexpr 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 |
| 616 | template <typename X, int base> | 618 | template <typename X, int base> |
| 617 | static inline decltype((X{} * int{} + X{} * int{}) / base) LerpInt(const X& begin, const X& end, | 619 | constexpr 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. |
| 624 | template <typename X> | 626 | template <typename X> |
| 625 | inline auto BilinearInterp(const X& x00, const X& x01, const X& x10, const X& x11, const float s, | 627 | constexpr 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 |
| 633 | template <typename T> | 635 | template <typename T> |
| 634 | static inline Vec2<T> MakeVec(const T& x, const T& y) { | 636 | constexpr 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 | ||
| 638 | template <typename T> | 640 | template <typename T> |
| 639 | static inline Vec3<T> MakeVec(const T& x, const T& y, const T& z) { | 641 | constexpr 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 | ||
| 643 | template <typename T> | 645 | template <typename T> |
| 644 | static inline Vec4<T> MakeVec(const T& x, const T& y, const Vec2<T>& zw) { | 646 | constexpr 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 | ||
| 648 | template <typename T> | 650 | template <typename T> |
| 649 | static inline Vec3<T> MakeVec(const Vec2<T>& xy, const T& z) { | 651 | constexpr 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 | ||
| 653 | template <typename T> | 655 | template <typename T> |
| 654 | static inline Vec3<T> MakeVec(const T& x, const Vec2<T>& yz) { | 656 | constexpr 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 | ||
| 658 | template <typename T> | 660 | template <typename T> |
| 659 | static inline Vec4<T> MakeVec(const T& x, const T& y, const T& z, const T& w) { | 661 | constexpr 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 | ||
| 663 | template <typename T> | 665 | template <typename T> |
| 664 | static inline Vec4<T> MakeVec(const Vec2<T>& xy, const T& z, const T& w) { | 666 | constexpr 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 | ||
| 668 | template <typename T> | 670 | template <typename T> |
| 669 | static inline Vec4<T> MakeVec(const T& x, const Vec2<T>& yz, const T& w) { | 671 | constexpr 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. |
| 676 | template <typename T> | 678 | template <typename T> |
| 677 | static inline Vec4<T> MakeVec(const Vec2<T>& xy, const Vec2<T>& zw) { | 679 | constexpr 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 | ||
| 681 | template <typename T> | 683 | template <typename T> |
| 682 | static inline Vec4<T> MakeVec(const Vec3<T>& xyz, const T& w) { | 684 | constexpr 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 | ||
| 686 | template <typename T> | 688 | template <typename T> |
| 687 | static inline Vec4<T> MakeVec(const T& x, const Vec3<T>& yzw) { | 689 | constexpr 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/common/x64/xbyak_util.h b/src/common/x64/xbyak_util.h index 0f52f704b..ec76e0a47 100644 --- a/src/common/x64/xbyak_util.h +++ b/src/common/x64/xbyak_util.h | |||
| @@ -34,7 +34,7 @@ inline bool IsWithin2G(const Xbyak::CodeGenerator& code, uintptr_t target) { | |||
| 34 | 34 | ||
| 35 | template <typename T> | 35 | template <typename T> |
| 36 | inline void CallFarFunction(Xbyak::CodeGenerator& code, const T f) { | 36 | inline void CallFarFunction(Xbyak::CodeGenerator& code, const T f) { |
| 37 | static_assert(std::is_pointer<T>(), "Argument must be a (function) pointer."); | 37 | static_assert(std::is_pointer_v<T>, "Argument must be a (function) pointer."); |
| 38 | size_t addr = reinterpret_cast<size_t>(f); | 38 | size_t addr = reinterpret_cast<size_t>(f); |
| 39 | if (IsWithin2G(code, addr)) { | 39 | if (IsWithin2G(code, addr)) { |
| 40 | code.call(f); | 40 | code.call(f); |
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 | ||
| 172 | NCA::NCA(VirtualFile file_) : file(std::move(file_)) { | 172 | NCA::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 | ||
| 65 | static 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. |
| 67 | class NACP { | 74 | class 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 | |||
| 9 | namespace RomFS { | ||
| 10 | |||
| 11 | struct 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 | |||
| 24 | static_assert(sizeof(Header) == 0x28, "Header has incorrect size"); | ||
| 25 | |||
| 26 | struct 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 | |||
| 36 | static_assert(sizeof(DirectoryMetadata) == 0x18, "DirectoryMetadata has incorrect size"); | ||
| 37 | |||
| 38 | struct 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 | |||
| 48 | static_assert(sizeof(FileMetadata) == 0x20, "FileMetadata has incorrect size"); | ||
| 49 | |||
| 50 | static 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 | |||
| 56 | const 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 | |||
| 11 | namespace 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 | */ | ||
| 20 | const 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 | ||
| 122 | void 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 | |||
| 122 | void Module::Interface::GetUserExistence(Kernel::HLERequestContext& ctx) { | 129 | void 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 | ||
| 9 | ACC_SU::ACC_SU(std::shared_ptr<Module> module) : Module::Interface(std::move(module), "acc:su") { | 9 | ACC_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 | ||
| 9 | ACC_U0::ACC_U0(std::shared_ptr<Module> module) : Module::Interface(std::move(module), "acc:u0") { | 9 | ACC_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 | ||
| 9 | ACC_U1::ACC_U1(std::shared_ptr<Module> module) : Module::Interface(std::move(module), "acc:u1") { | 9 | ACC_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/am/am.cpp b/src/core/hle/service/am/am.cpp index 9404d6b8c..762763463 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp | |||
| @@ -136,7 +136,7 @@ ISelfController::ISelfController(std::shared_ptr<NVFlinger::NVFlinger> nvflinger | |||
| 136 | {16, &ISelfController::SetOutOfFocusSuspendingEnabled, "SetOutOfFocusSuspendingEnabled"}, | 136 | {16, &ISelfController::SetOutOfFocusSuspendingEnabled, "SetOutOfFocusSuspendingEnabled"}, |
| 137 | {17, nullptr, "SetControllerFirmwareUpdateSection"}, | 137 | {17, nullptr, "SetControllerFirmwareUpdateSection"}, |
| 138 | {18, nullptr, "SetRequiresCaptureButtonShortPressedMessage"}, | 138 | {18, nullptr, "SetRequiresCaptureButtonShortPressedMessage"}, |
| 139 | {19, nullptr, "SetScreenShotImageOrientation"}, | 139 | {19, &ISelfController::SetScreenShotImageOrientation, "SetScreenShotImageOrientation"}, |
| 140 | {20, nullptr, "SetDesirableKeyboardLayout"}, | 140 | {20, nullptr, "SetDesirableKeyboardLayout"}, |
| 141 | {40, &ISelfController::CreateManagedDisplayLayer, "CreateManagedDisplayLayer"}, | 141 | {40, &ISelfController::CreateManagedDisplayLayer, "CreateManagedDisplayLayer"}, |
| 142 | {41, nullptr, "IsSystemBufferSharingEnabled"}, | 142 | {41, nullptr, "IsSystemBufferSharingEnabled"}, |
| @@ -254,6 +254,13 @@ void ISelfController::GetLibraryAppletLaunchableEvent(Kernel::HLERequestContext& | |||
| 254 | LOG_WARNING(Service_AM, "(STUBBED) called"); | 254 | LOG_WARNING(Service_AM, "(STUBBED) called"); |
| 255 | } | 255 | } |
| 256 | 256 | ||
| 257 | void ISelfController::SetScreenShotImageOrientation(Kernel::HLERequestContext& ctx) { | ||
| 258 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 259 | rb.Push(RESULT_SUCCESS); | ||
| 260 | |||
| 261 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 262 | } | ||
| 263 | |||
| 257 | void ISelfController::CreateManagedDisplayLayer(Kernel::HLERequestContext& ctx) { | 264 | void ISelfController::CreateManagedDisplayLayer(Kernel::HLERequestContext& ctx) { |
| 258 | // TODO(Subv): Find out how AM determines the display to use, for now just create the layer | 265 | // TODO(Subv): Find out how AM determines the display to use, for now just create the layer |
| 259 | // in the Default display. | 266 | // in the Default display. |
diff --git a/src/core/hle/service/am/am.h b/src/core/hle/service/am/am.h index 8f4f98346..862f338ac 100644 --- a/src/core/hle/service/am/am.h +++ b/src/core/hle/service/am/am.h | |||
| @@ -83,6 +83,7 @@ private: | |||
| 83 | void LockExit(Kernel::HLERequestContext& ctx); | 83 | void LockExit(Kernel::HLERequestContext& ctx); |
| 84 | void UnlockExit(Kernel::HLERequestContext& ctx); | 84 | void UnlockExit(Kernel::HLERequestContext& ctx); |
| 85 | void GetLibraryAppletLaunchableEvent(Kernel::HLERequestContext& ctx); | 85 | void GetLibraryAppletLaunchableEvent(Kernel::HLERequestContext& ctx); |
| 86 | void SetScreenShotImageOrientation(Kernel::HLERequestContext& ctx); | ||
| 86 | void CreateManagedDisplayLayer(Kernel::HLERequestContext& ctx); | 87 | void CreateManagedDisplayLayer(Kernel::HLERequestContext& ctx); |
| 87 | void SetScreenShotPermission(Kernel::HLERequestContext& ctx); | 88 | void SetScreenShotPermission(Kernel::HLERequestContext& ctx); |
| 88 | void SetHandlesRequestToDisplay(Kernel::HLERequestContext& ctx); | 89 | void SetHandlesRequestToDisplay(Kernel::HLERequestContext& ctx); |
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/devices/nvhost_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp index 116dabedb..4cdf7f613 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp | |||
| @@ -147,7 +147,7 @@ u32 nvhost_gpu::SubmitGPFIFO(const std::vector<u8>& input, std::vector<u8>& outp | |||
| 147 | } | 147 | } |
| 148 | params.fence_out.id = 0; | 148 | params.fence_out.id = 0; |
| 149 | params.fence_out.value = 0; | 149 | params.fence_out.value = 0; |
| 150 | std::memcpy(output.data(), ¶ms, output.size()); | 150 | std::memcpy(output.data(), ¶ms, sizeof(IoctlSubmitGpfifo)); |
| 151 | return 0; | 151 | return 0; |
| 152 | } | 152 | } |
| 153 | 153 | ||
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 | ||
| 20 | namespace Service::Nvidia { | 21 | namespace Service::Nvidia { |
| 21 | 22 | ||
| 22 | std::weak_ptr<Module> nvdrv; | 23 | void InstallInterfaces(SM::ServiceManager& service_manager, NVFlinger::NVFlinger& nvflinger) { |
| 23 | |||
| 24 | void 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 | ||
| 34 | Module::Module() { | 33 | Module::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 | ||
| 13 | namespace Service::NVFlinger { | ||
| 14 | class NVFlinger; | ||
| 15 | } | ||
| 16 | |||
| 13 | namespace Service::Nvidia { | 17 | namespace Service::Nvidia { |
| 14 | 18 | ||
| 15 | namespace Devices { | 19 | namespace 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. |
| 59 | void InstallInterfaces(SM::ServiceManager& service_manager); | 63 | void InstallInterfaces(SM::ServiceManager& service_manager, NVFlinger::NVFlinger& nvflinger); |
| 60 | |||
| 61 | extern 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 | ||
| 49 | void NVFlinger::SetNVDrvInstance(std::shared_ptr<Nvidia::Module> instance) { | ||
| 50 | nvdrv = std::move(instance); | ||
| 51 | } | ||
| 52 | |||
| 49 | u64 NVFlinger::OpenDisplay(std::string_view name) { | 53 | u64 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 { | |||
| 16 | struct EventType; | 16 | struct EventType; |
| 17 | } | 17 | } |
| 18 | 18 | ||
| 19 | namespace Service::Nvidia { | ||
| 20 | class Module; | ||
| 21 | } | ||
| 22 | |||
| 19 | namespace Service::NVFlinger { | 23 | namespace Service::NVFlinger { |
| 20 | 24 | ||
| 21 | class BufferQueue; | 25 | class 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 | ||
| 18 | namespace Loader { | 19 | namespace Loader { |
| 19 | 20 | ||
| 20 | AppLoader_DeconstructedRomDirectory::AppLoader_DeconstructedRomDirectory(FileSys::VirtualFile file) | 21 | AppLoader_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 | ||
| 23 | AppLoader_DeconstructedRomDirectory::AppLoader_DeconstructedRomDirectory( | 66 | AppLoader_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 | ||
| 151 | ResultStatus 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 | |||
| 158 | ResultStatus 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 | |||
| 165 | ResultStatus 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 | ||
| 43 | private: | 46 | private: |
| 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 | ||
| 71 | const char* GetFileTypeString(FileType type) { | 71 | std::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 | */ |
| 64 | const char* GetFileTypeString(FileType type); | 64 | std::string GetFileTypeString(FileType type); |
| 65 | 65 | ||
| 66 | /// Return type for functions in Loader namespace | 66 | /// Return type for functions in Loader namespace |
| 67 | enum class ResultStatus { | 67 | enum 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 | ||
| 79 | ResultStatus AppLoader_NCA::ReadProgramId(u64& out_program_id) { | 79 | ResultStatus 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: | |||
| 41 | private: | 40 | private: |
| 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 { | |||
| 26 | AppLoader_XCI::AppLoader_XCI(FileSys::VirtualFile file) | 26 | AppLoader_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 | ||
| 31 | AppLoader_XCI::~AppLoader_XCI() = default; | 49 | AppLoader_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 | ||
| 92 | ResultStatus 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 | |||
| 99 | ResultStatus 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 | ||
| 37 | private: | 39 | private: |
| 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/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp index 5c0ae8009..ed22a2090 100644 --- a/src/video_core/engines/maxwell_3d.cpp +++ b/src/video_core/engines/maxwell_3d.cpp | |||
| @@ -238,6 +238,8 @@ void Maxwell3D::ProcessCBBind(Regs::ShaderStage stage) { | |||
| 238 | 238 | ||
| 239 | auto& buffer = shader.const_buffers[bind_data.index]; | 239 | auto& buffer = shader.const_buffers[bind_data.index]; |
| 240 | 240 | ||
| 241 | ASSERT(bind_data.index < Regs::MaxConstBuffers); | ||
| 242 | |||
| 241 | buffer.enabled = bind_data.valid.Value() != 0; | 243 | buffer.enabled = bind_data.valid.Value() != 0; |
| 242 | buffer.index = bind_data.index; | 244 | buffer.index = bind_data.index; |
| 243 | buffer.address = regs.const_buffer.BufferAddress(); | 245 | buffer.address = regs.const_buffer.BufferAddress(); |
diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h index 4d0ff96a5..0506ac8fe 100644 --- a/src/video_core/engines/maxwell_3d.h +++ b/src/video_core/engines/maxwell_3d.h | |||
| @@ -44,7 +44,7 @@ public: | |||
| 44 | static constexpr size_t MaxShaderProgram = 6; | 44 | static constexpr size_t MaxShaderProgram = 6; |
| 45 | static constexpr size_t MaxShaderStage = 5; | 45 | static constexpr size_t MaxShaderStage = 5; |
| 46 | // Maximum number of const buffers per shader stage. | 46 | // Maximum number of const buffers per shader stage. |
| 47 | static constexpr size_t MaxConstBuffers = 16; | 47 | static constexpr size_t MaxConstBuffers = 18; |
| 48 | 48 | ||
| 49 | enum class QueryMode : u32 { | 49 | enum class QueryMode : u32 { |
| 50 | Write = 0, | 50 | Write = 0, |
diff --git a/src/video_core/gpu.cpp b/src/video_core/gpu.cpp index b2a83ce0b..4ff4d71c5 100644 --- a/src/video_core/gpu.cpp +++ b/src/video_core/gpu.cpp | |||
| @@ -42,6 +42,7 @@ u32 RenderTargetBytesPerPixel(RenderTargetFormat format) { | |||
| 42 | case RenderTargetFormat::RGB10_A2_UNORM: | 42 | case RenderTargetFormat::RGB10_A2_UNORM: |
| 43 | case RenderTargetFormat::BGRA8_UNORM: | 43 | case RenderTargetFormat::BGRA8_UNORM: |
| 44 | case RenderTargetFormat::R32_FLOAT: | 44 | case RenderTargetFormat::R32_FLOAT: |
| 45 | case RenderTargetFormat::R11G11B10_FLOAT: | ||
| 45 | return 4; | 46 | return 4; |
| 46 | default: | 47 | default: |
| 47 | UNIMPLEMENTED_MSG("Unimplemented render target format {}", static_cast<u32>(format)); | 48 | UNIMPLEMENTED_MSG("Unimplemented render target format {}", static_cast<u32>(format)); |
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index c2a931469..bf6b5c3a0 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp | |||
| @@ -161,7 +161,7 @@ std::pair<u8*, GLintptr> RasterizerOpenGL::SetupVertexArrays(u8* array_ptr, | |||
| 161 | // assume every shader uses them all. | 161 | // assume every shader uses them all. |
| 162 | for (unsigned index = 0; index < 16; ++index) { | 162 | for (unsigned index = 0; index < 16; ++index) { |
| 163 | auto& attrib = regs.vertex_attrib_format[index]; | 163 | auto& attrib = regs.vertex_attrib_format[index]; |
| 164 | LOG_DEBUG(HW_GPU, "vertex attrib {}, count={}, size={}, type={}, offset={}, normalize={}", | 164 | LOG_TRACE(HW_GPU, "vertex attrib {}, count={}, size={}, type={}, offset={}, normalize={}", |
| 165 | index, attrib.ComponentCount(), attrib.SizeString(), attrib.TypeString(), | 165 | index, attrib.ComponentCount(), attrib.SizeString(), attrib.TypeString(), |
| 166 | attrib.offset.Value(), attrib.IsNormalized()); | 166 | attrib.offset.Value(), attrib.IsNormalized()); |
| 167 | 167 | ||
| @@ -659,7 +659,10 @@ u32 RasterizerOpenGL::SetupConstBuffers(Maxwell::ShaderStage stage, GLuint progr | |||
| 659 | auto& buffer_draw_state = | 659 | auto& buffer_draw_state = |
| 660 | state.draw.const_buffers[static_cast<size_t>(stage)][used_buffer.GetIndex()]; | 660 | state.draw.const_buffers[static_cast<size_t>(stage)][used_buffer.GetIndex()]; |
| 661 | 661 | ||
| 662 | ASSERT_MSG(buffer.enabled, "Attempted to upload disabled constbuffer"); | 662 | if (!buffer.enabled) { |
| 663 | continue; | ||
| 664 | } | ||
| 665 | |||
| 663 | buffer_draw_state.enabled = true; | 666 | buffer_draw_state.enabled = true; |
| 664 | buffer_draw_state.bindpoint = current_bindpoint + bindpoint; | 667 | buffer_draw_state.bindpoint = current_bindpoint + bindpoint; |
| 665 | 668 | ||
diff --git a/src/video_core/renderer_opengl/gl_state.h b/src/video_core/renderer_opengl/gl_state.h index 24b1d956b..5c7b636e4 100644 --- a/src/video_core/renderer_opengl/gl_state.h +++ b/src/video_core/renderer_opengl/gl_state.h | |||
| @@ -7,6 +7,10 @@ | |||
| 7 | #include <array> | 7 | #include <array> |
| 8 | #include <glad/glad.h> | 8 | #include <glad/glad.h> |
| 9 | 9 | ||
| 10 | #include "video_core/engines/maxwell_3d.h" | ||
| 11 | |||
| 12 | using Regs = Tegra::Engines::Maxwell3D::Regs; | ||
| 13 | |||
| 10 | namespace TextureUnits { | 14 | namespace TextureUnits { |
| 11 | 15 | ||
| 12 | struct TextureUnit { | 16 | struct TextureUnit { |
| @@ -120,7 +124,7 @@ public: | |||
| 120 | GLuint bindpoint; | 124 | GLuint bindpoint; |
| 121 | GLuint ssbo; | 125 | GLuint ssbo; |
| 122 | }; | 126 | }; |
| 123 | std::array<std::array<ConstBufferConfig, 16>, 5> const_buffers{}; | 127 | std::array<std::array<ConstBufferConfig, Regs::MaxConstBuffers>, 5> const_buffers; |
| 124 | } draw; | 128 | } draw; |
| 125 | 129 | ||
| 126 | struct { | 130 | struct { |
diff --git a/src/video_core/renderer_opengl/maxwell_to_gl.h b/src/video_core/renderer_opengl/maxwell_to_gl.h index 16b1bd606..500d4d4b1 100644 --- a/src/video_core/renderer_opengl/maxwell_to_gl.h +++ b/src/video_core/renderer_opengl/maxwell_to_gl.h | |||
| @@ -27,6 +27,7 @@ inline GLenum VertexType(Maxwell::VertexAttribute attrib) { | |||
| 27 | case Maxwell::VertexAttribute::Type::UnsignedNorm: { | 27 | case Maxwell::VertexAttribute::Type::UnsignedNorm: { |
| 28 | 28 | ||
| 29 | switch (attrib.size) { | 29 | switch (attrib.size) { |
| 30 | case Maxwell::VertexAttribute::Size::Size_8_8: | ||
| 30 | case Maxwell::VertexAttribute::Size::Size_8_8_8_8: | 31 | case Maxwell::VertexAttribute::Size::Size_8_8_8_8: |
| 31 | return GL_UNSIGNED_BYTE; | 32 | return GL_UNSIGNED_BYTE; |
| 32 | case Maxwell::VertexAttribute::Size::Size_16_16: | 33 | case Maxwell::VertexAttribute::Size::Size_16_16: |
diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp index bf9131193..899865e3b 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.cpp +++ b/src/video_core/renderer_opengl/renderer_opengl.cpp | |||
| @@ -430,7 +430,7 @@ static void APIENTRY DebugHandler(GLenum source, GLenum type, GLuint id, GLenum | |||
| 430 | break; | 430 | break; |
| 431 | case GL_DEBUG_SEVERITY_NOTIFICATION: | 431 | case GL_DEBUG_SEVERITY_NOTIFICATION: |
| 432 | case GL_DEBUG_SEVERITY_LOW: | 432 | case GL_DEBUG_SEVERITY_LOW: |
| 433 | LOG_DEBUG(Render_OpenGL, format, str_source, str_type, id, message); | 433 | LOG_TRACE(Render_OpenGL, format, str_source, str_type, id, message); |
| 434 | break; | 434 | break; |
| 435 | } | 435 | } |
| 436 | } | 436 | } |
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 | ||
| 22 | void ConfigureDialog::applyConfiguration() { | 22 | void 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 | |||
| 11 | ConfigureGameList::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 | |||
| 45 | ConfigureGameList::~ConfigureGameList() {} | ||
| 46 | |||
| 47 | void 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 | |||
| 57 | void 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 | |||
| 10 | namespace Ui { | ||
| 11 | class ConfigureGameList; | ||
| 12 | } | ||
| 13 | |||
| 14 | class ConfigureGameList : public QWidget { | ||
| 15 | Q_OBJECT | ||
| 16 | |||
| 17 | public: | ||
| 18 | explicit ConfigureGameList(QWidget* parent = nullptr); | ||
| 19 | ~ConfigureGameList(); | ||
| 20 | |||
| 21 | void applyConfiguration(); | ||
| 22 | |||
| 23 | private: | ||
| 24 | void setConfiguration(); | ||
| 25 | |||
| 26 | private: | ||
| 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 | ||
| 400 | void GameListWorker::AddFstEntriesToGameList(const std::string& dir_path, unsigned int recursion) { | 403 | void 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 | */ |
| 21 | static QPixmap GetDefaultIcon(bool large) { | 22 | static 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 | ||
| 59 | extern Values values; | 65 | extern Values values; |