OpenTTD-patches/src/macros.h

199 lines
4.8 KiB
C++

/* $Id$ */
/** @file macros.h */
#ifndef MACROS_H
#define MACROS_H
/* Fetch n bits starting at bit s from x */
#define GB(x, s, n) (((x) >> (s)) & ((1U << (n)) - 1))
/* Set n bits starting at bit s in x to d */
#define SB(x, s, n, d) ((x) = ((x) & ~(((1U << (n)) - 1) << (s))) | ((d) << (s)))
/* Add i to the n bits starting at bit s in x */
#define AB(x, s, n, i) ((x) = ((x) & ~(((1U << (n)) - 1) << (s))) | (((x) + ((i) << (s))) & (((1U << (n)) - 1) << (s))))
#ifdef min
#undef min
#endif
#ifdef max
#undef max
#endif
template <typename T>
static inline T max(T a, T b)
{
return a >= b ? a : b;
}
template <typename T>
static inline T min(T a, T b)
{
return a < b ? a : b;
}
static inline int min(int a, int b) { if (a <= b) return a; return b; }
static inline uint minu(uint a, uint b) { if (a <= b) return a; return b; }
static inline int clamp(int a, int min, int max)
{
if (a <= min) return min;
if (a >= max) return max;
return a;
}
static inline uint clampu(uint a, uint min, uint max)
{
if (a <= min) return min;
if (a >= max) return max;
return a;
}
/* Gracefully reduce a signed 64-bit int to signed 32-bit -- no bogusly truncating the sign bit */
static inline int32 ClampToI32(int64 a)
{
if (a <= (int32)0x80000000) return 0x80000000;
if (a >= (int32)0x7FFFFFFF) return 0x7FFFFFFF;
return (int32)a;
}
static inline int32 BIGMULSS(int32 a, int32 b, int shift)
{
return (int32)((int64)a * (int64)b >> shift);
}
static inline uint32 BIGMULUS(uint32 a, uint32 b, int shift)
{
return (uint32)((uint64)a * (uint64)b >> shift);
}
/* OPT: optimized into an unsigned comparison */
//#define IS_INSIDE_1D(x, base, size) ((x) >= (base) && (x) < (base) + (size))
#define IS_INSIDE_1D(x, base, size) ( (uint)((x) - (base)) < ((uint)(size)) )
template<typename T> static inline bool HASBIT(T x, int y)
{
return (x & ((T)1 << y)) != 0;
}
template<typename T> static inline T SETBIT(T& x, int y)
{
return x |= (T)1 << y;
}
template<typename T> static inline T CLRBIT(T& x, int y)
{
return x &= ~((T)1 << y);
}
template<typename T> static inline T TOGGLEBIT(T& x, int y)
{
return x ^= (T)1 << y;
}
/* checking more bits. Maybe unneccessary, but easy to use */
#define HASBITS(x, y) ((x) & (y))
#define SETBITS(x, y) ((x) |= (y))
#define CLRBITS(x, y) ((x) &= ~(y))
#define GENERAL_SPRITE_COLOR(color) ((color) + PALETTE_RECOLOR_START)
#define PLAYER_SPRITE_COLOR(owner) (GENERAL_SPRITE_COLOR(_player_colors[owner]))
extern const byte _ffb_64[128];
/* Returns the position of the first bit that is not zero, counted from the
* left. Ie, 10110100 returns 2, 00000001 returns 0, etc. When x == 0 returns
* 0.
*/
#define FIND_FIRST_BIT(x) _ffb_64[(x)]
/* Returns x with the first bit that is not zero, counted from the left, set
* to zero. So, 10110100 returns 10110000, 00000001 returns 00000000, etc.
*/
#define KILL_FIRST_BIT(x) _ffb_64[(x) + 64]
static inline int FindFirstBit2x64(int value)
{
/*
int i = 0;
if ( (byte) value == 0) {
i += 8;
value >>= 8;
}
return i + FIND_FIRST_BIT(value & 0x3F);
Faster ( or at least cleaner ) implementation below?
*/
if (GB(value, 0, 8) == 0) {
return FIND_FIRST_BIT(GB(value, 8, 6)) + 8;
} else {
return FIND_FIRST_BIT(GB(value, 0, 6));
}
}
static inline int KillFirstBit2x64(int value)
{
if (GB(value, 0, 8) == 0) {
return KILL_FIRST_BIT(GB(value, 8, 6)) << 8;
} else {
return value & (KILL_FIRST_BIT(GB(value, 0, 6)) | 0x3F00);
}
}
/** returns true if value a has only one bit set to 1 */
#define HAS_SINGLE_BIT(a) ( ((a) & ((a) - 1)) == 0)
/* [min,max), strictly less than */
#define IS_BYTE_INSIDE(a, min, max) ((byte)((a) - (min)) < (byte)((max) - (min)))
#define IS_INT_INSIDE(a, min, max) ((uint)((a) - (min)) < (uint)((max) - (min)))
#define CHANCE16(a, b) ((uint16)Random() <= (uint16)((65536 * (a)) / (b)))
#define CHANCE16R(a, b, r) ((uint16)(r = Random()) <= (uint16)((65536 * (a)) / (b)))
#define CHANCE16I(a, b, v) ((uint16)(v) <= (uint16)((65536 * (a)) / (b)))
#define for_each_bit(_i, _b) \
for (_i = 0; _b != 0; _i++, _b >>= 1) \
if (_b & 1)
#define abs myabs
static inline uint16 ReadLE16Aligned(const void* x)
{
return FROM_LE16(*(const uint16*)x);
}
static inline uint16 ReadLE16Unaligned(const void* x)
{
#ifdef OTTD_ALIGNMENT
return ((const byte*)x)[0] | ((const byte*)x)[1] << 8;
#else
return FROM_LE16(*(const uint16*)x);
#endif
}
/**
* ROtate x Left/Right by n (must be >= 0)
* @note Assumes a byte has 8 bits
*/
#define ROL(x, n) ((x) << (n) | (x) >> (sizeof(x) * 8 - (n)))
#define ROR(x, n) ((x) >> (n) | (x) << (sizeof(x) * 8 - (n)))
/**
* Return the smallest multiple of n equal or greater than x
* @note n must be a power of 2
*/
#define ALIGN(x, n) (((x) + (n) - 1) & ~((n) - 1))
/** return the largest value that can be entered in a variable.
*/
#define MAX_UVALUE(type) ((type)~(type)0)
#endif /* MACROS_H */