1 /****************************************************************************
2  *  menu.c
3  *
4  *  Genesis Plus GX menu
5  *
6  *  Copyright Eke-Eke (2009-2019)
7  *
8  *  Redistribution and use of this code or any derivative works are permitted
9  *  provided that the following conditions are met:
10  *
11  *   - Redistributions may not be sold, nor may they be used in a commercial
12  *     product or activity.
13  *
14  *   - Redistributions that are modified from the original source must include the
15  *     complete source code, including the source code for all components used by a
16  *     binary built from the modified sources. However, as a special exception, the
17  *     source code distributed need not include anything that is normally distributed
18  *     (in either source or binary form) with the major components (compiler, kernel,
19  *     and so on) of the operating system on which the executable runs, unless that
20  *     component itself accompanies the executable.
21  *
22  *   - Redistributions must reproduce the above copyright notice, this list of
23  *     conditions and the following disclaimer in the documentation and/or other
24  *     materials provided with the distribution.
25  *
26  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
27  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29  *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
30  *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36  *  POSSIBILITY OF SUCH DAMAGE.
37  *
38  ****************************************************************************************/
39 
40 #include "shared.h"
41 #include "font.h"
42 #include "gui.h"
43 #include "filesel.h"
44 #include "cheats.h"
45 #include "file_load.h"
46 #include "file_slot.h"
47 
48 #ifdef HW_RVL
49 #include <ogc/usbmouse.h>
50 #include "wiidrc.h"
51 #endif
52 
53 #include <ogc/lwp_threads.h>
54 #include <ogc/lwp_watchdog.h>
55 
56 /* Credits */
57 extern const u8 Bg_credits_png[];
58 
59 /* Main menu */
60 extern const u8 Main_load_png[];
61 extern const u8 Main_options_png[];
62 extern const u8 Main_quit_png[];
63 extern const u8 Main_file_png[];
64 extern const u8 Main_reset_png[];
65 extern const u8 Main_cheats_png[];
66 extern const u8 Main_showinfo_png[];
67 extern const u8 Main_takeshot_png[];
68 #ifdef HW_RVL
69 extern const u8 Main_play_wii_png[];
70 #else
71 extern const u8 Main_play_gcn_png[];
72 #endif
73 
74 /* Options menu */
75 extern const u8 Option_menu_png[];
76 extern const u8 Option_ctrl_png[];
77 extern const u8 Option_sound_png[];
78 extern const u8 Option_video_png[];
79 extern const u8 Option_system_png[];
80 
81 /* Load ROM menu */
82 extern const u8 Load_recent_png[];
83 extern const u8 Load_md_png[];
84 extern const u8 Load_ms_png[];
85 extern const u8 Load_gg_png[];
86 extern const u8 Load_sg_png[];
87 extern const u8 Load_cd_png[];
88 
89 /* Save Manager menu */
90 extern const u8 Button_load_png[];
91 extern const u8 Button_load_over_png[];
92 extern const u8 Button_save_png[];
93 extern const u8 Button_save_over_png[];
94 extern const u8 Button_special_png[];
95 extern const u8 Button_special_over_png[];
96 extern const u8 Button_delete_png[];
97 extern const u8 Button_delete_over_png[];
98 
99 /* Controller Settings */
100 extern const u8 Ctrl_4wayplay_png[];
101 extern const u8 Ctrl_gamepad_png[];
102 extern const u8 Ctrl_justifiers_png[];
103 extern const u8 Ctrl_menacer_png[];
104 extern const u8 Ctrl_mouse_png[];
105 extern const u8 Ctrl_xe_1ap_png[];
106 extern const u8 Ctrl_activator_png[];
107 extern const u8 Ctrl_lightphaser_png[];
108 extern const u8 Ctrl_paddle_png[];
109 extern const u8 Ctrl_sportspad_png[];
110 extern const u8 Ctrl_none_png[];
111 extern const u8 Ctrl_teamplayer_png[];
112 extern const u8 Ctrl_mastertap_png[];
113 extern const u8 Ctrl_graphic_board_png[];
114 extern const u8 Ctrl_pad_auto_png[];
115 extern const u8 Ctrl_pad2b_png[];
116 extern const u8 Ctrl_pad3b_png[];
117 extern const u8 Ctrl_pad6b_png[];
118 extern const u8 Ctrl_config_png[];
119 extern const u8 ctrl_option_off_png[];
120 extern const u8 ctrl_option_on_png[];
121 extern const u8 ctrl_gamecube_png[];
122 #ifdef HW_RVL
123 extern const u8 ctrl_classic_png[];
124 extern const u8 ctrl_nunchuk_png[];
125 extern const u8 ctrl_wiimote_png[];
126 extern const u8 ctrl_wiiu_png[];
127 #endif
128 
129 /* Generic images */
130 extern const u8 Button_sm_blue_png[];
131 extern const u8 Button_sm_grey_png[];
132 extern const u8 Button_sm_yellow_png[];
133 
134 /* Exit callback */
135 void (*reload)(void);
136 
137 
138 /*****************************************************************************/
139 /*  Specific Menu Callbacks                                                  */
140 /*****************************************************************************/
141 static void ctrlmenu_cb(void);
142 static void savemenu_cb(void);
143 static void mainmenu_cb(void);
144 
145 /*****************************************************************************/
146 /*  Generic Buttons data                                                     */
147 /*****************************************************************************/
148 static butn_data arrow_up_data =
149 {
150   {NULL,NULL},
151   {Button_up_png,Button_up_over_png}
152 };
153 
154 static butn_data arrow_down_data =
155 {
156   {NULL,NULL},
157   {Button_down_png,Button_down_over_png}
158 };
159 
160 static butn_data button_text_data =
161 {
162   {NULL,NULL},
163   {Button_text_png,Button_text_over_png}
164 };
165 
166 static butn_data button_icon_data =
167 {
168   {NULL,NULL},
169   {Button_icon_png,Button_icon_over_png}
170 };
171 
172 static butn_data button_icon_sm_data =
173 {
174   {NULL,NULL},
175   {Button_icon_sm_png,Button_icon_sm_over_png}
176 };
177 
178 static butn_data button_player_data =
179 {
180   {NULL,NULL},
181   {Button_sm_blue_png,Button_sm_yellow_png}
182 };
183 
184 static butn_data button_player_none_data =
185 {
186   {NULL,NULL},
187   {Button_sm_grey_png,NULL}
188 };
189 
190 static butn_data button_load_data =
191 {
192   {NULL,NULL},
193   {Button_load_png,Button_load_over_png}
194 };
195 
196 static butn_data button_save_data =
197 {
198   {NULL,NULL},
199   {Button_save_png,Button_save_over_png}
200 };
201 
202 static butn_data button_special_data =
203 {
204   {NULL,NULL},
205   {Button_special_png,Button_special_over_png}
206 };
207 
208 static butn_data button_delete_data =
209 {
210   {NULL,NULL},
211   {Button_delete_png,Button_delete_over_png}
212 };
213 
214 /*****************************************************************************/
215 /*  Generic GUI items                                                         */
216 /*****************************************************************************/
217 static gui_item action_cancel =
218 {
219   NULL,Key_B_png,"","Back",10,422,28,28
220 };
221 
222 static gui_item action_select =
223 {
224   NULL,Key_A_png,"","",602,422,28,28
225 };
226 
227 /*****************************************************************************/
228 /* GUI backgrounds images                                                    */
229 /*****************************************************************************/
230 static gui_image bg_main[] =
231 {
232   {NULL,Bg_layer_png,IMAGE_VISIBLE|IMAGE_REPEAT,0,0,640,480,255},
233   {NULL,Bg_overlay_png,IMAGE_VISIBLE|IMAGE_REPEAT,0,0,640,480,255},
234   {NULL,Banner_main_png,IMAGE_VISIBLE|IMAGE_SLIDE_BOTTOM,0,340,640,140,255},
235   {NULL,Main_logo_png,IMAGE_VISIBLE|IMAGE_SLIDE_BOTTOM,202,362,232,56,255}
236 };
237 
238 static gui_image bg_misc[] =
239 {
240   {NULL,Bg_layer_png,IMAGE_VISIBLE|IMAGE_REPEAT,0,0,640,480,255},
241   {NULL,Bg_overlay_png,IMAGE_VISIBLE|IMAGE_REPEAT,0,0,640,480,255},
242   {NULL,Banner_top_png,IMAGE_VISIBLE|IMAGE_SLIDE_TOP,0,0,640,108,255},
243   {NULL,Banner_bottom_png,IMAGE_VISIBLE|IMAGE_SLIDE_BOTTOM,0,380,640,100,255},
244   {NULL,Main_logo_png,IMAGE_VISIBLE|IMAGE_SLIDE_TOP,466,40,152,44,255}
245 };
246 
247 static gui_image bg_ctrls[] =
248 {
249   {NULL,Bg_layer_png,IMAGE_VISIBLE|IMAGE_REPEAT,0,0,640,480,255},
250   {NULL,Bg_overlay_png,IMAGE_VISIBLE|IMAGE_REPEAT,0,0,640,480,255},
251   {NULL,Banner_top_png,IMAGE_VISIBLE,0,0,640,108,255},
252   {NULL,Banner_bottom_png,IMAGE_VISIBLE,0,380,640,100,255},
253   {NULL,Main_logo_png,IMAGE_VISIBLE,466,40,152,44,255},
254   {NULL,Frame_s2_png,IMAGE_VISIBLE,38,72,316,168,128},
255   {NULL,Frame_s2_png,IMAGE_VISIBLE,38,242,316,168,128},
256   {NULL,Frame_s3_png,IMAGE_SLIDE_RIGHT,400,134,292,248,128}
257 };
258 
259 static gui_image bg_list[] =
260 {
261   {NULL,Bg_layer_png,IMAGE_VISIBLE|IMAGE_REPEAT,0,0,640,480,255},
262   {NULL,Bg_overlay_png,IMAGE_VISIBLE|IMAGE_REPEAT,0,0,640,480,255},
263   {NULL,Banner_top_png,IMAGE_VISIBLE,0,0,640,108,255},
264   {NULL,Banner_bottom_png,IMAGE_VISIBLE,0,380,640,100,255},
265   {NULL,Main_logo_png,IMAGE_VISIBLE,466,40,152,44,255},
266   {NULL,Frame_s1_png,IMAGE_VISIBLE,8,70,372,336,76}
267 };
268 
269 static gui_image bg_saves[] =
270 {
271   {NULL,NULL,0,0,0,0,0,255},
272   {NULL,Bg_layer_png,IMAGE_VISIBLE|IMAGE_REPEAT,0,0,640,480,255},
273   {NULL,Bg_overlay_png,IMAGE_VISIBLE|IMAGE_REPEAT,0,0,640,480,255},
274   {NULL,Banner_top_png,IMAGE_VISIBLE|IMAGE_SLIDE_TOP,0,0,640,108,255},
275   {NULL,Banner_bottom_png,IMAGE_VISIBLE|IMAGE_SLIDE_BOTTOM,0,380,640,100,255},
276   {NULL,Main_logo_png,IMAGE_VISIBLE|IMAGE_SLIDE_TOP,466,40,152,44,255},
277   {NULL,Frame_s1_png,IMAGE_VISIBLE,8,70,372,336,76},
278   {NULL,Frame_s1_png,IMAGE_SLIDE_RIGHT,468,108,372,296,76}
279 };
280 
281 /*****************************************************************************/
282 /*  Menu Items description                                                   */
283 /*****************************************************************************/
284 
285 /* Main menu */
286 static gui_item items_main[] =
287 {
288   {NULL,Main_load_png    ,"","",114,162,80,92},
289   {NULL,Main_options_png ,"","",290,166,60,88},
290   {NULL,Main_quit_png    ,"","",460,170,52,84},
291   {NULL,Main_file_png    ,"","",114,216,80,92},
292   {NULL,Main_reset_png   ,"","",294,227,52,80},
293   {NULL,Main_cheats_png  ,"","",454,218,64,92},
294   {NULL,NULL             ,"","", 10,334,84,32},
295 #ifdef HW_RVL
296   {NULL,Main_play_wii_png,"","", 10,372,84,32},
297 #else
298   {NULL,Main_play_gcn_png,"","", 10,372,84,32},
299 #endif
300   {NULL,Main_takeshot_png,"","",546,334,84,32},
301   {NULL,Main_showinfo_png,"","",546,372,84,32}
302 };
303 
304 /* Controllers menu */
305 static gui_item items_ctrls[] =
306 {
307   {NULL,NULL,"","",  0,  0,  0,  0},
308   {NULL,NULL,"","",  0,  0,  0,  0},
309   {NULL,NULL,"","",305,  0, 24,  0},
310   {NULL,NULL,"","",305,  0, 24,  0},
311   {NULL,NULL,"","",305,  0, 24,  0},
312   {NULL,NULL,"","",305,  0, 24,  0},
313   {NULL,NULL,"","",305,  0, 24,  0},
314   {NULL,NULL,"","",305,  0, 24,  0},
315   {NULL,NULL,"","",305,  0, 24,  0},
316   {NULL,NULL,"","",305,  0, 24,  0},
317   {NULL,NULL,"","",  0,  0,  0,  0},
318   {NULL,NULL,"","",  0,  0,  0,  0},
319   {NULL,Ctrl_config_png,"Keys\nConfig","Configure Controller Keys",530,306,32,32}
320 };
321 
322 /* Load menu */
323 static gui_item items_load[] =
324 {
325   {NULL,Load_recent_png,"","Load recently played games",    119,144,72, 92},
326   {NULL,Load_md_png,    "","Load Mega Drive/Genesis games", 278,141,84, 92},
327   {NULL,Load_cd_png,    "","Load Sega/Mega CD games",       454,141,64, 92},
328   {NULL,Load_ms_png,    "","Load Master System games",      114,284,84, 96},
329   {NULL,Load_gg_png,    "","Load Game Gear games",          278,283,84,100},
330   {NULL,Load_sg_png,    "","Load SG-1000 games",            454,281,64, 96}
331 };
332 
333 /* Option menu */
334 static gui_item items_options[] =
335 {
336   {NULL,Option_system_png,"","System settings",       114,142,80,92},
337   {NULL,Option_video_png, "","Video settings",        288,150,64,84},
338   {NULL,Option_sound_png, "","Audio settings",        464,154,44,80},
339   {NULL,Option_ctrl_png,  "","Controllers settings",  192,286,88,92},
340   {NULL,Option_menu_png,  "","Menu settings",         370,286,60,92}
341 };
342 
343 /* Audio options */
344 static gui_item items_audio[] =
345 {
346   {NULL,NULL,"Master System FM: AUTO",   "Enable/Disable YM2413 chip",                           56,132,276,48},
347   {NULL,NULL,"YM2612 Type: DISCRETE",    "Select YM2612 chip model",                             56,132,276,48},
348   {NULL,NULL,"High-Quality FM: ON",      "Enable/Disable YM2612/YM2413 high-quality resampling", 56,132,276,48},
349   {NULL,NULL,"High-Quality PSG: ON",     "Enable/Disable SN76489 high-quality resampling",       56,132,276,48},
350   {NULL,NULL,"FM Volume: 1.00",          "Adjust YM2612/YM2413 audio balance",                   56,132,276,48},
351   {NULL,NULL,"PSG Volume: 2.50",         "Adjust SN76489 audio balance",                         56,132,276,48},
352   {NULL,NULL,"Audio Output: STEREO",     "Select audio mixing output type",                      56,132,276,48},
353   {NULL,NULL,"Filtering: 3-BAND EQ",     "Select audio filtering type",                          56,132,276,48},
354   {NULL,NULL,"Low Gain: 1.00",           "Adjust EQ Low Band Gain",                              56,132,276,48},
355   {NULL,NULL,"Mid Gain: 1.00",           "Adjust EQ Mid Band Gain",                              56,132,276,48},
356   {NULL,NULL,"High Gain: 1.00",          "Adjust EQ High Band Gain",                             56,132,276,48},
357   {NULL,NULL,"Low Freq: 200 Hz",         "Adjust EQ Lowest Frequency",                           56,132,276,48},
358   {NULL,NULL,"High Freq: 20000 Hz",      "Adjust EQ Highest Frequency",                          56,132,276,48}
359 };
360 
361 /* System ROM paths */
362 static gui_item items_rompaths[] =
363 {
364   {NULL,NULL,"CD BIOS (USA): NOT FOUND",  "Select Sega CD (USA) BIOS",            56,132,276,48},
365   {NULL,NULL,"CD BIOS (PAL): NOT FOUND",  "Select Mega CD (PAL) BIOS",            56,132,276,48},
366   {NULL,NULL,"CD BIOS (JAP): NOT FOUND",  "Select Mega CD (JAP) BIOS",            56,132,276,48},
367   {NULL,NULL,"MD BIOS (TMSS): NOT FOUND", "Select Mega Drive / Genesis BootROM",  56,132,276,48},
368   {NULL,NULL,"MS BIOS (USA): NOT FOUND",  "Select Master System (USA) BootROM",   56,132,276,48},
369   {NULL,NULL,"MS BIOS (PAL): NOT FOUND",  "Select Master System (PAL) BootROM",   56,132,276,48},
370   {NULL,NULL,"MS BIOS (JAP): NOT FOUND",  "Select Master System (JAP) BootROM",   56,132,276,48},
371   {NULL,NULL,"Game Gear BIOS: NOT FOUND", "Select Game Gear BootROM",             56,132,276,48},
372   {NULL,NULL,"Game Genie: NOT FOUND",     "Select Game Genie ROM",                56,132,276,48},
373   {NULL,NULL,"Action Replay: NOT FOUND",  "Select Action Replay (Pro) ROM",       56,132,276,48},
374   {NULL,NULL,"S&K (2MB ROM): NOT FOUND",  "Select Sonic & Knuckle main ROM",      56,132,276,48},
375   {NULL,NULL,"S2&K (256K ROM): NOT FOUND","Select Sonic 2 & Knuckle upmem ROM",   56,132,276,48},
376 };
377 
378 /* System options */
379 static gui_item items_system[] =
380 {
381   {NULL,NULL,"Console Hardware: AUTO",  "Select system hardware model",                56,132,276,48},
382   {NULL,NULL,"Console Region: AUTO",    "Select system region",                        56,132,276,48},
383   {NULL,NULL,"VDP Mode: AUTO",          "Select VDP mode",                             56,132,276,48},
384   {NULL,NULL,"System Clock: AUTO",      "Select system clock frequency",               56,132,276,48},
385   {NULL,NULL,"System Boot: BIOS&CART",  "Select system booting method",                56,132,276,48},
386   {NULL,NULL,"System Lockups: ON",      "Enable/Disable original system lock-ups",     56,132,276,48},
387   {NULL,NULL,"68k Address Error: ON",   "Enable/Disable 68k address error exceptions", 56,132,276,48},
388   {NULL,NULL,"Lock-on: OFF",            "Select Lock-On cartridge type",               56,132,276,48},
389   {NULL,NULL,"Cartridge Swap: OFF",     "Enable/Disable cartridge hot swap",           56,132,276,48},
390   {NULL,NULL,"BIOS & Lock-On ROM paths","Configure BIOS & Lock-On ROM paths",          56,132,276,48},
391   {NULL,NULL,"SVP Cycles: 1500",        "Adjust SVP chip emulation speed",             56,132,276,48}
392 };
393 
394 /* Video options */
395 static gui_item items_video[] =
396 {
397   {NULL,NULL,"Display: PROGRESSIVE",        "Select video mode",                                 56,132,276,48},
398   {NULL,NULL,"TV mode: 50/60HZ",            "Select video refresh rate",                         56,132,276,48},
399   {NULL,NULL,"VSYNC: AUTO",                 "Enable/Disable sync with video hardware",           56,132,276,48},
400   {NULL,NULL,"Bilinear Filter: OFF",        "Enable/Disable GX hardware texture filtering",      56,132,276,48},
401   {NULL,NULL,"Deflickering Filter: AUTO",   "Enable/Disable GX hardware framebuffer filtering",  56,132,276,48},
402 #ifdef HW_RVL
403   {NULL,NULL,"Trap Filter: ON",             "Enable/Disable VI hardware composite out filtering",56,132,276,48},
404   {NULL,NULL,"Gamma Correction: 1.0",       "Adjust VI hardware gamma correction",               56,132,276,48},
405 #endif
406   {NULL,NULL,"LCD Ghosting Filter: OFF",    "Enable/Disable software LCD image persistence",     56,132,276,48},
407   {NULL,NULL,"NTSC Filter: COMPOSITE",      "Enable/Disable software NTSC filtering",            56,132,276,48},
408   {NULL,NULL,"NTSC Sharpness: 0.0",         "Adjust edge contrast enhancement/blurring",         56,132,276,48},
409   {NULL,NULL,"NTSC Resolution: 0.0",        "Adjust image resolution",                           56,132,276,48},
410   {NULL,NULL,"NTSC Artifacts: 0.0",         "Adjust artifacts caused by color changes",          56,132,276,48},
411   {NULL,NULL,"NTSC Color Bleed: 0.0",       "Adjust color resolution reduction",                 56,132,276,48},
412   {NULL,NULL,"NTSC Color Fringing: 0.0",    "Adjust artifacts caused by brightness changes",     56,132,276,48},
413   {NULL,NULL,"Borders: OFF",                "Enable/Disable overscan emulation",                 56,132,276,48},
414   {NULL,NULL,"GG screen: ORIGINAL",         "Enable/Disable Game Gear extended screen",          56,132,276,48},
415   {NULL,NULL,"Aspect: ORIGINAL (4:3)",      "Select display aspect ratio",                       56,132,276,48},
416   {NULL,NULL,"Screen Position (+0,+0)",     "Adjust display position",                           56,132,276,48},
417   {NULL,NULL,"Screen Scaling (+0,+0)",      "Adjust display scaling",                            56,132,276,48}
418 };
419 
420 /* Menu options */
421 static gui_item items_prefs[] =
422 {
423   {NULL,NULL,"Auto ROM Load: OFF",  "Enable/Disable automatic ROM loading on startup", 56,132,276,48},
424   {NULL,NULL,"Auto Cheats: OFF",    "Enable/Disable automatic cheats activation",      56,132,276,48},
425   {NULL,NULL,"Auto Saves: OFF",     "Enable/Disable automatic saves",                  56,132,276,48},
426   {NULL,NULL,"ROM Load Device: SD", "Configure default device for ROM files",          56,132,276,48},
427   {NULL,NULL,"Saves Device: FAT",   "Configure default device for Save files",         56,132,276,48},
428   {NULL,NULL,"SFX Volume: 100",     "Adjust sound effects volume",                     56,132,276,48},
429   {NULL,NULL,"BGM Volume: 100",     "Adjust background music volume",                  56,132,276,48},
430   {NULL,NULL,"BG Overlay: ON",      "Enable/Disable background overlay",               56,132,276,48},
431   {NULL,NULL,"Screen Width: 658",   "Adjust menu screen width in pixels",              56,132,276,48},
432   {NULL,NULL,"Show CD Leds: OFF",   "Enable/Disable CD leds display",                  56,132,276,48},
433   {NULL,NULL,"Show FPS: OFF",       "Enable/Disable FPS counter",                      56,132,276,48},
434 #ifdef HW_RVL
435   {NULL,NULL,"Wiimote Timeout: OFF","Enable/Disable Wii remote automatic shutdown",    56,132,276,48},
436   {NULL,NULL,"Wiimote Calibration: AUTO","Calibrate Wii remote pointer",               56,132,276,48},
437 #endif
438 };
439 
440 /* Save Manager */
441 static gui_item items_saves[] =
442 {
443   {NULL,NULL,"",""                   ,0,0,0,0},
444   {NULL,NULL,"",""                   ,0,0,0,0},
445   {NULL,NULL,"",""                   ,0,0,0,0},
446   {NULL,NULL,"",""                   ,0,0,0,0},
447   {NULL,NULL,"",""                   ,0,0,0,0},
448   {NULL,NULL,"","Load file"          ,0,0,0,0},
449   {NULL,NULL,"","Set as default file",0,0,0,0},
450   {NULL,NULL,"","Delete file"        ,0,0,0,0},
451   {NULL,NULL,"","Save file"          ,0,0,0,0}
452 };
453 
454 /*****************************************************************************/
455 /*  Menu Buttons description                                                 */
456 /*****************************************************************************/
457 
458 /* Generic Buttons for list menu */
459 static gui_butn arrow_up = {&arrow_up_data,BUTTON_ACTIVE|BUTTON_OVER_SFX,{0,0,0,0},14,76,360,32};
460 static gui_butn arrow_down = {&arrow_down_data,BUTTON_ACTIVE|BUTTON_OVER_SFX,{0,0,0,0},14,368,360,32};
461 
462 /* Generic list menu */
463 static gui_butn buttons_list[] =
464 {
465   {&button_text_data,BUTTON_VISIBLE|BUTTON_ACTIVE|BUTTON_OVER_SFX,{1,1,0,0},56,132,276,48},
466   {&button_text_data,BUTTON_VISIBLE|BUTTON_ACTIVE|BUTTON_OVER_SFX,{1,1,0,0},56,188,276,48},
467   {&button_text_data,BUTTON_VISIBLE|BUTTON_ACTIVE|BUTTON_OVER_SFX,{1,1,0,0},56,244,276,48},
468   {&button_text_data,BUTTON_VISIBLE|BUTTON_ACTIVE|BUTTON_OVER_SFX,{1,1,0,0},56,300,276,48}
469 };
470 
471 /* Main menu */
472 static gui_butn buttons_main[] =
473 {
474   {&button_icon_data,BUTTON_VISIBLE|BUTTON_ACTIVE|BUTTON_OVER_SFX|BUTTON_SELECT_SFX,{0,0,0,1}, 80,140,148,132},
475   {&button_icon_data,BUTTON_VISIBLE|BUTTON_ACTIVE|BUTTON_OVER_SFX|BUTTON_SELECT_SFX,{0,0,1,1},246,140,148,132},
476   {&button_icon_data,BUTTON_VISIBLE|BUTTON_ACTIVE|BUTTON_OVER_SFX|BUTTON_SELECT_SFX,{0,0,1,0},412,140,148,132},
477   {&button_icon_data,                             BUTTON_OVER_SFX|BUTTON_SELECT_SFX,{3,4,0,1}, 80,194,148,132},
478   {&button_icon_data,                             BUTTON_OVER_SFX                  ,{3,4,1,1},246,194,148,132},
479   {&button_icon_data,                             BUTTON_OVER_SFX|BUTTON_SELECT_SFX,{3,3,1,0},412,194,148,132},
480   {NULL             ,                             BUTTON_OVER_SFX                  ,{3,1,0,2}, 10,334, 84, 32},
481   {NULL             ,                             BUTTON_OVER_SFX                  ,{4,0,0,2}, 10,372, 84, 32},
482   {NULL             ,                             BUTTON_OVER_SFX|BUTTON_SELECT_SFX,{3,1,1,0},546,334, 84, 32},
483   {NULL             ,                             BUTTON_OVER_SFX|BUTTON_SELECT_SFX,{1,0,2,0},546,372, 84, 32}
484 };
485 
486 /* Controllers Menu */
487 static gui_butn buttons_ctrls[] =
488 {
489   {&button_icon_data    ,BUTTON_VISIBLE|BUTTON_ACTIVE|BUTTON_OVER_SFX                  ,{0,1,0,2}, 60, 88,148,132},
490   {&button_icon_data    ,BUTTON_VISIBLE|BUTTON_ACTIVE|BUTTON_OVER_SFX                  ,{1,0,0,5}, 60,258,148,132},
491   {NULL                 ,BUTTON_VISIBLE|BUTTON_ACTIVE|BUTTON_OVER_SFX|BUTTON_SELECT_SFX,{0,1,2,0},250, 79, 84, 32},
492   {NULL                 ,BUTTON_VISIBLE|BUTTON_ACTIVE|BUTTON_OVER_SFX|BUTTON_SELECT_SFX,{1,1,3,0},250,117, 84, 32},
493   {NULL                 ,BUTTON_VISIBLE|BUTTON_ACTIVE|BUTTON_OVER_SFX|BUTTON_SELECT_SFX,{1,1,4,0},250,155, 84, 32},
494   {NULL                 ,BUTTON_VISIBLE|BUTTON_ACTIVE|BUTTON_OVER_SFX|BUTTON_SELECT_SFX,{1,1,5,0},250,193, 84, 32},
495   {NULL                 ,BUTTON_VISIBLE|BUTTON_ACTIVE|BUTTON_OVER_SFX|BUTTON_SELECT_SFX,{1,1,5,0},250,249, 84, 32},
496   {NULL                 ,BUTTON_VISIBLE|BUTTON_ACTIVE|BUTTON_OVER_SFX|BUTTON_SELECT_SFX,{1,1,6,0},250,287, 84, 32},
497   {NULL                 ,BUTTON_VISIBLE|BUTTON_ACTIVE|BUTTON_OVER_SFX|BUTTON_SELECT_SFX,{1,1,7,0},250,325, 84, 32},
498   {NULL                 ,BUTTON_VISIBLE|BUTTON_ACTIVE|BUTTON_OVER_SFX|BUTTON_SELECT_SFX,{1,0,8,0},250,363, 84, 32},
499   {&button_icon_sm_data ,BUTTON_SLIDE_RIGHT|BUTTON_OVER_SFX                            ,{0,1,1,0},436,168,160, 52},
500   {&button_icon_sm_data ,BUTTON_SLIDE_RIGHT|BUTTON_OVER_SFX                            ,{1,1,0,0},436,232,160, 52},
501   {&button_icon_sm_data ,BUTTON_SLIDE_RIGHT|BUTTON_OVER_SFX|BUTTON_SELECT_SFX          ,{1,0,0,0},436,296,160, 52}
502 };
503 
504 /* Load Game menu */
505 static gui_butn buttons_load[] =
506 {
507   {&button_icon_data,BUTTON_VISIBLE|BUTTON_ACTIVE|BUTTON_OVER_SFX|BUTTON_SELECT_SFX,{0,3,0,1}, 80,120,148,132},
508   {&button_icon_data,BUTTON_VISIBLE|BUTTON_ACTIVE|BUTTON_OVER_SFX|BUTTON_SELECT_SFX,{0,3,1,1},246,120,148,132},
509   {&button_icon_data,BUTTON_VISIBLE|BUTTON_ACTIVE|BUTTON_OVER_SFX|BUTTON_SELECT_SFX,{0,3,1,0},412,120,148,132},
510   {&button_icon_data,BUTTON_VISIBLE|BUTTON_ACTIVE|BUTTON_OVER_SFX|BUTTON_SELECT_SFX,{3,0,0,1}, 80,264,148,132},
511   {&button_icon_data,BUTTON_VISIBLE|BUTTON_ACTIVE|BUTTON_OVER_SFX|BUTTON_SELECT_SFX,{3,0,1,1},246,264,148,132},
512   {&button_icon_data,BUTTON_VISIBLE|BUTTON_ACTIVE|BUTTON_OVER_SFX|BUTTON_SELECT_SFX,{3,0,1,0},412,264,148,132}
513 };
514 
515 /* Options menu */
516 static gui_butn buttons_options[] =
517 {
518   {&button_icon_data,BUTTON_VISIBLE|BUTTON_ACTIVE|BUTTON_OVER_SFX|BUTTON_SELECT_SFX,{0,3,0,1}, 80,120,148,132},
519   {&button_icon_data,BUTTON_VISIBLE|BUTTON_ACTIVE|BUTTON_OVER_SFX|BUTTON_SELECT_SFX,{0,3,1,1},246,120,148,132},
520   {&button_icon_data,BUTTON_VISIBLE|BUTTON_ACTIVE|BUTTON_OVER_SFX|BUTTON_SELECT_SFX,{0,2,1,1},412,120,148,132},
521   {&button_icon_data,BUTTON_VISIBLE|BUTTON_ACTIVE|BUTTON_OVER_SFX|BUTTON_SELECT_SFX,{3,0,1,1},162,264,148,132},
522   {&button_icon_data,BUTTON_VISIBLE|BUTTON_ACTIVE|BUTTON_OVER_SFX|BUTTON_SELECT_SFX,{2,0,1,0},330,264,148,132}
523 };
524 
525 /* Save Manager Menu */
526 static gui_butn buttons_saves[] =
527 {
528   {&button_text_data   ,BUTTON_VISIBLE|BUTTON_ACTIVE|BUTTON_OVER_SFX,{0,1,0,0}, 56,102,276,48},
529   {&button_text_data   ,BUTTON_VISIBLE|BUTTON_ACTIVE|BUTTON_OVER_SFX,{1,1,0,0}, 56,158,276,48},
530   {&button_text_data   ,BUTTON_VISIBLE|BUTTON_ACTIVE|BUTTON_OVER_SFX,{1,1,0,0}, 56,214,276,48},
531   {&button_text_data   ,BUTTON_VISIBLE|BUTTON_ACTIVE|BUTTON_OVER_SFX,{1,1,0,0}, 56,270,276,48},
532   {&button_text_data   ,BUTTON_VISIBLE|BUTTON_ACTIVE|BUTTON_OVER_SFX,{1,0,0,0}, 56,326,276,48},
533   {&button_load_data   ,BUTTON_ACTIVE|BUTTON_SLIDE_RIGHT|BUTTON_OVER_SFX,{0,1,0,0},530,130, 56,56},
534   {&button_special_data,BUTTON_ACTIVE|BUTTON_SLIDE_RIGHT|BUTTON_OVER_SFX,{1,1,0,0},530,196, 56,56},
535   {&button_delete_data ,BUTTON_ACTIVE|BUTTON_SLIDE_RIGHT|BUTTON_OVER_SFX,{1,1,0,0},530,262, 56,56},
536   {&button_save_data   ,BUTTON_ACTIVE|BUTTON_SLIDE_RIGHT|BUTTON_OVER_SFX,{1,0,0,0},530,328, 56,56}
537 };
538 
539 /*****************************************************************************/
540 /*  Menu descriptions                                                        */
541 /*****************************************************************************/
542 
543 /* Main menu */
544 static gui_menu menu_main =
545 {
546   "",
547   0,0,
548   10,10,4,0,
549   items_main,
550   buttons_main,
551   bg_main,
552   {NULL,NULL},
553   {NULL,NULL},
554   NULL
555 };
556 
557 /* Main menu */
558 gui_menu menu_ctrls =
559 {
560   "Controller Settings",
561   0,0,
562   13,13,8,0,
563   items_ctrls,
564   buttons_ctrls,
565   bg_ctrls,
566   {&action_cancel, &action_select},
567   {NULL,NULL},
568   ctrlmenu_cb
569 };
570 
571 /* Load Game menu */
572 static gui_menu menu_load =
573 {
574   "Load Game",
575   0,0,
576   6,6,5,0,
577   items_load,
578   buttons_load,
579   bg_misc,
580   {&action_cancel, &action_select},
581   {NULL,NULL},
582   NULL
583 };
584 
585 /* Options menu */
586 static gui_menu menu_options =
587 {
588   "Settings",
589   0,0,
590   5,5,5,0,
591   items_options,
592   buttons_options,
593   bg_misc,
594   {&action_cancel, &action_select},
595   {NULL,NULL},
596   NULL
597 };
598 
599 /* System ROM Path submenu */
600 static gui_menu menu_rompaths =
601 {
602   "System ROM Paths",
603   0,0,
604   12,4,6,0,
605   items_rompaths,
606   buttons_list,
607   bg_list,
608   {&action_cancel, &action_select},
609   {&arrow_up,&arrow_down},
610   NULL
611 };
612 
613 /* System Options menu */
614 static gui_menu menu_system =
615 {
616   "System Settings",
617   0,0,
618   0,4,6,0,
619   items_system,
620   buttons_list,
621   bg_list,
622   {&action_cancel, &action_select},
623   {&arrow_up,&arrow_down},
624   NULL
625 };
626 
627 /* Video Options menu */
628 static gui_menu menu_video =
629 {
630   "Video Settings",
631   0,0,
632   0,4,6,0,
633   items_video,
634   buttons_list,
635   bg_list,
636   {&action_cancel, &action_select},
637   {&arrow_up,&arrow_down},
638   NULL
639 };
640 
641 /* Sound Options menu */
642 static gui_menu menu_audio =
643 {
644   "Audio Settings",
645   0,0,
646   0,4,6,0,
647   items_audio,
648   buttons_list,
649   bg_list,
650   {&action_cancel, &action_select},
651   {&arrow_up,&arrow_down},
652   NULL
653 };
654 
655 /* Sound Options menu */
656 static gui_menu menu_prefs =
657 {
658   "Menu Settings",
659   0,0,
660   0,4,6,0,
661   items_prefs,
662   buttons_list,
663   bg_list,
664   {&action_cancel, &action_select},
665   {&arrow_up,&arrow_down},
666   NULL
667 };
668 
669 
670 /* Save Manager menu */
671 static gui_menu menu_saves =
672 {
673   "Save Manager",
674   0,0,
675   9,9,8,0,
676   items_saves,
677   buttons_saves,
678   bg_saves,
679   {&action_cancel, &action_select},
680   {NULL,NULL},
681   savemenu_cb
682 };
683 
684 /****************************************************************************
685  * GUI Settings menu
686  *
687  ****************************************************************************/
update_screen_w(void)688 static void update_screen_w(void)
689 {
690   vmode->viWidth    = config.screen_w;
691   vmode->viXOrigin  = (VI_MAX_WIDTH_NTSC -config.screen_w)/2;
692   VIDEO_Configure(vmode);
693   VIDEO_Flush();
694 }
695 
update_bgm(void)696 static void update_bgm(void)
697 {
698   SetVolumeOgg(((int)config.bgm_volume * 255) / 100);
699 }
700 
prefmenu()701 static void prefmenu ()
702 {
703   int ret, quit = 0;
704   gui_menu *m = &menu_prefs;
705   gui_item *items = m->items;
706 
707   sprintf (items[0].text, "Auto ROM Load: %s", config.autoload ? "ON":"OFF");
708   sprintf (items[1].text, "Auto Cheats: %s", config.autocheat ? "ON":"OFF");
709   if (config.s_auto == 3) sprintf (items[2].text, "Auto Saves: ALL");
710   else if (config.s_auto == 2) sprintf (items[2].text, "Auto Saves: STATE ONLY");
711   else if (config.s_auto == 1) sprintf (items[2].text, "Auto Saves: SRAM ONLY");
712   else sprintf (items[2].text, "Auto Saves: NONE");
713 #ifdef HW_RVL
714   if (config.l_device == 1) sprintf (items[3].text, "ROM Load Device: USB");
715   else if (config.l_device == 2) sprintf (items[3].text, "ROM Load Device: DVD");
716 #else
717   if (config.l_device == 1) sprintf (items[3].text, "ROM Load Device: DVD");
718 #endif
719   else sprintf (items[3].text, "ROM Load Device: SD");
720   if (config.s_device == 1) sprintf (items[4].text, "Saves Device: MCARD A");
721   else if (config.s_device == 2) sprintf (items[4].text, "Saves Device: MCARD B");
722   else sprintf (items[4].text, "Saves Device: FAT");
723   sprintf (items[5].text, "SFX Volume: %1.1f", config.sfx_volume);
724   sprintf (items[6].text, "BGM Volume: %1.1f", config.bgm_volume);
725   sprintf (items[7].text, "BG Overlay: %s", config.bg_overlay ? "ON":"OFF");
726   sprintf (items[8].text, "Screen Width: %d", config.screen_w);
727   sprintf (items[9].text, "Show CD Leds: %s", config.cd_leds ? "ON":"OFF");
728   sprintf (items[10].text, "Show FPS: %s", config.fps ? "ON":"OFF");
729 #ifdef HW_RVL
730   sprintf (items[11].text, "Wiimote Timeout: %s", config.autosleep ? "5 MIN":"30 MIN");
731   sprintf (items[12].text, "Wiimote Calibration: %s", ((config.calx * config.caly) != 0) ? "MANUAL":"AUTO");
732   sprintf (items[12].comment, "%s", ((config.calx * config.caly) != 0) ? "Reset default Wii remote pointer calibration":"Calibrate Wii remote pointer");
733   m->max_items = 13;
734 #else
735   m->max_items = 11;
736 #endif
737 
738   GUI_InitMenu(m);
739   GUI_SlideMenuTitle(m,strlen("Menu "));
740 
741   while (quit == 0)
742   {
743     ret = GUI_RunMenu(m);
744 
745     switch (ret)
746     {
747       case 0:   /* Auto load last ROM file on startup */
748         config.autoload ^= 1;
749         sprintf (items[0].text, "Auto ROM Load: %s", config.autoload ? "ON":"OFF");
750         break;
751 
752       case 1:   /* Cheats automatic activation */
753         config.autocheat ^= 1;
754         sprintf (items[1].text, "Auto Cheats: %s", config.autocheat ? "ON":"OFF");
755         break;
756 
757       case 2:  /*** Auto load/save STATE & SRAM files ***/
758         config.s_auto = (config.s_auto + 1) % 4;
759         if (config.s_auto == 3) sprintf (items[2].text, "Auto Saves: ALL");
760         else if (config.s_auto == 2) sprintf (items[2].text, "Auto Saves: STATE ONLY");
761         else if (config.s_auto == 1) sprintf (items[2].text, "Auto Saves: SRAM ONLY");
762         else sprintf (items[2].text, "Auto Saves: NONE");
763         break;
764 
765       case 3:   /*** Default ROM device ***/
766 #ifdef HW_RVL
767         config.l_device = (config.l_device + 1) % 3;
768         if (config.l_device == 1) sprintf (items[3].text, "ROM Load Device: USB");
769         else if (config.l_device == 2) sprintf (items[3].text, "ROM Load Device: DVD");
770 #else
771         config.l_device ^= 1;
772         if (config.l_device == 1) sprintf (items[3].text, "ROM Load Device: DVD");
773 #endif
774         else sprintf (items[3].text, "ROM Load Device: SD");
775         break;
776 
777       case 4:   /*** Default saves device ***/
778         config.s_device = (config.s_device + 1) % 3;
779         if (config.s_device == 1) sprintf (items[4].text, "Saves Device: MCARD A");
780         else if (config.s_device == 2) sprintf (items[4].text, "Saves Device: MCARD B");
781         else sprintf (items[4].text, "Saves Device: FAT");
782         break;
783 
784       case 5:   /*** Sound effects volume ***/
785         GUI_OptionBox(m,0,"SFX Volume",(void *)&config.sfx_volume,10.0,0.0,100.0,0);
786         sprintf (items[5].text, "SFX Volume: %1.1f", config.sfx_volume);
787         break;
788 
789       case 6:   /*** Background music volume ***/
790         GUI_OptionBox(m,update_bgm,"BGM Volume",(void *)&config.bgm_volume,10.0,0.0,100.0,0);
791         sprintf (items[6].text, "BGM Volume: %1.1f", config.bgm_volume);
792         break;
793 
794       case 7:   /*** Background overlay ***/
795         config.bg_overlay ^= 1;
796         if (config.bg_overlay)
797         {
798           bg_main[1].state  |= IMAGE_VISIBLE;
799           bg_misc[1].state  |= IMAGE_VISIBLE;
800           bg_ctrls[1].state |= IMAGE_VISIBLE;
801           bg_list[1].state  |= IMAGE_VISIBLE;
802           bg_saves[2].state |= IMAGE_VISIBLE;
803           sprintf (items[7].text, "BG Overlay: ON");
804         }
805         else
806         {
807           bg_main[1].state  &= ~IMAGE_VISIBLE;
808           bg_misc[1].state  &= ~IMAGE_VISIBLE;
809           bg_ctrls[1].state &= ~IMAGE_VISIBLE;
810           bg_list[1].state  &= ~IMAGE_VISIBLE;
811           bg_saves[2].state &= ~IMAGE_VISIBLE;
812           sprintf (items[7].text, "BG Overlay: OFF");
813         }
814         break;
815 
816       case 8:   /*** Screen Width ***/
817         GUI_OptionBox(m,update_screen_w,"Screen Width",(void *)&config.screen_w,2,640,VI_MAX_WIDTH_NTSC,1);
818         sprintf (items[8].text, "Screen Width: %d", config.screen_w);
819         break;
820 
821       case 9:   /*** CD LEDS ***/
822         config.cd_leds ^= 1;
823         sprintf (items[9].text, "Show CD Leds: %s", config.cd_leds ? "ON":"OFF");
824         break;
825 
826       case 10:   /*** FPS counter ***/
827         config.fps ^= 1;
828         sprintf (items[10].text, "Show FPS: %s", config.fps ? "ON":"OFF");
829         break;
830 
831 #ifdef HW_RVL
832       case 11:   /*** Wii remote auto switch-off ***/
833         config.autosleep ^= 1;
834         sprintf (items[11].text, "Wiimote Timeout: %s", config.autosleep ? "5min":"30min");
835         WPAD_SetIdleTimeout(config.autosleep ? 300 : 1800);
836         break;
837 
838       case 12:   /*** Wii remote pointer calibration ***/
839         if ((config.calx * config.caly) == 0)
840         {
841           if (GUI_WaitConfirm("Pointer Calibration","Aim center of TV screen"))
842           {
843             sprintf (items[12].text, "Wiimote Calibration: MANUAL");
844             sprintf (items[12].comment, "Reset default Wii remote pointer calibration");
845             config.calx = 320 - m_input.ir.x;
846             config.caly = 240 - m_input.ir.y;
847             m_input.ir.x = 320;
848             m_input.ir.y = 240;
849           }
850         }
851         else
852         {
853           sprintf (items[12].text, "Wiimote Calibration: AUTO");
854           sprintf (items[12].comment, "Calibrate Wii remote pointer");
855           config.calx = config.caly = 0;
856         }
857         break;
858 #endif
859 
860       case -1:
861         quit = 1;
862         break;
863     }
864   }
865 
866   /* stop DVD drive when not in use */
867   if (config.l_device != 2)
868   {
869 #ifdef HW_RVL
870     DI_StopMotor();
871 #else
872     vu32* const dvd = (u32*)0xCC006000;
873     dvd[0] = 0x2e;
874     dvd[1] = 0;
875     dvd[2] = 0xe3000000;
876     dvd[3] = 0;
877     dvd[4] = 0;
878     dvd[5] = 0;
879     dvd[6] = 0;
880     dvd[7] = 1;
881     while (dvd[7] & 1);
882 #endif
883   }
884 
885   GUI_DeleteMenu(m);
886 }
887 
888 /****************************************************************************
889  * Audio Settings menu
890  *
891  ****************************************************************************/
soundmenu()892 static void soundmenu ()
893 {
894   int ret, quit = 0;
895   float fm_volume = (float)config.fm_preamp/100.0;
896   float psg_volume = (float)config.psg_preamp/100.0;
897   gui_menu *m = &menu_audio;
898   gui_item *items = m->items;
899 
900   if (config.ym2413 == 0) sprintf (items[0].text, "Master System FM: OFF");
901   else if (config.ym2413 == 1) sprintf (items[0].text, "Master System FM: ON");
902   else sprintf (items[0].text, "Master System FM: AUTO");
903 
904   if (config.ym2612 == YM2612_DISCRETE) sprintf (items[1].text, "YM2612 Type: DISCRETE");
905   else if (config.ym2612 == YM2612_INTEGRATED) sprintf (items[1].text, "YM2612 Type: ASIC");
906   else sprintf (items[1].text, "YM2612 Type: ENHANCED");
907 
908   sprintf (items[2].text, "High-Quality FM: %s", config.hq_fm ? "ON":"OFF");
909   sprintf (items[3].text, "High-Quality PSG: %s", config.hq_psg? "ON":"OFF");
910 
911   sprintf (items[4].text, "FM Volume: %1.2f", fm_volume);
912   sprintf (items[5].text, "PSG Volume: %1.2f", psg_volume);
913 
914   sprintf (items[6].text, "Audio Output: %s", config.mono ? "MONO":"STEREO");
915 
916   if (config.filter == 2)
917   {
918     float lg = (float)config.lg/100.0;
919     float mg = (float)config.mg/100.0;
920     float hg = (float)config.hg/100.0;
921 
922     sprintf(items[7].text, "Filtering: 3-BAND EQ");
923     sprintf(items[8].text, "Low Gain: %1.2f", lg);
924     strcpy(items[8].comment, "Adjust EQ Low Band Gain");
925     sprintf(items[9].text, "Middle Gain: %1.2f", mg);
926     sprintf(items[10].text, "High Gain: %1.2f", hg);
927     sprintf(items[11].text, "Low Freq: %d", config.low_freq);
928     sprintf(items[12].text, "High Freq: %d", config.high_freq);
929     m->max_items = 13;
930   }
931   else if (config.filter == 1)
932   {
933     int16 lp_range = (config.lp_range * 100 + 0xffff) / 0x10000;
934     sprintf (items[7].text, "Filtering: LOW-PASS");
935     sprintf (items[8].text, "Low-Pass Rate: %d %%", lp_range);
936     strcpy (items[8].comment, "Adjust Low Pass filter");
937     m->max_items = 9;
938   }
939   else
940   {
941     sprintf (items[7].text, "Filtering: OFF");
942     m->max_items = 8;
943   }
944 
945   GUI_InitMenu(m);
946   GUI_SlideMenuTitle(m,strlen("Audio "));
947 
948   while (quit == 0)
949   {
950     ret = GUI_RunMenu(m);
951 
952     switch (ret)
953     {
954       case 0:
955       {
956         config.ym2413++;
957         if (config.ym2413 > 2) config.ym2413 = 0;
958         if (config.ym2413 == 0) sprintf (items[0].text, "Master System FM: OFF");
959         else if (config.ym2413 == 1) sprintf (items[0].text, "Master System FM: ON");
960         else sprintf (items[0].text, "Master System FM: AUTO");
961 
962         /* Automatic detection */
963         if ((config.ym2413 & 2) && system_hw && ((system_hw & SYSTEM_PBC) != SYSTEM_MD))
964         {
965           /* detect if game is using YM2413 */
966           sms_cart_init();
967 
968           /* restore SRAM */
969           slot_autoload(0,config.s_device);
970         }
971         break;
972       }
973 
974       case 1:
975       {
976         config.ym2612++;
977         if (config.ym2612 > YM2612_ENHANCED) config.ym2612 = YM2612_DISCRETE;
978         if (config.ym2612 == YM2612_DISCRETE) sprintf (items[1].text, "YM2612 Type: DISCRETE");
979         else if (config.ym2612 == YM2612_INTEGRATED) sprintf (items[1].text, "YM2612 Type: ASIC");
980         else sprintf (items[1].text, "YM2612 Type: ENHANCED");
981         YM2612Config(config.ym2612);
982         break;
983       }
984 
985       case 2:
986       {
987         config.hq_fm ^= 1;
988         sprintf (items[2].text, "High-Quality FM: %s", config.hq_fm ? "ON":"OFF");
989         break;
990       }
991 
992       case 3:
993       {
994         config.hq_psg ^= 1;
995         sprintf (items[3].text, "High-Quality PSG: %s", config.hq_psg ? "ON":"OFF");
996         break;
997       }
998 
999       case 4:
1000       {
1001         GUI_OptionBox(m,0,"FM Volume",(void *)&fm_volume,0.01,0.0,5.0,0);
1002         sprintf (items[4].text, "FM Volume: %1.2f", fm_volume);
1003         config.fm_preamp = (int)(fm_volume * 100.0 + 0.5);
1004         break;
1005       }
1006 
1007       case 5:
1008       {
1009         GUI_OptionBox(m,0,"PSG Volume",(void *)&psg_volume,0.01,0.0,5.0,0);
1010         sprintf (items[5].text, "PSG Volume: %1.2f", psg_volume);
1011         config.psg_preamp = (int)(psg_volume * 100.0 + 0.5);
1012         if ((system_hw & SYSTEM_PBC) == SYSTEM_MD)
1013         {
1014           psg_config(0, config.psg_preamp, 0xff);
1015         }
1016         else
1017         {
1018           psg_config(0, config.psg_preamp, io_reg[6]);
1019         }
1020         break;
1021       }
1022 
1023       case 6:
1024       {
1025         config.mono ^= 1;
1026         sprintf (items[6].text, "Audio Out: %s", config.mono ? "MONO":"STEREO");
1027         break;
1028       }
1029 
1030       case 7:
1031       {
1032         config.filter = (config.filter + 1) % 3;
1033         if (config.filter == 2)
1034         {
1035           float lg = (float)config.lg/100.0;
1036           sprintf (items[7].text, "Filtering: 3-BAND EQ");
1037           sprintf (items[8].text, "Low Gain: %1.2f", lg);
1038           strcpy (items[8].comment, "Adjust EQ Low Band Gain");
1039           m->max_items = 13;
1040           audio_set_equalizer();
1041         }
1042         else if (config.filter == 1)
1043         {
1044           int lp_range = (config.lp_range * 100 + 0xffff) / 0x10000;
1045           sprintf (items[7].text, "Filtering: LOW-PASS");
1046           sprintf (items[8].text, "Low-Pass Rate: %d %%", lp_range);
1047           strcpy (items[8].comment, "Adjust Low Pass filter");
1048           m->max_items = 9;
1049         }
1050         else
1051         {
1052           sprintf (items[7].text, "Filtering: OFF");
1053           m->max_items = 8;
1054         }
1055 
1056         while ((m->offset + 4) > m->max_items)
1057         {
1058           m->offset--;
1059           m->selected++;
1060         }
1061         break;
1062       }
1063 
1064       case 8:
1065       {
1066         if (config.filter == 1)
1067         {
1068           int16 lp_range = (config.lp_range * 100 + 0xffff) / 0x10000;
1069           GUI_OptionBox(m,0,"Low-Pass Rate (%)",(void *)&lp_range,1,0,100,1);
1070           sprintf (items[8].text, "Low-Pass Rate: %d %%", lp_range);
1071           config.lp_range = (lp_range * 0x10000) / 100;
1072         }
1073         else
1074         {
1075           float lg = (float)config.lg/100.0;
1076           GUI_OptionBox(m,0,"Low Gain",(void *)&lg,0.01,0.0,2.0,0);
1077           sprintf (items[8].text, "Low Gain: %1.2f", lg);
1078           config.lg = (int)(lg * 100.0);
1079           audio_set_equalizer();
1080         }
1081         break;
1082       }
1083 
1084       case 9:
1085       {
1086         float mg = (float)config.mg/100.0;
1087         GUI_OptionBox(m,0,"Middle Gain",(void *)&mg,0.01,0.0,2.0,0);
1088         sprintf (items[9].text, "Middle Gain: %1.2f", mg);
1089         config.mg = (int)(mg * 100.0);
1090         audio_set_equalizer();
1091         break;
1092       }
1093 
1094       case 10:
1095       {
1096         float hg = (float)config.hg/100.0;
1097         GUI_OptionBox(m,0,"High Gain",(void *)&hg,0.01,0.0,2.0,0);
1098         sprintf (items[10].text, "High Gain: %1.2f", hg);
1099         config.hg = (int)(hg * 100.0);
1100         audio_set_equalizer();
1101         break;
1102       }
1103 
1104       case 11:
1105       {
1106         GUI_OptionBox(m,0,"Low Frequency",(void *)&config.low_freq,10,0,config.high_freq,1);
1107         sprintf (items[11].text, "Low Freq: %d", config.low_freq);
1108         audio_set_equalizer();
1109         break;
1110       }
1111 
1112       case 12:
1113       {
1114         GUI_OptionBox(m,0,"High Frequency",(void *)&config.high_freq,100,config.low_freq,30000,1);
1115         sprintf (items[12].text, "High Freq: %d", config.high_freq);
1116         audio_set_equalizer();
1117         break;
1118       }
1119 
1120       case -1:
1121       {
1122         quit = 1;
1123         break;
1124       }
1125     }
1126   }
1127 
1128   GUI_DeleteMenu(m);
1129 }
1130 
1131 /****************************************************************************
1132  * System ROM paths menu
1133  *
1134  ****************************************************************************/
1135 
rompathmenu()1136 static void rompathmenu ()
1137 {
1138   FILE *f;
1139   int i, ret;
1140   gui_menu *m = &menu_rompaths;
1141   gui_item *items = m->items;
1142 
1143   for (i=0; i<12; i++)
1144   {
1145     f = fopen(config.sys_rom[i],"rb");
1146     if (f)
1147     {
1148       strcpy(strstr(items[i].text,":") + 2, "FOUND");
1149       fclose(f);
1150     }
1151     else
1152     {
1153       strcpy(strstr(items[i].text,":") + 2, "NOT FOUND");
1154     }
1155   }
1156 
1157   GUI_InitMenu(m);
1158 
1159   while (1)
1160   {
1161     ret = GUI_RunMenu(m);
1162 
1163     if (ret < 0)
1164     {
1165       GUI_DeleteMenu(m);
1166       return;
1167     }
1168 
1169     /* Initialize System ROM browser */
1170     if (OpenDirectory(config.l_device, ret + FILETYPE_MAX))
1171     {
1172       /* Get current System ROM path */
1173       char *dir = GetCurrentDirectory();
1174 
1175       /* Open System ROM browser */
1176       GUI_DeleteMenu(m);
1177       i = FileSelector(ret + FILETYPE_MAX);
1178 
1179       /* System ROM selected ? */
1180       if (i >= 0)
1181       {
1182         /* full System ROM pathname */
1183         sprintf(config.sys_rom[ret],"%s%s",dir,filelist[i].filename);
1184 
1185         /* mark System ROM as found */
1186         strcpy(strstr(items[ret].text,":") + 2, "FOUND");
1187 
1188         /* BOOT ROM special cases */
1189         switch (ret)
1190         {
1191           case 0:
1192           case 1:
1193           case 2:
1194           {
1195             /* force CD BOOT ROM reloading */
1196             system_bios &= ~0x10;
1197             break;
1198           }
1199 
1200           case 3:
1201           {
1202             /* Genesis BOOT ROM must be reloaded */
1203             if (load_archive(MD_BIOS, boot_rom, 0x800, NULL) > 0)
1204             {
1205               /* check if BOOT ROM header is valid */
1206               if (!memcmp((char *)(boot_rom + 0x120),"GENESIS OS", 10))
1207               {
1208                 /* mark Genesis BOOT ROM as loaded */
1209                 system_bios |= SYSTEM_MD;
1210               }
1211               else
1212               {
1213                 /* mark Genesis BOOT ROM as unloaded */
1214                 system_bios &= ~SYSTEM_MD;
1215               }
1216             }
1217             break;
1218           }
1219 
1220           case 4:
1221           case 5:
1222           case 6:
1223           {
1224             /* force Master System BOOT ROM reloading */
1225             system_bios &= ~SYSTEM_SMS;
1226             break;
1227           }
1228 
1229           case 7:
1230           {
1231             /* force Game Gear BOOT ROM reloading */
1232             system_bios &= ~SYSTEM_GG;
1233             break;
1234           }
1235 
1236           default:
1237           {
1238             /* not a BOOT ROM */
1239             break;
1240           }
1241         }
1242       }
1243 
1244       free(dir);
1245       GUI_InitMenu(m);
1246     }
1247   }
1248 }
1249 
1250 /****************************************************************************
1251  * System Settings menu
1252  *
1253  ****************************************************************************/
1254 static const uint16 vc_table[4][2] =
1255 {
1256   /* NTSC, PAL */
1257   {0xDA , 0xF2},  /* Mode 4 (192 lines) */
1258   {0xEA , 0x102}, /* Mode 5 (224 lines) */
1259   {0xDA , 0xF2},  /* Mode 4 (192 lines) */
1260   {0x106, 0x10A}  /* Mode 5 (240 lines) */
1261 };
1262 
systemmenu()1263 static void systemmenu ()
1264 {
1265   int ret, quit = 0;
1266   int reinit = 0;
1267   gui_menu *m = &menu_system;
1268   gui_item *items = m->items;
1269 
1270   if (config.system == 0)
1271     sprintf (items[0].text, "Console Type: AUTO");
1272   else if (config.system == SYSTEM_SG)
1273     sprintf (items[0].text, "Console Type: SG-1000");
1274   else if (config.system == SYSTEM_SGII)
1275     sprintf (items[0].text, "Console Type: SG-1000 II");
1276   else if (config.system == SYSTEM_MARKIII)
1277     sprintf (items[0].text, "Console Type: MARK-III");
1278   else if (config.system == SYSTEM_SMS)
1279     sprintf (items[0].text, "Console Type: SMS");
1280   else if (config.system == SYSTEM_SMS2)
1281     sprintf (items[0].text, "Console Type: SMS II");
1282   else if (config.system == SYSTEM_GG)
1283     sprintf (items[0].text, "Console Type: GG");
1284   else if (config.system == SYSTEM_MD)
1285     sprintf (items[0].text, "Console Type: MD");
1286 
1287   if (config.region_detect == 0)
1288     sprintf (items[1].text, "Console Region: AUTO");
1289   else if (config.region_detect == 1)
1290     sprintf (items[1].text, "Console Region: USA");
1291   else if (config.region_detect == 2)
1292     sprintf (items[1].text, "Console Region: PAL");
1293   else if (config.region_detect == 3)
1294     sprintf (items[1].text, "Console Region: JAP");
1295 
1296   if (config.vdp_mode == 0)
1297     sprintf (items[2].text, "VDP Mode: AUTO");
1298   else if (config.vdp_mode == 1)
1299     sprintf (items[2].text, "VDP Mode: NTSC");
1300   else if (config.vdp_mode == 2)
1301     sprintf (items[2].text, "VDP Mode: PAL");
1302 
1303   if (config.master_clock == 0)
1304     sprintf (items[3].text, "System Clock: AUTO");
1305   else if (config.master_clock == 1)
1306     sprintf (items[3].text, "System Clock: NTSC");
1307   else if (config.master_clock == 2)
1308     sprintf (items[3].text, "System Clock: PAL");
1309 
1310   sprintf (items[4].text, "System Boot: %s", (config.bios & 1) ? ((config.bios & 2) ? "BIOS&CART" : "BIOS ONLY") : "CART");
1311   sprintf (items[5].text, "System Lockups: %s", config.force_dtack ? "OFF" : "ON");
1312   sprintf (items[6].text, "68k Address Error: %s", config.addr_error ? "ON" : "OFF");
1313 
1314   if (config.lock_on == TYPE_GG)
1315     sprintf (items[7].text, "Lock-On: GAME GENIE");
1316   else if (config.lock_on == TYPE_AR)
1317     sprintf (items[7].text, "Lock-On: ACTION REPLAY");
1318   else if (config.lock_on == TYPE_SK)
1319     sprintf (items[7].text, "Lock-On: SONIC&KNUCKLES");
1320   else
1321     sprintf (items[7].text, "Lock-On: OFF");
1322 
1323   sprintf (items[8].text, "Cartridge Swap: %s", (config.hot_swap & 1) ? "ON":"OFF");
1324 
1325   if (svp)
1326   {
1327     sprintf (items[10].text, "SVP Cycles: %d", SVP_cycles);
1328     m->max_items = 11;
1329   }
1330   else
1331   {
1332     m->max_items = 10;
1333   }
1334 
1335   GUI_InitMenu(m);
1336   GUI_SlideMenuTitle(m,strlen("System "));
1337 
1338   while (quit == 0)
1339   {
1340     ret = GUI_RunMenu(m);
1341 
1342     switch (ret)
1343     {
1344       case 0:  /*** Force System Hardware ***/
1345       {
1346         if (config.system == SYSTEM_MD)
1347         {
1348           config.system = 0;
1349           sprintf (items[0].text, "Console Type: AUTO");
1350 
1351           /* Default system hardware (auto) */
1352           if (system_hw) system_hw = romtype;
1353         }
1354         else if (config.system == 0)
1355         {
1356           config.system = SYSTEM_SG;
1357           sprintf (items[0].text, "Console Type: SG-1000");
1358           if (system_hw) system_hw = SYSTEM_SG;
1359         }
1360         else if (config.system == SYSTEM_SG)
1361         {
1362           config.system = SYSTEM_SGII;
1363           sprintf (items[0].text, "Console Type: SG-1000 II");
1364           if (system_hw) system_hw = SYSTEM_SGII;
1365         }
1366         else if (config.system == SYSTEM_SGII)
1367         {
1368           config.system = SYSTEM_MARKIII;
1369           sprintf (items[0].text, "Console Type: MARK-III");
1370           if (system_hw) system_hw = SYSTEM_MARKIII;
1371         }
1372         else if (config.system == SYSTEM_MARKIII)
1373         {
1374           config.system = SYSTEM_SMS;
1375           sprintf (items[0].text, "Console Type: SMS");
1376           if (system_hw) system_hw = SYSTEM_SMS;
1377         }
1378         else if (config.system == SYSTEM_SMS)
1379         {
1380           config.system = SYSTEM_SMS2;
1381           sprintf (items[0].text, "Console Type: SMS II");
1382           if (system_hw) system_hw = SYSTEM_SMS2;
1383         }
1384         else if (config.system == SYSTEM_SMS2)
1385         {
1386           config.system = SYSTEM_GG;
1387           sprintf (items[0].text, "Console Type: GG");
1388 
1389           if (romtype == SYSTEM_GG)
1390           {
1391             /* Game Gear mode  */
1392             if (system_hw) system_hw = SYSTEM_GG;
1393           }
1394           else
1395           {
1396             /* Game Gear in MS compatibility mode  */
1397             if (system_hw) system_hw = SYSTEM_GGMS;
1398           }
1399         }
1400         else if (config.system == SYSTEM_GG)
1401         {
1402           config.system = SYSTEM_MD;
1403           sprintf (items[0].text, "Console Type: MD");
1404 
1405           if (romtype & SYSTEM_MD)
1406           {
1407             /* Default mode */
1408             if (system_hw) system_hw = romtype;
1409           }
1410           else
1411           {
1412             /* Mega Drive in MS compatibility mode  */
1413             if (system_hw) system_hw = SYSTEM_PBC;
1414           }
1415         }
1416 
1417         if (system_hw)
1418         {
1419           /* restore previous input settings */
1420           if (old_system[0] != -1)
1421           {
1422             input.system[0] = old_system[0];
1423           }
1424           if (old_system[1] != -1)
1425           {
1426             input.system[1] = old_system[1];
1427           }
1428 
1429           /* reinitialize audio streams */
1430           audio_init(snd.sample_rate, snd.frame_rate);
1431 
1432           /* force hard reset */
1433           system_init();
1434           system_reset();
1435 
1436           /* restore SRAM */
1437           slot_autoload(0,config.s_device);
1438         }
1439 
1440         break;
1441       }
1442 
1443       case 1:  /*** Force Region ***/
1444       {
1445         config.region_detect = (config.region_detect + 1) % 4;
1446         if (config.region_detect == 0)
1447           sprintf (items[1].text, "Console Region: AUTO");
1448         else if (config.region_detect == 1)
1449           sprintf (items[1].text, "Console Region: USA");
1450         else if (config.region_detect == 2)
1451           sprintf (items[1].text, "Console Region: PAL");
1452         else if (config.region_detect == 3)
1453           sprintf (items[1].text, "Console Region: JAP");
1454 
1455         /* force system reinitialization + region BIOS */
1456         reinit = 2;
1457         break;
1458       }
1459 
1460       case 2:  /*** Force VDP mode ***/
1461       {
1462         config.vdp_mode = (config.vdp_mode + 1) % 3;
1463         if (config.vdp_mode == 0)
1464           sprintf (items[2].text, "VDP Mode: AUTO");
1465         else if (config.vdp_mode == 1)
1466           sprintf (items[2].text, "VDP Mode: NTSC");
1467         else if (config.vdp_mode == 2)
1468           sprintf (items[2].text, "VDP Mode: PAL");
1469 
1470         /* force system reinitialization */
1471         reinit = 1;
1472         break;
1473       }
1474 
1475       case 3:  /*** Force Master Clock ***/
1476       {
1477         config.master_clock = (config.master_clock + 1) % 3;
1478         if (config.master_clock == 0)
1479           sprintf (items[3].text, "System Clock: AUTO");
1480         else if (config.master_clock == 1)
1481           sprintf (items[3].text, "System Clock: NTSC");
1482         else if (config.master_clock == 2)
1483           sprintf (items[3].text, "System Clock: PAL");
1484 
1485         /* force system reinitialization */
1486         reinit = 1;
1487         break;
1488       }
1489 
1490       case 4:  /*** BIOS support ***/
1491       {
1492         if (config.bios == 0) config.bios = 3;
1493         else if (config.bios == 3) config.bios = 1;
1494         else config.bios = 0;
1495         sprintf (items[4].text, "System Boot: %s", (config.bios & 1) ? ((config.bios & 2) ? "BIOS&CART " : "BIOS ONLY") : "CART");
1496         if ((system_hw == SYSTEM_MD) || (system_hw & SYSTEM_GG) || (system_hw & SYSTEM_SMS))
1497         {
1498           /* force hard reset */
1499           system_init();
1500           system_reset();
1501 
1502           /* restore SRAM */
1503           slot_autoload(0,config.s_device);
1504         }
1505         break;
1506       }
1507 
1508       case 5:  /*** force DTACK ***/
1509       {
1510         config.force_dtack ^= 1;
1511         sprintf (items[5].text, "System Lockups: %s", config.force_dtack ? "OFF" : "ON");
1512         break;
1513       }
1514 
1515       case 6:  /*** 68k Address Error ***/
1516       {
1517         config.addr_error ^= 1;
1518         m68k.aerr_enabled = config.addr_error;
1519         sprintf (items[6].text, "68k Address Error: %s", config.addr_error ? "ON" : "OFF");
1520         break;
1521       }
1522 
1523       case 7:  /*** Cart Lock-On ***/
1524       {
1525         config.lock_on = (config.lock_on + 1) % (TYPE_SK + 1);
1526         if (config.lock_on == TYPE_GG)
1527           sprintf (items[7].text, "Lock-On: GAME GENIE");
1528         else if (config.lock_on == TYPE_AR)
1529           sprintf (items[7].text, "Lock-On: ACTION REPLAY");
1530         else if (config.lock_on == TYPE_SK)
1531           sprintf (items[7].text, "Lock-On: SONIC&KNUCKLES");
1532         else
1533           sprintf (items[7].text, "Lock-On: OFF");
1534 
1535         if ((system_hw == SYSTEM_MD) || (system_hw == SYSTEM_PICO))
1536         {
1537           /* force hard reset */
1538           system_init();
1539           system_reset();
1540 
1541           /* restore SRAM */
1542           slot_autoload(0,config.s_device);
1543 
1544           /* Action Replay switch */
1545           if (areplay_get_status() < 0)
1546           {
1547             menu_main.buttons[6].state &= ~(BUTTON_VISIBLE | BUTTON_ACTIVE);
1548             menu_main.items[6].data = NULL;
1549             menu_main.cb = NULL;
1550             menu_main.buttons[3].shift[1] = 4;
1551             menu_main.buttons[7].shift[0] = 4;
1552             menu_main.buttons[8].shift[2] = 1;
1553           }
1554           else
1555           {
1556             menu_main.buttons[6].state |= (BUTTON_VISIBLE | BUTTON_ACTIVE);
1557             menu_main.items[6].data = Button_sm_grey_png;
1558             menu_main.cb = mainmenu_cb;
1559             menu_main.buttons[3].shift[1] = 3;
1560             menu_main.buttons[7].shift[0] = 1;
1561             menu_main.buttons[8].shift[2] = 2;
1562           }
1563         }
1564         break;
1565       }
1566 
1567       case 8:  /*** Cartridge Hot Swap ***/
1568       {
1569         config.hot_swap ^= 1;
1570         sprintf (items[8].text, "Cartridge Swap: %s", (config.hot_swap & 1) ? "ON":"OFF");
1571         break;
1572       }
1573 
1574       case 9:  /*** System ROM paths ***/
1575       {
1576         GUI_DeleteMenu(m);
1577         rompathmenu();
1578         GUI_InitMenu(m);
1579         break;
1580       }
1581 
1582       case 10:  /*** SVP cycles per line ***/
1583       {
1584         GUI_OptionBox(m,0,"SVP Cycles",(void *)&SVP_cycles,1,1,1500,1);
1585         sprintf (items[10].text, "SVP Cycles: %d", SVP_cycles);
1586         break;
1587       }
1588 
1589       case -1:
1590       {
1591         quit = 1;
1592         break;
1593       }
1594     }
1595   }
1596 
1597   if (reinit && system_hw)
1598   {
1599     /* reinitialize console region */
1600     get_region(NULL);
1601 
1602     /* framerate might have changed, reinitialize audio timings */
1603     audio_init(snd.sample_rate, get_framerate());
1604 
1605     /* system with region BIOS should be reinitialized if region code has changed */
1606     if ((reinit & 2) && ((system_hw == SYSTEM_MCD) || ((system_hw & SYSTEM_SMS) && (config.bios & 1))))
1607     {
1608        system_init();
1609        system_reset();
1610 
1611        /* restore SRAM */
1612        slot_autoload(0,config.s_device);
1613     }
1614     else
1615     {
1616       /* reinitialize I/O region register */
1617       if (system_hw == SYSTEM_MD)
1618       {
1619         io_reg[0x00] = 0x20 | region_code | (config.bios & 1);
1620       }
1621       else if (system_hw == SYSTEM_MCD)
1622       {
1623         io_reg[0x00] = region_code | (config.bios & 1);
1624       }
1625       else
1626       {
1627         io_reg[0x00] = 0x80 | (region_code >> 1);
1628       }
1629 
1630       /* reinitialize VDP timings */
1631       lines_per_frame = vdp_pal ? 313 : 262;
1632 
1633       /* reinitialize NTSC/PAL mode in VDP status */
1634       if (system_hw & SYSTEM_MD)
1635       {
1636         status = (status & ~1) | vdp_pal;
1637       }
1638 
1639       /* reinitialize VC max value */
1640       switch (bitmap.viewport.h)
1641       {
1642         case 192:
1643           vc_max = vc_table[0][vdp_pal];
1644           break;
1645         case 224:
1646           vc_max = vc_table[1][vdp_pal];
1647           break;
1648         case 240:
1649           vc_max = vc_table[3][vdp_pal];
1650           break;
1651       }
1652     }
1653   }
1654 
1655   GUI_DeleteMenu(m);
1656 }
1657 
1658 /****************************************************************************
1659  * Video Settings menu
1660  *
1661  ****************************************************************************/
1662 #ifdef HW_RVL
1663 #define VI_OFFSET 7
update_gamma(void)1664 static void update_gamma(void)
1665 {
1666   VIDEO_SetGamma((int)(config.gamma * 10.0));
1667   VIDEO_Flush();
1668 }
1669 #else
1670 #define VI_OFFSET 5
1671 #endif
1672 
videomenu()1673 static void videomenu ()
1674 {
1675   u16 state[2];
1676   int ret, quit = 0;
1677   int reinit = 0;
1678   gui_menu *m = &menu_video;
1679   gui_item *items = m->items;
1680   int ntsc_offset = 0;
1681 
1682   if (config.render == 1)
1683     sprintf (items[0].text,"Display: INTERLACED");
1684   else if (config.render == 2)
1685     sprintf (items[0].text, "Display: PROGRESSIVE");
1686   else
1687     sprintf (items[0].text, "Display: ORIGINAL");
1688 
1689   if (config.tv_mode == 0)
1690     sprintf (items[1].text, "TV Mode: 60HZ");
1691   else if (config.tv_mode == 1)
1692     sprintf (items[1].text, "TV Mode: 50HZ");
1693   else
1694     sprintf (items[1].text, "TV Mode: 50/60HZ");
1695 
1696   if (config.vsync)
1697     sprintf (items[2].text, "VSYNC: AUTO");
1698   else
1699     sprintf (items[2].text, "VSYNC: OFF");
1700 
1701   sprintf (items[3].text, "Bilinear Filter: %s", config.bilinear ? " ON" : "OFF");
1702   sprintf (items[4].text, "Deflickering Filter: %s", config.vfilter ? "AUTO" : "OFF");
1703 
1704 #ifdef HW_RVL
1705   sprintf (items[5].text, "Trap Filter: %s", config.trap ? " ON" : "OFF");
1706   sprintf (items[6].text, "Gamma Correction: %1.1f", config.gamma);
1707 #endif
1708 
1709   if (config.lcd > 0)
1710   {
1711     int ratio = ((config.lcd * 100) + 254) / 255;
1712     sprintf (items[VI_OFFSET].text, "LCD Ghosting Filter: %d%%", ratio);
1713   }
1714   else
1715   {
1716     sprintf (items[VI_OFFSET].text, "LCD Ghosting Filter: OFF");
1717   }
1718 
1719   if (config.ntsc == 1)
1720     sprintf (items[VI_OFFSET+1].text, "NTSC Filter: COMPOSITE");
1721   else if (config.ntsc == 2)
1722     sprintf (items[VI_OFFSET+1].text, "NTSC Filter: S-VIDEO");
1723   else if (config.ntsc == 3)
1724     sprintf (items[VI_OFFSET+1].text, "NTSC Filter: RGB");
1725   else if (config.ntsc == 4)
1726   {
1727     sprintf (items[VI_OFFSET+1].text, "NTSC Filter: MANUAL");
1728     sprintf(items[VI_OFFSET+2].text, "NTSC Sharpness: %1.2f", config.ntsc_sharpness);
1729     sprintf(items[VI_OFFSET+3].text, "NTSC Resolution: %1.2f", config.ntsc_resolution);
1730     sprintf(items[VI_OFFSET+4].text, "NTSC Artifacts: %1.2f", config.ntsc_artifacts);
1731     sprintf(items[VI_OFFSET+5].text, "NTSC Color Bleed: %1.2f", config.ntsc_bleed);
1732     sprintf(items[VI_OFFSET+6].text, "NTSC Color Fringing: %1.2f", config.ntsc_fringing);
1733     strcpy(items[VI_OFFSET+2].comment, "Adjust edge contrast enhancement/blurring");
1734     strcpy(items[VI_OFFSET+3].comment, "Adjust image resolution");
1735     strcpy(items[VI_OFFSET+4].comment, "Adjust artifacts caused by color changes");
1736     strcpy(items[VI_OFFSET+5].comment, "Adjust color resolution reduction");
1737     strcpy(items[VI_OFFSET+6].comment, "Adjust artifacts caused by brightness changes");
1738     ntsc_offset = 5;
1739   }
1740   else
1741     sprintf (items[VI_OFFSET+1].text, "NTSC Filter: OFF");
1742 
1743   strcpy(items[VI_OFFSET+2+ntsc_offset].comment, "Enable/Disable overscan emulation");
1744   strcpy(items[VI_OFFSET+3+ntsc_offset].comment, "Enable/Disable Game Gear extended screen");
1745   strcpy(items[VI_OFFSET+4+ntsc_offset].comment, "Select display aspect ratio");
1746   strcpy(items[VI_OFFSET+5+ntsc_offset].comment, "Adjust display position");
1747   strcpy(items[VI_OFFSET+6+ntsc_offset].comment, "Adjust display scaling");
1748 
1749   if (config.overscan == 3)
1750     sprintf (items[VI_OFFSET+2+ntsc_offset].text, "Borders: FULL");
1751   else if (config.overscan == 2)
1752     sprintf (items[VI_OFFSET+2+ntsc_offset].text, "Borders: H ONLY");
1753   else if (config.overscan == 1)
1754     sprintf (items[VI_OFFSET+2+ntsc_offset].text, "Borders: V ONLY");
1755   else
1756     sprintf (items[VI_OFFSET+2+ntsc_offset].text, "Borders: NONE");
1757 
1758   sprintf(items[VI_OFFSET+3+ntsc_offset].text, "GG Screen: %s", config.gg_extra ? "EXTENDED":"ORIGINAL");
1759 
1760   if (config.aspect == 1)
1761     sprintf (items[VI_OFFSET+4+ntsc_offset].text,"Aspect: ORIGINAL (4:3)");
1762   else if (config.aspect == 2)
1763     sprintf (items[VI_OFFSET+4+ntsc_offset].text, "Aspect: ORIGINAL (16:9)");
1764   else
1765   {
1766     sprintf (items[VI_OFFSET+4+ntsc_offset].text, "Aspect: SCALED");
1767   }
1768 
1769   sprintf (items[VI_OFFSET+5+ntsc_offset].text, "Screen Position: (%s%02d,%s%02d)",
1770     (config.xshift < 0) ? "":"+", config.xshift,
1771     (config.yshift < 0) ? "":"+", config.yshift);
1772 
1773   sprintf (items[VI_OFFSET+6+ntsc_offset].text, "Screen Scaling: (%s%02d,%s%02d)",
1774     (config.xscale < 0) ? "":"+", config.xscale,
1775     (config.yscale < 0) ? "":"+", config.yscale);
1776 
1777   m->max_items  = VI_OFFSET + 6 + ntsc_offset + (config.aspect == 0);
1778 
1779   GUI_InitMenu(m);
1780   GUI_SlideMenuTitle(m,strlen("Video "));
1781 
1782   while (quit == 0)
1783   {
1784     ret = GUI_RunMenu(m);
1785 
1786     if (ret > (VI_OFFSET + 1))
1787     {
1788       ret += (5 - ntsc_offset);
1789     }
1790 
1791     switch (ret)
1792     {
1793       case 0:  /*** rendering ***/
1794       {
1795         config.render = (config.render + 1) % 3;
1796         if (config.render == 2)
1797         {
1798           /* progressive mode is only possible through component cable */
1799           if (!VIDEO_HaveComponentCable())
1800           {
1801             config.render = 0;
1802           }
1803         }
1804         if (config.render == 1)
1805           sprintf (items[0].text,"Display: INTERLACED");
1806         else if (config.render == 2)
1807           sprintf (items[0].text, "Display: PROGRESSIVE");
1808         else
1809           sprintf (items[0].text, "Display: ORIGINAL");
1810 
1811         reinit = 1;
1812         break;
1813       }
1814 
1815       case 1: /*** tv mode ***/
1816       {
1817         config.tv_mode = (config.tv_mode + 1) % 3;
1818         if (config.tv_mode == 0)
1819           sprintf (items[1].text, "TV Mode: 60HZ");
1820         else if (config.tv_mode == 1)
1821           sprintf (items[1].text, "TV Mode: 50HZ");
1822         else
1823           sprintf (items[1].text, "TV Mode: 50/60HZ");
1824         reinit = 1;
1825         break;
1826       }
1827 
1828       case 2: /*** VSYNC ***/
1829       {
1830         config.vsync ^= 1;
1831         if (config.vsync)
1832           sprintf (items[2].text, "VSYNC: AUTO");
1833         else
1834           sprintf (items[2].text, "VSYNC: OFF");
1835         reinit = 1;
1836         break;
1837       }
1838 
1839       case 3: /*** GX Texture filtering ***/
1840       {
1841         config.bilinear ^= 1;
1842         sprintf (items[3].text, "Bilinear Filter: %s", config.bilinear ? " ON" : "OFF");
1843         break;
1844       }
1845 
1846       case 4: /*** GX Copy filtering (deflickering filter) ***/
1847       {
1848         config.vfilter ^= 1;
1849         sprintf (items[4].text, "Deflickering Filter: %s", config.vfilter ? "AUTO" : "OFF");
1850         break;
1851       }
1852 
1853 #ifdef HW_RVL
1854       case 5: /*** VIDEO Trap filtering ***/
1855       {
1856         config.trap ^= 1;
1857         sprintf (items[5].text, "Trap Filter: %s", config.trap ? " ON" : "OFF");
1858         break;
1859       }
1860 
1861       case 6: /*** VIDEO Gamma correction ***/
1862       {
1863         if (system_hw)
1864         {
1865           update_gamma();
1866           state[0] = m->arrows[0]->state;
1867           state[1] = m->arrows[1]->state;
1868           m->max_buttons = 0;
1869           m->max_images = 0;
1870           m->arrows[0]->state = 0;
1871           m->arrows[1]->state = 0;
1872           m->screenshot = 255;
1873           strcpy(m->title,"");
1874           GUI_OptionBox(m,update_gamma,"Gamma Correction",(void *)&config.gamma,0.1,0.1,3.0,0);
1875           m->max_buttons = 4;
1876           m->max_images = 6;
1877           m->arrows[0]->state = state[0];
1878           m->arrows[1]->state = state[1];
1879           m->screenshot = 0;
1880           strcpy(m->title,"Video Settings");
1881           sprintf (items[6].text, "Gamma Correction: %1.1f", config.gamma);
1882           VIDEO_SetGamma(VI_GM_1_0);
1883           VIDEO_Flush();
1884         }
1885         else
1886         {
1887           GUI_WaitPrompt("Error","Please load a game first !\n");
1888         }
1889         break;
1890       }
1891 #endif
1892 
1893       case VI_OFFSET: /*** LCD filter (soft) ***/
1894       {
1895         if (config.ntsc)
1896         {
1897           GUI_WaitPrompt("Error","NTSC filter must be disabled\n");
1898           break;
1899         }
1900 
1901         int16 ratio = ((config.lcd * 100) + 254) / 255;
1902         GUI_OptionBox(m,0,"LCD Ghosting Ratio (%)",(void *)&ratio,1,0,100,1);
1903         if (ratio > 0)
1904         {
1905           sprintf (items[VI_OFFSET].text, "LCD Ghosting Filter: %d%%", ratio);
1906         }
1907         else
1908         {
1909           sprintf (items[VI_OFFSET].text, "LCD Ghosting Filter: OFF");
1910         }
1911         config.lcd = (ratio * 255) / 100;
1912         break;
1913       }
1914 
1915       case VI_OFFSET+1: /*** NTSC filter (soft) ***/
1916       {
1917         if (config.lcd)
1918         {
1919           GUI_WaitPrompt("Error","LCD filter must be disabled\n");
1920           break;
1921         }
1922 
1923         config.ntsc = (config.ntsc + 1) % 5;
1924         if (config.ntsc == 1)
1925         {
1926           sprintf (items[VI_OFFSET+1].text, "NTSC Filter: COMPOSITE");
1927         }
1928         else if (config.ntsc == 2)
1929         {
1930           sprintf (items[VI_OFFSET+1].text, "NTSC Filter: S-VIDEO");
1931         }
1932         else if (config.ntsc == 3)
1933         {
1934           sprintf (items[VI_OFFSET+1].text, "NTSC Filter: RGB");
1935         }
1936         else if (config.ntsc == 4)
1937         {
1938           sprintf (items[VI_OFFSET+1].text, "NTSC Filter: MANUAL");
1939           strcpy(items[VI_OFFSET+5+2].text, items[VI_OFFSET+2].text);
1940           strcpy(items[VI_OFFSET+5+3].text, items[VI_OFFSET+3].text);
1941           strcpy(items[VI_OFFSET+5+4].text, items[VI_OFFSET+4].text);
1942           strcpy(items[VI_OFFSET+5+5].text, items[VI_OFFSET+5].text);
1943           strcpy(items[VI_OFFSET+5+6].text, items[VI_OFFSET+6].text);
1944           strcpy(items[VI_OFFSET+5+2].comment, items[VI_OFFSET+2].comment);
1945           strcpy(items[VI_OFFSET+5+3].comment, items[VI_OFFSET+3].comment);
1946           strcpy(items[VI_OFFSET+5+4].comment, items[VI_OFFSET+4].comment);
1947           strcpy(items[VI_OFFSET+5+5].comment, items[VI_OFFSET+5].comment);
1948           strcpy(items[VI_OFFSET+5+6].comment, items[VI_OFFSET+6].comment);
1949           sprintf(items[VI_OFFSET+2].text, "NTSC Sharpness: %1.1f", config.ntsc_sharpness);
1950           sprintf(items[VI_OFFSET+3].text, "NTSC Resolution: %1.1f", config.ntsc_resolution);
1951           sprintf(items[VI_OFFSET+4].text, "NTSC Artifacts: %1.1f", config.ntsc_artifacts);
1952           sprintf(items[VI_OFFSET+5].text, "NTSC Color Bleed: %1.1f", config.ntsc_bleed);
1953           sprintf(items[VI_OFFSET+6].text, "NTSC Color Fringing: %1.1f", config.ntsc_fringing);
1954           strcpy(items[VI_OFFSET+2].comment, "Adjust edge contrast enhancement/blurring");
1955           strcpy(items[VI_OFFSET+3].comment, "Adjust image resolution");
1956           strcpy(items[VI_OFFSET+4].comment, "Adjust artifacts caused by color changes");
1957           strcpy(items[VI_OFFSET+5].comment, "Adjust color resolution reduction");
1958           strcpy(items[VI_OFFSET+6].comment, "Adjust artifacts caused by brightness changes");
1959           ntsc_offset = 5;
1960           m->max_items  = VI_OFFSET + 11 + (config.aspect == 0);
1961         }
1962         else
1963         {
1964           sprintf (items[VI_OFFSET+1].text, "NTSC Filter: OFF");
1965           strcpy(items[VI_OFFSET+2].text, items[VI_OFFSET+5+2].text);
1966           strcpy(items[VI_OFFSET+3].text, items[VI_OFFSET+5+3].text);
1967           strcpy(items[VI_OFFSET+4].text, items[VI_OFFSET+5+4].text);
1968           strcpy(items[VI_OFFSET+5].text, items[VI_OFFSET+5+5].text);
1969           strcpy(items[VI_OFFSET+6].text, items[VI_OFFSET+5+6].text);
1970           strcpy(items[VI_OFFSET+2].comment, items[VI_OFFSET+5+2].comment);
1971           strcpy(items[VI_OFFSET+3].comment, items[VI_OFFSET+5+3].comment);
1972           strcpy(items[VI_OFFSET+4].comment, items[VI_OFFSET+5+4].comment);
1973           strcpy(items[VI_OFFSET+5].comment, items[VI_OFFSET+5+5].comment);
1974           strcpy(items[VI_OFFSET+6].comment, items[VI_OFFSET+5+6].comment);
1975           ntsc_offset = 0;
1976           m->max_items  = VI_OFFSET + 6 + (config.aspect == 0);
1977         }
1978         break;
1979       }
1980 
1981       case VI_OFFSET+2: /*** NTSC Sharpness ***/
1982         GUI_OptionBox(m,update_bgm,"NTSC Sharpness",(void *)&config.ntsc_sharpness,0.01,-1.0,1.0,0);
1983         sprintf(items[VI_OFFSET+2].text, "NTSC Sharpness: %1.2f", config.ntsc_sharpness);
1984         break;
1985 
1986       case VI_OFFSET+3: /*** NTSC Resolution ***/
1987         GUI_OptionBox(m,update_bgm,"NTSC Resolution",(void *)&config.ntsc_resolution,0.01,0.0,1.0,0);
1988         sprintf(items[VI_OFFSET+3].text, "NTSC Resolution: %1.2f", config.ntsc_resolution);
1989         break;
1990 
1991       case VI_OFFSET+4: /*** NTSC Artifacts ***/
1992         GUI_OptionBox(m,update_bgm,"NTSC Artifacts",(void *)&config.ntsc_artifacts,0.01,-1.0,0.0,0);
1993         sprintf(items[VI_OFFSET+4].text, "NTSC Artifacts: %1.2f", config.ntsc_artifacts);
1994         break;
1995 
1996       case VI_OFFSET+5: /*** NTSC Color Bleed ***/
1997         GUI_OptionBox(m,update_bgm,"NTSC Color Bleed",(void *)&config.ntsc_bleed,0.01,-1.0,1.0,0);
1998         sprintf(items[VI_OFFSET+5].text, "NTSC Color Bleed: %1.2f", config.ntsc_bleed);
1999         break;
2000 
2001       case VI_OFFSET+6: /*** NTSC Color Fringing ***/
2002         GUI_OptionBox(m,update_bgm,"NTSC Color Fringing",(void *)&config.ntsc_fringing,0.01,-1.0,1.0,0);
2003         sprintf(items[VI_OFFSET+6].text, "NTSC Color Fringing: %1.2f", config.ntsc_fringing);
2004         break;
2005 
2006       case VI_OFFSET+7: /*** overscan emulation ***/
2007       {
2008         config.overscan = (config.overscan + 1) & 3;
2009         if (config.overscan == 3)
2010           sprintf (items[VI_OFFSET+ntsc_offset+2].text, "Borders: FULL");
2011         else if (config.overscan == 2)
2012           sprintf (items[VI_OFFSET+ntsc_offset+2].text, "Borders: H ONLY");
2013         else if (config.overscan == 1)
2014           sprintf (items[VI_OFFSET+ntsc_offset+2].text, "Borders: V ONLY");
2015         else
2016           sprintf (items[VI_OFFSET+ntsc_offset+2].text, "Borders: NONE");
2017         break;
2018       }
2019 
2020       case VI_OFFSET+8: /*** Game Gear extended screen */
2021       {
2022         config.gg_extra ^= 1;
2023         sprintf(items[VI_OFFSET+ntsc_offset+3].text, "GG Screen: %s", config.gg_extra ? "EXTENDED":"ORIGINAL");
2024         break;
2025       }
2026 
2027       case VI_OFFSET+9: /*** aspect ratio ***/
2028       {
2029         config.aspect = (config.aspect + 1) % 3;
2030         if (config.aspect == 1)
2031           sprintf (items[VI_OFFSET+ntsc_offset+4].text,"Aspect: ORIGINAL (4:3)");
2032         else if (config.aspect == 2)
2033           sprintf (items[VI_OFFSET+ntsc_offset+4].text, "Aspect: ORIGINAL (16:9)");
2034         else
2035           sprintf (items[VI_OFFSET+ntsc_offset+4].text, "Aspect: SCALED");
2036 
2037         if (config.aspect)
2038         {
2039           /* disable items */
2040           m->max_items  = VI_OFFSET + ntsc_offset + 6;
2041 
2042           /* reset menu selection */
2043           if (m->selected < 2)
2044           {
2045             m->offset  = VI_OFFSET + ntsc_offset + 2;
2046             m->selected = 2;
2047           }
2048         }
2049         else
2050         {
2051           /* enable items */
2052           m->max_items  = VI_OFFSET + ntsc_offset + 7;
2053         }
2054         break;
2055       }
2056 
2057       case VI_OFFSET+10: /*** screen position ***/
2058       {
2059         if (system_hw)
2060         {
2061           state[0] = m->arrows[0]->state;
2062           state[1] = m->arrows[1]->state;
2063           m->max_buttons = 0;
2064           m->max_images = 0;
2065           m->arrows[0]->state = 0;
2066           m->arrows[1]->state = 0;
2067           m->screenshot = 255;
2068           strcpy(m->title,"");
2069           GUI_OptionBox2(m,"X Offset","Y Offset",&config.xshift,&config.yshift,1,-99,99);
2070           m->max_buttons = 4;
2071           m->max_images = 6;
2072           m->arrows[0]->state = state[0];
2073           m->arrows[1]->state = state[1];
2074           m->screenshot = 0;
2075           strcpy(m->title,"Video Settings");
2076           sprintf (items[VI_OFFSET+ntsc_offset+5].text, "Screen Position: (%s%02d,%s%02d)",
2077                                             (config.xshift < 0) ? "":"+", config.xshift,
2078                                             (config.yshift < 0) ? "":"+", config.yshift);
2079         }
2080         else
2081         {
2082           GUI_WaitPrompt("Error","Please load a game first !\n");
2083         }
2084         break;
2085       }
2086 
2087       case VI_OFFSET+11: /*** screen scaling ***/
2088       {
2089         if (system_hw)
2090         {
2091           state[0] = m->arrows[0]->state;
2092           state[1] = m->arrows[1]->state;
2093           m->max_buttons = 0;
2094           m->max_images = 0;
2095           m->arrows[0]->state = 0;
2096           m->arrows[1]->state = 0;
2097           m->screenshot = 255;
2098           strcpy(m->title,"");
2099           GUI_OptionBox2(m,"X Scale","Y Scale",&config.xscale,&config.yscale,1,-99,99);
2100           m->max_buttons = 4;
2101           m->max_images = 6;
2102           m->arrows[0]->state = state[0];
2103           m->arrows[1]->state = state[1];
2104           m->screenshot = 0;
2105           strcpy(m->title,"Video Settings");
2106           sprintf (items[VI_OFFSET+ntsc_offset+6].text, "Screen Scaling: (%s%02d,%s%02d)",
2107                                             (config.xscale < 0) ? "":"+", config.xscale,
2108                                             (config.yscale < 0) ? "":"+", config.yscale);
2109         }
2110         else
2111         {
2112           GUI_WaitPrompt("Error","Please load a game first !\n");
2113         }
2114         break;
2115       }
2116 
2117       case -1:
2118       {
2119         quit = 1;
2120         break;
2121       }
2122     }
2123   }
2124 
2125   if (reinit && system_hw)
2126   {
2127     /* framerate might have changed, reinitialize audio timings */
2128     audio_init(snd.sample_rate, get_framerate());
2129   }
2130 
2131   GUI_DeleteMenu(m);
2132 }
2133 
2134 /****************************************************************************
2135  * Controllers Settings menu
2136  ****************************************************************************/
2137 static int player = 0;
ctrlmenu_cb(void)2138 static void ctrlmenu_cb(void)
2139 {
2140   int i, cnt = 1;
2141   char msg[16];
2142   gui_menu *m = &menu_ctrls;
2143 
2144   if (m->bg_images[7].state & IMAGE_VISIBLE)
2145   {
2146     /* draw device port number */
2147     if (config.input[player].device != -1)
2148     {
2149       sprintf(msg,"%d",config.input[player].port + 1);
2150       if (m->selected == 11)
2151         FONT_write(msg,16,m->items[11].x+m->items[11].w+2,m->items[11].y+m->items[11].h+2,640,(GXColor)DARK_GREY);
2152       else
2153         FONT_write(msg,14,m->items[11].x+m->items[11].w,m->items[11].y+m->items[11].h,640,(GXColor)DARK_GREY);
2154     }
2155   }
2156 
2157   /* draw players index */
2158   for (i=2; i<MAX_DEVICES+2; i++)
2159   {
2160     if (m->selected == i)
2161     {
2162       FONT_writeCenter("Player", 16, m->buttons[i].x + 2, m->buttons[i].x + 54, m->buttons[i].y + (m->buttons[i].h - 16)/2 + 16, (GXColor)DARK_GREY);
2163     }
2164     else
2165     {
2166       FONT_writeCenter("Player", 14, m->buttons[i].x + 4, m->buttons[i].x + 54, m->buttons[i].y + (m->buttons[i].h - 14)/2 + 14, (GXColor)DARK_GREY);
2167     }
2168 
2169     if (input.dev[i-2] != NO_DEVICE)
2170     {
2171       sprintf(msg,"%d",cnt++);
2172       if (m->selected == i)
2173       {
2174         FONT_writeCenter(msg,18,m->items[i].x+2,m->items[i].x+m->items[i].w+2,m->buttons[i].y+(m->buttons[i].h-18)/2+18,(GXColor)DARK_GREY);
2175       }
2176       else
2177       {
2178         FONT_writeCenter(msg,16,m->items[i].x,m->items[i].x+m->items[i].w,m->buttons[i].y+(m->buttons[i].h - 16)/2+16,(GXColor)DARK_GREY);
2179       }
2180     }
2181   }
2182 }
2183 
2184 /* Set menu elements depending on current system configuration */
ctrlmenu_raz(void)2185 static void ctrlmenu_raz(void)
2186 {
2187   int i,max = 0;
2188   gui_menu *m = &menu_ctrls;
2189 
2190   /* update players buttons */
2191   for (i=0; i<MAX_DEVICES; i++)
2192   {
2193     if (input.dev[i] == NO_DEVICE)
2194     {
2195       m->buttons[i+2].data  = &button_player_none_data;
2196       m->buttons[i+2].state &= ~BUTTON_ACTIVE;
2197       strcpy(m->items[i+2].comment,"");
2198     }
2199     else
2200     {
2201       m->buttons[i+2].data  = &button_player_data;
2202       m->buttons[i+2].state |= BUTTON_ACTIVE;
2203       if ((cart.special & HW_J_CART) && (i > 4))
2204         sprintf(m->items[i+2].comment,"Configure Player %d (J-CART) settings", max + 1);
2205       else
2206         sprintf(m->items[i+2].comment,"Configure Player %d settings", max + 1);
2207       max++;
2208     }
2209   }
2210 
2211   /* update buttons navigation */
2212   if (input.dev[0] != NO_DEVICE)
2213     m->buttons[0].shift[3] = 2;
2214   else if (input.dev[4] != NO_DEVICE)
2215     m->buttons[0].shift[3] = 6;
2216   else if (input.dev[5] != NO_DEVICE)
2217     m->buttons[0].shift[3] = 7;
2218   else
2219     m->buttons[0].shift[3] = 0;
2220   if (input.dev[4] != NO_DEVICE)
2221     m->buttons[1].shift[3] = 5;
2222   else if (input.dev[5] != NO_DEVICE)
2223     m->buttons[1].shift[3] = 6;
2224   else if (input.dev[0] != NO_DEVICE)
2225     m->buttons[1].shift[3] = 1;
2226   else
2227     m->buttons[1].shift[3] = 0;
2228 
2229   if (input.dev[1] != NO_DEVICE)
2230     m->buttons[2].shift[1] = 1;
2231   else if (input.dev[4] != NO_DEVICE)
2232     m->buttons[2].shift[1] = 4;
2233   else if (input.dev[5] != NO_DEVICE)
2234     m->buttons[2].shift[1] = 5;
2235   else
2236     m->buttons[2].shift[1] = 0;
2237 
2238   if (input.dev[4] != NO_DEVICE)
2239     m->buttons[5].shift[1] = 1;
2240   else if (input.dev[5] != NO_DEVICE)
2241     m->buttons[5].shift[1] = 2;
2242   else
2243     m->buttons[5].shift[1] = 0;
2244 
2245   if (input.dev[3] != NO_DEVICE)
2246     m->buttons[6].shift[0] = 1;
2247   else if (input.dev[0] != NO_DEVICE)
2248     m->buttons[6].shift[0] = 4;
2249   else
2250     m->buttons[6].shift[0] = 0;
2251 
2252   if (input.dev[5] != NO_DEVICE)
2253     m->buttons[6].shift[1] = 1;
2254   else
2255     m->buttons[6].shift[1] = 0;
2256 
2257   if (input.dev[6] != NO_DEVICE)
2258     m->buttons[7].shift[1] = 1;
2259   else
2260     m->buttons[7].shift[1] = 0;
2261 
2262   if (input.dev[7] != NO_DEVICE)
2263     m->buttons[8].shift[1] = 1;
2264   else
2265     m->buttons[8].shift[1] = 0;
2266 
2267   if (input.dev[4] != NO_DEVICE)
2268     m->buttons[7].shift[0] = 1;
2269   else if (input.dev[3] != NO_DEVICE)
2270     m->buttons[7].shift[0] = 2;
2271   else if (input.dev[0] != NO_DEVICE)
2272     m->buttons[7].shift[0] = 5;
2273   else
2274     m->buttons[7].shift[0] = 0;
2275 }
2276 
ctrlmenu(void)2277 static void ctrlmenu(void)
2278 {
2279   int old_player = -1;
2280   int i = 0;
2281   int update = 0;
2282   gui_item *items = NULL;
2283   u8 *special = NULL;
2284   u32 exp, index = 0;
2285 
2286   /* System devices */
2287   gui_item items_sys[2][14] =
2288   {
2289     {
2290       {NULL,Ctrl_none_png           ,"","Select Port 1 device",110,130,48,72},
2291       {NULL,Ctrl_gamepad_png        ,"","Select Port 1 device",100,109,68,92},
2292       {NULL,Ctrl_mouse_png          ,"","Select Port 1 device", 97,113,64,88},
2293       {NULL,Ctrl_menacer_png        ,"","Select Port 1 device", 94,113,80,88},
2294       {NULL,Ctrl_justifiers_png     ,"","Select Port 1 device", 88,117,80,84},
2295       {NULL,Ctrl_xe_1ap_png         ,"","Select Port 1 device", 98,118,72,84},
2296       {NULL,Ctrl_activator_png      ,"","Select Port 1 device", 94,121,72,80},
2297       {NULL,Ctrl_lightphaser_png    ,"","Select Port 1 device", 89,109,88,92},
2298       {NULL,Ctrl_paddle_png         ,"","Select Port 1 device", 86,117,96,84},
2299       {NULL,Ctrl_sportspad_png      ,"","Select Port 1 device", 95,117,76,84},
2300       {NULL,Ctrl_graphic_board_png  ,"","Select Port 1 device", 90,105,88,96},
2301       {NULL,Ctrl_mastertap_png      ,"","Select Port 1 device", 96,104,76,96},
2302       {NULL,Ctrl_teamplayer_png     ,"","Select Port 1 device", 94,109,80,92},
2303       {NULL,Ctrl_4wayplay_png       ,"","Select Port 1 device", 98,110,72,92}
2304     },
2305     {
2306       {NULL,Ctrl_none_png           ,"","Select Port 2 device",110,300,48,72},
2307       {NULL,Ctrl_gamepad_png        ,"","Select Port 2 device",100,279,68,92},
2308       {NULL,Ctrl_mouse_png          ,"","Select Port 2 device", 97,283,64,88},
2309       {NULL,Ctrl_menacer_png        ,"","Select Port 2 device", 94,283,80,88},
2310       {NULL,Ctrl_justifiers_png     ,"","Select Port 2 device", 88,287,80,84},
2311       {NULL,Ctrl_xe_1ap_png         ,"","Select Port 2 device", 98,288,72,84},
2312       {NULL,Ctrl_activator_png      ,"","Select Port 2 device", 94,291,72,80},
2313       {NULL,Ctrl_lightphaser_png    ,"","Select Port 2 device", 89,279,88,92},
2314       {NULL,Ctrl_paddle_png         ,"","Select Port 2 device", 86,287,96,84},
2315       {NULL,Ctrl_sportspad_png      ,"","Select Port 2 device", 95,287,76,84},
2316       {NULL,Ctrl_graphic_board_png  ,"","Select Port 2 device", 90,275,88,96},
2317       {NULL,Ctrl_mastertap_png      ,"","Select Port 1 device", 96,274,76,96},
2318       {NULL,Ctrl_teamplayer_png     ,"","Select Port 2 device", 94,279,80,92},
2319       {NULL,Ctrl_4wayplay_png       ,"","Select Port 2 device", 98,280,72,92}
2320     }
2321   };
2322 
2323   /* Specific controller options */
2324   gui_item items_special[4][4] =
2325   {
2326     {
2327       /* Gamepad option */
2328       {NULL,Ctrl_pad3b_png,"Pad\nType","Use 3-buttons Pad",528,180,44,28},
2329       {NULL,Ctrl_pad6b_png,"Pad\nType","Use 6-buttons Pad",528,180,44,28},
2330       {NULL,Ctrl_pad2b_png,"Pad\nType","Use 2-buttons Pad",528,180,44,28},
2331       {NULL,Ctrl_pad_auto_png,"Pad\nType","Auto-detect Pad type",528,180,44,28},
2332     },
2333     {
2334       /* Mouse option */
2335       {NULL,ctrl_option_off_png,"Invert\nMouse","Enable/Disable Y-Axis inversion",534,180,24,24},
2336       {NULL,ctrl_option_on_png ,"Invert\nMouse","Enable/Disable Y-Axis inversion",534,180,24,24},
2337       {NULL,NULL,"","",0,0,0,0},
2338       {NULL,NULL,"","",0,0,0,0},
2339     },
2340     {
2341       /* Gun option */
2342       {NULL,ctrl_option_off_png,"Show\nCursor","Enable/Disable Lightgun cursor",534,180,24,24},
2343       {NULL,ctrl_option_on_png ,"Show\nCursor","Enable/Disable Lightgun cursor",534,180,24,24},
2344       {NULL,NULL,"","",0,0,0,0},
2345       {NULL,NULL,"","",0,0,0,0},
2346     },
2347     {
2348       /* no option */
2349       {NULL,NULL,"No Option","",436,180,160,52},
2350       {NULL,NULL,"","",0,0,0,0},
2351       {NULL,NULL,"","",0,0,0,0},
2352       {NULL,NULL,"","",0,0,0,0},
2353     }
2354   };
2355 
2356   /* Player Configuration device items */
2357 #ifdef HW_RVL
2358   gui_item items_device[6] =
2359   {
2360     {NULL,ctrl_option_off_png ,"Input\nDevice","Select Input Controller",534,244,24,24},
2361     {NULL,ctrl_gamecube_png   ,"Input\nDevice","Select Input Controller",530,246,36,24},
2362     {NULL,ctrl_wiimote_png    ,"Input\nDevice","Select Input Controller",526,250,40,12},
2363     {NULL,ctrl_nunchuk_png    ,"Input\nDevice","Select Input Controller",532,242,32,32},
2364     {NULL,ctrl_classic_png    ,"Input\nDevice","Select Input Controller",526,242,40,32},
2365     {NULL,ctrl_wiiu_png       ,"Input\nDevice","Select Input Controller",526,246,40,24},
2366   };
2367 #else
2368   gui_item items_device[2] =
2369   {
2370     {NULL,ctrl_option_off_png ,"Input\nDevice","Select Input Controller",534,244,24,24},
2371     {NULL,ctrl_gamecube_png   ,"Input\nDevice","Select Input Controller",530,246,36,24}
2372   };
2373 #endif
2374 
2375   /* initialize menu */
2376   gui_menu *m = &menu_ctrls;
2377   GUI_InitMenu(m);
2378 
2379   /* initialize custom buttons */
2380   button_player_data.texture[0]      = gxTextureOpenPNG(button_player_data.image[0],0);
2381   button_player_data.texture[1]      = gxTextureOpenPNG(button_player_data.image[1],0);
2382   button_player_none_data.texture[0] = gxTextureOpenPNG(button_player_none_data.image[0],0);
2383 
2384   /* initialize custom images */
2385   for (i=0; i<14; i++)
2386   {
2387     items_sys[1][i].texture = items_sys[0][i].texture = gxTextureOpenPNG(items_sys[0][i].data,0);
2388   }
2389   items_special[0][0].texture = gxTextureOpenPNG(items_special[0][0].data,0);
2390   items_special[0][1].texture = gxTextureOpenPNG(items_special[0][1].data,0);
2391   items_special[0][2].texture = gxTextureOpenPNG(items_special[0][2].data,0);
2392   items_special[0][3].texture = gxTextureOpenPNG(items_special[0][3].data,0);
2393   items_special[2][0].texture = items_special[1][0].texture = gxTextureOpenPNG(items_special[1][0].data,0);
2394   items_special[2][1].texture = items_special[1][1].texture = gxTextureOpenPNG(items_special[1][1].data,0);
2395   items_device[0].texture = items_special[1][0].texture;
2396   items_device[1].texture = gxTextureOpenPNG(items_device[1].data,0);
2397 #ifdef HW_RVL
2398   items_device[2].texture = gxTextureOpenPNG(items_device[2].data,0);
2399   items_device[3].texture = gxTextureOpenPNG(items_device[3].data,0);
2400   items_device[4].texture = gxTextureOpenPNG(items_device[4].data,0);
2401   if (WiiDRC_Inited())
2402   {
2403     items_device[5].texture = gxTextureOpenPNG(items_device[5].data,0);
2404   }
2405 #endif
2406 
2407   /* restore current menu elements */
2408   player = 0;
2409   ctrlmenu_raz();
2410   memcpy(&m->items[0],&items_sys[0][input.system[0]],sizeof(gui_item));
2411   memcpy(&m->items[1],&items_sys[1][input.system[1]],sizeof(gui_item));
2412 
2413   /* menu title slide effect */
2414   m->selected = 0;
2415   GUI_SlideMenuTitle(m,strlen("Controller "));
2416 
2417   while (update != -1)
2418   {
2419     /* draw menu */
2420     GUI_DrawMenu(m);
2421 
2422     /* update menu */
2423     update = GUI_UpdateMenu(m);
2424 
2425     if (update > 0)
2426     {
2427       switch (m->selected)
2428       {
2429         case 0:   /* update port 1 system */
2430         {
2431           /* fixed configurations */
2432           if (system_hw)
2433           {
2434             if (cart.special & HW_TEREBI_OEKAKI)
2435             {
2436               GUI_WaitPrompt("Error","Terebi Oekaki detected !");
2437               break;
2438             }
2439             else if (system_hw == SYSTEM_PICO)
2440             {
2441               GUI_WaitPrompt("Error","PICO hardware detected !");
2442               break;
2443             }
2444           }
2445 
2446           /* next connected device */
2447           input.system[0]++;
2448 
2449           /* allow only one connected mouse */
2450           if ((input.system[0] == SYSTEM_MOUSE) && (input.system[1] == SYSTEM_MOUSE))
2451           {
2452             input.system[0] += 3;
2453           }
2454 
2455           /* Menacer & Justifiers on Port B only */
2456           if (input.system[0] == SYSTEM_MENACER)
2457           {
2458             input.system[0] += 2;
2459           }
2460 
2461           /* allow only one gun type */
2462           if ((input.system[0] == SYSTEM_LIGHTPHASER) && ((input.system[1] == SYSTEM_MENACER) || (input.system[1] == SYSTEM_JUSTIFIER)))
2463           {
2464             input.system[0]++;
2465           }
2466 
2467           /* allow only one connected graphic board */
2468           if ((input.system[0] == SYSTEM_GRAPHIC_BOARD) && (input.system[1] == SYSTEM_GRAPHIC_BOARD))
2469           {
2470             input.system[0]++;
2471           }
2472 
2473           /* 4-wayplay uses both ports */
2474           if (input.system[0] == SYSTEM_WAYPLAY)
2475           {
2476             input.system[1] = SYSTEM_WAYPLAY;
2477           }
2478 
2479           /* loop back */
2480           if (input.system[0] > SYSTEM_WAYPLAY)
2481           {
2482             input.system[0] = NO_SYSTEM;
2483             input.system[1] = SYSTEM_GAMEPAD;
2484           }
2485 
2486           /* reset I/O ports */
2487           io_init();
2488           input_reset();
2489 
2490           /* save current configuration */
2491           old_system[0] = input.system[0];
2492           old_system[1] = input.system[1];
2493 
2494           /* update menu elements */
2495           ctrlmenu_raz();
2496           memcpy(&m->items[0],&items_sys[0][input.system[0]],sizeof(gui_item));
2497           memcpy(&m->items[1],&items_sys[1][input.system[1]],sizeof(gui_item));
2498 
2499           if (m->bg_images[7].state & IMAGE_VISIBLE)
2500           {
2501             /* slide out configuration window */
2502             GUI_DrawMenuFX(m, 20, 1);
2503 
2504             /* remove configuration window */
2505             m->bg_images[7].state &= ~IMAGE_VISIBLE;
2506 
2507             /* disable configuration buttons */
2508             m->buttons[10].state &= (~BUTTON_VISIBLE & ~BUTTON_ACTIVE);
2509             m->buttons[11].state &= (~BUTTON_VISIBLE & ~BUTTON_ACTIVE);
2510             m->buttons[12].state &= (~BUTTON_VISIBLE & ~BUTTON_ACTIVE);
2511 
2512             /* update directions */
2513             m->buttons[2].shift[3] = 0;
2514             m->buttons[3].shift[3] = 0;
2515             m->buttons[4].shift[3] = 0;
2516             m->buttons[5].shift[3] = 0;
2517             m->buttons[6].shift[3] = 0;
2518             m->buttons[7].shift[3] = 0;
2519             m->buttons[8].shift[3] = 0;
2520             m->buttons[9].shift[3] = 0;
2521 
2522             /* update title */
2523             sprintf(m->title,"Controller Settings");
2524           }
2525           break;
2526         }
2527 
2528         case 1:   /* update port 2 system */
2529         {
2530           /* fixed configurations */
2531           if (system_hw)
2532           {
2533             if (cart.special & HW_TEREBI_OEKAKI)
2534             {
2535               GUI_WaitPrompt("Error","Terebi Oekaki detected !");
2536               break;
2537             }
2538             else if (system_hw == SYSTEM_PICO)
2539             {
2540               GUI_WaitPrompt("Error","PICO hardware detected !");
2541               break;
2542             }
2543           }
2544 
2545           /* next connected device */
2546           input.system[1]++;
2547 
2548           /* allow only one connected mouse */
2549           if ((input.system[0] == SYSTEM_MOUSE) && (input.system[1] == SYSTEM_MOUSE))
2550           {
2551             input.system[1]++;
2552           }
2553 
2554           /* allow only one gun type */
2555           if ((input.system[0] == SYSTEM_LIGHTPHASER) && (input.system[1] == SYSTEM_MENACER))
2556           {
2557             input.system[1]++;
2558           }
2559 
2560           /* allow only one gun type */
2561           if ((input.system[0] == SYSTEM_LIGHTPHASER) && (input.system[1] == SYSTEM_JUSTIFIER))
2562           {
2563             input.system[1]++;
2564           }
2565 
2566           /* allow only one connected graphic board */
2567           if ((input.system[0] == SYSTEM_GRAPHIC_BOARD) && (input.system[1] == SYSTEM_GRAPHIC_BOARD))
2568           {
2569             input.system[1]++;
2570           }
2571 
2572           /* 4-wayplay uses both ports */
2573           if (input.system[1] == SYSTEM_WAYPLAY)
2574           {
2575             input.system[0] = SYSTEM_WAYPLAY;
2576           }
2577 
2578           /* loop back */
2579           if (input.system[1] > SYSTEM_WAYPLAY)
2580           {
2581             input.system[1] = NO_SYSTEM;
2582             input.system[0] = SYSTEM_GAMEPAD;
2583           }
2584 
2585           /* reset I/O ports */
2586           io_init();
2587           input_reset();
2588 
2589           /* save current configuration */
2590           old_system[0] = input.system[0];
2591           old_system[1] = input.system[1];
2592 
2593           /* update menu elements */
2594           ctrlmenu_raz();
2595           memcpy(&m->items[0],&items_sys[0][input.system[0]],sizeof(gui_item));
2596           memcpy(&m->items[1],&items_sys[1][input.system[1]],sizeof(gui_item));
2597 
2598           if (m->bg_images[7].state & IMAGE_VISIBLE)
2599           {
2600             /* slide out configuration window */
2601             GUI_DrawMenuFX(m, 20, 1);
2602 
2603             /* remove configuration window */
2604             m->bg_images[7].state &= ~IMAGE_VISIBLE;
2605 
2606             /* disable configuration buttons */
2607             m->buttons[10].state &= (~BUTTON_VISIBLE & ~BUTTON_ACTIVE);
2608             m->buttons[11].state &= (~BUTTON_VISIBLE & ~BUTTON_ACTIVE);
2609             m->buttons[12].state &= (~BUTTON_VISIBLE & ~BUTTON_ACTIVE);
2610 
2611             /* update directions */
2612             m->buttons[2].shift[3] = 0;
2613             m->buttons[3].shift[3] = 0;
2614             m->buttons[4].shift[3] = 0;
2615             m->buttons[5].shift[3] = 0;
2616             m->buttons[6].shift[3] = 0;
2617             m->buttons[7].shift[3] = 0;
2618             m->buttons[8].shift[3] = 0;
2619             m->buttons[9].shift[3] = 0;
2620 
2621             /* update title */
2622             sprintf(m->title,"Controller Settings");
2623           }
2624 
2625           break;
2626         }
2627 
2628         case 2:
2629         case 3:
2630         case 4:
2631         case 5:
2632         case 6:
2633         case 7:
2634         case 8:
2635         case 9:
2636         {
2637           /* remove duplicate assigned inputs */
2638           for (i=0; i<MAX_INPUTS; i++)
2639           {
2640             if ((i!=player) && (config.input[i].port == config.input[player].port) &&
2641                 ((config.input[i].device == config.input[player].device) || ((config.input[i].device * config.input[player].device) == 2)))
2642             {
2643               config.input[i].device = -1;
2644               config.input[i].port = i%4;
2645             }
2646           }
2647 
2648           /* save device index */
2649           index = m->selected - 2;
2650 
2651           /* update player index */
2652           old_player = player;
2653           player = 0;
2654           for (i=0; i<index; i++)
2655           {
2656             if (input.dev[i] != NO_DEVICE) player ++;
2657           }
2658 
2659           if (m->bg_images[7].state & IMAGE_VISIBLE)
2660           {
2661             /* if already displayed, do nothing */
2662             if (old_player == player) break;
2663 
2664             /* slide out configuration window */
2665             GUI_DrawMenuFX(m, 20, 1);
2666           }
2667           else
2668           {
2669             /* append configuration window */
2670             m->bg_images[7].state |= IMAGE_VISIBLE;
2671 
2672             /* enable configuration buttons */
2673             m->buttons[10].state |= (BUTTON_VISIBLE | BUTTON_ACTIVE);
2674             m->buttons[11].state |= (BUTTON_VISIBLE | BUTTON_ACTIVE);
2675             m->buttons[12].state |= (BUTTON_VISIBLE | BUTTON_ACTIVE);
2676 
2677             /* update directions */
2678             m->buttons[2].shift[3] = 8;
2679             m->buttons[3].shift[3] = 7;
2680             m->buttons[4].shift[3] = 6;
2681             m->buttons[5].shift[3] = 5;
2682             m->buttons[6].shift[3] = 4;
2683             m->buttons[7].shift[3] = 3;
2684             m->buttons[8].shift[3] = 2;
2685             m->buttons[9].shift[3] = 1;
2686           }
2687 
2688           /* retrieve current player informations */
2689           switch (input.dev[index])
2690           {
2691             case DEVICE_PAD2B:
2692             case DEVICE_PAD3B:
2693             case DEVICE_PAD6B:
2694             {
2695               if (input.system[index/4] == SYSTEM_MASTERTAP)
2696               {
2697                 /* force 2-buttons pad */
2698                 items = items_special[3];
2699                 special = NULL;
2700               }
2701               else
2702               {
2703                 items = items_special[0];
2704                 special = &config.input[player].padtype;
2705               }
2706               break;
2707             }
2708 
2709             case DEVICE_MOUSE:
2710             {
2711               items = items_special[1];
2712               special = &config.invert_mouse;
2713               break;
2714             }
2715 
2716             case DEVICE_LIGHTGUN:
2717             {
2718               items = items_special[2];
2719               if ((input.system[1] == SYSTEM_MENACER) || (input.system[1] == SYSTEM_JUSTIFIER))
2720               {
2721                 /* Menacer & Justifiers affected to entries 4 & 5 */
2722                 special = &config.gun_cursor[index & 1];
2723               }
2724               else
2725               {
2726                 /* Lightphasers affected to entries 0 & 4 */
2727                 special = &config.gun_cursor[index / 4];
2728               }
2729               break;
2730             }
2731 
2732             default:
2733             {
2734               items = items_special[3];
2735               special = NULL;
2736               break;
2737             }
2738           }
2739 
2740           if (special)
2741           {
2742             memcpy(&m->items[10],&items[*special],sizeof(gui_item));
2743           }
2744           else
2745           {
2746             memcpy(&m->items[10],&items[0],sizeof(gui_item));
2747           }
2748 
2749           memcpy(&m->items[11],&items_device[config.input[player].device + 1],sizeof(gui_item));
2750 
2751           /* slide in configuration window */
2752           m->buttons[10].shift[2] = 10 - m->selected;
2753           m->buttons[11].shift[2] = 11 - m->selected;
2754           m->buttons[12].shift[2] = 12 - m->selected;
2755           m->selected = 10;
2756           GUI_DrawMenuFX(m, 20, 0);
2757 
2758           /* some devices require analog sticks */
2759           if ((input.dev[index] == DEVICE_XE_1AP) && ((config.input[player].device == -1) || (config.input[player].device == 1)))
2760           {
2761             GUI_WaitPrompt("Warning","One Analog Stick required !");
2762           }
2763           else if ((input.dev[index] == DEVICE_ACTIVATOR) && ((config.input[player].device != 0) && (config.input[player].device != 3)))
2764           {
2765             GUI_WaitPrompt("Warning","Two Analog Sticks required !");
2766           }
2767 
2768           /* update title */
2769           if ((cart.special & HW_J_CART) && (player > 1))
2770           {
2771             sprintf(m->title,"Controller Settings (Player %d) (J-CART)",player+1);
2772           }
2773           else
2774           {
2775             sprintf(m->title,"Controller Settings (Player %d)",player+1);
2776           }
2777           break;
2778         }
2779 
2780         case 10: /* specific option */
2781         {
2782           if (special)
2783           {
2784             /* specific case: controller type */
2785             if (input.dev[index] < 0x03)
2786             {
2787               /* switch pad type */
2788               *special = (*special + 1) & 0x03;
2789 
2790               /* reinitialize emulated device(s) */
2791               io_init();
2792               input_reset();
2793             }
2794             else
2795             {
2796               /* switch option */
2797               *special ^= 1;
2798             }
2799 
2800             /* update menu items */
2801             memcpy(&m->items[10],&items[*special],sizeof(gui_item));
2802           }
2803           break;
2804         }
2805 
2806         case 11:  /* input controller selection */
2807         {
2808           /* no input device */
2809           if (config.input[player].device < 0)
2810           {
2811             /* always try gamecube controllers first */
2812             config.input[player].device = 0;
2813             config.input[player].port = 0;
2814           }
2815           else
2816           {
2817             /* try next port */
2818             config.input[player].port ++;
2819           }
2820 
2821           /* autodetect connected gamecube controllers */
2822           if (config.input[player].device == 0)
2823           {
2824             /* find first connected controller */
2825             exp = 0;
2826             while ((config.input[player].port < 4) && !exp)
2827             {
2828               VIDEO_WaitVSync ();
2829               exp = PAD_ScanPads() & (1<<config.input[player].port);
2830               if (!exp) config.input[player].port ++;
2831             }
2832 
2833             /* no more gamecube controller */
2834             if (config.input[player].port >= 4)
2835             {
2836 #ifdef HW_RVL
2837               /* test wiimote */
2838               config.input[player].port = 0;
2839               config.input[player].device = 1;
2840 #else
2841               /* no input controller left */
2842               config.input[player].device = -1;
2843               config.input[player].port = player%4;
2844 #endif
2845             }
2846           }
2847 
2848 #ifdef HW_RVL
2849           /* autodetect connected wiimotes (without nunchuk) */
2850           if (config.input[player].device == 1)
2851           {
2852             /* find first connected controller */
2853             exp = 255;
2854             while ((config.input[player].port < 4) && (exp == 255))
2855             {
2856               WPAD_Probe(config.input[player].port,&exp);
2857 
2858               /* check if this is a Wii U Pro Controller */
2859               if (exp == WPAD_EXP_CLASSIC)
2860               {
2861                 WPADData *data = WPAD_Data(config.input[player].port);
2862                 if (data->exp.classic.type == 2)
2863                   exp = 255;
2864               }
2865 
2866               /* try next port if no wimote available */
2867               if (exp == 255)
2868                 config.input[player].port ++;
2869             }
2870 
2871             /* no more wiimote */
2872             if (config.input[player].port >= 4)
2873             {
2874               /* test wiimote+nunchuk */
2875               config.input[player].port = 0;
2876               config.input[player].device = 2;
2877             }
2878           }
2879 
2880           /* autodetect connected wiimote+nunchuk */
2881           if (config.input[player].device == 2)
2882           {
2883             /* test current port */
2884             exp = 255;
2885             if (config.input[player].port < 4)
2886             {
2887               WPAD_Probe(config.input[player].port,&exp);
2888             }
2889 
2890             /* find first connected controller */
2891             while ((config.input[player].port < 4) && (exp != WPAD_EXP_NUNCHUK))
2892             {
2893               /* try next port */
2894               config.input[player].port ++;
2895               if (config.input[player].port < 4)
2896               {
2897                 exp = 255;
2898                 WPAD_Probe(config.input[player].port,&exp);
2899               }
2900             }
2901 
2902             /* no more wiimote+nunchuk */
2903             if (config.input[player].port >= 4)
2904             {
2905               /* test classic controllers */
2906               config.input[player].port = 0;
2907               config.input[player].device = 3;
2908             }
2909           }
2910 
2911           /* autodetect connected classic controllers */
2912           if (config.input[player].device == 3)
2913           {
2914             /* test current port */
2915             exp = 255;
2916             if (config.input[player].port < 4)
2917             {
2918               WPAD_Probe(config.input[player].port,&exp);
2919             }
2920 
2921             /* find first connected controller */
2922             while ((config.input[player].port<4) && (exp != WPAD_EXP_CLASSIC))
2923             {
2924               /* try next port */
2925               config.input[player].port ++;
2926               if (config.input[player].port < 4)
2927               {
2928                 exp = 255;
2929                 WPAD_Probe(config.input[player].port,&exp);
2930               }
2931             }
2932 
2933             if (config.input[player].port >= 4)
2934             {
2935               /* test WiiU gamepad */
2936               config.input[player].device = 4;
2937               config.input[player].port = 0;
2938             }
2939           }
2940 
2941           /* autodetect WiiU gamepad */
2942           if (config.input[player].device == 4)
2943           {
2944             /* support for only one gamepad */
2945             if (!WiiDRC_Inited() || !WiiDRC_Connected() || (config.input[player].port >= 1))
2946             {
2947               /* no input controller left */
2948               config.input[player].device = -1;
2949               config.input[player].port = player%4;
2950             }
2951           }
2952 #endif
2953 
2954           /* update menu items */
2955           memcpy(&m->items[11],&items_device[config.input[player].device + 1],sizeof(gui_item));
2956 
2957           break;
2958         }
2959 
2960         case 12:  /* Controller Keys Configuration */
2961         {
2962           if (config.input[player].device >= 0)
2963           {
2964             GUI_MsgBoxOpen("Keys Configuration", "",0);
2965             if (!system_hw && special && (*special == 3))
2966             {
2967               /* no auto-detected pad type, use 6-buttons key mapping as default */
2968               gx_input_Config(config.input[player].port, config.input[player].device, DEVICE_PAD6B);
2969             }
2970             else
2971             {
2972               gx_input_Config(config.input[player].port, config.input[player].device, input.dev[index]);
2973             }
2974             GUI_MsgBoxClose();
2975           }
2976           break;
2977         }
2978       }
2979     }
2980 
2981     /* Close Window */
2982     else if (update < 0)
2983     {
2984       if (m->bg_images[7].state & IMAGE_VISIBLE)
2985       {
2986         /* slide out configuration window */
2987         GUI_DrawMenuFX(m, 20, 1);
2988 
2989         /* disable configuration window */
2990         m->bg_images[7].state &= ~IMAGE_VISIBLE;
2991 
2992         /* disable configuration buttons */
2993         m->buttons[10].state &= (~BUTTON_VISIBLE & ~BUTTON_ACTIVE);
2994         m->buttons[11].state &= (~BUTTON_VISIBLE & ~BUTTON_ACTIVE);
2995         m->buttons[12].state &= (~BUTTON_VISIBLE & ~BUTTON_ACTIVE);
2996 
2997         /* clear directions */
2998         m->buttons[2].shift[3] = 0;
2999         m->buttons[3].shift[3] = 0;
3000         m->buttons[4].shift[3] = 0;
3001         m->buttons[5].shift[3] = 0;
3002         m->buttons[6].shift[3] = 0;
3003         m->buttons[7].shift[3] = 0;
3004         m->buttons[8].shift[3] = 0;
3005         m->buttons[9].shift[3] = 0;
3006 
3007         /* update selector */
3008         m->selected -= m->buttons[m->selected].shift[2];
3009 
3010         /* restore title */
3011         sprintf(m->title,"Controller Settings");
3012 
3013         /* stay in menu */
3014         update = 0;
3015       }
3016       else
3017       {
3018         /* check we have at least one connected input before leaving */
3019         old_player = player;
3020         player = 0;
3021         for (i=0; i<MAX_DEVICES; i++)
3022         {
3023           /* check inputs */
3024           if (input.dev[i] != NO_DEVICE)
3025           {
3026             if (config.input[player].device != -1)
3027               break;
3028             player++;
3029           }
3030         }
3031         player = old_player;
3032 
3033         /* no input connected */
3034         if (i == MAX_DEVICES)
3035         {
3036           /* stay in menu */
3037           GUI_WaitPrompt("Error","No input connected !");
3038           update = 0;
3039         }
3040       }
3041     }
3042   }
3043 
3044   /* remove duplicate assigned inputs before leaving */
3045   for (i=0; i<MAX_INPUTS; i++)
3046   {
3047     if ((i!=player) && (config.input[i].port == config.input[player].port) &&
3048         ((config.input[i].device == config.input[player].device) || ((config.input[i].device * config.input[player].device) == 2)))
3049     {
3050       config.input[i].device = -1;
3051       config.input[i].port = i%4;
3052     }
3053   }
3054 
3055   /* disable configuration window */
3056   m->bg_images[7].state &= ~IMAGE_VISIBLE;
3057 
3058   /* disable configuration buttons */
3059   m->buttons[10].state &= (~BUTTON_VISIBLE & ~BUTTON_ACTIVE);
3060   m->buttons[11].state &= (~BUTTON_VISIBLE & ~BUTTON_ACTIVE);
3061   m->buttons[12].state &= (~BUTTON_VISIBLE & ~BUTTON_ACTIVE);
3062 
3063   /* clear directions */
3064   m->buttons[2].shift[3] = 0;
3065   m->buttons[3].shift[3] = 0;
3066   m->buttons[4].shift[3] = 0;
3067   m->buttons[5].shift[3] = 0;
3068   m->buttons[6].shift[3] = 0;
3069   m->buttons[7].shift[3] = 0;
3070   m->buttons[8].shift[3] = 0;
3071   m->buttons[9].shift[3] = 0;
3072 
3073   /* clear menu items */
3074   memset(&m->items[0],0,sizeof(gui_item));
3075   memset(&m->items[1],0,sizeof(gui_item));
3076   memset(&m->items[10],0,sizeof(gui_item));
3077   memset(&m->items[11],0,sizeof(gui_item));
3078 
3079   /* clear player buttons */
3080   m->buttons[2].data  = NULL;
3081   m->buttons[3].data  = NULL;
3082   m->buttons[4].data  = NULL;
3083   m->buttons[5].data  = NULL;
3084   m->buttons[6].data  = NULL;
3085   m->buttons[7].data  = NULL;
3086   m->buttons[8].data  = NULL;
3087   m->buttons[9].data  = NULL;
3088 
3089   /* delete menu */
3090   GUI_DeleteMenu(m);
3091 
3092   /* delete custom buttons */
3093   gxTextureClose(&button_player_data.texture[0]);
3094   gxTextureClose(&button_player_data.texture[1]);
3095   gxTextureClose(&button_player_none_data.texture[0]);
3096 
3097   /* delete custom images */
3098   for (i=0; i<14; i++)
3099   {
3100     gxTextureClose(&items_sys[0][i].texture);
3101   }
3102   gxTextureClose(&items_special[0][0].texture);
3103   gxTextureClose(&items_special[0][1].texture);
3104   gxTextureClose(&items_special[0][2].texture);
3105   gxTextureClose(&items_special[0][3].texture);
3106   gxTextureClose(&items_special[1][0].texture);
3107   gxTextureClose(&items_special[1][1].texture);
3108   gxTextureClose(&items_device[1].texture);
3109 #ifdef HW_RVL
3110   gxTextureClose(&items_device[2].texture);
3111   gxTextureClose(&items_device[3].texture);
3112   gxTextureClose(&items_device[4].texture);
3113   if (WiiDRC_Inited())
3114   {
3115     gxTextureClose(&items_device[5].texture);
3116   }
3117 #endif
3118 }
3119 
3120 /****************************************************************************
3121  * Main Option menu
3122  *
3123  ****************************************************************************/
optionmenu(void)3124 static void optionmenu(void)
3125 {
3126   int ret, quit = 0;
3127   gui_menu *m = &menu_options;
3128 
3129   GUI_InitMenu(m);
3130   GUI_DrawMenuFX(m,30,0);
3131 
3132   while (quit == 0)
3133   {
3134     ret = GUI_RunMenu(m);
3135 
3136     switch (ret)
3137     {
3138       case 0:
3139         GUI_DeleteMenu(m);
3140         systemmenu();
3141         GUI_InitMenu(m);
3142         break;
3143       case 1:
3144         GUI_DeleteMenu(m);
3145         videomenu();
3146         GUI_InitMenu(m);
3147         break;
3148       case 2:
3149         GUI_DeleteMenu(m);
3150         soundmenu();
3151         GUI_InitMenu(m);
3152         break;
3153       case 3:
3154         GUI_DeleteMenu(m);
3155         ctrlmenu();
3156         GUI_InitMenu(m);
3157         break;
3158       case 4:
3159         GUI_DeleteMenu(m);
3160         prefmenu();
3161         GUI_InitMenu(m);
3162         break;
3163       case -1:
3164         quit = 1;
3165         break;
3166     }
3167   }
3168 
3169   config_save();
3170   GUI_DrawMenuFX(m,30,1);
3171   GUI_DeleteMenu(m);
3172 }
3173 
3174 /****************************************************************************
3175 * Save Manager menu
3176 *
3177 ****************************************************************************/
3178 static t_slot slots[5];
3179 static gx_texture *star;
3180 
savemenu_cb(void)3181 static void savemenu_cb(void)
3182 {
3183   int i;
3184   char msg[16];
3185 
3186   if (sram.on)
3187   {
3188     FONT_write("Backup Memory",16,buttons_saves[0].x+16,buttons_saves[0].y+(buttons_saves[0].h-16)/2+16,buttons_saves[0].x+buttons_saves[0].w,(GXColor)DARK_GREY);
3189     if (slots[0].valid)
3190     {
3191       sprintf(msg,"%d/%02d/%02d",slots[0].day,slots[0].month,slots[0].year);
3192       FONT_alignRight(msg,12,buttons_saves[0].x+buttons_saves[0].w-16,buttons_saves[0].y+(buttons_saves[0].h-28)/2+12,(GXColor)DARK_GREY);
3193       sprintf(msg,"%02d:%02d",slots[0].hour,slots[0].min);
3194       FONT_alignRight(msg,12,buttons_saves[0].x+buttons_saves[0].w-16,buttons_saves[0].y+(buttons_saves[0].h-28)/2+28,(GXColor)DARK_GREY);
3195     }
3196 
3197     if (sram.crc != crc32(0, &sram.sram[0], 0x10000))
3198       gxDrawTexture(star,22,buttons_saves[0].y+(buttons_saves[0].h-star->height)/2,star->width,star->height,255);
3199   }
3200   else
3201   {
3202     FONT_writeCenter("Backup Memory disabled",16,buttons_saves[0].x,buttons_saves[0].x+buttons_saves[0].w,buttons_saves[0].y+(buttons_saves[0].h-16)/2+16,(GXColor)DARK_GREY);
3203   }
3204 
3205   for (i=1; i<5; i++)
3206   {
3207     if (slots[i].valid)
3208     {
3209       sprintf(msg,"Slot %d",i);
3210       FONT_write(msg,16,buttons_saves[i].x+16,buttons_saves[i].y+(buttons_saves[i].h-16)/2+16,buttons_saves[i].x+buttons_saves[i].w,(GXColor)DARK_GREY);
3211       sprintf(msg,"%d/%02d/%02d",slots[i].day,slots[i].month,slots[i].year);
3212       FONT_alignRight(msg,12,buttons_saves[i].x+buttons_saves[i].w-16,buttons_saves[i].y+(buttons_saves[i].h-28)/2+12,(GXColor)DARK_GREY);
3213       sprintf(msg,"%02d:%02d",slots[i].hour,slots[i].min);
3214       FONT_alignRight(msg,12,buttons_saves[i].x+buttons_saves[i].w-16,buttons_saves[i].y+(buttons_saves[i].h-28)/2+28,(GXColor)DARK_GREY);
3215     }
3216     else
3217     {
3218       FONT_write("Empty Slot",16,buttons_saves[i].x+16,buttons_saves[i].y+(buttons_saves[i].h-16)/2+16,buttons_saves[i].x+buttons_saves[i].h,(GXColor)DARK_GREY);
3219     }
3220 
3221     if (i == config.s_default)
3222       gxDrawTexture(star,22,buttons_saves[i].y+(buttons_saves[i].h-star->height)/2,star->width,star->height,255);
3223   }
3224 }
3225 
savemenu(void)3226 static int savemenu(void)
3227 {
3228   int i, update = 0;
3229   int ret = 0;
3230   int slot = -1;
3231   char filename[MAXPATHLEN];
3232   gui_menu *m = &menu_saves;
3233   FILE *snap;
3234 
3235   star = gxTextureOpenPNG(Star_full_png,0);
3236   GUI_InitMenu(m);
3237   GUI_DrawMenuFX(m,30,0);
3238 
3239   m->bg_images[3].state &= ~IMAGE_SLIDE_TOP;
3240   m->bg_images[4].state &= ~IMAGE_SLIDE_BOTTOM;
3241   m->bg_images[5].state &= ~IMAGE_SLIDE_TOP;
3242 
3243   /* detect existing files */
3244   for (i=0; i<5; i++)
3245     slot_autodetect(i, config.s_device, &slots[i]);
3246 
3247   /* SRAM disabled */
3248   if (sram.on)
3249   {
3250     m->buttons[0].state |= BUTTON_ACTIVE;
3251     m->buttons[1].shift[0] = 1;
3252   }
3253   else
3254   {
3255     m->buttons[0].state &= ~BUTTON_ACTIVE;
3256     m->buttons[1].shift[0] = 0;
3257     if (m->selected == 0)
3258       m->selected = 1;
3259   }
3260 
3261   while (update != -1)
3262   {
3263     /* slot selection */
3264     if ((m->selected < 5) && (slot != m->selected))
3265     {
3266       /* update slot */
3267       slot = m->selected;
3268 
3269       /* delete previous texture if any */
3270       gxTextureClose(&bg_saves[0].texture);
3271       bg_saves[0].state &= ~IMAGE_VISIBLE;
3272       bg_saves[1].state |= IMAGE_VISIBLE;
3273 
3274       /* state slot */
3275       if (!config.s_device && slot && slots[slot].valid)
3276       {
3277         /* open screenshot file */
3278         sprintf (filename, "%s/saves/%s__%d.png", DEFAULT_PATH, rom_filename, slot - 1);
3279         snap = fopen(filename, "rb");
3280         if (snap)
3281         {
3282           /* load texture from file */
3283           bg_saves[0].texture = gxTextureOpenPNG(0,snap);
3284           if (bg_saves[0].texture)
3285           {
3286             /* set menu background */
3287             bg_saves[0].w = bg_saves[0].texture->width * 2;
3288             if (config.aspect & 2) bg_saves[0].w = (bg_saves[0].w * 3) / 4;
3289             bg_saves[0].h = bg_saves[0].texture->height * 2;
3290             bg_saves[0].x = (vmode->fbWidth - bg_saves[0].w) / 2;
3291             bg_saves[0].y = (vmode->efbHeight - bg_saves[0].h) / 2;
3292             bg_saves[0].state |= IMAGE_VISIBLE;
3293             bg_saves[1].state &= ~IMAGE_VISIBLE;
3294           }
3295           fclose(snap);
3296         }
3297       }
3298     }
3299 
3300     /* draw menu */
3301     GUI_DrawMenu(m);
3302 
3303     /* update menu */
3304     update = GUI_UpdateMenu(m);
3305 
3306     if (update > 0)
3307     {
3308       switch (m->selected)
3309       {
3310         case 0:
3311         case 1:
3312         case 2:
3313         case 3:
3314         case 4: /* Slot selection */
3315         {
3316           /* enable right window */
3317           m->bg_images[7].state |= IMAGE_VISIBLE;
3318           m->buttons[5].state |= BUTTON_VISIBLE;
3319           m->buttons[6].state |= BUTTON_VISIBLE;
3320           m->buttons[7].state |= BUTTON_VISIBLE;
3321           m->buttons[8].state |= BUTTON_VISIBLE;
3322 
3323           /* only enable valid options */
3324           if (slots[slot].valid)
3325           {
3326             m->buttons[5].state |= BUTTON_ACTIVE;
3327             m->buttons[7].state |= BUTTON_ACTIVE;
3328             m->buttons[6].shift[0] = 1;
3329             m->buttons[6].shift[1] = 1;
3330             m->buttons[8].shift[0] = 1;
3331             m->selected = 5;
3332           }
3333           else
3334           {
3335             m->buttons[5].state &= ~BUTTON_ACTIVE;
3336             m->buttons[7].state &= ~BUTTON_ACTIVE;
3337             m->buttons[6].shift[0] = 0;
3338             m->buttons[6].shift[1] = 2;
3339             m->buttons[8].shift[0] = (slot > 0) ? 2 : 0;
3340             m->selected = 8;
3341           }
3342 
3343           /* state slot 'only' button */
3344           if (slot > 0)
3345           {
3346             m->buttons[6].state |= BUTTON_ACTIVE;
3347             m->buttons[5].shift[1] = 1;
3348             m->buttons[7].shift[0] = 1;
3349           }
3350           else
3351           {
3352             m->buttons[6].state &= ~BUTTON_ACTIVE;
3353             m->buttons[5].shift[1] = 2;
3354             m->buttons[7].shift[0] = 2;
3355           }
3356 
3357           /* disable left buttons */
3358           m->buttons[0].state &= ~BUTTON_ACTIVE;
3359           m->buttons[1].state &= ~BUTTON_ACTIVE;
3360           m->buttons[2].state &= ~BUTTON_ACTIVE;
3361           m->buttons[3].state &= ~BUTTON_ACTIVE;
3362           m->buttons[4].state &= ~BUTTON_ACTIVE;
3363 
3364           /* keep current selection highlighted */
3365           m->buttons[slot].state |= BUTTON_SELECTED;
3366 
3367           /* slide in window */
3368           GUI_DrawMenuFX(m, 20, 0);
3369 
3370           break;
3371         }
3372 
3373         case 5: /* load file */
3374         {
3375           if (slots[slot].valid)
3376           {
3377             ret = slot_load(slot,config.s_device);
3378 
3379             /* force exit */
3380             if (ret > 0)
3381             {
3382               GUI_DrawMenuFX(m, 20, 1);
3383               m->buttons[slot].state &= ~BUTTON_SELECTED;
3384               m->bg_images[7].state &= ~IMAGE_VISIBLE;
3385               if (sram.on)
3386                 m->buttons[0].state |= BUTTON_ACTIVE;
3387               m->buttons[1].state |= BUTTON_ACTIVE;
3388               m->buttons[2].state |= BUTTON_ACTIVE;
3389               m->buttons[3].state |= BUTTON_ACTIVE;
3390               m->buttons[4].state |= BUTTON_ACTIVE;
3391               m->buttons[5].state &= ~BUTTON_VISIBLE;
3392               m->buttons[6].state &= ~BUTTON_VISIBLE;
3393               m->buttons[7].state &= ~BUTTON_VISIBLE;
3394               m->buttons[8].state &= ~BUTTON_VISIBLE;
3395               m->selected = slot;
3396               update = -1;
3397             }
3398           }
3399           break;
3400         }
3401 
3402         case 6: /* set default slot */
3403         {
3404           config.s_default = slot;
3405           config_save();
3406           break;
3407         }
3408 
3409         case 7: /* delete file */
3410         {
3411           if (slots[slot].valid)
3412           {
3413             if (GUI_WaitConfirm("Warning","Delete Save File ?"))
3414             {
3415               if (slot_delete(slot,config.s_device) >= 0)
3416               {
3417                 /* hide screenshot */
3418                 gxTextureClose(&bg_saves[0].texture);
3419                 bg_saves[0].state &= ~IMAGE_VISIBLE;
3420                 bg_saves[1].state |= IMAGE_VISIBLE;
3421                 slots[slot].valid = 0;
3422                 update = -1;
3423               }
3424             }
3425           }
3426           break;
3427         }
3428 
3429         case 8: /* save file */
3430         {
3431           ret = slot_save(slot,config.s_device);
3432 
3433           /* force exit */
3434           if (ret > 0)
3435           {
3436             GUI_DrawMenuFX(m, 20, 1);
3437             m->buttons[slot].state &= ~BUTTON_SELECTED;
3438             m->bg_images[7].state &= ~IMAGE_VISIBLE;
3439             if (sram.on)
3440               m->buttons[0].state |= BUTTON_ACTIVE;
3441             m->buttons[1].state |= BUTTON_ACTIVE;
3442             m->buttons[2].state |= BUTTON_ACTIVE;
3443             m->buttons[3].state |= BUTTON_ACTIVE;
3444             m->buttons[4].state |= BUTTON_ACTIVE;
3445             m->buttons[5].state &= ~BUTTON_VISIBLE;
3446             m->buttons[6].state &= ~BUTTON_VISIBLE;
3447             m->buttons[7].state &= ~BUTTON_VISIBLE;
3448             m->buttons[8].state &= ~BUTTON_VISIBLE;
3449             m->selected = slot;
3450             update = -1;
3451           }
3452           break;
3453         }
3454 
3455         default:
3456           break;
3457       }
3458     }
3459 
3460     if (update < 0)
3461     {
3462       /* close right window */
3463       if (m->bg_images[7].state & IMAGE_VISIBLE)
3464       {
3465         /* slide out window */
3466         GUI_DrawMenuFX(m, 20, 1);
3467 
3468         /* clear current selection */
3469         m->buttons[slot].state &= ~BUTTON_SELECTED;
3470 
3471         /* enable left buttons */
3472         if (sram.on)
3473           m->buttons[0].state |= BUTTON_ACTIVE;
3474         m->buttons[1].state |= BUTTON_ACTIVE;
3475         m->buttons[2].state |= BUTTON_ACTIVE;
3476         m->buttons[3].state |= BUTTON_ACTIVE;
3477         m->buttons[4].state |= BUTTON_ACTIVE;
3478 
3479         /* disable right window */
3480         m->bg_images[7].state &= ~IMAGE_VISIBLE;
3481         m->buttons[5].state &= ~BUTTON_VISIBLE;
3482         m->buttons[6].state &= ~BUTTON_VISIBLE;
3483         m->buttons[7].state &= ~BUTTON_VISIBLE;
3484         m->buttons[8].state &= ~BUTTON_VISIBLE;
3485 
3486         /* stay in menu */
3487         m->selected = slot;
3488         update = 0;
3489       }
3490     }
3491   }
3492 
3493   /* leave menu */
3494   m->bg_images[3].state |= IMAGE_SLIDE_TOP;
3495   m->bg_images[4].state |= IMAGE_SLIDE_BOTTOM;
3496   m->bg_images[5].state |= IMAGE_SLIDE_TOP;
3497   GUI_DrawMenuFX(m,30,1);
3498   GUI_DeleteMenu(m);
3499   gxTextureClose(&star);
3500   return ret;
3501 }
3502 
3503 /****************************************************************************
3504  * Load Game menu
3505  *
3506  ****************************************************************************/
loadgamemenu()3507 static int loadgamemenu ()
3508 {
3509   int ret, filetype;
3510   gui_menu *m = &menu_load;
3511   GUI_InitMenu(m);
3512   GUI_DrawMenuFX(m,30,0);
3513 
3514   while (1)
3515   {
3516     ret = GUI_RunMenu(m);
3517 
3518     switch (ret)
3519     {
3520       /*** Button B ***/
3521       case -1:
3522         GUI_DrawMenuFX(m,30,1);
3523         GUI_DeleteMenu(m);
3524         return 0;
3525 
3526       /*** Load from selected device */
3527       default:
3528       {
3529         /* ROM File type */
3530         filetype = ret - 1;
3531 
3532         /* Try to open current directory */
3533         if (ret > 0)
3534         {
3535           ret = OpenDirectory(config.l_device, filetype);
3536         }
3537         else
3538         {
3539           ret = OpenDirectory(TYPE_RECENT, filetype);
3540         }
3541 
3542         if (ret)
3543         {
3544           GUI_DeleteMenu(m);
3545           if (FileSelector(filetype) > 0)
3546           {
3547             /* directly jump to game */
3548             return 1;
3549           }
3550           GUI_InitMenu(m);
3551         }
3552         break;
3553       }
3554     }
3555   }
3556 
3557   return 0;
3558 }
3559 
3560 /***************************************************************************
3561   * Show rom info screen
3562  ***************************************************************************/
showrominfo(void)3563 static void showrominfo (void)
3564 {
3565   char items[15][64];
3566 
3567   /* fill ROM infos */
3568   sprintf (items[0], "Console Type: %s", rominfo.consoletype);
3569   sprintf (items[1], "Copyright: %s", rominfo.copyright);
3570   sprintf (items[2], "Company Name: %s", get_company());
3571   sprintf (items[3], "Domestic Name:");
3572   sprintf (items[4], "%s",rominfo.domestic);
3573   sprintf (items[5], "International Name:");
3574   sprintf (items[6], "%s",rominfo.international);
3575   sprintf (items[7], "Type: %s (%s)",rominfo.ROMType, strcmp(rominfo.ROMType, "AI") ? "Game" : "Educational");
3576   sprintf (items[8], "Product ID: %s", rominfo.product);
3577   sprintf (items[9], "Checksum: %04x (%04x) (%s)", rominfo.checksum, rominfo.realchecksum,
3578                                                   (rominfo.checksum == rominfo.realchecksum) ? "GOOD" : "BAD");
3579 
3580   sprintf (items[10], "Supports: ");
3581   if (rominfo.peripherals & (1 << 1))
3582   {
3583     strcat(items[10],get_peripheral(1));
3584     strcat(items[10],", ");
3585   }
3586   else if (rominfo.peripherals & (1 << 0))
3587   {
3588     strcat(items[10],get_peripheral(0));
3589     strcat(items[10],", ");
3590   }
3591   if (rominfo.peripherals & (1 << 7))
3592   {
3593     strcat(items[10],get_peripheral(7));
3594     strcat(items[10],", ");
3595   }
3596   if (rominfo.peripherals & (1 << 8))
3597   {
3598     strcat(items[10],get_peripheral(8));
3599     strcat(items[10],", ");
3600   }
3601   if (rominfo.peripherals & (1 << 11))
3602   {
3603     strcat(items[10],get_peripheral(11));
3604     strcat(items[10],", ");
3605   }
3606   if (rominfo.peripherals & (1 << 13))
3607   {
3608     strcat(items[10],get_peripheral(13));
3609     strcat(items[10],", ");
3610   }
3611   if (strlen(items[10]) > 10)
3612     items[10][strlen(items[10]) - 2] = 0;
3613 
3614   sprintf (items[11], "ROM end: $%06X", rominfo.romend);
3615 
3616   if (sram.custom)
3617     sprintf (items[12], "Serial EEPROM");
3618   else if (sram.detected)
3619     sprintf (items[12], "SRAM Start: $%06X", sram.start);
3620   else
3621     sprintf (items[12], "No Backup Memory specified");
3622 
3623   if (sram.custom == 1)
3624     sprintf (items[13], "Type: I2C (24Cxx)");
3625   else if (sram.custom == 2)
3626     sprintf (items[13], "Type: SPI (25x512/95x512)");
3627   else if (sram.custom == 3)
3628     sprintf (items[13], "Type: I2C (93C46)");
3629   else if (sram.detected)
3630     sprintf (items[13], "SRAM End: $%06X", sram.end);
3631   else if (sram.on)
3632     sprintf (items[13], "SRAM enabled by default");
3633   else
3634     sprintf (items[13], "SRAM disabled by default");
3635 
3636   if (region_code == REGION_USA)
3637     sprintf (items[14], "Region Code: %s (USA)", rominfo.country);
3638   else if (region_code == REGION_EUROPE)
3639     sprintf (items[14], "Region Code: %s (EUR)", rominfo.country);
3640   else if (region_code == REGION_JAPAN_NTSC)
3641     sprintf (items[14], "Region Code: %s (JPN)", rominfo.country);
3642   else if (region_code == REGION_JAPAN_PAL)
3643     sprintf (items[14], "Region Code: %s (JPN-PAL)", rominfo.country);
3644 
3645   GUI_TextWindow(&menu_main, "ROM Header Info", items, 15, 15);
3646 }
3647 
3648 /***************************************************************************
3649   * Show credits
3650  ***************************************************************************/
showcredits(void)3651 static void showcredits(void)
3652 {
3653   int offset = 0;
3654 
3655   gx_texture *texture = gxTextureOpenPNG(Bg_credits_png,0);
3656   s16 p = 0;
3657 
3658   while (!p)
3659   {
3660     gxClearScreen ((GXColor)BLACK);
3661     if (texture)
3662       gxDrawTexture(texture, (640-texture->width)/2, (480-texture->height)/2, texture->width, texture->height,255);
3663 
3664     FONT_writeCenter("Genesis Plus GX Core", 24, 0, 640, 480 - offset, (GXColor)LIGHT_BLUE);
3665     FONT_writeCenter("improved emulation code & additional features by Eke-Eke", 18, 0, 640, 516 - offset, (GXColor)WHITE);
3666     FONT_writeCenter("original Genesis Plus (1.3) version by Charles MacDonald", 18, 0, 640, 534 - offset, (GXColor)WHITE);
3667     FONT_writeCenter("original Z80 core by Juergen Buchmueller", 18, 0, 640, 552 - offset, (GXColor)WHITE);
3668     FONT_writeCenter("original 68k core (Musashi) by Karl Stenerud", 18, 0, 640, 570 - offset, (GXColor)WHITE);
3669     FONT_writeCenter("original YM2612/2413 cores by Jarek Burczynski, Tatsuyuki Satoh", 18, 0, 640, 588 - offset, (GXColor)WHITE);
3670     FONT_writeCenter("SVP core by Gravydas Ignotas (Notaz)", 18, 0, 640, 606 - offset, (GXColor)WHITE);
3671     FONT_writeCenter("Blip Buffer Library & NTSC Video Filter by Shay Green (Blargg)", 18, 0, 640, 624 - offset, (GXColor)WHITE);
3672     FONT_writeCenter("3-Band EQ implementation by Neil C", 18, 0, 640, 642 - offset, (GXColor)WHITE);
3673     FONT_writeCenter("Ogg Vorbis 'Tremor' Library by Xiph.org Foundation", 18, 0, 640, 660 - offset, (GXColor)WHITE);
3674     FONT_writeCenter("CHD Library by Aaron Giles, Romain Tisserand", 18, 0, 640, 678 - offset, (GXColor)WHITE);
3675     FONT_writeCenter("FLAC Library by Josh Coalson & Xiph.org Foundation", 18, 0, 640, 696 - offset, (GXColor)WHITE);
3676     FONT_writeCenter("ZLIB Library by Jean-loup Gailly & Mark Adler", 18, 0, 640, 714 - offset, (GXColor)WHITE);
3677     FONT_writeCenter("LZMA Library by Igor Pavlov", 18, 0, 640, 732 - offset, (GXColor)WHITE);
3678 
3679     FONT_writeCenter("Special thanks to ...", 20, 0, 640, 772 - offset, (GXColor)LIGHT_GREEN);
3680     FONT_writeCenter("Nemesis, Tasco Deluxe, Mask of Destiny, Bart Trzynadlowski, Haze,", 18, 0, 640, 808 - offset, (GXColor)WHITE);
3681     FONT_writeCenter("Jorge Cwik, Stef, Notaz, AamirM, Steve Snake, Charles MacDonald", 18, 0, 640, 826 - offset, (GXColor)WHITE);
3682     FONT_writeCenter("Spritesmind & SMS Power forums members for their technical help", 18, 0, 640, 844 - offset, (GXColor)WHITE);
3683 
3684     FONT_writeCenter("Gamecube & Wii port", 24, 0, 640, 902 - offset, (GXColor)LIGHT_BLUE);
3685     FONT_writeCenter("porting code, GUI engine & design by Eke-Eke", 18, 0, 640, 938 - offset, (GXColor)WHITE);
3686     FONT_writeCenter("original Gamecube port by Softdev, Honkeykong & Markcube", 18, 0, 640, 956 - offset, (GXColor)WHITE);
3687     FONT_writeCenter("original icons, logo & button design by Low Lines", 18, 0, 640, 974 - offset, (GXColor)WHITE);
3688     FONT_writeCenter("credit illustration by Orioto (Deviant Art)", 18, 0, 640, 992 - offset, (GXColor)WHITE);
3689     FONT_writeCenter("memory card icon design by Brakken", 18, 0, 640, 1010 - offset, (GXColor)WHITE);
3690     FONT_writeCenter("libogc by Shagkur & various other contibutors", 18, 0, 640, 1028 - offset, (GXColor)WHITE);
3691     FONT_writeCenter("libfat by Chism", 18, 0, 640, 1046 - offset, (GXColor)WHITE);
3692     FONT_writeCenter("wiiuse by Michael Laforest (Para)", 18, 0, 640, 1064 - offset, (GXColor)WHITE);
3693     FONT_writeCenter("asndlib & OGG player by Francisco Mu�oz (Hermes)", 18, 0, 640, 1082 - offset, (GXColor)WHITE);
3694     FONT_writeCenter("libwiidrc by Fix94", 18, 0, 640, 1100 - offset, (GXColor)WHITE);
3695     FONT_writeCenter("libpng by their respective authors", 18, 0, 640, 1118 - offset, (GXColor)WHITE);
3696     FONT_writeCenter("devkitPPC by Wintermute", 18, 0, 640, 1136 - offset, (GXColor)WHITE);
3697 
3698     FONT_writeCenter("Special thanks to ...", 20, 0, 640, 1176 - offset, (GXColor)LIGHT_GREEN);
3699     FONT_writeCenter("Softdev, Tmbinc, Costis, Emukiddid, Team Twiizer", 18, 0, 640, 1212 - offset, (GXColor)WHITE);
3700     FONT_writeCenter("Brakken & former Tehskeen members for their support", 18, 0, 640, 1230 - offset, (GXColor)WHITE);
3701     FONT_writeCenter("Anca, my wife, for her patience & various ideas", 18, 0, 640, 1248 - offset, (GXColor)WHITE);
3702 
3703     gxSetScreen();
3704     p = m_input.keys;
3705     gxSetScreen();
3706     p |= m_input.keys;
3707     offset ++;
3708     if (offset > 1222)
3709       offset = 0;
3710   }
3711 
3712   gxTextureClose(&texture);
3713 }
3714 
exitmenu(void)3715 static void exitmenu(void)
3716 {
3717   char title[64];
3718   char infos[64];
3719   char *items[3] =
3720   {
3721     "View Credits",
3722 #ifdef HW_RVL
3723     "Exit to System Menu",
3724 #else
3725     "Reset System",
3726 #endif
3727     "Return to Loader",
3728   };
3729 
3730 #ifdef HW_RVL
3731   extern u8 __Arena2Lo[];
3732   sprintf(title, "%s (IOS %d)", VERSION, IOS_GetVersion());
3733   if ((u32)SYS_GetArena2Lo() > (u32)__Arena2Lo)
3734     sprintf(infos, "%d bytes free (MEM2)", (u32)SYS_GetArena2Size());
3735   else
3736     sprintf(infos, "%d bytes free (MEM1)", (u32)SYS_GetArena1Size());
3737 #else
3738   sprintf(title, "%s (GCN)", VERSION);
3739   sprintf(infos, "%d bytes free", (u32)SYS_GetArenaSize());
3740 #endif
3741 
3742   /* check if loader stub exists */
3743   int maxitems = reload ? 3 : 2;
3744 
3745   /* display option window */
3746   switch (GUI_OptionWindow(&menu_main, title, infos, items, maxitems))
3747   {
3748     case 0: /* credits */
3749       GUI_DeleteMenu(&menu_main);
3750       showcredits();
3751       GUI_InitMenu(&menu_main);
3752       break;
3753 
3754     case 1: /* reset */
3755 #ifdef HW_RVL
3756       gxTextureClose(&w_pointer);
3757 #endif
3758       GUI_DeleteMenu(&menu_main);
3759       GUI_FadeOut();
3760       shutdown();
3761 #ifdef HW_RVL
3762       SYS_ResetSystem(SYS_RETURNTOMENU, 0, 0);
3763 #else
3764       SYS_ResetSystem(SYS_HOTRESET,0,0);
3765 #endif
3766       break;
3767 
3768     case 2: /* exit to loader */
3769 #ifdef HW_RVL
3770       gxTextureClose(&w_pointer);
3771 #endif
3772       GUI_DeleteMenu(&menu_main);
3773       GUI_FadeOut();
3774       shutdown();
3775       SYS_ResetSystem(SYS_SHUTDOWN,0,0);
3776       __lwp_thread_stopmultitasking(*reload);
3777       break;
3778 
3779     default:
3780       break;
3781   }
3782 }
3783 
3784 /****************************************************************************
3785  * Main Menu
3786  *
3787  ****************************************************************************/
3788 
mainmenu_cb(void)3789 static void mainmenu_cb(void)
3790 {
3791   char temp[4];
3792   gui_menu *m = &menu_main;
3793   int status = areplay_get_status();
3794 
3795   /* Action Replay Switch current status */
3796   if (status == AR_SWITCH_TRAINER)
3797     strcpy(temp,"TM");
3798   else if (status == AR_SWITCH_ON)
3799     strcpy(temp,"ON");
3800   else
3801     strcpy(temp,"OFF");
3802 
3803   /* Display informations */
3804   if (m->selected == 6)
3805   {
3806     FONT_writeCenter("Action\nReplay", 14, m->items[6].x, m->items[6].x + 54, m->items[6].y + (m->items[6].h - 28)/2 + 14, (GXColor)DARK_GREY);
3807     FONT_writeCenter(temp, 11, m->items[6].x + 56 + 3, m->items[6].x + 78 + 2, m->items[6].y + (m->items[6].h - 11)/2 + 11, (GXColor)DARK_GREY);
3808   }
3809   else
3810   {
3811     FONT_writeCenter("Action\nReplay", 12, m->items[6].x + 4, m->items[6].x + 54, m->items[6].y + (m->items[6].h - 24)/2 + 12, (GXColor)DARK_GREY);
3812     FONT_writeCenter(temp, 10, m->items[6].x + 56, m->items[6].x + 78, m->items[6].y + (m->items[6].h - 10)/2 + 10, (GXColor)DARK_GREY);
3813   }
3814 }
3815 
mainmenu(void)3816 void mainmenu(void)
3817 {
3818   char filename[MAXPATHLEN];
3819   int status, quit = 0;
3820 
3821   /* Autosave Backup RAM */
3822   slot_autosave(0, config.s_device);
3823 
3824 #ifdef HW_RVL
3825   /* Detect shutdown request */
3826   if (Shutdown)
3827   {
3828     GUI_FadeOut();
3829     shutdown();
3830     if (reload)
3831     {
3832       /* exit to loader if requested */
3833       SYS_ResetSystem(SYS_SHUTDOWN,0,0);
3834       __lwp_thread_stopmultitasking(*reload);
3835     }
3836     else
3837     {
3838       /* shutdown system by default */
3839       SYS_ResetSystem(SYS_POWEROFF, 0, 0);
3840     }
3841   }
3842 
3843   /* Wiimote pointer */
3844   w_pointer = gxTextureOpenPNG(generic_point_png,0);
3845 #endif
3846 
3847   gui_menu *m = &menu_main;
3848 
3849   /* Update main menu */
3850   if (!m->screenshot)
3851   {
3852     if (config.bg_overlay)
3853     {
3854       bg_main[1].state  |= IMAGE_VISIBLE;
3855       bg_misc[1].state  |= IMAGE_VISIBLE;
3856       bg_ctrls[1].state |= IMAGE_VISIBLE;
3857       bg_list[1].state  |= IMAGE_VISIBLE;
3858       bg_saves[2].state |= IMAGE_VISIBLE;
3859     }
3860     else
3861     {
3862       bg_main[1].state  &= ~IMAGE_VISIBLE;
3863       bg_misc[1].state  &= ~IMAGE_VISIBLE;
3864       bg_ctrls[1].state &= ~IMAGE_VISIBLE;
3865       bg_list[1].state  &= ~IMAGE_VISIBLE;
3866       bg_saves[2].state &= ~IMAGE_VISIBLE;
3867     }
3868 
3869     if (system_hw)
3870     {
3871       m->screenshot = 128;
3872       m->bg_images[0].state &= ~IMAGE_VISIBLE;
3873       m->items[0].y -= 90;
3874       m->items[1].y -= 90;
3875       m->items[2].y -= 90;
3876       m->buttons[0].y -= 90;
3877       m->buttons[1].y -= 90;
3878       m->buttons[2].y -= 90;
3879       m->buttons[0].shift[1] = 3;
3880       m->buttons[1].shift[1] = 3;
3881       m->buttons[2].shift[1] = 3;
3882       m->buttons[3].state |= (BUTTON_VISIBLE | BUTTON_ACTIVE);
3883       m->buttons[4].state |= (BUTTON_VISIBLE | BUTTON_ACTIVE);
3884       m->buttons[5].state |= (BUTTON_VISIBLE | BUTTON_ACTIVE);
3885       m->buttons[7].state |= (BUTTON_VISIBLE | BUTTON_ACTIVE);
3886       m->buttons[8].state |= (BUTTON_VISIBLE | BUTTON_ACTIVE);
3887       m->buttons[9].state |= (BUTTON_VISIBLE | BUTTON_ACTIVE);
3888       if (areplay_get_status() >= 0)
3889       {
3890         menu_main.buttons[6].state |= (BUTTON_VISIBLE | BUTTON_ACTIVE);
3891         menu_main.items[6].data = Button_sm_grey_png;
3892         menu_main.cb = mainmenu_cb;
3893         menu_main.buttons[3].shift[1] = 3;
3894         menu_main.buttons[7].shift[0] = 1;
3895         menu_main.buttons[8].shift[2] = 2;
3896       }
3897     }
3898   }
3899 
3900   GUI_InitMenu(m);
3901   GUI_DrawMenuFX(m,10,0);
3902 
3903   while (quit == 0)
3904   {
3905     switch (GUI_RunMenu(m))
3906     {
3907       /*** Load Game Menu ***/
3908       case 0:
3909       {
3910         GUI_DrawMenuFX(m,30,1);
3911         GUI_DeleteMenu(m);
3912 
3913         if (loadgamemenu())
3914         {
3915           /* restart emulation */
3916           reloadrom();
3917 
3918           /* check current controller configuration */
3919           if (!gx_input_FindDevices())
3920           {
3921             GUI_InitMenu(m);
3922             GUI_DrawMenuFX(m,30,0);
3923             GUI_WaitPrompt("Error","Invalid Controllers Settings");
3924             break;
3925           }
3926 
3927           /* exit to game and reinitialize emulation */
3928           gxClearScreen((GXColor)BLACK);
3929           gxSetScreen();
3930           quit = 1;
3931           break;
3932         }
3933 
3934         GUI_InitMenu(m);
3935         GUI_DrawMenuFX(m,30,0);
3936         break;
3937       }
3938 
3939       /*** Options Menu */
3940       case 1:
3941       {
3942         GUI_DrawMenuFX(m,30,1);
3943         GUI_DeleteMenu(m);
3944         optionmenu();
3945         GUI_InitMenu(m);
3946         GUI_DrawMenuFX(m,30,0);
3947         break;
3948       }
3949 
3950       /*** Exit Menu ***/
3951       case 2:
3952       {
3953         exitmenu();
3954         break;
3955       }
3956 
3957       /*** Save Manager ***/
3958       case 3:
3959       {
3960         GUI_DrawMenuFX(m,30,1);
3961         GUI_DeleteMenu(m);
3962 
3963         if (savemenu())
3964         {
3965           /* check current controller configuration */
3966           if (!gx_input_FindDevices())
3967           {
3968             GUI_InitMenu(m);
3969             GUI_DrawMenuFX(m,30,0);
3970             GUI_WaitPrompt("Error","Invalid Controllers Settings");
3971             break;
3972           }
3973 
3974           /* exit to game */
3975           quit = 1;
3976           break;
3977         }
3978 
3979         GUI_InitMenu(m);
3980         GUI_DrawMenuFX(m,30,0);
3981         break;
3982       }
3983 
3984       /*** Soft / Hard reset ***/
3985       case 4:
3986       {
3987         /* check current controller configuration */
3988         if (!gx_input_FindDevices())
3989         {
3990           GUI_WaitPrompt("Error","Invalid Controllers Settings");
3991           break;
3992         }
3993 
3994         /* reinitialize emulation */
3995         GUI_DrawMenuFX(m,10,1);
3996         GUI_DeleteMenu(m);
3997         gxClearScreen((GXColor)BLACK);
3998         gxSetScreen();
3999 
4000         if (system_hw & SYSTEM_MD)
4001         {
4002           /* Soft Reset */
4003           gen_reset(0);
4004         }
4005         else if ((system_hw == SYSTEM_SMS) && (region_code != REGION_JAPAN_NTSC))
4006         {
4007           /* assert RESET input (export Master System 1 only) */
4008           io_reg[0x0D] &= ~IO_RESET_HI;
4009         }
4010         else
4011         {
4012           /* Hard Reset */
4013           system_reset();
4014         }
4015 
4016         /* exit to game */
4017         quit = 1;
4018         break;
4019       }
4020 
4021       /*** Cheats menu ***/
4022       case 5:
4023       {
4024         GUI_DrawMenuFX(m,30,1);
4025         GUI_DeleteMenu(m);
4026         CheatMenu();
4027         GUI_InitMenu(m);
4028         GUI_DrawMenuFX(m,30,0);
4029         break;
4030       }
4031 
4032       /*** Action Replay switch ***/
4033       case 6:
4034       {
4035         status = (areplay_get_status() + 1) % (AR_SWITCH_TRAINER + 1);
4036         areplay_set_status(status);
4037         status = areplay_get_status();
4038         GUI_DeleteMenu(m);
4039         if (status == AR_SWITCH_TRAINER) m->items[6].data = Button_sm_blue_png;
4040         else if (status == AR_SWITCH_ON) m->items[6].data = Button_sm_yellow_png;
4041         else m->items[6].data = Button_sm_grey_png;
4042         GUI_InitMenu(m);
4043         break;
4044       }
4045 
4046       /*** Return to Game ***/
4047       case 7:
4048       case -1:
4049       {
4050         if (system_hw)
4051         {
4052           /* check current controller configuration */
4053           if (!gx_input_FindDevices())
4054           {
4055             GUI_WaitPrompt("Error","Invalid Controllers Settings");
4056             break;
4057           }
4058 
4059           /* exit to game */
4060           GUI_DrawMenuFX(m,10,1);
4061           GUI_DeleteMenu(m);
4062           quit = 1;
4063         }
4064         break;
4065       }
4066 
4067       /*** Game Capture ***/
4068       case 8:
4069       {
4070         /* PNG filename */
4071         sprintf(filename,"%s/snaps/%s.png", DEFAULT_PATH, rom_filename);
4072 
4073         /* Save file and return */
4074         gxSaveScreenshot(filename);
4075         break;
4076       }
4077 
4078       /*** ROM information screen ***/
4079       case 9:
4080       {
4081         showrominfo();
4082         break;
4083       }
4084     }
4085   }
4086 
4087   /*** Remove any still held buttons ***/
4088   while (PAD_ButtonsHeld(0))
4089   {
4090     VIDEO_WaitVSync();
4091     PAD_ScanPads();
4092   }
4093 #ifdef HW_RVL
4094   while (WPAD_ButtonsHeld(0))
4095   {
4096     VIDEO_WaitVSync();
4097     WPAD_ScanPads();
4098   }
4099   gxTextureClose(&w_pointer);
4100 
4101   /* USB Mouse support */
4102   if ((input.system[0] == SYSTEM_MOUSE) || (input.system[1] == SYSTEM_MOUSE))
4103   {
4104     MOUSE_Init();
4105   }
4106   else
4107   {
4108     MOUSE_Deinit();
4109   }
4110 #endif
4111 }
4112