/**********************************************************************/
/* 'PolyTan2'           3D polygon shooting game       (tab size = 4) */
/*                      1995.4   development start                    */
/*                      1995.6   opened to the publick                */
/*                      1995.7-8 modified for FC11                    */
/*  created by TabTack  (Nifty:Tab01616)                              */
/**********************************************************************/

#include    <dos.h>
#include	<conio.h>
#include	<stdio.h>
#include	<stdlib.h>
#include	<string.h>
#include	<math.h>
#include	<msdos.cf>

#include	<egb.h>
#include	<tifflib.h>
#include	<mos.h>
#include	<spr.h>
#include	<snd.h>
#include	<wav.h>
// #include	<midiman.h>
#include	<cdrfrb.h>
#include	<fmcfrb.h>

/**************************** MIDI driver ****************************/
#define	MAXPLAYNOTE	256			/* 最大同時発音数			*/
#define	MAXTRACK	100			/* 最大ﾄﾗｯｸ数				*/
#define	PBSIZE		100000		/* 演奏ﾊﾞｯﾌｧｻｲｽﾞ			*/
#define	LOCALSTACKSIZE	4096	/* 割り込み用ﾛｰｶﾙｽﾀｯｸｻｲｽﾞ	*/

/* ｴﾗｰ番号 */
#define	OUTMEM		(0x01)
#define	ENDDETECT	(0x02)
#define	FORMATERR	(0x03)
#define	CANTOPEN	(0x04)
#define	CANTREAD	(0x05)

/*	clock resolusion	*/
#define RESO96	(0x60)
#define RESO480	(0x1e0)
/*********************************************************************/
#define	SPM		(short (*)[256])

/* system */
#define	PAD_LRUD	0x0f
#define	PAD_UP		0x01
#define	PAD_DOWN	0x02
#define	PAD_LEFT	0x04
#define	PAD_RIGHT	0x08
#define	PAD_A		0x10
#define	PAD_B		0x20
#define	PAD_SELECT	0x03
#define	PAD_RUN		0x0c
#define	PAD_C		0x800
#define	PAD_X		0x400
#define	PAD_Y		0x200
#define	PAD_Z		0x100

#define	MOUSELEFT	1
#define	MOUSERIGHT	2

#define	BASETONE	59

#define	PADMAX		30000

/* sound assign */
#define	BGMMUSIC	0
#define	ENSOUND		64
#define	ENENGINE	65
#define	MYSHOTSOUND	66
#define	ENSHOTSOUND	67
#define	MYSOUND		68
#define	MYENGINE	69
#define	ELSESOUND	70
#define	HUMANVOICE	71

/* caluculation */
#define	IPAI		2048
#define	RADMAX		4096
#define	ATMUL		64

/* tank active type */
#define	MYMBT		64
#define	CONTAINER	65
#define	MPV			66
#define	MBT			67
#define	AAT			68
#define	AH			69
#define	WING		70
#define	BASE		71
#define	WEAPON_END	72

/* shot active type */
#define	CANNON_SHOT	64
#define	SHOT_SHOT	65

#define	BLOCKMAX	8

#define	ENMAX		12
#define	ENSHOTMAX	8

#define	SHOTEDMAX	30
#define	BOMBING		63

#define	STILL		62
#define	EXPLOSION	61
#define	TOP_BLOW	60
#define	FLY			59
#define	FALL		58
#define	CRASH		57

#define	IN_RANGE	12000

/************************** Euphony driver ***************************/
char	eup_buf[100000];				/* 演奏データ用バッファ	*/
int 	flen,signature;					/* ファイル長,拍子値	*/
FILE	*eup_fp;						/* ストリーム用変数		*/
int		midi_mode = 0;

/*********************************************************************/

char	gwork[EgbWorkSize];				/* グラフイックBIOS work */
char    mwork[MosWorkSize];
char	sndwork[16*1024];

char	palt[256*8+4];			    	/* tiff パレット設定用 */
int	 	tiffx, tiffy;
FILE 	*tiff_fp;

int		si[4096], co[4096];				/* sin, cosin tables */
int		sq[4096], at[4096];				/* sqrt, atan tables */

long	iii[3] = {1, 1, 1};

int		pr;								/* for debug */
int		inter_count;					/* 10ms time counter */
int		demo;
int		land_color;						/* base land color */
int		light;
int		xsize, ysize;
int		gamewait = 20, reso = 0;
int		padmode = 0;
int		mission;
int		range_check, range_count;
int		oldmousex, oldmousey;
short	mouse_pattern[32*32];
short	*z_buffer;
short	*z_color;
short	*MBT_picture;					/* for texture mapping */
short	*pattern_picture;				/* for texture mapping */
short	*sand_picture;					/* sand data */
short	*sky_picture;					/* sky data */

#define	SNDMAX	60000
int		sndmode = 1;
char	*lets_go_snd;
char	*in_range_snd;
char	*go_next_snd;
char	*hit_snd;
char	*break_snd;
char	*bingo_snd;
char	*auti_snd;
char	*complete_snd;

struct INDEVICE
{
	short	pad;
	short	mousech;
	short	mousex;
	short	mousey;
} myold, *record;

struct TANK
{
	int	type;		/* 0:nonactive 1... MBT,etc.. */
	int	arm;		/* registivity */
	int	shoted;		/* check shoted */
	int	stat;		/* exploding or not */
	int	count;		/* work counter */
	int	x;			/* left-right position */
	int	y;			/* height */
	int	z;			/* foward-back position */
	int	r;			/* angle of body (rotate x) */
	int	s;			/* angle of body (rotate y) */
	int	t;			/* angle of body (rotate z) */
	int	wr;			/* vertical angle of weapon */
	int	ws;			/* horizonal angle of weapon */
} my, en[ENMAX];

struct SHOT
{
	int	type;		/* 0:nonactive 1-63:bomb 64-:active */
	int	life;		/* active down counter */
	int	speed;		/* speed */
	int	power;		/* power */
	int	x;			/* left-right position */
	int	y;			/* height */
	int	z;			/* foward-back position */
	int	r;			/* angle of body (rotate x) */
	int	s;			/* angle of body (rotate y) */
} myshot, enshot[ENSHOTMAX];

int	tankarm[] = {60/*not used*/, 1, 5, 40, 20, 2, 40, 60};

int MYMBT_body_point[12][3] =
{
/*     x    y    z (cm) */
	{ 100,   0, 240},		// 0
	{-100,   0, 240},		// 1
	{ 100,  40, 200},		// 2
	{-100,  40, 200},		// 3
	{ 100,  40,-200},		// 4
	{-100,  40,-200},		// 5
	{ 100,   0,-240},		// 6
	{-100,   0,-240},		// 7
	{ 100, -40,-240},		// 8
	{-100, -40,-240},		// 9
	{ 100, -40, 120},		// 10
	{-100, -40, 120}		// 11
};

int MYMBT_body_surface[10][12] =
{
/*   p0 p1 p2 p3  r   g   b dir <---tex_map---> */
	{ 0, 2, 4, 6, 15, 15, 15, 1,  0,  0,  0,  0},	// 0
	{ 1, 3, 5, 7, 15, 15, 15,-1,  0,  0,  0,  0},	// 1
	{ 0, 6, 8,10, 23, 23, 23, 1,  0,  0,  0,  0},	// 2
	{ 1, 7, 9,11, 23, 23, 23,-1,  0,  0,  0,  0},	// 3
	{11,10, 8, 9, 23, 23, 23, 1, 32,128,127,191},	// 4
	{ 0, 1,11,10, 23, 23, 23,-1,  0,  0,  0,  0},	// 5
	{ 2, 0, 1, 3, 15, 15, 15, 1,  0,  0,  0,  0},	// 6
	{ 2, 4, 5, 3, 15, 15, 15,-1,  0,  0,  0,  0},	// 7
	{ 6, 7, 9, 8, 23, 23, 23, 1, 16,128, 31,191},	// 8
	{ 4, 5, 7, 6, 15, 15, 15, 1,  0,  0,  0,  0}	// 9
/* to simplize, 4-top poligon only */
/* and p0,p1,p2 shuld be independent, not include zero point */
};

int		MYMBT_body_nx[12],  MYMBT_body_ny[12],  MYMBT_body_nz[12];
#define	MYMBT_BODY_NMAX	12
#define	MYMBT_BODY_SMAX	10

int MYMBT_gunner_point[12][3] =
{
/*     x    y    z (cm) */
	{  20,  20, 120},		// 0
	{ -20,  20, 120},		// 1
	{ 100,  20,  40},		// 2
	{-100,  20,  40},		// 3
	{ 100,  20,-120},		// 4
	{-100,  20,-120},		// 5
	{ 100, -20,-120},		// 6
	{-100, -20,-120},		// 7
	{ 100, -20,  40},		// 8
	{-100, -20,  40},		// 9
	{  20, -20, 120},		// 10
	{ -20, -20, 120}		// 11
};

int MYMBT_gunner_surface[10][12] =
{
/*   p0 p1 p2 p3  r   g   b dir   tex_map */
	{ 0, 2, 8,10, 23, 23, 23, 1,  0,  0,  0,  0},	// 0
	{ 1, 3, 9,11, 23, 23, 23,-1,  0,  0,  0,  0},	// 1
	{ 2, 4, 6, 8, 23, 23, 23, 1,  0,128, 15,191},	// 2
	{ 3, 5, 7, 9, 23, 23, 23,-1,  0,128, 15,191},	// 3
	{ 0, 1,11,10, 23, 23, 23,-1,  0,  0,  0,  0},	// 4
	{ 4, 5, 7, 6, 23, 23, 23, 1,  0,  0,  0,  0},	// 5
	{ 0, 1, 3, 2, 23, 23, 23, 1,  0,  0,  0,  0},	// 6
	{ 2, 3, 5, 4, 23, 23, 23, 1,  0,  0,  0,  0},	// 7
	{10,11, 9, 8, 23, 23, 23,-1,  0,  0,  0,  0},	// 8
	{ 9, 8, 6, 7, 23, 23, 23, 1,128,128,191,191}	// 9
};

int		MYMBT_gunner_nx[12], MYMBT_gunner_ny[12], MYMBT_gunner_nz[12];
#define	MYMBT_GUNNER_NMAX	10
#define	MYMBT_GUNNER_SMAX	10

int MBT_body_point[12][3] =
{
/*     x    y    z (cm) */
	{ 100,  20, 280},		// 0
	{-100,  20, 280},		// 1
	{ 100,  60, 240},		// 2
	{-100,  60, 240},		// 3
	{ 100,  60,-200},		// 4
	{-100,  60,-200},		// 5
	{ 100,  20,-220},		// 6
	{-100,  20,-220},		// 7
	{ 100, -60,-260},		// 8
	{-100, -60,-260},		// 9
	{ 100, -60, 200},		// 10
	{-100, -60, 200},		// 11
};

int MBT_body_surface[9][12] =
{
/*   p0 p1 p2 p3  r   g   b dir <---tex_map---> */
	{ 0, 2, 4, 6, 15, 15, 15, 1,  0,  0,  0,  0},	// 0
	{ 1, 3, 5, 7, 15, 15, 15,-1,  0,  0,  0,  0},	// 1
	{ 0, 6, 8,10, 31, 31,  0, 1,  0,  0,  0,  0},	// 2
	{ 1, 7, 9,11, 31, 31,  0,-1,  0,  0,  0,  0},	// 3
	{11,10, 8, 9, 31, 31,  0, 1,  0,128,255,255},	// 4
	{ 0, 1,11,10, 31, 31,  0,-1,  0,  0,  0,  0},	// 5
	{ 2, 0, 1, 3, 15, 15, 15, 1,  0,  0,  0,  0},	// 6
	{ 2, 4, 5, 3, 15, 15, 15,-1,  0,  0,  0,  0},	// 7
	{ 4, 5, 9, 8, 31, 31,  0, 1,  0,  0,  0,  0}	// 8
/* to simplize, 4-top poligon only */
/* and p0,p1,p2 shuld be independent, not include zero point */
};

int		MBT_body_nx[12],  MBT_body_ny[12],  MBT_body_nz[12];
#define	MBT_BODY_NMAX	12
#define	MBT_BODY_SMAX	9

int MBT_gunner_point[8][3] =
{
/*     x    y    z (cm) */
	{  40, -40,-120},		// 0
	{ -40, -40,-120},		// 1
	{  40, -40,  40},		// 2
	{ -40, -40,  40},		// 3
	{  80,  40, 120},		// 4
	{ -80,  40, 120},		// 5
	{  80,  40, -80},		// 6
	{ -80,  40, -80},		// 7
};

int MBT_gunner_surface[6][12] =
{
/*   p0 p1 p2 p3  r   g   b dir   tex_map */
	{ 2, 4, 6, 0, 31, 31,  0, 1,  0, 64,127,127},	// 0
	{ 3, 5, 7, 1, 31, 31,  0,-1,  0, 64,127,127},	// 1
	{ 3, 2, 0, 1, 31, 31,  0, 1,  0,  0,127, 63},	// 2
	{ 2, 3, 5, 4, 31, 31,  0, 1,  0,  0,  0,  0},	// 3
	{ 4, 5, 7, 6, 31, 31,  0, 1,  0,  0,  0,  0},	// 4
	{ 6, 7, 1, 0, 31, 31,  0, 1,  0,  0,  0,  0},	// 5
};

int		MBT_gunner_nx[8], MBT_gunner_ny[8], MBT_gunner_nz[8];
#define	MBT_GUNNER_NMAX	8
#define	MBT_GUNNER_SMAX	6

int MBT_gun_point[8][3] =
{
/*     x    y    z (cm) */
	{  10, -10, 240},		// 0
	{ -10, -10, 240},		// 1
	{  10,  10, 240},		// 2
	{ -10,  10, 240},		// 3
	{  10,  10, -40},		// 4
	{ -10,  10, -40},		// 5
	{  10, -10, -40},		// 6
	{ -10, -10, -40},		// 7
};

int MBT_gun_surface[6][12] =
{
/*   p0 p1 p2 p3  r   g   b dir   tex_map */
	{ 0, 2, 4, 6, 15, 15, 15, 1,  0,  0,  0,  0},	// 0
	{ 1, 3, 5, 7, 15, 15, 15,-1,  0,  0,  0,  0},	// 1
	{ 0, 1, 3, 2,  0,  0,  0, 1,  0,  0,  0,  0},	// 2
	{ 2, 3, 5, 4, 15, 15, 15, 1,  0,  0,  0,  0},	// 3
	{ 4, 5, 7, 6, 15, 15, 15, 1,  0,  0,  0,  0},	// 4
	{ 6, 7, 1, 0, 15, 15, 15, 1,  0,  0,  0,  0},	// 5
};

int		MBT_gun_nx[8], MBT_gun_ny[8], MBT_gun_nz[8];
#define	MBT_GUN_NMAX	8
#define	MBT_GUN_SMAX	6

int AAT_base_point[12][3] =
{
/*     x    y    z (cm) */
	{  40, -60,  40},		// 0
	{ -40, -60,  40},		// 1
	{  40,  20, 120},		// 2
	{ -40,  20, 120},		// 3
	{  40,  60,  80},		// 4
	{ -40,  60,  80},		// 5
	{  40,  60, -80},		// 6
	{ -40,  60, -80},		// 7
	{  40, -20,-120},		// 8
	{ -40, -20,-120},		// 9
	{  40, -60,-120},		// 10
	{ -40, -60,-120},		// 11
};

int AAT_base_surface[10][12] =
{
/*   p0 p1 p2 p3  r   g   b dir <---tex_map---> */
	{ 0, 2, 8,10, 31, 31,  0, 1,  0,  0,  0,  0},	// 0
	{ 1, 3, 9,11, 31, 31,  0,-1,  0,  0,  0,  0},	// 1
	{ 2, 4, 6, 8, 31, 31,  0, 1,  0,  0,  0,  0},	// 2
	{ 3, 5, 7, 9, 31, 31,  0,-1,  0,  0,  0,  0},	// 3
	{ 0,10,11, 1, 31, 31,  0, 1,  0,  0,  0,  0},	// 4
	{ 2, 0, 1, 3, 31, 31,  0, 1,128,  0,191, 63},	// 5
	{ 4, 2, 3, 5, 31, 31,  0, 1,  0,  0,  0,  0},	// 6
	{ 4, 6, 7, 5, 31, 31,  0,-1,  0,  0,  0,  0},	// 7
	{ 6, 8, 9, 7, 31, 31,  0,-1,128,  0,191, 63},	// 8
	{ 8,10,11, 9, 31, 31,  0,-1,  0,  0,  0,  0}	// 9
};

int		AAT_base_nx[12], AAT_base_ny[12], AAT_base_nz[12];
#define	AAT_BASE_NMAX	12
#define	AAT_BASE_SMAX	10

int AAT_gunner_point[8][3] =
{
/*     x    y    z (cm) */
	{  20,  20,  40},		// 0
	{ -20,  20,  40},		// 1
	{  20, -20,  40},		// 2
	{ -20, -20,  40},		// 3
	{  20,  20, -40},		// 4
	{ -20,  20, -40},		// 5
	{  20, -20, -40},		// 6
	{ -20, -20, -40},		// 7
};

int AAT_gunner_surface[6][12] =
{
/*   p0 p1 p2 p3  r   g   b dir <---tex_map---> */
	{ 0, 1, 3, 2, 23, 23, 23,-1,  0,  0,  0,  0},	// 0
	{ 4, 5, 7, 6, 23, 23, 23, 1,  0,  0,  0,  0},	// 1
	{ 0, 1, 5, 4, 23, 23, 23, 1,  0,  0,  0,  0},	// 2
	{ 2, 3, 7, 6, 23, 23, 23,-1,  0,  0,  0,  0},	// 3
	{ 0, 2, 6, 4, 23, 23, 23,-1,  0,  0,  0,  0},	// 4
	{ 1, 3, 7, 5, 23, 23, 23, 1,  0,  0,  0,  0},	// 5
};

int		AAT_gunner_nx[8], AAT_gunner_ny[8], AAT_gunner_nz[8];
#define	AAT_GUNNER_NMAX	8
#define	AAT_GUNNER_SMAX	6

int AAT_gun_point[8][3] =
{
/*     x    y    z (cm) */
	{   5,   5,   0},		// 0
	{  -5,   5,   0},		// 1
	{   5,  -5,   0},		// 2
	{  -5,  -5,   0},		// 3
	{   5,   5, 240},		// 4
	{  -5,   5, 240},		// 5
	{   5,  -5, 240},		// 6
	{  -5,  -5, 240},		// 7
};

int AAT_gun_surface[6][12] =
{
/*   p0 p1 p2 p3  r   g   b dir <---tex_map---> */
	{ 0, 1, 3, 2, 15, 15, 15, 1,  0,  0,  0,  0},	// 0
	{ 4, 5, 7, 6,  0,  0,  0,-1,  0,  0,  0,  0},	// 1
	{ 0, 1, 5, 4, 15, 15, 15,-1,  0,  0,  0,  0},	// 2
	{ 2, 3, 7, 6, 15, 15, 15, 1,  0,  0,  0,  0},	// 3
	{ 0, 2, 6, 4, 15, 15, 15, 1,  0,  0,  0,  0},	// 4
	{ 1, 3, 7, 5, 15, 15, 15,-1,  0,  0,  0,  0},	// 5
};

int		AAT_gun_nx[8], AAT_gun_ny[8], AAT_gun_nz[8];
#define	AAT_GUN_NMAX	8
#define	AAT_GUN_SMAX	6

int MPV_body_point[12][3] =
{
/*     x    y    z (cm) */
	{  80, -20, 200},		// 0
	{ -80, -20, 200},		// 1
	{  80,  60, 120},		// 2
	{ -80,  60, 120},		// 3
	{  80,  60,-160},		// 4
	{ -80,  60,-160},		// 5
	{  80, -20,-200},		// 6
	{ -80, -20,-200},		// 7
	{  40, -60,-200},		// 8
	{ -40, -60,-200},		// 9
	{  40, -60,  40},		// 10
	{ -40, -60,  40},		// 11
};

int MPV_body_surface[10][12] =
{
/*   p0 p1 p2 p3  r   g   b dir <---tex_map---> */
	{ 0, 6, 8,10, 31, 31,  0, 1,  0,  0,  0,  0},	// 0
	{ 1, 7, 9,11, 31, 31,  0,-1,  0,  0,  0,  0},	// 1
	{ 0, 2, 4, 6, 31, 31,  0, 1,  0,  0,  0,  0},	// 2
	{ 1, 3, 5, 7, 31, 31,  0,-1,  0,  0,  0,  0},	// 3
	{ 0, 1, 3, 2, 31, 31,  0, 1,  0,  0,  0,  0},	// 4
	{ 2, 3, 5, 4, 31, 31,  0, 1,  0,  0,  0,  0},	// 5
	{ 4, 5, 7, 6, 31, 31,  0, 1,  0,  0,  0,  0},	// 6
	{ 6, 7, 9, 8, 31, 31,  0, 1,  0,  0,  0,  0},	// 7
	{10,11, 9, 8, 31, 31,  0,-1, 96,128,255,255},	// 8
	{ 0, 1,11,10, 31, 31,  0,-1,  0,128, 95,255},	// 9
};

int		MPV_body_nx[12], MPV_body_ny[12], MPV_body_nz[12];
#define	MPV_BODY_NMAX	12
#define	MPV_BODY_SMAX	10

int MPV_gunner_point[8][3] =
{
/*     x    y    z (cm) */
	{  40,  20, -60},		// 0
	{ -40,  20, -60},		// 1
	{  20, -20, -40},		// 2
	{ -20, -20, -40},		// 3
	{  40,  20,  60},		// 4
	{ -40,  20,  60},		// 5
	{  20, -20,  20},		// 6
	{ -20, -20,  20},		// 7
};

int MPV_gunner_surface[6][12] =
{
/*   p0 p1 p2 p3  r   g   b dir <---tex_map---> */
	{ 0, 1, 3, 2, 23, 23, 23, 1,  0,  0,  0,  0},	// 0
	{ 4, 5, 7, 6, 23, 23, 23,-1,  0,  0,  0,  0},	// 1
	{ 0, 1, 5, 4, 23, 23, 23,-1,  0,  0,  0,  0},	// 2
	{ 2, 3, 7, 6, 23, 23, 23, 1,  0,  0,  0,  0},	// 3
	{ 0, 2, 6, 4, 23, 23, 23, 1,  0,  0,  0,  0},	// 4
	{ 1, 3, 7, 5, 23, 23, 23,-1,  0,  0,  0,  0},	// 5
};

int		MPV_gunner_nx[8], MPV_gunner_ny[8], MPV_gunner_nz[8];
#define	MPV_GUNNER_NMAX	8
#define	MPV_GUNNER_SMAX	6

int MPV_gun_point[8][3] =
{
/*     x    y    z (cm) */
	{   5,   5, -20},		// 0
	{  -5,   5, -20},		// 1
	{   5,  -5, -20},		// 2
	{  -5,  -5, -20},		// 3
	{   5,   5, 100},		// 4
	{  -5,   5, 100},		// 5
	{   5,  -5, 100},		// 6
	{  -5,  -5, 100},		// 7
};

int MPV_gun_surface[6][12] =
{
/*   p0 p1 p2 p3  r   g   b dir <---tex_map---> */
	{ 0, 1, 3, 2, 15, 15, 15, 1,  0,  0,  0,  0},	// 0
	{ 4, 5, 7, 6,  0,  0,  0,-1,  0,  0,  0,  0},	// 1
	{ 0, 1, 5, 4, 15, 15, 15,-1,  0,  0,  0,  0},	// 2
	{ 2, 3, 7, 6, 15, 15, 15, 1,  0,  0,  0,  0},	// 3
	{ 0, 2, 6, 4, 15, 15, 15, 1,  0,  0,  0,  0},	// 4
	{ 1, 3, 7, 5, 15, 15, 15,-1,  0,  0,  0,  0},	// 5
};

int		MPV_gun_nx[8], MPV_gun_ny[8], MPV_gun_nz[8];
#define	MPV_GUN_NMAX	8
#define	MPV_GUN_SMAX	6

int AH_body_point[23][3] =
{
/*     x    y    z (cm) */
	{  40, -80,  80},		// 0
	{ -40, -80,  80},		// 1
	{  40,  40, 280},		// 2
	{ -40,  40, 280},		// 3
	{  40,  80, 240},		// 4
	{ -40,  80, 240},		// 5
	{  40,  80, -40},		// 6
	{ -40,  80, -40},		// 7
	{   0, -40,-500},		// 8
	{   0, -80,-520},		// 9
	{  40, -80,-120},		// 10
	{ -40, -80,-120},		// 11
	{  40,  40, -60},		// 12
	{ -40,  40, -60},		// 13
	{ 200,  20, -40},		// 14
	{-200,  20, -40},		// 15
	{ 200,  20,  40},		// 16
	{-200,  20,  40},		// 17
	{   0,-160,-540},		// 18
	{   0,-160,-500},		// 19
	{   0, -80,-420},		// 20
	{   0, -80,-120},		// 21
	{   0,  80, -40}		// 22
};

int AH_body_surface[14][12] =
{
/*   p0 p1 p2 p3  r   g   b dir <---tex_map---> */
	{ 0, 2,12,10,  0, 31, 31, 1,192,  0,255, 63},	// 0
	{ 1, 3,13,11,  0, 31, 31,-1,192,  0,255, 63},	// 1
	{ 2, 4, 6,12,  0, 31, 31, 1,  0,  0,  0,  0},	// 2
	{ 3, 5, 7,13,  0, 31, 31,-1,  0,  0,  0,  0},	// 3
	{10, 6, 8, 9,  0, 31, 31, 1,  0,  0,  0,  0},	// 4
	{11, 7, 8, 9,  0, 31, 31,-1,  0,  0,  0,  0},	// 5
	{19,20, 9,18, 15, 15, 15, 1,128, 64,191,127},	// 6
	{ 0, 1, 3, 2,  0, 15, 31, 1,  0,  0,  0,  0},	// 7
	{ 2, 3, 5, 4,  0, 31, 31, 1,  0,  0,  0,  0},	// 8
	{ 4, 5, 7, 6,  0, 31, 31, 1,  0,  0,  0,  0},	// 9
	{ 6, 8, 7,22,  0, 31, 31,-1,  0,  0,  0,  0},	// 10
	{10, 9,11,21,  0, 31, 31, 1,  0,  0,  0,  0},	// 11
	{10,11, 1, 0,  0, 31, 31, 1,192, 64,255, 95},	// 12
	{14,15,17,16,  0, 31, 31, 1,  0,  0,  0,  0},	// 13
};

int		AH_body_nx[23], AH_body_ny[23], AH_body_nz[23];
#define	AH_BODY_NMAX	23
#define	AH_BODY_SMAX	14

int AH_roter_point[4][3] =
{
/*     x    y    z (cm) */
	{  20,   1, 400},		// 0
	{ -20,   1, 400},		// 1
	{  20,   1,-400},		// 2
	{ -20,   1,-400}		// 3
};

int AH_roter_surface[1][12] =
{
/*   p0 p1 p2 p3  r   g   b dir <---tex_map---> */
	{ 0, 1, 3, 2, 23, 23, 23,-1,  0,  0,  0,  0}	// 0
};

int		AH_roter_nx[4], AH_roter_ny[4], AH_roter_nz[4];
#define	AH_ROTER_NMAX	4
#define	AH_ROTER_SMAX	1

int AH_pod_point[8][3] =
{
/*     x    y    z (cm) */
	{  20,  20,  80},		// 0
	{ -20,  20,  80},		// 1
	{  20, -20,  80},		// 2
	{ -20, -20,  80},		// 3
	{  20,  20, -80},		// 4
	{ -20,  20, -80},		// 5
	{  20, -20, -80},		// 6
	{ -20, -20, -80}		// 7
};

int AH_pod_surface[6][12] =
{
/*   p0 p1 p2 p3  r   g   b dir <---tex_map---> */
	{ 0, 1, 3, 2,  7,  7,  7,-1,  0,  0,  0,  0},	// 0
	{ 4, 5, 7, 6, 31, 31, 31, 1,  0,  0,  0,  0},	// 1
	{ 0, 1, 5, 4, 31, 31, 31, 1,  0,  0,  0,  0},	// 2
	{ 2, 3, 7, 6, 31, 31, 31,-1,  0,  0,  0,  0},	// 3
	{ 0, 2, 6, 4, 31, 31, 31,-1,  0,  0,  0,  0},	// 4
	{ 1, 3, 7, 5, 31, 31, 31, 1,  0,  0,  0,  0}	// 5
};

int		AH_pod_nx[8], AH_pod_ny[8], AH_pod_nz[8];
#define	AH_POD_NMAX	8
#define	AH_POD_SMAX	6

int wing_point[8][3] =
{
/*     x    y    z (cm) */
	{ 250, 150, 100},		// 0
	{-250, 150, 300},		// 1
	{ 250,-150, 100},		// 2
	{-250,-150, 300},		// 3
	{ 250, 150,-100},		// 4
	{-250, 150,-300},		// 5
	{ 250,-150,-100},		// 6
	{-250,-150,-300}		// 7
};

int wing_surface[6][12] =
{
/*   p0 p1 p2 p3  r   g   b dir <---tex_map---> */
	{ 0, 1, 3, 2, 31, 31, 31,-1,  0,  0,  0,  0},	// 0
	{ 4, 5, 7, 6, 31, 31, 31, 1,  0,  0,  0,  0},	// 1
	{ 0, 1, 5, 4, 31, 31, 31, 1,  0,  0,  0,  0},	// 2
	{ 2, 3, 7, 6, 31, 31, 31,-1,  0,  0,  0,  0},	// 3
	{ 6, 4, 0, 2, 31, 31, 31,-1,  0,  0,  0,  0},	// 4
	{ 1, 3, 7, 5, 31, 31, 31, 1,  0,  0,  0,  0}	// 5
};

int		wing_nx[6], wing_ny[6], wing_nz[6];
#define	WING_NMAX	6
#define	WING_SMAX	6

int wing_gun_point[8][3] =
{
/*     x    y    z (cm) */
	{ 150,  50, 200},		// 0
	{-150,  50, 200},		// 1
	{ 100, -50, 100},		// 2
	{-100, -50, 100},		// 3
	{ 150,  50,-150},		// 4
	{-150,  50,-150},		// 5
	{ 100, -50,-100},		// 6
	{-100, -50,-100}		// 7
};

int wing_gun_surface[6][12] =
{
/*   p0 p1 p2 p3  r   g   b dir <---tex_map---> */
	{ 0, 1, 3, 2, 15, 31, 15,-1,  0,  0,  0,  0},	// 0
	{ 4, 5, 7, 6, 15, 31, 15, 1,  0,  0,  0,  0},	// 1
	{ 0, 1, 5, 4, 15, 31, 15, 1,  0,  0,  0,  0},	// 2
	{ 2, 3, 7, 6, 15, 31, 15,-1,  0,  0,  0,  0},	// 3
	{ 6, 4, 0, 2, 15, 31, 15,-1,  0,  0,  0,  0},	// 4
	{ 1, 3, 7, 5, 15, 31, 15, 1,  0,  0,  0,  0}	// 5
};

int		wing_gun_nx[6], wing_gun_ny[6], wing_gun_nz[6];
#define	WING_GUN_NMAX	6
#define	WING_GUN_SMAX	6

int garage_point[8][3] =
{
/*     x    y    z (cm) */
	{ 250, 150, 300},		// 0
	{-250, 150, 300},		// 1
	{ 250,-150, 300},		// 2
	{-250,-150, 300},		// 3
	{ 250, 150,-300},		// 4
	{-250, 150,-300},		// 5
	{ 250,-150,-300},		// 6
	{-250,-150,-300}		// 7
};

int garage_surface[6][12] =
{
/*   p0 p1 p2 p3  r   g   b dir <---tex_map---> */
	{ 0, 2, 3, 1, 31, 31, 31, 1, 62,238,  1,193},	// 0
	{ 4, 5, 7, 6, 31, 31, 31, 1,  0,  0,  0,  0},	// 1
	{ 0, 1, 5, 4, 31, 31, 31, 1,  0,  0,  0,  0},	// 2
	{ 2, 3, 7, 6, 31, 31, 31,-1,  0,  0,  0,  0},	// 3
	{ 6, 4, 0, 2, 31, 31, 31,-1,  0,  0,  0,  0},	// 4
	{ 1, 3, 7, 5, 31, 31, 31, 1,  0,  0,  0,  0}	// 5
};

int		garage_nx[6], garage_ny[6], garage_nz[6];
#define	GARAGE_NMAX	6
#define	GARAGE_SMAX	6

int base_neck_point[8][3] =
{
/*     x    y    z (cm) */
	{ 100, 200, 100},		// 0
	{-100, 200, 100},		// 1
	{ 100,-200, 100},		// 2
	{-100,-200, 100},		// 3
	{ 100, 200,-100},		// 4
	{-100, 200,-100},		// 5
	{ 100,-200,-100},		// 6
	{-100,-200,-100}		// 7
};

int base_neck_surface[6][12] =
{
/*   p0 p1 p2 p3  r   g   b dir <---tex_map---> */
	{ 0, 1, 3, 2, 23, 23, 23,-1,  0,  0,  0,  0},	// 0
	{ 4, 5, 7, 6, 23, 23, 23, 1,  0,  0,  0,  0},	// 1
	{ 0, 1, 5, 4, 23, 23, 23, 1,  0,  0,  0,  0},	// 2
	{ 2, 3, 7, 6, 23, 23, 23,-1,  0,  0,  0,  0},	// 3
	{ 6, 4, 0, 2, 23, 23, 23,-1,  0,  0,  0,  0},	// 4
	{ 1, 3, 7, 5, 23, 23, 23, 1,  0,  0,  0,  0}	// 5
};

int		base_neck_nx[6], base_neck_ny[6], base_neck_nz[6];
#define	BASE_NECK_NMAX	6
#define	BASE_NECK_SMAX	6

int base_head_point[8][3] =
{
/*     x    y    z (cm) */
	{ 200, 100, 200},		// 0
	{-200, 100, 200},		// 1
	{ 200,-100, 200},		// 2
	{-200,-100, 200},		// 3
	{ 200, 100,-200},		// 4
	{-200, 100,-200},		// 5
	{ 200,-100,-200},		// 6
	{-200,-100,-200}		// 7
};

int base_head_surface[6][12] =
{
/*   p0 p1 p2 p3  r   g   b dir <---tex_map---> */
	{ 0, 2, 3, 1, 31, 31, 31, 1,190,222,129,193},	// 0
	{ 4, 6, 7, 5, 31, 31, 31,-1,126,223, 65,193},	// 1
	{ 0, 1, 5, 4, 31, 31, 31, 1,  0,  0,  0,  0},	// 2
	{ 2, 3, 7, 6, 31, 31, 31,-1,  0,  0,  0,  0},	// 3
	{ 6, 4, 0, 2, 31, 31, 31,-1, 65,193,126,223},	// 4
	{ 1, 3, 7, 5, 31, 31, 31, 1,126,223, 65,193}	// 5
};

int		base_head_nx[6], base_head_ny[6], base_head_nz[6];
#define	BASE_HEAD_NMAX	6
#define	BASE_HEAD_SMAX	6

int container_point[8][3] =
{
/*     x    y    z (cm) */
	{ 100, 100, 200},		// 0
	{-100, 100, 200},		// 1
	{ 100,-100, 200},		// 2
	{-100,-100, 200},		// 3
	{ 100, 100,-200},		// 4
	{-100, 100,-200},		// 5
	{ 100,-100,-200},		// 6
	{-100,-100,-200}		// 7
};

int container_surface[6][12] =
{
/*   p0 p1 p2 p3  r   g   b dir <---tex_map---> */
	{ 0, 1, 3, 2, 23, 23, 23,-1,192,128,255,191},	// 0
	{ 4, 5, 7, 6, 23, 23, 23, 1,192,128,255,191},	// 1
	{ 0, 1, 5, 4, 23, 23, 23, 1,  0,  0,  0,  0},	// 2
	{ 2, 3, 7, 6, 23, 23, 23,-1,  0,  0,  0,  0},	// 3
	{ 6, 4, 0, 2, 23, 23, 23,-1,128,192,255,255},	// 4
	{ 1, 3, 7, 5, 23, 23, 23, 1,  0,  0,  0,  0}	// 5
};

int		container_nx[6], container_ny[6], container_nz[6];
#define	CONTAINER_NMAX	6
#define	CONTAINER_SMAX	6

int block_point[8][3] =
{
/*     x    y    z (cm) */
	{ 100, 100, 200},		// 0
	{-100, 100, 200},		// 1
	{ 100,-100, 200},		// 2
	{-100,-100, 200},		// 3
	{ 100, 100,-200},		// 4
	{-100, 100,-200},		// 5
	{ 100,-100,-200},		// 6
	{-100,-100,-200}		// 7
};

int block_surface[6][12] =
{
/*   p0 p1 p2 p3  r   g   b dir <---tex_map---> */
	{ 0, 1, 3, 2, 23, 23, 23,-1,  0,  0,  0,  0},	// 0
	{ 4, 5, 7, 6, 23, 23, 23, 1,  0,  0,  0,  0},	// 1
	{ 0, 1, 5, 4, 23, 23, 23, 1,  0,  0,  0,  0},	// 2
	{ 2, 3, 7, 6, 23, 23, 23,-1,  0,  0,  0,  0},	// 3
	{ 6, 4, 0, 2, 23, 23, 23,-1,  0,  0,  0,  0},	// 4
	{ 1, 3, 7, 5, 23, 23, 23, 1,  0,  0,  0,  0}	// 5
};

int		block_nx[6], block_ny[6], block_nz[6];
#define	BLOCK_NMAX	6
#define	BLOCK_SMAX	6

#define	CANNON_SPEED	1000
/* 1000cm/0.1s = 100m/s = 360km/h */

int cannon_point[8][3] =
{
/*     x    y    z (cm) (if y=0, error) */
	{  20,  20, CANNON_SPEED},		// 0
	{ -20,  20, CANNON_SPEED},		// 1
	{  20, -20, CANNON_SPEED},		// 2
	{ -20, -20, CANNON_SPEED},		// 3
	{  20,  20,  -5},				// 4
	{ -20,  20,  -5},				// 5
	{  20, -20,  -5},				// 6
	{ -20, -20,  -5}				// 7
};

int cannon_surface[6][12] =
{
/*   p0 p1 p2 p3  r   g   b dir <---tex_map---> */
	{ 0, 1, 3, 2, 31, 15, 31,-2,  0,  0,  0,  0},	// 0
	{ 4, 5, 7, 6, 31,  0, 15, 2,  0,  0,  0,  0},	// 1
	{ 0, 1, 5, 4, 31,  0, 31, 2,  0,  0,  0,  0},	// 2
	{ 2, 3, 7, 6, 31,  0, 31,-2,  0,  0,  0,  0},	// 3
	{ 0, 2, 6, 4, 31,  0, 31,-2,  0,  0,  0,  0},	// 4
	{ 1, 3, 7, 5, 31,  0, 31, 2,  0,  0,  0,  0}	// 5
};

int		cannon_nx[6], cannon_ny[6], cannon_nz[6];
#define	CANNON_NMAX	6
#define	CANNON_SMAX	6

int shot_point[8][3] =
{
/*     x    y    z (cm) (if y=0, error) */
	{  10,  10, CANNON_SPEED},		// 0
	{ -10,  10, CANNON_SPEED},		// 1
	{  10, -10, CANNON_SPEED},		// 2
	{ -10, -10, CANNON_SPEED},		// 3
	{  10,  10,  -5},				// 4
	{ -10,  10,  -5},				// 5
	{  10, -10,  -5},				// 6
	{ -10, -10,  -5}				// 7
};

int shot_surface[6][12] =
{
/*   p0 p1 p2 p3  r   g   b dir <---tex_map---> */
	{ 0, 1, 3, 2, 15, 31, 31,-2,  0,  0,  0,  0},	// 0
	{ 4, 5, 7, 6,  0, 15, 31, 2,  0,  0,  0,  0},	// 1
	{ 0, 1, 5, 4,  0, 31, 31, 2,  0,  0,  0,  0},	// 2
	{ 2, 3, 7, 6,  0, 31, 31,-2,  0,  0,  0,  0},	// 3
	{ 0, 2, 6, 4,  0, 31, 31,-2,  0,  0,  0,  0},	// 4
	{ 1, 3, 7, 5,  0, 31, 31, 2,  0,  0,  0,  0}	// 5
};

int		shot_nx[6], shot_ny[6], shot_nz[6];
#define	SHOT_NMAX	6
#define	SHOT_SMAX	6

int explosion_point[4][3] =
{
/*     x    y    z (cm) (if y=0, error) */
	{ 100, 100,  1},		// 0
	{-100, 100,  1},		// 1
	{ 100,-100,  1},		// 2
	{-100,-100,  1},		// 3
};

int explosion_surface[1][12] =
{
/*   p0 p1 p2 p3  r   g   b dir <---tex_map---> */
	{ 0, 1, 3, 2, 31, 15, 31,-1,  1,  1,126,126},	// 0
};

int		explosion_nx[1], explosion_ny[1], explosion_nz[1];
#define	EXPLOSION_NMAX	1
#define	EXPLOSION_SMAX	1

int bombing_point[4][3] =
{
/*     x    y    z (cm) (if y=0, error) */
	{ 100, 100,  1},		// 0
	{-100, 100,  1},		// 1
	{ 100,-100,  1},		// 2
	{-100,-100,  1},		// 3
};

int bombing_surface[1][12] =
{
/*   p0 p1 p2 p3  r   g   b dir <---tex_map---> */
	{ 0, 1, 3, 2, 31, 15, 31,-2,  1,  1,126,126},	// 0
};

int		bombing_nx[1], bombing_ny[1], bombing_nz[1];
#define	BOMBING_NMAX	1
#define	BOMBING_SMAX	1

int fire1_point[4][3] =
{
/*     x    y    z (cm) (if y=0, error) */
	{ 100,   0,  1},		// 0
	{-100,   0,  1},		// 1
	{ 150,-400,  1},		// 2
	{-150,-400,  1},		// 3
};

int fire1_surface[1][12] =
{
/*   p0 p1 p2 p3  r   g   b dir <---tex_map---> */
	{ 2, 0, 1, 3, 31, 15, 31,-2,129,  1,190,126},	// 0
};

int		fire1_nx[1], fire1_ny[1], fire1_nz[1];
#define	FIRE1_NMAX	1
#define	FIRE1_SMAX	1

int fire2_point[4][3] =
{
/*     x    y    z (cm) (if y=0, error) */
	{ 100,   0,  1},		// 0
	{-100,   0,  1},		// 1
	{ 150,-400,  1},		// 2
	{-150,-400,  1},		// 3
};

int fire2_surface[1][12] =
{
/*   p0 p1 p2 p3  r   g   b dir <---tex_map---> */
	{ 2, 0, 1, 3, 31, 15, 31,-2,193,  1,254,126},	// 0
};

int		fire2_nx[1], fire2_ny[1], fire2_nz[1];
#define	FIRE2_NMAX	1
#define	FIRE2_SMAX	1

/* NMAX = SMAXが正しい */

#define	MAPMAX	7

int	mapstat[] = {0, 0, 0, 1, 0, 1/*night*/, 0};
char *skyname[] = {"sky.tif", "sky.tif", "sky.tif",
					"darksky.tif", "sky.tif", "moon.tif", "sky.tif"};
char *midiname[] = {"", "", "", "", "", "galaxy.eup", ""};

int enemy_arrange[MAPMAX][4*ENMAX] =
{
	{
		/*   type    x      z    t */
		CONTAINER,  2000, 20000, 0,
		CONTAINER, -2000, 20000, 0,
		CONTAINER,  2000, 16000, 0,
		CONTAINER, -2000, 16000, 0,
		        0,     0,     0, 0,
		        0,     0,     0, 0,
		        0,     0,     0, 0,
		        0,     0,     0, 0,
		        0,     0,     0, 0,
		        0,     0,     0, 0,
		        0,     0,     0, 0,
		        0,     0,     0, 0,
	},
	{
		/*   type    x      z    t */
		      MPV, 20000, 20000, 0,
		      MPV, 16000, 20000, 0,
		      MPV, 20000, 16000, 0,
		      MPV, 16000, 16000, 0,
		        0,     0,     0, 0,
		        0,     0,     0, 0,
		        0,     0,     0, 0,
		        0,     0,     0, 0,
		        0,     0,     0, 0,
		        0,     0,     0, 0,
		        0,     0,     0, 0,
		        0,     0,     0, 0,
	},
	{
		/*   type    x      z    t */
		      MBT,  4000, 16000, 0,
		      MBT, -4000, 16000, 0,
		      MPV,  4000, 20000, 0,
		      MPV, -4000, 20000, 0,
		        0,     0,     0, 0,
		        0,     0,     0, 0,
		        0,     0,     0, 0,
		        0,     0,     0, 0,
		        0,     0,     0, 0,
		        0,     0,     0, 0,
		        0,     0,     0, 0,
		        0,     0,     0, 0,
	},
	{
		/*   type    x      z    t */
		       AH,  4000, 20000, 0,
		       AH, -4000, 20000, 0,
		      AAT,  4000, 16000, 0,
		      AAT, -4000, 16000, 0,
		        0,     0,     0, 0,
		        0,     0,     0, 0,
		        0,     0,     0, 0,
		        0,     0,     0, 0,
		        0,     0,     0, 0,
		        0,     0,     0, 0,
		        0,     0,     0, 0,
		        0,     0,     0, 0,
	},
	{
		/*   type    x      z    t */
		       AH,  2000, 20000, 0,
		       AH, -2000, 20000, 0,
		      MPV,  4000, 20000, 0,
		      MPV, -4000, 20000, 0,
		      AAT,  2000, 16000, 0,
		      AAT, -2000, 16000, 0,
		      MBT,  4000, 16000, 0,
		      MBT, -4000, 16000, 0,
		        0,     0,     0, 0,
		        0,     0,     0, 0,
		        0,     0,     0, 0,
		        0,     0,     0, 0,
	},
	{
		/*   type    x      z    t */
		      AAT,  4000, 24000, 0,
		      MBT, -4000, 24000, 0,
		      MPV,  4000, 16000, 0,
		      MPV,     0, 16000, 0,
		      MPV, -4000, 16000, 0,
		       AH,  4000, 20000, 0,
		        0,     0,     0, 0,
		        0,     0,     0, 0,
		        0,     0,     0, 0,
		        0,     0,     0, 0,
		        0,     0,     0, 0,
		        0,     0,     0, 0,
	},
	{
		/*   type    x      z    t */
		       AH,     0,150000, 0,
		       AH,     0,100000, 0,
		     WING,   500, 20000, 2048,
		     WING,  -500, 20000, 0,
		     WING,  7000, 24000, 2048,
		     WING, -7000, 24000, 0,
		     BASE,     0, 20000, 0,
		      MPV,     0, 21000, 0,
		      AAT,     0, 19000, 0,
		       AH,     0, 50000, 0,
		       AH,     0, 15000, 0,
		      MBT,  1000, 10000, 0,
	},
};

int block_arrange[MAPMAX][8*BLOCKMAX] =
{
	{
	/*  r   g   b     x    y     z     xp     zp */
		29, 29, 29,  400, 200, 2000, 4000, 16000,
		29, 29, 29,  400, 200, 2000,-4000, 16000,
		29, 29, 29, 2000, 200,  400,    0, 14000,
		29, 31, 29, 2000, 200,  400,    0, 22000,
		-1, -1, -1,    0,   0,    0,    0,     0,
		-1, -1, -1,    0,   0,    0,    0,     0,
		-1, -1, -1,    0,   0,    0,    0,     0,
		-1, -1, -1,    0,   0,    0,    0,     0,
	},
	{
		-1, -1, -1, 0, 0, 0, 0, 0,
		-1, -1, -1, 0, 0, 0, 0, 0,
		-1, -1, -1, 0, 0, 0, 0, 0,
		-1, -1, -1, 0, 0, 0, 0, 0,
		-1, -1, -1, 0, 0, 0, 0, 0,
		-1, -1, -1, 0, 0, 0, 0, 0,
		-1, -1, -1, 0, 0, 0, 0, 0,
		-1, -1, -1, 0, 0, 0, 0, 0,
	},
	{
		-1, -1, -1, 0, 0, 0, 0, 0,
		-1, -1, -1, 0, 0, 0, 0, 0,
		-1, -1, -1, 0, 0, 0, 0, 0,
		-1, -1, -1, 0, 0, 0, 0, 0,
		-1, -1, -1, 0, 0, 0, 0, 0,
		-1, -1, -1, 0, 0, 0, 0, 0,
		-1, -1, -1, 0, 0, 0, 0, 0,
		-1, -1, -1, 0, 0, 0, 0, 0,
	},
	{
		-1, -1, -1, 0, 0, 0, 0, 0,
		-1, -1, -1, 0, 0, 0, 0, 0,
		-1, -1, -1, 0, 0, 0, 0, 0,
		-1, -1, -1, 0, 0, 0, 0, 0,
		-1, -1, -1, 0, 0, 0, 0, 0,
		-1, -1, -1, 0, 0, 0, 0, 0,
		-1, -1, -1, 0, 0, 0, 0, 0,
		-1, -1, -1, 0, 0, 0, 0, 0,
	},
	{
		-1, -1, -1, 0, 0, 0, 0, 0,
		-1, -1, -1, 0, 0, 0, 0, 0,
		-1, -1, -1, 0, 0, 0, 0, 0,
		-1, -1, -1, 0, 0, 0, 0, 0,
		-1, -1, -1, 0, 0, 0, 0, 0,
		-1, -1, -1, 0, 0, 0, 0, 0,
		-1, -1, -1, 0, 0, 0, 0, 0,
		-1, -1, -1, 0, 0, 0, 0, 0,
	},
	{
		-1, -1, -1, 0, 0, 0, 0, 0,
		-1, -1, -1, 0, 0, 0, 0, 0,
		-1, -1, -1, 0, 0, 0, 0, 0,
		-1, -1, -1, 0, 0, 0, 0, 0,
		-1, -1, -1, 0, 0, 0, 0, 0,
		-1, -1, -1, 0, 0, 0, 0, 0,
		-1, -1, -1, 0, 0, 0, 0, 0,
		-1, -1, -1, 0, 0, 0, 0, 0,
	},
	{
	/*  r   g   b     x    y     z     xp     zp */
		29, 29, 29,  400, 200, 8000, 8000, 20000,
		29, 29, 29,  400, 200, 8000,-8000, 20000,
		29, 29, 29, 8000, 200,  400,    0, 27600,
		29, 29, 29, 6000, 200,  400,    0, 12400,
		29, 29, 29,  400, 200, 6000, 6000, 18000,
		29, 29, 29,  400, 200, 6000,-6000, 18000,
		-1, -1, -1,    0,   0,    0,    0,     0,
		-1, -1, -1,    0,   0,    0,    0,     0,
	},
};

/**************************** GNU-C 互換 *****************************/

void EGB_setPalette(char *w, int num, int g, int r, int b)
{
	unsigned char param[12];

	*(long *)&param[0] = 1L;					/* 設定パレット数 = 1 */
	*(long *)&param[4] = num;
	param[ 8] = b;
	param[ 9] = r;
	param[10] = g;
	param[11] = 0;

	EGB_palette(w, 0, param);					/* no wait Vsync */
}

void EGB_foreColor(char *w, int color)
{
	EGB_color(w, 0, color);
}

void EGB_singlePset(char *w, int x, int y)
{
	short param[3];

	param[0] = 1;
	param[1] = x;
	param[2] = y;
	EGB_pset(w, param);
}

void EGB_singleLine(char *w, int sx, int sy, int ex, int ey)
{
	short param[5];

	param[0] = 2;
	param[1] = sx;
	param[2] = sy;
	param[3] = ex;
	param[4] = ey;
	EGB_connect(w, param);
}

void EGB_box(char *w, int sx, int sy, int ex, int ey)
{
	short param[4];

	param[0] = sx;
	param[1] = sy;
	param[2] = ex;
	param[3] = ey;
	EGB_rectangle(w, param);
}

/************************** utilities *************************/

#define keymatrix(n)	( matrix[(n)/8] & (1 << ((n)%8)) )

void zprint(int x, int y, int a, char *s)
{
	int 	i;
	short	buf[100];
	char	*p;

	/* 文字列バッファの計算 */
	buf[0] = x;
	buf[1] = y;

	p = (char *) & buf[3];
	i = 0;
	do{
		*p++ = *s;
		i++;
		if(i >= 100-4) break;
	}while(*s++ != '\0');
			
	buf[2] = i-1;

	/* write */
	EGB_color(gwork, 0, a);
	EGB_writeMode(gwork, 9);
	EGB_sjisString(gwork, (char *)buf);
}

int onepad(int n)								/* 注 : nは未対応 */
{
	int		i, j, status2;

	if(padmode)
	{
		SND_joy_out(0x0f, &i, &status2);		/* com = 0 */
		SND_joy_out(0x3f, &j, &status2);		/* com = 1 */
		return( ((~j & 0x0f)<<8) | (~i & 0x3f) );
	}
	else
	{
		SND_joy_in_1(n, &i);					/* パッド入力 */
		return(~i & 0x3f);
	}
}

/* チャタリング防止付きパッド入力 */
int getpad(int n)								/* 注 : nは未対応 */
{
	int		a, b, c, d, e, f, g, h;

	while(1)
	{
		a = onepad(n);
		b = onepad(n);
		c = onepad(n);
		d = onepad(n);
		e = onepad(n);
		f = onepad(n);
		g = onepad(n);
		h = onepad(n);
		if(a==b && b==c && c==d && d==e && e==f && f==g && g==h) break;
	}

	return a;
}

/*
void ring(void)
{
	SND_key_off(0);
	SND_inst_change(0, 100);
	SND_key_on(0, 12*8, 60);
}
*/

int waitpad(int n)
{
	int i;

	/* pad input */
	do{i = getpad(n);} while(i != 0);		/* 離すまで待つ */

	do{i = getpad(n);} while(i == 0);		/* 押すまで待つ */

//	ring();

	return(i);
}

void inter_proc(void)
{
	inter_count++;
}

void screenterm(void)
{
	EGB_resolution(  gwork, 0, 3 );		/* 仮想画面の設定 */
	EGB_resolution(  gwork, 1, 3 );		/* 仮想画面の設定 */
	EGB_displayPage( gwork, 1, 2 );		/* 表示ページ=1 */
}

void error(char *p)
{
	EGB_writePage(gwork, 0);			/* 書き込みページを0に */
	zprint(15, 15, 15, p);
	waitpad(0);

	MOS_end();							/*  マウスの動作終了の設定 */
	SND_end();
	KYB_init(); 						/* buffer on */
	screenterm();						/* MS-DOSの画面モードに設定する。*/

	printf(p);

	exit(16);
}

/* console mode用 */
void error2(char *p)
{
	printf(p);

	exit(17);
}

/****************** Euphony driver (FUJITSU sample) ******************/
int eup_load(char *path)
{
	int		i,size,tempo;
	char	buffer[128];

	if((eup_fp = fopen(path,"rb")) == NULL)	return 255;

	fseek(eup_fp,0,SEEK_END);				/* ﾌｧｲﾙの最後にﾎﾟｲﾝﾀを移動	*/
	flen = (unsigned int)ftell(eup_fp);		/* EUPﾌｧｲﾙ全体のﾊﾞｲﾄ数を取得*/
	fseek(eup_fp,0,SEEK_SET);				/* ﾌｧｲﾙの先頭にﾎﾟｲﾝﾀを戻す	*/
	if (flen <= 2048+4+1+1)					/* 全体の大きさはﾍｯﾀﾞ長以下?*/
		return(1);

	/*  以下全32ﾄﾗｯｸについて設定	*/
	fseek(eup_fp,852,SEEK_SET);
	fread(buffer,1,32,eup_fp);
	for(i=0 ; i<32 ;i++)
		SND_eup_mute_set(i,(int)buffer[i]);	/* ミュートの設定			*/
	fread(buffer,1,32,eup_fp);
	for(i=0 ; i<32 ;i++)
		SND_eup_port_set(i,255);			/* 出力ポートの設定(内蔵音源) */
	fread(buffer,1,32,eup_fp);
	for(i=0 ; i<32 ;i++)
		SND_eup_midi_ch_set(i,(int)buffer[i]);
											/* 出力MIDIチャンネルの設定	*/
	fread(buffer,1,32,eup_fp);
	for(i=0 ; i<32 ;i++)
		SND_eup_bias_set(i,(int)buffer[i]);	/* キーバイアスの設定		*/
	fread(buffer,1,32,eup_fp);
	for(i=0 ; i<32 ;i++)
		SND_eup_transpose_set(i,(int)buffer[i]);
											/* トランスポーズの設定		*/
	fseek(eup_fp,1748,SEEK_SET);
	fread(buffer,1,6,eup_fp);
	for(i = 0;i < 6;i++)
		SND_midi_ch_assign(i,i);		/* FM音源のMIDIチャンネル設定	*/
//	fread(buffer,1,8,eup_fp);
//	for(i = 0;i < 8;i++)
//		SND_midi_ch_assign(i+64,(int)buffer[i]);
										/* PCM音源のMIDIチャンネル設定	*/

	fseek(eup_fp,2048,SEEK_SET);		/* 演奏ﾃﾞ-ﾀの先頭情報部に移動	*/
	fread(&size,4,1,eup_fp);			/* 演奏ﾃﾞｰﾀの大きさを読み込む	*/
	fread(buffer,1,2,eup_fp);			/* 2つ分のﾃﾞｰﾀを読み込む		*/
	signature = (int)buffer[0];
	tempo = (int)buffer[1];
	SND_eup_tempo_set(tempo);			/* 曲始めのテンポをセット		*/

	flen -= 2048+4+1+1;                	/* ファイル長からヘッダ長を除く	*/
	fread(eup_buf,1,flen,eup_fp);		/* 演奏データを読み込む			*/
	fclose(eup_fp);						/*  EUPファイルをクローズ		*/

	return(0);
}

int midi_play(char *filename)
{
	if(*filename == '\0') return(1);

	if(eup_load(filename)) return(2);

	/* 演奏開始 */
	SND_eup_play_start(eup_buf,flen,signature);

	return(0);
}

int	midi_end(void)
{
	SND_eup_play_stop();				/*  演奏の停止					*/
	return(0);
}

/****************************  graphic functions  ***********************/

/* tiff画面モードの設定 */
void setEGB(int bitsize, int x, int y)
{
/*  EGB_displayPage( gwork, 0, 3 );	*/

    switch(bitsize)
    {
	    case 4:         /* 16色 */
	        EGB_resolution(gwork, 0, 3);
			EGB_displayStart(gwork, 3, 512, 480);
	        EGB_color(gwork, 0,  0);
	        EGB_color(gwork, 1, 15);
	        break ;
	    case 8:         /* 256色 */
	        EGB_resolution(gwork, 0, 12);
			EGB_displayStart(gwork, 3, 512, 480);
	        break ;
	    case 16:        /* 32K色 */
	        if(x > 320)
	        {
	        	/* 高解像度モードにする */
				EGB_resolution(gwork, 0, 17);
				EGB_displayStart(gwork, 3, 512, 480);
	        }
	        else
			{
				EGB_resolution(gwork, 0, 10);
				EGB_displayStart(gwork, 2,   2,   2);
				EGB_displayStart(gwork, 3, 320, 240);
	        }
	        break ;
    }
    
	EGB_writePage(gwork, 0);			/* 書き込みページを0に */
}

/* tiff展開されたものを表示する */
tiff_put_data(char *buf, int lofs, int lines)
{
    struct
    {
        char  *bp;
        short sel;
        short sx, sy, ex, ey;
    } p;							/* EGB_putBlockのパラメータ */

    p.bp = buf;
    p.sel= getds();
    p.sx = 0;
    p.ex = tiffx -1;
    p.sy = lofs;
    p.ey = lofs + lines -1;

	EGB_putBlock(gwork , 0, (char *)&p);

    return 0 ;
}

/* tiffバッファにデータをロードする */
tiff_read_data(char *bp, int size)
{
	fread(bp, 1, size, tiff_fp);
	return 0;
}

#define TIFFBUF 32000

void loadtiff(char *filename, int nosize)
{
	char loadbuf[TIFFBUF], extbuf[TIFFBUF]/*1*/;
	char compressbuf[DECOMP_WORK_SIZE];

    int		bitsize, d_line;
    int		comp, fill;
    long	strip, clut, dw;

    if((tiff_fp = fopen(filename, "rb" )) == NULL)
    	error("No tiff file\n");
    fread(loadbuf, 1, TIFFBUF, tiff_fp);	   /* 最初のデータロード */

    /* ヘッダの解析 */
    if(TIFF_getHead(loadbuf, TIFFBUF) < 0) error("Erregal tiff header\n");

    /* タグの内容のチェック */
    if( (bitsize = TIFF_checkMode(&tiffx, &tiffy,
    								&comp, &fill, &strip, &clut)) < 0)
		error("tiff checkMode err\n");

    /* バッファ操作関数の登録 */
    TIFF_setLoadFunc(tiff_put_data, tiff_read_data);

    /* 画面モードの設定 */
    if(!nosize) setEGB(bitsize, tiffx, tiffy);

    /* 16色モードの場合,8ドット単位に調整しておく */
    dw = tiffx;
    if(bitsize == 4)
    if(dw & 7)
    	dw += 8 - (dw & 7) ;

    /* 展開用バッファに何行分のデータが入るかの計算  */
    d_line = TIFFBUF/*1*/ / ((dw * bitsize + 7)/ 8);

    /* パレットの設定 */
    if(TIFF_getPal(palt) != 0) EGB_palette(gwork, 0, palt);

    /* TIFFデータのロード&表示  */
    TIFF_loadImage(bitsize, tiffx, tiffy, strip, fill, comp,
    						extbuf, dw, d_line, compressbuf);

    fclose(tiff_fp);
}

void readtiff(char *filename, short *picture, int w, int h)
{
	struct _SREGS	sregs;
	short	pict[512*512], *p;		/* need 250kbyte stack */
	short	param[10];
	int		i, j;

	if(w <= 0) return;
	if(h <= 0) return;

	loadtiff(filename, 0);

    _segread(&sregs);
	*(long *)param = (long)pict;
	param[2] = sregs.ds;			/* global変数のセグメントは異なる */
	param[3] = 0;
	param[4] = 0;
	param[5] = w-1;
	param[6] = h-1;
	EGB_getBlock(gwork, param);

	p = pict;

	for(j=0; j<h; j++)
	{
		for(i=0; i<w; i++)
		{
			*picture++ = *p++;
		}
	}
}

/****************************  sound functions  *************************/

void fgetstr(FILE *f, char *s)
{
	int	d;

	do
	{
		d = fgetc(f);
		if(feof(f)) error("fgetstr err\n");
		
		if(d >= ' ') *s++ = d;
			else     *s++ ='\0';
	}
	while(d != '\n');
}

void loadsnd(char *filename, char playbuff[])
{
	int		i;
	FILE	*f;
	
	/* load */
	f = fopen(filename,"rb");
	if(f == NULL) error2("No snd file!");
	
	for (i=0;i<SNDMAX;i++)
	{
		playbuff[i] = fgetc(f);
		if(feof(f)) break;
	}

	fclose(f);
}

int sndplay(char playbuff[], int note)
{
	if(sndmode == 0) return(0);
	if(demo) return(0);

	/* play */
	if(SND_pcm_status(HUMANVOICE) != 0) SND_pcm_play_stop(HUMANVOICE); 
	SND_pcm_play2(HUMANVOICE, note, 127, playbuff);

	return(1);
}

void sndwait(void)
{
	int	i;

	if(sndmode == 0) return;

	do {
		i = SND_pcm_status(HUMANVOICE);
		if(i == 3) error("sndwait err\n");
	} while(i != 0);
}

/************************* main program begin ***************************/

int	isqrt(int i)
{
	if(i < 0) error("isqrt(i): i<0 !\n");
	if(i < 4096      )	return      sq[i];
	if(i < 4096*16   )	return    4*sq[i/16];
	if(i < 4096*256  )	return   16*sq[i/256];
	if(i < 4096*4096 )	return   64*sq[i/4096];
	if(i < 4096*65536)	return  256*sq[i/65536];
						return 1024*sq[i/1048576];
}

int	iatan2(int y, int x)
{
	register int	ans;

	if(x == 0)
	{
		if(y >=0) ans =  IPAI/2;		/*  90 degree */
			else  ans = -IPAI/2;		/* -90 degree */
	}
	else if(x > 0)
	{
		if(y > 0) ans =  at[ (ATMUL*y)/x];
			else  ans = -at[-(ATMUL*y)/x];
	}
	else
	{
		if(y > 0) ans = IPAI - at[-(ATMUL*y)/x];
			else  ans = IPAI + at[ (ATMUL*y)/x];
	}

	return ans&(RADMAX-1);
}

void invert_matrix(long *i, long a[3][3], long x[3], long y[3], long z[3])
{
	*i = x[0]*y[1]*z[2] + y[0]*z[1]*x[2] + z[0]*x[1]*y[2]
	   - x[0]*z[1]*y[2] - y[0]*x[1]*z[2] - z[0]*y[1]*x[2];
/*   low col */
	a[0][0] = y[1]*z[2]-z[1]*y[2];
	a[1][0] = z[1]*x[2]-x[1]*z[2];
	a[2][0] = x[1]*y[2]-y[1]*x[2];
	a[0][1] = y[2]*z[0]-z[2]*y[0];
	a[1][1] = z[2]*x[0]-x[2]*z[0];
	a[2][1] = x[2]*y[0]-y[2]*x[0];
	a[0][2] = y[0]*z[1]-z[0]*y[1];
	a[1][2] = z[0]*x[1]-x[0]*z[1];
	a[2][2] = x[0]*y[1]-y[0]*x[1];
}

void rotate_x(int *xr, int *yr, int *zr, int xa, int ya, int za, int t)
{
	/* t:0 .. 4095 */
	t &= 4095;
	
	*xr = xa;
	*yr = (int)( ( (long)ya*co[t] - (long)za*si[t] )/0x4000L );
	*zr = (int)( ( (long)ya*si[t] + (long)za*co[t] )/0x4000L );
}

void rotate_y(int *xr, int *yr, int *zr, int xa, int ya, int za, int t)
{
	/* t:0 .. 4095 */
	t &= 4095;
	
	*xr = (int)( ( (long)xa*co[t] + (long)za*si[t] )/0x4000L );
	*yr = ya;
	*zr = (int)( (-(long)xa*si[t] + (long)za*co[t] )/0x4000L );
}

void rotate_z(int *xr, int *yr, int *zr, int xa, int ya, int za, int t)
{
	/* t:0 .. 4095 */
	t &= 4095;
	
	*xr = (int)( ( (long)xa*co[t] - (long)ya*si[t] )/0x4000L );
	*yr = (int)( ( (long)xa*si[t] + (long)ya*co[t] )/0x4000L );
	*zr = za;
}

int theta_feedback(int x, int y, int theta, int add)
{
	int		t, r;

	if((x==0)&&(y==0)) return 0;

	/* 角度計算 */
	t = iatan2(y, x);

	r = 4095 & (theta - t);							/* 目的角との角度 */
	if(r >= 2048) r = r - 4096;

	     if(r >=  add) theta -= add;
	else if(r <= -add) theta += add;
	else               theta  = t;

	return(theta & 4095);
}

void get_nominal(int point_list[][3], int surface_list[][12],
				int surface_max, int nx[3], int ny[3], int nz[3])
{
	char	buff[128];
	int		i, n, s, sign;
	long	m, a[3][3], x[3], y[3], z[3];
	double	d;
	
	/* get nominal vector (regulared to 0x4000) */
	for(s=0; s<surface_max; s++)
	{
		for(i=0; i<3; i++)
		{
			n = surface_list[s][i];
			x[i] = point_list[n][0];
			y[i] = point_list[n][1];
			z[i] = point_list[n][2];
		}

		invert_matrix(&m, a, x, y, z);

		nx[s] = a[0][0]+a[0][1]+a[0][2];
		ny[s] = a[1][0]+a[1][1]+a[1][2];
		nz[s] = a[2][0]+a[2][1]+a[2][2];

		d =   (double)nx[s]*nx[s]
			+ (double)ny[s]*ny[s]
			+ (double)nz[s]*nz[s];
		
		sprintf(buff, "gn-error s:%d d:%d \n", s, d);
		if(d <= 0.1e-20) error(buff);

		d = sqrt(d);
		if(_abs(d) <= 0.1e-10) error("get nominal error 2\n");

		if(pr) printf("s:%d nx:%d ny:%d nz:%d \n", s, nx[s], ny[s], nz[s]);

		sign = surface_list[s][7];
		if(sign >= 0) sign =  1;
		else		  sign = -1;
		nx[s] = ((double)0x4000L * sign * nx[s]) / d;
		ny[s] = ((double)0x4000L * sign * ny[s]) / d;
		nz[s] = ((double)0x4000L * sign * nz[s]) / d;

		if(pr) printf("s:%d nx:%d ny:%d nz:%d \n", s, nx[s], ny[s], nz[s]);
	}
}

void init_polygon(void)
{
	int	i;

	/* make sin and cosine tables */
	for(i=0; i<4096; i++)
	{
		si[i] = (int)(0x4000 * sin(2.0*_PI*i/4096.0));
		co[i] = (int)(0x4000 * cos(2.0*_PI*i/4096.0));
		sq[i] = (int)sqrt((double)i);
		at[i] = (int)( ( IPAI*atan(i/64.0) ) / _PI);
	}
	
	/* initialize arrays */
	get_nominal(MYMBT_body_point, MYMBT_body_surface, MYMBT_BODY_SMAX,
				MYMBT_body_nx, MYMBT_body_ny, MYMBT_body_nz);
	get_nominal(MYMBT_gunner_point, MYMBT_gunner_surface, MYMBT_GUNNER_SMAX,
				MYMBT_gunner_nx, MYMBT_gunner_ny, MYMBT_gunner_nz);

	get_nominal(MBT_body_point, MBT_body_surface, MBT_BODY_SMAX,
				MBT_body_nx, MBT_body_ny, MBT_body_nz);
	get_nominal(MBT_gunner_point, MBT_gunner_surface, MBT_GUNNER_SMAX,
				MBT_gunner_nx, MBT_gunner_ny, MBT_gunner_nz);
	get_nominal(MBT_gun_point, MBT_gun_surface, MBT_GUN_SMAX,
				MBT_gun_nx, MBT_gun_ny, MBT_gun_nz);

	get_nominal(AAT_base_point, AAT_base_surface, AAT_BASE_SMAX,
				AAT_base_nx, AAT_base_ny, AAT_base_nz);
	get_nominal(AAT_gunner_point, AAT_gunner_surface, AAT_GUNNER_SMAX,
				AAT_gunner_nx, AAT_gunner_ny, AAT_gunner_nz);
	get_nominal(AAT_gun_point, AAT_gun_surface, AAT_GUN_SMAX,
				AAT_gun_nx, AAT_gun_ny, AAT_gun_nz);

	get_nominal(MPV_body_point, MPV_body_surface, MPV_BODY_SMAX,
				MPV_body_nx, MPV_body_ny, MPV_body_nz);
	get_nominal(MPV_gunner_point, MPV_gunner_surface, MPV_GUNNER_SMAX,
				MPV_gunner_nx, MPV_gunner_ny, MPV_gunner_nz);
	get_nominal(MPV_gun_point, MPV_gun_surface, MPV_GUN_SMAX,
				MPV_gun_nx, MPV_gun_ny, MPV_gun_nz);

	get_nominal(AH_body_point, AH_body_surface, AH_BODY_SMAX,
				AH_body_nx, AH_body_ny, AH_body_nz);
	get_nominal(AH_roter_point, AH_roter_surface, AH_ROTER_SMAX,
				AH_roter_nx, AH_roter_ny, AH_roter_nz);
	get_nominal(AH_pod_point, AH_pod_surface, AH_POD_SMAX,
				AH_pod_nx, AH_pod_ny, AH_pod_nz);

	get_nominal(wing_point, wing_surface, WING_SMAX,
				wing_nx, wing_ny, wing_nz);
	get_nominal(wing_gun_point, wing_gun_surface, WING_GUN_SMAX,
				wing_gun_nx, wing_gun_ny, wing_gun_nz);
	get_nominal(garage_point, garage_surface, GARAGE_SMAX,
				garage_nx, garage_ny, garage_nz);
	get_nominal(base_neck_point, base_neck_surface, BASE_NECK_SMAX,
				base_neck_nx, base_neck_ny, base_neck_nz);
	get_nominal(base_head_point, base_head_surface, BASE_HEAD_SMAX,
				base_head_nx, base_head_ny, base_head_nz);

	get_nominal(container_point, container_surface, CONTAINER_SMAX,
				container_nx, container_ny, container_nz);
	get_nominal(block_point, block_surface, BLOCK_SMAX,
				block_nx, block_ny, block_nz);
	get_nominal(cannon_point, cannon_surface, CANNON_SMAX,
				cannon_nx, cannon_ny, cannon_nz);
	get_nominal(shot_point, shot_surface, SHOT_SMAX,
				shot_nx, shot_ny, shot_nz);
	get_nominal(explosion_point, explosion_surface, EXPLOSION_SMAX,
				explosion_nx, explosion_ny, explosion_nz);
	get_nominal(bombing_point, bombing_surface, BOMBING_SMAX,
				bombing_nx, bombing_ny, bombing_nz);
	get_nominal(fire1_point, fire1_surface, FIRE1_SMAX,
				fire1_nx, fire1_ny, fire1_nz);
	get_nominal(fire2_point, fire2_surface, FIRE2_SMAX,
				fire2_nx, fire2_ny, fire2_nz);
}

/* clear z-buffer */
void clear_z_buffer(short z_buffer[240][256], short z_color[240][256],
								short back_picture[128][512], int theta)
{
	register short	*p;
	register long	y;
	long	i, x, offset;

	p = (short *)z_buffer;
	for(y = 0; y < ysize*256; y += 16)
	{
		*p++ = 0; *p++ = 0; *p++ = 0; *p++ = 0;
		*p++ = 0; *p++ = 0; *p++ = 0; *p++ = 0;
		*p++ = 0; *p++ = 0; *p++ = 0; *p++ = 0;
		*p++ = 0; *p++ = 0; *p++ = 0; *p++ = 0;
	}

	if((long)back_picture == 0)
	{
		for(x = 0; x < xsize; x++)
		{
			for(y = 0; y < ysize; y++)
			{
				z_color[y][x] = 0;
			}
		}
	}
	else
	{
		offset = (theta & 4095)/4;		/* theta:0..4095; offset:0..1023 */
		for(x = 0; x < xsize; x++)
		{
			i = 1023 & ((x<<reso) + offset);
			if(i > 511) i = 1023 - i;			/* mirror reverse */

			for(y = 0; y < ysize; y++)
			{
				z_color[y][x] = back_picture[y<<reso][i];
			}
		}
	}
}

/* display z-buffer */
void display_z_buffer(short z_buffer[240][256], short z_color[240][256])
{
	struct _SREGS	sregs;
	short	param[10];
	register int	y;

	EGB_writePage(gwork, 1);			/* 書き込みページを1に */

    _segread(&sregs);

	param[2] = sregs.ds;
	param[3] = 0;
	param[5] = xsize-1;
	for(y=0; y < ysize-10; y++)
	{
		*(long *)param = (long)&z_color[y][0];
		param[4] = y;
		param[6] = y;
		EGB_putBlock(gwork, 0, param);
	}
}

/* 以下の値は微妙 */
#define		ZMAX	0x3ffffL
#define		ZCLIP	128

/* clipping */
void clip(long *x, long *y, long *z,
			long x0, long y0, long z0, long x1, long y1, long z1)
{
	long	zz = ZCLIP;				/* (cm) : See polygon() */

	if(z1 != z0)
	{
		*x = x0 + ((x1-x0)*(zz-z0))/(z1-z0);
		*y = y0 + ((y1-y0)*(zz-z0))/(z1-z0);
	}
	else
	{
		*x = (x0+x1)/2;
		*y = (y0+y1)/2;
	}

	*z = zz;
}

void clip2(long *x, long *y, long *z, long x1, long y1, long z1)
{
	clip(x, y, z, *x, *y, *z, x1, y1, z1);
}

void clipping(long x[5], long y[5], long z[5], int *psize)
{
	int	i;

	/* 1点のみビュ−外のときは5角形ポリゴンになる */
	if(z[0]<ZCLIP && z[1]>ZCLIP && z[2]>ZCLIP && z[3]>ZCLIP)
	{
		clip(&x[4], &y[4], &z[4], x[0], y[0], z[0], x[3], y[3], z[3]);
		clip(&x[0], &y[0], &z[0], x[0], y[0], z[0], x[1], y[1], z[1]);
		*psize = 5;
	}
	if(z[0]>ZCLIP && z[1]<ZCLIP && z[2]>ZCLIP && z[3]>ZCLIP)
	{
		x[4] = x[0];
		y[4] = y[0];
		z[4] = z[0];
		clip(&x[0], &y[0], &z[0], x[1], y[1], z[1], x[0], y[0], z[0]);
		clip(&x[1], &y[1], &z[1], x[1], y[1], z[1], x[2], y[2], z[2]);
		*psize = 5;
	}
	if(z[0]>ZCLIP && z[1]>ZCLIP && z[2]<ZCLIP && z[3]>ZCLIP)
	{
		x[4] = x[3];
		y[4] = y[3];
		z[4] = z[3];
		clip(&x[3], &y[3], &z[3], x[2], y[2], z[2], x[3], y[3], z[3]);
		clip(&x[2], &y[2], &z[2], x[2], y[2], z[2], x[1], y[1], z[1]);
		*psize = 5;
	}
	if(z[0]>ZCLIP && z[1]>ZCLIP && z[2]>ZCLIP && z[3]<ZCLIP)
	{
		clip(&x[4], &y[4], &z[4], x[3], y[3], z[3], x[0], y[0], z[0]);
		clip(&x[3], &y[3], &z[3], x[3], y[3], z[3], x[2], y[2], z[2]);
		*psize = 5;
	}

	/* 2点のみビュ−内にある時 */
	for(i=0; i<4; i++)
	{
		if(z[0]<ZCLIP)
		{
			if(z[3]>ZCLIP)
				clip2(&x[0], &y[0], &z[0], x[3], y[3], z[3]);
			else if(z[1]>ZCLIP)
				clip2(&x[0], &y[0], &z[0], x[1], y[1], z[1]);
		}
		if(z[1]<ZCLIP)
		{
			if(z[0]>ZCLIP)
				clip2(&x[1], &y[1], &z[1], x[0], y[0], z[0]);
			else if(z[2]>ZCLIP)
				clip2(&x[1], &y[1], &z[1], x[2], y[2], z[2]);
		}
		if(z[2]<ZCLIP)
		{
			if(z[1]>ZCLIP)
				clip2(&x[2], &y[2], &z[2], x[1], y[1], z[1]);
			else if(z[3]>ZCLIP)
				clip2(&x[2], &y[2], &z[2], x[3], y[3], z[3]);
		}
		if(z[3]<ZCLIP)
		{
			if(z[2]>ZCLIP)
				clip2(&x[3], &y[3], &z[3], x[2], y[2], z[2]);
			else if(z[0]>ZCLIP)
				clip2(&x[3], &y[3], &z[3], x[0], y[0], z[0]);
		}
	}

	/* 3点ともビュ−外のときの追加処理 */
	if(z[0]<ZCLIP && z[1]==ZCLIP && z[3]==ZCLIP)
	{
		x[0] = (x[1]+x[3])/2;
		y[0] = (y[1]+y[3])/2;
		z[0] = ZCLIP;
	}
	if(z[1]<ZCLIP && z[2]==ZCLIP && z[0]==ZCLIP)
	{
		x[1] = (x[2]+x[0])/2;
		y[1] = (y[2]+y[0])/2;
		z[1] = ZCLIP;
	}
	if(z[2]<ZCLIP && z[3]==ZCLIP && z[1]==ZCLIP)
	{
		x[2] = (x[3]+x[1])/2;
		y[2] = (y[3]+y[1])/2;
		z[2] = ZCLIP;
	}
	if(z[3]<ZCLIP && z[0]==ZCLIP && z[2]==ZCLIP)
	{
		x[3] = (x[0]+x[2])/2;
		y[3] = (y[0]+y[2])/2;
		z[3] = ZCLIP;
	}
}

/********************************************************/
/* tetra-polygon processor 'tetra-pro' by TabTack, 1995 */
/********************************************************/
void polygon(short z_buffer[240][256], short z_color[240][256],
			short picture[256][256],
			int point_list[][3], int surface_list[][12], int surface_max,
			int nx[], int ny[], int nz[],
			int ax, int ay, int az,
			int tx, int ty, int tz,
			int bx, int by, int bz,
			int rx, int ry, int rz, int r, int offset)
{
	char	buff[128];
	int		s;
	int		i, j, n;
	int		xa, ya, za;
	int		xr, yr, zr;
	int		yy;
	int		u, v, w;
	int		intensity, red0, green0, blue0;
	int 	red, green, blue;
	int		point1, point2;
	int		left_point[5], right_point[5];	/* 1995.7 */
//	int		left_point[4], right_point[4];
	int		point_min, point_max, leftside;
	int		p1, p2, p3, p4, psize;
	int		x_start, x_end;
	int		x_index, y_index;
	int		texture_map, tmx0, tmy0, tmx1, tmy1;
	long	zzz, zzz0;
	long	a, b, c, m;
	long	mmm[3][3];
	long	x[5], y[5], z[5];				/* screen cordinate */
	long	y_min, y_max;
	long	xp, yp, u1, v1, u2, v2;
	long	tan1, tan2;
	register int	xx;

	EGB_writePage(gwork, 0);				/* 書き込みページを1に */

	if(r < 0) return;						/* no display */

	/* calculate polygons */
	for(s=0; s<surface_max; s++)			/* s:surface */
	{
		if(pr) printf("s = %d \n", s);

		/* texture mappint */
		tmx0 = surface_list[s][8];
		tmy0 = surface_list[s][9];
		tmx1 = surface_list[s][10];
		tmy1 = surface_list[s][11];

		texture_map = 1;
		if( (tmx0 == 0) && (tmy0 == 0) && (tmx1 == 0) && (tmy1 == 0) )
			texture_map = 0;

		/* rotate nominal vector (absolute cordinate) */
		rotate_x(&xr, &yr, &zr, nx[s], ny[s], nz[s], tx);
		rotate_z(&xa, &ya, &za, xr, yr, zr, tz);
		rotate_y(&u,  &v,  &w,  xa, ya, za, ty);

		/* ray:[2 2 1] (sqrt(...) is 3) */
		intensity = (2*u+2*v+1*w) / 3;			/* +-0x4000 */

		if(abs(surface_list[s][7]) == 2)
		{
			intensity = 0x4000;					/* ray source */
		}
		else if (r > 0)
		{
			intensity = 0x3000;					/* exploding */
		}
		else
		{
			intensity /= 2;
			if(intensity < 0) intensity = 0;
			intensity += 0x2000;				/* ambient */

			intensity = intensity*light/32;		/* light : global var. */
		}

		/* rotate nominal vector (screen cordinate) */
		rotate_x(&xr, &yr, &zr,  u,  v,  w, rx);
		rotate_z(&xa, &ya, &za, xr, yr, zr, rz);
		rotate_y(&u,  &v,  &w,  xa, ya, za, ry);

		/* for explosion (not before nominal vector) */
		/* (intensity becames irregal, sorry) */
		if(r > 1)
		{
			tx = 4095 & rand();
			ty = 4095 & rand();
			tz = 4095 & rand();
		}
		
		/* cordinate translation */
		for(i=0; i<4; i++)
		{
			n = surface_list[s][i];

			/* rotate & move datas (for body cordinate) */
			xa = point_list[n][0] + ax;
			ya = point_list[n][1] + ay;
			za = point_list[n][2] + az;

			/* for exploding */
			xa += (r*u)/0x4000;
			ya += (r*v)/0x4000;
			za += (r*w)/0x4000;

			rotate_x(&xr, &yr, &zr, xa, ya, za, tx);
			rotate_z(&xa, &ya, &za, xr, yr, zr, tz);
			rotate_y(&xr, &yr, &zr, xa, ya, za, ty);

			/* move & rotate datas (for screen cordinate) */
			xa = xr + bx;
			ya = yr + by;
			za = zr + bz;
			rotate_x(&xr, &yr, &zr, xa, ya, za, rx);
			rotate_z(&xa, &ya, &za, xr, yr, zr, rz);
			rotate_y(&xr, &yr, &zr, xa, ya, za, ry);
			x[i] = xr;
			y[i] = yr;
			z[i] = zr;
		}

		/* clipping */
		if(z[0]<=ZCLIP && z[1]<=ZCLIP && z[2]<=ZCLIP && z[3]<=ZCLIP)
			continue;

		psize = 4;
		clipping(x, y, z, &psize);
		if(texture_map && psize==5) texture_map = 0;		/* for safe */
		
		/* get x[0],y[1],z[1] ... z[2] to get a,b,c */
		for(i=0; i<psize; i++)
		{
			if(z[i] <= 0)
			{
				for(j=0; j<psize; j++)
				{
					sprintf(buff, "j: x:%ld y:%ld z:%ld \n",
										j, x[j], y[j], z[j]);
					zprint(15, 16*j+80, 15, buff);
				}
				goto next;			/* 来ない筈だが、何故か来る? */
//				error("za <= 0 !");
			}

			x[i] = ((xsize/2L)*x[i])/z[i];		/* -128 .. 127 */
			y[i] = ((xsize/2L)*y[i])/z[i] + offset;
			z[i] = ZMAX/z[i];					/* -0x3ffff .. 0x3ffff */
/*
			it must not, on texture mapping
			if(x[i] < -128) x[i] = -128;
			if(x[i] >  127) x[i] =  127;
			if(y[i] < -120) y[i] = -120;
			if(y[i] >  119) y[i] =  119;
*/
			if(pr) printf("i:%d x:%ld y:%ld z:%ld \n", i, x[i], y[i], z[i]);
		}

		/* get a,b,c of z=ax+by+c */
		/* (a,b,c is multiplied by m but not overflow) */
		invert_matrix(&m, mmm, x, y, iii);

		a = mmm[0][0]*z[0] + mmm[0][1]*z[1] + mmm[0][2]*z[2];
		b = mmm[1][0]*z[0] + mmm[1][1]*z[1] + mmm[1][2]*z[2];
		c = mmm[2][0]*z[0] + mmm[2][1]*z[1] + mmm[2][2]*z[2];
/*
		m =-x[0]*y[1]+x[0]*y[2]+x[1]*y[0]-x[1]*y[2]-x[2]*y[0]+x[2]*y[1];
		a = y[0]*z[1]-y[0]*z[2]-y[1]*z[0]+y[1]*z[2]+y[2]*z[0]-y[2]*z[1];
		b =-x[0]*z[1]+x[0]*z[2]+x[1]*z[0]-x[1]*z[2]-x[2]*z[0]+x[2]*z[1];
		c = m*z[0]-a*x[0]-b*y[0];
*/
		if(_abs(m) < 16) zprint(0,0,15,"identifier is too small!");
		if(m == 0) m = 1;				/* for safe */

		if(pr) printf("a:%ld b:%ld c:%ld m:%ld \n", a, b, c, m);

		/* get poligon-line list */

		/* get smallest y */
		point_min = 0;
		y_min = 0x7fffffffL;
		for(i=0; i<psize; i++)
		{
			if(y[i] < y_min)
			{
				y_min = y[i];
				point_min = i;
			}
		}

		if(pr) printf("y_min:%ld point_min:%d \n", y_min, point_min);

		/* get largest y */
		point_max = 0;
		y_max = -0x80000000L;
		for(i=0; i<psize; i++)
		{
			if(y[i] > y_max)
			{
				y_max = y[i];
				point_max = i;
			}
		}

		if(pr) printf("y_max:%ld point_max:%d \n", y_max, point_max);

		/* get polygon-line(left) */

		/* 一番上の2点に対応する点 */
		point1 = point_min+1;
		if(point1 > psize-1) point1 = 0;

		point2 = point_min-1;
		if(point2 < 0) point2 = psize-1;

		n = y[point1] - y[point_min];
		if(n == 0)
		{
			if(x[point1]-x[point_min] >= 0)
				tan1 =  0x7fffffffL;
			else
				tan1 = -0x80000000L;
		}
		else
			tan1 = 0x4000L*(x[point1]-x[point_min])/_abs(n);
		
		n = y[point2] - y[point_min];
		if(n == 0)
		{
			if(x[point2]-x[point_min] >= 0)
				tan2 =  0x7fffffffL;
			else
				tan2 = -0x80000000L;
		}
		else
			tan2 = 0x4000L*(x[point2]-x[point_min])/_abs(n);
		
		if(tan1 < tan2)
		{
			leftside = 1;
		}
		else
		{
			leftside =-1;
		}
		
		if(pr) printf("tan1:%d tan2:%d leftside:%d \n", tan1, tan2, leftside);
		i = 1;
		left_point[0] = point_min;
		while(1)
		{
			left_point[i] = left_point[i-1] + leftside;
			if(left_point[i] < 0) left_point[i] = psize-1;
			if(left_point[i] > psize-1) left_point[i] = 0;

			if(pr) printf("left_point[%d]:%d \n", i, left_point[i]);

			if(left_point[i] == point_max) break;

			i++;
			if(i >= psize)
			{
//				zprint(0, 16, 15, "left point error");
				goto next;
			}
		}
		
		i = 1;
		right_point[0] = point_min;
		while(1)
		{
			right_point[i] = right_point[i-1] - leftside;
			if(right_point[i] < 0) right_point[i] = psize-1;
			if(right_point[i] > psize-1) right_point[i] = 0;

			if(pr) printf("right_point[%d]:%d \n", i, right_point[i]);

			if(right_point[i] == point_max) break;

			i++;
			if(i >= psize)
			{
//				error("right point error");
				goto next;
			}
		}
		
		/* write to Z buffer */
		red0	= surface_list[s][4];
		green0	= surface_list[s][5];
		blue0	= surface_list[s][6];

		yy = y_min;
		if(yy < -(2*ysize)/3) yy = -(2*ysize)/3;
		yy--;
		
		while(1)						/* using continue */
		{
			if(getpad(0) == PAD_SELECT) break;

			yy++;
			if(yy >   y_max ) break;
			if(yy >= ysize/3) break;

			if(pr) printf("yy:%d \n", yy);

			/* calculate left point */
			for(i=0; i<psize-1; i++)
			{
				p1 = left_point[i];
				p2 = left_point[i+1];
				if((y[p1] <= yy)&&(yy <= y[p2])) break;
			}
			if(i>=3) zprint(0,0,15,"Z write error 1");

			if(pr) printf("y[p1:%d]:%ld y[p2:%d]:%ld \n",
									p1, y[p1], p2, y[p2]);

			if(y[p1] == y[p2])
			{
//				zprint(0, 16, 15, "y[p1] == y[p2] on start");
				continue;
//				x_start = x[p1];
			}
			else
			{
				x_start = x[p1] + ((yy-y[p1])*(x[p2]-x[p1])) / (y[p2]-y[p1]);

				/* texture mapping (クリッピング時にはうまくいかないので、 */
				/*           テクスチャマッピングは大きな物体には使わない) */
				if(texture_map)
				{
					if((p1 == 0)&&(p2 == 1)||(p1 == 1)&&(p2 == 0))
					{
						u1 = tmx0;
						v1 = tmy0;
						if(y[1] != y[0])
							v1 += ((tmy1 - tmy0)*(yy - y[0]))/(y[1]-y[0]);
					}
					else if((p1 == 1)&&(p2 == 2)||(p1 == 2)&&(p2 == 1))
					{
						u1 = tmx0;
						v1 = tmy1;
						if(y[2] != y[1])
							u1 += ((tmx1 - tmx0)*(yy - y[1]))/(y[2]-y[1]);
					}
					else if((p1 == 2)&&(p2 == 3)||(p1 == 3)&&(p2 == 2))
					{
						u1 = tmx1;
						v1 = tmy0;
						if(y[2] != y[3])
							v1 += ((tmy1 - tmy0)*(yy - y[3]))/(y[2]-y[3]);
					}
					else
					{
						u1 = tmx0;
						v1 = tmy0;
						if(y[3] != y[0])
							u1 += ((tmx1 - tmx0)*(yy - y[0]))/(y[3]-y[0]);
					}
				}
			}
			if(pr) printf("x_start:%d \n", x_start);
//			if(x_start < -128) x_start = -128;

			/* calculate right point */
			for(i=0; i<psize-1; i++)
			{
				p3 = right_point[i];
				p4 = right_point[i+1];
				if((y[p3] <= yy)&&(yy <= y[p4])) break;
			}
			if(i>=3) zprint(0,0,15,"Z write error 2");

			if(pr) printf("y[p3:%d]:%ld y[p4:%d]:%ld \n",
									p3, y[p3], p4, y[p4]);

			if(y[p3] == y[p4])
			{
//				zprint(0, 16, 15, "y[p3] == y[p4] on end");
//				continue;
				x_end = x[p3];
			}
			else
			{
				x_end = x[p3] + ((yy-y[p3])*(x[p4]-x[p3])) / (y[p4]-y[p3]);

				/* texture mapping */
				if(texture_map)
				{
					if((p3 == 0)&&(p4 == 1)||(p3 == 1)&&(p4 == 0))
					{
						u2 = tmx0;
						v2 = tmy0;
						if(y[1] != y[0])
							v2 += ((tmy1 - tmy0)*(yy - y[0]))/(y[1]-y[0]);
					}
					else if((p3 == 1)&&(p4 == 2)||(p3 == 2)&&(p4 == 1))
					{
						u2 = tmx0;
						v2 = tmy1;
						if(y[2] != y[1])
							u2 += ((tmx1 - tmx0)*(yy - y[1]))/(y[2]-y[1]);
					}
					else if((p3 == 2)&&(p4 == 3)||(p3 == 3)&&(p4 == 2))
					{
						u2 = tmx1;
						v2 = tmy0;
						if(y[2] != y[3])
							v2 += ((tmy1 - tmy0)*(yy - y[3]))/(y[2]-y[3]);
					}
					else
					{
						u2 = tmx0;
						v2 = tmy0;
						if(y[3] != y[0])
							u2 += ((tmx1 - tmx0)*(yy - y[0]))/(y[3]-y[0]);
					}
				}
			}
			if(pr) printf("x_end:%d \n", x_end);
//			if(x_end > 127) x_end = 127;

			/* write to Z buffer */
			if(x_start > x_end)
			{
//				zprint(0, 32, 15, "start>=end !");
			}
			else
			{
				zzz0 = b*yy + c;

				y_index = yy + (2*ysize)/3;
				if(y_index <   0  ) error("polygon error y_index-1 ");
				if(y_index > ysize) error("polygon error y_index-2 ");

				xx = x_start;
				if(xx < -xsize/2) xx = -xsize/2;
				xx--;
				while(1)		/* you must faster this loop */
				{
					xx++;
					if(xx >  x_end) break;
					if(xx >= xsize/2) break;
					x_index = xx+xsize/2;

					zzz = (a*xx + zzz0)/m;			/* no overflow */
					/* if(pr) printf("xx:%d zzz:%ld \n", xx, zzz); */
					/* if( (0 < zzz) && (zzz <= ZMAX) ) */
					if(zzz > 0)
					{
						/* near(large) << zzz >> (small)far (for 1/z) */
						if(z_buffer[y_index][x_index] < (short)zzz)
						{
							if(!texture_map)
							{
								red  = red0;
								green= green0;
								blue = blue0;
							}
							else
							{
								if(x_end != x_start)
								{
									/* texture mapping (xx:yy:+-128) */
									xp = u1 + ((u2-u1)*(xx-x_start))
													/(x_end-x_start);
									yp = v1 + ((v2-v1)*(xx-x_start))
													/(x_end-x_start);
									if(pr) printf("xp:%d yp:%ld \n", xp, yp);
								}
								else
								{
									xp = u1;
									yp = v1;
								}
								
								if(  (0 <= xp)&&(xp < 256)
								   &&(0 <= yp)&&(yp < 240) )
								{
									/* もし透明ならば... */
									i = picture[yp][xp];
									if(i == 0) continue;
									/* get r,g,b */
									red   = 31 & (i>>5);
									green = 31 & (i>>10);
									blue  = 31 &  i;
								}
								else
								{
									red  = red0;
									green= green0;
									blue = blue0;
								}
							}
							red   = (intensity*red  )>>14;
							green = (intensity*green)>>14;
							blue  = (intensity*blue )>>14;

							z_color[y_index][x_index] =
								(green<<10) | (red<<5) | blue;
							z_buffer[y_index][x_index] = (short)zzz;
						}
					}
				}
			}
		}
next:	;
	}
}

/* write ground (tx, ty is unuseable) */
/* まだ表示が不自然... */
void ground(short z_buffer[240][256], short z_color[240][256],
			short sand_picture[256][256], short land_color,
			int mx, int my, int mz, int tx, int ty, int tz)
{
	int max, x, y, y_index, gx, gz, px, pz, rx, rz;
	int	color, rr, gg, bb, land_r, land_g, land_b;
	int	si_t, co_t;
	register int	r, g, b;

	max = ysize/3;

	land_r = 31 & (land_color>> 5);
	land_g = 31 & (land_color>>10);
	land_b = 31 &  land_color;

	si_t = si[ty];
	co_t = co[ty];

	for(y = 1; y<max; y++)		/* if y=0, overflow */
	{
		gz = (my*128)/y; if(gz == 0) gz = 1;
		pz = gz + mz;

		rr = land_r*(max - y);
		gg = land_g*(max - y);
		bb = land_b*(max - y);

		y_index = (2*ysize)/3+y;

		for(x = -xsize/2; x < xsize/2; x++)
		{
			/* get correspond ground position */
			gx = (x*gz)/128;
			px = gx + mx;
			
			/* rotate_y(&rx, &ry, &rz,  px, my, pz, ty); */
			rx = ( (long)px*co_t + (long)pz*si_t )/0x4000L;
			rz = (-(long)px*si_t + (long)pz*co_t )/0x4000L;

			color = sand_picture[rz & 255][rx & 255];

			r = 31 & (color>> 5);
			g = 31 & (color>>10);
			b = 31 &  color;

			/* 遠くに行くほど均質化する */
			r = ( r*y + rr ) / max;
			g = ( g*y + gg ) / max;
			b = ( b*y + bb ) / max;

			r = (r*light)>>5;		/* light:照明を表すグロ−バル変数 */
			g = (g*light)>>5;		/* /32 */
			b = (b*light)>>5;

			color = ((g<<10) | (r<<5) | b);

			/* write texture pattern */
			z_color[y_index][x+xsize/2] = color;
			z_buffer[y_index][x+xsize/2] = ZMAX/gz;		/* 1994.5.7 */
			/* 疑似的であるのでresoの処理は無し */
		}
	}
}

short get_average_color(short *picture, long max)
{
	int		c, r, g, b;
	long	i;
	long	rsum, gsum, bsum;

	rsum = gsum = bsum = 0;
	for(i=0; i<max; i++)
	{
		c = *picture++;
		r = 31 & (c>> 5);
		g = 31 & (c>>10);
		b = 31 &  c;

		rsum += r;
		gsum += g;
		bsum += b;
	}
	r = rsum/max;
	g = gsum/max;
	b = bsum/max;
	
	return((g<<10) | (r<<5) | b);
}

void mouse_cursor(short *mousech, short *mousex, short *mousey)
{
	struct _SREGS	sregs;
	short	pict[32*32];
	short	param[10];
	register int	i;

	EGB_writePage(gwork, 0);			/* 書き込みページを0に */

	if(*mousex <  16) *mousex =  16;	/* カ−ソルが隠れないように */
	if(*mousex > 624) *mousex = 624;
	if(*mousey <   4) *mousey =   4;
	if(*mousey > 464) *mousey = 464;

	_segread(&sregs);

	/* clear old pattern */
	for(i=0; i<32*32; i++)				/* 実は8*32で可? */
		pict[i] = 0;					// save_mouse[i];

	*(long *)param = (long)pict;
	param[2] = sregs.ds;
	param[3] = oldmousex-16;
	param[4] = oldmousey-16;
	param[5] = oldmousex+15;
	param[6] = oldmousey+15;
	EGB_putBlock(gwork, 2/*mask on*/, param);

	/* write mouse cursor */
	for(i=0; i<32*32; i++)
		pict[i] = mouse_pattern[i];

	*(long *)param = (long)pict;
	param[2] = sregs.ds;
	param[3] = *mousex-16;
	param[4] = *mousey-16;
	param[5] = *mousex+15;
	param[6] = *mousey+15;
	EGB_putBlock(gwork, 2/*mask on*/, param);

	oldmousex = *mousex;
	oldmousey = *mousey;
}

void play_sound(int bombed, int key, int voice, int pan, int offset, int snd)
{
	/* 音を鳴らす */
	if(bombed & 2)						/* bomb */
	{
		SND_key_off(key);
		SND_inst_change(key, voice);
		SND_pan_set(key, pan);
		SND_key_on(key, offset, 120);
	}
	else if(bombed & 1)					/* damage */
	{
		SND_key_off(key);
		SND_inst_change(key, voice);
		SND_pan_set(key, pan);
		SND_key_on(key, 24+offset, 120);
	}

	/* PCM */
	if(snd == 0) return;

	if(bombed & 4)
		sndplay(bingo_snd, BASETONE);
	else if(bombed & 2)
		sndplay(break_snd, BASETONE);
	else if(bombed & 1)
		sndplay(hit_snd, BASETONE);
}

void lock_on(struct INDEVICE *in, struct TANK *my, struct TANK en[])
{
	int		x, z, r, t, minr, minno, mint;
	register int	j;

	minno = -1;
	minr  = IN_RANGE;						/* 射程内 */
	for(j=0; j<ENMAX; j++)
	{
		if(en[j].type!=0 && en[j].stat==0)
		{
			x = en[j].x - my->x;
			z = en[j].z - my->z;

			if(abs(x)>=0x8000) continue;	/* vs. overflow */
			if(abs(z)>=0x8000) continue;

			/* 視界内か */
			t = 4095 & (iatan2(x, z) - my->s);

			if(t<512 || 4096-512<=t)
			{
				/* 最短距離 */
				r = isqrt(x*x + z*z);
				if(r < minr)
				{
					minr  = r;
					minno = j;
					mint  = t;
				}
			}
		}
	}

	if(minno >= 0)
	{
		in->mousex =    320    + (256L*si[mint])/co[mint];
		in->mousey = (2*256)/3 + (256L*(en[minno].y - my->y))/minr;

		/* ロック音 */
		SND_key_off(ELSESOUND);
		SND_inst_change(ELSESOUND, 2);
		SND_key_on(ELSESOUND, 12*5+1, 120);
	}
}

void move_shot(struct SHOT *sh, struct TANK en[],
				int enmax, int key, int voice, int offset, int snd)
{
	int		u, v, w, x, y, z;
	int		i, p, q;
	int		n, t, enno;
	int		bombed;

	if(sh->type)
	{
		bombed = 0;

		rotate_x(&x, &y, &z, 0, 0, 100*256, sh->r);		/* move add */
		rotate_y(&u, &v, &w, x, y, z, sh->s);
		u /= 256;
		v /= 256;
		w /= 256;
		/* うまく当たらなかったらx,y,zを100倍する */

		/* 当たり判定 */
		if(sh->type > BOMBING)
		{
			for(i = 0; i < sh->speed; i += 100)
			{
				if(isblock(sh->x, sh->y, sh->z, 10))
				{
					sh->type = 1;
					sh->life = 1;
					break;
				}

				for(enno=0; enno<enmax; enno++)
				{
					/* hit? */
					if(en[enno].type == 0) continue;
					if(en[enno].stat != 0) continue;

					p = q = 100;			/* hit check, 100cm squre */
					if(en[enno].type == WING) { p = 250; q = 250; }
					if(en[enno].type == BASE) { p = 200; q = 750; }
					
					if(    (abs(sh->x - en[enno].x) < p)
						&& (abs(sh->y - en[enno].y) < q)
						&& (abs(sh->z - en[enno].z) < p) )
					{
						bombed |= 1;
						
						en[enno].arm -= sh->power;
						if(en[enno].arm <= 0)
						{
							sh->type = 2;				/* bombing */
							sh->life = 4;
							
							bombed |= 2;

							t = en[enno].type;

							if(t == CONTAINER)
								n = EXPLOSION;
							else if(   (t == MYMBT) || (t == MBT)
									|| (t == AAT  ) || (t == MPV) )
							{
								if(sh->y < -120)
									n = TOP_BLOW;
								else if(sh->y > -40)
									n = FLY;
								else
									n = EXPLOSION;
							}
							else if(t == AH)
							{
								if(abs(sh->y - en[enno].y) < p/2)
									n = EXPLOSION;
								else if(sh->y > en[enno].y)
									n = FALL;
								else
									n = CRASH;
							}
							else if((t == WING)||(t == BASE))
							{
								if(sh->y < -300)
									n = TOP_BLOW;
								else
									n = EXPLOSION;
							}
							en[enno].stat = n;
							en[enno].count = 1;
							
							if(n == EXPLOSION) bombed |= 4;
						}
						else
						{
							sh->type = 1;				/* bombing */
							sh->life = 3;
						}
						
						en[enno].shoted = SHOTEDMAX;

						goto next;
					}
				}
				
				/* 移動 */
				sh->x += u;
				sh->y += v;
				sh->z += w;
				
				if(sh->y > 0)
				{
					sh->type = 1;
					sh->life = 1;
					break;
				}
			}
		}
next:	;

		if(0 < sh->type && sh->type < BOMBING)
		{
			/* bombing (2個以上あるとバグるような...) */
			if(sh->life > 4) error("move shot error!\n");

			/* life=1 -> 400, 4 -> 100 */
			for(i=0; i<4; i++)
			{
				bombing_point[i][0]
					= explosion_point[i][0] * sh->type;			/* x */
				bombing_point[i][1]
					= explosion_point[i][1] * sh->type;			/* y */
			}
			sh->type++;
		}

		/* 寿命 */
		if(sh->life-- <= 0) sh->type = 0;					/* erased */

		play_sound(bombed, key, voice, 64, offset, snd);
	}
}

void regist_shot(struct SHOT enshot[ENSHOTMAX], struct TANK en,
								int pow, int shottype, int yoffset)
{
	int		i;

	for(i=0; i<ENSHOTMAX; i++)
	{
		if(enshot[i].type == 0)
		{
			enshot[i].type	= shottype;			/* active */
			enshot[i].life	= 10;				/* 1sec, 1000m */
			enshot[i].x		= en.x;
			enshot[i].y		= en.y + yoffset;
			enshot[i].z		= en.z;
			enshot[i].r		= 4095 & (en.wr + (31 & rand()) - 16);
			enshot[i].s		= 4095 & (en.ws + (31 & rand()) - 16);
			enshot[i].speed	= CANNON_SPEED;		/* 1000cm/0.1s (360km/h) */
			enshot[i].power = pow;

			/* 音を鳴らす */
			SND_key_off(ENSHOTSOUND);
			SND_inst_change(ENSHOTSOUND, 2);
			SND_pan_set(ENSHOTSOUND, 64);
			SND_key_on(ENSHOTSOUND, 24, 120);

			break;
		}
	}
}

#define	FIELD_SIZE	50000

/* write guide box */
void write_radar(int p, int q, int c, int d, int e)
{
	int	i, j, x, y;

	if(demo) return;

	EGB_writePage(gwork, 0);

	x = (100*p)/FIELD_SIZE + 460;					/* +-1km */
	y = (100*q)/FIELD_SIZE + 360;

	if(d >= 0)
	{
		i =  si[d]/(0x4000/16);
		j = -co[d]/(0x4000/16);
		EGB_color(gwork, 0, e);
		EGB_singleLine(gwork, x, y, x+i, y+j);
	}
	
	EGB_color(gwork, 0, c);
	EGB_singlePset(gwork, x, y);
}

/* ブロックとの衝突判定 */
int	isblock(int x, int y, int z, int offset)
{
	int		i, a, b, c, d, e;

	for(i=0; i<BLOCKMAX; i++)
	{
		/* block_arrange[MAPMAX][8*BLOCKMAX] = r g b x y z xp zp */
		if(block_arrange[mission][8*i] < 0) continue;

		/* set data */
		a = block_arrange[mission][8*i+3];
		b = block_arrange[mission][8*i+4];
		c = block_arrange[mission][8*i+5];

		d = block_arrange[mission][8*i+6];
		e = block_arrange[mission][8*i+7];

		if(	   (abs(d - x) < a+offset)			/* 2m */
			&& (abs(    y) < b    )
			&& (abs(e - z) < c+offset) )
		{
			return 1;
		}
	}
	
	return 0;
}

int check_and_move(int enno, int speed)			/* -1:error  1:衝突あり */
{
	int		i, p, q;
	int		*x, *y, *z, *s;
	int		range = 400;						/* 3m */

	if(enno < 0)
	{
		x = &(my.x);
		y = &(my.y);
		z = &(my.z);
		s = &(my.s);
	}
	else if(enno < ENMAX)
	{
		x = &(en[enno].x);
		y = &(en[enno].y);
		z = &(en[enno].z);
		s = &(en[enno].s);
	}
	else return -1;

	/* 敵機との衝突判定 */
	if(speed == 0) return 0;
	*s &= 4095;
	p = *x + si[*s]/(0x4000/speed);
	q = *z + co[*s]/(0x4000/speed);

	for(i = 0; i < ENMAX; i++)
	{
		if(i == enno) continue;
		if(en[i].type == 0) continue;

		if(	   (abs(en[i].x -  p) < range  )
			&& (abs(en[i].y - *y) < range/2)		/* for heri can't move */
			&& (abs(en[i].z -  q) < range  ) )
		{
			return 1;
		}
	}
	
	/* 自機との衝突判定 */
	if(enno >= 0)
	{
		if(	   (abs(my.x -  p) < range  )
			&& (abs(my.y - *y) < range/2)
			&& (abs(my.z -  q) < range  ) )
		{
			return 1;
		}
	}

	/* ブロックとの衝突判定 */
	if(isblock(p, *y, q, 300)) return 1;

	/* go forward */
	*x = p;
	*z = q;

	return 0;
}

/* 爆発の処理 */
int do_explosion(struct TANK *en)
{
	int	i, done = 0;

	if(en->type > 0)
	{
		if(en->stat == FLY)
		{
			en->t += 256;

			if(en->count < 5)
				en->y -= 40;
			else
			{
				en->y += 40;
				if(en->type == MPV) i = -80; else i = -100;
				if(en->y >= i) en->stat = STILL;
			}
			done = 1;
		}
		else if(en->stat == FALL)
		{
			en->r  -=  8;
			en->s  += 64;
			en->wr -=  8;
			en->ws += 64;
			en->y  += 20;
			if(en->y >= -80) en->stat = STILL;
			done = 1;
		}
		else if(en->stat == CRASH)
		{
			en->t  += 256;
			en->y  += 40;
			if(en->y >= -80) en->stat = STILL;
			done = 1;
		}
		else if(en->stat == EXPLOSION)
		{
			if(en->count > 5)
			{
//				en->stat = STILL;
				en->type = 0;		/* erased */
			}
			done = 1;
		}
		else if(en->stat == TOP_BLOW)
		{
			/* nothing */
			done = 1;
		}
		else if(en->stat == STILL)
		{
			/* nothing */
			done = 1;
		}
	}

	if((0 < en->count) && (en->count < 256)) en->count++;

	return done;
}

/* player's move */
void my_think(struct TANK *my, struct TANK en[],
				struct SHOT *sh, struct INDEVICE *in)
{
	int		x, y;
	int		pad, speed;
	int     mousech, mousex, mousey;

	my->s &= 4095;
	write_radar(my->x, -my->z, 0, my->s, 0);

	if(do_explosion(my)) return;

	if(my->type == 0) return;

	pad		= (int)in->pad;
	mousech = (int)in->mousech;

	/* get pad direction from pad code & move */
	if(pad & PAD_RIGHT)
	{
		my->s  = my->s  + 128;
		my->ws = my->ws + 128;
	}
	if(pad & PAD_LEFT )
	{
		my->s  = my->s  - 128;
		my->ws = my->ws - 128;
	}
	my->s  &= 4095;
	my->ws &= 4095;

	speed = 0;
	if(pad & PAD_UP  ) speed =  100;
	if(pad & PAD_DOWN) speed = -100;

	if(check_and_move(-1, speed) > 0)
	{
		/* 衝突音 */
		SND_key_off(ELSESOUND);
		SND_inst_change(ELSESOUND, 0);
		SND_key_on(ELSESOUND, 12*3, 120);
	}

	if(my->x < -FIELD_SIZE) my->x = -FIELD_SIZE;
	if(my->y < -FIELD_SIZE) my->y = -FIELD_SIZE;
	if(my->x >  FIELD_SIZE) my->x =  FIELD_SIZE;
	if(my->y >  FIELD_SIZE) my->y =  FIELD_SIZE;

	/* 攻撃 */
	if(mousech & MOUSERIGHT) lock_on(in, my, en);

	mousex  = (int)in->mousex;
	mousey  = (int)in->mousey;

	if((64 < mousex) && (mousex < 640-64))
	if((16 < mousey) && (mousey < 254))
	{
		y = mousex - 320;
		x = 2*128;								/* ｽｸﾘ-ﾝまでの距離 */
		my->ws = 4095 & (my->s + iatan2(y, x));

		y = (2*256)/3 - mousey;
		x =  2*128;
		my->wr = iatan2(y, x);

		if(mousech & MOUSELEFT)
		if(sh->type == 0)
		{
			sh->type	= CANNON_SHOT;			/* active */
			sh->life	= 10;					/* 1(2)sec, 100m */
			sh->x		= my->x;
			sh->y		= my->y-30;				/* fixed */
			sh->z		= my->z;
			sh->r		= my->wr;
			sh->s		= my->ws;
			sh->speed	= CANNON_SPEED;			/* 1000cm/0.1s (360km/h) */
			sh->power	= 10;
			
			/* 音を鳴らす */
			SND_key_off(MYSHOTSOUND);
			SND_inst_change(MYSHOTSOUND, 1);
			SND_pan_set(MYSHOTSOUND, 64);
			SND_key_on(MYSHOTSOUND, 24, 120);
		}
	}

	write_radar(my->x, -my->z, 15, my->s, 9);

	myold.pad     = in->pad;
	myold.mousech = in->mousech;
	myold.mousex  = in->mousex;
	myold.mousey  = in->mousey;
}

void enemy_think(int enno, struct TANK *en, struct TANK my)
{
	int		i, x, y;
	int		max, pow, speed, shottype, shotoffset;
	int		landmobil;
	int		delta, match;
	
	/* erase guide box */
	write_radar(en->x, -en->z, 0, -1, 0);

	if(do_explosion(en) == 0)
	{
		if(en->type != CONTAINER)
		{
			speed = 50;					/* 50cm/0.1s (18km/h) */
			i = 100000;					/* 1km */
			if(    (abs(en->x - my.x) < i)
				&& (abs(en->y - my.y) < i)
				&& (abs(en->z - my.z) < i) )
			{
				/* if near distance, trace and attack me */
				landmobil = 1;
				max		= 6;
				pow		= 1;
				speed	= 100;			/* 100cm/0.1s (36km/h) */
				shottype= SHOT_SHOT;
				shotoffset = 0;
				en->r	= 0;
				en->wr	= 0;

				delta	= en->ws;
				en->ws	= theta_feedback(my.z - en->z,
										my.x - en->x, en->ws, match=128);
				delta	= abs(delta - en->ws);

				if((en->type == WING)||(en->type == BASE))
				{
					if(en->type == WING)
					{
						shotoffset = -200;
						shottype= CANNON_SHOT;
						max		= 10;
						pow		= 10;
					}
					else
					{
						shotoffset = -650;
						shottype= SHOT_SHOT;
						max		= 6;
						pow		= 2;
					}
					landmobil = 0;
					speed	= 0;

					x = en->z - my.z;
					y = en->x - my.x;
					if(abs(x)<10000 && abs(y)<10000)
					{
						i = isqrt(x*x + y*y);
						i = -iatan2(my.y - en->y - shotoffset, i);

						if(i >  512) i =  512;
						if(i < -512) i = -512;
					}
					else i = 0;
					en->wr = 4095 & i;
				}
				else if(en->type == AH)
				{
					landmobil = 0;
					max		= 10;
					pow		= 10;
					shottype= CANNON_SHOT;
					speed = 200;
					x = en->z - my.z;
					y = en->x - my.x;
					if(abs(x)<10000 && abs(y)<10000)
					{
						i = isqrt(x*x + y*y);
						i = -iatan2(my.y - en->y, i);

						if(i >  512) i =  512;
						if(i < -512) i = -512;
					}
					else i = 0;
					en->wr = 4095 & i;

					if((rand() & 3) == 0)
						en->ws = 4095 & (en->ws + (511 & rand()) - 255);

					en->r = en->wr;
					en->s = en->ws;
				}
				else if(en->type == MBT)
				{
					max = 10;
					pow = 10;
					shottype= CANNON_SHOT;
				}
				else if(en->type == AAT)
				{
					max = 3;
					pow	= 2;
				}
				else if(en->type == MPV)
				{
					speed = 200;
				}
				
				if(landmobil)
				{
					if((rand() & 7) == 0)
						en->s = theta_feedback(my.z - en->z,
										my.x - en->x, en->s, 128);
					if((rand() & 7) == 0) en->s += 64;
					if((rand() & 7) == 0) en->s -= 64;
					en->s &= 4095;
				}

				i = 14000;					/* 140m */
				if(    (en->count > max)
					&& (abs(en->x - my.x) < i)
					&& (abs(en->y - my.y) < i)
					&& (abs(en->z - my.z) < i) )
				{
					if(en->type == AH)
					{
						if(delta < match)		 /* matched */
						{
							regist_shot(enshot, *en, pow, shottype, 0);
							en->count = 1;
							/* escape */
							speed = (3*speed)/2;
							en->ws = en->s =
								4095 & (en->ws + (511 & rand()) - 255);
						}
					}
					else
					{
						regist_shot(enshot, *en, pow, shottype, shotoffset);
						en->count = 1;
					}
				}
			}

			check_and_move(enno, speed);
		}

		write_radar(en->x, -en->z, 11, -1, 0);
	}

	if(en->x < -FIELD_SIZE) en->x = -FIELD_SIZE;
	if(en->y < -FIELD_SIZE) en->y = -FIELD_SIZE;
	if(en->x >  FIELD_SIZE) en->x =  FIELD_SIZE;
	if(en->y >  FIELD_SIZE) en->y =  FIELD_SIZE;
}

int pause(void)
{
	int		d, y;
	short	buff[2];
	char	str[128];

	EGB_writePage(gwork, 0);
	EGB_color(gwork, 0, 8);
	EGB_box(  gwork, 32*6, 32*2, 32*14, 32*7);

	buff[0] = 32*10;
	buff[1] = 32*2 + 1;
	EGB_paintMode(gwork, 0x222);
	EGB_color(gwork, 2, 8);
	EGB_closePaint(gwork, (char *)buff);
	
	EGB_color(gwork, 1, 8);

	y = 0;
	while(1)
	{
		EGB_color(gwork, 0, 15);
		EGB_box(  gwork, 32*6+8, 32*(2+y)+8, 32*14-8, 32*(3+y)+8);
		
		zprint(32*7, 32*3, 15,     " ******* Replay ******* ");
		sprintf(str,               "  Game Speed : %4d0 ms ", gamewait);
		zprint(32*7, 32*4, 15, str);

		if(padmode)
			zprint(32*7, 32*5, 15, "       6B Pad only      ");
		else
			zprint(32*7, 32*5, 15, "  Standard Pad + Mouse  ");

		zprint(32*7, 32*6, 15,     " ***** Quit game ****** ");

		d = waitpad(0);

		EGB_color(gwork, 0, 8);
		EGB_box(  gwork, 32*6+8, 32*(2+y)+8, 32*14-8, 32*(3+y)+8);

		if(d & PAD_A)
		{
			break;
		}
		if(d & PAD_B)
		{
			break;
		}
		if(d & PAD_RIGHT)
		{
			if(y == 1) gamewait+=5;
			if(y == 2) padmode = !padmode;
		}
		if(d & PAD_LEFT )
		{
			if(y == 1) gamewait-=5;
			if(y == 2) padmode = !padmode;
		}
		if(d & PAD_UP  ) y--;
		if(d & PAD_DOWN) y++;
		
		if(y        <  0) y = 3;
		if(y        >  3) y = 0;
		if(gamewait <  0) gamewait = 0;
		if(reso     <  0) reso = 1;
		if(reso     >  1) reso = 0;
	}

	zprint(32*7, 32*3, 15,"                         ");
	zprint(32*7, 32*4, 15,"                         ");
	zprint(32*7, 32*5, 15,"                         ");
	zprint(32*7, 32*6, 15,"                         ");
	
	EGB_color(gwork, 1, 0);
	EGB_color(gwork, 2, 0);
	EGB_closePaint(gwork, (char *)buff);

	EGB_paintMode(gwork, 0x002);

	if(y == 3) return(1);
		else   return(0);
}

void show_fire(short z_buffer[240][256], short z_color[240][256],
				int my_s, int x, int y, int z,
				int a, int b, int c, int d, int offset, int en_count)
{
	if(en_count & 1)
		polygon(z_buffer, z_color,
				(short (*)[256])pattern_picture,
				fire1_point, fire1_surface, FIRE1_SMAX,
				fire1_nx, fire1_ny, fire1_nz,
				0, 0, 0, 0, my_s, 0,
				x, y, z, a, b, c, d, offset);
	else
		polygon(z_buffer, z_color,
				(short (*)[256])pattern_picture,
				fire2_point, fire2_surface, FIRE2_SMAX,
				fire2_nx, fire2_ny, fire2_nz,
				0, 0, 0, 0, my_s, 0,
				x, y, z, a, b, c, d, offset);
}

void show_tank(struct TANK en, struct TANK my,
			short z_buffer[240][256], short z_color[240][256], int offset)
{
	int		stat;
	int		a, b, c, r, s, t;
	int		u, v, w, x, y, z, d;
	int		wr, ws;

	if(en.type == 0) return;

	stat = en.stat;

	u = 0;
	v = 0;
	w = 0;

	r = en.r;
	s = en.s;
	t = en.t;

	wr = en.wr;
	ws = en.ws;

	x = en.x - my.x;
	y = en.y - my.y;
	z = en.z - my.z;
	if(abs(x) > 40000) return;			/* 400m */
	if(abs(y) > 40000) return;
	if(abs(z) > 40000) return;

	my.s &= 4095;
	a = 0;
	b = -my.s;
	c = 0;

	d = 0;

	if(stat == EXPLOSION)
		d = en.count * 100;
	
	if(en.type == CONTAINER)
	{
		polygon(z_buffer, z_color, (short (*)[256])pattern_picture, 
				container_point, container_surface, CONTAINER_SMAX,
				container_nx, container_ny, container_nz,
				u, v-40, w, r, s, t, x, y, z, a, b, c, d, offset);
	}
	else if(en.type == MYMBT)
	{
		polygon(z_buffer, z_color, (short (*)[256])pattern_picture, 
				MYMBT_body_point, MYMBT_body_surface, MYMBT_BODY_SMAX,
				MYMBT_body_nx, MYMBT_body_ny, MYMBT_body_nz,
				u, v+20, w, r, s, t, x, y, z, a, b, c, d, offset);

		if(stat == TOP_BLOW)
		{
			if(en.count < 10)
				d = en.count * 100;
			else
				d = -1;			/* no display */
		}
		polygon(z_buffer, z_color, (short (*)[256])pattern_picture, 
				MYMBT_gunner_point, MYMBT_gunner_surface, MYMBT_GUNNER_SMAX,
				MYMBT_gunner_nx, MYMBT_gunner_ny, MYMBT_gunner_nz,
				u, v-40, w, r, ws, t, x, y, z, a, b, c, d, offset);
		polygon(z_buffer, z_color, (short (*)[256])MBT_picture, 
				MBT_gun_point, MBT_gun_surface, MBT_GUN_SMAX,
				MBT_gun_nx, MBT_gun_ny, MBT_gun_nz,
				u, v-40, w+100, wr, ws, t, x, y, z, a, b, c, d, offset);
	}
	else if(en.type == MBT)
	{
		polygon(z_buffer, z_color, (short (*)[256])MBT_picture, 
				MBT_body_point, MBT_body_surface, MBT_BODY_SMAX,
				MBT_body_nx, MBT_body_ny, MBT_body_nz,
				u, v, w, r, s, t, x, y, z, a, b, c, d, offset);

		if(stat == TOP_BLOW)
		{
			if(en.count > 5)
				show_fire(z_buffer, z_color, my.s,
							x, y, z, a, b, c, d, offset, en.count);
			if(en.count < 10)
				d = en.count * 100;
			else
				d = -1;			/* no display */
		}
		polygon(z_buffer, z_color, (short (*)[256])MBT_picture, 
				MBT_gunner_point, MBT_gunner_surface, MBT_GUNNER_SMAX,
				MBT_gunner_nx, MBT_gunner_ny, MBT_gunner_nz,
				u, v-100, w, r, ws, t, x, y, z, a, b, c, d, offset);
		polygon(z_buffer, z_color, (short (*)[256])MBT_picture, 
				MBT_gun_point, MBT_gun_surface, MBT_GUN_SMAX,
				MBT_gun_nx, MBT_gun_ny, MBT_gun_nz,
				u, v-100, w+80, wr, ws, t, x, y, z, a, b, c, d, offset);
	}
	else if(en.type == AAT)
	{
		polygon(z_buffer, z_color, (short (*)[256])MBT_picture, 
				MBT_body_point, MBT_body_surface, MBT_BODY_SMAX,
				MBT_body_nx, MBT_body_ny, MBT_body_nz,
				u, v, w, r, s, t, x, y, z, a, b, c, d, offset);

		if(stat == TOP_BLOW)
		{
			if(en.count > 5)
				show_fire(z_buffer, z_color, my.s,
							x, y, z, a, b, c, d, offset, en.count);
			if(en.count < 10)
				d = en.count * 100;
			else
				d = -1;			/* no display */
		}
		polygon(z_buffer, z_color, (short (*)[256])MBT_picture, 
				AAT_base_point, AAT_base_surface, AAT_BASE_SMAX,
				AAT_base_nx, AAT_base_ny, AAT_base_nz,
				u, v-120, w, r, ws, t, x, y, z, a, b, c, d, offset);

		polygon(z_buffer, z_color, (short (*)[256])MBT_picture, 
				AAT_gunner_point, AAT_gunner_surface, AAT_GUNNER_SMAX,
				AAT_gunner_nx, AAT_gunner_ny, AAT_gunner_nz,
				u+60, v-120, w, wr, ws, t, x, y, z, a, b, c, d, offset);
		polygon(z_buffer, z_color, (short (*)[256])MBT_picture, 
				AAT_gunner_point, AAT_gunner_surface, AAT_GUNNER_SMAX,
				AAT_gunner_nx, AAT_gunner_ny, AAT_gunner_nz,
				u-60, v-120, w, wr, ws, t, x, y, z, a, b, c, d, offset);

		polygon(z_buffer, z_color, (short (*)[256])MBT_picture, 
				AAT_gun_point, AAT_gun_surface, AAT_GUN_SMAX,
				AAT_gun_nx, AAT_gun_ny, AAT_gun_nz,
				u+60, v-120, w, wr, ws, t, x, y, z, a, b, c, d, offset);
		polygon(z_buffer, z_color, (short (*)[256])MBT_picture, 
				AAT_gun_point, AAT_gun_surface, AAT_GUN_SMAX,
				AAT_gun_nx, AAT_gun_ny, AAT_gun_nz,
				u-60, v-120, w, wr, ws, t, x, y, z, a, b, c, d, offset);
	}
	else if(en.type == MPV)
	{
		polygon(z_buffer, z_color, (short (*)[256])MBT_picture, 
				MPV_body_point, MPV_body_surface, MPV_BODY_SMAX,
				MPV_body_nx, MPV_body_ny, MPV_body_nz,
				u, v, w, r, s, t, x, y, z, a, b, c, d, offset);

		if(stat == TOP_BLOW)
		{
			if(en.count > 5)
				show_fire(z_buffer, z_color, my.s,
							x, y, z, a, b, c, d, offset, en.count);
			if(en.count < 10)
				d = en.count * 100;
			else
				d = -1;			/* no display */
		}
		polygon(z_buffer, z_color, (short (*)[256])MBT_picture, 
				MPV_gunner_point, MPV_gunner_surface, MPV_GUNNER_SMAX,
				MPV_gunner_nx, MPV_gunner_ny, MPV_gunner_nz,
				u, v-80, w-20, r, ws, t, x, y, z, a, b, c, d, offset);
		polygon(z_buffer, z_color, (short (*)[256])MBT_picture, 
				MPV_gun_point, MPV_gun_surface, MPV_GUN_SMAX,
				MPV_gun_nx, MPV_gun_ny, MPV_gun_nz,
				u, v-80, w+20, wr, ws, t, x, y, z, a, b, c, d, offset);
	}
	else if(en.type == AH)
	{
		/*	Attack Helicopter (AH) */
		polygon(z_buffer, z_color, (short (*)[256])MBT_picture, 
				AH_body_point, AH_body_surface, AH_BODY_SMAX,
				AH_body_nx, AH_body_ny, AH_body_nz,
				u, v, w, wr, ws, t, x, y, z, a, b, c, d, offset);
		polygon(z_buffer, z_color, (short (*)[256])MBT_picture, 
				AH_pod_point, AH_pod_surface, AH_POD_SMAX,
				AH_pod_nx, AH_pod_ny, AH_pod_nz,
				u+100, v+60, w, wr, ws, t, x, y, z, a, b, c, d, offset);
		polygon(z_buffer, z_color, (short (*)[256])MBT_picture, 
				AH_pod_point, AH_pod_surface, AH_POD_SMAX,
				AH_pod_nx, AH_pod_ny, AH_pod_nz,
				u-100, v+60, w, wr, ws, t, x, y, z, a, b, c, d, offset);
		polygon(z_buffer, z_color, (short (*)[256])MBT_picture, 
				AH_pod_point, AH_pod_surface, AH_POD_SMAX,
				AH_pod_nx, AH_pod_ny, AH_pod_nz,
				u+180, v+60, w, wr, ws, t, x, y, z, a, b, c, d, offset);
		polygon(z_buffer, z_color, (short (*)[256])MBT_picture, 
				AH_pod_point, AH_pod_surface, AH_POD_SMAX,
				AH_pod_nx, AH_pod_ny, AH_pod_nz,
				u-180, v+60, w, wr, ws, t, x, y, z, a, b, c, d, offset);

		/* 落ちたヘリの回転翼が変... */
		ws = 1024;
		if(en.stat==CRASH) ws = 0;
		if((en.stat==0)||(en.stat==FALL)) ws += en.count*640;
		polygon(z_buffer, z_color, (short (*)[256])MBT_picture, 
				AH_roter_point, AH_roter_surface, AH_ROTER_SMAX,
				AH_roter_nx, AH_roter_ny, AH_roter_nz,
				u, v-120, w, 0, ws, t, x, y, z, a, b, c, d, offset);

		if((en.stat==STILL)||(en.stat==FALL))
			if(en.count > 5)
				show_fire(z_buffer, z_color, my.s,
							x, y, z, a, b, c, d, offset, en.count);
	}
	else if(en.type == WING)
	{
		/*	base bilding's wing */
		polygon(z_buffer, z_color, (short (*)[256])MBT_picture, 
				wing_point, wing_surface, WING_SMAX,
				wing_nx, wing_ny, wing_nz,
				u, v, w, r, s, t, x, y, z, a, b, c, d, offset);

		if(stat == TOP_BLOW)
		{
			if(en.count < 10)
				d = en.count * 100;
			else
				d = -1;			/* no display */
		}
		polygon(z_buffer, z_color, (short (*)[256])MBT_picture, 
				wing_gun_point, wing_gun_surface, WING_GUN_SMAX,
				wing_gun_nx, wing_gun_ny, wing_gun_nz,
				u, v-200, w, r, ws, t, x, y, z, a, b, c, d, offset);
		polygon(z_buffer, z_color, (short (*)[256])MBT_picture, 
				MBT_gun_point, MBT_gun_surface, MBT_GUN_SMAX,
				MBT_gun_nx, MBT_gun_ny, MBT_gun_nz,
				u, v-200, w+150, wr, ws, t, x, y, z, a, b, c, d, offset);
	}
	else if(en.type == BASE)
	{
		/*	base bilding's center */
		polygon(z_buffer, z_color, (short (*)[256])pattern_picture, 
				garage_point, garage_surface, GARAGE_SMAX,
				garage_nx, garage_ny, garage_nz,
				u, v, w, r, s, t, x, y, z, a, b, c, d, offset);

		if(stat == TOP_BLOW)
		{
			if(en.count < 10)
				d = en.count * 100;
			else
				d = -1;			/* no display */
		}
		polygon(z_buffer, z_color, (short (*)[256])pattern_picture, 
				base_neck_point, base_neck_surface, BASE_NECK_SMAX,
				base_neck_nx, base_neck_ny, base_neck_nz,
				u, v-350, w, r, s, t, x, y, z, a, b, c, d, offset);
		polygon(z_buffer, z_color, (short (*)[256])pattern_picture, 
				base_head_point, base_head_surface, BASE_HEAD_SMAX,
				base_head_nx, base_head_ny, base_head_nz,
				u, v-650, w, r, ws, t, x, y, z, a, b, c, d, offset);
		polygon(z_buffer, z_color, (short (*)[256])MBT_picture, 
				AAT_gun_point, AAT_gun_surface, AAT_GUN_SMAX,
				AAT_gun_nx, AAT_gun_ny, AAT_gun_nz,
				u, v-650, w+150, wr, ws, t, x, y, z, a, b, c, d, offset);
	}
}

void show_shot(struct SHOT sh, struct TANK my,
				short z_buffer[240][256], short z_color[240][256])
{
	if(sh.type == CANNON_SHOT)
		polygon(z_buffer, z_color, (short (*)[256])pattern_picture, 
				cannon_point, cannon_surface, CANNON_SMAX,
				cannon_nx, cannon_ny, cannon_nz,
				0, 0, 0, sh.r, sh.s, 0,
				sh.x-my.x, sh.y-my.y, sh.z-my.z, 0, -my.s, 0, 0, 0);
	else if(sh.type == SHOT_SHOT)
		polygon(z_buffer, z_color, (short (*)[256])pattern_picture, 
				shot_point, shot_surface, SHOT_SMAX,
				shot_nx, shot_ny, shot_nz,
				0, 0, 0, sh.r, sh.s, 0,
				sh.x-my.x, sh.y-my.y, sh.z-my.z, 0, -my.s, 0, 0, 0);
	else if(sh.type > 0)
		polygon(z_buffer, z_color, (short (*)[256])pattern_picture, 
				bombing_point, bombing_surface, BOMBING_SMAX,
				bombing_nx, bombing_ny, bombing_nz,
				0, 0, 0, 0, my.s, 0,
				sh.x-my.x, sh.y-my.y, sh.z-my.z, 0, -my.s, 0, 0, 0);
}

void show_block(int mapno, struct TANK my,
				short z_buffer[240][256], short z_color[240][256])
{
	int	a, b, c, i, j, x, y, z;

	for(i=0; i<BLOCKMAX; i++)
	{
		/* block_arrange[MAPMAX][8*BLOCKMAX] = r g b x y z xp zp */
		if(block_arrange[mapno][8*i] < 0) continue;

		/* set data */
		x = block_arrange[mapno][8*i+3];
		y = block_arrange[mapno][8*i+4];
		z = block_arrange[mapno][8*i+5];
		for(c=0; c<=1; c++)
			for(b=0; b<=1; b++)
				for(a=0; a<=1; a++)
				{
					j = 4*c + 2*b + a;
					block_point[j][0] = (1 - 2*a)*x;
					block_point[j][1] = (1 - 2*b)*y;
					block_point[j][2] = (1 - 2*c)*z;
				}

		for(j=0; j<6; j++)
		{
			block_surface[j][4] = block_arrange[mapno][8*i+0];		/* r */
			block_surface[j][5] = block_arrange[mapno][8*i+1];		/* g */
			block_surface[j][6] = block_arrange[mapno][8*i+2];		/* b */
		}

		x = block_arrange[mapno][8*i+6];
		z = block_arrange[mapno][8*i+7];
		polygon(z_buffer, z_color, (short (*)[256])pattern_picture, 
				block_point, block_surface, BLOCK_SMAX,
				block_nx, block_ny, block_nz,
				0, 0, 0, 0, 0, 0,
				x-my.x, -my.y, z-my.z, 0, -my.s, 0, 0, 0);
	}
}

void init_grap(void)
{
	EGB_init(gwork, EgbWorkSize);		/* BIOSの初期化 */

	EGB_resolution(gwork, 0, 3); 		/* ページ0の解像度(640*480,16色)  */
	EGB_resolution(gwork, 1, 5);		/* ページ1の解像度(256*240,32k色) */

	EGB_writePage(gwork, 1);
	EGB_clearScreen(gwork);

	EGB_writePage(gwork, 0);
	EGB_clearScreen(gwork);

	EGB_displayPage(gwork, 0, 3);		/* 表示ページの設定 */
}

/* センタリング･プリント(for 640x480) */
void cprint(int y, int c, char *s)
{
	zprint(320-strlen(s)*8/2, y, c, s);
}

void engine_sound(struct INDEVICE in)
{
	static int	oldinst;
	int		i, r, minno, minr, inst, tone, x, z;

	/* engine sound */
	SND_key_off(MYENGINE);
	if(my.stat == 0)
	{
		i = 4*12;
		if(in.pad & PAD_UP  ) i = 5*12;
		if(in.pad & PAD_DOWN) i = 6*12;
		if((in.pad & PAD_LEFT) || (in.pad & PAD_RIGHT)) i += 6;
		SND_inst_change(MYENGINE, 5);
		SND_pan_set(MYENGINE, 64);
		SND_key_on(MYENGINE, i, 30);
	}

	/* enemy sound */
	minno = -1;
	minr  = IN_RANGE;						/* 射程内 */
	for(i=0; i<ENMAX; i++)					/* get nearist */
	{
		if(en[i].stat == 0)
		{
			if(   en[i].type==AH 
			   || en[i].type==MPV
			   || en[i].type==MBT
			   || en[i].type==AAT )
			{
				x = en[i].x - my.x;
				z = en[i].z - my.z;

				if(abs(x)>=0x8000) continue;	/* vs. overflow */
				if(abs(z)>=0x8000) continue;

				/* 最短距離 */
				r = isqrt(x*x + z*z);
				if(r < minr)
				{
					minr  = r;
					minno = i;
				}
			}
		}
	}
	
	if(minno >= 0)
	{
		inst = -1;
		if(en[minno].type==AH ) { inst = 4; tone = 12*4+7; }
		if(en[minno].type==MPV) { inst = 6; tone = 12*5  ; }
		if(en[minno].type==MBT) { inst = 5; tone = 12*3  ; }
		if(en[minno].type==AAT) { inst = 5; tone = 12*3  ; }
		if(inst >= 0)
		{
			if(inst != oldinst)
			{
				SND_key_off(ENENGINE);
				SND_inst_change(ENENGINE, inst);
				SND_pan_set(ENENGINE, 64);
				SND_key_on(ENENGINE, tone, 90);
			}
			if(minr < 1000) minr = 1000;
			i = (127*1000)/minr;
			SND_volume_change(ENENGINE, i);
		}
		else SND_key_off(ENENGINE);

		oldinst = inst;
	}
	else SND_key_off(ENENGINE);
}

/* return 1:player lost */
int play(int mapno, struct INDEVICE record[])
{
	struct INDEVICE	in;
	struct TANK		my2;
	char	matrix[16];
	int		i, j, k, n, *p;
	int		offset;
	int		endcount = 0;
	int		record_p = 0;

	/* show screen */
//	if(demo) offset = 64; else offset = 0;
	offset = 0;
	
	init_grap();

	if(demo)
	{
		EGB_writePage(gwork, 0);
		cprint(264+24*1, 15, "-------- Main Battle Tank 'Stone Tortoise' --------");
		cprint(264+24*2, 13, "Size : 4.8X2.0X1.2m");
		cprint(264+24*3, 13, "Average Speed : 36km/h");
		cprint(264+24*4, 13, "Armor : 240mm steel (max)");
		cprint(264+24*5, 13, "Weapon : 120mm Cannon");
		cprint(264+24*6, 13, "(Shell speed : 360km/h, Effective range : 100m)");
		if(midi_mode) midi_play("ending.eup");
	}
	else
	{
		if(midi_mode) midi_play(midiname[mapno]);
	}

	EGB_writePage(gwork, 1);			/* 書き込みページを1に */
	EGB_displayStart(gwork, 0,  64, offset);
	EGB_displayStart(gwork, 2, 2<<reso, 2<<reso);
	EGB_displayStart(gwork, 3, 256, 240);

	/* variables */
	srand(1995);

	light = 32;
	if(mapstat[mapno]) light = 8;

	my.type = MYMBT;
	my.arm  = 60;
	my.shoted = 0;
	my.stat = 0;
	my.x	= 0;
//	my.x	= 6850;		// @@@
	my.y	= -60;
	my.z	= 0;
//	my.z	= 12000;	// @@@
	my.r	= 0;
	my.s	= 0;
	my.t	= 0;
	my.wr	= 0;
	my.ws	= 0;
	in.mousex = 320;
	in.mousey = (2*256)/3;

	i = 0;
	for(i=0; i<ENMAX; i++)
	{
		p = &enemy_arrange[mapno][4*i];

		en[i].type	= *p++;
		if(en[i].type == 0) continue;

		en[i].arm	= tankarm[en[i].type - MYMBT];
		en[i].shoted= 0;
		en[i].count	= 1;
		en[i].stat	= 0;
		en[i].x		= *p++;
		en[i].z		= *p++;
		en[i].y		= -60;				/* else heri, container */
		if(en[i].type == AH  ) en[i].y = -400;
		if(en[i].type == WING) en[i].y = -150;
		if(en[i].type == BASE) en[i].y = -150;

		en[i].r		=    0;
		en[i].s		= 4095 & (2048 + *p++);
		en[i].t		=    0;
		en[i].wr	=    0;
		en[i].ws	= 2048;
	}

	myshot.type = 0;
	for(i=0; i<ENSHOTMAX; i++)
	{
		enshot[i].type = 0;
	}
	
	sndplay(lets_go_snd, BASETONE);

	/* game loop */
	range_count = 0;

	while(1)
	{
		inter_count = 0;

		EGB_writePage(gwork, 0);		/* 書き込みページを0に */

		/* action */
		move_shot(&myshot, en, ENMAX, MYSOUND, 3, 24, 1);
		for(i=0; i<ENSHOTMAX; i++)
		{
			move_shot(&enshot[i], (struct TANK *)&my, 1, ENSOUND, 1, 12, 0);
		}

		if(!demo)
		{
			in.mousech = 0;
			in.pad = (short)getpad(0);

			KYB_matrix( matrix ); 			/* キ−入力 */
			if(keymatrix(0x4d)) in.pad |= PAD_UP;
			if(keymatrix(0x51)) in.pad |= PAD_RIGHT;
			if(keymatrix(0x4f)) in.pad |= PAD_LEFT;
			if(keymatrix(0x50)) in.pad |= PAD_DOWN;

			if(padmode)						/* 6B pad or keyboard */
			{
				if(in.pad & PAD_B) in.mousex +=  8;
				if(in.pad & PAD_X) in.mousex -=  8;
				if(in.pad & PAD_A) in.mousey +=  8;
				if(in.pad & PAD_Y) in.mousey -=  8;
				if(in.pad & PAD_C) in.mousech = MOUSELEFT;
				if(in.pad & PAD_Z) in.mousech = MOUSERIGHT;

				if(keymatrix(0x40)) in.mousex +=  8;
				if(keymatrix(0x3e)) in.mousex -=  8;
				if(keymatrix(0x43)) in.mousey +=  8;
				if(keymatrix(0x3b)) in.mousey -=  8;
				if(keymatrix(0x45)) in.mousech = MOUSELEFT;
				if(keymatrix(0x46)) in.mousech = MOUSERIGHT;
			}
			else
			{
				MOS_rdpos(&i, &j, &k);
				MOS_motion(&j, &k);
				in.mousech = (short)i;
				in.mousex  += j;
				in.mousey  += k;
			}

			mouse_cursor(&in.mousech, &in.mousex, &in.mousey);
			record[record_p++] = in;
		}
		else
		{
			in = record[record_p++];
		}

		if(record_p >= PADMAX-1)				/* -1 : for safe */
		{
			if(demo) return -3;
				else record_p = PADMAX-2;
		}
		my_think(&my, en, &myshot, &in);
		if(my.stat != 0 && my.count >30) return 1;		/* lost */

		engine_sound(in);
		
		/* range check */
		n = 0;
		range_check = 0;
		for(i=0; i<ENMAX; i++)
		{
			if(en[i].type)
			{
				enemy_think(i, &en[i], my);
				if(en[i].stat == 0)
				{
					n = 1;
					if(    (abs(en[i].x - my.x) < IN_RANGE)		/* 120m */
						&& (abs(en[i].y - my.y) < IN_RANGE)
						&& (abs(en[i].z - my.z) < IN_RANGE) )
						range_check = 1;
				}
			}
		}

		if(range_check)
		{
			if(range_count == 0)
				sndplay(in_range_snd, BASETONE);
			range_count = 1;
		}
		else if(range_count>0)		/* 敵が死んでから1秒数える */
		{
			range_count = -10;
		}
		else if(range_count < 0)
		{
			range_count++;
			if((range_count == 0) && !endcount)
				sndplay(go_next_snd, BASETONE);
		}
		else 
			range_count = 0;
		
		if(n == 0)
		{
			if(endcount > 30) return 0;				/* (3 sec.) win */

			if(endcount)
				endcount++;
			else
				endcount = 1;
		
			if(endcount == 5) sndplay(complete_snd, BASETONE);
		}

		if(getpad(0) == PAD_RUN)
		{
			i = pause();
			if(i) return(-1);
		}

		if(demo)
			if((getpad(0) & PAD_A)||(getpad(0) & PAD_B))
				return(-3);

		/* display */
		my2   = my;			/* transfer structure var. */
		if(demo) my2.y = -200;
			else my2.y = -120;

		clear_z_buffer(SPM z_buffer, SPM z_color,
						(short(*)[512])sky_picture, my2.s);
		ground(SPM z_buffer, SPM z_color, SPM sand_picture, land_color,
				my2.x, -my2.y/*height*/, my2.z, 0, my2.s, 0);

		if(demo)
		{
			i = 800;
			my2.x = my.x - si[my.s]/(0x4000/i);
			my2.z = my.z - co[my.s]/(0x4000/i);
			show_tank(my, my2, SPM z_buffer, SPM z_color, -offset>>reso);
		}
		else if(my.stat != 0)
		{
			i = my.count*100;
			if(i > 600) i = 600;
			if(i == 0 ) i = 1;
			my2.x = my.x - si[my.s]/(0x4000/i);
			my2.z = my.z - co[my.s]/(0x4000/i);
			show_tank(my, my2, SPM z_buffer, SPM z_color, -offset>>reso);

			if(my.count == 2) sndplay(auti_snd, BASETONE);
		}

		for(i=0; i<ENMAX; i++)
		{
			show_tank(en[i], my2, SPM z_buffer, SPM z_color, -offset>>reso);
		}

		show_shot(myshot, my2, SPM z_buffer, SPM z_color);
		for(i=0; i<ENSHOTMAX; i++)
		{
			show_shot(enshot[i], my2, SPM z_buffer, SPM z_color);
		}

		show_block(mapno, my2, SPM z_buffer, SPM z_color);

		display_z_buffer(SPM z_buffer, SPM z_color);

		/* armor */
		if(!demo)
		{
			EGB_writePage(gwork, 0);				/* 書き込みページを1に */
			zprint(88, 288-16, 15, "Armor");
			zprint(320+120, 479, 15, "Radar");

			EGB_color(gwork, 0, 9);
			EGB_box(gwork, 340, 250, 580, 470);

			EGB_color(gwork, 0, 11);
			EGB_singleLine(gwork, 80, 288, 80+my.arm*2, 288);
			EGB_color(gwork, 0, 0);
			EGB_singleLine(gwork, 80+my.arm*2, 288, 300, 288);
		}

		while(inter_count < gamewait) { }		/* default 100ms */
	}

	return -2;									/* not came hear ... */
}

void game(int firstmission)
{
	char *mission_name[] =
	{
		"作戦１  敵補給物資を破壊せよ！",
		"作戦２  敵輸送部隊を破壊せよ！",
		"作戦３  敵戦車部隊を破壊せよ！",
		"作戦４  敵ヘリコプタ−部隊を破壊せよ！",
		"作戦５  敵混成部隊を破壊せよ！",
		"作戦６　銀河作戦",
		"作戦７  敵司令部を破壊せよ！",
	};

	char *enemy_type[] =
	{
		"敵兵力　コンテナ X4",
		"敵兵力　MPV(多目的車両) X4",
		"敵兵力　MBT(主力戦車) X2  MPV(多目的車両) X2",
		"敵兵力　AH(戦闘ヘリ) X2  AAT(対空戦車) X2",
		"敵兵力　AH X2  MBT X2  AAT X2  MPV X2",
		"敵兵力　AH X1  MBT X1  AAT X1  MPV X3",
		"",
	};

	char *mission_brief[] =
	{
		"敵の基地を強襲し、燃料・弾薬を破壊せよ",
		"輸送任務中の敵の戦闘車両を破壊せよ",
		"",
		"",
		"空陸混在の主力部隊を撃破せよ",
		"敵の夜間攻撃を撃退せよ！",
		"敵の本拠地を破壊し、戦いに終止符を打て",
	};

	int	i, j;

	for(mission=firstmission; mission<MAPMAX; mission++)
	{
		if(midi_mode) SND_eup_play_stop();				/* 演奏の停止 */

		EGB_displayPage(gwork, 0, 0);					/* 表示off */
		readtiff(skyname[mission], (short *)sky_picture , 512, 128);
		init_grap();

		/* show mission */
		EGB_writePage(gwork, 1);
		EGB_clearScreen(gwork);
		EGB_writePage(gwork, 0);
		EGB_clearScreen(gwork);
		
		cprint(192, 14, mission_name[mission]);
		cprint(256, 13, enemy_type[mission]);
		cprint(320, 15, mission_brief[mission]);
		waitpad(0);

		demo = 0;
		i = play(mission, record);	/* -1:break 0:continue 1:player lost */
		for(j=ENSOUND; j<HUMANVOICE; j++) SND_key_off(j);
		if(i != 0) break;

		EGB_writePage(gwork, 1);
		EGB_clearScreen(gwork);
		EGB_writePage(gwork, 0);
		EGB_clearScreen(gwork);

		zprint(320-4*8, 256, 15, "You win !");
		waitpad(0);
	}

	EGB_writePage(gwork, 1);
	EGB_clearScreen(gwork);
	EGB_writePage(gwork, 0);
	EGB_clearScreen(gwork);

	if(mission >= MAPMAX)
	{
		cprint(256-48, 14, "★★★★  全作戦完了  ★★★★");
		cprint(256,    15, "この区域での戦争は終わり、平和が訪れた。");
		cprint(256+24, 15, "しかし、今も、世界のどこかで、");
		cprint(256+48, 15, "ＭＢＴは戦っている。");
		waitpad(0);

		demo = 1;
		play(mission = MAPMAX-1, record);
		for(j=ENSOUND; j<HUMANVOICE; j++) SND_key_off(j);

		EGB_writePage(gwork, 1);
		EGB_clearScreen(gwork);
		EGB_writePage(gwork, 0);
		EGB_clearScreen(gwork);

		zprint(320-4*8, 256, 15, "Game End");
		waitpad(0);
	}
	else if(i > 0)
	{
		zprint(320-4*8, 256, 15, "Game Over");
		waitpad(0);
	}
}

void nomem(int i)
{
	printf("error %d : メモリが不足しています。増設してください。\n", i);
	error2("");
}

void main(int argc, char *argv[])
{
	struct TANK	my, en;
	int		i, j, y;
	int		mub, mux, muy;
	int		automode;
	int		firstmission;
	char	matrix[16];
	char	buff[128];
//	char	*stackcheck;

	pr = 0;
	if(argc > 1) pr = 1;

	/* set memory */
	/* sound 175kb */
	if((lets_go_snd = calloc(20000, sizeof(char))) == NULL) nomem(1);
	if((in_range_snd= calloc(40000, sizeof(char))) == NULL) nomem(2);
	if((go_next_snd = calloc(40000, sizeof(char))) == NULL) nomem(3);
	if((hit_snd		= calloc( 5000, sizeof(char))) == NULL) nomem(4);
	if((break_snd	= calloc( 5000, sizeof(char))) == NULL) nomem(5);
	if((bingo_snd	= calloc( 5000, sizeof(char))) == NULL) nomem(6);
	if((auti_snd	= calloc(20000, sizeof(char))) == NULL) nomem(7);
	if((complete_snd= calloc(40000, sizeof(char))) == NULL) nomem(8);

	/* record 8*30,000=240,000b */
	if((record = calloc(PADMAX, sizeof(struct INDEVICE))) == NULL) nomem(9);

	/* picture 128*4 = 512kb */
	if((MBT_picture		= calloc(256*256, sizeof(short))) == NULL) nomem(10);
	if((pattern_picture	= calloc(256*256, sizeof(short))) == NULL) nomem(11);
	if((sand_picture	= calloc(256*256, sizeof(short))) == NULL) nomem(12);
	if((sky_picture		= calloc(128*512, sizeof(short))) == NULL) nomem(13);

	/* buffer 128*2 = 256kb */
	if((z_buffer	= calloc(256*256, sizeof(short))) == NULL) nomem(14);
	if((z_color		= calloc(256*256, sizeof(short))) == NULL) nomem(15);

	/* 実行時スタックのチェック */
//	if((stackcheck = calloc(500000, sizeof(char))) == NULL) nomem(16);
//	free(stackcheck);

	/* 立ち上げ表示 */
	KYB_setbuf(1);						/* no buffer */ 
	KYB_clic(1);						/* no click sound */
	KYB_lock(1);						/* encode mode only */
	init_grap();
	zprint(8*(40-15),  4*16, 14,"３Ｄ戦車戦シュ−ティングゲ−ム");
	zprint(8*(40-15),  8*16, 15,"  　「ポリゴン・タンク 2」");
	zprint(8*(40-15), 12*16, 13,"    All program, datas are");
	zprint(8*(40-15), 14*16, 13,"  developed by TabTack, 1995");

	init_polygon();

	/* load sound */
	loadsnd("LETS_GO.SND" , lets_go_snd);
	loadsnd("IN_RANGE.SND", in_range_snd);
	loadsnd("go_next.snd" , go_next_snd);
	loadsnd("HIT.SND"     , hit_snd);
	loadsnd("BREAK.SND"   , break_snd);
	loadsnd("BINGO.SND"   , bingo_snd);
	loadsnd("AUTI.SND"    , auti_snd);
	loadsnd("COMPLETE.SND", complete_snd);

	/* load texture map */
	EGB_displayPage(gwork, 0, 0);			/* 表示off */
	readtiff("mbt.tif"     , MBT_picture    , 256, 256);
	readtiff("pattern2.tif", pattern_picture, 256, 256);
	readtiff("sand.tif"    , sand_picture   , 256, 256);
	readtiff("mouse.tif", (short *)mouse_pattern, 32, 32);
	EGB_displayPage(gwork, 0, 3);			/* 表示on */

	land_color = get_average_color((short *)sand_picture, 256*256);

	/* マウス初期化 */
	MOS_start(mwork, MosWorkSize);			/* mouse動作開始の設定 */
	MOS_resolution(0, 3);					/* mouse仮想画面の設定 */
	MOS_disp(0);							/* mouseカーソル非表示 */
	
	/* サウンド初期化 */
	SND_init(sndwork);
	SND_pcm_mode_set(1);
	SND_elevol_set(1, 100, 100);			/* CDボリューム設定 */
	SND_elevol_mute(0x33);

	i = SND_pcm_bank_load("POLYTAN2.PMB", buff);
	if (i != 0) error("PMB read err\n");

	i = SND_fm_bank_load("POLYTAN2.FMB", buff);
	if (i != 0) error("FMB read err\n");

	SND_int_timer_b_set( inter_proc );

	SND_eup_init();							/* EUPHONYドライバの初期化	*/
	SND_rs_midi_init();						/* RS-MIDIドライバの初期化	*/
	midi_mode = 1;
	midi_play("title.eup");

	/* display copyright */
//	inter_count = 0;
//	while(inter_count < 100) { /* 1 sec. */ }

	/* game loop */
	y = 0;
	my.x =  0;
	my.y =-200;
	my.z =  0;
	my.r =  0;
	my.s =  0;
	my.t =  0;
	my.ws = 0;
	en.type = MYMBT;
	en.r =  0;
	en.s =	0;
	en.t =	0;
	en.x =  0;
	en.y =  0;
	en.z = 600;
	en.wr = 0;

	while(1)
	{
		init_grap();

		EGB_writePage(  gwork, 1);			/* 書き込みページを1に */
		EGB_displayStart(gwork, 0,  64,  64);
		EGB_displayStart(gwork, 2, 2<<reso, 2<<reso);
		EGB_displayStart(gwork, 3, 256, 240);
		EGB_clearScreen(gwork);

		EGB_writePage(  gwork, 0);			/* 書き込みページを0に */
		EGB_clearScreen(gwork);
		EGB_displayPage(gwork, 0, 3);		/* 表示on */

		loadtiff("title.tif", 1);

		if(reso) zprint(8*32, 32*11, 1,			"resolution 160X120");
			else zprint(8*32, 32*11, 1,			"resolution 320X240");
		if(midi_mode) zprint(8*32, 32*12, 10,	"    Music Play    ");
			else	  zprint(8*32, 32*12, 10,	"     No Music     ");
		zprint(8*32, 32*13, 15,					"   Return to OS   ");

		EGB_paintMode(gwork, 0x002);
		automode = 1;
		firstmission = 0;

		while(1)
		{
			if(firstmission)
				sprintf(buff, " Start mission %2d ", firstmission+1);
			else
				sprintf(buff, "  Start mission   ");
			zprint(8*32, 32*10, 15, buff);

			EGB_writePage(gwork, 0);		/* 書き込みページを0に */
			EGB_color(gwork, 0, 15);
			EGB_box(gwork, 8*31, 32*(y+10)-20, 8*51, 32*(y+10)+4);

			/* 離すまで待つ */
			do {
				i = getpad(0);
			} while(i != 0);

			/* 押すまで待つ */
			do {
				inter_count = 0;

				i = getpad(0);

				EGB_writePage(gwork, 0);	/* 書き込みページを0に */

				light = 32;
				if(reso) { xsize = 128; ysize =  64; }
					else { xsize = 256; ysize = 128; }

				clear_z_buffer(SPM z_buffer, SPM z_color, 0, 0);
				show_tank(en, my, SPM z_buffer,	SPM z_color, -64>>reso);
				display_z_buffer(SPM z_buffer, SPM z_color);

				if(automode)
				{
					en.s += 64;
					en.ws += 60;
					en.count ++;
				}

				KYB_matrix( matrix ); 
				if(keymatrix(0x4d))   en.r -= 64;				/* UP */
				if(keymatrix(0x51)) { en.s += 64; en.ws += 64; }/* RIGHT */
				if(keymatrix(0x4f)) { en.s -= 64; en.ws -= 64; }/* LEFT */
				if(keymatrix(0x50))   en.r += 64;				/* DOWN */
				if(keymatrix(0x6e))   en.t -= 64;				/* P.UP */
				if(keymatrix(0x70))   en.t += 64;				/* P.DOWN */
				if(keymatrix(0x6c))   en.z -= 50;				/* WordDel */
				if(keymatrix(0x4b))   en.z += 50;				/* Del */
				if(keymatrix(0x35))   automode = 1-automode;	/* space*/

				while(inter_count < 10) { }						/* 100ms */
			} while(i == 0);

			if((i & PAD_A) || (i & PAD_B)) break;

			EGB_writePage(gwork, 0);
			EGB_color(gwork, 0, 0);
			EGB_box(gwork, 8*31, 32*(y+10)-20, 8*51, 32*(y+10)+4);

			j = 0;
			MOS_rdpos(&mub, &mux, &muy);
			j = (mub & MOUSELEFT) && (mub & MOUSERIGHT);
			if((y == 0) && j && (i & PAD_LEFT )) firstmission--;
			if((y == 0) && j && (i & PAD_RIGHT)) firstmission++;
			if(firstmission <    0   ) firstmission = 0;
			if(firstmission >= MAPMAX) firstmission = MAPMAX-1;

			if(i & PAD_UP  ) y--;
			if(i & PAD_DOWN) y++;
			if(y < 0) y = 3;
			if(y > 3) y = 0;
		}
		
		if(y==0)
		{
			game(firstmission);
		}
		else if(y==1)
		{
			reso = !reso;
		}
		else if(y==2)
		{
			/* 注:前回はMIDIドライバだったが、より手軽なEUPドライバに変更 */
			/* EUPドライバ全FM音源を使用 */
			if(midi_mode == 0)
			{
				midi_mode = 1;
				midi_play("title.eup");
			}
			else
			{
				midi_mode = 0;
				midi_end();
			}
		}
		else if(y==3)
		{
			break;
			/* power off(no Marty, U?-series), care cache memory */
			/* _outp(0x22, 0x40); */
		}
		en.type++;
		if(en.type > AH) en.type = MYMBT;
	}

	/* free memory */
	free(z_color);
	free(z_buffer);

	free(sky_picture);
	free(sand_picture);
	free(pattern_picture);
	free(MBT_picture);

	free(record);

	free(complete_snd);
	free(auti_snd);
	free(bingo_snd);
	free(break_snd);
	free(hit_snd);
	free(go_next_snd);
	free(in_range_snd);
	free(lets_go_snd);

	midi_end();
	SND_rs_midi_end();						/* RS-MIDIドライバの終了	*/
	SND_eup_end();							/* EUPHONYドライバの終了	*/

	MOS_end();								/* マウスの動作終了 */
	SND_end();
	KYB_init(); 							/* buffer on */
	screenterm();
}

