/*\r
- * (C) Gražvydas "notaz" Ignotas, 2006-2011\r
+ * (C) Gražvydas "notaz" Ignotas, 2006-2012\r
*\r
* This work is licensed under the terms of any of these licenses\r
* (at your option):\r
* - GNU GPL, version 2 or later.\r
* - GNU LGPL, version 2.1 or later.\r
+ * - MAME license.\r
* See the COPYING file in the top-level directory.\r
*/\r
\r
#endif\r
\r
static unsigned char *menu_font_data = NULL;\r
-static int menu_text_color = 0xffff; // default to white\r
+static int menu_text_color = 0xfffe; // default to white\r
static int menu_sel_color = -1; // disabled\r
\r
/* note: these might become non-constant in future */\r
static const int me_sfont_w = 6, me_sfont_h = 10;\r
#endif\r
\r
+static int g_menu_filter_off;\r
+static int g_border_style;\r
+static int border_left, border_right, border_top, border_bottom;\r
+\r
// draws text to current bbp16 screen\r
static void text_out16_(int x, int y, const char *text, int color)\r
{\r
}\r
dest += me_mfont_w;\r
}\r
+\r
+ if (x < border_left)\r
+ border_left = x;\r
+ if (x + i * me_mfont_w > border_right)\r
+ border_right = x + i * me_mfont_w;\r
+ if (y < border_top)\r
+ border_top = y;\r
+ if (y + me_mfont_h > border_bottom)\r
+ border_bottom = y + me_mfont_h;\r
}\r
\r
void text_out16(int x, int y, const char *texto, ...)\r
return c;\r
}\r
\r
-void menu_init(void)\r
+void menu_init_base(void)\r
{\r
int i, c, l;\r
unsigned char *fd, *fds;\r
setlocale(LC_TIME, "");\r
}\r
\r
-static void menu_draw_begin(int need_bg)\r
-{\r
- plat_video_menu_begin();\r
- if (need_bg)\r
- memcpy(g_menuscreen_ptr, g_menubg_ptr, g_menuscreen_w * g_menuscreen_h * 2);\r
-}\r
-\r
-static void menu_draw_end(void)\r
-{\r
- plat_video_menu_end();\r
-}\r
-\r
static void menu_darken_bg(void *dst, void *src, int pixels, int darker)\r
{\r
unsigned int *dest = dst;\r
}\r
}\r
\r
+static void menu_darken_text_bg(void)\r
+{\r
+ int x, y, xmin, xmax, ymax, ls;\r
+ unsigned short *screen = g_menuscreen_ptr;\r
+\r
+ xmin = border_left - 3;\r
+ if (xmin < 0)\r
+ xmin = 0;\r
+ xmax = border_right + 2;\r
+ if (xmax > g_menuscreen_w - 1)\r
+ xmax = g_menuscreen_w - 1;\r
+\r
+ y = border_top - 3;\r
+ if (y < 0)\r
+ y = 0;\r
+ ymax = border_bottom + 2;\r
+ if (ymax > g_menuscreen_h - 1)\r
+ ymax = g_menuscreen_h - 1;\r
+\r
+ for (x = xmin; x <= xmax; x++)\r
+ screen[y * g_menuscreen_w + x] = 0xa514;\r
+ for (y++; y < ymax; y++)\r
+ {\r
+ ls = y * g_menuscreen_w;\r
+ screen[ls + xmin] = 0xffff;\r
+ for (x = xmin + 1; x < xmax; x++)\r
+ {\r
+ unsigned int p = screen[ls + x];\r
+ if (p != menu_text_color)\r
+ screen[ls + x] = ((p&0xf79e)>>1) - ((p&0xc618)>>3);\r
+ }\r
+ screen[ls + xmax] = 0xffff;\r
+ }\r
+ ls = y * g_menuscreen_w;\r
+ for (x = xmin; x <= xmax; x++)\r
+ screen[ls + x] = 0xffff;\r
+}\r
+\r
+static int borders_pending;\r
+\r
+static void menu_reset_borders(void)\r
+{\r
+ border_left = g_menuscreen_w;\r
+ border_right = 0;\r
+ border_top = g_menuscreen_h;\r
+ border_bottom = 0;\r
+}\r
+\r
+static void menu_draw_begin(int need_bg, int no_borders)\r
+{\r
+ plat_video_menu_begin();\r
+\r
+ menu_reset_borders();\r
+ borders_pending = g_border_style && !no_borders;\r
+\r
+ if (need_bg) {\r
+ if (g_border_style && no_borders) {\r
+ menu_darken_bg(g_menuscreen_ptr, g_menubg_ptr,\r
+ g_menuscreen_w * g_menuscreen_h, 1);\r
+ }\r
+ else {\r
+ memcpy(g_menuscreen_ptr, g_menubg_ptr,\r
+ g_menuscreen_w * g_menuscreen_h * 2);\r
+ }\r
+ }\r
+}\r
+\r
+static void menu_draw_end(void)\r
+{\r
+ if (borders_pending)\r
+ menu_darken_text_bg();\r
+ plat_video_menu_end();\r
+}\r
+\r
+static void menu_separation(void)\r
+{\r
+ if (borders_pending) {\r
+ menu_darken_text_bg();\r
+ menu_reset_borders();\r
+ }\r
+}\r
+\r
static int me_id2offset(const menu_entry *ent, menu_id id)\r
{\r
int i;\r
#endif\r
\r
/* draw */\r
- menu_draw_begin(1);\r
+ menu_draw_begin(1, 0);\r
menu_draw_selection(x, y + vi_sel_ln * me_mfont_h, w);\r
x += me_mfont_w * 2;\r
\r
y += me_mfont_h;\r
}\r
\r
+ menu_separation();\r
+\r
/* display help or message if we have one */\r
h = (g_menuscreen_h - h) / 2; // bottom area height\r
if (menu_error_msg[0] != 0) {\r
smalltext_out16(5, g_menuscreen_h - (l * me_sfont_h + 4), tmp, 0xffff);\r
}\r
\r
+ menu_separation();\r
+\r
if (draw_more != NULL)\r
draw_more();\r
\r
if (x < 0) x = 0;\r
if (y < 0) y = 0;\r
\r
- menu_draw_begin(1);\r
+ menu_draw_begin(1, 0);\r
\r
for (p = msg; *p != 0 && y <= g_menuscreen_h - me_mfont_h; y += me_mfont_h) {\r
text_out16(x, y, p);\r
p++;\r
}\r
\r
+ menu_separation();\r
+\r
if (draw_more != NULL)\r
draw_more();\r
\r
const char *nm;\r
char tmp[64];\r
\r
- menu_draw_begin(1);\r
+ menu_draw_begin(1, 0);\r
\r
len = strlen(fname);\r
if (len > g_menuscreen_w / me_sfont_w)\r
\r
// -------------- ROM selector --------------\r
\r
-static void draw_dirlist(char *curdir, struct dirent **namelist, int n, int sel)\r
+static void draw_dirlist(char *curdir, struct dirent **namelist,\r
+ int n, int sel, int show_help)\r
{\r
int max_cnt, start, i, x, pos;\r
void *darken_ptr;\r
+ char buff[64];\r
\r
max_cnt = g_menuscreen_h / me_sfont_h;\r
start = max_cnt / 2 - sel;\r
n--; // exclude current dir (".")\r
\r
- menu_draw_begin(1);\r
+ menu_draw_begin(1, 1);\r
\r
// if (!rom_loaded)\r
// menu_darken_bg(gp2x_screen, 320*240, 0);\r
}\r
}\r
smalltext_out16(5, max_cnt/2 * me_sfont_h, ">", 0xffff);\r
+\r
+ if (show_help) {\r
+ darken_ptr = (short *)g_menuscreen_ptr\r
+ + g_menuscreen_w * (g_menuscreen_h - me_sfont_h * 5 / 2);\r
+ menu_darken_bg(darken_ptr, darken_ptr,\r
+ g_menuscreen_w * (me_sfont_h * 5 / 2), 1);\r
+\r
+ snprintf(buff, sizeof(buff), "%s - select, %s - back",\r
+ in_get_key_name(-1, -PBTN_MOK), in_get_key_name(-1, -PBTN_MBACK));\r
+ smalltext_out16(x, g_menuscreen_h - me_sfont_h * 2 - 2, buff, 0xe78c);\r
+ snprintf(buff, sizeof(buff), g_menu_filter_off ?\r
+ "%s - hide unknown files" : "%s - show all files",\r
+ in_get_key_name(-1, -PBTN_MA3));\r
+ smalltext_out16(x, g_menuscreen_h - me_sfont_h * 1 - 2, buff, 0xe78c);\r
+ }\r
+\r
menu_draw_end();\r
}\r
\r
return alphasort(d1, d2);\r
}\r
\r
+static const char **filter_exts_internal;\r
+\r
static int scandir_filter(const struct dirent *ent)\r
{\r
- const char *p;\r
+ const char **filter = filter_exts_internal;\r
+ const char *ext;\r
int i;\r
\r
- if (ent == NULL || ent->d_name == NULL) return 0;\r
- if (strlen(ent->d_name) < 5) return 1;\r
+ if (ent == NULL || ent->d_name == NULL)\r
+ return 0;\r
\r
- p = ent->d_name + strlen(ent->d_name) - 4;\r
+ if (ent->d_type == DT_DIR)\r
+ return 1;\r
\r
- for (i = 0; i < array_size(filter_exts); i++)\r
- if (strcmp(p, filter_exts[i]) == 0)\r
- return 0;\r
+ ext = strrchr(ent->d_name, '.');\r
+ if (ext == NULL)\r
+ return 0;\r
+\r
+ ext++;\r
+ for (i = 0; filter[i] != NULL; i++)\r
+ if (strcasecmp(ext, filter[i]) == 0)\r
+ return 1;\r
\r
- return 1;\r
+ return 0;\r
}\r
\r
static int dirent_seek_char(struct dirent **namelist, int len, int sel, char c)\r
return i - 1;\r
}\r
\r
-static char *menu_loop_romsel(char *curr_path, int len)\r
+static const char *menu_loop_romsel(char *curr_path, int len,\r
+ const char **filter_exts,\r
+ int (*extra_filter)(struct dirent **namelist, int count,\r
+ const char *basedir))\r
{\r
- struct dirent **namelist;\r
- int n, inp, sel = 0;\r
- char *ret = NULL, *fname = NULL;\r
+ static char rom_fname_reload[256]; // used for return\r
+ char sel_fname[256];\r
+ int (*filter)(const struct dirent *);\r
+ struct dirent **namelist = NULL;\r
+ int n = 0, inp = 0, sel = 0, show_help = 0;\r
+ char *curr_path_restore = NULL;\r
+ const char *ret = NULL;\r
char cinp;\r
\r
-rescan:\r
+ filter_exts_internal = filter_exts;\r
+ sel_fname[0] = 0;\r
+\r
// is this a dir or a full path?\r
if (!plat_is_dir(curr_path)) {\r
- char *p = curr_path + strlen(curr_path) - 1;\r
- for (; p > curr_path && *p != '/'; p--)\r
- ;\r
- *p = 0;\r
- fname = p+1;\r
+ char *p = strrchr(curr_path, '/');\r
+ if (p != NULL) {\r
+ *p = 0;\r
+ curr_path_restore = p;\r
+ snprintf(sel_fname, sizeof(sel_fname), "%s", p + 1);\r
+ }\r
+\r
+ if (rom_fname_reload[0] == 0)\r
+ show_help = 2;\r
+ }\r
+\r
+rescan:\r
+ if (namelist != NULL) {\r
+ while (n-- > 0)\r
+ free(namelist[n]);\r
+ free(namelist);\r
+ namelist = NULL;\r
}\r
\r
- n = scandir(curr_path, &namelist, scandir_filter, (void *)scandir_cmp);\r
+ filter = NULL;\r
+ if (!g_menu_filter_off)\r
+ filter = scandir_filter;\r
+\r
+ n = scandir(curr_path, &namelist, filter, (void *)scandir_cmp);\r
if (n < 0) {\r
char *t;\r
lprintf("menu_loop_romsel failed, dir: %s\n", curr_path);\r
t = getcwd(curr_path, len);\r
if (t == NULL)\r
plat_get_root_dir(curr_path, len);\r
- n = scandir(curr_path, &namelist, scandir_filter, (void *)scandir_cmp);\r
+ n = scandir(curr_path, &namelist, filter, (void *)scandir_cmp);\r
if (n < 0) {\r
// oops, we failed\r
lprintf("menu_loop_romsel failed, dir: %s\n", curr_path);\r
}\r
}\r
\r
- // try to find sel\r
+ if (!g_menu_filter_off && extra_filter != NULL)\r
+ n = extra_filter(namelist, n, curr_path);\r
+\r
+ // try to find selected file\r
// note: we don't show '.' so sel is namelist index - 1\r
- if (fname != NULL) {\r
+ sel = 0;\r
+ if (sel_fname[0] != 0) {\r
int i;\r
for (i = 1; i < n; i++) {\r
char *dname = namelist[i]->d_name;\r
- if (dname[0] == fname[0] && strcmp(dname, fname) == 0) {\r
+ if (dname[0] == sel_fname[0] && strcmp(dname, sel_fname) == 0) {\r
sel = i - 1;\r
break;\r
}\r
}\r
\r
/* make sure action buttons are not pressed on entering menu */\r
- draw_dirlist(curr_path, namelist, n, sel);\r
+ draw_dirlist(curr_path, namelist, n, sel, show_help);\r
while (in_menu_wait_any(NULL, 50) & (PBTN_MOK|PBTN_MBACK|PBTN_MENU))\r
;\r
\r
for (;;)\r
{\r
- draw_dirlist(curr_path, namelist, n, sel);\r
- inp = in_menu_wait(PBTN_UP|PBTN_DOWN|PBTN_LEFT|PBTN_RIGHT|\r
- PBTN_L|PBTN_R|PBTN_MA2|PBTN_MOK|PBTN_MBACK|PBTN_MENU|PBTN_CHAR, &cinp, 33);\r
+ draw_dirlist(curr_path, namelist, n, sel, show_help);\r
+ inp = in_menu_wait(PBTN_UP|PBTN_DOWN|PBTN_LEFT|PBTN_RIGHT\r
+ | PBTN_L|PBTN_R|PBTN_MA2|PBTN_MA3|PBTN_MOK|PBTN_MBACK\r
+ | PBTN_MENU|PBTN_CHAR, &cinp, 33);\r
if (inp & PBTN_UP ) { sel--; if (sel < 0) sel = n-2; }\r
if (inp & PBTN_DOWN) { sel++; if (sel > n-2) sel = 0; }\r
if (inp & PBTN_LEFT) { sel-=10; if (sel < 0) sel = 0; }\r
if (inp & PBTN_RIGHT) { sel+=10; if (sel > n-2) sel = n-2; }\r
if (inp & PBTN_R) { sel+=24; if (sel > n-2) sel = n-2; }\r
if (inp & PBTN_CHAR) sel = dirent_seek_char(namelist, n, sel, cinp);\r
+ if (inp & PBTN_MA3) {\r
+ g_menu_filter_off = !g_menu_filter_off;\r
+ snprintf(sel_fname, sizeof(sel_fname), "%s",\r
+ namelist[sel+1]->d_name);\r
+ goto rescan;\r
+ }\r
if ((inp & PBTN_MOK) || (inp & (PBTN_MENU|PBTN_MA2)) == (PBTN_MENU|PBTN_MA2))\r
{\r
again:\r
if (namelist[sel+1]->d_type == DT_REG)\r
{\r
- strcpy(rom_fname_reload, curr_path);\r
- strcat(rom_fname_reload, "/");\r
- strcat(rom_fname_reload, namelist[sel+1]->d_name);\r
+ snprintf(rom_fname_reload, sizeof(rom_fname_reload),\r
+ "%s/%s", curr_path, namelist[sel+1]->d_name);\r
if (inp & PBTN_MOK) { // return sel\r
ret = rom_fname_reload;\r
break;\r
}\r
do_delete(rom_fname_reload, namelist[sel+1]->d_name);\r
- if (n > 0) {\r
- while (n--) free(namelist[n]);\r
- free(namelist);\r
- }\r
goto rescan;\r
}\r
else if (namelist[sel+1]->d_type == DT_DIR)\r
strcat(newdir, "/");\r
strcat(newdir, namelist[sel+1]->d_name);\r
}\r
- ret = menu_loop_romsel(newdir, newlen);\r
+ ret = menu_loop_romsel(newdir, newlen, filter_exts, extra_filter);\r
free(newdir);\r
break;\r
}\r
{\r
// unknown file type, happens on NTFS mounts. Try to guess.\r
FILE *tstf; int tmp;\r
- strcpy(rom_fname_reload, curr_path);\r
- strcat(rom_fname_reload, "/");\r
- strcat(rom_fname_reload, namelist[sel+1]->d_name);\r
+ snprintf(rom_fname_reload, sizeof(rom_fname_reload),\r
+ "%s/%s", curr_path, namelist[sel+1]->d_name);\r
tstf = fopen(rom_fname_reload, "rb");\r
if (tstf != NULL)\r
{\r
}\r
if (inp & PBTN_MBACK)\r
break;\r
+\r
+ if (show_help > 0)\r
+ show_help--;\r
}\r
\r
if (n > 0) {\r
- while (n--) free(namelist[n]);\r
+ while (n-- > 0)\r
+ free(namelist[n]);\r
free(namelist);\r
}\r
\r
// restore curr_path\r
- if (fname != NULL) {\r
- n = strlen(curr_path);\r
- if (curr_path + n + 1 == fname)\r
- curr_path[n] = '/';\r
- }\r
+ if (curr_path_restore != NULL)\r
+ *curr_path_restore = '/';\r
\r
return ret;\r
}\r
x = 12 + me_mfont_w * 2;\r
#endif\r
\r
- menu_draw_begin(1);\r
+ menu_draw_begin(1, 1);\r
\r
text_out16(x, y, is_loading ? "Load state" : "Save state");\r
y += 3 * me_mfont_h;\r
if (menu_sel < STATE_SLOT_COUNT) {\r
state_slot = menu_sel;\r
if (emu_save_load_game(is_loading, 0)) {\r
- me_update_msg(is_loading ? "Load failed" : "Save failed");\r
+ menu_update_msg(is_loading ? "Load failed" : "Save failed");\r
break;\r
}\r
ret = 1;\r
if (x < me_mfont_w * 2)\r
x = me_mfont_w * 2;\r
\r
- menu_draw_begin(1);\r
+ menu_draw_begin(1, 0);\r
if (player_idx >= 0)\r
text_out16(x, y, "Player %i controls", player_idx + 1);\r
else\r
text_out16(x, y, "%s : %s", opts[i].name,\r
action_binds(player_idx, opts[i].mask, dev_id));\r
\r
+ menu_separation();\r
+\r
if (dev_id < 0)\r
dev_name = "(all devices)";\r
else\r
- dev_name = in_get_dev_name(dev_id, 1, 1);\r
+ dev_name = in_get_dev_name(dev_id, 0, 1);\r
w = strlen(dev_name) * me_mfont_w;\r
if (w < 30 * me_mfont_w)\r
w = 30 * me_mfont_w;\r
for (i = 0, dev_id--; i < IN_MAX_DEVS + 1; i++, dev_id--) {\r
if (dev_id < -1)\r
dev_id = IN_MAX_DEVS - 1;\r
- if (dev_id == -1 || in_get_dev_name(dev_id, 1, 0) != NULL)\r
+ if (dev_id == -1 || in_get_dev_name(dev_id, 0, 0) != NULL)\r
break;\r
}\r
continue;\r
for (i = 0, dev_id++; i < IN_MAX_DEVS; i++, dev_id++) {\r
if (dev_id >= IN_MAX_DEVS)\r
dev_id = -1;\r
- if (dev_id == -1 || in_get_dev_name(dev_id, 1, 0) != NULL)\r
+ if (dev_id == -1 || in_get_dev_name(dev_id, 0, 0) != NULL)\r
break;\r
}\r
continue;\r