release r13
[pcsx_rearmed.git] / frontend / menu.c
index cfdc62d..a8d2e48 100644 (file)
@@ -13,6 +13,9 @@
 #include <errno.h>
 #include <dlfcn.h>
 #include <zlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
 
 #include "main.h"
 #include "menu.h"
 #include "linux/in_evdev.h"
 #include "../libpcsxcore/misc.h"
 #include "../libpcsxcore/cdrom.h"
+#include "../libpcsxcore/cdriso.h"
 #include "../libpcsxcore/psemu_plugin_defs.h"
 #include "../libpcsxcore/new_dynarec/new_dynarec.h"
 #include "../plugins/dfinput/main.h"
 #include "revision.h"
 
+#define REARMED_BIRTHDAY_TIME 1293306830       /* 25 Dec 2010 */
+
 #define array_size(x) (sizeof(x) / sizeof(x[0]))
 
 typedef enum
@@ -44,6 +50,7 @@ typedef enum
        MA_MAIN_RESET_GAME,
        MA_MAIN_LOAD_ROM,
        MA_MAIN_SWAP_CD,
+       MA_MAIN_SWAP_CD_MULTI,
        MA_MAIN_RUN_BIOS,
        MA_MAIN_RUN_EXE,
        MA_MAIN_CONTROLS,
@@ -51,11 +58,13 @@ typedef enum
        MA_MAIN_EXIT,
        MA_CTRL_PLAYER1,
        MA_CTRL_PLAYER2,
+       MA_CTRL_ANALOG,
        MA_CTRL_EMU,
        MA_CTRL_DEV_FIRST,
        MA_CTRL_DEV_NEXT,
        MA_CTRL_NUBS_BTNS,
        MA_CTRL_DEADZONE,
+       MA_CTRL_VIBRATION,
        MA_CTRL_DONE,
        MA_OPT_SAVECFG,
        MA_OPT_SAVECFG_GAME,
@@ -120,10 +129,30 @@ void emu_make_path(char *buff, const char *end, int size)
                printf("Warning: path truncated: %s\n", buff);
 }
 
-static int emu_check_save_file(int slot)
+static int emu_check_save_file(int slot, int *time)
 {
-       int ret = emu_check_state(slot);
-       return ret == 0 ? 1 : 0;
+       char fname[MAXPATHLEN];
+       struct stat status;
+       int ret;
+       
+       ret = emu_check_state(slot);
+       if (ret != 0 || time == NULL)
+               return ret == 0 ? 1 : 0;
+
+       ret = get_state_filename(fname, sizeof(fname), slot);
+       if (ret != 0)
+               return 1;
+
+       ret = stat(fname, &status);
+       if (ret != 0)
+               return 1;
+
+       if (status.st_mtime < REARMED_BIRTHDAY_TIME)
+               return 1; // probably bad rtc like on some Caanoos
+
+       *time = status.st_mtime;
+
+       return 1;
 }
 
 static int emu_save_load_game(int load, int unused)
@@ -169,7 +198,7 @@ static void menu_sync_config(void)
        default: in_type2 = PSE_PAD_TYPE_STANDARD;
        }
        if (in_evdev_allow_abs_only != allow_abs_only_old) {
-               plat_rescan_inputs();
+               in_probe();
                allow_abs_only_old = in_evdev_allow_abs_only;
        }
 
@@ -212,6 +241,9 @@ static void menu_set_defconfig(void)
        { #val, sizeof(pl_rearmed_cbs.val), &pl_rearmed_cbs.val }
 
 // 'versioned' var, used when defaults change
+#define CE_CONFIG_STR_V(val, ver) \
+       { #val #ver, 0, Config.val }
+
 #define CE_INTVAL_V(val, ver) \
        { #val #ver, sizeof(val), &val }
 
@@ -224,7 +256,7 @@ static const struct {
        void *val;
 } config_data[] = {
        CE_CONFIG_STR(Bios),
-       CE_CONFIG_STR(Gpu),
+       CE_CONFIG_STR_V(Gpu, 2),
        CE_CONFIG_STR(Spu),
 //     CE_CONFIG_STR(Cdr),
        CE_CONFIG_VAL(Xa),
@@ -251,12 +283,14 @@ static const struct {
        CE_INTVAL(in_type_sel1),
        CE_INTVAL(in_type_sel2),
        CE_INTVAL(analog_deadzone),
-       CE_INTVAL_V(frameskip, 2),
+       CE_INTVAL_V(frameskip, 3),
        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_neon.allow_interlace),
        CE_INTVAL_V(iUseReverb, 3),
        CE_INTVAL_V(iXAPitch, 3),
        CE_INTVAL_V(iUseInterpolation, 3),
@@ -267,6 +301,7 @@ static const struct {
        CE_INTVAL(volume_boost),
        CE_INTVAL(psx_clock),
        CE_INTVAL(new_dynarec_hacks),
+       CE_INTVAL(in_enable_vibration),
 };
 
 static char *get_cd_label(void)
@@ -721,6 +756,9 @@ me_bind_action emuctrl_actions[] =
        { "Toggle Frameskip ", 1 << SACTION_TOGGLE_FSKIP },
        { "Take Screenshot  ", 1 << SACTION_SCREENSHOT },
        { "Enter Menu       ", 1 << SACTION_ENTER_MENU },
+#ifdef __ARM_ARCH_7A__ /* XXX */
+       { "Minimize         ", 1 << SACTION_MINIMIZE },
+#endif
        { "Gun Trigger      ", 1 << SACTION_GUN_TRIGGER },
        { "Gun A button     ", 1 << SACTION_GUN_A },
        { "Gun B button     ", 1 << SACTION_GUN_B },
@@ -815,6 +853,12 @@ static void keys_write_all(FILE *f)
                                }
                        }
                }
+
+               for (k = 0; k < array_size(in_adev); k++)
+               {
+                       if (in_adev[k] == d)
+                               fprintf(f, "bind_analog = %d\n", k);
+               }
        }
 }
 
@@ -857,7 +901,7 @@ static void keys_load_all(const char *cfg)
        char dev[256], key[128], *act;
        const char *p;
        int bind, bindtype;
-       int dev_id;
+       int ret, dev_id;
 
        p = cfg;
        while (p != NULL && (p = strstr(p, "binddev = ")) != NULL) {
@@ -875,6 +919,21 @@ static void keys_load_all(const char *cfg)
                        if (strncmp(p, "binddev = ", 10) == 0)
                                break;
 
+                       if (strncmp(p, "bind_analog", 11) == 0) {
+                               ret = sscanf(p, "bind_analog = %d", &bind);
+                               p += 11;
+                               if (ret != 1) {
+                                       printf("input: parse error: %16s..\n", p);
+                                       continue;
+                               }
+                               if ((unsigned int)bind >= array_size(in_adev)) {
+                                       printf("input: analog id %d out of range\n", bind);
+                                       continue;
+                               }
+                               in_adev[bind] = dev_id;
+                               continue;
+                       }
+
                        p += 4;
                        if (*p != ' ') {
                                printf("input: parse error: %16s..\n", p);
@@ -922,6 +981,57 @@ static int key_config_loop_wrap(int id, int keys)
        return 0;
 }
 
+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_end,
+};
+
+static int key_config_analog(int id, int keys)
+{
+       int i, d, count, sel = 0;
+       int sel2dev_map[IN_MAX_DEVS];
+
+       memset(adevnames, 0, sizeof(adevnames));
+       memset(sel2dev_map, 0xff, sizeof(sel2dev_map));
+       memset(stick_sel, 0, sizeof(stick_sel));
+
+       adevnames[0] = "None";
+       i = 1;
+       for (d = 0; d < IN_MAX_DEVS; d++)
+       {
+               const char *name = in_get_dev_name(d, 0, 1);
+               if (name == NULL)
+                       continue;
+
+               count = 0;
+               in_get_config(d, IN_CFG_ABS_AXIS_COUNT, &count);
+               if (count == 0)
+                       continue;
+
+               if (in_adev[0] == d) stick_sel[0] = i;
+               if (in_adev[1] == d) stick_sel[1] = i;
+               sel2dev_map[i] = d;
+               adevnames[i++] = name;
+       }
+       adevnames[i] = NULL;
+
+       me_loop(e_menu_keyconfig_analog, &sel);
+
+       in_adev[0] = sel2dev_map[stick_sel[0]];
+       in_adev[1] = sel2dev_map[stick_sel[1]];
+
+       return 0;
+}
+
 static const char *mgn_dev_name(int id, int *offs)
 {
        const char *name = NULL;
@@ -958,7 +1068,7 @@ static int mh_savecfg(int id, int keys)
 static int mh_input_rescan(int id, int keys)
 {
        //menu_sync_config();
-       plat_rescan_inputs();
+       in_probe();
        me_update_msg("rescan complete.");
 
        return 0;
@@ -971,24 +1081,26 @@ static const char *men_in_type_sel[] = {
        NULL
 };
 static const char h_nub_btns[] = "Experimental, keep this OFF if unsure. Select rescan after change.";
-static const char h_notsgun[] =  "Don't trigger (shoot) when touching screen in gun games.";
+static const char h_notsgun[]  = "Don't trigger (shoot) when touching screen in gun games.";
+static const char h_vibration[]= "Must select analog above and enable this ingame too.";
 
 static menu_entry e_menu_keyconfig[] =
 {
        mee_handler_id("Player 1",              MA_CTRL_PLAYER1,    key_config_loop_wrap),
        mee_handler_id("Player 2",              MA_CTRL_PLAYER2,    key_config_loop_wrap),
+       mee_handler_id("Analog controls",       MA_CTRL_ANALOG,     key_config_analog),
        mee_handler_id("Emulator/Gun controls", MA_CTRL_EMU,        key_config_loop_wrap),
        mee_label     (""),
        mee_enum      ("Port 1 device",     0, in_type_sel1,    men_in_type_sel),
        mee_enum      ("Port 2 device",     0, in_type_sel2,    men_in_type_sel),
        mee_onoff_h   ("Nubs as buttons",   MA_CTRL_NUBS_BTNS,  in_evdev_allow_abs_only, 1, h_nub_btns),
+       mee_onoff_h   ("Vibration",         MA_CTRL_VIBRATION,  in_enable_vibration, 1, h_vibration),
        mee_range     ("Analog deadzone",   MA_CTRL_DEADZONE,   analog_deadzone, 1, 99),
        mee_onoff_h   ("No TS Gun trigger", 0, g_opts, OPT_TSGUN_NOTRIGGER, h_notsgun),
        mee_cust_nosave("Save global config",       MA_OPT_SAVECFG,      mh_savecfg, mgn_saveloadcfg),
        mee_cust_nosave("Save cfg for loaded game", MA_OPT_SAVECFG_GAME, mh_savecfg, mgn_saveloadcfg),
-       mee_handler   ("Rescan devices",  mh_input_rescan),
+       mee_handler   ("Rescan devices:",  mh_input_rescan),
        mee_label     (""),
-       mee_label     ("Input devices:"),
        mee_label_mk  (MA_CTRL_DEV_FIRST, mgn_dev_name),
        mee_label_mk  (MA_CTRL_DEV_NEXT,  mgn_dev_name),
        mee_label_mk  (MA_CTRL_DEV_NEXT,  mgn_dev_name),
@@ -1085,8 +1197,29 @@ static int menu_loop_gfx_options(int id, int keys)
 
 // ------------ bios/plugins ------------
 
+#ifdef __ARM_NEON__
+
+static const char h_gpu_neon[] = "Configure built-in NEON GPU plugin";
+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_end,
+};
+
+static int menu_loop_plugin_gpu_neon(int id, int keys)
+{
+       int sel = 0;
+       me_loop(e_menu_plugin_gpu_neon, &sel);
+       return 0;
+}
+
+#endif
+
 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),
@@ -1101,12 +1234,12 @@ static int menu_loop_plugin_gpu_unai(int id, int keys)
 }
 
 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_0[]            = "Needed for Chrono Cross";
 static const char h_gpu_1[]            = "Capcom fighting games";
 static const char h_gpu_2[]            = "Black screens in Lunar";
 static const char h_gpu_3[]            = "Compatibility mode";
 static const char h_gpu_6[]            = "Pandemonium 2";
-static const char h_gpu_7[]            = "Skip every second frame";
+//static const char h_gpu_7[]            = "Skip every second frame";
 static const char h_gpu_8[]            = "Needed by Dark Forces";
 static const char h_gpu_9[]            = "better g-colors, worse textures";
 static const char h_gpu_10[]           = "Toggle busy flags after drawing";
@@ -1114,12 +1247,12 @@ static const char h_gpu_10[]           = "Toggle busy flags after drawing";
 static menu_entry e_menu_plugin_gpu_peops[] =
 {
        mee_enum      ("Dithering",                  0, pl_rearmed_cbs.gpu_peops.iUseDither, men_gpu_dithering),
-       mee_onoff_h   ("Odd/even bit hack",          0, pl_rearmed_cbs.gpu_peops.dwActFixes, 1<<0, h_gpu_0),
+//     mee_onoff_h   ("Odd/even bit hack",          0, pl_rearmed_cbs.gpu_peops.dwActFixes, 1<<0, h_gpu_0),
        mee_onoff_h   ("Expand screen width",        0, pl_rearmed_cbs.gpu_peops.dwActFixes, 1<<1, h_gpu_1),
        mee_onoff_h   ("Ignore brightness color",    0, pl_rearmed_cbs.gpu_peops.dwActFixes, 1<<2, h_gpu_2),
        mee_onoff_h   ("Disable coordinate check",   0, pl_rearmed_cbs.gpu_peops.dwActFixes, 1<<3, h_gpu_3),
        mee_onoff_h   ("Lazy screen update",         0, pl_rearmed_cbs.gpu_peops.dwActFixes, 1<<6, h_gpu_6),
-       mee_onoff_h   ("Old frame skipping",         0, pl_rearmed_cbs.gpu_peops.dwActFixes, 1<<7, h_gpu_7),
+//     mee_onoff_h   ("Old frame skipping",         0, pl_rearmed_cbs.gpu_peops.dwActFixes, 1<<7, h_gpu_7),
        mee_onoff_h   ("Repeated flat tex triangles ",0,pl_rearmed_cbs.gpu_peops.dwActFixes, 1<<8, h_gpu_8),
        mee_onoff_h   ("Draw quads with triangles",  0, pl_rearmed_cbs.gpu_peops.dwActFixes, 1<<9, h_gpu_9),
        mee_onoff_h   ("Fake 'gpu busy' states",     0, pl_rearmed_cbs.gpu_peops.dwActFixes, 1<<10, h_gpu_10),
@@ -1170,6 +1303,9 @@ 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_xpu),
        mee_enum_h    ("SPU plugin",                    0, spu_plugsel, spu_plugins, h_plugin_xpu),
+#ifdef __ARM_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 PCSX4ALL GPU plugin", menu_loop_plugin_gpu_unai, h_gpu_unai),
        mee_handler_h ("Configure built-in SPU plugin", menu_loop_plugin_spu, h_spu),
@@ -1269,7 +1405,7 @@ static int mh_restore_defaults(int id, int keys)
 }
 
 static const char *men_region[]       = { "Auto", "NTSC", "PAL", NULL };
-static const char *men_frameskip[]    = { "Auto", "Off", "1", NULL };
+static const char *men_frameskip[]    = { "Auto", "Off", "1", "2", "3", NULL };
 /*
 static const char *men_confirm_save[] = { "OFF", "writes", "loads", "both", NULL };
 static const char h_confirm_save[]    = "Ask for confirmation when overwriting save,\n"
@@ -1530,7 +1666,7 @@ static void draw_frame_main(void)
 
 static void draw_frame_credits(void)
 {
-       smalltext_out16(4, 1, "build: "__DATE__ " " __TIME__ " " REV, 0xe7fc);
+       smalltext_out16(4, 1, "build: " __DATE__ " " __TIME__ " " REV, 0xe7fc);
 }
 
 static const char credits_text[] = 
@@ -1538,13 +1674,16 @@ static const char credits_text[] =
        "(C) 1999-2003 PCSX Team\n"
        "(C) 2005-2009 PCSX-df Team\n"
        "(C) 2009-2011 PCSX-Reloaded Team\n\n"
-       "GPU and SPU code by Pete Bernert\n"
-       "  and the P.E.Op.S. team\n"
        "ARM recompiler (C) 2009-2011 Ari64\n"
-       "PCSX4ALL plugins by PCSX4ALL team\n"
+#ifdef __ARM_NEON__
+       "ARM NEON GPU (c) 2011-2012 Exophase\n"
+#endif
+       "PEOpS GPU and SPU by Pete Bernert\n"
+       "  and the P.E.Op.S. team\n"
+       "PCSX4ALL plugin by PCSX4ALL team\n"
        "  Chui, Franxis, Unai\n\n"
        "integration, optimization and\n"
-       "  frontend (C) 2010-2011 notaz\n";
+       "  frontend (C) 2010-2012 notaz\n";
 
 static int reset_game(void)
 {
@@ -1577,6 +1716,7 @@ static int reload_plugins(const char *cdimg)
        }
        plugin_call_rearmed_cbs();
 
+       cdrIsoMultidiskCount = 1;
        CdromId[0] = '\0';
        CdromLabel[0] = '\0';
 
@@ -1645,6 +1785,8 @@ static int run_cd_image(const char *fname)
        }
 
        ready_to_go = 1;
+       snprintf(hud_msg, sizeof(hud_msg), "Booting up...");
+       hud_new_msg = 2;
        return 0;
 }
 
@@ -1714,6 +1856,24 @@ static int swap_cd_image(void)
        return 0;
 }
 
+static int swap_cd_multidisk(void)
+{
+       cdrIsoMultidiskSelect++;
+       CdromId[0] = '\0';
+       CdromLabel[0] = '\0';
+
+       CDR_close();
+       if (CDR_open() < 0) {
+               me_update_msg("failed to open cdr plugin");
+               return -1;
+       }
+
+       SetCdOpenCaseTime(time(NULL) + 2);
+       LidInterrupt();
+
+       return 0;
+}
+
 static int main_menu_handler(int id, int keys)
 {
        switch (id)
@@ -1742,6 +1902,10 @@ static int main_menu_handler(int id, int keys)
                if (swap_cd_image() == 0)
                        return 1;
                break;
+       case MA_MAIN_SWAP_CD_MULTI:
+               if (swap_cd_multidisk() == 0)
+                       return 1;
+               break;
        case MA_MAIN_RUN_BIOS:
                if (run_bios() == 0)
                        return 1;
@@ -1767,9 +1931,10 @@ static int main_menu_handler(int id, int keys)
 
 static menu_entry e_menu_main2[] =
 {
-       mee_handler_id("Change CD image",    MA_MAIN_SWAP_CD,     main_menu_handler),
-       mee_handler_id("Run BIOS",           MA_MAIN_RUN_BIOS,    main_menu_handler),
-       mee_handler_id("Run EXE",            MA_MAIN_RUN_EXE,     main_menu_handler),
+       mee_handler_id("Change CD image",    MA_MAIN_SWAP_CD,       main_menu_handler),
+       mee_handler_id("Next multidisk CD",  MA_MAIN_SWAP_CD_MULTI, main_menu_handler),
+       mee_handler_id("Run BIOS",           MA_MAIN_RUN_BIOS,      main_menu_handler),
+       mee_handler_id("Run EXE",            MA_MAIN_RUN_EXE,       main_menu_handler),
        mee_handler   ("Memcard manager",    menu_loop_memcards),
        mee_end,
 };
@@ -1779,6 +1944,7 @@ static int main_menu2_handler(int id, int keys)
        static int sel = 0;
 
        me_enable(e_menu_main2, MA_MAIN_SWAP_CD,  ready_to_go);
+       me_enable(e_menu_main2, MA_MAIN_SWAP_CD_MULTI, ready_to_go && cdrIsoMultidiskCount > 1);
        me_enable(e_menu_main2, MA_MAIN_RUN_BIOS, bios_sel != 0);
 
        return me_loop_d(e_menu_main2, &sel, NULL, draw_frame_main);
@@ -2015,6 +2181,7 @@ void menu_init(void)
        me_enable(e_menu_options, MA_OPT_DISP_OPTS, 0);
        me_enable(e_menu_keyconfig, MA_CTRL_NUBS_BTNS, 0);
 #else
+       me_enable(e_menu_keyconfig, MA_CTRL_VIBRATION, 0);
        me_enable(e_menu_keyconfig, MA_CTRL_DEADZONE, 0);
 #endif
 }