/***************************************************************************************************
			Message Function
									programed by Iwamoto Daiki		[1995 September 7]
****************************************************************************************************/

#define CHARWIDTH  10
#define WORDS      15


#define   PUSH      1
#define NOPUSH      2

#define MESSAG		0
#define SELECT		1

/*----- Message Struct -----*/
typedef struct {
	int		code;
	char	line;
	short	posx;
	short	posy;
	unsigned char *string;
} Message;

extern Message* Messagelist[];
extern Message *Selectlist[];



static char message_flag = 0 ;				//-----------------------------------
											//message_flag -->  0 window open
											//				    1 font indication
											//				    2 font change
											//				    3 window close
											//-------------------------------------
static float theta = 90;
static short delta;
static float win_sc = 19;
static short font_tr = 0;

static char message_type = 0;
static short messageNo = -1;
static short mess_first_pointer = 0;
static short message_go = 0;

static char cursor_no = 1;
static char cursor_line;
static char cursor_flag = 0;

static int   message_value;        // Variable Number 

static unsigned short font_alpha;

static unsigned char sticktrg = 0;
static unsigned char trg_count = 0;

/*----------*/
int messageAnsNo = 0;





/*=================================================================================================
					Draw font Function File Include

===================================================================================================*/
#include "../drawfont.c"


/*================================================================================================
						Cursor Event

================================================================================================*/
/**************************************************************************************************/
/*	Cursor Event																				  */
/**************************************************************************************************/
extern void ContCursorEvent(char side_code ,char* cursol,char start,char end)
{
	unsigned char str = 0x00;

	if (side_code == 1) {						//Tate
		if (contOr->sticky >  60) str += 0x01;
		if (contOr->sticky < -60) str += 0x02;
	}
	else if (side_code == 2) {					//Yoko
		if (contOr->stickx >  60) str += 0x02;
		if (contOr->stickx < -60) str += 0x01;
	}


	if (((str^sticktrg) & str) == 0x02)  {
		if (*cursol == end) *cursol = end;
		else {
			Na_FixSeFlagEntry(NA_SYS_CURSOR);
			(*cursol) ++;
		}
	} 
	if (((str^sticktrg) & str) == 0x01) {
		if (*cursol == start) *cursol == start;
		else {
			Na_FixSeFlagEntry(NA_SYS_CURSOR);
			(*cursol)--;
		}
	} 

	if (trg_count == 10) {
		trg_count = 8;
		sticktrg = 0;
	}
	else {
		trg_count++;
		sticktrg = str;
	}

	if ( (str & 0x03) == 0) trg_count = 0;

}

/********************************************************************************/
/*	CCenterling         														*/
/********************************************************************************/
extern short CharCentering(short posx,unsigned char *font,float width)
{
	short i=0;
	float count = 0;
	float space = 0;

	while (font[i] != 0xff) {
		if (font[i] == 0x9e) space += 1.0;
		else if (font[i] != 0xf0 && font[i] != 0xf1)	count += 1.0;
		i++;
	}

	return(  (short)((float)posx - width*(count/2.) - (width/2.)*(space/2.))   );
}

/********************************************************************************/
/*	Draw Course Coin Number .  													*/
/********************************************************************************/
extern void DrawCoinScore(int mode,char player,char course,short posx,short posy) 
{
	unsigned char coin_num[4];
	short coin;
	static unsigned char se16_coinnum1[] = {0x33, 0xff};		//coin num
	static unsigned char se16_coinnum2[] = {0x32, 0xff};		//* num

	if (mode == 0) coin = BuGetHiScore(course);
	else		   coin = BuGetNumCoins(player,course);

	if (coin != 0) {
		Draw16bitFont(2,posx,posy,se16_coinnum1);
		Draw16bitFont(2,posx+16,posy,se16_coinnum2);
		I_itochar(coin,coin_num);
		Draw16bitFont(2,posx+32,posy,coin_num);
	}


}

/********************************************************************************/
/*	Draw Course Star Number .  													*/
/********************************************************************************/
extern void DrawCourseStar(char player,char course,short posx,short posy) 
{
	unsigned char star_num[4];
	short star;
	unsigned char se16_coinnum1[] = {0x35, 0xff};		//star num
	unsigned char se16_coinnum2[] = {0x32, 0xff};		//* num

	 star = BuGetCourseStars(player,course);

	if (star != 0) {
		Draw16bitFont(2,posx,posy,se16_coinnum1);
		Draw16bitFont(2,posx+16,posy,se16_coinnum2);
		I_itochar(star,star_num);
		Draw16bitFont(2,posx+32,posy,star_num);
	}


}

/********************************************************************************/
/*	Convert Integer to char .  													*/
/********************************************************************************/
extern void I_itochar(int num,unsigned char* font) 
{
	int n100;
	int n10;
	int n1;
	char i = 0;

	if (num > 999) { font[0] = 0; font[1] = 0xff; return;}

	n100 = (int)(num/100);
	n10  = (int)((num - n100*100)/10);
	n1   = (int)(num - n100*100 - n10*10);


	if (n100 != 0)              {font[i] = n100; i++;}
	if (n10  != 0 || n100 != 0) {font[i] = n10 ; i++;}
				                {font[i] = n1  ; i++;}

	font[i] = 0xff;


}


/*=================================================================================================
===================================================================================================*/
/***************************************************************************************************
			Get Message No
****************************************************************************************************/
extern short GetMessageNo(void)
{
	return(messageNo);

}
/***************************************************************************************************
			Call Message Normal
****************************************************************************************************/
extern void CallMessage(short callNo)
{

	if (messageNo == -1) {
		messageNo = callNo; 
		message_type = 0;
	}

}
/***************************************************************************************************
			Call Message  with Integer
****************************************************************************************************/
extern void CallMessageInt(short callNo,int num)
{

	if (messageNo == -1) {
		messageNo = callNo; 
		message_value = num;
		message_type = 0;
	}

}
/***************************************************************************************************
			Call Message  for Tatefuda
****************************************************************************************************/
extern void CallMessageFuda(short callNo)
{

	if (messageNo == -1) {
		messageNo = callNo; 
		message_type = 1;
	}

}
/***************************************************************************************************
			Call Message Normal
****************************************************************************************************/
extern void CallMessageYesNo(short callNo)
{

	if (messageNo == -1) {
		messageNo = callNo; 
		message_type = 0;
		cursor_flag = 1;
	}

}

/***************************************************************************************************
			Call Message Normal
****************************************************************************************************/
extern void MessageEnforcedDestroy(void)
{

	FreezeGame(0,NULL);									//Window Close!
	if (message_type == 1) ViewingCam(VIEW_OFF);
	win_sc = 19; 
	theta = 90;
	message_flag = 0;
	messageNo = -1;
	message_go = 0;
	cursor_flag = 0;
	mess_first_pointer = 0;
	messageAnsNo = 0;

}
/***************************************************************************************************
			Message Window
****************************************************************************************************/
static void DrawMessageWindow(Message *message,char line)
{
	Mtx*  matrix; 

	iTranslate(NOPUSH,message->posx,message->posy,0);

	switch (message_type) {
		case 0: if (message_flag == 0 || message_flag == 3) {
					iScale(NOPUSH,1./win_sc ,1./win_sc, 1.);
					iRotate(NOPUSH,theta*4,0., 0. , 1.0);
				}
				gDPSetEnvColor(graphPtr++,0,0,0,150);
				break;

		case 1: if (message_flag == 0 || message_flag == 3) {
					iTranslate(NOPUSH,(65.-65./win_sc),(40./win_sc-40),0);
					iScale(NOPUSH,1./win_sc,1./win_sc,1.);
				}
				gDPSetEnvColor(graphPtr++,255,255,255,150);
				break;

	}

	iTranslate(PUSH,-5,2,0);
	iScale(NOPUSH,1+0.1 ,(float)line/4+0.1 ,1.);
	gSPDisplayList(graphPtr++, RCP_Mess_window);	
	gSPPopMatrix(graphPtr++,G_MTX_MODELVIEW);



}
/***************************************************************************************************
			Set Font Color
****************************************************************************************************/
static void SetFontColor(char code ,char line)
{
	unsigned char color;


	if (code == SELECT) {				// CURSOL MESSAGE
		if (line == 1)        { gDPSetEnvColor(graphPtr++,255,255,255,255); }
		else {
			if (line == cursor_no){ 
				color = 200 + sin(delta)*50;
				gDPSetEnvColor(graphPtr++,color,color,color,255); 
			}
			else				  { gDPSetEnvColor(graphPtr++,200,200,200,255); }
		}
	}

	else {

		switch(message_type) {
			case 0:	break;
			case 1:	gDPSetEnvColor(graphPtr++,0,0,0,255); break;

		}
	}

}
/***************************************************************************************************
			Kaigyou
****************************************************************************************************/
static void KaigyouEvent(char line, char end_line,char *end_flag,char *space,short *words)
{

	gSPPopMatrix(graphPtr++,G_MTX_MODELVIEW);
	if (line ==  end_line) { *end_flag = 1; return; }
	iTranslate(PUSH, 5., 2-(line*20),0);
	*words = 0;
	*space = 1;
}

/***************************************************************************************************
			Kuten			
****************************************************************************************************/
static void ToutenEvent(char *space,short *words)
{
	if ((*words) != 0) {iTranslate(NOPUSH,CHARWIDTH*(*space),0,0); }

	iTranslate(PUSH,-2,-5,0);
	DrawMessageTexture(0xf1);
	gSPPopMatrix(graphPtr++,G_MTX_MODELVIEW);
	(*words)++;
	(*space) = 1;

}
/***************************************************************************************************
			Variable Event			
****************************************************************************************************/
static void VariableEvent(char *space,short *words)
{
	char ten_v = (char)(message_value/10);
	char one_v = (char)(message_value - ten_v*10);

	if (ten_v != 0) {
		iTranslate(NOPUSH,CHARWIDTH*(*space),0,0);
		DrawMessageTexture(ten_v);
	}
	else {
		(*space)++;
	}

	iTranslate(NOPUSH,CHARWIDTH*(*space),0,0);
	DrawMessageTexture(one_v);

	(*words)++;
	*space=1;

}
/***************************************************************************************************
			0 revise			
****************************************************************************************************/
static unsigned int ZeroRe(short number)
{

	if (number < 0) number = 0;

	return((unsigned int) number);

}
/***************************************************************************************************
			Message Font
****************************************************************************************************/
static void DrawMessageFont(char code,Message *message,char draw_line)
{
	int i,k;
	unsigned char  num;
	unsigned char* stringPtr = (uchar *)(SegmentToVirtual(message->string));
	char line = 1;
	char end_line;
	char end_flag = 0;
	char daku_flag = 0;
	char space  = 1;
	char page_line = message->line;
	short mesp;
	short words = 0;

	if (message_flag == 2) end_line = page_line*2 + 1;
	else				   end_line = page_line + 1;
	

	gSPDisplayList(graphPtr++, RCP_mess_font_on);	

	mesp = message_go;



	if (message_flag == 2) iTranslate(NOPUSH,0,font_tr ,0);
	iTranslate(PUSH, 5., 2-(line*20),0);

	while (end_flag == 0) {

		SetFontColor(code,line);
		num = stringPtr[mesp];   

		switch (num) {
/*end*/ 	case 0xff :	end_flag = 2;
						gSPPopMatrix(graphPtr++,G_MTX_MODELVIEW);
						break;
/*kaigyou*/	case 0xfe : line++;
						KaigyouEvent(line, end_line,&end_flag,&space,&words);
						daku_flag = 0;
						break;
/*daku*/	case 0xf0 : daku_flag = 1;
						break;
/*maru*/	case 0xf1 : daku_flag = 2;
						break;
/*space*/	case 0x9e : if (words != 0) space++;
						words++;
						break;
/*  .  */	case 0x6e : ToutenEvent(&space,&words);
						break;
/*value*/	case 0xe0 : VariableEvent(&space,&words);
						break;

			default   : if (line >= draw_line && line <= draw_line+page_line) {
							if (words != 0) iTranslate(NOPUSH,CHARWIDTH*space,0,0);
							DrawMessageTexture(num);
							space = 1;		
							words++;

							if (daku_flag != 0) {					// DAKUTEN
								iTranslate(PUSH,5,7,0);
								DrawMessageTexture(0xf0 + (daku_flag-1));
								gSPPopMatrix(graphPtr++,G_MTX_MODELVIEW);
								daku_flag = 0;
							}
						}
		}
#if 0			
		if (words == WORDS) {
			if (stringPtr[mesp+1] == 0x6e) { ToutenEvent(&space,&words); mesp++; }  // Touten
			if (stringPtr[mesp+1] == 0x6f) { iTranslate(NOPUSH,CHARWIDTH*space,0,0);
											 DrawMessageTexture(0x6f);
											 mesp++; 
											}	// Kuten

			if (stringPtr[mesp+1] == 0xfe) { mesp++; }								// Kaigyou
			if (stringPtr[mesp+1] == 0xff) { 
				end_flag = 2; 
				gSPPopMatrix(graphPtr++,G_MTX_MODELVIEW);
				break;
			}
			else {
				line++;
				KaigyouEvent(line, end_line,&end_flag,&space,&words);
			}
		}
#endif
		mesp++;


	}

	gSPDisplayList(graphPtr++, RCP_mess_font_off);	

	if (message_flag == 1) {
		if (end_flag == 2) mess_first_pointer = -1;
		else			   mess_first_pointer = mesp;	
	}

	cursor_line = line;


}
/***************************************************************************************************
			Draw Select Cursor
****************************************************************************************************/
static void DrawCursor(void)
{

	if (message_flag == 1) ContCursorEvent(2 ,&cursor_no,1,2);

	iTranslate(NOPUSH, 5+(CHARWIDTH*2)+(cursor_no-1)*(CHARWIDTH*5), 1-(cursor_line*20),0);

	if (message_type == 0) { gDPSetEnvColor(graphPtr++,255,255,255,255); } 
	else				   { gDPSetEnvColor(graphPtr++,  0,  0,  0,255); }

	gSPDisplayList(graphPtr++, RCP_mess_cursor);	


}

/***************************************************************************************************
			Draw Okuri
****************************************************************************************************/
static void DrawOkuri(char line)
{
	ulong counter = frameCounter;

	if ((counter & 0x000000008)) return;

	iTranslate(PUSH,123,-20*line+2,0);
	iScale(NOPUSH,0.8 ,0.8, 1.);
	iRotate(NOPUSH,-90. ,0., 0. , 1.0);

	if (message_type == 0) { gDPSetEnvColor(graphPtr++,255,255,255,255); } 
	else				   { gDPSetEnvColor(graphPtr++,  0,  0,  0,255); }

	gSPDisplayList(graphPtr++, RCP_mess_cursor);	
	gSPPopMatrix(graphPtr++,G_MTX_MODELVIEW);

}
/***************************************************************************************************
			Message Special Sound
****************************************************************************************************/
static void MessageSpecialSound(short message_no)
{
	short mess_boss[]     = {17,114,128,117,150};
	short mess_race[]     = { 5,9,55,164};
	short mess_switch[]   = {10,11,12,13,14};
	short mess_bossStop[] = {17,115,116,118,152};
	short i;


	for (i=0; i<5; i++) {
		if (mess_boss[i] == message_no) { Na_MusicMuteOff(); Na_MusicStart(NA_MUS_HANDLE,NA_BOSS_BGM,0);  	return; }
	}

	for (i=0; i<4; i++) {
		if (mess_race[i] == message_no && cursor_no == 1) { Na_RaceFanfareBgm();		return; }
	}

	for (i=0; i<5; i++) {
		if (mess_switch[i] == message_no && cursor_no == 1) { Na_FixSeFlagEntry(NA_SE2_SET);		return; }
	}

	for (i=0; i<5; i++) {
		if (mess_bossStop[i] == message_no) {  Na_BossBgmStop(); return; }
	}

}
/***************************************************************************************************
			Message Event
****************************************************************************************************/

static void MessageOnlyEvent(void)
{
	Message** mlist  = (Message **)(SegmentToVirtual(Messagelist));
	Message* message = (Message  *)(SegmentToVirtual(mlist[messageNo]));
	char draw_line;


	if (message == SegmentToVirtual(NULL)) { rmonpf(("Message not defined. (%d)\n",messageNo));  messageNo = -1;  return; }

	switch(message_flag) {
		case 0:	if (theta == 90) {
//					FreezeGame(-1,NULL);								//Window Open!
					Na_MessageSound(messageNo);
					Na_FixSeFlagEntry(NA_SYS_WIN_OPEN);	
				}
				if (message_type == 0) { theta -= 7.5; win_sc -=1.5; }
				else				   { theta -= 10.; win_sc -=2.; }
				if (theta == 0) {
					message_flag = 1;
					cursor_no   = 1;
				}
				draw_line = 1;
				break;

		case 1:	theta = 0;												//Message Draw!
				if (contOr->trigger & CONT_A || contOr->trigger & CONT_B) {
					if (mess_first_pointer == -1) { MessageSpecialSound(messageNo); message_flag = 3; }
					else 	{
						message_flag = 2;
						Na_FixSeFlagEntry(NA_SYS_MESSAGEPASS);
					}
				}
				draw_line = 1;
				break;

		case 2: font_tr += 2*(message->line);								//Next Message!
				if (font_tr >= 20*(message->line))  {
					message_go = mess_first_pointer;
					message_flag = 1;
					font_tr = 0;
				}
				draw_line = (font_tr/20) + 1;
				break;

		case 3:	if (theta == 20) {
					FreezeGame(0,NULL);									//Window Close!
					Na_FixSeFlagEntry(NA_SYS_WIN_CLOSE);
					if (message_type == 1) ViewingCam(VIEW_OFF);
					messageAnsNo = cursor_no;
				}
				theta += 10;
				win_sc +=2; 
				if (theta == 90) {
					message_flag = 0;
					messageNo = -1;
					message_go = 0;
					cursor_flag = 0;
					mess_first_pointer = 0;
					messageAnsNo = 0;
				}
				draw_line = 1;
				break;
	}


	DrawMessageWindow(message,message->line);

	gDPSetScissor(graphPtr++,G_SC_NON_INTERLACE,ZeroRe(message->posx),ZeroRe(SCREEN_HEIGHT - message->posy),
										ZeroRe(message->posx+130),ZeroRe(SCREEN_HEIGHT - message->posy+(80*message->line/4)));


	DrawMessageFont(MESSAG,message,draw_line);
	if (mess_first_pointer == -1 && cursor_flag == 1) DrawCursor();

	gDPSetScissor(graphPtr++, G_SC_NON_INTERLACE, 2, 2, SCREEN_WIDTH-4, SCREEN_HEIGHT-4);

	if (mess_first_pointer != -1 && message_flag == 1) DrawOkuri(message->line);
	
}
/***************************************************************************************************/
/***************************************************************************************************/
/***************************************************************************************************/
/***************************************************************************************************/

static short selectNo = -1;
/***************************************************************************************************
			Call Select Message
****************************************************************************************************/
extern void CallSelectMessage(short callNo)
{


	if (selectNo == -1) {	

		selectNo = callNo; 

	}


}

#if 0

/***************************************************************************************************
			Draw Select Cursor
****************************************************************************************************/
extern void DrawSelectCursor(char line_min,char line_max)
{
	unsigned char str = 0x00;

	if (contOr->sticky >  60) str += 0x08;
	if (contOr->sticky < -60) str += 0x04;
	if (contOr->stickx >  60) str += 0x02;
	if (contOr->stickx < -60) str += 0x01;

	if (((str^sticktrg) & str) == 0x08)  {
		cursor_no--; 
		if (cursor_no < line_min) cursor_no = line_min;
		else	Na_FixSeFlagEntry(NA_SYS_CURSOR);    //Sound CURSOL
	} 
	if (((str^sticktrg) & str) == 0x04) {
		cursor_no++; 
		if (cursor_no > line_max) cursor_no = line_max;
		else	Na_FixSeFlagEntry(NA_SYS_CURSOR);	//Sound CURSOL
	} 

	if (trg_count == 10) {
		trg_count = 8;
		sticktrg = 0;
	}
	else {
		trg_count++;
		sticktrg = str;
	}
	if ( (str & 0x0c) == 0) trg_count = 0;



	iTranslate(PUSH, 5., 2-(cursor_no*20),0);
	gDPSetEnvColor(graphPtr++,255,255,255,255); 
	gSPDisplayList(graphPtr++, RCP_mess_cursor);	
	gSPPopMatrix(graphPtr++,G_MTX_MODELVIEW);
	
}
/***************************************************************************************************
			Message Select Event
****************************************************************************************************/
extern short SelectMessageEvent(void)
{

	short ret_num;

	Message** mlist  = (Message **)(SegmentToVirtual(Selectlist));
	Message* message = (Message  *)(SegmentToVirtual(mlist[selectNo]));

	if (message == NULL) { rmonpf(("Message not defined. (%d)\n",selectNo)); selectNo = -1; return(NULL); }

	switch(message_flag) {
		case 0:	if (theta == 70) {
					FreezeGame(-1,NULL);								//Window Open!
					Na_FixSeFlagEntry(NA_SYS_PAUSE_ON);	//Sound ON
				}
				theta -= 10;											
				win_sc -= 2; 
				if (theta == 0) {
					message_flag = 1;
					cursor_no = 2;
				}
 				break;

		case 1:	theta = 0;															//Message Draw!
				if (contOr->trigger & CONT_A || contOr->trigger & CONT_START) {
					Na_FixSeFlagEntry(NA_SYS_ENTER);	//Sound Enter
					message_flag = 3;					
				}
				break;


		case 3:	if (theta == 20) {
					FreezeGame(0,NULL);								//Window Close!
					Na_FixSeFlagEntry(NA_SYS_PAUSE_OFF);	//Sound ON
				}
				theta += 10;
				win_sc += 2; 
				if (theta == 90) {
					message_flag = 0;
					selectNo = -1;
					message_go = 0;
					ret_num = cursor_no - 1;
					return(ret_num);
				}
				break;
	}

	DrawMessageWindow(message,message->line);
	DrawSelectCursor(2,message->line);
	DrawMessageFont(SELECT,message);


	return(NULL);




}

#endif

/*=================================================================================================*/


#include "../endingmess.c"

#include "../pausemess.c"

#if DEBUGSW
#include "../mess_Debug.c"
#endif

/*=================================================================================================
			Message Function Main



===================================================================================================*/
/***************************************************************************************************
			Message  Event
****************************************************************************************************/
extern short MessageEvent(void)
{
	short ret_num = 0;

#if DEBUGSW
	message_test();
#endif

	MakeSelectProjection(); 

	if (selectNo != -1) {
		switch (selectNo) {
			case 0 : ret_num = PauseSceneEvent(); break;
			case 1 : ret_num = PauseSceneEvent(); break;
			case 2 : ret_num = SaveSceneEvent(); break;
			case 3 : ret_num = SaveSceneEvent(); break;
//			default: ret_num = SelectMessageEvent();
		}

		delta += 0x1000;

	}

	else if (messageNo != -1) {
		if (messageNo == 20) { OpeningMessageEvent(); return(ret_num); }
		MessageOnlyEvent();
		delta += 0x1000;
	}


	return(ret_num);

}





