X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?p=fceu.git;a=blobdiff_plain;f=drivers%2Fcommon%2Fmenu.c;fp=drivers%2Fcommon%2Fmenu.c;h=5fe0cfc4b0c3cebd48b656149b66e016673039fd;hp=0000000000000000000000000000000000000000;hb=4a2a617ac879a95babe3b8a822188b71e9769ba4;hpb=396c448eb538587248ddbf586a90371c71b48183 diff --git a/drivers/common/menu.c b/drivers/common/menu.c new file mode 100644 index 0000000..5fe0cfc --- /dev/null +++ b/drivers/common/menu.c @@ -0,0 +1,649 @@ +/* + * (C) Gražvydas "notaz" Ignotas, 2010-2011 + * + * This work is licensed under the terms of any of these licenses + * (at your option): + * - GNU GPL, version 2 or later. + * - GNU LGPL, version 2.1 or later. + * See the COPYING file in the top-level directory. + */ + +#include +#include +#include +#include +#include + +#include "main.h" +#include "menu.h" +#include "input.h" +#include "settings.h" +#include "config.h" +#include "args.h" +#include "dface.h" +#include "../libpicofe/plat.h" +#include "../libpicofe/input.h" +#include "../../state.h" +#include "../../general.h" +#include "../../input.h" +#include "../../palette.h" +#include "revision.h" + +#define array_size(x) (sizeof(x) / sizeof(x[0])) + +#define state_slot CurrentState +extern uint8 Exit; + +typedef enum +{ + MA_NONE = 1, + MA_CTRL_PLAYER1, + MA_CTRL_PLAYER2, + MA_CTRL_EMU, + MA_CTRL_DEADZONE, + MA_OPT_SAVECFG, + MA_OPT_SAVECFG_GAME, + MA_CTRL_DEV_FIRST, + MA_CTRL_DEV_NEXT, + MA_OPT_NTSC_COLOR, + MA_OPT_NTSC_TINT, + MA_OPT_NTSC_HUE, + MA_OPT_SREND_N, + MA_OPT_EREND_N, + MA_OPT_SREND_P, + MA_OPT_EREND_P, + MA_OPT_CLIP, + MA_OPT_NO8LIM, + MA_OPT_GG, + MA_OPT_SHOWFPS, + MA_OPT_FSKIP, + MA_OPT_RENDERER, + MA_OPT_SOUNDON, + MA_OPT_SOUNDRATE, + MA_OPT_REGION, + MA_OPT_TURBO, + MA_OPT_SSTATE, + MA_OPT_SSLOT, + MA_OPT_GAMMA, + MA_MAIN_RESUME_GAME, + MA_MAIN_SAVE_STATE, + MA_MAIN_LOAD_STATE, + MA_MAIN_RESET_GAME, + MA_MAIN_LOAD_ROM, + MA_MAIN_CHEATS, + MA_MAIN_CREDITS, + MA_MAIN_EXIT, +} menu_id; + +void emu_make_path(char *buff, const char *end, int size) +{ + int pos, end_len; + + end_len = strlen(end); + pos = plat_get_root_dir(buff, size); + strncpy(buff + pos, end, size - pos); + buff[size - 1] = 0; + if (pos + end_len > size - 1) + printf("Warning: path truncated: %s\n", buff); +} + +static int emu_check_save_file(int slot, int *time) +{ + struct stat status; + char *fname; + FILE *st; + int retval = 0; + int ret; + + fname = FCEU_MakeFName(FCEUMKF_STATE,CurrentState,0); + st = fopen(fname,"rb"); + if (st == NULL) + goto out; + fclose(st); + + retval = 1; + if (time == NULL) + goto out; + + ret = stat(fname, &status); + if (ret != 0) + goto out; + + if (status.st_mtime < 1347000000) + goto out; // probably bad rtc like on some Caanoos + + *time = status.st_mtime; + +out: + free(fname); + return retval; +} + +static int emu_save_load_game(int load, int unused) +{ + if (load) + FCEUI_LoadState(); + else + FCEUI_SaveState(); + + return 0; +} + +// rrrr rggg gggb bbbb +static unsigned short fname2color(const char *fname) +{ + static const char *rom_exts[] = { ".zip", ".nes", ".fds", ".unf", + ".nez", ".unif" }; + static const char *other_exts[] = { ".nsf", ".ips", ".fcm" }; + const char *ext = strrchr(fname, '.'); + int i; + + if (ext == NULL) + return 0xffff; + for (i = 0; i < array_size(rom_exts); i++) + if (strcasecmp(ext, rom_exts[i]) == 0) + return 0xbdff; + for (i = 0; i < array_size(other_exts); i++) + if (strcasecmp(ext, other_exts[i]) == 0) + return 0xaff5; + return 0xffff; +} + +static const char *filter_exts[] = { + ".txt", ".srm", ".pnd" +}; + +#define MENU_ALIGN_LEFT +#ifdef __ARM_ARCH_7A__ // assume hires device +#define MENU_X2 1 +#else +#define MENU_X2 0 +#endif + +#include "../libpicofe/menu.c" + +static void draw_savestate_bg(int slot) +{ +} + +static void debug_menu_loop(void) +{ +} + +// ------------ patch/gg menu ------------ + +extern void *cheats; +static int cheat_count, cheat_start, cheat_pos; + +static int countcallb(char *name, uint32 a, uint8 v, int compare, int s, int type, void *data) +{ + cheat_count++; + return 1; +} + +static int clistcallb(char *name, uint32 a, uint8 v, int compare, int s, int type, void *data) +{ + int pos; + + pos = cheat_start + cheat_pos; + cheat_pos++; + if (pos < 0) return 1; + if (pos >= g_menuscreen_h / me_sfont_h) return 0; + + smalltext_out16(14, pos * me_sfont_h, s ? "ON " : "OFF", 0xffff); + smalltext_out16(14 + me_sfont_w*4, pos * me_sfont_h, type ? "S" : "R", 0xffff); + smalltext_out16(14 + me_sfont_w*6, pos * me_sfont_h, name, 0xffff); + + return 1; +} + +static void draw_patchlist(int sel) +{ + int pos, max_cnt; + + menu_draw_begin(1, 1); + + max_cnt = g_menuscreen_h / me_sfont_h; + cheat_start = max_cnt / 2 - sel; + cheat_pos = 0; + FCEUI_ListCheats(clistcallb, 0); + + pos = cheat_start + cheat_pos; + if (pos < max_cnt) + smalltext_out16(14, pos * me_sfont_h, "done", 0xffff); + + text_out16(5, max_cnt / 2 * me_sfont_h, ">"); + menu_draw_end(); +} + +void patches_menu_loop(void) +{ + static int menu_sel = 0; + int inp; + + cheat_count = 0; + FCEUI_ListCheats(countcallb, 0); + + for (;;) + { + draw_patchlist(menu_sel); + inp = in_menu_wait(PBTN_UP|PBTN_DOWN|PBTN_LEFT|PBTN_RIGHT|PBTN_L|PBTN_R + |PBTN_MOK|PBTN_MBACK, NULL, 33); + if (inp & PBTN_UP ) { menu_sel--; if (menu_sel < 0) menu_sel = cheat_count; } + if (inp & PBTN_DOWN) { menu_sel++; if (menu_sel > cheat_count) menu_sel = 0; } + if (inp &(PBTN_LEFT|PBTN_L)) { menu_sel-=10; if (menu_sel < 0) menu_sel = 0; } + if (inp &(PBTN_RIGHT|PBTN_R)) { menu_sel+=10; if (menu_sel > cheat_count) menu_sel = cheat_count; } + if (inp & PBTN_MOK) { // action + if (menu_sel < cheat_count) + FCEUI_ToggleCheat(menu_sel); + else break; + } + if (inp & PBTN_MBACK) + break; + } +} + +// -------------- key config -------------- + +// b_turbo,a_turbo RLDU SEBA +me_bind_action me_ctrl_actions[] = +{ + { "UP ", NKEY_UP }, + { "DOWN ", NKEY_DOWN }, + { "LEFT ", NKEY_LEFT }, + { "RIGHT ", NKEY_RIGHT }, + { "A ", NKEY_A }, + { "B ", NKEY_B }, + { "A TURBO", NKEY_A_TURBO }, + { "B TURBO", NKEY_B_TURBO }, + { "START ", NKEY_START }, + { "SELECT ", NKEY_SELECT }, + { NULL, 0 } +}; + +me_bind_action emuctrl_actions[] = +{ + { "Save State ", EACT_SAVE_STATE }, + { "Load State ", EACT_LOAD_STATE }, + { "Next State Slot ", EACT_NEXT_SLOT }, + { "Prev State Slot ", EACT_PREV_SLOT }, + { "FDS Insert/Eject ", EACT_FDS_INSERT }, + { "FDS Select Disk ", EACT_FDS_SELECT }, + { "VSUni Insert Coin", EACT_INSERT_COIN }, + { "Enter Menu ", EACT_ENTER_MENU }, + { NULL, 0 } +}; + +static int key_config_loop_wrap(int id, int keys) +{ + switch (id) { + case MA_CTRL_PLAYER1: + key_config_loop(me_ctrl_actions, array_size(me_ctrl_actions) - 1, 0); + break; + case MA_CTRL_PLAYER2: + key_config_loop(me_ctrl_actions, array_size(me_ctrl_actions) - 1, 1); + break; + case MA_CTRL_EMU: + key_config_loop(emuctrl_actions, array_size(emuctrl_actions) - 1, -1); + break; + default: + break; + } + return 0; +} + +static const char *mgn_dev_name(int id, int *offs) +{ + const char *name = NULL; + static int it = 0; + + if (id == MA_CTRL_DEV_FIRST) + it = 0; + + for (; it < IN_MAX_DEVS; it++) { + name = in_get_dev_name(it, 1, 1); + if (name != NULL) + break; + } + + it++; + return name; +} + +static const char *mgn_saveloadcfg(int id, int *offs) +{ + return ""; +} + +static void config_commit(void); + +static int mh_savecfg(int id, int keys) +{ + const char *fname = NULL; + if (id == MA_OPT_SAVECFG_GAME) + fname = lastLoadedGameName; + + config_commit(); + if (SaveConfig(fname) == 0) + menu_update_msg("config saved"); + else + menu_update_msg("failed to write config"); + + return 1; +} + +static int mh_input_rescan(int id, int keys) +{ + //menu_sync_config(); + in_probe(); + menu_update_msg("rescan complete."); + + return 0; +} + +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("Emulator controls", MA_CTRL_EMU, key_config_loop_wrap), + mee_label (""), +// mee_range ("Analog deadzone", MA_CTRL_DEADZONE, analog_deadzone, 1, 99), + 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_label (""), + 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), + mee_label_mk (MA_CTRL_DEV_NEXT, mgn_dev_name), + mee_label_mk (MA_CTRL_DEV_NEXT, mgn_dev_name), + mee_label_mk (MA_CTRL_DEV_NEXT, mgn_dev_name), + mee_label_mk (MA_CTRL_DEV_NEXT, mgn_dev_name), + mee_end, +}; + +static int menu_loop_keyconfig(int id, int keys) +{ + static int sel = 0; + + me_loop(e_menu_keyconfig, &sel); + return 0; +} + +// --------- FCEU options ---------- + +extern int ntsccol,ntschue,ntsctint; +extern int srendlinev[2]; +extern int erendlinev[2]; +extern int eoptions; +extern char *cpalette; +extern void LoadCPalette(void); + +static menu_entry e_menu_fceu_options[] = +{ + //gp2x_text_out15(tl_x, y, "Custom palette: %s", cpal); + mee_onoff ("NTSC Color Emulation", MA_OPT_NTSC_COLOR, ntsccol, 1), + mee_range (" Tint (default: 56)", MA_OPT_NTSC_TINT, ntsctint, 0, 128), + mee_range (" Hue (default: 72)", MA_OPT_NTSC_HUE, ntschue, 0, 128), + mee_range ("First visible line (NTSC)", MA_OPT_SREND_N, srendlinev[0], 0, 239), + mee_range ("Last visible line (NTSC)", MA_OPT_EREND_N, erendlinev[0], 0, 239), + mee_range ("First visible line (PAL)", MA_OPT_SREND_P, srendlinev[1], 0, 239), + mee_range ("Last visible line (PAL)", MA_OPT_EREND_P, erendlinev[1], 0, 239), + mee_onoff ("Clip 8 left/right columns", MA_OPT_CLIP, eoptions, EO_CLIPSIDES), + mee_onoff ("Disable 8 sprite limit", MA_OPT_NO8LIM, eoptions, EO_NO8LIM), + mee_onoff ("Enable authentic GameGenie",MA_OPT_GG, eoptions, EO_GG), + mee_end, +}; + +static int menu_loop_fceu_options(int id, int keys) +{ + static int sel = 0; + int i; + + FCEUI_GetNTSCTH(&ntsctint, &ntschue); + + me_loop(e_menu_fceu_options, &sel); + + for(i = 0; i < 2; i++) + { + if (srendlinev[i] < 0 || srendlinev[i] > 239) + srendlinev[i] = 0; + if (erendlinev[i] < srendlinev[i] || erendlinev[i] > 239) + erendlinev[i] = 239; + } + FCEUI_SetNTSCTH(ntsccol, ntsctint, ntschue); + FCEUI_SetRenderedLines(srendlinev[0],erendlinev[0],srendlinev[1],erendlinev[1]); + FCEUI_DisableSpriteLimitation(eoptions&EO_NO8LIM); + FCEUI_SetGameGenie(eoptions&EO_GG); + //if (cpalette) LoadCPalette(); + //else + FCEUI_SetPaletteArray(0); // set to default + FCEU_ResetPalette(); + + return 0; +} + +// -------------- options -------------- + +static const char *men_frameskip[] = { "Auto", "0", "1", "2", "3", "4", NULL }; +static const char *men_rates[] = { "8000", "11025", "16000", "22050", "44100", NULL }; +static const int men_rates_i[] = { 8000 , 11025 , 16000 , 22050 , 44100 }; +static const char *men_region[] = { "Auto", "NTSC", "PAL", NULL }; +static const char *men_sstate[] = { "OFF", "writes", "loads", "both", NULL }; +static const char h_renderer[] = "ROM reload required for this\n" + "setting to take effect"; + +static int sndrate_i; +static int sndon; +static int turbo_i; + +static void config_commit(void) +{ + Settings.sound_rate = men_rates_i[sndrate_i]; + soundvol = sndon ? 0 : 50; + Settings.turbo_rate_add = (turbo_i * 2 << 24) / 60 + 1; + + if (Settings.region_force) + FCEUI_SetVidSystem(Settings.region_force - 1); +} + +static menu_entry e_menu_options[] = +{ + mee_onoff ("Show FPS", MA_OPT_SHOWFPS, Settings.showfps, 1), + mee_enum ("Frameskip", MA_OPT_FSKIP, Settings.frameskip, men_frameskip), + mee_onoff_h ("Accurate renderer (slow)",MA_OPT_RENDERER, Settings.accurate_mode, 1, h_renderer), + mee_onoff ("Enable sound", MA_OPT_SOUNDON, sndon, 1), + mee_enum ("Sound Rate", MA_OPT_SOUNDRATE, sndrate_i, men_rates), + mee_enum ("Region", MA_OPT_REGION, Settings.region_force, men_region), + mee_range ("Turbo rate (Hz)", MA_OPT_TURBO, turbo_i, 1, 30), + mee_enum ("Confirm savestate", MA_OPT_SSTATE, Settings.sstate_confirm, men_sstate), + mee_range ("Save slot", MA_OPT_SSLOT, CurrentState, 0, 9), + mee_range ("Gamma correction", MA_OPT_GAMMA, Settings.gamma, 0, 300), + mee_handler ("[FCE Ultra options]", menu_loop_fceu_options), + mee_cust_nosave("Save global config", MA_OPT_SAVECFG, mh_savecfg, mgn_saveloadcfg), + mee_cust_nosave("Save cfg for loaded game",MA_OPT_SAVECFG_GAME, mh_savecfg, mgn_saveloadcfg), + mee_end, +}; + +static int menu_loop_options(int id, int keys) +{ + static int sel = 0; + int oldrate; + int i; + + oldrate = Settings.sound_rate; + for (i = 0; i < array_size(men_rates_i); i++) { + if (Settings.sound_rate == men_rates_i[i]) { + sndrate_i = i; + break; + } + } + sndon = soundvol != 0; + turbo_i = (Settings.turbo_rate_add * 60 / 2) >> 24; + + me_loop(e_menu_options, &sel); + + config_commit(); + if (oldrate != Settings.sound_rate) + InitSound(); + + return 0; +} + +// -------------- root menu -------------- + +static const char credits_text[] = + "GPFCE " REV "\n" + "(c) notaz, 2007,2012\n\n" + "Based on FCE Ultra versions\n" + "0.81 and 0.98.1x\n\n" + " - Credits -\n" + "Bero: FCE\n" + "Xodnizel: FCE Ultra\n" + "FCA author: 6502 core\n"; + +static void draw_frame_credits(void) +{ + smalltext_out16(4, 1, "build: " __DATE__ " " __TIME__ " " REV, 0xe7fc); +} + +static int romsel_run(void) +{ + const char *fname; + + fname = menu_loop_romsel(lastLoadedGameName, sizeof(lastLoadedGameName)); + if (fname == NULL) + return -1; + + printf("selected file: %s\n", fname); + //keys_load_all(cfg); + + strcpy(lastLoadedGameName, rom_fname_reload); + return 0; +} + +static int menu_loop_ret; + +static int main_menu_handler(int id, int keys) +{ + switch (id) + { + case MA_MAIN_RESUME_GAME: + if (fceugi) + return 1; + break; + case MA_MAIN_SAVE_STATE: + if (fceugi) { + Exit = 0; + return menu_loop_savestate(0); + } + break; + case MA_MAIN_LOAD_STATE: + if (fceugi) { + Exit = 0; + return menu_loop_savestate(1); + } + break; + case MA_MAIN_RESET_GAME: + if (fceugi) { + FCEU_DoSimpleCommand(FCEUNPCMD_RESET); + Exit = 0; + return 0; + } + break; + case MA_MAIN_LOAD_ROM: + if (romsel_run() == 0) { + menu_loop_ret = 2; + return 1; + } + break; + case MA_MAIN_CREDITS: + draw_menu_message(credits_text, draw_frame_credits); + in_menu_wait(PBTN_MOK|PBTN_MBACK, NULL, 70); + break; + case MA_MAIN_EXIT: + menu_loop_ret = 1; + return 1; + default: + lprintf("%s: something unknown selected\n", __FUNCTION__); + break; + } + + return 0; +} + +static menu_entry e_menu_main[] = +{ + mee_handler_id("Resume game", MA_MAIN_RESUME_GAME, main_menu_handler), + mee_handler_id("Save State", MA_MAIN_SAVE_STATE, main_menu_handler), + mee_handler_id("Load State", MA_MAIN_LOAD_STATE, main_menu_handler), + mee_handler_id("Reset game", MA_MAIN_RESET_GAME, main_menu_handler), + mee_handler_id("Load ROM", MA_MAIN_LOAD_ROM, main_menu_handler), + mee_handler ("Options", menu_loop_options), + mee_handler ("Controls", menu_loop_keyconfig), + mee_handler_id("Cheats", MA_MAIN_CHEATS, main_menu_handler), + mee_handler_id("Credits", MA_MAIN_CREDITS, main_menu_handler), + mee_handler_id("Exit", MA_MAIN_EXIT, main_menu_handler), + mee_end, +}; + +// ---------------------------- + +int menu_loop(void) +{ + static int sel = 0; + + menu_loop_ret = 0; + + me_enable(e_menu_main, MA_MAIN_RESUME_GAME, fceugi != NULL); + me_enable(e_menu_main, MA_MAIN_SAVE_STATE, fceugi != NULL); + me_enable(e_menu_main, MA_MAIN_LOAD_STATE, fceugi != NULL); + me_enable(e_menu_main, MA_MAIN_RESET_GAME, fceugi != NULL); + me_enable(e_menu_main, MA_MAIN_CHEATS, fceugi && cheats); + + plat_video_menu_enter(fceugi != NULL); + in_set_config_int(0, IN_CFG_BLOCKING, 1); + + do { + me_loop_d(e_menu_main, &sel, NULL, NULL); + } while (!fceugi && menu_loop_ret == 0); + + /* wait until menu, ok, back is released */ + while (in_menu_wait_any(NULL, 50) & (PBTN_MENU|PBTN_MOK|PBTN_MBACK)) + ; + + in_set_config_int(0, IN_CFG_BLOCKING, 0); + plat_video_menu_leave(); + + return menu_loop_ret; +} + +void menu_init(void) +{ + char buff[256]; + + g_border_style = 1; + menu_init_base(); + + //menu_load_config(0); + + g_menubg_src_ptr = calloc(g_menuscreen_w * g_menuscreen_h * 2, 1); + g_menubg_ptr = calloc(g_menuscreen_w * g_menuscreen_h * 2, 1); + if (g_menubg_src_ptr == NULL || g_menubg_ptr == NULL) { + fprintf(stderr, "OOM\n"); + exit(1); + } + + emu_make_path(buff, "skin/background.png", sizeof(buff)); + readpng(g_menubg_src_ptr, buff, READPNG_BG, g_menuscreen_w, g_menuscreen_h); +} + +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; + + menu_error_time = plat_get_ticks_ms(); + lprintf("msg: %s\n", menu_error_msg); +} +