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