/*---------------------------------------------------------------------------
 *	Import Headers
\*--------------------------------------------------------------------------*/

#include <sys\types.h>
#include <libgte.h>
#include <libgpu.h>
#include <libetc.h>
#include "typedefs.h"
#include "file.h"
#include "malloc.h"
#include "gpu.h"
#include "3d_gen.h"
#include "psxinput.h"
#include "memory.h"
#include "picture.h"
#include "specific.h"
#include "..\game\input.h"
#include "..\game\text.h"

extern void unpack(char*, char*);

/*---------------------------------------------------------------------------
 *	Constants
\*--------------------------------------------------------------------------*/

#define PIC_VRAMX	512
#define PIC_VRAMY	256

#define PIC_WIDTH		512
#define PIC_HEIGHT  	256
#define MAX_PACKED_SIZE	170000
#define PIC_SIZE		(MAX_PACKED_SIZE + ((PIC_WIDTH*PIC_HEIGHT)*2))

/*---------------------------------------------------------------------------
 *	Locals
\*--------------------------------------------------------------------------*/

static int LnFadeValue=FADE_MAX;
static int LnFadeTarget=FADE_MAX;
static int LnFadeDelta=32768;
static RECT LrcPic = { PIC_VRAMX, PIC_VRAMY, PIC_WIDTH, PIC_HEIGHT };

#if defined(CREATE_MOVIE) || defined(SNAPSHOT)
static int pic_save_num=0;	// handy static var for which picture file to save (ie pic0000.raw)
#endif

/*---------------------------------------------------------------------------
 *	Globals
\*--------------------------------------------------------------------------*/

char fades_enabled=1;

/*---------------------------------------------------------------------------
 *	Local Functions
\*--------------------------------------------------------------------------*/

static int ShowPic(int nframes, int quit)
{
	int i, ret=0;

	S_FadeUp();

	for ( i=0 ; i<nframes ; i++ )
	{
		if (quit)
		{
			S_UpdateInput();

			if (input & IN_PAUSE)
			{
				ret = 1;
				break;
			}
			else if (input)
				break;
		}

		S_InitialisePolyList();
		S_DrawPic();
		T_DrawText();
		S_OutputPolyList();
		S_DumpScreen();
	}
	S_FadeToBlack();
	return(ret);
}


#if defined(CREATE_MOVIE) || defined(SNAPSHOT)

#define MAX_PICS			(30*20)							// this is the MAX number of pics it will saveout.
#define PSX_SCREEN_BUFFER	0x400000					// this is where the original psx screen data gets shoved...
#define RAW_SCREEN_BUFFER	0x500000					// this is where the original psx screen data gets shoved...
#define TGA_FORMAT

#ifdef SAVE_TEXTUREPAGE
#define PIC_SIZEX 1024
#define PIC_SIZEY 512
#else
#ifdef NTSC
#define PIC_SIZEX 512
#define PIC_SIZEY 240
#else
#define PIC_SIZEX 512
#define PIC_SIZEY 256
#endif
#endif

#define PIC_PIXELS (PIC_SIZEX*PIC_SIZEY)

#ifndef TGA_FORMAT
#define PIC_SIZE (PIC_PIXELS*3)		// this is the size of the .RAW file that we saveout...
#else
#define PIC_SIZE ((PIC_PIXELS*2)+18)	// this is the size of the .TGA file that we saveout...
#endif

#ifndef TGA_FORMAT
static void make_raw_pic(char* src,char* dst)
{
	u_short* p1;
	u_char* p2;
	int i;

	p1=(u_short*)src;						// source data...
	p2=(u_char*)dst;						// dest data...
	for (i=0;i<(PIC_SIZEX*PIC_SIZEY);++i)
		{
		*(p2++)=((*(p1))&0x1f)<<3;
		*(p2++)=((*(p1)>>5)&0x1f)<<3;
		*(p2++)=((*(p1)>>10)&0x1f)<<3;
		p1++;
		}
	}
#else
static void make_tga_pic(char* src,char* dst)
	{
	int xcnt,ycnt;
	u_short r,g,b;
	u_short* dest1;
	u_short* image;

	dest1=(u_short*)dst;
	dest1[0]=0x0000;
	dest1[1]=0x0002;
	dest1[2]=0x0000;
	dest1[3]=0x0000;
	dest1[4]=0x0000;
	dest1[5]=0x0000;
	dest1[6]=PIC_SIZEX;	//width
	dest1[7]=PIC_SIZEY;	//height
	dest1[8]=0x0110;
	dest1+=9;
	image=((u_short*)src)+((PIC_SIZEY-1)*PIC_SIZEX);		// start at the bottom line...
	for (ycnt=0;ycnt<PIC_SIZEY;ycnt++)
		{
		for (xcnt=0;xcnt<PIC_SIZEX;xcnt++)
   			{
   			r=*image&0x1f;
   			g=(*image>>5)&0x1f;
  			b=(*image>>10)&0x1f;
   			*dest1++=r<<10|g<<5|b;
			image++;
   			}
		image-=(PIC_SIZEX*2);
		}
	}
#endif

void PIC_SaveCurrentScreen()
{
	int i;
	u_long* buffer;
	char namebuf[256];
	u_long* raw_buffer;
	RECT rc = { 0, 0, PIC_SIZEX, PIC_SIZEY };

	if (pic_save_num > MAX_PICS)
	{
		printf("nope, %d is your lot mate! don`t eat my hard-disk space...\n",MAX_PICS);
		return;
	}

#ifndef SAVE_TEXTUREPAGE
	if (db.current_buffer)
		rc.y=256;
#endif

	buffer = (u_long *)PSX_SCREEN_BUFFER;		// space for ((320*256)*2) = $28000 bytes
	raw_buffer = (u_long *)RAW_SCREEN_BUFFER;  	// space for ((320*256)*3) = $3c000 bytes

	StoreImage(&rc,(u_long *)PSX_SCREEN_BUFFER);		// grab the screen into RAM
	DrawSync(0);

#ifndef TGA_FORMAT
	make_raw_pic((char *)PSX_SCREEN_BUFFER,(char *)RAW_SCREEN_BUFFER);
#else
	make_tga_pic((char *)PSX_SCREEN_BUFFER,(char *)RAW_SCREEN_BUFFER);
#endif

	sprintf(&namebuf[0],"e:pic%4d",pic_save_num);

	for (i=0;i<255;i++)
	{
		if (namebuf[i]==0)		// did we reach the end of the filename?
			break;			// exit me!
		if (namebuf[i]==32)		// is this a space?
			namebuf[i]='0';	// fill in spaces in filename with 0's
	}

	namebuf[i]='.';
#ifndef TGA_FORMAT
	namebuf[i+1]='r';
	namebuf[i+2]='a';
	namebuf[i+3]='w';
#else
	namebuf[i+1]='t';
	namebuf[i+2]='g';
	namebuf[i+3]='a';
#endif
	namebuf[i+4]=0;

	printf("Saving '%s'!\n",namebuf);
	FILE_Save(namebuf,(char *)RAW_SCREEN_BUFFER,PIC_SIZE);	// save the RAW file...
	pic_save_num++;
	return;
}

#endif

/*---------------------------------------------------------------------------
 *	Public Functions
\*--------------------------------------------------------------------------*/

void S_CopyScreenToBuffer()
{
	RECT* pRect;

	if (!fades_enabled)
		return;

	pRect = GPU_GetDrawRect(BUF_CURRENT);
	DrawSync(0);
	MoveImage(pRect, PIC_VRAMX, PIC_VRAMY);
	DrawSync(0);
}

void CopyFrontToBack()
{
	RECT *draw, *disp;

	draw = GPU_GetDrawRect(BUF_CURRENT);
	disp = GPU_GetDispRect(BUF_CURRENT);

	DrawSync(0);
	MoveImage(disp, draw->x, draw->y);
	DrawSync(0);
}

void S_DrawPic()
{
	SPRT* p;
	DR_TPAGE* p1;
	u_char fademe;
	uint32* pOT = db.ot+(db.nOTSize-1);

	if (!fades_enabled)
		return;

	if (LnFadeValue != LnFadeTarget)
		LnFadeValue += LnFadeDelta;

	fademe = (128-(LnFadeValue>>12));

	p = (SPRT*)db.polyptr;
	setSprt(p);
	setShadeTex(p, 0);
	p->r0 = p->g0 = p->b0 = fademe;
	p->x0 = p->y0 = p->u0 = p->v0 = 0;
	setWH(p, 256, MY_PSX_H);
	addPrim(pOT, p);

	p1 = (DR_TPAGE*)(p+1);
	setDrawTPage(p1, 1, 1, (getTPage(2, 0, PIC_VRAMX,PIC_VRAMY)));
	addPrim(pOT,p1);

	p=(SPRT*)(p1+1);
	setSprt(p);
	setShadeTex(p,0);
	p->r0=p->g0=p->b0=fademe;
	p->x0=256;
	p->y0=p->u0=p->v0=0;
	setWH(p, 256, MY_PSX_H);

	addPrim(pOT,p);

	p1=(DR_TPAGE*)(p+1);
	setDrawTPage(p1,1,1,(getTPage(2, 0, PIC_VRAMX+256, PIC_VRAMY)));
	addPrim(pOT,p1);

	db.polyptr=(char*)(p1+1);
}

void S_DisplayPictureBuffer(void)
{
	S_InitialisePolyList();
	S_DrawPic();
	S_OutputPolyList();
	S_DumpScreen();
}

void S_InitFade(int nSource,int nDest,int tCopyBuf)
{
	if (!fades_enabled)
		return;

//##	SetGeomScreen(phd_persp);	// DUDE says: what the fuck is this doing in here?

	LnFadeValue=nSource;
	LnFadeTarget=nDest;

	if (LnFadeTarget > LnFadeValue)
		LnFadeDelta = 32768;
	else
		LnFadeDelta = -32768;

	if (tCopyBuf)
		S_CopyScreenToBuffer();
}

void S_FadeToBlack()
{
	if (!fades_enabled)
		return;

	S_InitFade(FADE_MAX, FADE_MIN, 1);
	S_WaitFade();
}

void S_FadeUp()
{
	if (!fades_enabled)
		return;

	S_InitFade(FADE_MIN, FADE_MAX, 0);
	S_WaitFade();
}

void S_WaitFade(void)
{
	if (!fades_enabled)
		return;

	do {
		S_DisplayPictureBuffer();
	} while (LnFadeValue != LnFadeTarget);

	S_DisplayPictureBuffer();
}

sint32 S_DisplayPicture(char *szFileName)
{
	char *pPacked;
	char *pUnpacked;

#ifdef GAMEDEBUG
	printf(__FUNCTION__"(%s)\n", szFileName);
#endif

	GPU_SetHorizontalResolution(512);

	pPacked = game_malloc(PIC_SIZE, LOAD_PICCY_BUFFER);
	pUnpacked = pPacked+MAX_PACKED_SIZE;

	if (szFileName[0]=='!')		// what is this all about?
		return(0);

	FILE_Load(szFileName,pPacked);
	unpack(pPacked,pUnpacked);

#ifdef NTSC
	LrcPic.h = 240;
	LoadImage(&LrcPic,(u_long *)(pUnpacked+(PIC_WIDTH*8*2)));
#else
	LoadImage(&LrcPic,(u_long *)pUnpacked);
#endif
	DrawSync(0);

	game_free(PIC_SIZE, LOAD_PICCY_BUFFER);

	return 1;
}

sint32 S_DisplayPictureMem(char *pPacked)
{
	char* pUnpacked;

	GPU_SetHorizontalResolution(512);

	pUnpacked = game_malloc(((PIC_WIDTH*PIC_HEIGHT)*2), LOAD_PICCY_BUFFER);
	unpack(pPacked,pUnpacked);

#ifdef NTSC
	LoadImage(&LrcPic,(u_long *)(pUnpacked+(PIC_WIDTH*8*2)));
#else
	LoadImage(&LrcPic,(u_long *)pUnpacked);
#endif
	DrawSync(0);

	game_free(((PIC_WIDTH*PIC_HEIGHT)*2), LOAD_PICCY_BUFFER);

	return 1;
}

int S_ShowPicture(char *fname, int frames, int quitable)
{
	S_DisplayPicture(fname);
	return ShowPic(frames, quitable);
}

int S_ShowPictureMem(char *addr, int frames, int quitable)
{
	S_DisplayPictureMem(addr);
	return ShowPic(frames, quitable);
}

void PIC_PirateScreen(char *fname)
{
	static RECT prc={0,0,640,256};
	u_char *packed_gfx;
	u_char *unpacked_gfx;
	int n;
	DISPENV dispme; 	     	 	   								// display environment

	GPU_ClearVRAM();
	SetDispMask(0);

// allocate the ram...(PAUL STYLE)
	init_game_malloc();												// init system for mallocs
	packed_gfx = (u_char *)game_malloc(400000,LOAD_PICCY_BUFFER);	// allocate 400k
	unpacked_gfx = packed_gfx+32768;								// skip 32k , for unpacked buffer

// load pirate screen and depack it.
	FILE_Load(fname,packed_gfx);							// load the Shite Eidos Logo

	unpack(packed_gfx,unpacked_gfx);						   		// depack the gfx...

#ifdef NTSC
	LoadImage(&prc,(u_long *)unpacked_gfx+(640*8) );				// slang it down to VRAM
	SetDefDispEnv(&dispme,0,0,640,240);					 			// SLAG 640*240 display...
#else
	LoadImage(&prc,(u_long *)unpacked_gfx);							// slang it down to VRAM
	SetDefDispEnv(&dispme,0,0,640,256);								// SLAG 640*256 display...
#endif

	dispme.screen.x=MY_PSX_X_OFF;
	dispme.screen.y=MY_PSX_Y_OFF;									// handy offset...

	#ifndef NTSC
// PAL tweaks by del...
	dispme.screen.w = PAL_MAGIC;
	dispme.screen.h = PAL_MAGIC;									// handy pal bodge
	#endif

	DrawSync(0);
	VSync(0);
	PutDispEnv(&dispme);
	DrawSync(0);													// just in case ???
	VSync(0);
	SetDispMask(1);	      											// enable the display

	for (n=4*60;n--;)												// display for a min of 2secs... (that what the guidelines say)
		VSync(0);
	GPU_ClearVRAM();
	VSync(0);
}

