4291ac5832ed0f76efb25ea63bc8bb27b5d1ee8d
[pcsx_rearmed.git] / frontend / menu.c
1 /*
2  * (C) GraÅžvydas "notaz" Ignotas, 2010
3  *
4  * This work is licensed under the terms of any of these licenses
5  * (at your option):
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.
9  */
10
11 #include <stdio.h>
12 #include <string.h>
13
14 #include "config.h"
15 #include "plugin_lib.h"
16 #include "omap.h"
17 #include "common/plat.h"
18 #include "../libpcsxcore/misc.h"
19 #include "../libpcsxcore/new_dynarec/new_dynarec.h"
20
21 #define MENU_X2 1
22 #define array_size(x) (sizeof(x) / sizeof(x[0]))
23
24 typedef enum
25 {
26         MA_NONE = 1,
27         MA_MAIN_RESUME_GAME,
28         MA_MAIN_SAVE_STATE,
29         MA_MAIN_LOAD_STATE,
30         MA_MAIN_RESET_GAME,
31         MA_MAIN_LOAD_ROM,
32         MA_MAIN_CONTROLS,
33         MA_MAIN_CREDITS,
34         MA_MAIN_EXIT,
35         MA_CTRL_PLAYER1,
36         MA_CTRL_PLAYER2,
37         MA_CTRL_EMU,
38         MA_CTRL_DEV_FIRST,
39         MA_CTRL_DEV_NEXT,
40         MA_CTRL_DONE,
41         MA_OPT_SAVECFG,
42         MA_OPT_SAVECFG_GAME,
43         MA_OPT_CPU_CLOCKS,
44 } menu_id;
45
46 extern int ready_to_go;
47
48 static int dummy, state_slot;
49 static char rom_fname_reload[MAXPATHLEN];
50 static char last_selected_fname[MAXPATHLEN];
51
52 void emu_make_path(char *buff, const char *end, int size)
53 {
54         int pos, end_len;
55
56         end_len = strlen(end);
57         pos = plat_get_root_dir(buff, size);
58         strncpy(buff + pos, end, size - pos);
59         buff[size - 1] = 0;
60         if (pos + end_len > size - 1)
61                 printf("Warning: path truncated: %s\n", buff);
62 }
63
64 static int emu_check_save_file(int slot)
65 {
66         return 0;
67 }
68
69 static int emu_save_load_game(int load, int sram)
70 {
71         return 0;
72 }
73
74 static int emu_write_config(int is_game)
75 {
76         return 0;
77 }
78
79 static void emu_set_defconfig(void)
80 {
81 }
82
83 #include "common/menu.c"
84
85 static void draw_savestate_bg(int slot)
86 {
87 }
88
89 // -------------- key config --------------
90
91 me_bind_action me_ctrl_actions[] =
92 {
93         { "UP      ", 1 << DKEY_UP},
94         { "DOWN    ", 1 << DKEY_DOWN },
95         { "LEFT    ", 1 << DKEY_LEFT },
96         { "RIGHT   ", 1 << DKEY_RIGHT },
97         { "TRIANGLE", 1 << DKEY_TRIANGLE },
98         { "CIRCLE  ", 1 << DKEY_SQUARE },
99         { "CROSS   ", 1 << DKEY_CROSS },
100         { "SQUARE  ", 1 << DKEY_SQUARE },
101         { "L1      ", 1 << DKEY_L1 },
102         { "R1      ", 1 << DKEY_R1 },
103         { "L2      ", 1 << DKEY_L2 },
104         { "R2      ", 1 << DKEY_R2 },
105         { "START   ", 1 << DKEY_START },
106         { "SELECT  ", 1 << DKEY_SELECT },
107         { NULL,       0 }
108 };
109
110 me_bind_action emuctrl_actions[] =
111 {
112         { "Load State       ", PEV_STATE_LOAD },
113         { "Save State       ", PEV_STATE_SAVE },
114         { "Prev Save Slot   ", PEV_SSLOT_PREV },
115         { "Next Save Slot   ", PEV_SSLOT_NEXT },
116         { "Enter Menu       ", PEV_MENU },
117         { NULL,                0 }
118 };
119
120 static int key_config_loop_wrap(int id, int keys)
121 {
122         switch (id) {
123                 case MA_CTRL_PLAYER1:
124                         key_config_loop(me_ctrl_actions, array_size(me_ctrl_actions) - 1, 0);
125                         break;
126                 case MA_CTRL_PLAYER2:
127                         key_config_loop(me_ctrl_actions, array_size(me_ctrl_actions) - 1, 1);
128                         break;
129                 case MA_CTRL_EMU:
130                         key_config_loop(emuctrl_actions, array_size(emuctrl_actions) - 1, -1);
131                         break;
132                 default:
133                         break;
134         }
135         return 0;
136 }
137
138 static const char *mgn_dev_name(int id, int *offs)
139 {
140         const char *name = NULL;
141         static int it = 0;
142
143         if (id == MA_CTRL_DEV_FIRST)
144                 it = 0;
145
146         for (; it < IN_MAX_DEVS; it++) {
147                 name = in_get_dev_name(it, 1, 1);
148                 if (name != NULL)
149                         break;
150         }
151
152         it++;
153         return name;
154 }
155
156 static const char *mgn_saveloadcfg(int id, int *offs)
157 {
158         return "";
159 }
160
161 static int mh_saveloadcfg(int id, int keys)
162 {
163         switch (id) {
164         case MA_OPT_SAVECFG:
165         case MA_OPT_SAVECFG_GAME:
166                 if (emu_write_config(id == MA_OPT_SAVECFG_GAME ? 1 : 0))
167                         me_update_msg("config saved");
168                 else
169                         me_update_msg("failed to write config");
170                 break;
171         default:
172                 return 0;
173         }
174
175         return 1;
176 }
177
178 static menu_entry e_menu_keyconfig[] =
179 {
180         mee_handler_id("Player 1",          MA_CTRL_PLAYER1,    key_config_loop_wrap),
181         mee_handler_id("Player 2",          MA_CTRL_PLAYER2,    key_config_loop_wrap),
182         mee_handler_id("Emulator controls", MA_CTRL_EMU,        key_config_loop_wrap),
183         mee_cust_nosave("Save global config",       MA_OPT_SAVECFG, mh_saveloadcfg, mgn_saveloadcfg),
184         mee_cust_nosave("Save cfg for loaded game", MA_OPT_SAVECFG_GAME, mh_saveloadcfg, mgn_saveloadcfg),
185         mee_label     (""),
186         mee_label     ("Input devices:"),
187         mee_label_mk  (MA_CTRL_DEV_FIRST, mgn_dev_name),
188         mee_label_mk  (MA_CTRL_DEV_NEXT,  mgn_dev_name),
189         mee_label_mk  (MA_CTRL_DEV_NEXT,  mgn_dev_name),
190         mee_label_mk  (MA_CTRL_DEV_NEXT,  mgn_dev_name),
191         mee_label_mk  (MA_CTRL_DEV_NEXT,  mgn_dev_name),
192         mee_label_mk  (MA_CTRL_DEV_NEXT,  mgn_dev_name),
193         mee_label_mk  (MA_CTRL_DEV_NEXT,  mgn_dev_name),
194         mee_end,
195 };
196
197 static int menu_loop_keyconfig(int id, int keys)
198 {
199         static int sel = 0;
200
201         me_enable(e_menu_keyconfig, MA_OPT_SAVECFG_GAME, ready_to_go);
202         me_loop(e_menu_keyconfig, &sel, NULL);
203         return 0;
204 }
205
206 // ------------ adv options menu ------------
207
208 static menu_entry e_menu_adv_options[] =
209 {
210         mee_onoff     ("captain placeholder", 0, dummy, 1),
211         mee_end,
212 };
213
214 static int menu_loop_adv_options(int id, int keys)
215 {
216         static int sel = 0;
217         me_loop(e_menu_adv_options, &sel, NULL);
218         return 0;
219 }
220
221 // ------------ gfx options menu ------------
222
223 static menu_entry e_menu_gfx_options[] =
224 {
225         mee_end,
226 };
227
228 static int menu_loop_gfx_options(int id, int keys)
229 {
230         static int sel = 0;
231
232         me_loop(e_menu_gfx_options, &sel, NULL);
233
234         return 0;
235 }
236
237 // ------------ options menu ------------
238
239 static menu_entry e_menu_options[];
240
241 static int mh_restore_defaults(int id, int keys)
242 {
243         emu_set_defconfig();
244         me_update_msg("defaults restored");
245         return 1;
246 }
247
248 static const char *men_confirm_save[] = { "OFF", "writes", "loads", "both", NULL };
249 static const char h_confirm_save[]    = "Ask for confirmation when overwriting save,\n"
250                                         "loading state or both";
251
252 static menu_entry e_menu_options[] =
253 {
254         mee_range     ("Save slot",                0, state_slot, 0, 9),
255         mee_enum_h    ("Confirm savestate",        0, dummy, men_confirm_save, h_confirm_save),
256         mee_range     ("",                         MA_OPT_CPU_CLOCKS, dummy, 20, 5000),
257         mee_handler   ("[Display]",                menu_loop_gfx_options),
258         mee_handler   ("[Advanced]",               menu_loop_adv_options),
259         mee_cust_nosave("Save global config",      MA_OPT_SAVECFG,      mh_saveloadcfg, mgn_saveloadcfg),
260         mee_cust_nosave("Save cfg for loaded game",MA_OPT_SAVECFG_GAME, mh_saveloadcfg, mgn_saveloadcfg),
261         mee_handler   ("Restore defaults",         mh_restore_defaults),
262         mee_end,
263 };
264
265 static int menu_loop_options(int id, int keys)
266 {
267         static int sel = 0;
268         int i;
269
270         i = me_id2offset(e_menu_options, MA_OPT_CPU_CLOCKS);
271         e_menu_options[i].enabled = e_menu_options[i].name[0] ? 1 : 0;
272         me_enable(e_menu_options, MA_OPT_SAVECFG_GAME, ready_to_go);
273
274         me_loop(e_menu_options, &sel, NULL);
275
276         return 0;
277 }
278
279 // ------------ debug menu ------------
280
281 #ifdef __GNUC__
282 #define COMPILER "gcc " __VERSION__
283 #else
284 #define COMPILER
285 #endif
286
287 static void draw_frame_debug(void)
288 {
289         smalltext_out16(4, 1, "build: "__DATE__ " " __TIME__ " " COMPILER, 0xffff);
290 }
291
292 static void debug_menu_loop(void)
293 {
294         int inp;
295
296         while (1)
297         {
298                 menu_draw_begin(1);
299                 draw_frame_debug();
300                 menu_draw_end();
301
302                 inp = in_menu_wait(PBTN_MOK|PBTN_MBACK|PBTN_MA2|PBTN_MA3|PBTN_L|PBTN_R |
303                                         PBTN_UP|PBTN_DOWN|PBTN_LEFT|PBTN_RIGHT, 70);
304                 if (inp & PBTN_MBACK)
305                         return;
306         }
307 }
308
309 // ------------ main menu ------------
310
311 const char *plat_get_credits(void)
312 {
313         return  "(C) 1999-2003 PCSX Team\n"
314                 "(C) 2005-2009 PCSX-df Team\n"
315                 "(C) 2009-2010 PCSX-Reloaded Team\n\n"
316                 "GPU and SPU code by Pete Bernert\n"
317                 "  and the P.E.Op.S. team\n"
318                 "ARM recompiler by Ari64\n\n"
319                 "integration, optimization and\n"
320                 "  frontend by (C) notaz, 2010\n";
321 }
322
323 static char *romsel_run(void)
324 {
325         char *ret;
326
327         ret = menu_loop_romsel(last_selected_fname, sizeof(last_selected_fname));
328         if (ret == NULL)
329                 return NULL;
330
331         lprintf("selected file: %s\n", ret);
332         ready_to_go = 0;
333
334         SetIsoFile(ret);
335         LoadPlugins();
336         NetOpened = 0;
337         if (OpenPlugins() == -1) {
338                 me_update_msg("failed to open plugins");
339                 return NULL;
340         }
341
342         SysReset();
343
344         if (CheckCdrom() == -1) {
345                 // Only check the CD if we are starting the console with a CD
346                 ClosePlugins();
347                 me_update_msg("unsupported/invalid CD image");
348                 return NULL;
349         }
350
351         // Read main executable directly from CDRom and start it
352         if (LoadCdrom() == -1) {
353                 ClosePlugins();
354                 me_update_msg("failed to load CD image");
355                 return NULL;
356         }
357
358         ready_to_go = 1;
359         return ret;
360 }
361
362 static int main_menu_handler(int id, int keys)
363 {
364         char *ret_name;
365
366         switch (id)
367         {
368         case MA_MAIN_RESUME_GAME:
369                 break;
370         case MA_MAIN_SAVE_STATE:
371                 if (ready_to_go)
372                         return menu_loop_savestate(0);
373                 break;
374         case MA_MAIN_LOAD_STATE:
375                 if (ready_to_go)
376                         return menu_loop_savestate(1);
377                 break;
378         case MA_MAIN_RESET_GAME:
379                 break;
380         case MA_MAIN_LOAD_ROM:
381                 ret_name = romsel_run();
382                 if (ret_name != NULL)
383                         return 1;
384                 break;
385         case MA_MAIN_CREDITS:
386                 draw_menu_credits();
387                 in_menu_wait(PBTN_MOK|PBTN_MBACK, 70);
388                 break;
389         case MA_MAIN_EXIT:
390                 exit(1); // FIXME
391         default:
392                 lprintf("%s: something unknown selected\n", __FUNCTION__);
393                 break;
394         }
395
396         return 0;
397 }
398
399 static menu_entry e_menu_main[] =
400 {
401         mee_label     (""),
402         mee_label     (""),
403         mee_handler_id("Resume game",        MA_MAIN_RESUME_GAME, main_menu_handler),
404         mee_handler_id("Save State",         MA_MAIN_SAVE_STATE,  main_menu_handler),
405         mee_handler_id("Load State",         MA_MAIN_LOAD_STATE,  main_menu_handler),
406         mee_handler_id("Reset game",         MA_MAIN_RESET_GAME,  main_menu_handler),
407         mee_handler_id("Load CD image",      MA_MAIN_LOAD_ROM,    main_menu_handler),
408         mee_handler   ("Options",            menu_loop_options),
409         mee_handler   ("Controls",           menu_loop_keyconfig),
410         mee_handler_id("Credits",            MA_MAIN_CREDITS,     main_menu_handler),
411         mee_handler_id("Exit",               MA_MAIN_EXIT,        main_menu_handler),
412         mee_end,
413 };
414
415 void menu_loop(void)
416 {
417         static int sel = 0;
418
419         omap_enable_layer(0);
420
421         me_enable(e_menu_main, MA_MAIN_RESUME_GAME, ready_to_go);
422         me_enable(e_menu_main, MA_MAIN_SAVE_STATE,  ready_to_go);
423         me_enable(e_menu_main, MA_MAIN_LOAD_STATE,  ready_to_go);
424         me_enable(e_menu_main, MA_MAIN_RESET_GAME,  ready_to_go);
425
426 strcpy(last_selected_fname, "/mnt/ntz/stuff/psx");
427         menu_enter(ready_to_go);
428         in_set_config_int(0, IN_CFG_BLOCKING, 1);
429
430         do {
431                 me_loop(e_menu_main, &sel, NULL);
432         } while (!ready_to_go);
433
434         /* wait until menu, ok, back is released */
435         while (in_menu_wait_any(50) & (PBTN_MENU|PBTN_MOK|PBTN_MBACK))
436                 ;
437
438         in_set_config_int(0, IN_CFG_BLOCKING, 0);
439
440         memset(g_menuscreen_ptr, 0, g_menuscreen_w * g_menuscreen_h * 2);
441         menu_draw_end();
442         omap_enable_layer(1);
443         stop = 0;
444 }
445
446 void me_update_msg(const char *msg)
447 {
448         strncpy(menu_error_msg, msg, sizeof(menu_error_msg));
449         menu_error_msg[sizeof(menu_error_msg) - 1] = 0;
450
451         menu_error_time = plat_get_ticks_ms();
452         lprintf("msg: %s\n", menu_error_msg);
453 }
454