www.pudn.com > ncdzsrc.rar > simbios.c


/***************************************************************************************************** 
 
   simbios.c 
  
   BIOSシミュレーション 
 
   ※ 解析が進んでロード画面がエミュレーションで再現されるようになれば、これらは不要となります。 
 
 
   BIOSの実行は、エミュレーション中のBIOSのカーソル位置とボタンの押下情報、CD-ROMの状態チェックを 
   トリガにして各機能を実行しています。シミュレートの為、完全に実機と同じ動作をしているわけでは 
   ありませんが、ほぼ同様の動作をするように作ってあります。 
 
   BIOS実行中の判断は、M68000のアドレスレジスタ0が101480hかつ、VRAMの131(83h)番目のスプライトの情報 
   がBIOSのカーソル情報と一致するかどうかで行っています。 
 
*****************************************************************************************************/ 
 
#include "neogeocd.h" 
 
 
// CDDAの状態フラグ 
#define BIOS_CDDA_READY		-1 
#define BIOS_CDDA_STOP		0 
#define BIOS_CDDA_PLAY		1 
#define BIOS_CDDA_PAUSE		2 
 
// メッセージ番号 
#define BIOS_MESSAGE_NONE	-1 
#define BIOS_MESSAGE_NOCD	0 
#define BIOS_MESSAGE_WAIT	1 
#define BIOS_MESSAGE_NODA	2 
 
// フラグ 
#define BIOS_FLAG_PUSHSTART	(1 << 0) 
#define BIOS_FLAG_PLUS10	(1 << 1) 
#define BIOS_FLAG_LOOPPLAY	(1 << 2) 
#define BIOS_FLAG_PROGRUN	(1 << 3) 
#define BIOS_FLAG_PROGEDIT	(1 << 4) 
 
 
/*************************************************************************** 
	プロトタイプ 
 ***************************************************************************/ 
 
static int  bios_check_cdrom(void); 
static void bios_run_firsttime(void); 
static void bios_run_game(void); 
static void bios_run_cdplayer(void); 
static void bios_exit_cdplayer(void); 
 
static void bios_show_push_start_message(void); 
static void bios_set_popup_message(int no, int sec); 
static void bios_popup_message(void); 
static void bios_draw_title(void); 
static void bios_draw_cdstatus(void); 
static void bios_cdplayer(void); 
 
 
/*************************************************************************** 
	グローバル変数 
 ***************************************************************************/ 
 
int first_time_boot; 
int boot_bios; 
int next_game_index = -1; 
int bios_ret_wait; 
 
 
/*************************************************************************** 
	ローカル変数 
 ***************************************************************************/ 
 
// 状態、フラグ等 
static int bios_status; 
static int bios_message; 
static int bios_flag; 
static int bios_wait; 
 
// カウンター 
static UINT32 bios_frame_counter; 
static UINT32 bios_popup_counter; 
static UINT32 bios_program_counter; 
 
// 再生トラック、次の再生トラック 
static int current_play_track; 
static int next_play_track; 
 
// 総トラック数、時間 
static int cdda_tracks; 
static int cdda_minutes; 
static int cdda_seconds; 
 
// プログラム再生 
static int program[100]; 
static int num_program; 
static int program_pos; 
static int program_sec; 
 
// ボタン押下フラグ 
static UINT8 cur_buttons[2][10]; 
static UINT8 prv_buttons[2][10]; 
 
// タイトル画像用メモリ 
static UINT16 title_pal[0x5a0 >> 1]; 
 
 
/*************************************************************************** 
	グローバル関数 
 ***************************************************************************/ 
 
/*-------------------------------------------------------- 
 
	BIOSシミュレート初期化 
 
	引  数: なし 
	戻り値: なし 
 
 -------------------------------------------------------*/ 
 
void bios_init(void) 
{ 
	int i; 
 
	// BIOS起動フラグ 
	if (game_index >= 0) 
		boot_bios = 0; 
	else 
		boot_bios = 1; 
 
	bios_status   = BIOS_CDDA_READY; 
	bios_message  = 0; 
	bios_flag     = 0; 
	bios_wait     = 0; 
	bios_ret_wait = 0; 
 
	// カウンター 
	bios_frame_counter = 0; 
	bios_popup_counter = 0; 
	bios_program_counter = 0; 
 
	// CDプレイヤー関係 
	current_play_track = 0; 
	next_play_track = 0; 
 
	// CD情報 
	if (options.region == 0) 
		cdda_tracks  = 77;	// なぞの数字77 
	else 
		cdda_tracks  = 0; 
	cdda_minutes = 0; 
	cdda_seconds = 0; 
 
	// プログラム再生 
	program[0] = 0; 
	num_program = 0; 
	program_pos = 0; 
 
	// ボタン押下情報を初期化 
	for (i = 0; i < 10; i++) 
	{ 
		cur_buttons[0][i] = 0; 
		cur_buttons[1][i] = 0; 
		prv_buttons[0][i] = 0; 
		prv_buttons[1][i] = 0; 
	} 
} 
 
 
/*-------------------------------------------------------- 
 
	ゲームからBIOSシミュレートへの復帰 
 
	引  数: なし 
	戻り値: なし 
 
 -------------------------------------------------------*/ 
 
void bios_check_exit(void) 
{ 
	if (m68000_get_reg(M68K_A0) == 0x101480) 
	{ 
		int cx, cy, tileno, tileatr; 
 
		// カーソル情報を取得し、BIOSのデータと一致した場合はBIOSに戻る 
		neogeo_bios_get_cursor_pos(&cx, &cy, &tileno, &tileatr); 
		if (tileno == 0x1dc && tileatr == 0x3000) 
		{ 
			logerror("Return to bios.\n"); 
 
			// CPUのリセットフラグを初期化 
			cpu_reset_flag = 0; 
 
			// NEOGEOのCDDA処理を終了 
			neogeo_cdda_exit(); 
 
			// 次回起動ゲーム番号に起動していたゲーム番号を設定 
			next_game_index = game_index; 
 
			// ゲーム番号をオーディオCDにする 
			game_index = -2; 
 
			// CD-PLAYER初期化 
			bios_run_cdplayer(); 
 
			// タイトル画面の読み込みと更新 
			bios_load_title(); 
 
			// ウィンドウタイトル設定 
			neogeo_set_title(); 
 
			// 操作の受付を停止 
			bios_wait = 2 * 60; 
			bios_ret_wait = 1 * 60; 
 
			clear_screen(); 
		} 
	} 
} 
 
 
/*-------------------------------------------------------- 
 
	BIOSシミュレートの実行 
 
	引  数: なし 
	戻り値: なし 
 
 -------------------------------------------------------*/ 
 
void bios_run(void) 
{ 
	int i, button; 
	static UINT32 reg; 
	static UINT32 prev_reg = 0; 
 
	if (bios_ret_wait) 
	{ 
		bios_ret_wait--; 
		clear_screen(); 
		return; 
	} 
 
	reg = m68000_get_reg(M68K_A0);	// PCよりこちらのほうが判断しやすい 
	if (reg == 0x101480) 
	{ 
		if (first_time_boot) 
		{ 
			// 初回起動時のチェック 
			bios_run_firsttime(); 
			return; 
		} 
 
		if ((bios_status == BIOS_CDDA_PLAY) && (bios_frame_counter % (5 * 60) == 0)) 
		{ 
			if (osd_drive_is_ready(cdrom_current_drive) == OSD_ERROR) 
			{ 
				// CD-PLAYER終了 
				bios_exit_cdplayer(); 
 
				// トレイがオープンされたのでメッセージ表示 
				bios_set_popup_message(BIOS_MESSAGE_NOCD, 2 * 60); 
			} 
		} 
		else if (bios_wait) 
		{ 
			// 待ち時間中の時は何もしない 
			bios_wait--; 
		} 
		else if (bios_frame_counter % (5 * 60) == 0) 
		{ 
			int status, min_drive, max_drive; 
 
			// 5秒毎にドライブのチェック 
			min_drive = 0; 
			max_drive = MAX_DRIVE; 
 
			// すでにドライブが設定されている場合はそのdライブのみチェック 
			if (cdrom_current_drive != -1) 
			{ 
				min_drive = cdrom_current_drive; 
				max_drive = cdrom_current_drive + 1; 
			} 
			else if (options.drive != -1) 
			{ 
				min_drive = options.drive; 
				max_drive = options.drive + 1; 
			} 
 
			for (i = min_drive; i < max_drive; i++) 
			{ 
				int previous_status = cdrom_get_state(i); 
 
				if ((status = cdrom_check_state(i)) != 0) 
				{ 
					if (status & CDROM_TRAYOPEN) 
					{ 
						// CDが入っていた場合は無効に 
						if (cdrom_current_drive != -1) 
						{ 
							// CD-PLAYER終了 
							bios_exit_cdplayer(); 
						} 
 
						// トレイがオープンされたのでメッセージ表示 
						bios_set_popup_message(BIOS_MESSAGE_NOCD, 2 * 60); 
					} 
					else if (((status & CDROM_TRAYOPEN) && (~previous_status & CDROM_TRAYOPEN)) || 
							 ((status & CDROM_READY) && (previous_status & CDROM_NOTREADY))) 
					{ 
						if ((cdrom_current_drive = bios_check_cdrom()) != -1) 
						{ 
							// ゲームCDかオーディオCDが挿入された 
							if (game_index >= 0) 
							{ 
								// タイトル画面読み込み 
								bios_load_title(); 
 
								// ゲームCDはゲーム番号のみ控えてとりあえずオーディオCDに設定 
								next_game_index = game_index; 
								game_index = -2; 
							} 
 
							// CD-PLAYER初期化 
							bios_run_cdplayer(); 
 
							// しばらくお待ちくださいを表示 
							bios_set_popup_message(BIOS_MESSAGE_WAIT, 2 * 60); 
						} 
					} 
				} 
			} 
		} 
 
		if (game_index != -1) 
		{ 
			if (next_game_index >= 0) 
			{ 
				// PUSH START BUTTON 表示 
				if (bios_wait == 0) 
					bios_flag |= BIOS_FLAG_PUSHSTART; 
 
				if (cur_buttons[0][NEOGEO_INPUT_START] || cur_buttons[1][NEOGEO_INPUT_START]) 
				{ 
					// スタートボタンが押された 
					bios_run_game(); 
					return; 
				} 
			} 
 
			if (game_index == -2 && bios_wait == 0) 
			{ 
				// CDプレイヤー 
				bios_cdplayer(); 
			} 
		} 
 
		// 画面更新 
		bios_draw_title(); 
		bios_draw_cdstatus(); 
		bios_popup_message(); 
 
		// フレームカウンタ更新 
		bios_frame_counter++; 
 
		// 適当にスリープ 
		if (!bios_wait) 
			Sleep(4); 
	} 
	else 
	{ 
#if 1 
		int i; 
 
		for (i = 0; i < 10; i++) 
		{ 
			if (cur_buttons[0][i] || cur_buttons[1][i]) 
			{ 
				if (options.region == 0) 
					cdda_tracks = 7;	// なぞの数字7 
				break; 
			} 
		} 
#else 
		// 実機と同じ動作にする場合はこちらを有効に 
		int i; 
 
		if (first_time_boot) 
		{ 
			for (i = 0; i < 10; i++) 
			{ 
				if (cur_buttons[0][i] || cur_buttons[1][i]) 
				{ 
					if (options.region == 0) 
						cdda_tracks = 7;	// なぞの数字7 
					first_time_boot = 0; 
 
					// タイトル画面の読み込み 
					bios_load_title(); 
					break; 
				} 
			} 
		} 
#endif 
		if (prev_reg == 0x101480 && reg == 0x10ff1a) 
		{ 
			// バックアップメモリユーティリティ 
			osd_cdda_exit(); 
			game_index = -1; 
			next_game_index = -1; 
			cdrom_current_drive = -1; 
			bios_init(); 
			first_time_boot = 1; 
			neogeo_set_title(); 
		} 
	} 
 
	prev_reg = reg; 
 
	// ボタンの押下情報を更新 
	for (i = 0; i < 10; i++) 
	{ 
		prv_buttons[0][i] = cur_buttons[0][i]; 
		prv_buttons[1][i] = cur_buttons[1][i]; 
	} 
 
	button = neogeo_controler1_16_r(0, 0); 
	for (i = 0; i < 8; i++) 
	{ 
		cur_buttons[0][i] = ((~button) & (0x0100 << i)) != 0; 
	} 
 
	button = neogeo_controler2_16_r(0, 0); 
	for (i = 0; i < 8; i++) 
	{ 
		cur_buttons[1][i] = ((~button) & (0x0100 << i)) != 0; 
	} 
 
	button = neogeo_controler3_16_r(0, 0); 
	for (i = 0; i < 2; i++) 
	{ 
		cur_buttons[0][i + 8] = ((~button) & (0x0100 << i)) != 0; 
		cur_buttons[1][i + 8] = ((~button) & (0x0100 << (i + 2))) != 0; 
	} 
} 
 
 
/*-------------------------------------------------------- 
 
	タイトル画像のロード 
 
	引  数: なし 
	戻り値: なし 
 
 -------------------------------------------------------*/ 
 
void bios_load_title(void) 
{ 
	int i; 
	UINT8 path[MAX_PATH]; 
	UINT8 region_chr[3] = {'j','u','e'}; 
#if ENABLE_SYSTEM_CHECK 
	UINT8 *gfx = memory_region(REGION_GFX6); 
#else 
	UINT8 *gfx = memory_region(REGION_GFX2); 
#endif 
	FILE *fp = NULL; 
 
	if (next_game_index >= 0) 
	{ 
		sprintf(path, "%c:/title_%c.sys", cdrom_current_drive + 'A', region_chr[options.region & 3]); 
		fp = fopen(path, "rb"); 
	} 
 
	if (fp != NULL) 
	{ 
		fread(title_pal, 0x5a0, 1, fp); 
		fread(gfx + 0x20000, 0x1680, 1, fp); 
		fclose(fp); 
 
		swab((UINT8 *)title_pal, (UINT8 *)title_pal, 0x5a0); 
 
		for (i = 0; i < 0x5a0 >> 1; i++) 
			title_pal[i] = video_color_lut[title_pal[i]]; 
	} 
	else 
	{ 
		int j; 
		UINT8 *mem = memory_region(REGION_USER1) + 0x60000; 
		UINT8 char_map[] = { 
			0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x03, 
			0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x04, 
			0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x05, 
			0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x06, 
			0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,0x07 
		}; 
		UINT8 pal_map[] = { 
			0x2c,0x2c,0x2c,0x2c,0x2c,0x2c,0x2c,0x2c,0x2c, 
			0x2c,0x2c,0x2a,0x2a,0x2a,0x2a,0x2a,0x2c,0x2c, 
			0x2d,0x2d,0x2d,0x2b,0x2b,0x2b,0x2d,0x2d,0x2d, 
			0x2d,0x2d,0x2d,0x2b,0x2b,0x2b,0x2d,0x2d,0x2d, 
			0x2d,0x2d,0x2d,0x2b,0x2b,0x2b,0x2d,0x2d,0x2d 
		}; 
 
		for (i = 0; i < 9 * 5; i++) 
		{ 
			for (j = 0; j < 16; j++) 
			{ 
				title_pal[i * 16 + j] = video_palette[pal_map[i] * 16 + j]; 
			} 
		} 
 
		for (i = 0; i < 9 * 5; i++) 
			swab(mem + char_map[i] * 128, gfx + 0x20000 + i * 128, 128); 
	} 
 
	neogeo_decode_spr(gfx, 0x20000, 0x1680); 
 
	osd_unregister_palette(title_pal); 
	osd_register_palette(title_pal, 0x5a0 >> 1); 
} 
 
 
/*************************************************************************** 
	ローカル関数 
 ***************************************************************************/ 
 
/*-------------------------------------------------------- 
 
	BIOSのFIXを描画 
 
	引  数: inr bank      バンク 
	        UINT16 charno キャラクタ番号 
	        int x         横座標 
	        int y         縦座標 
	        int palno     パレット番号 
	戻り値: なし 
 
 -------------------------------------------------------*/ 
 
void bios_draw_fix(int bank, UINT16 charno, int x, int y, int palno) 
{ 
	charno += bank * 0x100; 
 
	if (video_fix_usage[charno]) 
	{ 
#if ENABLE_SYSTEM_CHECK 
		UINT8 *gfx = memory_region(REGION_GFX5); 
#else 
		UINT8 *gfx = memory_region(REGION_GFX1); 
#endif 
 
		neogeo_draw_fix(gfx, charno, x, y, &video_palette[palno * 16], video_fix_usage[charno] & 1); 
	} 
} 
 
 
/*-------------------------------------------------------- 
 
	BIOSのSPRを描画 
 
	引  数: UINT16 tileno タイル番号 
	        int x         横座標 
	        int y         縦座標 
	        int palno     パレット番号 
	戻り値: なし 
 
 -------------------------------------------------------*/ 
 
void bios_draw_spr(UINT16 tileno, int x, int y, int palno) 
{ 
	if (video_spr_usage[tileno]) 
	{ 
#if ENABLE_SYSTEM_CHECK 
		UINT8 *gfx = memory_region(REGION_GFX6); 
#else 
		UINT8 *gfx = memory_region(REGION_GFX2); 
#endif 
 
		neogeo_draw_gfx(gfx, tileno, x, y, &video_palette[palno * 16], video_spr_usage[tileno] & 1); 
	} 
} 
 
 
/*-------------------------------------------------------- 
 
	CDの種別を判別し、ドライブを返す 
 
	引  数: なし 
	戻り値: ドライブ番号 
 
   ※ game_indexの値も設定 
 
 -------------------------------------------------------*/ 
 
static int bios_check_cdrom(void) 
{ 
	int i, index; 
 
	if (options.drive != -1) 
	{ 
		index = cdrom_verify_disc(options.drive); 
		if (index != -1) 
		{ 
			game_index = index; 
			return options.drive; 
		} 
	} 
	else 
	{ 
		for (i = 0; i < MAX_DRIVE; i++) 
		{ 
			index = cdrom_verify_disc(i); 
			if (index != -1) 
			{ 
				game_index = index; 
				return i; 
			} 
		} 
	} 
 
	return -1; 
} 
 
 
/*-------------------------------------------------------- 
 
	CDプレイヤー画面初回起動時の動作 
 
	引  数: なし 
	戻り値: なし 
 
 -------------------------------------------------------*/ 
 
void bios_run_firsttime(void) 
{ 
	int i; 
 
	for (i = 0; i < 60; i++) 
	{ 
		clear_screen(); 
		sound_update(); 
		osd_update_video(1); 
	} 
 
	// デフォルトタイトル画像読み込み 
	bios_load_title(); 
 
	// ドライブの状態更新 
	for (i = 0; i < MAX_DRIVE; i++) 
		cdrom_check_state(i); 
 
	if ((cdrom_current_drive = bios_check_cdrom()) != -1) 
	{ 
		if (game_index >= 0) 
		{ 
			// 初回起動時はゲームをチェックして可能であれば即起動 
			bios_run_game(); 
		} 
		else 
		{ 
			// オーディオCDが見つかった場合は準備 
			game_index = -2; 
 
			// CD-PLAYER実行 
			bios_run_cdplayer(); 
 
			// しばらくお待ちくださいを表示 
			bios_set_popup_message(BIOS_MESSAGE_WAIT, 2 * 60); 
		} 
	} 
	else 
	{ 
		// CDを入れて下さい 
		bios_set_popup_message(BIOS_MESSAGE_NOCD, 2 * 60); 
	} 
 
	// 初回起動フラグをクリア 
	first_time_boot = 0; 
} 
 
 
/*-------------------------------------------------------- 
 
	BIOSからゲームを起動 
 
	引  数: なし 
	戻り値: なし 
 
 -------------------------------------------------------*/ 
 
static void bios_run_game(void) 
{ 
	int i; 
 
	osd_cdda_exit(); 
 
	for (i = 0; i < 60; i++) 
	{ 
		clear_screen(); 
		sound_update(); 
		osd_update_video(1); 
	} 
 
	if (next_game_index != -1) 
	{ 
		game_index = next_game_index; 
		next_game_index = -1; 
	} 
	bios_init(); 
	cdda_tracks = 0; 
 
	osd_set_app_state(OSD_RESTART); 
} 
 
 
/*-------------------------------------------------------- 
 
	BIOSからCDプレイヤーを起動 
 
	引  数: なし 
	戻り値: なし 
 
 -------------------------------------------------------*/ 
 
static void bios_run_cdplayer(void) 
{ 
	// BIOSシミュレーション初期化 
	bios_init(); 
 
	// CDDAを再初期化 
	osd_cdda_init(cdrom_current_drive); 
 
	// トラック情報を取得 
	cdda_tracks = osd_cdda_get_num_tracks(); 
	osd_cdda_get_totaltime(&cdda_minutes, &cdda_seconds); 
 
	// 画面を更新 
	bios_draw_cdstatus(); 
 
	// ウィンドウタイトル設定 
	neogeo_set_title(); 
} 
 
 
/*-------------------------------------------------------- 
 
	BIOSのCDプレイヤーを終了 
 
	引  数: なし 
	戻り値: なし 
 
 -------------------------------------------------------*/ 
 
static void bios_exit_cdplayer(void) 
{ 
	cdrom_current_drive = -1; 
	game_index = -1; 
	next_game_index = -1; 
 
	bios_init(); 
 
	osd_cdda_exit(); 
 
	cdda_tracks = 0; 
 
	// タイトル画面読み込み 
	bios_load_title(); 
 
	// ウィンドウタイトル設定 
	neogeo_set_title(); 
} 
 
 
/*-------------------------------------------------------- 
 
	ポップアップメッセージを設定 
 
	引  数: int no    メッセージ番号 
	        int sec   表示秒数 
	戻り値: なし 
 
 -------------------------------------------------------*/ 
 
void bios_set_popup_message(int no, int sec) 
{ 
	bios_message = no; 
	bios_popup_counter = sec; 
	bios_wait = sec; 
} 
 
 
/*-------------------------------------------------------- 
 
	メッセージを表示 
 
	引  数: なし 
	戻り値: なし 
 
 -------------------------------------------------------*/ 
 
void bios_popup_message(void) 
{ 
	int x, y, sx, sy, pal, region; 
	int window[6 * 24] = { 
		0x0e8,0x0e9,0x0ea,0x0eb,0x0ec,0x0ed,0x0ee,0x0ef,0x0f0,0x0f1,0x0f2,0x0f3,0x0f4,0x0f5,0x0f6,0x0f7,0x0f8,0x0f9,0x0fa,0x0fb,0x0fc,0x0fd,0x0fe,0x120, 
		0x121,0x122,0x123,0x124,0x125,0x126,0x127,0x128,0x13e,0x13f,0x14f,0x150,0x151,0x152,0x153,0x154,0x155,0x156,0x157,0x158,0x159,0x15a,0x15b,0x15c, 
		0x15d,0x15e,0x15f,0x161,0x162,0x163,0x164,0x165,0x170,0x171,0x172,0x173,0x174,0x175,0x176,0x177,0x178,0x179,0x17a,0x17b,0x17c,0x17d,0x17e,0x17f, 
		0x181,0x182,0x183,0x184,0x185,0x190,0x191,0x192,0x193,0x194,0x195,0x196,0x197,0x198,0x199,0x19a,0x19b,0x19c,0x19d,0x19e,0x19f,0x1a0,0x1a1,0x1a2, 
		0x1a3,0x1a4,0x1a5,0x1a6,0x1a7,0x1a8,0x1a9,0x1aa,0x1ab,0x1ac,0x1ad,0x1ae,0x1af,0x1b0,0x1b1,0x1b2,0x1b3,0x1b4,0x1b5,0x1b6,0x1b7,0x1b8,0x1b9,0x1ba, 
		0x1bb,0x1bc,0x1bd,0x1be,0x1bf,0x1c0,0x1c1,0x1c2,0x1c3,0x1c4,0x1c5,0x1c6,0x1c7,0x1c8,0x1c9,0x1ca,0x1cb,0x1cc,0x1cd,0x1ce,0x1cf,0x1d0,0x1d1,0x1d2 
	}; 
	int mes[3][2][4 * 22] = { 
		{ 
		    { 
		    	0x122,0x123,0x124,0x125,0x126,0x127,0x128,0x13e,0x13f,0x14f,0x150,0x151,0x152,0x153,0x154,0x155,0x156,0x157,0x158,0x159,0x15a,0x15b, 
				0x034,0x035,0x036,0x037,0x038,0x039,0x03a,0x03b,0x03c,0x03d,0x03e,0x03f,0x020,0x021,0x060,0x061,0x02e,0x02f,0x030,0x031,0x032,0x033, 
				0x054,0x055,0x056,0x057,0x058,0x059,0x05a,0x05b,0x05c,0x05d,0x05e,0x05f,0x040,0x041,0x080,0x081,0x04e,0x04f,0x050,0x051,0x052,0x053, 
		    	0x1a4,0x1a5,0x1a6,0x1a7,0x1a8,0x1a9,0x1aa,0x1ab,0x1ac,0x1ad,0x1ae,0x1af,0x1b0,0x1b1,0x1b2,0x1b3,0x1b4,0x1b5,0x1b6,0x1b7,0x1b8,0x1b9 
		    }, 
		    { 
		    	0x122,0x123,0x124,0x125,0x126,0x127,0x128,0x13e,0x13f,0x14f,0x150,0x151,0x152,0x153,0x154,0x155,0x156,0x157,0x158,0x159,0x15a,0x15b, 
				0x15e,0x15f,0x161,0x162,0x163,0x164,0x165,0x0ac,0x0b4,0x0b5,0x0b3,0x0b1,0x0ad,0x0ae,0x0b6,0x0b7,0x179,0x17a,0x17b,0x17c,0x17d,0x17e, 
				0x182,0x183,0x184,0x185,0x190,0x191,0x192,0x0cc,0x0d4,0x0d5,0x0d3,0x0d1,0x0cd,0x0ce,0x0d6,0x0d7,0x19c,0x19d,0x19e,0x19f,0x1a0,0x1a1, 
		    	0x1a4,0x1a5,0x1a6,0x1a7,0x1a8,0x1a9,0x1aa,0x1ab,0x1ac,0x1ad,0x1ae,0x1af,0x1b0,0x1b1,0x1b2,0x1b3,0x1b4,0x1b5,0x1b6,0x1b7,0x1b8,0x1b9 
		    }, 
		}, 
		{ 
		    { 
		    	0x122,0x123,0x124,0x125,0x126,0x127,0x128,0x13e,0x13f,0x14f,0x150,0x151,0x152,0x153,0x154,0x155,0x156,0x157,0x158,0x159,0x15a,0x15b, 
				0x15e,0x020,0x021,0x022,0x023,0x024,0x025,0x026,0x027,0x028,0x029,0x02a,0x02b,0x02c,0x02d,0x02e,0x02f,0x030,0x031,0x032,0x033,0x17e, 
				0x182,0x040,0x041,0x042,0x043,0x044,0x045,0x046,0x047,0x048,0x049,0x04a,0x04b,0x04c,0x04d,0x04e,0x04f,0x050,0x051,0x052,0x053,0x1a1, 
		    	0x1a4,0x1a5,0x1a6,0x1a7,0x1a8,0x1a9,0x1aa,0x1ab,0x1ac,0x1ad,0x1ae,0x1af,0x1b0,0x1b1,0x1b2,0x1b3,0x1b4,0x1b5,0x1b6,0x1b7,0x1b8,0x1b9 
		    }, 
		    { 
		    	0x122,0x123,0x124,0x125,0x126,0x127,0x128,0x13e,0x13f,0x14f,0x150,0x151,0x152,0x153,0x154,0x155,0x156,0x157,0x158,0x159,0x15a,0x15b, 
				0x15e,0x15f,0x0aa,0x0ab,0x0ac,0x0ad,0x0ae,0x0af,0x0b0,0x0b1,0x0ae,0x0ab,0x0ae,0x0b2,0x0b0,0x0b2,0x0b3,0x0b4,0x0ad,0x17c,0x17d,0x17e, 
				0x182,0x183,0x0ca,0x0cb,0x0cc,0x0cd,0x0ce,0x0cf,0x0d0,0x0d1,0x0ce,0x0cb,0x0ce,0x0d2,0x0d0,0x0d2,0x0d3,0x0d4,0x0cd,0x19f,0x1a0,0x1a1, 
		    	0x1a4,0x1a5,0x1a6,0x1a7,0x1a8,0x1a9,0x1aa,0x1ab,0x1ac,0x1ad,0x1ae,0x1af,0x1b0,0x1b1,0x1b2,0x1b3,0x1b4,0x1b5,0x1b6,0x1b7,0x1b8,0x1b9 
		    }, 
		}, 
		{ 
			{ 
				0x062,0x063,0x062,0x063,0x064,0x065,0x066,0x067,0x068,0x069,0x06a,0x06b,0x06c,0x06d,0x06e,0x06f,0x070,0x071,0x072,0x073,0x074,0x075, 
				0x082,0x083,0x082,0x083,0x084,0x085,0x086,0x087,0x088,0x089,0x08a,0x08b,0x08c,0x08d,0x08e,0x08f,0x090,0x091,0x092,0x093,0x094,0x095, 
				0x182,0x183,0x184,0x185,0x076,0x077,0x078,0x079,0x060,0x061,0x032,0x033,0x07a,0x07b,0x07c,0x07d,0x07e,0x07f,0x19e,0x19f,0x1a0,0x1a1, 
				0x1a4,0x1a5,0x1a6,0x1a7,0x096,0x097,0x098,0x099,0x080,0x081,0x052,0x053,0x09a,0x09b,0x09c,0x09d,0x09e,0x09f,0x1b6,0x1b7,0x1b8,0x1b9 
			}, 
			{ 
				0x122,0x123,0x124,0x125,0x0b8,0x0b1,0x0b0,0x0b9,0x0b1,0x0ab,0x0b2,0x0ae,0x0ab,0x0b1,0x0b3,0x0ab,0x0ae,0x0ba,0x158,0x159,0x15a,0x15b, 
				0x15e,0x15f,0x161,0x162,0x0d8,0x0d1,0x0d0,0x0d9,0x0d1,0x0cb,0x0d2,0x0ce,0x0cb,0x0d1,0x0d3,0x0cb,0x0ce,0x0da,0x17b,0x17c,0x17d,0x17e, 
				0x182,0x0b5,0x0b3,0x0bb,0x0b3,0x0b6,0x0ad,0x0ae,0x0bc,0x0ab,0x0bd,0x0b7,0x0ac,0x0b0,0x0ae,0x0ad,0x0b1,0x0ab,0x0b6,0x0be,0x0bc,0x1a1, 
				0x1a4,0x0d5,0x0d3,0x0db,0x0d3,0x0d6,0x0cd,0x0ce,0x0dc,0x0cb,0x0dd,0x0d7,0x0cc,0x0d0,0x0ce,0x0cd,0x0d1,0x0cb,0x0d6,0x0de,0x0dc,0x1b9 
			}, 
		} 
	}; 
 
	if (bios_flag & BIOS_FLAG_PUSHSTART) 
	{ 
		if ((bios_frame_counter % 60) < 40) 
		{ 
			const char *push_start = "PUSH START BUTTON"; 
 
			// なぜかFIXなのに8ドットで割り切れる位置でない 
			for (x = 0; x < 17; x++) 
				bios_draw_fix(3, push_start[x], (18 + x) * 8, 27 * 8 + 4, 2); 
		} 
	} 
 
	if (bios_popup_counter == 0) 
		return; 
 
	// カウンタを減らす 
	bios_popup_counter--; 
	if (bios_popup_counter == 0) 
	{ 
		if (bios_message == BIOS_MESSAGE_WAIT) 
		{ 
			// しばらくお待ちください野表示が終わったら、タイトル画面更新 
			bios_load_title(); 
			bios_draw_title(); 
		} 
		bios_message = BIOS_MESSAGE_NONE; 
		return; 
	} 
 
	// パレット 
	if (bios_message == 2) 
		pal = 1; 
	else 
		pal = 0; 
 
	// 枠表示 
	sx = ((320/8) - 24) / 2; 
	sy = ((224/8) - 6) / 2 - 1; 
	for (y = 0; y < 6; y++) 
	{ 
		for (x = 0; x < 24; x++) 
		{ 
			bios_draw_fix(5, window[y * 24 + x], (sx + x) * 8, (sy + y) * 8, pal); 
		} 
	} 
 
	// メッセージ表示 
	sx++; 
	sy++; 
	region = (options.region != 0); 
	for (y = 0; y < 4; y++) 
	{ 
		for (x = 0; x < 22; x++) 
		{ 
			bios_draw_fix(5, mes[bios_message][region][y * 22 + x], (sx + x) * 8, (sy + y) * 8, pal); 
		} 
	} 
} 
 
 
/*-------------------------------------------------------- 
 
	タイトル画像の表示 
 
	引  数: なし 
	戻り値: なし 
 
 -------------------------------------------------------*/ 
 
void bios_draw_title(void) 
{ 
	int x, y, r, g, b, tileno; 
	UINT16 backup[24][48]; 
#if ENABLE_SYSTEM_CHECK 
	UINT8 *gfx = memory_region(REGION_GFX6); 
#else 
	UINT8 *gfx = memory_region(REGION_GFX2); 
#endif 
 
	tileno = 0; 
 
	ui_get_pixel_color(183+8, 122+16, &r, &g, &b); 
	if (r == g && r == b) 
	{ 
		for (y = 0; y < 24; y++) 
			for (x = 0; x < 48; x++) 
				backup[y][x] = scrbitmap.line[136 + y][136 + x]; 
	} 
 
	for (y = 0; y < 5; y++) 
	{ 
		for (x = 0; x < 9; x++) 
		{ 
			neogeo_draw_gfx(gfx + 0x20000, tileno, 40 + x * 16, 80 + y * 16, &title_pal[tileno * 16], 1); 
			tileno++; 
		} 
	} 
 
	if (r == g && r == b) 
	{ 
		for (y = 0; y < 24; y++) 
			for (x = 0; x < 48; x++) 
				scrbitmap.line[136 + y][136 + x] = backup[y][x]; 
	} 
} 
 
 
/*-------------------------------------------------------- 
 
	画面を指定された色で四角形に塗りつぶす 
 
	引  数: int sx  左上隅横座標 
	        int sy  左上隅縦座標 
	        int w   塗りつぶす幅 
	        int w   塗りつぶす高さ 
	        int r   塗りつぶす色の赤輝度 
	        int g   塗りつぶす色の緑輝度 
	        int v   塗りつぶす色の青輝度 
	戻り値: なし 
 
 -------------------------------------------------------*/ 
 
void bios_fill_box(int sx, int sy, int w, int h, int r, int g, int b) 
{ 
	UINT16 color = osd_make_pen(r, g, b); 
	int x, y; 
 
	for (y = 0; y < h; y++) 
		for (x = 0; x < w; x++) 
			scrbitmap.line[sy + y][sx + x] = color; 
} 
 
 
/*-------------------------------------------------------- 
 
	CDプレイヤーの画面を更新 
 
	引  数: なし 
	戻り値: なし 
 
 -------------------------------------------------------*/ 
 
void bios_draw_cdstatus(void) 
{ 
	int cx, cy, tileno, tileatr, status; 
	int program_is_open, program_not_flash; 
 
	// トラックの情報を更新 
	if (bios_status == BIOS_CDDA_PLAY) 
	{ 
		status = osd_cdda_get_status(); 
		if (status == CDDA_PLAY || status == CDDA_PAUSE) 
		{ 
			int current_track = osd_cdda_get_current_track(); 
 
			if (current_track != current_play_track) 
				current_play_track = current_track; 
		} 
		else if (status == CDDA_STOP) 
		{ 
			bios_status = BIOS_CDDA_STOP; 
			current_play_track = 0; 
		} 
	} 
 
	// 画面の色でナンバーキーの状態をチェック 
	program_not_flash = scrbitmap.line[139][212] == 0; 
	program_is_open   = scrbitmap.line[138][191] == 0; 
 
	if (bios_flag & BIOS_FLAG_LOOPPLAY) 
	{ 
		// 再生ボタンのループマーク 
		bios_draw_spr(0x0fb, 240, 72, 16); 
		bios_draw_spr(0x0fc, 256, 72, 16); 
	} 
 
	if (program_is_open) 
	{ 
		// プログラムボタン点灯 
		if (bios_flag & BIOS_FLAG_PROGRUN) 
		{ 
			bios_draw_spr(0x130, 140, 138, 0x39); 
			bios_draw_spr(0x131, 156, 138, 0x39); 
			bios_draw_spr(0x1d4, 172, 138, 0x39); 
			bios_draw_spr(0x1d5, 188, 138, 0x39); 
		} 
	} 
 
	if (program_not_flash) 
	{ 
		// 表示されている数字を必要に応じて消す 
		if (bios_status != BIOS_CDDA_STOP || (bios_status == BIOS_CDDA_STOP && (bios_flag & BIOS_FLAG_PROGEDIT))) 
		{ 
			if (bios_flag & BIOS_FLAG_PROGRUN) 
			{ 
				// プログラム中/プログラム実行中 
				bios_fill_box(259, 171, 15,  2, 0, 0, 0); 
			} 
			bios_fill_box(218, 165, 19, 14, 0, 0, 0); 
			bios_fill_box(238, 197, 43, 14, 0, 0, 0); 
		} 
 
		if (bios_status == BIOS_CDDA_READY) 
		{ 
			// 起動直後 
 
			// トラック数表示 
			bios_draw_spr(0x11f + cdda_tracks / 10, 218, 165, 25); 
			bios_draw_spr(0x11f + cdda_tracks % 10, 228, 165, 25); 
 
			// 総プレイ時間表示 
			bios_draw_spr(0x11f + cdda_minutes / 10, 238, 197, 25); 
			bios_draw_spr(0x11f + cdda_minutes % 10, 248, 197, 25); 
			bios_draw_spr(0x12a,                     252, 197, 25); 
			bios_draw_spr(0x11f + cdda_seconds / 10, 262, 197, 25); 
			bios_draw_spr(0x11f + cdda_seconds % 10, 272, 197, 25); 
		} 
		else if (bios_status == BIOS_CDDA_STOP) 
		{ 
			// 停止中 
 
			if (bios_flag & BIOS_FLAG_PROGEDIT) 
			{ 
				int play_time_temp = program_sec; 
 
				// プログラム中 
				bios_fill_box(218, 165, 19, 14, 0, 0, 0); 
				bios_fill_box(238, 197, 43, 14, 0, 0, 0); 
				bios_fill_box(259, 171, 15,  2, 0, 0, 0); 
 
				if (bios_program_counter) 
				{ 
					bios_draw_spr(0x11f + program[num_program + 1] / 10, 218, 165, 25); 
					bios_draw_spr(0x11f + program[num_program + 1] % 10, 228, 165, 25); 
					bios_draw_spr(0x11f + num_program / 10, 257, 165, 25); 
					bios_draw_spr(0x11f + num_program % 10, 267, 165, 25); 
					bios_program_counter--; 
				} 
				else if ((bios_frame_counter % 15) < 10) 
				{ 
					if (~bios_flag & BIOS_FLAG_PLUS10) 
					{ 
						// +10入力中以外 
						bios_draw_spr(0x11f + 0, 218, 165, 25); 
						bios_draw_spr(0x11f + 1, 228, 165, 25); 
					} 
					bios_draw_spr(0x11f + num_program / 10, 257, 165, 25); 
					bios_draw_spr(0x11f + num_program % 10, 267, 165, 25); 
				} 
 
				if (play_time_temp > 99 * 60 + 59) 
					play_time_temp = 99 * 60 + 59; 
 
				// 総プレイ時間表示 
				bios_draw_spr(0x11f + (play_time_temp / 60) / 10, 238, 197, 25); 
				bios_draw_spr(0x11f + (play_time_temp / 60) % 10, 248, 197, 25); 
				bios_draw_spr(0x11f + (play_time_temp % 60) / 10, 262, 197, 25); 
				bios_draw_spr(0x11f + (play_time_temp % 60) % 10, 272, 197, 25); 
				bios_draw_spr(0x12a, 252, 197, 25); 
			} 
		} 
		else 
		{ 
			int m, s; 
 
			// 再生/ポーズ中 
 
			if (~bios_flag & BIOS_FLAG_PLUS10) 
			{ 
				// +10入力中以外 
				bios_draw_spr(0x11f + current_play_track / 10, 218, 165, 25); 
				bios_draw_spr(0x11f + current_play_track % 10, 228, 165, 25); 
			} 
 
			if (bios_flag & BIOS_FLAG_PROGRUN) 
			{ 
				int program_no = osd_cdda_get_current_program(); 
 
				// プログラム番号 
				bios_draw_spr(0x11f + program_no / 10, 259, 165, 25); 
				bios_draw_spr(0x11f + program_no % 10, 269, 165, 25); 
			} 
 
			// プレイ時間表示 
			osd_cdda_get_play_time(&m, &s); 
			bios_draw_spr(0x11f + m / 10, 238, 197, 25); 
			bios_draw_spr(0x11f + m % 10, 248, 197, 25); 
			bios_draw_spr(0x11f + s / 10, 262, 197, 25); 
			bios_draw_spr(0x11f + s % 10, 272, 197, 25); 
			bios_draw_spr(0x12a, 252, 197, 25); 
 
			// 再生マーク 
			bios_draw_spr(0x12b, 220, 180, 1); 
 
			// ポーズマーク 
			if (bios_status == BIOS_CDDA_PAUSE) 
				bios_draw_spr(0x12c, 259, 180, 1); 
 
			// 各ボタンの点滅 
			if ((bios_frame_counter % 8) < 4) 
			{ 
				if (bios_status == BIOS_CDDA_PLAY) 
				{ 
					if (bios_flag & BIOS_FLAG_LOOPPLAY) 
					{ 
						// 再生ボタンループマーク付き 
						bios_draw_spr(0x0fb, 240, 72, 53); 
						bios_draw_spr(0x0fc, 256, 72, 53); 
					} 
					else 
					{ 
						// 再生ボタンループマークなし 
						bios_draw_spr(0x0f6, 240, 72, 53); 
					} 
				} 
				else if (bios_status == BIOS_CDDA_PAUSE) 
				{ 
					// ポーズボタン 
					bios_draw_spr(0x102, 254, 88, 54); 
					bios_draw_spr(0x103, 270, 88, 54); 
				} 
			} 
			else if (program_is_open) 
			{ 
				// プログラムボタン点灯消去 
				if (bios_flag & BIOS_FLAG_PROGRUN) 
				{ 
					bios_draw_spr(0x130, 140, 138, 22); 
					bios_draw_spr(0x131, 156, 138, 22); 
					bios_draw_spr(0x1d4, 172, 138, 22); 
					bios_draw_spr(0x1d5, 188, 138, 22); 
				} 
			} 
		} 
 
		// ループマーク 
		if (bios_flag & BIOS_FLAG_LOOPPLAY) 
			bios_draw_spr(0x1db, 232, 180, 1); 
 
		if (bios_flag & BIOS_FLAG_PLUS10) 
		{ 
			bios_fill_box(218, 165, 19, 14, 0, 0, 0); 
 
			if (bios_frame_counter % 15 < 10) 
			{ 
				// 再生/停止/ポーズ中 1- 表示 
				bios_draw_spr(0x11f + next_play_track / 10, 218, 165, 25); 
				bios_draw_spr(0x129, 228, 165, 25); 
			} 
		} 
	} 
 
	// カーソル 
	neogeo_bios_get_cursor_pos(&cx, &cy, &tileno, &tileatr); 
	bios_draw_spr(0x1dc, cx, cy, 3); 
} 
 
 
/*-------------------------------------------------------- 
 
	CDプレイヤーの実行 
 
	引  数: なし 
	戻り値: なし 
 
 -------------------------------------------------------*/ 
 
void bios_cdplayer(void) 
{ 
	int cx, cy, tileno, tileatr; 
	int play_start = 0; 
	int add_program = 0; 
 
	neogeo_bios_get_cursor_pos(&cx, &cy, &tileno, &tileatr); 
 
	if (cur_buttons[0][NEOGEO_INPUT_BUTTONA] || cur_buttons[1][NEOGEO_INPUT_BUTTONA]) 
	{ 
		if (bios_status == BIOS_CDDA_PLAY && (~bios_flag & BIOS_FLAG_PROGRUN)) 
		{ 
			if (bios_frame_counter % 10 == 0) 
			{ 
				if (cx == 227 && cy == 132) 
				{ 
					// 巻き戻し 
					osd_cdda_play_rewind(4); 
				} 
				else if (cx == 267 && cy == 132) 
				{ 
					// 早送り 
					osd_cdda_play_foward(4); 
				} 
			} 
		} 
	} 
 
	if ((prv_buttons[0][NEOGEO_INPUT_BUTTONA] == 0 && cur_buttons[0][NEOGEO_INPUT_BUTTONA]) 
	||  (prv_buttons[1][NEOGEO_INPUT_BUTTONA] == 0 && cur_buttons[1][NEOGEO_INPUT_BUTTONA])) 
	{ 
		if (cx == 243 && cy == 84) 
		{ 
			// 再生 
			if (bios_status == BIOS_CDDA_PLAY) 
			{ 
				bios_flag ^= BIOS_FLAG_LOOPPLAY; 
 
				if (bios_flag & BIOS_FLAG_PROGRUN) 
				{ 
					// オートループが有効なのはプログラム再生のみ 
					osd_cdda_set_autoloop((bios_flag & BIOS_FLAG_LOOPPLAY) != 0); 
				} 
				else 
				{ 
					osd_cdda_set_autoloop(0); 
				} 
			} 
			else if (bios_status == BIOS_CDDA_STOP || bios_status == BIOS_CDDA_READY) 
			{ 
				if (current_play_track == 0) 
				{ 
					if (osd_cdda_get_track_type(1) == 1) 
						next_play_track = 1; 
					else 
						next_play_track = 2; 
				} 
				play_start = 2; 
				bios_flag &= ~BIOS_FLAG_PROGEDIT; 
			} 
		} 
		else if (cx == 227 && cy == 100) 
		{ 
			// 停止 
			if (bios_status == BIOS_CDDA_PLAY || bios_status == BIOS_CDDA_PAUSE) 
			{ 
				osd_cdda_stop(); 
				bios_status = BIOS_CDDA_STOP; 
				current_play_track = 0; 
			} 
		} 
		else if (cx == 267 && cy == 100) 
		{ 
			// 一時停止 
			if (bios_status == BIOS_CDDA_PLAY) 
			{ 
				osd_cdda_pause(); 
				bios_status = BIOS_CDDA_PAUSE; 
			} 
			else if (bios_status == BIOS_CDDA_PAUSE) 
			{ 
				osd_cdda_resume(); 
				bios_status = BIOS_CDDA_PLAY; 
			} 
		} 
		else if (cx == 227 && cy == 116) 
		{ 
			// 前の曲 
			if (bios_status == BIOS_CDDA_PLAY) 
				osd_cdda_play_prev_track(); 
		} 
		else if (cx == 267 && cy == 116) 
		{ 
			// 次の曲 
			if (bios_status == BIOS_CDDA_PLAY) 
				osd_cdda_play_next_track(); 
		} 
		else if (cx == 171 && cy == 150) 
		{ 
			// プログラム 
			if (bios_status == BIOS_CDDA_READY) 
				bios_status = BIOS_CDDA_STOP; 
 
			if (bios_status == BIOS_CDDA_STOP) 
			{ 
				if (~bios_flag & BIOS_FLAG_PROGRUN) 
				{ 
					// プログラム編集開始 
					bios_flag |= BIOS_FLAG_PROGRUN; 
					bios_flag |= BIOS_FLAG_PROGEDIT; 
					program[1] = 0; 
					num_program = 0; 
					program_sec = 0; 
				} 
				else 
				{ 
					// プログラム終了 
					bios_flag &= ~BIOS_FLAG_PROGRUN; 
					bios_flag &= ~BIOS_FLAG_PROGEDIT; 
					program[1] = 0; 
					num_program = 0; 
				} 
			} 
			else if (bios_status == BIOS_CDDA_PLAY) 
			{ 
				if (bios_flag & BIOS_FLAG_PROGRUN) 
				{ 
					// プログラムキャンセル 
					bios_flag &= ~BIOS_FLAG_PROGRUN; 
					bios_flag &= ~BIOS_FLAG_PROGEDIT; 
					program[1] = 0; 
					num_program = 0; 
					osd_cdda_chancel_program(); 
				} 
			} 
		} 
		else if (((cx >= 149 && cx <= 197) && (cy >= 163 && cy <= 185)) || (cx == 149 && cy == 196)) 
		{ 
			int number = ((cx - 149) / 24) + ((cy - 163) / 11) * 3 + 1; 
 
			if (number == 10) number = 0; 
 
			// 0 - 9 
			if (next_play_track + number != 0) 
			{ 
				if (bios_status == BIOS_CDDA_READY) 
					bios_status = BIOS_CDDA_STOP; 
 
				if ((~bios_flag & BIOS_FLAG_PROGRUN) || ((bios_flag & BIOS_FLAG_PROGRUN) && bios_status == BIOS_CDDA_STOP)) 
				{ 
					if (next_play_track + number <= osd_cdda_get_num_tracks()) 
					{ 
						if (osd_cdda_get_track_type(next_play_track + number) == 0) 
						{ 
							// データトラックは無視する 
							next_play_track = 0; 
							bios_flag &= ~BIOS_FLAG_PLUS10; 
							bios_set_popup_message(BIOS_MESSAGE_NODA, 15); 
						} 
						else 
						{ 
							// 普通に再生中か、プログラム中 
							next_play_track += number; 
							if (bios_flag & BIOS_FLAG_PROGRUN) 
								add_program = 1; 
							else 
								play_start = 1; 
						} 
					} 
				} 
				else 
				{ 
					// プログラム再生中はプログラムナンバーの指定 
					if (next_play_track + number >= num_program) 
					 	next_play_track = num_program; 
					else 
						next_play_track += number; 
					play_start = 1; 
				} 
			} 
		} 
		else if (cx == 185 && cy == 196) 
		{ 
			// +10 
			if ((~bios_flag & BIOS_FLAG_PROGRUN) || ((bios_flag & BIOS_FLAG_PROGRUN) && bios_status == BIOS_CDDA_STOP)) 
			{ 
				if (next_play_track + 10 <= osd_cdda_get_num_tracks()) 
				{ 
					next_play_track += 10; 
					bios_flag |= BIOS_FLAG_PLUS10; 
					if (bios_status == BIOS_CDDA_READY) 
						bios_status = BIOS_CDDA_STOP; 
				} 
			} 
			else 
			{ 
				if (next_play_track + 10 <= num_program) 
				{ 
					next_play_track += 10; 
					bios_flag |= BIOS_FLAG_PLUS10; 
					if (bios_status == BIOS_CDDA_READY) 
						bios_status = BIOS_CDDA_STOP; 
				} 
			} 
		} 
		else if (cx == 171 && cy == 209) 
		{ 
			// キャンセル 
			next_play_track = 0; 
			bios_flag &= ~BIOS_FLAG_PLUS10; 
			if (bios_flag & BIOS_FLAG_PROGRUN) 
				add_program = 2; 
			else 
				play_start = 1; 
		} 
		else if (cx == 148 && cy == 74) 
		{ 
			// スタート 
			if (next_game_index != -1) 
			{ 
				// ゲーム起動 
				bios_run_game(); 
				return; 
			} 
		} 
 
		if (add_program) 
		{ 
			int i; 
 
			if (add_program == 1 && num_program < 98) 
			{ 
				program[num_program + 1] = next_play_track; 
				num_program++; 
			} 
			else if (add_program == 2 && num_program > 0) 
			{ 
				num_program--; 
				if (num_program == 0) 
				{ 
					// 全てキャンセルしたらプログラム終了 
					bios_flag &= ~BIOS_FLAG_PROGRUN; 
					bios_flag &= ~BIOS_FLAG_PROGEDIT; 
					return; 
				} 
			} 
			else 
				return; 
 
			program_sec = 0; 
			for (i = 1; i <= num_program; i++) 
			{ 
				program_sec += osd_cdda_get_track_sec(program[i]); 
			} 
			next_play_track = 0; 
			bios_flag &= ~BIOS_FLAG_PLUS10; 
			bios_program_counter = 30; 
		} 
 
		if (play_start) 
		{ 
			int play_type; 
 
			if (bios_flag & BIOS_FLAG_PROGRUN) 
			{ 
				if (play_start == 1) 
				{ 
					// プログラムナンバー指定 
					current_play_track = program[next_play_track]; 
					play_type = 2; 
				} 
				else if (num_program == 0) 
				{ 
					// プログラムが指定されていなければ解除して普通に再生 
					bios_flag &= ~BIOS_FLAG_PROGRUN; 
					bios_flag &= ~BIOS_FLAG_PROGEDIT; 
					current_play_track = next_play_track; 
					play_type = 0; 
				} 
				else 
				{ 
					// プログラムの最初から 
					program[num_program + 1] = 0; 
					current_play_track = program[1]; 
					play_type = 1; 
				} 
			} 
			else 
			{ 
				// プログラムの最初から普通に再生 
				current_play_track = next_play_track; 
				play_type = 0; 
			} 
 
			// 再生 
			switch (play_type) 
			{ 
			case 0: 
				osd_cdda_play_tracks(current_play_track); 
				break; 
 
			case 1: 
				osd_cdda_play_program(program); 
				break; 
 
			case 2: 
				osd_cdda_play_program_no(current_play_track); 
				break; 
			} 
 
			bios_status = BIOS_CDDA_PLAY; 
			bios_flag &= ~BIOS_FLAG_PLUS10; 
			next_play_track = 0; 
		} 
	} 
}