//----------------------------------------------------------------------------
// TYPE  fixed
//----------------------------------------------------------------------------

typedef unsigned int     fixed;

//----------------------------------------------------------------------------
// TYPE  angle_t
//----------------------------------------------------------------------------

typedef int     angle_t;

//----------------------------------------------------------------------------
// Conversion macros:
//----------------------------------------------------------------------------

#define int_to_fixed_(x)       ( ( (int) (x) ) << 16 )
#define double_to_fixed_(x)    ( (int) ((x) * 65536.0 + 0.5 ) )

#define fixed_to_int_(x)       ( (int) ( (x) >> 16 ) )
#define round_fixed_to_int_(x) ( ((x) + 0x8000) >> 16 )
#define fixed_to_double_(x)    ( (double) (x) / 65536.0 )
#define fixed_abs_(x)          ( ((x) >= 0) ? (x) : (-(x)) )

//----------------------------------------------------------------------------
// Common numerical constants:
//----------------------------------------------------------------------------

#define FIX_1      int_to_fixed_(1)
#define FIX_PI     205887L
#define FIX_2PI    411775L  // 2PI != 2 * PI
#define FIX_E      178144L
#define FIX_ROOT2   74804L
#define FIX_ROOT3  113512L
#define FIX_GOLDEN 106039L

//----------------------------------------------------------------------------
// Functions:
//----------------------------------------------------------------------------

fixed          FIX_mul       ( fixed, fixed );
fixed          FIX_div       ( fixed numerator, fixed denominator );
fixed          FIX_square    ( fixed ); // Faster than using FIX_mul
fixed          FIX_invert    ( fixed ); // 1 over n; faster than FIX_div
fixed          FIX_sqrt_lp   ( fixed ); // Low  Precision (8:8)
fixed          FIX_sqrt_hp   ( fixed ); // High Precision (8:16)

void           FIX_cos_sin   ( angle_t, fixed * cosine, fixed * sine );

//----------------------------------------------------------------------------
// FUNCTION  FIX_mul
//----------------------------------------------------------------------------
#ifdef ALT030196
#pragma aux FIX_mul =       \
    "imul edx"              \
    "add eax, 8000h"        \
    "adc edx, 0"            \
    "shrd eax, edx, 16"     \
    parm caller [eax] [edx] \
    value [eax]             \
    modify [eax edx];

//----------------------------------------------------------------------------
// FUNCTION  FIX_div
//----------------------------------------------------------------------------

#pragma aux FIX_div =       \
    "xor eax, eax"          \
    "shrd eax, edx, 16"     \
    "sar edx, 16"           \
    "idiv ebx"              \
    parm caller [edx] [ebx] \
    value [eax]             \
    modify [eax ebx edx];

//----------------------------------------------------------------------------
// FUNCTION  FIX_square
//----------------------------------------------------------------------------
// This is faster than using FIX_mul for squares.
//----------------------------------------------------------------------------

#pragma aux FIX_square =    \
    "imul eax"              \
    "add eax, 8000h"        \
    "adc edx, 0"            \
    "shrd eax, edx, 16"     \
    parm caller [eax]       \
    value [eax]             \
    modify [eax edx];

//----------------------------------------------------------------------------
// FUNCTION  FIX_invert
//----------------------------------------------------------------------------
// This is faster than using FIX_div.
//----------------------------------------------------------------------------

#pragma aux FIX_invert =    \
    "xor eax, eax"          \
    "mov edx, 1"            \
    "idiv ebx"              \
    parm caller [ebx]       \
    value [eax]             \
    modify [eax ebx edx];

//----------------------------------------------------------------------------
// FUNCTION  FIX_sqrt_lp
//----------------------------------------------------------------------------

#pragma aux FIX_sqrt_lp =            \
    "         xor eax, eax"          \
    "         mov ebx, 40000000h"    \
    "sqrtLP1: mov edx, ecx"          \
    "         sub edx, ebx"          \
    "         jl  sqrtLP2"           \
    "         sub edx, eax"          \
    "         jl  sqrtLP2"           \
    "         mov ecx,edx"           \
    "         shr eax, 1"            \
    "         or  eax, ebx"          \
    "         shr ebx, 2"            \
    "         jnz sqrtLP1"           \
    "         shl eax, 8"            \
    "         jmp sqrtLP3"           \
    "sqrtLP2: shr eax, 1"            \
    "         shr ebx, 2"            \
    "         jnz sqrtLP1"           \
    "         shl eax, 8"            \
    "sqrtLP3: nop"                   \
    parm caller [ecx]                \
    value [eax]                      \
    modify [eax ebx ecx edx];

//----------------------------------------------------------------------------
// FUNCTION  FIX_sqrt_hp
//----------------------------------------------------------------------------

#pragma aux FIX_sqrt_hp =            \
    "         xor eax, eax"          \
    "         mov ebx, 40000000h"    \
    "sqrtHP1: mov edx, ecx"          \
    "         sub edx, ebx"          \
    "         jb  sqrtHP2"           \
    "         sub edx, eax"          \
    "         jb  sqrtHP2"           \
    "         mov ecx,edx"           \
    "         shr eax, 1"            \
    "         or  eax, ebx"          \
    "         shr ebx, 2"            \
    "         jnz sqrtHP1"           \
    "         jz  sqrtHP5"           \
    "sqrtHP2: shr eax, 1"            \
    "         shr ebx, 2"            \
    "         jnz sqrtHP1"           \
    "sqrtHP5: mov ebx, 00004000h"    \
    "         shl eax, 16"           \
    "         shl ecx, 16"           \
    "sqrtHP3: mov edx, ecx"          \
    "         sub edx, ebx"          \
    "         jb  sqrtHP4"           \
    "         sub edx, eax"          \
    "         jb  sqrtHP4"           \
    "         mov ecx, edx"          \
    "         shr eax, 1"            \
    "         or  eax, ebx"          \
    "         shr ebx, 2"            \
    "         jnz sqrtHP3"           \
    "         jmp sqrtHP6"           \
    "sqrtHP4: shr eax, 1"            \
    "         shr ebx, 2"            \
    "         jnz sqrtHP3"           \
    "sqrtHP6: nop"                   \
    parm caller [ecx]                \
    value [eax]                      \
    modify [eax ebx ecx edx];
#endif
