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.
21 #include "plugin_lib.h"
25 #include "arm_utils.h"
26 #include "common/plat.h"
27 #include "common/input.h"
28 #include "linux/in_evdev.h"
29 #include "../libpcsxcore/misc.h"
30 #include "../libpcsxcore/cdrom.h"
31 #include "../libpcsxcore/psemu_plugin_defs.h"
32 #include "../libpcsxcore/new_dynarec/new_dynarec.h"
33 #include "../plugins/dfinput/pad.h"
37 #define array_size(x) (sizeof(x) / sizeof(x[0]))
71 static int last_psx_w, last_psx_h, last_psx_bpp;
72 static int scaling, filter, cpu_clock, cpu_clock_st;
73 static char rom_fname_reload[MAXPATHLEN];
74 static char last_selected_fname[MAXPATHLEN];
75 static int warned_about_bios, region, in_type_sel;
79 extern int iUseReverb;
80 extern int iUseInterpolation;
82 extern int iSPUIRQWait;
85 static const char *bioses[24];
86 static const char *gpu_plugins[16];
87 static const char *spu_plugins[16];
88 static int bios_sel, gpu_plugsel, spu_plugsel;
91 static int min(int x, int y) { return x < y ? x : y; }
92 static int max(int x, int y) { return x > y ? x : y; }
94 void emu_make_path(char *buff, const char *end, int size)
98 end_len = strlen(end);
99 pos = plat_get_root_dir(buff, size);
100 strncpy(buff + pos, end, size - pos);
102 if (pos + end_len > size - 1)
103 printf("Warning: path truncated: %s\n", buff);
106 static int emu_check_save_file(int slot)
108 int ret = emu_check_state(slot);
109 return ret == 0 ? 1 : 0;
112 static int emu_save_load_game(int load, int unused)
117 ret = emu_load_state(state_slot);
119 // reflect hle/bios mode from savestate
122 else if (bios_sel == 0 && bioses[1] != NULL)
123 // XXX: maybe find the right bios instead
127 ret = emu_save_state(state_slot);
132 // propagate menu settings to the emu vars
133 static void menu_sync_config(void)
135 static int allow_abs_only_old;
140 Config.PsxType = region - 1;
142 in_type = in_type_sel ? PSE_PAD_TYPE_ANALOGPAD : PSE_PAD_TYPE_STANDARD;
143 if (in_evdev_allow_abs_only != allow_abs_only_old) {
144 pandora_rescan_inputs();
145 allow_abs_only_old = in_evdev_allow_abs_only;
148 pl_frame_interval = Config.PsxType ? 20000 : 16667;
149 // used by P.E.Op.S. frameskip code
150 pl_rearmed_cbs.gpu_peops.fFrameRateHz = Config.PsxType ? 50.0f : 59.94f;
151 pl_rearmed_cbs.gpu_peops.dwFrameRateTicks =
152 (100000*100 / (unsigned long)(pl_rearmed_cbs.gpu_peops.fFrameRateHz*100));
155 static void menu_set_defconfig(void)
162 in_evdev_allow_abs_only = 0;
163 Config.Xa = Config.Cdda = Config.Sio =
164 Config.SpuIrq = Config.RCntFix = Config.VSyncWA = 0;
165 Config.CdrReschedule = 0;
167 pl_rearmed_cbs.frameskip = 0;
168 pl_rearmed_cbs.gpu_peops.iUseDither = 0;
169 pl_rearmed_cbs.gpu_peops.dwActFixes = 1<<7;
172 iUseInterpolation = 1;
180 #define CE_CONFIG_STR(val) \
181 { #val, 0, Config.val }
183 #define CE_CONFIG_VAL(val) \
184 { #val, sizeof(Config.val), &Config.val }
186 #define CE_STR(val) \
189 #define CE_INTVAL(val) \
190 { #val, sizeof(val), &val }
192 #define CE_INTVAL_P(val) \
193 { #val, sizeof(pl_rearmed_cbs.val), &pl_rearmed_cbs.val }
195 // 'versioned' var, used when defaults change
196 #define CE_INTVAL_V(val, ver) \
197 { #val #ver, sizeof(val), &val }
199 static const struct {
207 // CE_CONFIG_STR(Cdr),
212 CE_CONFIG_VAL(Debug),
213 CE_CONFIG_VAL(PsxOut),
214 CE_CONFIG_VAL(SpuIrq),
215 CE_CONFIG_VAL(RCntFix),
216 CE_CONFIG_VAL(VSyncWA),
218 CE_CONFIG_VAL(CdrReschedule),
221 CE_INTVAL(g_layer_x),
222 CE_INTVAL(g_layer_y),
223 CE_INTVAL(g_layer_w),
224 CE_INTVAL(g_layer_h),
226 CE_INTVAL(state_slot),
227 CE_INTVAL(cpu_clock),
229 CE_INTVAL(in_type_sel),
230 CE_INTVAL_P(frameskip),
231 CE_INTVAL_P(gpu_peops.iUseDither),
232 CE_INTVAL_P(gpu_peops.dwActFixes),
233 CE_INTVAL(iUseReverb),
235 CE_INTVAL_V(iUseInterpolation, 2),
236 CE_INTVAL_V(iSPUIRQWait, 2),
237 CE_INTVAL(iUseTimer),
238 CE_INTVAL(warned_about_bios),
239 CE_INTVAL(in_evdev_allow_abs_only),
242 static char *get_cd_label(void)
244 static char trimlabel[33];
247 strncpy(trimlabel, CdromLabel, 32);
249 for (j = 31; j >= 0; j--)
250 if (trimlabel[j] == ' ')
256 static void make_cfg_fname(char *buf, size_t size, int is_game)
259 snprintf(buf, size, "." PCSX_DOT_DIR "cfg/%.32s-%.9s.cfg", get_cd_label(), CdromId);
261 snprintf(buf, size, "." PCSX_DOT_DIR "%s", cfgfile_basename);
264 static void keys_write_all(FILE *f);
266 static int menu_write_config(int is_game)
268 char cfgfile[MAXPATHLEN];
272 make_cfg_fname(cfgfile, sizeof(cfgfile), is_game);
273 f = fopen(cfgfile, "w");
275 printf("menu_write_config: failed to open: %s\n", cfgfile);
279 for (i = 0; i < ARRAY_SIZE(config_data); i++) {
280 fprintf(f, "%s = ", config_data[i].name);
281 switch (config_data[i].len) {
283 fprintf(f, "%s\n", (char *)config_data[i].val);
286 fprintf(f, "%x\n", *(u8 *)config_data[i].val);
289 fprintf(f, "%x\n", *(u16 *)config_data[i].val);
292 fprintf(f, "%x\n", *(u32 *)config_data[i].val);
295 printf("menu_write_config: unhandled len %d for %s\n",
296 config_data[i].len, config_data[i].name);
302 fprintf(f, "lastcdimg = %s\n", last_selected_fname);
310 static void parse_str_val(char *cval, const char *src)
313 strncpy(cval, src, MAXPATHLEN);
314 cval[MAXPATHLEN - 1] = 0;
315 tmp = strchr(cval, '\n');
317 tmp = strchr(cval, '\r');
322 static void keys_load_all(const char *cfg);
324 static int menu_load_config(int is_game)
326 char cfgfile[MAXPATHLEN];
332 make_cfg_fname(cfgfile, sizeof(cfgfile), is_game);
333 f = fopen(cfgfile, "r");
335 printf("menu_load_config: failed to open: %s\n", cfgfile);
339 fseek(f, 0, SEEK_END);
342 printf("bad size %ld: %s\n", size, cfgfile);
346 cfg = malloc(size + 1);
350 fseek(f, 0, SEEK_SET);
351 if (fread(cfg, 1, size, f) != size) {
352 printf("failed to read: %s\n", cfgfile);
357 for (i = 0; i < ARRAY_SIZE(config_data); i++) {
361 tmp = strstr(cfg, config_data[i].name);
364 tmp += strlen(config_data[i].name);
365 if (strncmp(tmp, " = ", 3) != 0)
369 if (config_data[i].len == 0) {
370 parse_str_val(config_data[i].val, tmp);
375 val = strtoul(tmp, &tmp2, 16);
376 if (tmp2 == NULL || tmp == tmp2)
377 continue; // parse failed
379 switch (config_data[i].len) {
381 *(u8 *)config_data[i].val = val;
384 *(u16 *)config_data[i].val = val;
387 *(u32 *)config_data[i].val = val;
390 printf("menu_load_config: unhandled len %d for %s\n",
391 config_data[i].len, config_data[i].name);
397 char *tmp = strstr(cfg, "lastcdimg = ");
400 parse_str_val(last_selected_fname, tmp);
407 for (i = bios_sel = 0; bioses[i] != NULL; i++)
408 if (strcmp(Config.Bios, bioses[i]) == 0)
409 { bios_sel = i; break; }
411 for (i = gpu_plugsel = 0; gpu_plugins[i] != NULL; i++)
412 if (strcmp(Config.Gpu, gpu_plugins[i]) == 0)
413 { gpu_plugsel = i; break; }
415 for (i = spu_plugsel = 0; spu_plugins[i] != NULL; i++)
416 if (strcmp(Config.Spu, spu_plugins[i]) == 0)
417 { spu_plugsel = i; break; }
428 // rrrr rggg gggb bbbb
429 static unsigned short fname2color(const char *fname)
431 static const char *cdimg_exts[] = { ".bin", ".img", ".mdf", ".iso", ".cue", ".z", ".bz", ".znx", ".pbp" };
432 static const char *other_exts[] = { ".ccd", ".toc", ".mds", ".sub", ".table", ".index", ".sbi" };
433 const char *ext = strrchr(fname, '.');
438 for (i = 0; i < array_size(cdimg_exts); i++)
439 if (strcasecmp(ext, cdimg_exts[i]) == 0)
441 for (i = 0; i < array_size(other_exts); i++)
442 if (strcasecmp(ext, other_exts[i]) == 0)
447 static void draw_savestate_bg(int slot);
449 static const char *filter_exts[] = {
450 ".mp3", ".MP3", ".txt", ".htm", "html", ".jpg", ".pnd"
453 #define MENU_ALIGN_LEFT
454 #define menu_init menu_init_common
455 #include "common/menu.c"
458 // a bit of black magic here
459 static void draw_savestate_bg(int slot)
461 static const int psx_widths[8] = { 256, 368, 320, 384, 512, 512, 640, 640 };
463 char fname[MAXPATHLEN];
470 ret = get_state_filename(fname, sizeof(fname), slot);
474 f = gzopen(fname, "rb");
478 if (gzseek(f, 0x29933d, SEEK_SET) != 0x29933d) {
479 fprintf(stderr, "gzseek failed\n");
484 gpu = malloc(sizeof(*gpu));
490 ret = gzread(f, gpu, sizeof(*gpu));
492 if (ret != sizeof(*gpu)) {
493 fprintf(stderr, "gzread failed\n");
497 memcpy(g_menubg_ptr, g_menubg_src_ptr, g_menuscreen_w * g_menuscreen_h * 2);
499 if (gpu->ulStatus & 0x800000)
500 goto out; // disabled
502 x = gpu->ulControl[5] & 0x3ff;
503 y = (gpu->ulControl[5] >> 10) & 0x1ff;
504 s = (u16 *)gpu->psxVRam + y * 1024 + (x & ~1);
505 w = psx_widths[(gpu->ulStatus >> 16) & 7];
506 tmp = gpu->ulControl[7];
507 h = ((tmp >> 10) & 0x3ff) - (tmp & 0x3ff);
508 if (gpu->ulStatus & 0x80000) // doubleheight
511 x = max(0, g_menuscreen_w - w) & ~3;
512 y = max(0, g_menuscreen_h / 2 - h / 2);
513 w = min(g_menuscreen_w, w);
514 h = min(g_menuscreen_h, h);
515 d = (u16 *)g_menubg_ptr + g_menuscreen_w * y + x;
517 for (; h > 0; h--, d += g_menuscreen_w, s += 1024)
518 if (gpu->ulStatus & 0x200000)
519 bgr888_to_rgb565(d, s, w * 3);
521 bgr555_to_rgb565(d, s, w * 2);
527 // ---------- pandora specific -----------
529 static const char pnd_script_base[] = "sudo -n /usr/pandora/scripts";
530 static char **pnd_filter_list;
532 static int get_cpu_clock(void)
536 f = fopen("/proc/pandora/cpu_mhz_max", "r");
538 fscanf(f, "%d", &ret);
544 static void apply_cpu_clock(void)
548 if (cpu_clock != 0 && cpu_clock != get_cpu_clock()) {
549 snprintf(buf, sizeof(buf), "unset DISPLAY; echo y | %s/op_cpuspeed.sh %d",
550 pnd_script_base, cpu_clock);
555 static void apply_filter(int which)
561 if (pnd_filter_list == NULL || which == old)
564 for (i = 0; i < which; i++)
565 if (pnd_filter_list[i] == NULL)
568 if (pnd_filter_list[i] == NULL)
571 snprintf(buf, sizeof(buf), "%s/op_videofir.sh %s", pnd_script_base, pnd_filter_list[i]);
576 static void apply_lcdrate(int pal)
584 snprintf(buf, sizeof(buf), "%s/op_lcdrate.sh %d",
585 pnd_script_base, pal ? 50 : 60);
590 static menu_entry e_menu_gfx_options[];
592 static void pnd_menu_init(void)
600 cpu_clock_st = cpu_clock = get_cpu_clock();
602 dir = opendir("/etc/pandora/conf/dss_fir");
604 perror("filter opendir");
617 if (ent->d_type != DT_REG && ent->d_type != DT_LNK)
626 mfilters = calloc(count + 1, sizeof(mfilters[0]));
627 if (mfilters == NULL)
631 for (i = 0; (ent = readdir(dir)); ) {
634 if (ent->d_type != DT_REG && ent->d_type != DT_LNK)
637 len = strlen(ent->d_name);
639 // skip pre-HF5 extra files
640 if (len >= 3 && strcmp(ent->d_name + len - 3, "_v3") == 0)
642 if (len >= 3 && strcmp(ent->d_name + len - 3, "_v5") == 0)
645 // have to cut "_up_h" for pre-HF5
646 if (len > 5 && strcmp(ent->d_name + len - 5, "_up_h") == 0)
649 if (len > sizeof(buff) - 1)
652 strncpy(buff, ent->d_name, len);
654 mfilters[i] = strdup(buff);
655 if (mfilters[i] != NULL)
660 i = me_id2offset(e_menu_gfx_options, MA_OPT_FILTERING);
661 e_menu_gfx_options[i].data = (void *)mfilters;
662 pnd_filter_list = mfilters;
665 void menu_finish(void)
667 cpu_clock = cpu_clock_st;
671 // -------------- key config --------------
673 me_bind_action me_ctrl_actions[] =
675 { "UP ", 1 << DKEY_UP},
676 { "DOWN ", 1 << DKEY_DOWN },
677 { "LEFT ", 1 << DKEY_LEFT },
678 { "RIGHT ", 1 << DKEY_RIGHT },
679 { "TRIANGLE", 1 << DKEY_TRIANGLE },
680 { "CIRCLE ", 1 << DKEY_CIRCLE },
681 { "CROSS ", 1 << DKEY_CROSS },
682 { "SQUARE ", 1 << DKEY_SQUARE },
683 { "L1 ", 1 << DKEY_L1 },
684 { "R1 ", 1 << DKEY_R1 },
685 { "L2 ", 1 << DKEY_L2 },
686 { "R2 ", 1 << DKEY_R2 },
687 { "L3 ", 1 << DKEY_L3 },
688 { "R3 ", 1 << DKEY_R3 },
689 { "START ", 1 << DKEY_START },
690 { "SELECT ", 1 << DKEY_SELECT },
694 me_bind_action emuctrl_actions[] =
696 { "Save State ", 1 << SACTION_SAVE_STATE },
697 { "Load State ", 1 << SACTION_LOAD_STATE },
698 { "Prev Save Slot ", 1 << SACTION_PREV_SSLOT },
699 { "Next Save Slot ", 1 << SACTION_NEXT_SSLOT },
700 { "Toggle Frameskip ", 1 << SACTION_TOGGLE_FSKIP },
701 { "Take Screenshot ", 1 << SACTION_SCREENSHOT },
702 { "Enter Menu ", 1 << SACTION_ENTER_MENU },
706 static char *mystrip(char *str)
711 for (i = 0; i < len; i++)
712 if (str[i] != ' ') break;
713 if (i > 0) memmove(str, str + i, len - i + 1);
716 for (i = len - 1; i >= 0; i--)
717 if (str[i] != ' ') break;
723 static void get_line(char *d, size_t size, const char *s)
728 for (pe = s; *pe != '\r' && *pe != '\n' && *pe != 0; pe++)
739 static void keys_write_all(FILE *f)
743 for (d = 0; d < IN_MAX_DEVS; d++)
745 const int *binds = in_get_dev_binds(d);
746 const char *name = in_get_dev_name(d, 0, 0);
749 if (binds == NULL || name == NULL)
752 fprintf(f, "binddev = %s\n", name);
753 in_get_config(d, IN_CFG_BIND_COUNT, &count);
755 for (k = 0; k < count; k++)
760 act[0] = act[31] = 0;
761 name = in_get_key_name(d, k);
763 kbinds = binds[IN_BIND_OFFS(k, IN_BINDTYPE_PLAYER12)];
764 for (i = 0; kbinds && i < ARRAY_SIZE(me_ctrl_actions) - 1; i++) {
765 mask = me_ctrl_actions[i].mask;
767 strncpy(act, me_ctrl_actions[i].name, 31);
768 fprintf(f, "bind %s = player1 %s\n", name, mystrip(act));
771 mask = me_ctrl_actions[i].mask << 16;
773 strncpy(act, me_ctrl_actions[i].name, 31);
774 fprintf(f, "bind %s = player2 %s\n", name, mystrip(act));
779 kbinds = binds[IN_BIND_OFFS(k, IN_BINDTYPE_EMU)];
780 for (i = 0; kbinds && i < ARRAY_SIZE(emuctrl_actions) - 1; i++) {
781 mask = emuctrl_actions[i].mask;
783 strncpy(act, emuctrl_actions[i].name, 31);
784 fprintf(f, "bind %s = %s\n", name, mystrip(act));
792 static int parse_bind_val(const char *val, int *type)
796 *type = IN_BINDTYPE_NONE;
800 if (strncasecmp(val, "player", 6) == 0)
802 int player, shift = 0;
803 player = atoi(val + 6) - 1;
805 if ((unsigned int)player > 1)
810 *type = IN_BINDTYPE_PLAYER12;
811 for (i = 0; me_ctrl_actions[i].name != NULL; i++) {
812 if (strncasecmp(me_ctrl_actions[i].name, val + 8, strlen(val + 8)) == 0)
813 return me_ctrl_actions[i].mask << shift;
816 for (i = 0; emuctrl_actions[i].name != NULL; i++) {
817 if (strncasecmp(emuctrl_actions[i].name, val, strlen(val)) == 0) {
818 *type = IN_BINDTYPE_EMU;
819 return emuctrl_actions[i].mask;
826 static void keys_load_all(const char *cfg)
828 char dev[256], key[128], *act;
834 while (p != NULL && (p = strstr(p, "binddev = ")) != NULL) {
837 get_line(dev, sizeof(dev), p);
838 dev_id = in_config_parse_dev(dev);
840 printf("input: can't handle dev: %s\n", dev);
844 in_unbind_all(dev_id, -1, -1);
845 while ((p = strstr(p, "bind"))) {
846 if (strncmp(p, "binddev = ", 10) == 0)
851 printf("input: parse error: %16s..\n", p);
855 get_line(key, sizeof(key), p);
856 act = strchr(key, '=');
858 printf("parse failed: %16s..\n", p);
866 bind = parse_bind_val(act, &bindtype);
867 if (bind != -1 && bind != 0) {
868 //printf("bind #%d '%s' %08x (%s)\n", dev_id, key, bind, act);
869 in_config_bind_key(dev_id, key, bind, bindtype);
872 lprintf("config: unhandled action \"%s\"\n", act);
878 static int key_config_loop_wrap(int id, int keys)
881 case MA_CTRL_PLAYER1:
882 key_config_loop(me_ctrl_actions, array_size(me_ctrl_actions) - 1, 0);
884 case MA_CTRL_PLAYER2:
885 key_config_loop(me_ctrl_actions, array_size(me_ctrl_actions) - 1, 1);
888 key_config_loop(emuctrl_actions, array_size(emuctrl_actions) - 1, -1);
896 static const char *mgn_dev_name(int id, int *offs)
898 const char *name = NULL;
901 if (id == MA_CTRL_DEV_FIRST)
904 for (; it < IN_MAX_DEVS; it++) {
905 name = in_get_dev_name(it, 1, 1);
914 static const char *mgn_saveloadcfg(int id, int *offs)
919 static int mh_savecfg(int id, int keys)
921 if (menu_write_config(id == MA_OPT_SAVECFG_GAME ? 1 : 0) == 0)
922 me_update_msg("config saved");
924 me_update_msg("failed to write config");
929 static int mh_input_rescan(int id, int keys)
931 //menu_sync_config();
932 pandora_rescan_inputs();
933 me_update_msg("rescan complete.");
938 static const char *men_in_type_sel[] = { "Standard (SCPH-1080)", "Analog (SCPH-1150)", NULL };
939 static const char h_nub_btns[] = "Experimental, keep this OFF if unsure. Select rescan after change.";
941 static menu_entry e_menu_keyconfig[] =
943 mee_handler_id("Player 1", MA_CTRL_PLAYER1, key_config_loop_wrap),
944 mee_handler_id("Player 2", MA_CTRL_PLAYER2, key_config_loop_wrap),
945 mee_handler_id("Emulator controls", MA_CTRL_EMU, key_config_loop_wrap),
947 mee_enum ("Controller", 0, in_type_sel, men_in_type_sel),
948 mee_onoff_h ("Nubs as buttons", 0, in_evdev_allow_abs_only, 1, h_nub_btns),
949 mee_cust_nosave("Save global config", MA_OPT_SAVECFG, mh_savecfg, mgn_saveloadcfg),
950 mee_cust_nosave("Save cfg for loaded game", MA_OPT_SAVECFG_GAME, mh_savecfg, mgn_saveloadcfg),
951 mee_handler ("Rescan devices", mh_input_rescan),
953 mee_label ("Input devices:"),
954 mee_label_mk (MA_CTRL_DEV_FIRST, mgn_dev_name),
955 mee_label_mk (MA_CTRL_DEV_NEXT, mgn_dev_name),
956 mee_label_mk (MA_CTRL_DEV_NEXT, mgn_dev_name),
957 mee_label_mk (MA_CTRL_DEV_NEXT, mgn_dev_name),
958 mee_label_mk (MA_CTRL_DEV_NEXT, mgn_dev_name),
959 mee_label_mk (MA_CTRL_DEV_NEXT, mgn_dev_name),
960 mee_label_mk (MA_CTRL_DEV_NEXT, mgn_dev_name),
964 static int menu_loop_keyconfig(int id, int keys)
968 // me_enable(e_menu_keyconfig, MA_OPT_SAVECFG_GAME, ready_to_go && CdromId[0]);
969 me_loop(e_menu_keyconfig, &sel, NULL);
973 // ------------ gfx options menu ------------
975 static const char *men_scaler[] = { "1x1", "scaled 4:3", "fullscreen", "custom", NULL };
976 static const char h_cscaler[] = "Displays the scaler layer, you can resize it\n"
977 "using d-pad or move it using R+d-pad";
978 static const char *men_dummy[] = { NULL };
980 static int menu_loop_cscaler(int id, int keys)
984 scaling = SCALE_CUSTOM;
986 omap_enable_layer(1);
991 memset(g_menuscreen_ptr, 4, g_menuscreen_w * g_menuscreen_h * 2);
992 text_out16(2, 2, "%d,%d", g_layer_x, g_layer_y);
993 text_out16(2, 480 - 18, "%dx%d | d-pad: resize, R+d-pad: move", g_layer_w, g_layer_h);
996 inp = in_menu_wait(PBTN_UP|PBTN_DOWN|PBTN_LEFT|PBTN_RIGHT|PBTN_R|PBTN_MOK|PBTN_MBACK, 40);
997 if (inp & PBTN_UP) g_layer_y--;
998 if (inp & PBTN_DOWN) g_layer_y++;
999 if (inp & PBTN_LEFT) g_layer_x--;
1000 if (inp & PBTN_RIGHT) g_layer_x++;
1001 if (!(inp & PBTN_R)) {
1002 if (inp & PBTN_UP) g_layer_h += 2;
1003 if (inp & PBTN_DOWN) g_layer_h -= 2;
1004 if (inp & PBTN_LEFT) g_layer_w += 2;
1005 if (inp & PBTN_RIGHT) g_layer_w -= 2;
1007 if (inp & (PBTN_MOK|PBTN_MBACK))
1010 if (inp & (PBTN_UP|PBTN_DOWN|PBTN_LEFT|PBTN_RIGHT)) {
1011 if (g_layer_x < 0) g_layer_x = 0;
1012 if (g_layer_x > 640) g_layer_x = 640;
1013 if (g_layer_y < 0) g_layer_y = 0;
1014 if (g_layer_y > 420) g_layer_y = 420;
1015 if (g_layer_w < 160) g_layer_w = 160;
1016 if (g_layer_h < 60) g_layer_h = 60;
1017 if (g_layer_x + g_layer_w > 800)
1018 g_layer_w = 800 - g_layer_x;
1019 if (g_layer_y + g_layer_h > 480)
1020 g_layer_h = 480 - g_layer_y;
1021 omap_enable_layer(1);
1025 omap_enable_layer(0);
1030 static menu_entry e_menu_gfx_options[] =
1032 mee_enum ("Scaler", 0, scaling, men_scaler),
1033 mee_enum ("Filter", MA_OPT_FILTERING, filter, men_dummy),
1034 // mee_onoff ("Vsync", 0, vsync, 1),
1035 mee_cust_h ("Setup custom scaler", 0, menu_loop_cscaler, NULL, h_cscaler),
1039 static int menu_loop_gfx_options(int id, int keys)
1043 me_loop(e_menu_gfx_options, &sel, NULL);
1048 // ------------ bios/plugins ------------
1050 static const char *men_gpu_dithering[] = { "None", "Game dependant", "Always", NULL };
1051 static const char h_gpu_0[] = "Needed for Chrono Cross";
1052 static const char h_gpu_1[] = "Capcom fighting games";
1053 static const char h_gpu_2[] = "Black screens in Lunar";
1054 static const char h_gpu_3[] = "Compatibility mode";
1055 static const char h_gpu_6[] = "Pandemonium 2";
1056 static const char h_gpu_7[] = "Skip every second frame";
1057 static const char h_gpu_8[] = "Needed by Dark Forces";
1058 static const char h_gpu_9[] = "better g-colors, worse textures";
1059 static const char h_gpu_10[] = "Toggle busy flags after drawing";
1061 static menu_entry e_menu_plugin_gpu[] =
1063 mee_enum ("Dithering", 0, pl_rearmed_cbs.gpu_peops.iUseDither, men_gpu_dithering),
1064 mee_onoff_h ("Odd/even bit hack", 0, pl_rearmed_cbs.gpu_peops.dwActFixes, 1<<0, h_gpu_0),
1065 mee_onoff_h ("Expand screen width", 0, pl_rearmed_cbs.gpu_peops.dwActFixes, 1<<1, h_gpu_1),
1066 mee_onoff_h ("Ignore brightness color", 0, pl_rearmed_cbs.gpu_peops.dwActFixes, 1<<2, h_gpu_2),
1067 mee_onoff_h ("Disable coordinate check", 0, pl_rearmed_cbs.gpu_peops.dwActFixes, 1<<3, h_gpu_3),
1068 mee_onoff_h ("Lazy screen update", 0, pl_rearmed_cbs.gpu_peops.dwActFixes, 1<<6, h_gpu_6),
1069 mee_onoff_h ("Old frame skipping", 0, pl_rearmed_cbs.gpu_peops.dwActFixes, 1<<7, h_gpu_7),
1070 mee_onoff_h ("Repeated flat tex triangles ",0,pl_rearmed_cbs.gpu_peops.dwActFixes, 1<<8, h_gpu_8),
1071 mee_onoff_h ("Draw quads with triangles", 0, pl_rearmed_cbs.gpu_peops.dwActFixes, 1<<9, h_gpu_9),
1072 mee_onoff_h ("Fake 'gpu busy' states", 0, pl_rearmed_cbs.gpu_peops.dwActFixes, 1<<10, h_gpu_10),
1076 static int menu_loop_plugin_gpu(int id, int keys)
1079 me_loop(e_menu_plugin_gpu, &sel, NULL);
1083 static const char *men_spu_reverb[] = { "Off", "Fake", "On", NULL };
1084 static const char *men_spu_interp[] = { "None", "Simple", "Gaussian", "Cubic", NULL };
1085 static const char h_spu_irq_wait[] = "Wait for CPU (recommended set to ON)";
1086 static const char h_spu_thread[] = "Run sound emulation in main thread (recommended)";
1088 static menu_entry e_menu_plugin_spu[] =
1090 mee_enum ("Reverb", 0, iUseReverb, men_spu_reverb),
1091 mee_enum ("Interpolation", 0, iUseInterpolation, men_spu_interp),
1092 mee_onoff ("Adjust XA pitch", 0, iXAPitch, 1),
1093 mee_onoff_h ("SPU IRQ Wait", 0, iSPUIRQWait, 1, h_spu_irq_wait),
1094 mee_onoff_h ("Sound in main thread", 0, iUseTimer, 2, h_spu_thread),
1098 static int menu_loop_plugin_spu(int id, int keys)
1101 me_loop(e_menu_plugin_spu, &sel, NULL);
1105 static const char h_bios[] = "HLE is simulated BIOS. BIOS selection is saved in savestates\n"
1106 "and can't be changed there. Must save config and reload\n"
1107 "the game for change to take effect";
1108 static const char h_plugin_xpu[] = "Must save config and reload the game\n"
1109 "for plugin change to take effect";
1110 static const char h_gpu[] = "Configure P.E.Op.S. SoftGL Driver V1.17";
1111 static const char h_spu[] = "Configure built-in P.E.Op.S. Sound Driver V1.7";
1113 static menu_entry e_menu_plugin_options[] =
1115 mee_enum_h ("BIOS", 0, bios_sel, bioses, h_bios),
1116 mee_enum_h ("GPU plugin", 0, gpu_plugsel, gpu_plugins, h_plugin_xpu),
1117 mee_enum_h ("SPU plugin", 0, spu_plugsel, spu_plugins, h_plugin_xpu),
1118 mee_handler_h ("Configure gpu_peops plugin", menu_loop_plugin_gpu, h_gpu),
1119 mee_handler_h ("Configure built-in SPU plugin", menu_loop_plugin_spu, h_spu),
1123 static menu_entry e_menu_main[];
1125 static int menu_loop_plugin_options(int id, int keys)
1128 me_loop(e_menu_plugin_options, &sel, NULL);
1130 // sync BIOS/plugins
1131 snprintf(Config.Bios, sizeof(Config.Bios), "%s", bioses[bios_sel]);
1132 snprintf(Config.Gpu, sizeof(Config.Gpu), "%s", gpu_plugins[gpu_plugsel]);
1133 snprintf(Config.Spu, sizeof(Config.Spu), "%s", spu_plugins[spu_plugsel]);
1134 me_enable(e_menu_main, MA_MAIN_RUN_BIOS, bios_sel != 0);
1139 // ------------ adv options menu ------------
1141 static const char *men_cfg_cdrr[] = { "Auto", "ON", "OFF", NULL };
1142 static const char h_cfg_cpul[] = "Shows CPU usage in %";
1143 static const char h_cfg_fl[] = "Frame Limiter keeps the game from running too fast";
1144 static const char h_cfg_xa[] = "Disables XA sound, which can sometimes improve performance";
1145 static const char h_cfg_cdda[] = "Disable CD Audio for a performance boost\n"
1146 "(proper .cue/.bin dump is needed otherwise)";
1147 static const char h_cfg_sio[] = "You should not need this, breaks games";
1148 static const char h_cfg_spuirq[] = "Compatibility tweak; should be left off";
1149 static const char h_cfg_rcnt1[] = "Parasite Eve 2, Vandal Hearts 1/2 Fix\n"
1150 "(timing hack, breaks other games)";
1151 static const char h_cfg_rcnt2[] = "InuYasha Sengoku Battle Fix\n"
1152 "(timing hack, breaks other games)";
1153 static const char h_cfg_cdrr[] = "Compatibility tweak (fixes Team Buddies, maybe more)\n"
1154 "(CD timing hack, breaks FMVs)";
1155 static const char h_cfg_nodrc[] = "Disable dynamic recompiler and use interpreter\n"
1156 "Might be useful to overcome some dynarec bugs";
1158 static menu_entry e_menu_adv_options[] =
1160 mee_onoff_h ("Show CPU load", 0, g_opts, OPT_SHOWCPU, h_cfg_cpul),
1161 mee_onoff_h ("Disable Frame Limiter", 0, g_opts, OPT_NO_FRAMELIM, h_cfg_fl),
1162 mee_onoff_h ("Disable XA Decoding", 0, Config.Xa, 1, h_cfg_xa),
1163 mee_onoff_h ("Disable CD Audio", 0, Config.Cdda, 1, h_cfg_cdda),
1164 mee_onoff_h ("SIO IRQ Always Enabled", 0, Config.Sio, 1, h_cfg_sio),
1165 mee_onoff_h ("SPU IRQ Always Enabled", 0, Config.SpuIrq, 1, h_cfg_spuirq),
1166 mee_onoff_h ("Rootcounter hack", 0, Config.RCntFix, 1, h_cfg_rcnt1),
1167 mee_onoff_h ("Rootcounter hack 2", 0, Config.VSyncWA, 1, h_cfg_rcnt2),
1168 mee_enum_h ("CD read reschedule hack",0, Config.CdrReschedule, men_cfg_cdrr, h_cfg_cdrr),
1169 mee_onoff_h ("Disable dynarec (slow!)",0, Config.Cpu, 1, h_cfg_nodrc),
1173 static int menu_loop_adv_options(int id, int keys)
1176 me_loop(e_menu_adv_options, &sel, NULL);
1180 // ------------ options menu ------------
1182 static int mh_restore_defaults(int id, int keys)
1184 menu_set_defconfig();
1185 me_update_msg("defaults restored");
1189 static const char *men_region[] = { "Auto", "NTSC", "PAL", NULL };
1191 static const char *men_confirm_save[] = { "OFF", "writes", "loads", "both", NULL };
1192 static const char h_confirm_save[] = "Ask for confirmation when overwriting save,\n"
1193 "loading state or both";
1195 static const char h_restore_def[] = "Switches back to default / recommended\n"
1197 static const char h_frameskip[] = "Warning: frameskip sometimes causes glitches\n";
1199 static menu_entry e_menu_options[] =
1201 // mee_range ("Save slot", 0, state_slot, 0, 9),
1202 // mee_enum_h ("Confirm savestate", 0, dummy, men_confirm_save, h_confirm_save),
1203 mee_onoff_h ("Frameskip", 0, pl_rearmed_cbs.frameskip, 1, h_frameskip),
1204 mee_onoff ("Show FPS", 0, g_opts, OPT_SHOWFPS),
1205 mee_enum ("Region", 0, region, men_region),
1206 mee_range ("CPU clock", MA_OPT_CPU_CLOCKS, cpu_clock, 20, 5000),
1207 mee_handler ("[Display]", menu_loop_gfx_options),
1208 mee_handler ("[BIOS/Plugins]", menu_loop_plugin_options),
1209 mee_handler ("[Advanced]", menu_loop_adv_options),
1210 mee_cust_nosave("Save global config", MA_OPT_SAVECFG, mh_savecfg, mgn_saveloadcfg),
1211 mee_cust_nosave("Save cfg for loaded game",MA_OPT_SAVECFG_GAME, mh_savecfg, mgn_saveloadcfg),
1212 mee_handler_h ("Restore default config", mh_restore_defaults, h_restore_def),
1216 static int menu_loop_options(int id, int keys)
1221 i = me_id2offset(e_menu_options, MA_OPT_CPU_CLOCKS);
1222 e_menu_options[i].enabled = cpu_clock != 0 ? 1 : 0;
1223 me_enable(e_menu_options, MA_OPT_SAVECFG_GAME, ready_to_go && CdromId[0]);
1225 me_loop(e_menu_options, &sel, NULL);
1230 // ------------ debug menu ------------
1232 static void draw_frame_debug(GPUFreeze_t *gpuf)
1234 int w = min(g_menuscreen_w, 1024);
1235 int h = min(g_menuscreen_h, 512);
1236 u16 *d = g_menuscreen_ptr;
1237 u16 *s = (u16 *)gpuf->psxVRam;
1241 gpuf->ulFreezeVersion = 1;
1242 if (GPU_freeze != NULL)
1243 GPU_freeze(1, gpuf);
1245 for (; h > 0; h--, d += g_menuscreen_w, s += 1024)
1246 bgr555_to_rgb565(d, s, w * 2);
1248 smalltext_out16(4, 1, "build: "__DATE__ " " __TIME__ " " REV, 0xe7fc);
1249 snprintf(buff, sizeof(buff), "GPU sr: %08x", gpuf->ulStatus);
1250 smalltext_out16(4, (ty += me_sfont_h), buff, 0xe7fc);
1251 snprintf(buff, sizeof(buff), "PC/SP: %08x %08x", psxRegs.pc, psxRegs.GPR.n.sp);
1252 smalltext_out16(4, (ty += me_sfont_h), buff, 0xe7fc);
1255 static void debug_menu_loop(void)
1260 gpuf = malloc(sizeof(*gpuf));
1267 draw_frame_debug(gpuf);
1270 inp = in_menu_wait(PBTN_MOK|PBTN_MBACK|PBTN_MA2|PBTN_MA3|PBTN_L|PBTN_R |
1271 PBTN_UP|PBTN_DOWN|PBTN_LEFT|PBTN_RIGHT, 70);
1272 if (inp & PBTN_MBACK)
1279 // ------------ main menu ------------
1281 static void menu_bios_warn(void)
1284 static const char msg[] =
1285 "You don't seem to have copied any BIOS files to\n"
1286 "<SD card>/pandora/appdata/pcsx_rearmed/bios/\n\n"
1287 "While many games work fine with fake (HLE) BIOS,\n"
1288 "others (like MGS and FF8) require BIOS to work.\n"
1289 "After copying the file, you'll also need to\n"
1290 "select it in the emu's options->[BIOS/Plugins]\n\n"
1291 "The file is usually named SCPH1001.BIN, but\n"
1292 "other not compressed files can be used too.\n\n"
1293 "Press (B) or (X) to continue";
1297 draw_menu_message(msg, NULL);
1299 inp = in_menu_wait(PBTN_MOK|PBTN_MBACK, 70);
1300 if (inp & (PBTN_MBACK|PBTN_MOK))
1305 // ------------ main menu ------------
1309 static void draw_frame_main(void)
1311 if (CdromId[0] != 0) {
1313 snprintf(buff, sizeof(buff), "%.32s/%.9s (running as %s, with %s)",
1314 get_cd_label(), CdromId, Config.PsxType ? "PAL" : "NTSC",
1315 Config.HLE ? "HLE" : "BIOS");
1316 smalltext_out16(4, 1, buff, 0x105f);
1320 static void draw_frame_credits(void)
1322 smalltext_out16(4, 1, "build: "__DATE__ " " __TIME__ " " REV, 0xe7fc);
1325 static const char credits_text[] =
1327 "(C) 1999-2003 PCSX Team\n"
1328 "(C) 2005-2009 PCSX-df Team\n"
1329 "(C) 2009-2011 PCSX-Reloaded Team\n\n"
1330 "GPU and SPU code by Pete Bernert\n"
1331 " and the P.E.Op.S. team\n"
1332 "ARM recompiler (C) 2009-2011 Ari64\n"
1333 "PCSX4ALL plugins by PCSX4ALL team\n"
1334 " Chui, Franxis, Unai\n\n"
1335 "integration, optimization and\n"
1336 " frontend (C) 2010-2011 notaz\n";
1338 static int reset_game(void)
1341 if (bios_sel == 0 && !Config.HLE)
1347 if (CheckCdrom() != -1) {
1353 static int run_bios(void)
1359 pl_fbdev_buf = NULL;
1364 pcnt_hook_plugins();
1366 if (OpenPlugins() == -1) {
1367 me_update_msg("failed to open plugins");
1370 plugin_call_rearmed_cbs();
1373 CdromLabel[0] = '\0';
1381 static int run_cd_image(const char *fname)
1384 pl_fbdev_buf = NULL;
1387 set_cd_image(fname);
1389 pcnt_hook_plugins();
1391 if (OpenPlugins() == -1) {
1392 me_update_msg("failed to open plugins");
1395 plugin_call_rearmed_cbs();
1397 if (CheckCdrom() == -1) {
1398 // Only check the CD if we are starting the console with a CD
1400 me_update_msg("unsupported/invalid CD image");
1406 // Read main executable directly from CDRom and start it
1407 if (LoadCdrom() == -1) {
1409 me_update_msg("failed to load CD image");
1417 static int romsel_run(void)
1419 int prev_gpu, prev_spu;
1422 fname = menu_loop_romsel(last_selected_fname, sizeof(last_selected_fname));
1426 printf("selected file: %s\n", fname);
1428 new_dynarec_clear_full();
1430 if (run_cd_image(fname) != 0)
1433 prev_gpu = gpu_plugsel;
1434 prev_spu = spu_plugsel;
1435 if (menu_load_config(1) != 0)
1436 menu_load_config(0);
1438 // check for plugin changes, have to repeat
1439 // loading if game config changed plugins to reload them
1440 if (prev_gpu != gpu_plugsel || prev_spu != spu_plugsel) {
1441 printf("plugin change detected, reloading plugins..\n");
1442 if (run_cd_image(fname) != 0)
1446 strcpy(last_selected_fname, rom_fname_reload);
1450 static int swap_cd_image(void)
1454 fname = menu_loop_romsel(last_selected_fname, sizeof(last_selected_fname));
1458 printf("selected file: %s\n", fname);
1461 CdromLabel[0] = '\0';
1463 set_cd_image(fname);
1464 if (ReloadCdromPlugin() < 0) {
1465 me_update_msg("failed to load cdr plugin");
1468 if (CDR_open() < 0) {
1469 me_update_msg("failed to open cdr plugin");
1473 SetCdOpenCaseTime(time(NULL) + 2);
1476 strcpy(last_selected_fname, rom_fname_reload);
1480 static int main_menu_handler(int id, int keys)
1484 case MA_MAIN_RESUME_GAME:
1488 case MA_MAIN_SAVE_STATE:
1490 return menu_loop_savestate(0);
1492 case MA_MAIN_LOAD_STATE:
1494 return menu_loop_savestate(1);
1496 case MA_MAIN_RESET_GAME:
1497 if (ready_to_go && reset_game() == 0)
1500 case MA_MAIN_LOAD_ROM:
1501 if (romsel_run() == 0)
1504 case MA_MAIN_SWAP_CD:
1505 if (swap_cd_image() == 0)
1508 case MA_MAIN_RUN_BIOS:
1509 if (run_bios() == 0)
1512 case MA_MAIN_CREDITS:
1513 draw_menu_message(credits_text, draw_frame_credits);
1514 in_menu_wait(PBTN_MOK|PBTN_MBACK, 70);
1520 lprintf("%s: something unknown selected\n", __FUNCTION__);
1527 static menu_entry e_menu_main[] =
1531 mee_handler_id("Resume game", MA_MAIN_RESUME_GAME, main_menu_handler),
1532 mee_handler_id("Save State", MA_MAIN_SAVE_STATE, main_menu_handler),
1533 mee_handler_id("Load State", MA_MAIN_LOAD_STATE, main_menu_handler),
1534 mee_handler_id("Reset game", MA_MAIN_RESET_GAME, main_menu_handler),
1535 mee_handler_id("Load CD image", MA_MAIN_LOAD_ROM, main_menu_handler),
1536 mee_handler_id("Change CD image", MA_MAIN_SWAP_CD, main_menu_handler),
1537 mee_handler_id("Run BIOS", MA_MAIN_RUN_BIOS, main_menu_handler),
1538 mee_handler ("Options", menu_loop_options),
1539 mee_handler ("Controls", menu_loop_keyconfig),
1540 mee_handler_id("Credits", MA_MAIN_CREDITS, main_menu_handler),
1541 mee_handler_id("Exit", MA_MAIN_EXIT, main_menu_handler),
1545 // ----------------------------
1547 static void menu_leave_emu(void);
1549 void menu_loop(void)
1555 if (bioses[1] == NULL && !warned_about_bios) {
1557 warned_about_bios = 1;
1560 me_enable(e_menu_main, MA_MAIN_RESUME_GAME, ready_to_go);
1561 me_enable(e_menu_main, MA_MAIN_SAVE_STATE, ready_to_go && CdromId[0]);
1562 me_enable(e_menu_main, MA_MAIN_LOAD_STATE, ready_to_go && CdromId[0]);
1563 me_enable(e_menu_main, MA_MAIN_RESET_GAME, ready_to_go);
1564 me_enable(e_menu_main, MA_MAIN_SWAP_CD, ready_to_go);
1565 me_enable(e_menu_main, MA_MAIN_RUN_BIOS, bios_sel != 0);
1567 in_set_config_int(0, IN_CFG_BLOCKING, 1);
1570 me_loop(e_menu_main, &sel, draw_frame_main);
1571 } while (!ready_to_go);
1573 /* wait until menu, ok, back is released */
1574 while (in_menu_wait_any(50) & (PBTN_MENU|PBTN_MOK|PBTN_MBACK))
1577 in_set_config_int(0, IN_CFG_BLOCKING, 0);
1582 static void scan_bios_plugins(void)
1584 char fname[MAXPATHLEN];
1586 int bios_i, gpu_i, spu_i;
1591 gpu_plugins[0] = "builtin_gpu";
1592 spu_plugins[0] = "builtin_spu";
1593 bios_i = gpu_i = spu_i = 1;
1595 snprintf(fname, sizeof(fname), "%s/", Config.BiosDir);
1596 dir = opendir(fname);
1598 perror("scan_bios_plugins bios opendir");
1613 if (ent->d_type != DT_REG && ent->d_type != DT_LNK)
1616 snprintf(fname, sizeof(fname), "%s/%s", Config.BiosDir, ent->d_name);
1617 if (stat(fname, &st) != 0 || st.st_size != 512*1024) {
1618 printf("bad BIOS file: %s\n", ent->d_name);
1622 if (bios_i < ARRAY_SIZE(bioses) - 1) {
1623 bioses[bios_i++] = strdup(ent->d_name);
1627 printf("too many BIOSes, dropping \"%s\"\n", ent->d_name);
1633 snprintf(fname, sizeof(fname), "%s/", Config.PluginsDir);
1634 dir = opendir(fname);
1636 perror("scan_bios_plugins opendir");
1650 p = strstr(ent->d_name, ".so");
1654 snprintf(fname, sizeof(fname), "%s/%s", Config.PluginsDir, ent->d_name);
1655 h = dlopen(fname, RTLD_LAZY | RTLD_LOCAL);
1657 fprintf(stderr, "%s\n", dlerror());
1661 // now what do we have here?
1662 tmp = dlsym(h, "GPUinit");
1665 if (gpu_i < ARRAY_SIZE(gpu_plugins) - 1)
1666 gpu_plugins[gpu_i++] = strdup(ent->d_name);
1670 tmp = dlsym(h, "SPUinit");
1673 if (spu_i < ARRAY_SIZE(spu_plugins) - 1)
1674 spu_plugins[spu_i++] = strdup(ent->d_name);
1678 fprintf(stderr, "ignoring unidentified plugin: %s\n", fname);
1685 void menu_init(void)
1687 char buff[MAXPATHLEN];
1689 strcpy(last_selected_fname, "/media");
1691 scan_bios_plugins();
1695 menu_set_defconfig();
1696 menu_load_config(0);
1701 g_menubg_src_ptr = calloc(g_menuscreen_w * g_menuscreen_h * 2, 1);
1702 if (g_menubg_src_ptr == NULL)
1704 emu_make_path(buff, "skin/background.png", sizeof(buff));
1705 readpng(g_menubg_src_ptr, buff, READPNG_BG, g_menuscreen_w, g_menuscreen_h);
1708 void menu_notify_mode_change(int w, int h, int bpp)
1714 if (scaling == SCALE_1_1) {
1715 g_layer_x = 800/2 - w/2; g_layer_y = 480/2 - h/2;
1716 g_layer_w = w; g_layer_h = h;
1720 static void menu_leave_emu(void)
1722 if (GPU_close != NULL) {
1723 int ret = GPU_close();
1725 fprintf(stderr, "Warning: GPU_close returned %d\n", ret);
1728 memcpy(g_menubg_ptr, g_menubg_src_ptr, g_menuscreen_w * g_menuscreen_h * 2);
1729 if (pl_fbdev_buf != NULL && ready_to_go && last_psx_bpp == 16) {
1730 int x = max(0, g_menuscreen_w - last_psx_w);
1731 int y = max(0, g_menuscreen_h / 2 - last_psx_h / 2);
1732 int w = min(g_menuscreen_w, last_psx_w);
1733 int h = min(g_menuscreen_h, last_psx_h);
1734 u16 *d = (u16 *)g_menubg_ptr + g_menuscreen_w * y + x;
1735 u16 *s = pl_fbdev_buf;
1737 for (; h > 0; h--, d += g_menuscreen_w, s += last_psx_w)
1738 menu_darken_bg(d, s, w, 0);
1742 cpu_clock = get_cpu_clock();
1744 plat_video_menu_enter(ready_to_go);
1747 void menu_prepare_emu(void)
1749 R3000Acpu *prev_cpu = psxCpu;
1751 plat_video_menu_leave();
1755 menu_notify_mode_change(last_psx_w, last_psx_h, last_psx_bpp);
1758 g_layer_x = 80; g_layer_y = 0;
1759 g_layer_w = 640; g_layer_h = 480;
1761 case SCALE_FULLSCREEN:
1762 g_layer_x = 0; g_layer_y = 0;
1763 g_layer_w = 800; g_layer_h = 480;
1769 psxCpu = (Config.Cpu == CPU_INTERPRETER) ? &psxInt : &psxRec;
1770 if (psxCpu != prev_cpu)
1771 // note that this does not really reset, just clears drc caches
1774 // core doesn't care about Config.Cdda changes,
1775 // so handle them manually here
1780 apply_lcdrate(Config.PsxType);
1781 apply_filter(filter);
1784 // push config to GPU plugin
1785 plugin_call_rearmed_cbs();
1787 if (GPU_open != NULL) {
1788 int ret = GPU_open(&gpuDisp, "PCSX", NULL);
1790 fprintf(stderr, "Warning: GPU_open returned %d\n", ret);
1793 dfinput_activate(in_type == PSE_PAD_TYPE_ANALOGPAD);
1796 void me_update_msg(const char *msg)
1798 strncpy(menu_error_msg, msg, sizeof(menu_error_msg));
1799 menu_error_msg[sizeof(menu_error_msg) - 1] = 0;
1801 menu_error_time = plat_get_ticks_ms();
1802 lprintf("msg: %s\n", menu_error_msg);