mirror of
https://github.com/RetroDECK/Duckstation.git
synced 2024-11-22 22:05:38 +00:00
CDImage: Use ByteSwap()
This commit is contained in:
parent
4a906fd0a0
commit
f27a28b58c
|
@ -2,22 +2,26 @@
|
||||||
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
|
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
#include <intrin.h>
|
#include <stdlib.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Zero-extending helper
|
// Zero-extending helper
|
||||||
template<typename TReturn, typename TValue>
|
template<typename TReturn, typename TValue>
|
||||||
ALWAYS_INLINE constexpr TReturn ZeroExtend(TValue value)
|
ALWAYS_INLINE static constexpr TReturn ZeroExtend(TValue value)
|
||||||
{
|
{
|
||||||
return static_cast<TReturn>(static_cast<typename std::make_unsigned<TReturn>::type>(
|
return static_cast<TReturn>(static_cast<typename std::make_unsigned<TReturn>::type>(
|
||||||
static_cast<typename std::make_unsigned<TValue>::type>(value)));
|
static_cast<typename std::make_unsigned<TValue>::type>(value)));
|
||||||
}
|
}
|
||||||
// Sign-extending helper
|
// Sign-extending helper
|
||||||
template<typename TReturn, typename TValue>
|
template<typename TReturn, typename TValue>
|
||||||
ALWAYS_INLINE constexpr TReturn SignExtend(TValue value)
|
ALWAYS_INLINE static constexpr TReturn SignExtend(TValue value)
|
||||||
{
|
{
|
||||||
return static_cast<TReturn>(
|
return static_cast<TReturn>(
|
||||||
static_cast<typename std::make_signed<TReturn>::type>(static_cast<typename std::make_signed<TValue>::type>(value)));
|
static_cast<typename std::make_signed<TReturn>::type>(static_cast<typename std::make_signed<TValue>::type>(value)));
|
||||||
|
@ -25,97 +29,97 @@ ALWAYS_INLINE constexpr TReturn SignExtend(TValue value)
|
||||||
|
|
||||||
// Type-specific helpers
|
// Type-specific helpers
|
||||||
template<typename TValue>
|
template<typename TValue>
|
||||||
ALWAYS_INLINE constexpr u16 ZeroExtend16(TValue value)
|
ALWAYS_INLINE static constexpr u16 ZeroExtend16(TValue value)
|
||||||
{
|
{
|
||||||
return ZeroExtend<u16, TValue>(value);
|
return ZeroExtend<u16, TValue>(value);
|
||||||
}
|
}
|
||||||
template<typename TValue>
|
template<typename TValue>
|
||||||
ALWAYS_INLINE constexpr u32 ZeroExtend32(TValue value)
|
ALWAYS_INLINE static constexpr u32 ZeroExtend32(TValue value)
|
||||||
{
|
{
|
||||||
return ZeroExtend<u32, TValue>(value);
|
return ZeroExtend<u32, TValue>(value);
|
||||||
}
|
}
|
||||||
template<typename TValue>
|
template<typename TValue>
|
||||||
ALWAYS_INLINE constexpr u64 ZeroExtend64(TValue value)
|
ALWAYS_INLINE static constexpr u64 ZeroExtend64(TValue value)
|
||||||
{
|
{
|
||||||
return ZeroExtend<u64, TValue>(value);
|
return ZeroExtend<u64, TValue>(value);
|
||||||
}
|
}
|
||||||
template<typename TValue>
|
template<typename TValue>
|
||||||
ALWAYS_INLINE constexpr u16 SignExtend16(TValue value)
|
ALWAYS_INLINE static constexpr u16 SignExtend16(TValue value)
|
||||||
{
|
{
|
||||||
return SignExtend<u16, TValue>(value);
|
return SignExtend<u16, TValue>(value);
|
||||||
}
|
}
|
||||||
template<typename TValue>
|
template<typename TValue>
|
||||||
ALWAYS_INLINE constexpr u32 SignExtend32(TValue value)
|
ALWAYS_INLINE static constexpr u32 SignExtend32(TValue value)
|
||||||
{
|
{
|
||||||
return SignExtend<u32, TValue>(value);
|
return SignExtend<u32, TValue>(value);
|
||||||
}
|
}
|
||||||
template<typename TValue>
|
template<typename TValue>
|
||||||
ALWAYS_INLINE constexpr u64 SignExtend64(TValue value)
|
ALWAYS_INLINE static constexpr u64 SignExtend64(TValue value)
|
||||||
{
|
{
|
||||||
return SignExtend<u64, TValue>(value);
|
return SignExtend<u64, TValue>(value);
|
||||||
}
|
}
|
||||||
template<typename TValue>
|
template<typename TValue>
|
||||||
ALWAYS_INLINE constexpr u8 Truncate8(TValue value)
|
ALWAYS_INLINE static constexpr u8 Truncate8(TValue value)
|
||||||
{
|
{
|
||||||
return static_cast<u8>(static_cast<typename std::make_unsigned<decltype(value)>::type>(value));
|
return static_cast<u8>(static_cast<typename std::make_unsigned<decltype(value)>::type>(value));
|
||||||
}
|
}
|
||||||
template<typename TValue>
|
template<typename TValue>
|
||||||
ALWAYS_INLINE constexpr u16 Truncate16(TValue value)
|
ALWAYS_INLINE static constexpr u16 Truncate16(TValue value)
|
||||||
{
|
{
|
||||||
return static_cast<u16>(static_cast<typename std::make_unsigned<decltype(value)>::type>(value));
|
return static_cast<u16>(static_cast<typename std::make_unsigned<decltype(value)>::type>(value));
|
||||||
}
|
}
|
||||||
template<typename TValue>
|
template<typename TValue>
|
||||||
ALWAYS_INLINE constexpr u32 Truncate32(TValue value)
|
ALWAYS_INLINE static constexpr u32 Truncate32(TValue value)
|
||||||
{
|
{
|
||||||
return static_cast<u32>(static_cast<typename std::make_unsigned<decltype(value)>::type>(value));
|
return static_cast<u32>(static_cast<typename std::make_unsigned<decltype(value)>::type>(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
// BCD helpers
|
// BCD helpers
|
||||||
ALWAYS_INLINE constexpr u8 BinaryToBCD(u8 value)
|
ALWAYS_INLINE static constexpr u8 BinaryToBCD(u8 value)
|
||||||
{
|
{
|
||||||
return ((value / 10) << 4) + (value % 10);
|
return ((value / 10) << 4) + (value % 10);
|
||||||
}
|
}
|
||||||
ALWAYS_INLINE constexpr u8 PackedBCDToBinary(u8 value)
|
ALWAYS_INLINE static constexpr u8 PackedBCDToBinary(u8 value)
|
||||||
{
|
{
|
||||||
return ((value >> 4) * 10) + (value % 16);
|
return ((value >> 4) * 10) + (value % 16);
|
||||||
}
|
}
|
||||||
ALWAYS_INLINE constexpr u8 IsValidBCDDigit(u8 digit)
|
ALWAYS_INLINE static constexpr u8 IsValidBCDDigit(u8 digit)
|
||||||
{
|
{
|
||||||
return (digit <= 9);
|
return (digit <= 9);
|
||||||
}
|
}
|
||||||
ALWAYS_INLINE constexpr u8 IsValidPackedBCD(u8 value)
|
ALWAYS_INLINE static constexpr u8 IsValidPackedBCD(u8 value)
|
||||||
{
|
{
|
||||||
return IsValidBCDDigit(value & 0x0F) && IsValidBCDDigit(value >> 4);
|
return IsValidBCDDigit(value & 0x0F) && IsValidBCDDigit(value >> 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Boolean to integer
|
// Boolean to integer
|
||||||
ALWAYS_INLINE constexpr u8 BoolToUInt8(bool value)
|
ALWAYS_INLINE static constexpr u8 BoolToUInt8(bool value)
|
||||||
{
|
{
|
||||||
return static_cast<u8>(value);
|
return static_cast<u8>(value);
|
||||||
}
|
}
|
||||||
ALWAYS_INLINE constexpr u16 BoolToUInt16(bool value)
|
ALWAYS_INLINE static constexpr u16 BoolToUInt16(bool value)
|
||||||
{
|
{
|
||||||
return static_cast<u16>(value);
|
return static_cast<u16>(value);
|
||||||
}
|
}
|
||||||
ALWAYS_INLINE constexpr u32 BoolToUInt32(bool value)
|
ALWAYS_INLINE static constexpr u32 BoolToUInt32(bool value)
|
||||||
{
|
{
|
||||||
return static_cast<u32>(value);
|
return static_cast<u32>(value);
|
||||||
}
|
}
|
||||||
ALWAYS_INLINE constexpr u64 BoolToUInt64(bool value)
|
ALWAYS_INLINE static constexpr u64 BoolToUInt64(bool value)
|
||||||
{
|
{
|
||||||
return static_cast<u64>(value);
|
return static_cast<u64>(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Integer to boolean
|
// Integer to boolean
|
||||||
template<typename TValue>
|
template<typename TValue>
|
||||||
ALWAYS_INLINE constexpr bool ConvertToBool(TValue value)
|
ALWAYS_INLINE static constexpr bool ConvertToBool(TValue value)
|
||||||
{
|
{
|
||||||
return static_cast<bool>(value);
|
return static_cast<bool>(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unsafe integer to boolean
|
// Unsafe integer to boolean
|
||||||
template<typename TValue>
|
template<typename TValue>
|
||||||
ALWAYS_INLINE bool ConvertToBoolUnchecked(TValue value)
|
ALWAYS_INLINE static bool ConvertToBoolUnchecked(TValue value)
|
||||||
{
|
{
|
||||||
// static_assert(sizeof(uint8) == sizeof(bool));
|
// static_assert(sizeof(uint8) == sizeof(bool));
|
||||||
bool ret;
|
bool ret;
|
||||||
|
@ -125,7 +129,7 @@ ALWAYS_INLINE bool ConvertToBoolUnchecked(TValue value)
|
||||||
|
|
||||||
// Generic sign extension
|
// Generic sign extension
|
||||||
template<int NBITS, typename T>
|
template<int NBITS, typename T>
|
||||||
ALWAYS_INLINE constexpr T SignExtendN(T value)
|
ALWAYS_INLINE static constexpr T SignExtendN(T value)
|
||||||
{
|
{
|
||||||
// http://graphics.stanford.edu/~seander/bithacks.html#VariableSignExtend
|
// http://graphics.stanford.edu/~seander/bithacks.html#VariableSignExtend
|
||||||
constexpr int shift = 8 * sizeof(T) - NBITS;
|
constexpr int shift = 8 * sizeof(T) - NBITS;
|
||||||
|
@ -134,7 +138,7 @@ ALWAYS_INLINE constexpr T SignExtendN(T value)
|
||||||
|
|
||||||
/// Returns the number of zero bits before the first set bit, going MSB->LSB.
|
/// Returns the number of zero bits before the first set bit, going MSB->LSB.
|
||||||
template<typename T>
|
template<typename T>
|
||||||
ALWAYS_INLINE unsigned CountLeadingZeros(T value)
|
ALWAYS_INLINE static unsigned CountLeadingZeros(T value)
|
||||||
{
|
{
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
if constexpr (sizeof(value) >= sizeof(u64))
|
if constexpr (sizeof(value) >= sizeof(u64))
|
||||||
|
@ -161,7 +165,7 @@ ALWAYS_INLINE unsigned CountLeadingZeros(T value)
|
||||||
|
|
||||||
/// Returns the number of zero bits before the first set bit, going LSB->MSB.
|
/// Returns the number of zero bits before the first set bit, going LSB->MSB.
|
||||||
template<typename T>
|
template<typename T>
|
||||||
ALWAYS_INLINE unsigned CountTrailingZeros(T value)
|
ALWAYS_INLINE static unsigned CountTrailingZeros(T value)
|
||||||
{
|
{
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
if constexpr (sizeof(value) >= sizeof(u64))
|
if constexpr (sizeof(value) >= sizeof(u64))
|
||||||
|
@ -183,3 +187,37 @@ ALWAYS_INLINE unsigned CountTrailingZeros(T value)
|
||||||
return static_cast<unsigned>(__builtin_ctz(ZeroExtend32(value)));
|
return static_cast<unsigned>(__builtin_ctz(ZeroExtend32(value)));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// C++23-like std::byteswap()
|
||||||
|
template<typename T>
|
||||||
|
ALWAYS_INLINE static T ByteSwap(T value)
|
||||||
|
{
|
||||||
|
if constexpr (std::is_signed_v<T>)
|
||||||
|
{
|
||||||
|
return static_cast<T>(ByteSwap(std::make_unsigned_t<T>(value)));
|
||||||
|
}
|
||||||
|
else if constexpr (std::is_same_v<T, std::uint16_t>)
|
||||||
|
{
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
return _byteswap_ushort(value);
|
||||||
|
#else
|
||||||
|
return __builtin_bswap16(value);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else if constexpr (std::is_same_v<T, std::uint32_t>)
|
||||||
|
{
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
return _byteswap_ulong(value);
|
||||||
|
#else
|
||||||
|
return __builtin_bswap32(value);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else if constexpr (std::is_same_v<T, std::uint64_t>)
|
||||||
|
{
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
return _byteswap_uint64(value);
|
||||||
|
#else
|
||||||
|
return __builtin_bswap64(value);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
#include "cd_image.h"
|
#include "cd_image.h"
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
|
#include "common/bitutils.h"
|
||||||
#include "common/error.h"
|
#include "common/error.h"
|
||||||
#include "common/file_system.h"
|
#include "common/file_system.h"
|
||||||
#include "common/log.h"
|
#include "common/log.h"
|
||||||
|
@ -536,8 +537,8 @@ u16 CDImage::SubChannelQ::ComputeCRC(const Data& data)
|
||||||
for (u32 i = 0; i < 10; i++)
|
for (u32 i = 0; i < 10; i++)
|
||||||
value = crc16_table[(value >> 8) ^ data[i]] ^ (value << 8);
|
value = crc16_table[(value >> 8) ^ data[i]] ^ (value << 8);
|
||||||
|
|
||||||
value = ~value;
|
// Invert and swap
|
||||||
return (value >> 8) | (value << 8);
|
return ByteSwap(static_cast<u16>(~value));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CDImage::SubChannelQ::IsCRCValid() const
|
bool CDImage::SubChannelQ::IsCRCValid() const
|
||||||
|
|
Loading…
Reference in a new issue