]> icculus.org git repositories - taylor/freespace2.git/blob - src/menuui/mainhallmenu.cpp
Initial revision
[taylor/freespace2.git] / src / menuui / mainhallmenu.cpp
1 /*
2  * $Logfile: /Freespace2/code/MenuUI/MainHallMenu.cpp $
3  * $Revision$
4  * $Date$
5  * $Author$
6  *
7  * Header file for main-hall menu code
8  *
9  * $Log$
10  * Revision 1.1  2002/05/03 03:28:09  root
11  * Initial revision
12  *
13  * 
14  * 62    10/28/99 2:04a Jefff
15  * fixed a string
16  * 
17  * 61    9/15/99 6:28p Dave
18  * No load mission button in RELEASE_REAL
19  * 
20  * 60    9/13/99 4:52p Dave
21  * RESPAWN FIX
22  * 
23  * 59    9/13/99 11:30a Dave
24  * Added checkboxes and functionality for disabling PXO banners as well as
25  * disabling d3d zbuffer biasing.
26  * 
27  * 58    9/07/99 6:55p Jefff
28  * added jump-to-campaign-mission cheat
29  * 
30  * 57    9/07/99 4:01p Dave
31  * Fixed up a string.tbl paroblem (self destruct message). Make sure IPX
32  * does everything properly (setting up address when binding). Remove
33  * black rectangle background from UI_INPUTBOX.
34  * 
35  * 56    9/06/99 6:38p Dave
36  * Improved CD detection code.
37  * 
38  * 55    9/06/99 1:30a Dave
39  * Intermediate checkin. Started on enforcing CD-in-drive to play the
40  * game.
41  * 
42  * 54    9/03/99 1:31a Dave
43  * CD checking by act. Added support to play 2 cutscenes in a row
44  * seamlessly. Fixed super low level cfile bug related to files in the
45  * root directory of a CD. Added cheat code to set campaign mission # in
46  * main hall.
47  * 
48  * 53    9/01/99 11:02p Dave
49  * Made head guy look right when not animating.
50  * 
51  * 52    8/27/99 12:04a Dave
52  * Campaign loop screen.
53  * 
54  * 51    8/26/99 9:45a Dave
55  * First pass at easter eggs and cheats.
56  * 
57  * 50    8/25/99 11:57a Jefff
58  * freespace -> freespace 2 in tooltip strings
59  * 
60  * 49    8/25/99 10:50a Dave
61  * Added music to the mainhall.tbl
62  * 
63  * 48    8/24/99 8:55p Dave
64  * Make sure nondimming pixels work properly in tech menu.
65  * 
66  * 47    8/18/99 11:44a Jefff
67  * minor string fixes
68  * 
69  * 46    8/10/99 4:45p Jefff
70  * changed a string
71  * 
72  * 45    8/06/99 1:01p Andsager
73  * disable quick start (g) for demo
74  * 
75  * 44    8/05/99 10:34a Jefff
76  * more mouseover sound fixes
77  * 
78  * 43    8/04/99 9:12p Andsager
79  * Add campaign room popup allowing restart of campaign in demo.
80  * 
81  * 42    8/04/99 5:36p Dave
82  * Make glide and D3D switch out properly.
83  * 
84  * 41    8/04/99 4:35p Jefff
85  * fixed tech room & options sounds playing only once
86  * 
87  * 40    8/03/99 5:41p Jefff
88  * made "f1 for help" draw after animations, and stop if help overlay
89  * active
90  * 
91  * 39    8/03/99 4:42p Jefff
92  * small f1 text fix
93  * 
94  * 38    8/03/99 3:48p Jefff
95  * 
96  * 37    8/02/99 9:13p Dave
97  * Added popup tips.
98  * 
99  * 36    8/02/99 2:26p Jefff
100  * "press f1.." text reworked
101  * 
102  * 35    8/02/99 12:19p Andsager
103  * disable "L" load screen
104  * 
105  * 34    8/02/99 11:12a Jefff
106  * adjusted tooltip shader stuff for more a more pleasing effect.
107  * 
108  * 33    7/30/99 6:05p Jefff
109  * added shader behind tooltip text
110  * 
111  * 32    7/30/99 4:20p Andsager
112  * Added user click sounds to main hall
113  * 
114  * 31    7/29/99 10:47p Dave
115  * Standardized D3D fogging using vertex fog. Shook out Savage 4 bugs.
116  * 
117  * 30    7/27/99 6:53p Dave
118  * Hi-res main hall support.
119  * 
120  * 29    7/16/99 1:49p Dave
121  * 8 bit aabitmaps. yay.
122  * 
123  * 28    7/15/99 9:20a Andsager
124  * FS2_DEMO initial checkin
125  * 
126  * 27    7/13/99 1:15p Dave
127  * 32 bit support. Whee!
128  * 
129  * 26    6/25/99 2:51p Jasons
130  * Changed wording of network error message.
131  * 
132  * 25    6/21/99 1:30p Alanl
133  * changed main menu music tag
134  * 
135  * 24    6/19/99 3:56p Dave
136  * Moved main hall definitions into a table file. Whee!
137  * 
138  * 23    6/11/99 11:13a Dave
139  * last minute changes before press tour build.
140  * 
141  * 22    5/09/99 8:57p Dave
142  * Final E3 build preparations.
143  * 
144  * 21    4/25/99 3:02p Dave
145  * Build defines for the E3 build.
146  * 
147  * 20    4/12/99 10:07p Dave
148  * Made network startup more forgiving. Added checkmarks to dogfight
149  * screen for players who hit commit.
150  * 
151  * 19    3/28/99 5:58p Dave
152  * Added early demo code. Make objects move. Nice and framerate
153  * independant, but not much else. Don't use yet unless you're me :)
154  * 
155  * 18    3/25/99 5:47p Dave
156  * Removed the whee
157  * 
158  * 17    3/19/99 9:51a Dave
159  * Checkin to repair massive source safe crash. Also added support for
160  * pof-style nebulae, and some new weapons code.
161  * 
162  * 16    2/25/99 4:19p Dave
163  * Added multiplayer_beta defines. Added cd_check define. Fixed a few
164  * release build warnings. Added more data to the squad war request and
165  * response packets.
166  * 
167  * 15    2/03/99 11:44a Dave
168  * Fixed d3d transparent textures.
169  * 
170  * 14    1/30/99 5:08p Dave
171  * More new hi-res stuff.Support for nice D3D textures.
172  * 
173  * 13    1/27/99 9:56a Dave
174  * Temporary checkin of beam weapons for Dan to make cool sounds.
175  * 
176  * 12    12/31/98 11:23a Dave
177  * Put mini-indicators for status of ships.tbl and weapons.tbl in the
178  * lower left corner of the main hall.
179  * 
180  * 11    12/18/98 1:13a Dave
181  * Rough 1024x768 support for Direct3D. Proper detection and usage through
182  * the launcher.
183  * 
184  * 10    11/30/98 1:07p Dave
185  * 16 bit conversion, first run.
186  * 
187  * 9     11/20/98 4:08p Dave
188  * Fixed flak effect in multiplayer.
189  * 
190  * 8     11/20/98 11:16a Dave
191  * Fixed up IPX support a bit. Making sure that switching modes and
192  * loading/saving pilot files maintains proper state.
193  * 
194  * 7     11/19/98 4:57p Dave
195  * Ignore PXO option if IPX is selected.
196  * 
197  * 6     11/19/98 4:19p Dave
198  * Put IPX sockets back in psnet. Consolidated all multiplayer config
199  * files into one.
200  * 
201  * 5     11/05/98 5:55p Dave
202  * Big pass at reducing #includes
203  * 
204  * 4     11/05/98 4:18p Dave
205  * First run nebula support. Beefed up localization a bit. Removed all
206  * conditional compiles for foreign versions. Modified mission file
207  * format.
208  * 
209  * 3     10/13/98 9:28a Dave
210  * Started neatening up freespace.h. Many variables renamed and
211  * reorganized. Added AlphaColors.[h,cpp]
212  * 
213  * 2     10/07/98 10:53a Dave
214  * Initial checkin.
215  * 
216  * 1     10/07/98 10:49a Dave
217  * 
218  * 103   10/02/98 3:22p Allender
219  * fix up the -connect option and fix the -port option
220  * 
221  * 102   8/20/98 5:31p Dave
222  * Put in handy multiplayer logfile system. Now need to put in useful
223  * applications of it all over the code.
224  * 
225  * 101   8/07/98 10:40a Allender
226  * new command line flags for starting netgames.  Only starting currently
227  * works, and PXO isn't implemented yet
228  * 
229  * 100   7/13/98 10:46a Lawrance
230  * Index another localized string
231  * 
232  * 99    7/10/98 1:13a Allender
233  * lots of small multiplayer update changes.  Code in launcher to specify
234  * connection speed.  A couple of small fixes regarding empty mission
235  * files.  Time out players after 10 second when they don't connect on
236  * their reliable socket.
237  * 
238  * 98    6/09/98 10:31a Hoffoss
239  * Created index numbers for all xstr() references.  Any new xstr() stuff
240  * added from here on out should be added to the end if the list.  The
241  * current list count can be found in FreeSpace.cpp (search for
242  * XSTR_SIZE).
243  * 
244  * 97    6/05/98 9:50a Lawrance
245  * OEM changes
246  * 
247  * 96    6/01/98 11:43a John
248  * JAS & MK:  Classified all strings for localization.
249  * 
250  * 95    5/22/98 9:02p Allender
251  * remove G key from main hall
252  * 
253  * 94    5/22/98 10:54a Allender
254  * new dialog information for networking to tell user if connection type
255  * doesn't match the setup specified type
256  * 
257  * 93    5/15/98 5:15p Dave
258  * Fix a standalone resetting bug.Tweaked PXO interface. Display captaincy
259  * status for team vs. team. Put in asserts to check for invalid team vs.
260  * team situations.
261  * 
262  * 92    5/13/98 12:23a Lawrance
263  * Don't init main hall if already inited... not needed now, but may be
264  * useful if we don't always want to call main_hall_close() when switching
265  * states
266  * 
267  * 91    5/12/98 2:46a Dave
268  * Rudimentary communication between Parallax Online and freespace. Can
269  * get and store channel lists.
270  * 
271  * 90    5/08/98 5:33p Lawrance
272  * check for CD when trying to enter ready room in single player
273  *  
274  * 
275  * $NoKeywords: $
276  *
277  */
278
279 #include "mainhallmenu.h"
280 #include "palman.h"
281 #include "bmpman.h"
282 #include "2d.h"
283 #include "gamesequence.h"
284 #include "animplay.h"
285 #include "key.h"
286 #include "timer.h"
287 #include "ui.h"
288 #include "snazzyui.h"
289 #include "player.h"
290 #include "audiostr.h"
291 #include "gamesnd.h"
292 #include "eventmusic.h"
293 #include "mouse.h"
294 #include "contexthelp.h"
295 #include "cmdline.h"
296 #include "psnet.h"
297 #include "multiui.h"
298 #include "multiutil.h"
299 #include "popup.h"
300 #include "rtvoice.h"
301 #include "osapi.h"
302 #include "playermenu.h"
303 #include "freespace.h"
304 #include "multi_voice.h"
305 #include "multi.h"
306 #include "alphacolors.h"
307 #include "demo.h"
308 #include "fishtank.h"
309
310 // #include "movie.h"
311
312 // ----------------------------------------------------------------------------
313 // MAIN HALL DATA DEFINES
314 //
315 #define MAX_RANDOM_INTERCOM_SOUNDS                              10
316 #define NUM_RANDOM_INTERCOM_SOUNDS_0                    3
317 #define NUM_RANDOM_INTERCOM_SOUNDS_1                    3
318
319 #define MAX_MISC_ANIMATIONS                                             10
320 #define NUM_MISC_ANIMATIONS_0                                           2
321 #define NUM_MISC_ANIMATIONS_1                                           4
322
323 #define MAX_DOOR_ANIMATIONS                                             10
324 #define NUM_DOOR_ANIMATIONS_0                                           6
325 #define NUM_DOOR_ANIMATIONS_1                                           6
326
327 #define MAX_DOOR_SOUNDS                                                         10
328 #define NUM_DOOR_SOUNDS_0                                                       6
329 #define NUM_DOOR_SOUNDS_1                                                       6
330
331 #define MISC_ANIM_MODE_LOOP                                             0                               // loop the animation
332 #define MISC_ANIM_MODE_HOLD                                             1                               // play to the end and hold the animation
333 #define MISC_ANIM_MODE_TIMED                                            2                               // uses timestamps to determine when a finished anim should be checked again
334
335 #define NUM_REGIONS                                                                     7                               // (6 + 1 for multiplayer equivalent of campaign room)
336 typedef struct main_hall_defines {
337         // bitmap and mask
338         char bitmap[MAX_FILENAME_LEN+1];
339         char mask[MAX_FILENAME_LEN+1];
340
341         // music
342         char music[MAX_FILENAME_LEN+1];
343
344         // intercom defines -------------------
345         
346         // # of intercom sounds
347         int num_random_intercom_sounds;
348         
349         // random (min/max) delays between playing intercom sounds
350         int intercom_delay[MAX_RANDOM_INTERCOM_SOUNDS][2];
351         
352         // intercom sounds themselves
353         int intercom_sounds[MAX_RANDOM_INTERCOM_SOUNDS];
354
355         // intercom sound pan values
356         float intercom_sound_pan[MAX_RANDOM_INTERCOM_SOUNDS];
357
358
359         // misc animations --------------------
360
361         // # of misc animations
362         int num_misc_animations;
363
364         // filenames of the misc animations
365         char misc_anim_name[MAX_MISC_ANIMATIONS][MAX_FILENAME_LEN+1];
366
367         // Time until we will next play a given misc animation, min delay, and max delay
368         int misc_anim_delay[MAX_MISC_ANIMATIONS][3];
369
370         //      coords of where to play the misc anim
371         int misc_anim_coords[MAX_MISC_ANIMATIONS][2];
372         
373         // misc anim play modes (see MISC_ANIM_MODE_* above)
374         int misc_anim_modes[MAX_MISC_ANIMATIONS];
375
376         // panning values for each of the misc anims
377         float misc_anim_sound_pan[MAX_MISC_ANIMATIONS];
378
379         // [N][0] == # of sounds, [N][1-9] sound index
380         int misc_anim_special_sounds[MAX_MISC_ANIMATIONS][10];
381
382         // [N][0] == # of triggers, [N][1-9] >= frame num
383         int misc_anim_special_trigger[MAX_MISC_ANIMATIONS][10];
384
385         // [N][0] == # of handles, [N][1-9] == sound handle num
386         int misc_anim_sound_handles[MAX_MISC_ANIMATIONS][10];
387
388         // [N][0] == # of handles, [N][1-9] == sound "should" be playing
389         int misc_anim_sound_flag[MAX_MISC_ANIMATIONS][10];      
390
391
392         // door animations --------------------
393
394         // # of door animations
395         int num_door_animations;
396         
397         // filenames of the door animations
398         char door_anim_name[MAX_DOOR_ANIMATIONS][MAX_FILENAME_LEN+1];   
399
400         // first pair : coords of where to play a given door anim
401         // second pair : center of a given door anim in windowed mode
402         int door_anim_coords[MAX_DOOR_ANIMATIONS][4];
403         
404
405         // door sounds ------------------------
406
407         // # of door sounds
408         int num_door_sounds;
409
410         // sounds for each region (open/close)
411         int door_sounds[MAX_DOOR_SOUNDS][2];
412
413         // pan values for the door sounds
414         float door_sound_pan[MAX_DOOR_SOUNDS];
415
416         
417         // region descriptions ----------------
418         
419         // text (tooltip) description
420         char *region_descript[NUM_REGIONS];
421
422         // y coord of where to draw tooltip text
423         int region_yval;
424
425 } main_hall_defines;
426
427
428 // use main hall 0 by default
429 main_hall_defines Main_hall_defines[GR_NUM_RESOLUTIONS][NUM_MAIN_HALLS];
430 main_hall_defines *Main_hall = &Main_hall_defines[0][0];
431
432 int Vasudan_funny = 0;
433 int Vasudan_funny_plate = -1;
434
435 char Main_hall_campaign_cheat[512] = "";
436         
437 // ----------------------------------------------------------------------------
438 // MISC interface data
439 //
440 // is the main hall inited (for reentrancy)
441 int Main_hall_inited = 0;
442
443 // handle to the playing music
444 int Main_hall_music_handle = -1;
445
446 // background bitmap handle
447 int Main_hall_bitmap;
448
449 // background bitmap mask handle
450 int Main_hall_mask;
451
452 // variable used for automatic netgame starting/joining
453 int Main_hall_netgame_started = 0;
454
455 // bitmap struct for th background mask bitmap
456 bitmap *Main_hall_mask_bitmap;
457
458 // actual data for the background mask bitmap
459 ubyte *Main_hall_mask_data;
460
461 int Main_hall_mask_w, Main_hall_mask_h;
462
463
464 // ----------------------------------------------------------------------------
465 // MOUSE clicking stuff
466 //
467 // indicates whether a right click occured
468 int Main_hall_right_click;
469
470 // use this to cycle through the selectable regions instead of the mouse's current region
471 int Main_hall_last_clicked_region;
472
473 // use this to determine how long the cursor has to linger on a region before it starts playing
474 #define MAIN_HALL_REGION_LINGER                         175                             // in ms
475 int Main_hall_region_linger_stamp = -1;
476
477 // handle any right clicks which may have occured
478 void main_hall_handle_right_clicks();
479
480
481 // ----------------------------------------------------------------------------
482 // RANDOM intercom sounds
483 //
484
485 // next random intercom sound to play
486 int Main_hall_next_intercom_sound = 0;  
487
488 // delay for the next intercom sound
489 int Main_hall_next_intercom_sound_stamp = -1;
490
491 // handle to any playing instance of a random intercom sound
492 int Main_hall_intercom_sound_handle = -1;
493
494 // handle any details related to random intercom sounds
495 void main_hall_handle_random_intercom_sounds();
496
497
498 // ----------------------------------------------------------------------------
499 // MISC animations
500 //
501
502 // the misc animations themselves
503 anim *Main_hall_misc_anim[MAX_MISC_ANIMATIONS];                                                 
504
505 // the instance of a given misc animation
506 anim_instance *Main_hall_misc_anim_instance[MAX_MISC_ANIMATIONS];       
507
508 // handle starting, stopping and randomizing misc animations
509 void main_hall_handle_misc_anims();                                                                     
510
511 // cull any finished misc animation instances
512 void main_hall_cull_misc_anim_instances();                                                              
513
514 // render all playing misc animations
515 void main_hall_render_misc_anims(float frametime);
516
517
518 // ----------------------------------------------------------------------------
519 // DOOR animations (not all of these are doors anymore, but they're doorlike _regions_)
520 //
521 #define DOOR_TEXT_X 100
522 #define DOOR_TEXT_Y 450
523
524 // the door animations themselves
525 anim *Main_hall_door_anim[MAX_DOOR_ANIMATIONS];                                                 
526
527 // the instance of a given door animation
528 anim_instance *Main_hall_door_anim_instance[MAX_DOOR_ANIMATIONS];       
529
530 // render all playing door animations
531 void main_hall_render_door_anims(float frametime);
532
533
534 // ----------------------------------------------------------------------------
535 // SNAZZY MENU stuff
536 //
537 #define NUM_MAIN_HALL_REGIONS 10
538 #define NUM_MAIN_HALL_MOUSE_REGIONS 6
539
540 // region mask #'s (identifiers)
541 #define EXIT_REGION                              0
542 #define BARRACKS_REGION                  1
543 #define READY_ROOM_REGION                2
544 #define TECH_ROOM_REGION                 3
545 #define OPTIONS_REGION                   4
546 #define CAMPAIGN_ROOM_REGION     5
547 #define MULTIPLAYER_REGION     10
548 #define LOAD_MISSION_REGION    11
549 #define QUICK_START_REGION     12
550 #define SKILL_LEVEL_REGION     13
551
552 // all the menu regions in the main hall
553 MENU_REGION Main_hall_region[NUM_MAIN_HALL_REGIONS];
554
555 // # of regions (options) on this screen. parsed from a table
556 int Main_hall_num_options;
557
558 // region over which the mouse is currently residing, or -1 if over no region
559 // NOTE : you should nevery change this directly. Always use main_hall_handle_mouse_location(int)
560 //        to do this. Otherwise, the door opening and closing animations will get screwed up
561 int Main_hall_mouse_region;     
562
563 // set this to skip a frame
564 int Main_hall_frame_skip;
565
566 // do any necessary processing based upon the mouse location
567 void main_hall_handle_mouse_location(int cur_region);
568
569 // if the mouse has moved off of the currently active region, handle the anim accordingly
570 void main_hall_mouse_release_region(int region);                                
571
572 // if the mouse has moved on this region, handle it accordingly
573 void main_hall_mouse_grab_region(int region);                                   
574
575
576 // ----------------------------------------------------------------------------
577 // SOUND data / handlers
578 // -
579
580 // toaster oven room sound idex
581 #define TOASTER_REGION          3
582
583 // everyone's favorite desk guardian
584 #define ALLENDER_REGION         4
585
586 // handles to the sound instances of the doors opening/closing
587 int Main_hall_door_sound_handles[MAX_DOOR_SOUNDS] = {           
588         -1,-1,-1,-1,-1,-1
589 };
590
591 // sound handle for looping ambient sound
592 int Main_hall_ambient_loop = -1;                        
593
594 // cull any door sounds that have finished playing
595 void main_hall_cull_door_sounds();
596
597 // handle starting, stopping and reversing "door" animations
598 void main_hall_handle_region_anims();                                                           
599
600
601 // ----------------------------------------------------------------------------
602 // warning/notification messages
603 //
604 #define MAIN_HALL_NOTIFY_TIME  3500
605
606 // timestamp for the notification messages
607 int Main_hall_notify_stamp = -1;
608
609 // text to display as the current notification message
610 char Main_hall_notify_text[300]="";
611
612 // set the current notification string and the associated timestamp
613 void main_hall_set_notify_string(char *str);
614
615 // handle any drawing, culling, etc of notification messages
616 void main_hall_notify_do();
617
618
619 // ----------------------------------------------------------------------------
620 // MISC functions
621 //
622
623 // upper _RIGHT_ corner for the version text
624 #define MAIN_HALL_VERSION_X             630                     
625 #define MAIN_HALL_VERSION_Y             467
626
627 // main hall help overlay ID
628 int Main_hall_overlay_id;
629
630 // blit the freespace version #
631 void main_hall_blit_version();
632
633 // blit any necessary tooltips
634 void main_hall_maybe_blit_tooltips();
635
636 // shader for behind tooltips
637 shader Main_hall_tooltip_shader;
638
639 // num pixels shader is above/below tooltip text
640 static int Main_hall_tooltip_padding[GR_NUM_RESOLUTIONS] = {
641         4,              // GR_640
642         7,              // GR_1024
643 };
644 static int Main_hall_f1_text_frame = 0;
645 static int F1_text_done = 0;
646
647 // read in main hall table
648 void main_hall_read_table();
649
650 // "press f1" for help stuff
651 #define MAIN_HALL_HELP_TIME             5000
652 int Main_hall_help_stamp = -1;
653 void main_hall_process_help_stuff();
654
655
656 // ----------------------------------------------------------------------------
657 // VOICE RECORDING STUFF
658 //
659
660 // are we currently recording voice?
661 int Recording = 0;
662
663
664 // called when multiplayer clicks on the ready room door.  May pop up dialog depending on network
665 // connection status and errors
666 void main_hall_do_multi_ready()
667 {
668         int error;
669
670         error = psnet_get_network_status();
671         switch( error ) {
672         case NETWORK_ERROR_NO_TYPE:
673                 popup( PF_NO_NETWORKING, 1, POPUP_OK, XSTR( "You have not defined your type of Internet connection.  Please run the Launcher, hit the setup button, and go to the Network tab and choose your connection type.", 360));
674                 break;
675         case NETWORK_ERROR_NO_WINSOCK:
676                 popup( PF_NO_NETWORKING, 1, POPUP_OK, XSTR( "Winsock is not installed.  You must have TCP/IP and Winsock installed to play multiplayer FreeSpace.", 361));
677                 break;
678         case NETWORK_ERROR_NO_PROTOCOL:
679                 if(Multi_options_g.protocol == NET_TCP){
680                         popup( PF_NO_NETWORKING, 1, POPUP_OK, XSTR( "TCP/IP protocol not found.  This protocol is required for multiplayer FreeSpace.", 362));
681                 } else {
682                         Assert(Multi_options_g.protocol == NET_IPX);
683                         popup( PF_NO_NETWORKING, 1, POPUP_OK, XSTR( "IPX protocol not found.  This protocol is required for multiplayer FreeSpace.", 362));
684                 }
685                 break;
686         case NETWORK_ERROR_CONNECT_TO_ISP:
687                 popup( PF_NO_NETWORKING, 1, POPUP_OK, XSTR( "You have selected Dial Up Networking as your type of connection to the Internet.  You are not currently connected.  You must connect to your ISP before continuing on past this point.", 363));
688                 break;
689         case NETWORK_ERROR_LAN_AND_RAS:
690                 popup( PF_NO_NETWORKING, 1, POPUP_OK, XSTR( "You have indicated that you use a LAN for networking.  You also appear to be dialed into your ISP.  Please disconnect from your service provider, or choose Dial Up Networking.", 364));
691                 break;
692
693         case NETWORK_ERROR_NONE:
694         default:
695                 break;
696         }
697
698         // if our selected protocol is not active
699         if((Multi_options_g.protocol == NET_TCP) && !Tcp_active){
700                 popup( PF_NO_NETWORKING, 1, POPUP_OK, XSTR( "You have selected TCP/IP for multiplayer Freespace, but the TCP/IP protocol was not detected on your machine.", 362));
701                 return;
702         } 
703         if((Multi_options_g.protocol == NET_IPX) && !Ipx_active){               
704                 popup( PF_NO_NETWORKING, 1, POPUP_OK, XSTR( "You have selected IPX for multiplayer Freespace, but the IPX protocol was not detected on your machine.", 1402));
705                 return;
706         } 
707
708         if ( error != NETWORK_ERROR_NONE ){
709                 return;
710         }
711
712         // 7/9/98 -- MWA.  Deal with the connection speed issue.  make a call to the multiplayer code to
713         // determine is a valid connection setting exists
714         if ( Multi_connection_speed == CONNECTION_SPEED_NONE ) {
715                 popup( PF_NO_NETWORKING, 1, POPUP_OK, XSTR( "You must define your connection speed.  Please run the Launcher, hit the setup button, and go to the Network tab and choose your connection speed.", 986) );
716                 return;
717         }
718
719         // go to parallax online
720 #ifdef MULTIPLAYER_BETA_BUILD // do we want this for FS2_DEMO
721         Multi_options_g.pxo = 1;
722         Multi_options_g.protocol = NET_TCP;     
723         gameseq_post_event( GS_EVENT_PXO );
724 #else
725         
726         // go to the regular join game screen   
727         gameseq_post_event( GS_EVENT_MULTI_JOIN_GAME ); 
728 #endif  
729
730         // select protocol
731         psnet_use_protocol(Multi_options_g.protocol);
732 }
733
734 // blit some small color indicators to show whether ships.tbl and weapons.tbl are valid
735 // green == valid, red == invalid.
736 // ships.tbl will be on the left, weapons.tbl on the right
737 int Mh_ship_table_status[GR_NUM_RESOLUTIONS][2] = {
738         { 1, 479 },
739         { 1, 767 }
740 };
741 int Mh_weapon_table_status[GR_NUM_RESOLUTIONS][2] = {
742         { 3, 479 },
743         { 3, 767 }
744 };
745 void main_hall_blit_table_status()
746 {
747         // blit ship table status
748         gr_set_color_fast(Game_ships_tbl_valid ? &Color_bright_green : &Color_bright_red);
749         gr_line(Mh_ship_table_status[gr_screen.res][0], Mh_ship_table_status[gr_screen.res][1], Mh_ship_table_status[gr_screen.res][0], Mh_ship_table_status[gr_screen.res][1]);
750
751         // blit weapon table status
752         gr_set_color_fast(Game_weapons_tbl_valid ? &Color_bright_green : &Color_bright_red);
753         gr_line(Mh_weapon_table_status[gr_screen.res][0], Mh_weapon_table_status[gr_screen.res][1], Mh_weapon_table_status[gr_screen.res][0], Mh_ship_table_status[gr_screen.res][1]);
754 }
755
756 // bash the player to a specific mission in a campaign
757 void main_hall_campaign_cheat()
758 {
759         char *ret = popup_input(0, XSTR("Enter mission name.\n\n* This will destroy all legitimate progress in this campaign. *", -1));
760
761         // yay
762         if(ret != NULL) {
763                 // strcpy(Main_hall_campaign_cheat, ret);               
764                 mission_campaign_jump_to_mission(ret);
765         }
766 }
767
768 // -------------------------------------------------------------------------------------------------------------------
769 // FUNCTION DEFINITIONS BEGIN
770 //
771
772 // initialize the main hall proper 
773 void main_hall_init(int main_hall_num)
774 {
775         if ( Main_hall_inited ) {
776                 return;
777         }       
778
779         int idx,s_idx;
780         char temp[100], whee[100];      
781
782         // read in the main hall table
783         main_hall_read_table();
784
785         // create the snazzy interface and load up the info from the table
786         snazzy_menu_init();
787         read_menu_tbl(NOX("MAIN HALL"), temp, whee, Main_hall_region, &Main_hall_num_options, 0);
788
789         // assign the proper main hall data
790         Assert((main_hall_num >= 0) && (main_hall_num < NUM_MAIN_HALLS));
791         Main_hall = &Main_hall_defines[gr_screen.res][main_hall_num];   
792
793         // tooltip strings
794         Main_hall->region_descript[0] = XSTR( "Exit FreeSpace 2", 353);
795         Main_hall->region_descript[1] = XSTR( "Barracks - Manage your FreeSpace 2 pilots", 354);
796         Main_hall->region_descript[2] = XSTR( "Ready room - Start or continue a campaign", 355);
797         Main_hall->region_descript[3] = XSTR( "Tech room - View specifications of FreeSpace 2 ships and weaponry", 356);
798         Main_hall->region_descript[4] = XSTR( "Options - Change your FreeSpace 2 options", 357);
799         Main_hall->region_descript[5] = XSTR( "Campaign Room - View all available campaigns", 358);
800         Main_hall->region_descript[6] = XSTR( "Multiplayer - Start or join a multiplayer game", 359);
801         
802         // init tooltip shader
803         float gray_intensity = 0.02f;                                                                                                   // nearly black
804         float c = (gr_screen.mode == GR_DIRECT3D) ? 0.11f : 0.07f;                      // adjust for renderer differences
805         gr_create_shader(&Main_hall_tooltip_shader, gray_intensity, gray_intensity, gray_intensity, c);
806
807         // load the background bitmap
808         Main_hall_bitmap = bm_load(Main_hall->bitmap);
809         if(Main_hall_bitmap < 0){
810                 nprintf(("General","WARNING! Couldn't load main hall background bitmap %s\n", Main_hall->bitmap));
811         }       
812
813         // remove any multiplayer flags from the game mode
814         Game_mode &= ~(GM_MULTIPLAYER);
815
816         // set the interface palette 
817 #ifndef HARDWARE_ONLY
818         palette_use_bm_palette(Main_hall_bitmap);       
819 #endif
820
821         Main_hall_mask_w = -1;
822         Main_hall_mask_h = -1;
823                 
824         // load the mask
825         Main_hall_mask = bm_load(Main_hall->mask);
826         if (Main_hall_mask < 0) {
827                 Error(LOCATION,"Could not load in %s!", Main_hall->mask);
828         } else {
829                 // get a pointer to bitmap by using bm_lock(), so we can feed it to he snazzy menu system
830                 Main_hall_mask_bitmap = bm_lock(Main_hall_mask, 8, BMP_AABITMAP);
831                 Main_hall_mask_data = (ubyte*)Main_hall_mask_bitmap->data;
832                 bm_get_info(Main_hall_mask, &Main_hall_mask_w, &Main_hall_mask_h);
833         }
834
835         // load up the misc animations, and nullify all the delay timestamps for the misc animations    
836         for(idx=0;idx<Main_hall->num_misc_animations;idx++) {
837                 Main_hall_misc_anim[idx] = NULL;
838                 Main_hall_misc_anim[idx] = anim_load(Main_hall->misc_anim_name[idx]);
839                 if(Main_hall_misc_anim[idx] == NULL) {
840                         nprintf(("General","WARNING!, Could not load misc %s anim in main hall\n",Main_hall->misc_anim_name));
841                 }
842
843                 // null out the animation instances
844                 Main_hall_misc_anim_instance[idx] = NULL;
845                 
846                 // null out the delay timestamps
847                 Main_hall->misc_anim_delay[idx][0] = -1;
848         }       
849
850         // load up the door animations
851         for(idx=0;idx<Main_hall->num_door_animations;idx++) {
852                 Main_hall_door_anim[idx] = NULL;
853                 Main_hall_door_anim[idx] = anim_load(Main_hall->door_anim_name[idx]);
854                 if(Main_hall_door_anim[idx] == NULL){
855                         nprintf(("General","WARNING!, Could not load door anim %s in main hall\n",Main_hall->door_anim_name[idx]));
856                 }
857
858                 // null out the animation instances
859                 Main_hall_door_anim_instance[idx] = NULL;
860         }       
861
862         // load in help overlay bitmap          
863         if(Main_hall == &Main_hall_defines[gr_screen.res][0]) {
864                 Main_hall_overlay_id = MH_OVERLAY;
865         } else {
866                 Assert(Main_hall == &Main_hall_defines[gr_screen.res][1]);
867                 Main_hall_overlay_id = MH2_OVERLAY;
868         }
869         help_overlay_load(Main_hall_overlay_id);
870         help_overlay_set_state(Main_hall_overlay_id,0);         
871
872         // check to see if the "very first pilot" flag is set, and load the overlay if so
873         if (!F1_text_done) {
874                 if (Main_hall_f1_text_frame == 0) {
875                         Main_hall_help_stamp = timestamp(MAIN_HALL_HELP_TIME);
876                 } else {
877                         F1_text_done = 1;
878                 }
879         }
880
881 /*
882         if(Player_select_very_first_pilot) {                            
883                 Main_hall_help_stamp = timestamp(MAIN_HALL_HELP_TIME);
884                 
885                 // don't display the "press f1" message more than once
886                 Player_select_very_first_pilot = 0;
887         } else {
888                 Main_hall_help_stamp = -1;
889         }
890 */
891         Main_hall_region_linger_stamp = -1;
892
893         strcpy(Main_hall_campaign_cheat, "");
894
895         // zero out the door sounds
896         for(idx=0;idx<Main_hall->num_door_sounds;idx++){
897                 Main_hall_door_sound_handles[idx] = -1;
898         }
899
900         // zero out the misc anim sounds
901         for(idx=0;idx<Main_hall->num_misc_animations;idx++){
902                 for(s_idx = 1;s_idx < 10;s_idx++){
903                         Main_hall->misc_anim_sound_handles[idx][s_idx] = -1;
904                         Main_hall->misc_anim_sound_flag[idx][s_idx] = 0;
905                 }
906         }
907
908         // skip the first frame
909         Main_hall_frame_skip = 1;
910
911         // initialize the music
912         main_hall_start_music();
913
914         // initialize the main hall notify text
915         Main_hall_notify_stamp = 1;
916
917         // initialize the random intercom sound stuff
918         Main_hall_next_intercom_sound = 0;              
919         Main_hall_next_intercom_sound_stamp = -1;
920         Main_hall_intercom_sound_handle = -1;
921
922         // set the placement of the mouse cursor (start at the ready room)
923         Main_hall_mouse_region = -1;
924         Main_hall_last_clicked_region = READY_ROOM_REGION;      
925         mouse_set_pos(Main_hall->door_anim_coords[READY_ROOM_REGION][2],Main_hall->door_anim_coords[READY_ROOM_REGION][3]);     
926
927         Main_hall_inited = 1;
928
929         // determine if we have a right click
930         Main_hall_right_click = mouse_down(MOUSE_RIGHT_BUTTON);
931
932         // set the game_mode based on the type of player
933         Assert( Player != NULL );
934         if ( Player->flags & PLAYER_FLAGS_IS_MULTI ){
935                 Game_mode = GM_MULTIPLAYER;
936         } else {
937                 Game_mode = GM_NORMAL;
938         }
939
940         if ( (Cmdline_start_netgame || (Cmdline_connect_addr != NULL)) && !Main_hall_netgame_started ) {
941                 Main_hall_netgame_started = 1;
942                 main_hall_do_multi_ready();
943         }
944 }
945
946 void main_hall_exit_game()
947 {
948 #if defined(NDEBUG) || defined(INTERPLAYQA)
949         int choice;
950
951         // stop music first
952         main_hall_stop_music();
953         main_hall_stop_ambient();
954         choice = popup( PF_NO_NETWORKING | PF_BODY_BIG, 2, POPUP_NO, POPUP_YES, XSTR( "Exit Game?", 365));
955         if ( choice == 1 ) {
956                 gameseq_post_event(GS_EVENT_QUIT_GAME);
957         } else {
958                 main_hall_start_music();
959                 main_hall_start_ambient();
960         }
961 #else
962         gameseq_post_event(GS_EVENT_QUIT_GAME);
963 #endif
964 }
965
966
967 // do a frame for the main hall
968 void main_hall_do(float frametime)
969 {
970         int code, key, snazzy_action;   
971
972         // need to ensure ambient is playing, since it may be stopped by a playing movie
973         main_hall_start_ambient();
974
975         // handle any animation details 
976         main_hall_handle_misc_anims();
977         main_hall_handle_region_anims();
978
979         // handle any random intercom sound details
980         main_hall_handle_random_intercom_sounds();
981
982         // handle any mouse clicks
983         main_hall_handle_right_clicks();        
984
985         // handle any sound details
986         main_hall_cull_door_sounds();   
987
988         // process any keypresses/mouse events
989         snazzy_action = -1;
990         code = snazzy_menu_do(Main_hall_mask_data, Main_hall_mask_w, Main_hall_mask_h, Main_hall_num_options, Main_hall_region, &snazzy_action, 1, &key);
991
992         if(key){
993                 extern void game_process_cheats(int k);
994                 game_process_cheats(key);
995         }
996         switch(key){
997         case KEY_ENTER:
998                 snazzy_action = SNAZZY_CLICKED; 
999                 break;
1000         
1001 #ifndef NDEBUG  
1002         case KEY_1:             
1003                 // no soup for you!
1004                 // movie_play("endprt2b.mve", 0);
1005                 break;
1006         case KEY_2:             
1007                 // no soup for you!
1008                 // movie_play_two("endprt2a.mve", "endprt2b.mve", 0);
1009                 break;
1010         case KEY_3:             
1011                 main_hall_campaign_cheat();     
1012                 break;  
1013         case KEY_DEBUGGED + KEY_D:
1014                 demo_start_playback("test.fsd");
1015                 break;
1016         }
1017 #else 
1018         }
1019 #endif
1020
1021         // do any processing based upon what happened to the snazzy menu
1022         switch (snazzy_action) {
1023         case SNAZZY_OVER:
1024                 main_hall_handle_mouse_location(code);
1025                 break;
1026
1027         case SNAZZY_CLICKED:
1028                 switch (code) {
1029                 // clicked on the exit region
1030                 case EXIT_REGION:
1031                         gamesnd_play_iface(SND_IFACE_MOUSE_CLICK);
1032                         main_hall_exit_game();
1033                         break;
1034
1035                 // clicked on the readyroom region
1036                 case READY_ROOM_REGION:
1037 #ifdef MULTIPLAYER_BETA_BUILD
1038                         gamesnd_play_iface(SND_IFACE_MOUSE_CLICK);
1039                         Player->flags |= PLAYER_FLAGS_IS_MULTI;
1040                         main_hall_do_multi_ready();
1041 #elif defined(E3_BUILD) || defined(PRESS_TOUR_BUILD)                                                                    
1042                         gameseq_post_event(GS_EVENT_NEW_CAMPAIGN);                      
1043 #else
1044                         if (Player->flags & PLAYER_FLAGS_IS_MULTI){
1045                                 gamesnd_play_iface(SND_IFACE_MOUSE_CLICK);
1046                                 main_hall_do_multi_ready();
1047                         } else {                                
1048                                 if(strlen(Main_hall_campaign_cheat)){
1049                                         gameseq_post_event(GS_EVENT_CAMPAIGN_CHEAT);
1050                                 } else {
1051                                         gameseq_post_event(GS_EVENT_NEW_CAMPAIGN);                              
1052                                 }
1053                                 gamesnd_play_iface(SND_IFACE_MOUSE_CLICK);                              
1054                         }
1055 #endif
1056                         break;
1057
1058                 // clicked on the tech room region
1059                 case TECH_ROOM_REGION:
1060 #if defined(FS2_DEMO)
1061                         gamesnd_play_iface(SND_IFACE_MOUSE_CLICK);
1062                         game_feature_not_in_demo_popup();
1063 #else
1064                         gamesnd_play_iface(SND_IFACE_MOUSE_CLICK);
1065                         gameseq_post_event( GS_EVENT_TECH_MENU );
1066 #endif
1067                         break;
1068
1069                 // clicked on the options region
1070                 case OPTIONS_REGION:
1071                         gamesnd_play_iface(SND_IFACE_MOUSE_CLICK);
1072                         gameseq_post_event(GS_EVENT_OPTIONS_MENU);
1073                         break;
1074
1075                 // clicked on the campaign toom region
1076                 case CAMPAIGN_ROOM_REGION:
1077 #if !defined(MULTIPLAYER_BETA_BUILD) && !defined(E3_BUILD) && !defined(PRESS_TOUR_BUILD)
1078
1079 #ifdef FS2_DEMO
1080                         gamesnd_play_iface(SND_IFACE_MOUSE_CLICK);
1081                         {
1082                         //game_feature_not_in_demo_popup();
1083                         int reset_campaign = popup(PF_USE_AFFIRMATIVE_ICON|PF_BODY_BIG, 2, "Exit", "Restart Campaign", "Campaign Room only available in full version. However, you may restart the campaign.");
1084                         if (reset_campaign == 1) {
1085                                 mission_campaign_savefile_delete(Campaign.filename);
1086                                 mission_campaign_load(Campaign.filename);
1087                                 mission_campaign_next_mission();
1088                         }
1089                         }
1090
1091 #else
1092                         if(Player->flags & PLAYER_FLAGS_IS_MULTI){
1093                                 gamesnd_play_iface(SND_IFACE_MOUSE_CLICK);
1094                                 main_hall_set_notify_string(XSTR( "Campaign Room not valid for multiplayer pilots", 366));
1095                         } else {
1096                                 gamesnd_play_iface(SND_IFACE_MOUSE_CLICK);
1097                                 gameseq_post_event(GS_EVENT_CAMPAIGN_ROOM);                     
1098                         }
1099 #endif
1100
1101 #endif
1102                         break;
1103
1104                 // clicked on the multiplayer region
1105                 case MULTIPLAYER_REGION:
1106 #if defined(DEMO) || defined(OEM_BUILD) // not for FS2_DEMO
1107                         game_feature_not_in_demo_popup();
1108 #else
1109                         if (Player->flags & PLAYER_FLAGS_IS_MULTI){
1110                                 // NOTE : this isn't a great thing to be calling this anymore. But we'll leave it for now
1111                                 gameseq_post_event( GS_EVENT_MULTI_JOIN_GAME );
1112                         } else {
1113                                 main_hall_set_notify_string(XSTR( "Not a valid multiplayer pilot!!", 367));
1114                         }
1115 #endif
1116                         break;
1117
1118                 // load mission key was pressed
1119                 case LOAD_MISSION_REGION:
1120 #ifdef RELEASE_REAL
1121 #else
1122         #if !(defined(MULTIPLAYER_BETA_BUILD) || defined(FS2_DEMO))
1123         //#if !defined(NDEBUG) || defined(INTERPLAYQA)
1124                                 if (Player->flags & PLAYER_FLAGS_IS_MULTI){
1125                                         gamesnd_play_iface(SND_IFACE_MOUSE_CLICK);
1126                                         main_hall_set_notify_string(XSTR( "Load Mission not valid for multiplayer pilots", 368));
1127                                 } else {
1128         #ifdef GAME_CD_CHECK
1129                                         // if ( !game_do_cd_check() ) {
1130                                                 // break;
1131                                         // }
1132         #endif
1133                                         gamesnd_play_iface(SND_IFACE_MOUSE_CLICK);
1134                                         gameseq_post_event( GS_EVENT_LOAD_MISSION_MENU );
1135                                 }
1136         //#endif
1137         #endif
1138 #endif
1139                         break;
1140
1141                 // quick start a game region
1142                 case QUICK_START_REGION:
1143 #if !defined(NDEBUG) && !defined(FS2_DEMO)
1144                         if (Player->flags & PLAYER_FLAGS_IS_MULTI){
1145                                 main_hall_set_notify_string(XSTR( "Quick Start not valid for multiplayer pilots", 369));
1146                         } else {
1147
1148                                 if (Num_recent_missions > 0)    {
1149                                         strncpy( Game_current_mission_filename, Recent_missions[0], MAX_FILENAME_LEN );
1150                                 } else {
1151                                         mission_load_up_campaign();
1152                                         strncpy( Game_current_mission_filename, Campaign.missions[0].name, MAX_FILENAME_LEN );
1153                                 }
1154
1155                                 Campaign.current_mission = -1;
1156                                 gameseq_post_event(GS_EVENT_START_GAME_QUICK);
1157                         }
1158 #endif
1159                         break;
1160
1161                 // clicked on the barracks region
1162                 case BARRACKS_REGION:                   
1163                         gamesnd_play_iface(SND_IFACE_MOUSE_CLICK);
1164                         gameseq_post_event( GS_EVENT_BARRACKS_MENU );
1165                         break;
1166
1167                 // increate the skill level
1168                 case SKILL_LEVEL_REGION: 
1169                         char temp[100];
1170
1171                         game_increase_skill_level();
1172                         sprintf(temp, XSTR( "Skill level set to %s.", 370), Skill_level_names(Game_skill_level));
1173                         main_hall_set_notify_string(temp);
1174                         break;                          
1175
1176                 // escape was pressed
1177                 case ESC_PRESSED:
1178                         // if there is a help overlay active, then don't quit the game - just kill the overlay
1179                         if(!help_overlay_active(Main_hall_overlay_id)){
1180                                 gamesnd_play_iface(SND_IFACE_MOUSE_CLICK);
1181                                 main_hall_exit_game();
1182                         }
1183                         // kill the overlay
1184                         else {
1185                                 help_overlay_set_state(Main_hall_overlay_id,0);
1186                         }
1187                         break;
1188                 }
1189
1190                 // if the escape key wasn't pressed handle any mouse position related events
1191                 if (code != ESC_PRESSED){
1192                         main_hall_handle_mouse_location(code);
1193                 }
1194                 break;
1195
1196                 default:
1197                         main_hall_handle_mouse_location(-1);
1198                         break;
1199         }
1200
1201         if ( mouse_down(MOUSE_LEFT_BUTTON) ) {
1202                 help_overlay_set_state(Main_hall_overlay_id, 0);
1203         }
1204
1205         // draw the background bitmap   
1206         gr_reset_clip();        
1207         GR_MAYBE_CLEAR_RES(Main_hall_bitmap);
1208         if(Main_hall_bitmap >= 0){
1209                 gr_set_bitmap(Main_hall_bitmap);
1210                 gr_bitmap(0, 0);
1211         }
1212
1213         // draw any pending notification messages
1214         main_hall_notify_do();                  
1215
1216         // render misc animations
1217         main_hall_render_misc_anims(frametime);
1218
1219         // render door animtions
1220         main_hall_render_door_anims(frametime); 
1221
1222         // blit any appropriate tooltips
1223         main_hall_maybe_blit_tooltips();
1224
1225         // fishtank
1226         fishtank_process();
1227
1228         // process any help "hit f1" timestamps and display any messages if necessary
1229         if (!F1_text_done) {
1230                 main_hall_process_help_stuff();
1231         }
1232
1233         // blit help overlay if active
1234         help_overlay_maybe_blit(Main_hall_overlay_id);
1235
1236         // blit the freespace version #
1237         main_hall_blit_version();
1238
1239         // blit ship and weapon table status
1240         main_hall_blit_table_status();
1241
1242         // if we're in nice D3D texture format
1243 #ifndef NDEBUG
1244         gr_set_color_fast(&Color_white);
1245
1246         // d3d
1247         if(gr_screen.mode == GR_DIRECT3D){
1248                 if(Bm_pixel_format == BM_PIXEL_FORMAT_ARGB_D3D){                
1249                         gr_string(320, gr_screen.max_h - 10, "D3D ARGB");
1250                 }
1251                 extern int D3d_rendition_uvs;
1252                 extern int D3D_32bit;
1253                 extern int D3D_fog_mode;        
1254                 extern int D3D_zbias;
1255                 if(D3d_rendition_uvs){
1256                         gr_string(320, gr_screen.max_h - 20, "D3D rendition");
1257                 }
1258                 if(D3D_32bit){
1259                         gr_string(320, gr_screen.max_h - 30, "D3D 32bit");
1260                 }
1261                 gr_printf(320, gr_screen.max_h - 40, "Fog : %d", D3D_fog_mode);
1262                 gr_printf(320, gr_screen.max_h - 50, "Zbias : %d", D3D_zbias);
1263                 // extern void d3d_test();
1264                 // d3d_test();
1265         } else if(gr_screen.mode == GR_GLIDE){
1266                 extern int Glide_voodoo3;
1267                 if(Glide_voodoo3){
1268                         gr_string(320, gr_screen.max_h - 20, "VOODOO 3");
1269                 }
1270         }
1271 #endif  
1272
1273         gr_flip();
1274
1275         // maybe run the player tips popup
1276 // #if defined(FS2_DEMO) && defined(NDEBUG)
1277         player_tips_popup();
1278 // #endif
1279
1280         // if we were supposed to skip a frame, then stop doing it after 1 frame
1281         if(Main_hall_frame_skip){
1282                 Main_hall_frame_skip = 0;
1283         }
1284 }
1285
1286 // close the main hall proper
1287 void main_hall_close()
1288 {
1289         int idx,s_idx;
1290
1291         if(!Main_hall_inited){
1292                 return;
1293         }       
1294
1295         // unload the main hall bitmap
1296         if(Main_hall_bitmap != -1){
1297                 bm_unload(Main_hall_bitmap);
1298         }
1299
1300         // unload any bitmaps
1301         if(Main_hall_mask >= 0){                
1302                 // make sure we unlock the mask bitmap so it can be unloaded
1303                 bm_unlock(Main_hall_mask);
1304                 if(!bm_unload(Main_hall_mask)){
1305                         nprintf(("General","WARNING! Couldn't unload main hall mask bitmap!\n"));
1306                 }
1307         }
1308
1309         // free up any (possibly) playing misc animation handles
1310         for(idx=0;idx<Main_hall->num_misc_animations;idx++){
1311                 if(Main_hall_misc_anim_instance[idx]!=NULL){
1312                         anim_stop_playing(Main_hall_misc_anim_instance[idx]);
1313                         Main_hall_misc_anim_instance[idx] = NULL;
1314                 }
1315         }
1316         
1317         // free up any (possibly) playing door animation handles
1318         for(idx=0;idx<Main_hall->num_door_animations;idx++){
1319                 if(Main_hall_door_anim_instance[idx]!=NULL){
1320                         anim_stop_playing(Main_hall_door_anim_instance[idx]);
1321                         Main_hall_door_anim_instance[idx] = NULL;
1322                 }
1323         }
1324         
1325
1326         // free up any misc animations/instances        
1327         for(idx=0;idx<Main_hall->num_misc_animations;idx++){
1328                 if((Main_hall_misc_anim_instance[idx]!=NULL) && (anim_playing(Main_hall_misc_anim_instance[idx]))){             
1329                         Main_hall_misc_anim_instance[idx] = NULL;
1330                 }
1331                 if(Main_hall_misc_anim[idx]!=NULL){
1332                         if(anim_free(Main_hall_misc_anim[idx]) == -1){
1333                                 nprintf(("General","WARNING!, Could not free up misc anim %s in main hall\n",Main_hall->misc_anim_name[idx]));
1334                         }
1335                 }       
1336         }
1337
1338         // free up any door animations/instances
1339         for(idx=0;idx<Main_hall->num_door_animations;idx++){
1340                 if((Main_hall_door_anim_instance[idx]!=NULL) && (anim_playing(Main_hall_door_anim_instance[idx]))){
1341                         Main_hall_door_anim_instance[idx] = NULL;                       
1342                 }
1343                 if(Main_hall_door_anim[idx]!=NULL){
1344                         if(anim_free(Main_hall_door_anim[idx]) == -1){
1345                                 nprintf(("General","WARNING!, Could not free up door anim %s in main hall\n",Main_hall->door_anim_name[idx]));
1346                         }
1347                 }               
1348         }       
1349
1350         // stop any playing door sounds
1351         for(idx=0;idx<Main_hall->num_door_sounds-2;idx++){      // don't cut off the glow sounds (requested by Dan)
1352                 if((Main_hall_door_sound_handles[idx] != -1) && snd_is_playing(Main_hall_door_sound_handles[idx])){
1353                         snd_stop(Main_hall_door_sound_handles[idx]);
1354                         Main_hall_door_sound_handles[idx] = -1;
1355                 }
1356         }       
1357
1358         // stop any playing misc animation sounds
1359         for(idx=0;idx<Main_hall->num_misc_animations;idx++){
1360                 for(s_idx=1;s_idx<10;s_idx++){
1361                         if(snd_is_playing(Main_hall->misc_anim_sound_handles[idx][s_idx])){
1362                                 snd_stop(Main_hall->misc_anim_sound_handles[idx][s_idx]);
1363                                 Main_hall->misc_anim_sound_handles[idx][s_idx] = -1;
1364                         }
1365                 }
1366         }
1367
1368         // unload the overlay bitmap
1369         help_overlay_unload(Main_hall_overlay_id);
1370
1371         // close any snazzy menu details
1372         snazzy_menu_close();
1373
1374         // restore
1375         palette_restore_palette();
1376
1377         // no fish
1378         fishtank_stop();        
1379
1380         // not inited anymore
1381         Main_hall_inited = 0;
1382 }
1383
1384 // start the main hall music playing
1385 void main_hall_start_music()
1386 {
1387         // start a looping ambient sound
1388         main_hall_start_ambient();
1389
1390         // if we have selected no music, then don't do this
1391         if ( Cmdline_freespace_no_music ) {
1392                 return;
1393         }
1394
1395         int main_hall_spooled_music_index = event_music_get_spooled_music_index(Main_hall->music);
1396         
1397         if ((Main_hall_music_handle == -1) && (main_hall_spooled_music_index != -1)) {
1398                 char *music_wavfile_name = Spooled_music[main_hall_spooled_music_index].filename;
1399                 if (music_wavfile_name != NULL) {
1400                                 Main_hall_music_handle = audiostream_open( music_wavfile_name, ASF_EVENTMUSIC );
1401                                 if ( Main_hall_music_handle != -1 )
1402                                         audiostream_play(Main_hall_music_handle, Master_event_music_volume);
1403                 }
1404                 else {
1405                         nprintf(("Warning", "No music file exists to play music at the main menu!\n"));
1406                 }
1407         }
1408 }
1409
1410 // stop the main hall music
1411 void main_hall_stop_music()
1412 {
1413         if ( Main_hall_music_handle != -1 ) {
1414                 audiostream_close_file(Main_hall_music_handle);
1415                 Main_hall_music_handle = -1;
1416         }
1417 }
1418
1419 // do any necessary instantiation of misc animations
1420 void main_hall_handle_misc_anims()
1421 {
1422         int idx,s_idx;
1423
1424         if(Main_hall_frame_skip)
1425                 return;
1426         
1427         for(idx=0;idx<Main_hall->num_misc_animations;idx++){
1428                 // if the anim isn't playing
1429                 if(Main_hall_misc_anim_instance[idx] == NULL){
1430                         // if the timestamp is -1, then reset it to some random value (based on MIN and MAX) and continue
1431                         if(Main_hall->misc_anim_delay[idx][0] == -1){
1432                                 Main_hall->misc_anim_delay[idx][0] = timestamp(Main_hall->misc_anim_delay[idx][1] + 
1433                                                                                                                       (int)(((float)rand()/(float)RAND_MAX) * (float)(Main_hall->misc_anim_delay[idx][2] - Main_hall->misc_anim_delay[idx][1])));
1434
1435                         // if the timestamp is not -1 and has popped, play the anim and make the timestap -1
1436                         } else if (timestamp_elapsed(Main_hall->misc_anim_delay[idx][0]) && Main_hall_misc_anim[idx]) {
1437                                 anim_play_struct aps;
1438
1439                                 anim_play_init(&aps, Main_hall_misc_anim[idx], Main_hall->misc_anim_coords[idx][0], Main_hall->misc_anim_coords[idx][1]);
1440                                 aps.screen_id = GS_STATE_MAIN_MENU;
1441                                 aps.framerate_independent = 1;
1442                                 
1443                                 Main_hall_misc_anim_instance[idx] = anim_play(&aps);                            
1444                                 
1445                                 // kill the timestamp   
1446                                 Main_hall->misc_anim_delay[idx][0] = -1;                                
1447
1448                                 // reset the "should be playing" flags
1449                                 for(s_idx=1;s_idx<10;s_idx++){
1450                                         Main_hall->misc_anim_sound_flag[idx][s_idx] = 0;
1451                                 }
1452                         }
1453                 }               
1454                 // if the anim is playing
1455                 else {
1456                         // check to see if any special trigger points have been reached by the animation
1457                         // since the frame triggers must be in ascending order, we will count down so that we don't trigger too many sounds
1458                         for(s_idx=Main_hall->misc_anim_special_sounds[idx][0]; s_idx > 0; s_idx--){
1459                                 // if we've passed the trigger point, then play the sound and break out of the loop
1460                                 if((Main_hall_misc_anim_instance[idx]->frame_num >= Main_hall->misc_anim_special_trigger[idx][s_idx]) && !Main_hall->misc_anim_sound_flag[idx][s_idx]){                                 
1461                                         Main_hall->misc_anim_sound_flag[idx][s_idx] = 1;
1462
1463                                         // if the sound is already playing, then kill it. This is a pretty safe thing to do since we can assume that
1464                                         // by the time we get to this point again, the sound will have been long finished
1465                                         if(snd_is_playing(Main_hall->misc_anim_sound_handles[idx][s_idx])){
1466                                                 snd_stop(Main_hall->misc_anim_sound_handles[idx][s_idx]);
1467                                                 Main_hall->misc_anim_sound_handles[idx][s_idx] = -1;
1468                                         }
1469                                         // play the sound
1470                                         Main_hall->misc_anim_sound_handles[idx][s_idx] = snd_play(&Snds_iface[Main_hall->misc_anim_special_sounds[idx][s_idx]],Main_hall->misc_anim_sound_pan[idx]);                                    
1471                                         break;
1472                                 }
1473                         }
1474
1475                         // if the animation mode is MISC_ANIM_MODE_HOLD, pause it at the last frame
1476                         if((Main_hall->misc_anim_modes[idx] == MISC_ANIM_MODE_HOLD) && (Main_hall_misc_anim_instance[idx]->frame_num == Main_hall_misc_anim_instance[idx]->stop_at)){                           
1477                                 anim_pause(Main_hall_misc_anim_instance[idx]);
1478                                 Main_hall_misc_anim_instance[idx]->stop_now = FALSE;
1479                         }                       
1480
1481                         // if the animation mode is MISC_ANIM_MODE_LOOP, check to see if it should be looped
1482                         if((Main_hall->misc_anim_modes[idx] == MISC_ANIM_MODE_LOOP) && (Main_hall_misc_anim_instance[idx]->frame_num == Main_hall_misc_anim_instance[idx]->stop_at)){                           
1483                                 anim_release_render_instance(Main_hall_misc_anim_instance[idx]);
1484
1485                                 // start it playing again
1486                                 anim_play_struct aps;
1487
1488                                 anim_play_init(&aps, Main_hall_misc_anim[idx], Main_hall->misc_anim_coords[idx][0], Main_hall->misc_anim_coords[idx][1]);
1489                                 aps.screen_id = GS_STATE_MAIN_MENU;
1490                                 aps.framerate_independent = 1;
1491                                 
1492                                 Main_hall_misc_anim_instance[idx] = anim_play(&aps);                            
1493                                 
1494                                 // kill the timestamp   
1495                                 Main_hall->misc_anim_delay[idx][0] = -1;                                
1496
1497                                 // reset the "should be playing" flags
1498                                 for(s_idx=1;s_idx<10;s_idx++){
1499                                         Main_hall->misc_anim_sound_flag[idx][s_idx] = 0;
1500                                 }
1501                         }                       
1502
1503                         // cull any misc animations which are marked as done (!is_playing)                              
1504                         if(!anim_playing(Main_hall_misc_anim_instance[idx])){                   
1505                                 Main_hall_misc_anim_instance[idx] = NULL;                               
1506                         }
1507                 }                       
1508         }       
1509 }
1510
1511 // render all playing misc animations
1512 void main_hall_render_misc_anims(float frametime)
1513 {
1514         int idx;
1515         
1516         // HACKETY HACK HACK - always render misc anim 3 first, if it is playing
1517         if(Main_hall_misc_anim_instance[2] != NULL){
1518                 anim_render_one(GS_STATE_MAIN_MENU,Main_hall_misc_anim_instance[2],frametime);
1519         }
1520
1521         // render all other animations
1522         for(idx=0;idx<MAX_MISC_ANIMATIONS;idx++){
1523                 // skip anim 3, which was previously rendered, if at all
1524                 if(idx == 2){
1525                         continue;
1526                 }
1527
1528                 // render it
1529                 if(Main_hall_misc_anim_instance[idx] != NULL){
1530                         anim_render_one(GS_STATE_MAIN_MENU,Main_hall_misc_anim_instance[idx],frametime);
1531                 }
1532         }
1533 }
1534
1535 // render all playing door animations
1536 void main_hall_render_door_anims(float frametime)
1537 {
1538         int idx;        
1539
1540         // render all door animations
1541         for(idx=0;idx<MAX_DOOR_ANIMATIONS;idx++){               
1542                 // render it
1543                 if(Main_hall_door_anim_instance[idx] != NULL){
1544                         anim_render_one(GS_STATE_MAIN_MENU,Main_hall_door_anim_instance[idx],frametime);
1545                 }
1546         }
1547 }
1548
1549 // handle starting, stopping and reversing "door" animations
1550 void main_hall_handle_region_anims()
1551 {
1552         int idx;
1553
1554         if(Main_hall_frame_skip)
1555                 return;
1556         
1557         // make sure we make any finished door animations NULL
1558         for(idx=0;idx<Main_hall->num_door_animations;idx++){
1559                 if((Main_hall_door_anim_instance[idx] != NULL) && !anim_playing(Main_hall_door_anim_instance[idx])){
1560                         Main_hall_door_anim_instance[idx] = NULL;
1561                 }
1562         }
1563         
1564         // go through each region animation
1565         for(idx=0;idx<Main_hall->num_door_animations;idx++){
1566                 // if the instance is not null and the animation is playing
1567                 if((Main_hall_door_anim_instance[idx] != NULL) && anim_playing(Main_hall_door_anim_instance[idx])){
1568                         // check to see if we should hold a given door "open"
1569                         if((Main_hall_mouse_region == idx) && (Main_hall_door_anim_instance[idx]->frame_num == Main_hall_door_anim_instance[idx]->stop_at)){
1570                                 anim_pause(Main_hall_door_anim_instance[idx]);
1571                                 Main_hall_door_anim_instance[idx]->stop_now = FALSE;
1572                         }
1573                         // check to see if we should close a door being held open
1574                         if((Main_hall_mouse_region != idx) && (Main_hall_door_anim_instance[idx]->paused)){
1575                                 anim_unpause(Main_hall_door_anim_instance[idx]);
1576                         }
1577                 }               
1578         }       
1579 }
1580
1581 // do any necessary processing based upon the mouse location
1582 void main_hall_handle_mouse_location(int cur_region)
1583 {
1584    if(Main_hall_frame_skip)
1585                 return;
1586
1587         if(cur_region > NUM_MAIN_HALL_MOUSE_REGIONS) {
1588                 // MWA -- inserted return since Int3() was tripped when hitting L from main
1589                 // menu.
1590                 return;         
1591         }
1592
1593         // if the mouse is now over a resgion
1594         if (cur_region != -1) {
1595                 // if we're still over the same region we were last frame, check stuff
1596                 if (cur_region == Main_hall_mouse_region) {
1597                         // if we have a linger timestamp set and it has expired, then get moving                        
1598                         if ((Main_hall_region_linger_stamp != -1) && timestamp_elapsed(Main_hall_region_linger_stamp)) {
1599                                 main_hall_mouse_grab_region(cur_region);                                
1600
1601                                 // release the region linger stamp
1602                                 Main_hall_region_linger_stamp = -1;
1603                         }
1604                 } else {
1605                         // if we're currently on another region, release it
1606                         if ((Main_hall_mouse_region != -1) && (cur_region != Main_hall_mouse_region)) {
1607                                 main_hall_mouse_release_region(Main_hall_mouse_region);
1608                         }
1609                 
1610                         // set the linger time
1611                         if (Main_hall_region_linger_stamp == -1) {
1612                                 Main_hall_mouse_region = cur_region;
1613                                 Main_hall_region_linger_stamp = timestamp(MAIN_HALL_REGION_LINGER);
1614                         }                       
1615                 }
1616         }
1617         // if it was over a region but isn't anymore, release that region
1618         else {
1619                 if (Main_hall_mouse_region != -1) {
1620                         main_hall_mouse_release_region(Main_hall_mouse_region);
1621                         Main_hall_mouse_region = -1;
1622
1623                         // release the region linger timestamp
1624                         Main_hall_region_linger_stamp = -1;
1625                 }
1626         }
1627 }
1628
1629 // if the mouse has moved off of the currently active region, handle the anim accordingly
1630 void main_hall_mouse_release_region(int region)
1631 {
1632         if(Main_hall_frame_skip){
1633                 return;
1634         }
1635
1636         // if the animation is currently playing in the forward direction, change direction and be done, otherwise don't do a thing
1637         if ( (Main_hall_door_anim_instance[region] != NULL) && anim_playing(Main_hall_door_anim_instance[region]) && (Main_hall_door_anim_instance[region]->direction == ANIM_DIRECT_FORWARD)){
1638                 anim_reverse_direction(Main_hall_door_anim_instance[region]);
1639         }
1640
1641         // check for door sounds, ignoring the OPTIONS_REGION (which isn't a door)
1642         if ((Main_hall_door_anim_instance[region] != NULL)) {
1643                 // don't stop the toaster oven or microwave regions from playing all the way through
1644                 if (Main_hall_door_sound_handles[region] != -1) {
1645                         snd_stop(Main_hall_door_sound_handles[region]);
1646                 }
1647                 Main_hall_door_sound_handles[region] = snd_play(&Snds_iface[Main_hall->door_sounds[region][1]], Main_hall->door_sound_pan[region]);
1648
1649                 // make sure to set the sound to play from the right spot
1650                 snd_set_pos(Main_hall_door_sound_handles[region], &Snds_iface[SND_MAIN_HALL_DOOR_CLOSE],
1651                                                 (float)(Main_hall_door_anim_instance[region]->start_at - Main_hall_door_anim_instance[region]->frame_num) / (float)Main_hall_door_anim_instance[region]->parent->total_frames, 1);                      
1652         }
1653 }
1654
1655 // if the mouse has moved on this region, handle it accordingly
1656 void main_hall_mouse_grab_region(int region)
1657 {
1658         if (Main_hall_frame_skip) {
1659                 return;
1660         }
1661
1662         // if the animation is not playing, start it playing
1663         if ( !Main_hall_door_anim_instance[region] ) {
1664                 if ( Main_hall_door_anim[region] ) {
1665                         anim_play_struct aps;
1666
1667                         anim_play_init(&aps, Main_hall_door_anim[region], Main_hall->door_anim_coords[region][0], Main_hall->door_anim_coords[region][1]);
1668                         aps.screen_id = GS_STATE_MAIN_MENU;
1669                         aps.framerate_independent = 1;
1670
1671                         Main_hall_door_anim_instance[region] = anim_play(&aps);
1672                 }
1673         } 
1674         // otherwise if its playing in the reverse direction, change it to the forward direction
1675         else if (Main_hall_door_anim_instance[region]->direction == ANIM_DIRECT_REVERSE) {
1676                 anim_reverse_direction(Main_hall_door_anim_instance[region]);
1677         }
1678
1679         // check for opening/starting sounds
1680         // kill the currently playing sounds if necessary
1681         if(Main_hall_door_sound_handles[region] != -1){                 
1682                 snd_stop(Main_hall_door_sound_handles[region]);
1683         }       
1684         Main_hall_door_sound_handles[region] = snd_play(&Snds_iface[Main_hall->door_sounds[region][0]],Main_hall->door_sound_pan[region]);                              
1685
1686         // start the sound playing at the right spot relative to the completion of the animation                
1687         if(Main_hall_door_anim_instance[region]->frame_num != -1){                      
1688                         snd_set_pos(Main_hall_door_sound_handles[region],&Snds_iface[SND_MAIN_HALL_DOOR_OPEN],
1689                                                         (float)Main_hall_door_anim_instance[region]->frame_num / (float)Main_hall_door_anim_instance[region]->parent->total_frames,1);
1690         }                               
1691 }
1692
1693 // handle any right clicks which may have occured
1694 void main_hall_handle_right_clicks()
1695 {
1696         int new_region;
1697
1698         if(Main_hall_frame_skip)
1699                 return;
1700
1701         // check to see if the button has been clicked
1702         if(!Main_hall_right_click){
1703                 if(mouse_down(MOUSE_RIGHT_BUTTON)){
1704                         // cycle through the available regions
1705                         if(Main_hall_last_clicked_region == NUM_MAIN_HALL_MOUSE_REGIONS - 1){
1706                                 new_region = 0;
1707                         } else
1708                                 new_region = Main_hall_last_clicked_region + 1;
1709
1710                         // set the position of the mouse cursor and the newly clicked region                    
1711                         mouse_set_pos(Main_hall->door_anim_coords[new_region][2],Main_hall->door_anim_coords[new_region][3]);                   
1712
1713                         main_hall_handle_mouse_location(new_region);
1714                         Main_hall_last_clicked_region = new_region;
1715                         
1716                         // set the mouse as being clicked
1717                         Main_hall_right_click = 1;
1718                 }
1719         } 
1720         // set the mouse as being unclicked
1721         else if(Main_hall_right_click && !(mouse_down(MOUSE_RIGHT_BUTTON))){
1722                 Main_hall_right_click = 0;
1723         }
1724 }
1725
1726 // cull any door sounds that have finished playing
1727 void main_hall_cull_door_sounds()
1728 {
1729         int idx;
1730         // basically just set the handle of any finished sound to be -1, so that we know its free any where else in the code we may need it
1731         for(idx=0;idx<Main_hall->num_door_sounds;idx++){
1732                 if((Main_hall_door_sound_handles[idx] != -1) && !snd_is_playing(Main_hall_door_sound_handles[idx])){                    
1733                         Main_hall_door_sound_handles[idx] = -1;
1734                 }
1735         }
1736 }
1737
1738 void main_hall_handle_random_intercom_sounds()
1739 {
1740         // if we have no timestamp for the next random sound, then set on
1741         if((Main_hall_next_intercom_sound_stamp == -1) && (Main_hall_intercom_sound_handle == -1)){
1742                 Main_hall_next_intercom_sound_stamp = timestamp((int)(((float)rand()/(float)RAND_MAX) * 
1743                                                                     (float)(Main_hall->intercom_delay[Main_hall_next_intercom_sound][1]
1744                                                                                                                                           - Main_hall->intercom_delay[Main_hall_intercom_sound_handle][0])) );          
1745         }
1746
1747         // if the there is no sound playing
1748         if(Main_hall_intercom_sound_handle == -1){
1749                 // if the timestamp has popped, play a sound
1750                 if((Main_hall_next_intercom_sound_stamp != -1) && (timestamp_elapsed(Main_hall_next_intercom_sound_stamp))){
1751                         // play the sound
1752                         Main_hall_intercom_sound_handle = snd_play(&Snds_iface[Main_hall->intercom_sounds[Main_hall_next_intercom_sound]]);                     
1753                         
1754                         // unset the timestamp
1755                         Main_hall_next_intercom_sound_stamp = -1;
1756                 }
1757         }
1758         // if the sound is playing
1759         else {
1760                 // if the sound has finished, set the timestamp and continue
1761                 if(!snd_is_playing(Main_hall_intercom_sound_handle)){
1762                         // increment the next sound
1763                         if(Main_hall_next_intercom_sound >= (Main_hall->num_random_intercom_sounds-1)){
1764                                 Main_hall_next_intercom_sound = 0;
1765                         } else {
1766                                 Main_hall_next_intercom_sound++;
1767                         }
1768
1769                         // set the timestamp
1770                         Main_hall_next_intercom_sound_stamp = timestamp((int)(((float)rand()/(float)RAND_MAX) * 
1771                                                                     (float)(Main_hall->intercom_delay[Main_hall_next_intercom_sound][1]
1772                                                                                                                                           - Main_hall->intercom_delay[Main_hall_next_intercom_sound][0])) );
1773
1774                         // release the sound handle
1775                         Main_hall_intercom_sound_handle = -1;
1776                 }
1777         }
1778 }
1779
1780 // set the notification string with its decay timeout
1781 void main_hall_set_notify_string(char *str)
1782 {
1783         strcpy(Main_hall_notify_text,str);
1784         Main_hall_notify_stamp = timestamp(MAIN_HALL_NOTIFY_TIME);
1785 }
1786
1787 void main_hall_notify_do()
1788 {
1789         // check to see if we should try and do something
1790         if(Main_hall_notify_stamp != -1){
1791            // if the text time has expired
1792                 if(timestamp_elapsed(Main_hall_notify_stamp)){
1793                         strcpy(Main_hall_notify_text,"");
1794                         Main_hall_notify_stamp = -1;
1795                 } else {
1796                         int w,h;
1797                         gr_set_color_fast(&Color_bright);
1798
1799                         gr_get_string_size(&w,&h,Main_hall_notify_text);
1800                         gr_printf((gr_screen.max_w - w)/2, gr_screen.max_h - 40, Main_hall_notify_text);
1801                 }
1802         }
1803 }
1804
1805 // start a looping ambient sound for main hall
1806 void main_hall_start_ambient()
1807 {
1808         int play_ambient_loop = 0;
1809
1810         if ( Main_hall_ambient_loop == -1 ) {
1811                 play_ambient_loop = 1;
1812         } else {
1813                 if ( !snd_is_playing(Main_hall_ambient_loop) ) {
1814                         play_ambient_loop = 1;
1815                 }
1816         }
1817
1818         if ( play_ambient_loop ) {
1819                 Main_hall_ambient_loop = snd_play_looping(&Snds_iface[SND_MAIN_HALL_AMBIENT]);
1820         }
1821 }
1822
1823 // stop a looping ambient sound for the main hall
1824 void main_hall_stop_ambient()
1825 {
1826         if ( Main_hall_ambient_loop != -1 ) {
1827                 snd_stop(Main_hall_ambient_loop);
1828                 Main_hall_ambient_loop = -1;
1829         }
1830 }
1831
1832 // Reset the volume of the looping ambient sound.  This is called from the options 
1833 // screen when the looping ambient sound might be playing.
1834 void main_hall_reset_ambient_vol()
1835 {
1836         if ( Main_hall_ambient_loop >= 0 ) {
1837                 snd_set_volume(Main_hall_ambient_loop, Snds_iface[SND_MAIN_HALL_AMBIENT].default_volume);
1838         }
1839 }
1840
1841 // blit the freespace version #
1842 void main_hall_blit_version()
1843 {
1844         char version_string[100];
1845         int w;
1846
1847         // format the version string
1848         get_version_string(version_string);
1849
1850         // get the length of the string
1851         gr_get_string_size(&w,NULL,version_string);
1852
1853         // print the string out in the lower right corner
1854         gr_set_color_fast(&Color_white);
1855         gr_string(gr_screen.max_w - 55, gr_screen.max_h - 12, version_string);
1856 }
1857
1858 // blit any necessary tooltips
1859 void main_hall_maybe_blit_tooltips()
1860 {
1861         int w;
1862         int text_index;
1863
1864         // if we're over no region - don't blit anything
1865         if(Main_hall_mouse_region < 0) {
1866                 return;
1867         }
1868
1869         // get the index of the proper text to be using
1870         if(Main_hall_mouse_region == READY_ROOM_REGION) {
1871                 // if this is a multiplayer pilot, the ready room region becomes the multiplayer region
1872                 if(Player->flags & PLAYER_FLAGS_IS_MULTI){
1873                         text_index = NUM_REGIONS - 1;
1874                 } else {
1875                         text_index = READY_ROOM_REGION;
1876                 }
1877         } else {
1878                 text_index = Main_hall_mouse_region;
1879         }
1880
1881         // set the color and blit the string
1882         if(!help_overlay_active(Main_hall_overlay_id)) {
1883                 int shader_y = (Main_hall->region_yval) - Main_hall_tooltip_padding[gr_screen.res];     // subtract more to pull higher
1884                 // get the width of the string
1885                 gr_get_string_size(&w, NULL, Main_hall->region_descript[text_index]);
1886
1887                 gr_set_shader(&Main_hall_tooltip_shader);
1888                 gr_shade(0, shader_y, gr_screen.clip_width, (gr_screen.clip_height - shader_y));
1889
1890                 gr_set_color_fast(&Color_bright_white);
1891                 gr_string((gr_screen.max_w - w)/2, Main_hall->region_yval, Main_hall->region_descript[text_index]);
1892         }
1893 }
1894
1895
1896 void main_hall_process_help_stuff()
1897 {
1898         int w, h;
1899         char str[255];
1900         
1901         // if the timestamp has popped, don't do anything
1902         if(Main_hall_help_stamp == -1) {
1903                 return;
1904         }
1905
1906         // if the timestamp has popped, advance frame
1907         if(timestamp_elapsed(Main_hall_help_stamp)) {
1908                 Main_hall_f1_text_frame++;
1909         }
1910
1911         // otherwise print out the message
1912         strcpy(str, XSTR( "Press F1 for help", 371));
1913         gr_get_string_size(&w, &h, str);
1914
1915         int y_anim_offset = Main_hall_f1_text_frame;
1916
1917         // if anim is off the screen finally, stop altogether
1918         if ( (y_anim_offset >= (2*Main_hall_tooltip_padding[gr_screen.res]) + h) || (help_overlay_active(Main_hall_overlay_id)) ) {
1919                 Main_hall_f1_text_frame = -1;
1920                 Main_hall_help_stamp = -1;
1921                 F1_text_done = 1;
1922                 return;
1923         }
1924
1925         // set the color and print out text and shader
1926         gr_set_color_fast(&Color_bright_white);
1927         gr_shade(0, 0, gr_screen.max_w, (2*Main_hall_tooltip_padding[gr_screen.res]) + h - y_anim_offset);
1928         gr_string((gr_screen.max_w - w)/2, Main_hall_tooltip_padding[gr_screen.res] - y_anim_offset, str);
1929 }
1930
1931 // what main hall we're on (should be 0 or 1)
1932 int main_hall_id()
1933 {       
1934         // only 1 of 2 main halls
1935         if(Main_hall == &Main_hall_defines[gr_screen.res][0]){
1936                 return 0;
1937         }
1938
1939         return 1;
1940
1941
1942 // read in main hall table
1943 void main_hall_read_table()
1944 {
1945         main_hall_defines *m, temp;
1946         int count, idx, s_idx, m_idx;
1947
1948         // read the file in
1949         read_file_text("mainhall.tbl");
1950         reset_parse();
1951
1952         // go for it
1953         count = 0;
1954         while(!optional_string("#end")){
1955
1956                 // read in 2 resolutions
1957                 for(m_idx=0; m_idx<GR_NUM_RESOLUTIONS; m_idx++){
1958                         // maybe use a temp main hall stuct
1959                         if(count >= NUM_MAIN_HALLS){
1960                                 m = &temp;
1961                         } else {
1962                                 m = &Main_hall_defines[m_idx][count];
1963                         }
1964
1965                         // ready
1966                         required_string("$Main Hall");
1967
1968                         // bitmap and mask
1969                         required_string("+Bitmap:");
1970                         stuff_string(m->bitmap, F_NAME, NULL, MAX_FILENAME_LEN);
1971                         required_string("+Mask:");
1972                         stuff_string(m->mask, F_NAME, NULL, MAX_FILENAME_LEN);
1973                         required_string("+Music:");
1974                         stuff_string(m->music, F_NAME, NULL, MAX_FILENAME_LEN);
1975
1976                         // intercom sounds
1977                         required_string("+Num Intercom Sounds:");
1978                         stuff_int(&m->num_random_intercom_sounds);              
1979                         for(idx=0; idx<m->num_random_intercom_sounds; idx++){                   
1980                                 // intercom delay
1981                                 required_string("+Intercom delay:");
1982                                 stuff_int(&m->intercom_delay[idx][0]);
1983                                 stuff_int(&m->intercom_delay[idx][1]);
1984                         }
1985                         for(idx=0; idx<m->num_random_intercom_sounds; idx++){                   
1986                                 // intercom sound id
1987                                 required_string("+Intercom sound:");
1988                                 stuff_int(&m->intercom_sounds[idx]);                    
1989                         }                       
1990                         for(idx=0; idx<m->num_random_intercom_sounds; idx++){                   
1991                                 // intercom pan
1992                                 required_string("+Intercom pan:");
1993                                 stuff_float(&m->intercom_sound_pan[idx]);                       
1994                         }                       
1995
1996                         // misc animations
1997                         required_string("+Num Misc Animations:");
1998                         stuff_int(&m->num_misc_animations);
1999                         for(idx=0; idx<m->num_misc_animations; idx++){
2000                                 // anim names
2001                                 required_string("+Misc anim:");
2002                                 stuff_string(m->misc_anim_name[idx], F_NAME, NULL);
2003                         }
2004                         for(idx=0; idx<m->num_misc_animations; idx++){
2005                                 // anim delay
2006                                 required_string("+Misc anim delay:");
2007                                 stuff_int(&m->misc_anim_delay[idx][0]);
2008                                 stuff_int(&m->misc_anim_delay[idx][1]);
2009                                 stuff_int(&m->misc_anim_delay[idx][2]);
2010                         }
2011                         for(idx=0; idx<m->num_misc_animations; idx++){
2012                                 // anim coords
2013                                 required_string("+Misc anim coords:");
2014                                 stuff_int(&m->misc_anim_coords[idx][0]);
2015                                 stuff_int(&m->misc_anim_coords[idx][1]);
2016                         }
2017                         for(idx=0; idx<m->num_misc_animations; idx++){
2018                                 // anim mode
2019                                 required_string("+Misc anim mode:");
2020                                 stuff_int(&m->misc_anim_modes[idx]);                    
2021                         }
2022                         for(idx=0; idx<m->num_misc_animations; idx++){
2023                                 // anim pan
2024                                 required_string("+Misc anim pan:");
2025                                 stuff_float(&m->misc_anim_sound_pan[idx]);
2026                         }
2027                         for(idx=0; idx<m->num_misc_animations; idx++){
2028                                 // anim sound id
2029                                 required_string("+Misc anim sounds:");
2030                                 stuff_int(&m->misc_anim_special_sounds[idx][0]);
2031                                 for(s_idx=0; s_idx<m->misc_anim_special_sounds[idx][0]; s_idx++){
2032                                         stuff_int(&m->misc_anim_special_sounds[idx][s_idx + 1]);
2033                                 }
2034                         }
2035                         for(idx=0; idx<m->num_misc_animations; idx++){
2036                                 // anim sound triggers
2037                                 required_string("+Misc anim trigger:");
2038                                 stuff_int(&m->misc_anim_special_trigger[idx][0]);
2039                                 for(s_idx=0; s_idx<m->misc_anim_special_trigger[idx][0]; s_idx++){
2040                                         stuff_int(&m->misc_anim_special_trigger[idx][s_idx + 1]);
2041                                 }
2042                         }
2043                         for(idx=0; idx<m->num_misc_animations; idx++){
2044                                 // anim sound handles
2045                                 required_string("+Misc anim handles:");
2046                                 stuff_int(&m->misc_anim_sound_handles[idx][0]);                 
2047                         }
2048                         for(idx=0; idx<m->num_misc_animations; idx++){
2049                                 // anim sound flags
2050                                 required_string("+Misc anim flags:");
2051                                 stuff_int(&m->misc_anim_sound_flag[idx][0]);                    
2052                         }
2053
2054                         // door animations
2055                         required_string("+Num Door Animations:");
2056                         stuff_int(&m->num_door_animations);
2057                         for(idx=0; idx<m->num_door_animations; idx++){
2058                                 // door name
2059                                 required_string("+Door anim:");
2060                                 stuff_string(m->door_anim_name[idx], F_NAME, NULL);
2061                         }
2062                         for(idx=0; idx<m->num_door_animations; idx++){
2063                                 // door coords
2064                                 required_string("+Door coords:");
2065                                 stuff_int(&m->door_anim_coords[idx][0]);
2066                                 stuff_int(&m->door_anim_coords[idx][1]);
2067                                 stuff_int(&m->door_anim_coords[idx][2]);
2068                                 stuff_int(&m->door_anim_coords[idx][3]);
2069                         }
2070                         for(idx=0; idx<m->num_door_animations; idx++){
2071                                 // door open and close sounds
2072                                 required_string("+Door sounds:");
2073                                 stuff_int(&m->door_sounds[idx][0]);
2074                                 stuff_int(&m->door_sounds[idx][1]);                     
2075                         }
2076                         for(idx=0; idx<m->num_door_animations; idx++){
2077                                 // door pan value
2078                                 required_string("+Door pan:");
2079                                 stuff_float(&m->door_sound_pan[idx]);                   
2080                         }
2081
2082                         // tooltip y location
2083                         required_string("+Tooltip Y:");
2084                         stuff_int(&m->region_yval);
2085                         for(idx=0; idx<NUM_REGIONS; idx++){
2086                                 m->region_descript[idx] = NULL;
2087                         }
2088                 }
2089
2090                 if(count < NUM_MAIN_HALLS){
2091                         count++;
2092                 }
2093         }
2094
2095         // are we funny?
2096         if(Vasudan_funny){
2097                 Main_hall_defines[GR_640][1].door_sounds[OPTIONS_REGION][0] = SND_VASUDAN_BUP;
2098                 Main_hall_defines[GR_640][1].door_sounds[OPTIONS_REGION][1] = SND_VASUDAN_BUP;
2099                 Main_hall_defines[GR_1024][1].door_sounds[OPTIONS_REGION][0] = SND_VASUDAN_BUP;
2100                 Main_hall_defines[GR_1024][1].door_sounds[OPTIONS_REGION][1] = SND_VASUDAN_BUP;
2101
2102                 // set head anim. hehe
2103                 strcpy(Main_hall_defines[GR_640][1].door_anim_name[OPTIONS_REGION], "vhallheads");
2104                 strcpy(Main_hall_defines[GR_1024][1].door_anim_name[OPTIONS_REGION], "2_vhallheads");
2105
2106                 // set the background
2107                 strcpy(Main_hall_defines[GR_640][1].bitmap, "vhallhead");
2108                 strcpy(Main_hall_defines[GR_1024][1].bitmap, "2_vhallhead");            
2109         }
2110 }
2111
2112 // make the vasudan main hall funny
2113 void main_hall_vasudan_funny()
2114 {
2115         Vasudan_funny = 1;
2116 }
2117
2118
2119 /*
2120 #include "3d.h"
2121 int argh = -1;
2122 matrix view = {
2123         0.0f, 0.0f, 0.0f,
2124         0.0f, 0.0f, 0.0f,
2125         0.0f, 0.0f, 1.0f
2126 };
2127 */
2128 void d3d_test()
2129 {
2130         /*      
2131         vertex p1;
2132         vector sun_pos = vmd_zero_vector;
2133         sun_pos.z = 1.0f;
2134
2135         if(argh == -1){
2136                 argh = bm_load("sun01");
2137                 bm_lock(argh, 16, BMP_TEX_XPARENT);
2138                 bm_unlock(argh);
2139         }
2140         
2141         g3_start_frame(1);
2142         g3_set_view_matrix(&vmd_zero_vector, &view, 0.5f);      
2143         g3_rotate_vertex(&p1, &sun_pos);
2144         g3_project_vertex(&p1);
2145         gr_zbuffer_set(GR_ZBUFF_NONE);
2146         gr_set_bitmap( argh );
2147         g3_draw_bitmap(&p1, 0, 0.05f, TMAP_FLAG_TEXTURED | TMAP_FLAG_XPARENT);          
2148         g3_end_frame();
2149         */
2150 }
2151