X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?p=pcsx_rearmed.git;a=blobdiff_plain;f=frontend%2Fmenu.c;h=85f7b7f936e52a3092a30a080806fceadf7349a2;hp=2fc56ba68479a5569e8af9ec38dc3c6d15894d9e;hb=HEAD;hpb=0b02eb7712f1272fa7f38b0af41968b53af3b5a8 diff --git a/frontend/menu.c b/frontend/menu.c index 2fc56ba6..58efd218 100644 --- a/frontend/menu.c +++ b/frontend/menu.c @@ -1,5 +1,5 @@ /* - * (C) Gražvydas "notaz" Ignotas, 2010-2011 + * (C) Gražvydas "notaz" Ignotas, 2010-2015 * * This work is licensed under the terms of any of these licenses * (at your option): @@ -8,6 +8,12 @@ * See the COPYING file in the top-level directory. */ +#define _GNU_SOURCE 1 +#ifdef __FreeBSD__ +#define STAT stat +#else +#define STAT stat64 +#endif #include #include #include @@ -16,6 +22,7 @@ #include #include #include +#include #include "main.h" #include "menu.h" @@ -24,17 +31,19 @@ #include "plugin_lib.h" #include "plat.h" #include "pcnt.h" -#include "common/plat.h" -#include "common/input.h" -#include "linux/in_evdev.h" +#include "cspace.h" +#include "libpicofe/plat.h" +#include "libpicofe/input.h" +#include "libpicofe/linux/in_evdev.h" +#include "libpicofe/plat.h" #include "../libpcsxcore/misc.h" #include "../libpcsxcore/cdrom.h" #include "../libpcsxcore/cdriso.h" #include "../libpcsxcore/cheat.h" -#include "../libpcsxcore/psemu_plugin_defs.h" #include "../libpcsxcore/new_dynarec/new_dynarec.h" -#include "../plugins/dfinput/main.h" -#include "../plugins/gpulib/cspace.h" +#include "../plugins/dfsound/spu_config.h" +#include "psemu_plugin_defs.h" +#include "arm_features.h" #include "revision.h" #define REARMED_BIRTHDAY_TIME 1293306830 /* 25 Dec 2010 */ @@ -71,44 +80,60 @@ typedef enum MA_OPT_SAVECFG, MA_OPT_SAVECFG_GAME, MA_OPT_CPU_CLOCKS, + MA_OPT_SPU_THREAD, MA_OPT_DISP_OPTS, - MA_OPT_SCALER, + MA_OPT_VARSCALER, + MA_OPT_VARSCALER_C, MA_OPT_SCALER2, - MA_OPT_FILTERING, - MA_OPT_SCALER_C, + MA_OPT_HWFILTER, + MA_OPT_SWFILTER, + MA_OPT_GAMMA, + MA_OPT_VOUT_MODE, + MA_OPT_SCANLINES, + MA_OPT_SCANLINE_LEVEL, + MA_OPT_CENTERING, } menu_id; static int last_vout_w, last_vout_h, last_vout_bpp; -static int cpu_clock, cpu_clock_st, volume_boost, frameskip; -static char rom_fname_reload[MAXPATHLEN]; +static int cpu_clock, cpu_clock_st, volume_boost; +static int frameskip = 1; // 0 - auto, 1 - off static char last_selected_fname[MAXPATHLEN]; -static int warned_about_bios, region, in_type_sel1, in_type_sel2; +static int config_save_counter, region, in_type_sel1, in_type_sel2; static int psx_clock; -static int memcard1_sel, memcard2_sel; -int g_opts, g_scaler; +static int memcard1_sel = -1, memcard2_sel = -1; +extern int g_autostateld_opt; +static int menu_iopts[8]; +int g_opts, g_scaler, g_gamma = 100; +int scanlines, scanline_level = 20; int soft_scaling, analog_deadzone; // for Caanoo -int filter; +int soft_filter; -#ifdef __ARM_ARCH_7A__ -#define DEFAULT_PSX_CLOCK 57 +#ifndef HAVE_PRE_ARMV7 +#define DEFAULT_PSX_CLOCK (10000 / CYCLE_MULT_DEFAULT) #define DEFAULT_PSX_CLOCK_S "57" #else #define DEFAULT_PSX_CLOCK 50 #define DEFAULT_PSX_CLOCK_S "50" #endif -// sound plugin -extern int iUseReverb; -extern int iUseInterpolation; -extern int iXAPitch; -extern int iVolume; - -static const char *bioses[24]; +static const char *bioses[32]; static const char *gpu_plugins[16]; static const char *spu_plugins[16]; static const char *memcards[32]; static int bios_sel, gpu_plugsel, spu_plugsel; +#ifndef UI_FEATURES_H +#define MENU_BIOS_PATH "bios/" +#define MENU_SHOW_VARSCALER 0 +#define MENU_SHOW_VOUTMODE 1 +#define MENU_SHOW_SCALER2 0 +#define MENU_SHOW_NUBS_BTNS 0 +#define MENU_SHOW_VIBRATION 0 +#define MENU_SHOW_DEADZONE 0 +#define MENU_SHOW_MINIMIZE 0 +#define MENU_SHOW_FULLSCREEN 1 +#define MENU_SHOW_VOLUME 0 +#endif static int min(int x, int y) { return x < y ? x : y; } static int max(int x, int y) { return x > y ? x : y; } @@ -171,6 +196,112 @@ static int emu_save_load_game(int load, int unused) return ret; } +static void rm_namelist_entry(struct dirent **namelist, + int count, const char *name) +{ + int i; + + for (i = 1; i < count; i++) { + if (namelist[i] == NULL || namelist[i]->d_type == DT_DIR) + continue; + + if (strcmp(name, namelist[i]->d_name) == 0) { + free(namelist[i]); + namelist[i] = NULL; + break; + } + } +} + +static int optional_cdimg_filter(struct dirent **namelist, int count, + const char *basedir) +{ + const char *ext, *p; + char buf[256], buf2[257]; + int i, d, ret, good_cue; + struct STAT statf; + FILE *f; + + if (count <= 1) + return count; + + for (i = 1; i < count; i++) { + if (namelist[i] == NULL || namelist[i]->d_type == DT_DIR) + continue; + + ext = strrchr(namelist[i]->d_name, '.'); + if (ext == NULL) { + // should not happen but whatever + free(namelist[i]); + namelist[i] = NULL; + continue; + } + ext++; + + // first find .cue files and remove files they reference + if (strcasecmp(ext, "cue") == 0) + { + snprintf(buf, sizeof(buf), "%s/%s", basedir, + namelist[i]->d_name); + + f = fopen(buf, "r"); + if (f == NULL) { + free(namelist[i]); + namelist[i] = NULL; + continue; + } + + good_cue = 0; + while (fgets(buf, sizeof(buf), f)) { + ret = sscanf(buf, " FILE \"%256[^\"]\"", buf2); + if (ret != 1) + ret = sscanf(buf, " FILE %256s", buf2); + if (ret != 1) + continue; + + p = strrchr(buf2, '/'); + if (p == NULL) + p = strrchr(buf2, '\\'); + if (p != NULL) + p++; + else + p = buf2; + + snprintf(buf, sizeof(buf), "%s/%s", basedir, p); + ret = STAT(buf, &statf); + if (ret == 0) { + rm_namelist_entry(namelist, count, p); + good_cue = 1; + } + } + fclose(f); + + if (!good_cue) { + free(namelist[i]); + namelist[i] = NULL; + } + continue; + } + + p = strcasestr(namelist[i]->d_name, "track"); + if (p != NULL) { + ret = strtoul(p + 5, NULL, 10); + if (ret > 1) { + free(namelist[i]); + namelist[i] = NULL; + continue; + } + } + } + + // compact namelist + for (i = d = 1; i < count; i++) + if (namelist[i] != NULL) + namelist[d++] = namelist[i]; + + return d; +} + // propagate menu settings to the emu vars static void menu_sync_config(void) { @@ -181,24 +312,28 @@ static void menu_sync_config(void) Config.PsxAuto = 0; Config.PsxType = region - 1; } - cycle_multiplier = 10000 / psx_clock; + Config.cycle_multiplier = 10000 / psx_clock; switch (in_type_sel1) { - case 1: in_type1 = PSE_PAD_TYPE_ANALOGPAD; break; - case 2: in_type1 = PSE_PAD_TYPE_GUNCON; break; - default: in_type1 = PSE_PAD_TYPE_STANDARD; + case 1: in_type[0] = PSE_PAD_TYPE_ANALOGPAD; break; + case 2: in_type[0] = PSE_PAD_TYPE_GUNCON; break; + case 3: in_type[0] = PSE_PAD_TYPE_GUN; break; + case 4: in_type[0] = PSE_PAD_TYPE_NONE; break; + default: in_type[0] = PSE_PAD_TYPE_STANDARD; } switch (in_type_sel2) { - case 1: in_type2 = PSE_PAD_TYPE_ANALOGPAD; break; - case 2: in_type2 = PSE_PAD_TYPE_GUNCON; break; - default: in_type2 = PSE_PAD_TYPE_STANDARD; + case 1: in_type[1] = PSE_PAD_TYPE_ANALOGPAD; break; + case 2: in_type[1] = PSE_PAD_TYPE_GUNCON; break; + case 3: in_type[1] = PSE_PAD_TYPE_GUN; break; + case 4: in_type[1] = PSE_PAD_TYPE_NONE; break; + default: in_type[1] = PSE_PAD_TYPE_STANDARD; } if (in_evdev_allow_abs_only != allow_abs_only_old) { in_probe(); allow_abs_only_old = in_evdev_allow_abs_only; } - iVolume = 768 + 128 * volume_boost; + spu_config.iVolume = 768 + 128 * volume_boost; pl_rearmed_cbs.frameskip = frameskip - 1; pl_timing_prepare(Config.PsxType); } @@ -209,10 +344,15 @@ static void menu_set_defconfig(void) g_opts = 0; g_scaler = SCALE_4_3; + g_gamma = 100; volume_boost = 0; - frameskip = 0; + frameskip = 1; // 1 - off analog_deadzone = 50; soft_scaling = 1; + soft_filter = 0; + scanlines = 0; + scanline_level = 20; + plat_target.vout_fullscreen = 0; psx_clock = DEFAULT_PSX_CLOCK; region = 0; @@ -234,6 +374,9 @@ static void menu_set_defconfig(void) #define CE_INTVAL(val) \ { #val, sizeof(val), &val } +#define CE_INTVAL_N(name, val) \ + { name, sizeof(val), &val } + #define CE_INTVAL_P(val) \ { #val, sizeof(pl_rearmed_cbs.val), &pl_rearmed_cbs.val } @@ -257,39 +400,58 @@ static const struct { CE_CONFIG_STR(Spu), // CE_CONFIG_STR(Cdr), CE_CONFIG_VAL(Xa), - CE_CONFIG_VAL(Sio), CE_CONFIG_VAL(Mdec), CE_CONFIG_VAL(Cdda), CE_CONFIG_VAL(Debug), CE_CONFIG_VAL(PsxOut), - CE_CONFIG_VAL(SpuIrq), - CE_CONFIG_VAL(RCntFix), - CE_CONFIG_VAL(VSyncWA), + CE_CONFIG_VAL(icache_emulation), + CE_CONFIG_VAL(DisableStalls), CE_CONFIG_VAL(Cpu), - CE_CONFIG_VAL(CdrReschedule), + CE_CONFIG_VAL(GpuListWalking), + CE_CONFIG_VAL(FractionalFramerate), + CE_CONFIG_VAL(PreciseExceptions), CE_INTVAL(region), - CE_INTVAL_V(g_scaler, 2), + CE_INTVAL_V(g_scaler, 3), + CE_INTVAL(g_gamma), CE_INTVAL(g_layer_x), CE_INTVAL(g_layer_y), CE_INTVAL(g_layer_w), CE_INTVAL(g_layer_h), - CE_INTVAL(filter), + CE_INTVAL(soft_filter), + CE_INTVAL(scanlines), + CE_INTVAL(scanline_level), + CE_INTVAL(plat_target.vout_method), + CE_INTVAL(plat_target.hwfilter), + CE_INTVAL(plat_target.vout_fullscreen), CE_INTVAL(state_slot), CE_INTVAL(cpu_clock), CE_INTVAL(g_opts), CE_INTVAL(in_type_sel1), CE_INTVAL(in_type_sel2), CE_INTVAL(analog_deadzone), - CE_INTVAL_V(frameskip, 3), + CE_INTVAL(memcard1_sel), + CE_INTVAL(memcard2_sel), + CE_INTVAL(g_autostateld_opt), + CE_INTVAL_N("adev0_is_nublike", in_adev_is_nublike[0]), + CE_INTVAL_N("adev1_is_nublike", in_adev_is_nublike[1]), + CE_INTVAL_V(frameskip, 4), CE_INTVAL_P(gpu_peops.iUseDither), CE_INTVAL_P(gpu_peops.dwActFixes), - CE_INTVAL_P(gpu_unai.lineskip), - CE_INTVAL_P(gpu_unai.abe_hack), - CE_INTVAL_P(gpu_unai.no_light), - CE_INTVAL_P(gpu_unai.no_blend), + CE_INTVAL_P(gpu_unai_old.lineskip), + CE_INTVAL_P(gpu_unai_old.abe_hack), + CE_INTVAL_P(gpu_unai_old.no_light), + CE_INTVAL_P(gpu_unai_old.no_blend), + CE_INTVAL_P(gpu_unai.ilace_force), + CE_INTVAL_P(gpu_unai.pixel_skip), + CE_INTVAL_P(gpu_unai.lighting), + CE_INTVAL_P(gpu_unai.fast_lighting), + CE_INTVAL_P(gpu_unai.blending), + CE_INTVAL_P(gpu_unai.dithering), + CE_INTVAL_P(gpu_unai.scale_hires), CE_INTVAL_P(gpu_neon.allow_interlace), CE_INTVAL_P(gpu_neon.enhancement_enable), CE_INTVAL_P(gpu_neon.enhancement_no_main), + CE_INTVAL_P(gpu_neon.enhancement_tex_adj), CE_INTVAL_P(gpu_peopsgl.bDrawDither), CE_INTVAL_P(gpu_peopsgl.iFilterType), CE_INTVAL_P(gpu_peopsgl.iFrameTexType), @@ -300,10 +462,15 @@ static const struct { CE_INTVAL_P(gpu_peopsgl.iVRamSize), CE_INTVAL_P(gpu_peopsgl.iTexGarbageCollection), CE_INTVAL_P(gpu_peopsgl.dwActFixes), - CE_INTVAL_V(iUseReverb, 3), - CE_INTVAL_V(iXAPitch, 3), - CE_INTVAL_V(iUseInterpolation, 3), - CE_INTVAL(warned_about_bios), + CE_INTVAL_P(screen_centering_type), + CE_INTVAL_P(screen_centering_x), + CE_INTVAL_P(screen_centering_y), + CE_INTVAL(spu_config.iUseReverb), + CE_INTVAL(spu_config.iXAPitch), + CE_INTVAL(spu_config.iUseInterpolation), + CE_INTVAL(spu_config.iTempo), + CE_INTVAL(spu_config.iUseThread), + CE_INTVAL(config_save_counter), CE_INTVAL(in_evdev_allow_abs_only), CE_INTVAL(volume_boost), CE_INTVAL(psx_clock), @@ -336,12 +503,21 @@ static void make_cfg_fname(char *buf, size_t size, int is_game) static void keys_write_all(FILE *f); static char *mystrip(char *str); +static void write_u32_value(FILE *f, u32 v) +{ + if (v > 7) + fprintf(f, "0x"); + fprintf(f, "%x\n", v); +} + static int menu_write_config(int is_game) { char cfgfile[MAXPATHLEN]; FILE *f; int i; + config_save_counter++; + make_cfg_fname(cfgfile, sizeof(cfgfile), is_game); f = fopen(cfgfile, "w"); if (f == NULL) { @@ -356,13 +532,13 @@ static int menu_write_config(int is_game) fprintf(f, "%s\n", (char *)config_data[i].val); break; case 1: - fprintf(f, "%x\n", *(u8 *)config_data[i].val); + write_u32_value(f, *(u8 *)config_data[i].val); break; case 2: - fprintf(f, "%x\n", *(u16 *)config_data[i].val); + write_u32_value(f, *(u16 *)config_data[i].val); break; case 4: - fprintf(f, "%x\n", *(u32 *)config_data[i].val); + write_u32_value(f, *(u32 *)config_data[i].val); break; default: printf("menu_write_config: unhandled len %d for %s\n", @@ -379,14 +555,18 @@ static int menu_write_config(int is_game) static int menu_do_last_cd_img(int is_get) { + static const char *defaults[] = { "/media", "/mnt/sd", "/mnt" }; char path[256]; + struct STAT st; FILE *f; - int ret; + int i, ret = -1; snprintf(path, sizeof(path), "." PCSX_DOT_DIR "lastcdimg.txt"); f = fopen(path, is_get ? "r" : "w"); - if (f == NULL) - return -1; + if (f == NULL) { + ret = -1; + goto out; + } if (is_get) { ret = fread(last_selected_fname, 1, sizeof(last_selected_fname) - 1, f); @@ -397,6 +577,17 @@ static int menu_do_last_cd_img(int is_get) fprintf(f, "%s\n", last_selected_fname); fclose(f); +out: + if (is_get) { + for (i = 0; last_selected_fname[0] == 0 + || STAT(last_selected_fname, &st) != 0; i++) + { + if (i >= ARRAY_SIZE(defaults)) + break; + strcpy(last_selected_fname, defaults[i]); + } + } + return 0; } @@ -414,7 +605,7 @@ static void parse_str_val(char *cval, const char *src) static void keys_load_all(const char *cfg); -static int menu_load_config(int is_game) +int menu_load_config(int is_game) { char cfgfile[MAXPATHLEN]; int i, ret = -1; @@ -517,23 +708,54 @@ fail: if (strcmp(Config.Spu, spu_plugins[i]) == 0) { spu_plugsel = i; break; } + // memcard selections + char mcd1_old[sizeof(Config.Mcd1)]; + char mcd2_old[sizeof(Config.Mcd2)]; + strcpy(mcd1_old, Config.Mcd1); + strcpy(mcd2_old, Config.Mcd2); + + if ((unsigned int)memcard1_sel < ARRAY_SIZE(memcards)) { + if (memcard1_sel == 0) + strcpy(Config.Mcd1, "none"); + else if (memcards[memcard1_sel] != NULL) + snprintf(Config.Mcd1, sizeof(Config.Mcd1), ".%s%s", + MEMCARD_DIR, memcards[memcard1_sel]); + } + if ((unsigned int)memcard2_sel < ARRAY_SIZE(memcards)) { + if (memcard2_sel == 0) + strcpy(Config.Mcd2, "none"); + else if (memcards[memcard2_sel] != NULL) + snprintf(Config.Mcd2, sizeof(Config.Mcd2), ".%s%s", + MEMCARD_DIR, memcards[memcard2_sel]); + } + if (strcmp(mcd1_old, Config.Mcd1) || strcmp(mcd2_old, Config.Mcd2)) + LoadMcds(Config.Mcd1, Config.Mcd2); + return ret; } +static const char *filter_exts[] = { + "bin", "img", "mdf", "iso", "cue", "z", + #ifdef HAVE_CHD + "chd", + #endif + "bz", "znx", "pbp", "cbn", NULL +}; + // rrrr rggg gggb bbbb static unsigned short fname2color(const char *fname) { - static const char *cdimg_exts[] = { ".bin", ".img", ".mdf", ".iso", ".cue", ".z", - ".bz", ".znx", ".pbp", ".cbn" }; - static const char *other_exts[] = { ".ccd", ".toc", ".mds", ".sub", - ".table", ".index", ".sbi" }; + static const char *other_exts[] = { + "ccd", "toc", "mds", "sub", "table", "index", "sbi" + }; const char *ext = strrchr(fname, '.'); int i; if (ext == NULL) return 0xffff; - for (i = 0; i < array_size(cdimg_exts); i++) - if (strcasecmp(ext, cdimg_exts[i]) == 0) + ext++; + for (i = 0; filter_exts[i] != NULL; i++) + if (strcasecmp(ext, filter_exts[i]) == 0) return 0x7bff; for (i = 0; i < array_size(other_exts); i++) if (strcasecmp(ext, other_exts[i]) == 0) @@ -543,20 +765,14 @@ static unsigned short fname2color(const char *fname) static void draw_savestate_bg(int slot); -static const char *filter_exts[] = { - ".mp3", ".MP3", ".txt", ".htm", "html", ".jpg", ".pnd" -}; - #define MENU_ALIGN_LEFT -#ifdef __ARM_ARCH_7A__ // assume hires device +#ifndef HAVE_PRE_ARMV7 // assume hires device #define MENU_X2 1 #else #define MENU_X2 0 #endif -#define menu_init menu_init_common -#include "common/menu.c" -#undef menu_init +#include "libpicofe/menu.c" // a bit of black magic here static void draw_savestate_bg(int slot) @@ -578,8 +794,8 @@ static void draw_savestate_bg(int slot) if (f == NULL) return; - if (gzseek(f, 0x29933d, SEEK_SET) != 0x29933d) { - fprintf(stderr, "gzseek failed\n"); + if ((ret = (int)gzseek(f, 0x29933d, SEEK_SET)) != 0x29933d) { + fprintf(stderr, "gzseek failed: %d\n", ret); gzclose(f); return; } @@ -604,12 +820,18 @@ static void draw_savestate_bg(int slot) x = gpu->ulControl[5] & 0x3ff; y = (gpu->ulControl[5] >> 10) & 0x1ff; - s = (u16 *)gpu->psxVRam + y * 1024 + x; w = psx_widths[(gpu->ulStatus >> 16) & 7]; tmp = gpu->ulControl[7]; h = ((tmp >> 10) & 0x3ff) - (tmp & 0x3ff); if (gpu->ulStatus & 0x80000) // doubleheight h *= 2; + if (h <= 0 || h > 512) + goto out; + if (y > 512 - 64) + y = 0; + if (y + h > 512) + h = 512 - y; + s = (u16 *)gpu->psxVRam + y * 1024 + x; x = max(0, g_menuscreen_w - w) & ~3; y = max(0, g_menuscreen_h / 2 - h / 2); @@ -625,7 +847,7 @@ static void draw_savestate_bg(int slot) // darken this so that menu text is visible if (g_menuscreen_w - w < 320) - menu_darken_bg(d, d, w * 2, 0); + menu_darken_bg(d, d, w, 0); } out: @@ -663,18 +885,27 @@ me_bind_action emuctrl_actions[] = { "Next Save Slot ", 1 << SACTION_NEXT_SSLOT }, { "Toggle Frameskip ", 1 << SACTION_TOGGLE_FSKIP }, { "Take Screenshot ", 1 << SACTION_SCREENSHOT }, - { "Enter Menu ", 1 << SACTION_ENTER_MENU }, -#ifdef __ARM_ARCH_7A__ /* XXX */ + { "Show/Hide FPS ", 1 << SACTION_TOGGLE_FPS }, +#ifndef HAVE_PRE_ARMV7 + { "Switch Renderer ", 1 << SACTION_SWITCH_DISPMODE }, +#endif + { "Fast Forward ", 1 << SACTION_FAST_FORWARD }, +#if MENU_SHOW_MINIMIZE { "Minimize ", 1 << SACTION_MINIMIZE }, #endif +#if MENU_SHOW_FULLSCREEN + { "Toggle fullscreen", 1 << SACTION_TOGGLE_FULLSCREEN }, +#endif + { "Enter Menu ", 1 << SACTION_ENTER_MENU }, { "Gun Trigger ", 1 << SACTION_GUN_TRIGGER }, { "Gun A button ", 1 << SACTION_GUN_A }, { "Gun B button ", 1 << SACTION_GUN_B }, { "Gun Offscreen Trigger", 1 << SACTION_GUN_TRIGGER2 }, -#ifndef __ARM_ARCH_7A__ /* XXX */ +#if MENU_SHOW_VOLUME { "Volume Up ", 1 << SACTION_VOLUME_UP }, { "Volume Down ", 1 << SACTION_VOLUME_DOWN }, #endif + { "Analog toggle ", 1 << SACTION_ANALOG_TOGGLE }, { NULL, 0 } }; @@ -707,8 +938,6 @@ static void get_line(char *d, size_t size, const char *s) len = size - 1; strncpy(d, s, len); d[len] = 0; - - mystrip(d); } static void keys_write_all(FILE *f) @@ -815,7 +1044,10 @@ static void keys_load_all(const char *cfg) while (p != NULL && (p = strstr(p, "binddev = ")) != NULL) { p += 10; + // don't strip 'dev' because there are weird devices + // with names with space at the end get_line(dev, sizeof(dev), p); + dev_id = in_config_parse_dev(dev); if (dev_id < 0) { printf("input: can't handle dev: %s\n", dev); @@ -889,17 +1121,21 @@ static int key_config_loop_wrap(int id, int keys) return 0; } +static const char h_nubmode[] = "Maps nub-like analog controls to PSX ones better\n" + "Might cause problems with real analog sticks"; static const char *adevnames[IN_MAX_DEVS + 2]; static int stick_sel[2]; static menu_entry e_menu_keyconfig_analog[] = { - mee_enum ("Left stick (L3)", 0, stick_sel[0], adevnames), - mee_range(" X axis", 0, in_adev_axis[0][0], 0, 7), - mee_range(" Y axis", 0, in_adev_axis[0][1], 0, 7), - mee_enum ("Right stick (R3)", 0, stick_sel[1], adevnames), - mee_range(" X axis", 0, in_adev_axis[1][0], 0, 7), - mee_range(" Y axis", 0, in_adev_axis[1][1], 0, 7), + mee_enum ("Left stick (L3)", 0, stick_sel[0], adevnames), + mee_range (" X axis", 0, in_adev_axis[0][0], 0, 7), + mee_range (" Y axis", 0, in_adev_axis[0][1], 0, 7), + mee_onoff_h(" nub mode", 0, in_adev_is_nublike[0], 1, h_nubmode), + mee_enum ("Right stick (R3)", 0, stick_sel[1], adevnames), + mee_range (" X axis", 0, in_adev_axis[1][0], 0, 7), + mee_range (" Y axis", 0, in_adev_axis[1][1], 0, 7), + mee_onoff_h(" nub mode", 0, in_adev_is_nublike[1], 1, h_nubmode), mee_end, }; @@ -966,9 +1202,9 @@ static const char *mgn_saveloadcfg(int id, int *offs) static int mh_savecfg(int id, int keys) { if (menu_write_config(id == MA_OPT_SAVECFG_GAME ? 1 : 0) == 0) - me_update_msg("config saved"); + menu_update_msg("config saved"); else - me_update_msg("failed to write config"); + menu_update_msg("failed to write config"); return 1; } @@ -977,7 +1213,7 @@ static int mh_input_rescan(int id, int keys) { //menu_sync_config(); in_probe(); - me_update_msg("rescan complete."); + menu_update_msg("rescan complete."); return 0; } @@ -986,6 +1222,8 @@ static const char *men_in_type_sel[] = { "Standard (SCPH-1080)", "Analog (SCPH-1150)", "GunCon", + "Konami Gun", + "None", NULL }; static const char h_nub_btns[] = "Experimental, keep this OFF if unsure. Select rescan after change."; @@ -1030,26 +1268,64 @@ static int menu_loop_keyconfig(int id, int keys) // ------------ gfx options menu ------------ -static const char *men_scaler[] = { "1x1", "scaled 4:3", "integer scaled 4:3", "fullscreen", "custom", NULL }; +static const char *men_scaler[] = { + "1x1", "integer scaled 2x", "scaled 4:3", "integer scaled 4:3", "fullscreen", "custom", NULL +}; +static const char *men_soft_filter[] = { "None", +#ifdef __ARM_NEON__ + "scale2x", "eagle2x", +#endif + NULL }; +static const char *men_dummy[] = { NULL }; +static const char *men_centering[] = { "Auto", "Ingame", "Borderless", "Force", NULL }; +static const char h_scaler[] = "int. 2x - scales w. or h. 2x if it fits on screen\n" + "int. 4:3 - uses integer if possible, else fractional"; static const char h_cscaler[] = "Displays the scaler layer, you can resize it\n" "using d-pad or move it using R+d-pad"; -static const char *men_dummy[] = { NULL }; +static const char h_soft_filter[] = "Works only if game uses low resolution modes"; +static const char h_gamma[] = "Gamma/brightness adjustment (default 100)"; +#ifdef __ARM_NEON__ +static const char *men_scanlines[] = { "OFF", "1", "2", "3", NULL }; +static const char h_scanline_l[] = "Scanline brightness, 0-100%"; +#endif static int menu_loop_cscaler(int id, int keys) { + void *saved_layer = NULL; + size_t saved_layer_size = 0; + int was_layer_clipped = 0; unsigned int inp; + if (!pl_vout_buf) + return -1; + g_scaler = SCALE_CUSTOM; + saved_layer_size = last_vout_w * last_vout_h * last_vout_bpp / 8; + saved_layer = malloc(saved_layer_size); + if (saved_layer) + memcpy(saved_layer, pl_vout_buf, saved_layer_size); plat_gvideo_open(Config.PsxType); + menu_draw_begin(0, 1); + memset(g_menuscreen_ptr, 4, g_menuscreen_w * g_menuscreen_h * 2); + menu_draw_end(); + for (;;) { - menu_draw_begin(0); - memset(g_menuscreen_ptr, 4, g_menuscreen_w * g_menuscreen_h * 2); - text_out16(2, 2, "%d,%d", g_layer_x, g_layer_y); - text_out16(2, 480 - 18, "%dx%d | d-pad: resize, R+d-pad: move", g_layer_w, g_layer_h); - menu_draw_end(); + if (saved_layer && last_vout_bpp == 16) { + int top_x = max(0, -g_layer_x * last_vout_w / 800) + 1; + int top_y = max(0, -g_layer_y * last_vout_h / 480) + 1; + char text[128]; + memcpy(pl_vout_buf, saved_layer, saved_layer_size); + snprintf(text, sizeof(text), "%d,%d %dx%d", + g_layer_x, g_layer_y, g_layer_w, g_layer_h); + basic_text_out16_nf(pl_vout_buf, last_vout_w, + top_x, top_y, text); + basic_text_out16_nf(pl_vout_buf, last_vout_w, 2, + last_vout_h - 20, "d-pad: resize, R+d-pad: move"); + pl_vout_buf = plat_gvideo_flip(); + } inp = in_menu_wait(PBTN_UP|PBTN_DOWN|PBTN_LEFT|PBTN_RIGHT |PBTN_R|PBTN_MOK|PBTN_MBACK, NULL, 40); @@ -1067,33 +1343,49 @@ static int menu_loop_cscaler(int id, int keys) break; if (inp & (PBTN_UP|PBTN_DOWN|PBTN_LEFT|PBTN_RIGHT)) { - if (g_layer_x < 0) g_layer_x = 0; - if (g_layer_x > 640) g_layer_x = 640; - if (g_layer_y < 0) g_layer_y = 0; - if (g_layer_y > 420) g_layer_y = 420; - if (g_layer_w < 160) g_layer_w = 160; - if (g_layer_h < 60) g_layer_h = 60; - if (g_layer_x + g_layer_w > 800) - g_layer_w = 800 - g_layer_x; - if (g_layer_y + g_layer_h > 480) - g_layer_h = 480 - g_layer_y; + int layer_clipped = 0; + g_layer_x = max(-320, min(g_layer_x, 640)); + g_layer_y = max(-240, min(g_layer_y, 400)); + g_layer_w = max(160, g_layer_w); + g_layer_h = max( 60, g_layer_h); + if (g_layer_x < 0 || g_layer_x + g_layer_w > 800) + layer_clipped = 1; + if (g_layer_w > 800+400) + g_layer_w = 800+400; + if (g_layer_y < 0 || g_layer_y + g_layer_h > 480) + layer_clipped = 1; + if (g_layer_h > 480+360) + g_layer_h = 480+360; // resize the layer plat_gvideo_open(Config.PsxType); + if (layer_clipped || was_layer_clipped) + pl_vout_buf = plat_gvideo_set_mode(&last_vout_w, + &last_vout_h, &last_vout_bpp); + was_layer_clipped = layer_clipped; } } plat_gvideo_close(); + free(saved_layer); return 0; } static menu_entry e_menu_gfx_options[] = { - mee_enum ("Scaler", MA_OPT_SCALER, g_scaler, men_scaler), + mee_enum ("Screen centering", MA_OPT_CENTERING, pl_rearmed_cbs.screen_centering_type, men_centering), + mee_enum_h ("Scaler", MA_OPT_VARSCALER, g_scaler, men_scaler, h_scaler), + mee_enum ("Video output mode", MA_OPT_VOUT_MODE, plat_target.vout_method, men_dummy), mee_onoff ("Software Scaling", MA_OPT_SCALER2, soft_scaling, 1), - mee_enum ("Filter", MA_OPT_FILTERING, filter, men_dummy), + mee_enum ("Hardware Filter", MA_OPT_HWFILTER, plat_target.hwfilter, men_dummy), + mee_enum_h ("Software Filter", MA_OPT_SWFILTER, soft_filter, men_soft_filter, h_soft_filter), +#ifdef __ARM_NEON__ + mee_enum ("Scanlines", MA_OPT_SCANLINES, scanlines, men_scanlines), + mee_range_h ("Scanline brightness", MA_OPT_SCANLINE_LEVEL, scanline_level, 0, 100, h_scanline_l), +#endif + mee_range_h ("Gamma adjustment", MA_OPT_GAMMA, g_gamma, 1, 200, h_gamma), // mee_onoff ("Vsync", 0, vsync, 1), - mee_cust_h ("Setup custom scaler", MA_OPT_SCALER_C, menu_loop_cscaler, NULL, h_cscaler), + mee_cust_h ("Setup custom scaler", MA_OPT_VARSCALER_C, menu_loop_cscaler, NULL, h_cscaler), mee_end, }; @@ -1106,30 +1398,25 @@ static int menu_loop_gfx_options(int id, int keys) return 0; } -// XXX -void menu_set_filter_list(void *filters) -{ - int i; - - i = me_id2offset(e_menu_gfx_options, MA_OPT_FILTERING); - e_menu_gfx_options[i].data = filters; - me_enable(e_menu_gfx_options, MA_OPT_FILTERING, filters != NULL); -} - // ------------ bios/plugins ------------ -#ifdef __ARM_NEON__ +#ifdef BUILTIN_GPU_NEON -static const char h_gpu_neon[] = "Configure built-in NEON GPU plugin"; -static const char h_gpu_neon_enhanced[] = "Renders in double resolution at the cost of lower performance"; -static const char h_gpu_neon_enhanced_hack[] = "Speed hack for above option (glitches some games)"; +static const char h_gpu_neon[] = + "Configure built-in NEON GPU plugin"; +static const char h_gpu_neon_enhanced[] = + "Renders in double resolution at the cost of lower performance\n" + "(not available for high resolution games)"; +static const char h_gpu_neon_enhanced_hack[] = + "Speed hack for above option (glitches some games)"; static const char *men_gpu_interlace[] = { "Off", "On", "Auto", NULL }; static menu_entry e_menu_plugin_gpu_neon[] = { mee_enum ("Enable interlace mode", 0, pl_rearmed_cbs.gpu_neon.allow_interlace, men_gpu_interlace), - mee_onoff_h ("Enhanced resolution (slow)", 0, pl_rearmed_cbs.gpu_neon.enhancement_enable, 1, h_gpu_neon_enhanced), + mee_onoff_h ("Enhanced resolution", 0, pl_rearmed_cbs.gpu_neon.enhancement_enable, 1, h_gpu_neon_enhanced), mee_onoff_h ("Enhanced res. speed hack", 0, pl_rearmed_cbs.gpu_neon.enhancement_no_main, 1, h_gpu_neon_enhanced_hack), + mee_onoff ("Enh. res. texture adjust", 0, pl_rearmed_cbs.gpu_neon.enhancement_tex_adj, 1), mee_end, }; @@ -1142,12 +1429,30 @@ static int menu_loop_plugin_gpu_neon(int id, int keys) #endif +static menu_entry e_menu_plugin_gpu_unai_old[] = +{ + mee_onoff ("Skip every 2nd line", 0, pl_rearmed_cbs.gpu_unai_old.lineskip, 1), + mee_onoff ("Abe's Odyssey hack", 0, pl_rearmed_cbs.gpu_unai_old.abe_hack, 1), + mee_onoff ("Disable lighting", 0, pl_rearmed_cbs.gpu_unai_old.no_light, 1), + mee_onoff ("Disable blending", 0, pl_rearmed_cbs.gpu_unai_old.no_blend, 1), + mee_end, +}; + +static int menu_loop_plugin_gpu_unai_old(int id, int keys) +{ + int sel = 0; + me_loop(e_menu_plugin_gpu_unai_old, &sel); + return 0; +} + static menu_entry e_menu_plugin_gpu_unai[] = { - mee_onoff ("Skip every 2nd line", 0, pl_rearmed_cbs.gpu_unai.lineskip, 1), - mee_onoff ("Abe's Odyssey hack", 0, pl_rearmed_cbs.gpu_unai.abe_hack, 1), - mee_onoff ("Disable lighting", 0, pl_rearmed_cbs.gpu_unai.no_light, 1), - mee_onoff ("Disable blending", 0, pl_rearmed_cbs.gpu_unai.no_blend, 1), + mee_onoff ("Interlace", 0, pl_rearmed_cbs.gpu_unai.ilace_force, 1), + mee_onoff ("Dithering", 0, pl_rearmed_cbs.gpu_unai.dithering, 1), + mee_onoff ("Lighting", 0, pl_rearmed_cbs.gpu_unai.lighting, 1), + mee_onoff ("Fast lighting", 0, pl_rearmed_cbs.gpu_unai.fast_lighting, 1), + mee_onoff ("Blending", 0, pl_rearmed_cbs.gpu_unai.blending, 1), + mee_onoff ("Pixel skip", 0, pl_rearmed_cbs.gpu_unai.pixel_skip, 1), mee_end, }; @@ -1158,6 +1463,7 @@ static int menu_loop_plugin_gpu_unai(int id, int keys) return 0; } + static const char *men_gpu_dithering[] = { "None", "Game dependant", "Always", NULL }; //static const char h_gpu_0[] = "Needed for Chrono Cross"; static const char h_gpu_1[] = "Capcom fighting games"; @@ -1230,13 +1536,16 @@ static int menu_loop_plugin_gpu_peopsgl(int id, int keys) static const char *men_spu_interp[] = { "None", "Simple", "Gaussian", "Cubic", NULL }; static const char h_spu_volboost[] = "Large values cause distortion"; +static const char h_spu_tempo[] = "Slows down audio if emu is too slow\n" + "This is inaccurate and breaks games"; static menu_entry e_menu_plugin_spu[] = { mee_range_h ("Volume boost", 0, volume_boost, -5, 30, h_spu_volboost), - mee_onoff ("Reverb", 0, iUseReverb, 2), - mee_enum ("Interpolation", 0, iUseInterpolation, men_spu_interp), - mee_onoff ("Adjust XA pitch", 0, iXAPitch, 1), + mee_onoff ("Reverb", 0, spu_config.iUseReverb, 1), + mee_enum ("Interpolation", 0, spu_config.iUseInterpolation, men_spu_interp), + //mee_onoff ("Adjust XA pitch", 0, spu_config.iXAPitch, 1), + mee_onoff_h ("Adjust tempo", 0, spu_config.iTempo, 1, h_spu_tempo), mee_end, }; @@ -1251,18 +1560,20 @@ static const char h_bios[] = "HLE is simulated BIOS. BIOS selection is sav "savestates and can't be changed there. Must save\n" "config and reload the game for change to take effect"; static const char h_plugin_gpu[] = -#ifdef __ARM_NEON__ +#ifdef BUILTIN_GPU_NEON "builtin_gpu is the NEON GPU, very fast and accurate\n" #endif "gpu_peops is Pete's soft GPU, slow but accurate\n" - "gpu_unai is GPU from PCSX4ALL, fast but glitchy\n" + "gpu_unai_old is from old PCSX4ALL, fast but glitchy\n" + "gpu_unai is newer, more accurate but slower\n" "gpu_gles Pete's hw GPU, uses 3D chip but is glitchy\n" "must save config and reload the game if changed"; static const char h_plugin_spu[] = "spunull effectively disables sound\n" "must save config and reload the game if changed"; static const char h_gpu_peops[] = "Configure P.E.Op.S. SoftGL Driver V1.17"; static const char h_gpu_peopsgl[]= "Configure P.E.Op.S. MesaGL Driver V1.78"; -static const char h_gpu_unai[] = "Configure Unai/PCSX4ALL Team GPU plugin"; +static const char h_gpu_unai_old[] = "Configure Unai/PCSX4ALL Team GPU plugin (old)"; +static const char h_gpu_unai[] = "Configure Unai/PCSX4ALL Team plugin (new)"; static const char h_spu[] = "Configure built-in P.E.Op.S. Sound Driver V1.7"; static menu_entry e_menu_plugin_options[] = @@ -1270,10 +1581,11 @@ static menu_entry e_menu_plugin_options[] = mee_enum_h ("BIOS", 0, bios_sel, bioses, h_bios), mee_enum_h ("GPU plugin", 0, gpu_plugsel, gpu_plugins, h_plugin_gpu), mee_enum_h ("SPU plugin", 0, spu_plugsel, spu_plugins, h_plugin_spu), -#ifdef __ARM_NEON__ +#ifdef BUILTIN_GPU_NEON mee_handler_h ("Configure built-in GPU plugin", menu_loop_plugin_gpu_neon, h_gpu_neon), #endif mee_handler_h ("Configure gpu_peops plugin", menu_loop_plugin_gpu_peops, h_gpu_peops), + mee_handler_h ("Configure gpu_unai_old GPU plugin", menu_loop_plugin_gpu_unai_old, h_gpu_unai_old), mee_handler_h ("Configure gpu_unai GPU plugin", menu_loop_plugin_gpu_unai, h_gpu_unai), mee_handler_h ("Configure gpu_gles GPU plugin", menu_loop_plugin_gpu_peopsgl, h_gpu_peopsgl), mee_handler_h ("Configure built-in SPU plugin", menu_loop_plugin_spu, h_spu), @@ -1298,29 +1610,37 @@ static int menu_loop_plugin_options(int id, int keys) // ------------ adv options menu ------------ -static const char h_cfg_psxclk[] = "Over/under-clock the PSX, default is " DEFAULT_PSX_CLOCK_S "\n" - "(lower value - less work for the emu, may be faster)"; +#ifndef DRC_DISABLE +static const char h_cfg_noch[] = "Disables game-specific compatibility hacks"; static const char h_cfg_nosmc[] = "Will cause crashes when loading, break memcards"; static const char h_cfg_gteunn[] = "May cause graphical glitches"; static const char h_cfg_gteflgs[] = "Will cause graphical glitches"; +#endif +static const char h_cfg_stalls[] = "Will cause some games to run too fast"; static menu_entry e_menu_speed_hacks[] = { - mee_range_h ("PSX CPU clock, %%", 0, psx_clock, 1, 500, h_cfg_psxclk), +#ifndef DRC_DISABLE + mee_onoff_h ("Disable compat hacks", 0, new_dynarec_hacks, NDHACK_NO_COMPAT_HACKS, h_cfg_noch), mee_onoff_h ("Disable SMC checks", 0, new_dynarec_hacks, NDHACK_NO_SMC_CHECK, h_cfg_nosmc), mee_onoff_h ("Assume GTE regs unneeded", 0, new_dynarec_hacks, NDHACK_GTE_UNNEEDED, h_cfg_gteunn), mee_onoff_h ("Disable GTE flags", 0, new_dynarec_hacks, NDHACK_GTE_NO_FLAGS, h_cfg_gteflgs), +#endif + mee_onoff_h ("Disable CPU/GTE stalls", 0, menu_iopts[0], 1, h_cfg_stalls), mee_end, }; static int menu_loop_speed_hacks(int id, int keys) { static int sel = 0; + menu_iopts[0] = Config.DisableStalls; me_loop(e_menu_speed_hacks, &sel); + Config.DisableStalls = menu_iopts[0]; return 0; } -static const char *men_cfg_cdrr[] = { "Auto", "ON", "OFF", NULL }; +static const char *men_autooo[] = { "Auto", "Off", "On", NULL }; + static const char h_cfg_cpul[] = "Shows CPU usage in %"; static const char h_cfg_spu[] = "Shows active SPU channels\n" "(green: normal, red: fmod, blue: noise)"; @@ -1328,31 +1648,38 @@ static const char h_cfg_fl[] = "Frame Limiter keeps the game from running to static const char h_cfg_xa[] = "Disables XA sound, which can sometimes improve performance"; static const char h_cfg_cdda[] = "Disable CD Audio for a performance boost\n" "(proper .cue/.bin dump is needed otherwise)"; -static const char h_cfg_sio[] = "You should not need this, breaks games"; -static const char h_cfg_spuirq[] = "Compatibility tweak; should be left off"; -static const char h_cfg_rcnt1[] = "Parasite Eve 2, Vandal Hearts 1/2 Fix\n" - "(timing hack, breaks other games)"; -static const char h_cfg_rcnt2[] = "InuYasha Sengoku Battle Fix\n" - "(timing hack, breaks other games)"; -static const char h_cfg_cdrr[] = "Compatibility tweak (CD timing hack, breaks FMVs)"; +#ifndef DRC_DISABLE static const char h_cfg_nodrc[] = "Disable dynamic recompiler and use interpreter\n" "Might be useful to overcome some dynarec bugs"; -static const char h_cfg_shacks[] = "Breaks games but may give better performance\n" - "must reload game for any change to take effect"; +#endif +static const char h_cfg_shacks[] = "Breaks games but may give better performance"; +static const char h_cfg_icache[] = "Support F1 games (only when dynarec is off)"; +static const char h_cfg_exc[] = "Emulate some PSX's debug hw like breakpoints\n" + "and exceptions (slow, interpreter only, keep off)"; +static const char h_cfg_gpul[] = "Try enabling this if the game misses some graphics\n" + "causes a performance hit"; +static const char h_cfg_ffps[] = "Instead of 50/60fps for PAL/NTSC use ~49.75/59.81\n" + "Closer to real hw but doesn't match modern displays."; +static const char h_cfg_psxclk[] = "Over/under-clock the PSX, default is " DEFAULT_PSX_CLOCK_S "\n" + "(adjust this if the game is too slow/too fast/hangs)"; + +enum { AMO_XA, AMO_CDDA, AMO_IC, AMO_BP, AMO_CPU, AMO_GPUL, AMO_FFPS }; static menu_entry e_menu_adv_options[] = { mee_onoff_h ("Show CPU load", 0, g_opts, OPT_SHOWCPU, h_cfg_cpul), mee_onoff_h ("Show SPU channels", 0, g_opts, OPT_SHOWSPU, h_cfg_spu), mee_onoff_h ("Disable Frame Limiter", 0, g_opts, OPT_NO_FRAMELIM, h_cfg_fl), - mee_onoff_h ("Disable XA Decoding", 0, Config.Xa, 1, h_cfg_xa), - mee_onoff_h ("Disable CD Audio", 0, Config.Cdda, 1, h_cfg_cdda), - mee_onoff_h ("SIO IRQ Always Enabled", 0, Config.Sio, 1, h_cfg_sio), - mee_onoff_h ("SPU IRQ Always Enabled", 0, Config.SpuIrq, 1, h_cfg_spuirq), - //mee_onoff_h ("Rootcounter hack", 0, Config.RCntFix, 1, h_cfg_rcnt1), - mee_onoff_h ("Rootcounter hack 2", 0, Config.VSyncWA, 1, h_cfg_rcnt2), - mee_enum_h ("CD read reschedule hack",0, Config.CdrReschedule, men_cfg_cdrr, h_cfg_cdrr), - mee_onoff_h ("Disable dynarec (slow!)",0, Config.Cpu, 1, h_cfg_nodrc), + mee_onoff_h ("Disable XA Decoding", 0, menu_iopts[AMO_XA], 1, h_cfg_xa), + mee_onoff_h ("Disable CD Audio", 0, menu_iopts[AMO_CDDA], 1, h_cfg_cdda), + mee_onoff_h ("ICache emulation", 0, menu_iopts[AMO_IC], 1, h_cfg_icache), + mee_onoff_h ("BP exception emulation", 0, menu_iopts[AMO_BP], 1, h_cfg_exc), + mee_enum_h ("GPU l-list slow walking",0, menu_iopts[AMO_GPUL], men_autooo, h_cfg_gpul), + mee_enum_h ("Fractional framerate", 0, menu_iopts[AMO_FFPS], men_autooo, h_cfg_ffps), +#if !defined(DRC_DISABLE) || defined(LIGHTREC) + mee_onoff_h ("Disable dynarec (slow!)",0, menu_iopts[AMO_CPU], 1, h_cfg_nodrc), +#endif + mee_range_h ("PSX CPU clock, %", 0, psx_clock, 1, 500, h_cfg_psxclk), mee_handler_h ("[Speed hacks]", menu_loop_speed_hacks, h_cfg_shacks), mee_end, }; @@ -1360,7 +1687,29 @@ static menu_entry e_menu_adv_options[] = static int menu_loop_adv_options(int id, int keys) { static int sel = 0; + static struct { + boolean *opt; + int *mopt; + } opts[] = { + { &Config.Xa, &menu_iopts[AMO_XA] }, + { &Config.Cdda, &menu_iopts[AMO_CDDA] }, + { &Config.icache_emulation, &menu_iopts[AMO_IC] }, + { &Config.PreciseExceptions, &menu_iopts[AMO_BP] }, + { &Config.Cpu, &menu_iopts[AMO_CPU] }, + }; + int i; + for (i = 0; i < ARRAY_SIZE(opts); i++) + *opts[i].mopt = *opts[i].opt; + menu_iopts[AMO_GPUL] = Config.GpuListWalking + 1; + menu_iopts[AMO_FFPS] = Config.FractionalFramerate + 1; + me_loop(e_menu_adv_options, &sel); + + for (i = 0; i < ARRAY_SIZE(opts); i++) + *opts[i].opt = *opts[i].mopt; + Config.GpuListWalking = menu_iopts[AMO_GPUL] - 1; + Config.FractionalFramerate = menu_iopts[AMO_FFPS] - 1; + return 0; } @@ -1369,7 +1718,7 @@ static int menu_loop_adv_options(int id, int keys) static int mh_restore_defaults(int id, int keys) { menu_set_defconfig(); - me_update_msg("defaults restored"); + menu_update_msg("defaults restored"); return 1; } @@ -1383,6 +1732,7 @@ static const char h_confirm_save[] = "Ask for confirmation when overwriting s static const char h_restore_def[] = "Switches back to default / recommended\n" "configuration"; static const char h_frameskip[] = "Warning: frameskip sometimes causes glitches\n"; +static const char h_sputhr[] = "Warning: has some known bugs\n"; static menu_entry e_menu_options[] = { @@ -1392,6 +1742,11 @@ static menu_entry e_menu_options[] = mee_onoff ("Show FPS", 0, g_opts, OPT_SHOWFPS), mee_enum ("Region", 0, region, men_region), mee_range ("CPU clock", MA_OPT_CPU_CLOCKS, cpu_clock, 20, 5000), +#ifdef C64X_DSP + mee_onoff_h ("Use C64x DSP for sound", MA_OPT_SPU_THREAD, spu_config.iUseThread, 1, h_sputhr), +#else + mee_onoff_h ("Threaded SPU", MA_OPT_SPU_THREAD, spu_config.iUseThread, 1, h_sputhr), +#endif mee_handler_id("[Display]", MA_OPT_DISP_OPTS, menu_loop_gfx_options), mee_handler ("[BIOS/Plugins]", menu_loop_plugin_options), mee_handler ("[Advanced]", menu_loop_adv_options), @@ -1404,10 +1759,9 @@ static menu_entry e_menu_options[] = static int menu_loop_options(int id, int keys) { static int sel = 0; - int i; - i = me_id2offset(e_menu_options, MA_OPT_CPU_CLOCKS); - e_menu_options[i].enabled = cpu_clock_st > 0 ? 1 : 0; + me_enable(e_menu_options, MA_OPT_CPU_CLOCKS, cpu_clock_st > 0); + me_enable(e_menu_options, MA_OPT_SPU_THREAD, spu_config.iThreadAvail); me_enable(e_menu_options, MA_OPT_SAVECFG_GAME, ready_to_go && CdromId[0]); me_loop(e_menu_options, &sel); @@ -1451,7 +1805,7 @@ static void debug_menu_loop(void) while (1) { - menu_draw_begin(0); + menu_draw_begin(0, 1); draw_frame_debug(gpuf, df_x, df_y); menu_draw_end(); @@ -1503,7 +1857,7 @@ static void draw_mc_bg(void) GetMcdBlockInfo(2, i + 1, &blocks2[i]); } - menu_draw_begin(1); + menu_draw_begin(1, 1); memcpy(g_menuscreen_ptr, g_menubg_src_ptr, g_menuscreen_w * g_menuscreen_h * 2); @@ -1533,10 +1887,10 @@ out: static void handle_memcard_sel(void) { - Config.Mcd1[0] = 0; + strcpy(Config.Mcd1, "none"); if (memcard1_sel != 0) snprintf(Config.Mcd1, sizeof(Config.Mcd1), ".%s%s", MEMCARD_DIR, memcards[memcard1_sel]); - Config.Mcd2[0] = 0; + strcpy(Config.Mcd2, "none"); if (memcard2_sel != 0) snprintf(Config.Mcd2, sizeof(Config.Mcd2), ".%s%s", MEMCARD_DIR, memcards[memcard2_sel]); LoadMcds(Config.Mcd1, Config.Mcd2); @@ -1584,7 +1938,7 @@ static void draw_cheatlist(int sel) max_cnt = g_menuscreen_h / me_sfont_h; start = max_cnt / 2 - sel; - menu_draw_begin(1); + menu_draw_begin(1, 1); for (i = 0; i < NumCheats; i++) { pos = start + i; @@ -1636,11 +1990,8 @@ static void menu_bios_warn(void) static const char msg[] = "You don't seem to have copied any BIOS\n" "files to\n" -#ifdef __ARM_ARCH_7A__ // XXX - "/pandora/appdata/pcsx_rearmed/bios/\n\n" -#else - "pcsx_rearmed/bios/\n\n" -#endif + MENU_BIOS_PATH "\n\n" + "While many games work fine with fake\n" "(HLE) BIOS, others (like MGS and FF8)\n" "require BIOS to work.\n" @@ -1668,7 +2019,6 @@ static void menu_bios_warn(void) // ------------ main menu ------------ static menu_entry e_menu_main[]; -void OnFile_Exit(); static void draw_frame_main(void) { @@ -1687,7 +2037,7 @@ static void draw_frame_main(void) } if (ready_to_go) { - capacity = plat_get_bat_capacity(); + capacity = plat_target_bat_capacity_get(); ltime = time(NULL); tmp = localtime(<ime); strftime(ltime_s, sizeof(ltime_s), "%H:%M", tmp); @@ -1712,7 +2062,7 @@ static const char credits_text[] = "(C) 2005-2009 PCSX-df Team\n" "(C) 2009-2011 PCSX-Reloaded Team\n\n" "ARM recompiler (C) 2009-2011 Ari64\n" -#ifdef __ARM_NEON__ +#ifdef BUILTIN_GPU_NEON "ARM NEON GPU (c) 2011-2012 Exophase\n" #endif "PEOpS GPU and SPU by Pete Bernert\n" @@ -1720,19 +2070,16 @@ static const char credits_text[] = "PCSX4ALL plugin by PCSX4ALL team\n" " Chui, Franxis, Unai\n\n" "integration, optimization and\n" - " frontend (C) 2010-2012 notaz\n"; + " frontend (C) 2010-2015 notaz\n"; static int reset_game(void) { - // sanity check - if (bios_sel == 0 && !Config.HLE) - return -1; - ClosePlugins(); OpenPlugins(); SysReset(); - if (CheckCdrom() != -1) { - LoadCdrom(); + if (Config.HLE) { + if (LoadCdrom() == -1) + return -1; } return 0; } @@ -1748,7 +2095,7 @@ static int reload_plugins(const char *cdimg) pcnt_hook_plugins(); NetOpened = 0; if (OpenPlugins() == -1) { - me_update_msg("failed to open plugins"); + menu_update_msg("failed to open plugins"); return -1; } plugin_call_rearmed_cbs(); @@ -1762,13 +2109,17 @@ static int reload_plugins(const char *cdimg) static int run_bios(void) { + boolean origSlowBoot = Config.SlowBoot; + if (bios_sel == 0) return -1; ready_to_go = 0; if (reload_plugins(NULL) != 0) return -1; + Config.SlowBoot = 1; SysReset(); + Config.SlowBoot = origSlowBoot; ready_to_go = 1; return 0; @@ -1776,9 +2127,11 @@ static int run_bios(void) static int run_exe(void) { + const char *exts[] = { "exe", NULL }; const char *fname; - fname = menu_loop_romsel(last_selected_fname, sizeof(last_selected_fname)); + fname = menu_loop_romsel(last_selected_fname, + sizeof(last_selected_fname), exts, NULL); if (fname == NULL) return -1; @@ -1788,7 +2141,7 @@ static int run_exe(void) SysReset(); if (Load(fname) != 0) { - me_update_msg("exe load failed, bad file?"); + menu_update_msg("exe load failed, bad file?"); printf("meh\n"); return -1; } @@ -1799,6 +2152,8 @@ static int run_exe(void) static int run_cd_image(const char *fname) { + int autoload_state = g_autostateld_opt; + ready_to_go = 0; reload_plugins(fname); @@ -1808,7 +2163,7 @@ static int run_cd_image(const char *fname) if (CheckCdrom() == -1) { // Only check the CD if we are starting the console with a CD ClosePlugins(); - me_update_msg("unsupported/invalid CD image"); + menu_update_msg("unsupported/invalid CD image"); return -1; } @@ -1817,13 +2172,35 @@ static int run_cd_image(const char *fname) // Read main executable directly from CDRom and start it if (LoadCdrom() == -1) { ClosePlugins(); - me_update_msg("failed to load CD image"); + menu_update_msg("failed to load CD image"); return -1; } - emu_on_new_cd(); + emu_on_new_cd(1); ready_to_go = 1; + if (autoload_state) { + unsigned int newest = 0; + int time, slot, newest_slot = -1; + + for (slot = 0; slot < 10; slot++) { + if (emu_check_save_file(slot, &time)) { + if ((unsigned int)time > newest) { + newest = time; + newest_slot = slot; + } + } + } + + if (newest_slot >= 0) { + lprintf("autoload slot %d\n", newest_slot); + emu_load_state(newest_slot); + } + else { + lprintf("no save to autoload.\n"); + } + } + return 0; } @@ -1832,7 +2209,9 @@ static int romsel_run(void) int prev_gpu, prev_spu; const char *fname; - fname = menu_loop_romsel(last_selected_fname, sizeof(last_selected_fname)); + fname = menu_loop_romsel(last_selected_fname, + sizeof(last_selected_fname), filter_exts, + optional_cdimg_filter); if (fname == NULL) return -1; @@ -1856,16 +2235,18 @@ static int romsel_run(void) return -1; } - strcpy(last_selected_fname, rom_fname_reload); + strcpy(last_selected_fname, fname); menu_do_last_cd_img(0); return 0; } static int swap_cd_image(void) { - char *fname; + const char *fname; - fname = menu_loop_romsel(last_selected_fname, sizeof(last_selected_fname)); + fname = menu_loop_romsel(last_selected_fname, + sizeof(last_selected_fname), filter_exts, + optional_cdimg_filter); if (fname == NULL) return -1; @@ -1876,18 +2257,18 @@ static int swap_cd_image(void) set_cd_image(fname); if (ReloadCdromPlugin() < 0) { - me_update_msg("failed to load cdr plugin"); + menu_update_msg("failed to load cdr plugin"); return -1; } if (CDR_open() < 0) { - me_update_msg("failed to open cdr plugin"); + menu_update_msg("failed to open cdr plugin"); return -1; } SetCdOpenCaseTime(time(NULL) + 2); LidInterrupt(); - strcpy(last_selected_fname, rom_fname_reload); + strcpy(last_selected_fname, fname); return 0; } @@ -1899,7 +2280,7 @@ static int swap_cd_multidisk(void) CDR_close(); if (CDR_open() < 0) { - me_update_msg("failed to open cdr plugin"); + menu_update_msg("failed to open cdr plugin"); return -1; } @@ -1911,11 +2292,12 @@ static int swap_cd_multidisk(void) static void load_pcsx_cht(void) { - char path[256]; - char *fname; + static const char *exts[] = { "cht", NULL }; + const char *fname; + char msg[64]; - path[0] = 0; - fname = menu_loop_romsel(path, sizeof(path)); + fname = menu_loop_romsel(last_selected_fname, + sizeof(last_selected_fname), exts, NULL); if (fname == NULL) return; @@ -1923,10 +2305,10 @@ static void load_pcsx_cht(void) LoadCheats(fname); if (NumCheats == 0 && NumCodes == 0) - me_update_msg("failed to load cheats"); + menu_update_msg("failed to load cheats"); else { - snprintf(path, sizeof(path), "%d cheat(s) loaded", NumCheats + NumCodes); - me_update_msg(path); + snprintf(msg, sizeof(msg), "%d cheat(s) loaded", NumCheats + NumCodes); + menu_update_msg(msg); } me_enable(e_menu_main, MA_MAIN_CHEATS, ready_to_go && NumCheats); } @@ -1982,8 +2364,8 @@ static int main_menu_handler(int id, int keys) in_menu_wait(PBTN_MOK|PBTN_MBACK, NULL, 70); break; case MA_MAIN_EXIT: - OnFile_Exit(); - break; + emu_core_ask_exit(); + return 1; default: lprintf("%s: something unknown selected\n", __FUNCTION__); break; @@ -2041,13 +2423,22 @@ static void menu_leave_emu(void); void menu_loop(void) { + static int warned_about_bios = 0; static int sel = 0; menu_leave_emu(); - if (bioses[1] == NULL && !warned_about_bios) { - menu_bios_warn(); - warned_about_bios = 1; + if (config_save_counter == 0) { + // assume first run + if (bioses[1] != NULL) { + // autoselect BIOS to make user's life easier + snprintf(Config.Bios, sizeof(Config.Bios), "%s", bioses[1]); + bios_sel = 1; + } + else if (!warned_about_bios) { + menu_bios_warn(); + warned_about_bios = 1; + } } me_enable(e_menu_main, MA_MAIN_RESUME_GAME, ready_to_go); @@ -2060,7 +2451,7 @@ void menu_loop(void) do { me_loop_d(e_menu_main, &sel, NULL, draw_frame_main); - } while (!ready_to_go); + } while (!ready_to_go && !g_emu_want_quit); /* wait until menu, ok, back is released */ while (in_menu_wait_any(NULL, 50) & (PBTN_MENU|PBTN_MOK|PBTN_MBACK)) @@ -2114,7 +2505,8 @@ static void scan_bios_plugins(void) continue; snprintf(fname, sizeof(fname), "%s/%s", Config.BiosDir, ent->d_name); - if (stat(fname, &st) != 0 || st.st_size != 512*1024) { + if (stat(fname, &st) != 0 + || (st.st_size != 512*1024 && st.st_size != 4*1024*1024)) { printf("bad BIOS file: %s\n", ent->d_name); continue; } @@ -2225,13 +2617,12 @@ do_memcards: void menu_init(void) { char buff[MAXPATHLEN]; + int i; - strcpy(last_selected_fname, "/media"); - - cpu_clock_st = cpu_clock = plat_cpu_clock_get(); + cpu_clock_st = cpu_clock = plat_target_cpu_clock_get(); scan_bios_plugins(); - menu_init_common(); + menu_init_base(); menu_set_defconfig(); menu_load_config(0); @@ -2250,16 +2641,33 @@ void menu_init(void) emu_make_path(buff, "skin/background.png", sizeof(buff)); readpng(g_menubg_src_ptr, buff, READPNG_BG, g_menuscreen_w, g_menuscreen_h); -#ifndef __ARM_ARCH_7A__ /* XXX */ - me_enable(e_menu_gfx_options, MA_OPT_SCALER, 0); - me_enable(e_menu_gfx_options, MA_OPT_FILTERING, 0); - me_enable(e_menu_gfx_options, MA_OPT_SCALER_C, 0); - me_enable(e_menu_keyconfig, MA_CTRL_NUBS_BTNS, 0); -#else - me_enable(e_menu_gfx_options, MA_OPT_SCALER2, 0); - me_enable(e_menu_keyconfig, MA_CTRL_VIBRATION, 0); - me_enable(e_menu_keyconfig, MA_CTRL_DEADZONE, 0); + i = plat_target.cpu_clock_set != NULL + && plat_target.cpu_clock_get != NULL && cpu_clock_st > 0; + me_enable(e_menu_options, MA_OPT_CPU_CLOCKS, i); + + i = me_id2offset(e_menu_gfx_options, MA_OPT_VOUT_MODE); + e_menu_gfx_options[i].data = plat_target.vout_methods; + me_enable(e_menu_gfx_options, MA_OPT_VOUT_MODE, + plat_target.vout_methods != NULL); + + i = me_id2offset(e_menu_gfx_options, MA_OPT_HWFILTER); + e_menu_gfx_options[i].data = plat_target.hwfilters; + me_enable(e_menu_gfx_options, MA_OPT_HWFILTER, + plat_target.hwfilters != NULL); + + me_enable(e_menu_gfx_options, MA_OPT_GAMMA, + plat_target.gamma_set != NULL); + +#ifdef HAVE_PRE_ARMV7 + me_enable(e_menu_gfx_options, MA_OPT_SWFILTER, 0); #endif + me_enable(e_menu_gfx_options, MA_OPT_VARSCALER, MENU_SHOW_VARSCALER); + me_enable(e_menu_gfx_options, MA_OPT_VOUT_MODE, MENU_SHOW_VOUTMODE); + me_enable(e_menu_gfx_options, MA_OPT_VARSCALER_C, MENU_SHOW_VARSCALER); + me_enable(e_menu_gfx_options, MA_OPT_SCALER2, MENU_SHOW_SCALER2); + me_enable(e_menu_keyconfig, MA_CTRL_NUBS_BTNS, MENU_SHOW_NUBS_BTNS); + me_enable(e_menu_keyconfig, MA_CTRL_VIBRATION, MENU_SHOW_VIBRATION); + me_enable(e_menu_keyconfig, MA_CTRL_DEADZONE, MENU_SHOW_DEADZONE); } void menu_notify_mode_change(int w, int h, int bpp) @@ -2301,7 +2709,7 @@ static void menu_leave_emu(void) } if (ready_to_go) - cpu_clock = plat_cpu_clock_get(); + cpu_clock = plat_target_cpu_clock_get(); } void menu_prepare_emu(void) @@ -2310,19 +2718,29 @@ void menu_prepare_emu(void) plat_video_menu_leave(); + #if !defined(DRC_DISABLE) || defined(LIGHTREC) psxCpu = (Config.Cpu == CPU_INTERPRETER) ? &psxInt : &psxRec; - if (psxCpu != prev_cpu) - // note that this does not really reset, just clears drc caches + #else + psxCpu = &psxInt; + #endif + if (psxCpu != prev_cpu) { + prev_cpu->Notify(R3000ACPU_NOTIFY_BEFORE_SAVE, NULL); + prev_cpu->Shutdown(); + psxCpu->Init(); psxCpu->Reset(); + psxCpu->Notify(R3000ACPU_NOTIFY_AFTER_LOAD, NULL); + } + + menu_sync_config(); + psxCpu->ApplyConfig(); // core doesn't care about Config.Cdda changes, // so handle them manually here if (Config.Cdda) CDR_stop(); - menu_sync_config(); if (cpu_clock > 0) - plat_cpu_clock_apply(cpu_clock); + plat_target_cpu_clock_set(cpu_clock); // push config to GPU plugin plugin_call_rearmed_cbs(); @@ -2332,11 +2750,9 @@ void menu_prepare_emu(void) if (ret) fprintf(stderr, "Warning: GPU_open returned %d\n", ret); } - - dfinput_activate(); } -void me_update_msg(const char *msg) +void menu_update_msg(const char *msg) { strncpy(menu_error_msg, msg, sizeof(menu_error_msg)); menu_error_msg[sizeof(menu_error_msg) - 1] = 0; @@ -2347,5 +2763,6 @@ void me_update_msg(const char *msg) void menu_finish(void) { - plat_cpu_clock_apply(cpu_clock_st); + if (cpu_clock_st > 0) + plat_target_cpu_clock_set(cpu_clock_st); }