/****************************************************************************\
*                                                                            *
*  INTERNAL.H - Source Code Header Module                                    *
*                                                                            *
*  (c)Copyright 2001 Indotek, LLC. All Rights Reserved.                      *
*                                                                            *
\****************************************************************************/

#ifdef GLOBALS_DEFINED
#define GLOBAL
#else
#define GLOBAL extern
#endif


#define D3D_OVERLOADS

#include <d3drm.h> // Required for Direct3D error string definitions
#include <stdio.h>
#include "r3d.h"

// Used for textures and image loading
#define _R3D_MAXTEXTURESIZE 1024
GLOBAL unsigned char *_r3d_BGR; // These are allocated and deleted as needed
GLOBAL unsigned char *_r3d_A; // These are allocated and deleted as needed
GLOBAL unsigned char *_r3d_256; // These are allocated and deleted as needed
GLOBAL int _r3d_PixelFormatCode;
GLOBAL unsigned char *_r3d_FadeInBackBufferCopy; // These are allocated and deleted as needed

// Internal Definitions
#define _R3D_DELETE(p)  {if(p){delete (p);(p)=NULL;}}
#define _R3D_RELEASE(p) {if(p){(p)->Release();(p)=NULL;}}
#define _R3D_RESTORE(a) if((a)!=NULL){if((a)->IsLost())(a)->Restore();}

#define _R3D_DRAWPRIMITIVE_V_FLAGS D3DDP_DONOTUPDATEEXTENTS
#define _R3D_DRAWPRIMITIVE_LV_FLAGS D3DDP_DONOTUPDATEEXTENTS|D3DDP_DONOTLIGHT

#define _R3D_YUMMY_PI   3.14159265358979323846
#define _R3D_POSSIBLY_HEL   0
#define _R3D_POSSIBLY_HAL   1
#define _R3D_MAX_ATTACHED_MODELS    128
#define _R3D_TEXTUREFORMAT_16_RGB_565   0
#define _R3D_TEXTUREFORMAT_16_RGBA_1555 1
#define _R3D_TEXTUREFORMAT_16_RGBA_4444 2
#define _R3D_TEXTUREFORMAT_32_RGBA_8888 3
#define _R3D_TEXTUREFORMAT_16_BGR_565   4
#define _R3D_TEXTUREFORMAT_15_RGB_555   5
#define _R3D_TEXTUREFORMAT_16_LA_88 6
#define _R3D_MAXTEXTUREFORMATS          7

// Internal Type Definitions
#define _R3D_MAX_SURFACES 4096
typedef struct __R3D_SURFACE__
{
   unsigned char *RGBA;
   DWORD dwWidth;
   DWORD dwHeight;
} _R3D_SURFACE;
#define _R3D_MAX_DDSURFACES 4096
typedef struct __R3D_DDSURFACE__
{
   LPDIRECTDRAWSURFACE4 lpSurface;
   DWORD dwWidth;
   DWORD dwHeight;
} _R3D_DDSURFACE;
typedef struct __R3D_2DBEGINEND__
{
   DDSURFACEDESC2 ddsd;
   DWORD dwWidth;
   DWORD dwHeight;
   int PixelFormatCode;
   BOOL bIsLocked;
} _R3D_2DBEGINEND;
typedef struct __R3D_TEXTUREFORMATLIST__
{
   BOOL bSupported;
   DDPIXELFORMAT ddpfPixelFormat;
} _R3D_TEXTUREFORMATLIST;


typedef struct __R3D_MATERIAL__
{
   D3DMATERIALHANDLE hMaterial;
   D3DMATERIAL Material;
   LPDIRECT3DMATERIAL3 lpMaterial;
   char TextureBMP[129]; // Absolute path texture BMP filename, ex. "a.bmp"
   char AlphaBMP[129]; // Absolute path texture BMP filename, ex. "a.bmp"
   BOOL bTexture; // True if a texture is present
   BOOL bAlpha; // True if an alpha texture is present
   BOOL bStoreAlpha;
   LPDIRECTDRAWSURFACE4 lpSystemTextureSurface;
   LPDIRECT3DTEXTURE2 lpSystemTexture;
   BOOL bMipMap;
   DDSURFACEDESC2 ddsd; // ddsd is invalid if bMipMap==TRUE... We can not lock a mipmap texture surface
   BOOL bDuplicate; // This texture has already been loaded
   int DuplicateIndex; // This is the _R3D_MATERIAL index of the duplicate
   BOOL bColorKeyedTexture;
} _R3D_MATERIAL;
typedef struct __R3D_MODELCOMPONENT__
{
   DWORD NumV;
   DWORD NumT;
   D3DVERTEX *v;
   WORD *t;
   _R3D_MATERIAL *m;
} _R3D_MODELCOMPONENT;
typedef struct __R3D_MODEL__
{
   float x01, y01, z01, x02, y02, z02; // Bounding Box
   float Radius; // Bounding Sphere
   int NumM; // # Materials (# _R3D_MODELCOMPONENT's)
   int MCStartIndex; // _R3D_MODELCOMPONENT start index
   BOOL bPreLight;
   long AttachedModelIndexes[_R3D_MAX_ATTACHED_MODELS]; // A value of -1L, indicates nothing is attached
   float *AttachedModelMatrices[_R3D_MAX_ATTACHED_MODELS]; // pointer to attached model matrices
} _R3D_MODEL;
GLOBAL D3DVERTEX *_r3d_Vertex; // Allocated as needed
GLOBAL WORD *_r3d_Triangle; // Allocated as needed
GLOBAL _R3D_MATERIAL *_r3d_Material; // Allocated as needed
GLOBAL _R3D_MODEL *_r3d_Model; // Allocated as needed
GLOBAL _R3D_MODELCOMPONENT *_r3d_ModelComponent; // Allocated as needed
GLOBAL int _r3d_VertexIndex; // Next Available Position in Vertex Data
GLOBAL int _r3d_TriangleIndex; // Next Available Position in Triangle Data
GLOBAL int _r3d_MaterialIndex; // Next Available Position in Material Data
GLOBAL int _r3d_ModelIndex; // Next Available Position in Model Data
GLOBAL int _r3d_ModelComponentIndex; // Next Available Position in MC Data


typedef struct __R3D_STATE__
{
   unsigned long FogColor; // fog color RGBA where A=0
   float FogStart; // begining depth
   float FogEnd; // ending depth
   BOOL bFog;
   int FilterMethod;
   BOOL bSpecular;
} _R3D_STATE;
typedef struct __R3D_MATRIX__
{
   float x, y, z;
   D3DMATRIX m;
} _R3D_MATRIX;
typedef struct __R3D_MATERIALLIST__
{
   float r, g, b, a, pow, sr, sg, sb, er, eg, eb;
   BOOL bLoadTexture, bLoadAlpha;
   char TextureBMP[129], AlphaBMP[129];
   BOOL bMipMap;
} _R3D_MATERIALLIST;
GLOBAL _R3D_MATERIALLIST *_r3d_MaterialList[32767];
GLOBAL int _r3d_MaterialListIndex;
struct _R3D_MODELLIST
{
   char Filename[_MAX_PATH];
   BOOL bMipMap;
   int NumM;
   DWORD TotalNumV, TotalNumT;
};
GLOBAL _R3D_MODELLIST *_r3d_ModelList[32767]; // 32767 models (32767*sizeof(a pointer)=131068 bytes
GLOBAL int _r3d_ModelListIndex;


#define _R3D_BLITCLIP(SrcW,SrcH,DstW,DstH,SrcMinx,SrcMaxx,SrcMiny,SrcMaxy,DstMinx,DstMaxx,DstMiny,DstMaxy)  if ((SrcMinx)<0) \
{ \
   (DstMinx) = (DstMinx) + ((((DstMaxx)-(DstMinx))*(0-(SrcMinx))) / ((SrcMaxx)-(SrcMinx))); \
   (SrcMinx) = 0; \
} \
   if ((SrcMaxx)>((SrcW)-1)) \
{ \
   (DstMaxx) = (DstMinx) + ((((DstMaxx)-(DstMinx))*(((SrcW)-1)-(SrcMinx))) / ((SrcMaxx)-(SrcMinx))); \
   (SrcMaxx) = ((SrcW)-1); \
} \
   if ((SrcMiny)<0) \
{ \
   (DstMiny) = (DstMiny) + ((((DstMaxy)-(DstMiny))*(0-(SrcMiny))) / ((SrcMaxy)-(SrcMiny))); \
   (SrcMiny) = 0; \
} \
   if ((SrcMaxy)>((SrcH)-1)) \
{ \
   (DstMaxy) = (DstMiny) + ((((DstMaxy)-(DstMiny))*(((SrcH)-1)-(SrcMiny))) / ((SrcMaxy)-(SrcMiny))); \
   (SrcMaxy) = ((SrcH)-1); \
} \
   if ((DstMinx)<0) \
{ \
   (SrcMinx) = (SrcMinx) + ((((SrcMaxx)-(SrcMinx))*(0-(DstMinx))) / ((DstMaxx)-(DstMinx))); \
   (DstMinx) = 0; \
} \
   if ((DstMaxx)>((DstW)-1)) \
{ \
   (SrcMaxx) = (SrcMinx) + ((((SrcMaxx)-(SrcMinx))*(((DstW)-1)-(DstMinx))) / ((DstMaxx)-(DstMinx))); \
   (DstMaxx) = ((DstW)-1); \
} \
   if ((DstMiny)<0) \
{ \
   (SrcMiny) = (SrcMiny) + ((((SrcMaxy)-(SrcMiny))*(0-(DstMiny))) / ((DstMaxy)-(DstMiny))); \
   (DstMiny) = 0; \
} \
   if ((DstMaxy)>((DstH)-1)) \
{ \
   (SrcMaxy) = (SrcMiny) + ((((SrcMaxy)-(SrcMiny))*(((DstH)-1)-(DstMiny))) / ((DstMaxy)-(DstMiny))); \
   (DstMaxy) = ((DstH)-1); \
} \
   if ((DstMaxx)<0) \
   return TRUE; \
   if ((DstMinx)>((DstW)-1)) \
   return TRUE; \
   if ((DstMaxy)<0) \
   return TRUE; \
   if ((DstMiny)>((DstH)-1)) \
   return TRUE; \
   if ((SrcMaxx)<0) \
   return TRUE; \
   if ((SrcMinx)>((SrcW)-1)) \
   return TRUE; \
   if ((SrcMaxy)<0) \
   return TRUE; \
   if ((SrcMiny)>((SrcH)-1)) \
   return TRUE;

// Internal Functions
extern BOOL R3D_STDCALL _r3d_SurfaceCreateScaledTexture(int *hBitmapRet, char *pTextureFilename, BOOL bLoadAlpha, char *pAlphaFilename, char *FunctionNameString, unsigned long *dwWidthHeightRet);
extern char *R3D_STDCALL _r3d_strnset(char *string, int c, size_t count);
extern char *R3D_STDCALL _r3d_strcpy(char *dst, char *src);
extern char *R3D_STDCALL _r3d_strcat(char *dst, char *src);
extern BOOL R3D_STDCALL _r3d_BMPGetInfo(char *pFilename, char *FunctionNameString, DWORD *BMPWidth, DWORD *BMPHeight, BOOL *bPalette256);
extern BOOL R3D_STDCALL _r3d_BMPLoad(char *pFilename, char *FunctionNameString, unsigned char *pBGRImage, unsigned char *p256Image);
BOOL R3D_STDCALL _r3d_2DLineNoMask(int x01, int y01, int x02, int y02, unsigned char r, unsigned char g, unsigned char b);
extern void R3D_STDCALL _r3d_DestroyDirectX(void);
extern BOOL R3D_STDCALL _r3d_CreateDirectX(void);
extern BOOL R3D_STDCALL _r3d_ListUnloadInternal(void);
extern BOOL R3D_STDCALL _r3d_ListLoadInternal(void);
extern void R3D_STDCALL _r3d_ProperlyInitDDSD(DDSURFACEDESC2 *ddsd);
extern BOOL R3D_STDCALL _r3d_InitializeD3D(void);
extern int R3D_STDCALL _r3d_DetermineTextureSize(char *lpTextureBMP, BOOL bAlpha);
extern long R3D_STDCALL _r3d_Load3DModel(char *lpFilename, BOOL bMipMap);
extern BOOL R3D_STDCALL _r3d_MakeMaterial(_R3D_MATERIAL *pMaterial, float r, float g, float b, float a, float pow, float sr, float sg, float sb, float er, float eg, float eb, BOOL bLoadTexture, char *TextureFilenameBMP, BOOL bLoadAlpha, char *AlphaFilenameBMP, BOOL bMipMap);
extern BOOL R3D_STDCALL _r3d_SetMaterial(_R3D_MATERIAL *pMat);
extern D3DMATRIX R3D_STDCALL _r3d_IdentityMatrix(void);
extern D3DMATRIX R3D_STDCALL _r3d_ZeroMatrix(void);
extern D3DMATRIX R3D_STDCALL _r3d_ProjectionMatrix(double near_plane, double far_plane, double fov);
extern char *R3D_STDCALL _r3d_D3DAppErrorToString(HRESULT error);
extern void R3D_STDCALL _r3d_FormulateErrorString(char *pR3DFunc, char *pD3DFunc, HRESULT hResult);
extern BOOL R3D_STDCALL _r3d_RestoreSurfaces(void);
extern BOOL WINAPI _r3d_EnumDevicesCallback(GUID FAR *lpGuid, LPSTR lpDriverDesc, LPSTR lpDriverName, LPVOID lpContext);
extern HRESULT WINAPI _r3d_EnumModesCallback(LPDDSURFACEDESC2 lpDDSurfaceDesc, LPVOID lpContext);
extern HRESULT WINAPI _r3d_EnumD3DDriversCallback(LPGUID lpGuid, LPSTR lpDeviceDescription, LPSTR lpDeviceName, LPD3DDEVICEDESC lpHWDesc, LPD3DDEVICEDESC lpHELDesc, LPVOID lpContext);
extern BOOL R3D_STDCALL _r3d_InitTimer(void);
extern HRESULT WINAPI _r3d_EnumZBufferCallback(DDPIXELFORMAT *pddpf, VOID *pddpfDesired);
extern HRESULT CALLBACK _r3d_EnumPixelFormatsCallback(LPDDPIXELFORMAT lpDDPixFmt, LPVOID lpContext);
extern unsigned long R3D_STDCALL _r3dShareware_GetCurrentTick(void);
extern BOOL R3D_STDCALL _r3dShareware_SetCurrentTick(unsigned long tick);
extern int R3D_STDCALL _r3d_Line_Clip(int &x01, int &y01, int &x02, int &y02);

//-----------------------------------------------------------------------------
// Name: _r3d_Enum_ModeInfo
// Desc: Linked-list structure to hold information about a display mode. This
//       info is stored as a width, height, bpp, and pixelformat within a
//       DDSURFACEDESC2.
//-----------------------------------------------------------------------------
struct _r3d_Enum_ModeInfo
{
   DDSURFACEDESC2 ddsd;
   CHAR strDesc[40];
   _r3d_Enum_ModeInfo *pNext;
};
//-----------------------------------------------------------------------------
// Name: _r3d_Enum_DeviceInfo
// Desc: Linked-list structure to hold information about a Direct3D device. The
//       primary information recorded here is the D3DDEVICEDESC and a ptr to a
//       linked-list of valid display modes.
//-----------------------------------------------------------------------------
struct _r3d_Enum_DeviceInfo
{
   GUID guid;
   GUID *pGUID;
   CHAR strName[40];
   D3DDEVICEDESC ddDesc;
   BOOL bIsHardware;
   BOOL bCompatibleWithDesktop;
   DWORD dwDesktopRGBBitCount;
   DWORD dwDesktopRBitMask;
   DWORD dwDesktopGBitMask;
   DWORD dwDesktopBBitMask;
   _r3d_Enum_ModeInfo *pCurrentMode;
   _r3d_Enum_ModeInfo *pFirstMode;
   _r3d_Enum_DeviceInfo *pNext;
};
//-----------------------------------------------------------------------------
// Name: _r3d_Enum_DriverInfo
// Desc: Linked-list structure to hold information about a DirectX driver. The
//       info stored is the capability bits for the driver plus a linked-list
//       of valid Direct3D devices for the driver. Note: most systems will only
//       have one driver. The exception are multi-monitor systems, and systems
//       with non-GDI 3D video cards.
//-----------------------------------------------------------------------------
struct _r3d_Enum_DriverInfo
{
   GUID guid;
   GUID *pGUID;
   CHAR strDesc[40];
   CHAR strName[40];
   DDCAPS ddDriverCaps;
   DDCAPS ddHELCaps;
   HANDLE hMonitor;
   _r3d_Enum_DeviceInfo *pCurrentDevice;
   _r3d_Enum_DeviceInfo *pFirstDevice;
   _r3d_Enum_DriverInfo *pNext;
};
//-----------------------------------------------------------------------------
// Name: _r3d_Enum_EnumerateDevices()
// Desc: Enumerates all drivers, devices, and modes. The optional app-supplied
//       callback is called for each enumerated device, to confirm that the
//       device supports the feature set required by the app.
//-----------------------------------------------------------------------------
extern HRESULT _r3d_Enum_EnumerateDevices(HRESULT (*AppConfirmFn)(DDCAPS *, D3DDEVICEDESC *), BOOL b3DEmulation, BOOL b3DAcceleration);
//-----------------------------------------------------------------------------
// Name: _r3d_Enum_FreeResources()
// Desc: Frees all resources used for driver enumeration
//-----------------------------------------------------------------------------
extern VOID _r3d_Enum_FreeResources();
#define D3DENUMERR_NODIRECTDRAW        0x81000004 // DDraw couldn't initialize
GLOBAL _r3d_Enum_DriverInfo *_r3d_gpFirstDriver; // List of DD drivers
GLOBAL _r3d_Enum_DriverInfo *_r3d_gpDefaultDriver; // Default driver
GLOBAL _r3d_Enum_DriverInfo *_r3d_gpCurrentDriver; // The selected DD driver


#ifdef EVALUATIONVERSION
GLOBAL int *_r3d_ta; //Was _R3D_MAX_MATS
GLOBAL int *_r3d_tb;
GLOBAL unsigned char **_r3d_tc; // _r3d_tc = new unsigned char *[TotalMaterial]
GLOBAL int *_r3d_td;
#endif


// Internal Variables
GLOBAL LPDIRECTDRAW _r3d_DirectDraw;
GLOBAL LPDIRECTDRAW4 _r3d_DirectDraw4;
GLOBAL LPDIRECTDRAWSURFACE4 _r3d_FrontBuffer4;
GLOBAL LPDIRECTDRAWSURFACE4 _r3d_BackBuffer4;
GLOBAL LPDIRECTDRAWSURFACE4 _r3d_ZBuffer4;
GLOBAL LPDIRECTDRAWCLIPPER _r3d_Clipper;
GLOBAL LPDIRECT3D3 _r3d_Direct3D;
GLOBAL LPDIRECT3DDEVICE3 _r3d_Device;
GLOBAL LPDIRECT3DVIEWPORT3 _r3d_Viewport;
GLOBAL LPDIRECT3DLIGHT _r3d_Light;
GLOBAL BOOL _r3d_gbDefaultLightActive;
GLOBAL BOOL _r3d_gbInitialized;
// Mode stuff
GLOBAL BOOL _r3d_gbWindowed;
GLOBAL DWORD _r3d_dwRenderWidth;
GLOBAL DWORD _r3d_dwRenderHeight;
GLOBAL DWORD _r3d_dwRGBBitCount;
GLOBAL DWORD _r3d_dwRBitMask;
GLOBAL DWORD _r3d_dwGBitMask;
GLOBAL DWORD _r3d_dwBBitMask;
// End of Mode stuff
GLOBAL RECT _r3d_rcScreenRect; // Screen rect for window
GLOBAL RECT _r3d_rcViewportRect; // Offscreen rect for VPort
GLOBAL DDPIXELFORMAT _r3d_ddpfZBuffer;
GLOBAL unsigned long *_r3d_ScanLineLookUpTable; // Allocated to width of back buffer... This is used for 2DBlit optimization
GLOBAL float _r3d_gfFarClipPlane;
GLOBAL HWND _r3d_ghWnd;
GLOBAL HINSTANCE _r3d_ghInst;
GLOBAL float _r3d_SunX, _r3d_SunY, _r3d_SunZ;
GLOBAL float _r3d_SunR, _r3d_SunG, _r3d_SunB;
GLOBAL float _r3d_AmbientR, _r3d_AmbientG, _r3d_AmbientB;
GLOBAL float _r3d_gfFov;
GLOBAL _R3D_MATRIX _r3d_World;
GLOBAL _R3D_MATRIX _r3d_View;
GLOBAL D3DMATRIX _r3d_Projection;
GLOBAL LARGE_INTEGER _r3d_gliStart, _r3d_gliFreq;
GLOBAL unsigned long _r3d_set_tick, _r3d_current_tick;
GLOBAL unsigned long _r3d_set_current_tick;
GLOBAL int _r3d_change_tick;
GLOBAL unsigned long _r3dShareware_set_tick, _r3dShareware_current_tick;
GLOBAL unsigned long _r3dShareware_set_current_tick;
GLOBAL int _r3dShareware_change_tick;
GLOBAL long _r3d_lTotalPolygonsRendered;
GLOBAL BOOL _r3d_bInsideRenderBeginEnd;
GLOBAL _R3D_SURFACE *_r3d_Surface[_R3D_MAX_SURFACES];
GLOBAL BOOL _r3d_bSurfaceDoesNotExist[_R3D_MAX_SURFACES];
GLOBAL _R3D_DDSURFACE *_r3d_DDSurface[_R3D_MAX_DDSURFACES];
GLOBAL BOOL _r3d_bDDSurfaceDoesNotExist[_R3D_MAX_DDSURFACES];
GLOBAL _R3D_2DBEGINEND _r3d_2DBeginEnd;
GLOBAL BOOL _r3d_EnumerateProcessed;
GLOBAL BOOL _r3d_bColorKeyedTexturingSupport;
GLOBAL unsigned long _r3d_dwMinTextureWidthHeight, _r3d_dwMaxTextureWidthHeight;
GLOBAL _R3D_TEXTUREFORMATLIST _r3d_TextureFormatList[_R3D_MAXTEXTUREFORMATS]; // Index is one of the above defined  _R3D_TEXTUREFORMAT_###? formats
GLOBAL BOOL _r3d_gbLuminanceAlphaSupport;
GLOBAL int _r3d_SolidTextureFormat; // One of the above defined _R3D_TEXTUREFORMAT_###? formats
GLOBAL int _r3d_TranslucentTextureFormat; // One of the above defined _R3D_TEXTUREFORMAT_###? formats
GLOBAL _R3D_STATE _r3d_state;
GLOBAL BOOL gbForceAlpha;
GLOBAL int _r3d_SetMaterialLast;
GLOBAL unsigned long _r3d_dwSavedMinX, _r3d_dwSavedMaxX, _r3d_dwSavedMinY, _r3d_dwSavedMaxY;
GLOBAL float _r3d_BackGroundRed, _r3d_BackGroundGreen, _r3d_BackGroundBlue;
GLOBAL char *_r3d_lpApplicationName;
GLOBAL int _r3d_2DClipMinX, _r3d_2DClipMinY, _r3d_2DClipMaxX, _r3d_2DClipMaxY;
GLOBAL int _r3d_MaterialHandleLast;
GLOBAL BOOL _r3d_gbRenderItSortsAlphaPolys;

// Internal Macros
GLOBAL HRESULT _r3d_hResult;
GLOBAL char _r3d_strError[4096];
#define _R3D_FINTERPOLATE(_xa_,_ya_,_xb_,_yb_,_y_,_xresult_) (_xresult_)=((_xa_)+((((_xb_)-(_xa_))*((_y_)-(_ya_))) / ((_yb_)-(_ya_)) ))
#define _R3D_MAX(a,b) ((a)>(b)?(a):(b))
#define _R3D_MIN(a,b) ((a)<(b)?(a):(b))