~jazzva/fakenes/ubuntu

« back to all changes in this revision

Viewing changes to src/gui.c

  • Committer: Sasa Bodiroza
  • Date: 2007-08-15 05:37:49 UTC
  • Revision ID: jazzva@gmail.com-20070815053749-76l0xj66tzgt290p
Upstream release.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* FakeNES - A free, portable, Open Source NES emulator.
 
2
 
 
3
   gui.c: Implementation of the object-based GUI.
 
4
 
 
5
   Copyright (c) 2001-2006, FakeNES Team.
 
6
   This is free software.  See 'LICENSE' for details.
 
7
   You must read and accept the license prior to use. */
 
8
 
 
9
#include <allegro.h>
 
10
#ifdef USE_ALLEGROGL
 
11
#include <alleggl.h>
 
12
#endif
 
13
#include <stdio.h>
 
14
#include <stdlib.h>
 
15
#include <string.h>
 
16
#include "apu.h"
 
17
#include "audio.h"
 
18
#include "cheats.h"
 
19
#include "common.h"
 
20
#include "config.h"
 
21
#include "cpu.h"
 
22
#include "data.h"
 
23
#include "debug.h"
 
24
#include "gui.h"
 
25
#include "input.h"
 
26
#include "log.h"
 
27
#include "mmc.h"
 
28
#include "netplay.h"
 
29
#include "nsf.h"
 
30
#include "ppu.h"
 
31
#include "rom.h"
 
32
#include "save.h"
 
33
#include "timing.h"
 
34
#include "types.h"
 
35
#include "version.h"
 
36
#include "video.h"
 
37
 
 
38
// TODO: Add configuration for the real-time game rewinder.
 
39
 
 
40
static BITMAP *gui_buffer = NULL;
 
41
 
 
42
static int dialog_x = 0;
 
43
static int dialog_y = 0;
 
44
static BOOL restart_dialog = FALSE;
 
45
 
 
46
GUI_THEME gui_theme;
 
47
ENUM gui_theme_id = -1;
 
48
const GUI_THEME *last_theme = NULL;
 
49
 
 
50
RGB *gui_image_palette = NULL;
 
51
static BITMAP *gui_mouse_sprite = NULL;
 
52
static BITMAP *background_image = NULL;
 
53
 
 
54
BOOL gui_is_active = FALSE;
 
55
static BOOL gui_needs_restart = FALSE;
 
56
static BOOL want_exit = FALSE;
 
57
 
 
58
static USTRING message_buffer;
 
59
 
 
60
static PALETTE custom_palette;
 
61
 
 
62
static int save_state_index = 0; /* For save states. */
 
63
static int replay_index = 0;     /* For replays. */
 
64
 
 
65
/* Text that appears in "unused" menu slots for recent items. */
 
66
#define UNUSED_SLOT_TEXT   "Empty"
 
67
 
 
68
/* Number of slots available in each of the associated menus. */
 
69
#define OPEN_RECENT_SLOTS  10
 
70
#define REPLAY_SLOTS       10
 
71
#define SAVE_STATE_SLOTS   10
 
72
 
 
73
static USTRING open_recent_filenames[OPEN_RECENT_SLOTS];
 
74
static USTRING open_recent_menu_texts[OPEN_RECENT_SLOTS];
 
75
static USTRING replay_titles[REPLAY_SLOTS];
 
76
static USTRING replay_menu_texts[REPLAY_SLOTS];
 
77
static USTRING save_state_titles[SAVE_STATE_SLOTS];
 
78
static USTRING save_state_menu_texts[SAVE_STATE_SLOTS];
 
79
 
 
80
static BOOL lock_recent = FALSE;
 
81
 
 
82
/* Keep these in order! */
 
83
#include "gui/themes.h"
 
84
#include "gui/objects.h"
 
85
#include "gui/menus.h"
 
86
#include "gui/dialogs.h"
 
87
#include "gui/util.h"
 
88
#include "gui/file.h"
 
89
 
 
90
static INLINE void update_menus (void)
 
91
{
 
92
   static USTRING audio_menu_volume_text;
 
93
 
 
94
#ifndef USE_OPENAL
 
95
   DISABLE_MENU_ITEM(audio_output_menu_subsystem_openal);
 
96
#endif
 
97
 
 
98
   if (!rom_is_loaded)                
 
99
   {
 
100
      DISABLE_MENU_ITEM(main_menu_resume);
 
101
      DISABLE_MENU_ITEM(main_menu_close);
 
102
      DISABLE_SUBMENU(main_replay_menu);
 
103
      DISABLE_MENU_ITEM(main_menu_cheat_manager);
 
104
      DISABLE_MENU_ITEM(main_menu_save_snapshot);
 
105
      DISABLE_MENU_ITEM(main_menu_advance_frame);
 
106
      DISABLE_MENU_ITEM(machine_menu_reset);
 
107
      DISABLE_MENU_ITEM(machine_menu_power_cycle);
 
108
      DISABLE_SUBMENU(machine_save_state_menu);
 
109
      DISABLE_SUBMENU(audio_record_menu);
 
110
      DISABLE_MENU_ITEM(video_layers_menu_flip_mirroring);
 
111
      DISABLE_MENU_ITEM(options_menu_reset_clock);
 
112
   }
 
113
 
 
114
   /* Page buffer and VSync are not supported in OpenGL mode. */
 
115
   SET_MENU_ITEM_ENABLED(video_menu_page_buffer, !video_is_opengl_mode ());
 
116
   SET_MENU_ITEM_ENABLED(video_menu_vsync,       !video_is_opengl_mode ());
 
117
 
 
118
   TOGGLE_MENU_ITEM(main_open_recent_menu_lock, lock_recent);
 
119
 
 
120
   TOGGLE_MENU_ITEM(main_replay_select_menu_0, (replay_index == 0));
 
121
   TOGGLE_MENU_ITEM(main_replay_select_menu_1, (replay_index == 1));
 
122
   TOGGLE_MENU_ITEM(main_replay_select_menu_2, (replay_index == 2));
 
123
   TOGGLE_MENU_ITEM(main_replay_select_menu_3, (replay_index == 3));
 
124
   TOGGLE_MENU_ITEM(main_replay_select_menu_4, (replay_index == 4));
 
125
 
 
126
   TOGGLE_MENU_ITEM(machine_menu_show_status, video_display_status);
 
127
 
 
128
   TOGGLE_MENU_ITEM(machine_menu_timing_smoothest,     (machine_timing == MACHINE_TIMING_SMOOTH));
 
129
   TOGGLE_MENU_ITEM(machine_menu_timing_most_accurate, (machine_timing == MACHINE_TIMING_ACCURATE));
 
130
 
 
131
   TOGGLE_MENU_ITEM(machine_save_state_select_menu_0, (save_state_index == 0));
 
132
   TOGGLE_MENU_ITEM(machine_save_state_select_menu_1, (save_state_index == 1));
 
133
   TOGGLE_MENU_ITEM(machine_save_state_select_menu_2, (save_state_index == 2));
 
134
   TOGGLE_MENU_ITEM(machine_save_state_select_menu_3, (save_state_index == 3));
 
135
   TOGGLE_MENU_ITEM(machine_save_state_select_menu_4, (save_state_index == 4));
 
136
   TOGGLE_MENU_ITEM(machine_save_state_select_menu_5, (save_state_index == 5));
 
137
   TOGGLE_MENU_ITEM(machine_save_state_select_menu_6, (save_state_index == 6));
 
138
   TOGGLE_MENU_ITEM(machine_save_state_select_menu_7, (save_state_index == 7));
 
139
   TOGGLE_MENU_ITEM(machine_save_state_select_menu_8, (save_state_index == 8));
 
140
   TOGGLE_MENU_ITEM(machine_save_state_select_menu_9, (save_state_index == 9));
 
141
 
 
142
   TOGGLE_MENU_ITEM(machine_save_state_autosave_menu_disabled,   (input_autosave_interval == 0));
 
143
   TOGGLE_MENU_ITEM(machine_save_state_autosave_menu_10_seconds, (input_autosave_interval == 10));
 
144
   TOGGLE_MENU_ITEM(machine_save_state_autosave_menu_30_seconds, (input_autosave_interval == 30));
 
145
   TOGGLE_MENU_ITEM(machine_save_state_autosave_menu_60_seconds, (input_autosave_interval == 60));
 
146
 
 
147
   TOGGLE_MENU_ITEM(machine_region_menu_automatic, (machine_region == MACHINE_REGION_AUTOMATIC));
 
148
   TOGGLE_MENU_ITEM(machine_region_menu_ntsc,      (machine_region == MACHINE_REGION_NTSC));
 
149
   TOGGLE_MENU_ITEM(machine_region_menu_pal,       (machine_region == MACHINE_REGION_PAL));
 
150
 
 
151
   TOGGLE_MENU_ITEM(machine_speed_up_down_menu_50_percent,  COMPARE_TWO_REALS(timing_speed_multiplier, 0.5));
 
152
   TOGGLE_MENU_ITEM(machine_speed_up_down_menu_100_percent, COMPARE_TWO_REALS(timing_speed_multiplier, 1.0));
 
153
   TOGGLE_MENU_ITEM(machine_speed_up_down_menu_200_percent, COMPARE_TWO_REALS(timing_speed_multiplier, 2.0));
 
154
 
 
155
   TOGGLE_MENU_ITEM(machine_menu_speed_cap, speed_cap);
 
156
 
 
157
   TOGGLE_MENU_ITEM(machine_frame_skip_menu_automatic, (frame_skip == -1));
 
158
   TOGGLE_MENU_ITEM(machine_frame_skip_menu_disabled,  (frame_skip == 0));
 
159
   TOGGLE_MENU_ITEM(machine_frame_skip_menu_1_frames,  (frame_skip == 1));
 
160
   TOGGLE_MENU_ITEM(machine_frame_skip_menu_2_frames,  (frame_skip == 2));
 
161
   TOGGLE_MENU_ITEM(machine_frame_skip_menu_3_frames,  (frame_skip == 3));
 
162
   TOGGLE_MENU_ITEM(machine_frame_skip_menu_4_frames,  (frame_skip == 4));
 
163
   TOGGLE_MENU_ITEM(machine_frame_skip_menu_5_frames,  (frame_skip == 5));
 
164
   TOGGLE_MENU_ITEM(machine_frame_skip_menu_6_frames,  (frame_skip == 6));
 
165
   TOGGLE_MENU_ITEM(machine_frame_skip_menu_7_frames,  (frame_skip == 7));
 
166
   TOGGLE_MENU_ITEM(machine_frame_skip_menu_8_frames,  (frame_skip == 8));
 
167
   TOGGLE_MENU_ITEM(machine_frame_skip_menu_9_frames,  (frame_skip == 9));
 
168
   TOGGLE_MENU_ITEM(machine_frame_skip_menu_10_frames, (frame_skip == 10));
 
169
 
 
170
   TOGGLE_MENU_ITEM(audio_menu_enable_apu,    apu_options.enabled);
 
171
   TOGGLE_MENU_ITEM(audio_menu_enable_output, audio_options.enable_output);
 
172
 
 
173
   TOGGLE_MENU_ITEM(audio_menu_emulation_fast,         (apu_options.emulation == APU_EMULATION_FAST));
 
174
   TOGGLE_MENU_ITEM(audio_menu_emulation_accurate,     (apu_options.emulation == APU_EMULATION_ACCURATE));
 
175
   TOGGLE_MENU_ITEM(audio_menu_emulation_high_quality, (apu_options.emulation == APU_EMULATION_HIGH_QUALITY));
 
176
 
 
177
   TOGGLE_MENU_ITEM(audio_menu_volume_auto_normalize, apu_options.normalize);
 
178
 
 
179
   TOGGLE_MENU_ITEM(audio_channels_menu_square_1, apu_options.enable_square_1);
 
180
   TOGGLE_MENU_ITEM(audio_channels_menu_square_2, apu_options.enable_square_2);
 
181
   TOGGLE_MENU_ITEM(audio_channels_menu_triangle, apu_options.enable_triangle);
 
182
   TOGGLE_MENU_ITEM(audio_channels_menu_noise,    apu_options.enable_noise);
 
183
   TOGGLE_MENU_ITEM(audio_channels_menu_dmc,      apu_options.enable_dmc);
 
184
   TOGGLE_MENU_ITEM(audio_channels_menu_extra_1,  apu_options.enable_extra_1);
 
185
   TOGGLE_MENU_ITEM(audio_channels_menu_extra_2,  apu_options.enable_extra_2);
 
186
   TOGGLE_MENU_ITEM(audio_channels_menu_extra_3,  apu_options.enable_extra_3);
 
187
 
 
188
   TOGGLE_MENU_ITEM(audio_output_menu_subsystem_allegro, (audio_options.subsystem == AUDIO_SUBSYSTEM_ALLEGRO));
 
189
   TOGGLE_MENU_ITEM(audio_output_menu_subsystem_openal,  (audio_options.subsystem == AUDIO_SUBSYSTEM_OPENAL));
 
190
 
 
191
   TOGGLE_MENU_ITEM(audio_output_menu_sampling_rate_automatic, (audio_options.sample_rate_hint == -1));
 
192
   TOGGLE_MENU_ITEM(audio_output_menu_sampling_rate_22050_hz,  (audio_options.sample_rate_hint == 22050));
 
193
   TOGGLE_MENU_ITEM(audio_output_menu_sampling_rate_44100_hz,  (audio_options.sample_rate_hint == 44100));
 
194
   TOGGLE_MENU_ITEM(audio_output_menu_sampling_rate_48000_hz,  (audio_options.sample_rate_hint == 48000));
 
195
 
 
196
   TOGGLE_MENU_ITEM(audio_output_menu_mixing_mono,            !apu_options.stereo);
 
197
   TOGGLE_MENU_ITEM(audio_output_menu_mixing_stereo,          (apu_options.stereo && !apu_options.swap_channels)); TOGGLE_MENU_ITEM(audio_output_menu_mixing_stereo_inverted, (apu_options.stereo && apu_options.swap_channels)); 
 
198
 
 
199
   TOGGLE_MENU_ITEM(audio_output_buffer_menu_automatic, (audio_options.buffer_length_ms_hint == -1));
 
200
   TOGGLE_MENU_ITEM(audio_output_buffer_menu_30ms,      (audio_options.buffer_length_ms_hint == 30));
 
201
   TOGGLE_MENU_ITEM(audio_output_buffer_menu_50ms,      (audio_options.buffer_length_ms_hint == 50));
 
202
   TOGGLE_MENU_ITEM(audio_output_buffer_menu_75ms,      (audio_options.buffer_length_ms_hint == 75));
 
203
   TOGGLE_MENU_ITEM(audio_output_buffer_menu_100ms,     (audio_options.buffer_length_ms_hint == 100));
 
204
   TOGGLE_MENU_ITEM(audio_output_buffer_menu_125ms,     (audio_options.buffer_length_ms_hint == 125));
 
205
   TOGGLE_MENU_ITEM(audio_output_buffer_menu_150ms,     (audio_options.buffer_length_ms_hint == 150));
 
206
   TOGGLE_MENU_ITEM(audio_output_buffer_menu_175ms,     (audio_options.buffer_length_ms_hint == 175));
 
207
   TOGGLE_MENU_ITEM(audio_output_buffer_menu_200ms,     (audio_options.buffer_length_ms_hint == 200));
 
208
 
 
209
#ifdef ALLEGRO_DOS
 
210
 
 
211
   TOGGLE_MENU_ITEM(video_driver_dos_menu_vga,           (gfx_driver->id == GFX_VGA));
 
212
   TOGGLE_MENU_ITEM(video_driver_dos_menu_vga_mode_x,    (gfx_driver->id == GFX_MODEX));
 
213
   TOGGLE_MENU_ITEM(video_driver_dos_menu_vesa,          (gfx_driver->id == GFX_VESA1));
 
214
   TOGGLE_MENU_ITEM(video_driver_dos_menu_vesa_2_banked, (gfx_driver->id == GFX_VESA2B));
 
215
   TOGGLE_MENU_ITEM(video_driver_dos_menu_vesa_2_linear, (gfx_driver->id == GFX_VESA2L));
 
216
   TOGGLE_MENU_ITEM(video_driver_dos_menu_vesa_3,        (gfx_driver->id == GFX_VESA3));
 
217
   TOGGLE_MENU_ITEM(video_driver_dos_menu_vesa_vbe_af,   (gfx_driver->id == GFX_VBEAF));
 
218
 
 
219
#endif   /* ALLEGRO_DOS */
 
220
 
 
221
#ifdef ALLEGRO_WINDOWS
 
222
 
 
223
   TOGGLE_MENU_ITEM(video_driver_windows_menu_directx,         (gfx_driver->id == GFX_DIRECTX));
 
224
   TOGGLE_MENU_ITEM(video_driver_windows_menu_directx_window,  (gfx_driver->id == GFX_DIRECTX_WIN));
 
225
   TOGGLE_MENU_ITEM(video_driver_windows_menu_directx_overlay, (gfx_driver->id == GFX_DIRECTX_OVL));
 
226
   TOGGLE_MENU_ITEM(video_driver_windows_menu_gdi,             (gfx_driver->id == GFX_GDI));
 
227
 
 
228
#endif   /* ALLEGRO_WINDOWS */
 
229
 
 
230
#ifdef ALLEGRO_LINUX
 
231
 
 
232
   TOGGLE_MENU_ITEM(video_driver_linux_menu_vga,         (gfx_driver->id == GFX_VGA));
 
233
   TOGGLE_MENU_ITEM(video_driver_linux_menu_vga_mode_x,  (gfx_driver->id == GFX_MODEX));
 
234
   TOGGLE_MENU_ITEM(video_driver_linux_menu_vesa_vbe_af, (gfx_driver->id == GFX_VBEAF));
 
235
#ifdef GFX_FBCON
 
236
   TOGGLE_MENU_ITEM(video_driver_linux_menu_framebuffer, (gfx_driver->id == GFX_FBCON));
 
237
#endif
 
238
#ifdef GFX_SVGALIB
 
239
   TOGGLE_MENU_ITEM(video_driver_linux_menu_svgalib,     (gfx_driver->id == GFX_SVGALIB));
 
240
#endif
 
241
 
 
242
#endif   /* ALLEGRO_LINUX */
 
243
 
 
244
#ifdef ALLEGRO_UNIX
 
245
 
 
246
   TOGGLE_MENU_ITEM(video_driver_unix_menu_x_windows,      (gfx_driver->id == GFX_XWINDOWS));
 
247
   TOGGLE_MENU_ITEM(video_driver_unix_menu_x_windows_full, (gfx_driver->id == GFX_XWINDOWS_FULLSCREEN));
 
248
   TOGGLE_MENU_ITEM(video_driver_unix_menu_x_dga,          (gfx_driver->id == GFX_XDGA));
 
249
   TOGGLE_MENU_ITEM(video_driver_unix_menu_x_dga_full,     (gfx_driver->id == GFX_XDGA_FULLSCREEN));
 
250
   TOGGLE_MENU_ITEM(video_driver_unix_menu_x_dga_2,        (gfx_driver->id == GFX_XDGA2));
 
251
 
 
252
#endif   /* ALLEGRO_UNIX */
 
253
 
 
254
#ifdef USE_ALLEGROGL
 
255
 
 
256
   TOGGLE_MENU_ITEM(video_driver_menu_opengl_full, (gfx_driver->id == GFX_OPENGL_FULLSCREEN));
 
257
   TOGGLE_MENU_ITEM(video_driver_menu_opengl_win,  (gfx_driver->id == GFX_OPENGL_WINDOWED));
 
258
 
 
259
#endif   /* USE_ALLEGROGL */
 
260
 
 
261
   TOGGLE_MENU_ITEM(video_resolution_proportionate_menu_256_224,   ((SCREEN_W == 256)  && (SCREEN_H == 224)));
 
262
   TOGGLE_MENU_ITEM(video_resolution_proportionate_menu_256_240,   ((SCREEN_W == 256)  && (SCREEN_H == 240)));
 
263
   TOGGLE_MENU_ITEM(video_resolution_proportionate_menu_512_448,   ((SCREEN_W == 512)  && (SCREEN_H == 448)));
 
264
   TOGGLE_MENU_ITEM(video_resolution_proportionate_menu_512_480,   ((SCREEN_W == 512)  && (SCREEN_H == 480)));
 
265
   TOGGLE_MENU_ITEM(video_resolution_proportionate_menu_768_672,   ((SCREEN_W == 768)  && (SCREEN_H == 672)));
 
266
   TOGGLE_MENU_ITEM(video_resolution_proportionate_menu_768_720,   ((SCREEN_W == 768)  && (SCREEN_H == 720)));
 
267
   TOGGLE_MENU_ITEM(video_resolution_proportionate_menu_1024_896,  ((SCREEN_W == 1024) && (SCREEN_H == 896)));
 
268
   TOGGLE_MENU_ITEM(video_resolution_proportionate_menu_1024_960,  ((SCREEN_W == 1024) && (SCREEN_H == 960)));
 
269
   TOGGLE_MENU_ITEM(video_resolution_proportionate_menu_1280_1120, ((SCREEN_W == 1280) && (SCREEN_H == 1120)));
 
270
   TOGGLE_MENU_ITEM(video_resolution_proportionate_menu_1280_1200, ((SCREEN_W == 1280) && (SCREEN_H == 1200)));
 
271
 
 
272
   TOGGLE_MENU_ITEM(video_resolution_menu_320_240,   ((SCREEN_W == 320)  && (SCREEN_H == 240)));
 
273
   TOGGLE_MENU_ITEM(video_resolution_menu_400_300,   ((SCREEN_W == 400)  && (SCREEN_H == 300)));
 
274
   TOGGLE_MENU_ITEM(video_resolution_menu_640_480,   ((SCREEN_W == 640)  && (SCREEN_H == 480)));
 
275
   TOGGLE_MENU_ITEM(video_resolution_menu_800_600,   ((SCREEN_W == 800)  && (SCREEN_H == 600)));
 
276
   TOGGLE_MENU_ITEM(video_resolution_menu_1024_768,  ((SCREEN_W == 1024) && (SCREEN_H == 768)));
 
277
   TOGGLE_MENU_ITEM(video_resolution_menu_1152_864,  ((SCREEN_W == 1152) && (SCREEN_H == 864)));
 
278
   TOGGLE_MENU_ITEM(video_resolution_menu_1280_960,  ((SCREEN_W == 1280) && (SCREEN_H == 960)));
 
279
   TOGGLE_MENU_ITEM(video_resolution_menu_1280_1024, ((SCREEN_W == 1280) && (SCREEN_H == 1024)));
 
280
   TOGGLE_MENU_ITEM(video_resolution_menu_1600_1200, ((SCREEN_W == 1600) && (SCREEN_H == 1200)));
 
281
 
 
282
   TOGGLE_MENU_ITEM(video_color_depth_menu_paletted_8_bit,    (video_get_color_depth () == 8));
 
283
   TOGGLE_MENU_ITEM(video_color_depth_menu_true_color_15_bit, (video_get_color_depth () == 15));
 
284
   TOGGLE_MENU_ITEM(video_color_depth_menu_true_color_16_bit, (video_get_color_depth () == 16));
 
285
   TOGGLE_MENU_ITEM(video_color_depth_menu_true_color_24_bit, (video_get_color_depth () == 24));
 
286
   TOGGLE_MENU_ITEM(video_color_depth_menu_true_color_32_bit, (video_get_color_depth () == 32));
 
287
 
 
288
   TOGGLE_MENU_ITEM(video_buffer_menu_match_resolution, ((video_buffer_width == -1)  && (video_buffer_height == -1)));
 
289
   TOGGLE_MENU_ITEM(video_buffer_menu_256_240,          ((video_buffer_width == 256) && (video_buffer_height == 240)));
 
290
   TOGGLE_MENU_ITEM(video_buffer_menu_320_240,          ((video_buffer_width == 320) && (video_buffer_height == 240)));
 
291
   TOGGLE_MENU_ITEM(video_buffer_menu_512_480,          ((video_buffer_width == 512) && (video_buffer_height == 480)));
 
292
   TOGGLE_MENU_ITEM(video_buffer_menu_640_480,          ((video_buffer_width == 640) && (video_buffer_height == 480)));
 
293
   TOGGLE_MENU_ITEM(video_buffer_menu_256_256,          ((video_buffer_width == 256) && (video_buffer_height == 256)));
 
294
   TOGGLE_MENU_ITEM(video_buffer_menu_512_512,          ((video_buffer_width == 512) && (video_buffer_height == 512)));
 
295
 
 
296
   TOGGLE_MENU_ITEM(video_blitter_menu_automatic,          (video_get_blitter () == VIDEO_BLITTER_AUTOMATIC));
 
297
   TOGGLE_MENU_ITEM(video_blitter_menu_normal,             (video_get_blitter () == VIDEO_BLITTER_NORMAL));
 
298
   TOGGLE_MENU_ITEM(video_blitter_menu_des,                (video_get_blitter () == VIDEO_BLITTER_DES));
 
299
   TOGGLE_MENU_ITEM(video_blitter_menu_interpolated_2x,    (video_get_blitter () == VIDEO_BLITTER_INTERPOLATED_2X));
 
300
   TOGGLE_MENU_ITEM(video_blitter_menu_interpolated_2x_hq, (video_get_blitter () == VIDEO_BLITTER_INTERPOLATED_2X_HQ));
 
301
   TOGGLE_MENU_ITEM(video_blitter_menu_2xscl,              (video_get_blitter () == VIDEO_BLITTER_2XSCL));
 
302
   TOGGLE_MENU_ITEM(video_blitter_menu_desii,              (video_get_blitter () == VIDEO_BLITTER_DESII));
 
303
   TOGGLE_MENU_ITEM(video_blitter_menu_super_2xscl,        (video_get_blitter () == VIDEO_BLITTER_SUPER_2XSCL));
 
304
   TOGGLE_MENU_ITEM(video_blitter_menu_ultra_2xscl,        (video_get_blitter () == VIDEO_BLITTER_ULTRA_2XSCL));
 
305
   TOGGLE_MENU_ITEM(video_blitter_menu_hq2x,               (video_get_blitter () == VIDEO_BLITTER_HQ2X));
 
306
   TOGGLE_MENU_ITEM(video_blitter_menu_ntsc,               (video_get_blitter () == VIDEO_BLITTER_NTSC));
 
307
   TOGGLE_MENU_ITEM(video_blitter_menu_interpolated_3x,    (video_get_blitter () == VIDEO_BLITTER_INTERPOLATED_3X));
 
308
   TOGGLE_MENU_ITEM(video_blitter_menu_hq3x,               (video_get_blitter () == VIDEO_BLITTER_HQ3X));
 
309
   TOGGLE_MENU_ITEM(video_blitter_menu_hq4x,               (video_get_blitter () == VIDEO_BLITTER_HQ4X));
 
310
   TOGGLE_MENU_ITEM(video_blitter_menu_stretched,          (video_get_blitter () == VIDEO_BLITTER_STRETCHED));
 
311
 
 
312
   TOGGLE_MENU_ITEM(video_filters_menu_scanlines_25_percent,  (video_get_filter_list () & VIDEO_FILTER_SCANLINES_LOW));
 
313
   TOGGLE_MENU_ITEM(video_filters_menu_scanlines_50_percent,  (video_get_filter_list () & VIDEO_FILTER_SCANLINES_MEDIUM));
 
314
   TOGGLE_MENU_ITEM(video_filters_menu_scanlines_100_percent, (video_get_filter_list () & VIDEO_FILTER_SCANLINES_HIGH));
 
315
 
 
316
   TOGGLE_MENU_ITEM(video_menu_fullscreen,  video_force_fullscreen);
 
317
   TOGGLE_MENU_ITEM(video_menu_page_buffer, video_enable_page_buffer);
 
318
   TOGGLE_MENU_ITEM(video_menu_vsync,       video_enable_vsync);
 
319
 
 
320
   TOGGLE_MENU_ITEM(video_palette_menu_ntsc_color,     (video_get_palette_id () == DATA_INDEX(DEFAULT_PALETTE)));
 
321
   TOGGLE_MENU_ITEM(video_palette_menu_ntsc_grayscale, (video_get_palette_id () == DATA_INDEX(GRAYSCALE_PALETTE)));
 
322
   TOGGLE_MENU_ITEM(video_palette_menu_gnuboy,         (video_get_palette_id () == DATA_INDEX(GNUBOY_PALETTE)));
 
323
   TOGGLE_MENU_ITEM(video_palette_menu_nester,         (video_get_palette_id () == DATA_INDEX(NESTER_PALETTE)));
 
324
   TOGGLE_MENU_ITEM(video_palette_menu_nesticle,       (video_get_palette_id () == DATA_INDEX(NESTICLE_PALETTE)));
 
325
   TOGGLE_MENU_ITEM(video_palette_menu_modern_ntsc,    (video_get_palette_id () == DATA_INDEX(MODERN_NTSC_PALETTE)));
 
326
   TOGGLE_MENU_ITEM(video_palette_menu_modern_pal,     (video_get_palette_id () == DATA_INDEX(MODERN_PAL_PALETTE)));
 
327
   TOGGLE_MENU_ITEM(video_palette_menu_ega_mode_1,     (video_get_palette_id () == DATA_INDEX(EGA_PALETTE_1)));
 
328
   TOGGLE_MENU_ITEM(video_palette_menu_ega_mode_2,     (video_get_palette_id () == DATA_INDEX(EGA_PALETTE_2)));
 
329
   TOGGLE_MENU_ITEM(video_palette_menu_custom,         (video_get_palette_id () == -1));
 
330
 
 
331
   TOGGLE_MENU_ITEM(video_layers_menu_sprites_a,                 ppu_enable_sprite_layer_a);
 
332
   TOGGLE_MENU_ITEM(video_layers_menu_sprites_b,                 ppu_enable_sprite_layer_b);
 
333
   TOGGLE_MENU_ITEM(video_layers_menu_background,                ppu_enable_background_layer);
 
334
   TOGGLE_MENU_ITEM(video_layers_menu_hide_horizontal_scrolling, (video_edge_clipping & VIDEO_EDGE_CLIPPING_HORIZONTAL));
 
335
   TOGGLE_MENU_ITEM(video_layers_menu_hide_vertical_scrolling,   (video_edge_clipping & VIDEO_EDGE_CLIPPING_VERTICAL));
 
336
 
 
337
   TOGGLE_MENU_ITEM(input_menu_enable_zapper, input_enable_zapper);
 
338
 
 
339
   TOGGLE_MENU_ITEM(options_cpu_usage_menu_passive,    (cpu_usage == CPU_USAGE_PASSIVE));
 
340
   TOGGLE_MENU_ITEM(options_cpu_usage_menu_normal,     (cpu_usage == CPU_USAGE_NORMAL));
 
341
   TOGGLE_MENU_ITEM(options_cpu_usage_menu_aggressive, (cpu_usage == CPU_USAGE_AGGRESSIVE));
 
342
 
 
343
   TOGGLE_MENU_ITEM(options_gui_theme_menu_classic,         (last_theme == &classic_theme));
 
344
   TOGGLE_MENU_ITEM(options_gui_theme_menu_stainless_steel, (last_theme == &stainless_steel_theme));
 
345
   TOGGLE_MENU_ITEM(options_gui_theme_menu_zero_4,          (last_theme == &zero_4_theme));
 
346
   TOGGLE_MENU_ITEM(options_gui_theme_menu_panta,           (last_theme == &panta_theme));
 
347
   TOGGLE_MENU_ITEM(options_gui_theme_menu_xodiac,          (last_theme == &xodiac_theme));
 
348
   TOGGLE_MENU_ITEM(options_gui_theme_menu_monochrome,      (last_theme == &monochrome_theme));
 
349
   TOGGLE_MENU_ITEM(options_gui_theme_menu_essence,         (last_theme == &essence_theme));
 
350
   TOGGLE_MENU_ITEM(options_gui_theme_menu_voodoo,          (last_theme == &voodoo_theme));
 
351
   TOGGLE_MENU_ITEM(options_gui_theme_menu_hugs_and_kisses, (last_theme == &hugs_and_kisses_theme));
 
352
 
 
353
   /* TODO: Find a better way to do this. */
 
354
   uszprintf (audio_menu_volume_text, sizeof (audio_menu_volume_text),
 
355
      "Current volume: %d%%", (int)ROUND((apu_options.volume * 100.0)));
 
356
   audio_menu[AUDIO_MENU_VOLUME_TEXT].text = audio_menu_volume_text;
 
357
}
 
358
 
 
359
void gui_load_config (void)
 
360
{
 
361
   gui_theme_id = get_config_int ("gui", "theme",       GUI_THEME_PANTA);
 
362
   lock_recent  = get_config_int ("gui", "lock_recent", FALSE);
 
363
}
 
364
 
 
365
void gui_save_config (void)
 
366
{
 
367
   STRING save_path;
 
368
   STRING host;
 
369
 
 
370
   STRING_CLEAR(save_path);
 
371
   strncpy (save_path, get_config_string ("gui", "save_path", "./"),
 
372
      sizeof (save_path) - 1);
 
373
   set_config_string ("gui", "save_path", save_path);
 
374
 
 
375
   STRING_CLEAR(host);
 
376
   strncpy (host, get_config_string ("netplay", "host", ""), (sizeof(host) - 1));
 
377
   set_config_string ("netplay", "host", host);
 
378
 
 
379
   set_config_int ("gui", "theme",       gui_theme_id);
 
380
   set_config_int ("gui", "lock_recent", lock_recent);
 
381
}
 
382
 
 
383
int gui_init (void)
 
384
{
 
385
   int index;
 
386
 
 
387
   /* Set up replacement objects. */
 
388
   gui_menu_draw_menu = sl_draw_menu;
 
389
   gui_menu_draw_menu_item = sl_draw_menu_item;
 
390
 
 
391
   /* Set up menus & dialogs. */
 
392
   load_menus ();
 
393
   load_dialogs ();
 
394
 
 
395
#ifdef ALLEGRO_DOS
 
396
 
 
397
   CHECK_MENU_ITEM(video_menu_fullscreen);
 
398
   DISABLE_MENU_ITEM(video_menu_fullscreen);
 
399
   DISABLE_MENU(options_cpu_usage_menu);
 
400
 
 
401
#endif   /* ALLEGRO_DOS */
 
402
 
 
403
#ifdef ALLEGRO_LINUX
 
404
 
 
405
#ifndef GFX_FBCON
 
406
   DISABLE_MENU_ITEM(video_driver_linux_menu_framebuffer);
 
407
#endif
 
408
#ifndef GFX_SVGALIB
 
409
   DISABLE_MENU_ITEM(video_driver_linux_menu_svgalib);
 
410
#endif
 
411
 
 
412
#endif   /* !ALLEGRO_LINUX */
 
413
 
 
414
   /* Select default palette. */
 
415
   CHECK_MENU_ITEM(video_palette_menu_modern_ntsc);
 
416
 
 
417
   /* Load up recent items. */
 
418
 
 
419
   main_open_recent_menu_clear ();
 
420
 
 
421
   for (index = 0; index < OPEN_RECENT_SLOTS; index++)
 
422
   {
 
423
      USTRING key;
 
424
      const char *path;
 
425
      UCHAR *filename = open_recent_filenames[index];
 
426
      UCHAR *text     = open_recent_menu_texts[index];
 
427
      MENU  *menu     = &main_open_recent_menu[index];
 
428
 
 
429
      USTRING_CLEAR(key);
 
430
      uszprintf (key, sizeof (key), "recent%d", index);
 
431
 
 
432
      path = get_config_string ("gui", key, NULL);
 
433
      if (!path)
 
434
         continue;
 
435
 
 
436
      uszprintf (filename, USTRING_SIZE, "%s", path);
 
437
      uszprintf (text,     USTRING_SIZE, "&%d: %s", index, get_filename
 
438
         (path));
 
439
 
 
440
      /* Update menu. */
 
441
      menu->text = text;
 
442
 
 
443
      /* Enable menu. */
 
444
      menu->flags &= ~D_DISABLED;
 
445
   }
 
446
 
 
447
   /* Cheap hack to fix palette. */
 
448
   gui_is_active = TRUE;
 
449
   set_theme ();
 
450
   gui_is_active = FALSE;
 
451
 
 
452
   return (0);
 
453
}
 
454
 
 
455
void gui_exit (void)
 
456
{
 
457
   int index;
 
458
 
 
459
   /* Save recent items. */
 
460
 
 
461
   for (index = 0; index < OPEN_RECENT_SLOTS; index++)
 
462
   {
 
463
      USTRING key;
 
464
      const UCHAR *filename = open_recent_filenames[index];
 
465
 
 
466
      if (!filename)
 
467
         continue;
 
468
 
 
469
      USTRING_CLEAR(key);
 
470
      uszprintf (key, sizeof (key), "recent%d", index);
 
471
 
 
472
      set_config_string ("gui", key, filename);
 
473
   }
 
474
 
 
475
   unload_menus ();
 
476
   unload_dialogs ();
 
477
}
 
478
 
 
479
int show_gui (BOOL first_run)
 
480
{
 
481
   want_exit = FALSE;
 
482
 
 
483
   do
 
484
   {
 
485
      int result;
 
486
 
 
487
      /* Clear restart flag. */
 
488
      gui_needs_restart = FALSE;
 
489
 
 
490
      /* Open GUI. */
 
491
   
 
492
      result = gui_open ();
 
493
   
 
494
      if (result != 0)
 
495
      {
 
496
         WARN("Failed to open GUI");
 
497
         return ((8 + result));
 
498
      }
 
499
   
 
500
      if (first_run)
 
501
      {
 
502
         /* Show version. */
 
503
         help_menu_about ();
 
504
 
 
505
         /* Clear flag. */
 
506
         first_run = FALSE;
 
507
      }
 
508
 
 
509
      /* Update menu states. */
 
510
      update_menus ();
 
511
 
 
512
      /* Run main dialog. */
 
513
      run_dialog (main_dialog, -1);
 
514
 
 
515
      /* Close GUI. */
 
516
      gui_close (want_exit);
 
517
 
 
518
   } while (gui_needs_restart);
 
519
 
 
520
   return (want_exit);
 
521
}
 
522
 
 
523
int gui_alert (const UCHAR *title, const UCHAR *s1, const UCHAR *s2, const
 
524
   UCHAR *s3, const UCHAR *b1, const UCHAR *b2, int c1, int c2)
 
525
{
 
526
   /* Alert dialog with 1 or 2 buttons.  The title, first string, and first
 
527
      button are required.  The rest are optional and may be NULL.
 
528
 
 
529
      This function can even be called when the GUI isn't open.  It'll
 
530
      automatically open the GUI long enough to display the dialog. */
 
531
 
 
532
   int result;
 
533
   BOOL gui_opened = FALSE;
 
534
   DIALOG *dialog;
 
535
   DIALOG *objframe;
 
536
   DIALOG *objxbutton;
 
537
   DIALOG *objstr1, *objstr2, *objstr3;
 
538
   DIALOG *objbtn1, *objbtn2;
 
539
   int s1len, s2len, s3len;
 
540
   int collapse = 0;
 
541
 
 
542
   RT_ASSERT(title);
 
543
   RT_ASSERT(s1);
 
544
   RT_ASSERT(b1);
 
545
 
 
546
   /* Handle any NULL entries. */
 
547
 
 
548
   if (!s2) s2 = empty_string;
 
549
   if (!s3) s3 = empty_string;
 
550
 
 
551
   if (ustrlen (s2) == 0)
 
552
      collapse += (text_height (font) + 3);
 
553
   if (ustrlen (s3) == 0)
 
554
      collapse += (text_height (font) + 3);
 
555
 
 
556
   if (!gui_is_active)
 
557
   {
 
558
      /* Open GUI. */
 
559
   
 
560
      result = gui_open ();
 
561
   
 
562
      if (result != 0)
 
563
      {
 
564
         WARN("Failed to open GUI");
 
565
         return ((8 + result));
 
566
      }
 
567
 
 
568
      gui_opened = TRUE;
 
569
   }
 
570
 
 
571
   /* Create dialog. */
 
572
   dialog = load_dialog (alert_dialog_base);
 
573
   if (!dialog)
 
574
   {
 
575
      WARN("Failed to create dialog structure");
 
576
      return (-1);
 
577
   }
 
578
 
 
579
   /* Get all objects. */
 
580
 
 
581
   objframe   = &dialog[ALERT_DIALOG_FRAME];
 
582
   objxbutton = &dialog[ALERT_DIALOG_CLOSE_BUTTON];
 
583
   objstr1    = &dialog[ALERT_DIALOG_STRING_1];
 
584
   objstr2    = &dialog[ALERT_DIALOG_STRING_2];
 
585
   objstr3    = &dialog[ALERT_DIALOG_STRING_3];
 
586
   objbtn1    = &dialog[ALERT_DIALOG_BUTTON_1];
 
587
   objbtn2    = &dialog[ALERT_DIALOG_BUTTON_2];
 
588
 
 
589
   /* Calculate string lengths (in pixels). */
 
590
 
 
591
   s1len = text_length (font, s1);
 
592
   s2len = text_length (font, s2);
 
593
   s3len = text_length (font, s3);
 
594
 
 
595
   /* Set up frame. */
 
596
 
 
597
   objframe->w   = (9 + MAX3(s1len, s2len, s3len) + 9);
 
598
   objframe->dp2 = (char *)title;
 
599
 
 
600
   objxbutton->x = ((objframe->w - objxbutton->w) - 4);
 
601
 
 
602
   /* Set up strings. */
 
603
 
 
604
   objstr1->x   = ((objframe->w / 2) - (s1len / 2));
 
605
   objstr1->dp2 = (char *)s1;
 
606
 
 
607
   objstr2->x   = ((objframe->w / 2) - (s2len / 2));
 
608
   objstr2->dp2 = (char *)s2;
 
609
 
 
610
   objstr3->x   = ((objframe->w / 2) - (s3len / 2));
 
611
   objstr3->dp2 = (char *)s3;
 
612
 
 
613
   /* Set up buttons. */
 
614
 
 
615
   objbtn1->x   = ((objframe->w / 2) - (objbtn1->w / 2));
 
616
   objbtn1->dp  = (char *)b1;
 
617
   objbtn1->key = c1;
 
618
 
 
619
   objbtn1->y -= collapse;
 
620
 
 
621
   if (b2)
 
622
   {
 
623
      objbtn1->x -= ((objbtn2->w / 2) + 4);
 
624
 
 
625
      objbtn2->x   = ((objbtn1->x + objbtn1->w) + 8);
 
626
      objbtn2->dp  = (char *)b2;
 
627
      objbtn2->key = c2;
 
628
 
 
629
      objbtn2->y -= collapse;
 
630
   }
 
631
   else
 
632
   {
 
633
      /* Hide the unused button. */
 
634
 
 
635
      objbtn2->flags |= D_HIDDEN;
 
636
      objbtn2->flags |= D_DISABLED;
 
637
   }
 
638
 
 
639
   /* Collapse frame. */
 
640
   objframe->h -= collapse;
 
641
 
 
642
   /* Show dialog. */
 
643
   result = show_dialog (dialog, ALERT_DIALOG_BUTTON_1);
 
644
 
 
645
   /* Destroy dialog. */
 
646
   unload_dialog (dialog);
 
647
 
 
648
   if (gui_opened)
 
649
   {
 
650
      /* Close GUI. */
 
651
      gui_close (FALSE);
 
652
   }
 
653
 
 
654
   if (result == ALERT_DIALOG_BUTTON_1)
 
655
      return (1); /* OK. */
 
656
   else
 
657
      return (2); /* Cancel. */
 
658
}
 
659
 
 
660
void gui_message (int color, const UCHAR *message, ...)
 
661
{
 
662
   va_list format;
 
663
 
 
664
   RT_ASSERT(message);
 
665
 
 
666
   va_start (format, message);
 
667
   uvszprintf (message_buffer, USTRING_SIZE, message, format);
 
668
   va_end (format);
 
669
 
 
670
   if (gui_is_active)
 
671
   {
 
672
      if (color == -1)
 
673
         color = GUI_TEXT_COLOR;
 
674
 
 
675
      draw_message (color);
 
676
   }
 
677
 
 
678
   video_message (message_buffer);
 
679
   video_message_duration = 3000;
 
680
 
 
681
   log_printf ("GUI: %s", message_buffer);
 
682
}
 
683
 
 
684
void gui_heartbeat (void)
 
685
{
 
686
   /* Called in varous places to process NetPlay (if active), refresh the
 
687
      screen, and rest() to minimize CPU usage in the GUI. */
 
688
 
 
689
   if (netplay_mode)
 
690
      netplay_process ();
 
691
 
 
692
   refresh ();
 
693
 
 
694
   if (cpu_usage == CPU_USAGE_PASSIVE)
 
695
      rest (1);
 
696
   else if (cpu_usage == CPU_USAGE_NORMAL)
 
697
      rest (0);
 
698
}
 
699
 
 
700
void gui_handle_keypress (int c, int scancode)
 
701
{
 
702
   switch (scancode)
 
703
   {
 
704
      case KEY_F1:
 
705
      {
 
706
         /* Save snapshot. */
 
707
         main_menu_save_snapshot ();
 
708
 
 
709
         break;
 
710
      }
 
711
 
 
712
      case KEY_F2:
 
713
      {
 
714
         /* Toggle status display. */
 
715
         machine_menu_show_status ();
 
716
 
 
717
         break;
 
718
      }
 
719
 
 
720
      case KEY_F3:
 
721
      {
 
722
         /* Quick save state. */
 
723
         machine_save_state_menu_quick_save ();
 
724
 
 
725
         /* See if the save succeeded. */
 
726
         if (check_save_state (-1))
 
727
            message_local ("QuickSave: OK");
 
728
         else
 
729
            message_local ("QuickSave: Failed");
 
730
            
 
731
         break;
 
732
      }
 
733
 
 
734
      case KEY_F4:
 
735
      {
 
736
         /* Quick load state. */
 
737
 
 
738
         if (!(input_mode & INPUT_MODE_REPLAY))
 
739
            machine_save_state_menu_quick_load ();
 
740
 
 
741
         break;
 
742
      }
 
743
 
 
744
      case KEY_F5:
 
745
      {
 
746
         /* Save state. */
 
747
         machine_save_state_menu_save ();
 
748
 
 
749
         break;
 
750
      }
 
751
 
 
752
      case KEY_F6:
 
753
      {
 
754
         /* Load state. */
 
755
 
 
756
         if (!(input_mode & INPUT_MODE_REPLAY))
 
757
            machine_save_state_menu_restore ();
 
758
 
 
759
         break;
 
760
      }
 
761
 
 
762
      case KEY_F7:
 
763
      {
 
764
         /* Toggle sprites. */
 
765
 
 
766
         video_layers_menu_sprites_a ();
 
767
         video_layers_menu_sprites_b ();
 
768
 
 
769
         break;
 
770
      }
 
771
 
 
772
      case KEY_F8:
 
773
      {
 
774
         /* Toggle background. */
 
775
         video_layers_menu_background ();
 
776
 
 
777
         break;
 
778
      }
 
779
 
 
780
      case KEY_F9:
 
781
      {
 
782
         /* Toggle half speed mode. */
 
783
 
 
784
         timing_half_speed = !timing_half_speed;
 
785
         timing_update_speed ();
 
786
 
 
787
         break;
 
788
      }
 
789
 
 
790
      case KEY_F12:
 
791
      {
 
792
         /* Start/stop replay recording. */
 
793
 
 
794
         if (!(input_mode & INPUT_MODE_REPLAY_PLAY))
 
795
         {
 
796
            if (input_mode & INPUT_MODE_REPLAY_RECORD)
 
797
               main_replay_record_menu_stop ();
 
798
            else
 
799
               main_replay_record_menu_start ();
 
800
 
 
801
            break;
 
802
         }
 
803
      }
 
804
 
 
805
      case KEY_0:
 
806
      case KEY_1:
 
807
      case KEY_2:
 
808
      case KEY_3:
 
809
      case KEY_4:
 
810
      case KEY_5:
 
811
      case KEY_6:
 
812
      case KEY_7:
 
813
      case KEY_8:
 
814
      case KEY_9:
 
815
      {
 
816
         /* Select state slot. */
 
817
 
 
818
         if (!(input_mode & INPUT_MODE_CHAT))
 
819
         {
 
820
            save_state_index = (scancode - KEY_0);
 
821
    
 
822
            message_local ("Machine state slot set to %d.",
 
823
               save_state_index);
 
824
         }
 
825
 
 
826
         break;
 
827
      }
 
828
 
 
829
      case KEY_MINUS:
 
830
      case KEY_MINUS_PAD:
 
831
      {
 
832
         audio_menu_volume_decrease ();
 
833
         break;
 
834
      }
 
835
 
 
836
      case KEY_EQUALS:
 
837
      case KEY_PLUS_PAD:
 
838
      {
 
839
         audio_menu_volume_increase ();
 
840
         break;
 
841
      }
 
842
 
 
843
      default:
 
844
         break;
 
845
   }
 
846
}
 
847
 
 
848
void gui_stop_replay (void)
 
849
{
 
850
   main_replay_play_menu_stop ();
 
851
}
 
852
 
 
853
void gui_set_theme (const GUI_THEME *theme)
 
854
{
 
855
   int index;
 
856
 
 
857
   RT_ASSERT(theme);
 
858
 
 
859
   last_theme = theme;
 
860
 
 
861
   memcpy (&gui_theme, theme, sizeof (GUI_THEME));
 
862
 
 
863
   video_set_palette (NULL);
 
864
 
 
865
   for (index = 0; index < GUI_TOTAL_COLORS; index++)
 
866
      pack_color (&gui_theme[index]);
 
867
 
 
868
   gui_bg_color = GUI_FILL_COLOR;
 
869
   gui_fg_color = GUI_TEXT_COLOR;
 
870
   gui_mg_color = GUI_DISABLED_COLOR;
 
871
}
 
872
 
 
873
/* --- Utility functions. --- */
 
874
 
 
875
static INLINE void set_autosave (int interval)
 
876
{
 
877
   /* This function simply sets the save state autosave interval to
 
878
      'interval' seconds (in game speed, not real world speed :b). */
 
879
 
 
880
   input_autosave_interval = interval;
 
881
   update_menus ();
 
882
 
 
883
   if (interval <= 0)
 
884
      message_local ("Autosave disabled.");
 
885
   else
 
886
      message_local ("Autosave interval set to %d seconds.", interval);
 
887
}
 
888
 
 
889
static INLINE void close_file (void);
 
890
static int main_replay_menu_select (void);
 
891
 
 
892
static INLINE int load_file (const UCHAR *filename)
 
893
{
 
894
   /* This function loads the ROM specified by filename.  The file is NOT
 
895
      automatically added to the recent items list.  That must be done
 
896
      manually (currently by main_menu_open()).
 
897
 
 
898
      NSFs are also supported, and are determined from their extension.
 
899
      GZipped/Zipped NSFs are not supported however.
 
900
 
 
901
      The return value of this function should be passed back to the calling
 
902
      dialog (e.g, D_CLOSE to close it and start the emulation, etc.). */
 
903
 
 
904
   ROM rom;
 
905
 
 
906
   status_message ("Loading, please wait...");
 
907
 
 
908
   if (ustricmp (get_extension (filename), "NSF") == 0)
 
909
   {
 
910
      /* Attempt to intercept NSF file. */
 
911
 
 
912
      if (!nsf_open (filename))
 
913
      {
 
914
         gui_message (GUI_ERROR_COLOR, "Failed to load NSF file!");
 
915
 
 
916
         return (D_O_K);
 
917
      }
 
918
      else
 
919
      {
 
920
         USTRING scratch;
 
921
 
 
922
         /* Clear status bar. */
 
923
         status_message ("");
 
924
 
 
925
         if (rom_is_loaded)
 
926
         {
 
927
            /* Close currently open ROM and save data. */
 
928
            close_file ();
 
929
         }
 
930
 
 
931
         /* Big Batch O' Botches. */
 
932
         rom_is_loaded = TRUE;
 
933
         memset(&global_rom, 0, sizeof(global_rom));
 
934
         /* Mapper #0 = NONE. */
 
935
         mmc_force (&nsf_mapper);
 
936
 
 
937
         /* Initialize machine. */
 
938
         machine_init ();
 
939
 
 
940
         /* Update window title. */
 
941
         uszprintf (scratch, sizeof (scratch), "FakeNES - %s", get_filename (filename));
 
942
         set_window_title (scratch);
 
943
 
 
944
         /* Unfreeze audio. */
 
945
         audio_resume ();
 
946
 
 
947
         nsf_main ();
 
948
 
 
949
         /* Re-freeze audio. */
 
950
         audio_suspend ();
 
951
 
 
952
         /* Close NSF file. */
 
953
         nsf_close ();
 
954
 
 
955
         /* Close machine. */
 
956
         machine_exit ();
 
957
 
 
958
         /* Botch. */
 
959
         rom_is_loaded = FALSE;
 
960
 
 
961
         return (D_REDRAW);
 
962
      }
 
963
   }
 
964
 
 
965
   if (load_rom (filename, &rom) != 0)
 
966
   {
 
967
      gui_message (GUI_ERROR_COLOR, "Failed to load ROM!");
 
968
 
 
969
      return (D_O_K);
 
970
   }
 
971
   else
 
972
   {
 
973
      USTRING scratch;
 
974
 
 
975
      /* Clear status bar. */
 
976
      status_message ("");
 
977
 
 
978
      if (rom_is_loaded)
 
979
      {
 
980
         /* Close currently open ROM and save data. */
 
981
         close_file ();
 
982
      }
 
983
 
 
984
      memcpy (&global_rom, &rom, sizeof (ROM));
 
985
 
 
986
      /* Update save state titles. */
 
987
      machine_save_state_menu_select ();
 
988
      /* Update replay titles. */
 
989
      main_replay_menu_select ();
 
990
 
 
991
      rom_is_loaded = TRUE;
 
992
 
 
993
      /* Initialize machine. */
 
994
      machine_init ();
 
995
 
 
996
      /* Clear the game clock. */
 
997
      options_menu_reset_clock ();
 
998
 
 
999
      ENABLE_MENU_ITEM(main_menu_resume);
 
1000
      ENABLE_MENU_ITEM(main_menu_close);
 
1001
      ENABLE_SUBMENU(main_replay_menu);
 
1002
      ENABLE_MENU_ITEM(main_menu_cheat_manager);
 
1003
      ENABLE_MENU_ITEM(main_menu_save_snapshot);
 
1004
      ENABLE_MENU_ITEM(main_menu_advance_frame);
 
1005
      ENABLE_MENU_ITEM(machine_menu_reset);
 
1006
      ENABLE_MENU_ITEM(machine_menu_power_cycle);
 
1007
      ENABLE_SUBMENU(machine_save_state_menu);
 
1008
      ENABLE_SUBMENU(audio_record_menu);
 
1009
      ENABLE_MENU_ITEM(video_layers_menu_flip_mirroring);
 
1010
      ENABLE_MENU_ITEM(options_menu_reset_clock);
 
1011
 
 
1012
      /* Update window title. */
 
1013
      uszprintf (scratch, sizeof (scratch), "FakeNES - %s", get_filename
 
1014
         (global_rom.filename));
 
1015
      set_window_title (scratch);
 
1016
 
 
1017
      return (D_CLOSE);
 
1018
   }
 
1019
}
 
1020
 
 
1021
static INLINE void close_file (void)
 
1022
{
 
1023
   /* Unloads the current ROM and returns the emulator to it's default
 
1024
      state. */
 
1025
 
 
1026
   /* Save SRAM. */
 
1027
   save_sram ();      
 
1028
 
 
1029
   /* Save patches. */
 
1030
   save_patches ();
 
1031
 
 
1032
   /* Close machine. */
 
1033
   machine_exit ();
 
1034
 
 
1035
   /* Unload ROM. */
 
1036
   free_rom (&global_rom);
 
1037
   rom_is_loaded = FALSE;
 
1038
 
 
1039
   update_menus ();
 
1040
}
 
1041
 
 
1042
static int open_lobby (void)
 
1043
{
 
1044
   /* This function handles the entire GUI end of the NetPlay lobby.  It
 
1045
      does not return until the NetPlay session has been terminated.
 
1046
 
 
1047
      Returns one of the following:
 
1048
         D_O_K   - The NetPlay session has been closed, by pressing either
 
1049
                   the [ x] close button or the Cancel button.
 
1050
         D_CLOSE - The Netplay session is still open, all neccessary data
 
1051
                   has been distributed and subsequently loaded, and control
 
1052
                   should be transfered to the main loop. */
 
1053
 
 
1054
   BITMAP *bmp;                       
 
1055
   DIALOG *dialog;
 
1056
   int index = 0;
 
1057
   DIALOG *obj_frame;
 
1058
   DIALOG *obj_chat;
 
1059
   DIALOG *obj_list;
 
1060
   DIALOG *obj_message;
 
1061
   DIALOG *obj_load;
 
1062
   DIALOG *obj_ok;
 
1063
   USTRING chat;
 
1064
   USTRING list;
 
1065
   USTRING message;
 
1066
   DIALOG_PLAYER *player;
 
1067
   int object_id;
 
1068
 
 
1069
   bmp = gui_get_screen ();
 
1070
 
 
1071
   /* Clear screen. */
 
1072
   clear_bitmap (bmp);
 
1073
 
 
1074
   /* Get dialog. */
 
1075
   dialog = lobby_dialog;
 
1076
 
 
1077
   /* Center dialog. */
 
1078
   centre_dialog (dialog);
 
1079
 
 
1080
   while (dialog[index].d1 != SL_FRAME_END)
 
1081
   {
 
1082
      /* Update colors. */
 
1083
 
 
1084
      DIALOG *object = &dialog[index];
 
1085
 
 
1086
      object->fg = GUI_TEXT_COLOR;
 
1087
      object->bg = gui_bg_color;
 
1088
 
 
1089
      index++;
 
1090
   }
 
1091
 
 
1092
   /* Get dialog objects. */
 
1093
   obj_frame   = &dialog[LOBBY_DIALOG_FRAME];
 
1094
   obj_chat    = &dialog[LOBBY_DIALOG_CHAT];
 
1095
   obj_list    = &dialog[LOBBY_DIALOG_LIST];
 
1096
   obj_message = &dialog[LOBBY_DIALOG_MESSAGE];
 
1097
   obj_load    = &dialog[LOBBY_DIALOG_LOAD_BUTTON];
 
1098
   obj_ok      = &dialog[LOBBY_DIALOG_OK_BUTTON];
 
1099
 
 
1100
   /* Set up dialog objects. */
 
1101
 
 
1102
   obj_frame->dp3 = DATA_TO_FONT(LARGE_FONT);
 
1103
 
 
1104
   obj_chat->bg = makecol (0, 0, 0);
 
1105
   obj_chat->fg = makecol (240, 240, 240);
 
1106
   obj_chat->d1 = ((sizeof (chat) / MAX_UCHAR_LENGTH) - 1);
 
1107
   obj_chat->dp = chat;
 
1108
 
 
1109
   obj_list->bg = makecol (0, 0, 0);
 
1110
   obj_list->fg = makecol (240, 240, 240);
 
1111
   obj_list->d1 = ((sizeof (list) / MAX_UCHAR_LENGTH) - 1);
 
1112
   obj_list->dp = list;
 
1113
 
 
1114
   obj_message->d1 = ((sizeof (message) / MAX_UCHAR_LENGTH) - 1);
 
1115
   obj_message->dp = message;
 
1116
 
 
1117
   if (netplay_mode != NETPLAY_MODE_SERVER_OPEN)
 
1118
      obj_load->flags |= D_DISABLED;
 
1119
 
 
1120
   obj_ok->flags |= D_DISABLED;
 
1121
 
 
1122
   /* Clear text buffers. */
 
1123
   USTRING_CLEAR(chat);
 
1124
   USTRING_CLEAR(list);
 
1125
   USTRING_CLEAR(message);
 
1126
        
 
1127
   /* Run dialog. */
 
1128
 
 
1129
   player = init_dialog (dialog, -1);
 
1130
   if (!player)
 
1131
   {
 
1132
      gui_message (GUI_ERROR_COLOR, "Failed to create dialog player!");
 
1133
      return (D_O_K);
 
1134
   }
 
1135
 
 
1136
   while (update_dialog (player))
 
1137
   {
 
1138
      netplay_enumerate_chat (chat, sizeof(chat));
 
1139
      netplay_enumerate_clients (list, sizeof(list));
 
1140
 
 
1141
      scare_mouse ();
 
1142
      object_message (obj_chat, MSG_DRAW, 0);
 
1143
      object_message (obj_list, MSG_DRAW, 0);
 
1144
      unscare_mouse ();
 
1145
 
 
1146
      gui_heartbeat ();
 
1147
   }
 
1148
 
 
1149
   object_id = shutdown_dialog (player);
 
1150
 
 
1151
   switch (object_id)
 
1152
   {
 
1153
      case LOBBY_DIALOG_OK_BUTTON:
 
1154
         return (D_CLOSE);
 
1155
 
 
1156
      default:
 
1157
      {
 
1158
         /* End NetPlay session. */
 
1159
         netplay_close ();
 
1160
   
 
1161
         /* Clear screen. */
 
1162
         clear_bitmap (bmp);
 
1163
      
 
1164
         /* Draw background. */
 
1165
         draw_background ();
 
1166
      
 
1167
         message_local ("NetPlay session closed.");
 
1168
 
 
1169
         return (D_O_K);
 
1170
      }
 
1171
   }
 
1172
}
 
1173
 
 
1174
/* --- Menu handlers. --- */
 
1175
 
 
1176
static int main_menu_resume (void)
 
1177
{
 
1178
    return (D_CLOSE);
 
1179
}
 
1180
 
 
1181
static int main_menu_open (void)
 
1182
{
 
1183
   USTRING path;
 
1184
   BOOL locked;
 
1185
   int result;
 
1186
   USTRING scratch;
 
1187
 
 
1188
   if (rom_is_loaded)
 
1189
   {
 
1190
      if (gui_alert ("Confirmation", "A ROM is already loaded.", "If you continue, any unsaved progress will be lost.", "Are you sure?", "&OK", "&Cancel", 0, 0) == 2)
 
1191
      {
 
1192
         /* Cancelled. */
 
1193
         return (D_O_K);
 
1194
      }
 
1195
   }
 
1196
 
 
1197
   /* Retrive path from configuration file. */
 
1198
   USTRING_CLEAR(path);
 
1199
#ifdef POSIX
 
1200
   ustrncat (path, get_config_string ("gui", "open_path", "~/"), (sizeof(path) - 1));
 
1201
#else
 
1202
   ustrncat (path, get_config_string ("gui", "open_path", "/"), (sizeof(path) - 1));
 
1203
#endif
 
1204
 
 
1205
   locked = get_config_int ("gui", "lock_paths", FALSE);
 
1206
 
 
1207
#ifdef USE_ZLIB
 
1208
   result = gui_file_select ("Open", "Supported file types (*.NES, *.GZ, *.ZIP, *.NSF)", path, sizeof(path), "*.nes;*.gz;*.zip;*.nsf");
 
1209
#else
 
1210
   result = gui_file_select ("Open", "Supported file types (*.NES, *.NSF)", path, sizeof(path), "*.nes;*.nsf");
 
1211
#endif
 
1212
 
 
1213
   if (!locked)
 
1214
   {  
 
1215
      /* Update path. */
 
1216
      set_config_string ("gui", "open_path", replace_filename (scratch, path, "", sizeof (scratch)));
 
1217
   }
 
1218
 
 
1219
   if (result != 0)
 
1220
   {
 
1221
      /* Dialog was OK'ed. */
 
1222
 
 
1223
      int result;
 
1224
 
 
1225
      result = load_file (path);
 
1226
      if ((result == D_CLOSE) && !lock_recent)
 
1227
      {
 
1228
         /* Load succeeded; add file to recent items list. */
 
1229
 
 
1230
         int index;
 
1231
 
 
1232
         /* Move all existing entries down by 1 slot. */
 
1233
         for (index = (OPEN_RECENT_SLOTS - 2); index >= 0; index--)
 
1234
            ustrncpy (open_recent_filenames[(index + 1)], open_recent_filenames[index], USTRING_SIZE);
 
1235
 
 
1236
         /* Add new entry to the beginning of the list. */
 
1237
         uszprintf (open_recent_filenames[0], USTRING_SIZE, "%s", path);
 
1238
 
 
1239
         /* Update menus. */
 
1240
 
 
1241
         for (index = 0; index < OPEN_RECENT_SLOTS; index++)
 
1242
         {
 
1243
            const UCHAR *filename = open_recent_filenames[index];
 
1244
            UCHAR       *text     = open_recent_menu_texts[index];
 
1245
            MENU        *menu     = &main_open_recent_menu[index];
 
1246
 
 
1247
            if (filename[0])
 
1248
            {
 
1249
               /* Build menu text. */
 
1250
               uszprintf (text, USTRING_SIZE, "&%d: %s", index, get_filename (filename));
 
1251
 
 
1252
               /* Enable menu. */
 
1253
               menu->flags &= ~D_DISABLED;
 
1254
            }
 
1255
            else
 
1256
            {
 
1257
               /* Build menu text. */
 
1258
               uszprintf (text, USTRING_SIZE, "&%d: %s", index, UNUSED_SLOT_TEXT);
 
1259
 
 
1260
               /* Disable menu. */
 
1261
               menu->flags |= D_DISABLED;
 
1262
            }
 
1263
 
 
1264
            /* Set menu text. */
 
1265
            menu->text = text;
 
1266
         }
 
1267
      }
 
1268
 
 
1269
      return (result);
 
1270
   }
 
1271
 
 
1272
   /* Dialog was cancelled. */
 
1273
   return (D_O_K);
 
1274
}
 
1275
 
 
1276
#define OPEN_RECENT_MENU_HANDLER(index) \
 
1277
   static int main_open_recent_menu_##index (void)  \
 
1278
   {  \
 
1279
      if (rom_is_loaded) \
 
1280
      { \
 
1281
         if (gui_alert ("Confirmation", "A ROM is already loaded.", "If you continue, any unsaved progress will be lost.", "Are you sure?", "&OK", "&Cancel", 0, 0) == 2) \
 
1282
         { \
 
1283
            /* Cancelled. */ \
 
1284
            return (D_O_K); \
 
1285
         } \
 
1286
      } \
 
1287
      \
 
1288
      return (load_file (open_recent_filenames[index])); \
 
1289
   }
 
1290
 
 
1291
OPEN_RECENT_MENU_HANDLER(0)
 
1292
OPEN_RECENT_MENU_HANDLER(1)
 
1293
OPEN_RECENT_MENU_HANDLER(2)
 
1294
OPEN_RECENT_MENU_HANDLER(3)
 
1295
OPEN_RECENT_MENU_HANDLER(4)
 
1296
OPEN_RECENT_MENU_HANDLER(5)
 
1297
OPEN_RECENT_MENU_HANDLER(6)
 
1298
OPEN_RECENT_MENU_HANDLER(7)
 
1299
OPEN_RECENT_MENU_HANDLER(8)
 
1300
OPEN_RECENT_MENU_HANDLER(9)
 
1301
 
 
1302
#undef OPEN_RECENT_MENU_HANDLER
 
1303
 
 
1304
static int main_open_recent_menu_lock (void)
 
1305
{
 
1306
   lock_recent = !lock_recent;
 
1307
   update_menus ();
 
1308
 
 
1309
   return (D_O_K);
 
1310
}
 
1311
 
 
1312
static int main_open_recent_menu_clear (void)
 
1313
{
 
1314
   int index;
 
1315
 
 
1316
   for (index = 0; index < OPEN_RECENT_SLOTS; index++)
 
1317
   {
 
1318
      UCHAR *filename = open_recent_filenames[index];
 
1319
      UCHAR *text     = open_recent_menu_texts[index];
 
1320
      MENU  *menu     = &main_open_recent_menu[index];
 
1321
 
 
1322
      USTRING_CLEAR(filename);
 
1323
 
 
1324
      /* Build menu text. */
 
1325
      uszprintf (text, USTRING_SIZE, "&%d: %s", index, UNUSED_SLOT_TEXT);
 
1326
 
 
1327
      /* Update menu. */
 
1328
      menu->text = text;
 
1329
 
 
1330
      /* Disable menu. */
 
1331
      menu->flags |= D_DISABLED;
 
1332
   }
 
1333
 
 
1334
   return (D_O_K);
 
1335
}
 
1336
 
 
1337
static int main_menu_close (void)
 
1338
{
 
1339
   if (gui_alert ("Confirmation", "If you continue, any unsaved progress will be lost.", "Are you sure you want to unload the ROM?", NULL, "&OK", "&Cancel", 0, 0) == 2)
 
1340
   {
 
1341
      /* Cancelled. */
 
1342
      return (D_O_K);
 
1343
   }
 
1344
 
 
1345
   /* Unload ROM. */
 
1346
   close_file ();
 
1347
 
 
1348
   /* Clear the screen and restore background. */
 
1349
   cycle_video ();
 
1350
 
 
1351
   return (D_REDRAW);
 
1352
}
 
1353
 
 
1354
#define REPLAY_SELECT_MENU_HANDLER(index) \
 
1355
   static int main_replay_select_menu_##index (void)  \
 
1356
   {  \
 
1357
      replay_index = index;   \
 
1358
      update_menus ();  \
 
1359
      message_local ("Replay slot set to %d.", index);   \
 
1360
      return (D_O_K);   \
 
1361
   }
 
1362
 
 
1363
REPLAY_SELECT_MENU_HANDLER(0)
 
1364
REPLAY_SELECT_MENU_HANDLER(1)
 
1365
REPLAY_SELECT_MENU_HANDLER(2)
 
1366
REPLAY_SELECT_MENU_HANDLER(3)
 
1367
REPLAY_SELECT_MENU_HANDLER(4)
 
1368
REPLAY_SELECT_MENU_HANDLER(5)
 
1369
REPLAY_SELECT_MENU_HANDLER(6)
 
1370
REPLAY_SELECT_MENU_HANDLER(7)
 
1371
REPLAY_SELECT_MENU_HANDLER(8)
 
1372
REPLAY_SELECT_MENU_HANDLER(9)
 
1373
 
 
1374
#undef REPLAY_SELECT_MENU_HANDLER
 
1375
 
 
1376
static int main_replay_menu_select (void)
 
1377
{
 
1378
   int index;
 
1379
 
 
1380
   for (index = 0; index < REPLAY_SLOTS; index++)
 
1381
   {
 
1382
      UCHAR *title;
 
1383
      UCHAR *text;
 
1384
 
 
1385
      title = replay_titles[index];
 
1386
      text = replay_menu_texts[index];
 
1387
 
 
1388
      /* Get title. */
 
1389
      get_replay_title (index, title, USTRING_SIZE);
 
1390
 
 
1391
      /* Build menu text. */
 
1392
      uszprintf (text, USTRING_SIZE, "&%d: %s", index, title);
 
1393
 
 
1394
      /* Update menu. */
 
1395
      main_replay_select_menu[index].text = text;
 
1396
   }
 
1397
 
 
1398
   return (D_O_K);
 
1399
}
 
1400
 
 
1401
static int main_replay_record_menu_start (void)
 
1402
{
 
1403
   USTRING title;
 
1404
 
 
1405
   /* Duplicate title. */
 
1406
   ustrncpy (title, replay_titles[replay_index], USTRING_SIZE);
 
1407
 
 
1408
   /* Patch up duplicate. */
 
1409
   fix_save_title (title, sizeof (title));
 
1410
                 
 
1411
   if (gui_is_active)
 
1412
   {
 
1413
      DIALOG *dialog;
 
1414
      DIALOG *objtitle;
 
1415
 
 
1416
      /* Allow user to customize title before save. */
 
1417
 
 
1418
      dialog = main_replay_record_start_dialog;
 
1419
 
 
1420
      objtitle = &dialog[MAIN_REPLAY_RECORD_START_DIALOG_TITLE];
 
1421
 
 
1422
      objtitle->d1 = NEW_SAVE_TITLE_SIZE;
 
1423
      objtitle->dp = title;
 
1424
 
 
1425
      if (show_dialog (dialog, -1) !=
 
1426
         MAIN_REPLAY_RECORD_START_DIALOG_OK_BUTTON)
 
1427
      {
 
1428
         /* Dialog was cancelled. */
 
1429
         return (D_O_K);
 
1430
      }
 
1431
   }
 
1432
 
 
1433
   /* Open replay file. */
 
1434
   if (!open_replay (replay_index, "w", title))
 
1435
   {
 
1436
      gui_message (GUI_ERROR_COLOR, "Failed to open new machine state "
 
1437
         "file.");
 
1438
 
 
1439
      return (D_O_K);
 
1440
   }
 
1441
 
 
1442
   DISABLE_MENU_ITEM(main_menu_open);
 
1443
   DISABLE_SUBMENU(main_open_recent_menu);
 
1444
   DISABLE_MENU_ITEM(main_menu_close);
 
1445
   DISABLE_MENU_ITEM(main_replay_record_menu_start);
 
1446
   ENABLE_MENU_ITEM(main_replay_record_menu_stop);
 
1447
   DISABLE_SUBMENU(main_replay_select_menu);
 
1448
   DISABLE_SUBMENU(main_replay_play_menu);
 
1449
   DISABLE_SUBMENU(machine_save_state_autosave_menu);
 
1450
   DISABLE_SUBMENU(netplay_menu);
 
1451
 
 
1452
   /* Enter replay recording mode. */
 
1453
   input_mode |= INPUT_MODE_REPLAY;
 
1454
   input_mode |= INPUT_MODE_REPLAY_RECORD;
 
1455
 
 
1456
   message_local ("Replay recording session started.");
 
1457
 
 
1458
   /* Update replay titles. */
 
1459
   main_replay_menu_select ();
 
1460
 
 
1461
   return (D_CLOSE);
 
1462
}
 
1463
 
 
1464
static int main_replay_record_menu_stop (void)
 
1465
{
 
1466
   /* Close replay. */
 
1467
   close_replay ();
 
1468
 
 
1469
   /* Exit replay recording mode. */
 
1470
   input_mode &= ~INPUT_MODE_REPLAY;
 
1471
   input_mode &= ~INPUT_MODE_REPLAY_RECORD;
 
1472
 
 
1473
   ENABLE_MENU_ITEM(main_menu_open);
 
1474
   ENABLE_SUBMENU(main_open_recent_menu);
 
1475
   ENABLE_MENU_ITEM(main_menu_close);
 
1476
   ENABLE_MENU_ITEM(main_replay_record_menu_start);
 
1477
   DISABLE_MENU_ITEM(main_replay_record_menu_stop);
 
1478
   ENABLE_SUBMENU(main_replay_select_menu);
 
1479
   ENABLE_SUBMENU(main_replay_play_menu);
 
1480
   ENABLE_SUBMENU(machine_save_state_autosave_menu);
 
1481
   ENABLE_SUBMENU(netplay_menu);
 
1482
 
 
1483
   message_local ("Replay recording session stopped.");
 
1484
 
 
1485
   return (D_O_K);
 
1486
}
 
1487
 
 
1488
static int main_replay_play_menu_start (void)
 
1489
{
 
1490
   if (!open_replay (replay_index, "r", NULL))
 
1491
   {                       
 
1492
      gui_message (GUI_ERROR_COLOR, "Failed to open machine state file.");
 
1493
 
 
1494
      return (D_O_K);
 
1495
   }
 
1496
 
 
1497
   DISABLE_MENU_ITEM(main_menu_open);
 
1498
   DISABLE_SUBMENU(main_open_recent_menu);
 
1499
   DISABLE_MENU_ITEM(main_menu_close);
 
1500
   DISABLE_MENU_ITEM(main_replay_play_menu_start);
 
1501
   ENABLE_MENU_ITEM(main_replay_play_menu_stop);
 
1502
   DISABLE_SUBMENU(main_replay_select_menu);
 
1503
   DISABLE_SUBMENU(main_replay_record_menu);
 
1504
   DISABLE_MENU_ITEM(main_menu_cheat_manager);
 
1505
   DISABLE_MENU_ITEM(machine_menu_reset);
 
1506
   DISABLE_MENU_ITEM(machine_menu_power_cycle);
 
1507
   DISABLE_MENU_ITEM(machine_save_state_menu_quick_load);
 
1508
   DISABLE_MENU_ITEM(machine_save_state_menu_restore);
 
1509
   DISABLE_SUBMENU(netplay_menu);
 
1510
 
 
1511
   /* Enter replay playback mode. */
 
1512
   input_mode &= ~INPUT_MODE_PLAY;
 
1513
   input_mode |= INPUT_MODE_REPLAY;
 
1514
   input_mode |= INPUT_MODE_REPLAY_PLAY;
 
1515
 
 
1516
   message_local ("Replay playback started.");
 
1517
 
 
1518
   return (D_CLOSE);
 
1519
}
 
1520
 
 
1521
static int main_replay_play_menu_stop (void)
 
1522
{
 
1523
   /* Close replay. */
 
1524
   close_replay ();
 
1525
 
 
1526
   /* Exit replay playback mode. */
 
1527
   if (!(input_mode & INPUT_MODE_CHAT))
 
1528
      input_mode |= INPUT_MODE_PLAY;
 
1529
   input_mode &= ~INPUT_MODE_REPLAY;
 
1530
   input_mode &= ~INPUT_MODE_REPLAY_PLAY;
 
1531
 
 
1532
   ENABLE_MENU_ITEM(main_menu_open);
 
1533
   ENABLE_SUBMENU(main_open_recent_menu);
 
1534
   ENABLE_MENU_ITEM(main_menu_close);
 
1535
   ENABLE_MENU_ITEM(main_replay_play_menu_start);
 
1536
   DISABLE_MENU_ITEM(main_replay_play_menu_stop);
 
1537
   ENABLE_SUBMENU(main_replay_select_menu);
 
1538
   ENABLE_SUBMENU(main_replay_record_menu);
 
1539
   ENABLE_MENU_ITEM(main_menu_cheat_manager);
 
1540
   ENABLE_MENU_ITEM(machine_menu_reset);
 
1541
   ENABLE_MENU_ITEM(machine_menu_power_cycle);
 
1542
   ENABLE_MENU_ITEM(machine_save_state_menu_quick_load);
 
1543
   ENABLE_MENU_ITEM(machine_save_state_menu_restore);
 
1544
   ENABLE_SUBMENU(netplay_menu);
 
1545
 
 
1546
   if (gui_is_active)
 
1547
      message_local ("Replay playback stopped.");
 
1548
   else
 
1549
      message_local ("Replay playback finished.");
 
1550
 
 
1551
   return (D_O_K);
 
1552
}
 
1553
 
 
1554
static int main_menu_cheat_manager (void)
 
1555
{
 
1556
   if (show_dialog (main_cheat_manager_dialog, -1) ==
 
1557
      MAIN_CHEAT_MANAGER_DIALOG_SAVE_BUTTON)
 
1558
   {
 
1559
      save_patches ();
 
1560
   }
 
1561
 
 
1562
   return (D_O_K);
 
1563
}
 
1564
 
 
1565
static int main_menu_save_snapshot (void)
 
1566
{
 
1567
   int index;
 
1568
 
 
1569
   for (index = 0; index < 999; index++)
 
1570
   {
 
1571
      USTRING path;
 
1572
      USTRING filename;
 
1573
 
 
1574
      uszprintf (filename, sizeof (filename), "%s_%03d.pcx", get_filename
 
1575
         (global_rom.filename), index);
 
1576
 
 
1577
      /* Merge it with our save path. */
 
1578
      get_save_path (filename, sizeof (filename));
 
1579
 
 
1580
      if (exists (filename))
 
1581
         continue;
 
1582
 
 
1583
      save_bitmap (filename, video_buffer, video_palette);
 
1584
 
 
1585
      message_local ("Snapshot saved to %s.", filename);
 
1586
 
 
1587
      return (D_O_K);
 
1588
   }
 
1589
 
 
1590
   gui_message (GUI_ERROR_COLOR, "Couldn't find a suitable image "
 
1591
      "filename.");
 
1592
 
 
1593
   return (D_O_K);
 
1594
}
 
1595
 
 
1596
static int main_menu_advance_frame (void)
 
1597
{
 
1598
   frames_to_execute = 1;
 
1599
 
 
1600
   return (D_CLOSE);
 
1601
}
 
1602
 
 
1603
static int main_menu_save_configuration (void)
 
1604
{
 
1605
   save_config ();
 
1606
   gui_alert ("Confirmation", "Configuration has been saved.", NULL, NULL, "&OK", NULL, 0, 0);
 
1607
 
 
1608
   return (D_O_K);
 
1609
}
 
1610
 
 
1611
static int main_menu_exit (void)
 
1612
{
 
1613
   if (rom_is_loaded)
 
1614
   {
 
1615
      /* Confirm exit. */
 
1616
 
 
1617
      if (gui_alert ("Confirmation", "A ROM is currently loaded.", "If you continue, any unsaved progress will be lost.", "Really exit?", "&OK", "&Cancel", 0, 0) == 2)
 
1618
      {
 
1619
         /* Cancelled. */
 
1620
         return (D_O_K);
 
1621
      }
 
1622
      else
 
1623
      {
 
1624
         want_exit = TRUE;
 
1625
      
 
1626
         return (D_CLOSE);
 
1627
      }
 
1628
   }
 
1629
   else
 
1630
   {
 
1631
      /* Just exit. */
 
1632
 
 
1633
      want_exit = TRUE;
 
1634
   
 
1635
      return (D_CLOSE);
 
1636
   }
 
1637
}
 
1638
 
 
1639
#define SAVE_STATE_SELECT_MENU_HANDLER(index)   \
 
1640
   static int machine_save_state_select_menu_##index (void)   \
 
1641
   {  \
 
1642
      save_state_index = index;  \
 
1643
      update_menus ();  \
 
1644
      message_local ("Machine state slot set to %d.", index);  \
 
1645
      return (D_O_K);   \
 
1646
   }
 
1647
 
 
1648
SAVE_STATE_SELECT_MENU_HANDLER(0);
 
1649
SAVE_STATE_SELECT_MENU_HANDLER(1);
 
1650
SAVE_STATE_SELECT_MENU_HANDLER(2);
 
1651
SAVE_STATE_SELECT_MENU_HANDLER(3);
 
1652
SAVE_STATE_SELECT_MENU_HANDLER(4);
 
1653
SAVE_STATE_SELECT_MENU_HANDLER(5);
 
1654
SAVE_STATE_SELECT_MENU_HANDLER(6);
 
1655
SAVE_STATE_SELECT_MENU_HANDLER(7);
 
1656
SAVE_STATE_SELECT_MENU_HANDLER(8);
 
1657
SAVE_STATE_SELECT_MENU_HANDLER(9);
 
1658
 
 
1659
#undef SAVE_STATE_MENU_HANDLER
 
1660
 
 
1661
static int machine_save_state_menu_quick_save (void)
 
1662
{
 
1663
   if (!save_state (-1, "QUICKSAVE"))
 
1664
   {
 
1665
      gui_message (GUI_ERROR_COLOR, "Quick Save failed.");
 
1666
 
 
1667
      return (D_O_K);
 
1668
   }
 
1669
 
 
1670
   return (D_CLOSE);
 
1671
}
 
1672
 
 
1673
static int machine_save_state_menu_quick_load (void)
 
1674
{
 
1675
   if (!load_state (-1))
 
1676
   {
 
1677
      gui_message (GUI_ERROR_COLOR, "Quick Load failed.");
 
1678
 
 
1679
      return (D_O_K);
 
1680
   }
 
1681
 
 
1682
   return (D_CLOSE);
 
1683
}
 
1684
 
 
1685
static int machine_save_state_menu_save (void)
 
1686
{
 
1687
   USTRING title;
 
1688
   USTRING filename;
 
1689
 
 
1690
   /* Duplicate title. */
 
1691
   ustrncpy (title, save_state_titles[save_state_index], sizeof (title));
 
1692
 
 
1693
   /* Patch up duplicate. */
 
1694
   fix_save_title (title, sizeof (title));
 
1695
 
 
1696
   if (gui_is_active)
 
1697
   {
 
1698
      DIALOG *dialog;
 
1699
      DIALOG *objtitle;
 
1700
 
 
1701
      /* Allow user to customize title before save. */
 
1702
 
 
1703
      dialog = machine_save_state_save_dialog;
 
1704
 
 
1705
      objtitle = &dialog[MACHINE_SAVE_STATE_SAVE_DIALOG_TITLE];
 
1706
 
 
1707
      objtitle->d1 = NEW_SAVE_TITLE_SIZE;
 
1708
      objtitle->dp = title;
 
1709
 
 
1710
      if (show_dialog (dialog, -1) !=
 
1711
         MACHINE_SAVE_STATE_SAVE_DIALOG_OK_BUTTON)
 
1712
      {
 
1713
         /* Cancelled. */
 
1714
         return (D_O_K);
 
1715
      }
 
1716
   }
 
1717
 
 
1718
   if (!save_state (save_state_index, title))
 
1719
   {
 
1720
      gui_message (GUI_ERROR_COLOR, "Failed to open new machine state "
 
1721
         "file.");
 
1722
 
 
1723
      return (D_O_K);
 
1724
   }
 
1725
 
 
1726
   message_local ("Machine state saved to slot %d.", save_state_index);
 
1727
 
 
1728
   /* Update save state titles. */
 
1729
   machine_save_state_menu_select ();
 
1730
 
 
1731
   return (D_CLOSE);
 
1732
}
 
1733
 
 
1734
static int machine_save_state_menu_restore (void)
 
1735
{
 
1736
   if (!load_state (save_state_index))
 
1737
   {
 
1738
      gui_message (GUI_ERROR_COLOR, "Failed to open machine state file.");
 
1739
 
 
1740
      return (D_O_K);
 
1741
   }
 
1742
 
 
1743
   message_local ("Machine state loaded from slot %d.", save_state_index);
 
1744
 
 
1745
   return (D_CLOSE);
 
1746
}
 
1747
 
 
1748
static int machine_save_state_menu_select (void)
 
1749
{
 
1750
   int index;
 
1751
 
 
1752
   for (index = 0; index < SAVE_STATE_SLOTS; index++)
 
1753
   {
 
1754
      UCHAR *title;
 
1755
      UCHAR *text;
 
1756
 
 
1757
      title = save_state_titles[index];
 
1758
      text = save_state_menu_texts[index];
 
1759
 
 
1760
      /* Get title. */
 
1761
      get_state_title (index, title, USTRING_SIZE);
 
1762
 
 
1763
      /* Build menu text. */
 
1764
      uszprintf (text, USTRING_SIZE, "&%d: %s", index, title);
 
1765
 
 
1766
      /* Update menu. */
 
1767
      machine_save_state_select_menu[index].text = text;
 
1768
   }
 
1769
 
 
1770
   return (D_O_K);
 
1771
}
 
1772
 
 
1773
static int machine_save_state_autosave_menu_disabled (void)
 
1774
{
 
1775
   set_autosave (0);
 
1776
 
 
1777
   return (D_O_K);
 
1778
}
 
1779
 
 
1780
static int machine_save_state_autosave_menu_10_seconds (void)
 
1781
{
 
1782
   set_autosave (10);
 
1783
 
 
1784
   return (D_O_K);
 
1785
}
 
1786
 
 
1787
static int machine_save_state_autosave_menu_30_seconds (void)
 
1788
{
 
1789
   set_autosave (30);
 
1790
 
 
1791
   return (D_O_K);
 
1792
}
 
1793
 
 
1794
static int machine_save_state_autosave_menu_60_seconds (void)
 
1795
{
 
1796
   set_autosave (60);
 
1797
 
 
1798
   return (D_O_K);
 
1799
}
 
1800
 
 
1801
static int machine_save_state_autosave_menu_custom (void)
 
1802
{
 
1803
   int seconds;
 
1804
 
 
1805
   seconds = input_autosave_interval;
 
1806
 
 
1807
   if (get_integer_input ("Custom", &seconds, "seconds"))
 
1808
      set_autosave (seconds);
 
1809
 
 
1810
   return (D_O_K);
 
1811
}
 
1812
 
 
1813
static int machine_region_menu_automatic (void)
 
1814
{
 
1815
   machine_region = MACHINE_REGION_AUTOMATIC;
 
1816
   timing_update_machine_type ();
 
1817
   update_menus ();
 
1818
 
 
1819
   message_local ("System region set to automatic.");
 
1820
 
 
1821
   return (D_O_K);
 
1822
}
 
1823
 
 
1824
static int machine_region_menu_ntsc (void)
 
1825
{
 
1826
   machine_region = MACHINE_REGION_NTSC;
 
1827
   timing_update_machine_type ();
 
1828
   update_menus ();
 
1829
 
 
1830
   message_local ("System region set to NTSC.");
 
1831
 
 
1832
   return (D_O_K);
 
1833
}
 
1834
 
 
1835
static int machine_region_menu_pal (void)
 
1836
{
 
1837
   machine_region = MACHINE_REGION_PAL;
 
1838
   timing_update_machine_type ();
 
1839
   update_menus ();
 
1840
 
 
1841
   message_local ("System region set to PAL.");
 
1842
 
 
1843
   return (D_O_K);
 
1844
}
 
1845
 
 
1846
static int machine_speed_up_down_menu_50_percent (void)
 
1847
{
 
1848
   timing_speed_multiplier = 0.5;
 
1849
   timing_update_speed ();
 
1850
 
 
1851
   update_menus ();
 
1852
 
 
1853
   message_local ("Machine speed factor set to 50%%.");
 
1854
 
 
1855
   return (D_O_K);
 
1856
}
 
1857
 
 
1858
static int machine_speed_up_down_menu_100_percent (void)
 
1859
{
 
1860
   timing_speed_multiplier = 1.0;
 
1861
   timing_update_speed ();
 
1862
 
 
1863
   update_menus ();
 
1864
 
 
1865
   message_local ("Machine speed factor set to 100%%.");
 
1866
 
 
1867
   return (D_O_K);
 
1868
}
 
1869
 
 
1870
static int machine_speed_up_down_menu_200_percent (void)
 
1871
{
 
1872
   timing_speed_multiplier = 2.0;
 
1873
   timing_update_speed ();
 
1874
 
 
1875
   update_menus ();
 
1876
 
 
1877
   message_local ("Machine speed factor set to 200%%.");
 
1878
 
 
1879
   return (D_O_K);
 
1880
}
 
1881
 
 
1882
static int machine_speed_up_down_menu_custom (void)
 
1883
{
 
1884
   REAL value;
 
1885
 
 
1886
   value = (timing_speed_multiplier * 100.0);
 
1887
 
 
1888
   if (get_float_input ("Custom", &value, "percent"))
 
1889
   {
 
1890
      timing_speed_multiplier = (value / 100.0);
 
1891
      timing_update_speed ();
 
1892
 
 
1893
      update_menus ();
 
1894
 
 
1895
      message_local ("Machine speed factor set to custom.");
 
1896
   }
 
1897
 
 
1898
   return (D_O_K);
 
1899
}
 
1900
 
 
1901
static int machine_frame_skip_menu_automatic (void)
 
1902
{
 
1903
   frame_skip = -1;
 
1904
   update_menus ();
 
1905
 
 
1906
   message_local ("Frame skip set to automatic.");
 
1907
 
 
1908
   return (D_O_K);
 
1909
}
 
1910
 
 
1911
static int machine_frame_skip_menu_disabled (void)
 
1912
{
 
1913
   frame_skip = 0;
 
1914
   update_menus ();
 
1915
 
 
1916
   message_local ("Frame skip disabled.");
 
1917
 
 
1918
   return (D_O_K);
 
1919
}
 
1920
 
 
1921
#define FRAME_SKIP_MENU_HANDLER(frames)   \
 
1922
   static int machine_frame_skip_menu_##frames##_frames (void) \
 
1923
   {  \
 
1924
      frame_skip = frames; \
 
1925
      update_menus ();  \
 
1926
      message_local ("Frame skip set to %d frames.", frames);  \
 
1927
      return (D_O_K);   \
 
1928
   }
 
1929
 
 
1930
FRAME_SKIP_MENU_HANDLER(1)
 
1931
FRAME_SKIP_MENU_HANDLER(2)
 
1932
FRAME_SKIP_MENU_HANDLER(3)
 
1933
FRAME_SKIP_MENU_HANDLER(4)
 
1934
FRAME_SKIP_MENU_HANDLER(5)
 
1935
FRAME_SKIP_MENU_HANDLER(6)
 
1936
FRAME_SKIP_MENU_HANDLER(7)
 
1937
FRAME_SKIP_MENU_HANDLER(8)
 
1938
FRAME_SKIP_MENU_HANDLER(9)
 
1939
FRAME_SKIP_MENU_HANDLER(10)
 
1940
 
 
1941
#undef FRAME_SKIP_MENU_HANDLER
 
1942
 
 
1943
static int machine_frame_skip_menu_custom (void)
 
1944
{
 
1945
   int frames;
 
1946
 
 
1947
   frames = frame_skip;
 
1948
 
 
1949
   if (get_integer_input ("Custom", &frames, "frames"))
 
1950
   {
 
1951
      frame_skip = frames;
 
1952
      update_menus ();
 
1953
   
 
1954
      message_local ("Frame skip set to %d frames.", frames);
 
1955
   }
 
1956
 
 
1957
   return (D_O_K);
 
1958
}
 
1959
 
 
1960
static int machine_menu_show_status (void)
 
1961
{
 
1962
   video_display_status = (! video_display_status);
 
1963
   update_menus ();
 
1964
 
 
1965
   return (D_O_K);
 
1966
}
 
1967
 
 
1968
static int machine_menu_reset (void)
 
1969
{
 
1970
   /* Confirm reset. */
 
1971
 
 
1972
   if (gui_alert ("Confirmation", "This action will reset the virtual machine.", "If you continue, any unsaved progress will be lost.", "Really reset the virtual machine?", "&OK", "&Cancel", 0, 0) == 2)
 
1973
   {
 
1974
      /* Cancelled. */
 
1975
      return (D_O_K);
 
1976
   }
 
1977
   else
 
1978
   {
 
1979
      machine_reset ();
 
1980
 
 
1981
      /* Clear the game clock. */
 
1982
      options_menu_reset_clock ();
 
1983
 
 
1984
      return (D_CLOSE);
 
1985
   }
 
1986
}
 
1987
 
 
1988
static int machine_menu_power_cycle (void)
 
1989
{
 
1990
   /* Confirm power cycle. */
 
1991
 
 
1992
   if (gui_alert ("Confirmation", "This action will power cycle the virtual machine.", "If you continue, any unsaved progress will be lost.", "Really power cycle the virtual machine?", "&OK", "&Cancel", 0, 0) == 2)
 
1993
   {
 
1994
      /* Cancelled. */
 
1995
      return (D_O_K);
 
1996
   }
 
1997
   else
 
1998
   {
 
1999
      machine_exit ();
 
2000
      machine_init ();
 
2001
 
 
2002
      /* Clear the game clock. */
 
2003
      options_menu_reset_clock ();
 
2004
 
 
2005
      return (D_CLOSE);
 
2006
   }
 
2007
}
 
2008
 
 
2009
static int machine_menu_timing_smoothest (void)
 
2010
{
 
2011
   machine_timing = MACHINE_TIMING_SMOOTH;
 
2012
   timing_update_speed ();
 
2013
   update_menus ();
 
2014
 
 
2015
   message_local ("Machine timing mode set to smoothest.");
 
2016
 
 
2017
   return (D_O_K);
 
2018
}
 
2019
 
 
2020
static int machine_menu_timing_most_accurate (void)
 
2021
{
 
2022
   machine_timing = MACHINE_TIMING_ACCURATE;
 
2023
   timing_update_speed ();
 
2024
   update_menus ();
 
2025
 
 
2026
   message_local ("Machine timing mode set to most accurate.");
 
2027
 
 
2028
   return (D_O_K);
 
2029
}
 
2030
 
 
2031
static int machine_menu_speed_cap (void)
 
2032
{
 
2033
   speed_cap = !speed_cap;
 
2034
   update_menus ();
 
2035
 
 
2036
   message_local ("Speed cap %s.", get_enabled_text (speed_cap));
 
2037
 
 
2038
   return (D_O_K);
 
2039
}
 
2040
 
 
2041
static int audio_menu_enable_apu (void)
 
2042
{
 
2043
   apu_options.enabled = !apu_options.enabled;
 
2044
   update_menus ();
 
2045
 
 
2046
   apu_update ();
 
2047
 
 
2048
   message_local ("APU emulation %s.",
 
2049
      get_enabled_text (apu_options.enabled));
 
2050
 
 
2051
   return (D_O_K);
 
2052
}
 
2053
 
 
2054
static int audio_menu_enable_output (void)
 
2055
{
 
2056
   audio_options.enable_output = !audio_options.enable_output;
 
2057
 
 
2058
   cycle_audio ();
 
2059
   update_menus ();
 
2060
 
 
2061
   message_local ("Audio output %s.", get_enabled_text (audio_options.enable_output));
 
2062
 
 
2063
   return (D_O_K);
 
2064
}
 
2065
 
 
2066
static int audio_menu_emulation_fast (void)
 
2067
{
 
2068
   apu_options.emulation = APU_EMULATION_FAST;
 
2069
   update_menus ();
 
2070
 
 
2071
   apu_update ();
 
2072
 
 
2073
   gui_alert ("Accuracy Warning", "The fast emulation mode may introduce permanent accuracy glitches into save states, "
 
2074
      "replays and the game rewinder.",
 
2075
      "Only use it if you have a very slow computer that cannot handle one of the other emulation modes.",
 
2076
      NULL, "&OK", NULL, 0, 0);
 
2077
 
 
2078
   message_local ("APU emulation quality set to fast.");
 
2079
 
 
2080
   return (D_O_K);
 
2081
}
 
2082
 
 
2083
static int audio_menu_emulation_accurate (void)
 
2084
{
 
2085
   apu_options.emulation = APU_EMULATION_ACCURATE;
 
2086
   update_menus ();
 
2087
 
 
2088
   apu_update ();
 
2089
 
 
2090
   message_local ("APU emulation quality set to accurate.");
 
2091
 
 
2092
   return (D_O_K);
 
2093
}
 
2094
 
 
2095
static int audio_menu_emulation_high_quality (void)
 
2096
{
 
2097
   apu_options.emulation = APU_EMULATION_HIGH_QUALITY;
 
2098
   update_menus ();
 
2099
 
 
2100
   apu_update ();
 
2101
 
 
2102
   message_local ("APU emulation quality set to high quality.");
 
2103
 
 
2104
   return (D_O_K);
 
2105
}
 
2106
 
 
2107
#define AUDIO_CHANNELS_MENU_HANDLER(id, name)  \
 
2108
   static int audio_channels_menu_##id (void) \
 
2109
   { \
 
2110
      BOOL *enabled = &apu_options.enable_##id ; \
 
2111
      *enabled = !*enabled; \
 
2112
      update_menus (); \
 
2113
      apu_update (); \
 
2114
      message_local ("APU " name " %s.", get_enabled_text (*enabled)); \
 
2115
      return (D_O_K); \
 
2116
   }
 
2117
 
 
2118
AUDIO_CHANNELS_MENU_HANDLER(square_1, "first square wave channel")
 
2119
AUDIO_CHANNELS_MENU_HANDLER(square_2, "second square wave channel")
 
2120
AUDIO_CHANNELS_MENU_HANDLER(triangle, "triangle wave channel")
 
2121
AUDIO_CHANNELS_MENU_HANDLER(noise,    "noise channel")
 
2122
AUDIO_CHANNELS_MENU_HANDLER(dmc,      "delta modulation channel")
 
2123
AUDIO_CHANNELS_MENU_HANDLER(extra_1,  "first expansion channel")
 
2124
AUDIO_CHANNELS_MENU_HANDLER(extra_2,  "second expansion channel")
 
2125
AUDIO_CHANNELS_MENU_HANDLER(extra_3,  "third expansion channel")
 
2126
 
 
2127
#undef AUDIO_CHANNELS_MENU_HANDLER
 
2128
 
 
2129
static int audio_channels_menu_enable_all (void)
 
2130
{               
 
2131
   apu_options.enable_square_1 = TRUE;
 
2132
   apu_options.enable_square_2 = TRUE;
 
2133
   apu_options.enable_triangle = TRUE;
 
2134
   apu_options.enable_noise    = TRUE;
 
2135
   apu_options.enable_dmc      = TRUE;
 
2136
   apu_options.enable_extra_1  = TRUE;
 
2137
   apu_options.enable_extra_2  = TRUE;
 
2138
   apu_options.enable_extra_3  = TRUE;
 
2139
 
 
2140
   update_menus ();
 
2141
 
 
2142
   apu_update ();
 
2143
 
 
2144
   message_local ("All APU channels enabled.");
 
2145
 
 
2146
   return (D_O_K);
 
2147
}
 
2148
 
 
2149
static int audio_channels_menu_disable_all (void)
 
2150
{
 
2151
   apu_options.enable_square_1 = FALSE;
 
2152
   apu_options.enable_square_2 = FALSE;
 
2153
   apu_options.enable_triangle = FALSE;
 
2154
   apu_options.enable_noise    = FALSE;
 
2155
   apu_options.enable_dmc      = FALSE;
 
2156
   apu_options.enable_extra_1  = FALSE;
 
2157
   apu_options.enable_extra_2  = FALSE;
 
2158
   apu_options.enable_extra_3  = FALSE;
 
2159
 
 
2160
   update_menus ();
 
2161
 
 
2162
   apu_update ();
 
2163
 
 
2164
   message_local ("All APU channels disabled.");
 
2165
 
 
2166
   return (D_O_K);
 
2167
}
 
2168
 
 
2169
static int audio_output_menu_subsystem_allegro (void)
 
2170
{
 
2171
   audio_options.subsystem = AUDIO_SUBSYSTEM_ALLEGRO;
 
2172
   
 
2173
   cycle_audio ();
 
2174
   update_menus ();
 
2175
 
 
2176
   message_local ("Audio subsystem set to Allegro.");
 
2177
   
 
2178
   return (D_O_K);
 
2179
}
 
2180
 
 
2181
static int audio_output_menu_subsystem_openal (void)
 
2182
{
 
2183
   audio_options.subsystem = AUDIO_SUBSYSTEM_OPENAL;
 
2184
 
 
2185
   cycle_audio ();
 
2186
   update_menus ();
 
2187
 
 
2188
   message_local ("Audio subsystem set to OpenAL.");
 
2189
 
 
2190
   return (D_O_K);
 
2191
}
 
2192
 
 
2193
#define AUDIO_OUTPUT_MENU_SAMPLING_RATE_HANDLER(rate)  \
 
2194
   static int audio_output_menu_sampling_rate_##rate##_hz (void) \
 
2195
   {  \
 
2196
      audio_options.sample_rate_hint = rate;  \
 
2197
      cycle_audio ();   \
 
2198
      update_menus ();  \
 
2199
      message_local ("Audio sampling rate set to %d Hz.", rate);  \
 
2200
      return (D_O_K);   \
 
2201
   }
 
2202
 
 
2203
AUDIO_OUTPUT_MENU_SAMPLING_RATE_HANDLER(22050)
 
2204
AUDIO_OUTPUT_MENU_SAMPLING_RATE_HANDLER(44100)
 
2205
AUDIO_OUTPUT_MENU_SAMPLING_RATE_HANDLER(48000)
 
2206
 
 
2207
#undef AUDIO_OUTPUT_MENU_SAMPLING_RATE_HANDLER
 
2208
 
 
2209
static int audio_output_menu_sampling_rate_automatic (void)
 
2210
{
 
2211
   audio_options.sample_rate_hint = -1;
 
2212
 
 
2213
   cycle_audio ();
 
2214
   update_menus ();
 
2215
 
 
2216
   message_local ("Audio sampling rate set to automatic.");
 
2217
 
 
2218
   return (D_O_K);
 
2219
}
 
2220
 
 
2221
static int audio_output_menu_sampling_rate_custom (void)
 
2222
{
 
2223
   int rate;
 
2224
 
 
2225
   rate = audio_options.sample_rate_hint;
 
2226
 
 
2227
   if (get_integer_input ("Custom", &rate, "Hz"))
 
2228
   {
 
2229
      audio_options.sample_rate_hint = rate;
 
2230
 
 
2231
      cycle_audio ();
 
2232
      update_menus ();
 
2233
 
 
2234
      message_local ("Audio sampling rate set to %d Hz.", rate);
 
2235
   }
 
2236
 
 
2237
   return (D_O_K);
 
2238
}
 
2239
 
 
2240
static int audio_output_menu_mixing_mono (void)
 
2241
{
 
2242
   apu_options.stereo = FALSE;
 
2243
   
 
2244
   cycle_audio ();
 
2245
   update_menus ();
 
2246
 
 
2247
   gui_message (GUI_TEXT_COLOR, "Audio output set to mono.");
 
2248
 
 
2249
   return (D_O_K);
 
2250
}
 
2251
 
 
2252
static int audio_output_menu_mixing_stereo (void)
 
2253
{
 
2254
   apu_options.stereo = TRUE;
 
2255
   apu_options.swap_channels = FALSE;
 
2256
 
 
2257
   cycle_audio ();
 
2258
   update_menus ();
 
2259
 
 
2260
   gui_alert ("Information", "Stereo output may not be supported for all games, such as those with custom sound hardware (e.g MMC5, VRC6, etc.).",
 
2261
      "In cases where stereo output is not available, FakeNES will temporarily revert to mono output.",
 
2262
      "This is a harmless, accuracy-related procedure and should not be considered a bug.",
 
2263
      "&OK", NULL, 0, 0);
 
2264
      
 
2265
   message_local ("Audio output set to stereo.");
 
2266
 
 
2267
   return (D_O_K);
 
2268
}
 
2269
 
 
2270
static int audio_output_menu_mixing_stereo_inverted (void)
 
2271
{
 
2272
   apu_options.stereo = TRUE;
 
2273
   apu_options.swap_channels = TRUE;
 
2274
 
 
2275
   cycle_audio ();
 
2276
   update_menus ();
 
2277
   
 
2278
   message_local ("Audio output set to reverse stereo.");
 
2279
 
 
2280
   return (D_O_K);
 
2281
}
 
2282
 
 
2283
#define AUDIO_OUTPUT_BUFFER_MENU_HANDLER(length_ms) \
 
2284
   static int audio_output_buffer_menu_##length_ms##ms (void) \
 
2285
   { \
 
2286
      audio_options.buffer_length_ms_hint = length_ms; \
 
2287
      cycle_audio (); \
 
2288
      update_menus (); \
 
2289
      message_local ("Audio buffer size set to %dms.", length_ms); \
 
2290
      return (D_O_K); \
 
2291
   }
 
2292
                        
 
2293
AUDIO_OUTPUT_BUFFER_MENU_HANDLER(30)
 
2294
AUDIO_OUTPUT_BUFFER_MENU_HANDLER(50)
 
2295
AUDIO_OUTPUT_BUFFER_MENU_HANDLER(75)
 
2296
AUDIO_OUTPUT_BUFFER_MENU_HANDLER(100)
 
2297
AUDIO_OUTPUT_BUFFER_MENU_HANDLER(125)
 
2298
AUDIO_OUTPUT_BUFFER_MENU_HANDLER(150)
 
2299
AUDIO_OUTPUT_BUFFER_MENU_HANDLER(175)
 
2300
AUDIO_OUTPUT_BUFFER_MENU_HANDLER(200)
 
2301
 
 
2302
#undef AUDIO_OUTPUT_BUFFER_MENU_HANDLER
 
2303
 
 
2304
static int audio_output_buffer_menu_automatic (void)
 
2305
{
 
2306
   audio_options.buffer_length_ms_hint = -1;
 
2307
 
 
2308
   cycle_audio ();
 
2309
   update_menus ();
 
2310
 
 
2311
   message_local ("Audio buffer size set to automatic.");
 
2312
 
 
2313
   return (D_O_K);
 
2314
}
 
2315
 
 
2316
static int audio_output_buffer_menu_custom (void) 
 
2317
{
 
2318
   int ms = audio_options.buffer_length_ms_hint;
 
2319
   if (get_integer_input ("Custom", &ms, "ms"))
 
2320
   {
 
2321
      audio_options.buffer_length_ms_hint = ms;
 
2322
 
 
2323
      cycle_audio ();
 
2324
      update_menus ();
 
2325
 
 
2326
      message_local ("Audio buffer size set to %dms.", ms);
 
2327
   }
 
2328
 
 
2329
   return (D_O_K);
 
2330
}
 
2331
 
 
2332
static int audio_menu_volume_increase (void)
 
2333
{
 
2334
   apu_options.volume += 0.25;
 
2335
   if (apu_options.volume > 4.0)
 
2336
      apu_options.volume = 4.0;
 
2337
 
 
2338
   update_menus ();
 
2339
 
 
2340
   message_local ("Audio master volume level increased to %d%%.",
 
2341
      (int)ROUND(apu_options.volume * 100.0));
 
2342
 
 
2343
   return (D_O_K);
 
2344
}
 
2345
 
 
2346
static int audio_menu_volume_decrease (void)
 
2347
{
 
2348
   apu_options.volume -= 0.25;
 
2349
   if (apu_options.volume < 0)
 
2350
      apu_options.volume = 0;
 
2351
 
 
2352
   update_menus ();
 
2353
 
 
2354
   message_local ("Audio master volume level decreased to %d%%.",
 
2355
      (int)ROUND(apu_options.volume * 100.0));
 
2356
 
 
2357
   return (D_O_K);
 
2358
}
 
2359
 
 
2360
static int audio_menu_volume_custom (void)
 
2361
{
 
2362
   int percent;
 
2363
 
 
2364
   percent = ROUND(apu_options.volume * 100.0);
 
2365
 
 
2366
   if (get_integer_input ("Custom", &percent, "percent"))
 
2367
   {
 
2368
      apu_options.volume = (percent / 100.0);
 
2369
      update_menus ();
 
2370
   
 
2371
      message_local ("Audio master volume level set to %d%%.", percent);
 
2372
   }
 
2373
 
 
2374
   return (D_O_K);
 
2375
}
 
2376
 
 
2377
static int audio_menu_volume_reset (void)
 
2378
{
 
2379
   apu_options.volume = 1.0;
 
2380
   update_menus ();
 
2381
 
 
2382
   message_local ("Audio master volume level reset to %d%%.",
 
2383
      (int)ROUND(apu_options.volume * 100.0));
 
2384
 
 
2385
   return (D_O_K);
 
2386
}
 
2387
 
 
2388
static int audio_menu_volume_auto_normalize (void)
 
2389
{
 
2390
   apu_options.normalize = !apu_options.normalize;
 
2391
   update_menus ();
 
2392
 
 
2393
   apu_update ();
 
2394
 
 
2395
   message_local ("Audio volume level normalization %s.",
 
2396
      get_enabled_text (apu_options.normalize)); 
 
2397
 
 
2398
   return (D_O_K);
 
2399
}
 
2400
 
 
2401
static int audio_record_menu_start (void)
 
2402
{
 
2403
   int index;
 
2404
 
 
2405
   for (index = 0; index < 999; index++)
 
2406
   {
 
2407
      USTRING filename;
 
2408
 
 
2409
      uszprintf (filename, sizeof (filename), "%s_%03d.wav", get_filename
 
2410
         (global_rom.filename), index);
 
2411
 
 
2412
      /* Merge it with our save path. */
 
2413
      get_save_path (filename, sizeof (filename));
 
2414
 
 
2415
      if (exists (filename))
 
2416
         continue;
 
2417
 
 
2418
      if (audio_open_wav (filename) == 0)
 
2419
      {
 
2420
         DISABLE_MENU_ITEM(audio_record_menu_start);
 
2421
         ENABLE_MENU_ITEM(audio_record_menu_stop);
 
2422
      }
 
2423
   
 
2424
      message_local ("Audio WAV recording started to %s.", filename);
 
2425
 
 
2426
      return (D_O_K);
 
2427
   }
 
2428
   
 
2429
   gui_message (GUI_ERROR_COLOR, "Couldn't find a suitable image "
 
2430
      "filename.");
 
2431
 
 
2432
   return (D_O_K);
 
2433
}
 
2434
 
 
2435
static int audio_record_menu_stop (void)
 
2436
{
 
2437
   audio_close_wav ();
 
2438
 
 
2439
   ENABLE_MENU_ITEM(audio_record_menu_start);
 
2440
   DISABLE_MENU_ITEM(audio_record_menu_stop);
 
2441
 
 
2442
   message_local ("Audio WAV recording stopped.");
 
2443
 
 
2444
   return (D_O_K);
 
2445
}
 
2446
 
 
2447
static int video_menu_fullscreen (void)
 
2448
{
 
2449
   video_force_fullscreen = !video_force_fullscreen;
 
2450
   video_reinit ();
 
2451
 
 
2452
   gui_needs_restart = TRUE;
 
2453
   return (D_CLOSE);
 
2454
}
 
2455
 
 
2456
static int video_menu_page_buffer (void)
 
2457
{
 
2458
   video_enable_page_buffer = !video_enable_page_buffer;
 
2459
   update_menus ();
 
2460
 
 
2461
   video_reinit ();
 
2462
 
 
2463
   cycle_video ();
 
2464
 
 
2465
   message_local ("Page buffering %s.", get_enabled_text
 
2466
      (video_enable_page_buffer));
 
2467
 
 
2468
   return (D_O_K);
 
2469
}
 
2470
 
 
2471
static int video_menu_vsync (void)
 
2472
{
 
2473
   video_enable_vsync = !video_enable_vsync;
 
2474
   update_menus ();
 
2475
 
 
2476
   message_local ("VSync %s.", get_enabled_text (video_enable_vsync));
 
2477
 
 
2478
   return (D_O_K);
 
2479
}
 
2480
 
 
2481
static int video_menu_color (void)
 
2482
{
 
2483
   DIALOG *dialog;
 
2484
   DIALOG *objhue, *objsat, *objbright, *objcon, *objgamma;
 
2485
   int result;
 
2486
 
 
2487
   /* Get dialog. */
 
2488
   dialog = video_color_dialog;
 
2489
   
 
2490
   /* Get slider objects. */
 
2491
   
 
2492
   objhue    = &dialog[VIDEO_COLOR_DIALOG_HUE];
 
2493
   objsat    = &dialog[VIDEO_COLOR_DIALOG_SATURATION];
 
2494
   objbright = &dialog[VIDEO_COLOR_DIALOG_BRIGHTNESS];
 
2495
   objcon    = &dialog[VIDEO_COLOR_DIALOG_CONTRAST];
 
2496
   objgamma  = &dialog[VIDEO_COLOR_DIALOG_GAMMA];
 
2497
   
 
2498
   /* Load configuration. */
 
2499
   
 
2500
   objhue->d2    = (get_config_int ("video", "hue",        0) + 100);
 
2501
   objsat->d2    = (get_config_int ("video", "saturation", 0) + 100);
 
2502
   objbright->d2 = (get_config_int ("video", "brightness", 0) + 100);
 
2503
   objcon->d2    = (get_config_int ("video", "contrast",   0) + 100);
 
2504
   objgamma->d2  = (get_config_int ("video", "gamma",      0) + 100);
 
2505
   
 
2506
   /* Show dialog. */
 
2507
   result = show_dialog (dialog, -1);
 
2508
 
 
2509
   if (result == VIDEO_COLOR_DIALOG_SAVE_BUTTON)
 
2510
   {
 
2511
      /* Save configuration. */
 
2512
   
 
2513
      set_config_int ("video", "hue",        (objhue->d2    - 100));
 
2514
      set_config_int ("video", "saturation", (objsat->d2    - 100));
 
2515
      set_config_int ("video", "brightness", (objbright->d2 - 100));
 
2516
      set_config_int ("video", "contrast",   (objcon->d2    - 100));
 
2517
      set_config_int ("video", "gamma",      (objgamma->d2  - 100));
 
2518
   
 
2519
      /* Reinitialize palette to the load new configuration. */
 
2520
      video_set_palette (NULL);
 
2521
   
 
2522
      /* Display changes. */
 
2523
      cycle_video ();
 
2524
   }
 
2525
   else if (result == VIDEO_COLOR_DIALOG_RESET_BUTTON)
 
2526
   {
 
2527
      /* Save defaults. */
 
2528
   
 
2529
      set_config_int ("video", "hue",        0);
 
2530
      set_config_int ("video", "saturation", 0);
 
2531
      set_config_int ("video", "brightness", 0);
 
2532
      set_config_int ("video", "contrast",   0);
 
2533
      set_config_int ("video", "gamma",      0);
 
2534
   
 
2535
      /* Reinitialize palette to the load new configuration. */
 
2536
      video_set_palette (NULL);
 
2537
   
 
2538
      /* Display changes. */
 
2539
      cycle_video ();
 
2540
   }
 
2541
 
 
2542
   return (D_O_K);
 
2543
}
 
2544
 
 
2545
#define DRIVER_MENU_HANDLER(driver, id)   \
 
2546
   static int video_driver_menu_##driver (void) \
 
2547
   {  \
 
2548
      video_set_driver (id);  \
 
2549
      gui_needs_restart = TRUE;  \
 
2550
      return (D_CLOSE); \
 
2551
   }
 
2552
 
 
2553
#define DRIVER_MENU_HANDLER_EX(system, driver, id) \
 
2554
   static int video_driver_##system##_menu_##driver (void)   \
 
2555
   {  \
 
2556
      video_set_driver (id);  \
 
2557
      gui_needs_restart = TRUE;  \
 
2558
      return (D_CLOSE); \
 
2559
   }
 
2560
 
 
2561
DRIVER_MENU_HANDLER(automatic, GFX_AUTODETECT)
 
2562
 
 
2563
#ifdef ALLEGRO_DOS
 
2564
 
 
2565
DRIVER_MENU_HANDLER_EX(dos, vga,           GFX_VGA)
 
2566
DRIVER_MENU_HANDLER_EX(dos, vga_mode_x,    GFX_MODEX)
 
2567
DRIVER_MENU_HANDLER_EX(dos, vesa,          GFX_VESA1)
 
2568
DRIVER_MENU_HANDLER_EX(dos, vesa_2_banked, GFX_VESA2B)
 
2569
DRIVER_MENU_HANDLER_EX(dos, vesa_2_linear, GFX_VESA2L)
 
2570
DRIVER_MENU_HANDLER_EX(dos, vesa_3,        GFX_VESA3)
 
2571
DRIVER_MENU_HANDLER_EX(dos, vesa_vbe_af,   GFX_VBEAF)
 
2572
 
 
2573
#endif   /* ALLEGRO_DOS */
 
2574
 
 
2575
#ifdef ALLEGRO_WINDOWS
 
2576
 
 
2577
DRIVER_MENU_HANDLER_EX(windows, directx,         GFX_DIRECTX)
 
2578
DRIVER_MENU_HANDLER_EX(windows, directx_window,  GFX_DIRECTX_WIN)
 
2579
DRIVER_MENU_HANDLER_EX(windows, directx_overlay, GFX_DIRECTX_OVL)
 
2580
DRIVER_MENU_HANDLER_EX(windows, gdi,             GFX_GDI)
 
2581
                   
 
2582
#endif   /* ALLEGRO_WINDOWS */
 
2583
 
 
2584
#ifdef ALLEGRO_LINUX
 
2585
 
 
2586
DRIVER_MENU_HANDLER_EX(linux, vga,         GFX_VGA)
 
2587
DRIVER_MENU_HANDLER_EX(linux, vga_mode_x,  GFX_MODEX)
 
2588
DRIVER_MENU_HANDLER_EX(linux, vesa_vbe_af, GFX_VBEAF)
 
2589
#ifdef GFX_FBCON   
 
2590
DRIVER_MENU_HANDLER_EX(linux, framebuffer, GFX_FBCON)
 
2591
#else              
 
2592
DRIVER_MENU_HANDLER_EX(linux, framebuffer, NULL)
 
2593
#endif
 
2594
#ifdef GFX_SVGALIB
 
2595
DRIVER_MENU_HANDLER_EX(linux, svgalib,     GFX_SVGALIB)
 
2596
#else
 
2597
DRIVER_MENU_HANDLER_EX(linux, svgalib,     NULL)
 
2598
#endif
 
2599
 
 
2600
#endif   /* ALLEGRO_LINUX */
 
2601
 
 
2602
#ifdef ALLEGRO_UNIX
 
2603
 
 
2604
DRIVER_MENU_HANDLER_EX(unix, x_windows,      GFX_XWINDOWS)
 
2605
DRIVER_MENU_HANDLER_EX(unix, x_windows_full, GFX_XWINDOWS_FULLSCREEN)
 
2606
DRIVER_MENU_HANDLER_EX(unix, x_dga,          GFX_XDGA)
 
2607
DRIVER_MENU_HANDLER_EX(unix, x_dga_full,     GFX_XDGA_FULLSCREEN)
 
2608
DRIVER_MENU_HANDLER_EX(unix, x_dga_2,        GFX_XDGA2)
 
2609
 
 
2610
#endif   /* ALLEGRO_UNIX */
 
2611
 
 
2612
#ifdef USE_ALLEGROGL
 
2613
 
 
2614
DRIVER_MENU_HANDLER(opengl,      GFX_OPENGL)
 
2615
DRIVER_MENU_HANDLER(opengl_full, GFX_OPENGL_FULLSCREEN)
 
2616
DRIVER_MENU_HANDLER(opengl_win,  GFX_OPENGL_WINDOWED)
 
2617
 
 
2618
#endif   /* USE_ALLEGROGL */
 
2619
 
 
2620
#undef DRIVER_MENU_HANDLER
 
2621
#undef DRIVER_MENU_HANDLER_EX
 
2622
 
 
2623
#define RESOLUTION_MENU_HANDLER(width, height)  \
 
2624
   static int video_resolution_menu_##width##_##height (void)   \
 
2625
   {  \
 
2626
      video_set_resolution (width, height);  \
 
2627
      gui_needs_restart = TRUE;  \
 
2628
      return (D_CLOSE); \
 
2629
   }
 
2630
 
 
2631
#define RESOLUTION_MENU_HANDLER_EX(type, width, height)  \
 
2632
   static int video_resolution_##type##_menu_##width##_##height (void)   \
 
2633
   {  \
 
2634
      video_set_resolution (width, height);  \
 
2635
      gui_needs_restart = TRUE;  \
 
2636
      return (D_CLOSE); \
 
2637
   }
 
2638
 
 
2639
RESOLUTION_MENU_HANDLER_EX(proportionate, 256,  224)
 
2640
RESOLUTION_MENU_HANDLER_EX(proportionate, 256,  240)
 
2641
RESOLUTION_MENU_HANDLER_EX(proportionate, 512,  448)
 
2642
RESOLUTION_MENU_HANDLER_EX(proportionate, 512,  480)
 
2643
RESOLUTION_MENU_HANDLER_EX(proportionate, 768,  672)
 
2644
RESOLUTION_MENU_HANDLER_EX(proportionate, 768,  720)
 
2645
RESOLUTION_MENU_HANDLER_EX(proportionate, 1024, 896)
 
2646
RESOLUTION_MENU_HANDLER_EX(proportionate, 1024, 960)
 
2647
RESOLUTION_MENU_HANDLER_EX(proportionate, 1280, 1120)
 
2648
RESOLUTION_MENU_HANDLER_EX(proportionate, 1280, 1200)
 
2649
 
 
2650
RESOLUTION_MENU_HANDLER(320,  240)
 
2651
RESOLUTION_MENU_HANDLER(400,  300)
 
2652
RESOLUTION_MENU_HANDLER(640,  480)
 
2653
RESOLUTION_MENU_HANDLER(800,  600)
 
2654
RESOLUTION_MENU_HANDLER(1024, 768)
 
2655
RESOLUTION_MENU_HANDLER(1152, 864)
 
2656
RESOLUTION_MENU_HANDLER(1280, 960)
 
2657
RESOLUTION_MENU_HANDLER(1280, 1024)
 
2658
RESOLUTION_MENU_HANDLER(1600, 1200)
 
2659
 
 
2660
#undef RESOLUTION_MENU_HANDLER
 
2661
#undef RESOLUTION_MENU_HANDLER_EX
 
2662
 
 
2663
static int video_resolution_menu_custom (void)
 
2664
{
 
2665
   int width, height;
 
2666
 
 
2667
   width  = SCREEN_W;
 
2668
   height = SCREEN_H;
 
2669
 
 
2670
   if (get_resolution_input ("Custom", &width, &height))
 
2671
   {
 
2672
      video_set_resolution (width, height);
 
2673
 
 
2674
      gui_needs_restart = TRUE;
 
2675
      return (D_CLOSE);
 
2676
   }
 
2677
      
 
2678
   return (D_O_K);
 
2679
}
 
2680
 
 
2681
static int video_color_depth_menu_paletted_8_bit (void)
 
2682
{
 
2683
   video_set_color_depth (8);
 
2684
 
 
2685
   gui_needs_restart = TRUE;
 
2686
   return (D_CLOSE);
 
2687
}
 
2688
 
 
2689
static int video_color_depth_menu_true_color_15_bit (void)
 
2690
{
 
2691
   video_set_color_depth (15);
 
2692
 
 
2693
   gui_needs_restart = TRUE;
 
2694
   return (D_CLOSE);
 
2695
}
 
2696
 
 
2697
static int video_color_depth_menu_true_color_16_bit (void)
 
2698
{
 
2699
   video_set_color_depth (16);
 
2700
 
 
2701
   gui_needs_restart = TRUE;
 
2702
   return (D_CLOSE);
 
2703
}
 
2704
 
 
2705
static int video_color_depth_menu_true_color_24_bit (void)
 
2706
{
 
2707
   video_set_color_depth (24);
 
2708
 
 
2709
   gui_needs_restart = TRUE;
 
2710
   return (D_CLOSE);
 
2711
}
 
2712
 
 
2713
static int video_color_depth_menu_true_color_32_bit (void)
 
2714
{
 
2715
   video_set_color_depth (32);
 
2716
 
 
2717
   gui_needs_restart = TRUE;
 
2718
   return (D_CLOSE);
 
2719
}
 
2720
 
 
2721
static int video_buffer_menu_match_resolution (void)
 
2722
{
 
2723
   video_buffer_width  =
 
2724
   video_buffer_height = -1;
 
2725
   video_init_buffer ();
 
2726
 
 
2727
   update_menus ();
 
2728
   cycle_video ();
 
2729
 
 
2730
   return (D_O_K);
 
2731
}
 
2732
 
 
2733
#define BUFFER_MENU_HANDLER(width, height)  \
 
2734
   static int video_buffer_menu_##width##_##height (void)   \
 
2735
   {  \
 
2736
      video_buffer_width = width;   \
 
2737
      video_buffer_height = height; \
 
2738
      video_init_buffer ();   \
 
2739
      update_menus ();  \
 
2740
      cycle_video ();   \
 
2741
      return (D_O_K);   \
 
2742
   }
 
2743
 
 
2744
BUFFER_MENU_HANDLER(256, 240)
 
2745
BUFFER_MENU_HANDLER(320, 240)
 
2746
BUFFER_MENU_HANDLER(512, 480)
 
2747
BUFFER_MENU_HANDLER(640, 480)
 
2748
BUFFER_MENU_HANDLER(256, 256)
 
2749
BUFFER_MENU_HANDLER(512, 512)
 
2750
 
 
2751
#undef BUFFER_MENU_HANDLER
 
2752
 
 
2753
static int video_buffer_menu_custom (void)
 
2754
{
 
2755
   int width, height;
 
2756
 
 
2757
   width  = video_buffer_width;
 
2758
   height = video_buffer_height;
 
2759
 
 
2760
   if (get_resolution_input ("Custom", &width, &height))
 
2761
   {
 
2762
      video_buffer_width = width;
 
2763
      video_buffer_height = height;
 
2764
      video_init_buffer ();
 
2765
 
 
2766
      update_menus ();
 
2767
 
 
2768
      cycle_video ();
 
2769
   }
 
2770
      
 
2771
   return (D_O_K);
 
2772
}
 
2773
 
 
2774
#define BLITTER_MENU_HANDLER(name, caption, id) \
 
2775
   static int video_blitter_menu_##name (void)   \
 
2776
   {  \
 
2777
      video_set_blitter (id); \
 
2778
      update_menus ();  \
 
2779
      cycle_video ();   \
 
2780
      message_local ("Video blitter set to %s.", caption);  \
 
2781
      return (D_O_K);   \
 
2782
   }
 
2783
 
 
2784
BLITTER_MENU_HANDLER(automatic,          "automatic",            VIDEO_BLITTER_AUTOMATIC)
 
2785
BLITTER_MENU_HANDLER(normal,             "normal",               VIDEO_BLITTER_NORMAL)
 
2786
BLITTER_MENU_HANDLER(des,                "des engine",           VIDEO_BLITTER_DES)
 
2787
BLITTER_MENU_HANDLER(interpolated_2x,    "interpolated (2x)",    VIDEO_BLITTER_INTERPOLATED_2X)
 
2788
BLITTER_MENU_HANDLER(interpolated_2x_hq, "interpolated (2x HQ)", VIDEO_BLITTER_INTERPOLATED_2X_HQ)
 
2789
BLITTER_MENU_HANDLER(2xscl,              "2xSCL engine",         VIDEO_BLITTER_2XSCL)
 
2790
BLITTER_MENU_HANDLER(desii,              "des 2 engine",         VIDEO_BLITTER_DESII)
 
2791
BLITTER_MENU_HANDLER(super_2xscl,        "super 2xSCL engine",   VIDEO_BLITTER_SUPER_2XSCL)
 
2792
BLITTER_MENU_HANDLER(ultra_2xscl,        "ultra 2xSCL engine",   VIDEO_BLITTER_ULTRA_2XSCL)
 
2793
BLITTER_MENU_HANDLER(hq2x,               "hq2x filter",          VIDEO_BLITTER_HQ2X)
 
2794
BLITTER_MENU_HANDLER(ntsc,               "ntsc engine",          VIDEO_BLITTER_NTSC)
 
2795
BLITTER_MENU_HANDLER(interpolated_3x,    "interpolated (3x)",    VIDEO_BLITTER_INTERPOLATED_3X)
 
2796
BLITTER_MENU_HANDLER(hq3x,               "hq3x filter",          VIDEO_BLITTER_HQ3X)
 
2797
BLITTER_MENU_HANDLER(hq4x,               "hq4x filter",          VIDEO_BLITTER_HQ4X)
 
2798
BLITTER_MENU_HANDLER(stretched,          "stretched",            VIDEO_BLITTER_STRETCHED)
 
2799
 
 
2800
#undef BLITTER_MENU_HANDLER
 
2801
 
 
2802
static int video_blitter_menu_configure (void)
 
2803
{
 
2804
   switch (video_get_blitter ())
 
2805
   {
 
2806
      case VIDEO_BLITTER_NTSC:
 
2807
      {
 
2808
         DIALOG *dialog;
 
2809
         DIALOG *objhue, *objsat, *objhuew, *objbright, *objcon, *objgamma,
 
2810
            *objsharp, *objres, *objart, *objbleed, *objfring, *objmerge,
 
2811
            *objdbl[3], *objinterp;
 
2812
         int merge_fields, doubling, interpolated;
 
2813
         int result;
 
2814
         int index;
 
2815
 
 
2816
         /* Create dialog. */
 
2817
 
 
2818
         dialog = create_dialog (ntsc_config_dialog_base, "ntsc");
 
2819
         if (!dialog)
 
2820
            break;
 
2821
 
 
2822
         /* Get slider objects. */
 
2823
 
 
2824
         objhue     = &dialog[NTSC_CONFIG_DIALOG_HUE];
 
2825
         objhuew    = &dialog[NTSC_CONFIG_DIALOG_HUE_WARPING];
 
2826
         objsat     = &dialog[NTSC_CONFIG_DIALOG_SATURATION];
 
2827
         objbright  = &dialog[NTSC_CONFIG_DIALOG_BRIGHTNESS];
 
2828
         objcon     = &dialog[NTSC_CONFIG_DIALOG_CONTRAST];
 
2829
         objgamma   = &dialog[NTSC_CONFIG_DIALOG_GAMMA];
 
2830
         objsharp   = &dialog[NTSC_CONFIG_DIALOG_SHARPNESS];
 
2831
         objres     = &dialog[NTSC_CONFIG_DIALOG_RESOLUTION];
 
2832
         objart     = &dialog[NTSC_CONFIG_DIALOG_ARTIFACTS];
 
2833
         objbleed   = &dialog[NTSC_CONFIG_DIALOG_COLOR_BLEED];
 
2834
         objfring   = &dialog[NTSC_CONFIG_DIALOG_COLOR_FRINGING];
 
2835
         objmerge   = &dialog[NTSC_CONFIG_DIALOG_REDUCE_FLICKER];
 
2836
         objdbl[0]  = &dialog[NTSC_CONFIG_DIALOG_SCANLINE_DOUBLING_NORMAL];
 
2837
         objdbl[1]  = &dialog[NTSC_CONFIG_DIALOG_SCANLINE_DOUBLING_BRIGHTEN];
 
2838
         objdbl[2]  = &dialog[NTSC_CONFIG_DIALOG_SCANLINE_DOUBLING_DARKEN];
 
2839
         objinterp  = &dialog[NTSC_CONFIG_DIALOG_INTERPOLATED];
 
2840
 
 
2841
         /* Load configuration. */
 
2842
 
 
2843
         objhue->d2    = (get_config_int ("ntsc", "hue",         0) + 100);
 
2844
         objhuew->d2   = (get_config_int ("ntsc", "hue_warping", 0) + 100);
 
2845
         objsat->d2    = (get_config_int ("ntsc", "saturation",  20) + 100);
 
2846
         objbright->d2 = (get_config_int ("ntsc", "brightness",  10) + 100);
 
2847
         objcon->d2    = (get_config_int ("ntsc", "contrast",    0) + 100);
 
2848
         objgamma->d2  = (get_config_int ("ntsc", "gamma",       0) + 100);
 
2849
         objsharp->d2  = (get_config_int ("ntsc", "sharpness",   40) + 100);
 
2850
         objres->d2    = (get_config_int ("ntsc", "resolution",  30) + 100);
 
2851
         objart->d2    = (get_config_int ("ntsc", "artifacts",   0) + 100);
 
2852
         objbleed->d2  = (get_config_int ("ntsc", "bleed",       0) + 100);
 
2853
         objfring->d2  = (get_config_int ("ntsc", "fringing",    0) + 100);
 
2854
 
 
2855
         merge_fields = get_config_int ("ntsc", "merge_fields", 1); /* Default On */
 
2856
         if (merge_fields)
 
2857
            objmerge->flags |= D_SELECTED;
 
2858
         
 
2859
         doubling = fix (get_config_int ("ntsc", "doubling", 2), 0, 2); /* Default Darken */
 
2860
 
 
2861
         objdbl[doubling]->flags |= D_SELECTED;
 
2862
 
 
2863
         interpolated = get_config_int ("ntsc", "interpolated", 1);  /* Default On */
 
2864
         if (interpolated)
 
2865
            objinterp->flags |= D_SELECTED;
 
2866
 
 
2867
         /* Show dialog. */
 
2868
         result = show_dialog (dialog, -1);
 
2869
 
 
2870
         /* Destroy dialog. */
 
2871
         unload_dialog (dialog);
 
2872
 
 
2873
         if (result == NTSC_CONFIG_DIALOG_SAVE_BUTTON)
 
2874
         {
 
2875
            /* Save configuration. */
 
2876
 
 
2877
            set_config_int ("ntsc", "hue",         (objhue->d2    - 100));
 
2878
            set_config_int ("ntsc", "hue_warping", (objhuew->d2   - 100));
 
2879
            set_config_int ("ntsc", "saturation",  (objsat->d2    - 100));
 
2880
            set_config_int ("ntsc", "brightness",  (objbright->d2 - 100));
 
2881
            set_config_int ("ntsc", "contrast",    (objcon->d2    - 100));
 
2882
            set_config_int ("ntsc", "gamma",       (objgamma->d2  - 100));
 
2883
            set_config_int ("ntsc", "sharpness",   (objsharp->d2  - 100));
 
2884
            set_config_int ("ntsc", "resolution",  (objres->d2    - 100));
 
2885
            set_config_int ("ntsc", "artifacts",   (objart->d2    - 100));
 
2886
            set_config_int ("ntsc", "bleed",       (objbleed->d2  - 100));
 
2887
            set_config_int ("ntsc", "fringing",    (objfring->d2  - 100));
 
2888
 
 
2889
            merge_fields = ((objmerge->flags & D_SELECTED) ? 1 : 0);
 
2890
 
 
2891
            set_config_int ("ntsc", "merge_fields", merge_fields);
 
2892
 
 
2893
            for (index = 0; index < 3; index++)
 
2894
            {
 
2895
               if (objdbl[index]->flags & D_SELECTED)
 
2896
                  doubling = index;
 
2897
            }
 
2898
 
 
2899
            set_config_int ("ntsc", "doubling", doubling);
 
2900
 
 
2901
            interpolated = ((objinterp->flags & D_SELECTED) ? 1 : 0);
 
2902
 
 
2903
            set_config_int ("ntsc", "interpolated", interpolated);
 
2904
 
 
2905
            /* Reinitialize blitter to the load new configuration. */
 
2906
            video_blitter_reinit ();
 
2907
 
 
2908
            /* Display changes. */
 
2909
            cycle_video ();
 
2910
         }
 
2911
         else if (result == NTSC_CONFIG_DIALOG_SET_BUTTON)
 
2912
         {
 
2913
            DIALOG *objpres[5];
 
2914
            int preset = -1;
 
2915
 
 
2916
            /* Set a preset. */
 
2917
 
 
2918
            objpres[0] = &dialog[NTSC_CONFIG_DIALOG_PRESETS_DEFAULT];
 
2919
            objpres[1] = &dialog[NTSC_CONFIG_DIALOG_PRESETS_COMPOSITE];
 
2920
            objpres[2] = &dialog[NTSC_CONFIG_DIALOG_PRESETS_SVIDEO];
 
2921
            objpres[3] = &dialog[NTSC_CONFIG_DIALOG_PRESETS_RGB];
 
2922
            objpres[4] = &dialog[NTSC_CONFIG_DIALOG_PRESETS_MONOCHROME];
 
2923
 
 
2924
            for (index = 0; index < 5; index++)
 
2925
            {
 
2926
               if (objpres[index]->flags & D_SELECTED)
 
2927
                  preset = index;
 
2928
            }
 
2929
 
 
2930
            set_config_int ("ntsc", "preset", preset);
 
2931
 
 
2932
            /* Reinitialize blitter to the load new configuration. */
 
2933
            video_blitter_reinit ();
 
2934
 
 
2935
            /* Display changes. */
 
2936
            cycle_video ();
 
2937
         }
 
2938
 
 
2939
         break;
 
2940
      }
 
2941
 
 
2942
      case VIDEO_BLITTER_STRETCHED:
 
2943
      {
 
2944
         int width, height;
 
2945
 
 
2946
         /* Load configuration. */
 
2947
 
 
2948
         width  = get_config_int ("video", "stretch_width",  512);
 
2949
         height = get_config_int ("video", "stretch_height", 480);
 
2950
 
 
2951
         if (get_resolution_input ("Stretched", &width, &height))
 
2952
         {
 
2953
            /* Save configuration. */
 
2954
 
 
2955
            set_config_int ("video", "stretch_width",  width);
 
2956
            set_config_int ("video", "stretch_height", height);
 
2957
 
 
2958
            /* Reinitialize blitter to the load new configuration. */
 
2959
            video_blitter_reinit ();
 
2960
 
 
2961
            /* Display changes. */
 
2962
            cycle_video ();
 
2963
         }
 
2964
 
 
2965
         break;
 
2966
      }
 
2967
 
 
2968
      default:
 
2969
      {
 
2970
         gui_alert ("Error", "There are no configuration parameters "
 
2971
            "available for the selected blitter.", NULL, NULL, "&OK", NULL,
 
2972
               'o', 0);
 
2973
 
 
2974
         break;
 
2975
      }
 
2976
   }
 
2977
 
 
2978
   return (D_O_K);
 
2979
}
 
2980
 
 
2981
static int video_filters_menu_scanlines_25_percent (void)
 
2982
{
 
2983
   LIST filters;
 
2984
 
 
2985
   filters = video_get_filter_list ();
 
2986
   LIST_TOGGLE(filters, VIDEO_FILTER_SCANLINES_LOW);
 
2987
   video_set_filter_list (filters);
 
2988
 
 
2989
   update_menus ();
 
2990
 
 
2991
   cycle_video ();
 
2992
 
 
2993
   message_local ("Scanlines video filter %s.", get_enabled_text_ex
 
2994
      ((filters & VIDEO_FILTER_SCANLINES_LOW), "enabled (25%)"));
 
2995
 
 
2996
   return (D_O_K);
 
2997
}
 
2998
 
 
2999
static int video_filters_menu_scanlines_50_percent (void)
 
3000
{
 
3001
   LIST filters;
 
3002
 
 
3003
   filters = video_get_filter_list ();
 
3004
   LIST_TOGGLE(filters, VIDEO_FILTER_SCANLINES_MEDIUM);
 
3005
   video_set_filter_list (filters);
 
3006
 
 
3007
   update_menus ();
 
3008
 
 
3009
   cycle_video ();
 
3010
 
 
3011
   message_local ("Scanlines video filter %s.", get_enabled_text_ex
 
3012
      ((filters & VIDEO_FILTER_SCANLINES_MEDIUM), "enabled (50%)"));
 
3013
 
 
3014
   return (D_O_K);
 
3015
}
 
3016
 
 
3017
static int video_filters_menu_scanlines_100_percent (void)
 
3018
{
 
3019
   LIST filters;
 
3020
 
 
3021
   filters = video_get_filter_list ();
 
3022
   LIST_TOGGLE(filters, VIDEO_FILTER_SCANLINES_HIGH);
 
3023
   video_set_filter_list (filters);
 
3024
 
 
3025
   update_menus ();
 
3026
 
 
3027
   cycle_video ();
 
3028
 
 
3029
   message_local ("Scanlines video filter %s.", get_enabled_text_ex
 
3030
      ((filters & VIDEO_FILTER_SCANLINES_HIGH), "enabled (100%)"));
 
3031
 
 
3032
   return (D_O_K);
 
3033
}
 
3034
 
 
3035
static int video_layers_menu_sprites_a (void)
 
3036
{
 
3037
   ppu_enable_sprite_layer_a = !ppu_enable_sprite_layer_a;
 
3038
   update_menus ();
 
3039
 
 
3040
   message_local ("Video sprites layer A %s.", get_enabled_text
 
3041
      (ppu_enable_sprite_layer_a));
 
3042
 
 
3043
   return (D_O_K);
 
3044
}
 
3045
 
 
3046
static int video_layers_menu_sprites_b (void)
 
3047
{
 
3048
   ppu_enable_sprite_layer_b = !ppu_enable_sprite_layer_b;
 
3049
   update_menus ();
 
3050
 
 
3051
   message_local ("Video sprites layer B %s.", get_enabled_text
 
3052
      (ppu_enable_sprite_layer_b));
 
3053
 
 
3054
   return (D_O_K);
 
3055
}
 
3056
 
 
3057
 
 
3058
static int video_layers_menu_background (void)
 
3059
{
 
3060
   ppu_enable_background_layer = !ppu_enable_background_layer;
 
3061
   update_menus ();
 
3062
 
 
3063
   message_local ("Video background layer %s.", get_enabled_text
 
3064
      (ppu_enable_background_layer));
 
3065
 
 
3066
   return (D_O_K);
 
3067
}
 
3068
 
 
3069
static int video_layers_menu_hide_horizontal_scrolling (void)
 
3070
{
 
3071
   LIST clipping = video_edge_clipping;
 
3072
 
 
3073
   if (clipping & VIDEO_EDGE_CLIPPING_HORIZONTAL)
 
3074
      clipping &= ~VIDEO_EDGE_CLIPPING_HORIZONTAL;
 
3075
   else
 
3076
      clipping |= VIDEO_EDGE_CLIPPING_HORIZONTAL;
 
3077
 
 
3078
   video_edge_clipping = clipping;
 
3079
 
 
3080
   update_menus ();
 
3081
 
 
3082
   message_local ("Video horizontal edge clipping %s.", get_enabled_text
 
3083
      (video_edge_clipping & VIDEO_EDGE_CLIPPING_HORIZONTAL));
 
3084
 
 
3085
   return (D_O_K);
 
3086
}
 
3087
 
 
3088
static int video_layers_menu_hide_vertical_scrolling (void)
 
3089
{
 
3090
   LIST clipping = video_edge_clipping;
 
3091
 
 
3092
   if (clipping & VIDEO_EDGE_CLIPPING_VERTICAL)
 
3093
      clipping &= ~VIDEO_EDGE_CLIPPING_VERTICAL;
 
3094
   else
 
3095
      clipping |= VIDEO_EDGE_CLIPPING_VERTICAL;
 
3096
 
 
3097
   video_edge_clipping = clipping;
 
3098
 
 
3099
   update_menus ();
 
3100
 
 
3101
   message_local ("Video vertical edge clipping %s.", get_enabled_text
 
3102
      (video_edge_clipping & VIDEO_EDGE_CLIPPING_VERTICAL));
 
3103
 
 
3104
   return (D_O_K);
 
3105
}
 
3106
 
 
3107
static int video_layers_menu_flip_mirroring (void)
 
3108
{
 
3109
   ppu_invert_mirroring ();
 
3110
 
 
3111
   return (D_CLOSE);
 
3112
}
 
3113
 
 
3114
#define PALETTE_MENU_HANDLER(name, caption, id) \
 
3115
   static int video_palette_menu_##name (void)   \
 
3116
   {  \
 
3117
      video_set_palette (DATA_TO_RGB(id));  \
 
3118
      video_set_palette_id (DATA_INDEX(id)); \
 
3119
      update_menus ();  \
 
3120
      cycle_video ();   \
 
3121
      message_local ("Video palette set to %s.", caption);  \
 
3122
      return (D_O_K);   \
 
3123
   }
 
3124
 
 
3125
#ifdef ALLEGRO_WINDOWS
 
3126
/* Kludge to get around a conflict with Win32 API. */
 
3127
#undef DEFAULT_PALETTE
 
3128
#endif
 
3129
 
 
3130
PALETTE_MENU_HANDLER(ntsc_color,     "NTSC color",     DEFAULT_PALETTE)
 
3131
PALETTE_MENU_HANDLER(ntsc_grayscale, "NTSC grayscale", GRAYSCALE_PALETTE)
 
3132
PALETTE_MENU_HANDLER(gnuboy,         "gnuboy",         GNUBOY_PALETTE)
 
3133
PALETTE_MENU_HANDLER(nester,         "NESter",         NESTER_PALETTE)
 
3134
PALETTE_MENU_HANDLER(nesticle,       "NESticle",       NESTICLE_PALETTE)
 
3135
PALETTE_MENU_HANDLER(modern_ntsc,    "modern NTSC",    MODERN_NTSC_PALETTE)
 
3136
PALETTE_MENU_HANDLER(modern_pal,     "modern PAL",     MODERN_PAL_PALETTE)
 
3137
PALETTE_MENU_HANDLER(ega_mode_1,     "EGA (mode 1)",   EGA_PALETTE_1)
 
3138
PALETTE_MENU_HANDLER(ega_mode_2,     "EGA (mode 2)",   EGA_PALETTE_2)
 
3139
 
 
3140
#undef PALETTE_MENU_HANDLER
 
3141
 
 
3142
static int video_palette_menu_custom (void)
 
3143
{
 
3144
   PACKFILE *file;
 
3145
   int index;
 
3146
 
 
3147
   file = pack_fopen ("fakenes.pal", "r");
 
3148
 
 
3149
   if (!file)
 
3150
   {
 
3151
      gui_message (GUI_ERROR_COLOR, "Error opening FAKENES.PAL!");
 
3152
 
 
3153
      return (D_O_K);
 
3154
   }
 
3155
 
 
3156
   memset (custom_palette, 0, sizeof (PALETTE));
 
3157
 
 
3158
   for (index = 1; index <= 64; index++)
 
3159
   {
 
3160
      custom_palette[index].r = ROUND((pack_getc (file) / 4.0));
 
3161
      custom_palette[index].g = ROUND((pack_getc (file) / 4.0));
 
3162
      custom_palette[index].b = ROUND((pack_getc (file) / 4.0));
 
3163
   }
 
3164
 
 
3165
   pack_fclose (file);
 
3166
 
 
3167
   video_set_palette (((RGB *)custom_palette));
 
3168
   video_set_palette_id (-1);
 
3169
 
 
3170
   update_menus ();
 
3171
 
 
3172
   cycle_video ();
 
3173
 
 
3174
   message_local ("Video palette set to custom.");
 
3175
    
 
3176
   return (D_O_K);
 
3177
}
 
3178
 
 
3179
static int input_menu_configure (void)
 
3180
{
 
3181
   BOOL allow_conflicts, toggled_auto, merge_players;
 
3182
   REAL turbo_rate;
 
3183
   DIALOG *dialog;
 
3184
   DIALOG *objconf, *objauto, *objmerge, *objturbo;
 
3185
 
 
3186
   /* Load configuration. */
 
3187
 
 
3188
   allow_conflicts = get_config_int   ("input", "allow_conflicts", FALSE);
 
3189
   toggled_auto    = get_config_int   ("input", "toggled_auto",    FALSE);
 
3190
   merge_players   = get_config_int   ("input", "merge_players",   FALSE);
 
3191
   turbo_rate      = get_config_float ("input", "turbo_rate",      0.5);
 
3192
 
 
3193
   /* Get dialog. */
 
3194
 
 
3195
   dialog = input_configure_dialog;
 
3196
 
 
3197
   /* Get dialog objects. */
 
3198
 
 
3199
   objconf  = &dialog[INPUT_CONFIGURE_DIALOG_ALLOW_CONFLICTS];
 
3200
   objauto  = &dialog[INPUT_CONFIGURE_DIALOG_TOGGLED_AUTO];
 
3201
   objmerge = &dialog[INPUT_CONFIGURE_DIALOG_MERGE_PLAYERS];
 
3202
   objturbo = &dialog[INPUT_CONFIGURE_DIALOG_TURBO];
 
3203
 
 
3204
   /* Set up objects. */
 
3205
 
 
3206
   if (allow_conflicts)
 
3207
      objconf->flags |= D_SELECTED;
 
3208
 
 
3209
   if (toggled_auto)
 
3210
      objauto->flags |= D_SELECTED;
 
3211
 
 
3212
   if (merge_players)
 
3213
      objmerge->flags |= D_SELECTED;
 
3214
 
 
3215
   objturbo->d2 = ROUND((turbo_rate * 100.0));
 
3216
 
 
3217
   /* Show dialog. */   
 
3218
 
 
3219
   if (show_dialog (dialog, -1) ==
 
3220
      INPUT_CONFIGURE_DIALOG_SAVE_BUTTON)
 
3221
   {
 
3222
      /* Save configuration. */
 
3223
 
 
3224
      allow_conflicts = TRUE_OR_FALSE(objconf->flags  & D_SELECTED);
 
3225
      toggled_auto    = TRUE_OR_FALSE(objauto->flags  & D_SELECTED);
 
3226
      merge_players   = TRUE_OR_FALSE(objmerge->flags & D_SELECTED);
 
3227
 
 
3228
      turbo_rate = (objturbo->d2 / 100.0);
 
3229
 
 
3230
      /* Save existing configuration so we don't lose it. */
 
3231
      input_save_config ();
 
3232
 
 
3233
      /* Make any necessary changes. */
 
3234
 
 
3235
      set_config_int   ("input", "allow_conflicts", allow_conflicts);
 
3236
      set_config_int   ("input", "toggled_auto",    toggled_auto);
 
3237
      set_config_int   ("input", "merge_players",   merge_players);
 
3238
      set_config_float ("input", "turbo_rate",      turbo_rate);
 
3239
 
 
3240
      /* Reload configuration with our changes. */
 
3241
      input_load_config ();
 
3242
   }
 
3243
 
 
3244
   return (D_O_K);
 
3245
}
 
3246
 
 
3247
static int input_menu_enable_zapper (void)
 
3248
{
 
3249
   input_enable_zapper = !input_enable_zapper;
 
3250
   update_menus ();
 
3251
 
 
3252
   message_local ("Zapper emulation %s.", get_enabled_text
 
3253
      (input_enable_zapper));
 
3254
 
 
3255
   return (D_O_K);
 
3256
}
 
3257
 
 
3258
static int options_cpu_usage_menu_passive (void)
 
3259
{
 
3260
    cpu_usage = CPU_USAGE_PASSIVE;
 
3261
    update_menus ();
 
3262
 
 
3263
    message_local ("System CPU usage set to passive.");
 
3264
 
 
3265
    return (D_O_K);
 
3266
}
 
3267
 
 
3268
static int options_cpu_usage_menu_normal (void)
 
3269
{
 
3270
    cpu_usage = CPU_USAGE_NORMAL;
 
3271
    update_menus ();
 
3272
 
 
3273
    message_local ("System CPU usage set to normal.");
 
3274
 
 
3275
    return (D_O_K);
 
3276
}
 
3277
 
 
3278
static int options_cpu_usage_menu_aggressive (void)
 
3279
{
 
3280
    cpu_usage = CPU_USAGE_AGGRESSIVE;
 
3281
    update_menus ();
 
3282
 
 
3283
    message_local ("System CPU usage set to aggressive.");
 
3284
 
 
3285
    return (D_O_K);
 
3286
}
 
3287
 
 
3288
static int options_menu_paths (void)
 
3289
{
 
3290
   USTRING open_path, save_path;
 
3291
   BOOL locked;
 
3292
   DIALOG *dialog;
 
3293
   DIALOG *objopen, *objlock, *objsave;
 
3294
 
 
3295
   /* Load configuration. */
 
3296
 
 
3297
   USTRING_CLEAR(open_path);
 
3298
   ustrncat (open_path, get_config_string ("gui", "open_path", "/"),
 
3299
      (sizeof (open_path) - 1));
 
3300
 
 
3301
   USTRING_CLEAR(save_path);
 
3302
   ustrncat (save_path, get_config_string ("gui", "save_path", "./"),
 
3303
      (sizeof (save_path) - 1));
 
3304
 
 
3305
   locked = get_config_int ("gui", "lock_paths", FALSE);
 
3306
   
 
3307
   /* Get dialog. */
 
3308
   dialog = options_paths_dialog;
 
3309
 
 
3310
   /* Get dialog objects. */
 
3311
 
 
3312
   objopen = &dialog[OPTIONS_PATHS_DIALOG_OPEN_PATH];
 
3313
   objlock = &dialog[OPTIONS_PATHS_DIALOG_LOCKED];
 
3314
   objsave = &dialog[OPTIONS_PATHS_DIALOG_SAVE_PATH];
 
3315
 
 
3316
   /* Set up objects. */
 
3317
 
 
3318
   objopen->dp = open_path;
 
3319
   objopen->d1 = ((sizeof (open_path) / MAX_UCHAR_LENGTH) - 1);
 
3320
 
 
3321
   objsave->dp = save_path;
 
3322
   objsave->d1 = ((sizeof (save_path) / MAX_UCHAR_LENGTH) - 1);
 
3323
 
 
3324
   if (locked)
 
3325
      objlock->flags |= D_SELECTED;
 
3326
 
 
3327
   /* Show dialog. */
 
3328
 
 
3329
   if (show_dialog (dialog, -1) == OPTIONS_PATHS_DIALOG_OK_BUTTON)
 
3330
   {
 
3331
      /* Save configuration. */
 
3332
 
 
3333
      set_config_string ("gui", "open_path", open_path);
 
3334
      set_config_string ("gui", "save_path", save_path);
 
3335
 
 
3336
      set_config_int ("gui", "lock_paths",
 
3337
         TRUE_OR_FALSE(objlock->flags & D_SELECTED));
 
3338
   }
 
3339
 
 
3340
   return (D_O_K);
 
3341
}
 
3342
 
 
3343
#define OPTIONS_GUI_THEME_MENU_HANDLER(name)   \
 
3344
   static int options_gui_theme_menu_##name (void) \
 
3345
   {  \
 
3346
      set_##name##_theme ();  \
 
3347
      gui_needs_restart = TRUE;  \
 
3348
      return (D_CLOSE); \
 
3349
   }
 
3350
 
 
3351
OPTIONS_GUI_THEME_MENU_HANDLER(classic)
 
3352
OPTIONS_GUI_THEME_MENU_HANDLER(stainless_steel)
 
3353
OPTIONS_GUI_THEME_MENU_HANDLER(zero_4)
 
3354
OPTIONS_GUI_THEME_MENU_HANDLER(panta)
 
3355
OPTIONS_GUI_THEME_MENU_HANDLER(xodiac)
 
3356
OPTIONS_GUI_THEME_MENU_HANDLER(monochrome)
 
3357
OPTIONS_GUI_THEME_MENU_HANDLER(essence)
 
3358
OPTIONS_GUI_THEME_MENU_HANDLER(voodoo)
 
3359
OPTIONS_GUI_THEME_MENU_HANDLER(hugs_and_kisses)
 
3360
 
 
3361
#undef OPTIONS_GUI_THEME_MENU_HANDLER
 
3362
 
 
3363
static int options_menu_reset_clock (void)
 
3364
{
 
3365
   timing_clock = 0;
 
3366
 
 
3367
   return (D_O_K);
 
3368
}
 
3369
 
 
3370
static int netplay_menu_start_as_server (void)
 
3371
{
 
3372
   STRING host;
 
3373
   int port;
 
3374
   STRING port_str;
 
3375
   USTRING nick;
 
3376
   DIALOG *dialog;
 
3377
   DIALOG *obj_host_label;
 
3378
   DIALOG *obj_host;
 
3379
   DIALOG *obj_port;
 
3380
   DIALOG *obj_nick;
 
3381
 
 
3382
   /* Load configuration. */
 
3383
 
 
3384
   STRING_CLEAR(host);
 
3385
 
 
3386
   port = get_config_int ("netplay", "port", NETPLAY_DEFAULT_PORT);
 
3387
 
 
3388
   STRING_CLEAR(port_str);
 
3389
   sprintf (port_str, "%d", port);
 
3390
 
 
3391
   USTRING_CLEAR(nick);
 
3392
   ustrncat (nick, get_config_string ("netplay", "nick", "Player"), (sizeof(nick) - 1));
 
3393
 
 
3394
   /* Get dialog. */
 
3395
   dialog = netplay_dialog;
 
3396
 
 
3397
   /* Get dialog objects. */
 
3398
   obj_host_label = &dialog[NETPLAY_DIALOG_HOST_LABEL];
 
3399
   obj_host       = &dialog[NETPLAY_DIALOG_HOST];
 
3400
   obj_port       = &dialog[NETPLAY_DIALOG_PORT];
 
3401
   obj_nick       = &dialog[NETPLAY_DIALOG_NICK];
 
3402
 
 
3403
   /* Set up dialog objects. */
 
3404
 
 
3405
   obj_host_label->flags |= D_DISABLED;
 
3406
  
 
3407
   obj_host->d1 = 0;
 
3408
   obj_host->dp = host;
 
3409
   obj_host->flags |= D_DISABLED;
 
3410
 
 
3411
   obj_port->d1 = ((sizeof (port_str) / MAX_UCHAR_LENGTH) - 1);
 
3412
   obj_port->dp = port_str;
 
3413
 
 
3414
   obj_nick->d1 = ((sizeof (nick) / MAX_UCHAR_LENGTH) - 1);
 
3415
   obj_nick->dp = nick;
 
3416
 
 
3417
   /* Display dialog. */
 
3418
   if (show_dialog (dialog, -1) != NETPLAY_DIALOG_OK_BUTTON)
 
3419
      return (D_O_K);
 
3420
 
 
3421
   /* Integerize port. */
 
3422
   port = atoi (port_str);
 
3423
 
 
3424
   /* Save configuration. */
 
3425
   set_config_int    ("netplay", "port", port);
 
3426
   set_config_string ("netplay", "nick", nick);
 
3427
 
 
3428
   /* Start NetPlay session. */
 
3429
 
 
3430
   if (!netplay_open_server (port))
 
3431
   {
 
3432
      gui_message (GUI_ERROR_COLOR, "Failed to open server!");
 
3433
      return (D_O_K);
 
3434
   }
 
3435
 
 
3436
   message_local ("NetPlay session opened.");
 
3437
 
 
3438
   /* Set nickname. */
 
3439
   netplay_set_nickname (nick);
 
3440
 
 
3441
   /* Open lobby. */
 
3442
   return (open_lobby ());
 
3443
}
 
3444
 
 
3445
static int netplay_menu_start_as_client (void)
 
3446
{
 
3447
   STRING host;
 
3448
   int port;
 
3449
   STRING port_str;
 
3450
   USTRING nick;
 
3451
   DIALOG *dialog;
 
3452
   DIALOG *obj_host_label;
 
3453
   DIALOG *obj_host;
 
3454
   DIALOG *obj_port;
 
3455
   DIALOG *obj_nick;
 
3456
          
 
3457
   /* Load configuration. */
 
3458
 
 
3459
   STRING_CLEAR(host);
 
3460
   strncat (host, get_config_string ("netplay", "host", ""), (sizeof(host) - 1));
 
3461
 
 
3462
   port = get_config_int ("netplay", "port", NETPLAY_DEFAULT_PORT);
 
3463
 
 
3464
   STRING_CLEAR(port_str);
 
3465
   sprintf (port_str, "%d", port);
 
3466
 
 
3467
   USTRING_CLEAR(nick);
 
3468
   ustrncat (nick, get_config_string ("netplay", "nick", "Player"), (sizeof(nick) - 1));
 
3469
 
 
3470
   /* Get dialog. */
 
3471
   dialog = netplay_dialog;
 
3472
 
 
3473
   /* Get dialog objects. */
 
3474
   obj_host_label = &dialog[NETPLAY_DIALOG_HOST_LABEL];
 
3475
   obj_host       = &dialog[NETPLAY_DIALOG_HOST];
 
3476
   obj_port       = &dialog[NETPLAY_DIALOG_PORT];
 
3477
   obj_nick       = &dialog[NETPLAY_DIALOG_NICK];
 
3478
 
 
3479
   /* Set up dialog objects. */
 
3480
 
 
3481
   obj_host_label->flags &= ~D_DISABLED;
 
3482
 
 
3483
   obj_host->d1 = ((sizeof (host) / MAX_UCHAR_LENGTH) - 1);
 
3484
   obj_host->dp = host;
 
3485
   obj_host->flags &= ~D_DISABLED;
 
3486
 
 
3487
   obj_port->d1 = ((sizeof (port_str) / MAX_UCHAR_LENGTH) - 1);
 
3488
   obj_port->dp = port_str;
 
3489
 
 
3490
   obj_nick->d1 = ((sizeof (nick) / MAX_UCHAR_LENGTH) - 1);
 
3491
   obj_nick->dp = nick;
 
3492
 
 
3493
   /* Display dialog. */
 
3494
   if (show_dialog (dialog, -1) != NETPLAY_DIALOG_OK_BUTTON)
 
3495
      return (D_O_K);
 
3496
 
 
3497
   /* Integerize port. */
 
3498
   port = atoi (port_str);
 
3499
 
 
3500
   /* Save configuration. */
 
3501
   set_config_string ("netplay", "host", host);
 
3502
   set_config_int    ("netplay", "port", port);
 
3503
   set_config_string ("netplay", "nick", nick);
 
3504
 
 
3505
   /* Start NetPlay session. */
 
3506
 
 
3507
   if (!netplay_open_client (host, port))
 
3508
   {
 
3509
      gui_message (GUI_ERROR_COLOR, "Failed to connect to remote host!");
 
3510
      return (D_O_K);
 
3511
   }
 
3512
 
 
3513
   message_local ("NetPlay session opened.");
 
3514
 
 
3515
   /* Set nickname. */
 
3516
   netplay_set_nickname (nick);
 
3517
 
 
3518
   /* Open lobby. */
 
3519
   return (open_lobby ());
 
3520
}
 
3521
 
 
3522
static int help_menu_view_license (void)
 
3523
{
 
3524
   DIALOG *dialog;
 
3525
   DIALOG *objframe;
 
3526
   DIALOG *objview;
 
3527
 
 
3528
   /* Create dialog. */
 
3529
   dialog = load_dialog (viewer_dialog_base);
 
3530
   if (!dialog)
 
3531
   {
 
3532
      WARN("Failed to create dialog structure");
 
3533
      return (-1);
 
3534
   }
 
3535
 
 
3536
   /* Get objects. */
 
3537
 
 
3538
   objframe = &dialog[VIEWER_DIALOG_FRAME];
 
3539
   objview  = &dialog[VIEWER_DIALOG_TEXT];
 
3540
 
 
3541
   /* Set up objects. */
 
3542
 
 
3543
   objframe->dp2 = "License";
 
3544
 
 
3545
   objview->dp = get_console_text ();
 
3546
 
 
3547
   /* Show dialog. */
 
3548
   show_dialog (dialog, -1);
 
3549
 
 
3550
   /* Destroy dialog. */
 
3551
   unload_dialog (dialog);
 
3552
 
 
3553
   return (D_O_K);
 
3554
}
 
3555
 
 
3556
static int help_menu_view_log (void)
 
3557
{
 
3558
   DIALOG *dialog;
 
3559
   DIALOG *objframe;
 
3560
   DIALOG *objview;
 
3561
 
 
3562
   /* Create dialog. */
 
3563
   dialog = load_dialog (viewer_dialog_base);
 
3564
   if (!dialog)
 
3565
   {
 
3566
      WARN("Failed to create dialog structure");
 
3567
      return (-1);
 
3568
   }
 
3569
 
 
3570
   /* Get objects. */
 
3571
 
 
3572
   objframe = &dialog[VIEWER_DIALOG_FRAME];
 
3573
   objview  = &dialog[VIEWER_DIALOG_TEXT];
 
3574
 
 
3575
   /* Set up objects. */
 
3576
 
 
3577
   objframe->dp2 = "Log";
 
3578
 
 
3579
   objview->dp = get_log_text ();
 
3580
 
 
3581
   /* Show dialog. */
 
3582
   show_dialog (dialog, -1);
 
3583
 
 
3584
   /* Destroy dialog. */
 
3585
   unload_dialog (dialog);
 
3586
 
 
3587
   return (D_O_K);
 
3588
}
 
3589
 
 
3590
static int help_menu_keyboard_shortcuts (void)
 
3591
{
 
3592
   show_dialog (help_keyboard_shortcuts_dialog, -1);
 
3593
 
 
3594
   return (D_O_K);
 
3595
}
 
3596
 
 
3597
static int help_menu_about (void)
 
3598
{
 
3599
   gui_alert ("About", "FakeNES version " VERSION_STRING " "
 
3600
      ALLEGRO_PLATFORM_STR, "Get the latest from "
 
3601
         "http://fakenes.sourceforge.net/.", NULL, "&OK", NULL, 'o', 0);
 
3602
 
 
3603
   return (D_O_K);
 
3604
}
 
3605
 
 
3606
static int help_menu_fakenes_team (void)
 
3607
{
 
3608
   show_dialog (help_fakenes_team_dialog, -1);
 
3609
 
 
3610
   return (D_O_K);
 
3611
}
 
3612
 
 
3613
 
 
3614
/* ---- Dialog handlers. ---- */
 
3615
 
 
3616
 
 
3617
static int main_cheat_manager_dialog_list (DIALOG *dialog)
 
3618
{
 
3619
   CPU_PATCH *patch;
 
3620
   DIALOG *main_dialog;
 
3621
   DIALOG *obj_enabled;
 
3622
 
 
3623
   RT_ASSERT(dialog);
 
3624
 
 
3625
   if (cpu_patch_count == 0)
 
3626
      return (D_O_K);
 
3627
 
 
3628
   patch = &cpu_patch_info[dialog->d1];
 
3629
 
 
3630
   /* Get main dialog. */
 
3631
   main_dialog = main_cheat_manager_dialog;
 
3632
 
 
3633
   /* Get "Enabled" checkbox. */
 
3634
   obj_enabled = &main_dialog[MAIN_CHEAT_MANAGER_DIALOG_ENABLED_CHECKBOX];
 
3635
 
 
3636
   if (patch->enabled)
 
3637
      obj_enabled->flags |= D_SELECTED;
 
3638
   else
 
3639
      obj_enabled->flags &= ~D_SELECTED;
 
3640
 
 
3641
   scare_mouse ();
 
3642
   object_message (obj_enabled, MSG_DRAW, 0);
 
3643
   unscare_mouse ();
 
3644
 
 
3645
   return (D_O_K);
 
3646
}
 
3647
 
 
3648
static int main_cheat_manager_dialog_add (DIALOG *dialog)
 
3649
{
 
3650
   DIALOG *main_dialog;
 
3651
   DIALOG *obj_title;
 
3652
   DIALOG *obj_code;
 
3653
   USTRING title;
 
3654
   USTRING code;
 
3655
   CPU_PATCH *patch;
 
3656
   UINT8 value;
 
3657
 
 
3658
   if (cpu_patch_count >= CPU_MAX_PATCHES)
 
3659
   {
 
3660
      gui_alert ("Error", "The patch list is already full.", NULL, NULL,
 
3661
         "&OK", NULL, 'o', 0);
 
3662
 
 
3663
      return (D_O_K);
 
3664
   }
 
3665
 
 
3666
   /* Get dialog. */
 
3667
   main_dialog = main_cheat_manager_add_dialog;
 
3668
 
 
3669
   /* Get dialog objects. */
 
3670
   obj_title = &main_dialog[MAIN_CHEAT_MANAGER_ADD_DIALOG_TITLE];
 
3671
   obj_code  = &main_dialog[MAIN_CHEAT_MANAGER_ADD_DIALOG_CODE];
 
3672
 
 
3673
   /* Set up dialog objects. */
 
3674
 
 
3675
   USTRING_CLEAR(title);
 
3676
   obj_title->d1 = NEW_SAVE_TITLE_SIZE;
 
3677
   obj_title->dp = title;
 
3678
 
 
3679
   USTRING_CLEAR(code);
 
3680
   obj_code->d1 = (11 - 1);
 
3681
   obj_code->dp = code;
 
3682
 
 
3683
   /* Show dialog. */
 
3684
   if (show_dialog (main_dialog, -1) !=
 
3685
      MAIN_CHEAT_MANAGER_ADD_DIALOG_OK_BUTTON)
 
3686
   {
 
3687
      return (D_O_K);
 
3688
   }
 
3689
 
 
3690
   patch = &cpu_patch_info[cpu_patch_count];
 
3691
 
 
3692
   if (cheats_decode (code, &patch->address, &patch->value,
 
3693
      &patch->match_value) != 0)
 
3694
   {
 
3695
      gui_alert ("Error", "You must enter a valid Game Genie (or NESticle "
 
3696
         "raw) code.", NULL, NULL, "&OK", NULL, 'o', 0);
 
3697
 
 
3698
      return (D_O_K);
 
3699
   }
 
3700
 
 
3701
   /* Copy title. */
 
3702
   ustrncat (patch->title, title, (USTRING_SIZE - 1));
 
3703
 
 
3704
   /* Enable patch. */
 
3705
   patch->enabled = TRUE;
 
3706
 
 
3707
   cpu_patch_count++;
 
3708
 
 
3709
   if ((value = cpu_read (patch->address)) == patch->match_value)
 
3710
   {
 
3711
      /* Activate patch. */
 
3712
      patch->active = TRUE;
 
3713
 
 
3714
      cpu_patch_table[patch->address] = (patch->value - value);
 
3715
   }
 
3716
 
 
3717
   return (D_REDRAW);
 
3718
}
 
3719
 
 
3720
static int main_cheat_manager_dialog_remove (DIALOG *dialog)
 
3721
{
 
3722
   DIALOG *main_dialog;
 
3723
   int start;
 
3724
   CPU_PATCH *src;
 
3725
   int index;
 
3726
 
 
3727
   RT_ASSERT(dialog);
 
3728
 
 
3729
   if (cpu_patch_count == 0)
 
3730
      return (D_O_K);
 
3731
 
 
3732
   main_dialog = main_cheat_manager_dialog;
 
3733
 
 
3734
   start = main_dialog[MAIN_CHEAT_MANAGER_DIALOG_LIST].d1;
 
3735
   src = &cpu_patch_info[start];
 
3736
 
 
3737
   /* Disable patch. */
 
3738
   if (src->active)
 
3739
   {
 
3740
      if (gui_alert ("Confirmation", "Really deactivate and remove this "
 
3741
         "patch?", NULL, NULL, "&OK", "&Cancel", 'o', 'c') == 2)
 
3742
      {
 
3743
         return (D_O_K);
 
3744
      }
 
3745
 
 
3746
      cpu_patch_table[src->address] = 0;
 
3747
   }
 
3748
 
 
3749
   for (index = (start + 1); index < cpu_patch_count; index++)
 
3750
   {
 
3751
      CPU_PATCH *dest;
 
3752
 
 
3753
      src = &cpu_patch_info[index];
 
3754
      dest = &cpu_patch_info[(index - 1)];
 
3755
 
 
3756
      memcpy (dest, src, sizeof (CPU_PATCH));
 
3757
   }
 
3758
 
 
3759
   src = &cpu_patch_info[(cpu_patch_count - 1)];
 
3760
 
 
3761
   memset (src, 0, sizeof (CPU_PATCH));
 
3762
   sprintf (src->title, "?");
 
3763
 
 
3764
   cpu_patch_count--;
 
3765
 
 
3766
   if (cpu_patch_count == 0)
 
3767
   {
 
3768
      main_dialog[MAIN_CHEAT_MANAGER_DIALOG_ENABLED_CHECKBOX].flags &=
 
3769
         ~D_SELECTED;
 
3770
   }
 
3771
 
 
3772
   return (D_REDRAW);
 
3773
}
 
3774
 
 
3775
static int main_cheat_manager_dialog_enabled (DIALOG *dialog)
 
3776
{
 
3777
   DIALOG *obj_list;
 
3778
   CPU_PATCH *patch;
 
3779
 
 
3780
   RT_ASSERT(dialog);
 
3781
 
 
3782
   if (cpu_patch_count == 0)
 
3783
   {
 
3784
      dialog->flags &= ~D_SELECTED;
 
3785
 
 
3786
      return (D_O_K);
 
3787
   }
 
3788
 
 
3789
   obj_list = &main_cheat_manager_dialog[MAIN_CHEAT_MANAGER_DIALOG_LIST];
 
3790
 
 
3791
   patch = &cpu_patch_info[obj_list->d1];
 
3792
 
 
3793
   patch->enabled = TRUE_OR_FALSE(dialog->flags & D_SELECTED);
 
3794
 
 
3795
   /* Toggle patch. */
 
3796
   if (!patch->enabled && patch->active)
 
3797
   {
 
3798
      patch->active = FALSE;
 
3799
 
 
3800
      cpu_patch_table[patch->address] = 0;
 
3801
   }
 
3802
   else if (patch->enabled && !patch->active)
 
3803
   {
 
3804
      UINT8 value;
 
3805
 
 
3806
      if ((value = cpu_read (patch->address)) == patch->match_value)
 
3807
      {
 
3808
         /* Enable patch. */
 
3809
         patch->active = TRUE;
 
3810
    
 
3811
         cpu_patch_table[patch->address] = (patch->value - value);
 
3812
      }
 
3813
   }
 
3814
 
 
3815
   scare_mouse ();
 
3816
   object_message (obj_list, MSG_DRAW, 0);
 
3817
   unscare_mouse ();
 
3818
 
 
3819
   return (D_O_K);
 
3820
}
 
3821
 
 
3822
static USTRING main_cheat_manager_dialog_list_texts[CPU_MAX_PATCHES];
 
3823
 
 
3824
static char *main_cheat_manager_dialog_list_filler (int index, int *list_size)
 
3825
{
 
3826
   if (index >= 0)
 
3827
   {
 
3828
      CPU_PATCH *patch = &cpu_patch_info[index];
 
3829
      UCHAR *text = main_cheat_manager_dialog_list_texts[index];
 
3830
 
 
3831
      USTRING_CLEAR(text);
 
3832
      uszprintf (text, USTRING_SIZE, "$%04x -$%02x +$%02x %s ",
 
3833
         patch->address, patch->match_value, patch->value, (patch->active ?
 
3834
            "Active" : " Idle "));
 
3835
 
 
3836
      /* Copy title. */
 
3837
      ustrncat (text, patch->title, (USTRING_SIZE - 1));
 
3838
      
 
3839
      return (text);
 
3840
   }
 
3841
   else
 
3842
   {
 
3843
      RT_ASSERT(list_size);
 
3844
 
 
3845
      *list_size = cpu_patch_count;
 
3846
 
 
3847
      return (NULL);
 
3848
   }
 
3849
}
 
3850
 
 
3851
static int selected_player = -1;
 
3852
static int selected_player_device = INPUT_DEVICE_NONE;
 
3853
 
 
3854
static int input_configure_dialog_player_select (DIALOG *dialog)
 
3855
{
 
3856
   DIALOG *main_dialog;
 
3857
   int first, last;
 
3858
   int index;
 
3859
 
 
3860
   RT_ASSERT(dialog);
 
3861
 
 
3862
   selected_player = dialog->d2;
 
3863
   selected_player_device = input_get_player_device (selected_player);
 
3864
 
 
3865
   main_dialog = input_configure_dialog;
 
3866
 
 
3867
   first = INPUT_CONFIGURE_DIALOG_DEVICE_0_SELECT;
 
3868
   last  = INPUT_CONFIGURE_DIALOG_DEVICE_7_SELECT;
 
3869
 
 
3870
   for (index = first; index <= last; index++)
 
3871
      main_dialog[index].flags &= ~D_SELECTED;
 
3872
 
 
3873
   main_dialog[(first + selected_player_device)].flags |= D_SELECTED;
 
3874
 
 
3875
   scare_mouse ();
 
3876
 
 
3877
   for (index = first; index <= last; index++)
 
3878
      object_message (&main_dialog[index],  MSG_DRAW, 0);
 
3879
 
 
3880
   first = INPUT_CONFIGURE_DIALOG_SET_BUTTON_AUTO_1;
 
3881
   last  = INPUT_CONFIGURE_DIALOG_SET_BUTTON_AUTO_8;
 
3882
 
 
3883
   for (index = first; index <= last; index++)
 
3884
   {
 
3885
      DIALOG *dialog = &main_dialog[index];
 
3886
 
 
3887
      /* d2 = button. */
 
3888
 
 
3889
      if (input_get_player_button_param (selected_player, dialog->d2,
 
3890
         INPUT_PLAYER_BUTTON_PARAM_AUTO))
 
3891
      {
 
3892
         dialog->flags |= D_SELECTED;
 
3893
      }
 
3894
      else
 
3895
      {
 
3896
         dialog->flags &= ~D_SELECTED;
 
3897
      }
 
3898
 
 
3899
      object_message (dialog, MSG_DRAW, 0);
 
3900
   }
 
3901
 
 
3902
   first = INPUT_CONFIGURE_DIALOG_SET_BUTTON_TURBO_1;
 
3903
   last  = INPUT_CONFIGURE_DIALOG_SET_BUTTON_TURBO_8;
 
3904
 
 
3905
   for (index = first; index <= last; index++)
 
3906
   {
 
3907
      DIALOG *dialog = &main_dialog[index];
 
3908
 
 
3909
      /* d2 = button. */
 
3910
 
 
3911
      if (input_get_player_button_param (selected_player, dialog->d2,
 
3912
         INPUT_PLAYER_BUTTON_PARAM_TURBO))
 
3913
      {
 
3914
         dialog->flags |= D_SELECTED;
 
3915
      }
 
3916
      else
 
3917
      {
 
3918
         dialog->flags &= ~D_SELECTED;
 
3919
      }
 
3920
 
 
3921
      object_message (dialog, MSG_DRAW, 0);
 
3922
   }
 
3923
 
 
3924
   unscare_mouse ();
 
3925
 
 
3926
   return (D_O_K);
 
3927
}
 
3928
 
 
3929
static int input_configure_dialog_device_select (DIALOG *dialog)
 
3930
{
 
3931
   RT_ASSERT(dialog);
 
3932
 
 
3933
   if (selected_player < 0)
 
3934
   {
 
3935
      gui_alert ("Error", "Please select a player to modify first.", NULL,
 
3936
         NULL, "&OK", NULL, 'o', 0);
 
3937
 
 
3938
      return (D_O_K);
 
3939
   }
 
3940
 
 
3941
   selected_player_device = dialog->d2;
 
3942
 
 
3943
   input_set_player_device (selected_player, selected_player_device);
 
3944
 
 
3945
   return (D_O_K);
 
3946
}
 
3947
 
 
3948
static int input_configure_dialog_set_buttons (DIALOG *dialog)
 
3949
{
 
3950
   int button;
 
3951
 
 
3952
   RT_ASSERT(dialog);
 
3953
 
 
3954
   if (selected_player < 0)
 
3955
   {
 
3956
      gui_alert ("Error", "Please select a player to modify first.", NULL,
 
3957
         NULL, "&OK", NULL, 'o', 0);
 
3958
 
 
3959
      if (dialog->proc == sl_checkbox)
 
3960
         dialog->flags ^= D_SELECTED;
 
3961
 
 
3962
      return (D_O_K);
 
3963
   }
 
3964
 
 
3965
   button = dialog->d2;
 
3966
 
 
3967
   switch (dialog->d1)
 
3968
   {
 
3969
      case 0:  /* Map button. */
 
3970
      {
 
3971
         if (selected_player_device == INPUT_DEVICE_NONE)
 
3972
         {
 
3973
            gui_alert ("Error", "The selected player is currently "
 
3974
               "disabled.", NULL, NULL, "&OK", NULL, 'o', 0);
 
3975
      
 
3976
            return (D_O_K);
 
3977
         }
 
3978
      
 
3979
         if (selected_player_device == INPUT_DEVICE_MOUSE)
 
3980
         {
 
3981
            gui_alert ("Error", "Unable to set buttons for mouse at this "
 
3982
               "time.", NULL, NULL, "&OK", NULL, 'o', 0);
 
3983
      
 
3984
            return (D_O_K);
 
3985
         }
 
3986
      
 
3987
         message_local ("Scanning for device changes, press ESC to cancel.");
 
3988
          
 
3989
         input_map_player_button (selected_player, button);
 
3990
 
 
3991
         break;
 
3992
      }
 
3993
 
 
3994
      case 1:  /* Set auto. */
 
3995
      {
 
3996
         input_set_player_button_param (selected_player, button,
 
3997
            INPUT_PLAYER_BUTTON_PARAM_AUTO, (dialog->flags & D_SELECTED));
 
3998
 
 
3999
         break;
 
4000
      }
 
4001
 
 
4002
      case 2:  /* Set turbo. */
 
4003
      {
 
4004
         input_set_player_button_param (selected_player, button,
 
4005
            INPUT_PLAYER_BUTTON_PARAM_TURBO, (dialog->flags & D_SELECTED));
 
4006
            
 
4007
         break;
 
4008
      }
 
4009
 
 
4010
      default:
 
4011
         WARN_GENERIC();
 
4012
   }
 
4013
 
 
4014
   return (D_O_K);
 
4015
}
 
4016
 
 
4017
static int input_configure_dialog_calibrate (DIALOG *dialog)
 
4018
{
 
4019
   RT_ASSERT(dialog);
 
4020
 
 
4021
   if (selected_player < 0)
 
4022
   {
 
4023
      gui_alert ("Error", "Please select a player to modify first.", NULL,
 
4024
         NULL, "&OK", NULL, 'o', 0);
 
4025
 
 
4026
      return (D_O_K);
 
4027
   }
 
4028
 
 
4029
   switch (selected_player_device)
 
4030
   {
 
4031
      case INPUT_DEVICE_JOYSTICK_1:
 
4032
      case INPUT_DEVICE_JOYSTICK_2:
 
4033
      {
 
4034
         int index;
 
4035
 
 
4036
         index = (selected_player_device - INPUT_DEVICE_JOYSTICK_1);
 
4037
 
 
4038
         while (joy[index].flags & JOYFLAG_CALIBRATE)
 
4039
         {
 
4040
            int scancode;
 
4041
 
 
4042
            message_local ("%s, and press any key.",
 
4043
               calibrate_joystick_name (index));
 
4044
 
 
4045
            while (!keypressed ())
 
4046
               gui_heartbeat ();
 
4047
 
 
4048
            ureadkey (&scancode);
 
4049
 
 
4050
            if (scancode == KEY_ESC)
 
4051
            {
 
4052
               gui_message (GUI_ERROR_COLOR, "Joystick calibration "
 
4053
                  "cancelled.");
 
4054
    
 
4055
               return (D_O_K);
 
4056
            }
 
4057
 
 
4058
            if (calibrate_joystick (index) != 0)
 
4059
            {
 
4060
               gui_alert ("Error", "An unknown error occured while "
 
4061
                  "attempting to calibrate the device.", NULL, NULL, "&OK",
 
4062
                     NULL, 'o', 0);
 
4063
   
 
4064
               return (D_O_K);
 
4065
            }
 
4066
         }
 
4067
 
 
4068
         gui_alert ("Calibration Complete", "The selected device has been "
 
4069
            "calibrated.", NULL, NULL, "&Save", NULL, 's', 0);
 
4070
 
 
4071
         save_joystick_data (NULL);
 
4072
 
 
4073
         break;
 
4074
      }
 
4075
 
 
4076
      default:
 
4077
      {
 
4078
         gui_alert ("Error", "The selected device does not require "
 
4079
            "calibration.", NULL, NULL, "&OK", NULL, 'o', 0);
 
4080
 
 
4081
         break;
 
4082
      }
 
4083
   }
 
4084
 
 
4085
   return (D_O_K);
 
4086
}
 
4087
 
 
4088
static int lobby_dialog_load (void)
 
4089
{
 
4090
   /* Note: D_CLOSE means success, D_O_K means failure. */
 
4091
   if (main_menu_open () == D_CLOSE)
 
4092
   {
 
4093
      DIALOG *obj_ok;
 
4094
 
 
4095
      obj_ok = &lobby_dialog[LOBBY_DIALOG_OK_BUTTON];
 
4096
 
 
4097
      obj_ok->flags &= ~D_DISABLED;
 
4098
 
 
4099
      scare_mouse ();
 
4100
      object_message (obj_ok, MSG_DRAW, 0);
 
4101
      unscare_mouse ();
 
4102
   }
 
4103
 
 
4104
   return (D_O_K);
 
4105
}