Skip to content

Commit

Permalink
Swap.h: add parameter pack templates to automatically cast swap_t<>
Browse files Browse the repository at this point in the history
values to their basic types when passed as parameters to *_LOG calls.
plus some refactors.
  • Loading branch information
aliaspider committed Oct 2, 2020
1 parent dee1fcd commit 297b192
Show file tree
Hide file tree
Showing 14 changed files with 87 additions and 91 deletions.
2 changes: 1 addition & 1 deletion Common/Serialize/SerializeFuncs.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ void Do(PointerWrap &p, tm &t);
// Which also can be a problem, for example struct tm is non-POD on linux, for whatever reason...
#ifdef _MSC_VER
template<typename T, bool isPOD = std::is_pod<T>::value, bool isPointer = std::is_pointer<T>::value>
#elif defined (COMMON_BIG_ENDIAN) // treat swapped types as pod.
#elif defined (__BIG_ENDIAN__) // treat swapped types as pod.
template<typename T, bool isPOD = __is_enum(T) || __is_trivially_copyable(T), bool isPointer = std::is_pointer<T>::value>
#else
template<typename T, bool isPOD = __is_pod(T), bool isPointer = std::is_pointer<T>::value>
Expand Down
139 changes: 67 additions & 72 deletions Common/Swap.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,81 +21,27 @@
#include <cstring>
#include <type_traits>

#include "base/basictypes.h"
#include "Common/CommonTypes.h"
#include "Common/Log.h"

// Android
#if defined(__ANDROID__)
#include <sys/endian.h>

#if _BYTE_ORDER == _LITTLE_ENDIAN && !defined(COMMON_LITTLE_ENDIAN)
#define COMMON_LITTLE_ENDIAN 1
#elif _BYTE_ORDER == _BIG_ENDIAN && !defined(COMMON_BIG_ENDIAN)
#define COMMON_BIG_ENDIAN 1
#endif

// GCC 4.6+
#elif __GNUC__ >= 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)

#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 __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
#if !defined(__BIG_ENDIAN__) && defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
#define __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

#ifdef _MSC_VER
inline unsigned long long bswap64(unsigned long long x) { return _byteswap_uint64(x); }
inline unsigned int bswap32(unsigned int x) { return _byteswap_ulong(x); }
inline unsigned short bswap16(unsigned short x) { return _byteswap_ushort(x); }
#elif defined(__DragonFly__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
#include <sys/endian.h>
#ifdef __OpenBSD__
#define bswap16 swap16
#define bswap32 swap32
#define bswap64 swap64
#endif
#elif defined(__GNUC__)
#define bswap16 __builtin_bswap16
#define bswap32 __builtin_bswap32
#define bswap64 __builtin_bswap64
#else
// TODO: speedup
inline unsigned short bswap16(unsigned short x) { return (x << 8) | (x >> 8); }
inline unsigned int bswap32(unsigned int x) { return (x >> 24) | ((x & 0xFF0000) >> 8) | ((x & 0xFF00) << 8) | (x << 24); }
inline unsigned long long bswap64(unsigned long long x) { return ((unsigned long long)bswap32(x) << 32) | bswap32(x >> 32); }
#if !defined(__BIG_ENDIAN__) && !defined(__LITTLE_ENDIAN__)
#define __LITTLE_ENDIAN__ 1
#endif

template <typename T> struct swap_t {
static_assert(std::is_scalar<T>::value && (sizeof(T) > 1), "swap_t used with an invalid type");

private:
T swapped;

static T swap(T val) {
switch (sizeof(T)) {
case 2: *(u16 *)&val = bswap16(*(u16 *)&val); break;
case 4: *(u32 *)&val = bswap32(*(u32 *)&val); break;
case 8: *(u64 *)&val = bswap64(*(u64 *)&val); break;
case 2: *(u16 *)&val = swap16(*(u16 *)&val); break;
case 4: *(u32 *)&val = swap32(*(u32 *)&val); break;
case 8: *(u64 *)&val = swap64(*(u64 *)&val); break;
default: break;
}
return val;
Expand Down Expand Up @@ -133,9 +79,12 @@ template <typename T> struct swap_t {
}

operator T() const { return swap(swapped); }

private:
T swapped;
};

#if COMMON_LITTLE_ENDIAN
#ifdef __LITTLE_ENDIAN__
template <typename T> using LEndian = T;
template <typename T> using BEndian = swap_t<T>;
#else
Expand Down Expand Up @@ -165,20 +114,66 @@ typedef BEndian<s64> s64_be;
typedef BEndian<float> float_be;
typedef BEndian<double> double_be;

template <typename T> static inline void endian_convert(swap_t<T> *dst, const T *src, size_t count) {
template <typename T>
static inline void ToLEndian(BEndian<T> *ptr, size_t count) {
for (int i = 0; i < count; i++) {
dst[i] = src[i];
((LEndian<T>*)ptr)[i] = ptr[i];
}
}

template <typename T> static inline void endian_convert(T *dst, const swap_t<T> *src, size_t count) {
template <typename T>
static inline void ToLEndian(LEndian<T> *ptr, size_t count) {
return;
}

template <typename T>
static inline void ToBEndian(LEndian<T> *ptr, size_t count) {
for (int i = 0; i < count; i++) {
dst[i] = src[i];
((BEndian<T>*)ptr)[i] = ptr[i];
}
}

template <typename T> static inline void endian_convert(T *dst, const T *src, size_t count) {
if (src == dst)
return;
memcpy(dst, src, count * sizeof(T));
template <typename T>
static inline void ToBEndian(BEndian<T> *ptr, size_t count) {
return;
}

template <typename T, typename... Targs>
static inline void GenericLog(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type, const char *file, int line, const char *fmt, swap_t<T> v, Targs... args) {
GenericLog(level, type, file, line, fmt, (T)v, args...);
}

template <typename T0, typename T, typename... Targs>
static inline void GenericLog(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type, const char *file, int line, const char *fmt, T0 v0, swap_t<T> v, Targs... args) {
GenericLog(level, type, file, line, fmt, v0, (T)v, args...);
}

template <typename T0, typename T1, typename T, typename... Targs>
static inline void GenericLog(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type, const char *file, int line, const char *fmt, T0 v0, T1 v1, swap_t<T> v, Targs... args) {
GenericLog(level, type, file, line, fmt, v0, v1, (T)v, args...);
}

template <typename T0, typename T1, typename T2, typename T, typename... Targs>
static inline void GenericLog(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type, const char *file, int line, const char *fmt, T0 v0, T1 v1, T2 v2, swap_t<T> v, Targs... args) {
GenericLog(level, type, file, line, fmt, v0, v1, v2, (T)v, args...);
}

template <typename T0, typename T1, typename T2, typename T3, typename T, typename... Targs>
static inline void GenericLog(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type, const char *file, int line, const char *fmt, T0 v0, T1 v1, T2 v2, T3 v3, swap_t<T> v, Targs... args) {
GenericLog(level, type, file, line, fmt, v0, v1, v2, v3, (T)v, args...);
}

template <typename T0, typename T1, typename T2, typename T3, typename T4, typename T, typename... Targs>
static inline void GenericLog(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type, const char *file, int line, const char *fmt, T0 v0, T1 v1, T2 v2, T3 v3, T4 v4, swap_t<T> v, Targs... args) {
GenericLog(level, type, file, line, fmt, v0, v1, v2, v3, v4, (T)v, args...);
}

template <typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T, typename... Targs>
static inline void GenericLog(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type, const char *file, int line, const char *fmt, T0 v0, T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, swap_t<T> v, Targs... args) {
GenericLog(level, type, file, line, fmt, v0, v1, v2, v3, v4, v5, (T)v, args...);
}

template <typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T, typename... Targs>
static inline void GenericLog(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type, const char *file, int line, const char *fmt, T0 v0, T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, swap_t<T> v, Targs... args) {
GenericLog(level, type, file, line, fmt, v0, v1, v2, v3, v4, v5, v6, (T)v, args...);
}
2 changes: 1 addition & 1 deletion Core/FileSystems/BlockDevices.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ CISOFileBlockDevice::CISOFileBlockDevice(FileLoader *fileLoader)
const u32 indexSize = numFrames + 1;
const size_t headerEnd = hdr.ver > 1 ? (size_t)hdr.header_size : sizeof(hdr);

#if COMMON_LITTLE_ENDIAN
#if __LITTLE_ENDIAN__
index = new u32[indexSize];
if (fileLoader->ReadAt(headerEnd, sizeof(u32), indexSize, index) != indexSize) {
NotifyReadError();
Expand Down
2 changes: 1 addition & 1 deletion Core/FileSystems/ISOFileSystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ struct DirectoryEntry {
u8 identifierLength; //identifier comes right after
u8 firstIdChar;

#if COMMON_LITTLE_ENDIAN
#if __LITTLE_ENDIAN__
u32 firstDataSector() const
{
return firstDataSectorLE;
Expand Down
2 changes: 1 addition & 1 deletion Core/HLE/ReplaceTables.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -406,7 +406,7 @@ static int Replace_fabsf() {
}

static int Replace_vmmul_q_transp() {
#ifdef COMMON_BIG_ENDIAN
#ifdef __BIG_ENDIAN__
Crash(); // TODO
#endif
float *out = (float *)Memory::GetPointer(PARAM(0));
Expand Down
2 changes: 1 addition & 1 deletion Core/HLE/proAdhoc.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@

#ifdef _MSC_VER
#define PACK // on MSVC we use #pragma pack() instead so let's kill this.
#elif defined(COMMON_BIG_ENDIAN)
#elif defined(__BIG_ENDIAN__)
// packed cannot be used with non-POD *_le types.
// TODO: find a real solution for the couple of structs that actually need this
#define PACK
Expand Down
2 changes: 1 addition & 1 deletion Core/HLE/sceAtrac.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1227,7 +1227,7 @@ u32 _AtracDecodeData(int atracID, u8 *outbuf, u32 outbufPtr, u32 *SamplesNum, u3
if (avret < 0) {
ERROR_LOG(ME, "swr_convert: Error while converting %d", avret);
} else {
endian_convert((s16_le*)out, (s16*)out, avret * atrac->outputChannels_);
ToLEndian((s16*)out, avret * atrac->outputChannels_);
}
}
#endif // USE_FFMPEG
Expand Down
2 changes: 1 addition & 1 deletion Core/HLE/sceAudiocodec.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ static int sceAudiocodecDecode(u32 ctxPtr, int codec) {
// Decode audio
u8* outbuf = Memory::GetPointer(ctx->outDataPtr);
decoder->Decode(Memory::GetPointer(ctx->inDataPtr), ctx->inDataSize, outbuf, &outbytes);
endian_convert((s16_le*)outbuf, (s16*)outbuf, outbytes / 2);
ToLEndian((s16*)outbuf, outbytes / 2);
}
DEBUG_LOG(ME, "sceAudiocodecDec(%08x, %i (%s))", ctxPtr, codec, GetCodecName(codec));
return 0;
Expand Down
4 changes: 2 additions & 2 deletions Core/HLE/sceMp3.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -367,7 +367,7 @@ static int FindMp3Header(AuCtx *ctx, int &header, int end) {
for (int offset = 0; offset < end; ++offset) {
// If we hit valid sync bits, then we've found a header.
if (ptr[offset] == 0xFF && (ptr[offset + 1] & 0xC0) == 0xC0) {
header = bswap32(Memory::Read_U32(addr + offset));
header = swap32(Memory::Read_U32(addr + offset));
return offset;
}
}
Expand Down Expand Up @@ -685,7 +685,7 @@ static u32 sceMp3LowLevelDecode(u32 mp3, u32 sourceAddr, u32 sourceBytesConsumed

int outpcmbytes = 0;
ctx->decoder->Decode((void*)inbuff, 4096, outbuff, &outpcmbytes);
endian_convert((s16_le*)outbuff, (s16*)outbuff, outpcmbytes / 2);
ToLEndian((s16*)outbuff, outpcmbytes / 2);

Memory::Write_U32(ctx->decoder->GetSourcePos(), sourceBytesConsumedAddr);
Memory::Write_U32(outpcmbytes, sampleBytesAddr);
Expand Down
3 changes: 2 additions & 1 deletion Core/HLE/sceNetAdhoc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4646,7 +4646,8 @@ void __NetMatchingCallbacks() //(int matchingId)
if (params != matchingEvents.end())
{
u32 args[6];
endian_convert(args, (u32_le*)&(*params), 6);
for (int i = 0; i < 6; i++)
args[i] = params->data[i];
//auto context = findMatchingContext(args[0]);

if (actionAfterMatchingMipsCall < 0) {
Expand Down
4 changes: 2 additions & 2 deletions Core/HLE/scePsmf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -889,7 +889,7 @@ static u32 scePsmfQueryStreamOffset(u32 bufferAddr, u32 offsetAddr)
{
WARN_LOG(ME, "scePsmfQueryStreamOffset(%08x, %08x)", bufferAddr, offsetAddr);
if (Memory::IsValidAddress(offsetAddr)) {
Memory::Write_U32(bswap32(Memory::Read_U32(bufferAddr + PSMF_STREAM_OFFSET_OFFSET)), offsetAddr);
Memory::Write_U32(swap32(Memory::Read_U32(bufferAddr + PSMF_STREAM_OFFSET_OFFSET)), offsetAddr);
}
return 0;
}
Expand All @@ -898,7 +898,7 @@ static u32 scePsmfQueryStreamSize(u32 bufferAddr, u32 sizeAddr)
{
WARN_LOG(ME, "scePsmfQueryStreamSize(%08x, %08x)", bufferAddr, sizeAddr);
if (Memory::IsValidAddress(sizeAddr)) {
Memory::Write_U32(bswap32(Memory::Read_U32(bufferAddr + PSMF_STREAM_SIZE_OFFSET)), sizeAddr);
Memory::Write_U32(swap32(Memory::Read_U32(bufferAddr + PSMF_STREAM_SIZE_OFFSET)), sizeAddr);
}
return 0;
}
Expand Down
2 changes: 1 addition & 1 deletion Core/HW/SimpleAudioDec.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -340,7 +340,7 @@ u32 AuCtx::AuDecode(u32 pcmAddr) {
// FFmpeg doesn't seem to search for a sync for us, so let's do that.
int nextSync = (int)FindNextMp3Sync();
decoder->Decode(&sourcebuff[nextSync], (int)sourcebuff.size() - nextSync, outbuf, &outpcmbufsize);
endian_convert((u16_le*)outbuf, (u16*)outbuf, outpcmbufsize / 2);
ToLEndian((u16*)outbuf, outpcmbufsize / 2);

if (outpcmbufsize == 0) {
// Nothing was output, hopefully we're at the end of the stream.
Expand Down
4 changes: 2 additions & 2 deletions Core/MIPS/MIPSIntVFPU.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,7 @@ namespace MIPSInt
{
_dbg_assert_msg_( 0, "Misaligned lv.q at %08x (pc = %08x)", addr, PC);
}
#ifndef COMMON_BIG_ENDIAN
#ifndef __BIG_ENDIAN__
WriteVector((const float*)Memory::GetPointer(addr), V_Quad, vt);
#else
float lvqd[4];
Expand Down Expand Up @@ -290,7 +290,7 @@ namespace MIPSInt
{
_dbg_assert_msg_( 0, "Misaligned sv.q at %08x (pc = %08x)", addr, PC);
}
#ifndef COMMON_BIG_ENDIAN
#ifndef __BIG_ENDIAN__
ReadVector(reinterpret_cast<float *>(Memory::GetPointer(addr)), V_Quad, vt);
#else
float svqd[4];
Expand Down
8 changes: 4 additions & 4 deletions Core/Screenshot.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ static bool ConvertPixelTo8888RGBA(GPUDebugBufferFormat fmt, u8 &r, u8 &g, u8 &b
case GPU_DBG_FORMAT_565:
src = buf16[offset];
if (rev) {
src = bswap16(src);
src = swap16(src);
}
a = 255;
r = Convert5To8((src >> 0) & 0x1F);
Expand All @@ -143,7 +143,7 @@ static bool ConvertPixelTo8888RGBA(GPUDebugBufferFormat fmt, u8 &r, u8 &g, u8 &b
case GPU_DBG_FORMAT_5551:
src = buf16[offset];
if (rev) {
src = bswap16(src);
src = swap16(src);
}
a = (src >> 15) ? 255 : 0;
r = Convert5To8((src >> 0) & 0x1F);
Expand All @@ -153,7 +153,7 @@ static bool ConvertPixelTo8888RGBA(GPUDebugBufferFormat fmt, u8 &r, u8 &g, u8 &b
case GPU_DBG_FORMAT_4444:
src = buf16[offset];
if (rev) {
src = bswap16(src);
src = swap16(src);
}
a = Convert4To8((src >> 12) & 0xF);
r = Convert4To8((src >> 0) & 0xF);
Expand All @@ -163,7 +163,7 @@ static bool ConvertPixelTo8888RGBA(GPUDebugBufferFormat fmt, u8 &r, u8 &g, u8 &b
case GPU_DBG_FORMAT_8888:
src = buf32[offset];
if (rev) {
src = bswap32(src);
src = swap32(src);
}
a = (src >> 24) & 0xFF;
r = (src >> 0) & 0xFF;
Expand Down

0 comments on commit 297b192

Please sign in to comment.