Compare commits
59 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| dbb1cbce67 | |||
| db96034ea4 | |||
| 404362e1b0 | |||
| 1ee060ca0d | |||
| df72480395 | |||
| 2b601e8636 | |||
| e6f9231ef0 | |||
| cb6808b4d0 | |||
| 2aabd1eb05 | |||
| feb243b08d | |||
| fc2f8963bb | |||
| 2dace90346 | |||
| f482b4b40d | |||
| b14277ef97 | |||
| 1f9ac1541f | |||
| 03d5a5d9de | |||
| 2296e921d2 | |||
| 83d8bf9af9 | |||
| a93f6e51d3 | |||
| f808258ed9 | |||
| e050594706 | |||
| a9de967fa3 | |||
| ff0b14ee62 | |||
| b724a4d90c | |||
| e0ff98dd34 | |||
| a8ffe6eee4 | |||
| e143adc3cf | |||
| 4605e4d6ff | |||
| f00641459e | |||
| 257b1d2c4b | |||
| 85feaf3005 | |||
| d6672501ac | |||
| 9c6ae697f5 | |||
| 8928aa3008 | |||
| 504095cea9 | |||
| ed51c2abda | |||
| acfd771e79 | |||
| 664019954a | |||
| 1c3490a8db | |||
| f14bb61acd | |||
| 929fc849e9 | |||
| 5429ea0e69 | |||
| 62fa00f586 | |||
| 53e94c7be8 | |||
| 61cd7eb47d | |||
| 06ab28263b | |||
| 253a17451b | |||
| 5b89291308 | |||
| df96a214ae | |||
| 238208ee30 | |||
| 87c64c41d2 | |||
| a10d64ea79 | |||
| 0a5456feb9 | |||
| 123024cea2 | |||
| 0105368cc1 | |||
| e586921c28 | |||
| 2e511246fa | |||
| c5bdccfecb | |||
| dd4a02d15c |
@@ -7,7 +7,7 @@ if grep -nrI '\s$' src *.yml *.txt *.md Doxyfile .gitignore .gitmodules .ci* dis
|
||||
fi
|
||||
|
||||
# Default clang-format points to default 3.5 version one
|
||||
CLANG_FORMAT=clang-format-6.0
|
||||
CLANG_FORMAT=clang-format-10
|
||||
$CLANG_FORMAT --version
|
||||
|
||||
if [ "$TRAVIS_EVENT_TYPE" = "pull_request" ]; then
|
||||
|
||||
@@ -7,7 +7,7 @@ if grep -nrI '\s$' src *.yml *.txt *.md Doxyfile .gitignore .gitmodules .travis*
|
||||
fi
|
||||
|
||||
# Default clang-format points to default 3.5 version one
|
||||
CLANG_FORMAT=clang-format-6.0
|
||||
CLANG_FORMAT=clang-format-10.0
|
||||
$CLANG_FORMAT --version
|
||||
|
||||
if [ "$TRAVIS_EVENT_TYPE" = "pull_request" ]; then
|
||||
|
||||
+2
-2
@@ -161,7 +161,7 @@ macro(yuzu_find_packages)
|
||||
# Cmake Pkg Prefix Version Conan Pkg
|
||||
"Boost 1.73 boost/1.73.0"
|
||||
"Catch2 2.13 catch2/2.13.0"
|
||||
"fmt 7.0 fmt/7.0.1"
|
||||
"fmt 7.0 fmt/7.0.3"
|
||||
# can't use until https://github.com/bincrafters/community/issues/1173
|
||||
#"libzip 1.5 libzip/1.5.2@bincrafters/stable"
|
||||
"lz4 1.8 lz4/1.9.2"
|
||||
@@ -456,7 +456,7 @@ endif()
|
||||
# against all the src files. This should be used before making a pull request.
|
||||
# =======================================================================
|
||||
|
||||
set(CLANG_FORMAT_POSTFIX "-6.0")
|
||||
set(CLANG_FORMAT_POSTFIX "-10")
|
||||
find_program(CLANG_FORMAT
|
||||
NAMES clang-format${CLANG_FORMAT_POSTFIX}
|
||||
clang-format
|
||||
|
||||
@@ -78,7 +78,7 @@ public:
|
||||
const s16 surround_left{samples[i + 4]};
|
||||
const s16 surround_right{samples[i + 5]};
|
||||
// Not used in the ATSC reference implementation
|
||||
[[maybe_unused]] const s16 low_frequency_effects { samples[i + 3] };
|
||||
[[maybe_unused]] const s16 low_frequency_effects{samples[i + 3]};
|
||||
|
||||
constexpr s32 clev{707}; // center mixing level coefficient
|
||||
constexpr s32 slev{707}; // surround mixing level coefficient
|
||||
|
||||
@@ -15,7 +15,8 @@
|
||||
namespace Common {
|
||||
|
||||
template <class ForwardIt, class T, class Compare = std::less<>>
|
||||
ForwardIt BinaryFind(ForwardIt first, ForwardIt last, const T& value, Compare comp = {}) {
|
||||
[[nodiscard]] ForwardIt BinaryFind(ForwardIt first, ForwardIt last, const T& value,
|
||||
Compare comp = {}) {
|
||||
// Note: BOTH type T and the type after ForwardIt is dereferenced
|
||||
// must be implicitly convertible to BOTH Type1 and Type2, used in Compare.
|
||||
// This is stricter than lower_bound requirement (see above)
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
namespace Common {
|
||||
|
||||
template <typename T>
|
||||
constexpr T AlignUp(T value, std::size_t size) {
|
||||
[[nodiscard]] constexpr T AlignUp(T value, std::size_t size) {
|
||||
static_assert(std::is_unsigned_v<T>, "T must be an unsigned value.");
|
||||
auto mod{static_cast<T>(value % size)};
|
||||
value -= mod;
|
||||
@@ -17,31 +17,31 @@ constexpr T AlignUp(T value, std::size_t size) {
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
constexpr T AlignDown(T value, std::size_t size) {
|
||||
[[nodiscard]] constexpr T AlignDown(T value, std::size_t size) {
|
||||
static_assert(std::is_unsigned_v<T>, "T must be an unsigned value.");
|
||||
return static_cast<T>(value - value % size);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
constexpr T AlignBits(T value, std::size_t align) {
|
||||
[[nodiscard]] constexpr T AlignBits(T value, std::size_t align) {
|
||||
static_assert(std::is_unsigned_v<T>, "T must be an unsigned value.");
|
||||
return static_cast<T>((value + ((1ULL << align) - 1)) >> align << align);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
constexpr bool Is4KBAligned(T value) {
|
||||
[[nodiscard]] constexpr bool Is4KBAligned(T value) {
|
||||
static_assert(std::is_unsigned_v<T>, "T must be an unsigned value.");
|
||||
return (value & 0xFFF) == 0;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
constexpr bool IsWordAligned(T value) {
|
||||
[[nodiscard]] constexpr bool IsWordAligned(T value) {
|
||||
static_assert(std::is_unsigned_v<T>, "T must be an unsigned value.");
|
||||
return (value & 0b11) == 0;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
constexpr bool IsAligned(T value, std::size_t alignment) {
|
||||
[[nodiscard]] constexpr bool IsAligned(T value, std::size_t alignment) {
|
||||
using U = typename std::make_unsigned<T>::type;
|
||||
const U mask = static_cast<U>(alignment - 1);
|
||||
return (value & mask) == 0;
|
||||
@@ -64,7 +64,7 @@ public:
|
||||
template <typename T2>
|
||||
constexpr AlignmentAllocator(const AlignmentAllocator<T2, Align>&) noexcept {}
|
||||
|
||||
T* allocate(size_type n) {
|
||||
[[nodiscard]] T* allocate(size_type n) {
|
||||
return static_cast<T*>(::operator new (n * sizeof(T), std::align_val_t{Align}));
|
||||
}
|
||||
|
||||
|
||||
@@ -8,10 +8,10 @@
|
||||
|
||||
namespace Common {
|
||||
|
||||
bool AtomicCompareAndSwap(volatile u8* pointer, u8 value, u8 expected);
|
||||
bool AtomicCompareAndSwap(volatile u16* pointer, u16 value, u16 expected);
|
||||
bool AtomicCompareAndSwap(volatile u32* pointer, u32 value, u32 expected);
|
||||
bool AtomicCompareAndSwap(volatile u64* pointer, u64 value, u64 expected);
|
||||
bool AtomicCompareAndSwap(volatile u64* pointer, u128 value, u128 expected);
|
||||
[[nodiscard]] bool AtomicCompareAndSwap(volatile u8* pointer, u8 value, u8 expected);
|
||||
[[nodiscard]] bool AtomicCompareAndSwap(volatile u16* pointer, u16 value, u16 expected);
|
||||
[[nodiscard]] bool AtomicCompareAndSwap(volatile u32* pointer, u32 value, u32 expected);
|
||||
[[nodiscard]] bool AtomicCompareAndSwap(volatile u64* pointer, u64 value, u64 expected);
|
||||
[[nodiscard]] bool AtomicCompareAndSwap(volatile u64* pointer, u128 value, u128 expected);
|
||||
|
||||
} // namespace Common
|
||||
|
||||
+6
-13
@@ -36,13 +36,6 @@
|
||||
#include "common/common_funcs.h"
|
||||
#include "common/swap.h"
|
||||
|
||||
// Inlining
|
||||
#ifdef _WIN32
|
||||
#define FORCE_INLINE __forceinline
|
||||
#else
|
||||
#define FORCE_INLINE inline __attribute__((always_inline))
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Abstract bitfield class
|
||||
*
|
||||
@@ -142,8 +135,8 @@ public:
|
||||
* containing several bitfields can be assembled by formatting each of their values and ORing
|
||||
* the results together.
|
||||
*/
|
||||
static constexpr FORCE_INLINE StorageType FormatValue(const T& value) {
|
||||
return ((StorageType)value << position) & mask;
|
||||
[[nodiscard]] static constexpr StorageType FormatValue(const T& value) {
|
||||
return (static_cast<StorageType>(value) << position) & mask;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -151,7 +144,7 @@ public:
|
||||
* (such as Value() or operator T), but this can be used to extract a value from a bitfield
|
||||
* union in a constexpr context.
|
||||
*/
|
||||
static constexpr FORCE_INLINE T ExtractValue(const StorageType& storage) {
|
||||
[[nodiscard]] static constexpr T ExtractValue(const StorageType& storage) {
|
||||
if constexpr (std::numeric_limits<UnderlyingType>::is_signed) {
|
||||
std::size_t shift = 8 * sizeof(T) - bits;
|
||||
return static_cast<T>(static_cast<UnderlyingType>(storage << (shift - position)) >>
|
||||
@@ -175,7 +168,7 @@ public:
|
||||
constexpr BitField(BitField&&) noexcept = default;
|
||||
constexpr BitField& operator=(BitField&&) noexcept = default;
|
||||
|
||||
constexpr operator T() const {
|
||||
[[nodiscard]] constexpr operator T() const {
|
||||
return Value();
|
||||
}
|
||||
|
||||
@@ -183,11 +176,11 @@ public:
|
||||
storage = static_cast<StorageType>((storage & ~mask) | FormatValue(value));
|
||||
}
|
||||
|
||||
constexpr T Value() const {
|
||||
[[nodiscard]] constexpr T Value() const {
|
||||
return ExtractValue(storage);
|
||||
}
|
||||
|
||||
constexpr explicit operator bool() const {
|
||||
[[nodiscard]] constexpr explicit operator bool() const {
|
||||
return Value() != 0;
|
||||
}
|
||||
|
||||
|
||||
+17
-17
@@ -17,12 +17,12 @@ namespace Common {
|
||||
|
||||
/// Gets the size of a specified type T in bits.
|
||||
template <typename T>
|
||||
constexpr std::size_t BitSize() {
|
||||
[[nodiscard]] constexpr std::size_t BitSize() {
|
||||
return sizeof(T) * CHAR_BIT;
|
||||
}
|
||||
|
||||
#ifdef _MSC_VER
|
||||
inline u32 CountLeadingZeroes32(u32 value) {
|
||||
[[nodiscard]] inline u32 CountLeadingZeroes32(u32 value) {
|
||||
unsigned long leading_zero = 0;
|
||||
|
||||
if (_BitScanReverse(&leading_zero, value) != 0) {
|
||||
@@ -32,7 +32,7 @@ inline u32 CountLeadingZeroes32(u32 value) {
|
||||
return 32;
|
||||
}
|
||||
|
||||
inline u32 CountLeadingZeroes64(u64 value) {
|
||||
[[nodiscard]] inline u32 CountLeadingZeroes64(u64 value) {
|
||||
unsigned long leading_zero = 0;
|
||||
|
||||
if (_BitScanReverse64(&leading_zero, value) != 0) {
|
||||
@@ -42,7 +42,7 @@ inline u32 CountLeadingZeroes64(u64 value) {
|
||||
return 64;
|
||||
}
|
||||
#else
|
||||
inline u32 CountLeadingZeroes32(u32 value) {
|
||||
[[nodiscard]] inline u32 CountLeadingZeroes32(u32 value) {
|
||||
if (value == 0) {
|
||||
return 32;
|
||||
}
|
||||
@@ -50,7 +50,7 @@ inline u32 CountLeadingZeroes32(u32 value) {
|
||||
return static_cast<u32>(__builtin_clz(value));
|
||||
}
|
||||
|
||||
inline u32 CountLeadingZeroes64(u64 value) {
|
||||
[[nodiscard]] inline u32 CountLeadingZeroes64(u64 value) {
|
||||
if (value == 0) {
|
||||
return 64;
|
||||
}
|
||||
@@ -60,7 +60,7 @@ inline u32 CountLeadingZeroes64(u64 value) {
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
inline u32 CountTrailingZeroes32(u32 value) {
|
||||
[[nodiscard]] inline u32 CountTrailingZeroes32(u32 value) {
|
||||
unsigned long trailing_zero = 0;
|
||||
|
||||
if (_BitScanForward(&trailing_zero, value) != 0) {
|
||||
@@ -70,7 +70,7 @@ inline u32 CountTrailingZeroes32(u32 value) {
|
||||
return 32;
|
||||
}
|
||||
|
||||
inline u32 CountTrailingZeroes64(u64 value) {
|
||||
[[nodiscard]] inline u32 CountTrailingZeroes64(u64 value) {
|
||||
unsigned long trailing_zero = 0;
|
||||
|
||||
if (_BitScanForward64(&trailing_zero, value) != 0) {
|
||||
@@ -80,7 +80,7 @@ inline u32 CountTrailingZeroes64(u64 value) {
|
||||
return 64;
|
||||
}
|
||||
#else
|
||||
inline u32 CountTrailingZeroes32(u32 value) {
|
||||
[[nodiscard]] inline u32 CountTrailingZeroes32(u32 value) {
|
||||
if (value == 0) {
|
||||
return 32;
|
||||
}
|
||||
@@ -88,7 +88,7 @@ inline u32 CountTrailingZeroes32(u32 value) {
|
||||
return static_cast<u32>(__builtin_ctz(value));
|
||||
}
|
||||
|
||||
inline u32 CountTrailingZeroes64(u64 value) {
|
||||
[[nodiscard]] inline u32 CountTrailingZeroes64(u64 value) {
|
||||
if (value == 0) {
|
||||
return 64;
|
||||
}
|
||||
@@ -99,13 +99,13 @@ inline u32 CountTrailingZeroes64(u64 value) {
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
||||
inline u32 MostSignificantBit32(const u32 value) {
|
||||
[[nodiscard]] inline u32 MostSignificantBit32(const u32 value) {
|
||||
unsigned long result;
|
||||
_BitScanReverse(&result, value);
|
||||
return static_cast<u32>(result);
|
||||
}
|
||||
|
||||
inline u32 MostSignificantBit64(const u64 value) {
|
||||
[[nodiscard]] inline u32 MostSignificantBit64(const u64 value) {
|
||||
unsigned long result;
|
||||
_BitScanReverse64(&result, value);
|
||||
return static_cast<u32>(result);
|
||||
@@ -113,30 +113,30 @@ inline u32 MostSignificantBit64(const u64 value) {
|
||||
|
||||
#else
|
||||
|
||||
inline u32 MostSignificantBit32(const u32 value) {
|
||||
[[nodiscard]] inline u32 MostSignificantBit32(const u32 value) {
|
||||
return 31U - static_cast<u32>(__builtin_clz(value));
|
||||
}
|
||||
|
||||
inline u32 MostSignificantBit64(const u64 value) {
|
||||
[[nodiscard]] inline u32 MostSignificantBit64(const u64 value) {
|
||||
return 63U - static_cast<u32>(__builtin_clzll(value));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
inline u32 Log2Floor32(const u32 value) {
|
||||
[[nodiscard]] inline u32 Log2Floor32(const u32 value) {
|
||||
return MostSignificantBit32(value);
|
||||
}
|
||||
|
||||
inline u32 Log2Ceil32(const u32 value) {
|
||||
[[nodiscard]] inline u32 Log2Ceil32(const u32 value) {
|
||||
const u32 log2_f = Log2Floor32(value);
|
||||
return log2_f + ((value ^ (1U << log2_f)) != 0U);
|
||||
}
|
||||
|
||||
inline u32 Log2Floor64(const u64 value) {
|
||||
[[nodiscard]] inline u32 Log2Floor64(const u64 value) {
|
||||
return MostSignificantBit64(value);
|
||||
}
|
||||
|
||||
inline u32 Log2Ceil64(const u64 value) {
|
||||
[[nodiscard]] inline u32 Log2Ceil64(const u64 value) {
|
||||
const u64 log2_f = static_cast<u64>(Log2Floor64(value));
|
||||
return static_cast<u32>(log2_f + ((value ^ (1ULL << log2_f)) != 0ULL));
|
||||
}
|
||||
|
||||
+12
-11
@@ -61,42 +61,43 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <utility>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h> // for std::size_t.
|
||||
|
||||
namespace Common {
|
||||
|
||||
typedef std::pair<uint64_t, uint64_t> uint128;
|
||||
using uint128 = std::pair<uint64_t, uint64_t>;
|
||||
|
||||
inline uint64_t Uint128Low64(const uint128& x) {
|
||||
[[nodiscard]] inline uint64_t Uint128Low64(const uint128& x) {
|
||||
return x.first;
|
||||
}
|
||||
inline uint64_t Uint128High64(const uint128& x) {
|
||||
[[nodiscard]] inline uint64_t Uint128High64(const uint128& x) {
|
||||
return x.second;
|
||||
}
|
||||
|
||||
// Hash function for a byte array.
|
||||
uint64_t CityHash64(const char* buf, std::size_t len);
|
||||
[[nodiscard]] uint64_t CityHash64(const char* buf, std::size_t len);
|
||||
|
||||
// Hash function for a byte array. For convenience, a 64-bit seed is also
|
||||
// hashed into the result.
|
||||
uint64_t CityHash64WithSeed(const char* buf, std::size_t len, uint64_t seed);
|
||||
[[nodiscard]] uint64_t CityHash64WithSeed(const char* buf, std::size_t len, uint64_t seed);
|
||||
|
||||
// Hash function for a byte array. For convenience, two seeds are also
|
||||
// hashed into the result.
|
||||
uint64_t CityHash64WithSeeds(const char* buf, std::size_t len, uint64_t seed0, uint64_t seed1);
|
||||
[[nodiscard]] uint64_t CityHash64WithSeeds(const char* buf, std::size_t len, uint64_t seed0,
|
||||
uint64_t seed1);
|
||||
|
||||
// Hash function for a byte array.
|
||||
uint128 CityHash128(const char* s, std::size_t len);
|
||||
[[nodiscard]] uint128 CityHash128(const char* s, std::size_t len);
|
||||
|
||||
// Hash function for a byte array. For convenience, a 128-bit seed is also
|
||||
// hashed into the result.
|
||||
uint128 CityHash128WithSeed(const char* s, std::size_t len, uint128 seed);
|
||||
[[nodiscard]] uint128 CityHash128WithSeed(const char* s, std::size_t len, uint128 seed);
|
||||
|
||||
// Hash 128 input bits down to 64 bits of output.
|
||||
// This is intended to be a reasonably good hash function.
|
||||
inline uint64_t Hash128to64(const uint128& x) {
|
||||
[[nodiscard]] inline uint64_t Hash128to64(const uint128& x) {
|
||||
// Murmur-inspired hashing.
|
||||
const uint64_t kMul = 0x9ddfea08eb382d69ULL;
|
||||
uint64_t a = (Uint128Low64(x) ^ Uint128High64(x)) * kMul;
|
||||
|
||||
+17
-17
@@ -13,42 +13,42 @@
|
||||
namespace Color {
|
||||
|
||||
/// Convert a 1-bit color component to 8 bit
|
||||
constexpr u8 Convert1To8(u8 value) {
|
||||
[[nodiscard]] constexpr u8 Convert1To8(u8 value) {
|
||||
return value * 255;
|
||||
}
|
||||
|
||||
/// Convert a 4-bit color component to 8 bit
|
||||
constexpr u8 Convert4To8(u8 value) {
|
||||
[[nodiscard]] constexpr u8 Convert4To8(u8 value) {
|
||||
return (value << 4) | value;
|
||||
}
|
||||
|
||||
/// Convert a 5-bit color component to 8 bit
|
||||
constexpr u8 Convert5To8(u8 value) {
|
||||
[[nodiscard]] constexpr u8 Convert5To8(u8 value) {
|
||||
return (value << 3) | (value >> 2);
|
||||
}
|
||||
|
||||
/// Convert a 6-bit color component to 8 bit
|
||||
constexpr u8 Convert6To8(u8 value) {
|
||||
[[nodiscard]] constexpr u8 Convert6To8(u8 value) {
|
||||
return (value << 2) | (value >> 4);
|
||||
}
|
||||
|
||||
/// Convert a 8-bit color component to 1 bit
|
||||
constexpr u8 Convert8To1(u8 value) {
|
||||
[[nodiscard]] constexpr u8 Convert8To1(u8 value) {
|
||||
return value >> 7;
|
||||
}
|
||||
|
||||
/// Convert a 8-bit color component to 4 bit
|
||||
constexpr u8 Convert8To4(u8 value) {
|
||||
[[nodiscard]] constexpr u8 Convert8To4(u8 value) {
|
||||
return value >> 4;
|
||||
}
|
||||
|
||||
/// Convert a 8-bit color component to 5 bit
|
||||
constexpr u8 Convert8To5(u8 value) {
|
||||
[[nodiscard]] constexpr u8 Convert8To5(u8 value) {
|
||||
return value >> 3;
|
||||
}
|
||||
|
||||
/// Convert a 8-bit color component to 6 bit
|
||||
constexpr u8 Convert8To6(u8 value) {
|
||||
[[nodiscard]] constexpr u8 Convert8To6(u8 value) {
|
||||
return value >> 2;
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ constexpr u8 Convert8To6(u8 value) {
|
||||
* @param bytes Pointer to encoded source color
|
||||
* @return Result color decoded as Common::Vec4<u8>
|
||||
*/
|
||||
inline Common::Vec4<u8> DecodeRGBA8(const u8* bytes) {
|
||||
[[nodiscard]] inline Common::Vec4<u8> DecodeRGBA8(const u8* bytes) {
|
||||
return {bytes[3], bytes[2], bytes[1], bytes[0]};
|
||||
}
|
||||
|
||||
@@ -66,7 +66,7 @@ inline Common::Vec4<u8> DecodeRGBA8(const u8* bytes) {
|
||||
* @param bytes Pointer to encoded source color
|
||||
* @return Result color decoded as Common::Vec4<u8>
|
||||
*/
|
||||
inline Common::Vec4<u8> DecodeRGB8(const u8* bytes) {
|
||||
[[nodiscard]] inline Common::Vec4<u8> DecodeRGB8(const u8* bytes) {
|
||||
return {bytes[2], bytes[1], bytes[0], 255};
|
||||
}
|
||||
|
||||
@@ -75,7 +75,7 @@ inline Common::Vec4<u8> DecodeRGB8(const u8* bytes) {
|
||||
* @param bytes Pointer to encoded source color
|
||||
* @return Result color decoded as Common::Vec4<u8>
|
||||
*/
|
||||
inline Common::Vec4<u8> DecodeRG8(const u8* bytes) {
|
||||
[[nodiscard]] inline Common::Vec4<u8> DecodeRG8(const u8* bytes) {
|
||||
return {bytes[1], bytes[0], 0, 255};
|
||||
}
|
||||
|
||||
@@ -84,7 +84,7 @@ inline Common::Vec4<u8> DecodeRG8(const u8* bytes) {
|
||||
* @param bytes Pointer to encoded source color
|
||||
* @return Result color decoded as Common::Vec4<u8>
|
||||
*/
|
||||
inline Common::Vec4<u8> DecodeRGB565(const u8* bytes) {
|
||||
[[nodiscard]] inline Common::Vec4<u8> DecodeRGB565(const u8* bytes) {
|
||||
u16_le pixel;
|
||||
std::memcpy(&pixel, bytes, sizeof(pixel));
|
||||
return {Convert5To8((pixel >> 11) & 0x1F), Convert6To8((pixel >> 5) & 0x3F),
|
||||
@@ -96,7 +96,7 @@ inline Common::Vec4<u8> DecodeRGB565(const u8* bytes) {
|
||||
* @param bytes Pointer to encoded source color
|
||||
* @return Result color decoded as Common::Vec4<u8>
|
||||
*/
|
||||
inline Common::Vec4<u8> DecodeRGB5A1(const u8* bytes) {
|
||||
[[nodiscard]] inline Common::Vec4<u8> DecodeRGB5A1(const u8* bytes) {
|
||||
u16_le pixel;
|
||||
std::memcpy(&pixel, bytes, sizeof(pixel));
|
||||
return {Convert5To8((pixel >> 11) & 0x1F), Convert5To8((pixel >> 6) & 0x1F),
|
||||
@@ -108,7 +108,7 @@ inline Common::Vec4<u8> DecodeRGB5A1(const u8* bytes) {
|
||||
* @param bytes Pointer to encoded source color
|
||||
* @return Result color decoded as Common::Vec4<u8>
|
||||
*/
|
||||
inline Common::Vec4<u8> DecodeRGBA4(const u8* bytes) {
|
||||
[[nodiscard]] inline Common::Vec4<u8> DecodeRGBA4(const u8* bytes) {
|
||||
u16_le pixel;
|
||||
std::memcpy(&pixel, bytes, sizeof(pixel));
|
||||
return {Convert4To8((pixel >> 12) & 0xF), Convert4To8((pixel >> 8) & 0xF),
|
||||
@@ -120,7 +120,7 @@ inline Common::Vec4<u8> DecodeRGBA4(const u8* bytes) {
|
||||
* @param bytes Pointer to encoded source value
|
||||
* @return Depth value as an u32
|
||||
*/
|
||||
inline u32 DecodeD16(const u8* bytes) {
|
||||
[[nodiscard]] inline u32 DecodeD16(const u8* bytes) {
|
||||
u16_le data;
|
||||
std::memcpy(&data, bytes, sizeof(data));
|
||||
return data;
|
||||
@@ -131,7 +131,7 @@ inline u32 DecodeD16(const u8* bytes) {
|
||||
* @param bytes Pointer to encoded source value
|
||||
* @return Depth value as an u32
|
||||
*/
|
||||
inline u32 DecodeD24(const u8* bytes) {
|
||||
[[nodiscard]] inline u32 DecodeD24(const u8* bytes) {
|
||||
return (bytes[2] << 16) | (bytes[1] << 8) | bytes[0];
|
||||
}
|
||||
|
||||
@@ -140,7 +140,7 @@ inline u32 DecodeD24(const u8* bytes) {
|
||||
* @param bytes Pointer to encoded source values
|
||||
* @return Resulting values stored as a Common::Vec2
|
||||
*/
|
||||
inline Common::Vec2<u32> DecodeD24S8(const u8* bytes) {
|
||||
[[nodiscard]] inline Common::Vec2<u32> DecodeD24S8(const u8* bytes) {
|
||||
return {static_cast<u32>((bytes[2] << 16) | (bytes[1] << 8) | bytes[0]), bytes[3]};
|
||||
}
|
||||
|
||||
|
||||
@@ -53,14 +53,14 @@ __declspec(dllimport) void __stdcall DebugBreak(void);
|
||||
// Call directly after the command or use the error num.
|
||||
// This function might change the error code.
|
||||
// Defined in Misc.cpp.
|
||||
std::string GetLastErrorMsg();
|
||||
[[nodiscard]] std::string GetLastErrorMsg();
|
||||
|
||||
#define DECLARE_ENUM_FLAG_OPERATORS(type) \
|
||||
constexpr type operator|(type a, type b) noexcept { \
|
||||
[[nodiscard]] constexpr type operator|(type a, type b) noexcept { \
|
||||
using T = std::underlying_type_t<type>; \
|
||||
return static_cast<type>(static_cast<T>(a) | static_cast<T>(b)); \
|
||||
} \
|
||||
constexpr type operator&(type a, type b) noexcept { \
|
||||
[[nodiscard]] constexpr type operator&(type a, type b) noexcept { \
|
||||
using T = std::underlying_type_t<type>; \
|
||||
return static_cast<type>(static_cast<T>(a) & static_cast<T>(b)); \
|
||||
} \
|
||||
@@ -74,22 +74,22 @@ std::string GetLastErrorMsg();
|
||||
a = static_cast<type>(static_cast<T>(a) & static_cast<T>(b)); \
|
||||
return a; \
|
||||
} \
|
||||
constexpr type operator~(type key) noexcept { \
|
||||
[[nodiscard]] constexpr type operator~(type key) noexcept { \
|
||||
using T = std::underlying_type_t<type>; \
|
||||
return static_cast<type>(~static_cast<T>(key)); \
|
||||
} \
|
||||
constexpr bool True(type key) noexcept { \
|
||||
[[nodiscard]] constexpr bool True(type key) noexcept { \
|
||||
using T = std::underlying_type_t<type>; \
|
||||
return static_cast<T>(key) != 0; \
|
||||
} \
|
||||
constexpr bool False(type key) noexcept { \
|
||||
[[nodiscard]] constexpr bool False(type key) noexcept { \
|
||||
using T = std::underlying_type_t<type>; \
|
||||
return static_cast<T>(key) == 0; \
|
||||
}
|
||||
|
||||
namespace Common {
|
||||
|
||||
constexpr u32 MakeMagic(char a, char b, char c, char d) {
|
||||
[[nodiscard]] constexpr u32 MakeMagic(char a, char b, char c, char d) {
|
||||
return u32(a) | u32(b) << 8 | u32(c) << 16 | u32(d) << 24;
|
||||
}
|
||||
|
||||
|
||||
@@ -34,8 +34,7 @@ void DetachedTasks::AddTask(std::function<void()> task) {
|
||||
std::unique_lock lock{instance->mutex};
|
||||
--instance->count;
|
||||
std::notify_all_at_thread_exit(instance->cv, std::move(lock));
|
||||
})
|
||||
.detach();
|
||||
}).detach();
|
||||
}
|
||||
|
||||
} // namespace Common
|
||||
|
||||
@@ -33,7 +33,7 @@ public:
|
||||
~DynamicLibrary();
|
||||
|
||||
/// Returns the specified library name with the platform-specific suffix added.
|
||||
static std::string GetUnprefixedFilename(const char* filename);
|
||||
[[nodiscard]] static std::string GetUnprefixedFilename(const char* filename);
|
||||
|
||||
/// Returns the specified library name in platform-specific format.
|
||||
/// Major/minor versions will not be included if set to -1.
|
||||
@@ -41,28 +41,29 @@ public:
|
||||
/// Windows: LIBNAME-MAJOR-MINOR.dll
|
||||
/// Linux: libLIBNAME.so.MAJOR.MINOR
|
||||
/// Mac: libLIBNAME.MAJOR.MINOR.dylib
|
||||
static std::string GetVersionedFilename(const char* libname, int major = -1, int minor = -1);
|
||||
[[nodiscard]] static std::string GetVersionedFilename(const char* libname, int major = -1,
|
||||
int minor = -1);
|
||||
|
||||
/// Returns true if a module is loaded, otherwise false.
|
||||
bool IsOpen() const {
|
||||
[[nodiscard]] bool IsOpen() const {
|
||||
return handle != nullptr;
|
||||
}
|
||||
|
||||
/// Loads (or replaces) the handle with the specified library file name.
|
||||
/// Returns true if the library was loaded and can be used.
|
||||
bool Open(const char* filename);
|
||||
[[nodiscard]] bool Open(const char* filename);
|
||||
|
||||
/// Unloads the library, any function pointers from this library are no longer valid.
|
||||
void Close();
|
||||
|
||||
/// Returns the address of the specified symbol (function or variable) as an untyped pointer.
|
||||
/// If the specified symbol does not exist in this library, nullptr is returned.
|
||||
void* GetSymbolAddress(const char* name) const;
|
||||
[[nodiscard]] void* GetSymbolAddress(const char* name) const;
|
||||
|
||||
/// Obtains the address of the specified symbol, automatically casting to the correct type.
|
||||
/// Returns true if the symbol was found and assigned, otherwise false.
|
||||
template <typename T>
|
||||
bool GetSymbol(const char* name, T* ptr) const {
|
||||
[[nodiscard]] bool GetSymbol(const char* name, T* ptr) const {
|
||||
*ptr = reinterpret_cast<T>(GetSymbolAddress(name));
|
||||
return *ptr != nullptr;
|
||||
}
|
||||
|
||||
+1
-1
@@ -47,7 +47,7 @@ public:
|
||||
/// Yields control from Fiber 'from' to Fiber 'to'
|
||||
/// Fiber 'from' must be the currently running fiber.
|
||||
static void YieldTo(std::shared_ptr<Fiber>& from, std::shared_ptr<Fiber>& to);
|
||||
static std::shared_ptr<Fiber> ThreadToFiber();
|
||||
[[nodiscard]] static std::shared_ptr<Fiber> ThreadToFiber();
|
||||
|
||||
void SetRewindPoint(std::function<void(void*)>&& rewind_func, void* start_parameter);
|
||||
|
||||
|
||||
+34
-27
@@ -48,19 +48,19 @@ struct FSTEntry {
|
||||
};
|
||||
|
||||
// Returns true if file filename exists
|
||||
bool Exists(const std::string& filename);
|
||||
[[nodiscard]] bool Exists(const std::string& filename);
|
||||
|
||||
// Returns true if filename is a directory
|
||||
bool IsDirectory(const std::string& filename);
|
||||
[[nodiscard]] bool IsDirectory(const std::string& filename);
|
||||
|
||||
// Returns the size of filename (64bit)
|
||||
u64 GetSize(const std::string& filename);
|
||||
[[nodiscard]] u64 GetSize(const std::string& filename);
|
||||
|
||||
// Overloaded GetSize, accepts file descriptor
|
||||
u64 GetSize(const int fd);
|
||||
[[nodiscard]] u64 GetSize(int fd);
|
||||
|
||||
// Overloaded GetSize, accepts FILE*
|
||||
u64 GetSize(FILE* f);
|
||||
[[nodiscard]] u64 GetSize(FILE* f);
|
||||
|
||||
// Returns true if successful, or path already exists.
|
||||
bool CreateDir(const std::string& filename);
|
||||
@@ -120,7 +120,7 @@ u64 ScanDirectoryTree(const std::string& directory, FSTEntry& parent_entry,
|
||||
bool DeleteDirRecursively(const std::string& directory, unsigned int recursion = 256);
|
||||
|
||||
// Returns the current directory
|
||||
std::optional<std::string> GetCurrentDir();
|
||||
[[nodiscard]] std::optional<std::string> GetCurrentDir();
|
||||
|
||||
// Create directory and copy contents (does not overwrite existing files)
|
||||
void CopyDir(const std::string& source_path, const std::string& dest_path);
|
||||
@@ -132,20 +132,20 @@ bool SetCurrentDir(const std::string& directory);
|
||||
// directory. To be used in "multi-user" mode (that is, installed).
|
||||
const std::string& GetUserPath(UserPath path, const std::string& new_path = "");
|
||||
|
||||
std::string GetHactoolConfigurationPath();
|
||||
[[nodiscard]] std::string GetHactoolConfigurationPath();
|
||||
|
||||
std::string GetNANDRegistrationDir(bool system = false);
|
||||
[[nodiscard]] std::string GetNANDRegistrationDir(bool system = false);
|
||||
|
||||
// Returns the path to where the sys file are
|
||||
std::string GetSysDirectory();
|
||||
[[nodiscard]] std::string GetSysDirectory();
|
||||
|
||||
#ifdef __APPLE__
|
||||
std::string GetBundleDirectory();
|
||||
[[nodiscard]] std::string GetBundleDirectory();
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
const std::string& GetExeDirectory();
|
||||
std::string AppDataRoamingDirectory();
|
||||
[[nodiscard]] const std::string& GetExeDirectory();
|
||||
[[nodiscard]] std::string AppDataRoamingDirectory();
|
||||
#endif
|
||||
|
||||
std::size_t WriteStringToFile(bool text_file, const std::string& filename, std::string_view str);
|
||||
@@ -164,38 +164,45 @@ void SplitFilename83(const std::string& filename, std::array<char, 9>& short_nam
|
||||
|
||||
// Splits the path on '/' or '\' and put the components into a vector
|
||||
// i.e. "C:\Users\Yuzu\Documents\save.bin" becomes {"C:", "Users", "Yuzu", "Documents", "save.bin" }
|
||||
std::vector<std::string> SplitPathComponents(std::string_view filename);
|
||||
[[nodiscard]] std::vector<std::string> SplitPathComponents(std::string_view filename);
|
||||
|
||||
// Gets all of the text up to the last '/' or '\' in the path.
|
||||
std::string_view GetParentPath(std::string_view path);
|
||||
[[nodiscard]] std::string_view GetParentPath(std::string_view path);
|
||||
|
||||
// Gets all of the text after the first '/' or '\' in the path.
|
||||
std::string_view GetPathWithoutTop(std::string_view path);
|
||||
[[nodiscard]] std::string_view GetPathWithoutTop(std::string_view path);
|
||||
|
||||
// Gets the filename of the path
|
||||
std::string_view GetFilename(std::string_view path);
|
||||
[[nodiscard]] std::string_view GetFilename(std::string_view path);
|
||||
|
||||
// Gets the extension of the filename
|
||||
std::string_view GetExtensionFromFilename(std::string_view name);
|
||||
[[nodiscard]] std::string_view GetExtensionFromFilename(std::string_view name);
|
||||
|
||||
// Removes the final '/' or '\' if one exists
|
||||
std::string_view RemoveTrailingSlash(std::string_view path);
|
||||
[[nodiscard]] std::string_view RemoveTrailingSlash(std::string_view path);
|
||||
|
||||
// Creates a new vector containing indices [first, last) from the original.
|
||||
template <typename T>
|
||||
std::vector<T> SliceVector(const std::vector<T>& vector, std::size_t first, std::size_t last) {
|
||||
if (first >= last)
|
||||
[[nodiscard]] std::vector<T> SliceVector(const std::vector<T>& vector, std::size_t first,
|
||||
std::size_t last) {
|
||||
if (first >= last) {
|
||||
return {};
|
||||
}
|
||||
last = std::min<std::size_t>(last, vector.size());
|
||||
return std::vector<T>(vector.begin() + first, vector.begin() + first + last);
|
||||
}
|
||||
|
||||
enum class DirectorySeparator { ForwardSlash, BackwardSlash, PlatformDefault };
|
||||
enum class DirectorySeparator {
|
||||
ForwardSlash,
|
||||
BackwardSlash,
|
||||
PlatformDefault,
|
||||
};
|
||||
|
||||
// Removes trailing slash, makes all '\\' into '/', and removes duplicate '/'. Makes '/' into '\\'
|
||||
// depending if directory_separator is BackwardSlash or PlatformDefault and running on windows
|
||||
std::string SanitizePath(std::string_view path,
|
||||
DirectorySeparator directory_separator = DirectorySeparator::ForwardSlash);
|
||||
[[nodiscard]] std::string SanitizePath(
|
||||
std::string_view path,
|
||||
DirectorySeparator directory_separator = DirectorySeparator::ForwardSlash);
|
||||
|
||||
// simple wrapper for cstdlib file functions to
|
||||
// hopefully will make error checking easier
|
||||
@@ -215,7 +222,7 @@ public:
|
||||
|
||||
void Swap(IOFile& other) noexcept;
|
||||
|
||||
bool Open(const std::string& filename, const char openmode[], int flags = 0);
|
||||
[[nodiscard]] bool Open(const std::string& filename, const char openmode[], int flags = 0);
|
||||
bool Close();
|
||||
|
||||
template <typename T>
|
||||
@@ -256,13 +263,13 @@ public:
|
||||
return WriteArray(str.data(), str.length());
|
||||
}
|
||||
|
||||
bool IsOpen() const {
|
||||
[[nodiscard]] bool IsOpen() const {
|
||||
return nullptr != m_file;
|
||||
}
|
||||
|
||||
bool Seek(s64 off, int origin) const;
|
||||
u64 Tell() const;
|
||||
u64 GetSize() const;
|
||||
[[nodiscard]] u64 Tell() const;
|
||||
[[nodiscard]] u64 GetSize() const;
|
||||
bool Resize(u64 size);
|
||||
bool Flush();
|
||||
|
||||
|
||||
@@ -5,36 +5,11 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstring>
|
||||
#include <utility>
|
||||
#include <boost/functional/hash.hpp>
|
||||
#include "common/cityhash.h"
|
||||
#include "common/common_types.h"
|
||||
|
||||
namespace Common {
|
||||
|
||||
/**
|
||||
* Computes a 64-bit hash over the specified block of data
|
||||
* @param data Block of data to compute hash over
|
||||
* @param len Length of data (in bytes) to compute hash over
|
||||
* @returns 64-bit hash value that was computed over the data block
|
||||
*/
|
||||
static inline u64 ComputeHash64(const void* data, std::size_t len) {
|
||||
return CityHash64(static_cast<const char*>(data), len);
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes a 64-bit hash of a struct. In addition to being trivially copyable, it is also critical
|
||||
* that either the struct includes no padding, or that any padding is initialized to a known value
|
||||
* by memsetting the struct to 0 before filling it in.
|
||||
*/
|
||||
template <typename T>
|
||||
static inline u64 ComputeStructHash64(const T& data) {
|
||||
static_assert(std::is_trivially_copyable_v<T>,
|
||||
"Type passed to ComputeStructHash64 must be trivially copyable");
|
||||
return ComputeHash64(&data, sizeof(data));
|
||||
}
|
||||
|
||||
struct PairHash {
|
||||
template <class T1, class T2>
|
||||
std::size_t operator()(const std::pair<T1, T2>& pair) const noexcept {
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
namespace Common {
|
||||
|
||||
constexpr u8 ToHexNibble(char c) {
|
||||
[[nodiscard]] constexpr u8 ToHexNibble(char c) {
|
||||
if (c >= 65 && c <= 70) {
|
||||
return c - 55;
|
||||
}
|
||||
@@ -26,10 +26,10 @@ constexpr u8 ToHexNibble(char c) {
|
||||
return c - 48;
|
||||
}
|
||||
|
||||
std::vector<u8> HexStringToVector(std::string_view str, bool little_endian);
|
||||
[[nodiscard]] std::vector<u8> HexStringToVector(std::string_view str, bool little_endian);
|
||||
|
||||
template <std::size_t Size, bool le = false>
|
||||
constexpr std::array<u8, Size> HexStringToArray(std::string_view str) {
|
||||
[[nodiscard]] constexpr std::array<u8, Size> HexStringToArray(std::string_view str) {
|
||||
std::array<u8, Size> out{};
|
||||
if constexpr (le) {
|
||||
for (std::size_t i = 2 * Size - 2; i <= 2 * Size; i -= 2) {
|
||||
@@ -44,7 +44,7 @@ constexpr std::array<u8, Size> HexStringToArray(std::string_view str) {
|
||||
}
|
||||
|
||||
template <typename ContiguousContainer>
|
||||
std::string HexToString(const ContiguousContainer& data, bool upper = true) {
|
||||
[[nodiscard]] std::string HexToString(const ContiguousContainer& data, bool upper = true) {
|
||||
static_assert(std::is_same_v<typename ContiguousContainer::value_type, u8>,
|
||||
"Underlying type within the contiguous container must be u8.");
|
||||
|
||||
@@ -60,11 +60,11 @@ std::string HexToString(const ContiguousContainer& data, bool upper = true) {
|
||||
return out;
|
||||
}
|
||||
|
||||
constexpr std::array<u8, 16> AsArray(const char (&data)[17]) {
|
||||
[[nodiscard]] constexpr std::array<u8, 16> AsArray(const char (&data)[17]) {
|
||||
return HexStringToArray<16>(data);
|
||||
}
|
||||
|
||||
constexpr std::array<u8, 32> AsArray(const char (&data)[65]) {
|
||||
[[nodiscard]] constexpr std::array<u8, 32> AsArray(const char (&data)[65]) {
|
||||
return HexStringToArray<32>(data);
|
||||
}
|
||||
|
||||
|
||||
@@ -14,19 +14,19 @@ std::vector<u8> CompressDataLZ4(const u8* source, std::size_t source_size) {
|
||||
ASSERT_MSG(source_size <= LZ4_MAX_INPUT_SIZE, "Source size exceeds LZ4 maximum input size");
|
||||
|
||||
const auto source_size_int = static_cast<int>(source_size);
|
||||
const int max_compressed_size = LZ4_compressBound(source_size_int);
|
||||
const auto max_compressed_size = static_cast<std::size_t>(LZ4_compressBound(source_size_int));
|
||||
std::vector<u8> compressed(max_compressed_size);
|
||||
|
||||
const int compressed_size = LZ4_compress_default(reinterpret_cast<const char*>(source),
|
||||
reinterpret_cast<char*>(compressed.data()),
|
||||
source_size_int, max_compressed_size);
|
||||
const int compressed_size = LZ4_compress_default(
|
||||
reinterpret_cast<const char*>(source), reinterpret_cast<char*>(compressed.data()),
|
||||
source_size_int, static_cast<int>(max_compressed_size));
|
||||
|
||||
if (compressed_size <= 0) {
|
||||
// Compression failed
|
||||
return {};
|
||||
}
|
||||
|
||||
compressed.resize(compressed_size);
|
||||
compressed.resize(static_cast<std::size_t>(compressed_size));
|
||||
|
||||
return compressed;
|
||||
}
|
||||
@@ -38,19 +38,19 @@ std::vector<u8> CompressDataLZ4HC(const u8* source, std::size_t source_size,
|
||||
compression_level = std::clamp(compression_level, LZ4HC_CLEVEL_MIN, LZ4HC_CLEVEL_MAX);
|
||||
|
||||
const auto source_size_int = static_cast<int>(source_size);
|
||||
const int max_compressed_size = LZ4_compressBound(source_size_int);
|
||||
const auto max_compressed_size = static_cast<std::size_t>(LZ4_compressBound(source_size_int));
|
||||
std::vector<u8> compressed(max_compressed_size);
|
||||
|
||||
const int compressed_size = LZ4_compress_HC(
|
||||
reinterpret_cast<const char*>(source), reinterpret_cast<char*>(compressed.data()),
|
||||
source_size_int, max_compressed_size, compression_level);
|
||||
source_size_int, static_cast<int>(max_compressed_size), compression_level);
|
||||
|
||||
if (compressed_size <= 0) {
|
||||
// Compression failed
|
||||
return {};
|
||||
}
|
||||
|
||||
compressed.resize(compressed_size);
|
||||
compressed.resize(static_cast<std::size_t>(compressed_size));
|
||||
|
||||
return compressed;
|
||||
}
|
||||
|
||||
@@ -13,12 +13,12 @@ namespace Common::Compression {
|
||||
/**
|
||||
* Compresses a source memory region with LZ4 and returns the compressed data in a vector.
|
||||
*
|
||||
* @param source the uncompressed source memory region.
|
||||
* @param source_size the size in bytes of the uncompressed source memory region.
|
||||
* @param source The uncompressed source memory region.
|
||||
* @param source_size The size of the uncompressed source memory region.
|
||||
*
|
||||
* @return the compressed data.
|
||||
*/
|
||||
std::vector<u8> CompressDataLZ4(const u8* source, std::size_t source_size);
|
||||
[[nodiscard]] std::vector<u8> CompressDataLZ4(const u8* source, std::size_t source_size);
|
||||
|
||||
/**
|
||||
* Utilizes the LZ4 subalgorithm LZ4HC with the specified compression level. Higher compression
|
||||
@@ -26,23 +26,24 @@ std::vector<u8> CompressDataLZ4(const u8* source, std::size_t source_size);
|
||||
* compression level has almost no impact on decompression speed. Data compressed with LZ4HC can
|
||||
* also be decompressed with the default LZ4 decompression.
|
||||
*
|
||||
* @param source the uncompressed source memory region.
|
||||
* @param source_size the size in bytes of the uncompressed source memory region.
|
||||
* @param compression_level the used compression level. Should be between 3 and 12.
|
||||
* @param source The uncompressed source memory region.
|
||||
* @param source_size The size of the uncompressed source memory region.
|
||||
* @param compression_level The used compression level. Should be between 3 and 12.
|
||||
*
|
||||
* @return the compressed data.
|
||||
*/
|
||||
std::vector<u8> CompressDataLZ4HC(const u8* source, std::size_t source_size, s32 compression_level);
|
||||
[[nodiscard]] std::vector<u8> CompressDataLZ4HC(const u8* source, std::size_t source_size,
|
||||
s32 compression_level);
|
||||
|
||||
/**
|
||||
* Utilizes the LZ4 subalgorithm LZ4HC with the highest possible compression level.
|
||||
*
|
||||
* @param source the uncompressed source memory region.
|
||||
* @param source_size the size in bytes of the uncompressed source memory region.
|
||||
* @param source The uncompressed source memory region.
|
||||
* @param source_size The size of the uncompressed source memory region
|
||||
*
|
||||
* @return the compressed data.
|
||||
*/
|
||||
std::vector<u8> CompressDataLZ4HCMax(const u8* source, std::size_t source_size);
|
||||
[[nodiscard]] std::vector<u8> CompressDataLZ4HCMax(const u8* source, std::size_t source_size);
|
||||
|
||||
/**
|
||||
* Decompresses a source memory region with LZ4 and returns the uncompressed data in a vector.
|
||||
@@ -52,6 +53,7 @@ std::vector<u8> CompressDataLZ4HCMax(const u8* source, std::size_t source_size);
|
||||
*
|
||||
* @return the decompressed data.
|
||||
*/
|
||||
std::vector<u8> DecompressDataLZ4(const std::vector<u8>& compressed, std::size_t uncompressed_size);
|
||||
[[nodiscard]] std::vector<u8> DecompressDataLZ4(const std::vector<u8>& compressed,
|
||||
std::size_t uncompressed_size);
|
||||
|
||||
} // namespace Common::Compression
|
||||
@@ -23,7 +23,7 @@ struct Rectangle {
|
||||
constexpr Rectangle(T left, T top, T right, T bottom)
|
||||
: left(left), top(top), right(right), bottom(bottom) {}
|
||||
|
||||
T GetWidth() const {
|
||||
[[nodiscard]] T GetWidth() const {
|
||||
if constexpr (std::is_floating_point_v<T>) {
|
||||
return std::abs(right - left);
|
||||
} else {
|
||||
@@ -31,7 +31,7 @@ struct Rectangle {
|
||||
}
|
||||
}
|
||||
|
||||
T GetHeight() const {
|
||||
[[nodiscard]] T GetHeight() const {
|
||||
if constexpr (std::is_floating_point_v<T>) {
|
||||
return std::abs(bottom - top);
|
||||
} else {
|
||||
@@ -39,21 +39,21 @@ struct Rectangle {
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle<T> TranslateX(const T x) const {
|
||||
[[nodiscard]] Rectangle<T> TranslateX(const T x) const {
|
||||
return Rectangle{left + x, top, right + x, bottom};
|
||||
}
|
||||
|
||||
Rectangle<T> TranslateY(const T y) const {
|
||||
[[nodiscard]] Rectangle<T> TranslateY(const T y) const {
|
||||
return Rectangle{left, top + y, right, bottom + y};
|
||||
}
|
||||
|
||||
Rectangle<T> Scale(const float s) const {
|
||||
[[nodiscard]] Rectangle<T> Scale(const float s) const {
|
||||
return Rectangle{left, top, static_cast<T>(left + GetWidth() * s),
|
||||
static_cast<T>(top + GetHeight() * s)};
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
Rectangle(T, T, T, T)->Rectangle<T>;
|
||||
Rectangle(T, T, T, T) -> Rectangle<T>;
|
||||
|
||||
} // namespace Common
|
||||
|
||||
@@ -17,6 +17,6 @@ struct MemoryInfo {
|
||||
* Gets the memory info of the host system
|
||||
* @return Reference to a MemoryInfo struct with the physical and swap memory sizes in bytes
|
||||
*/
|
||||
const MemoryInfo& GetMemInfo();
|
||||
[[nodiscard]] const MemoryInfo& GetMemInfo();
|
||||
|
||||
} // namespace Common
|
||||
@@ -223,15 +223,15 @@ public:
|
||||
ListShiftForward(levels[priority], n);
|
||||
}
|
||||
|
||||
std::size_t depth() const {
|
||||
[[nodiscard]] std::size_t depth() const {
|
||||
return Depth;
|
||||
}
|
||||
|
||||
std::size_t size(u32 priority) const {
|
||||
[[nodiscard]] std::size_t size(u32 priority) const {
|
||||
return levels[priority].size();
|
||||
}
|
||||
|
||||
std::size_t size() const {
|
||||
[[nodiscard]] std::size_t size() const {
|
||||
u64 priorities = used_priorities;
|
||||
std::size_t size = 0;
|
||||
while (priorities != 0) {
|
||||
@@ -242,64 +242,64 @@ public:
|
||||
return size;
|
||||
}
|
||||
|
||||
bool empty() const {
|
||||
[[nodiscard]] bool empty() const {
|
||||
return used_priorities == 0;
|
||||
}
|
||||
|
||||
bool empty(u32 priority) const {
|
||||
[[nodiscard]] bool empty(u32 priority) const {
|
||||
return (used_priorities & (1ULL << priority)) == 0;
|
||||
}
|
||||
|
||||
u32 highest_priority_set(u32 max_priority = 0) const {
|
||||
[[nodiscard]] u32 highest_priority_set(u32 max_priority = 0) const {
|
||||
const u64 priorities =
|
||||
max_priority == 0 ? used_priorities : (used_priorities & ~((1ULL << max_priority) - 1));
|
||||
return priorities == 0 ? Depth : static_cast<u32>(CountTrailingZeroes64(priorities));
|
||||
}
|
||||
|
||||
u32 lowest_priority_set(u32 min_priority = Depth - 1) const {
|
||||
[[nodiscard]] u32 lowest_priority_set(u32 min_priority = Depth - 1) const {
|
||||
const u64 priorities = min_priority >= Depth - 1
|
||||
? used_priorities
|
||||
: (used_priorities & ((1ULL << (min_priority + 1)) - 1));
|
||||
return priorities == 0 ? Depth : 63 - CountLeadingZeroes64(priorities);
|
||||
}
|
||||
|
||||
const_iterator cbegin(u32 max_prio = 0) const {
|
||||
[[nodiscard]] const_iterator cbegin(u32 max_prio = 0) const {
|
||||
const u32 priority = highest_priority_set(max_prio);
|
||||
return priority == Depth ? cend()
|
||||
: const_iterator{*this, levels[priority].cbegin(), priority};
|
||||
}
|
||||
const_iterator begin(u32 max_prio = 0) const {
|
||||
[[nodiscard]] const_iterator begin(u32 max_prio = 0) const {
|
||||
return cbegin(max_prio);
|
||||
}
|
||||
iterator begin(u32 max_prio = 0) {
|
||||
[[nodiscard]] iterator begin(u32 max_prio = 0) {
|
||||
const u32 priority = highest_priority_set(max_prio);
|
||||
return priority == Depth ? end() : iterator{*this, levels[priority].begin(), priority};
|
||||
}
|
||||
|
||||
const_iterator cend(u32 min_prio = Depth - 1) const {
|
||||
[[nodiscard]] const_iterator cend(u32 min_prio = Depth - 1) const {
|
||||
return min_prio == Depth - 1 ? const_iterator{*this, Depth} : cbegin(min_prio + 1);
|
||||
}
|
||||
const_iterator end(u32 min_prio = Depth - 1) const {
|
||||
[[nodiscard]] const_iterator end(u32 min_prio = Depth - 1) const {
|
||||
return cend(min_prio);
|
||||
}
|
||||
iterator end(u32 min_prio = Depth - 1) {
|
||||
[[nodiscard]] iterator end(u32 min_prio = Depth - 1) {
|
||||
return min_prio == Depth - 1 ? iterator{*this, Depth} : begin(min_prio + 1);
|
||||
}
|
||||
|
||||
T& front(u32 max_priority = 0) {
|
||||
[[nodiscard]] T& front(u32 max_priority = 0) {
|
||||
const u32 priority = highest_priority_set(max_priority);
|
||||
return levels[priority == Depth ? 0 : priority].front();
|
||||
}
|
||||
const T& front(u32 max_priority = 0) const {
|
||||
[[nodiscard]] const T& front(u32 max_priority = 0) const {
|
||||
const u32 priority = highest_priority_set(max_priority);
|
||||
return levels[priority == Depth ? 0 : priority].front();
|
||||
}
|
||||
|
||||
T back(u32 min_priority = Depth - 1) {
|
||||
[[nodiscard]] T& back(u32 min_priority = Depth - 1) {
|
||||
const u32 priority = lowest_priority_set(min_priority); // intended
|
||||
return levels[priority == Depth ? 63 : priority].back();
|
||||
}
|
||||
const T& back(u32 min_priority = Depth - 1) const {
|
||||
[[nodiscard]] const T& back(u32 min_priority = Depth - 1) const {
|
||||
const u32 priority = lowest_priority_set(min_priority); // intended
|
||||
return levels[priority == Depth ? 63 : priority].back();
|
||||
}
|
||||
@@ -329,7 +329,8 @@ private:
|
||||
in_list.splice(position, out_list, element);
|
||||
}
|
||||
|
||||
static const_list_iterator ListIterateTo(const std::list<T>& list, const T& element) {
|
||||
[[nodiscard]] static const_list_iterator ListIterateTo(const std::list<T>& list,
|
||||
const T& element) {
|
||||
auto it = list.cbegin();
|
||||
while (it != list.cend() && *it != element) {
|
||||
++it;
|
||||
|
||||
@@ -36,11 +36,11 @@ struct SpecialRegion {
|
||||
|
||||
MemoryHookPointer handler;
|
||||
|
||||
bool operator<(const SpecialRegion& other) const {
|
||||
[[nodiscard]] bool operator<(const SpecialRegion& other) const {
|
||||
return std::tie(type, handler) < std::tie(other.type, other.handler);
|
||||
}
|
||||
|
||||
bool operator==(const SpecialRegion& other) const {
|
||||
[[nodiscard]] bool operator==(const SpecialRegion& other) const {
|
||||
return std::tie(type, handler) == std::tie(other.type, other.handler);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -24,14 +24,14 @@ public:
|
||||
ParamPackage& operator=(const ParamPackage& other) = default;
|
||||
ParamPackage& operator=(ParamPackage&& other) = default;
|
||||
|
||||
std::string Serialize() const;
|
||||
std::string Get(const std::string& key, const std::string& default_value) const;
|
||||
int Get(const std::string& key, int default_value) const;
|
||||
float Get(const std::string& key, float default_value) const;
|
||||
[[nodiscard]] std::string Serialize() const;
|
||||
[[nodiscard]] std::string Get(const std::string& key, const std::string& default_value) const;
|
||||
[[nodiscard]] int Get(const std::string& key, int default_value) const;
|
||||
[[nodiscard]] float Get(const std::string& key, float default_value) const;
|
||||
void Set(const std::string& key, std::string value);
|
||||
void Set(const std::string& key, int value);
|
||||
void Set(const std::string& key, float value);
|
||||
bool Has(const std::string& key) const;
|
||||
[[nodiscard]] bool Has(const std::string& key) const;
|
||||
void Erase(const std::string& key);
|
||||
void Clear();
|
||||
|
||||
|
||||
@@ -14,35 +14,36 @@ public:
|
||||
Vec3<T> xyz;
|
||||
T w{};
|
||||
|
||||
Quaternion<decltype(-T{})> Inverse() const {
|
||||
[[nodiscard]] Quaternion<decltype(-T{})> Inverse() const {
|
||||
return {-xyz, w};
|
||||
}
|
||||
|
||||
Quaternion<decltype(T{} + T{})> operator+(const Quaternion& other) const {
|
||||
[[nodiscard]] Quaternion<decltype(T{} + T{})> operator+(const Quaternion& other) const {
|
||||
return {xyz + other.xyz, w + other.w};
|
||||
}
|
||||
|
||||
Quaternion<decltype(T{} - T{})> operator-(const Quaternion& other) const {
|
||||
[[nodiscard]] Quaternion<decltype(T{} - T{})> operator-(const Quaternion& other) const {
|
||||
return {xyz - other.xyz, w - other.w};
|
||||
}
|
||||
|
||||
Quaternion<decltype(T{} * T{} - T{} * T{})> operator*(const Quaternion& other) const {
|
||||
[[nodiscard]] Quaternion<decltype(T{} * T{} - T{} * T{})> operator*(
|
||||
const Quaternion& other) const {
|
||||
return {xyz * other.w + other.xyz * w + Cross(xyz, other.xyz),
|
||||
w * other.w - Dot(xyz, other.xyz)};
|
||||
}
|
||||
|
||||
Quaternion<T> Normalized() const {
|
||||
[[nodiscard]] Quaternion<T> Normalized() const {
|
||||
T length = std::sqrt(xyz.Length2() + w * w);
|
||||
return {xyz / length, w / length};
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
auto QuaternionRotate(const Quaternion<T>& q, const Vec3<T>& v) {
|
||||
[[nodiscard]] auto QuaternionRotate(const Quaternion<T>& q, const Vec3<T>& v) {
|
||||
return v + 2 * Cross(q.xyz, Cross(q.xyz, v) + v * q.w);
|
||||
}
|
||||
|
||||
inline Quaternion<float> MakeQuaternion(const Vec3<float>& axis, float angle) {
|
||||
[[nodiscard]] inline Quaternion<float> MakeQuaternion(const Vec3<float>& axis, float angle) {
|
||||
return {axis * std::sin(angle / 2), std::cos(angle / 2)};
|
||||
}
|
||||
|
||||
|
||||
@@ -91,12 +91,12 @@ public:
|
||||
}
|
||||
|
||||
/// @returns Number of slots used
|
||||
std::size_t Size() const {
|
||||
[[nodiscard]] std::size_t Size() const {
|
||||
return m_write_index.load() - m_read_index.load();
|
||||
}
|
||||
|
||||
/// @returns Maximum size of ring buffer
|
||||
constexpr std::size_t Capacity() const {
|
||||
[[nodiscard]] constexpr std::size_t Capacity() const {
|
||||
return capacity;
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ class SpinLock {
|
||||
public:
|
||||
void lock();
|
||||
void unlock();
|
||||
bool try_lock();
|
||||
[[nodiscard]] bool try_lock();
|
||||
|
||||
private:
|
||||
std::atomic_flag lck = ATOMIC_FLAG_INIT;
|
||||
|
||||
+18
-16
@@ -12,19 +12,19 @@
|
||||
namespace Common {
|
||||
|
||||
/// Make a string lowercase
|
||||
std::string ToLower(std::string str);
|
||||
[[nodiscard]] std::string ToLower(std::string str);
|
||||
|
||||
/// Make a string uppercase
|
||||
std::string ToUpper(std::string str);
|
||||
[[nodiscard]] std::string ToUpper(std::string str);
|
||||
|
||||
std::string StringFromBuffer(const std::vector<u8>& data);
|
||||
[[nodiscard]] std::string StringFromBuffer(const std::vector<u8>& data);
|
||||
|
||||
std::string StripSpaces(const std::string& s);
|
||||
std::string StripQuotes(const std::string& s);
|
||||
[[nodiscard]] std::string StripSpaces(const std::string& s);
|
||||
[[nodiscard]] std::string StripQuotes(const std::string& s);
|
||||
|
||||
std::string StringFromBool(bool value);
|
||||
[[nodiscard]] std::string StringFromBool(bool value);
|
||||
|
||||
std::string TabsToSpaces(int tab_size, std::string in);
|
||||
[[nodiscard]] std::string TabsToSpaces(int tab_size, std::string in);
|
||||
|
||||
void SplitString(const std::string& str, char delim, std::vector<std::string>& output);
|
||||
|
||||
@@ -34,14 +34,15 @@ bool SplitPath(const std::string& full_path, std::string* _pPath, std::string* _
|
||||
|
||||
void BuildCompleteFilename(std::string& _CompleteFilename, const std::string& _Path,
|
||||
const std::string& _Filename);
|
||||
std::string ReplaceAll(std::string result, const std::string& src, const std::string& dest);
|
||||
[[nodiscard]] std::string ReplaceAll(std::string result, const std::string& src,
|
||||
const std::string& dest);
|
||||
|
||||
std::string UTF16ToUTF8(const std::u16string& input);
|
||||
std::u16string UTF8ToUTF16(const std::string& input);
|
||||
[[nodiscard]] std::string UTF16ToUTF8(const std::u16string& input);
|
||||
[[nodiscard]] std::u16string UTF8ToUTF16(const std::string& input);
|
||||
|
||||
#ifdef _WIN32
|
||||
std::string UTF16ToUTF8(const std::wstring& input);
|
||||
std::wstring UTF8ToUTF16W(const std::string& str);
|
||||
[[nodiscard]] std::string UTF16ToUTF8(const std::wstring& input);
|
||||
[[nodiscard]] std::wstring UTF8ToUTF16W(const std::string& str);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -50,7 +51,7 @@ std::wstring UTF8ToUTF16W(const std::string& str);
|
||||
* `other` for equality.
|
||||
*/
|
||||
template <typename InIt>
|
||||
bool ComparePartialString(InIt begin, InIt end, const char* other) {
|
||||
[[nodiscard]] bool ComparePartialString(InIt begin, InIt end, const char* other) {
|
||||
for (; begin != end && *other != '\0'; ++begin, ++other) {
|
||||
if (*begin != *other) {
|
||||
return false;
|
||||
@@ -64,14 +65,15 @@ bool ComparePartialString(InIt begin, InIt end, const char* other) {
|
||||
* Creates a std::string from a fixed-size NUL-terminated char buffer. If the buffer isn't
|
||||
* NUL-terminated then the string ends at max_len characters.
|
||||
*/
|
||||
std::string StringFromFixedZeroTerminatedBuffer(const char* buffer, std::size_t max_len);
|
||||
[[nodiscard]] std::string StringFromFixedZeroTerminatedBuffer(const char* buffer,
|
||||
std::size_t max_len);
|
||||
|
||||
/**
|
||||
* Creates a UTF-16 std::u16string from a fixed-size NUL-terminated char buffer. If the buffer isn't
|
||||
* null-terminated, then the string ends at the greatest multiple of two less then or equal to
|
||||
* max_len_bytes.
|
||||
*/
|
||||
std::u16string UTF16StringFromFixedZeroTerminatedBuffer(std::u16string_view buffer,
|
||||
std::size_t max_len);
|
||||
[[nodiscard]] std::u16string UTF16StringFromFixedZeroTerminatedBuffer(std::u16string_view buffer,
|
||||
std::size_t max_len);
|
||||
|
||||
} // namespace Common
|
||||
|
||||
@@ -63,30 +63,30 @@ public:
|
||||
|
||||
void Accept(VisitorInterface& visitor) const override;
|
||||
|
||||
const std::string& GetName() const override {
|
||||
[[nodiscard]] const std::string& GetName() const override {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the type of the field.
|
||||
*/
|
||||
FieldType GetType() const {
|
||||
[[nodiscard]] FieldType GetType() const {
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of the field.
|
||||
*/
|
||||
const T& GetValue() const {
|
||||
[[nodiscard]] const T& GetValue() const {
|
||||
return value;
|
||||
}
|
||||
|
||||
bool operator==(const Field& other) const {
|
||||
[[nodiscard]] bool operator==(const Field& other) const {
|
||||
return (type == other.type) && (name == other.name) && (value == other.value);
|
||||
}
|
||||
|
||||
bool operator!=(const Field& other) const {
|
||||
return !(*this == other);
|
||||
[[nodiscard]] bool operator!=(const Field& other) const {
|
||||
return !operator==(other);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
@@ -18,14 +18,14 @@ struct ThreadQueueList {
|
||||
using Priority = unsigned int;
|
||||
|
||||
// Number of priority levels. (Valid levels are [0..NUM_QUEUES).)
|
||||
static const Priority NUM_QUEUES = N;
|
||||
static constexpr Priority NUM_QUEUES = N;
|
||||
|
||||
ThreadQueueList() {
|
||||
first = nullptr;
|
||||
}
|
||||
|
||||
// Only for debugging, returns priority level.
|
||||
Priority contains(const T& uid) const {
|
||||
[[nodiscard]] Priority contains(const T& uid) const {
|
||||
for (Priority i = 0; i < NUM_QUEUES; ++i) {
|
||||
const Queue& cur = queues[i];
|
||||
if (std::find(cur.data.cbegin(), cur.data.cend(), uid) != cur.data.cend()) {
|
||||
@@ -36,7 +36,7 @@ struct ThreadQueueList {
|
||||
return -1;
|
||||
}
|
||||
|
||||
T get_first() const {
|
||||
[[nodiscard]] T get_first() const {
|
||||
const Queue* cur = first;
|
||||
while (cur != nullptr) {
|
||||
if (!cur->data.empty()) {
|
||||
@@ -49,7 +49,7 @@ struct ThreadQueueList {
|
||||
}
|
||||
|
||||
template <typename UnaryPredicate>
|
||||
T get_first_filter(UnaryPredicate filter) const {
|
||||
[[nodiscard]] T get_first_filter(UnaryPredicate filter) const {
|
||||
const Queue* cur = first;
|
||||
while (cur != nullptr) {
|
||||
if (!cur->data.empty()) {
|
||||
@@ -129,7 +129,7 @@ struct ThreadQueueList {
|
||||
first = nullptr;
|
||||
}
|
||||
|
||||
bool empty(Priority priority) const {
|
||||
[[nodiscard]] bool empty(Priority priority) const {
|
||||
const Queue* cur = &queues[priority];
|
||||
return cur->data.empty();
|
||||
}
|
||||
|
||||
@@ -25,15 +25,15 @@ public:
|
||||
delete read_ptr;
|
||||
}
|
||||
|
||||
std::size_t Size() const {
|
||||
[[nodiscard]] std::size_t Size() const {
|
||||
return size.load();
|
||||
}
|
||||
|
||||
bool Empty() const {
|
||||
[[nodiscard]] bool Empty() const {
|
||||
return Size() == 0;
|
||||
}
|
||||
|
||||
T& Front() const {
|
||||
[[nodiscard]] T& Front() const {
|
||||
return read_ptr->current;
|
||||
}
|
||||
|
||||
@@ -130,15 +130,15 @@ private:
|
||||
template <typename T>
|
||||
class MPSCQueue {
|
||||
public:
|
||||
std::size_t Size() const {
|
||||
[[nodiscard]] std::size_t Size() const {
|
||||
return spsc_queue.Size();
|
||||
}
|
||||
|
||||
bool Empty() const {
|
||||
[[nodiscard]] bool Empty() const {
|
||||
return spsc_queue.Empty();
|
||||
}
|
||||
|
||||
T& Front() const {
|
||||
[[nodiscard]] T& Front() const {
|
||||
return spsc_queue.Front();
|
||||
}
|
||||
|
||||
|
||||
@@ -10,9 +10,9 @@
|
||||
namespace Common::TimeZone {
|
||||
|
||||
/// Gets the default timezone, i.e. "GMT"
|
||||
std::string GetDefaultTimeZone();
|
||||
[[nodiscard]] std::string GetDefaultTimeZone();
|
||||
|
||||
/// Gets the offset of the current timezone (from the default), in seconds
|
||||
std::chrono::seconds GetCurrentOffsetSeconds();
|
||||
[[nodiscard]] std::chrono::seconds GetCurrentOffsetSeconds();
|
||||
|
||||
} // namespace Common::TimeZone
|
||||
|
||||
+8
-8
@@ -19,18 +19,18 @@ public:
|
||||
|
||||
// The time difference is always returned in milliseconds, regardless of alternative internal
|
||||
// representation
|
||||
std::chrono::milliseconds GetTimeDifference();
|
||||
[[nodiscard]] std::chrono::milliseconds GetTimeDifference();
|
||||
void AddTimeDifference();
|
||||
|
||||
static std::chrono::seconds GetTimeSinceJan1970();
|
||||
static std::chrono::seconds GetLocalTimeSinceJan1970();
|
||||
static double GetDoubleTime();
|
||||
[[nodiscard]] static std::chrono::seconds GetTimeSinceJan1970();
|
||||
[[nodiscard]] static std::chrono::seconds GetLocalTimeSinceJan1970();
|
||||
[[nodiscard]] static double GetDoubleTime();
|
||||
|
||||
static std::string GetTimeFormatted();
|
||||
std::string GetTimeElapsedFormatted() const;
|
||||
std::chrono::milliseconds GetTimeElapsed();
|
||||
[[nodiscard]] static std::string GetTimeFormatted();
|
||||
[[nodiscard]] std::string GetTimeElapsedFormatted() const;
|
||||
[[nodiscard]] std::chrono::milliseconds GetTimeElapsed();
|
||||
|
||||
static std::chrono::milliseconds GetTimeMs();
|
||||
[[nodiscard]] static std::chrono::milliseconds GetTimeMs();
|
||||
|
||||
private:
|
||||
std::chrono::milliseconds m_LastTime;
|
||||
|
||||
@@ -10,13 +10,13 @@
|
||||
namespace Common {
|
||||
|
||||
// This function multiplies 2 u64 values and divides it by a u64 value.
|
||||
u64 MultiplyAndDivide64(u64 a, u64 b, u64 d);
|
||||
[[nodiscard]] u64 MultiplyAndDivide64(u64 a, u64 b, u64 d);
|
||||
|
||||
// This function multiplies 2 u64 values and produces a u128 value;
|
||||
u128 Multiply64Into128(u64 a, u64 b);
|
||||
[[nodiscard]] u128 Multiply64Into128(u64 a, u64 b);
|
||||
|
||||
// This function divides a u128 by a u32 value and produces two u64 values:
|
||||
// the result of division and the remainder
|
||||
std::pair<u64, u64> Divide128On32(u128 dividend, u32 divisor);
|
||||
[[nodiscard]] std::pair<u64, u64> Divide128On32(u128 dividend, u32 divisor);
|
||||
|
||||
} // namespace Common
|
||||
|
||||
+7
-7
@@ -19,21 +19,21 @@ struct UUID {
|
||||
constexpr explicit UUID(const u128& id) : uuid{id} {}
|
||||
constexpr explicit UUID(const u64 lo, const u64 hi) : uuid{{lo, hi}} {}
|
||||
|
||||
constexpr explicit operator bool() const {
|
||||
[[nodiscard]] constexpr explicit operator bool() const {
|
||||
return uuid[0] != INVALID_UUID[0] && uuid[1] != INVALID_UUID[1];
|
||||
}
|
||||
|
||||
constexpr bool operator==(const UUID& rhs) const {
|
||||
[[nodiscard]] constexpr bool operator==(const UUID& rhs) const {
|
||||
// TODO(DarkLordZach): Replace with uuid == rhs.uuid with C++20
|
||||
return uuid[0] == rhs.uuid[0] && uuid[1] == rhs.uuid[1];
|
||||
}
|
||||
|
||||
constexpr bool operator!=(const UUID& rhs) const {
|
||||
[[nodiscard]] constexpr bool operator!=(const UUID& rhs) const {
|
||||
return !operator==(rhs);
|
||||
}
|
||||
|
||||
// TODO(ogniK): Properly generate uuids based on RFC-4122
|
||||
static UUID Generate();
|
||||
[[nodiscard]] static UUID Generate();
|
||||
|
||||
// Set the UUID to {0,0} to be considered an invalid user
|
||||
constexpr void Invalidate() {
|
||||
@@ -41,12 +41,12 @@ struct UUID {
|
||||
}
|
||||
|
||||
// TODO(ogniK): Properly generate a Nintendo ID
|
||||
constexpr u64 GetNintendoID() const {
|
||||
[[nodiscard]] constexpr u64 GetNintendoID() const {
|
||||
return uuid[0];
|
||||
}
|
||||
|
||||
std::string Format() const;
|
||||
std::string FormatSwitch() const;
|
||||
[[nodiscard]] std::string Format() const;
|
||||
[[nodiscard]] std::string FormatSwitch() const;
|
||||
};
|
||||
static_assert(sizeof(UUID) == 16, "UUID is an invalid size!");
|
||||
|
||||
|
||||
+103
-101
@@ -52,15 +52,15 @@ public:
|
||||
constexpr Vec2(const T& x_, const T& y_) : x(x_), y(y_) {}
|
||||
|
||||
template <typename T2>
|
||||
constexpr Vec2<T2> Cast() const {
|
||||
[[nodiscard]] constexpr Vec2<T2> Cast() const {
|
||||
return Vec2<T2>(static_cast<T2>(x), static_cast<T2>(y));
|
||||
}
|
||||
|
||||
static constexpr Vec2 AssignToAll(const T& f) {
|
||||
[[nodiscard]] static constexpr Vec2 AssignToAll(const T& f) {
|
||||
return Vec2{f, f};
|
||||
}
|
||||
|
||||
constexpr Vec2<decltype(T{} + T{})> operator+(const Vec2& other) const {
|
||||
[[nodiscard]] constexpr Vec2<decltype(T{} + T{})> operator+(const Vec2& other) const {
|
||||
return {x + other.x, y + other.y};
|
||||
}
|
||||
constexpr Vec2& operator+=(const Vec2& other) {
|
||||
@@ -68,7 +68,7 @@ public:
|
||||
y += other.y;
|
||||
return *this;
|
||||
}
|
||||
constexpr Vec2<decltype(T{} - T{})> operator-(const Vec2& other) const {
|
||||
[[nodiscard]] constexpr Vec2<decltype(T{} - T{})> operator-(const Vec2& other) const {
|
||||
return {x - other.x, y - other.y};
|
||||
}
|
||||
constexpr Vec2& operator-=(const Vec2& other) {
|
||||
@@ -78,15 +78,15 @@ public:
|
||||
}
|
||||
|
||||
template <typename U = T>
|
||||
constexpr Vec2<std::enable_if_t<std::is_signed_v<U>, U>> operator-() const {
|
||||
[[nodiscard]] constexpr Vec2<std::enable_if_t<std::is_signed_v<U>, U>> operator-() const {
|
||||
return {-x, -y};
|
||||
}
|
||||
constexpr Vec2<decltype(T{} * T{})> operator*(const Vec2& other) const {
|
||||
[[nodiscard]] constexpr Vec2<decltype(T{} * T{})> operator*(const Vec2& other) const {
|
||||
return {x * other.x, y * other.y};
|
||||
}
|
||||
|
||||
template <typename V>
|
||||
constexpr Vec2<decltype(T{} * V{})> operator*(const V& f) const {
|
||||
[[nodiscard]] constexpr Vec2<decltype(T{} * V{})> operator*(const V& f) const {
|
||||
return {x * f, y * f};
|
||||
}
|
||||
|
||||
@@ -97,7 +97,7 @@ public:
|
||||
}
|
||||
|
||||
template <typename V>
|
||||
constexpr Vec2<decltype(T{} / V{})> operator/(const V& f) const {
|
||||
[[nodiscard]] constexpr Vec2<decltype(T{} / V{})> operator/(const V& f) const {
|
||||
return {x / f, y / f};
|
||||
}
|
||||
|
||||
@@ -107,18 +107,18 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr T Length2() const {
|
||||
[[nodiscard]] constexpr T Length2() const {
|
||||
return x * x + y * y;
|
||||
}
|
||||
|
||||
// Only implemented for T=float
|
||||
float Length() const;
|
||||
float Normalize(); // returns the previous length, which is often useful
|
||||
[[nodiscard]] float Length() const;
|
||||
[[nodiscard]] float Normalize(); // returns the previous length, which is often useful
|
||||
|
||||
constexpr T& operator[](std::size_t i) {
|
||||
[[nodiscard]] constexpr T& operator[](std::size_t i) {
|
||||
return *((&x) + i);
|
||||
}
|
||||
constexpr const T& operator[](std::size_t i) const {
|
||||
[[nodiscard]] constexpr const T& operator[](std::size_t i) const {
|
||||
return *((&x) + i);
|
||||
}
|
||||
|
||||
@@ -128,46 +128,46 @@ public:
|
||||
}
|
||||
|
||||
// Common aliases: UV (texel coordinates), ST (texture coordinates)
|
||||
constexpr T& u() {
|
||||
[[nodiscard]] constexpr T& u() {
|
||||
return x;
|
||||
}
|
||||
constexpr T& v() {
|
||||
[[nodiscard]] constexpr T& v() {
|
||||
return y;
|
||||
}
|
||||
constexpr T& s() {
|
||||
[[nodiscard]] constexpr T& s() {
|
||||
return x;
|
||||
}
|
||||
constexpr T& t() {
|
||||
[[nodiscard]] constexpr T& t() {
|
||||
return y;
|
||||
}
|
||||
|
||||
constexpr const T& u() const {
|
||||
[[nodiscard]] constexpr const T& u() const {
|
||||
return x;
|
||||
}
|
||||
constexpr const T& v() const {
|
||||
[[nodiscard]] constexpr const T& v() const {
|
||||
return y;
|
||||
}
|
||||
constexpr const T& s() const {
|
||||
[[nodiscard]] constexpr const T& s() const {
|
||||
return x;
|
||||
}
|
||||
constexpr const T& t() const {
|
||||
[[nodiscard]] constexpr const T& t() const {
|
||||
return y;
|
||||
}
|
||||
|
||||
// swizzlers - create a subvector of specific components
|
||||
constexpr Vec2 yx() const {
|
||||
[[nodiscard]] constexpr Vec2 yx() const {
|
||||
return Vec2(y, x);
|
||||
}
|
||||
constexpr Vec2 vu() const {
|
||||
[[nodiscard]] constexpr Vec2 vu() const {
|
||||
return Vec2(y, x);
|
||||
}
|
||||
constexpr Vec2 ts() const {
|
||||
[[nodiscard]] constexpr Vec2 ts() const {
|
||||
return Vec2(y, x);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, typename V>
|
||||
constexpr Vec2<T> operator*(const V& f, const Vec2<T>& vec) {
|
||||
[[nodiscard]] constexpr Vec2<T> operator*(const V& f, const Vec2<T>& vec) {
|
||||
return Vec2<T>(f * vec.x, f * vec.y);
|
||||
}
|
||||
|
||||
@@ -196,15 +196,15 @@ public:
|
||||
constexpr Vec3(const T& x_, const T& y_, const T& z_) : x(x_), y(y_), z(z_) {}
|
||||
|
||||
template <typename T2>
|
||||
constexpr Vec3<T2> Cast() const {
|
||||
[[nodiscard]] constexpr Vec3<T2> Cast() const {
|
||||
return Vec3<T2>(static_cast<T2>(x), static_cast<T2>(y), static_cast<T2>(z));
|
||||
}
|
||||
|
||||
static constexpr Vec3 AssignToAll(const T& f) {
|
||||
[[nodiscard]] static constexpr Vec3 AssignToAll(const T& f) {
|
||||
return Vec3(f, f, f);
|
||||
}
|
||||
|
||||
constexpr Vec3<decltype(T{} + T{})> operator+(const Vec3& other) const {
|
||||
[[nodiscard]] constexpr Vec3<decltype(T{} + T{})> operator+(const Vec3& other) const {
|
||||
return {x + other.x, y + other.y, z + other.z};
|
||||
}
|
||||
|
||||
@@ -215,7 +215,7 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr Vec3<decltype(T{} - T{})> operator-(const Vec3& other) const {
|
||||
[[nodiscard]] constexpr Vec3<decltype(T{} - T{})> operator-(const Vec3& other) const {
|
||||
return {x - other.x, y - other.y, z - other.z};
|
||||
}
|
||||
|
||||
@@ -227,16 +227,16 @@ public:
|
||||
}
|
||||
|
||||
template <typename U = T>
|
||||
constexpr Vec3<std::enable_if_t<std::is_signed_v<U>, U>> operator-() const {
|
||||
[[nodiscard]] constexpr Vec3<std::enable_if_t<std::is_signed_v<U>, U>> operator-() const {
|
||||
return {-x, -y, -z};
|
||||
}
|
||||
|
||||
constexpr Vec3<decltype(T{} * T{})> operator*(const Vec3& other) const {
|
||||
[[nodiscard]] constexpr Vec3<decltype(T{} * T{})> operator*(const Vec3& other) const {
|
||||
return {x * other.x, y * other.y, z * other.z};
|
||||
}
|
||||
|
||||
template <typename V>
|
||||
constexpr Vec3<decltype(T{} * V{})> operator*(const V& f) const {
|
||||
[[nodiscard]] constexpr Vec3<decltype(T{} * V{})> operator*(const V& f) const {
|
||||
return {x * f, y * f, z * f};
|
||||
}
|
||||
|
||||
@@ -246,7 +246,7 @@ public:
|
||||
return *this;
|
||||
}
|
||||
template <typename V>
|
||||
constexpr Vec3<decltype(T{} / V{})> operator/(const V& f) const {
|
||||
[[nodiscard]] constexpr Vec3<decltype(T{} / V{})> operator/(const V& f) const {
|
||||
return {x / f, y / f, z / f};
|
||||
}
|
||||
|
||||
@@ -256,20 +256,20 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr T Length2() const {
|
||||
[[nodiscard]] constexpr T Length2() const {
|
||||
return x * x + y * y + z * z;
|
||||
}
|
||||
|
||||
// Only implemented for T=float
|
||||
float Length() const;
|
||||
Vec3 Normalized() const;
|
||||
float Normalize(); // returns the previous length, which is often useful
|
||||
[[nodiscard]] float Length() const;
|
||||
[[nodiscard]] Vec3 Normalized() const;
|
||||
[[nodiscard]] float Normalize(); // returns the previous length, which is often useful
|
||||
|
||||
constexpr T& operator[](std::size_t i) {
|
||||
[[nodiscard]] constexpr T& operator[](std::size_t i) {
|
||||
return *((&x) + i);
|
||||
}
|
||||
|
||||
constexpr const T& operator[](std::size_t i) const {
|
||||
[[nodiscard]] constexpr const T& operator[](std::size_t i) const {
|
||||
return *((&x) + i);
|
||||
}
|
||||
|
||||
@@ -280,63 +280,63 @@ public:
|
||||
}
|
||||
|
||||
// Common aliases: UVW (texel coordinates), RGB (colors), STQ (texture coordinates)
|
||||
constexpr T& u() {
|
||||
[[nodiscard]] constexpr T& u() {
|
||||
return x;
|
||||
}
|
||||
constexpr T& v() {
|
||||
[[nodiscard]] constexpr T& v() {
|
||||
return y;
|
||||
}
|
||||
constexpr T& w() {
|
||||
[[nodiscard]] constexpr T& w() {
|
||||
return z;
|
||||
}
|
||||
|
||||
constexpr T& r() {
|
||||
[[nodiscard]] constexpr T& r() {
|
||||
return x;
|
||||
}
|
||||
constexpr T& g() {
|
||||
[[nodiscard]] constexpr T& g() {
|
||||
return y;
|
||||
}
|
||||
constexpr T& b() {
|
||||
[[nodiscard]] constexpr T& b() {
|
||||
return z;
|
||||
}
|
||||
|
||||
constexpr T& s() {
|
||||
[[nodiscard]] constexpr T& s() {
|
||||
return x;
|
||||
}
|
||||
constexpr T& t() {
|
||||
[[nodiscard]] constexpr T& t() {
|
||||
return y;
|
||||
}
|
||||
constexpr T& q() {
|
||||
[[nodiscard]] constexpr T& q() {
|
||||
return z;
|
||||
}
|
||||
|
||||
constexpr const T& u() const {
|
||||
[[nodiscard]] constexpr const T& u() const {
|
||||
return x;
|
||||
}
|
||||
constexpr const T& v() const {
|
||||
[[nodiscard]] constexpr const T& v() const {
|
||||
return y;
|
||||
}
|
||||
constexpr const T& w() const {
|
||||
[[nodiscard]] constexpr const T& w() const {
|
||||
return z;
|
||||
}
|
||||
|
||||
constexpr const T& r() const {
|
||||
[[nodiscard]] constexpr const T& r() const {
|
||||
return x;
|
||||
}
|
||||
constexpr const T& g() const {
|
||||
[[nodiscard]] constexpr const T& g() const {
|
||||
return y;
|
||||
}
|
||||
constexpr const T& b() const {
|
||||
[[nodiscard]] constexpr const T& b() const {
|
||||
return z;
|
||||
}
|
||||
|
||||
constexpr const T& s() const {
|
||||
[[nodiscard]] constexpr const T& s() const {
|
||||
return x;
|
||||
}
|
||||
constexpr const T& t() const {
|
||||
[[nodiscard]] constexpr const T& t() const {
|
||||
return y;
|
||||
}
|
||||
constexpr const T& q() const {
|
||||
[[nodiscard]] constexpr const T& q() const {
|
||||
return z;
|
||||
}
|
||||
|
||||
@@ -345,7 +345,7 @@ public:
|
||||
// _DEFINE_SWIZZLER2 defines a single such function, DEFINE_SWIZZLER2 defines all of them for all
|
||||
// component names (x<->r) and permutations (xy<->yx)
|
||||
#define _DEFINE_SWIZZLER2(a, b, name) \
|
||||
constexpr Vec2<T> name() const { \
|
||||
[[nodiscard]] constexpr Vec2<T> name() const { \
|
||||
return Vec2<T>(a, b); \
|
||||
}
|
||||
#define DEFINE_SWIZZLER2(a, b, a2, b2, a3, b3, a4, b4) \
|
||||
@@ -366,7 +366,7 @@ public:
|
||||
};
|
||||
|
||||
template <typename T, typename V>
|
||||
constexpr Vec3<T> operator*(const V& f, const Vec3<T>& vec) {
|
||||
[[nodiscard]] constexpr Vec3<T> operator*(const V& f, const Vec3<T>& vec) {
|
||||
return Vec3<T>(f * vec.x, f * vec.y, f * vec.z);
|
||||
}
|
||||
|
||||
@@ -402,16 +402,16 @@ public:
|
||||
: x(x_), y(y_), z(z_), w(w_) {}
|
||||
|
||||
template <typename T2>
|
||||
constexpr Vec4<T2> Cast() const {
|
||||
[[nodiscard]] constexpr Vec4<T2> Cast() const {
|
||||
return Vec4<T2>(static_cast<T2>(x), static_cast<T2>(y), static_cast<T2>(z),
|
||||
static_cast<T2>(w));
|
||||
}
|
||||
|
||||
static constexpr Vec4 AssignToAll(const T& f) {
|
||||
[[nodiscard]] static constexpr Vec4 AssignToAll(const T& f) {
|
||||
return Vec4(f, f, f, f);
|
||||
}
|
||||
|
||||
constexpr Vec4<decltype(T{} + T{})> operator+(const Vec4& other) const {
|
||||
[[nodiscard]] constexpr Vec4<decltype(T{} + T{})> operator+(const Vec4& other) const {
|
||||
return {x + other.x, y + other.y, z + other.z, w + other.w};
|
||||
}
|
||||
|
||||
@@ -423,7 +423,7 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr Vec4<decltype(T{} - T{})> operator-(const Vec4& other) const {
|
||||
[[nodiscard]] constexpr Vec4<decltype(T{} - T{})> operator-(const Vec4& other) const {
|
||||
return {x - other.x, y - other.y, z - other.z, w - other.w};
|
||||
}
|
||||
|
||||
@@ -436,16 +436,16 @@ public:
|
||||
}
|
||||
|
||||
template <typename U = T>
|
||||
constexpr Vec4<std::enable_if_t<std::is_signed_v<U>, U>> operator-() const {
|
||||
[[nodiscard]] constexpr Vec4<std::enable_if_t<std::is_signed_v<U>, U>> operator-() const {
|
||||
return {-x, -y, -z, -w};
|
||||
}
|
||||
|
||||
constexpr Vec4<decltype(T{} * T{})> operator*(const Vec4& other) const {
|
||||
[[nodiscard]] constexpr Vec4<decltype(T{} * T{})> operator*(const Vec4& other) const {
|
||||
return {x * other.x, y * other.y, z * other.z, w * other.w};
|
||||
}
|
||||
|
||||
template <typename V>
|
||||
constexpr Vec4<decltype(T{} * V{})> operator*(const V& f) const {
|
||||
[[nodiscard]] constexpr Vec4<decltype(T{} * V{})> operator*(const V& f) const {
|
||||
return {x * f, y * f, z * f, w * f};
|
||||
}
|
||||
|
||||
@@ -456,7 +456,7 @@ public:
|
||||
}
|
||||
|
||||
template <typename V>
|
||||
constexpr Vec4<decltype(T{} / V{})> operator/(const V& f) const {
|
||||
[[nodiscard]] constexpr Vec4<decltype(T{} / V{})> operator/(const V& f) const {
|
||||
return {x / f, y / f, z / f, w / f};
|
||||
}
|
||||
|
||||
@@ -466,15 +466,15 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr T Length2() const {
|
||||
[[nodiscard]] constexpr T Length2() const {
|
||||
return x * x + y * y + z * z + w * w;
|
||||
}
|
||||
|
||||
constexpr T& operator[](std::size_t i) {
|
||||
[[nodiscard]] constexpr T& operator[](std::size_t i) {
|
||||
return *((&x) + i);
|
||||
}
|
||||
|
||||
constexpr const T& operator[](std::size_t i) const {
|
||||
[[nodiscard]] constexpr const T& operator[](std::size_t i) const {
|
||||
return *((&x) + i);
|
||||
}
|
||||
|
||||
@@ -486,29 +486,29 @@ public:
|
||||
}
|
||||
|
||||
// Common alias: RGBA (colors)
|
||||
constexpr T& r() {
|
||||
[[nodiscard]] constexpr T& r() {
|
||||
return x;
|
||||
}
|
||||
constexpr T& g() {
|
||||
[[nodiscard]] constexpr T& g() {
|
||||
return y;
|
||||
}
|
||||
constexpr T& b() {
|
||||
[[nodiscard]] constexpr T& b() {
|
||||
return z;
|
||||
}
|
||||
constexpr T& a() {
|
||||
[[nodiscard]] constexpr T& a() {
|
||||
return w;
|
||||
}
|
||||
|
||||
constexpr const T& r() const {
|
||||
[[nodiscard]] constexpr const T& r() const {
|
||||
return x;
|
||||
}
|
||||
constexpr const T& g() const {
|
||||
[[nodiscard]] constexpr const T& g() const {
|
||||
return y;
|
||||
}
|
||||
constexpr const T& b() const {
|
||||
[[nodiscard]] constexpr const T& b() const {
|
||||
return z;
|
||||
}
|
||||
constexpr const T& a() const {
|
||||
[[nodiscard]] constexpr const T& a() const {
|
||||
return w;
|
||||
}
|
||||
|
||||
@@ -520,7 +520,7 @@ public:
|
||||
// DEFINE_SWIZZLER2_COMP2 defines two component functions for all component names (x<->r) and
|
||||
// permutations (xy<->yx)
|
||||
#define _DEFINE_SWIZZLER2(a, b, name) \
|
||||
constexpr Vec2<T> name() const { \
|
||||
[[nodiscard]] constexpr Vec2<T> name() const { \
|
||||
return Vec2<T>(a, b); \
|
||||
}
|
||||
#define DEFINE_SWIZZLER2_COMP1(a, a2) \
|
||||
@@ -547,7 +547,7 @@ public:
|
||||
#undef _DEFINE_SWIZZLER2
|
||||
|
||||
#define _DEFINE_SWIZZLER3(a, b, c, name) \
|
||||
constexpr Vec3<T> name() const { \
|
||||
[[nodiscard]] constexpr Vec3<T> name() const { \
|
||||
return Vec3<T>(a, b, c); \
|
||||
}
|
||||
#define DEFINE_SWIZZLER3_COMP1(a, a2) \
|
||||
@@ -581,7 +581,7 @@ public:
|
||||
};
|
||||
|
||||
template <typename T, typename V>
|
||||
constexpr Vec4<decltype(V{} * T{})> operator*(const V& f, const Vec4<T>& vec) {
|
||||
[[nodiscard]] constexpr Vec4<decltype(V{} * T{})> operator*(const V& f, const Vec4<T>& vec) {
|
||||
return {f * vec.x, f * vec.y, f * vec.z, f * vec.w};
|
||||
}
|
||||
|
||||
@@ -593,39 +593,41 @@ constexpr decltype(T{} * T{} + T{} * T{}) Dot(const Vec2<T>& a, const Vec2<T>& b
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
constexpr decltype(T{} * T{} + T{} * T{}) Dot(const Vec3<T>& a, const Vec3<T>& b) {
|
||||
[[nodiscard]] constexpr decltype(T{} * T{} + T{} * T{}) Dot(const Vec3<T>& a, const Vec3<T>& b) {
|
||||
return a.x * b.x + a.y * b.y + a.z * b.z;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
constexpr decltype(T{} * T{} + T{} * T{}) Dot(const Vec4<T>& a, const Vec4<T>& b) {
|
||||
[[nodiscard]] constexpr decltype(T{} * T{} + T{} * T{}) Dot(const Vec4<T>& a, const Vec4<T>& b) {
|
||||
return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
constexpr Vec3<decltype(T{} * T{} - T{} * T{})> Cross(const Vec3<T>& a, const Vec3<T>& b) {
|
||||
[[nodiscard]] constexpr Vec3<decltype(T{} * T{} - T{} * T{})> Cross(const Vec3<T>& a,
|
||||
const Vec3<T>& b) {
|
||||
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};
|
||||
}
|
||||
|
||||
// linear interpolation via float: 0.0=begin, 1.0=end
|
||||
template <typename X>
|
||||
constexpr decltype(X{} * float{} + X{} * float{}) Lerp(const X& begin, const X& end,
|
||||
const float t) {
|
||||
[[nodiscard]] constexpr decltype(X{} * float{} + X{} * float{}) Lerp(const X& begin, const X& end,
|
||||
const float t) {
|
||||
return begin * (1.f - t) + end * t;
|
||||
}
|
||||
|
||||
// linear interpolation via int: 0=begin, base=end
|
||||
template <typename X, int base>
|
||||
constexpr decltype((X{} * int{} + X{} * int{}) / base) LerpInt(const X& begin, const X& end,
|
||||
const int t) {
|
||||
[[nodiscard]] constexpr decltype((X{} * int{} + X{} * int{}) / base) LerpInt(const X& begin,
|
||||
const X& end,
|
||||
const int t) {
|
||||
return (begin * (base - t) + end * t) / base;
|
||||
}
|
||||
|
||||
// bilinear interpolation. s is for interpolating x00-x01 and x10-x11, and t is for the second
|
||||
// interpolation.
|
||||
template <typename X>
|
||||
constexpr auto BilinearInterp(const X& x00, const X& x01, const X& x10, const X& x11, const float s,
|
||||
const float t) {
|
||||
[[nodiscard]] constexpr auto BilinearInterp(const X& x00, const X& x01, const X& x10, const X& x11,
|
||||
const float s, const float t) {
|
||||
auto y0 = Lerp(x00, x01, s);
|
||||
auto y1 = Lerp(x10, x11, s);
|
||||
return Lerp(y0, y1, t);
|
||||
@@ -633,42 +635,42 @@ constexpr auto BilinearInterp(const X& x00, const X& x01, const X& x10, const X&
|
||||
|
||||
// Utility vector factories
|
||||
template <typename T>
|
||||
constexpr Vec2<T> MakeVec(const T& x, const T& y) {
|
||||
[[nodiscard]] constexpr Vec2<T> MakeVec(const T& x, const T& y) {
|
||||
return Vec2<T>{x, y};
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
constexpr Vec3<T> MakeVec(const T& x, const T& y, const T& z) {
|
||||
[[nodiscard]] constexpr Vec3<T> MakeVec(const T& x, const T& y, const T& z) {
|
||||
return Vec3<T>{x, y, z};
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
constexpr Vec4<T> MakeVec(const T& x, const T& y, const Vec2<T>& zw) {
|
||||
[[nodiscard]] constexpr Vec4<T> MakeVec(const T& x, const T& y, const Vec2<T>& zw) {
|
||||
return MakeVec(x, y, zw[0], zw[1]);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
constexpr Vec3<T> MakeVec(const Vec2<T>& xy, const T& z) {
|
||||
[[nodiscard]] constexpr Vec3<T> MakeVec(const Vec2<T>& xy, const T& z) {
|
||||
return MakeVec(xy[0], xy[1], z);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
constexpr Vec3<T> MakeVec(const T& x, const Vec2<T>& yz) {
|
||||
[[nodiscard]] constexpr Vec3<T> MakeVec(const T& x, const Vec2<T>& yz) {
|
||||
return MakeVec(x, yz[0], yz[1]);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
constexpr Vec4<T> MakeVec(const T& x, const T& y, const T& z, const T& w) {
|
||||
[[nodiscard]] constexpr Vec4<T> MakeVec(const T& x, const T& y, const T& z, const T& w) {
|
||||
return Vec4<T>{x, y, z, w};
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
constexpr Vec4<T> MakeVec(const Vec2<T>& xy, const T& z, const T& w) {
|
||||
[[nodiscard]] constexpr Vec4<T> MakeVec(const Vec2<T>& xy, const T& z, const T& w) {
|
||||
return MakeVec(xy[0], xy[1], z, w);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
constexpr Vec4<T> MakeVec(const T& x, const Vec2<T>& yz, const T& w) {
|
||||
[[nodiscard]] constexpr Vec4<T> MakeVec(const T& x, const Vec2<T>& yz, const T& w) {
|
||||
return MakeVec(x, yz[0], yz[1], w);
|
||||
}
|
||||
|
||||
@@ -676,17 +678,17 @@ constexpr Vec4<T> MakeVec(const T& x, const Vec2<T>& yz, const T& w) {
|
||||
// Even if someone wanted to use an odd object like Vec2<Vec2<T>>, the compiler would error
|
||||
// out soon enough due to misuse of the returned structure.
|
||||
template <typename T>
|
||||
constexpr Vec4<T> MakeVec(const Vec2<T>& xy, const Vec2<T>& zw) {
|
||||
[[nodiscard]] constexpr Vec4<T> MakeVec(const Vec2<T>& xy, const Vec2<T>& zw) {
|
||||
return MakeVec(xy[0], xy[1], zw[0], zw[1]);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
constexpr Vec4<T> MakeVec(const Vec3<T>& xyz, const T& w) {
|
||||
[[nodiscard]] constexpr Vec4<T> MakeVec(const Vec3<T>& xyz, const T& w) {
|
||||
return MakeVec(xyz[0], xyz[1], xyz[2], w);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
constexpr Vec4<T> MakeVec(const T& x, const Vec3<T>& yzw) {
|
||||
[[nodiscard]] constexpr Vec4<T> MakeVec(const T& x, const Vec3<T>& yzw) {
|
||||
return MakeVec(x, yzw[0], yzw[1], yzw[2]);
|
||||
}
|
||||
|
||||
|
||||
@@ -5,16 +5,7 @@
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <stdio.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/types.h>
|
||||
#if defined __APPLE__ || defined __FreeBSD__ || defined __OpenBSD__
|
||||
#include <sys/sysctl.h>
|
||||
#elif defined __HAIKU__
|
||||
#include <OS.h>
|
||||
#else
|
||||
#include <sys/sysinfo.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "common/assert.h"
|
||||
|
||||
@@ -30,23 +30,23 @@ public:
|
||||
base_ptr = reinterpret_cast<T*>(AllocateMemoryPages(alloc_size));
|
||||
}
|
||||
|
||||
constexpr const T& operator[](std::size_t index) const {
|
||||
[[nodiscard]] constexpr const T& operator[](std::size_t index) const {
|
||||
return base_ptr[index];
|
||||
}
|
||||
|
||||
constexpr T& operator[](std::size_t index) {
|
||||
[[nodiscard]] constexpr T& operator[](std::size_t index) {
|
||||
return base_ptr[index];
|
||||
}
|
||||
|
||||
constexpr T* data() {
|
||||
[[nodiscard]] constexpr T* data() {
|
||||
return base_ptr;
|
||||
}
|
||||
|
||||
constexpr const T* data() const {
|
||||
[[nodiscard]] constexpr const T* data() const {
|
||||
return base_ptr;
|
||||
}
|
||||
|
||||
constexpr std::size_t size() const {
|
||||
[[nodiscard]] constexpr std::size_t size() const {
|
||||
return alloc_size / sizeof(T);
|
||||
}
|
||||
|
||||
|
||||
@@ -14,24 +14,24 @@ namespace Common {
|
||||
class WallClock {
|
||||
public:
|
||||
/// Returns current wall time in nanoseconds
|
||||
virtual std::chrono::nanoseconds GetTimeNS() = 0;
|
||||
[[nodiscard]] virtual std::chrono::nanoseconds GetTimeNS() = 0;
|
||||
|
||||
/// Returns current wall time in microseconds
|
||||
virtual std::chrono::microseconds GetTimeUS() = 0;
|
||||
[[nodiscard]] virtual std::chrono::microseconds GetTimeUS() = 0;
|
||||
|
||||
/// Returns current wall time in milliseconds
|
||||
virtual std::chrono::milliseconds GetTimeMS() = 0;
|
||||
[[nodiscard]] virtual std::chrono::milliseconds GetTimeMS() = 0;
|
||||
|
||||
/// Returns current wall time in emulated clock cycles
|
||||
virtual u64 GetClockCycles() = 0;
|
||||
[[nodiscard]] virtual u64 GetClockCycles() = 0;
|
||||
|
||||
/// Returns current wall time in emulated cpu cycles
|
||||
virtual u64 GetCPUCycles() = 0;
|
||||
[[nodiscard]] virtual u64 GetCPUCycles() = 0;
|
||||
|
||||
virtual void Pause(bool is_paused) = 0;
|
||||
|
||||
/// Tells if the wall clock, uses the host CPU's hardware clock
|
||||
bool IsNative() const {
|
||||
[[nodiscard]] bool IsNative() const {
|
||||
return is_native;
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ private:
|
||||
bool is_native;
|
||||
};
|
||||
|
||||
std::unique_ptr<WallClock> CreateBestMatchingClock(u32 emulated_cpu_frequency,
|
||||
u32 emulated_clock_frequency);
|
||||
[[nodiscard]] std::unique_ptr<WallClock> CreateBestMatchingClock(u32 emulated_cpu_frequency,
|
||||
u32 emulated_clock_frequency);
|
||||
|
||||
} // namespace Common
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
#include <algorithm>
|
||||
#include <zstd.h>
|
||||
|
||||
#include "common/assert.h"
|
||||
#include "common/zstd_compression.h"
|
||||
|
||||
namespace Common::Compression {
|
||||
|
||||
@@ -13,24 +13,25 @@ namespace Common::Compression {
|
||||
/**
|
||||
* Compresses a source memory region with Zstandard and returns the compressed data in a vector.
|
||||
*
|
||||
* @param source the uncompressed source memory region.
|
||||
* @param source_size the size in bytes of the uncompressed source memory region.
|
||||
* @param compression_level the used compression level. Should be between 1 and 22.
|
||||
* @param source The uncompressed source memory region.
|
||||
* @param source_size The size of the uncompressed source memory region.
|
||||
* @param compression_level The used compression level. Should be between 1 and 22.
|
||||
*
|
||||
* @return the compressed data.
|
||||
*/
|
||||
std::vector<u8> CompressDataZSTD(const u8* source, std::size_t source_size, s32 compression_level);
|
||||
[[nodiscard]] std::vector<u8> CompressDataZSTD(const u8* source, std::size_t source_size,
|
||||
s32 compression_level);
|
||||
|
||||
/**
|
||||
* Compresses a source memory region with Zstandard with the default compression level and returns
|
||||
* the compressed data in a vector.
|
||||
*
|
||||
* @param source the uncompressed source memory region.
|
||||
* @param source_size the size in bytes of the uncompressed source memory region.
|
||||
* @param source The uncompressed source memory region.
|
||||
* @param source_size The size of the uncompressed source memory region.
|
||||
*
|
||||
* @return the compressed data.
|
||||
*/
|
||||
std::vector<u8> CompressDataZSTDDefault(const u8* source, std::size_t source_size);
|
||||
[[nodiscard]] std::vector<u8> CompressDataZSTDDefault(const u8* source, std::size_t source_size);
|
||||
|
||||
/**
|
||||
* Decompresses a source memory region with Zstandard and returns the uncompressed data in a vector.
|
||||
@@ -39,6 +40,6 @@ std::vector<u8> CompressDataZSTDDefault(const u8* source, std::size_t source_siz
|
||||
*
|
||||
* @return the decompressed data.
|
||||
*/
|
||||
std::vector<u8> DecompressDataZSTD(const std::vector<u8>& compressed);
|
||||
[[nodiscard]] std::vector<u8> DecompressDataZSTD(const std::vector<u8>& compressed);
|
||||
|
||||
} // namespace Common::Compression
|
||||
@@ -133,9 +133,9 @@ public:
|
||||
// Parsing function defines the conversion from raw file to NCA. If there are other steps
|
||||
// besides creating the NCA from the file (e.g. NAX0 on SD Card), that should go in a custom
|
||||
// parsing function.
|
||||
explicit RegisteredCache(VirtualDir dir,
|
||||
ContentProviderParsingFunction parsing_function =
|
||||
[](const VirtualFile& file, const NcaID& id) { return file; });
|
||||
explicit RegisteredCache(
|
||||
VirtualDir dir, ContentProviderParsingFunction parsing_function =
|
||||
[](const VirtualFile& file, const NcaID& id) { return file; });
|
||||
~RegisteredCache() override;
|
||||
|
||||
void Refresh() override;
|
||||
|
||||
@@ -27,18 +27,12 @@ VirtualDir MiiModel() {
|
||||
auto out = std::make_shared<VectorVfsDirectory>(std::vector<VirtualFile>{},
|
||||
std::vector<VirtualDir>{}, "data");
|
||||
|
||||
out->AddFile(std::make_shared<ArrayVfsFile<MiiModelData::TEXTURE_LOW_LINEAR.size()>>(
|
||||
MiiModelData::TEXTURE_LOW_LINEAR, "NXTextureLowLinear.dat"));
|
||||
out->AddFile(std::make_shared<ArrayVfsFile<MiiModelData::TEXTURE_LOW_SRGB.size()>>(
|
||||
MiiModelData::TEXTURE_LOW_SRGB, "NXTextureLowSRGB.dat"));
|
||||
out->AddFile(std::make_shared<ArrayVfsFile<MiiModelData::TEXTURE_MID_LINEAR.size()>>(
|
||||
MiiModelData::TEXTURE_MID_LINEAR, "NXTextureMidLinear.dat"));
|
||||
out->AddFile(std::make_shared<ArrayVfsFile<MiiModelData::TEXTURE_MID_SRGB.size()>>(
|
||||
MiiModelData::TEXTURE_MID_SRGB, "NXTextureMidSRGB.dat"));
|
||||
out->AddFile(std::make_shared<ArrayVfsFile<MiiModelData::SHAPE_HIGH.size()>>(
|
||||
MiiModelData::SHAPE_HIGH, "ShapeHigh.dat"));
|
||||
out->AddFile(std::make_shared<ArrayVfsFile<MiiModelData::SHAPE_MID.size()>>(
|
||||
MiiModelData::SHAPE_MID, "ShapeMid.dat"));
|
||||
out->AddFile(MakeArrayFile(MiiModelData::TEXTURE_LOW_LINEAR, "NXTextureLowLinear.dat"));
|
||||
out->AddFile(MakeArrayFile(MiiModelData::TEXTURE_LOW_SRGB, "NXTextureLowSRGB.dat"));
|
||||
out->AddFile(MakeArrayFile(MiiModelData::TEXTURE_MID_LINEAR, "NXTextureMidLinear.dat"));
|
||||
out->AddFile(MakeArrayFile(MiiModelData::TEXTURE_MID_SRGB, "NXTextureMidSRGB.dat"));
|
||||
out->AddFile(MakeArrayFile(MiiModelData::SHAPE_HIGH, "ShapeHigh.dat"));
|
||||
out->AddFile(MakeArrayFile(MiiModelData::SHAPE_MID, "ShapeMid.dat"));
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
@@ -24,19 +24,18 @@ constexpr std::array<u8, 30> WORD_TXT{
|
||||
} // namespace NgWord1Data
|
||||
|
||||
VirtualDir NgWord1() {
|
||||
std::vector<VirtualFile> files(NgWord1Data::NUMBER_WORD_TXT_FILES);
|
||||
std::vector<VirtualFile> files;
|
||||
files.reserve(NgWord1Data::NUMBER_WORD_TXT_FILES);
|
||||
|
||||
for (std::size_t i = 0; i < files.size(); ++i) {
|
||||
files[i] = std::make_shared<ArrayVfsFile<NgWord1Data::WORD_TXT.size()>>(
|
||||
NgWord1Data::WORD_TXT, fmt::format("{}.txt", i));
|
||||
files.push_back(MakeArrayFile(NgWord1Data::WORD_TXT, fmt::format("{}.txt", i)));
|
||||
}
|
||||
|
||||
files.push_back(std::make_shared<ArrayVfsFile<NgWord1Data::WORD_TXT.size()>>(
|
||||
NgWord1Data::WORD_TXT, "common.txt"));
|
||||
files.push_back(std::make_shared<ArrayVfsFile<NgWord1Data::VERSION_DAT.size()>>(
|
||||
NgWord1Data::VERSION_DAT, "version.dat"));
|
||||
files.push_back(MakeArrayFile(NgWord1Data::WORD_TXT, "common.txt"));
|
||||
files.push_back(MakeArrayFile(NgWord1Data::VERSION_DAT, "version.dat"));
|
||||
|
||||
return std::make_shared<VectorVfsDirectory>(files, std::vector<VirtualDir>{}, "data");
|
||||
return std::make_shared<VectorVfsDirectory>(std::move(files), std::vector<VirtualDir>{},
|
||||
"data");
|
||||
}
|
||||
|
||||
namespace NgWord2Data {
|
||||
@@ -55,27 +54,22 @@ constexpr std::array<u8, 0x2C> AC_NX_DATA{
|
||||
} // namespace NgWord2Data
|
||||
|
||||
VirtualDir NgWord2() {
|
||||
std::vector<VirtualFile> files(NgWord2Data::NUMBER_AC_NX_FILES * 3);
|
||||
std::vector<VirtualFile> files;
|
||||
files.reserve(NgWord2Data::NUMBER_AC_NX_FILES * 3);
|
||||
|
||||
for (std::size_t i = 0; i < NgWord2Data::NUMBER_AC_NX_FILES; ++i) {
|
||||
files[3 * i] = std::make_shared<ArrayVfsFile<NgWord2Data::AC_NX_DATA.size()>>(
|
||||
NgWord2Data::AC_NX_DATA, fmt::format("ac_{}_b1_nx", i));
|
||||
files[3 * i + 1] = std::make_shared<ArrayVfsFile<NgWord2Data::AC_NX_DATA.size()>>(
|
||||
NgWord2Data::AC_NX_DATA, fmt::format("ac_{}_b2_nx", i));
|
||||
files[3 * i + 2] = std::make_shared<ArrayVfsFile<NgWord2Data::AC_NX_DATA.size()>>(
|
||||
NgWord2Data::AC_NX_DATA, fmt::format("ac_{}_not_b_nx", i));
|
||||
files.push_back(MakeArrayFile(NgWord2Data::AC_NX_DATA, fmt::format("ac_{}_b1_nx", i)));
|
||||
files.push_back(MakeArrayFile(NgWord2Data::AC_NX_DATA, fmt::format("ac_{}_b2_nx", i)));
|
||||
files.push_back(MakeArrayFile(NgWord2Data::AC_NX_DATA, fmt::format("ac_{}_not_b_nx", i)));
|
||||
}
|
||||
|
||||
files.push_back(std::make_shared<ArrayVfsFile<NgWord2Data::AC_NX_DATA.size()>>(
|
||||
NgWord2Data::AC_NX_DATA, "ac_common_b1_nx"));
|
||||
files.push_back(std::make_shared<ArrayVfsFile<NgWord2Data::AC_NX_DATA.size()>>(
|
||||
NgWord2Data::AC_NX_DATA, "ac_common_b2_nx"));
|
||||
files.push_back(std::make_shared<ArrayVfsFile<NgWord2Data::AC_NX_DATA.size()>>(
|
||||
NgWord2Data::AC_NX_DATA, "ac_common_not_b_nx"));
|
||||
files.push_back(std::make_shared<ArrayVfsFile<NgWord2Data::VERSION_DAT.size()>>(
|
||||
NgWord2Data::VERSION_DAT, "version.dat"));
|
||||
files.push_back(MakeArrayFile(NgWord2Data::AC_NX_DATA, "ac_common_b1_nx"));
|
||||
files.push_back(MakeArrayFile(NgWord2Data::AC_NX_DATA, "ac_common_b2_nx"));
|
||||
files.push_back(MakeArrayFile(NgWord2Data::AC_NX_DATA, "ac_common_not_b_nx"));
|
||||
files.push_back(MakeArrayFile(NgWord2Data::VERSION_DAT, "version.dat"));
|
||||
|
||||
return std::make_shared<VectorVfsDirectory>(files, std::vector<VirtualDir>{}, "data");
|
||||
return std::make_shared<VectorVfsDirectory>(std::move(files), std::vector<VirtualDir>{},
|
||||
"data");
|
||||
}
|
||||
|
||||
} // namespace FileSys::SystemArchive
|
||||
|
||||
@@ -654,12 +654,13 @@ static VirtualFile GenerateDefaultTimeZoneFile() {
|
||||
}
|
||||
|
||||
VirtualDir TimeZoneBinary() {
|
||||
const std::vector<VirtualDir> root_dirs{std::make_shared<VectorVfsDirectory>(
|
||||
std::vector<VirtualDir> root_dirs{std::make_shared<VectorVfsDirectory>(
|
||||
std::vector<VirtualFile>{GenerateDefaultTimeZoneFile()}, std::vector<VirtualDir>{},
|
||||
"zoneinfo")};
|
||||
const std::vector<VirtualFile> root_files{
|
||||
std::make_shared<ArrayVfsFile<LOCATION_NAMES.size()>>(LOCATION_NAMES, "binaryList.txt")};
|
||||
return std::make_shared<VectorVfsDirectory>(root_files, root_dirs, "data");
|
||||
std::vector<VirtualFile> root_files{MakeArrayFile(LOCATION_NAMES, "binaryList.txt")};
|
||||
|
||||
return std::make_shared<VectorVfsDirectory>(std::move(root_files), std::move(root_dirs),
|
||||
"data");
|
||||
}
|
||||
|
||||
} // namespace FileSys::SystemArchive
|
||||
|
||||
@@ -4,7 +4,11 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "core/file_sys/vfs.h"
|
||||
|
||||
namespace FileSys {
|
||||
@@ -13,7 +17,8 @@ namespace FileSys {
|
||||
template <std::size_t size>
|
||||
class ArrayVfsFile : public VfsFile {
|
||||
public:
|
||||
ArrayVfsFile(std::array<u8, size> data, std::string name = "", VirtualDir parent = nullptr)
|
||||
explicit ArrayVfsFile(const std::array<u8, size>& data, std::string name = "",
|
||||
VirtualDir parent = nullptr)
|
||||
: data(data), name(std::move(name)), parent(std::move(parent)) {}
|
||||
|
||||
std::string GetName() const override {
|
||||
@@ -61,6 +66,12 @@ private:
|
||||
VirtualDir parent;
|
||||
};
|
||||
|
||||
template <std::size_t Size, typename... Args>
|
||||
std::shared_ptr<ArrayVfsFile<Size>> MakeArrayFile(const std::array<u8, Size>& data,
|
||||
Args&&... args) {
|
||||
return std::make_shared<ArrayVfsFile<Size>>(data, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
// An implementation of VfsFile that is backed by a vector optionally supplied upon construction
|
||||
class VectorVfsFile : public VfsFile {
|
||||
public:
|
||||
|
||||
@@ -39,7 +39,7 @@ public:
|
||||
|
||||
class Scoped {
|
||||
public:
|
||||
explicit Scoped(GraphicsContext& context_) : context(context_) {
|
||||
[[nodiscard]] explicit Scoped(GraphicsContext& context_) : context(context_) {
|
||||
context.MakeCurrent();
|
||||
}
|
||||
~Scoped() {
|
||||
@@ -52,7 +52,7 @@ public:
|
||||
|
||||
/// Calls MakeCurrent on the context and calls DoneCurrent when the scope for the returned value
|
||||
/// ends
|
||||
Scoped Acquire() {
|
||||
[[nodiscard]] Scoped Acquire() {
|
||||
return Scoped{*this};
|
||||
}
|
||||
};
|
||||
|
||||
@@ -293,13 +293,15 @@ std::vector<u8> HLERequestContext::ReadBuffer(std::size_t buffer_index) const {
|
||||
BufferDescriptorA()[buffer_index].Size()};
|
||||
|
||||
if (is_buffer_a) {
|
||||
ASSERT_OR_EXECUTE_MSG(BufferDescriptorA().size() > buffer_index, { return buffer; },
|
||||
"BufferDescriptorA invalid buffer_index {}", buffer_index);
|
||||
ASSERT_OR_EXECUTE_MSG(
|
||||
BufferDescriptorA().size() > buffer_index, { return buffer; },
|
||||
"BufferDescriptorA invalid buffer_index {}", buffer_index);
|
||||
buffer.resize(BufferDescriptorA()[buffer_index].Size());
|
||||
memory.ReadBlock(BufferDescriptorA()[buffer_index].Address(), buffer.data(), buffer.size());
|
||||
} else {
|
||||
ASSERT_OR_EXECUTE_MSG(BufferDescriptorX().size() > buffer_index, { return buffer; },
|
||||
"BufferDescriptorX invalid buffer_index {}", buffer_index);
|
||||
ASSERT_OR_EXECUTE_MSG(
|
||||
BufferDescriptorX().size() > buffer_index, { return buffer; },
|
||||
"BufferDescriptorX invalid buffer_index {}", buffer_index);
|
||||
buffer.resize(BufferDescriptorX()[buffer_index].Size());
|
||||
memory.ReadBlock(BufferDescriptorX()[buffer_index].Address(), buffer.data(), buffer.size());
|
||||
}
|
||||
@@ -324,16 +326,16 @@ std::size_t HLERequestContext::WriteBuffer(const void* buffer, std::size_t size,
|
||||
}
|
||||
|
||||
if (is_buffer_b) {
|
||||
ASSERT_OR_EXECUTE_MSG(BufferDescriptorB().size() > buffer_index &&
|
||||
BufferDescriptorB()[buffer_index].Size() >= size,
|
||||
{ return 0; }, "BufferDescriptorB is invalid, index={}, size={}",
|
||||
buffer_index, size);
|
||||
ASSERT_OR_EXECUTE_MSG(
|
||||
BufferDescriptorB().size() > buffer_index &&
|
||||
BufferDescriptorB()[buffer_index].Size() >= size,
|
||||
{ return 0; }, "BufferDescriptorB is invalid, index={}, size={}", buffer_index, size);
|
||||
memory.WriteBlock(BufferDescriptorB()[buffer_index].Address(), buffer, size);
|
||||
} else {
|
||||
ASSERT_OR_EXECUTE_MSG(BufferDescriptorC().size() > buffer_index &&
|
||||
BufferDescriptorC()[buffer_index].Size() >= size,
|
||||
{ return 0; }, "BufferDescriptorC is invalid, index={}, size={}",
|
||||
buffer_index, size);
|
||||
ASSERT_OR_EXECUTE_MSG(
|
||||
BufferDescriptorC().size() > buffer_index &&
|
||||
BufferDescriptorC()[buffer_index].Size() >= size,
|
||||
{ return 0; }, "BufferDescriptorC is invalid, index={}, size={}", buffer_index, size);
|
||||
memory.WriteBlock(BufferDescriptorC()[buffer_index].Address(), buffer, size);
|
||||
}
|
||||
|
||||
@@ -344,12 +346,14 @@ std::size_t HLERequestContext::GetReadBufferSize(std::size_t buffer_index) const
|
||||
const bool is_buffer_a{BufferDescriptorA().size() > buffer_index &&
|
||||
BufferDescriptorA()[buffer_index].Size()};
|
||||
if (is_buffer_a) {
|
||||
ASSERT_OR_EXECUTE_MSG(BufferDescriptorA().size() > buffer_index, { return 0; },
|
||||
"BufferDescriptorA invalid buffer_index {}", buffer_index);
|
||||
ASSERT_OR_EXECUTE_MSG(
|
||||
BufferDescriptorA().size() > buffer_index, { return 0; },
|
||||
"BufferDescriptorA invalid buffer_index {}", buffer_index);
|
||||
return BufferDescriptorA()[buffer_index].Size();
|
||||
} else {
|
||||
ASSERT_OR_EXECUTE_MSG(BufferDescriptorX().size() > buffer_index, { return 0; },
|
||||
"BufferDescriptorX invalid buffer_index {}", buffer_index);
|
||||
ASSERT_OR_EXECUTE_MSG(
|
||||
BufferDescriptorX().size() > buffer_index, { return 0; },
|
||||
"BufferDescriptorX invalid buffer_index {}", buffer_index);
|
||||
return BufferDescriptorX()[buffer_index].Size();
|
||||
}
|
||||
}
|
||||
@@ -358,12 +362,14 @@ std::size_t HLERequestContext::GetWriteBufferSize(std::size_t buffer_index) cons
|
||||
const bool is_buffer_b{BufferDescriptorB().size() > buffer_index &&
|
||||
BufferDescriptorB()[buffer_index].Size()};
|
||||
if (is_buffer_b) {
|
||||
ASSERT_OR_EXECUTE_MSG(BufferDescriptorB().size() > buffer_index, { return 0; },
|
||||
"BufferDescriptorB invalid buffer_index {}", buffer_index);
|
||||
ASSERT_OR_EXECUTE_MSG(
|
||||
BufferDescriptorB().size() > buffer_index, { return 0; },
|
||||
"BufferDescriptorB invalid buffer_index {}", buffer_index);
|
||||
return BufferDescriptorB()[buffer_index].Size();
|
||||
} else {
|
||||
ASSERT_OR_EXECUTE_MSG(BufferDescriptorC().size() > buffer_index, { return 0; },
|
||||
"BufferDescriptorC invalid buffer_index {}", buffer_index);
|
||||
ASSERT_OR_EXECUTE_MSG(
|
||||
BufferDescriptorC().size() > buffer_index, { return 0; },
|
||||
"BufferDescriptorC invalid buffer_index {}", buffer_index);
|
||||
return BufferDescriptorC()[buffer_index].Size();
|
||||
}
|
||||
return 0;
|
||||
|
||||
@@ -604,7 +604,6 @@ ResultCode PageTable::MapPages(VAddr addr, const PageLinkedList& page_linked_lis
|
||||
if (const auto result{
|
||||
Operate(cur_addr, node.GetNumPages(), perm, OperationType::Map, node.GetAddress())};
|
||||
result.IsError()) {
|
||||
const MemoryInfo info{block_manager->FindBlock(cur_addr).GetMemoryInfo()};
|
||||
const std::size_t num_pages{(addr - cur_addr) / PageSize};
|
||||
|
||||
ASSERT(
|
||||
@@ -852,11 +851,12 @@ ResultCode PageTable::LockForDeviceAddressSpace(VAddr addr, std::size_t size) {
|
||||
return result;
|
||||
}
|
||||
|
||||
block_manager->UpdateLock(addr, size / PageSize,
|
||||
[](MemoryBlockManager::iterator block, MemoryPermission perm) {
|
||||
block->ShareToDevice(perm);
|
||||
},
|
||||
perm);
|
||||
block_manager->UpdateLock(
|
||||
addr, size / PageSize,
|
||||
[](MemoryBlockManager::iterator block, MemoryPermission perm) {
|
||||
block->ShareToDevice(perm);
|
||||
},
|
||||
perm);
|
||||
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
@@ -874,11 +874,12 @@ ResultCode PageTable::UnlockForDeviceAddressSpace(VAddr addr, std::size_t size)
|
||||
return result;
|
||||
}
|
||||
|
||||
block_manager->UpdateLock(addr, size / PageSize,
|
||||
[](MemoryBlockManager::iterator block, MemoryPermission perm) {
|
||||
block->UnshareToDevice(perm);
|
||||
},
|
||||
perm);
|
||||
block_manager->UpdateLock(
|
||||
addr, size / PageSize,
|
||||
[](MemoryBlockManager::iterator block, MemoryPermission perm) {
|
||||
block->UnshareToDevice(perm);
|
||||
},
|
||||
perm);
|
||||
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -7,22 +7,15 @@
|
||||
#include "core/hle/kernel/memory/system_control.h"
|
||||
|
||||
namespace Kernel::Memory::SystemControl {
|
||||
|
||||
u64 GenerateRandomU64ForInit() {
|
||||
static std::random_device device;
|
||||
static std::mt19937 gen(device());
|
||||
static std::uniform_int_distribution<u64> distribution(1, std::numeric_limits<u64>::max());
|
||||
return distribution(gen);
|
||||
}
|
||||
|
||||
namespace {
|
||||
template <typename F>
|
||||
u64 GenerateUniformRange(u64 min, u64 max, F f) {
|
||||
/* Handle the case where the difference is too large to represent. */
|
||||
// Handle the case where the difference is too large to represent.
|
||||
if (max == std::numeric_limits<u64>::max() && min == std::numeric_limits<u64>::min()) {
|
||||
return f();
|
||||
}
|
||||
|
||||
/* Iterate until we get a value in range. */
|
||||
// Iterate until we get a value in range.
|
||||
const u64 range_size = ((max + 1) - min);
|
||||
const u64 effective_max = (std::numeric_limits<u64>::max() / range_size) * range_size;
|
||||
while (true) {
|
||||
@@ -32,6 +25,14 @@ u64 GenerateUniformRange(u64 min, u64 max, F f) {
|
||||
}
|
||||
}
|
||||
|
||||
u64 GenerateRandomU64ForInit() {
|
||||
static std::random_device device;
|
||||
static std::mt19937 gen(device());
|
||||
static std::uniform_int_distribution<u64> distribution(1, std::numeric_limits<u64>::max());
|
||||
return distribution(gen);
|
||||
}
|
||||
} // Anonymous namespace
|
||||
|
||||
u64 GenerateRandomRange(u64 min, u64 max) {
|
||||
return GenerateUniformRange(min, max, GenerateRandomU64ForInit);
|
||||
}
|
||||
|
||||
@@ -8,11 +8,6 @@
|
||||
|
||||
namespace Kernel::Memory::SystemControl {
|
||||
|
||||
u64 GenerateRandomU64ForInit();
|
||||
|
||||
template <typename F>
|
||||
u64 GenerateUniformRange(u64 min, u64 max, F f);
|
||||
|
||||
u64 GenerateRandomRange(u64 min, u64 max);
|
||||
|
||||
} // namespace Kernel::Memory::SystemControl
|
||||
|
||||
@@ -664,32 +664,26 @@ void Scheduler::Reload() {
|
||||
}
|
||||
|
||||
void Scheduler::SwitchContextStep2() {
|
||||
Thread* previous_thread = current_thread_prev.get();
|
||||
Thread* new_thread = selected_thread.get();
|
||||
|
||||
// Load context of new thread
|
||||
Process* const previous_process =
|
||||
previous_thread != nullptr ? previous_thread->GetOwnerProcess() : nullptr;
|
||||
|
||||
if (new_thread) {
|
||||
ASSERT_MSG(new_thread->GetSchedulingStatus() == ThreadSchedStatus::Runnable,
|
||||
if (selected_thread) {
|
||||
ASSERT_MSG(selected_thread->GetSchedulingStatus() == ThreadSchedStatus::Runnable,
|
||||
"Thread must be runnable.");
|
||||
|
||||
// Cancel any outstanding wakeup events for this thread
|
||||
new_thread->SetIsRunning(true);
|
||||
new_thread->last_running_ticks = system.CoreTiming().GetCPUTicks();
|
||||
new_thread->SetWasRunning(false);
|
||||
selected_thread->SetIsRunning(true);
|
||||
selected_thread->last_running_ticks = system.CoreTiming().GetCPUTicks();
|
||||
selected_thread->SetWasRunning(false);
|
||||
|
||||
auto* const thread_owner_process = current_thread->GetOwnerProcess();
|
||||
if (thread_owner_process != nullptr) {
|
||||
system.Kernel().MakeCurrentProcess(thread_owner_process);
|
||||
}
|
||||
if (!new_thread->IsHLEThread()) {
|
||||
Core::ARM_Interface& cpu_core = new_thread->ArmInterface();
|
||||
cpu_core.LoadContext(new_thread->GetContext32());
|
||||
cpu_core.LoadContext(new_thread->GetContext64());
|
||||
cpu_core.SetTlsAddress(new_thread->GetTLSAddress());
|
||||
cpu_core.SetTPIDR_EL0(new_thread->GetTPIDR_EL0());
|
||||
if (!selected_thread->IsHLEThread()) {
|
||||
Core::ARM_Interface& cpu_core = selected_thread->ArmInterface();
|
||||
cpu_core.LoadContext(selected_thread->GetContext32());
|
||||
cpu_core.LoadContext(selected_thread->GetContext64());
|
||||
cpu_core.SetTlsAddress(selected_thread->GetTLSAddress());
|
||||
cpu_core.SetTPIDR_EL0(selected_thread->GetTPIDR_EL0());
|
||||
cpu_core.ChangeProcessorID(this->core_id);
|
||||
cpu_core.ClearExclusiveState();
|
||||
}
|
||||
|
||||
@@ -289,7 +289,7 @@ private:
|
||||
|
||||
class SchedulerLock {
|
||||
public:
|
||||
explicit SchedulerLock(KernelCore& kernel);
|
||||
[[nodiscard]] explicit SchedulerLock(KernelCore& kernel);
|
||||
~SchedulerLock();
|
||||
|
||||
protected:
|
||||
|
||||
@@ -342,8 +342,9 @@ ResultVal<std::remove_reference_t<Arg>> MakeResult(Arg&& arg) {
|
||||
*/
|
||||
#define CASCADE_RESULT(target, source) \
|
||||
auto CONCAT2(check_result_L, __LINE__) = source; \
|
||||
if (CONCAT2(check_result_L, __LINE__).Failed()) \
|
||||
if (CONCAT2(check_result_L, __LINE__).Failed()) { \
|
||||
return CONCAT2(check_result_L, __LINE__).Code(); \
|
||||
} \
|
||||
target = std::move(*CONCAT2(check_result_L, __LINE__))
|
||||
|
||||
/**
|
||||
@@ -351,6 +352,9 @@ ResultVal<std::remove_reference_t<Arg>> MakeResult(Arg&& arg) {
|
||||
* non-success, or discarded otherwise.
|
||||
*/
|
||||
#define CASCADE_CODE(source) \
|
||||
auto CONCAT2(check_result_L, __LINE__) = source; \
|
||||
if (CONCAT2(check_result_L, __LINE__).IsError()) \
|
||||
return CONCAT2(check_result_L, __LINE__);
|
||||
do { \
|
||||
auto CONCAT2(check_result_L, __LINE__) = source; \
|
||||
if (CONCAT2(check_result_L, __LINE__).IsError()) { \
|
||||
return CONCAT2(check_result_L, __LINE__); \
|
||||
} \
|
||||
} while (false)
|
||||
|
||||
@@ -378,7 +378,11 @@ void ISelfController::GetLibraryAppletLaunchableEvent(Kernel::HLERequestContext&
|
||||
}
|
||||
|
||||
void ISelfController::SetScreenShotPermission(Kernel::HLERequestContext& ctx) {
|
||||
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||
IPC::RequestParser rp{ctx};
|
||||
const auto permission = rp.PopEnum<ScreenshotPermission>();
|
||||
LOG_DEBUG(Service_AM, "called, permission={}", permission);
|
||||
|
||||
screenshot_permission = permission;
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
|
||||
@@ -149,6 +149,12 @@ private:
|
||||
void GetAccumulatedSuspendedTickValue(Kernel::HLERequestContext& ctx);
|
||||
void GetAccumulatedSuspendedTickChangedEvent(Kernel::HLERequestContext& ctx);
|
||||
|
||||
enum class ScreenshotPermission : u32 {
|
||||
Inherit = 0,
|
||||
Enable = 1,
|
||||
Disable = 2,
|
||||
};
|
||||
|
||||
Core::System& system;
|
||||
std::shared_ptr<NVFlinger::NVFlinger> nvflinger;
|
||||
Kernel::EventPair launchable_event;
|
||||
@@ -157,6 +163,7 @@ private:
|
||||
u32 idle_time_detection_extension = 0;
|
||||
u64 num_fatal_sections_entered = 0;
|
||||
bool is_auto_sleep_disabled = false;
|
||||
ScreenshotPermission screenshot_permission = ScreenshotPermission::Inherit;
|
||||
};
|
||||
|
||||
class ICommonStateGetter final : public ServiceFramework<ICommonStateGetter> {
|
||||
|
||||
@@ -122,8 +122,7 @@ void SoftwareKeyboard::ExecuteInteractive() {
|
||||
|
||||
switch (request) {
|
||||
case Request::Calc: {
|
||||
broker.PushNormalDataFromApplet(
|
||||
std::make_shared<IStorage>(std::move(std::vector<u8>{1})));
|
||||
broker.PushNormalDataFromApplet(std::make_shared<IStorage>(std::vector<u8>{1}));
|
||||
broker.SignalStateChanged();
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -551,7 +551,8 @@ void WebBrowser::ExecuteShop() {
|
||||
}
|
||||
|
||||
void WebBrowser::ExecuteOffline() {
|
||||
frontend.OpenPageLocal(filename, [this] { UnpackRomFS(); }, [this] { Finalize(); });
|
||||
frontend.OpenPageLocal(
|
||||
filename, [this] { UnpackRomFS(); }, [this] { Finalize(); });
|
||||
}
|
||||
|
||||
} // namespace Service::AM::Applets
|
||||
|
||||
@@ -206,7 +206,7 @@ private:
|
||||
AudioCore::StreamPtr stream;
|
||||
std::string device_name;
|
||||
|
||||
[[maybe_unused]] AudoutParams audio_params {};
|
||||
[[maybe_unused]] AudoutParams audio_params{};
|
||||
|
||||
/// This is the event handle used to check if the audio buffer was released
|
||||
Kernel::EventPair buffer_event;
|
||||
|
||||
@@ -365,8 +365,7 @@ bool Boxcat::Synchronize(TitleIDVersion title, ProgressServiceBackend& progress)
|
||||
|
||||
std::thread([this, title, &progress] {
|
||||
SynchronizeInternal(applet_manager, dir_getter, title, progress);
|
||||
})
|
||||
.detach();
|
||||
}).detach();
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -377,8 +376,7 @@ bool Boxcat::SynchronizeDirectory(TitleIDVersion title, std::string name,
|
||||
|
||||
std::thread([this, title, name, &progress] {
|
||||
SynchronizeInternal(applet_manager, dir_getter, title, progress, name);
|
||||
})
|
||||
.detach();
|
||||
}).detach();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -90,7 +90,7 @@ u32 Controller_NPad::IndexToNPad(std::size_t index) {
|
||||
default:
|
||||
UNIMPLEMENTED_MSG("Unknown npad index {}", index);
|
||||
return 0;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
Controller_NPad::Controller_NPad(Core::System& system) : ControllerBase(system), system(system) {}
|
||||
@@ -630,7 +630,7 @@ Controller_NPad::LedPattern Controller_NPad::GetLedPattern(u32 npad_id) {
|
||||
default:
|
||||
UNIMPLEMENTED_MSG("Unhandled npad_id {}", npad_id);
|
||||
return LedPattern{0, 0, 0, 0};
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
void Controller_NPad::SetVibrationEnabled(bool can_vibrate) {
|
||||
|
||||
@@ -21,8 +21,9 @@ namespace Service::Nvidia::Devices {
|
||||
/// implement the ioctl interface.
|
||||
class nvdevice {
|
||||
public:
|
||||
explicit nvdevice(Core::System& system) : system{system} {};
|
||||
explicit nvdevice(Core::System& system) : system{system} {}
|
||||
virtual ~nvdevice() = default;
|
||||
|
||||
union Ioctl {
|
||||
u32_le raw;
|
||||
BitField<0, 8, u32> cmd;
|
||||
|
||||
@@ -86,11 +86,13 @@ public:
|
||||
|
||||
[[nodiscard]] s64 GetNextTicks() const;
|
||||
|
||||
[[nodiscard]] std::unique_lock<std::mutex> Lock() const { return std::unique_lock{*guard}; }
|
||||
[[nodiscard]] std::unique_lock<std::mutex> Lock() const {
|
||||
return std::unique_lock{*guard};
|
||||
}
|
||||
|
||||
private :
|
||||
/// Finds the display identified by the specified ID.
|
||||
[[nodiscard]] VI::Display* FindDisplay(u64 display_id);
|
||||
private:
|
||||
/// Finds the display identified by the specified ID.
|
||||
[[nodiscard]] VI::Display* FindDisplay(u64 display_id);
|
||||
|
||||
/// Finds the display identified by the specified ID.
|
||||
[[nodiscard]] const VI::Display* FindDisplay(u64 display_id) const;
|
||||
|
||||
@@ -73,10 +73,8 @@ TimeZoneContentManager::TimeZoneContentManager(TimeManager& time_manager, Core::
|
||||
|
||||
std::string location_name;
|
||||
const auto timezone_setting = Settings::GetTimeZoneString();
|
||||
if (timezone_setting == "auto") {
|
||||
if (timezone_setting == "auto" || timezone_setting == "default") {
|
||||
location_name = Common::TimeZone::GetDefaultTimeZone();
|
||||
} else if (timezone_setting == "default") {
|
||||
location_name = location_name;
|
||||
} else {
|
||||
location_name = timezone_setting;
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ u64 StandardVmCallbacks::HidKeysDown() {
|
||||
if (applet_resource == nullptr) {
|
||||
LOG_WARNING(CheatEngine,
|
||||
"Attempted to read input state, but applet resource is not initialized!");
|
||||
return false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
const auto press_state =
|
||||
@@ -199,17 +199,29 @@ void CheatEngine::Initialize() {
|
||||
metadata.title_id = system.CurrentProcess()->GetTitleID();
|
||||
|
||||
const auto& page_table = system.CurrentProcess()->PageTable();
|
||||
metadata.heap_extents = {page_table.GetHeapRegionStart(), page_table.GetHeapRegionSize()};
|
||||
metadata.address_space_extents = {page_table.GetAddressSpaceStart(),
|
||||
page_table.GetAddressSpaceSize()};
|
||||
metadata.alias_extents = {page_table.GetAliasCodeRegionStart(),
|
||||
page_table.GetAliasCodeRegionSize()};
|
||||
metadata.heap_extents = {
|
||||
.base = page_table.GetHeapRegionStart(),
|
||||
.size = page_table.GetHeapRegionSize(),
|
||||
};
|
||||
|
||||
metadata.address_space_extents = {
|
||||
.base = page_table.GetAddressSpaceStart(),
|
||||
.size = page_table.GetAddressSpaceSize(),
|
||||
};
|
||||
|
||||
metadata.alias_extents = {
|
||||
.base = page_table.GetAliasCodeRegionStart(),
|
||||
.size = page_table.GetAliasCodeRegionSize(),
|
||||
};
|
||||
|
||||
is_pending_reload.exchange(true);
|
||||
}
|
||||
|
||||
void CheatEngine::SetMainMemoryParameters(VAddr main_region_begin, u64 main_region_size) {
|
||||
metadata.main_nso_extents = {main_region_begin, main_region_size};
|
||||
metadata.main_nso_extents = {
|
||||
.base = main_region_begin,
|
||||
.size = main_region_size,
|
||||
};
|
||||
}
|
||||
|
||||
void CheatEngine::Reload(std::vector<CheatEntry> cheats) {
|
||||
|
||||
+16
-15
@@ -107,28 +107,21 @@ void Freezer::Unfreeze(VAddr address) {
|
||||
|
||||
LOG_DEBUG(Common_Memory, "Unfreezing memory for address={:016X}", address);
|
||||
|
||||
entries.erase(
|
||||
std::remove_if(entries.begin(), entries.end(),
|
||||
[&address](const Entry& entry) { return entry.address == address; }),
|
||||
entries.end());
|
||||
std::erase_if(entries, [address](const Entry& entry) { return entry.address == address; });
|
||||
}
|
||||
|
||||
bool Freezer::IsFrozen(VAddr address) const {
|
||||
std::lock_guard lock{entries_mutex};
|
||||
|
||||
return std::find_if(entries.begin(), entries.end(), [&address](const Entry& entry) {
|
||||
return entry.address == address;
|
||||
}) != entries.end();
|
||||
return FindEntry(address) != entries.cend();
|
||||
}
|
||||
|
||||
void Freezer::SetFrozenValue(VAddr address, u64 value) {
|
||||
std::lock_guard lock{entries_mutex};
|
||||
|
||||
const auto iter = std::find_if(entries.begin(), entries.end(), [&address](const Entry& entry) {
|
||||
return entry.address == address;
|
||||
});
|
||||
const auto iter = FindEntry(address);
|
||||
|
||||
if (iter == entries.end()) {
|
||||
if (iter == entries.cend()) {
|
||||
LOG_ERROR(Common_Memory,
|
||||
"Tried to set freeze value for address={:016X} that is not frozen!", address);
|
||||
return;
|
||||
@@ -143,11 +136,9 @@ void Freezer::SetFrozenValue(VAddr address, u64 value) {
|
||||
std::optional<Freezer::Entry> Freezer::GetEntry(VAddr address) const {
|
||||
std::lock_guard lock{entries_mutex};
|
||||
|
||||
const auto iter = std::find_if(entries.begin(), entries.end(), [&address](const Entry& entry) {
|
||||
return entry.address == address;
|
||||
});
|
||||
const auto iter = FindEntry(address);
|
||||
|
||||
if (iter == entries.end()) {
|
||||
if (iter == entries.cend()) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
@@ -160,6 +151,16 @@ std::vector<Freezer::Entry> Freezer::GetEntries() const {
|
||||
return entries;
|
||||
}
|
||||
|
||||
Freezer::Entries::iterator Freezer::FindEntry(VAddr address) {
|
||||
return std::find_if(entries.begin(), entries.end(),
|
||||
[address](const Entry& entry) { return entry.address == address; });
|
||||
}
|
||||
|
||||
Freezer::Entries::const_iterator Freezer::FindEntry(VAddr address) const {
|
||||
return std::find_if(entries.begin(), entries.end(),
|
||||
[address](const Entry& entry) { return entry.address == address; });
|
||||
}
|
||||
|
||||
void Freezer::FrameCallback(std::uintptr_t, std::chrono::nanoseconds ns_late) {
|
||||
if (!IsActive()) {
|
||||
LOG_DEBUG(Common_Memory, "Memory freezer has been deactivated, ending callback events.");
|
||||
|
||||
@@ -73,13 +73,18 @@ public:
|
||||
std::vector<Entry> GetEntries() const;
|
||||
|
||||
private:
|
||||
using Entries = std::vector<Entry>;
|
||||
|
||||
Entries::iterator FindEntry(VAddr address);
|
||||
Entries::const_iterator FindEntry(VAddr address) const;
|
||||
|
||||
void FrameCallback(std::uintptr_t user_data, std::chrono::nanoseconds ns_late);
|
||||
void FillEntryReads();
|
||||
|
||||
std::atomic_bool active{false};
|
||||
|
||||
mutable std::mutex entries_mutex;
|
||||
std::vector<Entry> entries;
|
||||
Entries entries;
|
||||
|
||||
std::shared_ptr<Core::Timing::EventType> event;
|
||||
Core::Timing::CoreTiming& core_timing;
|
||||
|
||||
@@ -148,19 +148,17 @@ void GCButtonFactory::EndConfiguration() {
|
||||
|
||||
class GCAnalog final : public Input::AnalogDevice {
|
||||
public:
|
||||
GCAnalog(int port_, int axis_x_, int axis_y_, float deadzone_, GCAdapter::Adapter* adapter)
|
||||
GCAnalog(int port_, int axis_x_, int axis_y_, float deadzone_, GCAdapter::Adapter* adapter,
|
||||
float range_)
|
||||
: port(port_), axis_x(axis_x_), axis_y(axis_y_), deadzone(deadzone_), gcadapter(adapter),
|
||||
origin_value_x(adapter->GetOriginValue(port_, axis_x_)),
|
||||
origin_value_y(adapter->GetOriginValue(port_, axis_y_)) {}
|
||||
origin_value_y(adapter->GetOriginValue(port_, axis_y_)), range(range_) {}
|
||||
|
||||
float GetAxis(int axis) const {
|
||||
if (gcadapter->DeviceConnected(port)) {
|
||||
std::lock_guard lock{mutex};
|
||||
const auto origin_value = axis % 2 == 0 ? origin_value_x : origin_value_y;
|
||||
// division is not by a perfect 128 to account for some variance in center location
|
||||
// e.g. my device idled at 131 in X, 120 in Y, and full range of motion was in range
|
||||
// [20-230]
|
||||
return (gcadapter->GetPadState()[port].axes.at(axis) - origin_value) / 95.0f;
|
||||
return (gcadapter->GetPadState()[port].axes.at(axis) - origin_value) / (100.0f * range);
|
||||
}
|
||||
return 0.0f;
|
||||
}
|
||||
@@ -215,6 +213,7 @@ private:
|
||||
GCAdapter::Adapter* gcadapter;
|
||||
const float origin_value_x;
|
||||
const float origin_value_y;
|
||||
const float range;
|
||||
mutable std::mutex mutex;
|
||||
};
|
||||
|
||||
@@ -234,8 +233,9 @@ std::unique_ptr<Input::AnalogDevice> GCAnalogFactory::Create(const Common::Param
|
||||
const int axis_x = params.Get("axis_x", 0);
|
||||
const int axis_y = params.Get("axis_y", 1);
|
||||
const float deadzone = std::clamp(params.Get("deadzone", 0.0f), 0.0f, .99f);
|
||||
const float range = std::clamp(params.Get("range", 1.0f), 0.50f, 1.50f);
|
||||
|
||||
return std::make_unique<GCAnalog>(port, axis_x, axis_y, deadzone, adapter.get());
|
||||
return std::make_unique<GCAnalog>(port, axis_x, axis_y, deadzone, adapter.get(), range);
|
||||
}
|
||||
|
||||
void GCAnalogFactory::BeginConfiguration() {
|
||||
|
||||
@@ -66,14 +66,14 @@ public:
|
||||
state.axes.insert_or_assign(axis, value);
|
||||
}
|
||||
|
||||
float GetAxis(int axis) const {
|
||||
float GetAxis(int axis, float range) const {
|
||||
std::lock_guard lock{mutex};
|
||||
return state.axes.at(axis) / 32767.0f;
|
||||
return state.axes.at(axis) / (32767.0f * range);
|
||||
}
|
||||
|
||||
std::tuple<float, float> GetAnalog(int axis_x, int axis_y) const {
|
||||
float x = GetAxis(axis_x);
|
||||
float y = GetAxis(axis_y);
|
||||
std::tuple<float, float> GetAnalog(int axis_x, int axis_y, float range) const {
|
||||
float x = GetAxis(axis_x, range);
|
||||
float y = GetAxis(axis_y, range);
|
||||
y = -y; // 3DS uses an y-axis inverse from SDL
|
||||
|
||||
// Make sure the coordinates are in the unit circle,
|
||||
@@ -313,7 +313,7 @@ public:
|
||||
trigger_if_greater(trigger_if_greater_) {}
|
||||
|
||||
bool GetStatus() const override {
|
||||
const float axis_value = joystick->GetAxis(axis);
|
||||
const float axis_value = joystick->GetAxis(axis, 1.0f);
|
||||
if (trigger_if_greater) {
|
||||
return axis_value > threshold;
|
||||
}
|
||||
@@ -329,11 +329,13 @@ private:
|
||||
|
||||
class SDLAnalog final : public Input::AnalogDevice {
|
||||
public:
|
||||
SDLAnalog(std::shared_ptr<SDLJoystick> joystick_, int axis_x_, int axis_y_, float deadzone_)
|
||||
: joystick(std::move(joystick_)), axis_x(axis_x_), axis_y(axis_y_), deadzone(deadzone_) {}
|
||||
SDLAnalog(std::shared_ptr<SDLJoystick> joystick_, int axis_x_, int axis_y_, float deadzone_,
|
||||
float range_)
|
||||
: joystick(std::move(joystick_)), axis_x(axis_x_), axis_y(axis_y_), deadzone(deadzone_),
|
||||
range(range_) {}
|
||||
|
||||
std::tuple<float, float> GetStatus() const override {
|
||||
const auto [x, y] = joystick->GetAnalog(axis_x, axis_y);
|
||||
const auto [x, y] = joystick->GetAnalog(axis_x, axis_y, range);
|
||||
const float r = std::sqrt((x * x) + (y * y));
|
||||
if (r > deadzone) {
|
||||
return std::make_tuple(x / r * (r - deadzone) / (1 - deadzone),
|
||||
@@ -363,6 +365,7 @@ private:
|
||||
const int axis_x;
|
||||
const int axis_y;
|
||||
const float deadzone;
|
||||
const float range;
|
||||
};
|
||||
|
||||
/// A button device factory that creates button devices from SDL joystick
|
||||
@@ -458,13 +461,13 @@ public:
|
||||
const int axis_x = params.Get("axis_x", 0);
|
||||
const int axis_y = params.Get("axis_y", 1);
|
||||
const float deadzone = std::clamp(params.Get("deadzone", 0.0f), 0.0f, .99f);
|
||||
|
||||
const float range = std::clamp(params.Get("range", 1.0f), 0.50f, 1.50f);
|
||||
auto joystick = state.GetSDLJoystickByGUID(guid, port);
|
||||
|
||||
// This is necessary so accessing GetAxis with axis_x and axis_y won't crash
|
||||
joystick->SetAxis(axis_x, 0);
|
||||
joystick->SetAxis(axis_y, 0);
|
||||
return std::make_unique<SDLAnalog>(joystick, axis_x, axis_y, deadzone);
|
||||
return std::make_unique<SDLAnalog>(joystick, axis_x, axis_y, deadzone, range);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
@@ -224,8 +224,7 @@ void TestCommunication(const std::string& host, u16 port, u8 pad_index, u32 clie
|
||||
} else {
|
||||
failure_callback();
|
||||
}
|
||||
})
|
||||
.detach();
|
||||
}).detach();
|
||||
}
|
||||
|
||||
CalibrationConfigurationJob::CalibrationConfigurationJob(
|
||||
@@ -279,8 +278,7 @@ CalibrationConfigurationJob::CalibrationConfigurationJob(
|
||||
complete_event.Wait();
|
||||
socket.Stop();
|
||||
worker_thread.join();
|
||||
})
|
||||
.detach();
|
||||
}).detach();
|
||||
}
|
||||
|
||||
CalibrationConfigurationJob::~CalibrationConfigurationJob() {
|
||||
|
||||
@@ -647,7 +647,7 @@ public:
|
||||
GetX() + GetWidth(), // right
|
||||
GetY() // bottom
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
f32 GetX() const {
|
||||
return std::max(0.0f, translate_x - std::fabs(scale_x));
|
||||
|
||||
@@ -94,7 +94,8 @@ void MaxwellDMA::CopyPitchToPitch() {
|
||||
}
|
||||
|
||||
void MaxwellDMA::CopyBlockLinearToPitch() {
|
||||
ASSERT(regs.src_params.block_size.depth == 0);
|
||||
UNIMPLEMENTED_IF(regs.src_params.block_size.depth != 0);
|
||||
UNIMPLEMENTED_IF(regs.src_params.layer != 0);
|
||||
|
||||
// Optimized path for micro copies.
|
||||
const size_t dst_size = static_cast<size_t>(regs.pitch_out) * regs.line_count;
|
||||
@@ -123,17 +124,12 @@ void MaxwellDMA::CopyBlockLinearToPitch() {
|
||||
write_buffer.resize(dst_size);
|
||||
}
|
||||
|
||||
if (Settings::IsGPULevelExtreme()) {
|
||||
memory_manager.ReadBlock(regs.offset_in, read_buffer.data(), src_size);
|
||||
memory_manager.ReadBlock(regs.offset_out, write_buffer.data(), dst_size);
|
||||
} else {
|
||||
memory_manager.ReadBlockUnsafe(regs.offset_in, read_buffer.data(), src_size);
|
||||
memory_manager.ReadBlockUnsafe(regs.offset_out, write_buffer.data(), dst_size);
|
||||
}
|
||||
memory_manager.ReadBlock(regs.offset_in, read_buffer.data(), src_size);
|
||||
memory_manager.ReadBlock(regs.offset_out, write_buffer.data(), dst_size);
|
||||
|
||||
UnswizzleSubrect(regs.line_length_in, regs.line_count, regs.pitch_out, width, bytes_per_pixel,
|
||||
read_buffer.data() + src_layer_size * src_params.layer, write_buffer.data(),
|
||||
block_height, src_params.origin.x, src_params.origin.y);
|
||||
block_height, src_params.origin.x, src_params.origin.y, write_buffer.data(),
|
||||
read_buffer.data());
|
||||
|
||||
memory_manager.WriteBlock(regs.offset_out, write_buffer.data(), dst_size);
|
||||
}
|
||||
@@ -198,7 +194,6 @@ void MaxwellDMA::FastCopyBlockLinearToPitch() {
|
||||
if (read_buffer.size() < src_size) {
|
||||
read_buffer.resize(src_size);
|
||||
}
|
||||
|
||||
if (write_buffer.size() < dst_size) {
|
||||
write_buffer.resize(dst_size);
|
||||
}
|
||||
@@ -212,8 +207,8 @@ void MaxwellDMA::FastCopyBlockLinearToPitch() {
|
||||
}
|
||||
|
||||
UnswizzleSubrect(regs.line_length_in, regs.line_count, regs.pitch_out, regs.src_params.width,
|
||||
bytes_per_pixel, read_buffer.data(), write_buffer.data(),
|
||||
regs.src_params.block_size.height, pos_x, pos_y);
|
||||
bytes_per_pixel, regs.src_params.block_size.height, pos_x, pos_y,
|
||||
write_buffer.data(), read_buffer.data());
|
||||
|
||||
memory_manager.WriteBlock(regs.offset_out, write_buffer.data(), dst_size);
|
||||
}
|
||||
|
||||
@@ -403,7 +403,7 @@ void ShaderCacheOpenGL::LoadDiskCache(const std::atomic_bool& stop_loading,
|
||||
}
|
||||
};
|
||||
|
||||
const auto num_workers{static_cast<std::size_t>(std::thread::hardware_concurrency() + 1ULL)};
|
||||
const std::size_t num_workers{std::max(1U, std::thread::hardware_concurrency())};
|
||||
const std::size_t bucket_size{transferable->size() / num_workers};
|
||||
std::vector<std::unique_ptr<Core::Frontend::GraphicsContext>> contexts(num_workers);
|
||||
std::vector<std::thread> threads(num_workers);
|
||||
|
||||
@@ -756,8 +756,8 @@ public:
|
||||
}
|
||||
|
||||
VkResult GetQueryResults(VkQueryPool query_pool, u32 first, u32 count, std::size_t data_size,
|
||||
void* data, VkDeviceSize stride, VkQueryResultFlags flags) const
|
||||
noexcept {
|
||||
void* data, VkDeviceSize stride,
|
||||
VkQueryResultFlags flags) const noexcept {
|
||||
return dld->vkGetQueryPoolResults(handle, query_pool, first, count, data_size, data, stride,
|
||||
flags);
|
||||
}
|
||||
@@ -849,8 +849,8 @@ public:
|
||||
dld->vkCmdBindPipeline(handle, bind_point, pipeline);
|
||||
}
|
||||
|
||||
void BindIndexBuffer(VkBuffer buffer, VkDeviceSize offset, VkIndexType index_type) const
|
||||
noexcept {
|
||||
void BindIndexBuffer(VkBuffer buffer, VkDeviceSize offset,
|
||||
VkIndexType index_type) const noexcept {
|
||||
dld->vkCmdBindIndexBuffer(handle, buffer, offset, index_type);
|
||||
}
|
||||
|
||||
@@ -863,8 +863,8 @@ public:
|
||||
BindVertexBuffers(binding, 1, &buffer, &offset);
|
||||
}
|
||||
|
||||
void Draw(u32 vertex_count, u32 instance_count, u32 first_vertex, u32 first_instance) const
|
||||
noexcept {
|
||||
void Draw(u32 vertex_count, u32 instance_count, u32 first_vertex,
|
||||
u32 first_instance) const noexcept {
|
||||
dld->vkCmdDraw(handle, vertex_count, instance_count, first_vertex, first_instance);
|
||||
}
|
||||
|
||||
@@ -874,15 +874,15 @@ public:
|
||||
first_instance);
|
||||
}
|
||||
|
||||
void ClearAttachments(Span<VkClearAttachment> attachments, Span<VkClearRect> rects) const
|
||||
noexcept {
|
||||
void ClearAttachments(Span<VkClearAttachment> attachments,
|
||||
Span<VkClearRect> rects) const noexcept {
|
||||
dld->vkCmdClearAttachments(handle, attachments.size(), attachments.data(), rects.size(),
|
||||
rects.data());
|
||||
}
|
||||
|
||||
void BlitImage(VkImage src_image, VkImageLayout src_layout, VkImage dst_image,
|
||||
VkImageLayout dst_layout, Span<VkImageBlit> regions, VkFilter filter) const
|
||||
noexcept {
|
||||
VkImageLayout dst_layout, Span<VkImageBlit> regions,
|
||||
VkFilter filter) const noexcept {
|
||||
dld->vkCmdBlitImage(handle, src_image, src_layout, dst_image, dst_layout, regions.size(),
|
||||
regions.data(), filter);
|
||||
}
|
||||
@@ -907,8 +907,8 @@ public:
|
||||
regions.data());
|
||||
}
|
||||
|
||||
void CopyBuffer(VkBuffer src_buffer, VkBuffer dst_buffer, Span<VkBufferCopy> regions) const
|
||||
noexcept {
|
||||
void CopyBuffer(VkBuffer src_buffer, VkBuffer dst_buffer,
|
||||
Span<VkBufferCopy> regions) const noexcept {
|
||||
dld->vkCmdCopyBuffer(handle, src_buffer, dst_buffer, regions.size(), regions.data());
|
||||
}
|
||||
|
||||
@@ -924,8 +924,8 @@ public:
|
||||
regions.data());
|
||||
}
|
||||
|
||||
void FillBuffer(VkBuffer dst_buffer, VkDeviceSize dst_offset, VkDeviceSize size, u32 data) const
|
||||
noexcept {
|
||||
void FillBuffer(VkBuffer dst_buffer, VkDeviceSize dst_offset, VkDeviceSize size,
|
||||
u32 data) const noexcept {
|
||||
dld->vkCmdFillBuffer(handle, dst_buffer, dst_offset, size, data);
|
||||
}
|
||||
|
||||
|
||||
@@ -187,24 +187,26 @@ std::optional<std::pair<BufferInfo, u64>> TrackLDC(const CFGRebuildState& state,
|
||||
|
||||
std::optional<u64> TrackSHLRegister(const CFGRebuildState& state, u32& pos,
|
||||
u64 ldc_tracked_register) {
|
||||
return TrackInstruction<u64>(state, pos,
|
||||
[ldc_tracked_register](auto instr, const auto& opcode) {
|
||||
return opcode.GetId() == OpCode::Id::SHL_IMM &&
|
||||
instr.gpr0.Value() == ldc_tracked_register;
|
||||
},
|
||||
[](auto instr, const auto&) { return instr.gpr8.Value(); });
|
||||
return TrackInstruction<u64>(
|
||||
state, pos,
|
||||
[ldc_tracked_register](auto instr, const auto& opcode) {
|
||||
return opcode.GetId() == OpCode::Id::SHL_IMM &&
|
||||
instr.gpr0.Value() == ldc_tracked_register;
|
||||
},
|
||||
[](auto instr, const auto&) { return instr.gpr8.Value(); });
|
||||
}
|
||||
|
||||
std::optional<u32> TrackIMNMXValue(const CFGRebuildState& state, u32& pos,
|
||||
u64 shl_tracked_register) {
|
||||
return TrackInstruction<u32>(state, pos,
|
||||
[shl_tracked_register](auto instr, const auto& opcode) {
|
||||
return opcode.GetId() == OpCode::Id::IMNMX_IMM &&
|
||||
instr.gpr0.Value() == shl_tracked_register;
|
||||
},
|
||||
[](auto instr, const auto&) {
|
||||
return static_cast<u32>(instr.alu.GetSignedImm20_20() + 1);
|
||||
});
|
||||
return TrackInstruction<u32>(
|
||||
state, pos,
|
||||
[shl_tracked_register](auto instr, const auto& opcode) {
|
||||
return opcode.GetId() == OpCode::Id::IMNMX_IMM &&
|
||||
instr.gpr0.Value() == shl_tracked_register;
|
||||
},
|
||||
[](auto instr, const auto&) {
|
||||
return static_cast<u32>(instr.alu.GetSignedImm20_20() + 1);
|
||||
});
|
||||
}
|
||||
|
||||
std::optional<BranchIndirectInfo> TrackBranchIndirectInfo(const CFGRebuildState& state, u32 pos) {
|
||||
|
||||
@@ -471,9 +471,9 @@ std::tuple<Node, Node, GlobalMemoryBase> ShaderIR::TrackGlobalMemory(NodeBlock&
|
||||
|
||||
const auto [base_address, index, offset] =
|
||||
TrackCbuf(addr_register, global_code, static_cast<s64>(global_code.size()));
|
||||
ASSERT_OR_EXECUTE_MSG(base_address != nullptr,
|
||||
{ return std::make_tuple(nullptr, nullptr, GlobalMemoryBase{}); },
|
||||
"Global memory tracking failed");
|
||||
ASSERT_OR_EXECUTE_MSG(
|
||||
base_address != nullptr, { return std::make_tuple(nullptr, nullptr, GlobalMemoryBase{}); },
|
||||
"Global memory tracking failed");
|
||||
|
||||
bb.push_back(Comment(fmt::format("Base address is c[0x{:x}][0x{:x}]", index, offset)));
|
||||
|
||||
|
||||
@@ -96,7 +96,6 @@ SurfaceParams SurfaceParams::CreateForTexture(const FormatLookupTable& lookup_ta
|
||||
}
|
||||
params.type = GetFormatType(params.pixel_format);
|
||||
}
|
||||
params.type = GetFormatType(params.pixel_format);
|
||||
// TODO: on 1DBuffer we should use the tic info.
|
||||
if (tic.IsBuffer()) {
|
||||
params.target = SurfaceTarget::TextureBuffer;
|
||||
|
||||
@@ -228,24 +228,30 @@ void SwizzleSubrect(u32 subrect_width, u32 subrect_height, u32 source_pitch, u32
|
||||
}
|
||||
}
|
||||
|
||||
void UnswizzleSubrect(u32 subrect_width, u32 subrect_height, u32 dest_pitch, u32 swizzled_width,
|
||||
u32 bytes_per_pixel, u8* swizzled_data, u8* unswizzled_data,
|
||||
u32 block_height_bit, u32 offset_x, u32 offset_y) {
|
||||
const u32 block_height = 1U << block_height_bit;
|
||||
for (u32 line = 0; line < subrect_height; ++line) {
|
||||
const u32 y2 = line + offset_y;
|
||||
const u32 gob_address_y = (y2 / (GOB_SIZE_Y * block_height)) * GOB_SIZE * block_height +
|
||||
((y2 % (GOB_SIZE_Y * block_height)) / GOB_SIZE_Y) * GOB_SIZE;
|
||||
const auto& table = LEGACY_SWIZZLE_TABLE[y2 % GOB_SIZE_Y];
|
||||
for (u32 x = 0; x < subrect_width; ++x) {
|
||||
const u32 x2 = (x + offset_x) * bytes_per_pixel;
|
||||
const u32 gob_address = gob_address_y + (x2 / GOB_SIZE_X) * GOB_SIZE * block_height;
|
||||
const u32 swizzled_offset = gob_address + table[x2 % GOB_SIZE_X];
|
||||
const u32 unswizzled_offset = line * dest_pitch + x * bytes_per_pixel;
|
||||
u8* dest_line = unswizzled_data + unswizzled_offset;
|
||||
u8* source_addr = swizzled_data + swizzled_offset;
|
||||
void UnswizzleSubrect(u32 line_length_in, u32 line_count, u32 pitch, u32 width, u32 bytes_per_pixel,
|
||||
u32 block_height, u32 origin_x, u32 origin_y, u8* output, const u8* input) {
|
||||
const u32 stride = width * bytes_per_pixel;
|
||||
const u32 gobs_in_x = (stride + GOB_SIZE_X - 1) / GOB_SIZE_X;
|
||||
const u32 block_size = gobs_in_x << (GOB_SIZE_SHIFT + block_height);
|
||||
|
||||
std::memcpy(dest_line, source_addr, bytes_per_pixel);
|
||||
const u32 block_height_mask = (1U << block_height) - 1;
|
||||
const u32 x_shift = static_cast<u32>(GOB_SIZE_SHIFT) + block_height;
|
||||
|
||||
for (u32 line = 0; line < line_count; ++line) {
|
||||
const u32 src_y = line + origin_y;
|
||||
const auto& table = LEGACY_SWIZZLE_TABLE[src_y % GOB_SIZE_Y];
|
||||
|
||||
const u32 block_y = src_y >> GOB_SIZE_Y_SHIFT;
|
||||
const u32 src_offset_y = (block_y >> block_height) * block_size +
|
||||
((block_y & block_height_mask) << GOB_SIZE_SHIFT);
|
||||
for (u32 column = 0; column < line_length_in; ++column) {
|
||||
const u32 src_x = (column + origin_x) * bytes_per_pixel;
|
||||
const u32 src_offset_x = (src_x >> GOB_SIZE_X_SHIFT) << x_shift;
|
||||
|
||||
const u32 swizzled_offset = src_offset_y + src_offset_x + table[src_x % GOB_SIZE_X];
|
||||
const u32 unswizzled_offset = line * pitch + column * bytes_per_pixel;
|
||||
|
||||
std::memcpy(output + unswizzled_offset, input + swizzled_offset, bytes_per_pixel);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -261,7 +267,7 @@ void SwizzleSliceToVoxel(u32 line_length_in, u32 line_count, u32 pitch, u32 widt
|
||||
const u32 block_size = gobs_in_x << (GOB_SIZE_SHIFT + block_height + block_depth);
|
||||
|
||||
const u32 block_height_mask = (1U << block_height) - 1;
|
||||
const u32 x_shift = Common::CountTrailingZeroes32(GOB_SIZE << (block_height + block_depth));
|
||||
const u32 x_shift = static_cast<u32>(GOB_SIZE_SHIFT) + block_height + block_depth;
|
||||
|
||||
for (u32 line = 0; line < line_count; ++line) {
|
||||
const auto& table = LEGACY_SWIZZLE_TABLE[line % GOB_SIZE_Y];
|
||||
|
||||
@@ -48,9 +48,8 @@ void SwizzleSubrect(u32 subrect_width, u32 subrect_height, u32 source_pitch, u32
|
||||
u32 block_height_bit, u32 offset_x, u32 offset_y);
|
||||
|
||||
/// Copies a tiled subrectangle into a linear surface.
|
||||
void UnswizzleSubrect(u32 subrect_width, u32 subrect_height, u32 dest_pitch, u32 swizzled_width,
|
||||
u32 bytes_per_pixel, u8* swizzled_data, u8* unswizzled_data, u32 block_height,
|
||||
u32 offset_x, u32 offset_y);
|
||||
void UnswizzleSubrect(u32 line_length_in, u32 line_count, u32 pitch, u32 width, u32 bytes_per_pixel,
|
||||
u32 block_height, u32 origin_x, u32 origin_y, u8* output, const u8* input);
|
||||
|
||||
/// @brief Swizzles a 2D array of pixels into a 3D texture
|
||||
/// @param line_length_in Number of pixels per line
|
||||
|
||||
@@ -281,24 +281,25 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
|
||||
|
||||
button->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
connect(button, &QPushButton::clicked, [=, this] {
|
||||
HandleClick(button_map[button_id],
|
||||
[=, this](Common::ParamPackage params) {
|
||||
// Workaround for ZL & ZR for analog triggers like on XBOX controllors.
|
||||
// Analog triggers (from controllers like the XBOX controller) would not
|
||||
// work due to a different range of their signals (from 0 to 255 on
|
||||
// analog triggers instead of -32768 to 32768 on analog joysticks). The
|
||||
// SDL driver misinterprets analog triggers as analog joysticks.
|
||||
// TODO: reinterpret the signal range for analog triggers to map the
|
||||
// values correctly. This is required for the correct emulation of the
|
||||
// analog triggers of the GameCube controller.
|
||||
if (button_id == Settings::NativeButton::ZL ||
|
||||
button_id == Settings::NativeButton::ZR) {
|
||||
params.Set("direction", "+");
|
||||
params.Set("threshold", "0.5");
|
||||
}
|
||||
buttons_param[button_id] = std::move(params);
|
||||
},
|
||||
InputCommon::Polling::DeviceType::Button);
|
||||
HandleClick(
|
||||
button_map[button_id],
|
||||
[=, this](Common::ParamPackage params) {
|
||||
// Workaround for ZL & ZR for analog triggers like on XBOX controllors.
|
||||
// Analog triggers (from controllers like the XBOX controller) would not
|
||||
// work due to a different range of their signals (from 0 to 255 on
|
||||
// analog triggers instead of -32768 to 32768 on analog joysticks). The
|
||||
// SDL driver misinterprets analog triggers as analog joysticks.
|
||||
// TODO: reinterpret the signal range for analog triggers to map the
|
||||
// values correctly. This is required for the correct emulation of the
|
||||
// analog triggers of the GameCube controller.
|
||||
if (button_id == Settings::NativeButton::ZL ||
|
||||
button_id == Settings::NativeButton::ZR) {
|
||||
params.Set("direction", "+");
|
||||
params.Set("threshold", "0.5");
|
||||
}
|
||||
buttons_param[button_id] = std::move(params);
|
||||
},
|
||||
InputCommon::Polling::DeviceType::Button);
|
||||
});
|
||||
connect(button, &QPushButton::customContextMenuRequested,
|
||||
[=, this](const QPoint& menu_location) {
|
||||
@@ -325,12 +326,13 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
|
||||
|
||||
analog_button->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
connect(analog_button, &QPushButton::clicked, [=, this] {
|
||||
HandleClick(analog_map_buttons[analog_id][sub_button_id],
|
||||
[=, this](const Common::ParamPackage& params) {
|
||||
SetAnalogButton(params, analogs_param[analog_id],
|
||||
analog_sub_buttons[sub_button_id]);
|
||||
},
|
||||
InputCommon::Polling::DeviceType::Button);
|
||||
HandleClick(
|
||||
analog_map_buttons[analog_id][sub_button_id],
|
||||
[=, this](const Common::ParamPackage& params) {
|
||||
SetAnalogButton(params, analogs_param[analog_id],
|
||||
analog_sub_buttons[sub_button_id]);
|
||||
},
|
||||
InputCommon::Polling::DeviceType::Button);
|
||||
});
|
||||
connect(analog_button, &QPushButton::customContextMenuRequested,
|
||||
[=, this](const QPoint& menu_location) {
|
||||
@@ -357,11 +359,12 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
|
||||
tr("After pressing OK, first move your joystick horizontally, "
|
||||
"and then vertically."),
|
||||
QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Ok) {
|
||||
HandleClick(analog_map_stick[analog_id],
|
||||
[=, this](const Common::ParamPackage& params) {
|
||||
analogs_param[analog_id] = params;
|
||||
},
|
||||
InputCommon::Polling::DeviceType::Analog);
|
||||
HandleClick(
|
||||
analog_map_stick[analog_id],
|
||||
[=, this](const Common::ParamPackage& params) {
|
||||
analogs_param[analog_id] = params;
|
||||
},
|
||||
InputCommon::Polling::DeviceType::Analog);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -84,11 +84,12 @@ ConfigureMouseAdvanced::ConfigureMouseAdvanced(QWidget* parent)
|
||||
|
||||
button->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
connect(button, &QPushButton::clicked, [=, this] {
|
||||
HandleClick(button_map[button_id],
|
||||
[=, this](const Common::ParamPackage& params) {
|
||||
buttons_param[button_id] = params;
|
||||
},
|
||||
InputCommon::Polling::DeviceType::Button);
|
||||
HandleClick(
|
||||
button_map[button_id],
|
||||
[=, this](const Common::ParamPackage& params) {
|
||||
buttons_param[button_id] = params;
|
||||
},
|
||||
InputCommon::Polling::DeviceType::Button);
|
||||
});
|
||||
connect(button, &QPushButton::customContextMenuRequested,
|
||||
[=, this](const QPoint& menu_location) {
|
||||
|
||||
@@ -406,7 +406,7 @@ bool GameList::isEmpty() const {
|
||||
type == GameListItemType::SysNandDir)) {
|
||||
item_model->invisibleRootItem()->removeRow(child->row());
|
||||
i--;
|
||||
};
|
||||
}
|
||||
}
|
||||
return !item_model->invisibleRootItem()->hasChildren();
|
||||
}
|
||||
|
||||
@@ -350,6 +350,7 @@ void GameListWorker::ScanFileSystem(ScanTarget target, const std::string& dir_pa
|
||||
|
||||
void GameListWorker::run() {
|
||||
stop_processing = false;
|
||||
provider->ClearAllEntries();
|
||||
|
||||
for (UISettings::GameDir& game_dir : game_dirs) {
|
||||
if (game_dir.path == QStringLiteral("SDMC")) {
|
||||
@@ -368,13 +369,12 @@ void GameListWorker::run() {
|
||||
watch_list.append(game_dir.path);
|
||||
auto* const game_list_dir = new GameListDir(game_dir);
|
||||
emit DirEntryReady(game_list_dir);
|
||||
provider->ClearAllEntries();
|
||||
ScanFileSystem(ScanTarget::FillManualContentProvider, game_dir.path.toStdString(),
|
||||
game_dir.deep_scan ? 256 : 0, game_list_dir);
|
||||
ScanFileSystem(ScanTarget::PopulateGameList, game_dir.path.toStdString(),
|
||||
game_dir.deep_scan ? 256 : 0, game_list_dir);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
emit Finished(watch_list);
|
||||
}
|
||||
|
||||
@@ -29,14 +29,14 @@ extern const Themes themes;
|
||||
|
||||
struct GameDir {
|
||||
QString path;
|
||||
bool deep_scan;
|
||||
bool expanded;
|
||||
bool deep_scan = false;
|
||||
bool expanded = false;
|
||||
bool operator==(const GameDir& rhs) const {
|
||||
return path == rhs.path;
|
||||
};
|
||||
}
|
||||
bool operator!=(const GameDir& rhs) const {
|
||||
return !operator==(rhs);
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
struct Values {
|
||||
|
||||
Reference in New Issue
Block a user