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


/*************************************************************************** 
 
	usrintrf.c 
 
	ユーザインターフェース関連 
 
***************************************************************************/ 
 
#include "neogeocd.h" 
 
 
#ifndef swap 
#define swap(a, b) { int tmp = a; a = b; b = tmp; } 
#endif 
 
#define DISABLE 0 
#define ENABLE  1 
 
/**************************************************************************** 
	プロトタイプ 
 ***************************************************************************/ 
 
static void ui_keycheck(void); 
 
void build_joyid_list(char list[][8], char *subitem[], int value[]); 
 
static int build_drive_list(char list[][16], char *subitem[], int value[]); 
 
static void set_menu_items(options_type *opt); 
static void apply_menu_items(options_type *opt); 
 
static void level1_menu(void); 
static void level2_video(void); 
static void level2_input(void); 
static void level2_audio(void); 
static void level2_other(void); 
static void level3_p1key(void); 
static void level3_p2key(void); 
static void level3_p1joy(void); 
static void level3_p2joy(void); 
static void level3_p1hotkey(void); 
static void level3_p2hotkey(void); 
 
 
/**************************************************************************** 
	グローバル変数 
 ***************************************************************************/ 
 
int current_menu_level;	// 現在のメニューの階層 (win32/keyboard.cで使用) 
 
UINT16 ui_palette[UI_COLOR_MAX * 16]; 
 
 
/**************************************************************************** 
	ローカル構造体 
 ***************************************************************************/ 
 
struct menu_t 
{ 
	const char *item; 
	int   flag; 
	int   current; 
	const int y; 
 
	void  (*func)(void); 
	char  **subitem; 
	int   *value; 
}; 
 
 
/**************************************************************************** 
	ローカル変数 
 ***************************************************************************/ 
 
static int ui_screen; 
static int ui_font_color = 0; 
static int ui_pixel_color = 0; 
static int  ui_popup_counter = 0; 
static char ui_popup_strings[512]; 
 
static int L1_curpos; 
static int L2_curpos; 
static int L3_curpos; 
static UINT8 input_change_wait; 
 
#include "binary/movwav.c" 
 
 
/*-------------------------- 
 	joystick buttons 
--------------------------*/ 
 
static const char *padname[] = 
{ 
	"UP", 
	"DOWN", 
	"LEFT", 
	"RIGHT", 
	"BUTTON A", 
	"BUTTON B", 
	"BUTTON C", 
	"BUTTON D", 
	"START", 
	"SELECT", 
	0 
}; 
 
/*-------------------------- 
 	string of subitems 
--------------------------*/ 
 
static const char *subitem_yesno[] = 
{ 
	"NO", 
	"YES", 
	NULL 
}; 
 
static const char *subitem_enable[] = 
{ 
	"DISABLE", 
	"ENABLE", 
	NULL 
}; 
 
static const char *subitem_region[] = 
{ 
	"JAPAN", 
	"USA", 
	"EUROPE", 
	NULL 
}; 
 
static const char *subitem_cdspeed[] = 
{ 
	"FULL SPEED", 
	"SIMULATE 2x", 
	"SIMULATE 4x", 
	"SIMULATE 8x", 
	"SIMULATE 16x", 
	"SIMULATE 32x", 
	NULL 
}; 
 
static const char *subitem_scanlines[] = 
{ 
	"NOT USE", 
	"SCANLINE 0%", 
	"SCANLINE 25%", 
	"SCANLINE 50%", 
	"SCANLINE 75%", 
	NULL 
}; 
 
static const char *subitem_hwstretch[] = 
{ 
	"DISABLE", 
	"DISPLAY SIZE", 
	"2x", 
	"3x", 
	NULL 
}; 
 
static const char *subitem_fps[] = 
{ 
	"60.0Hz", 
	"59.1856Hz", 
	"ADJUST PC", 
	NULL 
}; 
 
static const char *subitem_samplerate[] = 
{ 
	"0Hz", 
	"11025Hz", 
	"22050Hz", 
	"44100Hz", 
	"48000Hz", 
	NULL 
}; 
 
static const char *subitem_latency[] = 
{ 
	"1","2","3","4","5", 
	"6","7","8","9","10", 
	NULL 
}; 
 
static const char *subitem_soundvolume[] = 
{ 
	"0%",   "10%",  "20%",  "30%", 
	"40%",  "50%",  "60%",  "70%", 
	"80%",  "90%",  "100%", "110%", 
	"120%",  "130%",  "140%", "150%", 
	"160%",  "170%",  "180%", "190%", 
	"200%", 
	NULL 
}; 
 
static const char *subitem_cddavolume[] = 
{ 
	"OS DEFAULT", 
	"0%",   "10%",  "20%",  "30%", 
	"40%",  "50%",  "60%",  "70%", 
	"80%",  "90%",  "100%", "110%", 
	"120%",  "130%",  "140%", "150%", 
	"160%",  "170%",  "180%", "190%", 
	"200%", 
	NULL 
}; 
 
 
static const char *subitem_sleep[] = 
{ 
	"NO SLEEP", 
	"0ms",  "1ms",  "2ms",  "3ms", 
	"4ms",  "5ms",  "6ms",  "7ms", 
	"8ms",  "9ms",  "10ms", "11ms", 
	"12ms", "13ms", "14ms", "15ms", 
	NULL 
}; 
 
 
static const char *subitem_hotkey[] = 
{ 
	"NOT USE", 
	"AUTOFIRE A", 
	"AUTOFIRE B", 
	"AUTOFIRE C", 
	"AUTOFIRE D", 
	"A+B", 
	"A+C", 
	"A+D", 
	"B+C", 
	"B+D", 
	"C+D", 
	"A+B+C", 
	"A+B+D", 
	"A+C+D", 
	"B+C+D", 
	"A+B+C+D", 
	NULL 
}; 
 
 
/*-------------------------- 
 	value of subitems 
--------------------------*/ 
 
static int value_scanlines[] = { 0, 0, 25, 50, 75, 0 }; 
static int value_samplerate[] = { 0, 11025, 22050, 44100, 48000, 0 }; 
 
 
/*-------------------------- 
 	not constant values 
 	(initalize on startup) 
--------------------------*/ 
 
static char drive_list[32][16]; 
static char *subitem_drive[32]; 
static int  value_drive[32]; 
 
static char joyid_list[10][8]; 
static char *subitem_joyid[10]; 
static int  value_joyid[10]; 
static int  joyid[2]; 
 
 
/*-------------------------------------------------------- 
 
  メニュー項目の設定 
 
---------------------------------------------------------- 
 
   左から以下のような内容になってます 
 
    1.画面に表示するメニュー項目名 
 
    2.メニュー項目の有効/無効初期値 
 
    3.メニュー項目の描画開始位置(Y軸) 
 
    4.下位メニューがある場合: メニュー項目の描画関数 
      下位メニューがない場合: NULL 
 
    5.可変のサブアイテム用配列 
 
    6.特殊なサブアイテム用の値を格納する配列 
 
--------------------------------------------------------*/ 
 
#define FONT_XSIZE		8 
#define FONT_YSIZE		12 
 
#define MENU_TOP		3 
#define MENU_BOTTOM		16 
#define MENU_ITEM_X		3 
#define MENU_SUBITEM_X	20 
 
/*-------------------------------- 
  トップメニュー 
--------------------------------*/ 
 
enum 
{ 
	MENU_REGION = 0, 
	MENU_RASTER, 
	MENU_DRIVE, 
	MENU_CDSPEED, 
	MENU_VIDEO, 
	MENU_INPUT, 
	MENU_AUDIO, 
	MENU_OTHER, 
	MENU_RETURN, 
	MENU_OPTMAX 
}; 
 
static struct menu_t L1_menu[] = 
{ 
	{ "MACHINE REGION", ENABLE, 0, MENU_TOP + MENU_REGION,    NULL,         (char **)subitem_region,  NULL        }, 
	{ "RASTER EFFECTS", ENABLE, 0, MENU_TOP + MENU_RASTER,    NULL,         (char **)subitem_enable,  NULL        }, 
	{ "CD-ROM DRIVE",   ENABLE, 0, MENU_TOP + MENU_DRIVE,     NULL,         (char **)subitem_drive,   value_drive }, 
	{ "CD-ROM SPEED",   ENABLE, 0, MENU_TOP + MENU_CDSPEED,   NULL,         (char **)subitem_cdspeed, NULL        }, 
	{ "VIDEO SETTINGS", ENABLE, 0, MENU_TOP + MENU_VIDEO + 1, level2_video, NULL,                     NULL        }, 
	{ "INPUT SETTINGS", ENABLE, 0, MENU_TOP + MENU_INPUT + 1, level2_input, NULL,                     NULL        }, 
	{ "AUDIO SETTINGS", ENABLE, 0, MENU_TOP + MENU_AUDIO + 1, level2_audio, NULL,                     NULL        }, 
	{ "OTHER SETTINGS", ENABLE, 0, MENU_TOP + MENU_OTHER + 1, level2_other, NULL,                     NULL        }, 
	{ "RETURN TO GAME", ENABLE, 0, MENU_BOTTOM,               NULL,         NULL,                     NULL        }, 
	{ 0 }, 
}; 
 
 
/*-------------------------------- 
  ビデオメニュー 
--------------------------------*/ 
 
enum 
{ 
	VIDEO_FULLSCREEN = 0, 
	VIDEO_SWSTRETCH, 
	VIDEO_SCANLINE, 
	VIDEO_HWSTRETCH, 
	VIDEO_TRIPLEBUF, 
	VIDEO_VSYNC, 
	VIDEO_DDHEL, 
	VIDEO_SYSMEM, 
	VIDEO_FPS, 
	VIDEO_RETURN, 
	VIDEO_OPTMAX 
}; 
 
static struct menu_t L2_video[] = 
{ 
	{ "FULL SCREEN",          ENABLE, 0, MENU_TOP + VIDEO_FULLSCREEN, NULL, (char **)subitem_yesno,      NULL             }, 
	{ "SW STRETCH 2x",        ENABLE, 0, MENU_TOP + VIDEO_SWSTRETCH,  NULL, (char **)subitem_enable,     NULL             }, 
	{ "SCANLINES",            ENABLE, 0, MENU_TOP + VIDEO_SCANLINE,   NULL, (char **)subitem_scanlines,  value_scanlines  }, 
	{ "HW STRETCH",           ENABLE, 0, MENU_TOP + VIDEO_HWSTRETCH,  NULL, (char **)subitem_hwstretch,  NULL             }, 
	{ "TRIPLE BUFFER",        ENABLE, 0, MENU_TOP + VIDEO_TRIPLEBUF,  NULL, (char **)subitem_enable,     NULL             }, 
	{ "WAIT VSYNC",           ENABLE, 0, MENU_TOP + VIDEO_VSYNC,      NULL, (char **)subitem_yesno,      NULL             }, 
	{ "DIRECTDRAW HEL",       ENABLE, 0, MENU_TOP + VIDEO_DDHEL,      NULL, (char **)subitem_enable,     NULL             }, 
	{ "USE SYSTEM MEMORY",    ENABLE, 0, MENU_TOP + VIDEO_SYSMEM,     NULL, (char **)subitem_yesno,      NULL             }, 
	{ "REFRESH RATE",         ENABLE, 0, MENU_TOP + VIDEO_FPS,        NULL, (char **)subitem_fps,        NULL             }, 
	{ "RETURN TO PRIOR MENU", ENABLE, 0, MENU_BOTTOM,                 NULL, NULL,                        NULL             }, 
	{ 0 }, 
}; 
 
/*-------------------------------- 
  入力デバイスメニュー 
--------------------------------*/ 
 
enum 
{ 
	INPUT_P1KEY = 0, 
	INPUT_P1JOY, 
	INPUT_P1HOTKEY, 
	INPUT_P2KEY, 
	INPUT_P2JOY, 
	INPUT_P2HOTKEY, 
	INPUT_RETURN, 
	INPUT_OPTMAX 
}; 
 
static struct menu_t L2_input[] = 
{ 
	{ "PLAYER1 KEYBOARD",     ENABLE, 0, MENU_TOP + INPUT_P1KEY,        level3_p1key,    NULL, NULL }, 
	{ "PLAYER1 JOYSTICK",     ENABLE, 0, MENU_TOP + INPUT_P1JOY,        level3_p1joy,    NULL, NULL }, 
	{ "PLAYER1 HOTKEY",       ENABLE, 0, MENU_TOP + INPUT_P1HOTKEY,     level3_p1hotkey, NULL, NULL }, 
	{ "PLAYER2 KEYBOARD",     ENABLE, 0, MENU_TOP + INPUT_P2KEY + 1,    level3_p2key,    NULL, NULL }, 
	{ "PLAYER2 JOYSTICK",     ENABLE, 0, MENU_TOP + INPUT_P2JOY + 1,    level3_p2joy,    NULL, NULL }, 
	{ "PLAYER2 HOTKEY",       ENABLE, 0, MENU_TOP + INPUT_P2HOTKEY + 1, level3_p2hotkey, NULL, NULL }, 
	{ "RETURN TO PRIOR MENU", ENABLE, 0, MENU_BOTTOM,                   NULL,            NULL, NULL }, 
	{ 0 }, 
}; 
 
 
/*-------------------------------- 
  サウンドメニュー 
--------------------------------*/ 
 
enum 
{ 
	SOUND_SAMPLERATE = 0, 
	SOUND_VOLUME, 
	SOUND_LATENCY, 
	CDDA_ENABLE, 
	CDDA_VOLUME, 
	AUDIO_RETURN, 
	AUDIO_OPTMAX 
}; 
 
static struct menu_t L2_audio[] = 
{ 
	{ "SAMPLE RATE",          ENABLE, 0, MENU_TOP +  SOUND_SAMPLERATE, NULL, (char **)subitem_samplerate,    value_samplerate }, 
	{ "SOUND VOLUME",         ENABLE, 0, MENU_TOP +  SOUND_VOLUME,     NULL, (char **)subitem_soundvolume,   NULL             }, 
	{ "SOUND LATENCY",        ENABLE, 0, MENU_TOP +  SOUND_LATENCY,    NULL, (char **)subitem_latency,       NULL             }, 
	{ "CDDA ENABLE",          ENABLE, 0, MENU_TOP + (CDDA_ENABLE + 1), NULL, (char **)subitem_yesno,         NULL             }, 
	{ "CDDA VOLUME",          ENABLE, 0, MENU_TOP + (CDDA_VOLUME + 1), NULL, (char **)subitem_cddavolume,    NULL             }, 
	{ "RETURN TO PRIOR MENU", ENABLE, 0, MENU_BOTTOM,                  NULL, NULL,                           NULL             }, 
	{ 0 }, 
}; 
 
 
/*-------------------------------- 
  その他メニュー 
--------------------------------*/ 
 
enum 
{ 
	OTHER_PAUSE = 0, 
	OTHER_MMX, 
	OTHER_SSE, 
	OTHER_SLEEP, 
	OTHER_ERRORLOG, 
	OTHER_RETURN, 
	OTHER_OPTMAX 
}; 
 
static struct menu_t L2_other[] = 
{ 
	{ "AUTO PAUSE",           ENABLE, 0, MENU_TOP + OTHER_PAUSE,     NULL, (char **)subitem_yesno, NULL }, 
	{ "ENABLE MMX",           ENABLE, 0, MENU_TOP + OTHER_MMX,       NULL, (char **)subitem_yesno, NULL }, 
	{ "ENABLE SSE",           ENABLE, 0, MENU_TOP + OTHER_SSE,       NULL, (char **)subitem_yesno, NULL }, 
	{ "SLEEP TIME",           ENABLE, 0, MENU_TOP + OTHER_SLEEP,     NULL, (char **)subitem_sleep, NULL }, 
	{ "ERROR LOG",            ENABLE, 0, MENU_TOP + OTHER_ERRORLOG,  NULL, (char **)subitem_yesno, NULL }, 
	{ "RETURN TO PRIOR MENU", ENABLE, 0, MENU_BOTTOM,                NULL, NULL,                   NULL }, 
	{ 0 }, 
}; 
 
 
/*************************************************************************** 
	グローバル関数 
 ***************************************************************************/ 
 
/*------------------------------------------------------ 
 
	ユーザインタフェースの初期化 
 
	引  数: なし 
	戻り値: 成功:1  失敗:0 
 
 -----------------------------------------------------*/ 
 
int ui_init(void) 
{ 
	UINT16 pen; 
	int i, r, g, b; 
 
	ui_screen = osd_create_screen(SCREEN_WIDTH, SCREEN_HEIGHT); 
	if (ui_screen == 0) 
		return 0; 
 
	current_menu_level = 0; 
	L1_curpos = 0; 
	L2_curpos = 0; 
	L3_curpos = 0; 
	input_change_wait = 0; 
 
	build_drive_list(drive_list, subitem_drive, value_drive); 
	build_joyid_list(joyid_list, subitem_joyid, value_joyid); 
 
	set_menu_items(&options); 
 
	// UI_COLOR_NORMAL 
	pen = UI_COLOR_NORMAL; 
	ui_palette[pen++] = osd_make_pen( 0,  0,  0); 
	ui_palette[pen++] = osd_make_pen(63, 63, 63); 
 
	for (i = 8; i >= 2; i--) 
	{ 
		int col = (255 - i * 16) >> 3; 
 
		r = (col << 3) | (col >> 2); 
		g = (col << 3) | (col >> 2); 
		b = (col << 3) | (col >> 2); 
 
		ui_palette[pen++] = osd_make_pen(r, g, b); 
	} 
 
	// UI_COLOR_SELECT 
	pen = UI_COLOR_SELECT * 16; 
	ui_palette[pen++] = osd_make_pen( 0,  0,  0); 
	ui_palette[pen++] = osd_make_pen(63, 63,  0); 
 
	for (i = 8; i >= 2; i--) 
	{ 
		int col = (255 - i * 16) >> 3; 
 
		r = (col << 3) | (col >> 2); 
		g = ((col - 1) << 3) | ((col - 1) >> 2); 
		b = 0; 
 
		ui_palette[pen++] = osd_make_pen(r, g, b); 
	} 
 
	// UI_COLOR_DISABLE 
	pen = UI_COLOR_DISABLE * 16; 
	ui_palette[pen++] = osd_make_pen( 0,  0,  0); 
	ui_palette[pen++] = osd_make_pen(31, 31,  0); 
 
	for (i = 8; i >= 2; i--) 
	{ 
		int col = (195 - i * 16) >> 3; 
 
		r = (col << 3) | (col >> 2); 
		g = (col << 3) | (col >> 2); 
		b = (col << 3) | (col >> 2); 
 
		ui_palette[pen++] = osd_make_pen(r, g, b); 
	} 
 
	// ユーザインタフェース用のパレットを設定 
	osd_register_palette(ui_palette, 16 * UI_COLOR_MAX); 
 
	return 1; 
} 
 
 
/*------------------------------------------------------ 
 
	ユーザインタフェースの終了 
 
	引  数: なし 
	戻り値: 成功:1  失敗:0 
 
 -----------------------------------------------------*/ 
 
void ui_exit(void) 
{ 
	osd_free_screen(ui_screen); 
	ui_screen = 0; 
 
	osd_unregister_palette(ui_palette); 
} 
 
 
/*------------------------------------------------------ 
 
	メニューの表示 
 
	引  数: なし 
	戻り値: なし 
 
 -----------------------------------------------------*/ 
 
void ui_menu(void) 
{ 
	int pause = 0; 
 
	// メニュー表示 
	if (osd_is_key_pressed_memory(KEYCODE_TAB)) 
	{ 
		options_type opt; 
		int x, y, r, g, b; 
		UINT16 pen; 
 
		set_menu_items(&options); 
 
		memcpy(&opt, &options, sizeof(options_type)); 
 
		osd_sound_enable(0); 
 
		if (osd_cdda_get_status() == CDDA_PLAY) 
		{ 
			pause = 1; 
			osd_cdda_pause(); 
		} 
 
		// 枠描画 
		ui_set_plot_color(192, 192, 192); 
		ui_plot_box(10, (MENU_TOP - 1) * FONT_YSIZE - 2,  294, (MENU_BOTTOM + 1) * FONT_YSIZE - 2); 
 
		for (y = visible_area.min_y; y <= visible_area.max_y; y++) 
		{ 
			for (x = visible_area.min_x; x <= visible_area.max_x; x++) 
			{ 
				pen = scrbitmap.line[y][x]; 
				osd_get_pen(pen, &r, &g, &b); 
				scrbitmap.line[y][x] = osd_make_pen(r / 2, g / 2, b / 2); 
			} 
		} 
 
		// 枠内部をディザリング付きグラデーションで描画 
		{ 
			int r, g, b, b2 = 200, db; 
 
			// このプログラムではひとつの色要素しか有効でないので、単純に処理 
			// 3ビット右シフト * 50%ブレンド = 4bit右シフト = 16ドットごとにマッハバンド発生 
			// 計算するのも面倒なので、単純にテーブルで処理 
			int d_table[16][8] = 
			{ 
				{  0,-1, 0,-1, 0,-1, 0,-1 },	// 0 
				{ -2, 0,-2, 0,-2, 0,-2, 0 },	// 1 
				{  0, 0, 0,-3, 0, 0, 0,-3 },	// 2 
				{  0,-4, 0, 0, 0,-4, 0, 0 },	// 3 
				{  0, 0, 0,-5, 0, 0, 0, 0 },	// 4 
				{  0, 0, 0, 0, 0, 0, 0, 0 },	// 5 
				{  0, 0, 0, 0, 0, 0, 0, 0 },	// 6 
				{  0, 0, 0, 0, 0, 0, 0, 0 },	// 7 
				{  0, 0, 0, 0, 0, 0, 0, 0 },	// 8 
				{  0, 0, 0, 0, 0, 0, 0, 0 },	// 9 
				{  0, 0, 0, 0, 0, 0, 0, 0 },	// 10 
				{  0, 0, 0, 5, 0, 0, 0, 0 },	// 11 
				{  0, 4, 0, 0, 0, 4, 0, 0 },	// 12 
				{  0, 0, 0, 3, 0, 0, 0, 3 },	// 13 
				{  2, 0, 2, 0, 2, 0, 2, 0 },	// 14 
				{  0, 1, 0, 1, 0, 1, 0, 1 }		// 15 
			}; 
 
			for (y = (MENU_TOP - 1) * FONT_YSIZE - 1; y <= (MENU_BOTTOM + 1) * FONT_YSIZE - 3; y++) 
			{ 
				for (x = 11; x <= 293; x++) 
				{ 
					ui_get_pixel_color(x, y, &r, &g, &b); 
 
					r >>= 1; 
					g >>= 1; 
 
					db = b + b2; 
					b = (db + d_table[db & 0x0f][x & 0x07] * 2) >> 1; 
 
					ui_set_plot_color(r, g, b); 
					ui_plot_pixel(x, y); 
				} 
 
				if (--b2 < 0) b2 = 0; 
			} 
		} 
 
		set_menu_items(&options); 
 
		current_menu_level = 1; 
 
		ui_save_screen(1); 
 
		while (current_menu_level) 
		{ 
			ui_restore_screen(); 
 
			level1_menu(); 
 
			if (osd_get_app_state() || osd_is_key_pressed_memory(KEYCODE_TAB)) 
			{ 
				current_menu_level = 0; 
				break; 
			} 
 
			ui_show_popup(); 
			ui_keycheck(); 
 
			update_input_port(); 
			sound_update(); 
			osd_update_video(1); 
		} 
 
		ui_save_screen(0); 
 
		apply_menu_items(&opt); 
 
		if (osd_get_app_state()) 
		{ 
			osd_cdda_stop(); 
		} 
		else 
		{ 
			if (pause) osd_cdda_resume(); 
		} 
		osd_sound_enable(1); 
	} 
	else 
	{ 
		ui_keycheck(); 
	} 
} 
 
 
/*------------------------------------------------------ 
 
	画面へのUI用固定スプライト描画 
 
	引  数: int no   スプライト番号 
	        int x    横座標 
	        int y    縦座標 
	戻り値: なし 
 
   ※描画位置は1ドット単位で指定 
     (基本的には直接使用しないこと。ui_draw_text用です) 
 
 -----------------------------------------------------*/ 
 
void ui_draw_fix(int no, int x, int y) 
{ 
	UINT8 *gfx = memory_region(REGION_GFX4); 
 
	neogeo_draw_fix(gfx, no, x, y, &ui_palette[ui_font_color], 0); 
} 
 
 
/*------------------------------------------------------ 
 
	画面への文字列描画 
 
	引  数: char *str 描画する文字列 
	        int x     描画開始位置(横座標) 
	        int y     描画開始位置(縦座標) 
	戻り値: なし 
 
    ※横座標は8ピクセル、縦座標は1ピクセル単位です 
 
 -----------------------------------------------------*/ 
 
void ui_draw_text(const char *str, int x, int y) 
{ 
	int i, len; 
 
	x = (x * 8) + visible_area.min_x; 
	y = y + visible_area.min_y; 
 
	len = strlen(str); 
 
	for (i = 0; i < len; i++) 
		ui_draw_fix(str[i], x + i * 8, y); 
} 
 
 
/*------------------------------------------------------ 
 
	UIのフォントカラー設定 
 
	引  数: int number  フォントカラー番号 
	戻り値: なし 
 
 -----------------------------------------------------*/ 
 
void ui_set_text_color(int number) 
{ 
	ui_font_color = number * 16; 
} 
 
 
/*------------------------------------------------------ 
 
	文字列のポップアップ表示 
 
	引  数: const char *str 描画する文字列 
	戻り値: なし 
 
    ※60フレーム表示します 
 
 -----------------------------------------------------*/ 
 
void __cdecl ui_popup(const char *text, ...) 
{ 
	va_list arg; 
 
	ui_popup_counter = 60; 
 
	memset(ui_popup_strings, 0, sizeof(ui_popup_strings)); 
 
	va_start(arg, text); 
	vsprintf(ui_popup_strings, text, arg); 
	va_end(arg); 
} 
 
 
/*------------------------------------------------------ 
 
	ポップアップ文字列の描画 
 
	引  数: const char *str 描画する文字列 
	戻り値: なし 
 
    ※60フレーム表示します 
 
 -----------------------------------------------------*/ 
 
void ui_show_popup(void) 
{ 
	if (ui_popup_counter) 
	{ 
		int i, x, y, len; 
		int x2, y2; 
 
		len = strlen(ui_popup_strings) * 8; 
		x = ((visible_area.max_x - visible_area.min_x) - len) / 2; 
		y = ((visible_area.max_y - visible_area.min_y) - 8) / 2; 
 
		ui_set_plot_color(196, 196, 196); 
		ui_plot_box(x - 4, y - 4, x + len + 4, y + 8 + 4); 
 
		for (y2 = y - 3; y2 < y + 8 + 4; y2++) 
		{ 
			for (x2 = x - 3; x2 < x + len + 4; x2++) 
			{ 
				int r, g, b; 
 
				ui_get_pixel_color(x2, y2, &r, &g, &b); 
				r *= 0.25; 
				g *= 0.25; 
				b *= 0.25; 
				ui_set_plot_color(r, g, b); 
				ui_plot_pixel(x2, y2); 
			} 
		} 
 
		x += visible_area.min_x; 
		y += visible_area.min_y; 
 
		ui_set_text_color(UI_COLOR_NORMAL); 
 
		for (i = 0; i < len; i++) 
			ui_draw_fix(ui_popup_strings[i], x + i * 8, y); 
 
		ui_popup_counter--; 
	} 
} 
 
 
/*------------------------------------------------------ 
 
	UIの描画ピクセルカラー設定 
 
	引  数: int r  赤輝度(0-255) 
	        int g  緑輝度(0-255) 
	        int b  青輝度(0-255) 
	戻り値: なし 
 
 -----------------------------------------------------*/ 
 
void ui_set_plot_color(int r, int g, int b) 
{ 
	ui_pixel_color = osd_make_pen(r, g, b); 
} 
 
 
/*------------------------------------------------------ 
 
	ビットマップの指定位置のピクセルカラー取得 
 
	引  数: int x  横座標 
	        int y  縦座標 
	        int r  赤輝度(0-255) 
	        int g  緑輝度(0-255) 
	        int b  青輝度(0-255) 
	戻り値: なし 
 
 -----------------------------------------------------*/ 
 
void ui_get_pixel_color(int x, int y, int *r, int *g, int *b) 
{ 
	x += visible_area.min_x; 
	y += visible_area.min_y; 
 
	*r = 0; 
	*g = 0; 
	*b = 0; 
 
	if (x <= visible_area.max_x && y <= visible_area.max_y) 
		osd_get_pen(scrbitmap.line[y][x], r, g, b); 
} 
 
 
/*------------------------------------------------------ 
 
	画面へのピクセル描画 
 
	引  数: int x  描画位置(横座標) 
	        int y  描画位置(縦座標) 
	戻り値: なし 
 
 -----------------------------------------------------*/ 
 
void ui_plot_pixel(int x, int y) 
{ 
	x += visible_area.min_x; 
	y += visible_area.min_y; 
 
	if (x <= visible_area.max_x && y <= visible_area.max_y) 
		scrbitmap.line[y][x] = ui_pixel_color; 
} 
 
 
/*------------------------------------------------------ 
 
	画面へのライン描画 
 
	引  数: int sx 描画開始横座標 
	        int sy 描画開始縦座標 
	        int ex 描画終了横座標 
	        int ey 描画終了縦座標 
	戻り値: なし 
 
 -----------------------------------------------------*/ 
 
void ui_plot_line(int sx, int sy, int ex, int ey) 
{ 
	int dx, dy, d, step; 
 
	if (sx > ex) 
	{ 
		swap(sx, ex); 
		swap(sy, ey); 
	} 
 
	dx = abs(ex - sx); 
	dy = abs(ey - sy); 
 
	if (dx > dy) 
	{ 
		if (sx > ex) 
		{ 
			step = (sy > ey) ? 1 : -1; 
			swap(sx, ey); 
			sy = ey; 
		} 
		else 
			step = (sy < ey) ? 1 : -1; 
 
		ui_plot_pixel(sx, sy); 
 
		d = dx >> 1; 
		while (++sx <= ex) 
		{ 
			if ((d -= dy) < 0) 
			{ 
				d += dx;  
				sy += step; 
			} 
			ui_plot_pixel(sx, sy); 
		} 
	} 
	else 
	{ 
		if (sy > ey) 
		{ 
			step = (sx > ex) ? 1 : -1; 
			swap(sy, ey); 
			sx = ex; 
		} 
		else 
			step = (sx < ex) ? 1 : -1; 
 
		ui_plot_pixel(sx, sy); 
 
		d = dy >> 1; 
		while (++sy <= ey) 
		{ 
			if ((d -= dx) < 0) 
			{ 
				d += dy; 
				sx += step; 
			} 
			ui_plot_pixel(sx, sy); 
		} 
	} 
} 
 
 
/*------------------------------------------------------ 
 
	画面への四角描画 
 
	引  数: int x1 描画開始横座標 
	        int y1 描画開始縦座標 
	        int x2 描画終了横座標 
	        int y2 描画終了縦座標 
	戻り値: なし 
 
 -----------------------------------------------------*/ 
 
void ui_plot_box(int x1, int y1, int x2, int y2) 
{ 
	if (x1 > x2) swap(x1, x2); 
	if (y1 > y2) swap(y1, y2); 
 
	ui_plot_line(x1,     y1,     x2, y1    ); // 左上→右上 
	ui_plot_line(x2,     y1 + 1, x2, y2    ); // 右上→右下 
	ui_plot_line(x2 - 1, y2,     x1, y2    ); // 右下→左下 
	ui_plot_line(x1,     y2 - 1, x1, y1 + 1); // 左下→右上 
} 
 
 
/*------------------------------------------------------ 
 
	描画ビットマップの切り替え(UI描画用) 
 
	引  数: int screen  1:退避 0:復帰 
	戻り値: なし 
 
 -----------------------------------------------------*/ 
 
void ui_save_screen(int save) 
{ 
	if (save) 
	{ 
		osd_copy_screen(ui_screen); 
		osd_set_screen(ui_screen); 
	} 
	else 
	{ 
		osd_set_screen(OSD_SCREEN); 
	} 
} 
 
 
/*------------------------------------------------------ 
 
	退避した画面を書き戻す(UI描画用) 
 
	引  数: なし 
	戻り値: なし 
 
 -----------------------------------------------------*/ 
 
void ui_restore_screen(void) 
{ 
	osd_set_screen(OSD_SCREEN); 
	osd_copy_screen(ui_screen); 
	osd_set_screen(ui_screen); 
} 
 
 
/*------------------------------------------------------ 
 
	スクリーンショットの保存 
 
	引  数: なし 
	戻り値: なし 
 
 -----------------------------------------------------*/ 
 
void save_snapshot(void) 
{ 
	char path[_MAX_PATH]; 
	FILE *fp; 
	int snapno = 0; 
#if 0 
	char str[30]; 
#endif 
 
	if (!osd_file_exist(options.snapdir)) 
		mkdir(options.snapdir); 
 
	if (game_name[0] == '\0') strcpy(game_name, "neogeocd"); 
	sprintf(path, "%s/%s.png", options.snapdir, game_name); 
 
	if (osd_file_exist(path)) 
	{ 
		do 
		{ 
			sprintf(path, "%s/%s_%03d.png", options.snapdir, game_name, snapno++); 
		} while (osd_file_exist(path)); 
	} 
 
#if 0 
	sprintf(str, "(C)%4d %s", games[game_index].year, games[game_index].manufacture); 
	ui_set_text_color(UI_COLOR_NORMAL); 
	ui_draw_text(str, 37 - strlen(str), 27*8); 
#endif 
 
	fp = fopen(path, "wb"); 
	if (fp) 
	{ 
		int sizex = (visible_area.max_x - visible_area.min_x) + 1; 
		int sizey = (visible_area.max_y - visible_area.min_y) + 1; 
		struct osd_bitmap *copy = osd_alloc_bitmap(sizex, sizey); 
 
		if (copy) 
		{ 
			int x, y, sx, sy; 
 
			sx = visible_area.min_x; 
			sy = visible_area.min_y; 
 
			for (y = 0; y < copy->height; y++) 
				for (x = 0; x < copy->width; x++) 
					copy->line[y][x] = scrbitmap.line[sy + y][sx + x]; 
 
			png_write_bitmap(fp, copy); 
			osd_free_bitmap(copy); 
			fclose(fp); 
 
			if (snapno == 0) 
				ui_popup("save screen shot (%s.png)", game_name); 
			else 
				ui_popup("save screen shot (%s_%03d.png)", game_name, snapno); 
			return; 
		} 
 
		fclose(fp); 
	} 
 
	logerror("snap: %s capture faild.\n", path); 
} 
 
 
/*************************************************************************** 
	Local functions 
 ***************************************************************************/ 
 
/*------------------------------------------------------ 
 
	システムキーが押されたかチェック 
 
	引  数: なし 
	戻り値: なし 
 
 -----------------------------------------------------*/ 
 
static void ui_keycheck(void) 
{ 
	// 終了 
	if (osd_is_key_pressed_memory(KEYCODE_ESC)) 
	{ 
		logerror("Quit by user.\n"); 
		osd_set_app_state(OSD_QUIT); 
	} 
 
	// リセット 
	if (osd_is_key_pressed_memory(KEYCODE_F3)) 
	{ 
		// シフトを押しながらの場合は、再起動 
		if (osd_is_key_pressed_memory(KEYCODE_LSHIFT) 
		||  osd_is_key_pressed_memory(KEYCODE_RSHIFT)) 
		{ 
			osd_set_app_state(OSD_RESTART); 
		} 
		else 
		{ 
			current_menu_level = 0; 
			machine_reset(); 
		} 
	} 
 
	// フルスクリーン/ウィンドウ表示切替 
	if ((osd_is_key_pressed(KEYCODE_LALT) || osd_is_key_pressed(KEYCODE_RALT)) 
	&&  (osd_is_key_pressed(KEYCODE_ENTER) || osd_is_key_pressed(KEYCODE_ENTER_PAD))) 
	{ 
		options.fullscreen ^= 1; 
		L2_video[VIDEO_FULLSCREEN].current = options.fullscreen; 
 
		if (osd_change_display() == OSD_ERROR) 
		{ 
			osd_set_app_state(OSD_QUIT); 
			return; 
		} 
	} 
 
	// スクリーンショット保存 
	if (osd_is_key_pressed_memory(KEYCODE_F12)) 
		save_snapshot(); 
} 
 
 
/*------------------------------------------------------ 
 
	メニュー用のCDドライブリスト作成 
 
	引  数: char list[][16] リストアイテム 
			char *subitem[] サブアイテム 
			int  value[]    ドライブ番号格納用 
	戻り値: リストアイテムの数 
 
 -----------------------------------------------------*/ 
 
static int build_drive_list(char list[][16], char *subitem[], int value[]) 
{ 
	int i, drive; 
 
	for (i = 0; i < 32; i++) 
	{ 
		memset(list[i], 0, 16); 
		subitem[i] = NULL; 
		value[i] = 0; 
	} 
 
	strcpy(list[0], "AUTO DETECT"); 
	subitem[0] = list[0]; 
	value[0] = -1; 
 
	i = 1; 
	for (drive = 0; drive < MAX_DRIVE; drive++) 
	{ 
		if (osd_get_drive_type(drive) == OSD_DRIVE_CDROM) 
		{ 
			sprintf(list[i], "DRIVE %c:", drive + 'A'); 
			subitem[i] = list[i]; 
			value[i] = drive; 
			i++; 
		} 
	} 
 
	for (i = 0; subitem[i] ; i++) 
	{ 
		if (options.drive == value[i]) 
			return i; 
	} 
	return 0; 
} 
 
 
/*-------------------------------------------------------- 
 
	メニューアイテムの初期化 
 
	引  数: options_type *opt オプション構造体のポインタ 
	戻り値: なし 
 
 -------------------------------------------------------*/ 
 
static void set_menu_items(options_type *opt) 
{ 
	int i; 
 
	// トップメニュー 
	/* machine settings */ 
	L1_menu[MENU_REGION].current    = opt->region; 
	L1_menu[MENU_RASTER].current    = opt->raster; 
	L1_menu[MENU_DRIVE].current     = 0; 
	L1_menu[MENU_CDSPEED].current   = opt->cdspeed; 
 
	for (i = 0; subitem_drive[i]; i++) 
	{ 
		if (value_drive[i] == opt->drive) 
			L1_menu[MENU_DRIVE].current = i; 
	} 
 
 
	// ビデオオプション 
	L2_video[VIDEO_FULLSCREEN].current = opt->fullscreen; 
	L2_video[VIDEO_SWSTRETCH].current  = opt->sw_stretch2x; 
	L2_video[VIDEO_SCANLINE].current   = 0; 
	L2_video[VIDEO_HWSTRETCH].current  = opt->hw_stretch; 
	L2_video[VIDEO_TRIPLEBUF].current  = opt->use_triplebuffer; 
	L2_video[VIDEO_VSYNC].current      = opt->wait_vsync; 
	L2_video[VIDEO_DDHEL].current      = opt->use_ddhel; 
	L2_video[VIDEO_SYSMEM].current     = opt->use_sysmem; 
	L2_video[VIDEO_FPS].current        = opt->refreshrate; 
 
	if (opt->scanlines) 
	{ 
		switch (opt->sl_brightness) 
		{ 
		case 0:  L2_video[VIDEO_SCANLINE].current = 1; break; 
		case 25: L2_video[VIDEO_SCANLINE].current = 2; break; 
		case 50: L2_video[VIDEO_SCANLINE].current = 3; break; 
		case 75: L2_video[VIDEO_SCANLINE].current = 4; break; 
		} 
	} 
 
 
	// ゲームコントローラーオプション 
	for (i = 0; subitem_joyid[i]; i++) 
	{ 
		int player; 
 
		for (player = 0; player < 2; player++) 
		{ 
			if (opt->joyid[player] == value_joyid[i]) 
			{ 
				joyid[player] = i; 
			} 
		} 
	} 
 
	// オーディオオプション 
	L2_audio[SOUND_VOLUME].current = opt->sound_volume / 10; 
	L2_audio[SOUND_LATENCY].current = opt->latency - 1; 
	L2_audio[CDDA_ENABLE].current  = opt->enable_cdda; 
	if (opt->cdda_volume == -1) 
		L2_audio[CDDA_VOLUME].current = 0; 
	else 
		L2_audio[CDDA_VOLUME].current = opt->cdda_volume / 10 + 1; 
 
	switch (opt->samplerate) 
	{ 
	case 11025: L2_audio[SOUND_SAMPLERATE].current = 1; break; 
	case 22050: L2_audio[SOUND_SAMPLERATE].current = 2; break; 
	case 44100: L2_audio[SOUND_SAMPLERATE].current = 3; break; 
	case 48000: L2_audio[SOUND_SAMPLERATE].current = 4; break; 
	default:    L2_audio[SOUND_SAMPLERATE].current = 0; break; 
	} 
 
 
	// その他のオプション 
	L2_other[OTHER_PAUSE].current     = opt->auto_pause; 
	L2_other[OTHER_MMX].current       = opt->enable_mmx; 
	L2_other[OTHER_SSE].current       = opt->enable_sse; 
	L2_other[OTHER_SLEEP].current     = opt->sleep_time + 1; 
	L2_other[OTHER_ERRORLOG].current  = opt->errorlog; 
} 
 
 
/*-------------------------------------------------------- 
 
	メニューアイテムの反映 
 
	引  数: options_type *opt オプション構造体のポインタ 
	戻り値: なし 
 
 -------------------------------------------------------*/ 
 
#define OPTION_CHANGED(name)	(options.name != opt->name) 
 
#define FLAG_RESET       (1 << 0) 
#define FLAG_RESTART     (1 << 1) 
#define FLAG_VIDEORESET  (1 << 2) 
#define FLAG_SOUNDVOLUME (1 << 3) 
#define FLAG_CDDAVOLUME  (1 << 4) 
#define FLAG_REBOOT      (1 << 5) 
 
static void apply_menu_items(options_type *opt) 
{ 
	int flag = 0; 
 
	build_hotkey(); 
 
	if (OPTION_CHANGED(region)) 
	{ 
		const char *fname[3] = { "backup_j.bin", "backup_u.bin", "backup_e.bin" }; 
		FILE *fp; 
 
		fp = fopen(fname[opt->region & 0x03], "wb"); 
		if (fp != NULL) 
		{ 
			fwrite(memory_region(REGION_USER2), 1, 0x2000, fp); 
			fclose(fp); 
		} 
 
		if (osd_file_exist(fname[options.region & 0x03])) 
		{ 
			fp = fopen(fname[options.region & 0x03], "rb"); 
			if (fp != NULL) 
			{ 
				fread(memory_region(REGION_USER2), 1, 0x2000, fp); 
				fclose(fp); 
			} 
		} 
 
		flag |= FLAG_REBOOT; 
	} 
 
	if (OPTION_CHANGED(drive) 
	||  OPTION_CHANGED(wait_vsync) 
	||	OPTION_CHANGED(refreshrate) 
	||	OPTION_CHANGED(latency) 
	||	OPTION_CHANGED(samplerate) 
	||	OPTION_CHANGED(errorlog)) 
	{ 
		flag |= FLAG_REBOOT; 
	} 
 
	if (OPTION_CHANGED(enable_cdda)) 
	{ 
		flag |= FLAG_RESTART; 
	} 
 
	if (OPTION_CHANGED(fullscreen) 
	||	OPTION_CHANGED(sw_stretch2x) 
	||	OPTION_CHANGED(scanlines) 
	||	OPTION_CHANGED(sl_brightness) 
	||	OPTION_CHANGED(hw_stretch) 
	||	OPTION_CHANGED(use_triplebuffer) 
	||	OPTION_CHANGED(use_ddhel) 
	||	OPTION_CHANGED(use_sysmem) 
	||	OPTION_CHANGED(sleep_time) 
	||	OPTION_CHANGED(enable_mmx) 
	||	OPTION_CHANGED(enable_sse)) 
	{ 
		flag |= FLAG_VIDEORESET; 
	} 
 
	if (OPTION_CHANGED(sound_volume)) 
	{ 
		flag |= FLAG_SOUNDVOLUME; 
	} 
 
	if (OPTION_CHANGED(cdda_volume)) 
	{ 
		flag |= FLAG_CDDAVOLUME; 
	} 
 
	if (osd_get_app_state()) 
		return; 
 
	if (flag & FLAG_REBOOT) 
	{ 
		osd_set_app_state(OSD_REBOOT); 
		return; 
	} 
 
	if (flag & FLAG_RESTART) 
	{ 
		osd_set_app_state(OSD_RESTART); 
		return; 
	} 
 
	if (flag & FLAG_VIDEORESET) 
	{ 
		if (osd_change_display() == OSD_ERROR) 
		{ 
			osd_set_app_state(OSD_QUIT); 
			return; 
		} 
	} 
 
	if (OPTION_CHANGED(raster)) 
	{ 
		if (options.raster) 
			driver_type |= 0x02; 
		else 
			driver_type &= ~0x02; 
 
		cpu_change_driver(); 
	} 
 
	if (flag & FLAG_SOUNDVOLUME) stream_set_volume(); 
 
	if (flag & FLAG_CDDAVOLUME) cdda_set_volume(options.cdda_volume); 
 
	if (flag & FLAG_RESET) machine_reset(); 
} 
 
 
/*-------------------------------------------------------- 
 
	各オプションのチェックと設定 
 
	引  数: なし 
	戻り値: なし 
 
 -------------------------------------------------------*/ 
 
/*-------------------------- 
 	machine options 
--------------------------*/ 
 
static void check_machine_options(void) 
{ 
	options.raster = L1_menu[MENU_RASTER].current; 
	options.region = L1_menu[MENU_REGION].current; 
	options.cdspeed = L1_menu[MENU_CDSPEED].current; 
 
	options.drive = L1_menu[MENU_DRIVE].value[L1_menu[MENU_DRIVE].current]; 
	if (options.drive == -1) 
		strcpy(options.drive_str, "auto"); 
	else 
		sprintf(options.drive_str, "%c", options.drive + 'A'); 
} 
 
/*-------------------------- 
 	video options 
--------------------------*/ 
 
static void check_video_options(void) 
{ 
	options.fullscreen       = L2_video[VIDEO_FULLSCREEN].current; 
	options.sw_stretch2x     = L2_video[VIDEO_SWSTRETCH].current; 
	options.scanlines        = L2_video[VIDEO_SCANLINE].current != 0; 
	options.hw_stretch       = L2_video[VIDEO_HWSTRETCH].current; 
	options.use_triplebuffer = L2_video[VIDEO_TRIPLEBUF].current; 
	options.wait_vsync       = L2_video[VIDEO_VSYNC].current; 
	options.use_ddhel        = L2_video[VIDEO_DDHEL].current; 
	options.use_sysmem       = L2_video[VIDEO_SYSMEM].current; 
	options.refreshrate      = L2_video[VIDEO_FPS].current; 
 
	if (L2_video[VIDEO_SCANLINE].current) 
		options.sl_brightness = (L2_video[VIDEO_SCANLINE].current - 1) * 25; 
} 
 
/*-------------------------- 
 	audio options 
--------------------------*/ 
 
static void check_audio_options(void) 
{ 
	options.samplerate   = L2_audio[SOUND_SAMPLERATE].value[L2_audio[SOUND_SAMPLERATE].current]; 
	options.sound_volume = L2_audio[SOUND_VOLUME].current * 10; 
	options.latency      = L2_audio[SOUND_LATENCY].current + 1; 
	options.enable_cdda  = L2_audio[CDDA_ENABLE].current; 
	options.cdda_volume  = (L2_audio[CDDA_VOLUME].current == 0) ? -1 : (L2_audio[CDDA_VOLUME].current - 1) * 5; 
 
	if (options.sound_enable == 0) 
	{ 
		L2_other[SOUND_SAMPLERATE].flag = DISABLE; 
		L2_other[SOUND_VOLUME].flag = DISABLE; 
		L2_other[SOUND_LATENCY].flag = DISABLE; 
	} 
} 
 
 
/*-------------------------- 
 	other options 
--------------------------*/ 
 
static void check_other_options(void) 
{ 
	int i; 
 
	for (i = 0; i < OTHER_OPTMAX; i++) L2_other[i].flag = ENABLE; 
 
	options.auto_pause  = L2_other[OTHER_PAUSE].current; 
	options.enable_mmx  = L2_other[OTHER_MMX].current; 
	options.enable_sse  = L2_other[OTHER_SSE].current; 
	options.sleep_time  = L2_other[OTHER_SLEEP].current - 1; 
	options.errorlog    = L2_other[OTHER_ERRORLOG].current; 
 
	if ((options.cpuid_result & HAS_MMX) == 0) 
	{ 
		options.enable_mmx = 0; 
		L2_other[OTHER_MMX].flag = DISABLE; 
	} 
	if ((options.cpuid_result & HAS_SSE) == 0) 
	{ 
		options.enable_sse = 0; 
		L2_other[OTHER_SSE].flag = DISABLE; 
	} 
} 
 
 
 
/*-------------------------------------------------------- 
 
	メニューの描画 
 
	引  数: struct menu_t *menu メニュー構造体のポインタ 
			int count           メニュー項目の数 
			int *curpos			カーソルの位置 
			int level			メニュー階層 
			int x1				メイン項目の横座標 
			int x2				サブ項目の横座標 
	戻り値: 現在のメニューの階層 
 
	※座標の指定は8ドット単位(3なら24ドット目から) 
 
 -------------------------------------------------------*/ 
 
#define ARROW_LEFT	1	// 左矢印フラグ 
#define ARROW_RIGHT	2	// 右矢印フラグ 
 
static const char *larrow = "\x1e";	//左矢印 
static const char *rarrow = "\x1f";	//右矢印 
 
static int draw_menu(struct menu_t *menu, int count, int *curpos, int level, int x1, int x2) 
{ 
	int i, arrowise = 0; 
 
	for (i = 0; i < count; i++) 
	{ 
		/* set font color */ 
		if (menu[i].flag == DISABLE) 
			ui_set_text_color(UI_COLOR_DISABLE); 
		else 
		if (i == *curpos) 
			ui_set_text_color(UI_COLOR_SELECT); 
		else 
			ui_set_text_color(UI_COLOR_NORMAL); 
 
 
		/* draw item */ 
		ui_draw_text(menu[i].item, x1, menu[i].y * FONT_YSIZE - 6); 
 
 
		if (menu[i].subitem) 
		{ 
			int  value = menu[i].current; 
			char *subitem = menu[i].subitem[value]; 
 
			/* draw sub item */ 
			ui_draw_text(subitem, x2, menu[i].y * FONT_YSIZE - 6); 
 
			if (i == *curpos) 
			{ 
				if (value > 0) 
				{ 
					ui_draw_text((char *)larrow, x2 - 2, menu[i].y * FONT_YSIZE - 6); 
					arrowise |= ARROW_LEFT; 
				} 
				if (menu[i].subitem[value + 1]) 
				{ 
					int len = strlen(subitem); 
					ui_draw_text((char *)rarrow, x2 + len + 1, menu[i].y * FONT_YSIZE - 6); 
					arrowise |= ARROW_RIGHT; 
				} 
			} 
		} 
	} 
 
	return arrowise; 
} 
 
 
/*------------------------------------------------------------------------ 
 
	メニューの移動 
 
	引  数: struct menu_t *menu 		メニュー構造体のポインタ 
			int count           		メニュー項目の数 
			int *curpos					カーソルの位置 
			int arrowise				矢印のフラグ 
			int level					メニュー階層 
			void (*check_func)(void))	前もしくは次の階層のメニュー関数 
 
	戻り値: なし 
 
 ------------------------------------------------------------------------*/ 
 
static void menu_move(struct menu_t *menu, int count, int *curpos, int arrowise, int level, void (*check_func)(void)) 
{ 
	if (input_ui_pressed(INPUT_UP, UI_ALL)) 
	{ 
		do 
		{ 
			if (--*curpos < 0) 
			{ 
				*curpos = count - 1; 
				break; 
			} 
		} while (menu[*curpos].flag == DISABLE); 
 
		osd_play_wav(move_wav); 
	} 
	else if (input_ui_pressed(INPUT_DOWN, UI_ALL)) 
	{ 
		do 
		{ 
			if (++*curpos == count) 
			{ 
				*curpos = 0; 
				break; 
			} 
		} while (menu[*curpos].flag == DISABLE); 
 
		osd_play_wav(move_wav); 
	} 
	else if (input_ui_pressed(INPUT_SELECT, UI_ALL)) 
	{ 
		if (*curpos == count -1) 
		{ 
			input_ui_wait_keyclear(4); 
			*curpos = 0; 
			current_menu_level = level - 1; 
			if (check_func) (*check_func)(); 
		} 
		else if (menu[*curpos].func) 
		{ 
			current_menu_level = level + 1; 
		} 
	} 
	else if (input_ui_pressed(INPUT_CANCEL, UI_ALL)) 
	{ 
		input_ui_wait_keyclear(4); 
		*curpos = 0; 
		current_menu_level = level - 1; 
		if (check_func) (*check_func)(); 
	} 
	else if (menu[*curpos].subitem) 
	{ 
		if ((arrowise & 1) && input_ui_pressed(INPUT_LEFT, UI_ALL)) 
		{ 
			menu[*curpos].current--; 
			osd_play_wav(move_wav); 
		} 
		if ((arrowise & 2) && input_ui_pressed(INPUT_RIGHT, UI_ALL)) 
		{ 
			menu[*curpos].current++; 
			osd_play_wav(move_wav); 
		} 
	} 
} 
 
 
/*-------------------------------------------------------- 
 
	各メニューの動作 
 
	引  数: なし 
	戻り値: なし 
 
  ※どの方向に動けるかチェックし、move_menu()に渡します 
 
 -------------------------------------------------------*/ 
 
/*-------------------------- 
 	machine menu (Level 1) 
--------------------------*/ 
 
static void level1_menu(void) 
{ 
	if (current_menu_level == 1) 
	{ 
		int arrowise; 
 
		if (cdrom_loading_state != CDROM_IDLE) 
			L1_menu[MENU_CDSPEED].flag = DISABLE; 
		else 
			L1_menu[MENU_CDSPEED].flag = ENABLE; 
 
		arrowise = draw_menu(L1_menu, MENU_OPTMAX, &L1_curpos, 1, MENU_ITEM_X, MENU_SUBITEM_X + 2); 
		menu_move(L1_menu, MENU_OPTMAX, &L1_curpos, arrowise, 1, check_machine_options); 
	} 
	else 
	{ 
		(*L1_menu[L1_curpos].func)(); 
	} 
} 
 
 
/*-------------------------- 
 	video menu (Level 2) 
--------------------------*/ 
 
static void level2_video(void) 
{ 
	int i, arrowise; 
 
	for (i = 0; i < VIDEO_OPTMAX; i++) L2_video[i].flag = ENABLE; 
 
	if (L2_video[VIDEO_FULLSCREEN].current == 0) 
		L2_video[VIDEO_TRIPLEBUF].flag = DISABLE; 
	else 
		L2_video[VIDEO_TRIPLEBUF].flag = ENABLE; 
 
	if (L2_video[VIDEO_SWSTRETCH].current == 1) 
		L2_video[VIDEO_SCANLINE].flag  = ENABLE; 
	else 
		L2_video[VIDEO_SCANLINE].flag  = DISABLE; 
 
	arrowise = draw_menu(L2_video, VIDEO_OPTMAX, &L2_curpos, 2, MENU_ITEM_X, MENU_SUBITEM_X + 2); 
	menu_move(L2_video, VIDEO_OPTMAX, &L2_curpos, arrowise, 2, check_video_options); 
} 
 
 
/*-------------------------- 
 	input menu (Level 2) 
--------------------------*/ 
 
static void level2_input(void) 
{ 
	if (current_menu_level == 2) 
	{ 
		int arrowise; 
 
		/*if (joyid[0] == 0) 
			L2_input[INPUT_P1HOTKEY].flag = DISABLE; 
		else 
			L2_input[INPUT_P1HOTKEY].flag = ENABLE; 
 
		if (joyid[1] == 0) 
			L2_input[INPUT_P2HOTKEY].flag = DISABLE; 
		else 
			L2_input[INPUT_P2HOTKEY].flag = ENABLE;*/ 
 
		arrowise = draw_menu(L2_input, INPUT_OPTMAX, &L2_curpos, 2, MENU_ITEM_X, MENU_SUBITEM_X + 2); 
		menu_move(L2_input, INPUT_OPTMAX, &L2_curpos, 0, 2, NULL); 
	} 
	else 
	{ 
		(*L2_input[L2_curpos].func)(); 
	} 
} 
 
 
/*-------------------------- 
 	audio menu (Level 2) 
--------------------------*/ 
 
static void level2_audio(void) 
{ 
	int i, arrowise; 
 
	for (i = 0; i < AUDIO_OPTMAX; i++) L2_audio[i].flag = ENABLE; 
 
	if (L2_audio[SOUND_SAMPLERATE].current != 0) 
	{ 
		L2_audio[SOUND_VOLUME].flag = ENABLE; 
		L2_audio[SOUND_LATENCY].flag = ENABLE; 
	} 
	else 
	{ 
		L2_audio[SOUND_VOLUME].flag = DISABLE; 
		L2_audio[SOUND_LATENCY].flag = DISABLE; 
	} 
 
	if (L2_audio[CDDA_ENABLE].current == 1) 
		L2_audio[CDDA_VOLUME].flag = ENABLE; 
	else 
		L2_audio[CDDA_VOLUME].flag = DISABLE; 
 
	arrowise = draw_menu(L2_audio, AUDIO_OPTMAX, &L2_curpos, 2, MENU_ITEM_X, MENU_SUBITEM_X + 2); 
	menu_move(L2_audio, AUDIO_OPTMAX, &L2_curpos, arrowise, 2, check_audio_options); 
} 
 
 
/*-------------------------- 
 	other menu (Level 2) 
--------------------------*/ 
 
static void level2_other(void) 
{ 
	int i, arrowise; 
 
	for (i = 0; i < OTHER_OPTMAX; i++) L2_other[i].flag = ENABLE; 
 
	if ((options.cpuid_result & HAS_MMX) == 0) 
		L2_other[OTHER_MMX].flag = DISABLE; 
 
	if ((options.cpuid_result & HAS_SSE) == 0) 
		L2_other[OTHER_SSE].flag = DISABLE; 
 
	arrowise = draw_menu(L2_other, OTHER_OPTMAX, &L2_curpos, 2, MENU_ITEM_X, MENU_SUBITEM_X + 2); 
	menu_move(L2_other, OTHER_OPTMAX, &L2_curpos, arrowise, 2, check_other_options); 
} 
 
 
/*---------------------------- 
 	keyboard menu (Level 3) 
----------------------------*/ 
 
static void level3_key(int player) 
{ 
	int i, count = 0; 
 
	while (padname[count]) count++; 
 
	for (i = 0; i <= count; i++) 
	{ 
		ui_set_text_color(i == L3_curpos); 
 
		if (i == count) 
		{ 
			ui_draw_text("RETURN TO PRIOR MENU", MENU_ITEM_X, MENU_BOTTOM * FONT_YSIZE - 6); 
		} 
		else 
		{ 
			char buf[32]; 
 
			sprintf(buf, "P%d %s", player + 1, padname[i]); 
			ui_draw_text(buf, MENU_ITEM_X, (MENU_TOP + i) * FONT_YSIZE - 6); 
 
			// 入力待ちでない時は設定されているキー名を表示 
			if (!input_change_wait || i != L3_curpos) 
				ui_draw_text(osd_keyboard_get_dispname(key_code[player][i]), MENU_SUBITEM_X, (MENU_TOP + i) * FONT_YSIZE - 6); 
		} 
	} 
	count++; 
 
	if (input_change_wait) 
	{ 
		if (input_ui_pressed(INPUT_CANCEL, UI_ALL)) 
		{ 
			input_change_wait = 0; 
		} 
		else 
		{ 
			for (i = 0; i < 256; i++) 
			{ 
				if (i != KEYCODE_ESC && i != KEYCODE_ENTER && i != KEYCODE_ENTER_PAD) 
				{ 
					if (osd_is_key_pressed(i)) 
					{ 
						key_code[player][L3_curpos] = i; 
						options.key[player][L3_curpos] = i; 
						osd_is_key_pressed_memory(i); 
						input_change_wait = 0; 
						input_ui_wait_keyclear(4); 
						break; 
					} 
				} 
			} 
		} 
	} 
	else 
	{ 
		if (input_ui_pressed(INPUT_UP, UI_ALL)) 
		{ 
			if (L3_curpos == 0) 
				L3_curpos = count - 1; 
			else 
				L3_curpos = (L3_curpos - 1) % count; 
			osd_play_wav(move_wav); 
		} 
		else 
		if (input_ui_pressed(INPUT_DOWN, UI_ALL)) 
		{ 
			if (L3_curpos == count - 1) 
				L3_curpos = 0; 
			else 
				L3_curpos = (L3_curpos + 1) % count; 
			osd_play_wav(move_wav); 
		} 
		else 
		if (input_ui_pressed(INPUT_SELECT, UI_ALL)) 
		{ 
			if (L3_curpos == count - 1) 
			{ 
				L3_curpos = 0; 
				current_menu_level = 2; 
			} 
			else if (!input_change_wait) 
			{ 
				input_ui_wait_keyclear(4); 
				input_change_wait = 1; 
			} 
		} 
		else 
		if (input_ui_pressed(INPUT_CANCEL, UI_ALL)) 
		{ 
			L3_curpos = 0; 
			current_menu_level = 2; 
		} 
	} 
} 
 
 
static void level3_p1key(void) 
{ 
	level3_key(0); 
} 
 
 
static void level3_p2key(void) 
{ 
	level3_key(1); 
} 
 
 
/*-------------------------------------------------------- 
 
	ゲームコントローラー設定メニュー 
 
	引  数: なし 
	戻り値: なし 
 
 -------------------------------------------------------*/ 
 
static void level3_joy(int player) 
{ 
	int i, count = 0, arrowise = 0; 
	char buf[32]; 
 
	while (padname[count]) count++; 
	count += 2; 
 
	// メニューの描画 
	for (i = 0; i < count; i++) 
	{ 
		// メニューの文字色を設定 
		if ((i > 0 && i < count - 1) && joyid[player] == 0) 
		{ 
			// ゲームコントローラーを使用しない場合はIDの変更以外を無効の色 
			ui_set_text_color(UI_COLOR_DISABLE); 
		} 
		else if (i == L3_curpos) 
		{ 
			// カーソルの位置の場合は選択の色 
			ui_set_text_color(UI_COLOR_SELECT); 
		} 
		else 
		{ 
			// 上記以外は標準の色 
			ui_set_text_color(UI_COLOR_NORMAL); 
		} 
 
		if (i == 0) 
		{ 
			int  value = joyid[player]; 
			char *subitem = subitem_joyid[value]; 
 
			// 一番上はID 
			ui_draw_text("JOYSTICK ID", MENU_ITEM_X, MENU_TOP * FONT_YSIZE - 6); 
			ui_draw_text(subitem, MENU_SUBITEM_X, MENU_TOP * FONT_YSIZE - 6); 
 
			if (i == L3_curpos) 
			{ 
				if (value > 0) 
				{ 
					ui_draw_text(larrow, MENU_SUBITEM_X - 2, MENU_TOP * FONT_YSIZE - 6); 
					arrowise |= ARROW_LEFT; 
				} 
				if (subitem_joyid[value + 1]) 
				{ 
					int len = strlen(subitem); 
					ui_draw_text(rarrow, MENU_SUBITEM_X + len + 1, MENU_TOP * FONT_YSIZE - 6); 
					arrowise |= ARROW_RIGHT; 
				} 
			} 
		} 
		else if (i == count - 1) 
		{ 
			// 一番下は前のメニューに戻る 
			ui_draw_text("RETURN TO PRIOR MENU", MENU_ITEM_X, MENU_BOTTOM * FONT_YSIZE - 6); 
		} 
		else 
		{ 
			// それ以外は設定されているボタン名を表示 
			sprintf(buf, "P%d %s", player + 1, padname[i - 1]); 
			ui_draw_text(buf, MENU_ITEM_X, (MENU_TOP + 1 + i) * FONT_YSIZE - 6); 
 
			// 入力待ちでない時は設定されているボタン名を表示 
			if (!input_change_wait || i != L3_curpos) 
			{ 
				int code = osd_restore_internal_joycode(joy_code[player][i - 1]); 
 
				ui_draw_text(osd_joystick_get_dispnamee(code), MENU_SUBITEM_X, (MENU_TOP + 1 + i) * FONT_YSIZE - 6); 
			} 
		} 
	} 
 
	if (input_change_wait) 
	{ 
		if (input_ui_pressed(INPUT_CANCEL, UI_ALL)) 
		{ 
			input_change_wait = 0; 
		} 
		else 
		{ 
			for (i = 0; i < JOY_UNKNOWN; i++) 
			{ 
				int code = osd_make_internal_joycode(player, i); 
 
				if (osd_is_joy_pressed(code)) 
				{ 
					joy_code[player][L3_curpos - 1] = code; 
					options.joy[player][L3_curpos - 1] = osd_restore_internal_joycode(code); 
					osd_is_joy_pressed_memory(code); 
					input_change_wait = 0; 
					input_ui_wait_keyclear(4); 
					break; 
				} 
			} 
		} 
	} 
	else 
	{ 
		if (input_ui_pressed(INPUT_UP, UI_ALL)) 
		{ 
			if (joyid[player] == 0) 
			{ 
				L3_curpos = L3_curpos ? 0 : count - 1; 
			} 
			else 
			{ 
				if (L3_curpos == 0) 
					L3_curpos = count - 1; 
				else 
					L3_curpos = (L3_curpos - 1) % count; 
			} 
			osd_play_wav(move_wav); 
		} 
		else 
		if (input_ui_pressed(INPUT_DOWN, UI_ALL)) 
		{ 
			if (joyid[player] == 0) 
			{ 
				L3_curpos = L3_curpos ? 0 : count - 1; 
			} 
			else 
			{ 
				if (L3_curpos == count - 1) 
					L3_curpos = 0; 
				else 
					L3_curpos = (L3_curpos + 1) % count; 
			} 
			osd_play_wav(move_wav); 
		} 
		else 
		if (input_ui_pressed(INPUT_SELECT, UI_ALL)) 
		{ 
			if (L3_curpos == count - 1) 
			{ 
				L3_curpos = 0; 
				current_menu_level = 2; 
			} 
			else if (!input_change_wait) 
			{ 
				input_ui_wait_keyclear(4); 
				input_change_wait = 1; 
			} 
		} 
		else 
		if (input_ui_pressed(INPUT_CANCEL, UI_ALL)) 
		{ 
			L3_curpos = 0; 
			current_menu_level = 2; 
		} 
		else 
		if (L3_curpos == 0) 
		{ 
			int update = 0; 
 
			if ((arrowise & 1) && input_ui_pressed(INPUT_LEFT, UI_ALL)) 
			{ 
				joyid[player]--; 
				update = 1; 
			} 
			if ((arrowise & 2) && input_ui_pressed(INPUT_RIGHT, UI_ALL)) 
			{ 
				joyid[player]++; 
				update = 1; 
			} 
			if (update) 
			{ 
				osd_play_wav(move_wav); 
				options.joyid[player] = joyid[player] - 1; 
				osd_set_joystick(); 
			} 
		} 
	} 
} 
 
 
/*-------------------------------------------------------- 
 
	プレイヤー1ゲームコントローラー設定メニュー 
 
	引  数: なし 
	戻り値: なし 
 
 -------------------------------------------------------*/ 
 
static void level3_p1joy(void) 
{ 
	level3_joy(PLAYER1); 
} 
 
 
/*-------------------------------------------------------- 
 
	プレイヤー2ゲームコントローラー設定メニュー 
 
	引  数: なし 
	戻り値: なし 
 
 -------------------------------------------------------*/ 
 
static void level3_p2joy(void) 
{ 
	level3_joy(PLAYER2); 
} 
 
 
/*-------------------------------------------------------- 
 
	ホットキー設定メニュー (ジョイスティックのみ) 
 
	引  数: なし 
	戻り値: なし 
 
 -------------------------------------------------------*/ 
 
static void level3_hotkey(int player) 
{ 
	int i, count = 0, arrowise = 0; 
	char buf[32]; 
 
	count = 10; 
 
	ui_set_text_color(UI_COLOR_NORMAL); 
	ui_draw_text("* CAN USE JOYSTICK ONLY *", MENU_ITEM_X, MENU_TOP * FONT_YSIZE - 6); 
 
	// メニューの描画 
	for (i = 0; i < count; i++) 
	{ 
		// メニューの文字色を設定 
		if (i == L3_curpos) 
		{ 
			// カーソルの位置の場合は選択の色 
			ui_set_text_color(UI_COLOR_SELECT); 
		} 
		else 
		{ 
			// 上記以外は標準の色 
			ui_set_text_color(UI_COLOR_NORMAL); 
		} 
 
		if (i >= 0 && i <= 3) 
		{ 
			sprintf(buf, "P%d HOTKEY%d", player + 1, i + 1); 
			ui_draw_text(buf, MENU_ITEM_X, (MENU_TOP + 2 + i) * FONT_YSIZE - 6); 
 
			// 入力待ちでない時は設定されているボタン名を表示 
			if (!input_change_wait || i != L3_curpos) 
			{ 
				int code = osd_restore_internal_joycode(joy_code[player][i + 10]); 
 
				ui_draw_text(osd_joystick_get_dispnamee(code), MENU_SUBITEM_X, (MENU_TOP + 2 + i) * FONT_YSIZE - 6); 
			} 
		} 
		else if (i >= 4 && i <= 7) 
		{ 
			int  value = options.hotkey[player][i - 4]; 
 
			sprintf(buf, "HOTKEY%d TYPE", i - 3); 
			ui_draw_text(buf, MENU_ITEM_X, (MENU_TOP + 3 + i) * FONT_YSIZE - 6); 
 
			ui_draw_text(subitem_hotkey[value], MENU_SUBITEM_X, (MENU_TOP + 3 + i) * FONT_YSIZE - 6); 
 
			if (i == L3_curpos) 
			{ 
				if (value > 0) 
				{ 
					ui_draw_text(larrow, MENU_SUBITEM_X - 2, (MENU_TOP + 3 + i) * FONT_YSIZE - 6); 
					arrowise |= ARROW_LEFT; 
				} 
				if (subitem_hotkey[value + 1]) 
				{ 
					int len = strlen(subitem_hotkey[value]); 
					ui_draw_text(rarrow, MENU_SUBITEM_X + len + 1, (MENU_TOP + 3 + i) * FONT_YSIZE - 6); 
					arrowise |= ARROW_RIGHT; 
				} 
			} 
		} 
		else if (i == 8) 
		{ 
			int  value = options.afinterval[player]; 
 
			ui_draw_text("AF INTERVAL", MENU_ITEM_X, (MENU_TOP + 3 + i) * FONT_YSIZE - 6); 
 
			sprintf(buf, "%d frame(s)", value); 
			ui_draw_text(buf, MENU_SUBITEM_X, (MENU_TOP + 3 + i) * FONT_YSIZE - 6); 
 
			if (i == L3_curpos) 
			{ 
				if (value > 0) 
				{ 
					ui_draw_text(larrow, MENU_SUBITEM_X - 2, (MENU_TOP + 3 + i) * FONT_YSIZE - 6); 
					arrowise |= ARROW_LEFT; 
				} 
				if (value < 20) 
				{ 
					int len = strlen(buf); 
					ui_draw_text(rarrow, MENU_SUBITEM_X + len + 1, (MENU_TOP + 3 + i) * FONT_YSIZE - 6); 
					arrowise |= ARROW_RIGHT; 
				} 
			} 
		} 
		else if (i == count - 1) 
		{ 
			// 一番下は前のメニューに戻る 
			ui_draw_text("RETURN TO PRIOR MENU", MENU_ITEM_X, MENU_BOTTOM * FONT_YSIZE - 6); 
		} 
	} 
 
	if (input_change_wait) 
	{ 
		if (input_ui_pressed(INPUT_CANCEL, UI_ALL)) 
		{ 
			input_change_wait = 0; 
		} 
		else 
		{ 
			for (i = 0; i < JOY_UNKNOWN; i++) 
			{ 
				int code = osd_make_internal_joycode(player, i); 
 
				if (osd_is_joy_pressed(code)) 
				{ 
					joy_code[player][L3_curpos + 10] = code; 
					options.joy[player][L3_curpos + 10] = osd_restore_internal_joycode(code); 
					osd_is_joy_pressed_memory(code); 
					input_change_wait = 0; 
					input_ui_wait_keyclear(4); 
					break; 
				} 
			} 
		} 
	} 
	else 
	{ 
		if (input_ui_pressed(INPUT_UP, UI_ALL)) 
		{ 
			if (L3_curpos == 0) 
				L3_curpos = count - 1; 
			else 
				L3_curpos = (L3_curpos - 1) % count; 
			osd_play_wav(move_wav); 
		} 
		else 
		if (input_ui_pressed(INPUT_DOWN, UI_ALL)) 
		{ 
			if (L3_curpos == count - 1) 
				L3_curpos = 0; 
			else 
				L3_curpos = (L3_curpos + 1) % count; 
 
			osd_play_wav(move_wav); 
		} 
		else 
		if (L3_curpos >= 4 && L3_curpos <= 7) 
		{ 
			int update = 0; 
			int no = L3_curpos - 4; 
 
			if ((arrowise & 1) && input_ui_pressed(INPUT_LEFT, UI_ALL)) 
			{ 
				options.hotkey[player][no]--; 
				update = 1; 
			} 
			if ((arrowise & 2) && input_ui_pressed(INPUT_RIGHT, UI_ALL)) 
			{ 
				options.hotkey[player][no]++; 
				update = 1; 
			} 
			if (update) 
			{ 
				osd_play_wav(move_wav); 
			} 
		} 
		else 
		if (L3_curpos == 8) 
		{ 
			int update = 0; 
 
			if ((arrowise & 1) && input_ui_pressed(INPUT_LEFT, UI_ALL)) 
			{ 
				options.afinterval[player]--; 
				update = 1; 
			} 
			if ((arrowise & 2) && input_ui_pressed(INPUT_RIGHT, UI_ALL)) 
			{ 
				options.afinterval[player]++; 
				update = 1; 
			} 
			if (update) 
			{ 
				osd_play_wav(move_wav); 
			} 
		} 
		else 
		if (input_ui_pressed(INPUT_SELECT, UI_ALL)) 
		{ 
			if (L3_curpos == count - 1) 
			{ 
				L3_curpos = 0; 
				current_menu_level = 2; 
			} 
			else if (!input_change_wait) 
			{ 
				input_ui_wait_keyclear(4); 
				input_change_wait = 1; 
			} 
		} 
		else 
		if (input_ui_pressed(INPUT_CANCEL, UI_ALL)) 
		{ 
			L3_curpos = 0; 
			current_menu_level = 2; 
		} 
	} 
} 
 
 
/*-------------------------------------------------------- 
 
	プレイヤー1ホットキー設定メニュー 
 
	引  数: なし 
	戻り値: なし 
 
 -------------------------------------------------------*/ 
 
static void level3_p1hotkey(void) 
{ 
	level3_hotkey(PLAYER1); 
} 
 
 
/*-------------------------------------------------------- 
 
	プレイヤー2ホットキー設定メニュー 
 
	引  数: なし 
	戻り値: なし 
 
 -------------------------------------------------------*/ 
 
static void level3_p2hotkey(void) 
{ 
	level3_hotkey(PLAYER2); 
}