/*==========================================
	"prmain.c" PR main program V2.0 L02
==========================================*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <fmcfrb.h>
#include <malloc.h>
#include "timekh.h"
#include "filekh.h"
#include "prdef.h"

//#define	POLMAX	2000

int    *_cos,*_sin;	//_cos[1000],_sin[1000];
short  polmax;
poly   *mapdata;	//[POLMAX];
poly   cardata[3*7];
pol2d  *poldat;		//[POLMAX];
short  rd;
rdata  *road;		//[POLMAX];
short  cpn, *cp;
short  *exTime;
poly   car[3];
poly   ecar[3];
int    _time[20]=0,_dn=0;

way *way1st,*waybst;
//extern way *ecar[6];
extern way cway;

int		maxtime=MAXTIME,h=25;
short	blap[10],flap[10];
int 	lapFlag=0,wayFlag=0;

int		mapNo=0;
char	mapfile[][13]={"course00.pmd","course01.pmd","course02.pmd"};
char	wayfile[][13]={"course00.way","course01.way","course02.way"};
char	lapfile[][13]={"course00.lap","course01.lap","course02.lap"};

char	mapName[][15]={	"  初級コース  ",
						"  中級コース  ",
						"  上級コース  " };

extern int initGrp();
extern int demo();
extern int game( short sx, short sy, short sang );

/*==============================
	マップデータの読み込み
==============================*/
int read_mapdata( int mn, short *x, short *y, short *ang )
{
	int i,j,ret=1;
	FILE *fp;

	fp=fopen(mapfile[mn],"rb");
	if (fp==NULL) {
		puts("マップファイルのオープンに失敗しました。");
		return -2;
	}
	getShort(*x,fp);
	getShort(*y,fp);
	getShort(*ang,fp);

	getShort(polmax,fp);
	mapdata = (poly *)malloc( polmax*sizeof(poly) );
	if( mapdata==NULL ){
		ret = -1;
		goto last;
	}
	for (i=0; i<polmax; ++i){
		for(j=0; j<4; ++j){
			getShort(mapdata[i].px[j],fp);
			getShort(mapdata[i].py[j],fp);
			getShort(mapdata[i].pz[j],fp);
		}
		getShort(mapdata[i].type,fp);
		mapdata[i].n=4;
	}

	getShort(rd,fp);
	road = (rdata *)malloc( rd*sizeof(rdata) );
	if( road==NULL ){
		ret = -1;
		goto last;
	}
	fread( road, sizeof(rdata), rd, fp );

	getShort(cpn,fp);
	cp = (short *)malloc( cpn*sizeof(short) );
	if( cp==NULL ){
		ret = -1;
		goto last;
	}
	fread( cp, sizeof(short), cpn, fp );

	exTime = (short *)malloc( cpn*sizeof(short) );	
	if( exTime==NULL ){
		ret = -1;
		goto last;
	}
	fread( exTime, sizeof(short), cpn, fp );

	if (ferror(fp)){
		puts("マップファイルのリードエラーです｡");
		ret = -2;
	}

  last:
	fclose(fp);
	return ret;
}

/*============================
	ｃａｒデータの設定
============================*/
int setCarDat()
{
	car[2].px[0] =0;	car[2].py[0] =-5;	car[2].pz[0] =4;
	car[2].px[1] =5;	car[2].py[1] =2;	car[2].pz[1] =4;
	car[2].px[2] =0;	car[2].py[2] =4;	car[2].pz[2] =4;
	car[2].px[3] =-5;	car[2].py[3] =2;	car[2].pz[3] =4;
	car[2].type = C32K(31,0,15);
	car[0].px[0] =0;	car[0].py[0] =-5;	car[0].pz[0] =4;
	car[0].px[1] =5;	car[0].py[1] =2;	car[0].pz[1] =4;
	car[0].px[2] =5;	car[0].py[2] =2;	car[0].pz[2] =0;
	car[0].px[3] =0;	car[0].py[3] =-5;	car[0].pz[3] =0;
	car[0].type = C32K(31,0,0);
	car[1].px[0] =0;	car[1].py[0] =-5;	car[1].pz[0] =4;
	car[1].px[1] =-5;	car[1].py[1] =2;	car[1].pz[1] =4;
	car[1].px[2] =-5;	car[1].py[2] =2;	car[1].pz[2] =0;
	car[1].px[3] =0;	car[1].py[3] =-5;	car[1].pz[3] =0;
	car[1].type = C32K(31,0,0);

	memcpy( ecar, car, sizeof(poly)*3 );
	ecar[0].type = 25;
	ecar[1].type = 25;
	ecar[2].type = 31;

	return 1;
}
/*=================================
	ｗａｙデータの読み書き
=================================*/
#define	WDSIZE ((2*6+8*1001)*12)
char *compressAway( way *wd, char *dc )
{
	struct cwdata{
		short lt;
		short st[5];
		vect  pt[1001];
		short ag[1001];
	} *wds;
	wds = (struct cwdata *)dc;

	int	i,j;
	memcpy( wds, &(wd->ltime), sizeof(short)*6);
	j = (wd->ltime -1) /10;
	for(i=0; i<j; ++i)
	{
		wds->pt[i] = wd->pt[i*10];
		wds->ag[i] = wd->ang[i*10];
	}
	wds->pt[i+1] = wd->pt[wd->ltime];
	wds->ag[i+1] = wd->ang[wd->ltime];

	return dc+sizeof(struct cwdata);
}
void compress_waydata( char *wdc )
{
	int i;
	for(i=0; i<6; ++i)
		wdc = compressAway(waybst+i,wdc);
	for(i=0; i<6; ++i)
		wdc = compressAway(way1st+i,wdc);
}
void	makeUpWay( way *wd, int st, int ed )
{
	int	i=st, j, gap=ed-st;
	int	a0,a1;
	for(j=1; j<gap; j++)
	{
		wd->pt[i+j].x = ( wd->pt[i].x*(gap-j) +
							wd->pt[i+gap].x*j )/gap ;
		wd->pt[i+j].y = ( wd->pt[i].y*(gap-j) +
							wd->pt[i+gap].y*j )/gap ;
		wd->pt[i+j].z = ( wd->pt[i].z*(gap-j) +
							wd->pt[i+gap].z*j )/gap ;
		a0 = wd->ang[i];
		a1 = wd->ang[i+gap];
		if( a0>800 && a1<200 ) a1+=1000;
		if( a1>800 && a0<200 ) a0+=1000;
		wd->ang[i+j] = (( a0*(gap-j)+a1*j )/gap) %1000 ;
	}
	return ;
}
char *decompressAway( way *wd, char *dc )
{
	struct cwdata{
		short lt;
		short st[5];
		vect  pt[1001];
		short ag[1001];
	} *wds;
	wds = (struct cwdata *)dc;

	int	i,j;
	memcpy( &(wd->ltime), wds, sizeof(short)*6);
	j = (wd->ltime -1) /10;
	for(i=0; i<j; ++i)
	{
		wd->pt[i*10] = wds->pt[i];
		wd->ang[i*10]= wds->ag[i];
	}
	for(i=1; i<j; ++i)
		makeUpWay( wd, i*10, (i+1)*10 );
	wd->pt[i*10] = wds->pt[i+1];
	wd->ang[i*10]= wds->ag[i+1];
	makeUpWay( wd, (i+1)*10, wd->ltime );

	return dc+sizeof(struct cwdata);
}
void decompress_waydata( char *wdc )
{
	int	i;
	for(i=0; i<6; ++i)
		wdc = decompressAway(waybst+i,wdc);
	for(i=0; i<6; ++i)
		wdc = decompressAway(way1st+i,wdc);
}
void read_waydata(int mn)
{
	FILE	*fp;
	int	i;
	fp = fopen(wayfile[mn],"rb");
	if( fp==NULL ){
		for(i=0; i<6; i++){
			way1st[i].ltime = 0;
			waybst[i].ltime = 0;
		}
		return;
	}
	char	*wdat;
	wdat = malloc( WDSIZE );
	if( wdat==NULL ){
		puts("Can't alloc memory!!");
		exit(0);
//		if( rdata!=NULL )
//			wdat = (char *)cway;
	}
	fread( wdat, 1, WDSIZE, fp );
//	fread( way1st, sizeof(way), 6, fp );
//	fread( waybst, sizeof(way), 6, fp );
	fclose( fp );
	decompress_waydata( wdat );
}
void save_waydata(int mn)
{
	FILE *fp;
	fp = fopen(wayfile[mn],"wb");
	if( fp==NULL ) return;

	char	*wdat;
	wdat = malloc( WDSIZE );
	if( wdat==NULL ){
		puts("Can't alloc memory!!");
		exit(0);
//		if( rdata!=NULL )
//			wdat = (char *)cway;
	}
	compress_waydata( wdat );
	fwrite( wdat, 1, WDSIZE, fp );
	fclose( fp );
}

/*==============================
	ベストラップの読み書き
==============================*/
void read_bestlap(int mn)
{
	FILE	*fp;
	int		i;
	fp=fopen(lapfile[mn],"rb");
	if (fp==NULL)
		for(i=0; i<10; ++i){
			blap[i]=30000; flap[i]=30000;
		}
	else{
		fread( blap, sizeof(short), 10, fp );
		fread( flap, sizeof(short), 10, fp );
		fclose(fp);
	}
}
void save_bestlap(int mn)
{
	FILE	*fp;
	fp=fopen(lapfile[mn],"wb");
	if( fp==NULL ) return;
	fwrite( blap, sizeof(short), 10, fp );
	fwrite( flap, sizeof(short), 10, fp );
	fclose(fp);
}

/*===================
	ラップの更新
===================*/
#define	swap(x,y)	{(y)^=(x);(x)^=(y);(y)^=(x);}
void	setLap( short blp, short flp )
{
	int	i;
	if( blp<blap[9] )
	{
		lapFlag=1;
		blap[9]=blp;
		for(i=8; i>=0; --i){
			if(blap[i]<=blap[i+1]) break;
			swap(blap[i+1],blap[i]);
		}
	}
	if( flp<flap[9] )
	{
		lapFlag=1;
		flap[9]=flp;
		for(i=8; i>=0; --i){
			if(flap[i]<=flap[i+1]) break;
			swap(flap[i+1],flap[i]);
		}
	}
}
/*============================
	三角関数データのセット
============================*/
void	setSCdata()
{
	int	i;
	for(i=0; i<1000; ++i){
		_cos[i] = cos(_PI*2*i/1000)*100;
		_sin[i] = sin(_PI*2*i/1000)*100;
	}
}
/*==================================
	マップの読み込み　(二度目以降)
==================================*/
short sx,sy,sang;
changeMap( int mn )
{
	int	i;
	if (lapFlag!=0) {
		save_bestlap(mapNo) ;
		lapFlag = 0 ;
	}
	if (wayFlag!=0) {
		save_waydata(mapNo);
		wayFlag = 0 ;
	}
	free(mapdata);
	free(road);
	free(cp);
	free(exTime);
	free(poldat);

	mapNo = mn;
	//	マップデータの読み込み
	i = read_mapdata( mapNo,&sx,&sy,&sang );
	if( i==-1 ) {
		puts("メモリが足りません");
	}
	if( i<0 ) exit(0);

	//	ポリゴン描画用データエリア取得
	poldat = (pol2d *)malloc( sizeof(pol2d)*polmax );
	if( poldat==NULL ) {
		puts("メモリが足りません");
		exit(0);
	}
	//	走行データ等の読み込み
	read_waydata(mapNo);
	read_bestlap(mapNo);
}

/*===================
	メイン関数
===================*/
void main(int argc, char *argv[])
{
	int	i;

	//	maxtime( 画面更新の時間 ) の決定
	if( argc>1 )
		if( *(argv[1])=='/' && *(argv[1]+1)=='t' )
			sscanf(argv[1],"/t%d",&maxtime);
	if( maxtime<=0 || maxtime>=20 ) maxtime = 7;

	//	マップデータの読み込み
	i = read_mapdata( mapNo,&sx,&sy,&sang );
	if( i==-1 ) {
		puts("メモリが足りません");
	}
	if( i<0 ) exit(0);

	//	ポリゴン描画用データエリア取得
	poldat = (pol2d *)malloc( sizeof(pol2d)*polmax );
	if( poldat==NULL ) {
		puts("メモリが足りません");
		exit(0);
	}
	//	走行データ保存エリアの取得
	way1st = (way *)malloc( sizeof(way)*6 );
	waybst = (way *)malloc( sizeof(way)*6 );
	if( way1st==NULL || waybst==NULL ) {
		puts("メモリが足りません");
		exit(0);
	}
	//	その他のメモリ取得
	_cos = (int *)malloc( sizeof(int)*1000 );
	_sin = (int *)malloc( sizeof(int)*1000 );
	if( _cos==NULL || _sin==NULL ) {
		puts("メモリが足りません");
		exit(0);
	}

	//	走行データ等の読み込み
	read_waydata(mapNo);
	read_bestlap(mapNo);
	setCarDat();

	//	初期化
	setSCdata();
	if (-1==initGrp()) {
		puts("グラフィックのイニシャライズに失敗しました。");
		puts("メモリの不足と思われます。");
		exit(0);
	}

	//	デモ & ゲーム
	int	f=0;
	while(1)
	{
		if( demo(f,sx,sy)==-1 ) break;
		game(sx,sy,sang);
		f=1;
	};

	//	終了処理
	if( lapFlag!=0 )
		save_bestlap(mapNo);
	if( wayFlag!=0 )
		save_waydata(mapNo);

	int	t=0;
	for(f=0; f<10; ++f){
		printf("%2d(csec) : %5d time(s) \t%2d(csec) : %5d time(s)\n"
				,f,_time[f],f+10,_time[f+10]);
		t += _time[f]*f+_time[f+10]*(f+10);
	}
	printf("%d(csec) で %d 回 描画｡ 平均秒間 %d.%2d 枚\n"
							,t,_dn,_dn*100/t,(_dn*10000/t)%100);
	printf("画面更新(予定)時間:%d \t",maxtime);
	printf("平均描画時間:%d.%02d\n",t/_dn,(t*100/_dn)%100);
}

