#include <string.h>\r
#include <stdlib.h>\r
#include <stdarg.h>\r
+#include <time.h>\r
+#include <locale.h> // savestate date\r
\r
#include "menu.h"\r
#include "fonts.h"\r
return -1;\r
}\r
\r
+static char tolower_simple(char c)\r
+{\r
+ if ('A' <= c && c <= 'Z')\r
+ c = c - 'A' + 'a';\r
+ return c;\r
+}\r
+\r
void menu_init(void)\r
{\r
int i, c, l;\r
}\r
fclose(f);\r
}\r
+\r
+ // use user's locale for savestate date display\r
+ setlocale(LC_TIME, "");\r
}\r
\r
static void menu_draw_begin(int need_bg)\r
\r
/* make sure action buttons are not pressed on entering menu */\r
me_draw(menu, sel, NULL);\r
- while (in_menu_wait_any(50) & (PBTN_MOK|PBTN_MBACK|PBTN_MENU));\r
+ while (in_menu_wait_any(NULL, 50) & (PBTN_MOK|PBTN_MBACK|PBTN_MENU));\r
\r
for (;;)\r
{\r
\r
me_draw(menu, sel, draw_more);\r
inp = in_menu_wait(PBTN_UP|PBTN_DOWN|PBTN_LEFT|PBTN_RIGHT|\r
- PBTN_MOK|PBTN_MBACK|PBTN_MENU|PBTN_L|PBTN_R, 70);\r
+ PBTN_MOK|PBTN_MBACK|PBTN_MENU|PBTN_L|PBTN_R, NULL, 70);\r
if (inp & (PBTN_MENU|PBTN_MBACK))\r
break;\r
\r
text_out16(mid - me_mfont_w * len / 2, 12 * me_mfont_h, tmp);\r
menu_draw_end();\r
\r
- while (in_menu_wait_any(50) & (PBTN_MENU|PBTN_MA2));\r
- inp = in_menu_wait(PBTN_MA3|PBTN_MBACK, 100);\r
+ while (in_menu_wait_any(NULL, 50) & (PBTN_MENU|PBTN_MA2));\r
+ inp = in_menu_wait(PBTN_MA3|PBTN_MBACK, NULL, 100);\r
if (inp & PBTN_MA3)\r
remove(fpath);\r
}\r
return 1;\r
}\r
\r
+static int dirent_seek_char(struct dirent **namelist, int len, int sel, char c)\r
+{\r
+ int i;\r
+\r
+ sel++;\r
+ for (i = sel + 1; i != sel; i++) {\r
+ if (i >= len)\r
+ i = 1;\r
+\r
+ if (tolower_simple(namelist[i]->d_name[0]) == c)\r
+ break;\r
+ }\r
+\r
+ return i - 1;\r
+}\r
+\r
static char *menu_loop_romsel(char *curr_path, int len)\r
{\r
struct dirent **namelist;\r
int n, inp, sel = 0;\r
char *ret = NULL, *fname = NULL;\r
+ char cinp;\r
\r
rescan:\r
// is this a dir or a full path?\r
}\r
\r
// try to find sel\r
+ // note: we don't show '.' so sel is namelist index - 1\r
if (fname != NULL) {\r
int i;\r
for (i = 1; i < n; i++) {\r
- if (strcmp(namelist[i]->d_name, fname) == 0) {\r
+ char *dname = namelist[i]->d_name;\r
+ if (dname[0] == fname[0] && strcmp(dname, fname) == 0) {\r
sel = i - 1;\r
break;\r
}\r
\r
/* make sure action buttons are not pressed on entering menu */\r
draw_dirlist(curr_path, namelist, n, sel);\r
- while (in_menu_wait_any(50) & (PBTN_MOK|PBTN_MBACK|PBTN_MENU))\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, 33);\r
+ PBTN_L|PBTN_R|PBTN_MA2|PBTN_MOK|PBTN_MBACK|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_L) { sel-=24; 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_MOK) || (inp & (PBTN_MENU|PBTN_MA2)) == (PBTN_MENU|PBTN_MA2))\r
{\r
again:\r
\r
// ------------ savestate loader ------------\r
\r
+#define STATE_SLOT_COUNT 10\r
+\r
static int state_slot_flags = 0;\r
+static int state_slot_times[STATE_SLOT_COUNT];\r
\r
static void state_check_slots(void)\r
{\r
\r
state_slot_flags = 0;\r
\r
- for (slot = 0; slot < 10; slot++) {\r
- if (emu_check_save_file(slot))\r
+ for (slot = 0; slot < STATE_SLOT_COUNT; slot++) {\r
+ state_slot_times[slot] = 0;\r
+ if (emu_check_save_file(slot, &state_slot_times[slot]))\r
state_slot_flags |= 1 << slot;\r
}\r
}\r
static void draw_savestate_menu(int menu_sel, int is_loading)\r
{\r
int i, x, y, w, h;\r
+ char time_buf[32];\r
\r
if (state_slot_flags & (1 << menu_sel))\r
draw_savestate_bg(menu_sel);\r
\r
w = (13 + 2) * me_mfont_w;\r
- h = (1+2+10+1) * me_mfont_h;\r
+ h = (1+2+STATE_SLOT_COUNT+1) * me_mfont_h;\r
x = g_menuscreen_w / 2 - w / 2;\r
if (x < 0) x = 0;\r
y = g_menuscreen_h / 2 - h / 2;\r
text_out16(x, y, is_loading ? "Load state" : "Save state");\r
y += 3 * me_mfont_h;\r
\r
- menu_draw_selection(x - me_mfont_w * 2, y + menu_sel * me_mfont_h, (13 + 2) * me_mfont_w + 4);\r
+ menu_draw_selection(x - me_mfont_w * 2, y + menu_sel * me_mfont_h, (23 + 2) * me_mfont_w + 4);\r
\r
- /* draw all 10 slots */\r
- for (i = 0; i < 10; i++, y += me_mfont_h)\r
+ /* draw all slots */\r
+ for (i = 0; i < STATE_SLOT_COUNT; i++, y += me_mfont_h)\r
{\r
- text_out16(x, y, "SLOT %i (%s)", i, (state_slot_flags & (1 << i)) ? "USED" : "free");\r
+ if (!(state_slot_flags & (1 << i)))\r
+ strcpy(time_buf, "free");\r
+ else {\r
+ strcpy(time_buf, "USED");\r
+ if (state_slot_times[i] != 0) {\r
+ time_t time = state_slot_times[i];\r
+ struct tm *t = localtime(&time);\r
+ strftime(time_buf, sizeof(time_buf), "%x %R", t);\r
+ }\r
+ }\r
+\r
+ text_out16(x, y, "SLOT %i (%s)", i, time_buf);\r
}\r
text_out16(x, y, "back");\r
\r
\r
static int menu_loop_savestate(int is_loading)\r
{\r
- static int menu_sel = 10;\r
- int menu_sel_max = 10;\r
+ static int menu_sel = STATE_SLOT_COUNT;\r
+ int menu_sel_max = STATE_SLOT_COUNT;\r
unsigned long inp = 0;\r
int ret = 0;\r
\r
for (;;)\r
{\r
draw_savestate_menu(menu_sel, is_loading);\r
- inp = in_menu_wait(PBTN_UP|PBTN_DOWN|PBTN_MOK|PBTN_MBACK, 100);\r
+ inp = in_menu_wait(PBTN_UP|PBTN_DOWN|PBTN_MOK|PBTN_MBACK, NULL, 100);\r
if (inp & PBTN_UP) {\r
do {\r
menu_sel--;\r
} while (!(state_slot_flags & (1 << menu_sel)) && menu_sel != menu_sel_max && is_loading);\r
}\r
if (inp & PBTN_MOK) { // save/load\r
- if (menu_sel < 10) {\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
for (;;)\r
{\r
draw_key_config(opts, opt_cnt, player_idx, sel, dev_id, dev_count, 0);\r
- mkey = in_menu_wait(PBTN_UP|PBTN_DOWN|PBTN_LEFT|PBTN_RIGHT|PBTN_MBACK|PBTN_MOK|PBTN_MA2, 100);\r
+ mkey = in_menu_wait(PBTN_UP|PBTN_DOWN|PBTN_LEFT|PBTN_RIGHT\r
+ |PBTN_MBACK|PBTN_MOK|PBTN_MA2, NULL, 100);\r
switch (mkey) {\r
case PBTN_UP: sel--; if (sel < 0) sel = menu_sel_max; continue;\r
case PBTN_DOWN: sel++; if (sel > menu_sel_max) sel = 0; continue;\r
case PBTN_MOK:\r
if (sel >= opt_cnt)\r
return;\r
- while (in_menu_wait_any(30) & PBTN_MOK)\r
+ while (in_menu_wait_any(NULL, 30) & PBTN_MOK)\r
;\r
break;\r
case PBTN_MA2:\r
\r
/* wait for some up event */\r
for (is_down = 1; is_down; )\r
- kc = in_update_keycode(&bind_dev_id, &is_down, -1);\r
+ kc = in_update_keycode(&bind_dev_id, &is_down, NULL, -1);\r
\r
i = count_bound_keys(bind_dev_id, opts[sel].mask << mask_shift, bindtype);\r
unbind = (i > 0);\r