MuckyFoot-UrbanChaos/MuckyBasic/Always.h
2017-05-20 11:14:17 +10:00

415 lines
6.7 KiB
C

#ifndef _ALWAYS_
#define _ALWAYS_
//
// Turn off the warning about [] arrays at the end of structures.
//
#pragma warning( disable : 4200 )
typedef signed long SLONG;
typedef unsigned long ULONG;
typedef signed short int SWORD;
typedef unsigned short int UWORD;
typedef signed char SBYTE;
typedef unsigned char UBYTE;
typedef char CBYTE;
//
// Standard libraries most often used.
//
#include <assert.h>
#include <ctype.h>
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
//
// Constants.
//
#define PI (3.14159265F)
#define ROOT2 (1.41421356F)
#define INFINITY (0x7fffffff)
//
// Useful defines.
//
#define MIN(mnx,mny) (((mnx) < (mny)) ? (mnx) : (mny))
#define MAX(mnx,mny) (((mnx) > (mny)) ? (mnx) : (mny))
#define MAX3(mnx,mny,mnz) (((mnx) > (mny)) ? MAX(mnx,mnz) : MAX(mny,mnz))
#define MIN3(mnx,mny,mnz) (((mnx) < (mny)) ? MIN(mnx,mnz) : MIN(mny,mnz))
#define MIN4(a,b,c,d) (MIN(MIN(a,b), MIN(c,d)))
#define MAX4(a,b,c,d) (MAX(MAX(a,b), MAX(c,d)))
#define SWAP(x,y) {SLONG SWAP_spare; SWAP_spare = x; x = y; y = SWAP_spare;}
#define SWAP_UB(x,y) {UBYTE SWAP_spare; SWAP_spare = x; x = y; y = SWAP_spare;}
#define SWAP_UW(x,y) {UWORD SWAP_spare; SWAP_spare = x; x = y; y = SWAP_spare;}
#define SWAP_FL(x,y) {float SWAP_spare; SWAP_spare = x; x = y; y = SWAP_spare;}
#define SWAP_DB(x,y) {double SWAP_spare; SWAP_spare = x; x = y; y = SWAP_spare;}
#define SWAP_HF(x,y) {Pointhf SWAP_spare; SWAP_spare = x; x = y; y = SWAP_spare;}
#define SWAP_P3(x,y) {Point3d SWAP_spare; SWAP_spare = x; x = y; y = SWAP_spare;}
#define SWAP_VD(x,y) {void *SWAP_spare; SWAP_spare = x; x = y; y = SWAP_spare;}
#define SWAP_UWP(x,y) {UWORD *SWAP_spare; SWAP_spare = x; x = y; y = SWAP_spare;}
#define SWAP_UBP(x,y) {UBYTE *SWAP_spare; SWAP_spare = x; x = y; y = SWAP_spare;}
#define WITHIN(x,a,b) ((x) >= (a) && (x) <= (b))
#define SATURATE(x,a,b) {if ((x) < (a)) (x) = (a); if ((x) > (b)) (x) = (b);}
#define SIGN(x) (((x)) ? (((x) > 0) ? 1 : -1) : 0)
#define QLEN(x,y) (((x) > (y)) ? (x) + ((y) >> 1) : (y) + ((x) >> 1))
#define XOR(a,b) ((!(a) && (b)) || ((a) && !(b)))
#define SQRT16(x) ((sqrt((double) (x)) * 256))
#define SHOW(a) {TRACE(#a" = %d\n", (a));}
#define SHOW_X(a) {TRACE(#a" = 0x%x\n", (a));}
#define SHOW_FL(a) {TRACE(#a" = %f\n", (a));}
#ifndef FALSE
#define FALSE 0
#endif
#ifndef TRUE
#define TRUE 1
#endif
//
// Error checking macros
//
#ifndef NDEBUG
void OS_string(CBYTE *fmt, ...);
#define ASSERT(x) {assert(x);}
#define TRACE OS_string
#define VERIFY(x) ASSERT(x)
#else
#define ASSERT(x) {__assume(x);}
#define TRACE
#define VERIFY(x) x
//
// In release build, get rid of the x == 1; warning message otherwise
// VERIFY generates it all the time!
//
#pragma warning( disable : 4553 )
#endif
//
// Assembler fixed point thingies from T.A.C.
//
static inline SLONG DIV16(SLONG a, SLONG b)
{
SLONG v;
_asm
{
mov edx,a
mov ebx,b
mov eax,edx
shl eax,16
sar edx,16
idiv ebx
mov v,eax
}
return v;
}
#pragma warning( disable : 4035 )
// stop warning of no return value : eax is valid
static inline SLONG MUL16(SLONG a, SLONG b)
// MSVC++ version, params:ecx,edx, return:eax
// this is as fast on 486/Pentium as the old version
// and 2.5* faster on Pentium Pro
{
__asm
{
mov eax, a
imul b // result in edx:eax
shl edx,16
shr eax,16
or eax,edx
// return in eax
}
}
#pragma warning( default : 4035 )
//
// Sets the precision of the floating point unit.
//
#define FPP_SINGLE 0x00 // 32-bits
#define FPP_DOUBLE 0x20 // 53-bits
#define FPP_EXTENDED 0x30 // 64-bits
static inline void fpp_set(UWORD precision)
{
short control;
__asm
{
wait
fnstcw control
wait
mov ax, control
and ax, 0xfcff
or ax, precision
mov control, ax
fldcw control
}
}
//
// For doing fast floating-point to long conversion...
//
//
// Sets the rounding to truncate automatically.
//
static inline void ftol_init(void)
{
short control;
__asm
{
wait
fnstcw control
wait
mov ax, control
or ah, 0Ch
mov control, ax
fldcw control
}
}
//
// Converts a float to an int using the current rounding. For normal
// C-style rounding, make sure you call ftol_init() at the start
// of your program.
//
static inline int ftol(float f)
{
int ans;
__asm
{
fld f
fistp ans
}
return ans;
}
//
// Finds the sign of the cross product x1y2 - x2y1 also from T.A.C.
//
static inline SBYTE CROSS_PROD_SIGN(SLONG x1, SLONG y1, SLONG x2, SLONG y2)
{
SBYTE ans;
__asm
{
mov eax, x1
mov ebx, y1
mov ecx, x2
mov edx, y2
imul edx
xchg eax,ebx
xchg edx,ecx
imul edx
sub ebx,eax
setnz al
sbb ecx,edx
jz done
setl ah
setg al
sub al,ah
done:
mov ans, al
}
return ans;
}
//
// Returns the number of the first bit set in the given value. Returns
// -1 if there is no bit set.
//
static inline first_bit(SLONG search)
{
SLONG ans;
__asm
{
mov eax, search
mov ebx, 0ffffffffh
bsf ebx, eax
mov ans, ebx
}
return ans;
}
//
// Returns the number of the last bit set in the given value. Returns
// -1 if there is no bit set.
//
static inline last_bit(SLONG search)
{
SLONG ans;
__asm
{
mov eax, search
mov ebx, 0ffffffffh
bsr ebx, eax
mov ans, ebx
}
return ans;
}
//
// Find the cross product.
//
#define CROSS_PROD(x1,y1,x2,y2) (((x1)*(y2)) - ((x2)*(y1)))
//
// Globally useful structures.
//
typedef struct {float x, y, z;} Point3d;
typedef struct {float x, y; } Point2d;
typedef struct {float x, z; } Pointhf;
typedef struct {float u, v; } Pointuv;
typedef struct
{
float yaw;
float pitch;
float roll;
} Direction;
typedef struct
{
UBYTE r;
UBYTE g;
UBYTE b;
} Colour;
//
// Fast approximation to sqrt(x*x + y*y)
//
static inline float qdist2(float x, float y)
{
float ans;
ASSERT(x >= 0.0F);
ASSERT(y >= 0.0F);
if (x > y)
{
ans = x + y * 0.5F;
}
else
{
ans = y + x * 0.5F;
}
return ans;
}
//
// Fast approximation to sqrt(x*x + y*y + z*z), x,y and z must
// be positive.
//
static inline float qdist3(float x, float y, float z)
{
float ans;
ASSERT(x >= 0.0F);
ASSERT(y >= 0.0F);
ASSERT(z >= 0.0F);
if (x > y)
{
if (x > z)
{
//
// x is the biggeset.
//
ans = x + (y + z) * 0.2941F;
return ans;
}
}
else
{
if (y > z)
{
//
// y is the biggeset.
//
ans = y + (x + z) * 0.2941F;
return ans;
}
}
//
// z is the biggeset.
//
ans = z + (x + y) * 0.2941F;
return ans;
}
//
// A floating point number between 0 and 1.0F
//
static inline float frand(void)
{
SLONG irand = rand();
float ans = float(irand) * (1.0F / float(RAND_MAX));
return ans;
}
#endif