/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
*/
//=============================================================================
//
// Memory utils and algorithms
//
//=============================================================================
#ifndef AGS_SHARED_UTIL_MEMORY_H
#define AGS_SHARED_UTIL_MEMORY_H
//include
#include "ags/shared/util/bbop.h"
#include "ags/shared/util/math.h"
namespace AGS3 {
#if defined (AGS_STRICT_ALIGNMENT) || defined (TEST_STRICT_ALIGNMENT)
#define MEMORY_STRICT_ALIGNMENT
#endif
namespace AGS {
namespace Shared {
namespace Memory {
//-------------------------------------------------------------------------
// Converts pointer to 32-bit integer value and vice-versa.
// Only for use in special cases for compatibility with 32-bit plugin API.
// Dangerous on 64-bit systems.
//-------------------------------------------------------------------------
template
inline int32_t PtrToInt32(T *ptr) {
return static_cast(reinterpret_cast(ptr));
}
template
inline T *Int32ToPtr(int32_t value) {
return reinterpret_cast(static_cast(value));
}
//-------------------------------------------------------------------------
// Functions for reading and writing basic types from/to the memory.
// Implement safety workaround for CPUs with alignment restrictions
// (e.g. MIPS).
//-------------------------------------------------------------------------
inline int16_t ReadInt16(const void *ptr) {
#if defined (MEMORY_STRICT_ALIGNMENT)
const uint8_t *b = (const uint8_t *)ptr;
#if defined (BITBYTE_BIG_ENDIAN)
return (b[0] << 8) | b[1];
#else
return (b[1] << 8) | b[0];
#endif
#else
return *(const int16_t *)ptr;
#endif
}
inline int32_t ReadInt32(const void *ptr) {
#if defined (MEMORY_STRICT_ALIGNMENT)
const uint8_t *b = (const uint8_t *)ptr;
#if defined (BITBYTE_BIG_ENDIAN)
return (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | b[3];
#else
return (b[3] << 24) | (b[2] << 16) | (b[1] << 8) | b[0];
#endif
#else
return *(const int32_t *)ptr;
#endif
}
inline int64_t ReadInt64(const void *ptr) {
#if defined (MEMORY_STRICT_ALIGNMENT)
const uint8_t *b = (const uint8_t *)ptr;
#if defined (BITBYTE_BIG_ENDIAN)
return ((uint64_t)b[0] << 56) | ((uint64_t)b[1] << 48) | ((uint64_t)b[2] << 40) | ((uint64_t)b[3] << 32) |
(b[4] << 24) | (b[5] << 16) | (b[6] << 8) | b[7];
#else
return ((uint64_t)b[7] << 56) | ((uint64_t)b[6] << 48) | ((uint64_t)b[5] << 40) | ((uint64_t)b[4] << 32) |
(b[3] << 24) | (b[2] << 16) | (b[1] << 8) | b[0];
#endif
#else
return *(const int64_t *)ptr;
#endif
}
inline void WriteInt16(void *ptr, int16_t value) {
#if defined (MEMORY_STRICT_ALIGNMENT)
uint8_t *b = (uint8_t *)ptr;
#if defined (BITBYTE_BIG_ENDIAN)
b[0] = (uint8_t)(value >> 8);
b[1] = (uint8_t)(value);
#else
b[1] = (uint8_t)(value >> 8);
b[0] = (uint8_t)(value);
#endif
#else
*(int16_t *)ptr = value;
#endif
}
inline void WriteInt32(void *ptr, int32_t value) {
#if defined (MEMORY_STRICT_ALIGNMENT)
uint8_t *b = (uint8_t *)ptr;
#if defined (BITBYTE_BIG_ENDIAN)
b[0] = (uint8_t)(value >> 24);
b[1] = (uint8_t)(value >> 16);
b[2] = (uint8_t)(value >> 8);
b[3] = (uint8_t)(value);
#else
b[3] = (uint8_t)(value >> 24);
b[2] = (uint8_t)(value >> 16);
b[1] = (uint8_t)(value >> 8);
b[0] = (uint8_t)(value);
#endif
#else
*(int32_t *)ptr = value;
#endif
}
inline void WriteInt64(void *ptr, int64_t value) {
#if defined (MEMORY_STRICT_ALIGNMENT)
uint8_t *b = (uint8_t *)ptr;
#if defined (BITBYTE_BIG_ENDIAN)
b[0] = (uint8_t)(value >> 56);
b[1] = (uint8_t)(value >> 48);
b[2] = (uint8_t)(value >> 40);
b[3] = (uint8_t)(value >> 32);
b[4] = (uint8_t)(value >> 24);
b[5] = (uint8_t)(value >> 16);
b[6] = (uint8_t)(value >> 8);
b[7] = (uint8_t)(value);
#else
b[7] = (uint8_t)(value >> 56);
b[6] = (uint8_t)(value >> 48);
b[5] = (uint8_t)(value >> 40);
b[4] = (uint8_t)(value >> 32);
b[3] = (uint8_t)(value >> 24);
b[2] = (uint8_t)(value >> 16);
b[1] = (uint8_t)(value >> 8);
b[0] = (uint8_t)(value);
#endif
#else
*(int64_t *)ptr = value;
#endif
}
//-------------------------------------------------------------------------
// Helpers for reading and writing from memory with respect for endianess.
//-------------------------------------------------------------------------
inline int16_t ReadInt16LE(const void *ptr) {
return BBOp::Int16FromLE(ReadInt16(ptr));
}
inline int32_t ReadInt32LE(const void *ptr) {
return BBOp::Int32FromLE(ReadInt32(ptr));
}
inline int64_t ReadInt64LE(const void *ptr) {
return BBOp::Int64FromLE(ReadInt64(ptr));
}
inline void WriteInt16LE(void *ptr, int16_t value) {
WriteInt16(ptr, BBOp::Int16FromLE(value));
}
inline void WriteInt32LE(void *ptr, int32_t value) {
WriteInt32(ptr, BBOp::Int32FromLE(value));
}
inline void WriteInt64LE(void *ptr, int64_t value) {
WriteInt64(ptr, BBOp::Int64FromLE(value));
}
inline int16_t ReadInt16BE(const void *ptr) {
return BBOp::Int16FromBE(ReadInt16(ptr));
}
inline int32_t ReadInt32BE(const void *ptr) {
return BBOp::Int32FromBE(ReadInt32(ptr));
}
inline int64_t ReadInt64BE(const void *ptr) {
return BBOp::Int64FromBE(ReadInt64(ptr));
}
inline void WriteInt16BE(void *ptr, int16_t value) {
WriteInt16(ptr, BBOp::Int16FromBE(value));
}
inline void WriteInt32BE(void *ptr, int32_t value) {
WriteInt32(ptr, BBOp::Int32FromBE(value));
}
inline void WriteInt64BE(void *ptr, int64_t value) {
WriteInt64(ptr, BBOp::Int64FromBE(value));
}
//-------------------------------------------------------------------------
// Memory data manipulation
//-------------------------------------------------------------------------
// Copies block of 2d data from source into destination.
inline void BlockCopy(uint8_t *dst, const size_t dst_pitch, const size_t dst_offset,
const uint8_t *src, const size_t src_pitch, const size_t src_offset,
const size_t height) {
for (size_t y = 0; y < height; ++y, src += src_pitch, dst += dst_pitch)
memcpy(dst + dst_offset, src + src_offset, MIN(dst_pitch - dst_offset, src_pitch - src_offset));
}
} // namespace Memory
} // namespace Shared
} // namespace AGS
} // namespace AGS3
#endif