sm64/dprint.c

467 lines
13 KiB
C

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