X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=menu.c;h=2e97f0640229ad96605564a76de20b1fb57871c4;hb=ec90b021373a7f9dd02c593f656eddc2b36b5252;hp=3acab62c34ffdb2f685e55bb84bd14596707c5ba;hpb=a86e9a3e58f55bf49d99dfd5e5d6413e17149593;p=libpicofe.git diff --git a/menu.c b/menu.c index 3acab62..2e97f06 100644 --- a/menu.c +++ b/menu.c @@ -1,10 +1,11 @@ /* - * (C) Gražvydas "notaz" Ignotas, 2006-2011 + * (C) Gražvydas "notaz" Ignotas, 2006-2012 * * This work is licensed under the terms of any of these licenses * (at your option): * - GNU GPL, version 2 or later. * - GNU LGPL, version 2.1 or later. + * - MAME license. * See the COPYING file in the top-level directory. */ @@ -30,13 +31,13 @@ void *g_menuscreen_ptr; void *g_menubg_src_ptr; void *g_menubg_ptr; -#if !MSCREEN_SIZE_FIXED int g_menuscreen_w; int g_menuscreen_h; -#endif + +int g_autostateld_opt; static unsigned char *menu_font_data = NULL; -static int menu_text_color = 0xffff; // default to white +static int menu_text_color = 0xfffe; // default to white static int menu_sel_color = -1; // disabled /* note: these might become non-constant in future */ @@ -48,6 +49,10 @@ static const int me_mfont_w = 8, me_mfont_h = 10; static const int me_sfont_w = 6, me_sfont_h = 10; #endif +static int g_menu_filter_off; +static int g_border_style; +static int border_left, border_right, border_top, border_bottom; + // draws text to current bbp16 screen static void text_out16_(int x, int y, const char *text, int color) { @@ -106,6 +111,15 @@ static void text_out16_(int x, int y, const char *text, int color) } dest += me_mfont_w; } + + if (x < border_left) + border_left = x; + if (x + i * me_mfont_w > border_right) + border_right = x + i * me_mfont_w; + if (y < border_top) + border_top = y; + if (y + me_mfont_h > border_bottom) + border_bottom = y + me_mfont_h; } void text_out16(int x, int y, const char *texto, ...) @@ -223,7 +237,7 @@ static char tolower_simple(char c) return c; } -void menu_init(void) +void menu_init_base(void) { int i, c, l; unsigned char *fd, *fds; @@ -323,18 +337,6 @@ void menu_init(void) setlocale(LC_TIME, ""); } -static void menu_draw_begin(int need_bg) -{ - plat_video_menu_begin(); - if (need_bg) - memcpy(g_menuscreen_ptr, g_menubg_ptr, g_menuscreen_w * g_menuscreen_h * 2); -} - -static void menu_draw_end(void) -{ - plat_video_menu_end(); -} - static void menu_darken_bg(void *dst, void *src, int pixels, int darker) { unsigned int *dest = dst; @@ -358,6 +360,88 @@ static void menu_darken_bg(void *dst, void *src, int pixels, int darker) } } +static void menu_darken_text_bg(void) +{ + int x, y, xmin, xmax, ymax, ls; + unsigned short *screen = g_menuscreen_ptr; + + xmin = border_left - 3; + if (xmin < 0) + xmin = 0; + xmax = border_right + 2; + if (xmax > g_menuscreen_w - 1) + xmax = g_menuscreen_w - 1; + + y = border_top - 3; + if (y < 0) + y = 0; + ymax = border_bottom + 2; + if (ymax > g_menuscreen_h - 1) + ymax = g_menuscreen_h - 1; + + for (x = xmin; x <= xmax; x++) + screen[y * g_menuscreen_w + x] = 0xa514; + for (y++; y < ymax; y++) + { + ls = y * g_menuscreen_w; + screen[ls + xmin] = 0xffff; + for (x = xmin + 1; x < xmax; x++) + { + unsigned int p = screen[ls + x]; + if (p != menu_text_color) + screen[ls + x] = ((p&0xf79e)>>1) - ((p&0xc618)>>3); + } + screen[ls + xmax] = 0xffff; + } + ls = y * g_menuscreen_w; + for (x = xmin; x <= xmax; x++) + screen[ls + x] = 0xffff; +} + +static int borders_pending; + +static void menu_reset_borders(void) +{ + border_left = g_menuscreen_w; + border_right = 0; + border_top = g_menuscreen_h; + border_bottom = 0; +} + +static void menu_draw_begin(int need_bg, int no_borders) +{ + plat_video_menu_begin(); + + menu_reset_borders(); + borders_pending = g_border_style && !no_borders; + + if (need_bg) { + if (g_border_style && no_borders) { + menu_darken_bg(g_menuscreen_ptr, g_menubg_ptr, + g_menuscreen_w * g_menuscreen_h, 1); + } + else { + memcpy(g_menuscreen_ptr, g_menubg_ptr, + g_menuscreen_w * g_menuscreen_h * 2); + } + } +} + +static void menu_draw_end(void) +{ + if (borders_pending) + menu_darken_text_bg(); + plat_video_menu_end(); +} + +static void menu_separation(void) +{ + if (borders_pending) { + menu_darken_text_bg(); + menu_reset_borders(); + } +} + static int me_id2offset(const menu_entry *ent, menu_id id) { int i; @@ -487,7 +571,7 @@ static void me_draw(const menu_entry *entries, int sel, void (*draw_more)(void)) #endif /* draw */ - menu_draw_begin(1); + menu_draw_begin(1, 0); menu_draw_selection(x, y + vi_sel_ln * me_mfont_h, w); x += me_mfont_w * 2; @@ -548,6 +632,8 @@ static void me_draw(const menu_entry *entries, int sel, void (*draw_more)(void)) y += me_mfont_h; } + menu_separation(); + /* display help or message if we have one */ h = (g_menuscreen_h - h) / 2; // bottom area height if (menu_error_msg[0] != 0) { @@ -569,6 +655,8 @@ static void me_draw(const menu_entry *entries, int sel, void (*draw_more)(void)) smalltext_out16(5, g_menuscreen_h - (l * me_sfont_h + 4), tmp, 0xffff); } + menu_separation(); + if (draw_more != NULL) draw_more(); @@ -710,7 +798,7 @@ static void draw_menu_message(const char *msg, void (*draw_more)(void)) if (x < 0) x = 0; if (y < 0) y = 0; - menu_draw_begin(1); + menu_draw_begin(1, 0); for (p = msg; *p != 0 && y <= g_menuscreen_h - me_mfont_h; y += me_mfont_h) { text_out16(x, y, p); @@ -721,6 +809,8 @@ static void draw_menu_message(const char *msg, void (*draw_more)(void)) p++; } + menu_separation(); + if (draw_more != NULL) draw_more(); @@ -735,7 +825,7 @@ static void do_delete(const char *fpath, const char *fname) const char *nm; char tmp[64]; - menu_draw_begin(1); + menu_draw_begin(1, 0); len = strlen(fname); if (len > g_menuscreen_w / me_sfont_w) @@ -764,16 +854,18 @@ static void do_delete(const char *fpath, const char *fname) // -------------- ROM selector -------------- -static void draw_dirlist(char *curdir, struct dirent **namelist, int n, int sel) +static void draw_dirlist(char *curdir, struct dirent **namelist, + int n, int sel, int show_help) { int max_cnt, start, i, x, pos; void *darken_ptr; + char buff[64]; max_cnt = g_menuscreen_h / me_sfont_h; start = max_cnt / 2 - sel; n--; // exclude current dir (".") - menu_draw_begin(1); + menu_draw_begin(1, 1); // if (!rom_loaded) // menu_darken_bg(gp2x_screen, 320*240, 0); @@ -797,6 +889,28 @@ static void draw_dirlist(char *curdir, struct dirent **namelist, int n, int sel) } } smalltext_out16(5, max_cnt/2 * me_sfont_h, ">", 0xffff); + + if (show_help) { + darken_ptr = (short *)g_menuscreen_ptr + + g_menuscreen_w * (g_menuscreen_h - me_sfont_h * 5 / 2); + menu_darken_bg(darken_ptr, darken_ptr, + g_menuscreen_w * (me_sfont_h * 5 / 2), 1); + + snprintf(buff, sizeof(buff), "%s - select, %s - back", + in_get_key_name(-1, -PBTN_MOK), in_get_key_name(-1, -PBTN_MBACK)); + smalltext_out16(x, g_menuscreen_h - me_sfont_h * 3 - 2, buff, 0xe78c); + + snprintf(buff, sizeof(buff), g_menu_filter_off ? + "%s - hide unknown files" : "%s - show all files", + in_get_key_name(-1, -PBTN_MA3)); + smalltext_out16(x, g_menuscreen_h - me_sfont_h * 2 - 2, buff, 0xe78c); + + snprintf(buff, sizeof(buff), g_autostateld_opt ? + "%s - autoload save is ON" : "%s - autoload save is OFF", + in_get_key_name(-1, -PBTN_MA2)); + smalltext_out16(x, g_menuscreen_h - me_sfont_h * 1 - 2, buff, 0xe78c); + } + menu_draw_end(); } @@ -814,21 +928,30 @@ static int scandir_cmp(const void *p1, const void *p2) return alphasort(d1, d2); } +static const char **filter_exts_internal; + static int scandir_filter(const struct dirent *ent) { - const char *p; + const char **filter = filter_exts_internal; + const char *ext; int i; - if (ent == NULL || ent->d_name == NULL) return 0; - if (strlen(ent->d_name) < 5) return 1; + if (ent == NULL || ent->d_name == NULL) + return 0; - p = ent->d_name + strlen(ent->d_name) - 4; + if (ent->d_type == DT_DIR) + return 1; - for (i = 0; i < array_size(filter_exts); i++) - if (strcmp(p, filter_exts[i]) == 0) - return 0; + ext = strrchr(ent->d_name, '.'); + if (ext == NULL) + return 0; + + ext++; + for (i = 0; filter[i] != NULL; i++) + if (strcasecmp(ext, filter[i]) == 0) + return 1; - return 1; + return 0; } static int dirent_seek_char(struct dirent **namelist, int len, int sel, char c) @@ -836,9 +959,11 @@ static int dirent_seek_char(struct dirent **namelist, int len, int sel, char c) int i; sel++; - for (i = sel + 1; i != sel; i++) { + for (i = sel + 1; ; i++) { if (i >= len) i = 1; + if (i == sel) + break; if (tolower_simple(namelist[i]->d_name[0]) == c) break; @@ -847,24 +972,49 @@ static int dirent_seek_char(struct dirent **namelist, int len, int sel, char c) return i - 1; } -static char *menu_loop_romsel(char *curr_path, int len) +static const char *menu_loop_romsel(char *curr_path, int len, + const char **filter_exts, + int (*extra_filter)(struct dirent **namelist, int count, + const char *basedir)) { - struct dirent **namelist; - int n, inp, sel = 0; - char *ret = NULL, *fname = NULL; + static char rom_fname_reload[256]; // used for return + char sel_fname[256]; + int (*filter)(const struct dirent *); + struct dirent **namelist = NULL; + int n = 0, inp = 0, sel = 0, show_help = 0; + char *curr_path_restore = NULL; + const char *ret = NULL; char cinp; -rescan: + filter_exts_internal = filter_exts; + sel_fname[0] = 0; + // is this a dir or a full path? if (!plat_is_dir(curr_path)) { - char *p = curr_path + strlen(curr_path) - 1; - for (; p > curr_path && *p != '/'; p--) - ; - *p = 0; - fname = p+1; + char *p = strrchr(curr_path, '/'); + if (p != NULL) { + *p = 0; + curr_path_restore = p; + snprintf(sel_fname, sizeof(sel_fname), "%s", p + 1); + } + + if (rom_fname_reload[0] == 0) + show_help = 2; + } + +rescan: + if (namelist != NULL) { + while (n-- > 0) + free(namelist[n]); + free(namelist); + namelist = NULL; } - n = scandir(curr_path, &namelist, scandir_filter, (void *)scandir_cmp); + filter = NULL; + if (!g_menu_filter_off) + filter = scandir_filter; + + n = scandir(curr_path, &namelist, filter, (void *)scandir_cmp); if (n < 0) { char *t; lprintf("menu_loop_romsel failed, dir: %s\n", curr_path); @@ -873,7 +1023,7 @@ rescan: t = getcwd(curr_path, len); if (t == NULL) plat_get_root_dir(curr_path, len); - n = scandir(curr_path, &namelist, scandir_filter, (void *)scandir_cmp); + n = scandir(curr_path, &namelist, filter, (void *)scandir_cmp); if (n < 0) { // oops, we failed lprintf("menu_loop_romsel failed, dir: %s\n", curr_path); @@ -881,13 +1031,17 @@ rescan: } } - // try to find sel + if (!g_menu_filter_off && extra_filter != NULL) + n = extra_filter(namelist, n, curr_path); + + // try to find selected file // note: we don't show '.' so sel is namelist index - 1 - if (fname != NULL) { + sel = 0; + if (sel_fname[0] != 0) { int i; for (i = 1; i < n; i++) { char *dname = namelist[i]->d_name; - if (dname[0] == fname[0] && strcmp(dname, fname) == 0) { + if (dname[0] == sel_fname[0] && strcmp(dname, sel_fname) == 0) { sel = i - 1; break; } @@ -895,39 +1049,41 @@ rescan: } /* make sure action buttons are not pressed on entering menu */ - draw_dirlist(curr_path, namelist, n, sel); + draw_dirlist(curr_path, namelist, n, sel, show_help); while (in_menu_wait_any(NULL, 50) & (PBTN_MOK|PBTN_MBACK|PBTN_MENU)) ; for (;;) { - draw_dirlist(curr_path, namelist, n, sel); - inp = in_menu_wait(PBTN_UP|PBTN_DOWN|PBTN_LEFT|PBTN_RIGHT| - PBTN_L|PBTN_R|PBTN_MA2|PBTN_MOK|PBTN_MBACK|PBTN_MENU|PBTN_CHAR, &cinp, 33); + draw_dirlist(curr_path, namelist, n, sel, show_help); + inp = in_menu_wait(PBTN_UP|PBTN_DOWN|PBTN_LEFT|PBTN_RIGHT + | PBTN_L|PBTN_R|PBTN_MA2|PBTN_MA3|PBTN_MOK|PBTN_MBACK + | PBTN_MENU|PBTN_CHAR, &cinp, 33); + if (inp & PBTN_MA3) { + g_menu_filter_off = !g_menu_filter_off; + snprintf(sel_fname, sizeof(sel_fname), "%s", + namelist[sel+1]->d_name); + goto rescan; + } if (inp & PBTN_UP ) { sel--; if (sel < 0) sel = n-2; } if (inp & PBTN_DOWN) { sel++; if (sel > n-2) sel = 0; } if (inp & PBTN_LEFT) { sel-=10; if (sel < 0) sel = 0; } if (inp & PBTN_L) { sel-=24; if (sel < 0) sel = 0; } if (inp & PBTN_RIGHT) { sel+=10; if (sel > n-2) sel = n-2; } if (inp & PBTN_R) { sel+=24; if (sel > n-2) sel = n-2; } - if (inp & PBTN_CHAR) sel = dirent_seek_char(namelist, n, sel, cinp); + if ((inp & PBTN_MOK) || (inp & (PBTN_MENU|PBTN_MA2)) == (PBTN_MENU|PBTN_MA2)) { again: if (namelist[sel+1]->d_type == DT_REG) { - strcpy(rom_fname_reload, curr_path); - strcat(rom_fname_reload, "/"); - strcat(rom_fname_reload, namelist[sel+1]->d_name); + snprintf(rom_fname_reload, sizeof(rom_fname_reload), + "%s/%s", curr_path, namelist[sel+1]->d_name); if (inp & PBTN_MOK) { // return sel ret = rom_fname_reload; break; } do_delete(rom_fname_reload, namelist[sel+1]->d_name); - if (n > 0) { - while (n--) free(namelist[n]); - free(namelist); - } goto rescan; } else if (namelist[sel+1]->d_type == DT_DIR) @@ -954,7 +1110,7 @@ rescan: strcat(newdir, "/"); strcat(newdir, namelist[sel+1]->d_name); } - ret = menu_loop_romsel(newdir, newlen); + ret = menu_loop_romsel(newdir, newlen, filter_exts, extra_filter); free(newdir); break; } @@ -962,9 +1118,8 @@ rescan: { // unknown file type, happens on NTFS mounts. Try to guess. FILE *tstf; int tmp; - strcpy(rom_fname_reload, curr_path); - strcat(rom_fname_reload, "/"); - strcat(rom_fname_reload, namelist[sel+1]->d_name); + snprintf(rom_fname_reload, sizeof(rom_fname_reload), + "%s/%s", curr_path, namelist[sel+1]->d_name); tstf = fopen(rom_fname_reload, "rb"); if (tstf != NULL) { @@ -976,21 +1131,31 @@ rescan: } } } + else if (inp & PBTN_MA2) { + g_autostateld_opt = !g_autostateld_opt; + show_help = 3; + } + else if (inp & PBTN_CHAR) { + // must be last + sel = dirent_seek_char(namelist, n, sel, cinp); + } + if (inp & PBTN_MBACK) break; + + if (show_help > 0) + show_help--; } if (n > 0) { - while (n--) free(namelist[n]); + while (n-- > 0) + free(namelist[n]); free(namelist); } // restore curr_path - if (fname != NULL) { - n = strlen(curr_path); - if (curr_path + n + 1 == fname) - curr_path[n] = '/'; - } + if (curr_path_restore != NULL) + *curr_path_restore = '/'; return ret; } @@ -1036,7 +1201,7 @@ static void draw_savestate_menu(int menu_sel, int is_loading) x = 12 + me_mfont_w * 2; #endif - menu_draw_begin(1); + menu_draw_begin(1, 1); text_out16(x, y, is_loading ? "Load state" : "Save state"); y += 3 * me_mfont_h; @@ -1098,7 +1263,7 @@ static int menu_loop_savestate(int is_loading) if (menu_sel < STATE_SLOT_COUNT) { state_slot = menu_sel; if (emu_save_load_game(is_loading, 0)) { - me_update_msg(is_loading ? "Load failed" : "Save failed"); + menu_update_msg(is_loading ? "Load failed" : "Save failed"); break; } ret = 1; @@ -1199,7 +1364,7 @@ static void draw_key_config(const me_bind_action *opts, int opt_cnt, int player_ if (x < me_mfont_w * 2) x = me_mfont_w * 2; - menu_draw_begin(1); + menu_draw_begin(1, 0); if (player_idx >= 0) text_out16(x, y, "Player %i controls", player_idx + 1); else @@ -1212,10 +1377,12 @@ static void draw_key_config(const me_bind_action *opts, int opt_cnt, int player_ text_out16(x, y, "%s : %s", opts[i].name, action_binds(player_idx, opts[i].mask, dev_id)); + menu_separation(); + if (dev_id < 0) dev_name = "(all devices)"; else - dev_name = in_get_dev_name(dev_id, 1, 1); + dev_name = in_get_dev_name(dev_id, 0, 1); w = strlen(dev_name) * me_mfont_w; if (w < 30 * me_mfont_w) w = 30 * me_mfont_w; @@ -1278,7 +1445,7 @@ static void key_config_loop(const me_bind_action *opts, int opt_cnt, int player_ for (i = 0, dev_id--; i < IN_MAX_DEVS + 1; i++, dev_id--) { if (dev_id < -1) dev_id = IN_MAX_DEVS - 1; - if (dev_id == -1 || in_get_dev_name(dev_id, 1, 0) != NULL) + if (dev_id == -1 || in_get_dev_name(dev_id, 0, 0) != NULL) break; } continue; @@ -1286,7 +1453,7 @@ static void key_config_loop(const me_bind_action *opts, int opt_cnt, int player_ for (i = 0, dev_id++; i < IN_MAX_DEVS; i++, dev_id++) { if (dev_id >= IN_MAX_DEVS) dev_id = -1; - if (dev_id == -1 || in_get_dev_name(dev_id, 1, 0) != NULL) + if (dev_id == -1 || in_get_dev_name(dev_id, 0, 0) != NULL) break; } continue;