/*======================================================================*/
/* Type definitions header file						*/
/*									*/
/* AUTHOR:	Gabor Nagy						*/
/* DATE:	1996-Dec-20 23:09:30					*/
/*									*/
/* Copyright (C) 1995 By Gabor Nagy. All rights reserved.		*/
/*======================================================================*/
#ifndef _ETypes_h
#define _ETypes_h


#ifdef WIN32
#include <windows.h>
#include <stdio.h>
#include <winsock.h>
#include <string.h>
#pragma warning (disable:4244)		// disable bogus conversion warnings

#else

#ifndef UNIX
#define UNIX
#include <strings.h>
#endif // UNIX
#endif // WIN32

#ifndef EBoolTYPE
typedef char	EBool;
#define EBoolTYPE
#endif	// EBoolTYPE


// Define boolean values
//
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif


typedef unsigned long long	u_long64;


typedef void*	EPointer;

#define EM_SwapLong(lw)	(((lw&0xFF000000)>>24)|((lw&0x00FF0000)>>8)|((lw&0x0000FF00)<<8)|((lw&0x000000FF)<<24))

#define E_ABS(x)	(((x<0)?(-x):(x)))


#ifndef EFLOAT16
#define EFLOAT16
typedef short	EFloat16;
#endif


// High-range fixed-point value
//
typedef struct
{
 int	P18, P9, P0, PM9;	// Powers of 10: 18, 9, 0, -9
} fixed;



// CPU types
//
enum
{
 ECPU_UNKNOWN=0,
 ECPU_MIPS_R5000,
 ECPU_MIPS_R5900,
 ECPU_MIPS_R8000,
 ECPU_MIPS_R10000,
 ECPU_PENTIUM2,
 ECPU_PENTIUM3,
 ECPU_PENTIUM4,
 ECPU_ITANIUM,
 ECPU_ATHLON,
 ECPU_DEC_ALPHA,
 ECPU_G4
};


// File I/O routine return values
//
enum
{
 EIO_SUCCESS=0,
 EIO_ERROR,
 EIO_NO_FILENAME,
 EIO_COULD_NOT_OPEN_FILE,
 EIO_NOT_A_NORMAL_FILE,
 EIO_DIRECTORY,
 EIO_NO_SUCH_FILE,
 EIO_NO_MEMORY,
 EIO_NO_READ_PERMISSION,
 EIO_FILE_EXISTS,
 EIO_DIRECTORY_DOES_NOT_EXIST,
 EIO_NO_WRITE_PERMISSION_FOR_DIR,
 EIO_NO_WRITE_PERMISSION_FOR_FILE,
 EIO_NO_SPACE,
 EIO_DESCRIPTOR_FILE_ERROR,
 EIO_UNSUPPORTED_OPERATION,		// E.g. an IOFilter can't write the given file (e.g. it can only read, but not write)
 EIO_UNSUPPORTED_FORMAT,		// E.g. an IOFilter can't read the given file (e.g. the Hierarchy reader can't read a 3D scene file)
 EIO_UNRECOGNIZED_FORMAT,		// E.g. an IOFilter can't open the given file
 EIO_NO_IOFILTER_FOUND,			// If the format is specified as FROM_EXTENSION...
 EIO_INCOMPATIBLE_DATA,			// E.g. an IOFilter can't save the given type of data (e.g. you can't save a hierarchy into a'.obj' file)
 EIO_FILE_ALREADY_LOADED,
 EIO_INVALID_WINDOW,
 EIO_CORRUPT_FILE
};


// Logging
//
#ifndef ELOG_ERROR
#define ELOG_ERROR	0
#define ELOG_WARNING	1
#define ELOG_MESSAGE	2
#endif






#ifndef EM_BinSearch
//================================================
// Binary search template function
//================================================
#define EM_BinSearch(mI, mCmpProc)\
{\
 int	mOffset=0, mIndex=mI;\
\
 while(mIndex>1)\
 {\
/* If this half has an odd length, we have to check the first item separately ("middle value" problem)*/\
  if(mIndex&0x1)\
  {\
   mIndex>>=1;\
\
   if(mCmpProc(mIndex+mOffset)) mOffset++;\
\
   if(mCmpProc(mIndex+mOffset)) mOffset+=mIndex;	/* Look in upper half*/\
  }\
  else\
  {\
   mIndex>>=1;\
   if(mCmpProc(mIndex+mOffset)) mOffset+=mIndex;	/* Look in upper half*/\
  }\
 }\
 mIndex+=mOffset;\
 LIndex=mIndex;\
}
#endif




#if defined(EM_GetShort)
#else

// CPU byte order-independence macros
//
extern unsigned char	_MPtr[8];	// Max 8 bytes for 'double'
extern EFloat16		_MFloat16;
extern float		_MFloat32;
extern double		_MFloat64;
extern unsigned char*	_MFloat16Ptr;
extern unsigned char*	_MFloat32Ptr;
extern unsigned char*	_MFloat64Ptr;


#define EM_GetShort(v, buffer)	v=((((unsigned short)(((unsigned char*)(buffer))[0]))<<8)|((unsigned short)(((unsigned char*)(buffer))[1])))
#define EM_GetShortI(v, buffer)	v=((((unsigned short)((buffer)[0])))<<8)|((unsigned short)((buffer)[1])), buffer+=2

#define EM_PutShort(v, buffer)	(buffer)[0]=((v)>>8), (buffer)[1]=((v)&0xFF)
#define EM_PutShortI(v, buffer)	(buffer)[0]=((v)>>8), (buffer)[1]=((v)&0xFF), (buffer)+=2

#define EM_GetInt(v, buffer)	v=((((int)(buffer)[0]))<<24)|((((int)(buffer)[1]))<<16)|((((int)(buffer)[2]))<<8)|((int)(buffer)[3])
#define EM_GetIntI(v, buffer)	v=((((int)(buffer)[0]))<<24)|((((int)(buffer)[1]))<<16)|((((int)(buffer)[2]))<<8)|((int)(buffer)[3]), buffer+=4

#define EM_PutInt(v, buffer)	(buffer)[0]=(((v)>>24)&0xFF), (buffer)[1]=(((v)>>16)&0xFF), (buffer)[2]=(((v)>>8)&0xFF), (buffer)[3]=((v)&0xFF)
#define EM_PutIntI(v, buffer)	(buffer)[0]=(((v)>>24)&0xFF), (buffer)[1]=(((v)>>16)&0xFF), (buffer)[2]=(((v)>>8)&0xFF), (buffer)[3]=((v)&0xFF), (buffer)+=4

#define EM_GetLong(v, buffer)	v=((((unsigned long)(((unsigned char*)(buffer))[0]))<<24)|(((unsigned long)(((unsigned char*)(buffer))[1]))<<16)|(((unsigned long)(((unsigned char*)(buffer))[2]))<<8)|((unsigned long)(((unsigned char*)(buffer))[3])));
#define EM_PutLong(v, buffer)	(buffer)[0]=((v)>>8), (buffer)[1]=((v)&0xFF), (buffer)+=2



#ifdef BYTE_BIG_ENDIAN


// Memory IO
// Even though we're in big endian here, the source / destination pointer might not be properly aligned,
// so we still have to do a byte copy
//
#define EM_GetFloat16(v, buffer)\
  _MFloat16Ptr[0]=((unsigned char*)(buffer))[0],_MFloat16Ptr[1]=((unsigned char*)(buffer))[1],\
  v=_MFloat32

#define EM_GetFloat16I(v, buffer)\
  _MFloat16Ptr[0]=((unsigned char*)(buffer))[0],_MFloat16Ptr[1]=((unsigned char*)(buffer))[1],\
  v=_MFloat32, (buffer)+=2

#define EM_GetFloat32(v, buffer)\
  _MFloat32Ptr[0]=((unsigned char*)(buffer))[0],_MFloat32Ptr[1]=((unsigned char*)(buffer))[1],_MFloat32Ptr[2]=((unsigned char*)(buffer))[2],_MFloat32Ptr[3]=((unsigned char*)(buffer))[3],\
  v=_MFloat32

#define EM_GetFloat32I(v, buffer)\
  _MFloat32Ptr[0]=((unsigned char*)(buffer))[0],_MFloat32Ptr[1]=((unsigned char*)(buffer))[1],_MFloat32Ptr[2]=((unsigned char*)(buffer))[2],_MFloat32Ptr[3]=((unsigned char*)(buffer))[3],\
  v=_MFloat32, (buffer)+=4

#define EM_GetFloat64(v, buffer)\
  _MFloat64Ptr[0]=((unsigned char*)(buffer))[0],\
  _MFloat64Ptr[1]=((unsigned char*)(buffer))[1],\
  _MFloat64Ptr[2]=((unsigned char*)(buffer))[2],\
  _MFloat64Ptr[3]=((unsigned char*)(buffer))[3],\
  _MFloat64Ptr[4]=((unsigned char*)(buffer))[4],\
  _MFloat64Ptr[5]=((unsigned char*)(buffer))[5],\
  _MFloat64Ptr[6]=((unsigned char*)(buffer))[6],\
  _MFloat64Ptr[7]=((unsigned char*)(buffer))[7],\
  v=_MFloat64

#define EM_GetFloat64I(v, buffer)\
  _MFloat64Ptr[0]=((unsigned char*)(buffer))[0],\
  _MFloat64Ptr[1]=((unsigned char*)(buffer))[1],\
  _MFloat64Ptr[2]=((unsigned char*)(buffer))[2],\
  _MFloat64Ptr[3]=((unsigned char*)(buffer))[3],\
  _MFloat64Ptr[4]=((unsigned char*)(buffer))[4],\
  _MFloat64Ptr[5]=((unsigned char*)(buffer))[5],\
  _MFloat64Ptr[6]=((unsigned char*)(buffer))[6],\
  _MFloat64Ptr[7]=((unsigned char*)(buffer))[7],\
  v=_MFloat64, (buffer)+=8


#define EM_PutFloat16(v, buffer)	_MFloat16=v,buffer[0]=_MFloat16Ptr[1],buffer[0]=_MFloat16Ptr[1]
#define EM_PutFloat16I(v, buffer)	_MFloat16=v,buffer[0]=_MFloat16Ptr[1],buffer[0]=_MFloat16Ptr[1], (buffer)+=2

#define EM_PutFloat32(v, buffer)	_MFloat32=v,buffer[0]=_MFloat32Ptr[0],buffer[1]=_MFloat32Ptr[1],buffer[2]=_MFloat32Ptr[2],buffer[3]=_MFloat32Ptr[3]
#define EM_PutFloat32I(v, buffer)	_MFloat32=v,buffer[0]=_MFloat32Ptr[0],buffer[1]=_MFloat32Ptr[1],buffer[2]=_MFloat32Ptr[2],buffer[3]=_MFloat32Ptr[3], (buffer)+=4

#define EM_PutFloat64(v, buffer)		_MFloat64=v,\
	buffer[0]=_MFloat64Ptr[0],\
	buffer[1]=_MFloat64Ptr[1],\
	buffer[2]=_MFloat64Ptr[2],\
	buffer[3]=_MFloat64Ptr[3],\
	buffer[4]=_MFloat64Ptr[4],\
	buffer[5]=_MFloat64Ptr[5],\
	buffer[6]=_MFloat64Ptr[6],\
	buffer[7]=_MFloat64Ptr[7]

#define EM_PutFloat64I(v, buffer)		_MFloat64=v,\
	buffer[0]=_MFloat64Ptr[0],\
	buffer[1]=_MFloat64Ptr[1],\
	buffer[2]=_MFloat64Ptr[2],\
	buffer[3]=_MFloat64Ptr[3],\
	buffer[4]=_MFloat64Ptr[4],\
	buffer[5]=_MFloat64Ptr[5],\
	buffer[6]=_MFloat64Ptr[6],\
	buffer[7]=_MFloat64Ptr[7], (buffer)+=8



#define EM_FDPutShort(ptr, fd)		fwrite(fd, &ptr, 2)

#define EM_freadShort(ptr, file)	fread(&ptr, 2, 1, file)
#define EM_freadShortP(ptr,file)	fread(ptr, 2, 1, file)
#define EM_freadInt(ptr, file)		fread(&ptr, 4, 1, file)
#define EM_freadLong(ptr, file)		fread(&ptr, 4, 1, file)
#define EM_freadFloat16(ptr, file)	fread(&ptr, 2, 1, file)
#define EM_freadFloat32(ptr, file)	fread(&ptr, 4, 1, file)
#define EM_freadFloat64(ptr, file)	fread(&ptr, 8, 1, file)

#define EM_fwriteFloat16(v, file)	fwrite(&(v), 2, 1, file)
#define EM_fwriteFloat32(v, file)	fwrite(&(v), 4, 1, file)
#define EM_fwriteFloat64(v, file)	fwrite(&(v), 8, 1, file)

#define EM_fwriteInt(v, file)		fwrite(&(v), 4, 1, file)

#define EM_fwriteShort(ptr, file)	fwrite(&ptr, 2, 1, file)
#define EM_writeShort(v, fd)		write(fd, &v, 2)
#define EM_writeInt(v, fd)		write(fd, &v, 4)
#define EM_writeLong(v, fd)		write(fd, &v, 4)


#else


// Memory I/O
//
#define EM_GetFloat16(v, buffer)\
  _MFloat16Ptr[0]=((unsigned char*)(buffer))[1],_MFloat16Ptr[1]=((unsigned char*)(buffer))[0],\
  v=_MFloat32

#define EM_GetFloat16I(v, buffer)\
  _MFloat16Ptr[0]=((unsigned char*)(buffer))[1],_MFloat16Ptr[1]=((unsigned char*)(buffer))[0],\
  v=_MFloat32, (buffer)+=2

#define EM_GetFloat32(v, buffer)\
  _MFloat32Ptr[0]=((unsigned char*)(buffer))[3],_MFloat32Ptr[1]=((unsigned char*)(buffer))[2],_MFloat32Ptr[2]=((unsigned char*)(buffer))[1],_MFloat32Ptr[3]=((unsigned char*)(buffer))[0],\
  v=_MFloat32

#define EM_GetFloat32I(v, buffer)\
  _MFloat32Ptr[0]=((unsigned char*)(buffer))[3],_MFloat32Ptr[1]=((unsigned char*)(buffer))[2],_MFloat32Ptr[2]=((unsigned char*)(buffer))[1],_MFloat32Ptr[3]=((unsigned char*)(buffer))[0],\
  v=_MFloat32, (buffer)+=4

#define EM_GetFloat64(v, buffer)\
  _MFloat64Ptr[0]=((unsigned char*)(buffer))[7],\
  _MFloat64Ptr[1]=((unsigned char*)(buffer))[6],\
  _MFloat64Ptr[2]=((unsigned char*)(buffer))[5],\
  _MFloat64Ptr[3]=((unsigned char*)(buffer))[4],\
  _MFloat64Ptr[4]=((unsigned char*)(buffer))[3],\
  _MFloat64Ptr[5]=((unsigned char*)(buffer))[2],\
  _MFloat64Ptr[6]=((unsigned char*)(buffer))[1],\
  _MFloat64Ptr[7]=((unsigned char*)(buffer))[0],\
  v=_MFloat64

#define EM_GetFloat64I(v, buffer)\
  _MFloat64Ptr[0]=((unsigned char*)(buffer))[7],\
  _MFloat64Ptr[1]=((unsigned char*)(buffer))[6],\
  _MFloat64Ptr[2]=((unsigned char*)(buffer))[5],\
  _MFloat64Ptr[3]=((unsigned char*)(buffer))[4],\
  _MFloat64Ptr[4]=((unsigned char*)(buffer))[3],\
  _MFloat64Ptr[5]=((unsigned char*)(buffer))[2],\
  _MFloat64Ptr[6]=((unsigned char*)(buffer))[1],\
  _MFloat64Ptr[7]=((unsigned char*)(buffer))[0],\
  v=_MFloat64, (buffer)+=8


#define EM_PutFloat16(v, buffer)	_MFloat16=v,buffer[0]=_MFloat16Ptr[1],buffer[1]=_MFloat16Ptr[0]
#define EM_PutFloat16I(v, buffer)	_MFloat16=v,buffer[0]=_MFloat16Ptr[1],buffer[1]=_MFloat16Ptr[0], (buffer)+=2

#define EM_PutFloat32(v, buffer)	_MFloat32=v,buffer[0]=_MFloat32Ptr[3],buffer[1]=_MFloat32Ptr[2],buffer[2]=_MFloat32Ptr[1],buffer[3]=_MFloat32Ptr[0]
#define EM_PutFloat32I(v, buffer)	_MFloat32=v,buffer[0]=_MFloat32Ptr[3],buffer[1]=_MFloat32Ptr[2],buffer[2]=_MFloat32Ptr[1],buffer[3]=_MFloat32Ptr[0], (buffer)+=4

#define EM_PutFloat64(v, buffer)		_MFloat64=v,\
	buffer[0]=_MFloat64Ptr[7],\
	buffer[1]=_MFloat64Ptr[6],\
	buffer[2]=_MFloat64Ptr[5],\
	buffer[3]=_MFloat64Ptr[4],\
	buffer[4]=_MFloat64Ptr[3],\
	buffer[5]=_MFloat64Ptr[2],\
	buffer[6]=_MFloat64Ptr[1],\
	buffer[7]=_MFloat64Ptr[0]

#define EM_PutFloat64I(v, buffer)		_MFloat64=v,\
	buffer[0]=_MFloat64Ptr[7],\
	buffer[1]=_MFloat64Ptr[6],\
	buffer[2]=_MFloat64Ptr[5],\
	buffer[3]=_MFloat64Ptr[4],\
	buffer[4]=_MFloat64Ptr[3],\
	buffer[5]=_MFloat64Ptr[2],\
	buffer[6]=_MFloat64Ptr[1],\
	buffer[7]=_MFloat64Ptr[0], (buffer)+=8


// File I/O
//

#define EM_freadShort(v, file)\
  fread(_MPtr, 2, 1, file),\
  v=(((unsigned short)(_MPtr[0]))<<8)|((unsigned short)(_MPtr[1]))

#define EM_freadShortP(ptr, file)\
  fread(_MPtr, 2, 1, file),\
  *(ptr)=(((unsigned short)(_MPtr[0]))<<8)|((unsigned short)(_MPtr[1]))

#define EM_freadInt(ptr, file)\
  fread(_MPtr, 4, 1, file),\
  ptr=(int)((((unsigned int)(_MPtr[0]))<<24)|(((unsigned int)(_MPtr[1]))<<16)|(((unsigned int)(_MPtr[2]))<<8)|((unsigned int)(_MPtr[3])))

#define EM_freadUInt(ptr, file)\
  fread(_MPtr, 4, 1, file),\
  ptr=((((unsigned int)(_MPtr[0]))<<24)|(((unsigned int)(_MPtr[1]))<<16)|(((unsigned int)(_MPtr[2]))<<8)|((unsigned int)(_MPtr[3])))

#define EM_freadLong(v, file)\
  fread(_MPtr, 4, 1, file),\
  v=(long)((((unsigned long)(_MPtr[0]))<<24)|(((unsigned long)(_MPtr[1]))<<16)|(((unsigned long)(_MPtr[2]))<<8)|((unsigned long)(_MPtr[3])))

#define EM_freadULong(v, file)\
  fread(_MPtr, 4, 1, file),\
  v=((((unsigned long)(_MPtr[0]))<<24)|(((unsigned long)(_MPtr[1]))<<16)|(((unsigned long)(_MPtr[2]))<<8)|((unsigned long)(_MPtr[3])))


#define EM_freadFloat16(v, file)\
  fread(_MPtr, 2, 1, file),\
  *(ptr)=(((EFloat16)(_MPtr[0]))<<8)|((EFloat16)(_MPtr[1]))

#define EM_freadFloat32(v, file)\
  fread(_MPtr, 4, 1, file),\
  _MFloat32Ptr[0]=_MPtr[3],_MFloat32Ptr[1]=_MPtr[2],_MFloat32Ptr[2]=_MPtr[1],_MFloat32Ptr[3]=_MPtr[0],\
  v=_MFloat32

#define EM_freadFloat64(v, file)\
  fread(_MPtr, 8, 1, file),\
  _MFloat64Ptr[0]=_MPtr[7],_MFloat64Ptr[1]=_MPtr[6],_MFloat64Ptr[2]=_MPtr[5],_MFloat64Ptr[3]=_MPtr[4],\
  _MFloat64Ptr[4]=_MPtr[3],_MFloat64Ptr[5]=_MPtr[2],_MFloat64Ptr[6]=_MPtr[1],_MFloat64Ptr[7]=_MPtr[0],\
  v=_MFloat64

#define EM_FGetDefType(ptr, file)\
  EM_freadInt(ptr, file)			// Must figure out by experimenting!!!!



// Write to file
//
#define EM_fwriteShort(v, file)\
  _MPtr[0]=(unsigned char)((v)>>8),_MPtr[1]=(unsigned char)(v),\
  fwrite(_MPtr, 2, 1, file)

#define EM_writeShort(v, fd)\
  _MPtr[0]=(unsigned char)((v)>>8),_MPtr[1]=(unsigned char)(v),\
  write(fd, _MPtr, 2)

#define EM_fwriteInt(ptr,file)\
  _MPtr[0]=(unsigned char)((ptr)>>24),_MPtr[1]=(unsigned char)((ptr)>>16),_MPtr[2]=(unsigned char)((ptr)>>8),_MPtr[3]=(unsigned char)(ptr),\
  fwrite(_MPtr, 4, 1, file)

#define EM_writeInt(ptr, fd)\
   _MPtr[0]=(unsigned char)((ptr)>>24), _MPtr[1]=(unsigned char)((ptr)>>16), _MPtr[2]=(unsigned char)((ptr)>>8), _MPtr[3]=(unsigned char)(ptr),\
   write(fd, _MPtr, 4)

#define EM_fwriteUInt(ptr, file)\
  _MPtr[0]=(unsigned char)((ptr)>>24),_MPtr[1]=(unsigned char)((ptr)>>16),_MPtr[2]=(unsigned char)((ptr)>>8),_MPtr[3]=(unsigned char)(ptr),\
  fwrite(_MPtr, 4, 1, file)

#define EM_fwriteLong(ptr, file)\
  _MPtr[0]=(unsigned char)((ptr)>>24),_MPtr[1]=(unsigned char)((ptr)>>16),_MPtr[2]=(unsigned char)((ptr)>>8),_MPtr[3]=(unsigned char)(ptr),\
  fwrite(_MPtr, 4, 1, file)

#define EM_writeLong(ptr, fd)\
  _MPtr[0]=(unsigned char)((ptr)>>24),_MPtr[1]=(unsigned char)((ptr)>>16),_MPtr[2]=(unsigned char)((ptr)>>8),_MPtr[3]=(unsigned char)(ptr),\
  write(fd, _MPtr, 4)

#define EM_fwriteULong(ptr, file)\
  _MPtr[0]=(unsigned char)((ptr)>>24),_MPtr[1]=(unsigned char)((ptr)>>16),_MPtr[2]=(unsigned char)((ptr)>>8),_MPtr[3]=(unsigned char)(ptr),\
  fwrite(_MPtr, 4, 1, file)

#define EM_fwriteFloat32(v, file)\
  _MFloat32=v;\
  _MPtr[3]=_MFloat32Ptr[0],_MPtr[2]=_MFloat32Ptr[1],_MPtr[1]=_MFloat32Ptr[2],_MPtr[0]=_MFloat32Ptr[3],\
  fwrite(_MPtr, 4, 1, file)

#endif // BYTE_BIG_ENDIAN


#define EM_freadColor24(ptr, file)\
  EM_freadFloat((ptr).r, file),EM_freadFloat((ptr).g,file),EM_freadFloat((ptr).b,file)

#define EM_freadVector(ptr, file)\
  EM_freadFloat((ptr).x, file),EM_freadFloat((ptr).y,file),EM_freadFloat((ptr).z,file)

#define EM_freadMatrixFloat32(ptr,file)\
  EM_freadFloat32((ptr)[M00],file),EM_freadFloat32((ptr)[M01],file),EM_freadFloat32((ptr)[M02],file),EM_freadFloat32((ptr)[M03],file),\
  EM_freadFloat32((ptr)[M10],file),EM_freadFloat32((ptr)[M11],file),EM_freadFloat32((ptr)[M12],file),EM_freadFloat32((ptr)[M13],file),\
  EM_freadFloat32((ptr)[M20],file),EM_freadFloat32((ptr)[M21],file),EM_freadFloat32((ptr)[M22],file),EM_freadFloat32((ptr)[M23],file),\
  EM_freadFloat32((ptr)[M30],file),EM_freadFloat32((ptr)[M31],file),EM_freadFloat32((ptr)[M32],file),EM_freadFloat32((ptr)[M33],file)


#endif	// defined(EM_GetShort)


#endif // _ETypes_h
