/*
	File	:	picture.cpp
	Author	:	Richard Flower (c) 1998 Core Design
	----------------------------------------------------------------------------------
	Functions
	----------------------------------------------------------------------------------


	
	----------------------------------------------------------------------------------
*/


#include "standard.h"
#include "global.h"
#include "picture.h"
#include "winmain.h"
#include "hwrender.h"
#include "drawprimitive.h"
#include "scanlines.h"
#include "texture.h"


DXTEXTURE PicTextureList[MAX_D3D_TEXTURES];


/*
	Function	:	LoadPicture
	Useage		:   Loads BMP Picture Into Surface
*/

bool LoadPicture(char* File,LPDIRECTDRAWSURFACE3 lpPictureBuffer,int Flag)
{
		BITMAP              bm;
		HBITMAP             Bitmap;
		HDC					BitmapDC;
		HDC					SurfaceDC;
		
		// ToDo : Sort Pictures For 8 Bit

		if(DXD3DTexture(App.DeviceInfoPtr,App.DXConfigPtr).bPalette)
			return true;

		Bitmap = (HBITMAP) LoadImage(NULL,File,IMAGE_BITMAP,0,0,LR_LOADFROMFILE|LR_CREATEDIBSECTION);
		if(Bitmap == NULL) return false;
		BitmapDC = CreateCompatibleDC(NULL);
		SelectObject(BitmapDC,Bitmap);
		GetObject(Bitmap,sizeof(bm),&bm);
		lpPictureBuffer->GetDC(&SurfaceDC);
		BitBlt(SurfaceDC,0,0,bm.bmWidth,bm.bmHeight,BitmapDC,0,0,SRCCOPY);
		lpPictureBuffer->ReleaseDC(SurfaceDC);

		Log("LoadPicture : %s",File);
		
		if(Flag)
			ConvertSurfaceToTextures(lpPictureBuffer);
		
		return true;
}

// EOF : LoadPicture


/*
	Function	:	FreePictureTextures
	Useage		:	Release Picture Texture Handles
*/

void FreePictureTextures()
{
	DXTextureFinish(PicTextureList);
}

// EOF : FreePictureTextures


/*
	Function	:	MemBlt
	Useage		:	Memcpy for Picture Sections (short*)
*/

void MemBlt(unsigned short* pDest,int nDX,int nDY,int nDW,int nDH,int nDStride,unsigned short* pSrc,int nSX,int nSY,int nSStride)
{
	pDest+= nDX+(nDY*nDStride);
	pSrc += nSX+(nSY*nSStride);
	while (nDH--)
	{
		memcpy(pDest,pSrc,nDW*sizeof(short));
		pDest+=nDStride;
		pSrc+=nSStride;
	}
}

// EOF : MemBlt


void ConvertSurfaceToTextures(LPDIRECTDRAWSURFACE3 lpSurface)
{
	if(DXD3DTexture(App.DeviceInfoPtr,App.DXConfigPtr).bPalette)
		return;
	
	ConvertSurfaceToTextures16Bit(lpSurface);
}



/*
	Function	:	ConvertSurfaceToTextures
	Useage		:	Convert lpSurface into Textures
*/

void ConvertSurfaceToTextures16Bit(LPDIRECTDRAWSURFACE3 lpSurface)
{
	unsigned short* pTPage,*pImage;
	pTPage = (unsigned short*) malloc(sizeof(short)*256*256);
	if(pTPage != NULL)
	{
		
		DDSURFACEDESC ddsd;
		DXInit(ddsd);
		lpSurface->Lock(NULL,&ddsd,DDLOCK_NOSYSLOCK|DDLOCK_WAIT,NULL);	
		pImage = (unsigned short*) ddsd.lpSurface;
	
		unsigned char rshift,gshift,bshift;
		unsigned char rbpp,gbpp,bbpp;
			
		DXBitMask2ShiftCnt(ddsd.ddpfPixelFormat.dwRBitMask,&rshift,&rbpp);
		DXBitMask2ShiftCnt(ddsd.ddpfPixelFormat.dwGBitMask,&gshift,&gbpp);
		DXBitMask2ShiftCnt(ddsd.ddpfPixelFormat.dwBBitMask,&bshift,&bbpp);

		int BitMask;
		BitMask = (rbpp*100)+(gbpp*10)+bbpp;

		DXTextureInit(PicTextureList,0);
	
		MemBlt(pTPage,0,0,256,256,256,pImage,0,0,ddsd.lPitch>>1);
		
		lpSurface->Unlock(NULL);
			
		DXTextureAdd(256,256,pTPage,PicTextureList,BitMask);
		
		DXInit(ddsd);
		lpSurface->Lock(NULL,&ddsd,DDLOCK_NOSYSLOCK|DDLOCK_WAIT,NULL);	
		pImage = (unsigned short*) ddsd.lpSurface;
		
		MemBlt(pTPage,0,0,256,256,256,pImage,256,0,ddsd.lPitch>>1);
			
		lpSurface->Unlock(NULL);
			
		DXTextureAdd(256,256,pTPage,PicTextureList,BitMask);
	
		DXInit(ddsd);
		lpSurface->Lock(NULL,&ddsd,DDLOCK_NOSYSLOCK|DDLOCK_WAIT,NULL);	

		pImage = (unsigned short*) ddsd.lpSurface;
		MemBlt(pTPage,0,0,128,256,256,pImage,512,0,ddsd.lPitch>>1);
		MemBlt(pTPage,128,0,128,224,256,pImage,512,256,ddsd.lPitch>>1);
					
		lpSurface->Unlock(NULL);
		DXTextureAdd(256,256,pTPage,PicTextureList,BitMask);
		
		DXInit(ddsd);
		lpSurface->Lock(NULL,&ddsd,DDLOCK_NOSYSLOCK|DDLOCK_WAIT,NULL);	
		pImage = (unsigned short*) ddsd.lpSurface;
						
		MemBlt(pTPage,0,0,256,224,256,pImage,0,256,ddsd.lPitch>>1);
		
		lpSurface->Unlock(NULL);
		
		DXTextureAdd(256,256,pTPage,PicTextureList,BitMask);
			
		DXInit(ddsd);
		lpSurface->Lock(NULL,&ddsd,DDLOCK_NOSYSLOCK|DDLOCK_WAIT,NULL);	
		pImage = (unsigned short*) ddsd.lpSurface;
					
		MemBlt(pTPage,0,0,256,224,256,pImage,256,256,ddsd.lPitch>>1);
			
		lpSurface->Unlock(NULL);

		DXTextureAdd(256,256,pTPage,PicTextureList,BitMask);
		
		free(pTPage);
	}
	else
		Log("ConvertPictureToTexture: Failed To Allocate Temp Texture Page");
}

// EOF : ConvertPictureToTextures



/*
	Function	:	DrawTile
	Useage		:	Display A Single Tile
*/

void DrawTile(int nDX,int nDY,int nDW,int nDH,int hTPage,int nSX,int nSY,int nSW,int nSH,uint32 dwV0C,uint32 dwV1C,uint32 dwV2C,uint32 dwV3C)
{
	D3DTLVERTEX v[4];
	float fX1,fY1,fX2,fY2;
	float fU1,fV1,fU2,fV2;
	float fZ,fRHW;

	fX1=float(nDX);
	fY1=float(nDY);
	fX2=float(nDX+nDW);
	fY2=float(nDY+nDH);
	fU1=float(nSX)*(1.0f/256.0f);
	fV1=float(nSY)*(1.0f/256.0f);
	fU2=float(nSX+nSW)*(1.0f/256.0f);
	fV2=float(nSY+nSH)*(1.0f/256.0f);
	float fAdd= float(App.nUVAdd)*(1.0f/65536.0f);
	fU1+=fAdd;
	fV1+=fAdd;
	fU2-=fAdd;
	fV2-=fAdd;
	fZ=0.995f;
	fRHW=one/f_zfar;
	v[0].sx=fX1; v[0].sy=fY1; v[0].sz=fZ; v[0].rhw=fRHW; v[0].color=dwV0C; v[0].specular=0; v[0].tu=fU1; v[0].tv=fV1;
	v[1].sx=fX2; v[1].sy=fY1; v[1].sz=fZ; v[1].rhw=fRHW; v[1].color=dwV1C; v[1].specular=0; v[1].tu=fU2; v[1].tv=fV1;
	v[2].sx=fX1; v[2].sy=fY2; v[2].sz=fZ; v[2].rhw=fRHW; v[2].color=dwV2C; v[2].specular=0; v[2].tu=fU1; v[2].tv=fV2;
	v[3].sx=fX2; v[3].sy=fY2; v[3].sz=fZ; v[3].rhw=fRHW; v[3].color=dwV3C; v[3].specular=0; v[3].tu=fU2; v[3].tv=fV2;
	HWR_SetCurrentTexture(hTPage);
	HWR_EnableColorKey(false);
	DrawPrimitive(D3DPT_TRIANGLESTRIP,D3DVT_TLVERTEX,v,4,D3DDP_DONOTCLIP|D3DDP_DONOTUPDATEEXTENTS);
}

// EOF : DrawTile



/*
	Function	:	DrawPicture
	Useage		:	Draw Picture From Picture Texture Tiles
*/

void DrawPicture()
{
	static int anVirtualX[4]={0,256,512,640},anVirtualY[3]={0,256,480};
	int anX[4],anY[4];
	int nW,nH,nCoord;
	
	// ToDo : Sort Pictures For 8 Bit

	if(DXD3DTexture(App.DeviceInfoPtr,App.DXConfigPtr).bPalette)
		return;

	nW = phd_winwidth;
	nH = phd_winheight;

	for (nCoord=0;nCoord<3;++nCoord)
	{
		anX[nCoord]=(anVirtualX[nCoord]*nW)/640+phd_winxmin;
		anY[nCoord]=(anVirtualY[nCoord]*nH)/480+phd_winymin;
	}
	anX[3]=(anVirtualX[3]*nW)/640+phd_winxmin;

	HWR_EnableZBuffer(false,false);

	bForceAffineMap = 1;

	DrawTile(anX[0],anY[0],anX[1]-anX[0],anY[1]-anY[0],DXTextureGetHandle(0,PicTextureList),0,0,256,256,0xffffffff,0xffffffff,0xffffffff,0xffffffff);
	DrawTile(anX[1],anY[0],anX[2]-anX[1],anY[1]-anY[0],DXTextureGetHandle(1,PicTextureList),0,0,256,256,0xffffffff,0xffffffff,0xffffffff,0xffffffff);
	DrawTile(anX[2],anY[0],anX[3]-anX[2],anY[1]-anY[0],DXTextureGetHandle(2,PicTextureList),0,0,128,256,0xffffffff,0xffffffff,0xffffffff,0xffffffff);
	DrawTile(anX[0],anY[1],anX[1]-anX[0],anY[2]-anY[1],DXTextureGetHandle(3,PicTextureList),0,0,256,224,0xffffffff,0xffffffff,0xffffffff,0xffffffff);
	DrawTile(anX[1],anY[1],anX[2]-anX[1],anY[2]-anY[1],DXTextureGetHandle(4,PicTextureList),0,0,256,224,0xffffffff,0xffffffff,0xffffffff,0xffffffff);
	DrawTile(anX[2],anY[1],anX[3]-anX[2],anY[2]-anY[1],DXTextureGetHandle(2,PicTextureList),128,0,128,224,0xffffffff,0xffffffff,0xffffffff,0xffffffff);

	bForceAffineMap = 0;

	HWR_EnableZBuffer(true,true);
}

// EOF : DrawPicture




void FadePictureUp()
{
	int n;
	float sw = float(DXDisplayMode(App.DeviceInfoPtr,App.DXConfigPtr).w);
	float sh = float(DXDisplayMode(App.DeviceInfoPtr,App.DXConfigPtr).h);
	
	D3DTLVERTEX v[4];
	
	v[0].sx = 0;
	v[0].sy = 0;
	v[0].sz = 0;
	v[0].specular = 0;
	
	v[1].sx = sw;
	v[1].sy = 0;
	v[1].sz = 0;
	v[1].specular = 0;
	
	v[2].sx = 0;
	v[2].sy = sh;
	v[2].sz = 0;
	v[2].specular = 0;

	v[3].sx = sw;
	v[3].sy = sh;
	v[3].sz = 0;
	v[3].specular = 0;


	IDirectDrawSurface3* pSrcSurf;

	for(n=0;n<32;n++)
	{
		int a;
		a = 255-((256/32)*n);
		v[0].color = RGBA_MAKE(0,0,0,a);
		v[1].color = RGBA_MAKE(0,0,0,a);
		v[2].color = RGBA_MAKE(0,0,0,a);
		v[3].color = RGBA_MAKE(0,0,0,a);
	
		HWR_BeginScene();

		DrawPicture();
		
		HWR_SetCurrentTexture(0);	
		App.lpD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE,true);
		App.lpD3DDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND,D3DBLEND_SRCALPHA);
		App.lpD3DDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND,D3DBLEND_INVSRCALPHA);
		DrawPrimitive(D3DPT_TRIANGLESTRIP,D3DVT_TLVERTEX,&v,4,D3DDP_DONOTCLIP|D3DDP_DONOTUPDATEEXTENTS);
		App.lpD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE,false);
		HWR_EndScene();
		
		if(DXD3D(App.DeviceInfoPtr,App.DXConfigPtr).bHardware)
			App.lpFrontBuffer->Flip(NULL,DDFLIP_WAIT);
		else
		{
			pSrcSurf= App.lpBackBuffer;
			App.lpFrontBuffer->Blt(NULL,pSrcSurf,NULL,DDBLT_WAIT,NULL);
		}
	}
	
	DrawPicture();
	
	if(DXD3D(App.DeviceInfoPtr,App.DXConfigPtr).bHardware)
		App.lpFrontBuffer->Flip(NULL,DDFLIP_WAIT);
	else
	{
		pSrcSurf= App.lpBackBuffer;
		App.lpFrontBuffer->Blt(NULL,pSrcSurf,NULL,DDBLT_WAIT,NULL);
	}
}


void FadePictureDown()
{
	int n;
	float sw = float(DXDisplayMode(App.DeviceInfoPtr,App.DXConfigPtr).w);
	float sh = float(DXDisplayMode(App.DeviceInfoPtr,App.DXConfigPtr).h);
	D3DTLVERTEX v[4];

	v[0].sx = 0;
	v[0].sy = 0;
	v[0].sz = 0;
	v[0].specular = 0;
	
	v[1].sx = sw;
	v[1].sy = 0;
	v[1].sz = 0;
	v[1].specular = 0;
	
	v[2].sx = 0;
	v[2].sy = sh;
	v[2].sz = 0;
	v[2].specular = 0;

	v[3].sx = sw;
	v[3].sy = sh;
	v[3].sz = 0;
	v[3].specular = 0;

	IDirectDrawSurface3* pSrcSurf;
	
	for(n=32;n>0;n--)
	{
		int a;
		a = 255-(((256/32)*n)-1);
		v[0].color = RGBA_MAKE(0,0,0,a);
		v[1].color = RGBA_MAKE(0,0,0,a);
		v[2].color = RGBA_MAKE(0,0,0,a);
		v[3].color = RGBA_MAKE(0,0,0,a);
		HWR_BeginScene();

		DrawPicture();

		HWR_SetCurrentTexture(0);
		App.lpD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE,true);
		App.lpD3DDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND,D3DBLEND_SRCALPHA);
		App.lpD3DDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND,D3DBLEND_INVSRCALPHA);
		DrawPrimitive(D3DPT_TRIANGLESTRIP,D3DVT_TLVERTEX,&v,4,D3DDP_DONOTCLIP|D3DDP_DONOTUPDATEEXTENTS);
		
		App.lpD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE,false);

		HWR_EndScene();

		if(DXD3D(App.DeviceInfoPtr,App.DXConfigPtr).bHardware)
			App.lpFrontBuffer->Flip(NULL,DDFLIP_WAIT);
		else
		{
			pSrcSurf= App.lpBackBuffer;
			App.lpFrontBuffer->Blt(NULL,pSrcSurf,NULL,DDBLT_WAIT,NULL);
		}
	}
	
	v[0].color = RGBA_MAKE(0,0,0,255);
	v[1].color = RGBA_MAKE(0,0,0,255);
	v[2].color = RGBA_MAKE(0,0,0,255);
	v[3].color = RGBA_MAKE(0,0,0,255);
	
	HWR_BeginScene();
	HWR_SetCurrentTexture(0);
	App.lpD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE,true);
	App.lpD3DDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND,D3DBLEND_SRCALPHA);
	App.lpD3DDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND,D3DBLEND_INVSRCALPHA);
	DrawPrimitive(D3DPT_TRIANGLESTRIP,D3DVT_TLVERTEX,&v,4,D3DDP_DONOTCLIP|D3DDP_DONOTUPDATEEXTENTS);
	App.lpD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE,false);
	HWR_EndScene();

	if(DXD3D(App.DeviceInfoPtr,App.DXConfigPtr).bHardware)
		App.lpFrontBuffer->Flip(NULL,DDFLIP_WAIT);
	else
	{
		pSrcSurf= App.lpBackBuffer;
		App.lpFrontBuffer->Blt(NULL,pSrcSurf,NULL,DDBLT_WAIT,NULL);
	}

	FreePictureTextures();
}





void CreateMonoScreen()
{
	DXTextureSetGreyScale(true);

	if(DXD3D(App.DeviceInfoPtr,App.DXConfigPtr).bHardware)
	{
		// Release First HW Device 5 Texture Pages
//		DXTextureReleaseDeviceSurface(DXTextureList[0]);
//		DXTextureReleaseDeviceSurface(DXTextureList[1]);
//		DXTextureReleaseDeviceSurface(DXTextureList[2]);
//		DXTextureReleaseDeviceSurface(DXTextureList[3]);
//		DXTextureReleaseDeviceSurface(DXTextureList[4]);
	}
		
	int w = DXDisplayMode(App.DeviceInfoPtr,App.DXConfigPtr).w;
	int h = DXDisplayMode(App.DeviceInfoPtr,App.DXConfigPtr).h;

	if(w == 640 && h == 480)
		ConvertSurfaceToTextures(App.lpFrontBuffer);
	else
	{
		App.lpPictureBuffer->Blt(NULL,App.lpFrontBuffer,NULL,DDBLT_WAIT,NULL);
		ConvertSurfaceToTextures(App.lpPictureBuffer);
	}
	
	DXTextureSetGreyScale(false);
}


void DrawMonoScreen()
{
	DrawPicture();
	HWR_EnableZBuffer(true,true);
}



void RemoveMonoScreen(int fade)
{
	if(fade)
		FadePictureDown();
	
	FreePictureTextures();	

	if(DXD3D(App.DeviceInfoPtr,App.DXConfigPtr).bHardware)
	{
		// Recreate First Five Texture Pages
		
//		DXTextureMakeDeviceSurface(DXTextureList[0]);
//		DXTextureMakeDeviceSurface(DXTextureList[1]);
//		DXTextureMakeDeviceSurface(DXTextureList[2]);
//		DXTextureMakeDeviceSurface(DXTextureList[3]);
//		DXTextureMakeDeviceSurface(DXTextureList[4]);

//		DXTextureRestore(0,true,DXTextureList);
//		DXTextureRestore(1,true,DXTextureList);
//		DXTextureRestore(2,true,DXTextureList);
//		DXTextureRestore(3,true,DXTextureList);
//		DXTextureRestore(4,true,DXTextureList);
	}
}










