/***************************************************************************************************
			Printf Function
									programed by Iwamoto Daiki		[1995 June 21]
****************************************************************************************************/
#include "headers.h"

#define PUSH    1
#define NOPUSH  0
#define CHARWIDTH  12

extern unsigned short texDataPtr[]; 

typedef struct {
	int posx;
	int posy;
	short nstrs;
	char str[50];
} PString;

static PString *printPtr[50];
static short nprints = 0;

/***************************************************************************************************
		Calculate 10^x and return its rsult.
****************************************************************************************************/
static unsigned int PowTen(int decimal,int x)
{
	unsigned int return_value ;
	int		i ;

	return_value = 1 ;
	for ( i = 0 ; i < x ; i++ )	return_value = return_value*decimal ;

	return(return_value) ;
}

/***************************************************************************************************
		Change a value to strings by Decimal.
****************************************************************************************************/
static void ChangeValueString(int value,int decimal, char	*buffer,int *counter,unsigned char girder,char ox_flag) 
{
	unsigned int	beki;
	int				p = 0;
	int 			i;
	int 			k = 0;
	char			syou;
	char minus_flag = 0;
	char space_0;

	if (ox_flag == 1) space_0 = '0';
	else			 space_0 = -1;

	if (value != 0)		{
		if (value < 0) {
			value = -value;
			minus_flag = 1;
		}

		while(1)		{
			beki = PowTen(decimal,p) ;			/*		beki = 10^p		*/
			if ( beki > value )	break;
			p++ ;
		}


		if (girder > p) {
			for (k=0; k<(girder-p); k++) *(buffer+k) = space_0;
			if (minus_flag == 1) k--;
		}

		if (minus_flag == 1) { *(buffer+k) = 'M'; k++;}

		for ( i = p-1 ; i >= 0 ; i-- )		{
			beki = PowTen(decimal,i) ;
			syou = (char)(value / beki) ;
			if (syou < 10) *(buffer + k + (p-1) - i) = syou + '0';
			else		   *(buffer + k + (p-1) - i) = (syou-10) + 'A';
			value = value - syou*beki ;
		}

	}

	else	{
		p = 1;
		if (girder > p) for (k=0; k<(girder-p); k++) *(buffer+k) = space_0;
		*(buffer+k) = '0' ;
	}

	*counter += p+k;
}
/***************************************************************************************************
			%3d is 3 girder
****************************************************************************************************/
static void CheckGirder(const char *format,int *fo_counter,unsigned char *girder,char *ox_flag)
{
	char str[10];
	char count = 0;
	short i;

	if ((format[*fo_counter] - '0') == 0) *ox_flag = 1;

	while (format[*fo_counter] != 'd' && format[*fo_counter] != 'x') {
		str[count] = format[*fo_counter] - '0';
		if (str[count] < 0 || str[count] > 9) { *girder = 0; return;}
		count++;
		*fo_counter += 1;
	}

	if (count == 0) return;	

	for (i=0; i<count-1; i++) *girder = *girder + 10*(count-i-1)*str[i];
	*girder = *girder + str[count-1];


}
/***************************************************************************************************
			Printf Character
****************************************************************************************************/
extern void dprintf(int posx,int posy,const char *format,int value)
{

	char str = 0;
	char ox_flag = 0;
	unsigned char girder = 0; 
	int decimal = 0;
	int counter = 0;
	int fo_counter = 0;

	if ((printPtr[nprints] = (PString *)malloc(sizeof(PString)) ) == NULL) { rmonpf(("malloc error in dprint!!\n")); return;}


	printPtr[nprints]->posx = posx;
	printPtr[nprints]->posy = posy;

	str = format[fo_counter];
	while (str != NULL) {

		if (str == '%') {
			fo_counter++;
			CheckGirder(format, &fo_counter,&girder,&ox_flag);
			if (format[fo_counter] != 'd' && format[fo_counter] != 'x') break;
			if (format[fo_counter] == 'd') decimal = 10;
			if (format[fo_counter] == 'x') decimal = 16; 
			fo_counter++;
			ChangeValueString(value,decimal,&printPtr[nprints]->str[counter],&counter,girder,ox_flag); 

		}
		else {
			printPtr[nprints]->str[counter] = str;
			counter++;
			fo_counter++;
		}
		str = format[fo_counter];
	}		

	printPtr[nprints]->nstrs = counter;
	nprints++;

}
/***************************************************************************************************
			Printf Character Message Only
****************************************************************************************************/
extern void dmprintf(int posx,int posy,const char *format)
{

	char str = 0;
	int counter = 0;
	int fo_counter = 0;

	if ((printPtr[nprints] = (PString *)malloc(sizeof(PString)) ) == NULL) { rmonpf(("malloc error in dprint!!\n")); return;}


	printPtr[nprints]->posx = posx;
	printPtr[nprints]->posy = posy;

	str = format[fo_counter];
	while (str != NULL) {

		printPtr[nprints]->str[counter] = str;
		counter++;
		fo_counter++;
		str = format[fo_counter];
	}		

	printPtr[nprints]->nstrs = counter;
	nprints++;

}

/***************************************************************************************************
			Printf Character Message (Translate Center)
****************************************************************************************************/
extern void dcprintf(int posx,int posy,const char *format)
{

	char str = 0;
	unsigned char girder = 0; 
	int decimal = 0;
	int counter = 0;
	int fo_counter = 0;
#if CHINA
	int width = 0;
#endif

	if ((printPtr[nprints] = (PString *)malloc(sizeof(PString)) ) == NULL) {rmonpf(("malloc error in dprint!!\n"));  return;}


	str = format[fo_counter];
	while (str != NULL) {
#if CHINA
		if ((unsigned char)str==0xB0 || (unsigned char)str==0xC0)
			width = 16;
		else 
			width = 12;
#endif

		printPtr[nprints]->str[counter] = str;
		counter++;
		fo_counter++;
		str = format[fo_counter];
	}		

	printPtr[nprints]->nstrs = counter;
#if CHINA
	printPtr[nprints]->posx = posx - (width*counter)/2;
#else
	printPtr[nprints]->posx = posx - (CHARWIDTH*counter)/2;
#endif
	printPtr[nprints]->posy = posy;

	nprints++;

}





/**************************************************************************************************/
/***************************************************************************************************
			Character Check
****************************************************************************************************/
extern char CharacterCheck(char character)
{

	if (character >= 65 && character <= 90) { return(character - 55); }  //BigCharacter
	if (character >= 97 && character <= 122){ return(character - 87); }  //SmallCharacter
	if (character >= 48 && character <= 57) { return(character - 48); }  //Number
	if (character == 32) return(-1);
	if (character == 33) return(36);
	if (character == 35) return(37);
	if (character == 63) return(38);
	if (character == 38) return(39);
	if (character == 37) return(40);

	if (character == 42) return(50);    // batu
	if (character == 43) return(51);	// coin
	if (character == 44) return(52);	//mario
	if (character == 45) return(53);	//star
	if (character == 46) return(54);	//coin_shadow
	if (character == 47) return(55);	//key

	return(-1);

}
/***************************************************************************************************
			Draw Font Texture
****************************************************************************************************/
static void DrawMessageFont(char num)
{
	unsigned short **texture = (unsigned short**)SegmentToVirtual(texDataPtr); 

	gDPPipeSync(graphPtr++);
	gDPSetTextureImage(graphPtr++,G_IM_FMT_RGBA, G_IM_SIZ_16b, 1, texture[(unsigned char)num]);
	gSPDisplayList(graphPtr++, RCP_tfont_main);	


}

/***************************************************************************************************
			Make Font Texture
****************************************************************************************************/
#if 0
static void MakeVertex(int posx,int posy,int numbers)
{

    Vtx font_init[] = {
		{   0 ,   0 ,  0,  0 ,        0 ,            0,    255,255,255,255}, 
		{  16 ,   0 ,  0,  0 , (16 << 5),            0,    255,255,255,255}, 
		{  16 ,  16 ,  0,  0 , (16 << 5),    (-15 << 5),   255,255,255,255}, 
		{   0 ,  16 ,  0,  0 ,         0,    (-15 << 5),   255,255,255,255}, 
	};

	VtxPtr  vertexp = (VtxPtr) AllocDynamic(sizeof(Vtx)*(4));
	if (vertexp == NULL)	{ rmonpf(("AllocDynamic error in dprint!!\n")); return;}

	vertexp[0] = font_init[0];
	(vertexp+0   ) ->v.ob[0] = posx +(numbers*CHARWIDTH) + 0;
	(vertexp+0   ) ->v.ob[1] = posy +  0;
	(vertexp+0   ) ->v.ob[2] =  0;

	vertexp[1] = font_init[1];
	(vertexp+1   ) ->v.ob[0] = posx +(numbers*CHARWIDTH) +16;
	(vertexp+1   ) ->v.ob[1] = posy +  0;
	(vertexp+1   ) ->v.ob[2] =  0;

	vertexp[2] = font_init[2];
	(vertexp+2   ) ->v.ob[0] = posx +(numbers*CHARWIDTH) +16;
	(vertexp+2   ) ->v.ob[1] = posy + 16;
	(vertexp+2   ) ->v.ob[2] =  0;

	vertexp[3] = font_init[3];
	(vertexp+3   ) ->v.ob[0] = posx +(numbers*CHARWIDTH) + 0;
	(vertexp+3   ) ->v.ob[1] = posy + 16;
	(vertexp+3   ) ->v.ob[2] =  0;

	gSPVertex(graphPtr++,K0_TO_PHYS((u32) (vertexp)), 4, 0);
	gSP1Triangle(graphPtr++, 0, 1, 2, 0);
	gSP1Triangle(graphPtr++, 0, 2, 3, 0);


}
#endif
/***************************************************************************************************
		Position X,Y Check
****************************************************************************************************/
static void PosXYCheck(int *posx, int *posy)
{

	if (*posx <  10) *posx =   10;
	if (*posx > 300) *posx =  300;

	if (*posy <   5) *posy =    5;
	if (*posy > 220) *posy =  220;

}
/***************************************************************************************************
			Make Font Texture
****************************************************************************************************/
static void DrawFontToFrame(int posx,int posy,int numbers, int width)
{
	int ortho_posix;
	int ortho_posiy;
	uint posix;
	uint posiy;


	ortho_posix = (int) (posx + (numbers*width));
	ortho_posiy = (int) (240 - (posy+16));
	PosXYCheck(&ortho_posix, &ortho_posiy);

	posix = (uint)ortho_posix;
	posiy = (uint)ortho_posiy;


	
/* ======== 1 Cycle Mode Copy ===============
	gSPTextureRectangle(graphPtr++,( ortho_posix << 2), (ortho_posiy << 2), (ortho_posix+16 << 2), (ortho_posiy+16 << 2), 0,
						 (0 << 5), (0 << 5),	 (1 << 10), (1 << 10)  );
*/


/* ======== Copy Mode Copy ==================*/
	gSPTextureRectangle(graphPtr++,( posix << 2), (posiy << 2), (posix+15 << 2), (posiy+15 << 2), 0,
						 (0 << 5), (0 << 5),	 (4 << 10), (1 << 10)  );


}
/***************************************************************************************************
			Draw Message
****************************************************************************************************/
extern void DrawMessage(void)
{

	int i,k;
	char num;
	Mtx *projection;

	if (nprints == 0) return;

	if ( (projection = (Mtx *) AllocDynamic(sizeof(Mtx)) ) == NULL) { nprints = 0; rmonpf(("AllocDynamic error in dprint!!\n")); return; }

	guOrtho(projection, 0., 320., 0., 240.,-10., 10., 1.0);

	gSPPerspNormalize(graphPtr++, 0xffff);
	gSPMatrix(graphPtr++,K0_TO_PHYS((u32) (projection)),G_MTX_PROJECTION|G_MTX_LOAD|G_MTX_NOPUSH);



	gSPDisplayList(graphPtr++, RCP_tfont_on);	

	for (i=0; i<nprints; i++) {

		for (k=0; k<printPtr[i]->nstrs; k++) {
#if CHINA
			if ((unsigned char)(printPtr[i]->str[k]) < 0xA0) {
				num = CharacterCheck(printPtr[i]->str[k]);
			} else {
				if ((unsigned char)(printPtr[i]->str[k])==0xB0) {  // "PRESS"
					num = 0xb0;
				} else if ((unsigned char)(printPtr[i]->str[k])==0xC0) {  // "TIME"
					num = 0xc0;
				} else {
					num = -1;
				}
			}
#else
			num = CharacterCheck(printPtr[i]->str[k]);
#endif
			if (num != -1) {
#if CHINA
				if ((unsigned char)num==0xb0) {  // "PRESS"
				    DrawMessageFont(0x92);
				    DrawFontToFrame(45, 50, 0, 16);	
				    DrawMessageFont(0x93);
				    DrawFontToFrame(45, 50, 1, 16);			 
				    DrawMessageFont(0x94);
				    DrawFontToFrame(45, 34, 0, 16);			 
				    DrawMessageFont(0x95);
				    DrawFontToFrame(45, 34, 1, 16);			 
				} else if ((unsigned char)num==0xc0) {  // "TIME"
				    DrawMessageFont(0xae);
				    DrawFontToFrame(170, 193,0, 16);
				    DrawMessageFont(0xaf);
				    DrawFontToFrame(170, 193,1, 16);
				    DrawMessageFont(0xb0);
				    DrawFontToFrame(170, 193-16,0, 16);
				    DrawMessageFont(0xb1);
				    DrawFontToFrame(170, 193-16,1, 16);

				    DrawMessageFont(0xb2);
				    DrawFontToFrame(170, 193,2, 16);
				    DrawMessageFont(0xb3);
				    DrawFontToFrame(170, 193,3, 16);
				    DrawMessageFont(0xb4);
				    DrawFontToFrame(170, 193-16,2, 16);
				    DrawMessageFont(0xb5);
				    DrawFontToFrame(170, 193-16,3, 16);
				} else {
				DrawMessageFont(num);

				//MakeVertex(printPtr[i]->posx,printPtr[i]->posy,k);
				DrawFontToFrame(printPtr[i]->posx,printPtr[i]->posy,k, CHARWIDTH);			 
				}

#else
				DrawMessageFont(num);

				//MakeVertex(printPtr[i]->posx,printPtr[i]->posy,k);
				DrawFontToFrame(printPtr[i]->posx,printPtr[i]->posy,k, CHARWIDTH);			 
#endif
			}
		}
		
		free(printPtr[i]);
	}

	gSPDisplayList(graphPtr++, RCP_tfont_off);	

	nprints = 0;



}


