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