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