+static menu_entry e_menu_options[] =
+{
+// mee_range ("Save slot", 0, state_slot, 0, 9),
+// mee_enum_h ("Confirm savestate", 0, dummy, men_confirm_save, h_confirm_save),
+ mee_enum_h ("Frameskip", 0, frameskip, men_frameskip, h_frameskip),
+ mee_onoff ("Show FPS", 0, g_opts, OPT_SHOWFPS),
+ mee_enum ("Region", 0, region, men_region),
+ mee_range ("CPU clock", MA_OPT_CPU_CLOCKS, cpu_clock, 20, 5000),
+ mee_handler_id("[Display]", MA_OPT_DISP_OPTS, menu_loop_gfx_options),
+ mee_handler ("[BIOS/Plugins]", menu_loop_plugin_options),
+ mee_handler ("[Advanced]", menu_loop_adv_options),
+ mee_cust_nosave("Save global config", MA_OPT_SAVECFG, mh_savecfg, mgn_saveloadcfg),
+ mee_cust_nosave("Save cfg for loaded game",MA_OPT_SAVECFG_GAME, mh_savecfg, mgn_saveloadcfg),
+ mee_handler_h ("Restore default config", mh_restore_defaults, h_restore_def),
+ mee_end,
+};
+
+static int menu_loop_options(int id, int keys)
+{
+ static int sel = 0;
+ int i;
+
+ i = me_id2offset(e_menu_options, MA_OPT_CPU_CLOCKS);
+ e_menu_options[i].enabled = cpu_clock_st > 0 ? 1 : 0;
+ me_enable(e_menu_options, MA_OPT_SAVECFG_GAME, ready_to_go && CdromId[0]);
+
+ me_loop(e_menu_options, &sel);
+
+ return 0;
+}
+
+// ------------ debug menu ------------
+
+static void draw_frame_debug(GPUFreeze_t *gpuf, int x, int y)
+{
+ int w = min(g_menuscreen_w, 1024);
+ int h = min(g_menuscreen_h, 512);
+ u16 *d = g_menuscreen_ptr;
+ u16 *s = (u16 *)gpuf->psxVRam + y * 1024 + x;
+ char buff[64];
+ int ty = 1;
+
+ gpuf->ulFreezeVersion = 1;
+ if (GPU_freeze != NULL)
+ GPU_freeze(1, gpuf);
+
+ for (; h > 0; h--, d += g_menuscreen_w, s += 1024)
+ bgr555_to_rgb565(d, s, w * 2);
+
+ smalltext_out16(4, 1, "build: "__DATE__ " " __TIME__ " " REV, 0xe7fc);
+ snprintf(buff, sizeof(buff), "GPU sr: %08x", gpuf->ulStatus);
+ smalltext_out16(4, (ty += me_sfont_h), buff, 0xe7fc);
+ snprintf(buff, sizeof(buff), "PC/SP: %08x %08x", psxRegs.pc, psxRegs.GPR.n.sp);
+ smalltext_out16(4, (ty += me_sfont_h), buff, 0xe7fc);
+}
+
+static void debug_menu_loop(void)
+{
+ int inp, df_x = 0, df_y = 0;
+ GPUFreeze_t *gpuf;
+
+ gpuf = malloc(sizeof(*gpuf));
+ if (gpuf == NULL)
+ return;
+
+ while (1)
+ {
+ menu_draw_begin(0, 1);
+ draw_frame_debug(gpuf, df_x, df_y);
+ menu_draw_end();
+
+ inp = in_menu_wait(PBTN_MOK|PBTN_MBACK|PBTN_MA2|PBTN_MA3|PBTN_L|PBTN_R |
+ PBTN_UP|PBTN_DOWN|PBTN_LEFT|PBTN_RIGHT, NULL, 10);
+ if (inp & PBTN_MBACK) break;
+ else if (inp & PBTN_UP) { if (df_y > 0) df_y--; }
+ else if (inp & PBTN_DOWN) { if (df_y < 512 - g_menuscreen_h) df_y++; }
+ else if (inp & PBTN_LEFT) { if (df_x > 0) df_x -= 2; }
+ else if (inp & PBTN_RIGHT) { if (df_x < 1024 - g_menuscreen_w) df_x += 2; }
+ }
+
+ free(gpuf);
+}
+
+// --------- memcard manager ---------
+
+static void draw_mc_icon(int dx, int dy, const u16 *s)
+{
+ u16 *d;
+ int x, y, l, p;
+
+ d = (u16 *)g_menuscreen_ptr + g_menuscreen_w * dy + dx;
+
+ for (y = 0; y < 16; y++, s += 16) {
+ for (l = 0; l < 2; l++, d += g_menuscreen_w) {
+ for (x = 0; x < 16; x++) {
+ p = s[x];
+ d[x*2] = d[x*2 + 1] = ((p & 0x7c00) >> 10)
+ | ((p & 0x03e0) << 1) | ((p & 0x1f) << 11);
+ }
+ }
+ }
+}
+
+static void draw_mc_bg(void)
+{
+ McdBlock *blocks1, *blocks2;
+ int maxicons = 15;
+ int i, y, row2;
+
+ blocks1 = malloc(15 * sizeof(blocks1[0]));
+ blocks2 = malloc(15 * sizeof(blocks1[0]));
+ if (blocks1 == NULL || blocks2 == NULL)
+ goto out;
+
+ for (i = 0; i < 15; i++) {
+ GetMcdBlockInfo(1, i + 1, &blocks1[i]);
+ GetMcdBlockInfo(2, i + 1, &blocks2[i]);
+ }
+
+ menu_draw_begin(1, 1);
+
+ memcpy(g_menuscreen_ptr, g_menubg_src_ptr, g_menuscreen_w * g_menuscreen_h * 2);
+
+ y = g_menuscreen_h / 2 - 15 * 32 / 2;
+ if (y < 0) {
+ // doesn't fit..
+ y = 0;
+ maxicons = g_menuscreen_h / 32;
+ }
+
+ row2 = g_menuscreen_w / 2;
+ for (i = 0; i < maxicons; i++) {
+ draw_mc_icon(8, y + i * 32, (u16 *)blocks1[i].Icon);
+ smalltext_out16(10+32, y + i * 32 + 8, blocks1[i].sTitle, 0xf71e);
+
+ draw_mc_icon(row2 + 8, y + i * 32, (u16 *)blocks2[i].Icon);
+ smalltext_out16(row2 + 10+32, y + i * 32 + 8, blocks2[i].sTitle, 0xf71e);
+ }
+
+ menu_darken_bg(g_menubg_ptr, g_menuscreen_ptr, g_menuscreen_w * g_menuscreen_h, 0);
+
+ menu_draw_end();
+out:
+ free(blocks1);
+ free(blocks2);
+}
+
+static void handle_memcard_sel(void)
+{
+ Config.Mcd1[0] = 0;
+ if (memcard1_sel != 0)
+ snprintf(Config.Mcd1, sizeof(Config.Mcd1), ".%s%s", MEMCARD_DIR, memcards[memcard1_sel]);
+ Config.Mcd2[0] = 0;
+ if (memcard2_sel != 0)
+ snprintf(Config.Mcd2, sizeof(Config.Mcd2), ".%s%s", MEMCARD_DIR, memcards[memcard2_sel]);
+ LoadMcds(Config.Mcd1, Config.Mcd2);
+ draw_mc_bg();
+}
+
+static menu_entry e_memcard_options[] =
+{
+ mee_enum("Memory card 1", 0, memcard1_sel, memcards),
+ mee_enum("Memory card 2", 0, memcard2_sel, memcards),
+ mee_end,
+};
+
+static int menu_loop_memcards(int id, int keys)
+{
+ static int sel = 0;
+ char *p;
+ int i;
+
+ memcard1_sel = memcard2_sel = 0;
+ p = strrchr(Config.Mcd1, '/');
+ if (p != NULL)
+ for (i = 0; memcards[i] != NULL; i++)
+ if (strcmp(p + 1, memcards[i]) == 0)
+ { memcard1_sel = i; break; }
+ p = strrchr(Config.Mcd2, '/');
+ if (p != NULL)
+ for (i = 0; memcards[i] != NULL; i++)
+ if (strcmp(p + 1, memcards[i]) == 0)
+ { memcard2_sel = i; break; }
+
+ me_loop_d(e_memcard_options, &sel, handle_memcard_sel, NULL);
+
+ memcpy(g_menubg_ptr, g_menubg_src_ptr, g_menuscreen_w * g_menuscreen_h * 2);
+
+ return 0;
+}
+
+// ------------ cheats menu ------------
+
+static void draw_cheatlist(int sel)
+{
+ int max_cnt, start, i, pos, active;
+
+ max_cnt = g_menuscreen_h / me_sfont_h;
+ start = max_cnt / 2 - sel;
+
+ menu_draw_begin(1, 1);
+
+ for (i = 0; i < NumCheats; i++) {
+ pos = start + i;
+ if (pos < 0) continue;
+ if (pos >= max_cnt) break;
+ active = Cheats[i].Enabled;
+ smalltext_out16(14, pos * me_sfont_h,
+ active ? "ON " : "OFF", active ? 0xfff6 : 0xffff);
+ smalltext_out16(14 + me_sfont_w*4, pos * me_sfont_h,
+ Cheats[i].Descr, active ? 0xfff6 : 0xffff);
+ }
+ pos = start + i;
+ if (pos < max_cnt)
+ smalltext_out16(14, pos * me_sfont_h, "done", 0xffff);
+
+ text_out16(5, max_cnt / 2 * me_sfont_h, ">");
+ menu_draw_end();
+}
+
+static void menu_loop_cheats(void)
+{
+ static int menu_sel = 0;
+ int inp;
+
+ for (;;)
+ {
+ draw_cheatlist(menu_sel);
+ inp = in_menu_wait(PBTN_UP|PBTN_DOWN|PBTN_LEFT|PBTN_RIGHT|PBTN_L|PBTN_R
+ |PBTN_MOK|PBTN_MBACK, NULL, 33);
+ if (inp & PBTN_UP ) { menu_sel--; if (menu_sel < 0) menu_sel = NumCheats; }
+ if (inp & PBTN_DOWN) { menu_sel++; if (menu_sel > NumCheats) menu_sel = 0; }
+ if (inp &(PBTN_LEFT|PBTN_L)) { menu_sel-=10; if (menu_sel < 0) menu_sel = 0; }
+ if (inp &(PBTN_RIGHT|PBTN_R)) { menu_sel+=10; if (menu_sel > NumCheats) menu_sel = NumCheats; }
+ if (inp & PBTN_MOK) { // action
+ if (menu_sel < NumCheats)
+ Cheats[menu_sel].Enabled = !Cheats[menu_sel].Enabled;
+ else break;
+ }
+ if (inp & PBTN_MBACK)
+ break;
+ }
+}
+
+// --------- main menu help ----------
+
+static void menu_bios_warn(void)
+{
+ int inp;
+ static const char msg[] =
+ "You don't seem to have copied any BIOS\n"
+ "files to\n"
+ MENU_BIOS_PATH "\n\n"
+
+ "While many games work fine with fake\n"
+ "(HLE) BIOS, others (like MGS and FF8)\n"
+ "require BIOS to work.\n"
+ "After copying the file, you'll also need\n"
+ "to select it in the emu's menu:\n"
+ "options->[BIOS/Plugins]\n\n"
+ "The file is usually named SCPH1001.BIN,\n"
+ "but other not compressed files can be\n"
+ "used too.\n\n"
+ "Press %s or %s to continue";
+ char tmp_msg[sizeof(msg) + 64];
+
+ snprintf(tmp_msg, sizeof(tmp_msg), msg,
+ in_get_key_name(-1, -PBTN_MOK), in_get_key_name(-1, -PBTN_MBACK));
+ while (1)
+ {
+ draw_menu_message(tmp_msg, NULL);
+
+ inp = in_menu_wait(PBTN_MOK|PBTN_MBACK, NULL, 70);
+ if (inp & (PBTN_MBACK|PBTN_MOK))
+ return;
+ }
+}
+
+// ------------ main menu ------------
+
+static menu_entry e_menu_main[];
+void OnFile_Exit();
+
+static void draw_frame_main(void)
+{
+ struct tm *tmp;
+ time_t ltime;
+ int capacity;
+ char ltime_s[16];
+ char buff[64];
+ char *out;
+
+ if (CdromId[0] != 0) {
+ snprintf(buff, sizeof(buff), "%.32s/%.9s (running as %s, with %s)",
+ get_cd_label(), CdromId, Config.PsxType ? "PAL" : "NTSC",
+ Config.HLE ? "HLE" : "BIOS");
+ smalltext_out16(4, 1, buff, 0x105f);
+ }
+
+ if (ready_to_go) {
+ capacity = plat_target_bat_capacity_get();
+ ltime = time(NULL);
+ tmp = localtime(<ime);
+ strftime(ltime_s, sizeof(ltime_s), "%H:%M", tmp);
+ if (capacity >= 0) {
+ snprintf(buff, sizeof(buff), "%s %3d%%", ltime_s, capacity);
+ out = buff;
+ }
+ else
+ out = ltime_s;
+ smalltext_out16(4, 1 + me_sfont_h, out, 0x105f);
+ }
+}
+
+static void draw_frame_credits(void)
+{
+ smalltext_out16(4, 1, "build: " __DATE__ " " __TIME__ " " REV, 0xe7fc);
+}
+
+static const char credits_text[] =
+ "PCSX-ReARMed\n\n"
+ "(C) 1999-2003 PCSX Team\n"
+ "(C) 2005-2009 PCSX-df Team\n"
+ "(C) 2009-2011 PCSX-Reloaded Team\n\n"
+ "ARM recompiler (C) 2009-2011 Ari64\n"
+#ifdef __ARM_NEON__
+ "ARM NEON GPU (c) 2011-2012 Exophase\n"
+#endif
+ "PEOpS GPU and SPU by Pete Bernert\n"
+ " and the P.E.Op.S. team\n"
+ "PCSX4ALL plugin by PCSX4ALL team\n"
+ " Chui, Franxis, Unai\n\n"
+ "integration, optimization and\n"
+ " frontend (C) 2010-2012 notaz\n";
+
+static int reset_game(void)
+{
+ // sanity check
+ if (bios_sel == 0 && !Config.HLE)
+ return -1;
+
+ ClosePlugins();
+ OpenPlugins();
+ SysReset();
+ if (CheckCdrom() != -1) {
+ LoadCdrom();
+ }
+ return 0;
+}
+
+static int reload_plugins(const char *cdimg)
+{
+ pl_vout_buf = NULL;
+
+ ClosePlugins();
+
+ set_cd_image(cdimg);