]> icculus.org git repositories - taylor/freespace2.git/blob - src/menuui/optionsmenu.cpp
Various 64-bit platform 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.6  2005/03/29 02:18:47  taylor
19  * Various 64-bit platform fixes
20  * Fix compiler errors with MAKE_FS1 and fix gr_set_bitmap() too
21  * Make sure that turrets can fire at asteroids for FS1 (needed for a couple missions)
22  * Streaming audio support (big thanks to Pierre Willenbrock!!)
23  * Removed dependance on strings.tbl for FS1 since we don't actually need it now
24  *
25  * Revision 1.5  2004/09/20 01:31:44  theoddone33
26  * GCC 3.4 fixes.
27  *
28  * Revision 1.4  2003/05/25 02:30:42  taylor
29  * Freespace 1 support
30  *
31  * Revision 1.3  2002/06/09 04:41:22  relnev
32  * added copyright header
33  *
34  * Revision 1.2  2002/05/26 22:06:17  relnev
35  * makefile: disable stand_gui for now.
36  *
37  * rest: staticize some globals
38  *
39  * Revision 1.1.1.1  2002/05/03 03:28:09  root
40  * Initial import.
41  *
42  * 
43  * 31    10/25/99 5:47p Jefff
44  * reassigned some xstr ids
45  * 
46  * 30    10/14/99 2:50p Jefff
47  * localization fixes
48  * 
49  * 29    9/13/99 6:07p Jefff
50  * took out audiostream pausing to allow for correct volume adjustments
51  * 
52  * 28    9/09/99 2:28p Jefff
53  * some detail slider #defines were switched around
54  * 
55  * 27    9/08/99 2:38p Jefff
56  * sound pausing going to menu from game
57  * 
58  * 26    8/05/99 3:40p Jefff
59  * hi-res text adjustments
60  * 
61  * 25    8/04/99 4:06p Jefff
62  * fixed volume sliders blacking out at master volume of 1.0
63  * 
64  * 24    8/02/99 6:05p Jefff
65  * failure sound on skill slider when disabled in game
66  * 
67  * 23    7/19/99 3:29p Dave
68  * Fixed gamma bitmap in the options screen.
69  * 
70  * 22    7/19/99 2:13p Dave
71  * Added some new strings for Heiko.
72  * 
73  * 21    7/18/99 9:54p Andsager
74  * Demo build clean up
75  * 
76  * 20    7/15/99 7:15p Jefff
77  * Added sounds for skill select
78  * 
79  * 19    7/15/99 4:10p Andsager
80  * Disable control_config hud_config in FS2_DEMO
81  * 
82  * 18    7/15/99 9:20a Andsager
83  * FS2_DEMO initial checkin
84  * 
85  * 17    7/13/99 1:15p Dave
86  * 32 bit support. Whee!
87  * 
88  * 16    7/09/99 5:54p Dave
89  * Seperated cruiser types into individual types. Added tons of new
90  * briefing icons. Campaign screen.
91  * 
92  * 15    6/25/99 11:59a Dave
93  * Multi options screen.
94  * 
95  * 14    6/24/99 12:34a Dave
96  * Main options screen.
97  * 
98  * 13    6/22/99 7:03p Dave
99  * New detail options screen.
100  * 
101  * 12    6/16/99 4:06p Dave
102  * New pilot info popup. Added new draw-bitmap-as-poly function.
103  * 
104  * 11    5/24/99 5:45p Dave
105  * Added detail levels to the nebula, with a decent speedup. Split nebula
106  * lightning into its own section.
107  * 
108  * 10    4/02/99 4:44p Jasenw
109  * 
110  * 9     2/05/99 7:22p Neilk
111  * Fixed gamma bitmap and converted coordinates for multiple resolutions
112  * 
113  * 8     1/30/99 5:08p Dave
114  * More new hi-res stuff.Support for nice D3D textures.
115  * 
116  * 7     12/18/98 1:13a Dave
117  * Rough 1024x768 support for Direct3D. Proper detection and usage through
118  * the launcher.
119  * 
120  * 6     11/30/98 1:07p Dave
121  * 16 bit conversion, first run.
122  * 
123  * 5     11/05/98 5:55p Dave
124  * Big pass at reducing #includes
125  * 
126  * 4     10/13/98 9:28a Dave
127  * Started neatening up freespace.h. Many variables renamed and
128  * reorganized. Added AlphaColors.[h,cpp]
129  * 
130  * 3     10/09/98 2:57p Dave
131  * Starting splitting up OS stuff.
132  * 
133  * 2     10/07/98 10:53a Dave
134  * Initial checkin.
135  * 
136  * 1     10/07/98 10:49a Dave
137  * 
138  * 123   6/12/98 7:13p Hoffoss
139  * Fixed options screen problem where it wasn't showing tooltips.
140  * 
141  * 122   6/12/98 4:52p Hoffoss
142  * Added support for special characters in in forgeign languages.
143  * 
144  * 121   6/09/98 10:31a Hoffoss
145  * Created index numbers for all xstr() references.  Any new xstr() stuff
146  * added from here on out should be added to the end if the list.  The
147  * current list count can be found in FreeSpace.cpp (search for
148  * XSTR_SIZE).
149  * 
150  * 120   6/05/98 9:50a Lawrance
151  * OEM changes
152  * 
153  * 119   6/01/98 11:43a John
154  * JAS & MK:  Classified all strings for localization.
155  * 
156  * 118   5/24/98 4:42p Dan
157  * AL: Fix several bugs related to pausing and enabling/disabling event
158  * music
159  * 
160  * 117   5/20/98 5:18p John
161  * Made the gamma box draw as a bitmap, not a bunch of pixels.  Speeds up
162  * the menu dramatically.
163  * 
164  * 116   5/19/98 1:21p Duncan
165  * Use 'InterfacePalette' instad of 'OptionsMainPalette'
166  * 
167  * 115   5/18/98 9:14p Dave
168  * Put in network config files support.
169  * 
170  * 114   5/18/98 5:16p Hoffoss
171  * Changed code to use new palette Jasen told me to use.
172  * 
173  * 113   5/16/98 3:40p Lawrance
174  * Don't restore the original details unless they've been stored!
175  * 
176  * 112   5/13/98 10:03a Mitri
177  * AL: Fix some bugs as a result of recent rearranging of code
178  * 
179  * 111   5/13/98 12:24a Lawrance
180  * Only load required bitmaps and masks for the options screen
181  * 
182  * 110   5/08/98 3:52p Hoffoss
183  * Fixed placement of gamma graphic.
184  * 
185  * 109   5/07/98 12:41p Hoffoss
186  * Added joystick deadzone slider support and mouse on/off support.
187  * 
188  * 108   5/06/98 8:06p Dave
189  * Made standalone reset properly under weird conditions. Tweak
190  * optionsmulti screen. Upped MAX_WEAPONS to 350. Put in new launch
191  * countdown anim. Minro ui fixes/tweaks.
192  * 
193  * 107   5/05/98 8:38p Hoffoss
194  * Added sensitivity adjustment to options menu and made it save to pilot
195  * file.
196  * 
197  * 106   4/27/98 9:00a Jasen
198  * Updated coords for button change.
199  * 
200  * 105   4/25/98 3:33p Allender
201  * do exit confirmation
202  * 
203  * 104   4/22/98 12:34a Dave
204  * Make sure hud config and control config buttons draw properly in all
205  * tab modes. Make small tab buttons light up correctly in multi options
206  * screen.
207  * 
208  * 103   4/21/98 12:14a Allender
209  * disable skill level buttons for multiplayer games
210  * 
211  * 102   4/20/98 6:04p Dave
212  * Implement multidata cache flushing and xferring mission files to
213  * multidata. Make sure observers can't change hud config. Fix pilot image
214  * viewing in popup. Put in game status field. Tweaked multi options. 
215  * 
216  * 101   4/18/98 12:45p Dave
217  * Aesthetic changes to multi options screen. Put in missing exit button.
218  * oops.
219  * 
220  * 100   4/17/98 5:27p Dave
221  * More work on the multi options screen. Fixed many minor ui todo bugs.
222  *  
223  *
224  * $NoKeywords: $
225  *
226 */
227
228 #include "grinternal.h"
229 #include "ui.h"
230 #include "missionscreencommon.h"
231 #include "bmpman.h"
232 #include "gamesequence.h"
233 #include "key.h"
234 #include "managepilot.h"
235 #include "freespace.h"
236 #include "gamesnd.h"
237 #include "sound.h"
238 #include "eventmusic.h"
239 #include "mainhallmenu.h"
240 #include "audiostr.h"
241 #include "multi.h"
242 #include "psnet.h"
243 #include "popup.h"
244 #include "popupdead.h"
245 #include "missionbriefcommon.h"
246 #include "optionsmenu.h"
247 #include "optionsmenumulti.h"
248 #include "joy.h"
249 #include "mouse.h"
250 #include "osregistry.h"
251 #include "alphacolors.h"
252 #include "timer.h"
253 #include "neb.h"
254 #include "beam.h"
255
256
257 // will display a notification warning message
258 #define OPTIONS_NOTIFY_TIME                     3500
259 #define OPTIONS_NOTIFY_Y            450
260
261 #ifdef MAKE_FS1
262 #define NUM_BUTTONS 26
263 #else
264 #define NUM_BUTTONS     24
265 #endif
266 #define NUM_ANIS                4
267 #define NUM_TABS                3
268 #define NUM_COMMONS     10
269
270 #define TABLESS                                                 999
271
272 #define OPTIONS_TAB                                             0
273 #define MULTIPLAYER_TAB                                 1
274 #define DETAIL_LEVELS_TAB                               2
275 #define ABORT_GAME_BUTTON                               3
276 #define CONTROL_CONFIG_BUTTON                   4
277 #define HUD_CONFIG_BUTTON                               5
278 #define ACCEPT_BUTTON                                   6
279
280 #define BRIEF_VOICE_OFF                                 7
281 #define BRIEF_VOICE_ON                                  8
282 #define MOUSE_OFF                                                       9
283 #define MOUSE_ON                                                        10
284 #define GAMMA_DOWN                                              11
285 #define GAMMA_UP                                                        12
286
287 // detail level screen buttons
288 #define PLANETS_ON                                              13
289 #define PLANETS_OFF                                             14
290 #define HUD_TARGETVIEW_RENDER_ON                15
291 #define HUD_TARGETVIEW_RENDER_OFF       16
292 #define WEAPON_EXTRAS_ON                                17
293 #define WEAPON_EXTRAS_OFF                               18
294
295 #ifdef MAKE_FS1
296 #define ENGINE_GLOWS_ON                                 24
297 #define ENGINE_GLOWS_OFF                                25
298 #endif
299
300 #define LOW_DETAIL_N                                            19
301 #define MEDIUM_DETAIL_N                                 20
302 #define HIGH_DETAIL_N                                   21
303 #define VERY_HIGH_DETAIL_N                              22
304 #define CUSTOM_DETAIL_N                                 23
305
306 #define REPEAT                                          (1<<0)
307 #define NO_MOUSE_OVER_SOUND     (1<<1)
308
309 // indicies for options coordinates
310 #define OPTIONS_X_COORD 0
311 #define OPTIONS_Y_COORD 1
312 #define OPTIONS_W_COORD 2
313 #define OPTIONS_H_COORD 3
314
315 struct options_buttons {
316         char *filename;
317         int x, y;
318         int hotspot;
319         int tab;
320         int flags;
321         UI_BUTTON button;  // because we have a class inside this struct, we need the constructor below..
322
323         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) {}
324 };
325
326 static options_buttons Buttons[GR_NUM_RESOLUTIONS][NUM_BUTTONS] = {
327         {       // GR_640
328 #ifdef MAKE_FS1
329                 options_buttons("OPa_00",       84,             25,             0,      -1),    // options tab
330                 options_buttons("OPa_01",       173,    25,             1,      -1),    // multiplayer tab
331                 options_buttons("OPa_02",       256,    25,             2,      -1),    // detail levels tab
332                 options_buttons("OPa_03",       6,              380,    3,      -1),    // abort game button
333                 options_buttons("OPa_05",       448,    335,    5,      -1),    // control config button
334                 options_buttons("OPa_06",       541,    335,    6,      -1),    // hud config
335                 options_buttons("OPa_07",       560,    411,    7,      -1),    // accept button                
336
337                 options_buttons("OPa_58",       39,             99,             58,     OPTIONS_TAB,    2),     // Briefing / debriefing voice toggle off
338                 options_buttons("OPa_59",       104,    99,             59,     OPTIONS_TAB,    2),     // Briefing / debriefing voice toggle on
339                 options_buttons("OPa_62",       359,    274,    62,     OPTIONS_TAB,    2),     // Mouse off
340                 options_buttons("OPa_63",       424,    274,    63,     OPTIONS_TAB,    2),     // Mouse on
341                 options_buttons("OPa_56",       451,    79,             56,     OPTIONS_TAB,    1),     // Gamma Down
342                 options_buttons("OPa_57",       484,    79,             57,     OPTIONS_TAB,    1),     // Gamma Up
343         
344                 options_buttons("OPc_40",       321,    237,    40,     DETAIL_LEVELS_TAB,      2),     // Planets On (Nebula)
345                 options_buttons("OPc_39",       264,    237,    39,     DETAIL_LEVELS_TAB,      2),     // Planets Off (Nebula)
346                 options_buttons("OPc_42",       321,    284,    42,     DETAIL_LEVELS_TAB,      2),     // Target View Rendering On
347                 options_buttons("OPc_41",       264,    284,    41,     DETAIL_LEVELS_TAB,      2),     // Target View Rendering Off
348                 options_buttons("OPc_44",       321,    331,    44,     DETAIL_LEVELS_TAB,      2),     // Weapon Extras On
349                 options_buttons("OPc_43",       264,    331,    43,     DETAIL_LEVELS_TAB,      2),     // Weapon Extras Off
350
351                 options_buttons("OPc_50",       516,    194,    50,     DETAIL_LEVELS_TAB,      2),     // Low Preset Detail
352                 options_buttons("OPc_51",       516,    213,    51,     DETAIL_LEVELS_TAB,      2),     // Medium Preset Detail
353                 options_buttons("OPc_52",       516,    232,    52,     DETAIL_LEVELS_TAB,      2),     // High Preset Detail
354                 options_buttons("OPc_53",       498,    251,    53,     DETAIL_LEVELS_TAB,      2),     // Highest Preset Detail
355                 options_buttons("OPc_54",       516,    270,    54,     DETAIL_LEVELS_TAB,      2),     // Custom Detail
356
357                 options_buttons("OPc_38",       321,    190,    38,     DETAIL_LEVELS_TAB,      2),     // Engine Glow On
358                 options_buttons("OPc_37",       264,    190,    37,     DETAIL_LEVELS_TAB,      2),     // Engine Glow Off
359 #else
360                 options_buttons("OPT_00",       17,     2,              0,              -1),                                                    // options tab
361                 options_buttons("OPT_01",       102,    2,              1,              -1),                                                    // multiplayer tab
362                 options_buttons("OPT_02",       170,    2,              2,              -1),                                                    // detail levels tab
363                 options_buttons("OPT_03",       10,     444,    3,              -1),                                                    // abort game button
364                 options_buttons("OPT_04",       411,    444,    4,              -1),                                                    // control config button
365                 options_buttons("OPT_05",       506,    444,    5,              -1),                                                    // hud config
366                 options_buttons("OPT_06",       576,    434,    6,              -1),                                                    // accept button                                
367
368                 options_buttons("OMB_07",       51,     74,     7,              OPTIONS_TAB, 2),                        // Briefing / debriefing voice toggle off
369                 options_buttons("OMB_08",       106,    74,     8,              OPTIONS_TAB, 2),                        // Briefing / debriefing voice toggle on
370                 options_buttons("OMB_18",       51,     266,    18,     OPTIONS_TAB, 2),                        // Mouse off
371                 options_buttons("OMB_19",       106,    266,    19,     OPTIONS_TAB, 2),                        // Mouse on
372                 options_buttons("OMB_26",       578,    149,    26,     OPTIONS_TAB, 1),                        // Gamma Down
373                 options_buttons("OMB_27",       607,    149,    27,     OPTIONS_TAB, 1),                        // Gamma Up
374                 
375                 options_buttons("ODB_21",       597,    261,    21,     DETAIL_LEVELS_TAB, 2),  // Planets On
376                 options_buttons("ODB_20",       539,    261,    20,     DETAIL_LEVELS_TAB, 2),  // Planets Off
377                 options_buttons("ODB_23",       597,    307,    23,     DETAIL_LEVELS_TAB, 2),  // Target View Rendering On
378                 options_buttons("ODB_22",       539,    307,    22,     DETAIL_LEVELS_TAB, 2),  // Target View Rendering Off
379                 options_buttons("ODB_25",       597,    354,    25,     DETAIL_LEVELS_TAB, 2),  // Weapon Extras On
380                 options_buttons("ODB_24",       539,    354,    24,     DETAIL_LEVELS_TAB, 2),  // Weapon Extras Off
381
382                 options_buttons("ODB_14",       614,    76,     14,     DETAIL_LEVELS_TAB, 2),  // Low Preset Detail
383                 options_buttons("ODB_15",       614,    96,     15,     DETAIL_LEVELS_TAB, 2),  // Medium Preset Detail
384                 options_buttons("ODB_16",       614,    114,    16,     DETAIL_LEVELS_TAB, 2),  // High Preset Detail
385                 options_buttons("ODB_17",       614,    133,    17,     DETAIL_LEVELS_TAB, 2),  // Highest Preset Detail
386                 options_buttons("ODB_18",       614,    152,    18,     DETAIL_LEVELS_TAB, 2),  // Custom Detail
387 #endif
388         },
389         {       // GR_1024
390                 options_buttons("2_OPT_00",     27,     4,              0,              -1),                                            // options tab
391                 options_buttons("2_OPT_01",     164,    4,              1,              -1),                                            // multiplayer tab
392                 options_buttons("2_OPT_02",     272,    4,              2,              -1),                                            // detail levels tab
393                 options_buttons("2_OPT_03",     16,     711,    3,              -1),                                            // abort game
394                 options_buttons("2_OPT_04",     657,    711,    4,              -1),                                            // control config button
395                 options_buttons("2_OPT_05",     809,    711,    5,              -1),                                            // hud config button
396                 options_buttons("2_OPT_06",     922,    694,    6,              -1),                                            // accept button                
397
398                 options_buttons("2_OMB_07",     81,     118,    7,              OPTIONS_TAB, 2),                        // Briefing / debriefing voice toggle off
399                 options_buttons("2_OMB_08",     170,    118,    8,              OPTIONS_TAB, 2),                        // Briefing / debriefing voice toggle on
400                 options_buttons("2_OMB_18",     81,     425,    18,     OPTIONS_TAB, 2),                        // Mouse off
401                 options_buttons("2_OMB_19",     170,    425,    19,     OPTIONS_TAB, 2),                        // Mouse on
402                 options_buttons("2_OMB_26",     925,    238,    26,     OPTIONS_TAB, 1),                        // Gamma Down
403                 options_buttons("2_OMB_27",     971,    238,    27,     OPTIONS_TAB, 1),                        // Gamma Up
404                 
405                 options_buttons("2_ODB_21",     956,    417,    21,     DETAIL_LEVELS_TAB, 2),  // Planets On
406                 options_buttons("2_ODB_20",     863,    417,    20,     DETAIL_LEVELS_TAB, 2),  // Planets Off
407                 options_buttons("2_ODB_23",     956,    492,    23,     DETAIL_LEVELS_TAB, 2),  // Target View Rendering On
408                 options_buttons("2_ODB_22",     863,    492,    22,     DETAIL_LEVELS_TAB, 2),  // Target View Rendering Off
409                 options_buttons("2_ODB_25",     956,    567,    25,     DETAIL_LEVELS_TAB, 2),  // Weapon Extras On
410                 options_buttons("2_ODB_24",     863,    567,    24,     DETAIL_LEVELS_TAB, 2),  // Weapon Extras Off
411
412                 options_buttons("2_ODB_14",     983,    122,    14,     DETAIL_LEVELS_TAB, 2),  // Low Preset Detail
413                 options_buttons("2_ODB_15",     983,    153,    15,     DETAIL_LEVELS_TAB, 2),  // Medium Preset Detail
414                 options_buttons("2_ODB_16",     983,    183,    16,     DETAIL_LEVELS_TAB, 2),  // High Preset Detail
415                 options_buttons("2_ODB_17",     983,    213,    17,     DETAIL_LEVELS_TAB, 2),  // Highest Preset Detail
416                 options_buttons("2_ODB_18",     983,    243,    18,     DETAIL_LEVELS_TAB, 2),  // Custom Detail
417 #ifdef MAKE_FS1 // just filler
418                 options_buttons("OPc_38",       321,    290,    38,     DETAIL_LEVELS_TAB,      2),     // Engine Glow On
419                 options_buttons("OPc_37",       264,    290,    37,     DETAIL_LEVELS_TAB,      2),     // Engine Glow Off
420 #endif
421         }       
422 };
423
424 #define NUM_OPTIONS_SLIDERS                     7
425 #define OPT_SOUND_VOLUME_SLIDER         0
426 #define OPT_MUSIC_VOLUME_SLIDER         1
427 #define OPT_VOICE_VOLUME_SLIDER         2
428 #define OPT_MOUSE_SENS_SLIDER                   3
429 #define OPT_JOY_SENS_SLIDER                     4
430 #define OPT_JOY_DEADZONE_SLIDER         5
431 #define OPT_SKILL_SLIDER                                6
432
433 op_sliders Options_sliders[GR_NUM_RESOLUTIONS][NUM_OPTIONS_SLIDERS] = {
434         { // GR_640             
435 #ifdef MAKE_FS1
436 // slider, right arrow, left arrow
437 // 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)
438                 op_sliders("OPa_09",    53,     160,    -1,     -1,     9,      20,     10,
439                                         "OPa_10",       10,     245,    159,
440                                         "OPa_08",       8,      29,             159),   // sound fx volume slider
441                 op_sliders("OPa_17",    53,     195,    -1,     -1,     17,     20,     10,
442                                         "OPa_18",       18,     245,    194,
443                                         "OPa_16",       16,     29,             194),   // music volume slider
444                 op_sliders("OPa_20",    53,     229,    -1,     -1,     20,     20,     10,
445                                         "OPa_21",       21,     245,    228,
446                                         "OPa_19",       19,     29,             228),   // voice volume slider
447                 op_sliders("OPa_64",    358,    301,    -1,     -1,     64,     20,     10,     NULL,   -1,     -1,     -1,     NULL,   -1,     -1,     -1),    // mouse sensitivity    
448                 op_sliders("OPa_60",    358,    194,    -1,     -1,     60,     20,     10,     NULL,   -1,     -1,     -1,     NULL,   -1,     -1,     -1),    // joystick sensitivity
449                 op_sliders("OPa_61",    358,    226,    -1,     -1,     61,     20,     10,     NULL,   -1,     -1,     -1,     NULL,   -1,     -1,     -1),    // joystick deadzone
450                 op_sliders("OPa_11",    28,             285,    -1,     -1,     11,     42,     5,      NULL,   -1,     -1,     -1,     NULL,   -1,     -1,     -1)             // skill
451 #else
452                 op_sliders("OMB_10",            31,     139,    -1,     -1,     10,     20,     10,
453                                           "OMB_11",             11,     226,    137,
454                                           "OMB_09",             9,              4,              137 ),                                                          // sound fx volume slider
455                 op_sliders("OMB_13",            31,     174,    -1,     -1,     13,     20,     10,
456                                           "OMB_14",             14,     226,    172,
457                                           "OMB_12",             12,     4,              172 ),                                                          // music volume slider
458                 op_sliders("OMB_16",            31,     209,    -1,     -1,     16,     20,     10,
459                                           "OMB_17",             17,     226,    206,
460                                           "OMB_15",             15,     4,              206 ),                                                          // voice volume slider
461                 op_sliders("OMB_20",            6,              316,    -1,     -1,     20,     20,     10, NULL, -1, -1, -1, NULL, -1, -1, -1),        // mouse sensitivity    
462                 op_sliders("OMB_28",            440,    259,    -1,     -1,     28,     20,     10, NULL, -1, -1, -1, NULL, -1, -1, -1),        // joystick sensitivity
463                 op_sliders("OMB_29",            440,    290,    -1,     -1,     29,     20,     10, NULL, -1, -1, -1, NULL, -1, -1, -1),        // joystick deadzone
464                 op_sliders("OMB_21",            440,    75,     -1,     -1,     21,     36,     5,      NULL, -1, -1, -1, NULL, -1, -1, -1)
465 #endif  // MAKE_FS1
466         },      
467         { // GR_1024            
468                 op_sliders("2_OMB_10",          50,     223,    -1,     -1,     10,     32,     10,
469                                           "2_OMB_11",           11,     361,    219,
470                                           "2_OMB_09",           9,              7,              219 ),                                                          // sound fx volume slider
471                 op_sliders("2_OMB_13",          50,     281,    -1,     -1,     13,     32,     10,
472                                           "2_OMB_14",           14,     361,    275,
473                                           "2_OMB_12",           12,     7,              275 ),                                                          // music volume slider
474                 op_sliders("2_OMB_16",          50,     335,    -1,     -1,     16,     32,     10,
475                                           "2_OMB_17",           17,     361,    330,
476                                           "2_OMB_15",           15,     7,              330 ),                                                          // voice volume slider
477                 op_sliders("2_OMB_20",          9,              505,    -1,     -1,     20,     32,     10, NULL, -1, -1, -1, NULL, -1, -1, -1),        // mouse sensitivity    
478                 op_sliders("2_OMB_28",          704,    414,    -1,     -1,     28,     32,     10, NULL, -1, -1, -1, NULL, -1, -1, -1),        // joystick sensitivity
479                 op_sliders("2_OMB_29",          704,    464,    -1,     -1,     29,     32,     10, NULL, -1, -1, -1, NULL, -1, -1, -1),        // joystick deadzone
480                 op_sliders("2_OMB_21",          704,    120,    -1,     -1,     21,     60,     5,      NULL, -1, -1, -1, NULL, -1, -1, -1)
481         }
482 };
483
484 static struct {
485         char *filename;
486         char *mask_filename;
487         int bitmap;
488         int mask;
489         
490 } Backgrounds[GR_NUM_RESOLUTIONS][NUM_TABS] = {
491 //XSTR:OFF
492         {       // GR_640
493                 { "OptionsMain", "OptionsMain-M"},
494                 { "OptionsMulti", "OptionsMulti-M"},
495                 { "OptionsDetail", "OptionsDetail-M"},
496         },
497         {       // GR_1024
498                 { "2_OptionsMain", "2_OptionsMain-M"},
499                 { "2_OptionsMulti", "2_OptionsMulti-M"},
500                 { "2_OptionsDetail", "2_OptionsDetail-M"},
501         }
502 //XSTR:ON
503 };
504
505 static int Tab = 0;
506 static int Options_menu_inited = 0;
507 static int Options_multi_inited = 0;
508 static int Options_detail_inited = 0;
509 static int Button_bms[NUM_COMMONS][MAX_BMAPS_PER_GADGET];
510
511 static UI_WINDOW Ui_window;
512 UI_GADGET Options_bogus;
513
514 static int Backup_skill_level;
515 static float Backup_sound_volume;
516 static float Backup_music_volume;
517 static float Backup_voice_volume;
518
519 static int Backup_briefing_voice_enabled;
520 static int Backup_use_mouse_to_fly;
521
522 static int Sound_volume_int;
523 static int Music_volume_int;
524 static int Voice_volume_int;
525
526 static int Voice_vol_handle = -1;
527 int Options_notify_stamp = -1;
528 char Options_notify_string[200];
529
530 // called whenever accept is hit
531 // do any processing, etc in here.
532 void options_accept();
533 void options_force_button_frame(int n, int frame_num);
534
535 extern float Freespace_gamma;
536
537 void options_add_notify(char *str);
538 void options_notify_do_frame();
539
540 int Options_gamma_coords[GR_NUM_RESOLUTIONS][4] = {
541         {
542 #ifdef MAKE_FS1
543                 376, 116, 203, 34
544 #else
545                 435, 179, 195,  28      // GR_640
546 #endif  // MAKE_FS1
547         },
548         {
549                 692, 287, 308, 44               // GR_1024
550         }
551 };
552
553 #define MAX_GAMMA_BITMAP_SIZE 17500
554
555 int Options_gamma_num_coords[GR_NUM_RESOLUTIONS][4] = {
556         {
557 #ifdef MAKE_FS1
558                 390, 87, 45, 10
559 #else
560                 489, 159, 65, 17                // GR_640
561 #endif  // MAKE_FS1
562         },
563         {
564                 779, 254, 65, 17                // GR_1024
565         }
566 };
567
568 int Options_skills_text_coords[GR_NUM_RESOLUTIONS][4] = {
569         {
570 #ifdef MAKE_FS1
571                 41, 326, 186, 10
572 #else
573                 468, 104, 155, 10               // GR_640
574 #endif
575         },
576         {
577                 750, 169, 246, 21               // GR_1024
578         }
579 };
580
581
582 // ---------------------------------------------------------------------------------------------------------
583 // DETAIL LEVEL OPTIONS definitions  BEGIN
584 //
585
586 #ifdef MAKE_FS1
587         #define NUM_DETAIL_SLIDERS              9
588 #else
589         #define NUM_DETAIL_SLIDERS              8
590 #endif
591
592 /*
593 #define DETAIL_DISTANCE_SLIDER  0
594 #define NEBULA_DETAIL_SLIDER            1
595 #define HARDWARE_TEXTURES_SLIDER        2
596 #define NUM_PARTICLES_SLIDER            6
597 #define SHARD_CULLING_SLIDER            3
598 #define SHIELD_DETAIL_SLIDER            4
599 #define NUM_STARS_SLIDER                        5
600 #define LIGHTING_SLIDER                         7
601 */
602 #define DETAIL_DISTANCE_SLIDER  0
603 #define NEBULA_DETAIL_SLIDER            1
604 #define HARDWARE_TEXTURES_SLIDER        2
605 #define NUM_PARTICLES_SLIDER            3
606 #define SHARD_CULLING_SLIDER            4
607 #define SHIELD_DETAIL_SLIDER            5
608 #define NUM_STARS_SLIDER                        6
609 #define LIGHTING_SLIDER                         7
610 #ifdef MAKE_FS1
611 #define WEAPON_REDNERING_SLIDER         8
612 #endif
613 op_sliders Detail_sliders[GR_NUM_RESOLUTIONS][NUM_DETAIL_SLIDERS] = {
614         { // GR_640
615 #ifdef MAKE_FS1
616                 op_sliders("OPc_29",    38,             96,             -1,     -1,     29,     20,     5,      NULL,   -1,     -1,     -1,     NULL,   -1,     -1,     -1),    // model detail
617                 op_sliders("OPc_30",    38,             143,    -1,     -1,     30,     20,     5,      NULL,   -1,     -1,     -1,     NULL,   -1,     -1,     -1),    // nebula detail
618                 op_sliders("OPc_31",    38,             176,    -1,     -1,     31,     20,     5,      NULL,   -1,     -1,     -1,     NULL,   -1,     -1,     -1),    // textures
619                 op_sliders("OPc_36",    273,    143,    -1,     -1,     36,     20,     5,      NULL,   -1,     -1,     -1,     NULL,   -1,     -1,     -1),    // particles
620                 op_sliders("Opc_33",    38,             284,    -1,     -1,     33,     20,     5,      NULL,   -1,     -1,     -1,     NULL,   -1,     -1,     -1),    // impact effects
621                 op_sliders("OPc_34",    38,             333,    -1,     -1,     34,     20,     5,      NULL,   -1,     -1,     -1,     NULL,   -1,     -1,     -1),    // shield hit
622                 op_sliders("OPc_35",    273,    96,             -1,     -1,     35,     20,     5,      NULL,   -1,     -1,     -1,     NULL,   -1,     -1,     -1),    // stars
623                 op_sliders("OPc_45",    496,    96,             -1,     -1,     45,     20,     5,      NULL,   -1,     -1,     -1,     NULL,   -1,     -1,     -1),    // lighting
624                 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
625 #else
626                 op_sliders("ODB_07",    21,     71,     -1,     -1,     7,              20,     5, NULL, -1, -1, -1, NULL, -1, -1, -1),                 // model detail
627                 op_sliders("ODB_08",    21,     119,    -1,     -1,     8,              20,     5, NULL, -1, -1, -1, NULL, -1, -1, -1),                 // nebula detail
628                 op_sliders("ODB_09",    21,     166,    -1,     -1,     9,              20,     5, NULL, -1, -1, -1, NULL, -1, -1, -1),                 // textures
629                 op_sliders("ODB_10",    21,     212,    -1,     -1,     10,     20,     5, NULL, -1, -1, -1, NULL, -1, -1, -1),                 // particles
630                 op_sliders("ODB_11",    21,     260,    -1,     -1,     11,     20,     5, NULL, -1, -1, -1, NULL, -1, -1, -1),                 // debris
631                 op_sliders("ODB_12",    21,     307,    -1,     -1,     12,     20,     5, NULL, -1, -1, -1, NULL, -1, -1, -1),                 // shield hit
632                 op_sliders("ODB_13",    21,     354,    -1,     -1,     13,     20,     5, NULL, -1, -1, -1, NULL, -1, -1, -1),                 // stars
633                 op_sliders("ODB_19",    518,    212,    -1,     -1,     19,     20,     5, NULL, -1, -1, -1, NULL, -1, -1, -1),                 // lighting             
634 #endif
635         },      
636         { // GR_1024
637                 op_sliders("2_ODB_07",  34,     114,    -1,     -1,     7,              32,     5, NULL, -1, -1, -1, NULL, -1, -1, -1),         // model detail
638                 op_sliders("2_ODB_08",  34,     190,    -1,     -1,     8,              32,     5, NULL, -1, -1, -1, NULL, -1, -1, -1),         // nebula detail
639                 op_sliders("2_ODB_09",  34,     265,    -1,     -1,     9,              32,     5, NULL, -1, -1, -1, NULL, -1, -1, -1),         // textures
640                 op_sliders("2_ODB_10",  34,     340,    -1,     -1,     10,     32,     5, NULL, -1, -1, -1, NULL, -1, -1, -1),         // particles
641                 op_sliders("2_ODB_11",  34,     416,    -1,     -1,     11,     32,     5, NULL, -1, -1, -1, NULL, -1, -1, -1),         // debris
642                 op_sliders("2_ODB_12",  34,     492,    -1,     -1,     12,     32,     5, NULL, -1, -1, -1, NULL, -1, -1, -1),         // shield hit
643                 op_sliders("2_ODB_13",  34,     567,    -1,     -1,     13,     32,     5, NULL, -1, -1, -1, NULL, -1, -1, -1),         // stars
644                 op_sliders("2_ODB_19",  829,    340,    -1,     -1,     19,     32,     5, NULL, -1, -1, -1, NULL, -1, -1, -1),         // lighting
645 #ifdef MAKE_FS1 // filler
646                 op_sliders("none",              -1,     -1,             -1,     -1,     -1,     -1,     -1,     NULL,   -1,     -1,     -1,     NULL,   -1,     -1,     -1),
647 #endif
648         }
649 };
650 int Detail_slider_pos[NUM_DETAIL_SLIDERS];
651 detail_levels Detail_original;  // backup of Detail settings when screen is first entered
652 UI_GADGET Detail_bogus;
653 void options_detail_init();
654 void options_detail_hide_stuff();
655 void options_detail_unhide_stuff();
656 void options_detail_do_frame();
657 void options_detail_set_level(int level);
658
659 // text
660 #ifndef MAKE_FS1
661 #define OPTIONS_NUM_TEXT                                49
662
663 UI_XSTR Options_text[GR_NUM_RESOLUTIONS][OPTIONS_NUM_TEXT] = {
664         { // GR_640
665                 // common text
666                 { "Options",    1036,           10,     35,     UI_XSTR_COLOR_GREEN,    -1, &Buttons[0][OPTIONS_TAB].button },
667                 { "Multi",              1042,           97,     35,     UI_XSTR_COLOR_GREEN,    -1, &Buttons[0][MULTIPLAYER_TAB].button },
668                 { "Detail",             1351,           166,    35,     UI_XSTR_COLOR_GREEN,    -1, &Buttons[0][DETAIL_LEVELS_TAB].button },
669                 { "Exit",               1059,           8,              417,    UI_XSTR_COLOR_PINK,     -1, &Buttons[0][ABORT_GAME_BUTTON].button },
670                 { "Game",               1412,           8,              430,    UI_XSTR_COLOR_PINK,     -1, &Buttons[0][ABORT_GAME_BUTTON].button },
671                 { "Control",    1352,           409,    418,    UI_XSTR_COLOR_GREEN,    -1, &Buttons[0][CONTROL_CONFIG_BUTTON].button },
672                 { "Config",             1353,           409,    430,    UI_XSTR_COLOR_GREEN,    -1, &Buttons[0][CONTROL_CONFIG_BUTTON].button },
673                 { "HUD",                        1354,           504,    418,    UI_XSTR_COLOR_GREEN,    -1, &Buttons[0][HUD_CONFIG_BUTTON].button },
674                 { "Config",             1415,           504,    430,    UI_XSTR_COLOR_GREEN,    -1, &Buttons[0][HUD_CONFIG_BUTTON].button },
675                 { "Accept",             1035,           573,    412,    UI_XSTR_COLOR_PINK,     -1, &Buttons[0][ACCEPT_BUTTON].button },
676
677                 // text for the detail level screen 
678                 { "Preset Detail Levels",       1355,   455,    56,     UI_XSTR_COLOR_GREEN,    -1, &Detail_bogus },
679                 { "Low",                        1160,           570,    82,     UI_XSTR_COLOR_GREEN, -1, &Buttons[0][LOW_DETAIL_N].button },
680                 { "Medium",             1161,           550,    100,    UI_XSTR_COLOR_GREEN, -1, &Buttons[0][MEDIUM_DETAIL_N].button },
681                 { "High",               1162,           568,    120,    UI_XSTR_COLOR_GREEN, -1, &Buttons[0][HIGH_DETAIL_N].button },
682                 { "Very High",  1163,           530,    139,    UI_XSTR_COLOR_GREEN, -1, &Buttons[0][VERY_HIGH_DETAIL_N].button },
683                 { "Custom",             1356,           546,    158,    UI_XSTR_COLOR_GREEN, -1, &Buttons[0][CUSTOM_DETAIL_N].button },         
684                 { "Off",                        1286,           509,    267,    UI_XSTR_COLOR_GREEN,    -1, &Buttons[0][PLANETS_OFF].button },
685                 { "On",                 1285,           573,    267,    UI_XSTR_COLOR_GREEN,    -1, &Buttons[0][PLANETS_ON].button },
686                 { "Off",                        1286,           509,    314,    UI_XSTR_COLOR_GREEN,    -1, &Buttons[0][HUD_TARGETVIEW_RENDER_OFF].button },
687                 { "On",                 1285,           573,    314,    UI_XSTR_COLOR_GREEN,    -1, &Buttons[0][HUD_TARGETVIEW_RENDER_ON].button },
688                 { "Off",                        1286,           509,    361,    UI_XSTR_COLOR_GREEN,    -1, &Buttons[0][WEAPON_EXTRAS_OFF].button },
689                 { "On",                 1285,           573,    361,    UI_XSTR_COLOR_GREEN,    -1, &Buttons[0][WEAPON_EXTRAS_ON].button },
690                 { "Planets/Backgrounds",                1357,   455,    244, UI_XSTR_COLOR_GREEN, -1, &Detail_bogus },
691                 { "Target View Rendering",              1358,   446,    291, UI_XSTR_COLOR_GREEN, -1, &Detail_bogus },
692                 { "Weapon Extras",                              1359,   497,    338, UI_XSTR_COLOR_GREEN, -1, &Detail_bogus },
693                 { "Model Detail",                                       1360,   27,     56,     UI_XSTR_COLOR_GREEN, -1, &Detail_bogus },
694                 { "Nebula Detail",                              1361,   27,     103,    UI_XSTR_COLOR_GREEN, -1, &Detail_bogus },
695                 { "3D Hardware Textures",               1362,   27,     150,    UI_XSTR_COLOR_GREEN, -1, &Detail_bogus },
696                 { "Particles",                                          1363,   27,     197,    UI_XSTR_COLOR_GREEN, -1, &Detail_bogus },
697                 { "Impact Effects",                             1364,   27,     244,    UI_XSTR_COLOR_GREEN, -1, &Detail_bogus },
698                 { "Shield Hit Effects",                 1365,   27,     291,    UI_XSTR_COLOR_GREEN, -1, &Detail_bogus },
699                 { "Stars",                                                      1366,   27,     338,    UI_XSTR_COLOR_GREEN, -1, &Detail_bogus },
700                 { "Lighting",                                           1367, 549,      197,    UI_XSTR_COLOR_GREEN, -1, &Detail_bogus },
701
702                 // main options screen text
703                 { "Briefing Voice",     1368,   14,     58,     UI_XSTR_COLOR_GREEN,    -1, &Options_bogus },
704                 { "Off",                                        1286,   20,     81,     UI_XSTR_COLOR_GREEN,    -1, &Buttons[0][BRIEF_VOICE_OFF].button },
705                 { "On",                                 1285,   83,     81,     UI_XSTR_COLOR_GREEN,    -1, &Buttons[0][BRIEF_VOICE_ON].button },
706                 { "Volume",                             1369,   14,     111,    UI_XSTR_COLOR_GREEN,    -1, &Options_bogus },
707                 { "Effects",                    1370,   20,     130,    UI_XSTR_COLOR_GREEN,    -1, &Options_bogus },
708                 { "Music",                              1371,   20,     165,    UI_XSTR_COLOR_GREEN,    -1, &Options_bogus },
709                 { "Voice",                              1372,   20,     199,    UI_XSTR_COLOR_GREEN,    -1, &Options_bogus },
710                 { "Mouse",                              1373,   14,     249,    UI_XSTR_COLOR_GREEN,    -1, &Options_bogus },
711                 { "Off",                                        1286,   20,     273,    UI_XSTR_COLOR_GREEN,    -1, &Buttons[0][MOUSE_OFF].button },
712                 { "On",                                 1285,   83,     273,    UI_XSTR_COLOR_GREEN,    -1, &Buttons[0][MOUSE_ON].button },
713                 { "Sensitivity",                1529,   20,     297,    UI_XSTR_COLOR_GREEN,    -1, &Options_sliders[0][OPT_MOUSE_SENS_SLIDER].slider },
714                 { "Skill Level",                1509,   533,    58,     UI_XSTR_COLOR_GREEN,    -1, &Options_bogus },
715                 { "Brightness",         1375,   532,    133,    UI_XSTR_COLOR_GREEN,    -1, &Options_bogus },
716                 { "Joystick",                   1376,   556,    231,    UI_XSTR_COLOR_GREEN,    -1, &Options_bogus },
717                 { "Sensitivity",                1374,   538,    250,    UI_XSTR_COLOR_GREEN,    -1, &Options_bogus },
718                 { "Deadzone",                   1377,   538,    281,    UI_XSTR_COLOR_GREEN,    -1, &Options_bogus },
719         },
720         { // GR_1024
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         }
776 };
777 #endif
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 #ifndef MAKE_FS1
1306         // add all xstr text
1307         for(i=0; i<OPTIONS_NUM_TEXT; i++){
1308                 Ui_window.add_XSTR(&Options_text[gr_screen.res][i]);
1309         }
1310 #endif
1311
1312         // bogus controls
1313         Detail_bogus.base_create(&Ui_window, UI_KIND_ICON, 0, 0, 0, 0);
1314         Options_bogus.base_create(&Ui_window, UI_KIND_ICON, 0, 0, 0, 0);
1315
1316         Buttons[gr_screen.res][GAMMA_DOWN].button.set_hotkey(KEY_COMMA);
1317         Buttons[gr_screen.res][GAMMA_UP].button.set_hotkey(KEY_PERIOD);
1318
1319         /*
1320         Skill_control.first_frame = bm_load_animation("OPa_11", &Skill_control.total_frames);
1321         if (Skill_control.first_frame < 0) {
1322                 Error(LOCATION, "Could not load OPa_11.ani\n");
1323                 return;
1324         }
1325         */
1326
1327         for (i=0; i<NUM_TABS; i++) {
1328                 Backgrounds[gr_screen.res][i].bitmap = -1;
1329                 Backgrounds[gr_screen.res][i].mask = -1;
1330         }
1331
1332         options_load_background_and_mask(OPTIONS_TAB);
1333         options_tab_setup(0);
1334
1335         Backup_skill_level = Game_skill_level;
1336         Backup_sound_volume = Master_sound_volume;
1337         Backup_music_volume = Master_event_music_volume;
1338         Backup_voice_volume = Master_voice_volume;
1339         Backup_briefing_voice_enabled = Briefing_voice_enabled;
1340         Backup_use_mouse_to_fly = Use_mouse_to_fly;
1341         
1342         // create slider        
1343         for ( i = 0; i < NUM_OPTIONS_SLIDERS; i++ ) {
1344                  Options_sliders[gr_screen.res][i].slider.create(&Ui_window, Options_sliders[gr_screen.res][i].x, Options_sliders[gr_screen.res][i].y,
1345                                                                                                                                                 Options_sliders[gr_screen.res][i].dots, Options_sliders[gr_screen.res][i].filename,
1346                                                                                                                                                 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,
1347                                                                                                                                                 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,
1348                                                                                                                                                 Options_sliders[gr_screen.res][i].dot_w);
1349         }       
1350
1351         // maybe disable the skill slider
1352         if( ((Game_mode & GM_IN_MISSION) && (!popupdead_is_active())) || (Game_mode & GM_MULTIPLAYER) ) {
1353                 Options_sliders[gr_screen.res][OPT_SKILL_SLIDER].slider.disable();
1354                 Ui_window.use_hack_to_get_around_stupid_problem_flag = 0;
1355         }
1356         
1357         // setup slider values 
1358         // note slider scale is 0-9, while Master_ values calc with 1-10 scale (hence the -1)
1359         Sound_volume_int = Options_sliders[gr_screen.res][OPT_SOUND_VOLUME_SLIDER].slider.pos = (int) (Master_sound_volume * 9.0f + 0.5f);
1360         Music_volume_int = Options_sliders[gr_screen.res][OPT_MUSIC_VOLUME_SLIDER].slider.pos = (int) (Master_event_music_volume * 9.0f + 0.5f);        
1361         Voice_volume_int = Options_sliders[gr_screen.res][OPT_VOICE_VOLUME_SLIDER].slider.pos = (int) (Master_voice_volume * 9.0f + 0.5f);
1362         Options_sliders[gr_screen.res][OPT_JOY_SENS_SLIDER].slider.pos = Joy_sensitivity;       
1363         Options_sliders[gr_screen.res][OPT_JOY_DEADZONE_SLIDER].slider.pos = Dead_zone_size / 5;        
1364         Options_sliders[gr_screen.res][OPT_MOUSE_SENS_SLIDER].slider.pos = Mouse_sensitivity;
1365         Options_sliders[gr_screen.res][OPT_SKILL_SLIDER].slider.pos = Game_skill_level;
1366
1367         Gamma_colors_inited = 0;
1368
1369         // used to allow all keystrokes, even when called from a demo playback
1370         key_clear_filter();
1371         Options_menu_inited = 1;
1372
1373         // hide options crap
1374         options_detail_hide_stuff();
1375 }
1376
1377 void options_menu_close()
1378 {
1379         int i;  
1380
1381         Assert(Options_menu_inited);    
1382
1383         for (i=0; i<NUM_TABS; i++) {
1384                 if (Backgrounds[gr_screen.res][i].bitmap >= 0){
1385                         bm_unload(Backgrounds[gr_screen.res][i].bitmap);
1386                 }
1387                 if ((Backgrounds[gr_screen.res][i].mask >= 0) && (i != Tab)){  // Ui_window.destroy() expects to release current tab's mask.
1388                         bm_unload(Backgrounds[gr_screen.res][i].mask);
1389                 }
1390         }
1391
1392         if ( Voice_vol_handle >= 0 ) {
1393                 snd_stop(Voice_vol_handle);
1394                 Voice_vol_handle = -1;
1395         }
1396
1397 #if !defined(DEMO) && !defined(OEM_BUILD) // not for FS2_DEMO
1398         options_multi_close();
1399 #endif
1400
1401         Ui_window.destroy();
1402         common_free_interface_palette();                // restore game palette
1403         write_pilot_file();
1404         game_flush();
1405         
1406         // unpause all sounds, since we could be headed back to the game
1407         beam_unpause_sounds();
1408         //audiostream_unpause_all();
1409         
1410         Options_menu_inited = 0;
1411         Options_multi_inited = 0;
1412         Options_detail_inited = 0;
1413
1414
1415 }
1416
1417
1418 void draw_gamma_box()
1419 {
1420         int x, y, v;
1421
1422 // 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)
1423 // TODO: change MAX size to maximum size for a 1024x768 bitmap
1424 //      ushort Gamma_data[Options_gamma_coords[gr_screen.res][OPTIONS_W_COORD]*Options_gamma_coords[gr_screen.res][OPTIONS_H_COORD]*2];
1425         ushort Gamma_data[MAX_GAMMA_BITMAP_SIZE];
1426
1427         v = fl2i( pow(0.5f, 1.0f / Freespace_gamma) * 255.0f );
1428         if (v > 255){
1429                 v = 255;
1430         } else if (v < 0){
1431                 v = 0;
1432         }
1433
1434         int Gamma_changed = 0;
1435         if ( v != Gamma_last_set )      {
1436                 Gamma_changed = 1;
1437         } else {
1438                 Gamma_changed = 0;
1439         }
1440         Gamma_last_set = v;
1441
1442         {
1443                 ushort clr_full_white = 0;
1444                 ushort clr_half_white = 0;
1445                 ubyte r, g, b, a;
1446
1447                 // if we're in bitmap poly mode
1448                 if(Gr_bitmap_poly){
1449                         BM_SELECT_TEX_FORMAT();
1450                 } else {
1451                         BM_SELECT_SCREEN_FORMAT();
1452                 }
1453
1454                 // set full white
1455                 r = g = b = a = 255;            
1456                 bm_set_components((ubyte*)&clr_full_white, &r, &g, &b, &a);
1457
1458                 // set half white
1459                 r = g = b = (ubyte)v;
1460                 bm_set_components((ubyte*)&clr_half_white, &r, &g, &b, &a);
1461
1462                 ushort *dptr = Gamma_data;
1463                 for (y=0; y<Options_gamma_coords[gr_screen.res][OPTIONS_H_COORD]; y++) {
1464                         for (x=0; x<Options_gamma_coords[gr_screen.res][OPTIONS_W_COORD]; x++) {
1465                                 if ((x / 20) & 1) {
1466                                         *dptr = clr_half_white;
1467                                 } else {
1468                                         if ((x & 1) == (y & 1)) {
1469                                                 *dptr = clr_full_white;
1470                                         } else {
1471                                                 *dptr = 0;
1472                                         }
1473                                 }
1474                                 dptr++;
1475                         }
1476                 }
1477
1478                 // always go back to screen format
1479                 BM_SELECT_SCREEN_FORMAT();
1480
1481                 // if we're in bitmap poly mode         
1482                 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 );
1483                 gr_set_bitmap(Gamma_bitmap, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
1484                 gr_bitmap( Options_gamma_coords[gr_screen.res][OPTIONS_X_COORD], Options_gamma_coords[gr_screen.res][OPTIONS_Y_COORD] );
1485
1486                 bm_release( Gamma_bitmap );
1487
1488         }
1489 }
1490
1491
1492 void options_menu_do_frame(float frametime)
1493 {
1494         int i, k, x, y; 
1495
1496         Assert(Options_menu_inited);
1497         k = Ui_window.process() & ~KEY_DEBUGGED;
1498         switch (k) {
1499                 case KEY_SHIFTED | KEY_TAB:
1500                 case KEY_LEFT:  // activate previous tab
1501                         i = Tab - 1;
1502                         if (i < 0)
1503                                 i = NUM_TABS - 1;
1504
1505                         options_change_tab(i);
1506                         break;
1507
1508                 case KEY_TAB:
1509                 case KEY_RIGHT:  // activate next tab
1510                         // check to see if the multiplayer options screen wants to eat the tab kay
1511                         if ((k == KEY_TAB) && (Tab == MULTIPLAYER_TAB)) {
1512                                 if (options_multi_eat_tab()) {
1513                                         break;
1514                                 }
1515                         }
1516
1517                         i = Tab + 1;
1518                         if (i >= NUM_TABS)
1519                                 i = 0;
1520
1521                         options_change_tab(i);
1522                         break;
1523
1524                 case KEY_C:
1525                         if (Tab == OPTIONS_TAB) {
1526                                 gamesnd_play_iface(SND_SWITCH_SCREENS);
1527                                 gameseq_post_event(GS_EVENT_CONTROL_CONFIG);
1528                         }
1529
1530                         break;
1531
1532                 case KEY_H:
1533                         if (Tab == OPTIONS_TAB) {
1534                                 gamesnd_play_iface(SND_SWITCH_SCREENS);
1535                                 gameseq_post_event(GS_EVENT_HUD_CONFIG);
1536                         }
1537
1538                         break;
1539
1540                 case KEY_ESC:
1541                         // if(Tab != MULTIPLAYER_TAB){
1542                                 options_cancel_exit();
1543                         // }
1544                         break;
1545
1546                 case KEY_CTRLED | KEY_ENTER:
1547                         options_accept();
1548                         break;
1549
1550                 case KEY_DELETE:
1551                         break;
1552
1553                 case KEY_ENTER:                 
1554                         break;
1555         }       
1556
1557         for (i=0; i<NUM_BUTTONS; i++) {
1558                 if (Buttons[gr_screen.res][i].button.pressed())
1559                         options_button_pressed(i);
1560         }
1561
1562         options_sliders_update();
1563
1564         // if we're in the multiplayer options tab, get the background bitmap from the options multi module
1565         if(Tab == MULTIPLAYER_TAB){
1566                 i = options_multi_background_bitmap();
1567         } else {
1568                 i = Backgrounds[gr_screen.res][Tab].bitmap;
1569         }
1570
1571         GR_MAYBE_CLEAR_RES(i);
1572         if (i >= 0) {
1573                 gr_set_bitmap(i, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
1574                 gr_bitmap(0, 0);
1575         } 
1576
1577         Ui_window.draw();
1578
1579         // NOTE : this must be done here so that any special drawing crap we do is not overwritten by the UI_WINDOW::draw() call
1580         // do specific processing for the multiplayer tab
1581         switch (Tab) {
1582                 case MULTIPLAYER_TAB:
1583 #if !defined(DEMO) && !defined(OEM_BUILD) // not for FS2_DEMO
1584                         options_multi_do(k);
1585 #endif
1586                         break;
1587
1588                 case DETAIL_LEVELS_TAB:
1589                         options_detail_do_frame();
1590                         break;
1591
1592                 default:
1593                         Game_skill_level = Options_sliders[gr_screen.res][OPT_SKILL_SLIDER].slider.pos;
1594                         break;
1595         }
1596
1597         // handle the displaying of any notification messages
1598         options_notify_do_frame();
1599
1600         for (i=0; i<NUM_TABS; i++){
1601                 if (Buttons[gr_screen.res][i].button.button_down()){
1602                         break;
1603                 }
1604         }
1605
1606         if ((i == NUM_TABS) /*&& (Tab != MULTIPLAYER_TAB)*/ ){
1607                 Buttons[gr_screen.res][Tab].button.draw_forced(2);
1608         }
1609
1610         if (Tab == OPTIONS_TAB) {
1611                 // draw correct frame for briefing voice radio buttons
1612                 if (Briefing_voice_enabled) {
1613                         options_force_button_frame(BRIEF_VOICE_ON, 2);
1614                         options_force_button_frame(BRIEF_VOICE_OFF, 0);
1615
1616                 } else {
1617                         options_force_button_frame(BRIEF_VOICE_OFF, 2);
1618                         options_force_button_frame(BRIEF_VOICE_ON, 0);
1619                 }
1620
1621                 if (Use_mouse_to_fly) {
1622                         options_force_button_frame(MOUSE_ON, 2);
1623                         options_force_button_frame(MOUSE_OFF, 0);
1624
1625                 } else {
1626                         options_force_button_frame(MOUSE_OFF, 2);
1627                         options_force_button_frame(MOUSE_ON, 0);
1628                 }               
1629
1630                 int w;
1631                 gr_get_string_size(&w, NULL, Skill_level_names(Game_skill_level));
1632                 x = Options_skills_text_coords[gr_screen.res][OPTIONS_X_COORD];
1633                 y = Options_skills_text_coords[gr_screen.res][OPTIONS_Y_COORD];
1634                 gr_set_color_fast(&Color_bright_white);
1635                 gr_string(x + (Options_skills_text_coords[gr_screen.res][OPTIONS_W_COORD] / 2) - (w/2), y, Skill_level_names(Game_skill_level));
1636         }
1637
1638         
1639         //==============================================================================
1640         // Draw the gamma adjustment grid.
1641         if (Tab == OPTIONS_TAB) {
1642
1643                 draw_gamma_box();
1644                 
1645                 gr_set_color_fast(&Color_white);
1646                 x = Options_gamma_num_coords[gr_screen.res][OPTIONS_X_COORD]; //  + Options_gamma_num_coords[gr_screen.res][OPTIONS_W_COORD] / 2 - 12;
1647                 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;
1648
1649                 gr_printf(x, y, NOX("%.2f"), Freespace_gamma);
1650                 //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.");
1651         }
1652         //==============================================================================
1653
1654         // maybe blit a waveform
1655         if(Tab == MULTIPLAYER_TAB){
1656                 options_multi_vox_process_waveform();
1657         }
1658         
1659 /*  Debug code: Graphs the joystick range scaling
1660 {
1661 int joy_get_scaled_reading(int raw, int axn);
1662         int x, y;
1663
1664         gr_set_color_fast(&Color_white);
1665         for (x=0; x<256; x+=16) {
1666                 gr_line(x + 15, 0, x + 15, 255);
1667                 gr_line(0, x + 15, 255, x + 15);
1668         }
1669
1670         gr_set_color_fast(&Color_bright_white);
1671         for (x=0; x<256; x++) {
1672                 y = joy_get_scaled_reading(x * 256, 0) / 512;
1673                 gr_line(x, 128, x, 128 + y);
1674         }
1675 }*/     
1676
1677         gr_flip();
1678 }
1679
1680
1681 // ---------------------------------------------------------------------------------------------------------
1682 // DETAIL LEVEL OPTIONS definitions  BEGIN
1683 //
1684
1685 void options_detail_synch_sliders()
1686 {
1687         Detail_slider_pos[DETAIL_DISTANCE_SLIDER] = Detail_sliders[gr_screen.res][DETAIL_DISTANCE_SLIDER].slider.pos = Detail.detail_distance;
1688         Detail_slider_pos[NEBULA_DETAIL_SLIDER] = Detail_sliders[gr_screen.res][NEBULA_DETAIL_SLIDER].slider.pos = Detail.nebula_detail;
1689         Detail_slider_pos[HARDWARE_TEXTURES_SLIDER] = Detail_sliders[gr_screen.res][HARDWARE_TEXTURES_SLIDER].slider.pos = Detail.hardware_textures;    
1690         Detail_slider_pos[SHARD_CULLING_SLIDER] = Detail_sliders[gr_screen.res][SHARD_CULLING_SLIDER].slider.pos = Detail.num_small_debris;
1691         Detail_slider_pos[SHIELD_DETAIL_SLIDER] = Detail_sliders[gr_screen.res][SHIELD_DETAIL_SLIDER].slider.pos = Detail.shield_effects;
1692         Detail_slider_pos[NUM_STARS_SLIDER] = Detail_sliders[gr_screen.res][NUM_STARS_SLIDER].slider.pos = Detail.num_stars;
1693         Detail_slider_pos[NUM_PARTICLES_SLIDER] = Detail_sliders[gr_screen.res][NUM_PARTICLES_SLIDER].slider.pos = Detail.num_particles;
1694         Detail_slider_pos[LIGHTING_SLIDER] = Detail_sliders[gr_screen.res][LIGHTING_SLIDER].slider.pos = Detail.lighting;
1695 }
1696
1697 void options_detail_init()
1698 {
1699         int i;
1700         options_buttons *b;
1701
1702         Detail_original = Detail;
1703
1704         options_load_background_and_mask(DETAIL_LEVELS_TAB);
1705
1706         for (i=PLANETS_ON; i<NUM_BUTTONS; i++) {
1707                 b = &Buttons[gr_screen.res][i];
1708
1709                 b->button.create(&Ui_window, "", b->x, b->y, 60, 30, b->flags & REPEAT, 1);
1710                 // set up callback for when a mouse first goes over a button
1711                 if (b->filename) {
1712                         b->button.set_bmaps(b->filename);
1713                         if ( !(b->flags & NO_MOUSE_OVER_SOUND) ) {
1714                                 b->button.set_highlight_action(common_play_highlight_sound);
1715                         }
1716
1717                 } else {
1718                         b->button.hide();
1719                 }
1720
1721                 b->button.link_hotspot(b->hotspot);
1722         }
1723
1724         // create detail level sliders  
1725         for ( i = 0; i < NUM_DETAIL_SLIDERS; i++ ) {
1726                 Detail_sliders[gr_screen.res][i].slider.create(&Ui_window, Detail_sliders[gr_screen.res][i].x, Detail_sliders[gr_screen.res][i].y,
1727                                                                                                                                                 Detail_sliders[gr_screen.res][i].dots, Detail_sliders[gr_screen.res][i].filename,
1728                                                                                                                                                 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,
1729                                                                                                                                                 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,
1730                                                                                                                                                 Detail_sliders[gr_screen.res][i].dot_w);
1731         }
1732
1733         // init the actual slider positions and our internal positions
1734         options_detail_synch_sliders();
1735 }
1736
1737 void options_detail_sliders_update()
1738 {
1739         int i;
1740
1741         for ( i = 0; i < NUM_DETAIL_SLIDERS; i++ ) {
1742                 if ( Detail_sliders[gr_screen.res][i].slider.pos != Detail_slider_pos[i] ) {
1743                         Detail_slider_pos[i] = Detail_sliders[gr_screen.res][i].slider.pos;
1744                         gamesnd_play_iface(SND_USER_SELECT);
1745                 }
1746         }
1747
1748         // set Detail based on slider positions
1749         Detail.detail_distance = Detail_sliders[gr_screen.res][DETAIL_DISTANCE_SLIDER].slider.pos;
1750
1751         // modify nebula stuff
1752         Detail.nebula_detail = Detail_sliders[gr_screen.res][NEBULA_DETAIL_SLIDER].slider.pos;
1753         neb2_set_detail_level(Detail.nebula_detail);
1754
1755         Detail.hardware_textures = Detail_sliders[gr_screen.res][HARDWARE_TEXTURES_SLIDER].slider.pos;  
1756         Detail.num_small_debris = Detail_sliders[gr_screen.res][SHARD_CULLING_SLIDER].slider.pos;
1757         Detail.shield_effects = Detail_sliders[gr_screen.res][SHIELD_DETAIL_SLIDER].slider.pos;
1758         Detail.num_stars = Detail_sliders[gr_screen.res][NUM_STARS_SLIDER].slider.pos;
1759         Detail.num_particles = Detail_sliders[gr_screen.res][NUM_PARTICLES_SLIDER].slider.pos;
1760         Detail.lighting = Detail_sliders[gr_screen.res][LIGHTING_SLIDER].slider.pos;
1761 }
1762
1763 void options_detail_hide_stuff()
1764 {
1765         int i;
1766
1767         for ( i = 0; i < NUM_DETAIL_SLIDERS; i++ ) {
1768                 Detail_sliders[gr_screen.res][i].slider.disable();
1769                 Detail_sliders[gr_screen.res][i].slider.hide();
1770         }
1771
1772         // this will hide text unassociated with any real control
1773         Detail_bogus.hide();
1774 }
1775
1776 void options_detail_unhide_stuff()
1777 {
1778         int i;
1779
1780         for ( i = 0; i < NUM_DETAIL_SLIDERS; i++ ) {
1781                 Detail_sliders[gr_screen.res][i].slider.enable();
1782                 Detail_sliders[gr_screen.res][i].slider.unhide();
1783         }
1784
1785         // this will hide text unassociated with any real control
1786         Detail_bogus.unhide();
1787 }
1788
1789 void options_force_button_frame(int n, int frame_num)
1790 {
1791         if ( !Buttons[gr_screen.res][n].button.button_down() ) {
1792                 Buttons[gr_screen.res][n].button.draw_forced(frame_num);
1793         }
1794 }
1795
1796 // called once per frame to set lit buttons
1797 void options_detail_do_frame()
1798 {
1799         options_detail_sliders_update();        
1800
1801         // force on/off buttons to draw their correct setting
1802
1803         if ( Detail.targetview_model ) {
1804                 options_force_button_frame(HUD_TARGETVIEW_RENDER_ON, 2);
1805                 options_force_button_frame(HUD_TARGETVIEW_RENDER_OFF, 0);
1806         } else {
1807                 options_force_button_frame(HUD_TARGETVIEW_RENDER_OFF, 2);
1808                 options_force_button_frame(HUD_TARGETVIEW_RENDER_ON, 0);
1809         }
1810
1811         if ( Detail.planets_suns == 1 ) {
1812                 options_force_button_frame(PLANETS_ON, 2);
1813                 options_force_button_frame(PLANETS_OFF, 0);
1814         } else {
1815                 options_force_button_frame(PLANETS_OFF, 2);
1816                 options_force_button_frame(PLANETS_ON, 0);
1817         }
1818
1819         if ( Detail.weapon_extras) {
1820                 options_force_button_frame(WEAPON_EXTRAS_ON, 2);
1821                 options_force_button_frame(WEAPON_EXTRAS_OFF, 0);
1822         } else {
1823                 options_force_button_frame(WEAPON_EXTRAS_OFF, 2);
1824                 options_force_button_frame(WEAPON_EXTRAS_ON, 0);
1825         }       
1826
1827 #ifdef MAKE_FS1
1828         if ( Detail.engine_glows) {
1829                 options_force_button_frame(ENGINE_GLOWS_ON, 2);
1830                 options_force_button_frame(ENGINE_GLOWS_OFF, 0);
1831         } else {
1832                 options_force_button_frame(ENGINE_GLOWS_OFF, 2);
1833                 options_force_button_frame(ENGINE_GLOWS_ON, 0);
1834         }
1835 #endif
1836
1837         int current_detail;
1838
1839         if ( Detail.setting >= 0 ) {
1840                 current_detail = current_detail_level();
1841                 Detail.setting = current_detail;
1842         } else {
1843                 current_detail = -1;
1844         }
1845
1846         options_force_button_frame(LOW_DETAIL_N, 0);
1847         options_force_button_frame(MEDIUM_DETAIL_N, 0);
1848         options_force_button_frame(HIGH_DETAIL_N, 0);
1849         options_force_button_frame(VERY_HIGH_DETAIL_N, 0);
1850         options_force_button_frame(CUSTOM_DETAIL_N, 0);
1851
1852         switch ( current_detail ) {
1853         case -1:
1854                 options_force_button_frame(CUSTOM_DETAIL_N, 2);
1855                 break;
1856         case 0:
1857                 options_force_button_frame(LOW_DETAIL_N, 2);
1858                 break;
1859         case 1:
1860                 options_force_button_frame(MEDIUM_DETAIL_N, 2);
1861                 break;
1862         case 2:
1863                 options_force_button_frame(HIGH_DETAIL_N, 2);
1864                 break;
1865         case 3:
1866                 options_force_button_frame(VERY_HIGH_DETAIL_N, 2);
1867                 break;
1868         }
1869 }
1870
1871 // Set all the detail settings to a predefined level
1872 void options_detail_set_level(int level)
1873 {
1874         detail_level_set(level);
1875         options_detail_synch_sliders();
1876 }
1877
1878 //
1879 // DETAIL LEVEL tab definitions END
1880 // ---------------------------------------------------------------------------------------------------------
1881
1882