+ return 0;
+}
+
+// ------------ adv options menu ------------
+
+static const char *men_cfg_cdrr[] = { "Auto", "ON", "OFF", NULL };
+static const char h_cfg_cpul[] = "Shows CPU usage in %";
+static const char h_cfg_spu[] = "Shows active SPU channels\n"
+ "(green: normal, red: fmod, blue: noise)";
+static const char h_cfg_fl[] = "Frame Limiter keeps the game from running too fast";
+static const char h_cfg_xa[] = "Disables XA sound, which can sometimes improve performance";
+static const char h_cfg_cdda[] = "Disable CD Audio for a performance boost\n"
+ "(proper .cue/.bin dump is needed otherwise)";
+static const char h_cfg_sio[] = "You should not need this, breaks games";
+static const char h_cfg_spuirq[] = "Compatibility tweak; should be left off";
+static const char h_cfg_rcnt1[] = "Parasite Eve 2, Vandal Hearts 1/2 Fix\n"
+ "(timing hack, breaks other games)";
+static const char h_cfg_rcnt2[] = "InuYasha Sengoku Battle Fix\n"
+ "(timing hack, breaks other games)";
+static const char h_cfg_cdrr[] = "Compatibility tweak (fixes Team Buddies, maybe more)\n"
+ "(CD timing hack, breaks FMVs)";
+static const char h_cfg_nodrc[] = "Disable dynamic recompiler and use interpreter\n"
+ "Might be useful to overcome some dynarec bugs";
+
+static menu_entry e_menu_adv_options[] =
+{
+ mee_onoff_h ("Show CPU load", 0, g_opts, OPT_SHOWCPU, h_cfg_cpul),
+ mee_onoff_h ("Show SPU channels", 0, g_opts, OPT_SHOWSPU, h_cfg_spu),
+ mee_onoff_h ("Disable Frame Limiter", 0, g_opts, OPT_NO_FRAMELIM, h_cfg_fl),
+ mee_onoff_h ("Disable XA Decoding", 0, Config.Xa, 1, h_cfg_xa),
+ mee_onoff_h ("Disable CD Audio", 0, Config.Cdda, 1, h_cfg_cdda),
+ mee_onoff_h ("SIO IRQ Always Enabled", 0, Config.Sio, 1, h_cfg_sio),
+ mee_onoff_h ("SPU IRQ Always Enabled", 0, Config.SpuIrq, 1, h_cfg_spuirq),
+ mee_onoff_h ("Rootcounter hack", 0, Config.RCntFix, 1, h_cfg_rcnt1),
+ mee_onoff_h ("Rootcounter hack 2", 0, Config.VSyncWA, 1, h_cfg_rcnt2),
+ mee_enum_h ("CD read reschedule hack",0, Config.CdrReschedule, men_cfg_cdrr, h_cfg_cdrr),
+ mee_onoff_h ("Disable dynarec (slow!)",0, Config.Cpu, 1, h_cfg_nodrc),
+ mee_end,
+};
+
+static int menu_loop_adv_options(int id, int keys)
+{
+ static int sel = 0;
+ me_loop(e_menu_adv_options, &sel);
+ return 0;
+}
+
+// ------------ options menu ------------
+
+static int mh_restore_defaults(int id, int keys)
+{
+ menu_set_defconfig();
+ me_update_msg("defaults restored");
+ return 1;
+}
+
+static const char *men_region[] = { "Auto", "NTSC", "PAL", NULL };
+/*
+static const char *men_confirm_save[] = { "OFF", "writes", "loads", "both", NULL };
+static const char h_confirm_save[] = "Ask for confirmation when overwriting save,\n"
+ "loading state or both";
+*/
+static const char h_restore_def[] = "Switches back to default / recommended\n"
+ "configuration";
+static const char h_frameskip[] = "Warning: frameskip sometimes causes glitches\n";
+
+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_onoff_h ("Frameskip", 0, pl_rearmed_cbs.frameskip, 1, 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 ("[Display]", 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 != 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 w = min(g_menuscreen_w, 1024);
+ int h = min(g_menuscreen_h, 512);
+ u16 *d = g_menuscreen_ptr;
+ u16 *s = (u16 *)gpuf->psxVRam;
+ 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)
+{
+ GPUFreeze_t *gpuf;
+ int inp;
+
+ gpuf = malloc(sizeof(*gpuf));
+ if (gpuf == NULL)
+ return;
+
+ while (1)
+ {
+ menu_draw_begin(0);
+ draw_frame_debug(gpuf);
+ 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, 70);
+ if (inp & PBTN_MBACK)
+ break;
+ }
+
+ 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);
+
+ 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;
+}
+
+// --------- main menu help ----------
+
+static void menu_bios_warn(void)
+{
+ int inp;
+ static const char msg[] =
+ "You don't seem to have copied any BIOS files to\n"
+ "<SD card>/pandora/appdata/pcsx_rearmed/bios/\n\n"
+ "While many games work fine with fake (HLE) BIOS,\n"
+ "others (like MGS and FF8) require BIOS to work.\n"
+ "After copying the file, you'll also need to\n"
+ "select it in the emu's options->[BIOS/Plugins]\n\n"
+ "The file is usually named SCPH1001.BIN, but\n"
+ "other not compressed files can be used too.\n\n"
+ "Press (B) or (X) to continue";
+
+ while (1)
+ {
+ draw_menu_message(msg, NULL);
+
+ inp = in_menu_wait(PBTN_MOK|PBTN_MBACK, 70);
+ if (inp & (PBTN_MBACK|PBTN_MOK))
+ return;