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);
}