//
// Project UnReality: The First Nintendo 64 Emulator
// Copyright (C) 1997-1998, Cold Fusion Entertainment
// All rights reserved
//
// This source code is unpublished propietary information of Cold Fusion Entertainment.  No portion of this software
// may be disclosed to any third party or copied or duplicated in any form, in whole or in part, without the prior
// written consent of Cold Fusion Entertainment.
// 

//
// $Log: fixed32.cpp $
// Revision 1.2  1998/05/24 05:58:30  BREAKPOINT
// Added new types (10.2, 10.5, and 5.10) to fixed point conversions..
// Revision 1.1  1998/05/06 21:01:52  BREAKPOINT
// Initial revision
//

//---------------------------------------------------------------------------------------------------------------------

typedef long Fixed32;				// 16.16 FixedPoint

#define INT_TO_FIXED(x)				(((long)(x)) << 16)
#define DOUBLE_TO_FIXED(x)			((long)(x * 65536.0 + 0.5))
#define FIXED_TO_INT(x)				((x) >> 16)
#define FIXED_TO_DOUBLE(x)			(((double)x) / 65536.0)
#define ROUND_FIXED_TO_INT(x)		(((x) + 0x8000) >> 16)

#define FRAC_TO_FIXED(x)			((unsigned long)((ushort)(x)))
#define FIXED_TO_FRAC(x)			((unsigned short)(x))
#define S5p10_TO_FIXED(x)			(((long)(x)) <<  6)
#define S10p5_TO_FIXED(x)			(((long)(x)) << 11)
#define S10p2_TO_FIXED(x)			(((long)(x)) << 14)

#define ONE							INT_TO_FIXED(1)
#define FIXED_PI					205887L
#define FIXED_2PI					411775L
#define FIXED_E						178144L
#define FIXED_ROOT2					 74804L
#define FIXED_ROOT3					113512L
#define FIXED_GOLDEN				106039L

inline Fixed32 FixedMul(Fixed32 num1, Fixed32 num2)
{
	Fixed32 result;

	__asm {
		push eax
		push edx
		mov  eax, num1
		mov  edx, num2
		imul edx
		add  eax, 8000h
		adc  edx, 0
		shrd eax, edx, 16
		mov  result, eax
		pop  edx
		pop  eax
	};

	return result;
}

inline Fixed32 FixedDiv(Fixed32 numer, Fixed32 denom)
{
	Fixed32 result;

	__asm {
		push eax
		push ebx
		push edx
		mov  edx, numer
		mov  ebx, denom
		xor  eax, eax
		shrd eax, edx, 16
		sar  edx, 16
		idiv ebx
		mov  result, eax
		pop  edx
		pop  ebx
		pop  eax
	};

	return result;
}

/*
Fixed32 FixedSquare(Fixed32 n);
Fixed32 OneOver(Fixed32 n);
Fixed32 FixedSqrtLP(Fixed32 n);  // Low  Precision (8.8)
Fixed32 FixedSqrtHP(Fixed32 n);  // High Precision (8.16)

// This is faster than using FixedMul for squares.
#pragma aux FixedSquare =   \
    "imul eax"              \
    "add eax, 8000h"        \
    "adc edx, 0"            \
    "shrd eax, edx, 16"     \
    parm caller [eax]       \
    value [eax]             \
    modify [eax edx];

// This is faster than using FixedDiv.
#pragma aux OneOver =       \
    "xor eax, eax"          \
    "mov edx, 1"            \
    "idiv ebx"              \
    parm caller [ebx]       \
    value [eax]             \
    modify [eax ebx edx];

#pragma aux FixedSqrtLP =            \
    "         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];

#pragma aux FixedSqrtHP =            \
    "         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];
*/
