mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-30 21:30:04 +00:00 
			
		
		
		
	common: Miscellaneous cleanups (#7239)
* code: Remove some old msvc workarounds * android: Upgrade to NDK 26 * Allows access to newer libc++ * common/swap: Make use of std::endian Allows removing a bunch of defines in favor of a two liner. * common: Remove misc.cpp * GetLastErrorMsg has been in error.h for a while and also helps removing a depedency from a hot header like common_funcs * common: use SetThreadDescription API for thread names * common: Remove linear disk cache * Has never been used? * bit_set: Make constexpr * ring_buffer: Use feature macro * bit_set: Use <bit> and concepts * gsp_gpu: Restore comment * core: Ignore GCC warning --------- Co-authored-by: Lioncash <mathew1800@gmail.com> Co-authored-by: Liam <byteslice@airmail.cc>
This commit is contained in:
		
							parent
							
								
									15ea0c6336
								
							
						
					
					
						commit
						2b20082581
					
				
					 15 changed files with 50 additions and 426 deletions
				
			
		|  | @ -128,6 +128,7 @@ else() | ||||||
|         # GCC may warn when it ignores attributes like maybe_unused, |         # GCC may warn when it ignores attributes like maybe_unused, | ||||||
|         # which is a problem for older versions (e.g. GCC 11). |         # which is a problem for older versions (e.g. GCC 11). | ||||||
|         add_compile_options("-Wno-attributes") |         add_compile_options("-Wno-attributes") | ||||||
|  |         add_compile_options("-Wno-interference-size") | ||||||
|     endif() |     endif() | ||||||
| 
 | 
 | ||||||
|     if (MINGW) |     if (MINGW) | ||||||
|  |  | ||||||
|  | @ -29,7 +29,7 @@ android { | ||||||
|     namespace = "org.citra.citra_emu" |     namespace = "org.citra.citra_emu" | ||||||
| 
 | 
 | ||||||
|     compileSdkVersion = "android-34" |     compileSdkVersion = "android-34" | ||||||
|     ndkVersion = "25.2.9519653" |     ndkVersion = "26.1.10909125" | ||||||
| 
 | 
 | ||||||
|     compileOptions { |     compileOptions { | ||||||
|         sourceCompatibility = JavaVersion.VERSION_17 |         sourceCompatibility = JavaVersion.VERSION_17 | ||||||
|  |  | ||||||
|  | @ -83,14 +83,6 @@ class GMainWindow : public QMainWindow { | ||||||
|     /// Max number of recently loaded items to keep track of
 |     /// Max number of recently loaded items to keep track of
 | ||||||
|     static const int max_recent_files_item = 10; |     static const int max_recent_files_item = 10; | ||||||
| 
 | 
 | ||||||
|     // TODO: Make use of this!
 |  | ||||||
|     enum { |  | ||||||
|         UI_IDLE, |  | ||||||
|         UI_EMU_BOOTING, |  | ||||||
|         UI_EMU_RUNNING, |  | ||||||
|         UI_EMU_STOPPING, |  | ||||||
|     }; |  | ||||||
| 
 |  | ||||||
| public: | public: | ||||||
|     void filterBarSetChecked(bool state); |     void filterBarSetChecked(bool state); | ||||||
|     void UpdateUITheme(); |     void UpdateUITheme(); | ||||||
|  |  | ||||||
|  | @ -90,7 +90,6 @@ add_library(citra_common STATIC | ||||||
|     file_util.cpp |     file_util.cpp | ||||||
|     file_util.h |     file_util.h | ||||||
|     hash.h |     hash.h | ||||||
|     linear_disk_cache.h |  | ||||||
|     literals.h |     literals.h | ||||||
|     logging/backend.cpp |     logging/backend.cpp | ||||||
|     logging/backend.h |     logging/backend.h | ||||||
|  | @ -110,7 +109,6 @@ add_library(citra_common STATIC | ||||||
|     microprofile.cpp |     microprofile.cpp | ||||||
|     microprofile.h |     microprofile.h | ||||||
|     microprofileui.h |     microprofileui.h | ||||||
|     misc.cpp |  | ||||||
|     param_package.cpp |     param_package.cpp | ||||||
|     param_package.h |     param_package.h | ||||||
|     polyfill_thread.h |     polyfill_thread.h | ||||||
|  |  | ||||||
|  | @ -2,78 +2,14 @@ | ||||||
| 
 | 
 | ||||||
| #pragma once | #pragma once | ||||||
| 
 | 
 | ||||||
|  | #include <bit> | ||||||
| #include <cstddef> | #include <cstddef> | ||||||
| #ifdef _WIN32 |  | ||||||
| #include <intrin.h> |  | ||||||
| #endif |  | ||||||
| #include <initializer_list> | #include <initializer_list> | ||||||
| #include <new> |  | ||||||
| #include <type_traits> | #include <type_traits> | ||||||
| #include "common/common_types.h" | #include "common/common_types.h" | ||||||
| 
 | 
 | ||||||
| // namespace avoids conflict with OS X Carbon; don't use BitSet<T> directly
 |  | ||||||
| namespace Common { | namespace Common { | ||||||
| 
 | 
 | ||||||
| // Helper functions:
 |  | ||||||
| 
 |  | ||||||
| #ifdef _MSC_VER |  | ||||||
| template <typename T> |  | ||||||
| static inline int CountSetBits(T v) { |  | ||||||
|     // from https://graphics.stanford.edu/~seander/bithacks.html
 |  | ||||||
|     // GCC has this built in, but MSVC's intrinsic will only emit the actual
 |  | ||||||
|     // POPCNT instruction, which we're not depending on
 |  | ||||||
|     v = v - ((v >> 1) & (T) ~(T)0 / 3); |  | ||||||
|     v = (v & (T) ~(T)0 / 15 * 3) + ((v >> 2) & (T) ~(T)0 / 15 * 3); |  | ||||||
|     v = (v + (v >> 4)) & (T) ~(T)0 / 255 * 15; |  | ||||||
|     return (T)(v * ((T) ~(T)0 / 255)) >> (sizeof(T) - 1) * 8; |  | ||||||
| } |  | ||||||
| static inline int LeastSignificantSetBit(u8 val) { |  | ||||||
|     unsigned long index; |  | ||||||
|     _BitScanForward(&index, val); |  | ||||||
|     return (int)index; |  | ||||||
| } |  | ||||||
| static inline int LeastSignificantSetBit(u16 val) { |  | ||||||
|     unsigned long index; |  | ||||||
|     _BitScanForward(&index, val); |  | ||||||
|     return (int)index; |  | ||||||
| } |  | ||||||
| static inline int LeastSignificantSetBit(u32 val) { |  | ||||||
|     unsigned long index; |  | ||||||
|     _BitScanForward(&index, val); |  | ||||||
|     return (int)index; |  | ||||||
| } |  | ||||||
| static inline int LeastSignificantSetBit(u64 val) { |  | ||||||
|     unsigned long index; |  | ||||||
|     _BitScanForward64(&index, val); |  | ||||||
|     return (int)index; |  | ||||||
| } |  | ||||||
| #else |  | ||||||
| static inline int CountSetBits(u8 val) { |  | ||||||
|     return __builtin_popcount(val); |  | ||||||
| } |  | ||||||
| static inline int CountSetBits(u16 val) { |  | ||||||
|     return __builtin_popcount(val); |  | ||||||
| } |  | ||||||
| static inline int CountSetBits(u32 val) { |  | ||||||
|     return __builtin_popcount(val); |  | ||||||
| } |  | ||||||
| static inline int CountSetBits(u64 val) { |  | ||||||
|     return __builtin_popcountll(val); |  | ||||||
| } |  | ||||||
| static inline int LeastSignificantSetBit(u8 val) { |  | ||||||
|     return __builtin_ctz(val); |  | ||||||
| } |  | ||||||
| static inline int LeastSignificantSetBit(u16 val) { |  | ||||||
|     return __builtin_ctz(val); |  | ||||||
| } |  | ||||||
| static inline int LeastSignificantSetBit(u32 val) { |  | ||||||
|     return __builtin_ctz(val); |  | ||||||
| } |  | ||||||
| static inline int LeastSignificantSetBit(u64 val) { |  | ||||||
|     return __builtin_ctzll(val); |  | ||||||
| } |  | ||||||
| #endif |  | ||||||
| 
 |  | ||||||
| // Similar to std::bitset, this is a class which encapsulates a bitset, i.e.
 | // Similar to std::bitset, this is a class which encapsulates a bitset, i.e.
 | ||||||
| // using the set bits of an integer to represent a set of integers.  Like that
 | // using the set bits of an integer to represent a set of integers.  Like that
 | ||||||
| // class, it acts like an array of bools:
 | // class, it acts like an array of bools:
 | ||||||
|  | @ -92,22 +28,19 @@ static inline int LeastSignificantSetBit(u64 val) { | ||||||
| //   operation.)
 | //   operation.)
 | ||||||
| // - Counting set bits using .Count() - see comment on that method.
 | // - Counting set bits using .Count() - see comment on that method.
 | ||||||
| 
 | 
 | ||||||
| // TODO: use constexpr when MSVC gets out of the Dark Ages
 |  | ||||||
| 
 |  | ||||||
| template <typename IntTy> | template <typename IntTy> | ||||||
|  |     requires std::is_unsigned_v<IntTy> | ||||||
| class BitSet { | class BitSet { | ||||||
|     static_assert(!std::is_signed_v<IntTy>, "BitSet should not be used with signed types"); |  | ||||||
| 
 |  | ||||||
| public: | public: | ||||||
|     // A reference to a particular bit, returned from operator[].
 |     // A reference to a particular bit, returned from operator[].
 | ||||||
|     class Ref { |     class Ref { | ||||||
|     public: |     public: | ||||||
|         Ref(Ref&& other) : m_bs(other.m_bs), m_mask(other.m_mask) {} |         constexpr Ref(Ref&& other) : m_bs(other.m_bs), m_mask(other.m_mask) {} | ||||||
|         Ref(BitSet* bs, IntTy mask) : m_bs(bs), m_mask(mask) {} |         constexpr Ref(BitSet* bs, IntTy mask) : m_bs(bs), m_mask(mask) {} | ||||||
|         operator bool() const { |         constexpr operator bool() const { | ||||||
|             return (m_bs->m_val & m_mask) != 0; |             return (m_bs->m_val & m_mask) != 0; | ||||||
|         } |         } | ||||||
|         bool operator=(bool set) { |         constexpr bool operator=(bool set) { | ||||||
|             m_bs->m_val = (m_bs->m_val & ~m_mask) | (set ? m_mask : 0); |             m_bs->m_val = (m_bs->m_val & ~m_mask) | (set ? m_mask : 0); | ||||||
|             return set; |             return set; | ||||||
|         } |         } | ||||||
|  | @ -120,26 +53,26 @@ public: | ||||||
|     // A STL-like iterator is required to be able to use range-based for loops.
 |     // A STL-like iterator is required to be able to use range-based for loops.
 | ||||||
|     class Iterator { |     class Iterator { | ||||||
|     public: |     public: | ||||||
|         Iterator(const Iterator& other) : m_val(other.m_val) {} |         constexpr Iterator(const Iterator& other) : m_val(other.m_val) {} | ||||||
|         Iterator(IntTy val) : m_val(val) {} |         constexpr Iterator(IntTy val) : m_val(val) {} | ||||||
|         int operator*() { |         constexpr int operator*() { | ||||||
|             // This will never be called when m_val == 0, because that would be the end() iterator
 |             // This will never be called when m_val == 0, because that would be the end() iterator
 | ||||||
|             return LeastSignificantSetBit(m_val); |             return std::countr_zero(m_val); | ||||||
|         } |         } | ||||||
|         Iterator& operator++() { |         constexpr Iterator& operator++() { | ||||||
|             // Unset least significant set bit
 |             // Unset least significant set bit
 | ||||||
|             m_val &= m_val - IntTy(1); |             m_val &= m_val - IntTy(1); | ||||||
|             return *this; |             return *this; | ||||||
|         } |         } | ||||||
|         Iterator operator++(int _) { |         constexpr Iterator operator++(int) { | ||||||
|             Iterator other(*this); |             Iterator other(*this); | ||||||
|             ++*this; |             ++*this; | ||||||
|             return other; |             return other; | ||||||
|         } |         } | ||||||
|         bool operator==(Iterator other) const { |         constexpr bool operator==(Iterator other) const { | ||||||
|             return m_val == other.m_val; |             return m_val == other.m_val; | ||||||
|         } |         } | ||||||
|         bool operator!=(Iterator other) const { |         constexpr bool operator!=(Iterator other) const { | ||||||
|             return m_val != other.m_val; |             return m_val != other.m_val; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  | @ -147,74 +80,69 @@ public: | ||||||
|         IntTy m_val; |         IntTy m_val; | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     BitSet() : m_val(0) {} |     constexpr BitSet() : m_val(0) {} | ||||||
|     explicit BitSet(IntTy val) : m_val(val) {} |     constexpr explicit BitSet(IntTy val) : m_val(val) {} | ||||||
|     BitSet(std::initializer_list<int> init) { |     constexpr BitSet(std::initializer_list<int> init) { | ||||||
|         m_val = 0; |         m_val = 0; | ||||||
|         for (int bit : init) |         for (int bit : init) | ||||||
|             m_val |= (IntTy)1 << bit; |             m_val |= (IntTy)1 << bit; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     static BitSet AllTrue(std::size_t count) { |     constexpr static BitSet AllTrue(std::size_t count) { | ||||||
|         return BitSet(count == sizeof(IntTy) * 8 ? ~(IntTy)0 : (((IntTy)1 << count) - 1)); |         return BitSet(count == sizeof(IntTy) * 8 ? ~(IntTy)0 : (((IntTy)1 << count) - 1)); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     Ref operator[](std::size_t bit) { |     constexpr Ref operator[](std::size_t bit) { | ||||||
|         return Ref(this, (IntTy)1 << bit); |         return Ref(this, (IntTy)1 << bit); | ||||||
|     } |     } | ||||||
|     const Ref operator[](std::size_t bit) const { |     constexpr const Ref operator[](std::size_t bit) const { | ||||||
|         return (*const_cast<BitSet*>(this))[bit]; |         return (*const_cast<BitSet*>(this))[bit]; | ||||||
|     } |     } | ||||||
|     bool operator==(BitSet other) const { |     constexpr bool operator==(BitSet other) const { | ||||||
|         return m_val == other.m_val; |         return m_val == other.m_val; | ||||||
|     } |     } | ||||||
|     bool operator!=(BitSet other) const { |     constexpr bool operator!=(BitSet other) const { | ||||||
|         return m_val != other.m_val; |         return m_val != other.m_val; | ||||||
|     } |     } | ||||||
|     bool operator<(BitSet other) const { |     constexpr bool operator<(BitSet other) const { | ||||||
|         return m_val < other.m_val; |         return m_val < other.m_val; | ||||||
|     } |     } | ||||||
|     bool operator>(BitSet other) const { |     constexpr bool operator>(BitSet other) const { | ||||||
|         return m_val > other.m_val; |         return m_val > other.m_val; | ||||||
|     } |     } | ||||||
|     BitSet operator|(BitSet other) const { |     constexpr BitSet operator|(BitSet other) const { | ||||||
|         return BitSet(m_val | other.m_val); |         return BitSet(m_val | other.m_val); | ||||||
|     } |     } | ||||||
|     BitSet operator&(BitSet other) const { |     constexpr BitSet operator&(BitSet other) const { | ||||||
|         return BitSet(m_val & other.m_val); |         return BitSet(m_val & other.m_val); | ||||||
|     } |     } | ||||||
|     BitSet operator^(BitSet other) const { |     constexpr BitSet operator^(BitSet other) const { | ||||||
|         return BitSet(m_val ^ other.m_val); |         return BitSet(m_val ^ other.m_val); | ||||||
|     } |     } | ||||||
|     BitSet operator~() const { |     constexpr BitSet operator~() const { | ||||||
|         return BitSet(~m_val); |         return BitSet(~m_val); | ||||||
|     } |     } | ||||||
|     BitSet& operator|=(BitSet other) { |     constexpr BitSet& operator|=(BitSet other) { | ||||||
|         return *this = *this | other; |         return *this = *this | other; | ||||||
|     } |     } | ||||||
|     BitSet& operator&=(BitSet other) { |     constexpr BitSet& operator&=(BitSet other) { | ||||||
|         return *this = *this & other; |         return *this = *this & other; | ||||||
|     } |     } | ||||||
|     BitSet& operator^=(BitSet other) { |     constexpr BitSet& operator^=(BitSet other) { | ||||||
|         return *this = *this ^ other; |         return *this = *this ^ other; | ||||||
|     } |     } | ||||||
|     operator u32() = delete; |     operator u32() = delete; | ||||||
|     operator bool() { |     constexpr operator bool() { | ||||||
|         return m_val != 0; |         return m_val != 0; | ||||||
|     } |     } | ||||||
| 
 |     constexpr u32 Count() const { | ||||||
|     // Warning: Even though on modern CPUs this is a single fast instruction,
 |         return std::popcount(m_val); | ||||||
|     // Dolphin's official builds do not currently assume POPCNT support on x86,
 |  | ||||||
|     // so slower explicit bit twiddling is generated.  Still should generally
 |  | ||||||
|     // be faster than a loop.
 |  | ||||||
|     unsigned int Count() const { |  | ||||||
|         return CountSetBits(m_val); |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     Iterator begin() const { |     constexpr Iterator begin() const { | ||||||
|         return Iterator(m_val); |         return Iterator(m_val); | ||||||
|     } |     } | ||||||
|     Iterator end() const { |     constexpr Iterator end() const { | ||||||
|         return Iterator(0); |         return Iterator(0); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -4,7 +4,6 @@ | ||||||
| 
 | 
 | ||||||
| #pragma once | #pragma once | ||||||
| 
 | 
 | ||||||
| #include <string> |  | ||||||
| #include "common/common_types.h" | #include "common/common_types.h" | ||||||
| 
 | 
 | ||||||
| /// Textually concatenates two tokens. The double-expansion is required by the C preprocessor.
 | /// Textually concatenates two tokens. The double-expansion is required by the C preprocessor.
 | ||||||
|  | @ -46,14 +45,8 @@ __declspec(dllimport) void __stdcall DebugBreak(void); | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| #ifdef _MSC_VER | #ifdef _MSC_VER | ||||||
| #if (_MSC_VER < 1900) |  | ||||||
| // Function Cross-Compatibility
 |  | ||||||
| #define snprintf _snprintf |  | ||||||
| #endif |  | ||||||
| 
 |  | ||||||
| // Locale Cross-Compatibility
 | // Locale Cross-Compatibility
 | ||||||
| #define locale_t _locale_t | #define locale_t _locale_t | ||||||
| 
 |  | ||||||
| #endif // _MSC_VER
 | #endif // _MSC_VER
 | ||||||
| 
 | 
 | ||||||
| #define DECLARE_ENUM_FLAG_OPERATORS(type)                                                          \ | #define DECLARE_ENUM_FLAG_OPERATORS(type)                                                          \ | ||||||
|  | @ -109,9 +102,3 @@ __declspec(dllimport) void __stdcall DebugBreak(void); | ||||||
|         using T = std::underlying_type_t<type>;                                                    \ |         using T = std::underlying_type_t<type>;                                                    \ | ||||||
|         return static_cast<T>(key) == 0;                                                           \ |         return static_cast<T>(key) == 0;                                                           \ | ||||||
|     } |     } | ||||||
| 
 |  | ||||||
| // Generic function to get last error message.
 |  | ||||||
| // Call directly after the command or use the error num.
 |  | ||||||
| // This function might change the error code.
 |  | ||||||
| // Defined in Misc.cpp.
 |  | ||||||
| [[nodiscard]] std::string GetLastErrorMsg(); |  | ||||||
|  |  | ||||||
|  | @ -14,6 +14,7 @@ | ||||||
| #include "common/assert.h" | #include "common/assert.h" | ||||||
| #include "common/common_funcs.h" | #include "common/common_funcs.h" | ||||||
| #include "common/common_paths.h" | #include "common/common_paths.h" | ||||||
|  | #include "common/error.h" | ||||||
| #include "common/file_util.h" | #include "common/file_util.h" | ||||||
| #include "common/logging/log.h" | #include "common/logging/log.h" | ||||||
| #include "common/scope_exit.h" | #include "common/scope_exit.h" | ||||||
|  | @ -90,6 +91,8 @@ | ||||||
| // REMEMBER: strdup considered harmful!
 | // REMEMBER: strdup considered harmful!
 | ||||||
| namespace FileUtil { | namespace FileUtil { | ||||||
| 
 | 
 | ||||||
|  | using Common::GetLastErrorMsg; | ||||||
|  | 
 | ||||||
| // Remove any ending forward slashes from directory paths
 | // Remove any ending forward slashes from directory paths
 | ||||||
| // Modifies argument.
 | // Modifies argument.
 | ||||||
| static void StripTailDirSlashes(std::string& fname) { | static void StripTailDirSlashes(std::string& fname) { | ||||||
|  |  | ||||||
|  | @ -1,168 +0,0 @@ | ||||||
| // Copyright 2013 Dolphin Emulator Project / 2014 Citra Emulator Project
 |  | ||||||
| // Licensed under GPLv2 or any later version
 |  | ||||||
| // Refer to the license.txt file included.
 |  | ||||||
| 
 |  | ||||||
| #pragma once |  | ||||||
| 
 |  | ||||||
| #include <fstream> |  | ||||||
| #include <vector> |  | ||||||
| #include "common/common_types.h" |  | ||||||
| 
 |  | ||||||
| // defined in Version.cpp
 |  | ||||||
| extern const char* scm_rev_git_str; |  | ||||||
| 
 |  | ||||||
| // On disk format:
 |  | ||||||
| // header{
 |  | ||||||
| // u32 'DCAC';
 |  | ||||||
| // u32 version;  // svn_rev
 |  | ||||||
| // u16 sizeof(key_type);
 |  | ||||||
| // u16 sizeof(value_type);
 |  | ||||||
| //}
 |  | ||||||
| 
 |  | ||||||
| // key_value_pair{
 |  | ||||||
| // u32 value_size;
 |  | ||||||
| // key_type   key;
 |  | ||||||
| // value_type[value_size]   value;
 |  | ||||||
| //}
 |  | ||||||
| 
 |  | ||||||
| template <typename K, typename V> |  | ||||||
| class LinearDiskCacheReader { |  | ||||||
| public: |  | ||||||
|     virtual void Read(const K& key, const V* value, u32 value_size) = 0; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| // Dead simple unsorted key-value store with append functionality.
 |  | ||||||
| // No random read functionality, all reading is done in OpenAndRead.
 |  | ||||||
| // Keys and values can contain any characters, including \0.
 |  | ||||||
| //
 |  | ||||||
| // Suitable for caching generated shader bytecode between executions.
 |  | ||||||
| // Not tuned for extreme performance but should be reasonably fast.
 |  | ||||||
| // Does not support keys or values larger than 2GB, which should be reasonable.
 |  | ||||||
| // Keys must have non-zero length; values can have zero length.
 |  | ||||||
| 
 |  | ||||||
| // K and V are some POD type
 |  | ||||||
| // K : the key type
 |  | ||||||
| // V : value array type
 |  | ||||||
| template <typename K, typename V> |  | ||||||
| class LinearDiskCache { |  | ||||||
| public: |  | ||||||
|     // return number of read entries
 |  | ||||||
|     u32 OpenAndRead(const char* filename, LinearDiskCacheReader<K, V>& reader) { |  | ||||||
|         using std::ios_base; |  | ||||||
| 
 |  | ||||||
|         // close any currently opened file
 |  | ||||||
|         Close(); |  | ||||||
|         m_num_entries = 0; |  | ||||||
| 
 |  | ||||||
|         // try opening for reading/writing
 |  | ||||||
|         OpenFStream(m_file, filename, ios_base::in | ios_base::out | ios_base::binary); |  | ||||||
| 
 |  | ||||||
|         m_file.seekg(0, std::ios::end); |  | ||||||
|         std::fstream::pos_type end_pos = m_file.tellg(); |  | ||||||
|         m_file.seekg(0, std::ios::beg); |  | ||||||
|         std::fstream::pos_type start_pos = m_file.tellg(); |  | ||||||
|         std::streamoff file_size = end_pos - start_pos; |  | ||||||
| 
 |  | ||||||
|         if (m_file.is_open() && ValidateHeader()) { |  | ||||||
|             // good header, read some key/value pairs
 |  | ||||||
|             K key; |  | ||||||
| 
 |  | ||||||
|             std::vector<V> value; |  | ||||||
|             u32 value_size; |  | ||||||
|             u32 entry_number; |  | ||||||
| 
 |  | ||||||
|             std::fstream::pos_type last_pos = m_file.tellg(); |  | ||||||
| 
 |  | ||||||
|             while (Read(&value_size)) { |  | ||||||
|                 std::streamoff next_extent = |  | ||||||
|                     (last_pos - start_pos) + sizeof(value_size) + value_size; |  | ||||||
|                 if (next_extent > file_size) |  | ||||||
|                     break; |  | ||||||
| 
 |  | ||||||
|                 value.clear(); |  | ||||||
|                 value.resize(value_size); |  | ||||||
| 
 |  | ||||||
|                 // read key/value and pass to reader
 |  | ||||||
|                 if (Read(&key) && Read(value.data(), value_size) && Read(&entry_number) && |  | ||||||
|                     entry_number == m_num_entries + 1) { |  | ||||||
|                     reader.Read(key, value.data(), value_size); |  | ||||||
|                 } else { |  | ||||||
|                     break; |  | ||||||
|                 } |  | ||||||
| 
 |  | ||||||
|                 m_num_entries++; |  | ||||||
|                 last_pos = m_file.tellg(); |  | ||||||
|             } |  | ||||||
|             m_file.seekp(last_pos); |  | ||||||
|             m_file.clear(); |  | ||||||
| 
 |  | ||||||
|             value.clear(); |  | ||||||
|             return m_num_entries; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         // failed to open file for reading or bad header
 |  | ||||||
|         // close and recreate file
 |  | ||||||
|         Close(); |  | ||||||
|         m_file.open(filename, ios_base::out | ios_base::trunc | ios_base::binary); |  | ||||||
|         WriteHeader(); |  | ||||||
|         return 0; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     void Sync() { |  | ||||||
|         m_file.flush(); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     void Close() { |  | ||||||
|         if (m_file.is_open()) |  | ||||||
|             m_file.close(); |  | ||||||
|         // clear any error flags
 |  | ||||||
|         m_file.clear(); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     // Appends a key-value pair to the store.
 |  | ||||||
|     void Append(const K& key, const V* value, u32 value_size) { |  | ||||||
|         // TODO: Should do a check that we don't already have "key"? (I think each caller does that
 |  | ||||||
|         // already.)
 |  | ||||||
|         Write(&value_size); |  | ||||||
|         Write(&key); |  | ||||||
|         Write(value, value_size); |  | ||||||
|         m_num_entries++; |  | ||||||
|         Write(&m_num_entries); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
| private: |  | ||||||
|     void WriteHeader() { |  | ||||||
|         Write(&m_header); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     bool ValidateHeader() { |  | ||||||
|         char file_header[sizeof(Header)]; |  | ||||||
| 
 |  | ||||||
|         return (Read(file_header, sizeof(Header)) && |  | ||||||
|                 !memcmp((const char*)&m_header, file_header, sizeof(Header))); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     template <typename D> |  | ||||||
|     bool Write(const D* data, u32 count = 1) { |  | ||||||
|         return m_file.write((const char*)data, count * sizeof(D)).good(); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     template <typename D> |  | ||||||
|     bool Read(const D* data, u32 count = 1) { |  | ||||||
|         return m_file.read((char*)data, count * sizeof(D)).good(); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     struct Header { |  | ||||||
|         Header() : id(*(u32*)"DCAC"), key_t_size(sizeof(K)), value_t_size(sizeof(V)) { |  | ||||||
|             std::memcpy(ver, scm_rev_git_str, 40); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         const u32 id; |  | ||||||
|         const u16 key_t_size, value_t_size; |  | ||||||
|         char ver[40]; |  | ||||||
| 
 |  | ||||||
|     } m_header; |  | ||||||
| 
 |  | ||||||
|     std::fstream m_file; |  | ||||||
|     u32 m_num_entries; |  | ||||||
| }; |  | ||||||
|  | @ -1,48 +0,0 @@ | ||||||
| // Copyright 2013 Dolphin Emulator Project / 2014 Citra Emulator Project
 |  | ||||||
| // Licensed under GPLv2 or any later version
 |  | ||||||
| // Refer to the license.txt file included.
 |  | ||||||
| 
 |  | ||||||
| #include <cstddef> |  | ||||||
| #ifdef _WIN32 |  | ||||||
| #include <windows.h> |  | ||||||
| #else |  | ||||||
| #include <cerrno> |  | ||||||
| #include <cstring> |  | ||||||
| #endif |  | ||||||
| 
 |  | ||||||
| #include "common/common_funcs.h" |  | ||||||
| 
 |  | ||||||
| // Generic function to get last error message.
 |  | ||||||
| // Call directly after the command or use the error num.
 |  | ||||||
| // This function might change the error code.
 |  | ||||||
| std::string GetLastErrorMsg() { |  | ||||||
| #ifdef _WIN32 |  | ||||||
|     LPSTR err_str; |  | ||||||
| 
 |  | ||||||
|     DWORD res = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | |  | ||||||
|                                    FORMAT_MESSAGE_IGNORE_INSERTS, |  | ||||||
|                                nullptr, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), |  | ||||||
|                                reinterpret_cast<LPSTR>(&err_str), 1, nullptr); |  | ||||||
|     if (!res) { |  | ||||||
|         return "(FormatMessageA failed to format error)"; |  | ||||||
|     } |  | ||||||
|     std::string ret(err_str); |  | ||||||
|     LocalFree(err_str); |  | ||||||
|     return ret; |  | ||||||
| #else |  | ||||||
|     char err_str[255]; |  | ||||||
| #if (defined(__GLIBC__) || __ANDROID_API__ >= 23) &&                                               \ |  | ||||||
|     (_GNU_SOURCE || (_POSIX_C_SOURCE < 200112L && _XOPEN_SOURCE < 600)) |  | ||||||
|     // Thread safe (GNU-specific)
 |  | ||||||
|     const char* str = strerror_r(errno, err_str, sizeof(err_str)); |  | ||||||
|     return std::string(str); |  | ||||||
| #else |  | ||||||
|     // Thread safe (XSI-compliant)
 |  | ||||||
|     int second_err = strerror_r(errno, err_str, sizeof(err_str)); |  | ||||||
|     if (second_err != 0) { |  | ||||||
|         return "(strerror_r failed to format error)"; |  | ||||||
|     } |  | ||||||
|     return std::string(err_str); |  | ||||||
| #endif // GLIBC etc.
 |  | ||||||
| #endif // _WIN32
 |  | ||||||
| } |  | ||||||
|  | @ -105,9 +105,7 @@ public: | ||||||
| private: | private: | ||||||
|     // It is important to separate the below atomics for performance reasons:
 |     // It is important to separate the below atomics for performance reasons:
 | ||||||
|     // Having them on the same cache-line would result in false-sharing between them.
 |     // Having them on the same cache-line would result in false-sharing between them.
 | ||||||
|     // TODO: Remove this ifdef whenever clang and GCC support
 | #ifdef __cpp_lib_hardware_interference_size | ||||||
|     //       std::hardware_destructive_interference_size.
 |  | ||||||
| #if defined(_MSC_VER) && _MSC_VER >= 1911 |  | ||||||
|     static constexpr std::size_t padding_size = |     static constexpr std::size_t padding_size = | ||||||
|         std::hardware_destructive_interference_size - sizeof(std::atomic_size_t); |         std::hardware_destructive_interference_size - sizeof(std::atomic_size_t); | ||||||
| #else | #else | ||||||
|  |  | ||||||
|  | @ -17,43 +17,14 @@ | ||||||
| 
 | 
 | ||||||
| #pragma once | #pragma once | ||||||
| 
 | 
 | ||||||
| #include <type_traits> |  | ||||||
| 
 |  | ||||||
| #if defined(_MSC_VER) | #if defined(_MSC_VER) | ||||||
| #include <cstdlib> | #include <cstdlib> | ||||||
| #endif | #endif | ||||||
|  | #include <bit> | ||||||
| #include <cstring> | #include <cstring> | ||||||
|  | #include <type_traits> | ||||||
| #include "common/common_types.h" | #include "common/common_types.h" | ||||||
| 
 | 
 | ||||||
| // GCC
 |  | ||||||
| #ifdef __GNUC__ |  | ||||||
| 
 |  | ||||||
| #if __BYTE_ORDER__ && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) && !defined(COMMON_LITTLE_ENDIAN) |  | ||||||
| #define COMMON_LITTLE_ENDIAN 1 |  | ||||||
| #elif __BYTE_ORDER__ && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) && !defined(COMMON_BIG_ENDIAN) |  | ||||||
| #define COMMON_BIG_ENDIAN 1 |  | ||||||
| #endif |  | ||||||
| 
 |  | ||||||
| // LLVM/clang
 |  | ||||||
| #elif defined(__clang__) |  | ||||||
| 
 |  | ||||||
| #if __LITTLE_ENDIAN__ && !defined(COMMON_LITTLE_ENDIAN) |  | ||||||
| #define COMMON_LITTLE_ENDIAN 1 |  | ||||||
| #elif __BIG_ENDIAN__ && !defined(COMMON_BIG_ENDIAN) |  | ||||||
| #define COMMON_BIG_ENDIAN 1 |  | ||||||
| #endif |  | ||||||
| 
 |  | ||||||
| // MSVC
 |  | ||||||
| #elif defined(_MSC_VER) && !defined(COMMON_BIG_ENDIAN) && !defined(COMMON_LITTLE_ENDIAN) |  | ||||||
| 
 |  | ||||||
| #define COMMON_LITTLE_ENDIAN 1 |  | ||||||
| #endif |  | ||||||
| 
 |  | ||||||
| // Worst case, default to little endian.
 |  | ||||||
| #if !COMMON_BIG_ENDIAN && !COMMON_LITTLE_ENDIAN |  | ||||||
| #define COMMON_LITTLE_ENDIAN 1 |  | ||||||
| #endif |  | ||||||
| 
 |  | ||||||
| namespace Common { | namespace Common { | ||||||
| 
 | 
 | ||||||
| #ifdef _MSC_VER | #ifdef _MSC_VER | ||||||
|  | @ -675,17 +646,8 @@ struct AddEndian<T, SwapTag> { | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| // Alias LETag/BETag as KeepTag/SwapTag depending on the system
 | // Alias LETag/BETag as KeepTag/SwapTag depending on the system
 | ||||||
| #if COMMON_LITTLE_ENDIAN | using LETag = std::conditional_t<std::endian::native == std::endian::little, KeepTag, SwapTag>; | ||||||
| 
 | using BETag = std::conditional_t<std::endian::native == std::endian::big, KeepTag, SwapTag>; | ||||||
| using LETag = KeepTag; |  | ||||||
| using BETag = SwapTag; |  | ||||||
| 
 |  | ||||||
| #else |  | ||||||
| 
 |  | ||||||
| using BETag = KeepTag; |  | ||||||
| using LETag = SwapTag; |  | ||||||
| 
 |  | ||||||
| #endif |  | ||||||
| 
 | 
 | ||||||
| // Aliases for LE types
 | // Aliases for LE types
 | ||||||
| using u16_le = AddEndian<u16, LETag>::type; | using u16_le = AddEndian<u16, LETag>::type; | ||||||
|  |  | ||||||
|  | @ -11,6 +11,7 @@ | ||||||
| #include <mach/mach.h> | #include <mach/mach.h> | ||||||
| #elif defined(_WIN32) | #elif defined(_WIN32) | ||||||
| #include <windows.h> | #include <windows.h> | ||||||
|  | #include "common/string_util.h" | ||||||
| #else | #else | ||||||
| #if defined(__Bitrig__) || defined(__DragonFly__) || defined(__FreeBSD__) || defined(__OpenBSD__) | #if defined(__Bitrig__) || defined(__DragonFly__) || defined(__FreeBSD__) || defined(__OpenBSD__) | ||||||
| #include <pthread_np.h> | #include <pthread_np.h> | ||||||
|  | @ -82,29 +83,8 @@ void SetCurrentThreadPriority(ThreadPriority new_priority) { | ||||||
| #ifdef _MSC_VER | #ifdef _MSC_VER | ||||||
| 
 | 
 | ||||||
| // Sets the debugger-visible name of the current thread.
 | // Sets the debugger-visible name of the current thread.
 | ||||||
| // Uses trick documented in:
 |  | ||||||
| // https://docs.microsoft.com/en-us/visualstudio/debugger/how-to-set-a-thread-name-in-native-code
 |  | ||||||
| void SetCurrentThreadName(const char* name) { | void SetCurrentThreadName(const char* name) { | ||||||
|     static const DWORD MS_VC_EXCEPTION = 0x406D1388; |     SetThreadDescription(GetCurrentThread(), UTF8ToUTF16W(name).data()); | ||||||
| 
 |  | ||||||
| #pragma pack(push, 8) |  | ||||||
|     struct THREADNAME_INFO { |  | ||||||
|         DWORD dwType;     // must be 0x1000
 |  | ||||||
|         LPCSTR szName;    // pointer to name (in user addr space)
 |  | ||||||
|         DWORD dwThreadID; // thread ID (-1=caller thread)
 |  | ||||||
|         DWORD dwFlags;    // reserved for future use, must be zero
 |  | ||||||
|     } info; |  | ||||||
| #pragma pack(pop) |  | ||||||
| 
 |  | ||||||
|     info.dwType = 0x1000; |  | ||||||
|     info.szName = name; |  | ||||||
|     info.dwThreadID = std::numeric_limits<DWORD>::max(); |  | ||||||
|     info.dwFlags = 0; |  | ||||||
| 
 |  | ||||||
|     __try { |  | ||||||
|         RaiseException(MS_VC_EXCEPTION, 0, sizeof(info) / sizeof(ULONG_PTR), (ULONG_PTR*)&info); |  | ||||||
|     } __except (EXCEPTION_CONTINUE_EXECUTION) { |  | ||||||
|     } |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #else // !MSVC_VER, so must be POSIX threads
 | #else // !MSVC_VER, so must be POSIX threads
 | ||||||
|  |  | ||||||
|  | @ -5,6 +5,7 @@ | ||||||
| #include <algorithm> | #include <algorithm> | ||||||
| #include <memory> | #include <memory> | ||||||
| #include "common/archives.h" | #include "common/archives.h" | ||||||
|  | #include "common/error.h" | ||||||
| #include "common/file_util.h" | #include "common/file_util.h" | ||||||
| #include "common/logging/log.h" | #include "common/logging/log.h" | ||||||
| #include "common/settings.h" | #include "common/settings.h" | ||||||
|  | @ -103,7 +104,7 @@ ResultVal<std::unique_ptr<FileBackend>> SDMCArchive::OpenFileBase(const Path& pa | ||||||
| 
 | 
 | ||||||
|     FileUtil::IOFile file(full_path, mode.write_flag ? "r+b" : "rb"); |     FileUtil::IOFile file(full_path, mode.write_flag ? "r+b" : "rb"); | ||||||
|     if (!file.IsOpen()) { |     if (!file.IsOpen()) { | ||||||
|         LOG_CRITICAL(Service_FS, "Error opening {}: {}", full_path, GetLastErrorMsg()); |         LOG_CRITICAL(Service_FS, "Error opening {}: {}", full_path, Common::GetLastErrorMsg()); | ||||||
|         return ERROR_NOT_FOUND; |         return ERROR_NOT_FOUND; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -97,10 +97,8 @@ struct FrameBufferUpdate { | ||||||
| static_assert(sizeof(FrameBufferUpdate) == 0x40, "Struct has incorrect size"); | static_assert(sizeof(FrameBufferUpdate) == 0x40, "Struct has incorrect size"); | ||||||
| // TODO: Not sure if this padding is correct.
 | // TODO: Not sure if this padding is correct.
 | ||||||
| // Chances are the second block is stored at offset 0x24 rather than 0x20.
 | // Chances are the second block is stored at offset 0x24 rather than 0x20.
 | ||||||
| #ifndef _MSC_VER |  | ||||||
| static_assert(offsetof(FrameBufferUpdate, framebuffer_info[1]) == 0x20, | static_assert(offsetof(FrameBufferUpdate, framebuffer_info[1]) == 0x20, | ||||||
|               "FrameBufferInfo element has incorrect alignment"); |               "FrameBufferInfo element has incorrect alignment"); | ||||||
| #endif |  | ||||||
| 
 | 
 | ||||||
| /// GSP command
 | /// GSP command
 | ||||||
| struct Command { | struct Command { | ||||||
|  |  | ||||||
|  | @ -64,22 +64,14 @@ private: | ||||||
| }; | }; | ||||||
| static_assert(std::is_standard_layout<Regs>::value, "Structure does not use standard layout"); | static_assert(std::is_standard_layout<Regs>::value, "Structure does not use standard layout"); | ||||||
| 
 | 
 | ||||||
| // TODO: MSVC does not support using offsetof() on non-static data members even though this
 |  | ||||||
| //       is technically allowed since C++11. This macro should be enabled once MSVC adds
 |  | ||||||
| //       support for that.
 |  | ||||||
| #ifndef _MSC_VER |  | ||||||
| #define ASSERT_REG_POSITION(field_name, position)                                                  \ | #define ASSERT_REG_POSITION(field_name, position)                                                  \ | ||||||
|     static_assert(offsetof(Regs, field_name) == position * 4,                                      \ |     static_assert(offsetof(Regs, field_name) == position * 4,                                      \ | ||||||
|                   "Field " #field_name " has invalid position") |                   "Field " #field_name " has invalid position") | ||||||
| 
 |  | ||||||
| ASSERT_REG_POSITION(color_fill_top, 0x81); | ASSERT_REG_POSITION(color_fill_top, 0x81); | ||||||
| ASSERT_REG_POSITION(backlight_top, 0x90); | ASSERT_REG_POSITION(backlight_top, 0x90); | ||||||
| ASSERT_REG_POSITION(color_fill_bottom, 0x281); | ASSERT_REG_POSITION(color_fill_bottom, 0x281); | ||||||
| ASSERT_REG_POSITION(backlight_bottom, 0x290); | ASSERT_REG_POSITION(backlight_bottom, 0x290); | ||||||
| 
 | 
 | ||||||
| #undef ASSERT_REG_POSITION |  | ||||||
| #endif // !defined(_MSC_VER)
 |  | ||||||
| 
 |  | ||||||
| extern Regs g_regs; | extern Regs g_regs; | ||||||
| 
 | 
 | ||||||
| template <typename T> | template <typename T> | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue