sm64/Message/message.sou

855 lines
23 KiB
Plaintext

/***************************************************************************************************
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);
}