/****************************************************************************/
/*	LifeGame for WonderWitch												*/
/****************************************************************************/
/*	History																	*/
/*	01.01.16	ひたすらペントミノパターンで動くテスト版(仮想画面もOK)		*/
/*	01.01.17	タイトル画面とメインメニューを追加							*/
/*	01.01.18	仮想画面をchar配列からbit配列に変更してSAVE/LOADを追加		*/
/*	01.01.22	エディットメニュー追加(ただしエディットモードは未実装)		*/
/*				画面更新の間隔をウエイトで調整するようにした				*/
/*	01.01.23	エディットモード実装、仮想画面を3×3画面から5×5画面に変更	*/
/*				ゲームオーバー判定追加、配列処理を一部ポインタ化(速度対策)	*/
/*	01.01.27	リリース準備(コメントの修正など)							*/
/****************************************************************************/
#define	TICKCOUNT	0					/* 1: 処理時間測定					*/
/****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/bios.h>
#include <sys/types.h>

#include "ww_defs.h"


/* テキストキャラクタ */
#define	C_FACE		0x02
#define	C_DOT		0x07
#define	C_MARU		0x09
#define	C_TR		0x10
#define	C_TL		0x11
#define	C_CHK		0x14
#define	C_C			0x1c
#define	C_TU		0x1e
#define	C_TD		0x1f
#define	C_SPC		0x20

/* 表示画面のサイズ */
#define	LCD_W		LCD_CHAR_WIDTH
#define	LCD_H		(LCD_CHAR_HEIGHT-1)

/* ライフゲームの盤面のサイズ(仮想画面) */
#define	MAX_W		(LCD_W * 5)
#define	MAX_H		(LCD_H * 5)

/* 動作ウエイト */
#define	TICKWAIT	16

/* データファイル名 */
#define	FILENAME	"/ram0/lifegame.scr"

/* メニュー表示位置 */
#define	MENU_X		1
#define	MENU_Y		1

/* メニュー処理初期値 */
#define	MENU_INIT	(-1)

/* ゲームモード */
enum {
	GM_MENU = MENU_INIT,
	GM_GAME = 0,
	GM_EDIT,
	GM_SAVE,
	GM_LOAD,
	GM_EXIT
};

/* エディットモード */
enum {
	ED_MENU = MENU_INIT,
	ED_EDIT = 0,
	ED_CLS,
	ED_DEMO,
	ED_RET
};

/* ステータス表示モード */
typedef enum {
	SP_LEFT = 0,
	SP_CENTER,
	SP_RIGHT
} SP_MODE;

/* ゲーム管理構造体 */
typedef struct {
	BOOL	game_f;	/* TRUE: ゲーム中	*/
	BOOL	play_f;	/* TRUE: プレイ中	*/
	int		mode;	/* ゲームモード		*/
	int		menu;	/* 選択メニューNo.	*/
	int		scrx;	/* X表示画面位置	*/
	int		scry;	/* Y表示画面位置	*/
	int		step;	/* 世代カウンタ		*/
	DWORD	tick;	/* TICKカウンタ		*/
} WORKAREA_T;


/************************************/
/*	グローバルワーク				*/
/************************************/
static BYTE scr1[(MAX_W+2+8)/8][MAX_H+2];	/* 仮想画面1(bit配列)			*/
static BYTE scr2[(MAX_W+2+8)/8][MAX_H+2];	/* 仮想画面2(bit配列)			*/
static BYTE atr[MAX_W+2][MAX_H+2];			/* 仮想画面アトリビュート		*/

static char sbuf[LCD_CHAR_WIDTH+2];			/* 文字列バッファ(ステータス用)	*/
static char buf[256];						/* 文字列バッファ(sprintf用)	*/

/* 処理時間測定用 */
#if TICKCOUNT
#define MAXTICKS 5							/* TICKログの個数				*/
static DWORD t[MAXTICKS][2];				/* TICKログ						*/
#endif


/************************************/
/*	const データ					*/
/************************************/
/* bit配列アクセス用 */
const BYTE bit[] = {
	0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01
};
const BYTE rbit[] = {
	~0x80, ~0x40, ~0x20, ~0x10, ~0x08, ~0x04, ~0x02, ~0x01
};

/* メインメニュー */
const char far *mainmenu[] = {
	"GAME",
	"EDIT",
	"SAVE",
	"LOAD",
	"EXIT",
	0
};

/* エディットメニュー */
const char far *editmenu[] = {
	"EDIT",
	"CLS ",
	"DEMO",
	"RET ",
	0
};


/************************************/
/*	仮想画面に値をセット			*/
/************************************/
#define	scrset0(x, y)		scr1[(x)>>3][y] &= rbit[(x) & 0x07]
#define	scrset1(x, y)		scr1[(x)>>3][y] |= bit[(x) & 0x07]
#define	scrset0x(ix, bx, y)	scr1[ix][y] &= rbit[bx]
#define	scrset1x(ix, bx, y)	scr1[ix][y] |= bit[bx]

/************************************/
/*	仮想画面の値をチェック			*/
/************************************/
#define	scrchk(x, y)		((scr1[(x)>>3][y] & bit[(x) & 0x07]) ? TRUE : FALSE)
#define	scrchkx(ix, bx, y)	((scr1[ix][y] & bit[bx]) ? TRUE : FALSE)

/************************************/
/*	キーが離されるまで待つ処理		*/
/************************************/
void
key_release_check(void)
{
	while(key_press_check() & KEY_ALL) {
		;
	}
}

/************************************/
/*	キーが離されるのを待つ key_wait	*/
/************************************/
void
key_wait_release(void)
{
	key_wait();
	key_release_check();
}

/************************************/
/*	表示画面をクリアする			*/
/************************************/
void
text_screen_clear(void)
{
	text_fill_char(0, 0, (LCD_W * LCD_H), C_SPC);
}

/************************************/
/*	仮想画面をクリアする			*/
/************************************/
void
init_screen(void)
{
	memset(scr1, 0, sizeof(scr1));
}

/************************************/
/*	デモ用ペントミノパターン		*/
/************************************/
void
init_lifegame_demo(void)
{
	scrset1(1+MAX_W/2  , 1+MAX_H/2  );
	scrset1(1+MAX_W/2  , 1+MAX_H/2-1);
	scrset1(1+MAX_W/2  , 1+MAX_H/2+1);
	scrset1(1+MAX_W/2+1, 1+MAX_H/2  );
	scrset1(1+MAX_W/2-1, 1+MAX_H/2-1);
}

/************************************/
/*	ワークエリア初期化				*/
/************************************/
void
init_workarea(WORKAREA_T *w)
{
	w->scrx = (MAX_W - LCD_W) / 2;	/* X表示画面位置	*/
	w->scry = (MAX_H - LCD_H) / 2;	/* Y表示画面位置	*/
	w->step = 1;					/* 世代カウンタ		*/
	w->tick = ~(0UL);				/* TICKカウンタ		*/
}

/************************************/
/*	最下行ステータス表示処理		*/
/************************************/
void
status_print(SP_MODE mode, char far *str)
{
	int len;

	len = strlen(str);
	if(len > LCD_CHAR_WIDTH) len = LCD_CHAR_WIDTH;

	memset(sbuf, C_SPC, LCD_CHAR_WIDTH);
	switch(mode) {
	default:
	case SP_LEFT:
		memcpy(sbuf, str, len);
		break;
	case SP_CENTER:
		memcpy(&sbuf[(LCD_CHAR_WIDTH - len) / 2], str, len);
		break;
	case SP_RIGHT:
		memcpy(&sbuf[LCD_CHAR_WIDTH - len], str, len);
		break;
	}
	sbuf[LCD_CHAR_WIDTH] = '\0';

	text_put_string(0, (LCD_CHAR_HEIGHT - 1), sbuf);
}

/************************************/
/*	タイトル画面処理				*/
/************************************/
void
proc_title(WORKAREA_T *w)
{
	int key;

	text_screen_clear();

	/**
	 *  タイトル表示
	 */
	text_fill_char(0, 2, LCD_CHAR_WIDTH, C_MARU);
	text_put_char(0, 3, C_MARU);
	text_put_char(LCD_CHAR_WIDTH-1, 3, C_MARU);
	sprintf(buf, "%c LifeGame for WonderWitch %c", C_MARU, C_MARU);
	text_put_string(0, 4, buf);
	text_put_char(0, 5, C_MARU);
	text_put_char(LCD_CHAR_WIDTH-1, 5, C_MARU);
	text_fill_char(0, 6, LCD_CHAR_WIDTH, C_MARU);

	text_put_string(4, 10, "Push [START] to Start");
	text_put_string(4, 12, "Push [A]/[B] to Exit");

	sprintf(buf, "Copyright %c 2001, hiro-s", C_C);
	status_print(SP_CENTER, buf);

	key_release_check();
	while(TRUE) {
		key = key_press_check();

		if(key & KEY_START) {
			w->game_f =
			w->play_f = TRUE;
			w->mode   =
			w->menu   = MENU_INIT;
			break;
		}
		else if(key & KEY_AB) {
			w->game_f =
			w->play_f = FALSE;
			break;
		}
		sys_wait(1);
	}
	key_release_check();

	text_screen_clear();
}

/************************************/
/*	メニュー表示/選択				*/
/************************************/
void
menu_select(int mx, int my, const char far *menu[], WORKAREA_T *w)
{
	int num;
	int sy;
	int cy;
	int key;

	num = 0;
	sy  = my+1;

	/**
	 *  前回選択したメニューNo.があれば使用する
	 */
	if(w->menu == MENU_INIT) {
		cy = sy;
	}
	else {
		cy = w->menu;
	}

	/* メニューウィンドウ表示 */
	text_fill_char(mx+1, my++, 5, C_TU);
	while(menu[num]) {
		sprintf(buf, "%c %s%c", C_TL, menu[num++], C_TR);
		text_put_string(mx, my++, buf);
	}
	text_fill_char(mx+1, my, 5, C_TD);

	mx++;
	my--;

	/* カーソル表示 */
	text_put_char(mx, cy, C_CHK);

	/**
	 *  メニュー選択
	 */
	key_release_check();
	while(TRUE) {
		key = key_press_check();

		/**
		 *  STARTボタン	何も選択しない(現在のモードのまま)
		 *  Bボタン		同上
		 *  Aボタン		メニュー決定
		 *  X1/X3ボタン	メニュー選択
		 */
		if(key & (KEY_START|KEY_B)) {
			break;
		}
		else if(key & KEY_A) {
			w->mode = (cy - sy);
			w->menu = cy;
			break;
		}
		else if(key & KEY_X1) {
			text_put_char(mx, cy, C_SPC);
			cy--;
			if(cy < sy) cy = my;
			text_put_char(mx, cy, C_CHK);
		}
		else if(key & KEY_X3) {
			text_put_char(mx, cy, C_SPC);
			cy++;
			if(cy > my) cy = sy;
			text_put_char(mx, cy, C_CHK);
		}

		key_release_check();
		sys_wait(1);
	}
	key_release_check();
}

/************************************/
/*	メニュー処理					*/
/************************************/
void
proc_menu(const char far *menu[], WORKAREA_T *w)
{
	menu_select(MENU_X, MENU_Y, menu, w);
}

/************************************/
/*	仮想画面の一部を画面に表示する	*/
/************************************/
/* 6tick */
void
proc_printscreen(BOOL mode, WORKAREA_T *w)
{
	register int x;
	register int y;
	register char ix;
	register char bx;

#if TICKCOUNT
	t[0][0] = sys_get_tick_count();
#else
	DWORD t;

	/**
	 *  画面更新間隔のウエイト待ち処理(一番時間がかかる処理にあわせる)
	 */
	t = sys_get_tick_count();
	if(t < w->tick) {
		t = ~(0UL) - w->tick + t;
	}
	else {
		t = t - w->tick;
	}
	if(t < TICKWAIT) {
		sys_wait(TICKWAIT - t);
	}
#endif

	/**
	 *  画面に表示する
	 */
	for(x = 0; x < LCD_W; x++) {
		bx = 1+(w->scrx + x);
		ix = bx >> 3;
		bx &= 0x07;
		for(y = 0; y < LCD_H; y++) {
			if(scrchkx(ix, bx, 1+(w->scry+y))) {
				text_put_char(x, y, C_FACE);
			}
			else {
				text_put_char(x, y, C_DOT);
			}
		}
	}

	if(mode) {
		/**
		 *  ステータス表示
		 */
		sprintf(buf, "[X:%03d Y:%03d] S:%d",
			w->scrx,
			w->scry,
			w->step
		);
		status_print(SP_LEFT, buf);
	}

#if TICKCOUNT
	t[0][1] = sys_get_tick_count();
#else
	w->tick = sys_get_tick_count();
#endif
}

/************************************/
/*	キー入力処理					*/
/************************************/
BOOL
proc_keyinput(WORKAREA_T *w)
{
	int ret;
	int key;

	/**
	 *  キー入力があれば TRUE を返す
	 */
	ret = TRUE;

	key = key_press_check();

	/**
	 *  STARTボタン		メニュー表示
	 *  Bボタン			同上
	 *  Aボタン			表示画面をセンターに戻す
	 *  X1〜X4ボタン	表示画面を移動する(1キャラ単位)
	 *  Y1〜Y4ボタン	表示画面を移動する(1画面単位)
	 */
	if(key & (KEY_START|KEY_B)) {
		w->mode = MENU_INIT;
	}
	else if(key & KEY_A) {
		w->scrx = (MAX_W - LCD_W) / 2;
		w->scry = (MAX_H - LCD_H) / 2;
	}
	else if(key & KEY_X1) {
		w->scry--;
	}
	else if(key & KEY_X2) {
		w->scrx++;
	}
	else if(key & KEY_X3) {
		w->scry++;
	}
	else if(key & KEY_X4) {
		w->scrx--;
	}
	else if(key & KEY_Y1) {
		w->scry -= LCD_H;
	}
	else if(key & KEY_Y2) {
		w->scrx += LCD_W;
	}
	else if(key & KEY_Y3) {
		w->scry += LCD_H;
	}
	else if(key & KEY_Y4) {
		w->scrx -= LCD_W;
	}
	else {
		ret = FALSE;
	}

	if(w->scrx < 0) w->scrx = 0;
	if(w->scry < 0) w->scry = 0;
	if((w->scrx + LCD_W) > MAX_W) w->scrx = (MAX_W - LCD_W);
	if((w->scry + LCD_H) > MAX_H) w->scry = (MAX_H - LCD_H);

	return ret;
}

/************************************/
/*	仮想画面アトリビュート作成処理	*/
/************************************/
/* 15tick */
void
proc_make_atr(void)
{
	register int x;
	register int y;
	register char ix;
	register char bx;

#if TICKCOUNT
	t[1][0] = sys_get_tick_count();
#endif
	memset(atr, 0, sizeof(atr));

	for(x = 1; x <= MAX_W; x++) {
		ix = (x >> 3);
		bx = (x & 0x07);
		for(y = 1; y <= MAX_H; y++) {
			if(scrchkx(ix, bx, y)) {
				atr[x-1][y-1]++;
				atr[x-1][y  ]++;
				atr[x-1][y+1]++;
				atr[x  ][y-1]++;
				atr[x  ][y+1]++;
				atr[x+1][y-1]++;
				atr[x+1][y  ]++;
				atr[x+1][y+1]++;
			}
		}
	}
#if TICKCOUNT
	t[1][1] = sys_get_tick_count();
#endif
}

/************************************/
/*	仮想画面更新処理				*/
/************************************/
/* 16tick */
BOOL
proc_next_scr(void)
{
	BOOL ret;

	int x;
	register int y;
	register char ix;
	register char bx;
	register BYTE *p;
	BYTE *q;

#if TICKCOUNT
	t[2][0] = sys_get_tick_count();
#endif
	/**
	 *  更新前の仮想画面を保存しておく
	 */
	memcpy(scr2, scr1, sizeof(scr1));

	/**
	 *  仮想画面更新
	 */
	for(x = 1; x <= MAX_W; x++) {
		ix = (x >> 3);
		bx = (x & 0x07);
		p  = (BYTE *)&atr[x][0];
		for(y = 1; y <= MAX_H; y++) {
			switch(*(p+y)) {
			case 2:
				break;
			case 3:
				scrset1x(ix, bx, y);
				break;
			default:
				scrset0x(ix, bx, y);
				break;
			}
		}
	}

	/**
	 *  仮想画面が変化したか？
	 */
	ret = FALSE;
	for(p = (BYTE *)scr1, q = (BYTE *)scr2;
		p < (BYTE *)((size_t)scr1 + sizeof(scr1)); p++, q++) {
		if(*p != *q) {
			ret = TRUE;
			break;
		}
	}

#if TICKCOUNT
	t[2][1] = sys_get_tick_count();
#endif
	return ret;
}

/************************************/
/*	仮想画面を1世代分更新する		*/
/************************************/
void
proc_lifegame(WORKAREA_T *w)
{
	BOOL gameover_f;
	register BYTE *p;

	/**
	 *  仮想画面アトリビュートを作る
	 */
	proc_make_atr();

	/**
	 *  キー入力があれば現在の仮想画面を表示する
	 */
	if(proc_keyinput(w)) {
		/**
		 *  メニュー選択であれば即終了
		 */
		if(w->mode == GM_MENU) {
			return;
		}
		proc_printscreen(TRUE, w);
	}

	gameover_f = FALSE;

	/**
	 *  仮想画面を更新する
	 */
	if(!proc_next_scr()) {
		/**
		 *  盤面に変化なし
		 */
		gameover_f = TRUE;
	}
	else {
		/**
		 *  生命体がなくなった
		 */
		gameover_f = TRUE;
		for(p = (BYTE *)scr1; p < (BYTE *)((size_t)scr1 + sizeof(scr1)); p++) {
			if(*p) {
				gameover_f = FALSE;
				break;
			}
		}
	}

	/**
	 *  ゲームオーバー/継続処理
	 */
	if(gameover_f) {
		proc_printscreen(FALSE, w);

		sprintf(buf, "S:%d Over [Push Any Key]", w->step);
		status_print(SP_RIGHT, buf);
		key_wait_release();

		init_workarea(w);
		w->mode = GM_MENU;
	}
	else {
		w->step++;
	}
}

/************************************/
/*	エディット処理					*/
/************************************/
void
proc_edit(WORKAREA_T *w)
{
	int key;
	int pre_key;
	int repeat;

	int  cx;
	int  cy;
	BOOL flg;

	cx = LCD_W / 2;
	cy = LCD_H / 2;

	/* カーソル表示 */
	cursor_set_location(cx, cy, 1, 1);
	cursor_display(TRUE);

	pre_key = key_press_check();
	repeat  = 0;
	while(TRUE) {
		key = key_press_check();
		if(key == pre_key) {
			if(repeat++ < TICKWAIT) {
				sys_wait(1);
				continue;
			}
			else {
				repeat = 0;
			}
		}
		pre_key = key;
		repeat  = 0;

		flg = FALSE;

		/**
		 *  STARTボタン		エディットメニューに戻る
		 *  Bボタン			同上
		 *  Aボタン			生命体を置く/消す
		 *  X1〜X4ボタン	カーソル移動
		 *  Y1〜Y4ボタン	表示画面を移動する(1画面単位)
		 */
		if(key & (KEY_START|KEY_B)) {
			break;
		}
		else if(key & KEY_A) {
			if(scrchk(1+(w->scrx + cx), 1+(w->scry + cy))) {
				text_put_char(cx, cy, C_DOT);
				scrset0(1+(w->scrx + cx), 1+(w->scry + cy));
			}
			else {
				text_put_char(cx, cy, C_FACE);
				scrset1(1+(w->scrx + cx), 1+(w->scry + cy));
			}
		}
		else if(key & KEY_X1) {
			cy--;
			if(cy < 0) {
				cy = 0;
				w->scry--;
				flg = TRUE;
			}
		}
		else if(key & KEY_X2) {
			cx++;
			if(cx >= LCD_W) {
				cx = (LCD_W - 1);
				w->scrx++;
				flg = TRUE;
			}
		}
		else if(key & KEY_X3) {
			cy++;
			if(cy >= LCD_H) {
				cy = (LCD_H - 1);
				w->scry++;
				flg = TRUE;
			}
		}
		else if(key & KEY_X4) {
			cx--;
			if(cx < 0) {
				cx = 0;
				w->scrx--;
				flg = TRUE;
			}
		}
		else if(key & KEY_Y1) {
			w->scry -= LCD_H;
			flg = TRUE;
		}
		else if(key & KEY_Y2) {
			w->scrx += LCD_W;
			flg = TRUE;
		}
		else if(key & KEY_Y3) {
			w->scry += LCD_H;
			flg = TRUE;
		}
		else if(key & KEY_Y4) {
			w->scrx -= LCD_W;
			flg = TRUE;
		}
		else {
			sys_wait(1);
			continue;
		}

		cursor_set_location(cx, cy, 1, 1);
		if(flg) {
			if(w->scrx < 0) w->scrx = 0;
			if(w->scry < 0) w->scry = 0;
			if((w->scrx + LCD_W) > MAX_W) w->scrx = (MAX_W - LCD_W);
			if((w->scry + LCD_H) > MAX_H) w->scry = (MAX_H - LCD_H);

			proc_printscreen(TRUE, w);
		}

		sys_wait(1);
	}
	key_release_check();

	/* カーソル消去 */
	cursor_display(FALSE);

	w->mode = ED_MENU;
}

/************************************/
/*	エディットメニュー処理			*/
/************************************/
void
proc_editmenu(WORKAREA_T *w)
{
	w->mode = 
	w->menu = MENU_INIT;

	while(w->mode != ED_RET) {
		status_print(SP_RIGHT, "[Edit Mode]");
		proc_menu(editmenu, w);

		switch(w->mode) {
		case ED_EDIT:
			proc_printscreen(TRUE, w);
			proc_edit(w);
			break;
		case ED_CLS:
			init_screen();
			init_workarea(w);
			proc_printscreen(FALSE, w);
			break;
		case ED_DEMO:
			init_screen();
			init_lifegame_demo();
			init_workarea(w);
			proc_printscreen(FALSE, w);
			break;
		case ED_RET:
			break;
		}
	}

	w->mode = 
	w->menu = MENU_INIT;
}

/************************************/
/*	仮想画面セーブ処理				*/
/************************************/
void
proc_save(WORKAREA_T *w)
{
	FILE far *fp;

	fp = fopen(FILENAME, "w");
	if(!fp) {
		status_print(SP_RIGHT, "fopen err [Push Any Key]");
	}
	else {
		fwrite(scr1, 1, sizeof(scr1), fp);
		if(ferror(fp)) {
			status_print(SP_RIGHT, "fwrite err [Push Any Key]");
		}
		else {
			status_print(SP_RIGHT, "Save OK [Push Any Key]");
		}
		fclose(fp);
	}
	key_wait_release();

	w->mode = GM_MENU;
}

/************************************/
/*	仮想画面ロード処理				*/
/************************************/
void
proc_load(WORKAREA_T *w)
{
	FILE far *fp;

	fp = fopen(FILENAME, "r");
	if(!fp) {
		status_print(SP_RIGHT, "fopen err [Push Any Key]");
	}
	else {
		/**
		 *  仮想画面/ワークエリアを初期化する
		 */
		init_screen();
		init_workarea(w);

		fread(scr1, 1, sizeof(scr1), fp);
		if(ferror(fp)) {
			status_print(SP_RIGHT, "fread err [Push Any Key]");
		}
		else {
			/**
			 *  ロードした仮想画面を表示する
			 */
			proc_printscreen(FALSE, w);
			status_print(SP_RIGHT, "Load OK [Push Any Key]");
		}
		fclose(fp);
	}
	key_wait_release();

	w->mode = GM_MENU;
}

/************************************/
/*	メイン処理						*/
/************************************/
void
main(void)
{
	static WORKAREA_T w;

#if TICKCOUNT
	int i;
	for(i = 0; i < MAXTICKS; i++) {
		t[i][0] = t[i][1] = 0;
	}
#endif

	/**
	 *  テキスト画面BIOS初期化
	 */
	text_screen_init();
	text_set_palette(0);
	cursor_display(FALSE);
	cursor_set_type(1, 0);

	palette_set_color(0, 0x7530);
	palette_set_color(1, 0x0357);

	w.game_f =
	w.play_f = TRUE;

	/**
	 *  ゲーム中
	 */
	while(w.game_f) {
		/* 仮想画面初期化 */
		init_screen();
		init_lifegame_demo();

		/* ワークエリア初期化 */
		init_workarea(&w);

		/* タイトル画面処理(ゲーム終了/開始) */
		proc_title(&w);

		if(!w.game_f) break;					/* ゲーム終了？		*/

		/**
		 *  プレイ中
		 */
		while(w.play_f) {
			switch(w.mode) {
			case GM_MENU:
				proc_printscreen(FALSE, &w);	/* 画面表示処理		*/
				status_print(SP_RIGHT, "[Main Menu]");
#if TICKCOUNT
				for(i = 0; i < MAXTICKS; i++) {
					text_put_numeric( 1, 11+i, 8, 0, t[i][0]);
					text_put_numeric(10, 11+i, 8, 0, t[i][1]);
					text_put_numeric(19, 11+i, 8, 0, t[i][1]-t[i][0]);
				}
#endif
				proc_menu(mainmenu, &w);
				break;
			case GM_GAME:
				proc_printscreen(TRUE, &w);		/* 画面表示処理		*/
				proc_lifegame(&w);				/* 仮想画面更新		*/
				proc_keyinput(&w);				/* キー入力処理		*/
				break;
			case GM_EDIT:
				proc_printscreen(FALSE, &w);	/* 画面表示処理		*/
				proc_editmenu(&w);
				break;
			case GM_SAVE:
				proc_printscreen(FALSE, &w);	/* 画面表示処理		*/
				proc_save(&w);
				break;
			case GM_LOAD:
				proc_printscreen(FALSE, &w);	/* 画面表示処理		*/
				proc_load(&w);
				break;
			case GM_EXIT:
				w.play_f = FALSE;
				break;
			}
			sys_wait(1);
		} /* プレイ中 */
	} /* ゲーム中 */
}

/****************************************************************************/
/*	Copyright (C) 2001, hiro-s@wa2.so-net.ne.jp								*/
/****************************************************************************/
