2 * (C) GraÅžvydas "notaz" Ignotas, 2010-2011
4 * This work is licensed under the terms of any of these licenses
6 * - GNU GPL, version 2 or later.
7 * - GNU LGPL, version 2.1 or later.
8 * See the COPYING file in the top-level directory.
16 #include <sys/types.h>
24 #include "plugin_lib.h"
27 #include "common/plat.h"
28 #include "common/input.h"
29 #include "linux/in_evdev.h"
30 #include "../libpcsxcore/misc.h"
31 #include "../libpcsxcore/cdrom.h"
32 #include "../libpcsxcore/cdriso.h"
33 #include "../libpcsxcore/psemu_plugin_defs.h"
34 #include "../libpcsxcore/new_dynarec/new_dynarec.h"
35 #include "../plugins/dfinput/main.h"
36 #include "../plugins/gpulib/cspace.h"
39 #define REARMED_BIRTHDAY_TIME 1293306830 /* 25 Dec 2010 */
41 #define array_size(x) (sizeof(x) / sizeof(x[0]))
52 MA_MAIN_SWAP_CD_MULTI,
86 static int last_psx_w, last_psx_h, last_psx_bpp;
87 static int scaling, filter, cpu_clock, cpu_clock_st, volume_boost, frameskip;
88 static char rom_fname_reload[MAXPATHLEN];
89 static char last_selected_fname[MAXPATHLEN];
90 static int warned_about_bios, region, in_type_sel1, in_type_sel2;
92 static int memcard1_sel, memcard2_sel;
94 int soft_scaling, analog_deadzone; // for Caanoo
96 #ifdef __ARM_ARCH_7A__
97 #define DEFAULT_PSX_CLOCK 57
98 #define DEFAULT_PSX_CLOCK_S "57"
100 #define DEFAULT_PSX_CLOCK 50
101 #define DEFAULT_PSX_CLOCK_S "50"
105 extern int iUseReverb;
106 extern int iUseInterpolation;
108 extern int iSPUIRQWait;
109 extern int iUseTimer;
112 static const char *bioses[24];
113 static const char *gpu_plugins[16];
114 static const char *spu_plugins[16];
115 static const char *memcards[32];
116 static int bios_sel, gpu_plugsel, spu_plugsel;
119 static int min(int x, int y) { return x < y ? x : y; }
120 static int max(int x, int y) { return x > y ? x : y; }
122 void emu_make_path(char *buff, const char *end, int size)
126 end_len = strlen(end);
127 pos = plat_get_root_dir(buff, size);
128 strncpy(buff + pos, end, size - pos);
130 if (pos + end_len > size - 1)
131 printf("Warning: path truncated: %s\n", buff);
134 static int emu_check_save_file(int slot, int *time)
136 char fname[MAXPATHLEN];
140 ret = emu_check_state(slot);
141 if (ret != 0 || time == NULL)
142 return ret == 0 ? 1 : 0;
144 ret = get_state_filename(fname, sizeof(fname), slot);
148 ret = stat(fname, &status);
152 if (status.st_mtime < REARMED_BIRTHDAY_TIME)
153 return 1; // probably bad rtc like on some Caanoos
155 *time = status.st_mtime;
160 static int emu_save_load_game(int load, int unused)
165 ret = emu_load_state(state_slot);
167 // reflect hle/bios mode from savestate
170 else if (bios_sel == 0 && bioses[1] != NULL)
171 // XXX: maybe find the right bios instead
175 ret = emu_save_state(state_slot);
180 // propagate menu settings to the emu vars
181 static void menu_sync_config(void)
183 static int allow_abs_only_old;
188 Config.PsxType = region - 1;
190 cycle_multiplier = 10000 / psx_clock;
192 switch (in_type_sel1) {
193 case 1: in_type1 = PSE_PAD_TYPE_ANALOGPAD; break;
194 case 2: in_type1 = PSE_PAD_TYPE_GUNCON; break;
195 default: in_type1 = PSE_PAD_TYPE_STANDARD;
197 switch (in_type_sel2) {
198 case 1: in_type2 = PSE_PAD_TYPE_ANALOGPAD; break;
199 case 2: in_type2 = PSE_PAD_TYPE_GUNCON; break;
200 default: in_type2 = PSE_PAD_TYPE_STANDARD;
202 if (in_evdev_allow_abs_only != allow_abs_only_old) {
204 allow_abs_only_old = in_evdev_allow_abs_only;
207 iVolume = 768 + 128 * volume_boost;
208 pl_rearmed_cbs.frameskip = frameskip - 1;
209 pl_timing_prepare(Config.PsxType);
212 static void menu_set_defconfig(void)
214 emu_set_default_config();
220 analog_deadzone = 50;
222 psx_clock = DEFAULT_PSX_CLOCK;
225 in_type_sel1 = in_type_sel2 = 0;
226 in_evdev_allow_abs_only = 0;
231 #define CE_CONFIG_STR(val) \
232 { #val, 0, Config.val }
234 #define CE_CONFIG_VAL(val) \
235 { #val, sizeof(Config.val), &Config.val }
237 #define CE_STR(val) \
240 #define CE_INTVAL(val) \
241 { #val, sizeof(val), &val }
243 #define CE_INTVAL_P(val) \
244 { #val, sizeof(pl_rearmed_cbs.val), &pl_rearmed_cbs.val }
246 // 'versioned' var, used when defaults change
247 #define CE_CONFIG_STR_V(val, ver) \
248 { #val #ver, 0, Config.val }
250 #define CE_INTVAL_V(val, ver) \
251 { #val #ver, sizeof(val), &val }
253 #define CE_INTVAL_PV(val, ver) \
254 { #val #ver, sizeof(pl_rearmed_cbs.val), &pl_rearmed_cbs.val }
256 static const struct {
262 CE_CONFIG_STR_V(Gpu, 2),
264 // CE_CONFIG_STR(Cdr),
269 CE_CONFIG_VAL(Debug),
270 CE_CONFIG_VAL(PsxOut),
271 CE_CONFIG_VAL(SpuIrq),
272 CE_CONFIG_VAL(RCntFix),
273 CE_CONFIG_VAL(VSyncWA),
275 CE_CONFIG_VAL(CdrReschedule),
277 CE_INTVAL_V(scaling, 2),
278 CE_INTVAL(g_layer_x),
279 CE_INTVAL(g_layer_y),
280 CE_INTVAL(g_layer_w),
281 CE_INTVAL(g_layer_h),
283 CE_INTVAL(state_slot),
284 CE_INTVAL(cpu_clock),
286 CE_INTVAL(in_type_sel1),
287 CE_INTVAL(in_type_sel2),
288 CE_INTVAL(analog_deadzone),
289 CE_INTVAL_V(frameskip, 3),
290 CE_INTVAL_P(gpu_peops.iUseDither),
291 CE_INTVAL_P(gpu_peops.dwActFixes),
292 CE_INTVAL_P(gpu_unai.lineskip),
293 CE_INTVAL_P(gpu_unai.abe_hack),
294 CE_INTVAL_P(gpu_unai.no_light),
295 CE_INTVAL_P(gpu_unai.no_blend),
296 CE_INTVAL_P(gpu_neon.allow_interlace),
297 CE_INTVAL_P(gpu_peopsgl.bDrawDither),
298 CE_INTVAL_P(gpu_peopsgl.iFilterType),
299 CE_INTVAL_P(gpu_peopsgl.iFrameTexType),
300 CE_INTVAL_P(gpu_peopsgl.iUseMask),
301 CE_INTVAL_P(gpu_peopsgl.bOpaquePass),
302 CE_INTVAL_P(gpu_peopsgl.bAdvancedBlend),
303 CE_INTVAL_P(gpu_peopsgl.bUseFastMdec),
304 CE_INTVAL_P(gpu_peopsgl.iVRamSize),
305 CE_INTVAL_P(gpu_peopsgl.iTexGarbageCollection),
306 CE_INTVAL_P(gpu_peopsgl.dwActFixes),
307 CE_INTVAL_V(iUseReverb, 3),
308 CE_INTVAL_V(iXAPitch, 3),
309 CE_INTVAL_V(iUseInterpolation, 3),
310 CE_INTVAL_V(iSPUIRQWait, 3),
311 CE_INTVAL_V(iUseTimer, 3),
312 CE_INTVAL(warned_about_bios),
313 CE_INTVAL(in_evdev_allow_abs_only),
314 CE_INTVAL(volume_boost),
315 CE_INTVAL(psx_clock),
316 CE_INTVAL(new_dynarec_hacks),
317 CE_INTVAL(in_enable_vibration),
320 static char *get_cd_label(void)
322 static char trimlabel[33];
325 strncpy(trimlabel, CdromLabel, 32);
327 for (j = 31; j >= 0; j--)
328 if (trimlabel[j] == ' ')
334 static void make_cfg_fname(char *buf, size_t size, int is_game)
337 snprintf(buf, size, "." PCSX_DOT_DIR "cfg/%.32s-%.9s.cfg", get_cd_label(), CdromId);
339 snprintf(buf, size, "." PCSX_DOT_DIR "%s", cfgfile_basename);
342 static void keys_write_all(FILE *f);
344 static int menu_write_config(int is_game)
346 char cfgfile[MAXPATHLEN];
350 make_cfg_fname(cfgfile, sizeof(cfgfile), is_game);
351 f = fopen(cfgfile, "w");
353 printf("menu_write_config: failed to open: %s\n", cfgfile);
357 for (i = 0; i < ARRAY_SIZE(config_data); i++) {
358 fprintf(f, "%s = ", config_data[i].name);
359 switch (config_data[i].len) {
361 fprintf(f, "%s\n", (char *)config_data[i].val);
364 fprintf(f, "%x\n", *(u8 *)config_data[i].val);
367 fprintf(f, "%x\n", *(u16 *)config_data[i].val);
370 fprintf(f, "%x\n", *(u32 *)config_data[i].val);
373 printf("menu_write_config: unhandled len %d for %s\n",
374 config_data[i].len, config_data[i].name);
380 fprintf(f, "lastcdimg = %s\n", last_selected_fname);
388 static void parse_str_val(char *cval, const char *src)
391 strncpy(cval, src, MAXPATHLEN);
392 cval[MAXPATHLEN - 1] = 0;
393 tmp = strchr(cval, '\n');
395 tmp = strchr(cval, '\r');
400 static void keys_load_all(const char *cfg);
402 static int menu_load_config(int is_game)
404 char cfgfile[MAXPATHLEN];
410 make_cfg_fname(cfgfile, sizeof(cfgfile), is_game);
411 f = fopen(cfgfile, "r");
413 printf("menu_load_config: failed to open: %s\n", cfgfile);
417 fseek(f, 0, SEEK_END);
420 printf("bad size %ld: %s\n", size, cfgfile);
424 cfg = malloc(size + 1);
428 fseek(f, 0, SEEK_SET);
429 if (fread(cfg, 1, size, f) != size) {
430 printf("failed to read: %s\n", cfgfile);
435 for (i = 0; i < ARRAY_SIZE(config_data); i++) {
439 tmp = strstr(cfg, config_data[i].name);
442 tmp += strlen(config_data[i].name);
443 if (strncmp(tmp, " = ", 3) != 0)
447 if (config_data[i].len == 0) {
448 parse_str_val(config_data[i].val, tmp);
453 val = strtoul(tmp, &tmp2, 16);
454 if (tmp2 == NULL || tmp == tmp2)
455 continue; // parse failed
457 switch (config_data[i].len) {
459 *(u8 *)config_data[i].val = val;
462 *(u16 *)config_data[i].val = val;
465 *(u32 *)config_data[i].val = val;
468 printf("menu_load_config: unhandled len %d for %s\n",
469 config_data[i].len, config_data[i].name);
475 char *tmp = strstr(cfg, "lastcdimg = ");
478 parse_str_val(last_selected_fname, tmp);
492 // caanoo old config compat hack
493 if (strcmp(Config.Gpu, "gpuPCSX4ALL.so") == 0)
494 strcpy(Config.Gpu, "gpu_unai.so");
497 for (i = bios_sel = 0; bioses[i] != NULL; i++)
498 if (strcmp(Config.Bios, bioses[i]) == 0)
499 { bios_sel = i; break; }
501 for (i = gpu_plugsel = 0; gpu_plugins[i] != NULL; i++)
502 if (strcmp(Config.Gpu, gpu_plugins[i]) == 0)
503 { gpu_plugsel = i; break; }
505 for (i = spu_plugsel = 0; spu_plugins[i] != NULL; i++)
506 if (strcmp(Config.Spu, spu_plugins[i]) == 0)
507 { spu_plugsel = i; break; }
512 // rrrr rggg gggb bbbb
513 static unsigned short fname2color(const char *fname)
515 static const char *cdimg_exts[] = { ".bin", ".img", ".mdf", ".iso", ".cue", ".z",
516 ".bz", ".znx", ".pbp", ".cbn" };
517 static const char *other_exts[] = { ".ccd", ".toc", ".mds", ".sub",
518 ".table", ".index", ".sbi" };
519 const char *ext = strrchr(fname, '.');
524 for (i = 0; i < array_size(cdimg_exts); i++)
525 if (strcasecmp(ext, cdimg_exts[i]) == 0)
527 for (i = 0; i < array_size(other_exts); i++)
528 if (strcasecmp(ext, other_exts[i]) == 0)
533 static void draw_savestate_bg(int slot);
535 static const char *filter_exts[] = {
536 ".mp3", ".MP3", ".txt", ".htm", "html", ".jpg", ".pnd"
539 #define MENU_ALIGN_LEFT
540 #ifdef __ARM_ARCH_7A__ // assume hires device
546 #define menu_init menu_init_common
547 #include "common/menu.c"
550 // a bit of black magic here
551 static void draw_savestate_bg(int slot)
553 static const int psx_widths[8] = { 256, 368, 320, 384, 512, 512, 640, 640 };
555 char fname[MAXPATHLEN];
562 ret = get_state_filename(fname, sizeof(fname), slot);
566 f = gzopen(fname, "rb");
570 if (gzseek(f, 0x29933d, SEEK_SET) != 0x29933d) {
571 fprintf(stderr, "gzseek failed\n");
576 gpu = malloc(sizeof(*gpu));
582 ret = gzread(f, gpu, sizeof(*gpu));
584 if (ret != sizeof(*gpu)) {
585 fprintf(stderr, "gzread failed\n");
589 memcpy(g_menubg_ptr, g_menubg_src_ptr, g_menuscreen_w * g_menuscreen_h * 2);
591 if (gpu->ulStatus & 0x800000)
592 goto out; // disabled
594 x = gpu->ulControl[5] & 0x3ff;
595 y = (gpu->ulControl[5] >> 10) & 0x1ff;
596 s = (u16 *)gpu->psxVRam + y * 1024 + (x & ~1);
597 w = psx_widths[(gpu->ulStatus >> 16) & 7];
598 tmp = gpu->ulControl[7];
599 h = ((tmp >> 10) & 0x3ff) - (tmp & 0x3ff);
600 if (gpu->ulStatus & 0x80000) // doubleheight
603 x = max(0, g_menuscreen_w - w) & ~3;
604 y = max(0, g_menuscreen_h / 2 - h / 2);
605 w = min(g_menuscreen_w, w);
606 h = min(g_menuscreen_h, h);
607 d = (u16 *)g_menubg_ptr + g_menuscreen_w * y + x;
609 for (; h > 0; h--, d += g_menuscreen_w, s += 1024) {
610 if (gpu->ulStatus & 0x200000)
611 bgr888_to_rgb565(d, s, w * 3);
613 bgr555_to_rgb565(d, s, w * 2);
615 // darken this so that menu text is visible
616 if (g_menuscreen_w - w < 320)
617 menu_darken_bg(d, d, w * 2, 0);
624 // ---------- XXX: pandora specific -----------
626 static const char pnd_script_base[] = "sudo -n /usr/pandora/scripts";
627 static char **pnd_filter_list;
629 static void apply_filter(int which)
635 if (pnd_filter_list == NULL || which == old)
638 for (i = 0; i < which; i++)
639 if (pnd_filter_list[i] == NULL)
642 if (pnd_filter_list[i] == NULL)
645 snprintf(buf, sizeof(buf), "%s/op_videofir.sh %s", pnd_script_base, pnd_filter_list[i]);
650 static void apply_lcdrate(int pal)
658 snprintf(buf, sizeof(buf), "%s/op_lcdrate.sh %d",
659 pnd_script_base, pal ? 50 : 60);
664 static menu_entry e_menu_gfx_options[];
666 static void pnd_menu_init(void)
674 cpu_clock_st = cpu_clock = plat_cpu_clock_get();
676 dir = opendir("/etc/pandora/conf/dss_fir");
678 perror("filter opendir");
691 if (ent->d_type != DT_REG && ent->d_type != DT_LNK)
700 mfilters = calloc(count + 1, sizeof(mfilters[0]));
701 if (mfilters == NULL)
705 for (i = 0; (ent = readdir(dir)); ) {
708 if (ent->d_type != DT_REG && ent->d_type != DT_LNK)
711 len = strlen(ent->d_name);
713 // skip pre-HF5 extra files
714 if (len >= 3 && strcmp(ent->d_name + len - 3, "_v3") == 0)
716 if (len >= 3 && strcmp(ent->d_name + len - 3, "_v5") == 0)
719 // have to cut "_up_h" for pre-HF5
720 if (len > 5 && strcmp(ent->d_name + len - 5, "_up_h") == 0)
723 if (len > sizeof(buff) - 1)
726 strncpy(buff, ent->d_name, len);
728 mfilters[i] = strdup(buff);
729 if (mfilters[i] != NULL)
734 i = me_id2offset(e_menu_gfx_options, MA_OPT_FILTERING);
735 e_menu_gfx_options[i].data = (void *)mfilters;
736 pnd_filter_list = mfilters;
739 void menu_finish(void)
741 plat_cpu_clock_apply(cpu_clock_st);
744 // -------------- key config --------------
746 me_bind_action me_ctrl_actions[] =
748 { "UP ", 1 << DKEY_UP},
749 { "DOWN ", 1 << DKEY_DOWN },
750 { "LEFT ", 1 << DKEY_LEFT },
751 { "RIGHT ", 1 << DKEY_RIGHT },
752 { "TRIANGLE", 1 << DKEY_TRIANGLE },
753 { "CIRCLE ", 1 << DKEY_CIRCLE },
754 { "CROSS ", 1 << DKEY_CROSS },
755 { "SQUARE ", 1 << DKEY_SQUARE },
756 { "L1 ", 1 << DKEY_L1 },
757 { "R1 ", 1 << DKEY_R1 },
758 { "L2 ", 1 << DKEY_L2 },
759 { "R2 ", 1 << DKEY_R2 },
760 { "L3 ", 1 << DKEY_L3 },
761 { "R3 ", 1 << DKEY_R3 },
762 { "START ", 1 << DKEY_START },
763 { "SELECT ", 1 << DKEY_SELECT },
767 me_bind_action emuctrl_actions[] =
769 { "Save State ", 1 << SACTION_SAVE_STATE },
770 { "Load State ", 1 << SACTION_LOAD_STATE },
771 { "Prev Save Slot ", 1 << SACTION_PREV_SSLOT },
772 { "Next Save Slot ", 1 << SACTION_NEXT_SSLOT },
773 { "Toggle Frameskip ", 1 << SACTION_TOGGLE_FSKIP },
774 { "Take Screenshot ", 1 << SACTION_SCREENSHOT },
775 { "Enter Menu ", 1 << SACTION_ENTER_MENU },
776 #ifdef __ARM_ARCH_7A__ /* XXX */
777 { "Minimize ", 1 << SACTION_MINIMIZE },
779 { "Gun Trigger ", 1 << SACTION_GUN_TRIGGER },
780 { "Gun A button ", 1 << SACTION_GUN_A },
781 { "Gun B button ", 1 << SACTION_GUN_B },
782 { "Gun Offscreen Trigger", 1 << SACTION_GUN_TRIGGER2 },
783 #ifndef __ARM_ARCH_7A__ /* XXX */
784 { "Volume Up ", 1 << SACTION_VOLUME_UP },
785 { "Volume Down ", 1 << SACTION_VOLUME_DOWN },
790 static char *mystrip(char *str)
795 for (i = 0; i < len; i++)
796 if (str[i] != ' ') break;
797 if (i > 0) memmove(str, str + i, len - i + 1);
800 for (i = len - 1; i >= 0; i--)
801 if (str[i] != ' ') break;
807 static void get_line(char *d, size_t size, const char *s)
812 for (pe = s; *pe != '\r' && *pe != '\n' && *pe != 0; pe++)
823 static void keys_write_all(FILE *f)
827 for (d = 0; d < IN_MAX_DEVS; d++)
829 const int *binds = in_get_dev_binds(d);
830 const char *name = in_get_dev_name(d, 0, 0);
833 if (binds == NULL || name == NULL)
836 fprintf(f, "binddev = %s\n", name);
837 in_get_config(d, IN_CFG_BIND_COUNT, &count);
839 for (k = 0; k < count; k++)
844 act[0] = act[31] = 0;
845 name = in_get_key_name(d, k);
847 kbinds = binds[IN_BIND_OFFS(k, IN_BINDTYPE_PLAYER12)];
848 for (i = 0; kbinds && i < ARRAY_SIZE(me_ctrl_actions) - 1; i++) {
849 mask = me_ctrl_actions[i].mask;
851 strncpy(act, me_ctrl_actions[i].name, 31);
852 fprintf(f, "bind %s = player1 %s\n", name, mystrip(act));
855 mask = me_ctrl_actions[i].mask << 16;
857 strncpy(act, me_ctrl_actions[i].name, 31);
858 fprintf(f, "bind %s = player2 %s\n", name, mystrip(act));
863 kbinds = binds[IN_BIND_OFFS(k, IN_BINDTYPE_EMU)];
864 for (i = 0; kbinds && emuctrl_actions[i].name != NULL; i++) {
865 mask = emuctrl_actions[i].mask;
867 strncpy(act, emuctrl_actions[i].name, 31);
868 fprintf(f, "bind %s = %s\n", name, mystrip(act));
874 for (k = 0; k < array_size(in_adev); k++)
877 fprintf(f, "bind_analog = %d\n", k);
882 static int parse_bind_val(const char *val, int *type)
886 *type = IN_BINDTYPE_NONE;
890 if (strncasecmp(val, "player", 6) == 0)
892 int player, shift = 0;
893 player = atoi(val + 6) - 1;
895 if ((unsigned int)player > 1)
900 *type = IN_BINDTYPE_PLAYER12;
901 for (i = 0; me_ctrl_actions[i].name != NULL; i++) {
902 if (strncasecmp(me_ctrl_actions[i].name, val + 8, strlen(val + 8)) == 0)
903 return me_ctrl_actions[i].mask << shift;
906 for (i = 0; emuctrl_actions[i].name != NULL; i++) {
907 if (strncasecmp(emuctrl_actions[i].name, val, strlen(val)) == 0) {
908 *type = IN_BINDTYPE_EMU;
909 return emuctrl_actions[i].mask;
916 static void keys_load_all(const char *cfg)
918 char dev[256], key[128], *act;
924 while (p != NULL && (p = strstr(p, "binddev = ")) != NULL) {
927 get_line(dev, sizeof(dev), p);
928 dev_id = in_config_parse_dev(dev);
930 printf("input: can't handle dev: %s\n", dev);
934 in_unbind_all(dev_id, -1, -1);
935 while ((p = strstr(p, "bind"))) {
936 if (strncmp(p, "binddev = ", 10) == 0)
939 if (strncmp(p, "bind_analog", 11) == 0) {
940 ret = sscanf(p, "bind_analog = %d", &bind);
943 printf("input: parse error: %16s..\n", p);
946 if ((unsigned int)bind >= array_size(in_adev)) {
947 printf("input: analog id %d out of range\n", bind);
950 in_adev[bind] = dev_id;
956 printf("input: parse error: %16s..\n", p);
960 get_line(key, sizeof(key), p);
961 act = strchr(key, '=');
963 printf("parse failed: %16s..\n", p);
971 bind = parse_bind_val(act, &bindtype);
972 if (bind != -1 && bind != 0) {
973 //printf("bind #%d '%s' %08x (%s)\n", dev_id, key, bind, act);
974 in_config_bind_key(dev_id, key, bind, bindtype);
977 lprintf("config: unhandled action \"%s\"\n", act);
983 static int key_config_loop_wrap(int id, int keys)
986 case MA_CTRL_PLAYER1:
987 key_config_loop(me_ctrl_actions, array_size(me_ctrl_actions) - 1, 0);
989 case MA_CTRL_PLAYER2:
990 key_config_loop(me_ctrl_actions, array_size(me_ctrl_actions) - 1, 1);
993 key_config_loop(emuctrl_actions, array_size(emuctrl_actions) - 1, -1);
1001 static const char *adevnames[IN_MAX_DEVS + 2];
1002 static int stick_sel[2];
1004 static menu_entry e_menu_keyconfig_analog[] =
1006 mee_enum ("Left stick (L3)", 0, stick_sel[0], adevnames),
1007 mee_range(" X axis", 0, in_adev_axis[0][0], 0, 7),
1008 mee_range(" Y axis", 0, in_adev_axis[0][1], 0, 7),
1009 mee_enum ("Right stick (R3)", 0, stick_sel[1], adevnames),
1010 mee_range(" X axis", 0, in_adev_axis[1][0], 0, 7),
1011 mee_range(" Y axis", 0, in_adev_axis[1][1], 0, 7),
1015 static int key_config_analog(int id, int keys)
1017 int i, d, count, sel = 0;
1018 int sel2dev_map[IN_MAX_DEVS];
1020 memset(adevnames, 0, sizeof(adevnames));
1021 memset(sel2dev_map, 0xff, sizeof(sel2dev_map));
1022 memset(stick_sel, 0, sizeof(stick_sel));
1024 adevnames[0] = "None";
1026 for (d = 0; d < IN_MAX_DEVS; d++)
1028 const char *name = in_get_dev_name(d, 0, 1);
1033 in_get_config(d, IN_CFG_ABS_AXIS_COUNT, &count);
1037 if (in_adev[0] == d) stick_sel[0] = i;
1038 if (in_adev[1] == d) stick_sel[1] = i;
1040 adevnames[i++] = name;
1042 adevnames[i] = NULL;
1044 me_loop(e_menu_keyconfig_analog, &sel);
1046 in_adev[0] = sel2dev_map[stick_sel[0]];
1047 in_adev[1] = sel2dev_map[stick_sel[1]];
1052 static const char *mgn_dev_name(int id, int *offs)
1054 const char *name = NULL;
1057 if (id == MA_CTRL_DEV_FIRST)
1060 for (; it < IN_MAX_DEVS; it++) {
1061 name = in_get_dev_name(it, 1, 1);
1070 static const char *mgn_saveloadcfg(int id, int *offs)
1075 static int mh_savecfg(int id, int keys)
1077 if (menu_write_config(id == MA_OPT_SAVECFG_GAME ? 1 : 0) == 0)
1078 me_update_msg("config saved");
1080 me_update_msg("failed to write config");
1085 static int mh_input_rescan(int id, int keys)
1087 //menu_sync_config();
1089 me_update_msg("rescan complete.");
1094 static const char *men_in_type_sel[] = {
1095 "Standard (SCPH-1080)",
1096 "Analog (SCPH-1150)",
1100 static const char h_nub_btns[] = "Experimental, keep this OFF if unsure. Select rescan after change.";
1101 static const char h_notsgun[] = "Don't trigger (shoot) when touching screen in gun games.";
1102 static const char h_vibration[]= "Must select analog above and enable this ingame too.";
1104 static menu_entry e_menu_keyconfig[] =
1106 mee_handler_id("Player 1", MA_CTRL_PLAYER1, key_config_loop_wrap),
1107 mee_handler_id("Player 2", MA_CTRL_PLAYER2, key_config_loop_wrap),
1108 mee_handler_id("Analog controls", MA_CTRL_ANALOG, key_config_analog),
1109 mee_handler_id("Emulator/Gun controls", MA_CTRL_EMU, key_config_loop_wrap),
1111 mee_enum ("Port 1 device", 0, in_type_sel1, men_in_type_sel),
1112 mee_enum ("Port 2 device", 0, in_type_sel2, men_in_type_sel),
1113 mee_onoff_h ("Nubs as buttons", MA_CTRL_NUBS_BTNS, in_evdev_allow_abs_only, 1, h_nub_btns),
1114 mee_onoff_h ("Vibration", MA_CTRL_VIBRATION, in_enable_vibration, 1, h_vibration),
1115 mee_range ("Analog deadzone", MA_CTRL_DEADZONE, analog_deadzone, 1, 99),
1116 mee_onoff_h ("No TS Gun trigger", 0, g_opts, OPT_TSGUN_NOTRIGGER, h_notsgun),
1117 mee_cust_nosave("Save global config", MA_OPT_SAVECFG, mh_savecfg, mgn_saveloadcfg),
1118 mee_cust_nosave("Save cfg for loaded game", MA_OPT_SAVECFG_GAME, mh_savecfg, mgn_saveloadcfg),
1119 mee_handler ("Rescan devices:", mh_input_rescan),
1121 mee_label_mk (MA_CTRL_DEV_FIRST, mgn_dev_name),
1122 mee_label_mk (MA_CTRL_DEV_NEXT, mgn_dev_name),
1123 mee_label_mk (MA_CTRL_DEV_NEXT, mgn_dev_name),
1124 mee_label_mk (MA_CTRL_DEV_NEXT, mgn_dev_name),
1125 mee_label_mk (MA_CTRL_DEV_NEXT, mgn_dev_name),
1126 mee_label_mk (MA_CTRL_DEV_NEXT, mgn_dev_name),
1127 mee_label_mk (MA_CTRL_DEV_NEXT, mgn_dev_name),
1131 static int menu_loop_keyconfig(int id, int keys)
1135 // me_enable(e_menu_keyconfig, MA_OPT_SAVECFG_GAME, ready_to_go && CdromId[0]);
1136 me_loop(e_menu_keyconfig, &sel);
1140 // ------------ gfx options menu ------------
1142 static const char *men_scaler[] = { "1x1", "scaled 4:3", "integer scaled 4:3", "fullscreen", "custom", NULL };
1143 static const char h_cscaler[] = "Displays the scaler layer, you can resize it\n"
1144 "using d-pad or move it using R+d-pad";
1145 static const char *men_dummy[] = { NULL };
1147 static int menu_loop_cscaler(int id, int keys)
1151 scaling = SCALE_CUSTOM;
1158 memset(g_menuscreen_ptr, 4, g_menuscreen_w * g_menuscreen_h * 2);
1159 text_out16(2, 2, "%d,%d", g_layer_x, g_layer_y);
1160 text_out16(2, 480 - 18, "%dx%d | d-pad: resize, R+d-pad: move", g_layer_w, g_layer_h);
1163 inp = in_menu_wait(PBTN_UP|PBTN_DOWN|PBTN_LEFT|PBTN_RIGHT|PBTN_R|PBTN_MOK|PBTN_MBACK, 40);
1164 if (inp & PBTN_UP) g_layer_y--;
1165 if (inp & PBTN_DOWN) g_layer_y++;
1166 if (inp & PBTN_LEFT) g_layer_x--;
1167 if (inp & PBTN_RIGHT) g_layer_x++;
1168 if (!(inp & PBTN_R)) {
1169 if (inp & PBTN_UP) g_layer_h += 2;
1170 if (inp & PBTN_DOWN) g_layer_h -= 2;
1171 if (inp & PBTN_LEFT) g_layer_w += 2;
1172 if (inp & PBTN_RIGHT) g_layer_w -= 2;
1174 if (inp & (PBTN_MOK|PBTN_MBACK))
1177 if (inp & (PBTN_UP|PBTN_DOWN|PBTN_LEFT|PBTN_RIGHT)) {
1178 if (g_layer_x < 0) g_layer_x = 0;
1179 if (g_layer_x > 640) g_layer_x = 640;
1180 if (g_layer_y < 0) g_layer_y = 0;
1181 if (g_layer_y > 420) g_layer_y = 420;
1182 if (g_layer_w < 160) g_layer_w = 160;
1183 if (g_layer_h < 60) g_layer_h = 60;
1184 if (g_layer_x + g_layer_w > 800)
1185 g_layer_w = 800 - g_layer_x;
1186 if (g_layer_y + g_layer_h > 480)
1187 g_layer_h = 480 - g_layer_y;
1193 plat_gvideo_close();
1198 static menu_entry e_menu_gfx_options[] =
1200 mee_enum ("Scaler", MA_OPT_SCALER, scaling, men_scaler),
1201 mee_onoff ("Software Scaling", MA_OPT_SCALER2, soft_scaling, 1),
1202 mee_enum ("Filter", MA_OPT_FILTERING, filter, men_dummy),
1203 // mee_onoff ("Vsync", 0, vsync, 1),
1204 mee_cust_h ("Setup custom scaler", MA_OPT_SCALER_C, menu_loop_cscaler, NULL, h_cscaler),
1208 static int menu_loop_gfx_options(int id, int keys)
1212 me_loop(e_menu_gfx_options, &sel);
1217 // ------------ bios/plugins ------------
1221 static const char h_gpu_neon[] = "Configure built-in NEON GPU plugin";
1222 static const char *men_gpu_interlace[] = { "Off", "On", "Auto", NULL };
1224 static menu_entry e_menu_plugin_gpu_neon[] =
1226 mee_enum ("Enable interlace mode", 0, pl_rearmed_cbs.gpu_neon.allow_interlace, men_gpu_interlace),
1230 static int menu_loop_plugin_gpu_neon(int id, int keys)
1233 me_loop(e_menu_plugin_gpu_neon, &sel);
1239 static menu_entry e_menu_plugin_gpu_unai[] =
1241 mee_onoff ("Skip every 2nd line", 0, pl_rearmed_cbs.gpu_unai.lineskip, 1),
1242 mee_onoff ("Abe's Odyssey hack", 0, pl_rearmed_cbs.gpu_unai.abe_hack, 1),
1243 mee_onoff ("Disable lighting", 0, pl_rearmed_cbs.gpu_unai.no_light, 1),
1244 mee_onoff ("Disable blending", 0, pl_rearmed_cbs.gpu_unai.no_blend, 1),
1248 static int menu_loop_plugin_gpu_unai(int id, int keys)
1251 me_loop(e_menu_plugin_gpu_unai, &sel);
1255 static const char *men_gpu_dithering[] = { "None", "Game dependant", "Always", NULL };
1256 //static const char h_gpu_0[] = "Needed for Chrono Cross";
1257 static const char h_gpu_1[] = "Capcom fighting games";
1258 static const char h_gpu_2[] = "Black screens in Lunar";
1259 static const char h_gpu_3[] = "Compatibility mode";
1260 static const char h_gpu_6[] = "Pandemonium 2";
1261 //static const char h_gpu_7[] = "Skip every second frame";
1262 static const char h_gpu_8[] = "Needed by Dark Forces";
1263 static const char h_gpu_9[] = "better g-colors, worse textures";
1264 static const char h_gpu_10[] = "Toggle busy flags after drawing";
1266 static menu_entry e_menu_plugin_gpu_peops[] =
1268 mee_enum ("Dithering", 0, pl_rearmed_cbs.gpu_peops.iUseDither, men_gpu_dithering),
1269 // mee_onoff_h ("Odd/even bit hack", 0, pl_rearmed_cbs.gpu_peops.dwActFixes, 1<<0, h_gpu_0),
1270 mee_onoff_h ("Expand screen width", 0, pl_rearmed_cbs.gpu_peops.dwActFixes, 1<<1, h_gpu_1),
1271 mee_onoff_h ("Ignore brightness color", 0, pl_rearmed_cbs.gpu_peops.dwActFixes, 1<<2, h_gpu_2),
1272 mee_onoff_h ("Disable coordinate check", 0, pl_rearmed_cbs.gpu_peops.dwActFixes, 1<<3, h_gpu_3),
1273 mee_onoff_h ("Lazy screen update", 0, pl_rearmed_cbs.gpu_peops.dwActFixes, 1<<6, h_gpu_6),
1274 // mee_onoff_h ("Old frame skipping", 0, pl_rearmed_cbs.gpu_peops.dwActFixes, 1<<7, h_gpu_7),
1275 mee_onoff_h ("Repeated flat tex triangles ",0,pl_rearmed_cbs.gpu_peops.dwActFixes, 1<<8, h_gpu_8),
1276 mee_onoff_h ("Draw quads with triangles", 0, pl_rearmed_cbs.gpu_peops.dwActFixes, 1<<9, h_gpu_9),
1277 mee_onoff_h ("Fake 'gpu busy' states", 0, pl_rearmed_cbs.gpu_peops.dwActFixes, 1<<10, h_gpu_10),
1281 static int menu_loop_plugin_gpu_peops(int id, int keys)
1284 me_loop(e_menu_plugin_gpu_peops, &sel);
1288 static const char *men_peopsgl_texfilter[] = { "None", "Standard", "Extended",
1289 "Standard-sprites", "Extended-sprites", "Standard+sprites", "Extended+sprites", NULL };
1290 static const char *men_peopsgl_fbtex[] = { "Emulated VRam", "Black", "Card", "Card+soft" };
1292 static menu_entry e_menu_plugin_gpu_peopsgl[] =
1294 mee_onoff ("Dithering", 0, pl_rearmed_cbs.gpu_peopsgl.bDrawDither, 1),
1295 mee_enum ("Texture Filtering", 0, pl_rearmed_cbs.gpu_peopsgl.iFilterType, men_peopsgl_texfilter),
1296 mee_enum ("Framebuffer Textures", 0, pl_rearmed_cbs.gpu_peopsgl.iFrameTexType, men_peopsgl_fbtex),
1297 mee_onoff ("Mask Detect", 0, pl_rearmed_cbs.gpu_peopsgl.iUseMask, 1),
1298 mee_onoff ("Opaque Pass", 0, pl_rearmed_cbs.gpu_peopsgl.bOpaquePass, 1),
1299 mee_onoff ("Advanced Blend", 0, pl_rearmed_cbs.gpu_peopsgl.bAdvancedBlend, 1),
1300 mee_onoff ("Use Fast Mdec", 0, pl_rearmed_cbs.gpu_peopsgl.bUseFastMdec, 1),
1301 mee_range ("Texture RAM size (MB)", 0, pl_rearmed_cbs.gpu_peopsgl.iVRamSize, 4, 128),
1302 mee_onoff ("Texture garbage collection", 0, pl_rearmed_cbs.gpu_peopsgl.iTexGarbageCollection, 1),
1303 mee_label ("Fixes/hacks:"),
1304 mee_onoff ("FF7 cursor", 0, pl_rearmed_cbs.gpu_peopsgl.dwActFixes, 1<<0),
1305 mee_onoff ("Direct FB updates", 0, pl_rearmed_cbs.gpu_peopsgl.dwActFixes, 1<<1),
1306 mee_onoff ("Black brightness", 0, pl_rearmed_cbs.gpu_peopsgl.dwActFixes, 1<<2),
1307 mee_onoff ("Swap front detection", 0, pl_rearmed_cbs.gpu_peopsgl.dwActFixes, 1<<3),
1308 mee_onoff ("Disable coord check", 0, pl_rearmed_cbs.gpu_peopsgl.dwActFixes, 1<<4),
1309 mee_onoff ("No blue glitches (LoD)", 0, pl_rearmed_cbs.gpu_peopsgl.dwActFixes, 1<<5),
1310 mee_onoff ("Soft FB access", 0, pl_rearmed_cbs.gpu_peopsgl.dwActFixes, 1<<6),
1311 mee_onoff ("FF9 rect", 0, pl_rearmed_cbs.gpu_peopsgl.dwActFixes, 1<<9),
1312 mee_onoff ("No subtr. blending", 0, pl_rearmed_cbs.gpu_peopsgl.dwActFixes, 1<<10),
1313 mee_onoff ("Lazy upload (DW7)", 0, pl_rearmed_cbs.gpu_peopsgl.dwActFixes, 1<<11),
1314 mee_onoff ("Additional uploads", 0, pl_rearmed_cbs.gpu_peopsgl.dwActFixes, 1<<15),
1318 static int menu_loop_plugin_gpu_peopsgl(int id, int keys)
1321 me_loop(e_menu_plugin_gpu_peopsgl, &sel);
1325 static const char *men_spu_interp[] = { "None", "Simple", "Gaussian", "Cubic", NULL };
1326 static const char h_spu_volboost[] = "Large values cause distortion";
1327 static const char h_spu_irq_wait[] = "Wait for CPU (recommended set to ON)";
1328 static const char h_spu_thread[] = "Run sound emulation in main thread (recommended)";
1330 static menu_entry e_menu_plugin_spu[] =
1332 mee_range_h ("Volume boost", 0, volume_boost, -5, 30, h_spu_volboost),
1333 mee_onoff ("Reverb", 0, iUseReverb, 2),
1334 mee_enum ("Interpolation", 0, iUseInterpolation, men_spu_interp),
1335 mee_onoff ("Adjust XA pitch", 0, iXAPitch, 1),
1336 mee_onoff_h ("SPU IRQ Wait", 0, iSPUIRQWait, 1, h_spu_irq_wait),
1337 mee_onoff_h ("Sound in main thread", 0, iUseTimer, 2, h_spu_thread),
1341 static int menu_loop_plugin_spu(int id, int keys)
1344 me_loop(e_menu_plugin_spu, &sel);
1348 static const char h_bios[] = "HLE is simulated BIOS. BIOS selection is saved in\n"
1349 "savestates and can't be changed there. Must save\n"
1350 "config and reload the game for change to take effect";
1351 static const char h_plugin_gpu[] =
1353 "builtin_gpu is the NEON GPU, very fast and accurate\n"
1358 "is Pete's soft GPU, slow but accurate\n"
1359 "gpuPCSX4ALL is GPU from PCSX4ALL, fast but glitchy\n"
1360 "gpuGLES Pete's hw GPU, uses 3D chip but is glitchy\n"
1361 "must save config and reload the game if changed";
1362 static const char h_plugin_spu[] = "spunull effectively disables sound\n"
1363 "must save config and reload the game if changed";
1364 static const char h_gpu_peops[] = "Configure P.E.Op.S. SoftGL Driver V1.17";
1365 static const char h_gpu_peopsgl[]= "Configure P.E.Op.S. MesaGL Driver V1.78";
1366 static const char h_gpu_unai[] = "Configure Unai/PCSX4ALL Team GPU plugin";
1367 static const char h_spu[] = "Configure built-in P.E.Op.S. Sound Driver V1.7";
1369 static menu_entry e_menu_plugin_options[] =
1371 mee_enum_h ("BIOS", 0, bios_sel, bioses, h_bios),
1372 mee_enum_h ("GPU plugin", 0, gpu_plugsel, gpu_plugins, h_plugin_gpu),
1373 mee_enum_h ("SPU plugin", 0, spu_plugsel, spu_plugins, h_plugin_spu),
1375 mee_handler_h ("Configure built-in GPU plugin", menu_loop_plugin_gpu_neon, h_gpu_neon),
1377 mee_handler_h ("Configure gpu_peops plugin", menu_loop_plugin_gpu_peops, h_gpu_peops),
1378 mee_handler_h ("Configure PCSX4ALL GPU plugin", menu_loop_plugin_gpu_unai, h_gpu_unai),
1379 mee_handler_h ("Configure GLES GPU plugin", menu_loop_plugin_gpu_peopsgl, h_gpu_peopsgl),
1380 mee_handler_h ("Configure built-in SPU plugin", menu_loop_plugin_spu, h_spu),
1384 static menu_entry e_menu_main2[];
1386 static int menu_loop_plugin_options(int id, int keys)
1389 me_loop(e_menu_plugin_options, &sel);
1391 // sync BIOS/plugins
1392 snprintf(Config.Bios, sizeof(Config.Bios), "%s", bioses[bios_sel]);
1393 snprintf(Config.Gpu, sizeof(Config.Gpu), "%s", gpu_plugins[gpu_plugsel]);
1394 snprintf(Config.Spu, sizeof(Config.Spu), "%s", spu_plugins[spu_plugsel]);
1395 me_enable(e_menu_main2, MA_MAIN_RUN_BIOS, bios_sel != 0);
1400 // ------------ adv options menu ------------
1402 static const char h_cfg_psxclk[] = "Over/under-clock the PSX, default is " DEFAULT_PSX_CLOCK_S "\n"
1403 "(lower value - less work for the emu, may be faster)";
1404 static const char h_cfg_nosmc[] = "Will cause crashes when loading, break memcards";
1405 static const char h_cfg_gteunn[] = "May cause graphical glitches";
1406 static const char h_cfg_gteflgs[] = "Will cause graphical glitches";
1408 static menu_entry e_menu_speed_hacks[] =
1410 mee_range_h ("PSX CPU clock, %%", 0, psx_clock, 1, 500, h_cfg_psxclk),
1411 mee_onoff_h ("Disable SMC checks", 0, new_dynarec_hacks, NDHACK_NO_SMC_CHECK, h_cfg_nosmc),
1412 mee_onoff_h ("Assume GTE regs unneeded", 0, new_dynarec_hacks, NDHACK_GTE_UNNEEDED, h_cfg_gteunn),
1413 mee_onoff_h ("Disable GTE flags", 0, new_dynarec_hacks, NDHACK_GTE_NO_FLAGS, h_cfg_gteflgs),
1417 static int menu_loop_speed_hacks(int id, int keys)
1420 me_loop(e_menu_speed_hacks, &sel);
1424 static const char *men_cfg_cdrr[] = { "Auto", "ON", "OFF", NULL };
1425 static const char h_cfg_cpul[] = "Shows CPU usage in %";
1426 static const char h_cfg_spu[] = "Shows active SPU channels\n"
1427 "(green: normal, red: fmod, blue: noise)";
1428 static const char h_cfg_fl[] = "Frame Limiter keeps the game from running too fast";
1429 static const char h_cfg_xa[] = "Disables XA sound, which can sometimes improve performance";
1430 static const char h_cfg_cdda[] = "Disable CD Audio for a performance boost\n"
1431 "(proper .cue/.bin dump is needed otherwise)";
1432 static const char h_cfg_sio[] = "You should not need this, breaks games";
1433 static const char h_cfg_spuirq[] = "Compatibility tweak; should be left off";
1434 static const char h_cfg_rcnt1[] = "Parasite Eve 2, Vandal Hearts 1/2 Fix\n"
1435 "(timing hack, breaks other games)";
1436 static const char h_cfg_rcnt2[] = "InuYasha Sengoku Battle Fix\n"
1437 "(timing hack, breaks other games)";
1438 static const char h_cfg_cdrr[] = "Compatibility tweak (CD timing hack, breaks FMVs)";
1439 static const char h_cfg_nodrc[] = "Disable dynamic recompiler and use interpreter\n"
1440 "Might be useful to overcome some dynarec bugs";
1441 static const char h_cfg_shacks[] = "Breaks games but may give better performance\n"
1442 "must reload game for any change to take effect";
1444 static menu_entry e_menu_adv_options[] =
1446 mee_onoff_h ("Show CPU load", 0, g_opts, OPT_SHOWCPU, h_cfg_cpul),
1447 mee_onoff_h ("Show SPU channels", 0, g_opts, OPT_SHOWSPU, h_cfg_spu),
1448 mee_onoff_h ("Disable Frame Limiter", 0, g_opts, OPT_NO_FRAMELIM, h_cfg_fl),
1449 mee_onoff_h ("Disable XA Decoding", 0, Config.Xa, 1, h_cfg_xa),
1450 mee_onoff_h ("Disable CD Audio", 0, Config.Cdda, 1, h_cfg_cdda),
1451 mee_onoff_h ("SIO IRQ Always Enabled", 0, Config.Sio, 1, h_cfg_sio),
1452 mee_onoff_h ("SPU IRQ Always Enabled", 0, Config.SpuIrq, 1, h_cfg_spuirq),
1453 //mee_onoff_h ("Rootcounter hack", 0, Config.RCntFix, 1, h_cfg_rcnt1),
1454 mee_onoff_h ("Rootcounter hack 2", 0, Config.VSyncWA, 1, h_cfg_rcnt2),
1455 mee_enum_h ("CD read reschedule hack",0, Config.CdrReschedule, men_cfg_cdrr, h_cfg_cdrr),
1456 mee_onoff_h ("Disable dynarec (slow!)",0, Config.Cpu, 1, h_cfg_nodrc),
1457 mee_handler_h ("[Speed hacks]", menu_loop_speed_hacks, h_cfg_shacks),
1461 static int menu_loop_adv_options(int id, int keys)
1464 me_loop(e_menu_adv_options, &sel);
1468 // ------------ options menu ------------
1470 static int mh_restore_defaults(int id, int keys)
1472 menu_set_defconfig();
1473 me_update_msg("defaults restored");
1477 static const char *men_region[] = { "Auto", "NTSC", "PAL", NULL };
1478 static const char *men_frameskip[] = { "Auto", "Off", "1", "2", "3", NULL };
1480 static const char *men_confirm_save[] = { "OFF", "writes", "loads", "both", NULL };
1481 static const char h_confirm_save[] = "Ask for confirmation when overwriting save,\n"
1482 "loading state or both";
1484 static const char h_restore_def[] = "Switches back to default / recommended\n"
1486 static const char h_frameskip[] = "Warning: frameskip sometimes causes glitches\n";
1488 static menu_entry e_menu_options[] =
1490 // mee_range ("Save slot", 0, state_slot, 0, 9),
1491 // mee_enum_h ("Confirm savestate", 0, dummy, men_confirm_save, h_confirm_save),
1492 mee_enum_h ("Frameskip", 0, frameskip, men_frameskip, h_frameskip),
1493 mee_onoff ("Show FPS", 0, g_opts, OPT_SHOWFPS),
1494 mee_enum ("Region", 0, region, men_region),
1495 mee_range ("CPU clock", MA_OPT_CPU_CLOCKS, cpu_clock, 20, 5000),
1496 mee_handler_id("[Display]", MA_OPT_DISP_OPTS, menu_loop_gfx_options),
1497 mee_handler ("[BIOS/Plugins]", menu_loop_plugin_options),
1498 mee_handler ("[Advanced]", menu_loop_adv_options),
1499 mee_cust_nosave("Save global config", MA_OPT_SAVECFG, mh_savecfg, mgn_saveloadcfg),
1500 mee_cust_nosave("Save cfg for loaded game",MA_OPT_SAVECFG_GAME, mh_savecfg, mgn_saveloadcfg),
1501 mee_handler_h ("Restore default config", mh_restore_defaults, h_restore_def),
1505 static int menu_loop_options(int id, int keys)
1510 i = me_id2offset(e_menu_options, MA_OPT_CPU_CLOCKS);
1511 e_menu_options[i].enabled = cpu_clock_st > 0 ? 1 : 0;
1512 me_enable(e_menu_options, MA_OPT_SAVECFG_GAME, ready_to_go && CdromId[0]);
1514 me_loop(e_menu_options, &sel);
1519 // ------------ debug menu ------------
1521 static void draw_frame_debug(GPUFreeze_t *gpuf, int x, int y)
1523 int w = min(g_menuscreen_w, 1024);
1524 int h = min(g_menuscreen_h, 512);
1525 u16 *d = g_menuscreen_ptr;
1526 u16 *s = (u16 *)gpuf->psxVRam + y * 1024 + x;
1530 gpuf->ulFreezeVersion = 1;
1531 if (GPU_freeze != NULL)
1532 GPU_freeze(1, gpuf);
1534 for (; h > 0; h--, d += g_menuscreen_w, s += 1024)
1535 bgr555_to_rgb565(d, s, w * 2);
1537 smalltext_out16(4, 1, "build: "__DATE__ " " __TIME__ " " REV, 0xe7fc);
1538 snprintf(buff, sizeof(buff), "GPU sr: %08x", gpuf->ulStatus);
1539 smalltext_out16(4, (ty += me_sfont_h), buff, 0xe7fc);
1540 snprintf(buff, sizeof(buff), "PC/SP: %08x %08x", psxRegs.pc, psxRegs.GPR.n.sp);
1541 smalltext_out16(4, (ty += me_sfont_h), buff, 0xe7fc);
1544 static void debug_menu_loop(void)
1546 int inp, df_x = 0, df_y = 0;
1549 gpuf = malloc(sizeof(*gpuf));
1556 draw_frame_debug(gpuf, df_x, df_y);
1559 inp = in_menu_wait(PBTN_MOK|PBTN_MBACK|PBTN_MA2|PBTN_MA3|PBTN_L|PBTN_R |
1560 PBTN_UP|PBTN_DOWN|PBTN_LEFT|PBTN_RIGHT, 10);
1561 if (inp & PBTN_MBACK) break;
1562 else if (inp & PBTN_UP) { if (df_y > 0) df_y--; }
1563 else if (inp & PBTN_DOWN) { if (df_y < 512 - g_menuscreen_h) df_y++; }
1564 else if (inp & PBTN_LEFT) { if (df_x > 0) df_x--; }
1565 else if (inp & PBTN_RIGHT) { if (df_x < 1024 - g_menuscreen_w) df_x++; }
1571 // --------- memcard manager ---------
1573 static void draw_mc_icon(int dx, int dy, const u16 *s)
1578 d = (u16 *)g_menuscreen_ptr + g_menuscreen_w * dy + dx;
1580 for (y = 0; y < 16; y++, s += 16) {
1581 for (l = 0; l < 2; l++, d += g_menuscreen_w) {
1582 for (x = 0; x < 16; x++) {
1584 d[x*2] = d[x*2 + 1] = ((p & 0x7c00) >> 10)
1585 | ((p & 0x03e0) << 1) | ((p & 0x1f) << 11);
1591 static void draw_mc_bg(void)
1593 McdBlock *blocks1, *blocks2;
1597 blocks1 = malloc(15 * sizeof(blocks1[0]));
1598 blocks2 = malloc(15 * sizeof(blocks1[0]));
1599 if (blocks1 == NULL || blocks2 == NULL)
1602 for (i = 0; i < 15; i++) {
1603 GetMcdBlockInfo(1, i + 1, &blocks1[i]);
1604 GetMcdBlockInfo(2, i + 1, &blocks2[i]);
1609 memcpy(g_menuscreen_ptr, g_menubg_src_ptr, g_menuscreen_w * g_menuscreen_h * 2);
1611 y = g_menuscreen_h / 2 - 15 * 32 / 2;
1615 maxicons = g_menuscreen_h / 32;
1618 row2 = g_menuscreen_w / 2;
1619 for (i = 0; i < maxicons; i++) {
1620 draw_mc_icon(8, y + i * 32, (u16 *)blocks1[i].Icon);
1621 smalltext_out16(10+32, y + i * 32 + 8, blocks1[i].sTitle, 0xf71e);
1623 draw_mc_icon(row2 + 8, y + i * 32, (u16 *)blocks2[i].Icon);
1624 smalltext_out16(row2 + 10+32, y + i * 32 + 8, blocks2[i].sTitle, 0xf71e);
1627 menu_darken_bg(g_menubg_ptr, g_menuscreen_ptr, g_menuscreen_w * g_menuscreen_h, 0);
1635 static void handle_memcard_sel(void)
1638 if (memcard1_sel != 0)
1639 snprintf(Config.Mcd1, sizeof(Config.Mcd1), ".%s%s", MEMCARD_DIR, memcards[memcard1_sel]);
1641 if (memcard2_sel != 0)
1642 snprintf(Config.Mcd2, sizeof(Config.Mcd2), ".%s%s", MEMCARD_DIR, memcards[memcard2_sel]);
1643 LoadMcds(Config.Mcd1, Config.Mcd2);
1647 static menu_entry e_memcard_options[] =
1649 mee_enum("Memory card 1", 0, memcard1_sel, memcards),
1650 mee_enum("Memory card 2", 0, memcard2_sel, memcards),
1654 static int menu_loop_memcards(int id, int keys)
1660 memcard1_sel = memcard2_sel = 0;
1661 p = strrchr(Config.Mcd1, '/');
1663 for (i = 0; memcards[i] != NULL; i++)
1664 if (strcmp(p + 1, memcards[i]) == 0)
1665 { memcard1_sel = i; break; }
1666 p = strrchr(Config.Mcd2, '/');
1668 for (i = 0; memcards[i] != NULL; i++)
1669 if (strcmp(p + 1, memcards[i]) == 0)
1670 { memcard2_sel = i; break; }
1672 me_loop_d(e_memcard_options, &sel, handle_memcard_sel, NULL);
1674 memcpy(g_menubg_ptr, g_menubg_src_ptr, g_menuscreen_w * g_menuscreen_h * 2);
1679 // --------- main menu help ----------
1681 static void menu_bios_warn(void)
1684 static const char msg[] =
1685 "You don't seem to have copied any BIOS\n"
1687 #ifdef __ARM_ARCH_7A__ // XXX
1688 "<SD card>/pandora/appdata/pcsx_rearmed/bios/\n\n"
1690 "pcsx_rearmed/bios/\n\n"
1692 "While many games work fine with fake\n"
1693 "(HLE) BIOS, others (like MGS and FF8)\n"
1694 "require BIOS to work.\n"
1695 "After copying the file, you'll also need\n"
1696 "to select it in the emu's menu:\n"
1697 "options->[BIOS/Plugins]\n\n"
1698 "The file is usually named SCPH1001.BIN,\n"
1699 "but other not compressed files can be\n"
1701 "Press (B) or (X) to continue";
1705 draw_menu_message(msg, NULL);
1707 inp = in_menu_wait(PBTN_MOK|PBTN_MBACK, 70);
1708 if (inp & (PBTN_MBACK|PBTN_MOK))
1713 // ------------ main menu ------------
1717 static void draw_frame_main(void)
1726 if (CdromId[0] != 0) {
1727 snprintf(buff, sizeof(buff), "%.32s/%.9s (running as %s, with %s)",
1728 get_cd_label(), CdromId, Config.PsxType ? "PAL" : "NTSC",
1729 Config.HLE ? "HLE" : "BIOS");
1730 smalltext_out16(4, 1, buff, 0x105f);
1734 capacity = plat_get_bat_capacity();
1736 tmp = localtime(<ime);
1737 strftime(ltime_s, sizeof(ltime_s), "%H:%M", tmp);
1738 if (capacity >= 0) {
1739 snprintf(buff, sizeof(buff), "%s %3d%%", ltime_s, capacity);
1744 smalltext_out16(4, 1 + me_sfont_h, out, 0x105f);
1748 static void draw_frame_credits(void)
1750 smalltext_out16(4, 1, "build: " __DATE__ " " __TIME__ " " REV, 0xe7fc);
1753 static const char credits_text[] =
1755 "(C) 1999-2003 PCSX Team\n"
1756 "(C) 2005-2009 PCSX-df Team\n"
1757 "(C) 2009-2011 PCSX-Reloaded Team\n\n"
1758 "ARM recompiler (C) 2009-2011 Ari64\n"
1760 "ARM NEON GPU (c) 2011-2012 Exophase\n"
1762 "PEOpS GPU and SPU by Pete Bernert\n"
1763 " and the P.E.Op.S. team\n"
1764 "PCSX4ALL plugin by PCSX4ALL team\n"
1765 " Chui, Franxis, Unai\n\n"
1766 "integration, optimization and\n"
1767 " frontend (C) 2010-2012 notaz\n";
1769 static int reset_game(void)
1772 if (bios_sel == 0 && !Config.HLE)
1778 if (CheckCdrom() != -1) {
1784 static int reload_plugins(const char *cdimg)
1790 set_cd_image(cdimg);
1792 pcnt_hook_plugins();
1794 if (OpenPlugins() == -1) {
1795 me_update_msg("failed to open plugins");
1798 plugin_call_rearmed_cbs();
1800 cdrIsoMultidiskCount = 1;
1802 CdromLabel[0] = '\0';
1807 static int run_bios(void)
1813 if (reload_plugins(NULL) != 0)
1821 static int run_exe(void)
1825 fname = menu_loop_romsel(last_selected_fname, sizeof(last_selected_fname));
1830 if (reload_plugins(NULL) != 0)
1834 if (Load(fname) != 0) {
1835 me_update_msg("exe load failed, bad file?");
1844 static int run_cd_image(const char *fname)
1847 reload_plugins(fname);
1849 // always autodetect, menu_sync_config will override as needed
1852 if (CheckCdrom() == -1) {
1853 // Only check the CD if we are starting the console with a CD
1855 me_update_msg("unsupported/invalid CD image");
1861 // Read main executable directly from CDRom and start it
1862 if (LoadCdrom() == -1) {
1864 me_update_msg("failed to load CD image");
1869 snprintf(hud_msg, sizeof(hud_msg), "Booting up...");
1874 static int romsel_run(void)
1876 int prev_gpu, prev_spu;
1879 fname = menu_loop_romsel(last_selected_fname, sizeof(last_selected_fname));
1883 printf("selected file: %s\n", fname);
1885 new_dynarec_clear_full();
1887 if (run_cd_image(fname) != 0)
1890 prev_gpu = gpu_plugsel;
1891 prev_spu = spu_plugsel;
1892 if (menu_load_config(1) != 0)
1893 menu_load_config(0);
1895 // check for plugin changes, have to repeat
1896 // loading if game config changed plugins to reload them
1897 if (prev_gpu != gpu_plugsel || prev_spu != spu_plugsel) {
1898 printf("plugin change detected, reloading plugins..\n");
1899 if (run_cd_image(fname) != 0)
1904 printf("note: running without BIOS, expect compatibility problems\n");
1906 strcpy(last_selected_fname, rom_fname_reload);
1910 static int swap_cd_image(void)
1914 fname = menu_loop_romsel(last_selected_fname, sizeof(last_selected_fname));
1918 printf("selected file: %s\n", fname);
1921 CdromLabel[0] = '\0';
1923 set_cd_image(fname);
1924 if (ReloadCdromPlugin() < 0) {
1925 me_update_msg("failed to load cdr plugin");
1928 if (CDR_open() < 0) {
1929 me_update_msg("failed to open cdr plugin");
1933 SetCdOpenCaseTime(time(NULL) + 2);
1936 strcpy(last_selected_fname, rom_fname_reload);
1940 static int swap_cd_multidisk(void)
1942 cdrIsoMultidiskSelect++;
1944 CdromLabel[0] = '\0';
1947 if (CDR_open() < 0) {
1948 me_update_msg("failed to open cdr plugin");
1952 SetCdOpenCaseTime(time(NULL) + 2);
1958 static int main_menu_handler(int id, int keys)
1962 case MA_MAIN_RESUME_GAME:
1966 case MA_MAIN_SAVE_STATE:
1968 return menu_loop_savestate(0);
1970 case MA_MAIN_LOAD_STATE:
1972 return menu_loop_savestate(1);
1974 case MA_MAIN_RESET_GAME:
1975 if (ready_to_go && reset_game() == 0)
1978 case MA_MAIN_LOAD_ROM:
1979 if (romsel_run() == 0)
1982 case MA_MAIN_SWAP_CD:
1983 if (swap_cd_image() == 0)
1986 case MA_MAIN_SWAP_CD_MULTI:
1987 if (swap_cd_multidisk() == 0)
1990 case MA_MAIN_RUN_BIOS:
1991 if (run_bios() == 0)
1994 case MA_MAIN_RUN_EXE:
1998 case MA_MAIN_CREDITS:
1999 draw_menu_message(credits_text, draw_frame_credits);
2000 in_menu_wait(PBTN_MOK|PBTN_MBACK, 70);
2006 lprintf("%s: something unknown selected\n", __FUNCTION__);
2013 static menu_entry e_menu_main2[] =
2015 mee_handler_id("Change CD image", MA_MAIN_SWAP_CD, main_menu_handler),
2016 mee_handler_id("Next multidisk CD", MA_MAIN_SWAP_CD_MULTI, main_menu_handler),
2017 mee_handler_id("Run BIOS", MA_MAIN_RUN_BIOS, main_menu_handler),
2018 mee_handler_id("Run EXE", MA_MAIN_RUN_EXE, main_menu_handler),
2019 mee_handler ("Memcard manager", menu_loop_memcards),
2023 static int main_menu2_handler(int id, int keys)
2027 me_enable(e_menu_main2, MA_MAIN_SWAP_CD, ready_to_go);
2028 me_enable(e_menu_main2, MA_MAIN_SWAP_CD_MULTI, ready_to_go && cdrIsoMultidiskCount > 1);
2029 me_enable(e_menu_main2, MA_MAIN_RUN_BIOS, bios_sel != 0);
2031 return me_loop_d(e_menu_main2, &sel, NULL, draw_frame_main);
2034 static const char h_extra[] = "Change CD, manage memcards..\n";
2036 static menu_entry e_menu_main[] =
2040 mee_handler_id("Resume game", MA_MAIN_RESUME_GAME, main_menu_handler),
2041 mee_handler_id("Save State", MA_MAIN_SAVE_STATE, main_menu_handler),
2042 mee_handler_id("Load State", MA_MAIN_LOAD_STATE, main_menu_handler),
2043 mee_handler_id("Reset game", MA_MAIN_RESET_GAME, main_menu_handler),
2044 mee_handler_id("Load CD image", MA_MAIN_LOAD_ROM, main_menu_handler),
2045 mee_handler ("Options", menu_loop_options),
2046 mee_handler ("Controls", menu_loop_keyconfig),
2047 mee_handler_h ("Extra stuff", main_menu2_handler, h_extra),
2048 mee_handler_id("Credits", MA_MAIN_CREDITS, main_menu_handler),
2049 mee_handler_id("Exit", MA_MAIN_EXIT, main_menu_handler),
2053 // ----------------------------
2055 static void menu_leave_emu(void);
2057 void menu_loop(void)
2063 if (bioses[1] == NULL && !warned_about_bios) {
2065 warned_about_bios = 1;
2068 me_enable(e_menu_main, MA_MAIN_RESUME_GAME, ready_to_go);
2069 me_enable(e_menu_main, MA_MAIN_SAVE_STATE, ready_to_go && CdromId[0]);
2070 me_enable(e_menu_main, MA_MAIN_LOAD_STATE, ready_to_go && CdromId[0]);
2071 me_enable(e_menu_main, MA_MAIN_RESET_GAME, ready_to_go);
2073 in_set_config_int(0, IN_CFG_BLOCKING, 1);
2076 me_loop_d(e_menu_main, &sel, NULL, draw_frame_main);
2077 } while (!ready_to_go);
2079 /* wait until menu, ok, back is released */
2080 while (in_menu_wait_any(50) & (PBTN_MENU|PBTN_MOK|PBTN_MBACK))
2083 in_set_config_int(0, IN_CFG_BLOCKING, 0);
2088 static int qsort_strcmp(const void *p1, const void *p2)
2090 char * const *s1 = (char * const *)p1;
2091 char * const *s2 = (char * const *)p2;
2092 return strcasecmp(*s1, *s2);
2095 static void scan_bios_plugins(void)
2097 char fname[MAXPATHLEN];
2099 int bios_i, gpu_i, spu_i, mc_i;
2104 gpu_plugins[0] = "builtin_gpu";
2105 spu_plugins[0] = "builtin_spu";
2106 memcards[0] = "(none)";
2107 bios_i = gpu_i = spu_i = mc_i = 1;
2109 snprintf(fname, sizeof(fname), "%s/", Config.BiosDir);
2110 dir = opendir(fname);
2112 perror("scan_bios_plugins bios opendir");
2127 if (ent->d_type != DT_REG && ent->d_type != DT_LNK)
2130 snprintf(fname, sizeof(fname), "%s/%s", Config.BiosDir, ent->d_name);
2131 if (stat(fname, &st) != 0 || st.st_size != 512*1024) {
2132 printf("bad BIOS file: %s\n", ent->d_name);
2136 if (bios_i < ARRAY_SIZE(bioses) - 1) {
2137 bioses[bios_i++] = strdup(ent->d_name);
2141 printf("too many BIOSes, dropping \"%s\"\n", ent->d_name);
2147 snprintf(fname, sizeof(fname), "%s/", Config.PluginsDir);
2148 dir = opendir(fname);
2150 perror("scan_bios_plugins plugins opendir");
2164 p = strstr(ent->d_name, ".so");
2168 snprintf(fname, sizeof(fname), "%s/%s", Config.PluginsDir, ent->d_name);
2169 h = dlopen(fname, RTLD_LAZY | RTLD_LOCAL);
2171 fprintf(stderr, "%s\n", dlerror());
2175 // now what do we have here?
2176 tmp = dlsym(h, "GPUinit");
2179 if (gpu_i < ARRAY_SIZE(gpu_plugins) - 1)
2180 gpu_plugins[gpu_i++] = strdup(ent->d_name);
2184 tmp = dlsym(h, "SPUinit");
2187 if (spu_i < ARRAY_SIZE(spu_plugins) - 1)
2188 spu_plugins[spu_i++] = strdup(ent->d_name);
2192 fprintf(stderr, "ignoring unidentified plugin: %s\n", fname);
2199 dir = opendir("." MEMCARD_DIR);
2201 perror("scan_bios_plugins memcards opendir");
2216 if (ent->d_type != DT_REG && ent->d_type != DT_LNK)
2219 snprintf(fname, sizeof(fname), "." MEMCARD_DIR "%s", ent->d_name);
2220 if (stat(fname, &st) != 0) {
2221 printf("bad memcard file: %s\n", ent->d_name);
2225 if (mc_i < ARRAY_SIZE(memcards) - 1) {
2226 memcards[mc_i++] = strdup(ent->d_name);
2230 printf("too many memcards, dropping \"%s\"\n", ent->d_name);
2234 qsort(memcards + 1, mc_i - 1, sizeof(memcards[0]), qsort_strcmp);
2239 void menu_init(void)
2241 char buff[MAXPATHLEN];
2243 strcpy(last_selected_fname, "/media");
2245 scan_bios_plugins();
2249 menu_set_defconfig();
2250 menu_load_config(0);
2255 g_menubg_src_ptr = calloc(g_menuscreen_w * g_menuscreen_h * 2, 1);
2256 g_menubg_ptr = calloc(g_menuscreen_w * g_menuscreen_h * 2, 1);
2257 if (g_menubg_src_ptr == NULL || g_menubg_ptr == NULL) {
2258 fprintf(stderr, "OOM\n");
2262 emu_make_path(buff, "skin/background.png", sizeof(buff));
2263 readpng(g_menubg_src_ptr, buff, READPNG_BG, g_menuscreen_w, g_menuscreen_h);
2265 #ifndef __ARM_ARCH_7A__ /* XXX */
2266 me_enable(e_menu_gfx_options, MA_OPT_SCALER, 0);
2267 me_enable(e_menu_gfx_options, MA_OPT_FILTERING, 0);
2268 me_enable(e_menu_gfx_options, MA_OPT_SCALER_C, 0);
2269 me_enable(e_menu_keyconfig, MA_CTRL_NUBS_BTNS, 0);
2271 me_enable(e_menu_gfx_options, MA_OPT_SCALER2, 0);
2272 me_enable(e_menu_keyconfig, MA_CTRL_VIBRATION, 0);
2273 me_enable(e_menu_keyconfig, MA_CTRL_DEADZONE, 0);
2277 void menu_notify_mode_change(int w, int h, int bpp)
2286 // XXX: should really menu code cotrol the layer size?
2289 g_layer_w = w; g_layer_h = h;
2293 if (h > g_menuscreen_h || (240 < h && h <= 360))
2294 goto fractional_4_3;
2296 // 4:3 that prefers integer scaling
2297 imult = g_menuscreen_h / h;
2298 g_layer_w = w * imult;
2299 g_layer_h = h * imult;
2300 mult = (float)g_layer_w / (float)g_layer_h;
2301 if (mult < 1.25f || mult > 1.666f)
2302 g_layer_w = 4.0f/3.0f * (float)g_layer_h;
2303 printf(" -> %dx%d %.1f\n", g_layer_w, g_layer_h, mult);
2308 mult = 240.0f / (float)h * 4.0f / 3.0f;
2311 g_layer_w = mult * (float)g_menuscreen_h;
2312 g_layer_h = g_menuscreen_h;
2313 printf(" -> %dx%d %.1f\n", g_layer_w, g_layer_h, mult);
2316 case SCALE_FULLSCREEN:
2317 g_layer_w = g_menuscreen_w;
2318 g_layer_h = g_menuscreen_h;
2325 g_layer_x = g_menuscreen_w / 2 - g_layer_w / 2;
2326 g_layer_y = g_menuscreen_h / 2 - g_layer_h / 2;
2327 if (g_layer_x < 0) g_layer_x = 0;
2328 if (g_layer_y < 0) g_layer_y = 0;
2329 if (g_layer_w > g_menuscreen_w) g_layer_w = g_menuscreen_w;
2330 if (g_layer_h > g_menuscreen_h) g_layer_w = g_menuscreen_h;
2333 static void menu_leave_emu(void)
2335 if (GPU_close != NULL) {
2336 int ret = GPU_close();
2338 fprintf(stderr, "Warning: GPU_close returned %d\n", ret);
2341 plat_video_menu_enter(ready_to_go);
2343 memcpy(g_menubg_ptr, g_menubg_src_ptr, g_menuscreen_w * g_menuscreen_h * 2);
2344 if (pl_vout_buf != NULL && ready_to_go) {
2345 int x = max(0, g_menuscreen_w - last_psx_w);
2346 int y = max(0, g_menuscreen_h / 2 - last_psx_h / 2);
2347 int w = min(g_menuscreen_w, last_psx_w);
2348 int h = min(g_menuscreen_h, last_psx_h);
2349 u16 *d = (u16 *)g_menubg_ptr + g_menuscreen_w * y + x;
2350 char *s = pl_vout_buf;
2352 if (last_psx_bpp == 16) {
2353 for (; h > 0; h--, d += g_menuscreen_w, s += last_psx_w * 2)
2354 menu_darken_bg(d, s, w, 0);
2357 for (; h > 0; h--, d += g_menuscreen_w, s += last_psx_w * 3) {
2358 bgr888_to_rgb565(d, s, w * 3);
2359 menu_darken_bg(d, d, w, 0);
2365 cpu_clock = plat_cpu_clock_get();
2368 void menu_prepare_emu(void)
2370 R3000Acpu *prev_cpu = psxCpu;
2372 plat_video_menu_leave();
2374 menu_notify_mode_change(last_psx_w, last_psx_h, last_psx_bpp);
2376 psxCpu = (Config.Cpu == CPU_INTERPRETER) ? &psxInt : &psxRec;
2377 if (psxCpu != prev_cpu)
2378 // note that this does not really reset, just clears drc caches
2381 // core doesn't care about Config.Cdda changes,
2382 // so handle them manually here
2387 apply_lcdrate(Config.PsxType);
2388 apply_filter(filter);
2390 plat_cpu_clock_apply(cpu_clock);
2392 // push config to GPU plugin
2393 plugin_call_rearmed_cbs();
2395 if (GPU_open != NULL) {
2396 int ret = GPU_open(&gpuDisp, "PCSX", NULL);
2398 fprintf(stderr, "Warning: GPU_open returned %d\n", ret);
2404 void me_update_msg(const char *msg)
2406 strncpy(menu_error_msg, msg, sizeof(menu_error_msg));
2407 menu_error_msg[sizeof(menu_error_msg) - 1] = 0;
2409 menu_error_time = plat_get_ticks_ms();
2410 lprintf("msg: %s\n", menu_error_msg);