mirror of
https://github.com/wheremyfoodat/Panda3DS.git
synced 2025-09-26 11:18:35 +00:00
Add std::bit_cast fallback for Helpers::bit_cast and run clang-format
This commit is contained in:
parent
e9b3b7c2a2
commit
88e3eb1558
1 changed files with 119 additions and 121 deletions
|
@ -1,6 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <cstdarg>
|
|
||||||
#include <climits>
|
#include <climits>
|
||||||
|
#include <cstdarg>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
@ -8,8 +8,16 @@
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "termcolor.hpp"
|
#include "termcolor.hpp"
|
||||||
|
|
||||||
|
// We have to detect and special-case AppleClang at the moment since its C++20 support is finicky and doesn't quite support std::bit_cast
|
||||||
|
#if defined(__clang__) && defined(__apple_build_version__)
|
||||||
|
#define HELPERS_APPLE_CLANG
|
||||||
|
#else
|
||||||
|
#include <bit>
|
||||||
|
#endif
|
||||||
|
|
||||||
using u8 = std::uint8_t;
|
using u8 = std::uint8_t;
|
||||||
using u16 = std::uint16_t;
|
using u16 = std::uint16_t;
|
||||||
using u32 = std::uint32_t;
|
using u32 = std::uint32_t;
|
||||||
|
@ -23,78 +31,74 @@ using s32 = std::int32_t;
|
||||||
using s64 = std::int64_t;
|
using s64 = std::int64_t;
|
||||||
|
|
||||||
namespace Helpers {
|
namespace Helpers {
|
||||||
[[noreturn]] static void panic(const char* fmt, ...) {
|
[[noreturn]] static void panic(const char* fmt, ...) {
|
||||||
std::va_list args;
|
std::va_list args;
|
||||||
va_start(args, fmt);
|
va_start(args, fmt);
|
||||||
std::cout << termcolor::on_red << "[FATAL] ";
|
std::cout << termcolor::on_red << "[FATAL] ";
|
||||||
std::vprintf (fmt, args);
|
std::vprintf(fmt, args);
|
||||||
std::cout << termcolor::reset << "\n";
|
std::cout << termcolor::reset << "\n";
|
||||||
va_end(args);
|
va_end(args);
|
||||||
|
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void warn(const char* fmt, ...) {
|
static void warn(const char* fmt, ...) {
|
||||||
std::va_list args;
|
std::va_list args;
|
||||||
va_start(args, fmt);
|
va_start(args, fmt);
|
||||||
std::cout << termcolor::on_red << "[Warning] ";
|
std::cout << termcolor::on_red << "[Warning] ";
|
||||||
std::vprintf (fmt, args);
|
std::vprintf(fmt, args);
|
||||||
std::cout << termcolor::reset << "\n";
|
std::cout << termcolor::reset << "\n";
|
||||||
va_end(args);
|
va_end(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::vector <u8> loadROM(std::string directory) {
|
static std::vector<u8> loadROM(std::string directory) {
|
||||||
std::ifstream file (directory, std::ios::binary);
|
std::ifstream file(directory, std::ios::binary);
|
||||||
if (file.fail())
|
if (file.fail()) panic("Couldn't read %s", directory.c_str());
|
||||||
panic("Couldn't read %s", directory.c_str());
|
|
||||||
|
|
||||||
std::vector<u8> ROM;
|
std::vector<u8> ROM;
|
||||||
|
|
||||||
file.unsetf(std::ios::skipws);
|
file.unsetf(std::ios::skipws);
|
||||||
ROM.insert(ROM.begin(),
|
ROM.insert(ROM.begin(), std::istream_iterator<uint8_t>(file), std::istream_iterator<uint8_t>());
|
||||||
std::istream_iterator<uint8_t>(file),
|
|
||||||
std::istream_iterator<uint8_t>());
|
|
||||||
|
|
||||||
file.close();
|
file.close();
|
||||||
|
|
||||||
printf ("%s loaded successfully\n", directory.c_str());
|
printf("%s loaded successfully\n", directory.c_str());
|
||||||
return ROM;
|
return ROM;
|
||||||
}
|
}
|
||||||
|
|
||||||
static constexpr bool buildingInDebugMode() {
|
static constexpr bool buildingInDebugMode() {
|
||||||
#ifdef NDEBUG
|
#ifdef NDEBUG
|
||||||
return false;
|
return false;
|
||||||
#endif
|
#endif
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
static void debug_printf(const char* fmt, ...) {
|
||||||
}
|
if constexpr (buildingInDebugMode()) {
|
||||||
|
std::va_list args;
|
||||||
static void debug_printf (const char* fmt, ...) {
|
va_start(args, fmt);
|
||||||
if constexpr (buildingInDebugMode()) {
|
std::vprintf(fmt, args);
|
||||||
std::va_list args;
|
va_end(args);
|
||||||
va_start(args, fmt);
|
}
|
||||||
std::vprintf (fmt, args);
|
}
|
||||||
va_end(args);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Sign extend an arbitrary-size value to 32 bits
|
/// Sign extend an arbitrary-size value to 32 bits
|
||||||
static constexpr u32 inline signExtend32 (u32 value, u32 startingSize) {
|
static constexpr u32 inline signExtend32(u32 value, u32 startingSize) {
|
||||||
auto temp = (s32) value;
|
auto temp = (s32)value;
|
||||||
auto bitsToShift = 32 - startingSize;
|
auto bitsToShift = 32 - startingSize;
|
||||||
return (u32) (temp << bitsToShift >> bitsToShift);
|
return (u32)(temp << bitsToShift >> bitsToShift);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sign extend an arbitrary-size value to 16 bits
|
/// Sign extend an arbitrary-size value to 16 bits
|
||||||
static constexpr u16 signExtend16 (u16 value, u32 startingSize) {
|
static constexpr u16 signExtend16(u16 value, u32 startingSize) {
|
||||||
auto temp = (s16) value;
|
auto temp = (s16)value;
|
||||||
auto bitsToShift = 16 - startingSize;
|
auto bitsToShift = 16 - startingSize;
|
||||||
return (u16) (temp << bitsToShift >> bitsToShift);
|
return (u16)(temp << bitsToShift >> bitsToShift);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a mask with `count` number of one bits.
|
/// Create a mask with `count` number of one bits.
|
||||||
template<typename T, usize count>
|
template <typename T, usize count>
|
||||||
static constexpr T ones () {
|
static constexpr T ones() {
|
||||||
constexpr usize bitsize = CHAR_BIT * sizeof(T);
|
constexpr usize bitsize = CHAR_BIT * sizeof(T);
|
||||||
static_assert(count <= bitsize, "count larger than bitsize of T");
|
static_assert(count <= bitsize, "count larger than bitsize of T");
|
||||||
|
|
||||||
|
@ -105,80 +109,74 @@ namespace Helpers {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Extract bits from an integer-type
|
/// Extract bits from an integer-type
|
||||||
template<usize offset, typename T>
|
template <usize offset, typename T>
|
||||||
static constexpr T getBit (T value) {
|
static constexpr T getBit(T value) {
|
||||||
return (value >> offset) & T(1);
|
return (value >> offset) & T(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Extract bits from an integer-type
|
/// Extract bits from an integer-type
|
||||||
template<usize offset, usize bits, typename T>
|
template <usize offset, usize bits, typename T>
|
||||||
static constexpr T getBits (T value) {
|
static constexpr T getBits(T value) {
|
||||||
return (value >> offset) & ones<T, bits>();
|
return (value >> offset) & ones<T, bits>();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check if a bit "bit" of value is set
|
/// Check if a bit "bit" of value is set
|
||||||
static constexpr bool isBitSet (u32 value, int bit) {
|
static constexpr bool isBitSet(u32 value, int bit) { return (value >> bit) & 1; }
|
||||||
return (value >> bit) & 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// rotate number right
|
/// rotate number right
|
||||||
template <typename T>
|
template <typename T>
|
||||||
static constexpr T rotr (T value, int bits) {
|
static constexpr T rotr(T value, int bits) {
|
||||||
constexpr auto bitWidth = sizeof(T) * 8;
|
constexpr auto bitWidth = sizeof(T) * 8;
|
||||||
bits &= bitWidth - 1;
|
bits &= bitWidth - 1;
|
||||||
return (value >> bits) | (value << (bitWidth - bits));
|
return (value >> bits) | (value << (bitWidth - bits));
|
||||||
}
|
}
|
||||||
|
|
||||||
// rotate number left
|
// rotate number left
|
||||||
template <typename T>
|
template <typename T>
|
||||||
static constexpr T rotl (T value, int bits) {
|
static constexpr T rotl(T value, int bits) {
|
||||||
constexpr auto bitWidth = sizeof(T) * 8;
|
constexpr auto bitWidth = sizeof(T) * 8;
|
||||||
bits &= bitWidth - 1;
|
bits &= bitWidth - 1;
|
||||||
return (value << bits) | (value >> (bitWidth - bits));
|
return (value << bits) | (value >> (bitWidth - bits));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Used to make the compiler evaluate beeg loops at compile time for the tablegen
|
/// Used to make the compiler evaluate beeg loops at compile time for the tablegen
|
||||||
template <typename T, T Begin, class Func, T ...Is>
|
template <typename T, T Begin, class Func, T... Is>
|
||||||
static constexpr void static_for_impl( Func&& f, std::integer_sequence<T, Is...> ) {
|
static constexpr void static_for_impl(Func&& f, std::integer_sequence<T, Is...>) {
|
||||||
( f( std::integral_constant<T, Begin + Is>{ } ),... );
|
(f(std::integral_constant<T, Begin + Is>{}), ...);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, T Begin, T End, class Func>
|
template <typename T, T Begin, T End, class Func>
|
||||||
static constexpr void static_for(Func&& f) {
|
static constexpr void static_for(Func&& f) {
|
||||||
static_for_impl<T, Begin>( std::forward<Func>(f), std::make_integer_sequence<T, End - Begin>{ } );
|
static_for_impl<T, Begin>(std::forward<Func>(f), std::make_integer_sequence<T, End - Begin>{});
|
||||||
}
|
}
|
||||||
|
|
||||||
// For values < 0x99
|
// For values < 0x99
|
||||||
static constexpr inline u8 incBCDByte(u8 value) {
|
static constexpr inline u8 incBCDByte(u8 value) { return ((value & 0xf) == 0x9) ? value + 7 : value + 1; }
|
||||||
return ((value & 0xf) == 0x9) ? value + 7 : value + 1;
|
|
||||||
}
|
#ifdef HELPERS_APPLE_CLANG
|
||||||
// Use this helper for platforms that lack a working std::bit_cast implementation
|
template <class To, class From>
|
||||||
// TODO: Replace this with C++20 version if available
|
constexpr To bit_cast(const From& from) noexcept {
|
||||||
template< class To, class From >
|
return *reinterpret_cast<const To*>(&from);
|
||||||
constexpr To bit_cast( const From& from ) noexcept{
|
}
|
||||||
return *reinterpret_cast<const To*>(&from);
|
#else
|
||||||
}
|
template <class To, class From>
|
||||||
};
|
constexpr To bit_cast(const From& from) noexcept {
|
||||||
|
return std::bit_cast<To, From>(from);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}; // namespace Helpers
|
||||||
|
|
||||||
// UDLs for memory size values
|
// UDLs for memory size values
|
||||||
constexpr size_t operator""_KB(unsigned long long int x) {
|
constexpr size_t operator""_KB(unsigned long long int x) { return 1024ULL * x; }
|
||||||
return 1024ULL * x;
|
constexpr size_t operator""_MB(unsigned long long int x) { return 1024_KB * x; }
|
||||||
}
|
constexpr size_t operator""_GB(unsigned long long int x) { return 1024_MB * x; }
|
||||||
|
|
||||||
constexpr size_t operator""_MB(unsigned long long int x) {
|
|
||||||
return 1024_KB * x;
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr size_t operator""_GB(unsigned long long int x) {
|
|
||||||
return 1024_MB * x;
|
|
||||||
}
|
|
||||||
|
|
||||||
// useful macros
|
// useful macros
|
||||||
// likely/unlikely
|
// likely/unlikely
|
||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
#define likely(x) __builtin_expect((x),1)
|
#define likely(x) __builtin_expect((x), 1)
|
||||||
#define unlikely(x) __builtin_expect((x),0)
|
#define unlikely(x) __builtin_expect((x), 0)
|
||||||
#else
|
#else
|
||||||
#define likely(x) (x)
|
#define likely(x) (x)
|
||||||
#define unlikely(x) (x)
|
#define unlikely(x) (x)
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue