summaryrefslogtreecommitdiff
path: root/macros.h
blob: 5e0ff540c432dc68e2e102b7bce5817f6bc393ee (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
#ifndef MACROS_H
#define MACROS_H

#define MAX_INT 0x7FFFFFFF

#ifdef min
#undef min
#endif

#ifdef max
#undef max
#endif

static INLINE int min(int a, int b) { if (a <= b) return a; return b; }
static INLINE int max(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 uint maxu(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 int clamp2(int a, int min, int max) { if (a <= min) a=min; if (a >= max) a=max; return a; }
static INLINE bool int32_add_overflow(int32 a, int32 b) { return (int32)(a^b)>=0 && (int32)(a^(a+b))<0; }
static INLINE bool int32_sub_overflow(int32 a, int32 b) { return (int32)(a^b)<0 && (int32)(a^(a-b))<0; }

static INLINE bool str_eq(const byte *a, const byte *b)
{
	int i=0;
	while (a[i] == b[i]) {
		if (a[i] == 0)
			return true;
		i++;
	}
	return false;
}

// Will crash if strings are equal
static INLINE bool str_is_below(byte *a, byte *b) {
	while (*a <= *b) {
		if (*a < *b) return true;
		a++;
		b++;
	}
	return false;
}


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));
}

static INLINE int64 BIGMULS(int32 a, int32 b) {
	return (int32)(((int64)(a) * (int64)(b)));
}

/* 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)) )

#define TILE_X_BITS 8
#define TILE_Y_BITS 8
#define LANDSCAPE_SIZE_FACTOR 1

#define TILE_FROM_XY(x,y) (int)((((y) >> 4) << TILE_X_BITS) + ((x) >> 4))
#define TILE_XY(x,y) (int)(((y) << TILE_X_BITS) + (x))

#define IS_TILETYPE(_t_, _s_) (_map_type_and_height[(_t_)] >> 4 == (_s_))
#define GET_TILETYPE(_t_) (_map_type_and_height[(_t_)] >> 4)
#define GET_TILEHEIGHT(_t_) ((_map_type_and_height[_t_] & 0xF) * 8)

enum {
	CORRECT_Z_BITS = 1 << 1 | 1 << 2 | 1 << 3 | 1 << 4 | 1 << 5 | 1 << 6 | 1 << 7
};
#define CORRECT_Z(tileh) (CORRECT_Z_BITS & (1 << tileh))

#define TILES_X (1 << TILE_X_BITS)
#define TILES_Y (1 << TILE_Y_BITS)

#define TILE_X_MAX (TILES_X-1)
#define TILE_Y_MAX (TILES_Y-1)

#define TILE_ASSERT(x) assert( TILE_MASK(x) == (x) );

extern uint SafeTileAdd(uint x, int add, const char *exp, const char *file, int line);

#if !defined(_DEBUG) || TILE_X_BITS != 8
#	define TILE_ADD(x,y) ((x)+(y))
#else
#	if defined(__GNUC__)
#		define TILE_ADD(x,y) (SafeTileAdd((x),(y), "??",  __FILE__, __LINE__))
#	else
#		define TILE_ADD(x,y) (SafeTileAdd((x),(y), #x ## ", " ## #y,  __FILE__, __LINE__))
#	endif
#endif

#define TILE_ADDXY(tile, x, y) TILE_ADD(tile, TILE_XY(x,y))

#if TILE_X_BITS == 8
#define GET_TILE_X(t) (uint)((byte)(t))
#define GET_TILE_Y(t) (uint)((t) >> 8)
#define TILE_MASK(x) ((uint16)(x))
#else
#define GET_TILE_X(t) (uint)((t) & ((1 << TILE_X_BITS)-1))
#define GET_TILE_Y(t) (uint)((t) >> TILE_X_BITS)
#define TILE_MASK(x) (int)((x) & ((1 << (TILE_X_BITS + TILE_Y_BITS))-1))
#endif

//#define REMADP_COORDS(x,y,z) { int t = x; x = (y-t)*2; y+=t-z; }

#define PACK_POINT(x,y) ((x) | ((y) << 16))
#define UNPACK_POINT_X(p) ((uint16)(p))
#define UNPACK_POINT_Y(p) ((uint16)(p>>16))

#define PACK_PPOINT(p) PACK_POINT((p).x, (p).y)

#define HASBIT(x,y) ((x) & (1 << (y)))
#define SETBIT(x,y) ((x) |= (1 << (y)))
#define CLRBIT(x,y) ((x) &= ~(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 PLAYER_SPRITE_COLOR(owner) ((_player_colors[owner] << 16) + 0x3070000)
#define SPRITE_PALETTE(x) ((x) + 0x8000)

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);
}


#if TILE_X_BITS + TILE_Y_BITS <= 16
	typedef uint16 TileIndex;
	typedef int16 TileIndexDiff;
#else
	typedef uint32 TileIndex;
	typedef int32 TileIndexDiff;
#endif

/* [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 BEGIN_TILE_LOOP(var,w,h,tile)		\
		{int h_cur = h;									\
		uint var = tile;									\
		do {														\
			int w_cur = w;								\
			do {

#define END_TILE_LOOP(var,w,h,tile)			\
			} while (++var, --w_cur != 0);						\
		} while (var += TILE_XY(0,1) - (w), --h_cur != 0);}


#define for_each_bit(_i,_b)										\
	for(_i=0; _b!=0; _i++,_b>>=1)								\
		if (_b&1)

#define assert_array(i,j) assert(i < lengthof(j))

#define abs myabs


static INLINE int intxchg_(int *a, int b) { int t = *a; *a = b; return t; }
#define intxchg(a,b) intxchg_(&(a), (b))
#define intswap(a,b) ((b) = intxchg_(&(a), (b)))

static INLINE int myabs(int a) { if (a<0) a = -a; return a; }

static INLINE void swap_byte(byte *a, byte *b) { byte t = *a; *a = *b; *b = t; }
static INLINE void swap_uint16(uint16 *a, uint16 *b) { uint16 t = *a; *a = *b; *b = t; }
static INLINE void swap_int16(int16 *a, int16 *b) { int16 t = *a; *a = *b; *b = t; }
static INLINE void swap_tile(TileIndex *a, TileIndex *b) { TileIndex t = *a; *a = *b; *b = t; }



#if defined(TTD_LITTLE_ENDIAN)
#	define READ_LE_UINT16(b) (*(const uint16*)(b))
#	define ADD_WORD(x) (x)&0xFF, ((x) >> 8)&0xFF
#	define ADD_DWORD(x) (x)&0xFF, ((x) >> 8)&0xFF, ((x) >> 16)&0xFF, ((x) >> 24)&0xFF
#elif defined(TTD_BIG_ENDIAN)
	static INLINE uint16 READ_LE_UINT16(const void *b) {
		return ((const byte*)b)[0] + (((const byte*)b)[1] << 8);
	}
#	define ADD_WORD(x) ((x) >> 8)&0xFF, (x)&0xFF
#	define ADD_DWORD(x) ((x) >> 24)&0xFF, ((x) >> 16)&0xFF, ((x) >> 8)&0xFF,  (x)&0xFF
#endif

static INLINE void WRITE_LE_UINT16(void *b, uint16 x) {
	((byte*)b)[0] = (byte)x;
	((byte*)b)[1] = (byte)(x >> 8);
}

#define MAX_DETOUR 6

#endif /* MACROS_H */