/************************************************************************
 *									*
 *	ライブラリ 関数							*
 *				1995年 12月26日(火曜日) 16時00分00秒 JST*
 ************************************************************************/
#include "sys_main.h"
#include "fox_std_lib.h"
#include "fox_ram.h"
#include "fox_edisplay.h"
#include "fox_texture.h"
#include "fox_std_Dmoji.h"
#include "fox_std_rcp.h"
#include "fox_main.h"
#include <stdarg.h>

#define STR_BUF_SIZE (100)
static char str_buf[STR_BUF_SIZE]; /* printf出力用バッファ */

/*>>>>>>>>>>
funvtion : いわゆるmemset
 void *Memset(void *buffer, int character, int n)
entry : comment
<<<<<<<<<<*/
void *Memset(void *buffer, int character, int n)
{
    int lp1;
    unsigned char *rbuf;

    rbuf = (unsigned char *)buffer;
    for (lp1 = n ; lp1 > 0 ; lp1--) {
	*(rbuf++) = (unsigned char) character;
    }

    return  buffer;
}

/*>>>>>>>>>>
function : いわゆるprintfただし,サブセット版（表示可能文字数は８０文字）
 int Printf(const char *format,...)
entry              : i/o : comment
 const char format : i/  :
 ...               : i/  :
return
 non
<<<<<<<<<<*/
 int Printf(const char *format,...)
{
    va_list argptr;

    Memset(str_buf, 0x00, STR_BUF_SIZE);
    va_start(argptr, format);
    VSPRINTF(&str_buf[0], format, argptr);
//    vsPrintf(&str_buf[0], format, argptr);
//    vsprintf(&str_buf[0], format, argptr);
    va_end(argptr);
    PUTS8X8(&NOW_DISP02, &str_buf[0]);
    return 0;
}

#if 0
#define G_ZBUFFER2  G_ZBUFFER 

#define DEC_BUF_SIZE (30)
static char dec_buf[DEC_BUF_SIZE]; /* printfフィールド幅 */

/*>>>>>>>>>>
  funciton : メモリ転送
  void *Memcpy(void *, const void *, int)
  entry
  return
  <<<<<<<<<<*/
void *Memcpy(void *d, const void *s, int l)
{
    unsigned char *dst;
    unsigned char *src;

    dst = (unsigned char *)d;
    src = (unsigned char *)s;
    for (; l > 0 ; l--) {
	*dst++ = *src++;
    }

    return ((void *)d);
}

/*>>>>>>>>>>
function : zのx乗を返す。（ただしintのみ。）
 int Ipow(int z, int x)
entry        : i/o : comment
 int z       : i/  : 被乗数
 int x       : i/  : 乗数
return : comment
 int   : 解
 <<<<<<<<<<*/
int Ipow(int z, int x)
{
    int rt;
    
    rt = 1;
    while (x--)
	rt = rt * z;
    return rt;
}

/*>>>>>>>>>>
function : 文字列コピー
 char *Strcpy(char *d, const char *s)
entry
 char *d : i/o : コピー先文字列
 char *s : i/o : コピー元文字列
>>>>>>>>>>*/
 char *Strcpy(char *d, const char *s)
{
    while ((*(d++) = (*s++)) != '\0')
	;
    return d;
}

/*>>>>>>>>>>
function : 文字列長調査
0 int Strlen(const char *s)
entry
 char *str : i/o : 調査文字列ポインタ
return : comment
 int : 文字列長
 >>>>>>>>>>*/
int Strlen(const char *s)
{
    int cnt;

    cnt = 0;
    while (*(s++) != '\0') {
	cnt++;
    }
    
    return cnt;
}

/*>>>>>>>>>>
function : 文字列反転
 Strrev(char *str)
entry
 char *str : i/o : 文字列ポインタ
>>>>>>>>>>*/
char *Strrev(char *str)
{
    int l;
    char w;
    int lp1;

    l = Strlen(str);
    for (lp1 = 0 ; lp1 < l/2 ; lp1++) {
	w = *(str+lp1);
	*(str+lp1) = *(str+l-lp1-1);
	*(str+l-lp1-1) = w;
    }
    return str;
}

/*>>>>>>>>>>
function : 数値から１０進文字列変換
 int Atoi(const char *str)
entry            : i/o : comment
 const char *str : i/  : 変換文字列
return : comment
 int   : １０進変換値
<<<<<<<<<<*/
int Atoi(const char *str)
{
    int lp1;
    int a;
    int b;

    a = 0;
    b = 1;
    for (lp1 = Strlen(str)-1 ; lp1 >= 0 ; lp1-- , b *= 10) {
	a += (*(str+lp1)-0x30) * b;
    }

    return a;
}

/*>>>>>>>>>>
funvtion : 数値から１０進文字列変換
 char *Itoa(int i, char *str, int size, int zero_flg)
entry : comment
 int i       : i/  :
 char str    :  /o :
 int size    : i/  : 変換文字列長。指定しないときは,０を入力する。
 int pad_flg : i/  : 文字列長よりも変換文字が少ないときに埋める文字の指定。=0(スペース),=1(０キャラクター)
<<<<<<<<<<*/
char *Itoa(int i, char *str, int size, int pad_flg)
{
    static char blank_chr[] = {0x20,0x30};
    int pt;
    int c; /*桁の数値:キャラクター*/
    int mF; /*マイナスフラグ*/
    
    pt = 0;
    if (i < 0) {
	i = -i;
	size--;
	mF = 1;
    } else {
	mF = 0;
    }

    do {
	c = i % 10;
	i /= 10;
	*(str+pt) = c + 0x30;
	pt++;
    } while (i != 0 && (size == 0 || pt < size)) ;
    while (pt < size) {
	*(str+pt) = blank_chr[pad_flg];
	pt++;
    }
    if (mF == 1) {
	*(str+pt) = '-';
	pt++;
    }
    *(str+pt) = '\0';
    
    return (Strrev(str));
}


/*>>>>>>>>>>
function : 小数数値から１０進文字列変換
 char *Ftoa(float f, char *str, int size_i, int size_f, int pad_flg)
entry : comment
 int i       : i/  :
 char *str   :  /o :
 int size_i  : i/  : 整数変換文字列長。指定しないときは,０を入力する。
 int size_f  : i/  : 小数変換文字列長。指定しないときは,０を入力する。
 int pad_flg : i/  : 文字列長よりも変換文字が少ないときに埋める文字の指定。=0(スペース),=1(０キャラクター)
<<<<<<<<<<*/
char *Ftoa(double f, char *str, int size_i, int size_f, int pad_flg)
{
    int mF;
    double wi;  /* 整数 */
    double wf;  /* 小数 */
    int pt;  /* カウンター */
    int pt2;
    char c;


    if (f < 0) {
	f  = -f;
	size_i--;
	*str = '-';
	mF = 1;
    } else {
	mF = 0;
    }
	
    wi = (double)(int)f;
    wf = fabsf(f - (double)wi);
#if 0
    wf += 5. / (double)Ipow(10, size_f + 1);
#endif
#if 0
    printf("f =<%12.10f>\n",f);
    printf("wi=<%12.10f>\n",wi);
    printf("wf=<%12.10f>\n",wf);
#endif
    /*整数部の変換*/
    Itoa((int)wi, str+mF, size_i, pad_flg);
    pt  = Strlen(str);
    pt2 = 0;
    if (size_f > 0) {
	*(str+pt) = '.';
	pt++;
	while (wf != 0 && pt2 < size_f) {
	    wf *= 10;
	    c   = (char)wf;
	    wf -= c;
	    *(str+pt+pt2) =  c + 0x30;
	    pt2++;
	}
	while (pt2 < size_f) {
	    *(str+pt+pt2) = '0';
	    pt2++;
	}
    }
    *(str+pt+pt2) = '\0';
    
    return str;
}

/*
  static void FormatGet(int *f, int *s, char *dec_s, int flg)
 */
static void FormatGet(int *f, int *s, char *dec_s, int flg)
{
    if ((flg & 0x04) == 0x00) /*フィールド指定？*/
	*f = Atoi(dec_s);
    else
	*s = Atoi(dec_s);
    Memset(dec_s, 0x00, DEC_BUF_SIZE);
}

/*>>>>>>>>>>
function : いわゆるsPrintfただし,サブセット版（表示可能文字数は８０文字）
 int sPrintf(char *str, const char *format,...)
entry              : i/o : comment
 const char format : i/  :
 ...               : i/  :
return
 non
<<<<<<<<<<*/
int sPrintf(char *str, const char *format,...)
{
    va_list argptr;

    va_start(argptr, format);
    vsPrintf(str, format, argptr);
    va_end(argptr);
    return 0;
}

/*>>>>>>>>>>
function : いわゆるvsprintfただし,サブセット版（表示可能文字数は８０文字）
 void Printf(const char *format,...)
entry              : i/o : comment
 const char format : i/  :
 ...               : i/  :
return
 non
<<<<<<<<<<*/
int vsPrintf(char *str, const char *format,va_list argptr)
{
    char rch;
    int rp;    /*format read pointer*/
    int sp;    /*send string set pointer*/
    int dp;    /*decimal pointer*/
    int f_len; /*fieled len*/
    int s_len; /*seido  len*/
    int wk1;
    int lp1;
    unsigned int s_flg;

    sp = 0;
    rp = 0;
    dp = 0;
    s_flg = 0;
    Memset(dec_buf, 0x00, DEC_BUF_SIZE);
    while ((rch = *(format+rp++)) != '\0') {
	if ((s_flg & 0x80)== 0x00) {
	    if (rch == '%') {
		s_flg |= 0x80;
	    }
	    else {
		*(str+sp) = rch;
		sp++;
	    }
	}
	else {
	    switch (rch) {
	    case '%' :
		s_flg &= 0x7f;
		*(str+sp) = rch;
		sp++;
		break;
	    case '0' :
		if (dp == 0) {
		    s_flg |= 1; /*'0'flg set*/
		    break;
		}
		else {
		    dec_buf[dp++] = rch;
		    break;
		}
	    case '1' :
	    case '2' :
	    case '3' :
	    case '4' :
	    case '5' :
	    case '6' :
	    case '7' :
	    case '8' :
	    case '9' :
		dec_buf[dp++] = rch;
		s_flg |= 8; /*file len */
		break;
	    case '.' :
		f_len =  Atoi(dec_buf);
		Memset(dec_buf, 0x00, DEC_BUF_SIZE);
		dp =0;
		s_flg |= 4;
		break;
	    case '-' :
		s_flg |= 2; /*left_pack flg set*/
		break;
	    case 'd' :
		FormatGet(&f_len, &s_len, dec_buf, s_flg);
		if ((s_flg & 0x02) == 0x00) { /*左詰めなし*/
		    Itoa(va_arg(argptr, int),str+sp, f_len, s_flg & 1);
		}
		else {
		    wk1 = Strlen(Itoa(va_arg(argptr, int),str+sp, 0, 0));
		    for (lp1 = f_len - wk1 ; lp1 >= 0 ; lp1-- ) {
			*(str+sp+wk1+lp1) = ' ';
		    }
		    *(str+sp+f_len) = '\0';
		}
		Memset(dec_buf, 0x00, DEC_BUF_SIZE);
		dp =0;
		sp += Strlen(str+sp);
		s_flg &= 0x78; /*'%'flg '0'flg '-' flg '.'flg reset*/
		break;
	    case 'f' :
		if ((s_flg & 0x0c) == 0) {
		    f_len = 1;
		    s_len = 6;
		}
		FormatGet(&f_len, &s_len, dec_buf, s_flg);
		sp += Strlen(Ftoa(va_arg(argptr, double),str+sp,f_len - s_len - 1,s_len,s_flg & 1));
		s_flg &= 0x7e;
		break;
	    case 's' :
		Strcpy(str+sp, va_arg(argptr, char*));
		sp += Strlen(str+sp);
		s_flg &= 0x7f; /*'%'flg '0'flg reset*/
		break;
	    default :
		*(str+sp) = rch; 
		sp++;
		break;
	    }
	}
    }
    return 0;
}
#endif

/*======================================================================*
 *									*
 *	テクスチャー を 動かす						*
 *									*
 *======================================================================*/
void texture_loop(
    unsigned short	*texture,
    int			xsize,
    int			ysize,
    unsigned char	muki
)
{
    unsigned short	*tex, buffer;
    int			x, y;

    tex = (unsigned short *)SEGMENT_TO_KSEG0(texture);

    switch(muki) {
    case TEXTURE_LOOP_UP:
	for(x = 0; x < xsize; x += 1) {
	    buffer = tex[x];
	    for(y = 1; y < ysize; y += 1) {
		tex[(y - 1) * xsize + x] = tex[y * xsize + x];
	    }
	    tex[(ysize - 1) * xsize + x] = buffer;
	}
	break;
    case TEXTURE_LOOP_DOWN:
	for(x = 0; x < xsize; x += 1) {
	    buffer = tex[(ysize - 1) * xsize + x];
	    for(y = ysize - 2; y >= 0; y -= 1) {
		tex[(y + 1) * xsize + x] = tex[y * xsize + x];
	    }
	    tex[x] = buffer;
	}
	break;
    case TEXTURE_LOOP_RIGHT:
	for(y = 0; y < ysize; y += 1) {
	    buffer = tex[y * xsize + xsize - 1];
	    for(x = xsize - 2; x >= 0; x -= 1) {
		tex[y * xsize + x + 1] = tex[y * xsize + x];
	    }
	    tex[y * xsize] = buffer;
	}
	break;
    case TEXTURE_LOOP_LEFT:
	for(y = 0; y < ysize; y += 1) {
	    buffer = tex[y * xsize];
	    for(x = 1; x < xsize; x += 1) {
		tex[y * xsize + x - 1] = tex[y * xsize + x];
	    }
	    tex[(y * xsize) + xsize - 1] = buffer;
	}
	break;
    default:
	break;
    }
}
#if 1
/*======================================================================*
 *	テクスチャー を ラスタす					*
 *======================================================================*/
void texture_raster(  /* ２ > ラスター  >１ */
    unsigned short	*tex1,
    unsigned short	*tex2,
    unsigned char       tex_size
)
{
    int i,j,x;
    float r; /*,xf;*/
    unsigned char *tex11,*tex22;
    
    tex1 = (unsigned short *)SEGMENT_TO_KSEG0(tex1);
    tex2 = (unsigned short *)SEGMENT_TO_KSEG0(tex2);

    switch(tex_size) {
    case R_32x32:
//	PRINTF("raster\n");
	for(i = 0; i < 1024; i+=32) {
//	    r = (float) ((i/16 + frcnt/2) & 0x1f) * (2.0f * F_PI / 16.0f);
	    r = (float) ((i/32 + frcnt/4) & 0x1f) * (2.0f * F_PI / 32.0f);
	    x = (int)(sinf(r) * 3.0f);
	    
	    for(j = 0; j < 32; j+=1) {
		tex1[i+ ((x + j) & 0x1f)] = tex2[i+j];
	    }
	    
	}
	break;
	
    case R_64x32:
	for(i = 0; i < 1024+1024/3; i+=64) {
	    r = (float) ((i/64 + frcnt/4) & 0x1f) * (2.0f * F_PI /  8.0f);
	    
/*	    if(fmodf((xf = (sinf(r) * 0.5f) + 0.5f), 1.0f) >= 0.5f) {
	    xf += 1.0f;
	    }
	    
	    x = (int)xf;*/
	    
	    x = (int)(sinf(r) * 1.0f);
	    
	    for(j = 0; j < 64; j+=1) {
		tex1[i+ ((x + j) & 0x3f)] = tex2[i+j];
	    }
	}
	break;

    case R_16x16:
  	for(i = 0; i < 256; i+=16) {
	    r = (float) ((i/16 + frcnt/2) & 0xf) * (2.0f * F_PI / 16.0f);
	    x = (int)(sinf(r) * 2.0f);
	    
	    for(j = 0; j < 16; j+=1) {
		tex1[i+ ((x + j) & 0xf)] = tex2[i+j];
	    }
	    
	}
	break;

    case R_8x8:
	for(i = 0; i < 1024; i+=32) {
	    r = (float) ((i/32 + frcnt/2) & 0x1f) * (2.0f * F_PI / 32.0f);
	    x = (int)(sinf(r) * 2.0f);
	    
	    for(j = 0; j < 32; j+=1) {
		tex1[i+ ((x + j) & 0x1f)] = tex2[i+j];
	    }
	    
	}
	break;
    case R_64x64IA8:
	tex11 = (unsigned char *)tex1;
	tex22 = (unsigned char *)tex2;
	for(i = 0; i < 4096; i+=64) {
//	    r = (float) ((i/64 + frcnt/4) & 0x1f) * (2.0f * F_PI / 64.0f);
	    r = (float) ((i/64 + frcnt/4) & 0x1f) * (2.0f * F_PI / 32.0f);
	    
	    x = (int)(sinf(r) * 4.0f);
	    
	    for(j = 0; j < 64; j+=1) {
		tex11[i+ ((x + j) & 0x3f)] = tex22[i+j];
	    }
	}
	break;
    }
}
#endif
/*======================================================================*
 *									*
 *	ＳＯＦＴ ＩＭＡＧＥ ＤＡＴＡ 補間処理				*
 *									*
 *======================================================================*/
/*----------------------------------------------------------------------*
 *									*
 *	アニメーション データ の 位置 を 調べる				*
 *									*
 *----------------------------------------------------------------------*/
static int si_no(
    SkeletonRecord	*obj_skel,
    SkeletonPtr		*obj_list
)
{
#if 0
    int		i;

    for(i = 0; *(obj_list + i) != NULL; i += 1) {
	if(*(obj_list + i) == obj_skel) return i;
    }
    return 0;
#else
    int		i;

    for(i = 1; *obj_list != NULL; i += 1, obj_list++) {
	if(*obj_list == obj_skel) return i;
    }
    return 0;
#endif
}

/*----------------------------------------------------------------------*
 *									*
 *	データを表示する						*
 *									*
 *----------------------------------------------------------------------*/
static void si_draw_child(
    int			flg,
    SkeletonRecord	*skel0,
    SkeletonPtr		*skel,
    xyz_t		*data,
    int			(*prog0)(int, Gfx **, xyz_t *, xyz_t *, void *),
    void		(*prog1)(int, xyz_t *, void *),
    void		*p
)
{
    int			i;
    int			n;
    Gfx			*d;
    xyz_t		t, r, s;
    xyz_t zero = {
	0.0f,
	0.0f,
	0.0f,
    };

    /* 計算 行列プッシュ */
    push_work();

    /* ローテートデータの位置 */
    n = si_no(skel0, skel);

    skel0 = (SkeletonRecord *)SEGMENT_TO_KSEG0(skel0);

    /* ローテートデータ */
    r = *(data + n);

    /* トランスレートデータ */
    t.x = skel0->ofsx;
    t.y = skel0->ofsy;
    t.z = skel0->ofsz;

    /* シェイプデータ */
    d = skel0->shape;

    push_now();
    
    /* コール プログラム ０ */
    if(prog0 == NULL) {
	i = 0;
    } else {
	i = prog0(n - 1, &d, &t, &r, p);
    }
    

    if(i == 0) {
	translate_work(t.x, t.y, t.z, MULT_MTX);
	rotateZ_work(DEG2RAD(r.z), MULT_MTX);
	rotateY_work(DEG2RAD(r.y), MULT_MTX);
	rotateX_work(DEG2RAD(r.x), MULT_MTX);
	
	if(d != NULL) {

	    if(flg >= 2) {  /* トップはつらいよ */ 
		MtxF_Position_work(&zero, &s);
		
		if(flg != 5)   /* 人間はなし */ 
		    Exstra_light_set(&s);  /* 部品別ライト計算 */
	    }
	    mult_now_work();
	    set_matrix(&NOW_DISP);
	    gSPDisplayList(NEXT_DISP, d);
	}
    }

    /* コール プログラム １ */
    if(prog1 != NULL) {
	prog1(n - 1, &r, p);
    }
    pull_now();

    if(skel0->child != NULL) {
	si_draw_child(flg, skel0->child, skel, data, prog0, prog1, p);
    }

    pull_work();

    if(skel0->brother != NULL) {
	si_draw_child(flg, skel0->brother, skel, data, prog0, prog1, p);
    }
}

/*
  _si_draw
 */
void _si_draw(
    int			flg,
    SkeletonPtr		*seg_skel,
    xyz_t		*data,
    int			(*prog0)(int, Gfx **, xyz_t *, xyz_t *, void *),
    void		(*prog1)(int, xyz_t *, void *),
    void		*p,
    MtxF                *mtx
)
{
    int			i;
    SkeletonPtr		*skel;
    SkeletonRecord	*skel0;
    int			n;
    Gfx			*d;
    xyz_t		t, r;

    /* 計算用行列プッシュ */
    push_work();
    put_work(mtx);
    
    skel  = (SkeletonPtr *)SEGMENT_TO_KSEG0(seg_skel);
    skel0 = (SkeletonRecord *)SEGMENT_TO_KSEG0(*skel);

    /* ローテートデータの位置 */
    n = si_no(*skel, skel);

    /* ローテートデータ */
    r = *(data + n);

    /* トランスレートデータ */
    if(flg & 1) {
	t.x = skel0->ofsx;
	t.y = skel0->ofsy;
	t.z = skel0->ofsz;
    } else {
	t.x = data->x;
	t.y = data->y;
	t.z = data->z;
    }

    /* シェイプデータ */
    d = skel0->shape;

    push_now();
    
    /* コール プログラム ０ */
    if(prog0 == NULL) {
	i = 0;
    } else {
	i = prog0(n - 1, &d, &t, &r, p);
    }

    if(i == 0) {
	translate_work(t.x, t.y, t.z, MULT_MTX);
	rotateZ_work(DEG2RAD(r.z), MULT_MTX);
	rotateY_work(DEG2RAD(r.y), MULT_MTX);
	rotateX_work(DEG2RAD(r.x), MULT_MTX);

	if(d != NULL) {
	    mult_now_work();
	    set_matrix(&NOW_DISP);
	    gSPDisplayList(NEXT_DISP, d);
	}
    }

    /* コール プログラム １ */
    if(prog1 != NULL) {
	prog1(n - 1, &r, p);
    }
    pull_now();

    if(skel0->child != NULL) {
	si_draw_child(flg, skel0->child, skel, data, prog0, prog1, p);
    }

    pull_work();
    
    if(flg >= 2)         /* トップはつらいよ */ 
	mult_now_work();
}

/*----------------------------------------------------------------------*
 *									*
 *	各関節のデータをとる						*
 *									*
 *----------------------------------------------------------------------*/
short si_get(
    AnimeRecord		*anime,
    int			frame,
    xyz_t		*out
)
{
    AnimeRecord		*p;
    unsigned short	joint, *tbl, *prm;
    int			i;

    p = (AnimeRecord *)SEGMENT_TO_KSEG0(anime);

    joint = p->joint;
    tbl = (unsigned short *)SEGMENT_TO_KSEG0(p->anime_table);
    prm = (unsigned short *)SEGMENT_TO_KSEG0(p->anime_param);

    out->x = (float)(short)
	(*(tbl + 0) > frame
	 ? *(prm + *(tbl + 1) + frame) : *(prm + *(tbl + 1)));
    out->y = (float)(short)
	(*(tbl + 2) > frame
	 ? *(prm + *(tbl + 3) + frame) : *(prm + *(tbl + 3)));
    out->z = (float)(short)
	(*(tbl + 4) > frame
	 ? *(prm + *(tbl + 5) + frame) : *(prm + *(tbl + 5)));

    
    out += 1;
    
#if 0
    for(i = 1; i <= joint; i += 1) {
	out->x = (float)
	    (*(tbl + i * 6 + 0) > frame
	     ? *(prm + *(tbl + i * 6 + 1) + frame)
	     : *(prm + *(tbl + i * 6 + 1))) * 360.0f / 65536.0f;
	out->y = (float)
	    (*(tbl + i * 6 + 2) > frame
	     ? *(prm + *(tbl + i * 6 + 3) + frame)
	     : *(prm + *(tbl + i * 6 + 3))) * 360.0f / 65536.0f;
	out->z = (float)
	    (*(tbl + i * 6 + 4) > frame
	     ? *(prm + *(tbl + i * 6 + 5) + frame)
	     : *(prm + *(tbl + i * 6 + 5))) * 360.0f / 65536.0f;
	out += 1;
    }
#else
    tbl += 6;
    for(i = 1 ; i <= joint ; i += 1, tbl += 6, out += 1) {
	out->x = (float)
	    (*(tbl + 0) > frame
	     ? *(prm + *(tbl + 1) + frame)
	     : *(prm + *(tbl + 1))) * 360.0f / 65536.0f;
	out->y = (float)
	    (*(tbl + 2) > frame
	     ? *(prm + *(tbl + 3) + frame)
	     : *(prm + *(tbl + 3))) * 360.0f / 65536.0f;
	out->z = (float)
	    (*(tbl + 4) > frame
	     ? *(prm + *(tbl + 5) + frame)
	     : *(prm + *(tbl + 5))) * 360.0f / 65536.0f;
    }
	
#endif

    return joint + 1;	/* データの数を返す */
}

/*======================================================================*
 *									*
 *	アニメーション データ の フレーム数 を とる			*
 *									*
 *======================================================================*/
short anime_frame(
    AnimeRecord		*anime
)
{
    AnimeRecord		*p;

    p = (AnimeRecord *)SEGMENT_TO_KSEG0(anime);

    return p->frame;
}
/*======================================================================*
 *									*
 *	ディスプレイ リスト から ポリゴン の 大きさ を 調べる。		*
 *									*
 *======================================================================*/
/*----------------------------------------------------------------------*
 *									*
 *	再帰的 に 呼ばれる所						*
 *									*
 *----------------------------------------------------------------------*/
void get_polygon_size_recursive(
    Gfx		*display,
    int		number,
    xyz_t	*small,
    xyz_t	*large,
    int		*fast_flag,
    int		*number_vertex,
    Vtx		*(*p_vertex)
)
{
    long long		*p, *i;

    p = (long long *)SEGMENT_TO_KSEG0(display);

    for(i = p; (int)((*i) >> 56) != G_ENDDL && (i - p) < number; i += 1) {
	switch((int)((*i) >> 56)) {
	case G_DL:
	    get_polygon_size_recursive(
		(Gfx *)(*i & 0xffffffff), (int)((*i >> 32) & 0xffff),
		small, large, fast_flag, number_vertex, p_vertex);
	    break;
	case G_VTX:
	    *p_vertex = (Vtx *)SEGMENT_TO_KSEG0(*i & 0xffffffff);
	    *number_vertex = (int)((*i >> 48) & 0xf);
	    break;
	case G_TRI1:
	    if(*fast_flag == 0) {
		*fast_flag = 1;
		large->x = small->x =
		    (float)((*p_vertex)[(int)((*i) & 0xff)].v.ob[0]);
		large->y = small->y =
		    (float)((*p_vertex)[(int)((*i) & 0xff)].v.ob[1]);
		large->z = small->z =
		    (float)((*p_vertex)[(int)((*i) & 0xff)].v.ob[2]);
	    } else {
		small->x =
		    Min(small->x,
			(float)((*p_vertex)[(int)((*i) & 0xff)].v.ob[0]));
		small->y =
		    Min(small->y,
			(float)((*p_vertex)[(int)((*i) & 0xff)].v.ob[1]));
		small->z =
		    Min(small->z,
			(float)((*p_vertex)[(int)((*i) & 0xff)].v.ob[2]));
		large->x =
		    Max(large->x,
			(float)((*p_vertex)[(int)((*i) & 0xff)].v.ob[0]));
		large->y =
		    Max(large->y,
			(float)((*p_vertex)[(int)((*i) & 0xff)].v.ob[1]));
		large->z =
		    Max(large->z,
			(float)((*p_vertex)[(int)((*i) & 0xff)].v.ob[2]));
	    }
	    small->x =
		Min(small->x,
		    (float)((*p_vertex)[(int)((*i >> 8) & 0xff)].v.ob[0]));
	    small->y =
		Min(small->y,
		    (float)((*p_vertex)[(int)((*i >> 8) & 0xff)].v.ob[1]));
	    small->z =
		Min(small->z,
		    (float)((*p_vertex)[(int)((*i >> 8) & 0xff)].v.ob[2]));
	    large->x =
		Max(large->x,
		    (float)((*p_vertex)[(int)((*i >> 8) & 0xff)].v.ob[0]));
	    large->y =
		Max(large->y,
		    (float)((*p_vertex)[(int)((*i >> 8) & 0xff)].v.ob[1]));
	    large->z =
		Max(large->z,
		    (float)((*p_vertex)[(int)((*i >> 8) & 0xff)].v.ob[2]));
	    small->x =
		Min(small->x,
		    (float)((*p_vertex)[(int)((*i >> 16) & 0xff)].v.ob[0]));
	    small->y =
		Min(small->y,
		    (float)((*p_vertex)[(int)((*i >> 16) & 0xff)].v.ob[1]));
	    small->z =
		Min(small->z,
		    (float)((*p_vertex)[(int)((*i >> 16) & 0xff)].v.ob[2]));
	    large->x =
		Max(large->x,
		    (float)((*p_vertex)[(int)((*i >> 16) & 0xff)].v.ob[0]));
	    large->y =
		Max(large->y,
		    (float)((*p_vertex)[(int)((*i >> 16) & 0xff)].v.ob[1]));
	    large->z =
		Max(large->z,
		    (float)((*p_vertex)[(int)((*i >> 16) & 0xff)].v.ob[2]));
	    break;
	default:
	    break;
	}
    }
}
/*----------------------------------------------------------------------*
 *									*
 *	最初 に 呼ばれる所						*
 *									*
 *----------------------------------------------------------------------*/
void get_polygon_size(
    Gfx		*display,
    int		number,
    xyz_t	*small,
    xyz_t	*large
)
{
    int		fast_flag;
    int		number_vertex;
    Vtx		*p_vertex;

    fast_flag = 0;
    get_polygon_size_recursive(display, number, small, large,
			       &fast_flag, &number_vertex, &p_vertex);
}

/*======================================================================*
 *									*
 *	アニメーション データ から ポリゴン の 大きさ を 調べる。	*
 *									*
 *======================================================================*/
void get_polygon_size_anime_data(
    SkeletonPtr		seg_skel[],
    AnimeRecord		*seg_anime,
    int			frame,
    xyz_t		*small,
    xyz_t		*large
)
{
    short		*tbl;
    unsigned short	*prm;
    SkeletonPtr		*skel;
    SkeletonRecord	*skel0;
    AnimeRecord		*anime;
    int			fast_flag;
    int			number_vertex;
    Vtx			*p_vertex;
    xyz_t		p[8], pw[8];
    int			i;

    skel  = (SkeletonPtr *)SEGMENT_TO_KSEG0(seg_skel);
    skel0 = (SkeletonRecord *)SEGMENT_TO_KSEG0(skel[0]);
    anime = (AnimeRecord *)SEGMENT_TO_KSEG0(seg_anime);

    tbl = (short *)SEGMENT_TO_KSEG0(anime->anime_table);
    prm = (unsigned short *)SEGMENT_TO_KSEG0(anime->anime_param);

    rotateZ_now(ANGLE(
	(float)
	((int)tbl[10] > frame ? prm[(int)tbl[11] + frame] : prm[(int)tbl[11]])
	* 360.0f / 65536.0f), SET_MTX);
    rotateY_now(ANGLE(
	(float)
	((int)tbl[8] > frame ? prm[(int)tbl[9] + frame] : prm[(int)tbl[9]])
	* 360.0f / 65536.0f), MULT_MTX);
    rotateX_now(ANGLE(
	(float)
	((int)tbl[6] > frame ? prm[(int)tbl[7] + frame] : prm[(int)tbl[7]])
	* 360.0f / 65536.0f), MULT_MTX);

    fast_flag = 0;
    if(skel0->shape != NULL) {
	get_polygon_size_recursive(skel0->shape, 0x2000,
				   small, large,
				   &fast_flag, &number_vertex, &p_vertex);
	if(fast_flag != 0) {
	    p[0].x = p[3].x = p[4].x = p[7].x = small->x;
	    p[0].y = p[1].y = p[4].y = p[5].y = large->y;
	    p[0].z = p[1].z = p[2].z = p[3].z = large->z;
	    p[1].x = p[2].x = p[5].x = p[6].x = large->x;
	    p[2].y = p[3].y = p[6].y = p[7].y = small->y;
	    p[4].z = p[5].z = p[6].z = p[7].z = small->z;
	    for(i = 0; i < 8; i += 1) {
//		MtxF_Position(&p[i], &pw[i]);
	    }
	    *small = *large = pw[0];
	    for(i = 1; i < 8; i += 1) {
		small->x = Min(small->x, pw[i].x);
		large->x = Max(large->x, pw[i].x);
		small->y = Min(small->y, pw[i].y);
		large->y = Max(large->y, pw[i].y);
		small->z = Min(small->z, pw[i].z);
		large->z = Max(large->z, pw[i].z);
	    }
	}
    }

/*    if(skel0->child != NULL)
	draw_child(skel0->child, skel, anime, frame);*/
}

/*===========================================================================
  function : 減速接近計算
  entry :
  float *a  : i/o : 現在の値（計算後書き換えられる）
  float b   : i/  : 目標の値
  float p   : i/  : 変化率（目標に対しての変化する割合）
  float max : i/  : 変化値の最大値（絶対値）
  float min : i/  : 変化値の最小値（絶対値）この値に達したときは*a = bになる
  =============================================================================*/

float add_calc(float *a, float b, float p, float max, float min)
{
    float s;

    if((s = b - *a) != 0.0f) {
	s *= p;
	if(s >= min || s <= -min)  {
	    if(s > max)
		s = max;
	    else if(s < -max)
		s = -max;
	    *a += s;
	} else if(s < min) {
	    s = min;
	    *a += s;
	    if(*a > b)
		*a = b;
	} else if(s > -min) {
	    s = -min;
	    *a += s;
	    if(*a < b)
		*a = b;
	}
    }
    return s;
}

/*======================================================================*
 *	減速接近計算（角度用） 						*
 *======================================================================*/

float add_calc_a(float *a, float b, float p, float max, float min)
{
    float s;

    
    if((s = b - *a) != 0.0f) {

	if( s > 180.0f)  {
	    s -= 360.0f;
	} else if( s < -180.0f)  {
		s += 360.0f;
	}

	s *= p;

	if(s >= min || s <= -min)  {
	
	    if(s > max)
		s = max;
	    else if(s < -max)
		s = -max;
	    
	    *a += s;
	
	} else if(s <  min) {
		s = min;
		*a += s;
		if(*a > b)
		    *a = b;
	} else if (s > -min) {
	    s = -min;
	    *a += s;
	    if(*a < b)
		*a = b;
	}
	
    }

    if(*a >= 360.0f)
	*a -= 360.0f;
    else if(*a < 0.0f)
	*a += 360.0f;

    return s;
}

/*-----------------------------------------------------------------------
  アニメーション補間計算
  -----------------------------------------------------------------------*/
void anime_calc(xyz_t *a,
		xyz_t *b,
		int s,
		int c,
		float p,
		float max,
		float min
)
{
    xyz_t *angle0P;
    xyz_t *angle1P;
    int i;
    
    switch (s) {  /* 0は完全ロック*/
    case 0 :
	for(i = 0; i < c; i++)  {
	    b[i].x = a[i].x;
	    b[i].y = a[i].y;
	    b[i].z = a[i].z;
	}
	break;
    case 1 :
	angle0P = &b[0];
	angle1P = &a[0];
	/*トランスレートデーター*/
	add_calc(&angle0P->x,  angle1P->x, p, max, min);
	add_calc(&angle0P->y,  angle1P->y, p, max, min);
	add_calc(&angle0P->z,  angle1P->z, p, max, min);
	angle0P++;
	angle1P++;
	
	for(i = 1 ; i < c ; i++, angle0P++, angle1P++)  {
	    /* ローテートデータ */
	    add_calc_a(&angle0P->x,  angle1P->x, p, max, min);
	    add_calc_a(&angle0P->y,  angle1P->y, p, max, min);
	    add_calc_a(&angle0P->z,  angle1P->z, p, max, min);
	}
	break;
    default :
	break;
    }
}
/*-----------------------------------------------------------------------
      3D座標移動計算(おもにカメラ用）  (使い物になるかどうか楽しみ）
  -----------------------------------------------------------------------*/
int add_calc_3D(xyz_t *now,           /* 現在座標 */
		xyz_t *after,         /* 目標座標 */
		xyz_t *angle,         /* 計算用角度 */
		float v_sp,           /* 移動ベクトル速度 */
		float turn_power,     /* 軌道補正力 (Max : 1.0f)*/
		float turn_max,       /* 軌道補正最大値 */
		float hit_range       /* 到達判定範囲 */
)                                     /* return:  1 到達判定範囲内 */ 
{
    float x,y,z;
    float xa,ya;
    xyz_t mae = {0.0f, 0.0f, 0.0f},sp;
    MtxF  m;
    
    x = after->x - now->x;
    y = after->y - now->y;
    z = after->z - now->z;

    ya = rad_ang(fatan3( x, z ));
    xa = rad_ang(-(fatan3(y, sqrtf(x*x + z*z))));

    add_calc_a(&angle->y,
	       ya,
	       turn_power,
	       turn_max,
	       0.0f);
    add_calc_a(&angle->x,
	       xa,
	       turn_power,
	       turn_max,
	       0.0f);
    
    _sys_rotateY(&m, DEG2RAD(angle->y), SET_MTX);
    _sys_rotateX(&m, DEG2RAD(angle->x), MULT_MTX);

    mae.z = v_sp;
    
    _sys_MtxF_PositionRS(&m, &mae, &sp);

    now->x += sp.x;
    now->y += sp.y;
    now->z += sp.z;
    
    x = after->x - now->x;
    y = after->y - now->y;
    z = after->z - now->z;

    return ( (sqrtf(x*x + y*y + z*z) < hit_range) );
}

/*======================================================================*
 *									*
 *	Ｔｅｘｔｕｒｅ Ｒｅｃｔａｎｇｌｅ を 使って表示する		*
 *									*
 *======================================================================*/
void texture_rectangleCI4(
    Gfx			**d,
    void		*timg,
    void		*timgtlut,
    unsigned int	width,
    unsigned int	height,
    float		px,
    float		py,
    float 		xs,
    float 		ys
)
{
    gDPLoadTLUT((*d)++, 0x10, 0x100, timgtlut);
    gDPLoadTextureBlock_4b((*d)++, timg, G_IM_FMT_CI,
			   width, height, 0, G_TX_NOMIRROR, G_TX_NOMIRROR,
			   G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD);
    gSPTextureRectangle((*d)++, (int)(px * 0x4), (int)(py * 0x4),
			(int)((px + (width * xs)) * 0x4),
			(int)((py + (height * ys )) * 0x4),
			G_TX_RENDERTILE, 0 * 0x20, 0 * 0x20,
			(int)(1 / xs * 0x400), (int)(1 / ys * 0x400));
}

void texture_rectangleCI4F(
    Gfx			**d,
    void		*timg,
    void		*timgtlut,
    unsigned int	width,
    unsigned int	height,
    float		px,
    float		py,
    float 		xs,
    float 		ys
)
{
    gDPLoadTLUT((*d)++, 0x10, 0x100, timgtlut);
    gDPLoadTextureBlock_4b((*d)++, timg, G_IM_FMT_CI,
			   width, height, 0, G_TX_NOMIRROR, G_TX_NOMIRROR,
			   G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD);
    gSPTextureRectangleFlip((*d)++, (int)(px * 0x4), (int)(py * 0x4),
			    (int)((px + (width * xs)) * 0x4),
			    (int)((py + (height * ys )) * 0x4),
			    G_TX_RENDERTILE,
			    0 * 0x20,
			    0 * 0x20,
			    (int)(1 / xs * 0x400) ,(int)(1 / ys * 0x400) );
}

void texture_rectangleCI4X(
    Gfx			**d,
    void		*timg,
    void		*timgtlut,
    unsigned int	width,
    unsigned int	height,
    float		px,
    float		py,
    float 		xs,
    float 		ys
)
{
    gDPLoadTLUT((*d)++, 0x10, 0x100, timgtlut);
    gDPLoadTextureBlock_4b((*d)++, timg, G_IM_FMT_CI,
			   width, height, 0, G_TX_MIRROR, G_TX_MIRROR,
			   G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD);
    gSPTextureRectangle((*d)++, (int)(px * 0x4), (int)(py * 0x4),
			(int)((px + (width * xs)) * 0x4),
			(int)((py + (height * ys )) * 0x4),
			G_TX_RENDERTILE,
			(width - 1) * 0x20,
			0 * 0x20,
			(int)(-1 / xs * 0x400) & 0xffff,
			(int)(1 / ys * 0x400));
}

void texture_rectangleCI4Y(
    Gfx			**d,
    void		*timg,
    void		*timgtlut,
    unsigned int	width,
    unsigned int	height,
    float		px,
    float		py,
    float 		xs,
    float 		ys
)
{
    gDPLoadTLUT((*d)++, 0x10, 0x100, timgtlut);
    gDPLoadTextureBlock_4b((*d)++, timg, G_IM_FMT_CI,
			   width, height, 0, G_TX_MIRROR, G_TX_MIRROR,
			   G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD);
    gSPTextureRectangle((*d)++, (int)(px * 0x4), (int)(py * 0x4),
			(int)((px + (width * xs)) * 0x4),
			(int)((py + (height * ys )) * 0x4),
			G_TX_RENDERTILE,
			0 * 0x20,
			(height - 1) * 0x20,
			(int)(1 / xs * 0x400),
			(int)(-1 / ys * 0x400) & 0xffff );
}

void texture_rectangleCI8(
    Gfx			**d,
    void		*timg,
    void		*timgtlut,
    unsigned int	width,
    unsigned int	height,
    float		px,
    float		py,
    float 		xs,
    float 		ys
)
{
    gDPLoadTLUT((*d)++, 0x100, 0x100, timgtlut);
    gDPLoadTextureBlock((*d)++, timg, G_IM_FMT_CI, G_IM_SIZ_8b,
			width, height, 0, G_TX_NOMIRROR, G_TX_NOMIRROR,
			G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD);
    gSPTextureRectangle((*d)++, (int)(px * 0x4), (int)(py * 0x4),
			(int)((px + (width * xs)) * 0x4),
			(int)((py + (height * ys )) * 0x4),
			G_TX_RENDERTILE, 0 * 0x20, 0 * 0x20,
			(int)(1 / xs * 0x400), (int)(1 / ys * 0x400));
}

void texture_rectangleRGBA16(
    Gfx			**d,
    void		*timg,
    unsigned int	width,
    unsigned int	height,
    float		px,
    float		py,
    float 		xs,
    float 		ys
)
{
    gDPLoadTextureBlock((*d)++, timg, G_IM_FMT_RGBA, G_IM_SIZ_16b,
			width, height, 0, G_TX_NOMIRROR, G_TX_NOMIRROR,
			G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD);
    gSPTextureRectangle((*d)++, (int)(px * 0x4), (int)(py * 0x4),
			(int)((px + (width * xs)) * 0x4),
			(int)((py + (height * ys )) * 0x4),
			G_TX_RENDERTILE, 0 * 0x20, 0 * 0x20,
			(int)(1 / xs * 0x400), (int)(1 / ys * 0x400));
}

void texture_rectangleRGBA16X(
    Gfx			**d,
    void		*timg,
    unsigned int	width,
    unsigned int	height,
    float		px,
    float		py,
    float 		xs,
    float 		ys
)
{
    gDPLoadTextureBlock((*d)++, timg, G_IM_FMT_RGBA, G_IM_SIZ_16b,
			width, height, 0, G_TX_NOMIRROR, G_TX_NOMIRROR,
			G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD);
    gSPTextureRectangle((*d)++, (int)(px * 0x4), (int)(py * 0x4),
			(int)((px + (width * xs)) * 0x4),
			(int)((py + (height * ys )) * 0x4),
			G_TX_RENDERTILE,
			(width - 1) * 0x20,
			0 * 0x20,
			(int)(-1 / xs * 0x400) & 0xffff,
			(int)(1 / ys * 0x400));
}


void texture_rectangleIA8(
    Gfx			**d,
    void		*timg,
    unsigned int	width,
    unsigned int	height,
    float		px,
    float		py,
    float 		xs,
    float 		ys
)
{
    gDPLoadTextureBlock((*d)++, timg, G_IM_FMT_IA, G_IM_SIZ_8b,
			width, height, 0, G_TX_NOMIRROR, G_TX_NOMIRROR,
			G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD);
    gSPTextureRectangle((*d)++, (int)(px * 0x4), (int)(py * 0x4),
			(int)((px + (width * xs)) * 0x4),
			(int)((py + (height * ys )) * 0x4),
			G_TX_RENDERTILE, 0 * 0x20, 0 * 0x20,
			(int)(1 / xs * 0x400), (int)(1 / ys * 0x400));
}

void texture_rectangleIA8F(
    Gfx			**d,
    void		*timg,
    unsigned int	width,
    unsigned int	height,
    float		px,
    float		py,
    float 		xs,
    float 		ys
)
{
    gDPLoadTextureBlock((*d)++, timg, G_IM_FMT_IA, G_IM_SIZ_8b,
			width, height, 0, G_TX_NOMIRROR, G_TX_NOMIRROR,
			G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD);
    gSPTextureRectangleFlip((*d)++, (int)(px * 0x4), (int)(py * 0x4),
			    (int)((px + (height * xs)) * 0x4),
			    (int)((py + (width * ys )) * 0x4),
			    G_TX_RENDERTILE,
			    (width - 1) * 0x20,
			    0 * 0x20,
			    (int)(-1 / ys * 0x400) & 0xffff,
			    (int)(1 / xs * 0x400));
}

void texture_rectangleIA8FY(
    Gfx			**d,
    void		*timg,
    unsigned int	width,
    unsigned int	height,
    float		px,
    float		py,
    float 		xs,
    float 		ys
)
{
    gDPLoadTextureBlock((*d)++, timg, G_IM_FMT_IA, G_IM_SIZ_8b,
			width, height, 0, G_TX_NOMIRROR, G_TX_NOMIRROR,
			G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD);
    gSPTextureRectangleFlip((*d)++, (int)(px * 0x4), (int)(py * 0x4),
			    (int)((px + (height * xs)) * 0x4),
			    (int)((py + (width * ys)) * 0x4),
			    G_TX_RENDERTILE,
			    0 * 0x20,
			    (height - 1) * 0x20,
			    (int)(1 / ys * 0x400),
			    (int)(-1 / xs * 0x400) & 0xffff);
}

void texture_rectangleIA8X(
    Gfx			**d,
    void		*timg,
    unsigned int	width,
    unsigned int	height,
    float		px,
    float		py,
    float 		xs,
    float 		ys
)
{
    gDPLoadTextureBlock((*d)++, timg, G_IM_FMT_IA, G_IM_SIZ_8b,
			width, height, 0, G_TX_NOMIRROR, G_TX_NOMIRROR,
			G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD);
    gSPTextureRectangle((*d)++, (int)(px * 0x4), (int)(py * 0x4),
			(int)((px + (width * xs)) * 0x4),
			(int)((py + (height * ys )) * 0x4),
			G_TX_RENDERTILE,
			(width - 1) * 0x20,
			0 * 0x20,
			(int)(-1 / xs * 0x400) & 0xffff,
			(int)(1 / ys * 0x400));
}

void texture_rectangleIA8Y(
    Gfx			**d,
    void		*timg,
    unsigned int	width,
    unsigned int	height,
    float		px,
    float		py,
    float 		xs,
    float 		ys
)
{
    gDPLoadTextureBlock((*d)++, timg, G_IM_FMT_IA, G_IM_SIZ_8b,
			width, height, 0, G_TX_NOMIRROR, G_TX_NOMIRROR,
			G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD);
    gSPTextureRectangle((*d)++, (int)(px * 0x4), (int)(py * 0x4),
			(int)((px + (width * xs)) * 0x4),
			(int)((py + (height * ys )) * 0x4),
			G_TX_RENDERTILE,
			0 * 0x20,
			(height -1) * 0x20,
			(int)(1 / xs * 0x400),
			(int)(-1 / ys * 0x400) & 0xffff);
}

void texture_rectangleIA16(
    Gfx			**d,
    void		*timg,
    unsigned int	width,
    unsigned int	height,
    float		px,
    float		py,
    float 		xs,
    float 		ys
)
{
    gDPLoadTextureBlock((*d)++, timg, G_IM_FMT_IA, G_IM_SIZ_16b,
			width, height, 0, G_TX_NOMIRROR, G_TX_NOMIRROR,
			G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD);
    gSPTextureRectangle((*d)++, (int)(px * 0x4), (int)(py * 0x4),
			(int)((px + (width * xs)) * 0x4),
			(int)((py + (height * ys )) * 0x4),
			G_TX_RENDERTILE, 0 * 0x20, 0 * 0x20,
			(int)(1 / xs * 0x400), (int)(1 / ys * 0x400));
}

void texture_rectangleIA16X(
    Gfx			**d,
    void		*timg,
    unsigned int	width,
    unsigned int	height,
    float		px,
    float		py,
    float 		xs,
    float 		ys
)
{
    gDPLoadTextureBlock((*d)++, timg, G_IM_FMT_IA, G_IM_SIZ_16b,
			width, height, 0, G_TX_MIRROR, G_TX_MIRROR,
			G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD);
    gSPTextureRectangle((*d)++, (int)(px * 0x4), (int)(py * 0x4),
			(int)((px + (width * xs)) * 0x4),
			(int)((py + (height * ys )) * 0x4),
			G_TX_RENDERTILE,
			(width - 1) * 0x20,
			0 * 0x20,
			(int)(-1 / xs * 0x400) & 0xffff,
			(int)(1 / ys * 0x400));
}

void texture_rectangleIA16Y(
    Gfx			**d,
    void		*timg,
    unsigned int	width,
    unsigned int	height,
    float		px,
    float		py,
    float 		xs,
    float 		ys
)
{
    gDPLoadTextureBlock((*d)++, timg, G_IM_FMT_IA, G_IM_SIZ_16b,
			width, height, 0, G_TX_MIRROR, G_TX_MIRROR,
			G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD);
    gSPTextureRectangle((*d)++, (int)(px * 0x4), (int)(py * 0x4),
			(int)((px + (width * xs)) * 0x4),
			(int)((py + (height * ys )) * 0x4),
			G_TX_RENDERTILE,
			0 * 0x20,
			(height -1) * 0x20,
			(int)(1 / xs * 0x400),
			(int)(-1 / ys * 0x400) & 0xffff);
}

void texture_rectangleIA16XY(
    Gfx			**d,
    void		*timg,
    unsigned int	width,
    unsigned int	height,
    float		px,
    float		py,
    float 		xs,
    float 		ys
)
{
    gDPLoadTextureBlock((*d)++, timg, G_IM_FMT_IA, G_IM_SIZ_16b,
			width, height, 0, G_TX_MIRROR, G_TX_MIRROR,
			G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD);
    gSPTextureRectangle((*d)++, (int)(px * 0x4), (int)(py * 0x4),
			(int)((px + (width * xs)) * 0x4),
			(int)((py + (height * ys )) * 0x4),
			G_TX_RENDERTILE,
			(width - 1) * 0x20,
			(height - 1) * 0x20,
			(int)(-1 / xs * 0x400) & 0xffff,
			(int)(-1 / ys * 0x400) & 0xffff);
}

void texture_rectangleRGBA32(
    Gfx			**d,
    void		*timg,
    unsigned int	width,
    unsigned int	height,
    float		px,
    float		py,
    float 		xs,
    float 		ys
)
{
    gDPLoadTextureBlock((*d)++, timg, G_IM_FMT_RGBA, G_IM_SIZ_32b,
			width, height, 0, G_TX_NOMIRROR, G_TX_NOMIRROR,
			G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD);
    gSPTextureRectangle((*d)++, (int)(px * 0x4), (int)(py * 0x4),
			(int)((px + (width * xs)) * 0x4),
			(int)((py + (height * ys )) * 0x4),
			G_TX_RENDERTILE, 0 * 0x20, 0 * 0x20,
			(int)(1 / xs * 0x400), (int)(1 / ys * 0x400));
}

/*======================================================================*
 *									*
 *	フェード							*
 *									*
 *======================================================================*/
/* フェードアウト */
#if 0
/*HAYAKAWA Special*/
#define RM_FADEOUT_FOX(clk) \
    IM_RD | CLR_ON_CVG | CVG_DST_SAVE | FORCE_BL | ZMODE_OPA | \
    GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA)
#else
#define RM_FADEOUT_FOX(clk) \
    IM_RD | CVG_DST_SAVE | FORCE_BL | ZMODE_OPA | \
    GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA)
#endif
#define	G_RM_FADEOUT_FOX RM_FADEOUT_FOX(1)
#define	G_RM_FADEOUT_FOX2 RM_FADEOUT_FOX(2)

void fade(
    Gfx		**d,
    int		x0,
    int		y0,
    int		x1,
    int		y1,
    char	r,
    char	g,
    char	b,
    char	a
)
{
#if 1
    if(a != 0) {
	gDPPipeSync((*d)++);
	gDPSetPrimColor((*d)++, 0, 0, r, g, b, a);
#if 1
	/*HAYAKAWA*/
	gDPSetColorDither((*d)++, G_CD_NOISE);
	gDPSetAlphaDither((*d)++, G_AD_NOISE);
#else
//	gDPSetColorDither((*d)++, G_CD_NOISE);
//	gDPSetAlphaDither((*d)++, G_AD_PATTERN);
	gDPSetColorDither((*d)++, G_CD_MAGICSQ);
	gDPSetAlphaDither((*d)++, G_AD_PATTERN);
#endif
	gDPSetCycleType((*d)++, G_CYC_1CYCLE);
	gDPSetCombineMode((*d)++, G_CC_PRIMITIVE, G_CC_PRIMITIVE);
	gDPSetRenderMode((*d)++, G_RM_FADEOUT_FOX, G_RM_FADEOUT_FOX2);
	gDPFillRectangle((*d)++, x0, y0, x1, y1);
    }
#endif
}

/*======================================================================*
 *	角度 ー＞ 座標                          			*
 *======================================================================*/
void angle_position(xyz_t *xyz, float xa, float ya, float v)
{
    xyz_t mae;
    
    rotateY_work( DEG2RAD(ya) , SET_MTX);
    rotateX_work( DEG2RAD(xa) , MULT_MTX);
    
    mae.x =
    mae.y =  0.0f;
    mae.z =  v;
    
    MtxF_PositionRS_work(&mae, xyz);
    
}
#if 0
/*+=====================================================================+
  |	ラジアン ー＞ 度 変換                                  		|
  +=====================================================================+*/
/*rad_angは,rad2degを使うようになりました 96/11/5*/
/*#define rad_ang(X) rad2deg(X) 設定*/
float rad_ang(float ang)
{
    if(rad < 0.0f) {
	rad = DEG2RAD(360.0f) + rad;
    }

    return RAD2DEG(rad);
}
#endif


/*-------------------------------------------------------------------------
  function :
   rad2deg
  -------------------------------------------------------------------------*/
float rad2deg(float ang)
{
    ang = RAD2DEG(ang); /*この時点でangは,度になっている*/
    while (ang < 0.0f) {
	ang += 360.0f;
    }

#if 0
    /*いらないかな？*/
    while (ang > 360.0f) {
	ang -= 360.0f;
    }
#endif

    return ang;
}
/*======================================================================*
 *									*
 *	レンダリング バッファ の 設定					*
 *									*
 *======================================================================*/
u16 *set_renderbuffer(
    Gfx			**d,
    unsigned char	xs,
    unsigned char	ys
)
{
    u16		*rt;
    u16		perspNorm;

    xs += 15;
    xs &= 0x70;

    rt = RenderBufferP;
    RenderBufferP = RenderBufferP + (xs * ys);

    gDPPipeSync((*d)++);
    gDPSetCycleType((*d)++, G_CYC_FILL);
    gDPSetRenderMode((*d)++, G_RM_NOOP, G_RM_NOOP2);

    /*
     *	ビューポート セット
     */
    NOW_VIEW->vp.vscale[0] = xs * 2;
    NOW_VIEW->vp.vscale[1] = ys * 2;
    NOW_VIEW->vp.vscale[2] = G_MAXZ / 2;
    NOW_VIEW->vp.vscale[3] = 0;
    NOW_VIEW->vp.vtrans[0] = xs * 2;
    NOW_VIEW->vp.vtrans[1] = ys * 2;
    NOW_VIEW->vp.vtrans[2] = G_MAXZ / 2;
    NOW_VIEW->vp.vtrans[3] = 0;
    gSPViewport((*d)++, NEXT_VIEW);
    
    /*
     *	シザー セット
     */
    gDPSetScissor((*d)++, G_SC_NON_INTERLACE, 0, 0, xs, ys);

    /*
     *	Ｚバッファ クリア
     */
    gDPSetDepthImage((*d)++, ZBuffer);
    gDPSetColorImage((*d)++, G_IM_FMT_RGBA, G_IM_SIZ_16b, xs, ZBuffer);
    gDPSetFillColor((*d)++,
		    GPACK_ZDZ(G_MAXFBZ, 0) << 16 | GPACK_ZDZ(G_MAXFBZ, 0));
    gDPFillRectangle((*d)++, 0, 0, xs - 1, ys - 1);

    gDPPipeSync((*d)++);
    gDPSetDepthSource((*d)++, G_ZS_PIXEL);

    /*
     *	画面 クリア
     */
    gDPSetColorImage((*d)++, G_IM_FMT_RGBA, G_IM_SIZ_16b, xs, rt);
    gDPSetColorDither((*d)++, G_CD_DISABLE);
    gDPSetFillColor((*d)++, 0);
    gDPSetFillColor((*d)++,
		    ((unsigned long)(BG_color | 1) << 16)
		    | (unsigned long)(BG_color | 1));
    gDPFillRectangle((*d)++, 0, 0, xs - 1, ys - 1);

    gDPPipeSync((*d)++);

    guPerspective(NOW_MTX, &perspNorm, Fovy, (float)xs / (float)ys,
		  10.0f, 12800.0f, 1.0f);
    gSPPerspNormalize((*d)++, perspNorm);
    gSPMatrix((*d)++, NEXT_MTX,
	      G_MTX_PROJECTION | G_MTX_LOAD | G_MTX_NOPUSH);
    guLookAt(NOW_MTX,
	     0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -12800.0f, 0.0f, 1.0f, 0.0f);
    gSPMatrix((*d)++, NEXT_MTX,
	      G_MTX_PROJECTION | G_MTX_MUL | G_MTX_NOPUSH);
    put_now(&MtxF_clear);

    return rt;
}

/*======================================================================*
 *									*
 *	常駐の数字 を 表示する						*
 *									*
 *======================================================================*/
void jt_number(
    int		x,
    int		y,
    int		n
)
{
    unsigned char	*texture[] = {
	JT_0_txt, JT_1_txt, JT_2_txt, JT_3_txt, JT_4_txt,
	JT_5_txt, JT_6_txt, JT_7_txt, JT_8_txt, JT_9_txt,};

    unsigned short	*texturetlut[] = {
	JT_0_txttlut, JT_1_txttlut, JT_2_txttlut, JT_3_txttlut, JT_4_txttlut,
	JT_5_txttlut, JT_6_txttlut, JT_7_txttlut, JT_8_txttlut, JT_9_txttlut,};
    int			i, flg;

    flg = OFF;
    i =	10000000;
    n %= i;
    for(i /= 10; i != 1; i /= 10) {
	if(n / i || flg == ON) {
	    texture_rectangleCI4(&NOW_DISP, texture[n / i], texturetlut[n / i],
			       16, 8,
			      (float)x, (float)y, 1.0f, 1.0f);
	    x += 9;
	    n %= i;
	    flg = ON;
	}
    }
    texture_rectangleCI4(&NOW_DISP, texture[n / i], texturetlut[n / i],
			 16, 8,
			 (float)x, (float)y, 1.0f, 1.0f);
}

/*======================================================================*/
/* 数字 を 表示する							*/
/*======================================================================*/
void moji_number(
    int		x,
    int		y,
    int		n
)
{
    static unsigned char *num_text[] = {
	MOJI_00_txt, MOJI_01_txt, MOJI_02_txt, MOJI_03_txt, MOJI_04_txt,
	MOJI_05_txt, MOJI_06_txt, MOJI_07_txt, MOJI_08_txt, MOJI_09_txt,
    };

    int			i, flg;

    flg = OFF;
    i =	10000000;
    n %= i;
    for(i /= 10; i != 1; i /= 10) {
	if(n / i || flg == ON) {
	    texture_rectangleIA8(&NOW_DISP, num_text[n / i],
			       16, 8,
			      (float)x, (float)y, 1.0f, 1.0f);
	    x += 9;
	    n %= i;
	    flg = ON;
	}
    }
    texture_rectangleIA8(&NOW_DISP, num_text[n / i],
			 16, 8,
			 (float)x, (float)y, 1.0f, 1.0f);
}

static char sch[] = " ABCDEFGHIJKLMNOPQRSTUVWXYZ!:-.0123456789";
static char rch[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ. 0123456789st-";
static char rchw[] = {
/*   A   B   C   D   E   F   G   H  I   J   K   L   M   N   O   P	*/
    15, 14, 14, 13, 13, 13, 14, 14, 5, 12, 14, 12, 16, 14, 15, 13,
/*   Q   R   S   T   U   V   W   X   Y   Z   .	sp		*/
    16, 14, 13, 13, 13, 16, 17, 17, 16, 13, 5, 16,
/*   0   1   2   3   4   5   6   7   8   9   s  t  -			*/
    13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 10, 9, 14
};

/*======================================================================*
 *									*
 *	ＭＯＪＩ を 表示する						*
 *									*
 *======================================================================*/
void moji_puts(
    int		x,
    int		y,
    float	xs,
    float	ys,
    char	*s
)
{
    static unsigned char *rtxt[] = {
	MOJI_nA_txt, MOJI_nB_txt, MOJI_nC_txt, MOJI_nD_txt, MOJI_nE_txt,
	MOJI_nF_txt, MOJI_nG_txt, MOJI_nH_txt, MOJI_nI_txt, MOJI_nJ_txt,
	MOJI_nK_txt, MOJI_nL_txt, MOJI_nM_txt, MOJI_nN_txt, MOJI_nO_txt,
	MOJI_nP_txt, MOJI_nQ_txt, MOJI_nR_txt, MOJI_nS_txt, MOJI_nT_txt,
	MOJI_nU_txt, MOJI_nV_txt, MOJI_nW_txt, MOJI_nX_txt, MOJI_nY_txt,
	MOJI_nZ_txt, MOJI_priod_txt,NULL,
	MOJI_s0_txt, MOJI_s1_txt, MOJI_s2_txt, MOJI_s3_txt, MOJI_s4_txt,
	MOJI_s5_txt, MOJI_s6_txt, MOJI_s7_txt, MOJI_s8_txt, MOJI_s9_txt,
	MOJI_nsS_txt, MOJI_nsT_txt,MOJI_nYOKO_txt,
    };

    int		i;
    float	xp = (float)x, yp = (float)y;
    int xsiz;
    int		f = OFF;
    
    for(; *s != NULL; s += 1) {
	for(i = 0; i < number(rch) && rch[i] != *s; i += 1);
	if(rch[i] == *s) {
	    if(f == ON && *(s - 1) == 'Y' && *s == 'A') xp -= 3.0f;
	    if(f == ON && *(s - 1) == 'K' && *s == 'A') xp -= 1.0f;
	    if(f == ON && *(s - 1) == 'A' && *s == 'O') xp -= 2.0f;
	    if(f == ON && *(s - 1) == 'T' && *s == 'A') xp -= 3.0f;
	    if(f == ON && *(s - 1) == 'A' && *s == 'Y') xp -= 4.0f;
	    if(f == ON && *(s - 1) == 'K' && *s == 'I') xp -= 1.0f;
	    if(f == ON && *(s - 1) == 'K' && *s == 'O') xp -= 3.0f;
	    if(f == ON && *(s - 1) == 'A' && *s == 'J') xp -= 1.0f;
	    if(f == ON && *(s - 1) == 'W' && *s == 'A') xp -= 2.0f;
	    if(f == ON && *(s - 1) == 'Y' && *s == 'O') xp -= 3.0f;
	    if(f == ON && *(s - 1) == 'A' && *s == 'T') xp -= 3.0f;
	    if(f == ON && *(s - 1) == 'A' && *s == 'W') xp -= 3.0f;
	    if(f == ON && *(s - 1) == 'O' && *s == 'T') xp -= 1.0f;
	    if(f == ON && *(s - 1) == 'A' && *s == 'G') xp -= 2.0f;
	    if(f == ON && *(s - 1) == 'O' && *s == 'Y') xp -= 2.0f;
	    if(f == ON && *(s - 1) == 'A' && *s == 'J') xp -= 1.0f;
	    if(f == ON && *(s - 1) == 'T' && *s == 'O') xp -= 2.0f;
	    if(f == ON && *(s - 1) == 'K' && *s == 'U') xp -= 1.0f;
	    if(f == ON && *(s - 1) == 'A' && *s == 'S') xp -= 2.0f;
	    if(f == ON && *(s - 1) == 'R' && *s == 'O') xp -= 1.0f;
	    if(f == ON && *(s - 1) == 'K' && *s == 'Y') xp -= 1.0f;
	    if(f == ON && *(s - 1) == 'N' && *s == 'J') xp -= 1.0f;
	    if(f == ON && *(s - 1) == 'K' && *s == 'E') xp -= 1.0f;
	    if(f == ON && *(s - 1) == 'S' && *s == 't') xp -= 2.0f;
	    if(f == ON && *(s - 1) == 'X' && *s == 'X') xp -= 3.0f;
	    if(f == ON && *(s - 1) == 'O' && *s == 'X') xp -= 1.0f;
	    if(f == ON && *(s - 1) == 'W' && *s == 'W') xp -= 1.0f;
	    if(f == ON && *(s - 1) == 'X' && *s == 'W') xp -= 1.0f;
	    if(f == ON && *(s - 1) == 'W' && *s == 'X') xp -= 1.0f;


	    if(f == ON && *(s - 1) == 'H' && *s == 'O') xp += 1.0f;
	    if(f == ON && *(s - 1) == 'J' && *s == 'I') xp += 1.0f;
	    if(f == ON && *(s - 1) == 'I' && *s == 'N') xp += 1.0f;
	    if(f == ON && *(s - 1) == 'I' && *s == 'M') xp += 1.0f;
	    if(f == ON && *(s - 1) == 'I' && *s == 'D') xp += 1.0f;
	    if(f == ON && *(s - 1) == 'U' && *s == 'K') xp += 1.0f;


	    if(rtxt[i] != NULL) {
		xsiz = 16;
		if( *s == 'W' || *s == 'X' ) xsiz = 32;
		texture_rectangleIA8(&NOW_DISP,
				     rtxt[i],
				     xsiz, 15,
				     xp, yp, xs, ys);
	    }
	    xp += (rchw[i]*xs)+2.0f;
	    f = ON;
	}
    }
}

/*======================================================================*
 *									*
 *	ＭＯＪＩ の ドット数を返す					*
 *									*
 *======================================================================*/
int mojiL_dot( char *s )
{
    int i;
    int dots;
    int	f = OFF;

    dots = 0;
    for(; *s != NULL; s += 1) {
	for(i = 0; i < number(rch) && rch[i] != *s; i += 1);
	if(rch[i] == *s) {
	    if(f == ON && *(s - 1) == 'Y' && *s == 'A') dots -= 3.0f;
	    if(f == ON && *(s - 1) == 'K' && *s == 'A') dots -= 1.0f;
	    if(f == ON && *(s - 1) == 'A' && *s == 'O') dots -= 2.0f;
	    if(f == ON && *(s - 1) == 'T' && *s == 'A') dots -= 3.0f;
	    if(f == ON && *(s - 1) == 'A' && *s == 'Y') dots -= 4.0f;
	    if(f == ON && *(s - 1) == 'K' && *s == 'I') dots -= 1.0f;
	    if(f == ON && *(s - 1) == 'K' && *s == 'O') dots -= 3.0f;
	    if(f == ON && *(s - 1) == 'A' && *s == 'J') dots -= 1.0f;
	    if(f == ON && *(s - 1) == 'W' && *s == 'A') dots -= 2.0f;
	    if(f == ON && *(s - 1) == 'Y' && *s == 'O') dots -= 3.0f;
	    if(f == ON && *(s - 1) == 'A' && *s == 'T') dots -= 3.0f;
	    if(f == ON && *(s - 1) == 'A' && *s == 'W') dots -= 3.0f;
	    if(f == ON && *(s - 1) == 'O' && *s == 'T') dots -= 1.0f;
	    if(f == ON && *(s - 1) == 'A' && *s == 'G') dots -= 2.0f;
	    if(f == ON && *(s - 1) == 'O' && *s == 'Y') dots -= 2.0f;
	    if(f == ON && *(s - 1) == 'A' && *s == 'J') dots -= 1.0f;
	    if(f == ON && *(s - 1) == 'T' && *s == 'O') dots -= 2.0f;
	    if(f == ON && *(s - 1) == 'K' && *s == 'U') dots -= 1.0f;
	    if(f == ON && *(s - 1) == 'A' && *s == 'S') dots -= 2.0f;
	    if(f == ON && *(s - 1) == 'R' && *s == 'O') dots -= 1.0f;
	    if(f == ON && *(s - 1) == 'K' && *s == 'Y') dots -= 1.0f;
	    if(f == ON && *(s - 1) == 'N' && *s == 'J') dots -= 1.0f;
	    if(f == ON && *(s - 1) == 'K' && *s == 'E') dots -= 1.0f;
	    if(f == ON && *(s - 1) == 'S' && *s == 't') dots -= 2.0f;
	    if(f == ON && *(s - 1) == 'X' && *s == 'X') dots -= 3.0f;
	    if(f == ON && *(s - 1) == 'O' && *s == 'X') dots -= 1.0f;
	    if(f == ON && *(s - 1) == 'W' && *s == 'W') dots -= 1.0f;
	    if(f == ON && *(s - 1) == 'X' && *s == 'W') dots -= 1.0f;
	    if(f == ON && *(s - 1) == 'W' && *s == 'X') dots -= 1.0f;


	    if(f == ON && *(s - 1) == 'H' && *s == 'O') dots += 1.0f;
	    if(f == ON && *(s - 1) == 'J' && *s == 'I') dots += 1.0f;
	    if(f == ON && *(s - 1) == 'I' && *s == 'N') dots += 1.0f;
	    if(f == ON && *(s - 1) == 'I' && *s == 'M') dots += 1.0f;
	    if(f == ON && *(s - 1) == 'I' && *s == 'D') dots += 1.0f;
	    if(f == ON && *(s - 1) == 'U' && *s == 'K') dots += 1.0f;
	    dots += rchw[i]+2.0f;
	    f = ON;
	}
    }

    return( dots );
}

/*======================================================================*/
/* 数字 を 表示する							*/
/*======================================================================*/
void large_moji_number(
    int		x,
    int		y,
    int		n
)
{
    static unsigned char *lnum_text[] = {
	MOJI_s0_txt, MOJI_s1_txt, MOJI_s2_txt, MOJI_s3_txt, MOJI_s4_txt,
	MOJI_s5_txt, MOJI_s6_txt, MOJI_s7_txt, MOJI_s8_txt, MOJI_s9_txt,
    };

    int			i, flg;

    flg = OFF;
    i =	10000000;
    n %= i;
    for(i /= 10; i != 1; i /= 10) {
	if(n / i || flg == ON) {
	    texture_rectangleIA8(&NOW_DISP, lnum_text[n / i],
			       16, 15,
			      (float)x, (float)y, 1.0f, 1.0f);
	    x += 13;
	    n %= i;
	    flg = ON;
	}
    }
    texture_rectangleIA8(&NOW_DISP, lnum_text[n / i],
			 16, 15,
			 (float)x, (float)y, 1.0f, 1.0f);
}

/*======================================================================*/
/*	ＭＯＪＩ を 表示する(小さいやつ)				*/
/*======================================================================*/
void small_moji_puts(
    int		x,
    int		y,
    float	xs,
    float	ys,
    char	*s
)
{
    static unsigned char *stext[] = {
	NULL,
	MOJI_a_txt, MOJI_b_txt, MOJI_c_txt, MOJI_d_txt, MOJI_e_txt,
	MOJI_f_txt, MOJI_g_txt, MOJI_h_txt, MOJI_i_txt, MOJI_j_txt,
	MOJI_k_txt, MOJI_l_txt, MOJI_m_txt, MOJI_n_txt, MOJI_o_txt,
	MOJI_p_txt, MOJI_q_txt, MOJI_r_txt, MOJI_s_txt, MOJI_t_txt,
	MOJI_u_txt, MOJI_v_txt, MOJI_w_txt, MOJI_x_txt, MOJI_y_txt,
	MOJI_z_txt,
	MOJI_biikuri_txt, MOJI_tenten_txt, MOJI_yoko_txt, MOJI_ten_txt,
	MOJI_00_txt, MOJI_01_txt, MOJI_02_txt, MOJI_03_txt, MOJI_04_txt,
	MOJI_05_txt, MOJI_06_txt, MOJI_07_txt, MOJI_08_txt, MOJI_09_txt,
    };

    int		i;
    int		xsiz;
    float	xp = (float)x, yp = (float)y;

    for(; *s != NULL; s += 1) {
	for(i = 0; i < number(sch) && sch[i] != *s; i += 1);
	if(sch[i] == *s) {
	    if(stext[i] != NULL) {
		xsiz = 8;
		if( i > 30 ) xsiz = 16;
		texture_rectangleIA8( &NOW_DISP, stext[i],
				      xsiz, 8, xp, yp, xs, ys);
	    }
	    switch( *s ) {
	    case 'I':
	    case '!':
	    case ':':
		xp += (4.0f * xs);
		break;
	    case '-':
		xp += (6.0f * xs);
		break;
	    default:
		if( i > 29 ) xp += (9.0f * xs);
		else	     xp += (8.0f * xs);
		
		break;
	    }
	}
    }
}

/*======================================================================*/
/*	ＭＯＪＩ の ドット数を返す(小さいやつ)				*/
/*======================================================================*/
int mojiS_dot( char *s )
{
    int i;
    int dots;

    dots = 0;
    for(; *s != NULL; s += 1) {
	for(i = 0; i < number(sch) && sch[i] != *s; i += 1);
	if(sch[i] == *s) {
	    switch( *s ) {
	    case 'I':
	    case '!':
	    case ':':
		dots += 4.0f;
		break;
	    case '-':
		dots += 6.0f;
		break;
	    default:
		if( i > 29 ) dots += 9.0f;
		else	     dots += 8.0f;
		break;
	    }
	}
    }

    return( dots );
}

/*======================================================================*/
/*	カタカナＭＯＪＩ を 表示する(小さいやつ)			*/
/*======================================================================*/
void small_kana_puts(
    int		x,
    int		y,
    float	xs,
    float	ys,
    unsigned char *s
)
{
#if 0
    static char kana_ch[] = "　アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミムメモヤユヨラリルレロワヲンァィゥェォッャュョベゾボビピグペドー６ＸＹＺ";

    static unsigned char *kana_text[] = {
	NULL,
	MOJI_aa_txt, MOJI_ii_txt, MOJI_uu_txt, MOJI_ee_txt, MOJI_oo_txt,
	MOJI_ka_txt, MOJI_ki_txt, MOJI_ku_txt, MOJI_ke_txt, MOJI_ko_txt,
	MOJI_sa_txt, MOJI_si_txt, MOJI_su_txt, MOJI_se_txt, MOJI_so_txt,
	MOJI_ta_txt, MOJI_ti_txt, MOJI_tu_txt, MOJI_te_txt, MOJI_to_txt,
	MOJI_na_txt, MOJI_ni_txt, MOJI_nu_txt, MOJI_ne_txt, MOJI_no_txt,
	MOJI_ha_txt, MOJI_hi_txt, MOJI_hu_txt, MOJI_he_txt, MOJI_ho_txt,
	MOJI_ma_txt, MOJI_mi_txt, MOJI_mu_txt, MOJI_me_txt, MOJI_mo_txt,
	MOJI_ya_txt, MOJI_yu_txt, MOJI_yo_txt,
	MOJI_ra_txt, MOJI_ri_txt, MOJI_ru_txt, MOJI_re_txt, MOJI_ro_txt,
	MOJI_wa_txt, MOJI_wo_txt, MOJI_nn_txt,
	MOJI_ko_aa_txt, MOJI_ko_ii_txt, MOJI_ko_uu_txt,
	MOJI_ko_ee_txt, MOJI_ko_oo_txt,
	MOJI_ko_tu_txt, MOJI_ko_ya_txt, MOJI_ko_yu_txt, MOJI_ko_yo_txt,
	MOJI_be_txt,
	MOJI_zo_txt, MOJI_bo_txt, MOJI_bi_txt, MOJI_pi_txt, MOJI_gu_txt,
	MOJI_pe_txt,
	MOJI_do_txt,
	MOJI_yoko_txt,
	MOJI_ko_6_txt,
	MOJI_ko_x_txt,
	MOJI_ko_y_txt,
	MOJI_ko_z_txt,
    };

    int i;
    float hh;
    float xp = (float)x, yp = (float)y;
    unsigned short *ss,*cc;

    for(; *s != NULL; s += 2) {
	ss = (unsigned short *)s;
	cc = (unsigned short *)kana_ch;
	for(i = 0; i < number(kana_ch)/2 && *cc != *ss; cc++,i += 1);
	if(*cc == *ss) {
	    if(kana_text[i] != NULL) {
		hh = 8.0f;
		if( *ss == 'ベ' || *ss == 'ゾ' || *ss == 'ボ' || *ss == 'グ' ) {
		    hh = 9.0f;
		}
		if( *ss == 'ピ' ) {
		    hh = 10.0f;
		}
		if( *ss == 'ペ' ) {
		    hh = 11.0f;
		}

		texture_rectangleIA8( &NOW_DISP,kana_text[i],
				      8, hh, xp, yp-hh, xs, ys);
	    }
	    switch( *ss ) {
	    case 'ー':
		xp += (6.0f * xs);
		break;
	    default:
		xp += (7.0f * xs);
		break;
	    }
	}
    }
#endif
}

/*======================================================================*
 *									*
 *	テクスチャーの補間 ＲＧＢＡ１６					*
 *									*
 *======================================================================*/
void texture_hokan_rgba16(
    float 		par,	/* 混ざり方 (％) (IN 1)0 - 100(IN 2) */
    unsigned short 	s,	/* ＳＩＺＥ */
    unsigned short	*txt1,	/* テクスチャー ＩＮ １ */
    unsigned short	*txt2,	/* テクスチャー ＩＮ ２ */
    unsigned short	*txt	/* テクスチャー ＯＵＴ */
)
{
    int			i;
    unsigned short	*t1, *t2, *t, w;
    float		r1, g1, b1, r2, g2, b2;
    unsigned short 	a1, a2, r, g, b;

    t1 = (unsigned short *)SEGMENT_TO_KSEG0(txt1);
    t2 = (unsigned short *)SEGMENT_TO_KSEG0(txt2);
    t = (unsigned short *)SEGMENT_TO_KSEG0(txt);

    for(i = 0; i < s; i += 1) {
	w = t1[i];
	r1 = (w >> 11) & 0x001f;
	g1 = (w >> 6) & 0x001f;
	b1 = (w >> 1) & 0x001f;
	a1 = (w) & 0x0001;
	w = t2[i];
	r2 = (w >> 11) & 0x001f;
	g2 = (w >> 6) & 0x001f;
	b2 = (w >> 1) & 0x001f;
	a2 = (w) & 0x0001;
	r = (r1 + ((r2 - r1) * par) / 100.0f) * 2048.0f;
	g = (g1 + ((g2 - g1) * par) / 100.0f) * 64.0f;
	b = (b1 + ((b2 - b1) * par) / 100.0f) * 2.0f;
	t[i] = (r & 0xf800) | (g & 0x07c0) | (b & 0x003e) | (a1 | a2);
    }
}
/*EOF*/
