#ifndef _GLOBAL_H_
#define _GLOBAL_H_

#include "../game/anim.h"
#include "debug.h"


#define XYZ	3
#define X	0
#define Y   1
#define Z   2


#define DPQ_S (DPQ_START<<W2V_SHIFT)
#define DPQ_E (DPQ_END<<W2V_SHIFT)

#define S_CalculateStaticMeshLight(x, y, z, shade, shadeB, r) S_CalculateStaticLight(shade)


#ifdef __cplusplus
extern "C" {
#endif

#ifndef DONT_DEFINE_DBLOG
#ifdef DBLOG
void __cdecl DB_Log(char* format,...);
#define Log DB_Log
#else
#define Log 0&&
#endif
#endif



typedef unsigned char	uint8;
typedef signed char		sint8;
typedef unsigned short	uint16;
typedef signed short	sint16;
typedef unsigned long	uint32;
typedef signed long		sint32;

#ifndef NULL
#define NULL ((void*)0)
#endif

enum
{
	RENDERER_INTERNAL,
	RENDERER_HAL
};


#define global		extern
#define local		static
#define defglobal     

#define S_GOURAUD_COL(a,b,c,S) ((512-S)<<4)

#define ArraySize(a) (sizeof(a)/sizeof((a)[0]))
#define Zero(thing) memset(&(thing),0,sizeof(thing))

extern RECT GrcDumpWindow;

extern uint8		game_palette[];
extern sint16		Option_SoundFX_Volume;
extern sint16		Option_Music_Volume;
extern int			game_closedown;
extern SETUP		game_setup;
extern int			sound_active;

extern sint16 	*mesh_base;


enum game_malloc_types
{
	TEMP_ALLOC,
	TEXTURE_PAGES,
	MESH_POINTERS,
	MESHES,
	ANIMS,
	STRUCTS,
	RANGES,
	COMMANDS,
	BONES,
	FRAMES,
	ROOM_TEXTURES,
	ROOM_INFOS,
	ROOM_MESH,
	ROOM_DOOR,
	ROOM_FLOOR,
	ROOM_LIGHTS,
	ROOM_STATIC_MESH_INFOS,
	FLOOR_DATA,
	ITEMS,
	CAMERAS,
	SOUND_FX,
	BOXES,
	OVERLAPS,
	GROUNDZONE,
	FLYZONE,
	ANIMATING_TEXTURE_RANGES,
	CINEMATIC_FRAMES,
	LOADDEMO_BUFFER,
	SAVEDEMO_BUFFER,
	CINEMATIC_EFFECTS,
	MUMMY_HEAD_TURN,
	EXTRA_DOOR_STUFF,
	EFFECTS_ARRAY,
	CREATURE_DATA,
	CREATURE_LOT,
	SAMPLEINFOS,
	SAMPLES,
	SAMPLEOFFSETS,
	ROLLINGBALL_STUFF,
	SKIDOO_STUFF,
	LOAD_PICCY_BUFFER,
	FMV_BUFFERS,
	POLYGON_BUFFERS,
	ORDER_TABLES,
	CLUTS,
	TEXTURE_INFOS,
	SPRITE_INFOS,
	NUM_MALLOC_TYPES
};

#define RELEASE_NOLOG(x) if (x) {(x)->Release();(x)=0;}
#define RELEASE_LOGTYPE(x,lt) if (x) {int nRef=(x)->Release();Log((lt),"Releasing " #x " -> %d",nRef);(x)=0;}
#define RELEASE(x) RELEASE_LOGTYPE(x,LT_Release)

extern int framedump;

#ifdef __cplusplus


char* ERR_Describe_DX(HRESULT error);

inline bool DX_TRY(HRESULT hr)
	{
	if (SUCCEEDED(hr))
		return false;
	Log(ERR_Describe_DX(hr));
	return true;
	}


extern bool GtWindowClosed;




bool DX_CheckForLostSurfaces(void);
bool DD_SpinMessageLoop(bool tWait=false);
void DX_DoFlipWait();
void DX_ClearBuffers(DWORD dwClrFlags,DWORD dwColour=0);


#define DXCB_FRONT 1
#define DXCB_BACK 2
#define DXCB_THIRD 4
#define DXCB_ZBUFFER 8
#define DXCB_RENDER 16
#define DXCB_PICTURE 32
#define DXCB_CLIENT 64
#define DXCB_CLRWINDOW 256

int	DecompPCX(uint8* pSrc,int nLength,uint8* pDest,uint8* pPalette);
bool DD_CopyBitmapToSurface(IDirectDrawSurface3* pSurf,void* pSrc);
void SWR_Make236Palette(uint8* pSrc,uint8* pImage,int nPixels,uint8* pDest);

inline bool DX_FAILED(HRESULT hr)
	{
	return FAILED(hr);
	}

HRESULT DD_LockSurface(IDirectDrawSurface3* pSurf,DDSURFACEDESC& rDDSD,DWORD dwFlags=DDLOCK_WAIT|DDLOCK_WRITEONLY);
void SWR_ConvertImage(uint8* pSrc,int nSX,int nSY,int nSP,uint8* pOldPalette,uint8* pDest,int nDP,uint8* pNewPalette,bool tDontUseWindowsColours=false);
HRESULT DD_UnlockSurface(IDirectDrawSurface3* pSurf,DDSURFACEDESC& rDDSD);
bool DX_UpdateFrame(bool tSpinMessageLoop=true,RECT* prcWindow=0);
bool DD_ClearSurface(IDirectDrawSurface3* pSurf,RECT* pRect=0,DWORD dwColour=0);

struct PixelFormat
	{
	DWORD dwRMask,dwGMask,dwBMask,dwAMask;
	int nRBits,nGBits,nBBits,nABits;
	int nRShift,nGShift,nBShift,nAShift;
	void SetFromDDPF(DDPIXELFORMAT& rDDPF);
	};

HRESULT DD_EnsureSurfaceAvailable(IDirectDrawSurface3* pSurf,IDirectDrawSurface3* pTopSurf=0,bool tClearIfLost=false);
HRESULT DD_CreateSurface(DDSURFACEDESC& ddsd,IDirectDrawSurface3*& rpSurf);

extern char* GpCmdLine;
void		setup_screen_size		();
extern bool GtFullScreenClearNeeded;
int			GameMain				();

uint8 SWR_FindNearestPaletteEntry(uint8* pPal,int nR,int nG,int nB,bool tDontUseWindowsColours=false);

#endif


sint32	GetRandomDraw				(void);
void	SeedRandomDraw				(sint32 seed);
sint32	GetRandomControl			(void);
void	SeedRandomControl			(sint32 seed);

void		S_SeedRandom			(void);
void SaveDDBuffer(IDirectDrawSurface3 *pSurf);


int Sync(void);


extern OBJECT_INFO 	objects[];

extern int 			wet;
extern uint8		water_palette[];
extern sint16*		aranges;


enum InitResult	// possible initialisation results
	{
	INIT_OK,

	INIT_ERR_PreferredAdapterNotFound,
	INIT_ERR_CantCreateWindow,
	INIT_ERR_CantCreateDirectDraw,
	INIT_ERR_CantInitRenderer,
	INIT_ERR_CantCreateDirectInput,
	INIT_ERR_CantCreateKeyboardDevice,
	INIT_ERR_CantSetKBCooperativeLevel,
	INIT_ERR_CantSetKBDataFormat,
	INIT_ERR_CantAcquireKeyboard,
	INIT_ERR_CantSetDSCooperativeLevel,

	INIT_ERR_DD_SetExclusiveMode,
	INIT_ERR_DD_ClearExclusiveMode,
	INIT_ERR_SetDisplayMode,
	INIT_ERR_CreateScreenBuffers,
	INIT_ERR_GetBackBuffer,
	INIT_ERR_CreatePalette,
	INIT_ERR_SetPalette,
	INIT_ERR_CreatePrimarySurface,
	INIT_ERR_CreateBackBuffer,
	INIT_ERR_CreateClipper,
	INIT_ERR_SetClipperHWnd,
	INIT_ERR_SetClipper,
	INIT_ERR_CreateZBuffer,
	INIT_ERR_AttachZBuffer,
	INIT_ERR_CreateRenderBuffer,
	INIT_ERR_CreatePictureBuffer,
	INIT_ERR_D3D_Create,
	INIT_ERR_CreateDevice,
	INIT_ERR_CreateViewport,
	INIT_ERR_AddViewport,
	INIT_ERR_SetViewport2,
	INIT_ERR_SetCurrentViewport,

	INIT_ERR_ClearRenderBuffer,
	INIT_ERR_UpdateRenderInfo,
	INIT_ERR_GetThirdBuffer,

	INIT_ERR_GoFullScreen,
	INIT_ERR_GoWindowed,

	INIT_ERR_WrongBitDepth,
	INIT_ERR_GetPixelFormat,
	INIT_ERR_GetDisplayMode
	};



#ifdef DBLOG
	#define RELEASEARRAY(x) {int n=0; for (int i=0;i<ArraySize(x);++i) if ((x)[i]) {(x)[i]->Release();(x)[i]=0;++n;} Log(LT_Release,"Released %d of "#x"[%d]",n,ArraySize(x));}
#else
	#define RELEASEARRAY(x) for (int i=0;i<ArraySize(x);++i) if ((x)[i]) {(x)[i]->Release();(x)[i]=0;}
#endif

#define InitDXStruct(s) memset(&(s),0,sizeof(s)),(s).dwSize=sizeof(s)
#define ZeroArray(a) memset((a),0,sizeof(a))


/*** specific.cpp ***/
#define		ERR_SOUND_NOT_ENABLED	(-3)
#define		ERR_SOUND_FAILED		(-2)
#define		ERR_SOUND_NO_FREE_SLOTS	(-1)

sint32		S_SoundPlaySample(int nSample,uint16 wVol,int nPitch,sint16 wPan);
sint32		S_SoundPlaySampleLooped(int nSample,uint16 wVol,int nPitch,sint16 wPan);
sint32		S_SoundSampleIsPlaying(sint32 handle);
void 		S_SoundStopAllSamples(void);
void	 	S_SoundStopSample(sint32 handle);
void		S_SoundSetPanAndVolume(sint32 handle, sint16 wPan, uint16 newvol);
void		S_SoundSetPitch(sint32 handle,int nPitch);
void		S_SoundSetMasterVolume(int nVolume);

void		S_CDPlay				(sint16 track,int mode);
void		S_CDLoop				(void);
void		S_CDStop				(void);
void		S_CDPause				(void);
void		S_CDRestart				(void);
int		S_StartSyncedAudio		(int num);
void		S_UpdateSyncedAudio		(void);
void		S_CDVolume				(int volume);
int		S_CDGetLoc				(void);

void SetCutsceneTrack( int track );
void SetCutscene( int cut );
void SetCutsceneAngle( int angle );

/*** display.cpp ***/
void 		TempVideoAdjust			(int hires,double sizer);


extern int	hires_flag, game_hires, detail_level;

void		FadeToPal				(int nframes,uint8* pal);


extern char			exit_message[];
extern double		screen_sizer, game_sizer;

extern void S_ExitSystem(char *message);


extern	char*		malloc_buffer;
extern	int			script_malloc_size;
extern	int			malloc_size;
extern	int			malloc_free,malloc_used;
extern	char*		malloc_ptr;

extern int 				level_complete;






extern int record_demo;


extern int GnDirectDrawLocks;

#define EndOfArray(a) ((a)+ArraySize(a))




#ifdef __cplusplus
}
#endif


#endif