]> icculus.org git repositories - taylor/freespace2.git/blob - src/menuui/optionsmenu.cpp
GCC 3.4 fixes.
[taylor/freespace2.git] / src / menuui / optionsmenu.cpp
1 /*
2  * Copyright (C) Volition, Inc. 1999.  All rights reserved.
3  *
4  * All source code herein is the property of Volition, Inc. You may not sell 
5  * or otherwise commercially exploit the source or things you created based on
6  * the source.
7  */
8
9 /*
10  * $Logfile: /Freespace2/code/MenuUI/OptionsMenu.cpp $
11  * $Revision$
12  * $Date$
13  * $Author$
14  *
15  * C module that contains functions to drive the Options user interface
16  *
17  * $Log$
18  * Revision 1.5  2004/09/20 01:31:44  theoddone33
19  * GCC 3.4 fixes.
20  *
21  * Revision 1.4  2003/05/25 02:30:42  taylor
22  * Freespace 1 support
23  *
24  * Revision 1.3  2002/06/09 04:41:22  relnev
25  * added copyright header
26  *
27  * Revision 1.2  2002/05/26 22:06:17  relnev
28  * makefile: disable stand_gui for now.
29  *
30  * rest: staticize some globals
31  *
32  * Revision 1.1.1.1  2002/05/03 03:28:09  root
33  * Initial import.
34  *
35  * 
36  * 31    10/25/99 5:47p Jefff
37  * reassigned some xstr ids
38  * 
39  * 30    10/14/99 2:50p Jefff
40  * localization fixes
41  * 
42  * 29    9/13/99 6:07p Jefff
43  * took out audiostream pausing to allow for correct volume adjustments
44  * 
45  * 28    9/09/99 2:28p Jefff
46  * some detail slider #defines were switched around
47  * 
48  * 27    9/08/99 2:38p Jefff
49  * sound pausing going to menu from game
50  * 
51  * 26    8/05/99 3:40p Jefff
52  * hi-res text adjustments
53  * 
54  * 25    8/04/99 4:06p Jefff
55  * fixed volume sliders blacking out at master volume of 1.0
56  * 
57  * 24    8/02/99 6:05p Jefff
58  * failure sound on skill slider when disabled in game
59  * 
60  * 23    7/19/99 3:29p Dave
61  * Fixed gamma bitmap in the options screen.
62  * 
63  * 22    7/19/99 2:13p Dave
64  * Added some new strings for Heiko.
65  * 
66  * 21    7/18/99 9:54p Andsager
67  * Demo build clean up
68  * 
69  * 20    7/15/99 7:15p Jefff
70  * Added sounds for skill select
71  * 
72  * 19    7/15/99 4:10p Andsager
73  * Disable control_config hud_config in FS2_DEMO
74  * 
75  * 18    7/15/99 9:20a Andsager
76  * FS2_DEMO initial checkin
77  * 
78  * 17    7/13/99 1:15p Dave
79  * 32 bit support. Whee!
80  * 
81  * 16    7/09/99 5:54p Dave
82  * Seperated cruiser types into individual types. Added tons of new
83  * briefing icons. Campaign screen.
84  * 
85  * 15    6/25/99 11:59a Dave
86  * Multi options screen.
87  * 
88  * 14    6/24/99 12:34a Dave
89  * Main options screen.
90  * 
91  * 13    6/22/99 7:03p Dave
92  * New detail options screen.
93  * 
94  * 12    6/16/99 4:06p Dave
95  * New pilot info popup. Added new draw-bitmap-as-poly function.
96  * 
97  * 11    5/24/99 5:45p Dave
98  * Added detail levels to the nebula, with a decent speedup. Split nebula
99  * lightning into its own section.
100  * 
101  * 10    4/02/99 4:44p Jasenw
102  * 
103  * 9     2/05/99 7:22p Neilk
104  * Fixed gamma bitmap and converted coordinates for multiple resolutions
105  * 
106  * 8     1/30/99 5:08p Dave
107  * More new hi-res stuff.Support for nice D3D textures.
108  * 
109  * 7     12/18/98 1:13a Dave
110  * Rough 1024x768 support for Direct3D. Proper detection and usage through
111  * the launcher.
112  * 
113  * 6     11/30/98 1:07p Dave
114  * 16 bit conversion, first run.
115  * 
116  * 5     11/05/98 5:55p Dave
117  * Big pass at reducing #includes
118  * 
119  * 4     10/13/98 9:28a Dave
120  * Started neatening up freespace.h. Many variables renamed and
121  * reorganized. Added AlphaColors.[h,cpp]
122  * 
123  * 3     10/09/98 2:57p Dave
124  * Starting splitting up OS stuff.
125  * 
126  * 2     10/07/98 10:53a Dave
127  * Initial checkin.
128  * 
129  * 1     10/07/98 10:49a Dave
130  * 
131  * 123   6/12/98 7:13p Hoffoss
132  * Fixed options screen problem where it wasn't showing tooltips.
133  * 
134  * 122   6/12/98 4:52p Hoffoss
135  * Added support for special characters in in forgeign languages.
136  * 
137  * 121   6/09/98 10:31a Hoffoss
138  * Created index numbers for all xstr() references.  Any new xstr() stuff
139  * added from here on out should be added to the end if the list.  The
140  * current list count can be found in FreeSpace.cpp (search for
141  * XSTR_SIZE).
142  * 
143  * 120   6/05/98 9:50a Lawrance
144  * OEM changes
145  * 
146  * 119   6/01/98 11:43a John
147  * JAS & MK:  Classified all strings for localization.
148  * 
149  * 118   5/24/98 4:42p Dan
150  * AL: Fix several bugs related to pausing and enabling/disabling event
151  * music
152  * 
153  * 117   5/20/98 5:18p John
154  * Made the gamma box draw as a bitmap, not a bunch of pixels.  Speeds up
155  * the menu dramatically.
156  * 
157  * 116   5/19/98 1:21p Duncan
158  * Use 'InterfacePalette' instad of 'OptionsMainPalette'
159  * 
160  * 115   5/18/98 9:14p Dave
161  * Put in network config files support.
162  * 
163  * 114   5/18/98 5:16p Hoffoss
164  * Changed code to use new palette Jasen told me to use.
165  * 
166  * 113   5/16/98 3:40p Lawrance
167  * Don't restore the original details unless they've been stored!
168  * 
169  * 112   5/13/98 10:03a Mitri
170  * AL: Fix some bugs as a result of recent rearranging of code
171  * 
172  * 111   5/13/98 12:24a Lawrance
173  * Only load required bitmaps and masks for the options screen
174  * 
175  * 110   5/08/98 3:52p Hoffoss
176  * Fixed placement of gamma graphic.
177  * 
178  * 109   5/07/98 12:41p Hoffoss
179  * Added joystick deadzone slider support and mouse on/off support.
180  * 
181  * 108   5/06/98 8:06p Dave
182  * Made standalone reset properly under weird conditions. Tweak
183  * optionsmulti screen. Upped MAX_WEAPONS to 350. Put in new launch
184  * countdown anim. Minro ui fixes/tweaks.
185  * 
186  * 107   5/05/98 8:38p Hoffoss
187  * Added sensitivity adjustment to options menu and made it save to pilot
188  * file.
189  * 
190  * 106   4/27/98 9:00a Jasen
191  * Updated coords for button change.
192  * 
193  * 105   4/25/98 3:33p Allender
194  * do exit confirmation
195  * 
196  * 104   4/22/98 12:34a Dave
197  * Make sure hud config and control config buttons draw properly in all
198  * tab modes. Make small tab buttons light up correctly in multi options
199  * screen.
200  * 
201  * 103   4/21/98 12:14a Allender
202  * disable skill level buttons for multiplayer games
203  * 
204  * 102   4/20/98 6:04p Dave
205  * Implement multidata cache flushing and xferring mission files to
206  * multidata. Make sure observers can't change hud config. Fix pilot image
207  * viewing in popup. Put in game status field. Tweaked multi options. 
208  * 
209  * 101   4/18/98 12:45p Dave
210  * Aesthetic changes to multi options screen. Put in missing exit button.
211  * oops.
212  * 
213  * 100   4/17/98 5:27p Dave
214  * More work on the multi options screen. Fixed many minor ui todo bugs.
215  *  
216  *
217  * $NoKeywords: $
218  *
219 */
220
221 #include "grinternal.h"
222 #include "ui.h"
223 #include "missionscreencommon.h"
224 #include "bmpman.h"
225 #include "gamesequence.h"
226 #include "key.h"
227 #include "managepilot.h"
228 #include "freespace.h"
229 #include "gamesnd.h"
230 #include "sound.h"
231 #include "eventmusic.h"
232 #include "mainhallmenu.h"
233 #include "audiostr.h"
234 #include "multi.h"
235 #include "psnet.h"
236 #include "popup.h"
237 #include "popupdead.h"
238 #include "missionbriefcommon.h"
239 #include "optionsmenu.h"
240 #include "optionsmenumulti.h"
241 #include "joy.h"
242 #include "mouse.h"
243 #include "osregistry.h"
244 #include "alphacolors.h"
245 #include "timer.h"
246 #include "neb.h"
247 #include "beam.h"
248
249
250 // will display a notification warning message
251 #define OPTIONS_NOTIFY_TIME                     3500
252 #define OPTIONS_NOTIFY_Y            450
253
254 #ifdef MAKE_FS1
255 #define NUM_BUTTONS 26
256 #else
257 #define NUM_BUTTONS     24
258 #endif
259 #define NUM_ANIS                4
260 #define NUM_TABS                3
261 #define NUM_COMMONS     10
262
263 #define TABLESS                                                 999
264
265 #define OPTIONS_TAB                                             0
266 #define MULTIPLAYER_TAB                                 1
267 #define DETAIL_LEVELS_TAB                               2
268 #define ABORT_GAME_BUTTON                               3
269 #define CONTROL_CONFIG_BUTTON                   4
270 #define HUD_CONFIG_BUTTON                               5
271 #define ACCEPT_BUTTON                                   6
272
273 #define BRIEF_VOICE_OFF                                 7
274 #define BRIEF_VOICE_ON                                  8
275 #define MOUSE_OFF                                                       9
276 #define MOUSE_ON                                                        10
277 #define GAMMA_DOWN                                              11
278 #define GAMMA_UP                                                        12
279
280 // detail level screen buttons
281 #define PLANETS_ON                                              13
282 #define PLANETS_OFF                                             14
283 #define HUD_TARGETVIEW_RENDER_ON                15
284 #define HUD_TARGETVIEW_RENDER_OFF       16
285 #define WEAPON_EXTRAS_ON                                17
286 #define WEAPON_EXTRAS_OFF                               18
287
288 #ifdef MAKE_FS1
289 #define ENGINE_GLOWS_ON                                 24
290 #define ENGINE_GLOWS_OFF                                25
291 #endif
292
293 #define LOW_DETAIL_N                                            19
294 #define MEDIUM_DETAIL_N                                 20
295 #define HIGH_DETAIL_N                                   21
296 #define VERY_HIGH_DETAIL_N                              22
297 #define CUSTOM_DETAIL_N                                 23
298
299 #define REPEAT                                          (1<<0)
300 #define NO_MOUSE_OVER_SOUND     (1<<1)
301
302 // indicies for options coordinates
303 #define OPTIONS_X_COORD 0
304 #define OPTIONS_Y_COORD 1
305 #define OPTIONS_W_COORD 2
306 #define OPTIONS_H_COORD 3
307
308 struct options_buttons {
309         char *filename;
310         int x, y;
311         int hotspot;
312         int tab;
313         int flags;
314         UI_BUTTON button;  // because we have a class inside this struct, we need the constructor below..
315
316         options_buttons(char *name, int x1, int y1, int h, int t, int f = 0) : filename(name), x(x1), y(y1), hotspot(h), tab(t), flags(f) {}
317 };
318
319 static options_buttons Buttons[GR_NUM_RESOLUTIONS][NUM_BUTTONS] = {
320         {       // GR_640
321 #ifdef MAKE_FS1
322                 options_buttons("OPa_00",       84,             25,             0,      -1),    // options tab
323                 options_buttons("OPa_01",       173,    25,             1,      -1),    // multiplayer tab
324                 options_buttons("OPa_02",       256,    25,             2,      -1),    // detail levels tab
325                 options_buttons("OPa_03",       6,              380,    3,      -1),    // abort game button
326                 options_buttons("OPa_05",       448,    335,    5,      -1),    // control config button
327                 options_buttons("OPa_06",       541,    335,    6,      -1),    // hud config
328                 options_buttons("OPa_07",       560,    411,    7,      -1),    // accept button                
329
330                 options_buttons("OPa_58",       39,             99,             58,     OPTIONS_TAB,    2),     // Briefing / debriefing voice toggle off
331                 options_buttons("OPa_59",       104,    99,             59,     OPTIONS_TAB,    2),     // Briefing / debriefing voice toggle on
332                 options_buttons("OPa_62",       359,    274,    62,     OPTIONS_TAB,    2),     // Mouse off
333                 options_buttons("OPa_63",       424,    274,    63,     OPTIONS_TAB,    2),     // Mouse on
334                 options_buttons("OPa_56",       451,    79,             56,     OPTIONS_TAB,    1),     // Gamma Down
335                 options_buttons("OPa_57",       484,    79,             57,     OPTIONS_TAB,    1),     // Gamma Up
336         
337                 options_buttons("OPc_40",       321,    237,    40,     DETAIL_LEVELS_TAB,      2),     // Planets On (Nebula)
338                 options_buttons("OPc_39",       264,    237,    39,     DETAIL_LEVELS_TAB,      2),     // Planets Off (Nebula)
339                 options_buttons("OPc_42",       321,    284,    42,     DETAIL_LEVELS_TAB,      2),     // Target View Rendering On
340                 options_buttons("OPc_41",       264,    284,    41,     DETAIL_LEVELS_TAB,      2),     // Target View Rendering Off
341                 options_buttons("OPc_44",       321,    331,    44,     DETAIL_LEVELS_TAB,      2),     // Weapon Extras On
342                 options_buttons("OPc_43",       264,    331,    43,     DETAIL_LEVELS_TAB,      2),     // Weapon Extras Off
343
344                 options_buttons("OPc_50",       516,    194,    50,     DETAIL_LEVELS_TAB,      2),     // Low Preset Detail
345                 options_buttons("OPc_51",       516,    213,    51,     DETAIL_LEVELS_TAB,      2),     // Medium Preset Detail
346                 options_buttons("OPc_52",       516,    232,    52,     DETAIL_LEVELS_TAB,      2),     // High Preset Detail
347                 options_buttons("OPc_53",       498,    251,    53,     DETAIL_LEVELS_TAB,      2),     // Highest Preset Detail
348                 options_buttons("OPc_54",       516,    270,    54,     DETAIL_LEVELS_TAB,      2),     // Custom Detail
349
350                 options_buttons("OPc_38",       321,    190,    38,     DETAIL_LEVELS_TAB,      2),     // Engine Glow On
351                 options_buttons("OPc_37",       264,    190,    37,     DETAIL_LEVELS_TAB,      2),     // Engine Glow Off
352 #else
353                 options_buttons("OPT_00",       17,     2,              0,              -1),                                                    // options tab
354                 options_buttons("OPT_01",       102,    2,              1,              -1),                                                    // multiplayer tab
355                 options_buttons("OPT_02",       170,    2,              2,              -1),                                                    // detail levels tab
356                 options_buttons("OPT_03",       10,     444,    3,              -1),                                                    // abort game button
357                 options_buttons("OPT_04",       411,    444,    4,              -1),                                                    // control config button
358                 options_buttons("OPT_05",       506,    444,    5,              -1),                                                    // hud config
359                 options_buttons("OPT_06",       576,    434,    6,              -1),                                                    // accept button                                
360
361                 options_buttons("OMB_07",       51,     74,     7,              OPTIONS_TAB, 2),                        // Briefing / debriefing voice toggle off
362                 options_buttons("OMB_08",       106,    74,     8,              OPTIONS_TAB, 2),                        // Briefing / debriefing voice toggle on
363                 options_buttons("OMB_18",       51,     266,    18,     OPTIONS_TAB, 2),                        // Mouse off
364                 options_buttons("OMB_19",       106,    266,    19,     OPTIONS_TAB, 2),                        // Mouse on
365                 options_buttons("OMB_26",       578,    149,    26,     OPTIONS_TAB, 1),                        // Gamma Down
366                 options_buttons("OMB_27",       607,    149,    27,     OPTIONS_TAB, 1),                        // Gamma Up
367                 
368                 options_buttons("ODB_21",       597,    261,    21,     DETAIL_LEVELS_TAB, 2),  // Planets On
369                 options_buttons("ODB_20",       539,    261,    20,     DETAIL_LEVELS_TAB, 2),  // Planets Off
370                 options_buttons("ODB_23",       597,    307,    23,     DETAIL_LEVELS_TAB, 2),  // Target View Rendering On
371                 options_buttons("ODB_22",       539,    307,    22,     DETAIL_LEVELS_TAB, 2),  // Target View Rendering Off
372                 options_buttons("ODB_25",       597,    354,    25,     DETAIL_LEVELS_TAB, 2),  // Weapon Extras On
373                 options_buttons("ODB_24",       539,    354,    24,     DETAIL_LEVELS_TAB, 2),  // Weapon Extras Off
374
375                 options_buttons("ODB_14",       614,    76,     14,     DETAIL_LEVELS_TAB, 2),  // Low Preset Detail
376                 options_buttons("ODB_15",       614,    96,     15,     DETAIL_LEVELS_TAB, 2),  // Medium Preset Detail
377                 options_buttons("ODB_16",       614,    114,    16,     DETAIL_LEVELS_TAB, 2),  // High Preset Detail
378                 options_buttons("ODB_17",       614,    133,    17,     DETAIL_LEVELS_TAB, 2),  // Highest Preset Detail
379                 options_buttons("ODB_18",       614,    152,    18,     DETAIL_LEVELS_TAB, 2),  // Custom Detail
380 #endif
381         },
382         {       // GR_1024
383                 options_buttons("2_OPT_00",     27,     4,              0,              -1),                                            // options tab
384                 options_buttons("2_OPT_01",     164,    4,              1,              -1),                                            // multiplayer tab
385                 options_buttons("2_OPT_02",     272,    4,              2,              -1),                                            // detail levels tab
386                 options_buttons("2_OPT_03",     16,     711,    3,              -1),                                            // abort game
387                 options_buttons("2_OPT_04",     657,    711,    4,              -1),                                            // control config button
388                 options_buttons("2_OPT_05",     809,    711,    5,              -1),                                            // hud config button
389                 options_buttons("2_OPT_06",     922,    694,    6,              -1),                                            // accept button                
390
391                 options_buttons("2_OMB_07",     81,     118,    7,              OPTIONS_TAB, 2),                        // Briefing / debriefing voice toggle off
392                 options_buttons("2_OMB_08",     170,    118,    8,              OPTIONS_TAB, 2),                        // Briefing / debriefing voice toggle on
393                 options_buttons("2_OMB_18",     81,     425,    18,     OPTIONS_TAB, 2),                        // Mouse off
394                 options_buttons("2_OMB_19",     170,    425,    19,     OPTIONS_TAB, 2),                        // Mouse on
395                 options_buttons("2_OMB_26",     925,    238,    26,     OPTIONS_TAB, 1),                        // Gamma Down
396                 options_buttons("2_OMB_27",     971,    238,    27,     OPTIONS_TAB, 1),                        // Gamma Up
397                 
398                 options_buttons("2_ODB_21",     956,    417,    21,     DETAIL_LEVELS_TAB, 2),  // Planets On
399                 options_buttons("2_ODB_20",     863,    417,    20,     DETAIL_LEVELS_TAB, 2),  // Planets Off
400                 options_buttons("2_ODB_23",     956,    492,    23,     DETAIL_LEVELS_TAB, 2),  // Target View Rendering On
401                 options_buttons("2_ODB_22",     863,    492,    22,     DETAIL_LEVELS_TAB, 2),  // Target View Rendering Off
402                 options_buttons("2_ODB_25",     956,    567,    25,     DETAIL_LEVELS_TAB, 2),  // Weapon Extras On
403                 options_buttons("2_ODB_24",     863,    567,    24,     DETAIL_LEVELS_TAB, 2),  // Weapon Extras Off
404
405                 options_buttons("2_ODB_14",     983,    122,    14,     DETAIL_LEVELS_TAB, 2),  // Low Preset Detail
406                 options_buttons("2_ODB_15",     983,    153,    15,     DETAIL_LEVELS_TAB, 2),  // Medium Preset Detail
407                 options_buttons("2_ODB_16",     983,    183,    16,     DETAIL_LEVELS_TAB, 2),  // High Preset Detail
408                 options_buttons("2_ODB_17",     983,    213,    17,     DETAIL_LEVELS_TAB, 2),  // Highest Preset Detail
409                 options_buttons("2_ODB_18",     983,    243,    18,     DETAIL_LEVELS_TAB, 2),  // Custom Detail
410 #ifdef MAKE_FS1 // just filler
411                 options_buttons("OPc_38",       321,    290,    38,     DETAIL_LEVELS_TAB,      2),     // Engine Glow On
412                 options_buttons("OPc_37",       264,    290,    37,     DETAIL_LEVELS_TAB,      2),     // Engine Glow Off
413 #endif
414         }       
415 };
416
417 #define NUM_OPTIONS_SLIDERS                     7
418 #define OPT_SOUND_VOLUME_SLIDER         0
419 #define OPT_MUSIC_VOLUME_SLIDER         1
420 #define OPT_VOICE_VOLUME_SLIDER         2
421 #define OPT_MOUSE_SENS_SLIDER                   3
422 #define OPT_JOY_SENS_SLIDER                     4
423 #define OPT_JOY_DEADZONE_SLIDER         5
424 #define OPT_SKILL_SLIDER                                6
425
426 op_sliders Options_sliders[GR_NUM_RESOLUTIONS][NUM_OPTIONS_SLIDERS] = {
427         { // GR_640             
428 #ifdef MAKE_FS1
429 // slider, right arrow, left arrow
430 // s(name), s(x), s(y), s(?), s(?), s(h), s(?), s(?), ra(name), ra(h), ra(x), ra(y), la(name), la(h), la(x), la(y)
431                 op_sliders("OPa_09",    53,     160,    -1,     -1,     9,      20,     10,
432                                         "OPa_10",       10,     245,    159,
433                                         "OPa_08",       8,      29,             159),   // sound fx volume slider
434                 op_sliders("OPa_17",    53,     195,    -1,     -1,     17,     20,     10,
435                                         "OPa_18",       18,     245,    194,
436                                         "OPa_16",       16,     29,             194),   // music volume slider
437                 op_sliders("OPa_20",    53,     229,    -1,     -1,     20,     20,     10,
438                                         "OPa_21",       21,     245,    228,
439                                         "OPa_19",       19,     29,             228),   // voice volume slider
440                 op_sliders("OPa_64",    358,    301,    -1,     -1,     64,     20,     10,     NULL,   -1,     -1,     -1,     NULL,   -1,     -1,     -1),    // mouse sensitivity    
441                 op_sliders("OPa_60",    358,    194,    -1,     -1,     60,     20,     10,     NULL,   -1,     -1,     -1,     NULL,   -1,     -1,     -1),    // joystick sensitivity
442                 op_sliders("OPa_61",    358,    226,    -1,     -1,     61,     20,     10,     NULL,   -1,     -1,     -1,     NULL,   -1,     -1,     -1),    // joystick deadzone
443                 op_sliders("OPa_11",    28,             285,    -1,     -1,     11,     42,     5,      NULL,   -1,     -1,     -1,     NULL,   -1,     -1,     -1)             // skill
444 #else
445                 op_sliders("OMB_10",            31,     139,    -1,     -1,     10,     20,     10,
446                                           "OMB_11",             11,     226,    137,
447                                           "OMB_09",             9,              4,              137 ),                                                          // sound fx volume slider
448                 op_sliders("OMB_13",            31,     174,    -1,     -1,     13,     20,     10,
449                                           "OMB_14",             14,     226,    172,
450                                           "OMB_12",             12,     4,              172 ),                                                          // music volume slider
451                 op_sliders("OMB_16",            31,     209,    -1,     -1,     16,     20,     10,
452                                           "OMB_17",             17,     226,    206,
453                                           "OMB_15",             15,     4,              206 ),                                                          // voice volume slider
454                 op_sliders("OMB_20",            6,              316,    -1,     -1,     20,     20,     10, NULL, -1, -1, -1, NULL, -1, -1, -1),        // mouse sensitivity    
455                 op_sliders("OMB_28",            440,    259,    -1,     -1,     28,     20,     10, NULL, -1, -1, -1, NULL, -1, -1, -1),        // joystick sensitivity
456                 op_sliders("OMB_29",            440,    290,    -1,     -1,     29,     20,     10, NULL, -1, -1, -1, NULL, -1, -1, -1),        // joystick deadzone
457                 op_sliders("OMB_21",            440,    75,     -1,     -1,     21,     36,     5,      NULL, -1, -1, -1, NULL, -1, -1, -1)
458 #endif  // MAKE_FS1
459         },      
460         { // GR_1024            
461                 op_sliders("2_OMB_10",          50,     223,    -1,     -1,     10,     32,     10,
462                                           "2_OMB_11",           11,     361,    219,
463                                           "2_OMB_09",           9,              7,              219 ),                                                          // sound fx volume slider
464                 op_sliders("2_OMB_13",          50,     281,    -1,     -1,     13,     32,     10,
465                                           "2_OMB_14",           14,     361,    275,
466                                           "2_OMB_12",           12,     7,              275 ),                                                          // music volume slider
467                 op_sliders("2_OMB_16",          50,     335,    -1,     -1,     16,     32,     10,
468                                           "2_OMB_17",           17,     361,    330,
469                                           "2_OMB_15",           15,     7,              330 ),                                                          // voice volume slider
470                 op_sliders("2_OMB_20",          9,              505,    -1,     -1,     20,     32,     10, NULL, -1, -1, -1, NULL, -1, -1, -1),        // mouse sensitivity    
471                 op_sliders("2_OMB_28",          704,    414,    -1,     -1,     28,     32,     10, NULL, -1, -1, -1, NULL, -1, -1, -1),        // joystick sensitivity
472                 op_sliders("2_OMB_29",          704,    464,    -1,     -1,     29,     32,     10, NULL, -1, -1, -1, NULL, -1, -1, -1),        // joystick deadzone
473                 op_sliders("2_OMB_21",          704,    120,    -1,     -1,     21,     60,     5,      NULL, -1, -1, -1, NULL, -1, -1, -1)
474         }
475 };
476
477 static struct {
478         char *filename;
479         char *mask_filename;
480         int bitmap;
481         int mask;
482         
483 } Backgrounds[GR_NUM_RESOLUTIONS][NUM_TABS] = {
484 //XSTR:OFF
485         {       // GR_640
486                 { "OptionsMain", "OptionsMain-M"},
487                 { "OptionsMulti", "OptionsMulti-M"},
488                 { "OptionsDetail", "OptionsDetail-M"},
489         },
490         {       // GR_1024
491                 { "2_OptionsMain", "2_OptionsMain-M"},
492                 { "2_OptionsMulti", "2_OptionsMulti-M"},
493                 { "2_OptionsDetail", "2_OptionsDetail-M"},
494         }
495 //XSTR:ON
496 };
497
498 static int Tab = 0;
499 static int Options_menu_inited = 0;
500 static int Options_multi_inited = 0;
501 static int Options_detail_inited = 0;
502 static int Button_bms[NUM_COMMONS][MAX_BMAPS_PER_GADGET];
503
504 static UI_WINDOW Ui_window;
505 UI_GADGET Options_bogus;
506
507 static int Backup_skill_level;
508 static float Backup_sound_volume;
509 static float Backup_music_volume;
510 static float Backup_voice_volume;
511
512 static int Backup_briefing_voice_enabled;
513 static int Backup_use_mouse_to_fly;
514
515 static int Sound_volume_int;
516 static int Music_volume_int;
517 static int Voice_volume_int;
518
519 static int Voice_vol_handle = -1;
520 int Options_notify_stamp = -1;
521 char Options_notify_string[200];
522
523 // called whenever accept is hit
524 // do any processing, etc in here.
525 void options_accept();
526 void options_force_button_frame(int n, int frame_num);
527
528 extern float Freespace_gamma;
529
530 void options_add_notify(char *str);
531 void options_notify_do_frame();
532
533 int Options_gamma_coords[GR_NUM_RESOLUTIONS][4] = {
534         {
535 #ifdef MAKE_FS1
536                 376, 116, 203, 34
537 #else
538                 435, 179, 195,  28      // GR_640
539 #endif  // MAKE_FS1
540         },
541         {
542                 692, 287, 308, 44               // GR_1024
543         }
544 };
545
546 #define MAX_GAMMA_BITMAP_SIZE 17500
547
548 int Options_gamma_num_coords[GR_NUM_RESOLUTIONS][4] = {
549         {
550 #ifdef MAKE_FS1
551                 390, 87, 45, 10
552 #else
553                 489, 159, 65, 17                // GR_640
554 #endif  // MAKE_FS1
555         },
556         {
557                 779, 254, 65, 17                // GR_1024
558         }
559 };
560
561 int Options_skills_text_coords[GR_NUM_RESOLUTIONS][4] = {
562         {
563 #ifdef MAKE_FS1
564                 41, 326, 186, 10
565 #else
566                 468, 104, 155, 10               // GR_640
567 #endif
568         },
569         {
570                 750, 169, 246, 21               // GR_1024
571         }
572 };
573
574
575 // ---------------------------------------------------------------------------------------------------------
576 // DETAIL LEVEL OPTIONS definitions  BEGIN
577 //
578
579 #ifdef MAKE_FS1
580         #define NUM_DETAIL_SLIDERS              9
581 #else
582         #define NUM_DETAIL_SLIDERS              8
583 #endif
584
585 /*
586 #define DETAIL_DISTANCE_SLIDER  0
587 #define NEBULA_DETAIL_SLIDER            1
588 #define HARDWARE_TEXTURES_SLIDER        2
589 #define NUM_PARTICLES_SLIDER            6
590 #define SHARD_CULLING_SLIDER            3
591 #define SHIELD_DETAIL_SLIDER            4
592 #define NUM_STARS_SLIDER                        5
593 #define LIGHTING_SLIDER                         7
594 */
595 #define DETAIL_DISTANCE_SLIDER  0
596 #define NEBULA_DETAIL_SLIDER            1
597 #define HARDWARE_TEXTURES_SLIDER        2
598 #define NUM_PARTICLES_SLIDER            3
599 #define SHARD_CULLING_SLIDER            4
600 #define SHIELD_DETAIL_SLIDER            5
601 #define NUM_STARS_SLIDER                        6
602 #define LIGHTING_SLIDER                         7
603 #ifdef MAKE_FS1
604 #define WEAPON_REDNERING_SLIDER         8
605 #endif
606 op_sliders Detail_sliders[GR_NUM_RESOLUTIONS][NUM_DETAIL_SLIDERS] = {
607         { // GR_640
608 #ifdef MAKE_FS1
609                 op_sliders("OPc_29",    38,             96,             -1,     -1,     29,     20,     5,      NULL,   -1,     -1,     -1,     NULL,   -1,     -1,     -1),    // model detail
610                 op_sliders("OPc_30",    38,             143,    -1,     -1,     30,     20,     5,      NULL,   -1,     -1,     -1,     NULL,   -1,     -1,     -1),    // nebula detail
611                 op_sliders("OPc_31",    38,             176,    -1,     -1,     31,     20,     5,      NULL,   -1,     -1,     -1,     NULL,   -1,     -1,     -1),    // textures
612                 op_sliders("OPc_36",    273,    143,    -1,     -1,     36,     20,     5,      NULL,   -1,     -1,     -1,     NULL,   -1,     -1,     -1),    // particles
613                 op_sliders("Opc_33",    38,             284,    -1,     -1,     33,     20,     5,      NULL,   -1,     -1,     -1,     NULL,   -1,     -1,     -1),    // impact effects
614                 op_sliders("OPc_34",    38,             333,    -1,     -1,     34,     20,     5,      NULL,   -1,     -1,     -1,     NULL,   -1,     -1,     -1),    // shield hit
615                 op_sliders("OPc_35",    273,    96,             -1,     -1,     35,     20,     5,      NULL,   -1,     -1,     -1,     NULL,   -1,     -1,     -1),    // stars
616                 op_sliders("OPc_45",    496,    96,             -1,     -1,     45,     20,     5,      NULL,   -1,     -1,     -1,     NULL,   -1,     -1,     -1),    // lighting
617                 op_sliders("OPc_32",    38,             223,    -1,     -1,     32,     20,     5,      NULL,   -1,     -1,     -1,     NULL,   -1,     -1,     -1),    // weapon rendering - doesn't actually do anything
618 #else
619                 op_sliders("ODB_07",    21,     71,     -1,     -1,     7,              20,     5, NULL, -1, -1, -1, NULL, -1, -1, -1),                 // model detail
620                 op_sliders("ODB_08",    21,     119,    -1,     -1,     8,              20,     5, NULL, -1, -1, -1, NULL, -1, -1, -1),                 // nebula detail
621                 op_sliders("ODB_09",    21,     166,    -1,     -1,     9,              20,     5, NULL, -1, -1, -1, NULL, -1, -1, -1),                 // textures
622                 op_sliders("ODB_10",    21,     212,    -1,     -1,     10,     20,     5, NULL, -1, -1, -1, NULL, -1, -1, -1),                 // particles
623                 op_sliders("ODB_11",    21,     260,    -1,     -1,     11,     20,     5, NULL, -1, -1, -1, NULL, -1, -1, -1),                 // debris
624                 op_sliders("ODB_12",    21,     307,    -1,     -1,     12,     20,     5, NULL, -1, -1, -1, NULL, -1, -1, -1),                 // shield hit
625                 op_sliders("ODB_13",    21,     354,    -1,     -1,     13,     20,     5, NULL, -1, -1, -1, NULL, -1, -1, -1),                 // stars
626                 op_sliders("ODB_19",    518,    212,    -1,     -1,     19,     20,     5, NULL, -1, -1, -1, NULL, -1, -1, -1),                 // lighting             
627 #endif
628         },      
629         { // GR_1024
630                 op_sliders("2_ODB_07",  34,     114,    -1,     -1,     7,              32,     5, NULL, -1, -1, -1, NULL, -1, -1, -1),         // model detail
631                 op_sliders("2_ODB_08",  34,     190,    -1,     -1,     8,              32,     5, NULL, -1, -1, -1, NULL, -1, -1, -1),         // nebula detail
632                 op_sliders("2_ODB_09",  34,     265,    -1,     -1,     9,              32,     5, NULL, -1, -1, -1, NULL, -1, -1, -1),         // textures
633                 op_sliders("2_ODB_10",  34,     340,    -1,     -1,     10,     32,     5, NULL, -1, -1, -1, NULL, -1, -1, -1),         // particles
634                 op_sliders("2_ODB_11",  34,     416,    -1,     -1,     11,     32,     5, NULL, -1, -1, -1, NULL, -1, -1, -1),         // debris
635                 op_sliders("2_ODB_12",  34,     492,    -1,     -1,     12,     32,     5, NULL, -1, -1, -1, NULL, -1, -1, -1),         // shield hit
636                 op_sliders("2_ODB_13",  34,     567,    -1,     -1,     13,     32,     5, NULL, -1, -1, -1, NULL, -1, -1, -1),         // stars
637                 op_sliders("2_ODB_19",  829,    340,    -1,     -1,     19,     32,     5, NULL, -1, -1, -1, NULL, -1, -1, -1),         // lighting
638 #ifdef MAKE_FS1 // filler
639                 op_sliders("none",              -1,     -1,             -1,     -1,     -1,     -1,     -1,     NULL,   -1,     -1,     -1,     NULL,   -1,     -1,     -1),
640 #endif
641         }
642 };
643 int Detail_slider_pos[NUM_DETAIL_SLIDERS];
644 detail_levels Detail_original;  // backup of Detail settings when screen is first entered
645 UI_GADGET Detail_bogus;
646 void options_detail_init();
647 void options_detail_hide_stuff();
648 void options_detail_unhide_stuff();
649 void options_detail_do_frame();
650 void options_detail_set_level(int level);
651
652 // text
653 #ifdef MAKE_FS1
654         #define OPTIONS_NUM_TEXT                                0
655 #else
656         #define OPTIONS_NUM_TEXT                                49
657 #endif
658 UI_XSTR Options_text[GR_NUM_RESOLUTIONS][OPTIONS_NUM_TEXT] = {
659         { // GR_640
660                 // nothing needed
661 #ifndef MAKE_FS1
662                 // common text
663                 { "Options",    1036,           10,     35,     UI_XSTR_COLOR_GREEN,    -1, &Buttons[0][OPTIONS_TAB].button },
664                 { "Multi",              1042,           97,     35,     UI_XSTR_COLOR_GREEN,    -1, &Buttons[0][MULTIPLAYER_TAB].button },
665                 { "Detail",             1351,           166,    35,     UI_XSTR_COLOR_GREEN,    -1, &Buttons[0][DETAIL_LEVELS_TAB].button },
666                 { "Exit",               1059,           8,              417,    UI_XSTR_COLOR_PINK,     -1, &Buttons[0][ABORT_GAME_BUTTON].button },
667                 { "Game",               1412,           8,              430,    UI_XSTR_COLOR_PINK,     -1, &Buttons[0][ABORT_GAME_BUTTON].button },
668                 { "Control",    1352,           409,    418,    UI_XSTR_COLOR_GREEN,    -1, &Buttons[0][CONTROL_CONFIG_BUTTON].button },
669                 { "Config",             1353,           409,    430,    UI_XSTR_COLOR_GREEN,    -1, &Buttons[0][CONTROL_CONFIG_BUTTON].button },
670                 { "HUD",                        1354,           504,    418,    UI_XSTR_COLOR_GREEN,    -1, &Buttons[0][HUD_CONFIG_BUTTON].button },
671                 { "Config",             1415,           504,    430,    UI_XSTR_COLOR_GREEN,    -1, &Buttons[0][HUD_CONFIG_BUTTON].button },
672                 { "Accept",             1035,           573,    412,    UI_XSTR_COLOR_PINK,     -1, &Buttons[0][ACCEPT_BUTTON].button },
673
674                 // text for the detail level screen 
675                 { "Preset Detail Levels",       1355,   455,    56,     UI_XSTR_COLOR_GREEN,    -1, &Detail_bogus },
676                 { "Low",                        1160,           570,    82,     UI_XSTR_COLOR_GREEN, -1, &Buttons[0][LOW_DETAIL_N].button },
677                 { "Medium",             1161,           550,    100,    UI_XSTR_COLOR_GREEN, -1, &Buttons[0][MEDIUM_DETAIL_N].button },
678                 { "High",               1162,           568,    120,    UI_XSTR_COLOR_GREEN, -1, &Buttons[0][HIGH_DETAIL_N].button },
679                 { "Very High",  1163,           530,    139,    UI_XSTR_COLOR_GREEN, -1, &Buttons[0][VERY_HIGH_DETAIL_N].button },
680                 { "Custom",             1356,           546,    158,    UI_XSTR_COLOR_GREEN, -1, &Buttons[0][CUSTOM_DETAIL_N].button },         
681                 { "Off",                        1286,           509,    267,    UI_XSTR_COLOR_GREEN,    -1, &Buttons[0][PLANETS_OFF].button },
682                 { "On",                 1285,           573,    267,    UI_XSTR_COLOR_GREEN,    -1, &Buttons[0][PLANETS_ON].button },
683                 { "Off",                        1286,           509,    314,    UI_XSTR_COLOR_GREEN,    -1, &Buttons[0][HUD_TARGETVIEW_RENDER_OFF].button },
684                 { "On",                 1285,           573,    314,    UI_XSTR_COLOR_GREEN,    -1, &Buttons[0][HUD_TARGETVIEW_RENDER_ON].button },
685                 { "Off",                        1286,           509,    361,    UI_XSTR_COLOR_GREEN,    -1, &Buttons[0][WEAPON_EXTRAS_OFF].button },
686                 { "On",                 1285,           573,    361,    UI_XSTR_COLOR_GREEN,    -1, &Buttons[0][WEAPON_EXTRAS_ON].button },
687                 { "Planets/Backgrounds",                1357,   455,    244, UI_XSTR_COLOR_GREEN, -1, &Detail_bogus },
688                 { "Target View Rendering",              1358,   446,    291, UI_XSTR_COLOR_GREEN, -1, &Detail_bogus },
689                 { "Weapon Extras",                              1359,   497,    338, UI_XSTR_COLOR_GREEN, -1, &Detail_bogus },
690                 { "Model Detail",                                       1360,   27,     56,     UI_XSTR_COLOR_GREEN, -1, &Detail_bogus },
691                 { "Nebula Detail",                              1361,   27,     103,    UI_XSTR_COLOR_GREEN, -1, &Detail_bogus },
692                 { "3D Hardware Textures",               1362,   27,     150,    UI_XSTR_COLOR_GREEN, -1, &Detail_bogus },
693                 { "Particles",                                          1363,   27,     197,    UI_XSTR_COLOR_GREEN, -1, &Detail_bogus },
694                 { "Impact Effects",                             1364,   27,     244,    UI_XSTR_COLOR_GREEN, -1, &Detail_bogus },
695                 { "Shield Hit Effects",                 1365,   27,     291,    UI_XSTR_COLOR_GREEN, -1, &Detail_bogus },
696                 { "Stars",                                                      1366,   27,     338,    UI_XSTR_COLOR_GREEN, -1, &Detail_bogus },
697                 { "Lighting",                                           1367, 549,      197,    UI_XSTR_COLOR_GREEN, -1, &Detail_bogus },
698
699                 // main options screen text
700                 { "Briefing Voice",     1368,   14,     58,     UI_XSTR_COLOR_GREEN,    -1, &Options_bogus },
701                 { "Off",                                        1286,   20,     81,     UI_XSTR_COLOR_GREEN,    -1, &Buttons[0][BRIEF_VOICE_OFF].button },
702                 { "On",                                 1285,   83,     81,     UI_XSTR_COLOR_GREEN,    -1, &Buttons[0][BRIEF_VOICE_ON].button },
703                 { "Volume",                             1369,   14,     111,    UI_XSTR_COLOR_GREEN,    -1, &Options_bogus },
704                 { "Effects",                    1370,   20,     130,    UI_XSTR_COLOR_GREEN,    -1, &Options_bogus },
705                 { "Music",                              1371,   20,     165,    UI_XSTR_COLOR_GREEN,    -1, &Options_bogus },
706                 { "Voice",                              1372,   20,     199,    UI_XSTR_COLOR_GREEN,    -1, &Options_bogus },
707                 { "Mouse",                              1373,   14,     249,    UI_XSTR_COLOR_GREEN,    -1, &Options_bogus },
708                 { "Off",                                        1286,   20,     273,    UI_XSTR_COLOR_GREEN,    -1, &Buttons[0][MOUSE_OFF].button },
709                 { "On",                                 1285,   83,     273,    UI_XSTR_COLOR_GREEN,    -1, &Buttons[0][MOUSE_ON].button },
710                 { "Sensitivity",                1529,   20,     297,    UI_XSTR_COLOR_GREEN,    -1, &Options_sliders[0][OPT_MOUSE_SENS_SLIDER].slider },
711                 { "Skill Level",                1509,   533,    58,     UI_XSTR_COLOR_GREEN,    -1, &Options_bogus },
712                 { "Brightness",         1375,   532,    133,    UI_XSTR_COLOR_GREEN,    -1, &Options_bogus },
713                 { "Joystick",                   1376,   556,    231,    UI_XSTR_COLOR_GREEN,    -1, &Options_bogus },
714                 { "Sensitivity",                1374,   538,    250,    UI_XSTR_COLOR_GREEN,    -1, &Options_bogus },
715                 { "Deadzone",                   1377,   538,    281,    UI_XSTR_COLOR_GREEN,    -1, &Options_bogus },
716 #endif
717         },
718         { // GR_1024
719                 // nothing needed
720 #ifndef MAKE_FS1
721                 // common text
722                 { "Options",    1036,           16,     57,     UI_XSTR_COLOR_GREEN,    -1, &Buttons[1][OPTIONS_TAB].button },
723                 { "Multi",              1042,           172,    57,     UI_XSTR_COLOR_GREEN,    -1, &Buttons[1][MULTIPLAYER_TAB].button },
724                 { "Detail",             1351,           283,    57,     UI_XSTR_COLOR_GREEN,    -1, &Buttons[1][DETAIL_LEVELS_TAB].button },
725                 { "Exit",               1059,           13,     685,    UI_XSTR_COLOR_PINK,     -1, &Buttons[1][ABORT_GAME_BUTTON].button },
726                 { "Game",               1412,           13,     696,    UI_XSTR_COLOR_PINK,     -1, &Buttons[1][ABORT_GAME_BUTTON].button },
727                 { "Control",    1352,           655,    685,    UI_XSTR_COLOR_GREEN,    -1, &Buttons[1][CONTROL_CONFIG_BUTTON].button },
728                 { "Config",             1353,           655,    696,    UI_XSTR_COLOR_GREEN,    -1, &Buttons[1][CONTROL_CONFIG_BUTTON].button },
729                 { "HUD",                        1354,           806,    685,    UI_XSTR_COLOR_GREEN,    -1, &Buttons[1][HUD_CONFIG_BUTTON].button },
730                 { "Config",             1415,           806,    696,    UI_XSTR_COLOR_GREEN,    -1, &Buttons[1][HUD_CONFIG_BUTTON].button },
731                 { "Accept",             1035,           927,    672,    UI_XSTR_COLOR_PINK,     -1, &Buttons[1][ACCEPT_BUTTON].button },
732
733                 // text for the detail level screen 
734                 { "Preset Detail Levels",       1355,   809,    90,     UI_XSTR_COLOR_GREEN,    -1, &Detail_bogus },
735                 { "Low",                        1160,           944,    131,    UI_XSTR_COLOR_GREEN, -1, &Buttons[1][LOW_DETAIL_N].button },
736                 { "Medium",             1161,           924,    161,    UI_XSTR_COLOR_GREEN, -1, &Buttons[1][MEDIUM_DETAIL_N].button },
737                 { "High",               1162,           942,    192,    UI_XSTR_COLOR_GREEN, -1, &Buttons[1][HIGH_DETAIL_N].button },
738                 { "Very High",  1163,           903,    222,    UI_XSTR_COLOR_GREEN, -1, &Buttons[1][VERY_HIGH_DETAIL_N].button },
739                 { "Custom",             1356,           922,    252,    UI_XSTR_COLOR_GREEN, -1, &Buttons[1][CUSTOM_DETAIL_N].button },         
740                 { "Off",                        1286,           835,    427,    UI_XSTR_COLOR_GREEN,    -1, &Buttons[1][PLANETS_OFF].button },
741                 { "On",                 1285,           936,    427,    UI_XSTR_COLOR_GREEN,    -1, &Buttons[1][PLANETS_ON].button },
742                 { "Off",                        1286,           835,    503,    UI_XSTR_COLOR_GREEN,    -1, &Buttons[1][HUD_TARGETVIEW_RENDER_OFF].button },
743                 { "On",                 1285,           936,    503,    UI_XSTR_COLOR_GREEN,    -1, &Buttons[1][HUD_TARGETVIEW_RENDER_ON].button },
744                 { "Off",                        1286,           835,    578,    UI_XSTR_COLOR_GREEN,    -1, &Buttons[1][WEAPON_EXTRAS_OFF].button },
745                 { "On",                 1285,           936,    578,    UI_XSTR_COLOR_GREEN,    -1, &Buttons[1][WEAPON_EXTRAS_ON].button },
746                 { "Planets/Backgrounds",        1357,   808,    391, UI_XSTR_COLOR_GREEN, -1, &Detail_bogus },
747                 { "Target View Rendering",      1358,   799,    466, UI_XSTR_COLOR_GREEN, -1, &Detail_bogus },
748                 { "Weapon Extras",                      1359,   850,    542, UI_XSTR_COLOR_GREEN, -1, &Detail_bogus },                          
749                 { "Model Detail",                                       1360,   44,     99,     UI_XSTR_COLOR_GREEN, -1, &Detail_sliders[1][DETAIL_DISTANCE_SLIDER].slider },
750                 { "Nebula Detail",                              1361,   44,     175,    UI_XSTR_COLOR_GREEN, -1, &Detail_sliders[1][NEBULA_DETAIL_SLIDER].slider },
751                 { "3D Hardware Textures",               1362,   44,     250,    UI_XSTR_COLOR_GREEN, -1, &Detail_sliders[1][HARDWARE_TEXTURES_SLIDER].slider },
752                 { "Particles",                                          1363,   44,     325,    UI_XSTR_COLOR_GREEN, -1, &Detail_sliders[1][NUM_PARTICLES_SLIDER].slider },
753                 { "Impact Effects",                             1364,   44,     401,    UI_XSTR_COLOR_GREEN, -1, &Detail_sliders[1][SHARD_CULLING_SLIDER].slider },
754                 { "Shield Hit Effects",                 1365,   44,     476,    UI_XSTR_COLOR_GREEN, -1, &Detail_sliders[1][SHIELD_DETAIL_SLIDER].slider },
755                 { "Stars",                                                      1366, 44,       552,    UI_XSTR_COLOR_GREEN, -1, &Detail_sliders[1][NUM_STARS_SLIDER].slider },
756                 { "Lighting",                                           1367, 903,      326,    UI_XSTR_COLOR_GREEN, -1, &Detail_sliders[1][LIGHTING_SLIDER].slider },
757
758                 // main options screen text
759                 { "Briefing Voice",     1368,   23,     93,     UI_XSTR_COLOR_GREEN,    -1, &Options_bogus },
760                 { "Off",                                        1286,   32,     130,    UI_XSTR_COLOR_GREEN,    -1, &Buttons[1][BRIEF_VOICE_OFF].button },
761                 { "On",                                 1285,   134,    130,    UI_XSTR_COLOR_GREEN,    -1, &Buttons[1][BRIEF_VOICE_ON].button },
762                 { "Volume",                             1369,   23,     178,    UI_XSTR_COLOR_GREEN,    -1, &Options_bogus },
763                 { "Effects",                    1370,   33,     209,    UI_XSTR_COLOR_GREEN,    -1, &Options_bogus },
764                 { "Music",                              1371,   33,     264,    UI_XSTR_COLOR_GREEN,    -1, &Options_bogus },
765                 { "Voice",                              1372,   33,     319,    UI_XSTR_COLOR_GREEN,    -1, &Options_bogus },
766                 { "Mouse",                              1373,   23,     399,    UI_XSTR_COLOR_GREEN,    -1, &Options_bogus },
767                 { "Off",                                        1286,   32,     437,    UI_XSTR_COLOR_GREEN,    -1, &Buttons[1][MOUSE_OFF].button },
768                 { "On",                                 1285,   134,    437,    UI_XSTR_COLOR_GREEN,    -1, &Buttons[1][MOUSE_ON].button },
769                 { "Sensitivity",                1529,   34,     477,    UI_XSTR_COLOR_GREEN,    -1, &Options_sliders[1][OPT_MOUSE_SENS_SLIDER].slider },
770                 { "Skill Level",                1509,   854,    93,     UI_XSTR_COLOR_GREEN,    -1, &Options_bogus },
771                 { "Brightness",         1375,   852,    214,    UI_XSTR_COLOR_GREEN,    -1, &Options_bogus },
772                 { "Joystick",                   1376,   891,    370,    UI_XSTR_COLOR_GREEN,    -1, &Options_bogus },
773                 { "Sensitivity",                1374,   861,    400,    UI_XSTR_COLOR_GREEN,    -1, &Options_bogus },
774                 { "Deadzone",                   1377,   861,    451,    UI_XSTR_COLOR_GREEN,    -1, &Options_bogus },
775 #endif
776         }
777 };
778
779
780 //
781 // DETAIL LEVEL tab definitions END
782 // ---------------------------------------------------------------------------------------------------------
783
784 void options_play_voice_clip()
785 {
786         int snd_id;
787
788         if ( snd_is_playing(Voice_vol_handle) ) {
789                 snd_stop(Voice_vol_handle);
790                 Voice_vol_handle=-1;
791         }
792
793         snd_id = snd_load(&Snds_iface[SND_VOICE_SLIDER_CLIP]);
794         Voice_vol_handle = snd_play_raw( snd_id, 0.0f, 1.0f, SND_PRIORITY_SINGLE_INSTANCE );
795 }
796
797 void options_add_notify(char *str)
798 {
799         strcpy(Options_notify_string, str);
800         Options_notify_stamp = timestamp(OPTIONS_NOTIFY_TIME);
801 }
802
803 void options_notify_do_frame()
804 {
805         int w,h;
806
807         if (Options_notify_stamp != -1) {
808                 if (timestamp_elapsed(Options_notify_stamp)) {
809                         Options_notify_stamp = -1;
810
811                 } else {
812                         gr_get_string_size(&w, &h, Options_notify_string);
813                         gr_printf((gr_screen.max_w - w) / 2, OPTIONS_NOTIFY_Y, Options_notify_string);
814                 }
815         }
816 }
817
818 /*
819 void options_set_bmaps(int btn, int bm_index)
820 {
821         int j;
822
823         for (j=0; j<MAX_BMAPS_PER_GADGET; j++){
824                 Buttons[gr_screen.res][btn].button.bmap_ids[j] = Button_bms[bm_index][j];
825         }
826 }
827 */
828
829 void options_tab_setup(int set_palette)
830 {
831         // char *pal;
832         int i;
833         int flags[256];
834
835         if (Tab != MULTIPLAYER_TAB) {
836                 Assert(Backgrounds[gr_screen.res][Tab].mask >= 0);
837                 Ui_window.set_mask_bmap(Backgrounds[gr_screen.res][Tab].mask, Backgrounds[gr_screen.res][Tab].mask_filename);
838         }
839
840         for (i=0; i<256; i++){
841                 flags[i] = 0;
842         }
843
844         // activate, deactivate any necessary controls
845         for (i=0; i<NUM_BUTTONS; i++) {
846                 if ( ((Buttons[gr_screen.res][i].tab == Tab) || (Buttons[gr_screen.res][i].tab == -1)) && !flags[Buttons[gr_screen.res][i].hotspot] ) {
847                         flags[Buttons[gr_screen.res][i].hotspot] = 1;
848                         Buttons[gr_screen.res][i].button.enable();
849                         if (Buttons[gr_screen.res][i].filename)
850                                 Buttons[gr_screen.res][i].button.unhide();
851
852                 } else {
853                         Buttons[gr_screen.res][i].button.disable();
854                         Buttons[gr_screen.res][i].button.hide();
855                 }
856         }
857
858         // maybe enable/disable controls based upon current tab
859         if (Tab == OPTIONS_TAB) {
860                 for(i=0; i<NUM_OPTIONS_SLIDERS; i++){
861                         Options_sliders[gr_screen.res][i].slider.enable();
862                         Options_sliders[gr_screen.res][i].slider.unhide();
863                 }               
864         } else {
865                 for(i=0; i<NUM_OPTIONS_SLIDERS; i++){
866                         Options_sliders[gr_screen.res][i].slider.hide();
867                         Options_sliders[gr_screen.res][i].slider.disable();
868                 }               
869         }       
870
871         if( ((Game_mode & GM_IN_MISSION) && (!popupdead_is_active())) || (Game_mode & GM_MULTIPLAYER) ){
872                 Options_sliders[gr_screen.res][OPT_SKILL_SLIDER].slider.disable();
873                 Ui_window.use_hack_to_get_around_stupid_problem_flag = 0;
874         }
875
876         // do other special processing
877         switch (Tab) {
878                 case MULTIPLAYER_TAB:
879 #if !defined(DEMO) && !defined(OEM_BUILD) // not for FS2_DEMO
880                         options_multi_select();
881 #ifdef MAKE_FS1         
882                         // need to hide the hud config and control config buttons
883                         Buttons[gr_screen.res][CONTROL_CONFIG_BUTTON].button.hide();
884                         Buttons[gr_screen.res][HUD_CONFIG_BUTTON].button.hide();
885 #endif // MAKE_FS1
886 #endif // DEMO
887                         break;
888
889                 case DETAIL_LEVELS_TAB:
890                         options_detail_unhide_stuff();  
891                         break;
892         }
893 }
894
895 // call this function to close down, do other processing of data in the tab that's being left
896 void options_tab_close()
897 {
898         switch (Tab) {
899                 case MULTIPLAYER_TAB:
900 #if !defined(DEMO) && !defined(OEM_BUILD) // not for FS2_DEMO
901                         options_multi_unselect();               
902 #endif
903                         break;
904
905                 case DETAIL_LEVELS_TAB:
906                         options_detail_hide_stuff();
907                         break;
908         }
909 }
910
911 void options_change_tab(int n)
912 {
913         int idx;
914
915 #if defined(DEMO) || defined(OEM_BUILD) // not for FS2_DEMO
916         if (n == MULTIPLAYER_TAB) {
917                 game_feature_not_in_demo_popup();
918                 return;
919         }
920 #endif
921
922         switch (n) {
923                 case MULTIPLAYER_TAB:
924                         if ( !Options_multi_inited ) {
925                                 // init multiplayer
926 #if !defined(DEMO) && !defined(OEM_BUILD) // not for FS2_DEMO
927                                 options_multi_init(&Ui_window);
928                                 options_multi_unselect();
929 #endif
930                                 Options_multi_inited = 1;
931                         }
932
933                         break;
934
935                 case DETAIL_LEVELS_TAB:
936                         if (!Options_detail_inited) {
937                                 // init detail levels
938                                 options_detail_init();
939                                 options_detail_hide_stuff();
940                                 Options_detail_inited = 1;
941                         }
942
943                         break;
944         }
945
946         // if we're going into the main screen
947         if(n == OPTIONS_TAB){
948                 Options_bogus.enable();
949                 Options_bogus.unhide();
950                 for(idx=0; idx<NUM_OPTIONS_SLIDERS; idx++){
951                         Options_sliders[gr_screen.res][idx].slider.enable();
952                         Options_sliders[gr_screen.res][idx].slider.unhide();
953                 }
954         } else {
955                 Options_bogus.hide();
956                 Options_bogus.disable();
957                 for(idx=0; idx<NUM_OPTIONS_SLIDERS; idx++){
958                         Options_sliders[gr_screen.res][idx].slider.hide();
959                         Options_sliders[gr_screen.res][idx].slider.disable();
960                 }
961         }
962
963         if (n != MULTIPLAYER_TAB) {
964                 if (Backgrounds[gr_screen.res][n].mask < 0) {
965                         gamesnd_play_iface(SND_GENERAL_FAIL);
966                         return;
967                 }
968         }
969
970         options_tab_close();
971
972         Tab = n;
973         options_tab_setup(1);
974         gamesnd_play_iface(SND_SCREEN_MODE_PRESSED);
975 }
976
977 void set_sound_volume()
978 {
979         main_hall_reset_ambient_vol();
980 }
981
982 void set_music_volume()
983 {
984         event_music_set_volume_all(Master_event_music_volume);
985 }
986
987 void set_voice_volume()
988 {
989         audiostream_set_volume_all(Master_voice_volume, ASF_VOICE);
990 }
991
992 void options_cancel_exit()
993 {
994         Master_sound_volume = Backup_sound_volume;
995         set_sound_volume();
996         Master_event_music_volume = Backup_music_volume;
997         set_music_volume();
998         Master_voice_volume = Backup_voice_volume;
999         set_voice_volume();
1000
1001         if(!(Game_mode & GM_MULTIPLAYER)){
1002                 Game_skill_level = Backup_skill_level;
1003         }
1004
1005         Briefing_voice_enabled = Backup_briefing_voice_enabled;
1006         Use_mouse_to_fly = Backup_use_mouse_to_fly;
1007
1008         if ( Options_detail_inited ) {
1009                 Detail = Detail_original;
1010         }
1011
1012         gameseq_post_event(GS_EVENT_PREVIOUS_STATE);
1013 }
1014
1015 void options_change_gamma(float delta)
1016 {
1017         char tmp_gamma_string[32];
1018
1019         Freespace_gamma += delta;
1020         if (Freespace_gamma < 0.1f) {
1021                 Freespace_gamma = 0.1f;
1022                 gamesnd_play_iface(SND_GENERAL_FAIL);
1023
1024         } else if (Freespace_gamma > 5.0f) {
1025                 Freespace_gamma = 5.0f;
1026                 gamesnd_play_iface(SND_GENERAL_FAIL);
1027
1028         } else {
1029                 gamesnd_play_iface(SND_USER_SELECT);
1030         }
1031
1032         gr_set_gamma(Freespace_gamma);
1033         sprintf(tmp_gamma_string, NOX("%.2f"), Freespace_gamma);
1034         os_config_write_string(NULL, NOX("Gamma"), tmp_gamma_string);
1035 }
1036
1037 void options_button_pressed(int n)
1038 {
1039         int choice;     
1040
1041         switch (n) {            
1042                 case OPTIONS_TAB:
1043                 case MULTIPLAYER_TAB:
1044                 case DETAIL_LEVELS_TAB: 
1045                         if (Tab != n)
1046                                 options_change_tab(n);
1047
1048                         break;
1049
1050                 case ABORT_GAME_BUTTON:
1051                         gamesnd_play_iface(SND_USER_SELECT);
1052                         choice = popup( PF_NO_NETWORKING | PF_BODY_BIG, 2, POPUP_NO, POPUP_YES, XSTR( "Exit Game?", 374));
1053                         if ( choice == 1 )
1054                                 gameseq_post_event(GS_EVENT_QUIT_GAME);
1055                         break;
1056
1057                 case CONTROL_CONFIG_BUTTON:
1058                         gamesnd_play_iface(SND_SWITCH_SCREENS);
1059                         gameseq_post_event(GS_EVENT_CONTROL_CONFIG);
1060                         break;                          
1061
1062                 case HUD_CONFIG_BUTTON:
1063 #if defined(FS2_DEMO) || defined(FS1_DEMO)
1064                         game_feature_not_in_demo_popup();
1065 #else
1066                         // can't go to the hud config screen when a multiplayer observer
1067                         if((Game_mode & GM_MULTIPLAYER) && (Net_player->flags & NETINFO_FLAG_OBSERVER)){
1068                                 gamesnd_play_iface(SND_GENERAL_FAIL);
1069                                 options_add_notify(XSTR( "Cannot use HUD config when an observer!", 375));
1070                                 break;
1071                         }
1072
1073                         gamesnd_play_iface(SND_SWITCH_SCREENS);
1074                         gameseq_post_event(GS_EVENT_HUD_CONFIG);
1075 #endif
1076                         break;
1077
1078                 case ACCEPT_BUTTON:
1079                         options_accept();
1080                         break;          
1081
1082                         // BEGIN - detail level tab buttons
1083
1084                 case HUD_TARGETVIEW_RENDER_ON:
1085                         Detail.targetview_model = 1;
1086                         gamesnd_play_iface(SND_USER_SELECT);
1087                         break;
1088
1089                 case HUD_TARGETVIEW_RENDER_OFF:
1090                         Detail.targetview_model = 0;
1091                         gamesnd_play_iface(SND_USER_SELECT);
1092                         break;
1093
1094                 case PLANETS_ON:
1095                         Detail.planets_suns = 1;
1096                         gamesnd_play_iface(SND_USER_SELECT);
1097                         break;
1098
1099                 case PLANETS_OFF:
1100                         Detail.planets_suns = 0;
1101                         gamesnd_play_iface(SND_USER_SELECT);
1102                         break;
1103
1104                 case WEAPON_EXTRAS_ON:
1105                         Detail.weapon_extras = 1;
1106                         gamesnd_play_iface(SND_USER_SELECT);
1107                         break;
1108
1109                 case WEAPON_EXTRAS_OFF:
1110                         Detail.weapon_extras = 0;
1111                         gamesnd_play_iface(SND_USER_SELECT);
1112                         break;          
1113
1114 #ifdef MAKE_FS1
1115                 case ENGINE_GLOWS_ON:
1116                         Detail.engine_glows = 1;
1117                         gamesnd_play_iface(SND_USER_SELECT);
1118                         break;
1119                 
1120                 case ENGINE_GLOWS_OFF:
1121                         Detail.engine_glows = 0;
1122                         gamesnd_play_iface(SND_USER_SELECT);
1123                         break;
1124 #endif
1125
1126                 case LOW_DETAIL_N:
1127                         options_detail_set_level(0);
1128                         gamesnd_play_iface(SND_USER_SELECT);
1129                         break;
1130
1131                 case MEDIUM_DETAIL_N:
1132                         options_detail_set_level(1);
1133                         gamesnd_play_iface(SND_USER_SELECT);
1134                         break;
1135
1136                 case HIGH_DETAIL_N:
1137                         options_detail_set_level(2);
1138                         gamesnd_play_iface(SND_USER_SELECT);
1139                         break;
1140
1141                 case VERY_HIGH_DETAIL_N:
1142                         options_detail_set_level(3);
1143                         gamesnd_play_iface(SND_USER_SELECT);
1144                         break;
1145
1146                 case CUSTOM_DETAIL_N:
1147                         options_detail_set_level(-1);
1148                         gamesnd_play_iface(SND_USER_SELECT);
1149                         break;
1150                         // END - detail level tab buttons
1151
1152                 case GAMMA_DOWN:
1153                         options_change_gamma(-0.05f);
1154                         break;
1155
1156                 case GAMMA_UP:
1157                         options_change_gamma(0.05f);
1158                         break;
1159
1160                 case BRIEF_VOICE_ON:
1161                         Briefing_voice_enabled = 1;
1162                         gamesnd_play_iface(SND_USER_SELECT);
1163                         break;
1164
1165                 case BRIEF_VOICE_OFF:
1166                         Briefing_voice_enabled = 0;
1167                         gamesnd_play_iface(SND_USER_SELECT);
1168                         break;
1169
1170                 case MOUSE_ON:
1171                         Use_mouse_to_fly = 1;
1172                         gamesnd_play_iface(SND_USER_SELECT);
1173                         break;
1174
1175                 case MOUSE_OFF:
1176                         Use_mouse_to_fly = 0;
1177                         gamesnd_play_iface(SND_USER_SELECT);
1178                         break;
1179         }
1180 }
1181
1182 void options_sliders_update()
1183 {
1184         // sound slider
1185         if (Options_sliders[gr_screen.res][OPT_SOUND_VOLUME_SLIDER].slider.pos != Sound_volume_int) {
1186                 Sound_volume_int = Options_sliders[gr_screen.res][OPT_SOUND_VOLUME_SLIDER].slider.pos;
1187                 Master_sound_volume = ((float) (Sound_volume_int) / 9.0f);
1188                 set_sound_volume();
1189                 gamesnd_play_iface(SND_USER_SELECT);
1190         }
1191
1192         // music slider
1193         if (Options_sliders[gr_screen.res][OPT_MUSIC_VOLUME_SLIDER].slider.pos != Music_volume_int) {
1194                 Music_volume_int = Options_sliders[gr_screen.res][OPT_MUSIC_VOLUME_SLIDER].slider.pos;
1195                 Master_event_music_volume = ((float) (Music_volume_int) / 9.0f);
1196                 if (Master_event_music_volume > 0.0f) {
1197                         event_music_enable();
1198                 }
1199
1200                 set_music_volume();
1201                 gamesnd_play_iface(SND_USER_SELECT);
1202         }
1203
1204         // voice slider
1205         if (Options_sliders[gr_screen.res][OPT_VOICE_VOLUME_SLIDER].slider.pos != Voice_volume_int) {
1206                 Voice_volume_int = Options_sliders[gr_screen.res][OPT_VOICE_VOLUME_SLIDER].slider.pos;
1207                 Master_voice_volume = ((float) (Voice_volume_int) / 9.0f);
1208                 set_voice_volume();
1209                 options_play_voice_clip();
1210         }
1211
1212         if (Mouse_sensitivity != Options_sliders[gr_screen.res][OPT_MOUSE_SENS_SLIDER].slider.pos) {
1213                 Mouse_sensitivity = Options_sliders[gr_screen.res][OPT_MOUSE_SENS_SLIDER].slider.pos;
1214                 gamesnd_play_iface(SND_USER_SELECT);
1215         }
1216
1217         if (Joy_sensitivity != Options_sliders[gr_screen.res][OPT_JOY_SENS_SLIDER].slider.pos) {
1218                 Joy_sensitivity = Options_sliders[gr_screen.res][OPT_JOY_SENS_SLIDER].slider.pos;
1219                 gamesnd_play_iface(SND_USER_SELECT);
1220         }
1221
1222         if (Dead_zone_size != Options_sliders[gr_screen.res][OPT_JOY_DEADZONE_SLIDER].slider.pos * 5) {
1223                 Dead_zone_size = Options_sliders[gr_screen.res][OPT_JOY_DEADZONE_SLIDER].slider.pos * 5;
1224                 gamesnd_play_iface(SND_USER_SELECT);
1225         }
1226
1227         if (Game_skill_level != Options_sliders[gr_screen.res][OPT_SKILL_SLIDER].slider.pos) {
1228                 Game_skill_level = Options_sliders[gr_screen.res][OPT_SKILL_SLIDER].slider.pos;
1229                 gamesnd_play_iface(SND_USER_SELECT);
1230         }
1231 }
1232
1233 void options_accept()
1234 {
1235         // apply the selected multiplayer options
1236         if ( Options_multi_inited ) {
1237                 #if !defined(DEMO) && !defined(OEM_BUILD) // not for FS2_DEMO
1238                 options_multi_accept();
1239                 #endif
1240         }
1241
1242         // If music is zero volume, disable
1243         if ( Master_event_music_volume <= 0.0f ) {
1244 //              event_music_disable();
1245                 event_music_level_close();
1246         }
1247
1248         // apply other options (display options, etc)
1249         // note: return in here (and play failed sound) if they can't accept yet for some reason
1250
1251         gamesnd_play_iface(SND_COMMIT_PRESSED);
1252         gameseq_post_event(GS_EVENT_PREVIOUS_STATE);
1253 }
1254
1255 void options_load_background_and_mask(int tab)
1256 {
1257         Assert(tab == OPTIONS_TAB || tab == DETAIL_LEVELS_TAB );
1258         Backgrounds[gr_screen.res][tab].bitmap = bm_load(Backgrounds[gr_screen.res][tab].filename);
1259         Backgrounds[gr_screen.res][tab].mask = bm_load(Backgrounds[gr_screen.res][tab].mask_filename);
1260 }
1261
1262 int Gamma_last_set = -1;
1263 int Gamma_colors_inited = 0;
1264
1265 void options_menu_init()
1266 {
1267         int i, j;
1268         options_buttons *b;
1269
1270         Assert(!Options_menu_inited);
1271
1272         // pause all sounds, since we could get here through the game
1273         beam_pause_sounds();
1274         //audiostream_pause_all();
1275
1276         Tab = 0;
1277         Gamma_last_set = -1;
1278
1279         common_set_interface_palette("InterfacePalette");  // set the interface palette
1280         Ui_window.create(0, 0, gr_screen.max_w, gr_screen.max_h, 0);
1281
1282         for (i=0; i<PLANETS_ON; i++) {
1283                 b = &Buttons[gr_screen.res][i];
1284
1285                 b->button.create(&Ui_window, "", b->x, b->y, 60, 30, b->flags & REPEAT, 1);
1286                 // set up callback for when a mouse first goes over a button
1287                 if (b->filename) {
1288                         b->button.set_bmaps(b->filename);
1289                         if ( !(b->flags & NO_MOUSE_OVER_SOUND) ) {
1290                                 b->button.set_highlight_action(common_play_highlight_sound);
1291                         }
1292
1293                 } else {
1294                         b->button.hide();
1295                 }
1296
1297                 b->button.link_hotspot(b->hotspot);
1298                 if (i < NUM_COMMONS) {
1299                         for (j=0; j<MAX_BMAPS_PER_GADGET; j++){
1300                                 Button_bms[i][j] = b->button.bmap_ids[j];
1301                         }
1302                 }
1303         }
1304
1305         // add all xstr text
1306         for(i=0; i<OPTIONS_NUM_TEXT; i++){
1307                 Ui_window.add_XSTR(&Options_text[gr_screen.res][i]);
1308         }
1309
1310         // bogus controls
1311         Detail_bogus.base_create(&Ui_window, UI_KIND_ICON, 0, 0, 0, 0);
1312         Options_bogus.base_create(&Ui_window, UI_KIND_ICON, 0, 0, 0, 0);
1313
1314         Buttons[gr_screen.res][GAMMA_DOWN].button.set_hotkey(KEY_COMMA);
1315         Buttons[gr_screen.res][GAMMA_UP].button.set_hotkey(KEY_PERIOD);
1316
1317         /*
1318         Skill_control.first_frame = bm_load_animation("OPa_11", &Skill_control.total_frames);
1319         if (Skill_control.first_frame < 0) {
1320                 Error(LOCATION, "Could not load OPa_11.ani\n");
1321                 return;
1322         }
1323         */
1324
1325         for (i=0; i<NUM_TABS; i++) {
1326                 Backgrounds[gr_screen.res][i].bitmap = -1;
1327                 Backgrounds[gr_screen.res][i].mask = -1;
1328         }
1329
1330         options_load_background_and_mask(OPTIONS_TAB);
1331         options_tab_setup(0);
1332
1333         Backup_skill_level = Game_skill_level;
1334         Backup_sound_volume = Master_sound_volume;
1335         Backup_music_volume = Master_event_music_volume;
1336         Backup_voice_volume = Master_voice_volume;
1337         Backup_briefing_voice_enabled = Briefing_voice_enabled;
1338         Backup_use_mouse_to_fly = Use_mouse_to_fly;
1339         
1340         // create slider        
1341         for ( i = 0; i < NUM_OPTIONS_SLIDERS; i++ ) {
1342                  Options_sliders[gr_screen.res][i].slider.create(&Ui_window, Options_sliders[gr_screen.res][i].x, Options_sliders[gr_screen.res][i].y,
1343                                                                                                                                                 Options_sliders[gr_screen.res][i].dots, Options_sliders[gr_screen.res][i].filename,
1344                                                                                                                                                 Options_sliders[gr_screen.res][i].hotspot, Options_sliders[gr_screen.res][i].right_filename, Options_sliders[gr_screen.res][i].right_mask, Options_sliders[gr_screen.res][i].right_x, Options_sliders[gr_screen.res][i].right_y,
1345                                                                                                                                                 Options_sliders[gr_screen.res][i].left_filename, Options_sliders[gr_screen.res][i].left_mask, Options_sliders[gr_screen.res][i].left_x, Options_sliders[gr_screen.res][i].left_y,
1346                                                                                                                                                 Options_sliders[gr_screen.res][i].dot_w);
1347         }       
1348
1349         // maybe disable the skill slider
1350         if( ((Game_mode & GM_IN_MISSION) && (!popupdead_is_active())) || (Game_mode & GM_MULTIPLAYER) ) {
1351                 Options_sliders[gr_screen.res][OPT_SKILL_SLIDER].slider.disable();
1352                 Ui_window.use_hack_to_get_around_stupid_problem_flag = 0;
1353         }
1354         
1355         // setup slider values 
1356         // note slider scale is 0-9, while Master_ values calc with 1-10 scale (hence the -1)
1357         Sound_volume_int = Options_sliders[gr_screen.res][OPT_SOUND_VOLUME_SLIDER].slider.pos = (int) (Master_sound_volume * 9.0f + 0.5f);
1358         Music_volume_int = Options_sliders[gr_screen.res][OPT_MUSIC_VOLUME_SLIDER].slider.pos = (int) (Master_event_music_volume * 9.0f + 0.5f);        
1359         Voice_volume_int = Options_sliders[gr_screen.res][OPT_VOICE_VOLUME_SLIDER].slider.pos = (int) (Master_voice_volume * 9.0f + 0.5f);
1360         Options_sliders[gr_screen.res][OPT_JOY_SENS_SLIDER].slider.pos = Joy_sensitivity;       
1361         Options_sliders[gr_screen.res][OPT_JOY_DEADZONE_SLIDER].slider.pos = Dead_zone_size / 5;        
1362         Options_sliders[gr_screen.res][OPT_MOUSE_SENS_SLIDER].slider.pos = Mouse_sensitivity;
1363         Options_sliders[gr_screen.res][OPT_SKILL_SLIDER].slider.pos = Game_skill_level;
1364
1365         Gamma_colors_inited = 0;
1366
1367         // used to allow all keystrokes, even when called from a demo playback
1368         key_clear_filter();
1369         Options_menu_inited = 1;
1370
1371         // hide options crap
1372         options_detail_hide_stuff();
1373 }
1374
1375 void options_menu_close()
1376 {
1377         int i;  
1378
1379         Assert(Options_menu_inited);    
1380
1381         for (i=0; i<NUM_TABS; i++) {
1382                 if (Backgrounds[gr_screen.res][i].bitmap >= 0){
1383                         bm_unload(Backgrounds[gr_screen.res][i].bitmap);
1384                 }
1385                 if ((Backgrounds[gr_screen.res][i].mask >= 0) && (i != Tab)){  // Ui_window.destroy() expects to release current tab's mask.
1386                         bm_unload(Backgrounds[gr_screen.res][i].mask);
1387                 }
1388         }
1389
1390         if ( Voice_vol_handle >= 0 ) {
1391                 snd_stop(Voice_vol_handle);
1392                 Voice_vol_handle = -1;
1393         }
1394
1395 #if !defined(DEMO) && !defined(OEM_BUILD) // not for FS2_DEMO
1396         options_multi_close();
1397 #endif
1398
1399         Ui_window.destroy();
1400         common_free_interface_palette();                // restore game palette
1401         write_pilot_file();
1402         game_flush();
1403         
1404         // unpause all sounds, since we could be headed back to the game
1405         beam_unpause_sounds();
1406         //audiostream_unpause_all();
1407         
1408         Options_menu_inited = 0;
1409         Options_multi_inited = 0;
1410         Options_detail_inited = 0;
1411
1412
1413 }
1414
1415
1416 void draw_gamma_box()
1417 {
1418         int x, y, v;
1419
1420 // NEILK: i had to change this declaration because the size is determined dynamically. I just picked an arbitrary large number to data size (although we should always be using less)
1421 // TODO: change MAX size to maximum size for a 1024x768 bitmap
1422 //      ushort Gamma_data[Options_gamma_coords[gr_screen.res][OPTIONS_W_COORD]*Options_gamma_coords[gr_screen.res][OPTIONS_H_COORD]*2];
1423         ushort Gamma_data[MAX_GAMMA_BITMAP_SIZE];
1424
1425         v = fl2i( pow(0.5f, 1.0f / Freespace_gamma) * 255.0f );
1426         if (v > 255){
1427                 v = 255;
1428         } else if (v < 0){
1429                 v = 0;
1430         }
1431
1432         int Gamma_changed = 0;
1433         if ( v != Gamma_last_set )      {
1434                 Gamma_changed = 1;
1435         } else {
1436                 Gamma_changed = 0;
1437         }
1438         Gamma_last_set = v;
1439
1440         {
1441                 ushort clr_full_white = 0;
1442                 ushort clr_half_white = 0;
1443                 ubyte r, g, b, a;
1444
1445                 // if we're in bitmap poly mode
1446                 if(Gr_bitmap_poly){
1447                         BM_SELECT_TEX_FORMAT();
1448                 } else {
1449                         BM_SELECT_SCREEN_FORMAT();
1450                 }
1451
1452                 // set full white
1453                 r = g = b = a = 255;            
1454                 bm_set_components((ubyte*)&clr_full_white, &r, &g, &b, &a);
1455
1456                 // set half white
1457                 r = g = b = (ubyte)v;
1458                 bm_set_components((ubyte*)&clr_half_white, &r, &g, &b, &a);
1459
1460                 ushort *dptr = Gamma_data;
1461                 for (y=0; y<Options_gamma_coords[gr_screen.res][OPTIONS_H_COORD]; y++) {
1462                         for (x=0; x<Options_gamma_coords[gr_screen.res][OPTIONS_W_COORD]; x++) {
1463                                 if ((x / 20) & 1) {
1464                                         *dptr = clr_half_white;
1465                                 } else {
1466                                         if ((x & 1) == (y & 1)) {
1467                                                 *dptr = clr_full_white;
1468                                         } else {
1469                                                 *dptr = 0;
1470                                         }
1471                                 }
1472                                 dptr++;
1473                         }
1474                 }
1475
1476                 // always go back to screen format
1477                 BM_SELECT_SCREEN_FORMAT();
1478
1479                 // if we're in bitmap poly mode         
1480                 int Gamma_bitmap = bm_create( 16, Options_gamma_coords[gr_screen.res][OPTIONS_W_COORD], Options_gamma_coords[gr_screen.res][OPTIONS_H_COORD], Gamma_data );
1481                 gr_set_bitmap(Gamma_bitmap, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
1482                 gr_bitmap( Options_gamma_coords[gr_screen.res][OPTIONS_X_COORD], Options_gamma_coords[gr_screen.res][OPTIONS_Y_COORD] );
1483
1484                 bm_release( Gamma_bitmap );
1485
1486         }
1487 }
1488
1489
1490 void options_menu_do_frame(float frametime)
1491 {
1492         int i, k, x, y; 
1493
1494         Assert(Options_menu_inited);
1495         k = Ui_window.process() & ~KEY_DEBUGGED;
1496         switch (k) {
1497                 case KEY_SHIFTED | KEY_TAB:
1498                 case KEY_LEFT:  // activate previous tab
1499                         i = Tab - 1;
1500                         if (i < 0)
1501                                 i = NUM_TABS - 1;
1502
1503                         options_change_tab(i);
1504                         break;
1505
1506                 case KEY_TAB:
1507                 case KEY_RIGHT:  // activate next tab
1508                         // check to see if the multiplayer options screen wants to eat the tab kay
1509                         if ((k == KEY_TAB) && (Tab == MULTIPLAYER_TAB)) {
1510                                 if (options_multi_eat_tab()) {
1511                                         break;
1512                                 }
1513                         }
1514
1515                         i = Tab + 1;
1516                         if (i >= NUM_TABS)
1517                                 i = 0;
1518
1519                         options_change_tab(i);
1520                         break;
1521
1522                 case KEY_C:
1523                         if (Tab == OPTIONS_TAB) {
1524                                 gamesnd_play_iface(SND_SWITCH_SCREENS);
1525                                 gameseq_post_event(GS_EVENT_CONTROL_CONFIG);
1526                         }
1527
1528                         break;
1529
1530                 case KEY_H:
1531                         if (Tab == OPTIONS_TAB) {
1532                                 gamesnd_play_iface(SND_SWITCH_SCREENS);
1533                                 gameseq_post_event(GS_EVENT_HUD_CONFIG);
1534                         }
1535
1536                         break;
1537
1538                 case KEY_ESC:
1539                         // if(Tab != MULTIPLAYER_TAB){
1540                                 options_cancel_exit();
1541                         // }
1542                         break;
1543
1544                 case KEY_CTRLED | KEY_ENTER:
1545                         options_accept();
1546                         break;
1547
1548                 case KEY_DELETE:
1549                         break;
1550
1551                 case KEY_ENTER:                 
1552                         break;
1553         }       
1554
1555         for (i=0; i<NUM_BUTTONS; i++) {
1556                 if (Buttons[gr_screen.res][i].button.pressed())
1557                         options_button_pressed(i);
1558         }
1559
1560         options_sliders_update();
1561
1562         // if we're in the multiplayer options tab, get the background bitmap from the options multi module
1563         if(Tab == MULTIPLAYER_TAB){
1564                 i = options_multi_background_bitmap();
1565         } else {
1566                 i = Backgrounds[gr_screen.res][Tab].bitmap;
1567         }
1568
1569         GR_MAYBE_CLEAR_RES(i);
1570         if (i >= 0) {
1571                 gr_set_bitmap(i, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
1572                 gr_bitmap(0, 0);
1573         } 
1574
1575         Ui_window.draw();
1576
1577         // NOTE : this must be done here so that any special drawing crap we do is not overwritten by the UI_WINDOW::draw() call
1578         // do specific processing for the multiplayer tab
1579         switch (Tab) {
1580                 case MULTIPLAYER_TAB:
1581 #if !defined(DEMO) && !defined(OEM_BUILD) // not for FS2_DEMO
1582                         options_multi_do(k);
1583 #endif
1584                         break;
1585
1586                 case DETAIL_LEVELS_TAB:
1587                         options_detail_do_frame();
1588                         break;
1589
1590                 default:
1591                         Game_skill_level = Options_sliders[gr_screen.res][OPT_SKILL_SLIDER].slider.pos;
1592                         break;
1593         }
1594
1595         // handle the displaying of any notification messages
1596         options_notify_do_frame();
1597
1598         for (i=0; i<NUM_TABS; i++){
1599                 if (Buttons[gr_screen.res][i].button.button_down()){
1600                         break;
1601                 }
1602         }
1603
1604         if ((i == NUM_TABS) /*&& (Tab != MULTIPLAYER_TAB)*/ ){
1605                 Buttons[gr_screen.res][Tab].button.draw_forced(2);
1606         }
1607
1608         if (Tab == OPTIONS_TAB) {
1609                 // draw correct frame for briefing voice radio buttons
1610                 if (Briefing_voice_enabled) {
1611                         options_force_button_frame(BRIEF_VOICE_ON, 2);
1612                         options_force_button_frame(BRIEF_VOICE_OFF, 0);
1613
1614                 } else {
1615                         options_force_button_frame(BRIEF_VOICE_OFF, 2);
1616                         options_force_button_frame(BRIEF_VOICE_ON, 0);
1617                 }
1618
1619                 if (Use_mouse_to_fly) {
1620                         options_force_button_frame(MOUSE_ON, 2);
1621                         options_force_button_frame(MOUSE_OFF, 0);
1622
1623                 } else {
1624                         options_force_button_frame(MOUSE_OFF, 2);
1625                         options_force_button_frame(MOUSE_ON, 0);
1626                 }               
1627
1628                 int w;
1629                 gr_get_string_size(&w, NULL, Skill_level_names(Game_skill_level));
1630                 x = Options_skills_text_coords[gr_screen.res][OPTIONS_X_COORD];
1631                 y = Options_skills_text_coords[gr_screen.res][OPTIONS_Y_COORD];
1632                 gr_set_color_fast(&Color_bright_white);
1633                 gr_string(x + (Options_skills_text_coords[gr_screen.res][OPTIONS_W_COORD] / 2) - (w/2), y, Skill_level_names(Game_skill_level));
1634         }
1635
1636         
1637         //==============================================================================
1638         // Draw the gamma adjustment grid.
1639         if (Tab == OPTIONS_TAB) {
1640
1641                 draw_gamma_box();
1642                 
1643                 gr_set_color_fast(&Color_white);
1644                 x = Options_gamma_num_coords[gr_screen.res][OPTIONS_X_COORD]; //  + Options_gamma_num_coords[gr_screen.res][OPTIONS_W_COORD] / 2 - 12;
1645                 y = Options_gamma_num_coords[gr_screen.res][OPTIONS_Y_COORD]; // + Options_gamma_num_coords[gr_screen.res][OPTIONS_H_COORD] / 2 - gr_get_font_height() / 2;
1646
1647                 gr_printf(x, y, NOX("%.2f"), Freespace_gamma);
1648                 //gr_printf(GAMMA_TEXT_X, GAMMA_TEXT_Y, "Squint and try to make the above\nbar appear to be one solid color.\nThere are more 'ranges' to see\nif you set this in Glide mode.");
1649         }
1650         //==============================================================================
1651
1652         // maybe blit a waveform
1653         if(Tab == MULTIPLAYER_TAB){
1654                 options_multi_vox_process_waveform();
1655         }
1656         
1657 /*  Debug code: Graphs the joystick range scaling
1658 {
1659 int joy_get_scaled_reading(int raw, int axn);
1660         int x, y;
1661
1662         gr_set_color_fast(&Color_white);
1663         for (x=0; x<256; x+=16) {
1664                 gr_line(x + 15, 0, x + 15, 255);
1665                 gr_line(0, x + 15, 255, x + 15);
1666         }
1667
1668         gr_set_color_fast(&Color_bright_white);
1669         for (x=0; x<256; x++) {
1670                 y = joy_get_scaled_reading(x * 256, 0) / 512;
1671                 gr_line(x, 128, x, 128 + y);
1672         }
1673 }*/     
1674
1675         gr_flip();
1676 }
1677
1678
1679 // ---------------------------------------------------------------------------------------------------------
1680 // DETAIL LEVEL OPTIONS definitions  BEGIN
1681 //
1682
1683 void options_detail_synch_sliders()
1684 {
1685         Detail_slider_pos[DETAIL_DISTANCE_SLIDER] = Detail_sliders[gr_screen.res][DETAIL_DISTANCE_SLIDER].slider.pos = Detail.detail_distance;
1686         Detail_slider_pos[NEBULA_DETAIL_SLIDER] = Detail_sliders[gr_screen.res][NEBULA_DETAIL_SLIDER].slider.pos = Detail.nebula_detail;
1687         Detail_slider_pos[HARDWARE_TEXTURES_SLIDER] = Detail_sliders[gr_screen.res][HARDWARE_TEXTURES_SLIDER].slider.pos = Detail.hardware_textures;    
1688         Detail_slider_pos[SHARD_CULLING_SLIDER] = Detail_sliders[gr_screen.res][SHARD_CULLING_SLIDER].slider.pos = Detail.num_small_debris;
1689         Detail_slider_pos[SHIELD_DETAIL_SLIDER] = Detail_sliders[gr_screen.res][SHIELD_DETAIL_SLIDER].slider.pos = Detail.shield_effects;
1690         Detail_slider_pos[NUM_STARS_SLIDER] = Detail_sliders[gr_screen.res][NUM_STARS_SLIDER].slider.pos = Detail.num_stars;
1691         Detail_slider_pos[NUM_PARTICLES_SLIDER] = Detail_sliders[gr_screen.res][NUM_PARTICLES_SLIDER].slider.pos = Detail.num_particles;
1692         Detail_slider_pos[LIGHTING_SLIDER] = Detail_sliders[gr_screen.res][LIGHTING_SLIDER].slider.pos = Detail.lighting;
1693 }
1694
1695 void options_detail_init()
1696 {
1697         int i;
1698         options_buttons *b;
1699
1700         Detail_original = Detail;
1701
1702         options_load_background_and_mask(DETAIL_LEVELS_TAB);
1703
1704         for (i=PLANETS_ON; i<NUM_BUTTONS; i++) {
1705                 b = &Buttons[gr_screen.res][i];
1706
1707                 b->button.create(&Ui_window, "", b->x, b->y, 60, 30, b->flags & REPEAT, 1);
1708                 // set up callback for when a mouse first goes over a button
1709                 if (b->filename) {
1710                         b->button.set_bmaps(b->filename);
1711                         if ( !(b->flags & NO_MOUSE_OVER_SOUND) ) {
1712                                 b->button.set_highlight_action(common_play_highlight_sound);
1713                         }
1714
1715                 } else {
1716                         b->button.hide();
1717                 }
1718
1719                 b->button.link_hotspot(b->hotspot);
1720         }
1721
1722         // create detail level sliders  
1723         for ( i = 0; i < NUM_DETAIL_SLIDERS; i++ ) {
1724                 Detail_sliders[gr_screen.res][i].slider.create(&Ui_window, Detail_sliders[gr_screen.res][i].x, Detail_sliders[gr_screen.res][i].y,
1725                                                                                                                                                 Detail_sliders[gr_screen.res][i].dots, Detail_sliders[gr_screen.res][i].filename,
1726                                                                                                                                                 Detail_sliders[gr_screen.res][i].hotspot, Detail_sliders[gr_screen.res][i].right_filename, Detail_sliders[gr_screen.res][i].right_mask, Detail_sliders[gr_screen.res][i].right_x, Detail_sliders[gr_screen.res][i].right_y,
1727                                                                                                                                                 Detail_sliders[gr_screen.res][i].left_filename, Detail_sliders[gr_screen.res][i].left_mask, Detail_sliders[gr_screen.res][i].left_x, Detail_sliders[gr_screen.res][i].left_y,
1728                                                                                                                                                 Detail_sliders[gr_screen.res][i].dot_w);
1729         }
1730
1731         // init the actual slider positions and our internal positions
1732         options_detail_synch_sliders();
1733 }
1734
1735 void options_detail_sliders_update()
1736 {
1737         int i;
1738
1739         for ( i = 0; i < NUM_DETAIL_SLIDERS; i++ ) {
1740                 if ( Detail_sliders[gr_screen.res][i].slider.pos != Detail_slider_pos[i] ) {
1741                         Detail_slider_pos[i] = Detail_sliders[gr_screen.res][i].slider.pos;
1742                         gamesnd_play_iface(SND_USER_SELECT);
1743                 }
1744         }
1745
1746         // set Detail based on slider positions
1747         Detail.detail_distance = Detail_sliders[gr_screen.res][DETAIL_DISTANCE_SLIDER].slider.pos;
1748
1749         // modify nebula stuff
1750         Detail.nebula_detail = Detail_sliders[gr_screen.res][NEBULA_DETAIL_SLIDER].slider.pos;
1751         neb2_set_detail_level(Detail.nebula_detail);
1752
1753         Detail.hardware_textures = Detail_sliders[gr_screen.res][HARDWARE_TEXTURES_SLIDER].slider.pos;  
1754         Detail.num_small_debris = Detail_sliders[gr_screen.res][SHARD_CULLING_SLIDER].slider.pos;
1755         Detail.shield_effects = Detail_sliders[gr_screen.res][SHIELD_DETAIL_SLIDER].slider.pos;
1756         Detail.num_stars = Detail_sliders[gr_screen.res][NUM_STARS_SLIDER].slider.pos;
1757         Detail.num_particles = Detail_sliders[gr_screen.res][NUM_PARTICLES_SLIDER].slider.pos;
1758         Detail.lighting = Detail_sliders[gr_screen.res][LIGHTING_SLIDER].slider.pos;
1759 }
1760
1761 void options_detail_hide_stuff()
1762 {
1763         int i;
1764
1765         for ( i = 0; i < NUM_DETAIL_SLIDERS; i++ ) {
1766                 Detail_sliders[gr_screen.res][i].slider.disable();
1767                 Detail_sliders[gr_screen.res][i].slider.hide();
1768         }
1769
1770         // this will hide text unassociated with any real control
1771         Detail_bogus.hide();
1772 }
1773
1774 void options_detail_unhide_stuff()
1775 {
1776         int i;
1777
1778         for ( i = 0; i < NUM_DETAIL_SLIDERS; i++ ) {
1779                 Detail_sliders[gr_screen.res][i].slider.enable();
1780                 Detail_sliders[gr_screen.res][i].slider.unhide();
1781         }
1782
1783         // this will hide text unassociated with any real control
1784         Detail_bogus.unhide();
1785 }
1786
1787 void options_force_button_frame(int n, int frame_num)
1788 {
1789         if ( !Buttons[gr_screen.res][n].button.button_down() ) {
1790                 Buttons[gr_screen.res][n].button.draw_forced(frame_num);
1791         }
1792 }
1793
1794 // called once per frame to set lit buttons
1795 void options_detail_do_frame()
1796 {
1797         options_detail_sliders_update();        
1798
1799         // force on/off buttons to draw their correct setting
1800
1801         if ( Detail.targetview_model ) {
1802                 options_force_button_frame(HUD_TARGETVIEW_RENDER_ON, 2);
1803                 options_force_button_frame(HUD_TARGETVIEW_RENDER_OFF, 0);
1804         } else {
1805                 options_force_button_frame(HUD_TARGETVIEW_RENDER_OFF, 2);
1806                 options_force_button_frame(HUD_TARGETVIEW_RENDER_ON, 0);
1807         }
1808
1809         if ( Detail.planets_suns == 1 ) {
1810                 options_force_button_frame(PLANETS_ON, 2);
1811                 options_force_button_frame(PLANETS_OFF, 0);
1812         } else {
1813                 options_force_button_frame(PLANETS_OFF, 2);
1814                 options_force_button_frame(PLANETS_ON, 0);
1815         }
1816
1817         if ( Detail.weapon_extras) {
1818                 options_force_button_frame(WEAPON_EXTRAS_ON, 2);
1819                 options_force_button_frame(WEAPON_EXTRAS_OFF, 0);
1820         } else {
1821                 options_force_button_frame(WEAPON_EXTRAS_OFF, 2);
1822                 options_force_button_frame(WEAPON_EXTRAS_ON, 0);
1823         }       
1824
1825 #ifdef MAKE_FS1
1826         if ( Detail.engine_glows) {
1827                 options_force_button_frame(ENGINE_GLOWS_ON, 2);
1828                 options_force_button_frame(ENGINE_GLOWS_OFF, 0);
1829         } else {
1830                 options_force_button_frame(ENGINE_GLOWS_OFF, 2);
1831                 options_force_button_frame(ENGINE_GLOWS_ON, 0);
1832         }
1833 #endif
1834
1835         int current_detail;
1836
1837         if ( Detail.setting >= 0 ) {
1838                 current_detail = current_detail_level();
1839                 Detail.setting = current_detail;
1840         } else {
1841                 current_detail = -1;
1842         }
1843
1844         options_force_button_frame(LOW_DETAIL_N, 0);
1845         options_force_button_frame(MEDIUM_DETAIL_N, 0);
1846         options_force_button_frame(HIGH_DETAIL_N, 0);
1847         options_force_button_frame(VERY_HIGH_DETAIL_N, 0);
1848         options_force_button_frame(CUSTOM_DETAIL_N, 0);
1849
1850         switch ( current_detail ) {
1851         case -1:
1852                 options_force_button_frame(CUSTOM_DETAIL_N, 2);
1853                 break;
1854         case 0:
1855                 options_force_button_frame(LOW_DETAIL_N, 2);
1856                 break;
1857         case 1:
1858                 options_force_button_frame(MEDIUM_DETAIL_N, 2);
1859                 break;
1860         case 2:
1861                 options_force_button_frame(HIGH_DETAIL_N, 2);
1862                 break;
1863         case 3:
1864                 options_force_button_frame(VERY_HIGH_DETAIL_N, 2);
1865                 break;
1866         }
1867 }
1868
1869 // Set all the detail settings to a predefined level
1870 void options_detail_set_level(int level)
1871 {
1872         detail_level_set(level);
1873         options_detail_synch_sliders();
1874 }
1875
1876 //
1877 // DETAIL LEVEL tab definitions END
1878 // ---------------------------------------------------------------------------------------------------------
1879
1880