b6a73bd5146bde1e44b0956ba3b7ab4ecab55394
[taylor/freespace2.git] / src / freespace2 / freespace.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/Freespace2/FreeSpace.cpp $
11  * $Revision$
12  * $Date$
13  * $Author$
14  *
15  * Freespace main body
16  *
17  * $Log$
18  * Revision 1.40  2005/10/01 21:40:38  taylor
19  * deal with OS X apps a little better, sets the path only based on ".app" in the name rather than the name itself
20  * make sure a global cmdline.cfg file works with OS X when built as an app
21  *
22  * Revision 1.39  2005/08/12 08:57:20  taylor
23  * don't show hardware S-RAM value on HUD in debug
24  * do show in use GL texture memory
25  * have an actual fade effect for the credits screen artwork
26  *
27  * Revision 1.38  2004/09/20 01:31:44  theoddone33
28  * GCC 3.4 fixes.
29  *
30  * Revision 1.37  2004/07/04 11:31:43  taylor
31  * amd64 support, compiler warning fixes, don't use software rendering
32  *
33  * Revision 1.36  2004/06/12 01:11:35  taylor
34  * x86 compile fixes for OSX patch
35  *
36  * Revision 1.35  2004/06/11 00:53:02  tigital
37  * OSX: .app name, casts for gcc
38  *
39  * Revision 1.34  2003/08/09 03:18:03  taylor
40  * fix tips popup not having any tips
41  *
42  * Revision 1.33  2003/08/03 15:57:00  taylor
43  * simpler mouse usage; default ini settings in os_init(); cleanup
44  *
45  * Revision 1.32  2003/06/19 11:51:41  taylor
46  * adjustments to memory leak fixes
47  *
48  * Revision 1.31  2003/06/11 18:30:32  taylor
49  * plug memory leaks
50  *
51  * Revision 1.30  2003/06/03 04:00:39  taylor
52  * Polish language support (Janusz Dziemidowicz)
53  *
54  * Revision 1.29  2003/05/25 02:30:42  taylor
55  * Freespace 1 support
56  *
57  * Revision 1.28  2003/05/18 03:55:30  taylor
58  * automatic language selection support
59  *
60  * Revision 1.27  2003/03/03 04:54:44  theoddone33
61  * Commit Taylor's ShowFPS fix
62  *
63  * Revision 1.26  2003/02/20 17:41:07  theoddone33
64  * Userdir patch from Taylor Richards
65  *
66  * Revision 1.25  2003/01/30 19:54:10  relnev
67  * ini config option for the frames per second counter (Taylor Richards)
68  *
69  * Revision 1.24  2002/08/31 01:39:13  theoddone33
70  * Speed up the renderer a tad
71  *
72  * Revision 1.23  2002/08/04 02:31:00  relnev
73  * make numlock not overlap with pause
74  *
75  * Revision 1.22  2002/08/02 23:07:03  relnev
76  * don't access the mouse in standalone mode
77  *
78  * Revision 1.21  2002/07/28 05:05:08  relnev
79  * removed some old stuff
80  *
81  * Revision 1.20  2002/07/24 00:20:41  relnev
82  * nothing interesting
83  *
84  * Revision 1.19  2002/06/17 06:33:08  relnev
85  * ryan's struct patch for gcc 2.95
86  *
87  * Revision 1.18  2002/06/16 04:46:33  relnev
88  * set up correct checksums for demo
89  *
90  * Revision 1.17  2002/06/09 04:41:17  relnev
91  * added copyright header
92  *
93  * Revision 1.16  2002/06/09 03:16:04  relnev
94  * added _splitpath.
95  *
96  * removed unneeded asm, old sdl 2d setup.
97  *
98  * fixed crash caused by opengl_get_region.
99  *
100  * Revision 1.15  2002/06/05 08:05:28  relnev
101  * stub/warning removal.
102  *
103  * reworked the sound code.
104  *
105  * Revision 1.14  2002/06/05 04:03:32  relnev
106  * finished cfilesystem.
107  *
108  * removed some old code.
109  *
110  * fixed mouse save off-by-one.
111  *
112  * sound cleanups.
113  *
114  * Revision 1.13  2002/06/02 04:26:34  relnev
115  * warning cleanup
116  *
117  * Revision 1.12  2002/06/02 00:31:35  relnev
118  * implemented osregistry
119  *
120  * Revision 1.11  2002/06/01 09:00:34  relnev
121  * silly debug memmanager
122  *
123  * Revision 1.10  2002/06/01 07:12:32  relnev
124  * a few NDEBUG updates.
125  *
126  * removed a few warnings.
127  *
128  * Revision 1.9  2002/05/31 03:05:59  relnev
129  * sane default
130  *
131  * Revision 1.8  2002/05/29 02:52:32  theoddone33
132  * Enable OpenGL renderer
133  *
134  * Revision 1.7  2002/05/28 08:52:03  relnev
135  * implemented two assembly stubs.
136  *
137  * cleaned up a few warnings.
138  *
139  * added a little demo hackery to make it progress a little farther.
140  *
141  * Revision 1.6  2002/05/28 06:28:20  theoddone33
142  * Filesystem mods, actually reads some data files now
143  *
144  * Revision 1.5  2002/05/28 04:07:28  theoddone33
145  * New graphics stubbing arrangement
146  *
147  * Revision 1.4  2002/05/27 22:46:52  theoddone33
148  * Remove more undefined symbols
149  *
150  * Revision 1.3  2002/05/26 23:31:18  relnev
151  * added a few files that needed to be compiled
152  *
153  * freespace.cpp: now compiles
154  *
155  * Revision 1.2  2002/05/07 03:16:44  theoddone33
156  * The Great Newline Fix
157  *
158  * Revision 1.1.1.1  2002/05/03 03:28:09  root
159  * Initial import.
160  *
161  * 
162  * 201   6/16/00 3:15p Jefff
163  * sim of the year dvd version changes, a few german soty localization
164  * fixes
165  * 
166  * 200   11/03/99 11:06a Jefff
167  * 1.2 checksums
168  * 
169  * 199   10/26/99 5:07p Jamest
170  * fixed jeffs dumb debug code
171  * 
172  * 198   10/25/99 5:53p Jefff
173  * call control_config_common_init() on startup
174  * 
175  * 197   10/14/99 10:18a Daveb
176  * Fixed incorrect CD checking problem on standalone server.
177  * 
178  * 196   10/13/99 9:22a Daveb
179  * Fixed Fred jumpnode placing bug. Fixed 1024 glide tiled texture problem
180  * related to movies. Fixed launcher spawning from PXO screen.
181  * 
182  * 195   10/06/99 11:05a Jefff
183  * new oem upsell 3 hotspot coords
184  * 
185  * 194   10/06/99 10:31a Jefff
186  * OEM updates
187  * 
188  * 193   10/01/99 9:10a Daveb
189  * V 1.1 PATCH
190  * 
191  * 192   9/15/99 4:57a Dave
192  * Updated ships.tbl checksum
193  * 
194  * 191   9/15/99 3:58a Dave
195  * Removed framerate warning at all times.
196  * 
197  * 190   9/15/99 3:16a Dave
198  * Remove mt-011.fs2 from the builtin mission list.
199  * 
200  * 189   9/15/99 1:45a Dave
201  * Don't init joystick on standalone. Fixed campaign mode on standalone.
202  * Fixed no-score-report problem in TvT
203  * 
204  * 188   9/14/99 6:08a Dave
205  * Updated (final) single, multi, and campaign list.
206  * 
207  * 187   9/14/99 3:26a Dave
208  * Fixed laser fogging problem in nebula (D3D)> Fixed multiplayer
209  * respawn-too-early problem. Made a few crash points safe.
210  * 
211  * 186   9/13/99 4:52p Dave
212  * RESPAWN FIX
213  * 
214  * 185   9/12/99 8:09p Dave
215  * Fixed problem where skip-training button would cause mission messages
216  * not to get paged out for the current mission.
217  * 
218  * 184   9/10/99 11:53a Dave
219  * Shutdown graphics before sound to eliminate apparent lockups when
220  * Directsound decides to be lame. Fix TOPMOST problem with D3D windows.
221  * 
222  * 183   9/09/99 11:40p Dave
223  * Handle an SDL_assert() in beam code. Added supernova sounds. Play the right
224  * 2 end movies properly, based upon what the player did in the mission.
225  * 
226  * 182   9/08/99 10:29p Dave
227  * Make beam sound pausing and unpausing much safer.
228  * 
229  * 181   9/08/99 10:01p Dave
230  * Make sure game won't run in a drive's root directory. Make sure
231  * standalone routes suqad war messages properly to the host.
232  * 
233  * 180   9/08/99 3:22p Dave
234  * Updated builtin mission list.
235  * 
236  * 179   9/08/99 12:01p Jefff
237  * fixed Game_builtin_mission_list typo on Training-2.fs2
238  * 
239  * 178   9/08/99 9:48a Andsager
240  * Add force feedback for engine wash.
241  * 
242  * 177   9/07/99 4:01p Dave
243  * Fixed up a string.tbl paroblem (self destruct message). Make sure IPX
244  * does everything properly (setting up address when binding). Remove
245  * black rectangle background from UI_INPUTBOX.
246  * 
247  * 176   9/13/99 2:40a Dave
248  * Comment in full 80 minute CD check for RELEASE_REAL builds.
249  * 
250  * 175   9/06/99 6:38p Dave
251  * Improved CD detection code.
252  * 
253  * 174   9/06/99 1:30a Dave
254  * Intermediate checkin. Started on enforcing CD-in-drive to play the
255  * game.
256  * 
257  * 173   9/06/99 1:16a Dave
258  * Make sure the user sees the intro movie.
259  * 
260  * 172   9/04/99 8:00p Dave
261  * Fixed up 1024 and 32 bit movie support.
262  * 
263  * 171   9/03/99 1:32a Dave
264  * CD checking by act. Added support to play 2 cutscenes in a row
265  * seamlessly. Fixed super low level cfile bug related to files in the
266  * root directory of a CD. Added cheat code to set campaign mission # in
267  * main hall.
268  * 
269  * 170   9/01/99 10:49p Dave
270  * Added nice SquadWar checkbox to the client join wait screen.
271  * 
272  * 169   9/01/99 10:14a Dave
273  * Pirate bob.
274  * 
275  * 168   8/29/99 4:51p Dave
276  * Fixed damaged checkin.
277  * 
278  * 167   8/29/99 4:18p Andsager
279  * New "burst" limit for friendly damage.  Also credit more damage done
280  * against large friendly ships.
281  * 
282  * 166   8/27/99 6:38p Alanl
283  * crush the blasted repeating messages bug
284  * 
285  * 164   8/26/99 9:09p Dave
286  * Force framerate check in everything but a RELEASE_REAL build.
287  * 
288  * 163   8/26/99 9:45a Dave
289  * First pass at easter eggs and cheats.
290  * 
291  * 162   8/24/99 8:55p Dave
292  * Make sure nondimming pixels work properly in tech menu.
293  * 
294  * 161   8/24/99 1:49a Dave
295  * Fixed client-side afterburner stuttering. Added checkbox for no version
296  * checking on PXO join. Made button info passing more friendly between
297  * client and server.
298  * 
299  * 160   8/22/99 5:53p Dave
300  * Scoring fixes. Added self destruct key. Put callsigns in the logfile
301  * instead of ship designations for multiplayer players.
302  * 
303  * 159   8/22/99 1:19p Dave
304  * Fixed up http proxy code. Cleaned up scoring code. Reverse the order in
305  * which d3d cards are detected.
306  * 
307  * 158   8/20/99 2:09p Dave
308  * PXO banner cycling.
309  * 
310  * 157   8/19/99 10:59a Dave
311  * Packet loss detection.
312  * 
313  * 156   8/19/99 10:12a Alanl
314  * preload mission-specific messages on machines greater than 48MB
315  * 
316  * 155   8/16/99 4:04p Dave
317  * Big honking checkin.
318  * 
319  * 154   8/11/99 5:54p Dave
320  * Fixed collision problem. Fixed standalone ghost problem.
321  * 
322  * 153   8/10/99 7:59p Jefff
323  * XSTR'ed some stuff
324  * 
325  * 152   8/10/99 6:54p Dave
326  * Mad optimizations. Added paging to the nebula effect.
327  * 
328  * 151   8/10/99 3:44p Jefff
329  * loads Intelligence information on startup
330  * 
331  * 150   8/09/99 3:47p Dave
332  * Fixed incorrect nebula regeneration. Default HUD to low-contrast in
333  * non-nebula missions.
334  * 
335  * 149   8/09/99 2:21p Andsager
336  * Fix patching from multiplayer direct to launcher update tab.
337  * 
338  * 148   8/09/99 10:36a Dave
339  * Version info for game.
340  * 
341  * 147   8/06/99 9:46p Dave
342  * Hopefully final changes for the demo.
343  * 
344  * 146   8/06/99 3:34p Andsager
345  * Make title version info "(D)" -> "D"  show up nicely
346  * 
347  * 145   8/06/99 2:59p Adamp
348  * Fixed NT launcher/update problem.
349  * 
350  * 144   8/06/99 1:52p Dave
351  * Bumped up MAX_BITMAPS for the demo.
352  * 
353  * 143   8/06/99 12:17p Andsager
354  * Demo: down to just 1 demo dog
355  * 
356  * 142   8/05/99 9:39p Dave
357  * Yet another new checksum.
358  * 
359  * 141   8/05/99 6:19p Dave
360  * New demo checksums.
361  * 
362  * 140   8/05/99 5:31p Andsager
363  * Up demo version 1.01
364  * 
365  * 139   8/05/99 4:22p Andsager
366  * No time limit on upsell screens.  Reverse order of display of upsell
367  * bitmaps.
368  * 
369  * 138   8/05/99 4:17p Dave
370  * Tweaks to client interpolation.
371  * 
372  * 137   8/05/99 3:52p Danw
373  * 
374  * 136   8/05/99 3:01p Danw
375  * 
376  * 135   8/05/99 2:43a Anoop
377  * removed duplicate definition.
378  * 
379  * 134   8/05/99 2:13a Dave
380  * Fixed build error.
381  * 
382  * 133   8/05/99 2:05a Dave
383  * Whee.
384  * 
385  * 132   8/05/99 1:22a Andsager
386  * fix upsell bug.
387  * 
388  * 131   8/04/99 9:51p Andsager
389  * Add title screen to demo
390  * 
391  * 130   8/04/99 6:47p Jefff
392  * fixed link error resulting from #ifdefs
393  * 
394  * 129   8/04/99 6:26p Dave
395  * Updated ship tbl checksum.
396  * 
397  * 128   8/04/99 5:40p Andsager
398  * Add multiple demo dogs
399  * 
400  * 127   8/04/99 5:36p Andsager
401  * Show upsell screens at end of demo campaign before returning to main
402  * hall.
403  * 
404  * 126   8/04/99 11:42a Danw
405  * tone down EAX reverb
406  * 
407  * 125   8/04/99 11:23a Dave
408  * Updated demo checksums.
409  * 
410  * 124   8/03/99 11:02p Dave
411  * Maybe fixed sync problems in multiplayer.
412  * 
413  * 123   8/03/99 6:21p Jefff
414  * minor text change
415  * 
416  * 122   8/03/99 3:44p Andsager
417  * Launch laucher if trying to run FS without first having configured
418  * system.
419  * 
420  * 121   8/03/99 12:45p Dave
421  * Update checksums.
422  * 
423  * 120   8/02/99 9:13p Dave
424  * Added popup tips.
425  * 
426  * 119   7/30/99 10:31p Dave
427  * Added comm menu to the configurable hud files.
428  * 
429  * 118   7/30/99 5:17p Andsager
430  * first fs2demo checksums
431  * 
432  * 117   7/29/99 3:09p Anoop
433  * 
434  * 116   7/29/99 12:05a Dave
435  * Nebula speed optimizations.
436  * 
437  * 115   7/27/99 8:59a Andsager
438  * Make major, minor version consistent for all builds.  Only show major
439  * and minor for launcher update window.
440  * 
441  * 114   7/26/99 5:50p Dave
442  * Revised ingame join. Better? We'll see....
443  * 
444  * 113   7/26/99 5:27p Andsager
445  * Add training mission as builtin to demo build
446  * 
447  * 112   7/24/99 1:54p Dave
448  * Hud text flash gauge. Reworked dead popup to use 4 buttons in red-alert
449  * missions.
450  * 
451  * 111   7/22/99 4:00p Dave
452  * Fixed beam weapon muzzle glow rendering. Externalized hud shield info.
453  * 
454  * 110   7/21/99 8:10p Dave
455  * First run of supernova effect.
456  * 
457  * 109   7/20/99 1:49p Dave
458  * Peter Drake build. Fixed some release build warnings.
459  * 
460  * 108   7/19/99 2:26p Andsager
461  * set demo multiplayer missions
462  * 
463  * 107   7/18/99 5:19p Dave
464  * Jump node icon. Fixed debris fogging. Framerate warning stuff.
465  * 
466  * 106   7/16/99 1:50p Dave
467  * 8 bit aabitmaps. yay.
468  * 
469  * 105   7/15/99 3:07p Dave
470  * 32 bit detection support. Mouse coord commandline.
471  * 
472  * 104   7/15/99 2:13p Dave
473  * Added 32 bit detection.
474  * 
475  * 103   7/15/99 9:20a Andsager
476  * FS2_DEMO initial checkin
477  * 
478  * 102   7/14/99 11:02a Dave
479  * Skill level default back to easy. Blech.
480  * 
481  * 101   7/09/99 5:54p Dave
482  * Seperated cruiser types into individual types. Added tons of new
483  * briefing icons. Campaign screen.
484  * 
485  * 100   7/08/99 4:43p Andsager
486  * New check for sparky_hi and print if not found.
487  * 
488  * 99    7/08/99 10:53a Dave
489  * New multiplayer interpolation scheme. Not 100% done yet, but still
490  * better than the old way.
491  * 
492  * 98    7/06/99 4:24p Dave
493  * Mid-level checkin. Starting on some potentially cool multiplayer
494  * smoothness crap.
495  * 
496  * 97    7/06/99 3:35p Andsager
497  * Allow movie to play before red alert mission.
498  * 
499  * 96    7/03/99 5:50p Dave
500  * Make rotated bitmaps draw properly in padlock views.
501  * 
502  * 95    7/02/99 9:55p Dave
503  * Player engine wash sound.
504  * 
505  * 94    7/02/99 4:30p Dave
506  * Much more sophisticated lightning support.
507  * 
508  * 93    6/29/99 7:52p Dave
509  * Put in exception handling in FS2.
510  * 
511  * 92    6/22/99 9:37p Dave
512  * Put in pof spewing.
513  * 
514  * 91    6/16/99 4:06p Dave
515  * New pilot info popup. Added new draw-bitmap-as-poly function.
516  * 
517  * 90    6/15/99 1:56p Andsager
518  * For release builds, allow start up in high res only with
519  * sparky_hi._fs2.vp
520  * 
521  * 89    6/15/99 9:34a Dave
522  * Fixed key checking in single threaded version of the stamp notification
523  * screen. 
524  * 
525  * 88    6/09/99 2:55p Andsager
526  * Allow multiple asteroid subtypes (of large, medium, small) and follow
527  * family.
528  * 
529  * 87    6/08/99 1:14a Dave
530  * Multi colored hud test.
531  * 
532  * 86    6/04/99 9:52a Dave
533  * Fixed some rendering problems.
534  * 
535  * 85    6/03/99 10:15p Dave
536  * Put in temporary main hall screen.
537  * 
538  * 84    6/02/99 6:18p Dave
539  * Fixed TNT lockup problems! Wheeeee!
540  * 
541  * 83    6/01/99 3:52p Dave
542  * View footage screen. Fixed xstrings to not display the & symbol. Popup,
543  * dead popup, pxo find player popup, pxo private room popup.
544  * 
545  * 82    5/26/99 1:28p Jasenw
546  * changed coords for loading ani
547  * 
548  * 81    5/26/99 11:46a Dave
549  * Added ship-blasting lighting and made the randomization of lighting
550  * much more customizable.
551  * 
552  * 80    5/24/99 5:45p Dave
553  * Added detail levels to the nebula, with a decent speedup. Split nebula
554  * lightning into its own section.
555  * 
556  * 
557  */
558
559 #include <stdio.h>
560 #include <stdlib.h>
561 #include <time.h>
562
563 #include "pstypes.h"
564 #include "systemvars.h"
565 #include "key.h"
566 #include "vecmat.h"
567 #include "2d.h"
568 #include "3d.h"
569 #include "starfield.h"
570 #include "lighting.h"
571 #include "weapon.h"
572 #include "ship.h"
573 #include "palman.h"
574 #include "osapi.h"
575 #include "fireballs.h"
576 #include "debris.h"
577 #include "timer.h"
578 #include "fix.h"
579 #include "floating.h"
580 #include "gamesequence.h"
581 #include "radar.h"
582 #include "optionsmenu.h"
583 #include "playermenu.h"
584 #include "trainingmenu.h"
585 #include "techmenu.h"
586 #include "ai.h"
587 #include "hud.h"
588 #include "hudmessage.h"
589 #include "psnet.h"
590 #include "missiongoals.h"
591 #include "missionparse.h"
592 #include "bmpman.h"
593 #include "joy.h"
594 #include "joy_ff.h"
595 #include "multi.h"
596 #include "multiutil.h"
597 #include "multimsgs.h"
598 #include "multiui.h"
599 #include "multi_pxo.h"
600 #include "cfile.h"
601 #include "player.h"
602 #include "freespace.h"
603 #include "managepilot.h"
604 #include "sound.h"
605 #include "contexthelp.h"
606 #include "mouse.h"
607 #include "joy.h"
608 #include "missionbrief.h"
609 #include "missiondebrief.h"
610 #include "ui.h"
611 #include "missionshipchoice.h"
612 #include "model.h"
613 #include "hudconfig.h"
614 #include "controlsconfig.h"
615 #include "missionmessage.h"
616 #include "missiontraining.h"
617 #include "hudets.h"
618 #include "hudtarget.h"
619 #include "gamesnd.h"
620 #include "eventmusic.h"
621 #include "animplay.h"
622 #include "missionweaponchoice.h"
623 #include "missionlog.h"
624 #include "audiostr.h"
625 #include "hudlock.h"
626 #include "missioncampaign.h"
627 #include "credits.h"
628 #include "missionhotkey.h"
629 #include "objectsnd.h"
630 #include "cmeasure.h"
631 #include "ai.h"
632 #include "linklist.h"
633 #include "shockwave.h"
634 #include "afterburner.h"
635 #include "scoring.h"
636 #include "stats.h"
637 #include "cmdline.h"
638 #include "timer.h"
639 #include "stand_server.h"
640 #include "pcxutils.h"
641 #include "hudtargetbox.h"
642 #include "multi_xfer.h"
643 #include "hudescort.h"
644 #include "multiutil.h"
645 #include "sexp.h"
646 #include "medals.h"
647 #include "multiteamselect.h"
648 #include "shipfx.h"
649 #include "readyroom.h"
650 #include "mainhallmenu.h"
651 #include "multilag.h"
652 #include "trails.h"
653 #include "particle.h"
654 #include "popup.h"
655 #include "multi_ingame.h"
656 #include "snazzyui.h"
657 #include "asteroid.h"
658 #include "popupdead.h"
659 #include "multi_voice.h"
660 #include "missioncmdbrief.h"
661 #include "redalert.h"
662 #include "gameplayhelp.h"
663 #include "multilag.h"
664 #include "staticrand.h"
665 #include "multi_pmsg.h"
666 #include "levelpaging.h"
667 #include "observer.h"
668 #include "multi_pause.h"
669 #include "multi_endgame.h"
670 #include "cutscenes.h"
671 #include "multi_respawn.h"
672 #include "movie.h"
673 #include "multi_obj.h"
674 #include "multi_log.h"
675 #include "emp.h"
676 #include "localize.h"
677 #include "osregistry.h"
678 #include "barracks.h"
679 #include "missionpause.h"
680 #include "font.h"
681 #include "alphacolors.h"
682 #include "objcollide.h"
683 #include "flak.h"
684 #include "neb.h"
685 #include "neblightning.h"
686 #include "shipcontrails.h"
687 #include "awacs.h"
688 #include "beam.h"
689 #include "multi_dogfight.h"
690 #include "multi_rate.h"
691 #include "muzzleflash.h"
692 #include "encrypt.h"
693 #include "demo.h"
694 #include "version.h"
695 #include "mainhalltemp.h"
696 #include "exceptionhandler.h"
697 #include "supernova.h"
698 #include "hudshield.h"
699 // #include "names.h"
700 #include "shiphit.h"
701 #include "missionloopbrief.h"
702
703 #ifdef NDEBUG
704 #ifdef FRED
705 #error macro FRED is defined when trying to build release Fred.  Please undefine FRED macro in build settings
706 #endif
707 #endif
708
709 //      Revision history.
710 //      Full version:
711 //    1.00.04   5/26/98 MWA -- going final (12 pm)
712 //    1.00.03   5/26/98 MWA -- going final (3 am)
713 //    1.00.02   5/25/98 MWA -- going final
714 //    1.00.01   5/25/98 MWA -- going final
715 //              0.90            5/21/98 MWA -- getting ready for final.
716 //              0.10            4/9/98.  Set by MK.
717 //
718 //      Demo version: (obsolete since DEMO codebase split from tree)
719 //              0.03            4/10/98 AL.     Interplay rev
720 //              0.02            4/8/98  MK.     Increased when this system was modified.
721 //              0.01            4/7/98? AL.     First release to Interplay QA.
722 //
723 //      OEM version:
724 //              1.00            5/28/98 AL.     First release to Interplay QA.
725
726 void game_level_init(int seed = -1);
727 void game_post_level_init();
728 void game_do_frame();
729 void game_update_missiontime(); // called from game_do_frame() and navmap_do_frame()
730 void game_reset_time();
731 void game_show_framerate();                     // draws framerate in lower right corner
732
733 int Game_no_clear = 0;
734
735 int Pofview_running = 0;
736 int Nebedit_running = 0;
737 int Fonttool_running = 0;
738
739 typedef struct big_expl_flash {
740         float max_flash_intensity;      // max intensity
741         float cur_flash_intensity;      // cur intensity
742         int     flash_start;            // start time
743 } big_expl_flash;
744
745 #define FRAME_FILTER 16
746
747 #define DEFAULT_SKILL_LEVEL     1
748 int     Game_skill_level = DEFAULT_SKILL_LEVEL;
749
750 #define VIEWER_ZOOM_DEFAULT 0.75f                       //      Default viewer zoom, 0.625 as per multi-lateral agreement on 3/24/97
751 float Viewer_zoom = VIEWER_ZOOM_DEFAULT;
752
753 #define EXE_FNAME       ("fs2.exe")
754 #define LAUNCHER_FNAME  ("freespace2.exe")
755
756
757 // JAS: Code for warphole camera.
758 // Needs to be cleaned up.
759 vector Camera_pos = ZERO_VECTOR;
760 vector Camera_velocity = ZERO_VECTOR;
761 vector Camera_desired_velocity = ZERO_VECTOR;
762 matrix Camera_orient = IDENTITY_MATRIX;
763 float Camera_damping = 1.0f;
764 float Camera_time = 0.0f;
765 float Warpout_time = 0.0f;
766 int Warpout_forced = 0;         // Set if this is a forced warpout that cannot be cancelled.
767 int Warpout_sound = -1;
768 void camera_move();
769 int Use_joy_mouse = 0;
770 int Use_palette_flash = 1;
771 int Show_area_effect = 0;
772 object  *Last_view_target = NULL;
773
774 int dogfight_blown = 0;
775
776 int     frame_int = -1;
777 float frametimes[FRAME_FILTER];
778 float frametotal = 0.0f;
779 float flFrametime;
780
781 #ifdef RELEASE_REAL
782         int     Show_framerate = 0;
783 #else 
784         int     Show_framerate = 1;
785 #endif
786
787 int     Framerate_cap = 120;
788 int     Show_mem = 0;
789 int     Show_cpu = 0;
790 int     Show_target_debug_info = 0;
791 int     Show_target_weapons = 0;
792 int     Game_font = -1;
793
794 #ifndef NDEBUG
795 static int Show_player_pos = 0;         // debug console command to show player world pos on HUD
796 #endif
797
798 int Debug_octant = -1;
799
800 fix Game_time_compression = F1_0;
801
802 // if the ships.tbl the player has is valid
803 int Game_ships_tbl_valid = 0;
804
805 // if the weapons.tbl the player has is valid
806 int Game_weapons_tbl_valid = 0;
807
808 #ifndef NDEBUG
809 int Test_begin = 0;
810 extern int      Player_attacking_enabled;
811 int Show_net_stats;
812 #endif
813
814 int Pre_player_entry;
815
816 int     Fred_running = 0;
817 char Game_current_mission_filename[MAX_FILENAME_LEN];
818 int game_single_step = 0;
819 int last_single_step=0;
820
821 extern int MSG_WINDOW_X_START;  // used to position mission_time and shields output
822 extern int MSG_WINDOW_Y_START;
823 extern int MSG_WINDOW_HEIGHT;
824
825 int game_zbuffer = 1;
826 //static int Game_music_paused;
827 static int Game_paused;
828
829 int Game_level_seed;
830
831 #define EXPIRE_BAD_CHECKSUM                     1
832 #define EXPIRE_BAD_TIME                                 2
833
834 extern void ssm_init();
835 extern void ssm_level_init();
836 extern void ssm_process();
837
838 // static variable to contain the time this version was built
839 // commented out for now until
840 // I figure out how to get the username into the file
841 //static char freespace_build_time[] = "Compiled on:"__DATE__" "__TIME__" by "__USER__;
842
843 // defines and variables used for dumping frame for making trailers.
844 #ifndef NDEBUG
845 int Debug_dump_frames = 0;                      // Set to 0 to not dump frames, else equal hz to dump. (15 or 30 probably)
846 int Debug_dump_trigger = 0;
847 int Debug_dump_frame_count;
848 int Debug_dump_frame_num = 0;
849 #define DUMP_BUFFER_NUM_FRAMES  1                       // store every 15 frames
850 #endif
851
852 // amount of time to wait after the player has died before we display the death died popup
853 #define PLAYER_DIED_POPUP_WAIT          2500
854 int Player_died_popup_wait = -1;
855 time_t Player_multi_died_check = -1;
856
857 // builtin mission list stuff
858 #ifdef FS2_DEMO
859         int Game_builtin_mission_count = 6;
860         fs_builtin_mission Game_builtin_mission_list[MAX_BUILTIN_MISSIONS] = {
861                 { "SPDemo-01.fs2",                              (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
862                 { "SPDemo-02.fs2",                              (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
863                 { "DemoTrain.fs2",                              (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
864                 { "Demo.fc2",                                           (FSB_FROM_VOLITION | FSB_CAMPAIGN_FILE) },
865                 { "MPDemo-01.fs2",                              (FSB_FROM_VOLITION | FSB_MULTI) },
866                 { "Demo-DOG-01.fs2",                            (FSB_FROM_VOLITION | FSB_MULTI) },
867         };
868 #elif defined(FS1_DEMO)
869         int Game_builtin_mission_count = 5;
870         fs_builtin_mission Game_builtin_mission_list[MAX_BUILTIN_MISSIONS] = {
871                 { "btmdemo.fsm",                                (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
872                 { "demo.fsc",                                   (FSB_FROM_VOLITION | FSB_CAMPAIGN_FILE) },
873                 { "demo01.fsm",                                 (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
874                 { "demo02a.fsm",                                (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
875                 { "demo02b.fsm",                                (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
876         };
877 #elif defined(PD_BUILD)
878         int Game_builtin_mission_count = 4;
879         fs_builtin_mission Game_builtin_mission_list[MAX_BUILTIN_MISSIONS] = {
880                 { "sm1-01.fs2",                                 (FSB_FROM_VOLITION) },
881                 { "sm1-05.fs2",                                 (FSB_FROM_VOLITION) },
882                 { "sm1-01",                                                     (FSB_FROM_VOLITION) },
883                 { "sm1-05",                                                     (FSB_FROM_VOLITION) },
884         };
885 #elif defined(MULTIPLAYER_BETA)
886         int Game_builtin_mission_count = 17;
887         fs_builtin_mission Game_builtin_mission_list[MAX_BUILTIN_MISSIONS] = {
888                 // multiplayer beta
889                 { "md-01.fs2",                                          (FSB_FROM_VOLITION | FSB_MULTI) },
890                 { "md-02.fs2",                                          (FSB_FROM_VOLITION | FSB_MULTI) },
891                 { "md-03.fs2",                                          (FSB_FROM_VOLITION | FSB_MULTI) },
892                 { "md-04.fs2",                                          (FSB_FROM_VOLITION | FSB_MULTI) },
893                 { "md-05.fs2",                                          (FSB_FROM_VOLITION | FSB_MULTI) },
894                 { "md-06.fs2",                                          (FSB_FROM_VOLITION | FSB_MULTI) },
895                 { "md-07.fs2",                                          (FSB_FROM_VOLITION | FSB_MULTI) },
896                 { "mt-02.fs2",                                          (FSB_FROM_VOLITION | FSB_MULTI) },
897                 { "mt-03.fs2",                                          (FSB_FROM_VOLITION | FSB_MULTI) },
898                 { "m-03.fs2",                                           (FSB_FROM_VOLITION | FSB_MULTI) },
899                 { "m-04.fs2",                                           (FSB_FROM_VOLITION | FSB_MULTI) },
900                 { "m-05.fs2",                                           (FSB_FROM_VOLITION | FSB_MULTI) },
901                 { "templar-01.fs2",                             (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN) },
902                 { "templar-02.fs2",                             (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN) },
903                 { "templar-03a.fs2",                            (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN) },
904                 { "templar-04a.fs2",                            (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN) },
905                 { "templar.fc2",                                        (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN_FILE) },
906         };
907 #elif defined(OEM_BUILD)
908         int Game_builtin_mission_count = 17;
909         fs_builtin_mission Game_builtin_mission_list[MAX_BUILTIN_MISSIONS] = {
910                 // oem version - act 1 only
911                 { "freespace2oem.fc2",                  (FSB_FROM_VOLITION | FSB_CAMPAIGN_FILE) },
912                         
913                 // act 1
914                 { "sm1-01.fs2",                                 (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
915                 { "sm1-02.fs2",                                 (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
916                 { "sm1-03.fs2",                                 (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
917                 { "sm1-04.fs2",                                 (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
918                 { "sm1-05.fs2",                                 (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
919                 { "sm1-06.fs2",                                 (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
920                 { "sm1-07.fs2",                                 (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
921                 { "sm1-08.fs2",                                 (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
922                 { "sm1-09.fs2",                                 (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
923                 { "sm1-10.fs2",                                 (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
924                 { "training-1.fs2",                             (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
925                 { "training-2.fs2",                             (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
926                 { "training-3.fs2",                             (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
927                 { "tsm-104.fs2",                                        (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
928                 { "tsm-105.fs2",                                        (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
929                 { "tsm-106.fs2",                                        (FSB_FROM_VOLITION | FSB_CAMPAIGN) }
930         };
931 #elif defined(MAKE_FS1) 
932         int Game_builtin_mission_count = 125;
933         fs_builtin_mission Game_builtin_mission_list[MAX_BUILTIN_MISSIONS] = {
934                 // single player campaign
935                 { "freespace.fsc",                              (FSB_FROM_VOLITION | FSB_CAMPAIGN_FILE) },
936
937                 // act 1
938                 { "sm1-01.fsm",                                 (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
939                 { "sm1-02a.fsm",                                (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
940                 { "sm1-03a.fsm",                                (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
941                 { "sm1-04a.fsm",                                (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
942                 { "sm1-05a.fsm",                                (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
943                 { "sm1-06a.fsm",                                (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
944                 { "sm1-07a.fsm",                                (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
945                 { "sm1-08a.fsm",                                (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
946                 { "sm1-09a.fsm",                                (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
947                 { "sm1-10a.fsm",                                (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
948
949                 // act 2
950                 { "sm2-01a.fsm",                                (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
951                 { "sm2-02a.fsm",                                (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
952                 { "sm2-03a.fsm",                                (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
953                 { "sm2-04a.fsm",                                (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
954                 { "sm2-05a.fsm",                                (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
955                 { "sm2-06a.fsm",                                (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
956                 { "sm2-07a.fsm",                                (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
957                 { "sm2-08a.fsm",                                (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
958                 { "sm2-09a.fsm",                                (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
959                 { "sm2-10a.fsm",                                (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
960
961                 // act 3
962                 { "sm3-01a.fsm",                                (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
963                 { "sm3-02a.fsm",                                (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
964                 { "sm3-03a.fsm",                                (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
965                 { "sm3-04a.fsm",                                (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
966                 { "sm3-05a.fsm",                                (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
967                 { "sm3-06a.fsm",                                (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
968                 { "sm3-07a.fsm",                                (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
969                 { "sm3-08a.fsm",                                (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
970                 { "sm3-09a.fsm",                                (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
971
972                 // gauntlet
973                 { "t-gauntlet.fsm",                             (FSB_FROM_VOLITION | FSB_MULTI) },
974                 { "v-gauntlet.fsm",                             (FSB_FROM_VOLITION | FSB_MULTI) },
975                 { "s-gauntlet.fsm",                             (FSB_FROM_VOLITION | FSB_MULTI) },
976
977                 // training
978                 { "btm-01.fsm",                                 (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
979                 { "btm-02.fsm",                                 (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
980                 { "btm-03.fsm",                                 (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
981                 { "btm-04.fsm",                                 (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
982                 { "btm-05.fsm",                                 (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
983
984                 // multiplayer
985                 { "m-hope.fsc",                                 (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN_FILE) },
986                 { "m-altair.fsc",                               (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN_FILE) },
987
988                 { "m-v-gauntlet.fsm",                   (FSB_FROM_VOLITION | FSB_MULTI) },
989                 { "m-va.fsm",                                   (FSB_FROM_VOLITION | FSB_MULTI) },
990                 { "m-unstoppable.fsm",                  (FSB_FROM_VOLITION | FSB_MULTI) },
991                 { "m-t-gauntlet.fsm",                   (FSB_FROM_VOLITION | FSB_MULTI) },
992                 { "m-s-gauntlet.fsm",                   (FSB_FROM_VOLITION | FSB_MULTI) },
993                 { "m-rescue.fsm",                               (FSB_FROM_VOLITION | FSB_MULTI) },
994                 { "m-pain.fsm",                                 (FSB_FROM_VOLITION | FSB_MULTI) },
995                 { "m-orecovery.fsm",                    (FSB_FROM_VOLITION | FSB_MULTI) },
996                 { "mm3-01a.fsm",                                (FSB_FROM_VOLITION | FSB_MULTI) },
997                 { "mm3-02a.fsm",                                (FSB_FROM_VOLITION | FSB_MULTI) },
998                 { "mm3-03a.fsm",                                (FSB_FROM_VOLITION | FSB_MULTI) },
999                 { "mm3-04a.fsm",                                (FSB_FROM_VOLITION | FSB_MULTI) },
1000                 { "mm3-05a.fsm",                                (FSB_FROM_VOLITION | FSB_MULTI) },
1001                 { "mm3-06a.fsm",                                (FSB_FROM_VOLITION | FSB_MULTI) },
1002                 { "m-guardduty.fsm",                    (FSB_FROM_VOLITION | FSB_MULTI) },
1003                 { "m-gate.fsm",                                 (FSB_FROM_VOLITION | FSB_MULTI) },
1004                 { "m-duel.fsm",                                 (FSB_FROM_VOLITION | FSB_MULTI) },
1005                 { "m-convoyassault.fsm",                (FSB_FROM_VOLITION | FSB_MULTI) },
1006                 { "m-clash.fsm",                                (FSB_FROM_VOLITION | FSB_MULTI) },
1007
1008         // SilentThreat missions
1009                 // Main SilentThreat campaign
1010                 { "SilentThreat.fsc",                   (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN_FILE) },
1011
1012                 { "md-01.fsm",                                  (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN) },
1013                 { "md-02.fsm",                                  (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN) },
1014                 { "md-03.fsm",                                  (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN) },
1015                 { "md-04.fsm",                                  (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN) },
1016                 { "md-05.fsm",                                  (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN) },
1017                 { "md-06.fsm",                                  (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN) },
1018                 { "md-07.fsm",                                  (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN) },
1019                 { "md-08.fsm",                                  (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN) },
1020                 { "md-09.fsm",                                  (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN) },
1021                 { "md-10.fsm",                                  (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN) },
1022                 { "md-11.fsm",                                  (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN) },
1023                 { "md-12.fsm",                                  (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN) },
1024
1025                 // SilentThreat Part 1 - multi-coop
1026                 { "ST-Part1.fsc",                               (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN_FILE) },
1027
1028                 { "stmm-01.fsm",                                (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN) },
1029                 { "stmm-02.fsm",                                (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN) },
1030                 { "stmm-03.fsm",                                (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN) },
1031
1032                 // SilentThreat Part 2 - multi-coop
1033                 { "ST-Part2.fsc",                               (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN_FILE) },
1034
1035                 { "stmm-04.fsm",                                (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN) },
1036                 { "stmm-05.fsm",                                (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN) },
1037                 { "stmm-06.fsm",                                (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN) },
1038
1039                 // SilentThreat Part 3 - multi-coop
1040                 { "ST-Part3.fsc",                               (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN_FILE) },
1041
1042                 { "stmm-07.fsm",                                (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN) },
1043                 { "stmm-08.fsm",                                (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN) },
1044                 { "stmm-09.fsm",                                (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN) },
1045
1046                 // SilentThreat Part 4 - multi-coop
1047                 { "ST-Part4.fsc",                               (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN_FILE) },
1048
1049                 { "stmm-10.fsm",                                (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN) },
1050                 { "stmm-11.fsm",                                (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN) },
1051                 { "stmm-12.fsm",                                (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN) },
1052
1053                 // multiplayer missions
1054                 { "mdmm-01.fsm",                                (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI) },
1055                 { "mdmm-02.fsm",                                (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI) },
1056                 { "mdmm-03.fsm",                                (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI) },
1057                 { "mdmm-04.fsm",                                (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI) },
1058                 // user supplied missions
1059                 { "mdu-02.fsm",                                 (FSB_FROM_MDISK | FSB_MULTI) },
1060                 { "mdu-03.fsm",                                 (FSB_FROM_MDISK | FSB_MULTI) },
1061                 { "mdu-04.fsm",                                 (FSB_FROM_MDISK | FSB_MULTI) },
1062                 { "mdu-05.fsm",                                 (FSB_FROM_MDISK | FSB_MULTI) },
1063                 { "mdu-06.fsm",                                 (FSB_FROM_MDISK | FSB_MULTI) },
1064                 { "mdu-07.fsm",                                 (FSB_FROM_MDISK | FSB_MULTI) },
1065                 { "mdu-08.fsm",                                 (FSB_FROM_MDISK | FSB_MULTI) },
1066                 { "mdu-09.fsm",                                 (FSB_FROM_MDISK | FSB_MULTI) },
1067                 { "mdu-10.fsm",                                 (FSB_FROM_MDISK | FSB_MULTI) },
1068                 { "mdu-11.fsm",                                 (FSB_FROM_MDISK | FSB_MULTI) },
1069                 { "mdu-12.fsm",                                 (FSB_FROM_MDISK | FSB_MULTI) },
1070                 { "mdu-13.fsm",                                 (FSB_FROM_MDISK | FSB_MULTI) },
1071                 { "mdu-14.fsm",                                 (FSB_FROM_MDISK | FSB_MULTI) },
1072                 { "mdu-15.fsm",                                 (FSB_FROM_MDISK | FSB_MULTI) },
1073                 { "mdu-16.fsm",                                 (FSB_FROM_MDISK | FSB_MULTI) },
1074                 { "mdu-17.fsm",                                 (FSB_FROM_MDISK | FSB_MULTI) },
1075                 { "mdu-18.fsm",                                 (FSB_FROM_MDISK | FSB_MULTI) },
1076                 { "mdu-19.fsm",                                 (FSB_FROM_MDISK | FSB_MULTI) },
1077                 { "mdu-20.fsm",                                 (FSB_FROM_MDISK | FSB_MULTI) },
1078                 { "mdu-21.fsm",                                 (FSB_FROM_MDISK | FSB_MULTI) },
1079                 { "mdu-22.fsm",                                 (FSB_FROM_MDISK | FSB_MULTI) },
1080                 { "mdu-23.fsm",                                 (FSB_FROM_MDISK | FSB_MULTI) },
1081                 { "mdu-24.fsm",                                 (FSB_FROM_MDISK | FSB_MULTI) },
1082                 { "mdu-25.fsm",                                 (FSB_FROM_MDISK | FSB_MULTI) },
1083                 { "mdu-26.fsm",                                 (FSB_FROM_MDISK | FSB_MULTI) },
1084                 { "mdu-27.fsm",                                 (FSB_FROM_MDISK | FSB_MULTI) },
1085                 { "mdu-28.fsm",                                 (FSB_FROM_MDISK | FSB_MULTI) },
1086                 { "mdu-29.fsm",                                 (FSB_FROM_MDISK | FSB_MULTI) },
1087                 { "mdu-30.fsm",                                 (FSB_FROM_MDISK | FSB_MULTI) },
1088                 { "mdu-31.fsm",                                 (FSB_FROM_MDISK | FSB_MULTI) },
1089                 { "mdumm-01.fsm",                               (FSB_FROM_MDISK | FSB_MULTI) },
1090                 { "mdumm-02.fsm",                               (FSB_FROM_MDISK | FSB_MULTI) },
1091         };
1092 #else
1093         int Game_builtin_mission_count = 92;
1094         fs_builtin_mission Game_builtin_mission_list[MAX_BUILTIN_MISSIONS] = {
1095                 // single player campaign
1096                 { "freespace2.fc2",                             (FSB_FROM_VOLITION | FSB_CAMPAIGN_FILE) },
1097                         
1098                 // act 1
1099                 { "sm1-01.fs2",                                 (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1100                 { "sm1-02.fs2",                                 (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1101                 { "sm1-03.fs2",                                 (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1102                 { "sm1-04.fs2",                                 (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1103                 { "sm1-05.fs2",                                 (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1104                 { "sm1-06.fs2",                                 (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1105                 { "sm1-07.fs2",                                 (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1106                 { "sm1-08.fs2",                                 (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1107                 { "sm1-09.fs2",                                 (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1108                 { "sm1-10.fs2",                                 (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1109                 { "loop1-1.fs2",                                        (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1110                 { "loop1-2.fs2",                                        (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1111                 { "loop1-3.fs2",                                        (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1112                 { "training-1.fs2",                             (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1113                 { "training-2.fs2",                             (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1114                 { "training-3.fs2",                             (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1115                 { "tsm-104.fs2",                                        (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1116                 { "tsm-105.fs2",                                        (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1117                 { "tsm-106.fs2",                                        (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1118
1119                 // act 2
1120                 { "sm2-01.fs2",                                 (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1121                 { "sm2-02.fs2",                                 (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1122                 { "sm2-03.fs2",                                 (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1123                 { "sm2-04.fs2",                                 (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1124                 { "sm2-05.fs2",                                 (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1125                 { "sm2-06.fs2",                                 (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1126                 { "sm2-07.fs2",                                 (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1127                 { "sm2-08.fs2",                                 (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1128                 { "sm2-09.fs2",                                 (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1129                 { "sm2-10.fs2",                                 (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1130
1131                 // act 3
1132                 { "sm3-01.fs2",                                 (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1133                 { "sm3-02.fs2",                                 (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1134                 { "sm3-03.fs2",                                 (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1135                 { "sm3-04.fs2",                                 (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1136                 { "sm3-05.fs2",                                 (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1137                 { "sm3-06.fs2",                                 (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1138                 { "sm3-07.fs2",                                 (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1139                 { "sm3-08.fs2",                                 (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1140                 { "sm3-09.fs2",                                 (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1141                 { "sm3-10.fs2",                                 (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1142                 { "loop2-1.fs2",                                        (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1143                 { "loop2-2.fs2",                                        (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1144
1145                 // multiplayer missions
1146
1147                 // gauntlet
1148                 { "g-shi.fs2",                                          (FSB_FROM_VOLITION | FSB_MULTI) },
1149                 { "g-ter.fs2",                                          (FSB_FROM_VOLITION | FSB_MULTI) },
1150                 { "g-vas.fs2",                                          (FSB_FROM_VOLITION | FSB_MULTI) },
1151
1152                 // coop
1153                 { "m-01.fs2",                                           (FSB_FROM_VOLITION | FSB_MULTI) },
1154                 { "m-02.fs2",                                           (FSB_FROM_VOLITION | FSB_MULTI) },
1155                 { "m-03.fs2",                                           (FSB_FROM_VOLITION | FSB_MULTI) },
1156                 { "m-04.fs2",                                           (FSB_FROM_VOLITION | FSB_MULTI) },
1157
1158                 // dogfight
1159                 { "mdh-01.fs2",                                 (FSB_FROM_VOLITION | FSB_MULTI) },
1160                 { "mdh-02.fs2",                                 (FSB_FROM_VOLITION | FSB_MULTI) },
1161                 { "mdh-03.fs2",                                 (FSB_FROM_VOLITION | FSB_MULTI) },
1162                 { "mdh-04.fs2",                                 (FSB_FROM_VOLITION | FSB_MULTI) },
1163                 { "mdh-05.fs2",                                 (FSB_FROM_VOLITION | FSB_MULTI) },
1164                 { "mdh-06.fs2",                                 (FSB_FROM_VOLITION | FSB_MULTI) },
1165                 { "mdh-07.fs2",                                 (FSB_FROM_VOLITION | FSB_MULTI) },
1166                 { "mdh-08.fs2",                                 (FSB_FROM_VOLITION | FSB_MULTI) },
1167                 { "mdh-09.fs2",                                 (FSB_FROM_VOLITION | FSB_MULTI) },
1168                 { "mdl-01.fs2",                                 (FSB_FROM_VOLITION | FSB_MULTI) },
1169                 { "mdl-02.fs2",                                 (FSB_FROM_VOLITION | FSB_MULTI) },
1170                 { "mdl-03.fs2",                                 (FSB_FROM_VOLITION | FSB_MULTI) },
1171                 { "mdl-04.fs2",                                 (FSB_FROM_VOLITION | FSB_MULTI) },
1172                 { "mdl-05.fs2",                                 (FSB_FROM_VOLITION | FSB_MULTI) },
1173                 { "mdl-06.fs2",                                 (FSB_FROM_VOLITION | FSB_MULTI) },
1174                 { "mdl-07.fs2",                                 (FSB_FROM_VOLITION | FSB_MULTI) },
1175                 { "mdl-08.fs2",                                 (FSB_FROM_VOLITION | FSB_MULTI) },
1176                 { "mdl-09.fs2",                                 (FSB_FROM_VOLITION | FSB_MULTI) },
1177                 { "mdm-01.fs2",                                 (FSB_FROM_VOLITION | FSB_MULTI) },
1178                 { "mdm-02.fs2",                                 (FSB_FROM_VOLITION | FSB_MULTI) },
1179                 { "mdm-03.fs2",                                 (FSB_FROM_VOLITION | FSB_MULTI) },
1180                 { "mdm-04.fs2",                                 (FSB_FROM_VOLITION | FSB_MULTI) },
1181                 { "mdm-05.fs2",                                 (FSB_FROM_VOLITION | FSB_MULTI) },
1182                 { "mdm-06.fs2",                                 (FSB_FROM_VOLITION | FSB_MULTI) },
1183                 { "mdm-07.fs2",                                 (FSB_FROM_VOLITION | FSB_MULTI) },
1184                 { "mdm-08.fs2",                                 (FSB_FROM_VOLITION | FSB_MULTI) },
1185                 { "mdm-09.fs2",                                 (FSB_FROM_VOLITION | FSB_MULTI) },
1186                 { "osdog.fs2",                                          (FSB_FROM_VOLITION | FSB_MULTI) },
1187
1188                 // TvT          
1189                 { "mt-01.fs2",                                          (FSB_FROM_VOLITION | FSB_MULTI) },
1190                 { "mt-02.fs2",                                          (FSB_FROM_VOLITION | FSB_MULTI) },
1191                 { "mt-03.fs2",                                          (FSB_FROM_VOLITION | FSB_MULTI) },
1192                 { "mt-04.fs2",                                          (FSB_FROM_VOLITION | FSB_MULTI) },
1193                 { "mt-05.fs2",                                          (FSB_FROM_VOLITION | FSB_MULTI) },
1194                 { "mt-06.fs2",                                          (FSB_FROM_VOLITION | FSB_MULTI) },
1195                 { "mt-07.fs2",                                          (FSB_FROM_VOLITION | FSB_MULTI) },
1196                 { "mt-08.fs2",                                          (FSB_FROM_VOLITION | FSB_MULTI) },
1197                 { "mt-09.fs2",                                          (FSB_FROM_VOLITION | FSB_MULTI) },
1198                 { "mt-10.fs2",                                          (FSB_FROM_VOLITION | FSB_MULTI) },
1199
1200                 // campaign
1201                 { "templar.fc2",                                (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN_FILE) },
1202                 { "templar-01.fs2",                             (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN) },
1203                 { "templar-02.fs2",                             (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN) },
1204                 { "templar-03.fs2",                             (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN) },
1205                 { "templar-04.fs2",                             (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN) },
1206         };
1207 #endif
1208
1209
1210 // Internal function prototypes
1211 void game_maybe_draw_mouse(float frametime);
1212 void init_animating_pointer();
1213 void load_animating_pointer(const char *filename, int dx, int dy);
1214 void unload_animating_pointer();
1215 void game_do_training_checks();
1216 void game_shutdown(void);
1217 void game_show_event_debug(float frametime);
1218 void game_event_debug_init();
1219 void game_frame();
1220 void demo_upsell_show_screens();
1221 void game_start_subspace_ambient_sound();
1222 void game_stop_subspace_ambient_sound();
1223 void verify_ships_tbl();
1224 void verify_weapons_tbl();
1225 void display_title_screen();
1226
1227 // loading background filenames
1228 static const char *Game_loading_bground_fname[GR_NUM_RESOLUTIONS] = {
1229         "LoadingBG",            // GR_640
1230         "2_LoadingBG"           // GR_1024
1231 };
1232
1233
1234 static const char *Game_loading_ani_fname[GR_NUM_RESOLUTIONS] = {
1235         "Loading.ani",          // GR_640
1236         "2_Loading.ani"         // GR_1024
1237 };
1238
1239 #if defined(FS2_DEMO)
1240 static const char *Game_demo_title_screen_fname[GR_NUM_RESOLUTIONS] = {
1241         "PreLoad",
1242         "2_PreLoad"
1243 };
1244 #elif defined(OEM_BUILD)
1245 static const char *Game_demo_title_screen_fname[GR_NUM_RESOLUTIONS] = {
1246         "OEMPreLoad",
1247         "2_OEMPreLoad"
1248 };
1249 #endif
1250
1251 // auto-lang stuff
1252 int detect_lang();
1253
1254 // How much RAM is on this machine. Set in WinMain
1255 static int Freespace_total_ram = 0;
1256
1257 // game flash stuff
1258 float Game_flash_red = 0.0f;
1259 float Game_flash_green = 0.0f;
1260 float Game_flash_blue = 0.0f;
1261 float Sun_spot = 0.0f;
1262 big_expl_flash Big_expl_flash = {0.0f, 0.0f, 0};
1263
1264 // game shudder stuff (in ms)
1265 int Game_shudder_time = -1;
1266 int Game_shudder_total = 0;
1267 float Game_shudder_intensity = 0.0f;                    // should be between 0.0 and 100.0
1268
1269 // EAX stuff
1270 sound_env Game_sound_env;
1271 //sound_env Game_default_sound_env = {SND_ENV_AUDITORIUM, 0.25f, 0.35f, 3.0f};
1272 sound_env Game_default_sound_env = {SND_ENV_GENERIC, 0.2F,0.2F,1.0F};
1273
1274 int Game_sound_env_update_timestamp;
1275
1276 // WARPIN CRAP BEGIN --------------------------------------------------------------------------------------------
1277
1278
1279 // WARPIN CRAP END --------------------------------------------------------------------------------------------
1280
1281 fs_builtin_mission *game_find_builtin_mission(const char *filename)
1282 {
1283         int idx;
1284
1285         // look through all existing builtin missions
1286         for(idx=0; idx<Game_builtin_mission_count; idx++){
1287                 if(!SDL_strcasecmp(Game_builtin_mission_list[idx].filename, filename)){
1288                         return &Game_builtin_mission_list[idx];
1289                 }
1290         }
1291
1292         // didn't find it
1293         return NULL;
1294 }
1295
1296 int game_get_default_skill_level()
1297 {
1298         return DEFAULT_SKILL_LEVEL;
1299 }
1300
1301 // Resets the flash
1302 void game_flash_reset()
1303 {
1304         Game_flash_red = 0.0f;
1305         Game_flash_green = 0.0f;
1306         Game_flash_blue = 0.0f;
1307         Sun_spot = 0.0f;
1308         Big_expl_flash.max_flash_intensity = 0.0f;
1309         Big_expl_flash.cur_flash_intensity = 0.0f;
1310         Big_expl_flash.flash_start = 0;
1311 }
1312
1313 float Gf_critical = -1.0f;                                      // framerate we should be above on the average for this mission
1314 float Gf_critical_time = 0.0f;                  // how much time we've been at the critical framerate
1315
1316 void game_framerate_check_init()
1317 {
1318         // zero critical time
1319         Gf_critical_time = 0.0f;
1320                 
1321         // nebula missions
1322         if(The_mission.flags & MISSION_FLAG_FULLNEB){
1323                 Gf_critical = 15.0f;
1324         } else {
1325                 Gf_critical = 25.0f;
1326         }
1327 }
1328
1329 extern float Framerate;
1330 void game_framerate_check()
1331 {
1332         int y_start = 100;
1333         
1334         // if the current framerate is above the critical level, add frametime
1335         if(Framerate >= Gf_critical){
1336                 Gf_critical_time += flFrametime;
1337         }       
1338
1339         if(!Show_framerate){
1340                 return;
1341         }
1342
1343         // display if we're above the critical framerate
1344         if(Framerate < Gf_critical){
1345                 gr_set_color_fast(&Color_bright_red);
1346                 gr_string(200, y_start, "Framerate warning");
1347
1348                 y_start += 10;
1349         }
1350
1351         // display our current pct of good frametime
1352         if(f2fl(Missiontime) >= 0.0f){
1353                 float pct = (Gf_critical_time / f2fl(Missiontime)) * 100.0f;
1354
1355                 if(pct >= 85.0f){
1356                         gr_set_color_fast(&Color_bright_green);
1357                 } else {
1358                         gr_set_color_fast(&Color_bright_red);
1359                 }
1360
1361                 gr_printf(200, y_start, "%d%%", (int)pct);
1362         }
1363 }
1364
1365
1366 // Adds a flash effect.  These can be positive or negative.
1367 // The range will get capped at around -1 to 1, so stick 
1368 // with a range like that.
1369 void game_flash( float r, float g, float b )
1370 {
1371         Game_flash_red += r;
1372         Game_flash_green += g;
1373         Game_flash_blue += b;
1374
1375         if ( Game_flash_red < -1.0f )   {
1376                 Game_flash_red = -1.0f;
1377         } else if ( Game_flash_red > 1.0f )     {
1378                 Game_flash_red = 1.0f;
1379         }
1380
1381         if ( Game_flash_green < -1.0f ) {
1382                 Game_flash_green = -1.0f;
1383         } else if ( Game_flash_green > 1.0f )   {
1384                 Game_flash_green = 1.0f;
1385         }
1386
1387         if ( Game_flash_blue < -1.0f )  {
1388                 Game_flash_blue = -1.0f;
1389         } else if ( Game_flash_blue > 1.0f )    {
1390                 Game_flash_blue = 1.0f;
1391         }
1392
1393 }
1394
1395 // Adds a flash for Big Ship explosions
1396 // cap range from 0 to 1
1397 void big_explosion_flash(float flash)
1398 {
1399         Big_expl_flash.flash_start = timestamp(1);
1400
1401         if (flash > 1.0f) {
1402                 flash = 1.0f;
1403         } else if (flash < 0.0f) {
1404                 flash = 0.0f;
1405         }
1406
1407         Big_expl_flash.max_flash_intensity = flash;
1408         Big_expl_flash.cur_flash_intensity = 0.0f;
1409 }
1410
1411 //      Amount to diminish palette towards normal, per second.
1412 #define DIMINISH_RATE   0.75f
1413 #define SUN_DIMINISH_RATE       6.00f
1414
1415 int Sun_drew = 0;
1416
1417 float sn_glare_scale = 1.7f;
1418 DCF(sn_glare, "")
1419 {
1420         dc_get_arg(ARG_FLOAT);
1421         sn_glare_scale = Dc_arg_float;
1422 }
1423
1424 float Supernova_last_glare = 0.0f;
1425 void game_sunspot_process(float frametime)
1426 {
1427         int n_lights, idx;
1428         int sn_stage;
1429         float Sun_spot_goal = 0.0f;
1430
1431         // supernova
1432         sn_stage = supernova_active();
1433         if(sn_stage){           
1434                 // sunspot differently based on supernova stage
1435                 switch(sn_stage){
1436                 // approaching. player still in control
1437                 case 1:                 
1438                         float pct;
1439                         pct = (1.0f - (supernova_time_left() / SUPERNOVA_CUT_TIME));
1440
1441                         vector light_dir;                               
1442                         light_get_global_dir(&light_dir, 0);
1443                         float dot;
1444                         dot = vm_vec_dot( &light_dir, &Eye_matrix.v.fvec );
1445                         
1446                         if(dot >= 0.0f){
1447                                 // scale it some more
1448                                 dot = dot * (0.5f + (pct * 0.5f));
1449                                 dot += 0.05f;                                   
1450
1451                                 Sun_spot_goal += (dot * sn_glare_scale);
1452                         }
1453
1454                         // draw the sun glow
1455                         if ( !shipfx_eye_in_shadow( &Eye_position, Viewer_obj, 0 ) )    {
1456                                 // draw the glow for this sun
1457                                 stars_draw_sun_glow(0); 
1458                         }
1459
1460                         Supernova_last_glare = Sun_spot_goal;
1461                         break;
1462
1463                 // camera cut. player not in control. note : at this point camera starts out facing the sun. so we can go nice and bright
1464                 case 2:                                         
1465                 case 3:
1466                         Sun_spot_goal = 0.9f;
1467                         Sun_spot_goal += (1.0f - (supernova_time_left() / SUPERNOVA_CUT_TIME)) * 0.1f;
1468
1469                         if(Sun_spot_goal > 1.0f){
1470                                 Sun_spot_goal = 1.0f;
1471                         }
1472
1473                         Sun_spot_goal *= sn_glare_scale;
1474                         Supernova_last_glare = Sun_spot_goal;
1475                         break;          
1476
1477                 // fade to white. display dead popup
1478                 case 4:
1479                 case 5:
1480                         Supernova_last_glare += (2.0f * flFrametime);
1481                         if(Supernova_last_glare > 2.0f){
1482                                 Supernova_last_glare = 2.0f;
1483                         }
1484
1485                         Sun_spot_goal = Supernova_last_glare;
1486                         break;
1487                 }
1488         
1489                 Sun_drew = 0;                           
1490         } else {
1491                 if ( Sun_drew ) {
1492                         // check sunspots for all suns
1493                         n_lights = light_get_global_count();
1494
1495                         // check
1496                         for(idx=0; idx<n_lights; idx++){
1497                                 //(vector *eye_pos, matrix *eye_orient)
1498                                 if ( !shipfx_eye_in_shadow( &Eye_position, Viewer_obj, idx ) )  {
1499
1500                                         vector light_dir;                               
1501                                         light_get_global_dir(&light_dir, idx);
1502
1503                                         float dot = vm_vec_dot( &light_dir, &Eye_matrix.v.fvec )*0.5f+0.5f;
1504
1505                                         Sun_spot_goal += (float)pow(dot,85.0f);
1506
1507                                         // draw the glow for this sun
1508                                         stars_draw_sun_glow(idx);                               
1509                                 } else {
1510                                         Sun_spot_goal = 0.0f;
1511                                 }
1512                         }
1513
1514                         Sun_drew = 0;
1515                 } else {
1516                         Sun_spot_goal = 0.0f;
1517                 }
1518         }
1519
1520         float dec_amount = frametime*SUN_DIMINISH_RATE;
1521
1522         if ( Sun_spot < Sun_spot_goal ) {
1523                 Sun_spot += dec_amount;
1524                 if ( Sun_spot > Sun_spot_goal ) {
1525                         Sun_spot = Sun_spot_goal;
1526                 }
1527         } else if ( Sun_spot > Sun_spot_goal )  {
1528                 Sun_spot -= dec_amount;
1529                 if ( Sun_spot < Sun_spot_goal ) {
1530                         Sun_spot = Sun_spot_goal;
1531                 }
1532         }
1533 }
1534
1535
1536 // Call once a frame to diminish the
1537 // flash effect to 0.
1538 void game_flash_diminish(float frametime)
1539 {
1540         float dec_amount = frametime*DIMINISH_RATE;
1541
1542         if ( Game_flash_red > 0.0f ) {
1543                 Game_flash_red -= dec_amount;           
1544                 if ( Game_flash_red < 0.0f )
1545                         Game_flash_red = 0.0f;
1546         } else {
1547                 Game_flash_red += dec_amount;           
1548                 if ( Game_flash_red > 0.0f )
1549                         Game_flash_red = 0.0f;
1550         } 
1551
1552         if ( Game_flash_green > 0.0f ) {
1553                 Game_flash_green -= dec_amount;         
1554                 if ( Game_flash_green < 0.0f )
1555                         Game_flash_green = 0.0f;
1556         } else {
1557                 Game_flash_green += dec_amount;         
1558                 if ( Game_flash_green > 0.0f )
1559                         Game_flash_green = 0.0f;
1560         } 
1561
1562         if ( Game_flash_blue > 0.0f ) {
1563                 Game_flash_blue -= dec_amount;          
1564                 if ( Game_flash_blue < 0.0f )
1565                         Game_flash_blue = 0.0f;
1566         } else {
1567                 Game_flash_blue += dec_amount;          
1568                 if ( Game_flash_blue > 0.0f )
1569                         Game_flash_blue = 0.0f;
1570         } 
1571
1572         // update big_explosion_cur_flash
1573 #define TIME_UP         1500
1574 #define TIME_DOWN       2500
1575         int duration = TIME_UP + TIME_DOWN;
1576         int time = timestamp_until(Big_expl_flash.flash_start);
1577         if (time > -duration) {
1578                 time = -time;
1579                 if (time < TIME_UP) {
1580                         Big_expl_flash.cur_flash_intensity = Big_expl_flash.max_flash_intensity * time / (float) TIME_UP;
1581                 } else {
1582                         time -= TIME_UP;
1583                         Big_expl_flash.cur_flash_intensity = Big_expl_flash.max_flash_intensity * ((float) TIME_DOWN - time) / (float) TIME_DOWN;
1584                 }
1585         }
1586         
1587         if ( Use_palette_flash )        {
1588                 int r,g,b;
1589 //              static int or=0, og=0, ob=0;
1590
1591                 // Change the 200 to change the color range of colors.
1592                 r = fl2i( Game_flash_red*128.0f );  
1593                 g = fl2i( Game_flash_green*128.0f );   
1594                 b = fl2i( Game_flash_blue*128.0f );  
1595
1596                 if ( Sun_spot > 0.0f )  {
1597                         r += fl2i(Sun_spot*128.0f);
1598                         g += fl2i(Sun_spot*128.0f);
1599                         b += fl2i(Sun_spot*128.0f);
1600                 }
1601
1602                 if ( Big_expl_flash.cur_flash_intensity  > 0.0f ) {
1603                         r += fl2i(Big_expl_flash.cur_flash_intensity*128.0f);
1604                         g += fl2i(Big_expl_flash.cur_flash_intensity*128.0f);
1605                         b += fl2i(Big_expl_flash.cur_flash_intensity*128.0f);
1606                 }
1607
1608                 if ( r < 0 ) r = 0; else if ( r > 255 ) r = 255;
1609                 if ( g < 0 ) g = 0; else if ( g > 255 ) g = 255;
1610                 if ( b < 0 ) b = 0; else if ( b > 255 ) b = 255;
1611
1612                 if ( (r!=0) || (g!=0) || (b!=0) ) {
1613                         gr_flash( r, g, b );
1614
1615                         //mprintf(( "Flash! %d,%d,%d\n", r, g, b ));
1616
1617 //                      or = r;
1618 //                      og = g;
1619 //                      ob = b;
1620                 }
1621         }
1622         
1623 }
1624
1625
1626 void game_level_close()
1627 {
1628         // De-Initialize the game subsystems
1629         event_music_level_close();
1630         game_stop_looped_sounds();
1631         snd_stop_all();
1632         obj_snd_level_close();                                  // uninit object-linked persistant sounds
1633         gamesnd_unload_gameplay_sounds();       // unload gameplay sounds from memory
1634         anim_level_close();                                             // stop and clean up any anim instances
1635         message_mission_shutdown();                             // called after anim_level_close() to make sure anim instances are free
1636         shockwave_level_close();
1637         fireball_level_close(); 
1638         shield_hit_close();
1639         mission_event_shutdown();
1640         asteroid_level_close();
1641         flak_level_close();                                             // unload flak stuff
1642         neb2_level_close();                                             // shutdown gaseous nebula stuff
1643         ct_level_close();
1644         beam_level_close();
1645         mflash_level_close();
1646         mission_brief_common_reset();                   // close out parsed briefing/mission stuff
1647
1648         audiostream_unpause_all();
1649         Game_paused = 0;
1650 }
1651
1652
1653 // intializes game stuff and loads the mission.  Returns 0 on failure, 1 on success
1654 // input: seed =>       DEFAULT PARAMETER (value -1).  Only set by demo playback code.
1655 void game_level_init(int seed)
1656 {
1657         // seed the random number generator
1658         if ( seed == -1 ) {
1659                 // if no seed was passed, seed the generator either from the time value, or from the
1660                 // netgame security flags -- ensures that all players in multiplayer game will have the
1661                 // same randon number sequence (with static rand functions)
1662                 if ( Game_mode & GM_NORMAL ) {
1663                         Game_level_seed = (int)time(NULL);
1664                 } else {
1665                         Game_level_seed = Netgame.security;
1666                 }
1667         } else {
1668                 // mwa 9/17/98 -- maybe this assert isn't needed????
1669                 SDL_assert( !(Game_mode & GM_MULTIPLAYER) );
1670                 Game_level_seed = seed;
1671         }
1672         srand( Game_level_seed );
1673
1674         // semirand function needs to get re-initted every time in multiplayer
1675         if ( Game_mode & GM_MULTIPLAYER ){
1676                 init_semirand();
1677         }
1678
1679         Framecount = 0;
1680
1681         Key_normal_game = (Game_mode & GM_NORMAL);
1682         Cheats_enabled = 0;
1683
1684         Game_shudder_time = -1;
1685
1686         // Initialize the game subsystems
1687 //      timestamp_reset();                      // Must be inited before everything else
1688         if(!Is_standalone){
1689                 game_reset_time();                      // resets time, and resets saved time too
1690         }
1691         obj_init();                                             // Must be inited before the other systems
1692         model_free_all();                               // Free all existing models
1693         mission_brief_common_init();            // Free all existing briefing/debriefing text
1694         weapon_level_init();
1695         ai_level_init();                                //      Call this before ship_init() because it reads ai.tbl.
1696         ship_level_init();
1697         player_level_init();    
1698         shipfx_flash_init();                    // Init the ship gun flash system.
1699         game_flash_reset();                     // Reset the flash effect
1700         particle_init();                                // Reset the particle system
1701         fireball_init();
1702         debris_init();
1703         cmeasure_init();
1704         shield_hit_init();                              //      Initialize system for showing shield hits
1705         radar_mission_init();
1706         mission_init_goals();
1707         mission_log_init();
1708         messages_init();
1709         obj_snd_level_init();                                   // init object-linked persistant sounds
1710         anim_level_init();
1711         shockwave_level_init();
1712         afterburner_level_init();
1713         scoring_level_init( &Player->stats );
1714         key_level_init();
1715         asteroid_level_init();
1716         control_config_clear_used_status();
1717         collide_ship_ship_sounds_init();
1718         Missiontime = 0;
1719         Pre_player_entry = 1;                   //      Means the player has not yet entered.
1720         Entry_delay_time = 0;                   //      Could get overwritten in mission read.
1721         fireball_preload();                             //      page in warphole bitmaps
1722         observer_init();
1723         flak_level_init();                              // initialize flak - bitmaps, etc
1724         ct_level_init();                                        // initialize ships contrails, etc
1725         awacs_level_init();                             // initialize AWACS
1726         beam_level_init();                              // initialize beam weapons
1727         mflash_level_init();
1728         ssm_level_init();       
1729         supernova_level_init();
1730
1731         // multiplayer dogfight hack
1732         dogfight_blown = 0;
1733
1734         shipfx_engine_wash_level_init();
1735
1736         nebl_level_init();
1737
1738         Last_view_target = NULL;
1739         Game_paused = 0;
1740
1741         Game_no_clear = 0;
1742
1743         // campaign wasn't ended
1744         Campaign_ended_in_mission = 0;
1745 }
1746
1747 // called when a mission is over -- does server specific stuff.
1748 void freespace_stop_mission()
1749 {       
1750         game_level_close();
1751         Game_mode &= ~GM_IN_MISSION;
1752 }
1753
1754 // called at frame interval to process networking stuff
1755 void game_do_networking()
1756 {
1757         SDL_assert( Net_player != NULL );
1758         if (!(Game_mode & GM_MULTIPLAYER)){
1759                 return;
1760         }
1761
1762         // see if this player should be reading/writing data.  Bit is set when at join
1763         // screen onward until quits back to main menu.
1764         if ( !(Net_player->flags & NETINFO_FLAG_DO_NETWORKING) ){
1765                 return;
1766         }
1767
1768         if(gameseq_get_state()!=GS_STATE_MULTI_PAUSED){
1769                 multi_do_frame();
1770         } else {
1771                 multi_pause_do_frame();
1772         }       
1773 }
1774
1775
1776 // Loads the best palette for this level, based
1777 // on nebula color and hud color.  You could just call palette_load_table with
1778 // the appropriate filename, but who wants to do that.
1779 void game_load_palette()
1780 {
1781         char palette_filename[1024];
1782
1783         // We only use 3 hud colors right now
1784 #ifdef MAKE_FS1
1785         SDL_assert( HUD_config.main_color >= 0 );
1786         SDL_assert( HUD_config.main_color <= 2 );
1787 #endif
1788
1789         SDL_assert( Mission_palette >= 0 );
1790         SDL_assert( Mission_palette <= 98 );
1791
1792 #ifdef MAKE_FS1
1793         if ( The_mission.flags & MISSION_FLAG_SUBSPACE )        {
1794                 SDL_strlcpy( palette_filename, NOX("gamepalette-subspace"), SDL_arraysize(palette_filename) );
1795         } else {
1796                 SDL_snprintf( palette_filename, SDL_arraysize(palette_filename), NOX("gamepalette%d-%02d"), HUD_config.main_color+1, Mission_palette+1 );
1797         }
1798
1799         mprintf(( "Loading palette %s\n", palette_filename ));
1800
1801         palette_load_table(palette_filename);
1802 #else
1803         SDL_strlcpy( palette_filename, NOX("gamepalette-subspace"), SDL_arraysize(palette_filename) );
1804
1805         mprintf(( "Loading palette %s\n", palette_filename ));
1806 #endif
1807 }
1808
1809 void game_post_level_init()
1810 {
1811         // Stuff which gets called after mission is loaded.  Because player isn't created until
1812         // after mission loads, some things must get initted after the level loads
1813
1814         model_level_post_init();
1815
1816         HUD_init();
1817         hud_setup_escort_list();
1818         mission_hotkey_set_defaults();  // set up the default hotkeys (from mission file)
1819
1820         stars_level_init();     
1821         neb2_level_init();              
1822
1823 #ifndef NDEBUG
1824         game_event_debug_init();
1825 #endif
1826
1827         training_mission_init();
1828         asteroid_create_all();
1829         
1830         game_framerate_check_init();
1831 }
1832
1833
1834 // An estimate as to how high the count passed to game_loading_callback will go.
1835 // This is just a guess, it seems to always be about the same.   The count is
1836 // proportional to the code being executed, not the time, so this works good
1837 // for a bar, assuming the code does about the same thing each time you
1838 // load a level.   You can find this value by looking at the return value
1839 // of game_busy_callback(NULL), which I conveniently print out to the
1840 // debug output window with the '=== ENDING LOAD ==' stuff.   
1841 //#define COUNT_ESTIMATE 3706
1842 #define COUNT_ESTIMATE 1111
1843
1844 int Game_loading_callback_inited = 0;
1845
1846 int Game_loading_background = -1;
1847 anim * Game_loading_ani = NULL;
1848 anim_instance   *Game_loading_ani_instance;
1849 int Game_loading_frame=-1;
1850
1851 static int Game_loading_ani_coords[GR_NUM_RESOLUTIONS][2] = {
1852         {
1853 #if defined(FS1_DEMO)
1854                 133, 337
1855 #elif defined(MAKE_FS1)
1856                 118, 316
1857 #else
1858                 63, 316  // GR_640
1859 #endif
1860         },
1861         {
1862                 101, 505        // GR_1024
1863         }
1864 };
1865
1866 // This gets called 10x per second and count is the number of times 
1867 // game_busy() has been called since the current callback function
1868 // was set.
1869 void game_loading_callback(int count)
1870 {       
1871         game_do_networking();
1872
1873         SDL_assert( Game_loading_callback_inited==1 );
1874         SDL_assert( Game_loading_ani != NULL );
1875
1876         int framenum = ((Game_loading_ani->total_frames*count) / COUNT_ESTIMATE)+1;
1877         if ( framenum > Game_loading_ani->total_frames-1 )      {
1878                 framenum = Game_loading_ani->total_frames-1;
1879         } else if ( framenum < 0 )      {
1880                 framenum = 0;
1881         }
1882
1883         int cbitmap = -1;
1884         while ( Game_loading_frame < framenum ) {
1885                 Game_loading_frame++;
1886                 cbitmap = anim_get_next_frame(Game_loading_ani_instance);
1887         }
1888
1889
1890         if ( cbitmap > -1 )     {
1891                 if ( Game_loading_background > -1 )     {
1892                         gr_set_bitmap( Game_loading_background, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
1893                         gr_bitmap(0,0);
1894                 }
1895
1896                 //mprintf(( "Showing frame %d/%d [ Bitmap=%d ]\n", Game_loading_frame ,  Game_loading_ani->total_frames, cbitmap ));
1897                 gr_set_bitmap( cbitmap, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
1898                 gr_bitmap(Game_loading_ani_coords[gr_screen.res][0],Game_loading_ani_coords[gr_screen.res][1]);
1899
1900                 bm_release(cbitmap);
1901         
1902                 gr_flip();
1903         }
1904 }
1905
1906 void game_loading_callback_init()
1907 {
1908         SDL_assert( Game_loading_callback_inited==0 );
1909
1910         Game_loading_background = bm_load(Game_loading_bground_fname[gr_screen.res]);
1911 #ifdef MAKE_FS1
1912         common_set_interface_palette("InterfacePalette");  // set the interface palette
1913 #endif
1914
1915
1916         Game_loading_ani = anim_load( Game_loading_ani_fname[gr_screen.res]);
1917         SDL_assert( Game_loading_ani != NULL );
1918         Game_loading_ani_instance = init_anim_instance(Game_loading_ani, 16);
1919         SDL_assert( Game_loading_ani_instance != NULL );
1920         Game_loading_frame = -1;
1921
1922         Game_loading_callback_inited = 1;
1923         Mouse_hidden = 1;
1924         game_busy_callback( game_loading_callback, (COUNT_ESTIMATE/Game_loading_ani->total_frames)+1 ); 
1925
1926
1927 }
1928
1929 void game_loading_callback_close()
1930 {
1931         SDL_assert( Game_loading_callback_inited==1 );
1932
1933         // Make sure bar shows all the way over.
1934         game_loading_callback(COUNT_ESTIMATE);
1935
1936 #ifndef NDEBUG
1937         int real_count = game_busy_callback( NULL );
1938
1939         mprintf(( "=================== ENDING LOAD ================\n" ));
1940         mprintf(( "Real count = %d,  Estimated count = %d\n", real_count, COUNT_ESTIMATE ));
1941         mprintf(( "================================================\n" ));
1942 #else
1943         game_busy_callback( NULL );
1944 #endif
1945
1946         Mouse_hidden = 0;
1947
1948         Game_loading_callback_inited = 0;
1949
1950         free_anim_instance(Game_loading_ani_instance);
1951         Game_loading_ani_instance = NULL;
1952         anim_free(Game_loading_ani);
1953         Game_loading_ani = NULL;
1954
1955         bm_release( Game_loading_background );
1956         common_free_interface_palette();                // restore game palette
1957         Game_loading_background = -1;
1958
1959         gr_set_font( FONT1 );
1960 }
1961
1962 // Update the sound environment (ie change EAX settings based on proximity to large ships)
1963 //
1964 void game_maybe_update_sound_environment()
1965 {
1966         // do nothing for now
1967 }
1968
1969 // Assign the sound environment for the game, based on the current mission
1970 //
1971 void game_assign_sound_environment()
1972 {
1973 #ifdef MAKE_FS1
1974         if (The_mission.flags & MISSION_FLAG_SUBSPACE) {
1975                 Game_sound_env.id = SND_ENV_DRUGGED;
1976                 Game_sound_env.volume = 0.800f;
1977                 Game_sound_env.damping = 1.188f;
1978                 Game_sound_env.decay = 6.392f;
1979 #ifndef FS1_DEMO
1980         } else if (Num_asteroids > 30) {
1981                 Game_sound_env.id = SND_ENV_AUDITORIUM;
1982                 Game_sound_env.volume = 0.603f;
1983                 Game_sound_env.damping = 0.5f;
1984                 Game_sound_env.decay = 4.279f;
1985 #endif
1986         } else {
1987                 Game_sound_env = Game_default_sound_env;
1988         }
1989 #else
1990         Game_sound_env = Game_default_sound_env;
1991 #endif
1992
1993         Game_sound_env_update_timestamp = timestamp(1);
1994 }
1995
1996 // function which gets called before actually entering the mission.  It is broken down into a funciton
1997 // since it will get called in one place from a single player game and from another place for
1998 // a multiplayer game
1999 void freespace_mission_load_stuff()
2000 {
2001         // called if we're not on a freespace dedicated (non rendering, no pilot) server
2002         // IE : we _don't_ want to load any sounds or bitmap/texture info on this machine.
2003         if(!(Game_mode & GM_STANDALONE_SERVER)){        
2004         
2005                 mprintf(( "=================== STARTING LEVEL DATA LOAD ==================\n" ));
2006
2007                 game_loading_callback_init();
2008                 
2009                 event_music_level_init();       // preloads the first 2 seconds for each event music track
2010                 game_busy();
2011
2012                 gamesnd_unload_interface_sounds();              // unload interface sounds from memory
2013                 game_busy();
2014
2015                 gamesnd_preload_common_sounds();                        // load in sounds that are expected to play
2016                 game_busy();
2017
2018                 ship_assign_sound_all();        // assign engine sounds to ships
2019                 game_assign_sound_environment();         // assign the sound environment for this mission
2020                 game_busy();
2021
2022                 // call function in missionparse.cpp to fixup player/ai stuff.
2023                 mission_parse_fixup_players();
2024                 game_busy();
2025
2026                 // Load in all the bitmaps for this level
2027                 level_page_in();
2028
2029                 game_busy();
2030
2031                 game_loading_callback_close();  
2032         } 
2033         // the only thing we need to call on the standalone for now.
2034         else {
2035                 // call function in missionparse.cpp to fixup player/ai stuff.
2036                 mission_parse_fixup_players();
2037
2038                 // Load in all the bitmaps for this level
2039                 level_page_in();
2040         }
2041 }
2042
2043 time_t load_gl_init;
2044 time_t load_mission_load;
2045 time_t load_post_level_init;
2046 time_t load_mission_stuff;
2047
2048 // tells the server to load the mission and initialize structures
2049 int game_start_mission()
2050 {       
2051         mprintf(( "=================== STARTING LEVEL LOAD ==================\n" ));
2052         
2053         load_gl_init = time(NULL);
2054         game_level_init();
2055         load_gl_init = time(NULL) - load_gl_init;
2056         
2057         if (Game_mode & GM_MULTIPLAYER) {
2058                 Player->flags |= PLAYER_FLAGS_IS_MULTI;
2059
2060                 // clear multiplayer stats
2061                 init_multiplayer_stats();
2062         }
2063
2064         load_mission_load = time(NULL);
2065         if (mission_load()) {
2066                 if ( !(Game_mode & GM_MULTIPLAYER) ) {
2067                         popup(PF_BODY_BIG, 1, POPUP_OK, XSTR( "Attempt to load the mission failed", 169));
2068                         gameseq_post_event(GS_EVENT_MAIN_MENU);
2069                 } else {
2070                         multi_quit_game(PROMPT_NONE, MULTI_END_NOTIFY_NONE, MULTI_END_ERROR_LOAD_FAIL);
2071                 }
2072
2073                 return 0;
2074         }
2075         load_mission_load = time(NULL) - load_mission_load;
2076
2077         // If this is a red alert mission in campaign mode, bash wingman status
2078         if ( (Game_mode & GM_CAMPAIGN_MODE) && red_alert_mission() ) {
2079                 red_alert_bash_wingman_status();
2080         }
2081
2082         // the standalone server in multiplayer doesn't do any rendering, so we will not even bother loading the palette
2083         if ( !(Game_mode & GM_STANDALONE_SERVER) ) {
2084                 mprintf(( "=================== LOADING GAME PALETTE ================\n" ));
2085 #ifdef MAKE_FS1
2086                 game_load_palette();
2087 #endif
2088         }
2089
2090         load_post_level_init = time(NULL);
2091         game_post_level_init();
2092         load_post_level_init = time(NULL) - load_post_level_init;
2093
2094         #ifndef NDEBUG
2095         {
2096                 void Do_model_timings_test();
2097                 Do_model_timings_test();        
2098         }
2099         #endif
2100
2101         load_mission_stuff = time(NULL);
2102         freespace_mission_load_stuff();
2103         load_mission_stuff = time(NULL) - load_mission_stuff;
2104
2105         return 1;
2106 }
2107
2108 int Interface_framerate = 0;
2109 #ifndef NDEBUG
2110
2111 DCF_BOOL( mouse_control, Use_mouse_to_fly )
2112 DCF_BOOL( show_framerate, Show_framerate )
2113 DCF_BOOL( show_target_debug_info, Show_target_debug_info )
2114 DCF_BOOL( show_target_weapons, Show_target_weapons )
2115 DCF_BOOL( lead_target_cheat, Players[Player_num].lead_target_cheat )
2116 DCF_BOOL( sound, Sound_enabled )
2117 DCF_BOOL( zbuffer, game_zbuffer )
2118 DCF_BOOL( shield_system, New_shield_system )
2119 DCF_BOOL( show_shield_mesh, Show_shield_mesh)
2120 DCF_BOOL( player_attacking, Player_attacking_enabled )
2121 DCF_BOOL( show_waypoints, Show_waypoints )
2122 DCF_BOOL( show_area_effect, Show_area_effect )
2123 DCF_BOOL( show_net_stats, Show_net_stats )
2124 DCF_BOOL( log, Log_debug_output_to_file )
2125 DCF_BOOL( training_msg_method, Training_msg_method )
2126 DCF_BOOL( show_player_pos, Show_player_pos )
2127 DCF_BOOL(i_framerate, Interface_framerate )
2128
2129 DCF(show_mem,"Toggles showing mem usage")
2130 {
2131         if ( Dc_command )       {       
2132                 dc_get_arg(ARG_TRUE|ARG_FALSE|ARG_NONE);                
2133                 if ( Dc_arg_type & ARG_TRUE )   Show_mem = 1;   
2134                 else if ( Dc_arg_type & ARG_FALSE ) Show_mem = 0;       
2135                 else if ( Dc_arg_type & ARG_NONE ) Show_mem ^= 1;       
2136
2137                 if ( Show_mem ) {
2138                         Show_cpu = 0;
2139                 }
2140         }       
2141         if ( Dc_help )  dc_printf( "Usage: Show_mem\nSets show_mem to true or false.  If nothing passed, then toggles it.\n" ); 
2142         if ( Dc_status )        {
2143                 dc_printf( "Show_mem is %s\n", (Show_mem?"TRUE":"FALSE") );     
2144                 dc_printf( "Show_cpu is %s\n", (Show_cpu?"TRUE":"FALSE") );     
2145         }
2146 }
2147
2148 DCF(show_cpu,"Toggles showing cpu usage")
2149 {
2150         if ( Dc_command )       {       
2151                 dc_get_arg(ARG_TRUE|ARG_FALSE|ARG_NONE);                
2152                 if ( Dc_arg_type & ARG_TRUE )   Show_cpu = 1;   
2153                 else if ( Dc_arg_type & ARG_FALSE ) Show_cpu = 0;       
2154                 else if ( Dc_arg_type & ARG_NONE ) Show_cpu ^= 1;       
2155
2156                 if ( Show_cpu ) {
2157                         Show_mem = 0;
2158                 }
2159         }       
2160         if ( Dc_help )  dc_printf( "Usage: Show_cpu\nSets show_cpu to true or false.  If nothing passed, then toggles it.\n" ); 
2161         if ( Dc_status )        {
2162                 dc_printf( "Show_mem is %s\n", (Show_mem?"TRUE":"FALSE") );     
2163                 dc_printf( "Show_cpu is %s\n", (Show_cpu?"TRUE":"FALSE") );     
2164
2165         }
2166 }
2167
2168 #else
2169
2170         // AL 4-8-98: always allow players to display their framerate
2171
2172         #ifdef FS2_DEMO
2173                 DCF_BOOL( show_framerate, Show_framerate )
2174         #endif
2175
2176 #endif  // NDEBUG
2177
2178                         int Game_init_seed;
2179
2180 DCF(use_joy_mouse,"Makes joystick move mouse cursor")
2181 {
2182         if ( Dc_command )       {       
2183                 dc_get_arg(ARG_TRUE|ARG_FALSE|ARG_NONE);                
2184                 if ( Dc_arg_type & ARG_TRUE )   Use_joy_mouse = 1;      
2185                 else if ( Dc_arg_type & ARG_FALSE ) Use_joy_mouse = 0;  
2186                 else if ( Dc_arg_type & ARG_NONE ) Use_joy_mouse ^= 1;  
2187         }       
2188         if ( Dc_help )  dc_printf( "Usage: use_joy_mouse [bool]\nSets use_joy_mouse to true or false.  If nothing passed, then toggles it.\n" );        
2189         if ( Dc_status )        dc_printf( "use_joy_mouse is %s\n", (Use_joy_mouse?"TRUE":"FALSE") );   
2190
2191         os_config_write_uint( NULL, NOX("JoystickMovesCursor"), Use_joy_mouse );
2192 }
2193
2194 DCF(palette_flash,"Toggles palette flash effect on/off")
2195 {
2196         if ( Dc_command )       {       
2197                 dc_get_arg(ARG_TRUE|ARG_FALSE|ARG_NONE);                
2198                 if ( Dc_arg_type & ARG_TRUE )   Use_palette_flash = 1;  
2199                 else if ( Dc_arg_type & ARG_FALSE ) Use_palette_flash = 0;      
2200                 else if ( Dc_arg_type & ARG_NONE ) Use_palette_flash ^= 1;      
2201         }       
2202         if ( Dc_help )  dc_printf( "Usage: palette_flash [bool]\nSets palette_flash to true or false.  If nothing passed, then toggles it.\n" );        
2203         if ( Dc_status )        dc_printf( "palette_flash is %s\n", (Use_palette_flash?"TRUE":"FALSE") );       
2204 }
2205
2206 int Use_low_mem = 0;
2207
2208 DCF(low_mem,"Uses low memory settings regardless of RAM")
2209 {
2210         if ( Dc_command )       {       
2211                 dc_get_arg(ARG_TRUE|ARG_FALSE|ARG_NONE);                
2212                 if ( Dc_arg_type & ARG_TRUE )   Use_low_mem = 1;        
2213                 else if ( Dc_arg_type & ARG_FALSE ) Use_low_mem = 0;    
2214                 else if ( Dc_arg_type & ARG_NONE ) Use_low_mem ^= 1;    
2215         }       
2216         if ( Dc_help )  dc_printf( "Usage: low_mem [bool]\nSets low_mem to true or false.  If nothing passed, then toggles it.\n" );    
2217         if ( Dc_status )        dc_printf( "low_mem is %s\n", (Use_low_mem?"TRUE":"FALSE") );   
2218
2219         os_config_write_uint( NULL, NOX("LowMem"), Use_low_mem );
2220 }
2221
2222
2223 int     Framerate_delay = 0;
2224
2225 float Freespace_gamma = 1.8f;
2226
2227 DCF(gamma,"Sets Gamma factor")
2228 {
2229         if ( Dc_command )       {
2230                 dc_get_arg(ARG_FLOAT|ARG_NONE);
2231                 if ( Dc_arg_type & ARG_FLOAT )  {
2232                         Freespace_gamma = Dc_arg_float;
2233                 } else {
2234                         dc_printf( "Gamma reset to 1.0f\n" );
2235                         Freespace_gamma = 1.0f;
2236                 }
2237                 if ( Freespace_gamma < 0.1f )   {
2238                         Freespace_gamma = 0.1f;
2239                 } else if ( Freespace_gamma > 5.0f )    {
2240                         Freespace_gamma = 5.0f;
2241                 }
2242                 gr_set_gamma(Freespace_gamma);
2243
2244                 char tmp_gamma_string[32];
2245                 SDL_snprintf( tmp_gamma_string, SDL_arraysize(tmp_gamma_string), NOX("%.2f"), Freespace_gamma );
2246                 os_config_write_string( NULL, NOX("Gamma"), tmp_gamma_string );
2247         }
2248
2249         if ( Dc_help )  {
2250                 dc_printf( "Usage: gamma <float>\n" );
2251                 dc_printf( "Sets gamma in range 1-3, no argument resets to default 1.2\n" );
2252                 Dc_status = 0;  // don't print status if help is printed.  Too messy.
2253         }
2254
2255         if ( Dc_status )        {
2256                 dc_printf( "Gamma = %.2f\n", Freespace_gamma );
2257         }
2258 }
2259
2260 void game_init()
2261 {
2262         Game_current_mission_filename[0] = 0;
2263
2264         // seed the random number generator
2265         Game_init_seed = (int)time(NULL);
2266         srand( Game_init_seed );
2267
2268         Framerate_delay = 0;
2269
2270         #ifndef NDEBUG
2271         load_filter_info();
2272         #endif
2273
2274         extern void bm_init();
2275         bm_init();
2276
2277         // encrypt stuff
2278         encrypt_init();
2279
2280         // Initialize the timer before the os
2281         timer_init();
2282
2283 #ifndef NDEBUG
2284         int s1, e1;
2285         // int s2, e2;
2286
2287         //Initialize the libraries
2288         s1 = timer_get_milliseconds();
2289 #endif
2290
2291         if ( cfile_init() ) {                   // initialize before calling any cfopen stuff!!!
2292                 exit(1);
2293         }
2294
2295 #ifndef NDEBUG
2296         e1 = timer_get_milliseconds();
2297 #endif
2298
2299         // time a bunch of cfopens      
2300         /*
2301         s2 = timer_get_milliseconds();  
2302         CFILE *whee;
2303         for(int idx=0; idx<10000; idx++){
2304                 whee = cfopen("capital01.pof", "rb", CFILE_NORMAL, CF_TYPE_MODELS);
2305                 if(whee != NULL){
2306                         cfclose(whee);
2307                 }
2308                 whee = NULL;
2309                 //cf_exist("capital01.pof", CF_TYPE_MODELS);
2310         }
2311         e2 = timer_get_milliseconds();  
2312         */
2313
2314         os_init( Osreg_class_name, Osreg_app_name );
2315         os_set_title(Osreg_title);
2316
2317         // initialize localization module. Make sure this is down AFTER initialzing OS.
2318 //      int t1 = timer_get_milliseconds();
2319         lcl_init( detect_lang() );
2320         lcl_xstr_init();
2321 //      mprintf(("LCL_INIT() TOOK %d MS\n", timer_get_milliseconds()-t1));
2322
2323         // verify that he has a valid ships.tbl (will Game_ships_tbl_valid if so)
2324         verify_ships_tbl();
2325
2326         // verify that he has a valid weapons.tbl
2327         verify_weapons_tbl();
2328
2329         // Output version numbers to registry for auto patching purposes
2330         os_config_write_uint(NOX("Version"), NOX("Major"), FS_VERSION_MAJOR);
2331         os_config_write_uint(NOX("Version"), NOX("Minor"), FS_VERSION_MINOR);
2332         os_config_write_uint(NOX("Version"), NOX("Build"), FS_VERSION_BUILD);
2333
2334         Use_joy_mouse = 0;              //os_config_read_uint( NULL, NOX("JoystickMovesCursor"), 1 );
2335         //Use_palette_flash = os_config_read_uint( NULL, NOX("PaletteFlash"), 0 );
2336         Use_low_mem = os_config_read_uint( NULL, NOX("LowMem"), 0 );
2337
2338         // show the FPS counter if the config file says so
2339         Show_framerate = os_config_read_uint( "Video", "ShowFPS", Show_framerate );
2340
2341 #if !(defined(FS2_DEMO) || defined(FS1_DEMO))
2342         Asteroids_enabled = 1;          
2343 #endif
2344
2345 /////////////////////////////
2346 // SOUND INIT START
2347 /////////////////////////////
2348
2349         if (!Is_standalone) {
2350                 snd_init();
2351         }
2352
2353 /////////////////////////////
2354 // SOUND INIT END
2355 /////////////////////////////
2356
2357
2358         gr_init();
2359
2360         os_set_icon();
2361
2362 #if defined(FS2_DEMO) || defined(OEM_BUILD)
2363         // add title screen
2364         if(!Is_standalone){
2365                 display_title_screen();
2366         }
2367 #endif
2368
2369         // If less than 48MB of RAM, use low memory model.
2370         if ( (Freespace_total_ram < 48) || Use_low_mem )        {
2371                 mprintf(( "Using normal memory settings...\n" ));
2372                 bm_set_low_mem(1);              // Use every other frame of bitmaps
2373         } else {
2374                 mprintf(( "Using high memory settings...\n" ));
2375                 bm_set_low_mem(0);              // Use all frames of bitmaps
2376         }
2377
2378         // load non-darkening pixel defs
2379         palman_load_pixels();
2380
2381         // hud shield icon stuff
2382         hud_shield_game_init();
2383
2384         control_config_common_init();                           // sets up localization stuff in the control config
2385         parse_rank_tbl();
2386         parse_medal_tbl();
2387         cutscene_init();
2388         key_init();
2389         mouse_init();
2390         gamesnd_parse_soundstbl();
2391         radar_init();
2392         gameseq_init();
2393         multi_init();   
2394
2395         // standalone's don't use hte joystick and it seems to sometimes cause them to not get shutdown properly
2396         if(!Is_standalone){
2397                 joy_init();
2398         }
2399
2400         player_controls_init();
2401         model_init();   
2402
2403         //if(!Is_standalone){
2404                 event_music_init();
2405         //}     
2406
2407         obj_init();     
2408         mflash_game_init();     
2409         weapon_init();  
2410         ai_init();              
2411         ship_init();                                            // read in ships.tbl    
2412         player_init();  
2413         mission_campaign_init();                // load in the default campaign 
2414         anim_init();
2415 //      navmap_init();                                          // init the navigation map system
2416         context_help_init();                    
2417         techroom_intel_init();                  // parse species.tbl, load intel info   
2418         // initialize psnet
2419         psnet_init( Multi_options_g.protocol, Multi_options_g.port );                                           // initialize the networking code               
2420         init_animating_pointer();       
2421         asteroid_init();
2422         mission_brief_common_init();    // Mark all the briefing structures as empty.           
2423         gr_font_init();                                 // loads up all fonts           
2424
2425         neb2_init();                                            // fullneb stuff
2426         nebl_init();
2427         stars_init();
2428         ssm_init();     
2429         player_tips_init();                             // helpful tips
2430         beam_init();
2431         
2432         // load the list of pilot pic filenames (for barracks and pilot select popup quick reference)
2433         pilot_load_pic_list();  
2434         pilot_load_squad_pic_list();
2435
2436         load_animating_pointer(NOX("cursor"), 0, 0);    
2437
2438         // initialize alpha colors
2439         alpha_colors_init();    
2440
2441         Viewer_mode = 0;
2442 //      Game_music_paused = 0;
2443         Game_paused = 0;
2444
2445         if (Is_standalone) {
2446                 std_init_standalone();
2447         }
2448
2449         nprintf(("General", "Ships.tbl is : %s\n", Game_ships_tbl_valid ? "VALID" : "INVALID!!!!"));
2450         nprintf(("General", "Weapons.tbl is : %s\n", Game_weapons_tbl_valid ? "VALID" : "INVALID!!!!"));
2451
2452         mprintf(("cfile_init() took %d\n", e1 - s1));
2453         // mprintf(("1000 cfopens() took %d\n", e2 - s2));      
2454 }
2455
2456 char transfer_text[128];
2457
2458 float   Start_time = 0.0f;
2459
2460 float Framerate = 0.0f;
2461
2462 float Timing_total = 0.0f;
2463 float Timing_render2 = 0.0f;
2464 float Timing_render3 = 0.0f;
2465 float Timing_flip = 0.0f;
2466 float Timing_clear = 0.0f;
2467
2468 MONITOR(NumPolysDrawn);
2469 MONITOR(NumPolys);
2470 MONITOR(NumVerts);
2471 MONITOR(BmpUsed);
2472 MONITOR(BmpNew);
2473
2474 void game_get_framerate()
2475 {
2476         if ( frame_int == -1 )  {
2477                 int i;
2478                 for (i=0; i<FRAME_FILTER; i++ ) {
2479                         frametimes[i] = 0.0f;
2480                 }
2481                 frametotal = 0.0f;
2482                 frame_int = 0;
2483         }
2484         frametotal -= frametimes[frame_int];
2485         frametotal += flFrametime;
2486         frametimes[frame_int] = flFrametime;
2487         frame_int = (frame_int + 1 ) % FRAME_FILTER;
2488
2489         if ( frametotal != 0.0 )        {
2490                 if ( Framecount >= FRAME_FILTER )
2491                         Framerate = FRAME_FILTER / frametotal;
2492                 else
2493                         Framerate = Framecount / frametotal;
2494         }
2495         Framecount++;
2496
2497         if (Show_framerate)     {
2498                 gr_set_color_fast(&HUD_color_debug);
2499                 gr_printf(570, 2, NOX("FPS: %.1f"), Framerate);
2500         }
2501 }
2502
2503 void game_show_framerate()
2504 {       
2505         float   cur_time;
2506
2507         cur_time = f2fl(timer_get_approx_seconds());
2508         if (cur_time - Start_time > 30.0f) {
2509                 mprintf(("%i frames executed in %7.3f seconds, %7.3f frames per second.\n", Framecount, cur_time - Start_time, Framecount/(cur_time - Start_time)));
2510                 Start_time += 1000.0f;
2511         }
2512
2513         //mprintf(( "%s\n", text ));
2514
2515 #ifndef NDEBUG
2516         if ( Debug_dump_frames )
2517                 return;
2518 #endif  
2519
2520         // possibly show control checking info
2521         control_check_indicate();
2522
2523 //      int bitmaps_used_this_frame, bitmaps_new_this_frame;
2524 //      bm_get_frame_usage(&bitmaps_used_this_frame,&bitmaps_new_this_frame);
2525 //      MONITOR_INC(BmpUsed, bitmaps_used_this_frame);
2526 // MONITOR_INC(BmpNew, bitmaps_new_this_frame);
2527
2528 #ifndef NDEBUG
2529         if ( Show_cpu == 1 ) {
2530                 
2531                 int sx,sy,dy;
2532                 sx = 530;
2533                 sy = 15;
2534                 dy = gr_get_font_height() + 1;
2535
2536                 gr_set_color_fast(&HUD_color_debug);
2537
2538                 {
2539                         extern int Gr_textures_in;
2540                         gr_printf( sx, sy, NOX("VRAM: %d KB\n"), Gr_textures_in/1024 );
2541                         sy += dy;
2542                 }
2543 //              gr_printf( sx, sy, "BPP: %d", gr_screen.bits_per_pixel );
2544 //              sy += dy;
2545                 gr_printf( sx, sy, NOX("DMA: %s"), transfer_text );
2546                 sy += dy;
2547                 gr_printf( sx, sy, NOX("POLYP: %d"), modelstats_num_polys );
2548                 sy += dy;
2549                 gr_printf( sx, sy, NOX("POLYD: %d"), modelstats_num_polys_drawn );
2550                 sy += dy;
2551                 gr_printf( sx, sy, NOX("VERTS: %d"), modelstats_num_verts );
2552                 sy += dy;
2553
2554                 {
2555
2556                         extern int Num_pairs;           // Number of object pairs that were checked.
2557                         gr_printf( sx, sy, NOX("PAIRS: %d"), Num_pairs );
2558                         sy += dy;
2559
2560                         extern int Num_pairs_checked;   // What percent of object pairs were checked.
2561                         gr_printf( sx, sy, NOX("FVI: %d"), Num_pairs_checked );
2562                         sy += dy;
2563                         Num_pairs_checked = 0;
2564
2565                 }
2566
2567                 gr_printf( sx, sy, NOX("Snds: %d"), snd_num_playing() );
2568                 sy += dy;
2569
2570                 if ( Timing_total > 0.01f )     {
2571                         gr_printf(  sx, sy, NOX("CLEAR: %.0f%%"), Timing_clear*100.0f/Timing_total );
2572                         sy += dy;
2573                         gr_printf( sx, sy, NOX("REND2D: %.0f%%"), Timing_render2*100.0f/Timing_total );
2574                         sy += dy;
2575                         gr_printf( sx, sy, NOX("REND3D: %.0f%%"), Timing_render3*100.0f/Timing_total );
2576                         sy += dy;
2577                         gr_printf( sx, sy, NOX("FLIP: %.0f%%"), Timing_flip*100.0f/Timing_total );
2578                         sy += dy;
2579                         gr_printf( sx, sy, NOX("GAME: %.0f%%"), (Timing_total-(Timing_render2+Timing_render3+Timing_flip+Timing_clear))*100.0f/Timing_total );
2580                 }
2581         }
2582                 
2583         if ( Show_mem  ) {
2584                 
2585                 int sx,sy,dy;
2586                 sx = 530;
2587                 sy = 15;
2588                 dy = gr_get_font_height() + 1;
2589
2590                 gr_set_color_fast(&HUD_color_debug);
2591
2592                 {
2593                         extern int TotalRam;
2594                         gr_printf( sx, sy, NOX("DYN: %d KB\n"), TotalRam/1024 );
2595                         sy += dy;
2596                 }       
2597
2598                 {
2599                         extern int Model_ram;
2600                         gr_printf( sx, sy, NOX("POF: %d KB\n"), Model_ram/1024 );
2601                         sy += dy;
2602                 }       
2603
2604                 gr_printf( sx, sy, NOX("BMP: %d KB\n"), bm_texture_ram/1024 );
2605                 sy += dy;
2606                 gr_printf( sx, sy, NOX("S-SRAM: %d KB\n"), Snd_sram/1024 );             // mem used to store game sound
2607                 sy += dy;
2608
2609                 {
2610                         extern int Gr_textures_in;
2611                         gr_printf( sx, sy, NOX("VRAM: %d KB\n"), Gr_textures_in/1024 );
2612                 }
2613         }
2614
2615
2616         if ( Show_player_pos ) {
2617                 int sx, sy;
2618                 sx = 320;
2619                 sy = 100;
2620                 gr_printf(sx, sy, NOX("Player Pos: (%d,%d,%d)"), fl2i(Player_obj->pos.xyz.x), fl2i(Player_obj->pos.xyz.y), fl2i(Player_obj->pos.xyz.z));
2621         }
2622
2623         MONITOR_INC(NumPolys, modelstats_num_polys);
2624         MONITOR_INC(NumPolysDrawn, modelstats_num_polys_drawn );
2625         MONITOR_INC(NumVerts, modelstats_num_verts );
2626
2627         modelstats_num_polys = 0;
2628         modelstats_num_polys_drawn = 0;
2629         modelstats_num_verts = 0;
2630         modelstats_num_sortnorms = 0;
2631 #endif
2632 }
2633
2634 void game_show_standalone_framerate()
2635 {
2636         float frame_rate=30.0f;
2637         if ( frame_int == -1 )  {
2638                 int i;
2639                 for (i=0; i<FRAME_FILTER; i++ ) {
2640                         frametimes[i] = 0.0f;
2641                 }
2642                 frametotal = 0.0f;
2643                 frame_int = 0;
2644         }
2645         frametotal -= frametimes[frame_int];
2646         frametotal += flFrametime;
2647         frametimes[frame_int] = flFrametime;
2648         frame_int = (frame_int + 1 ) % FRAME_FILTER;
2649
2650         if ( frametotal != 0.0 )        {
2651                 if ( Framecount >= FRAME_FILTER ){
2652                         frame_rate = FRAME_FILTER / frametotal;
2653                 } else {
2654                         frame_rate = Framecount / frametotal;
2655                 }
2656         }
2657         std_set_standalone_fps(frame_rate);
2658         Framecount++;
2659 }
2660
2661 // function to show the time remaining in a mission.  Used only when the end-mission sexpression is used
2662 void game_show_time_left()
2663 {
2664         int diff;
2665
2666         // mission_end_time is a global from missionparse.cpp that contains the mission time at which the
2667         // mission should end (in fixed seconds).  There is code in missionparse.cpp which actually handles
2668         // checking how much time is left
2669
2670         if ( Mission_end_time == -1 ){
2671                 return;
2672         }
2673
2674         diff = f2i(Mission_end_time - Missiontime);
2675         // be sure to bash to 0.  diff could be negative on frame that we quit mission
2676         if ( diff < 0 ){
2677                 diff = 0;
2678         }
2679
2680         hud_set_default_color();
2681         gr_printf( 5, 40, XSTR( "Mission time remaining: %d seconds", 179), diff );
2682 }
2683
2684 //========================================================================================
2685 //=================== NEW DEBUG CONSOLE COMMANDS TO REPLACE OLD DEBUG PAUSE MENU =========
2686 //========================================================================================
2687
2688 #ifndef NDEBUG
2689
2690 DCF(ai_pause,"Pauses ai")
2691 {
2692         if ( Dc_command )       {       
2693                 dc_get_arg(ARG_TRUE|ARG_FALSE|ARG_NONE);                
2694                 if ( Dc_arg_type & ARG_TRUE )   ai_paused = 1;  
2695                 else if ( Dc_arg_type & ARG_FALSE ) ai_paused = 0;      
2696                 else if ( Dc_arg_type & ARG_NONE ) ai_paused = !ai_paused;      
2697
2698                 if (ai_paused)  {       
2699                         obj_init_all_ships_physics();
2700                 }
2701         }       
2702         if ( Dc_help )  dc_printf( "Usage: ai_paused [bool]\nSets ai_paused to true or false.  If nothing passed, then toggles it.\n" );        
2703         if ( Dc_status )        dc_printf( "ai_paused is %s\n", (ai_paused?"TRUE":"FALSE") );   
2704 }
2705
2706 DCF(single_step,"Single steps the game")
2707 {
2708         if ( Dc_command )       {       
2709                 dc_get_arg(ARG_TRUE|ARG_FALSE|ARG_NONE);                
2710                 if ( Dc_arg_type & ARG_TRUE )   game_single_step = 1;   
2711                 else if ( Dc_arg_type & ARG_FALSE ) game_single_step = 0;       
2712                 else if ( Dc_arg_type & ARG_NONE ) game_single_step = !game_single_step;        
2713
2714                 last_single_step = 0;   // Make so single step waits a frame before stepping
2715
2716         }       
2717         if ( Dc_help )  dc_printf( "Usage: single_step [bool]\nSets single_step to true or false.  If nothing passed, then toggles it.\n" );    
2718         if ( Dc_status )        dc_printf( "single_step is %s\n", (game_single_step?"TRUE":"FALSE") );  
2719 }
2720
2721 DCF_BOOL(physics_pause, physics_paused)
2722 DCF_BOOL(ai_rendering, Ai_render_debug_flag)
2723 DCF_BOOL(ai_firing, Ai_firing_enabled )
2724
2725 // Create some simple aliases to these commands...
2726 debug_command dc_s("s","shortcut for single_step",dcf_single_step);
2727 debug_command dc_p("p","shortcut for physics_pause", dcf_physics_pause );
2728 debug_command dc_r("r","shortcut for ai_rendering", dcf_ai_rendering );
2729 debug_command dc_f("f","shortcut for ai_firing", dcf_ai_firing);
2730 debug_command dc_a("a","shortcut for ai_pause", dcf_ai_pause);
2731 #endif
2732
2733 //========================================================================================
2734 //========================================================================================
2735
2736
2737 void game_training_pause_do()
2738 {
2739         int key;
2740
2741         key = game_check_key();
2742         if (key > 0){
2743                 gameseq_post_event(GS_EVENT_PREVIOUS_STATE);
2744         }
2745
2746         gr_flip();
2747 }
2748
2749
2750 void game_increase_skill_level()
2751 {
2752         Game_skill_level++;
2753         if (Game_skill_level >= NUM_SKILL_LEVELS){
2754                 Game_skill_level = 0;
2755         }
2756 }
2757
2758 int     Player_died_time;
2759
2760 int View_percent = 100;
2761
2762
2763 DCF(view, "Sets the percent of the 3d view to render.")
2764 {
2765         if ( Dc_command ) {
2766                 dc_get_arg(ARG_INT);
2767                 if ( (Dc_arg_int >= 5 ) || (Dc_arg_int <= 100) ) {
2768                         View_percent = Dc_arg_int;
2769                 } else {
2770                         dc_printf( "Illegal value for view. (Must be from 5-100) \n\n");
2771                         Dc_help = 1;
2772                 }
2773         }
2774
2775         if ( Dc_help ) {
2776                 dc_printf("Usage: view [n]\nwhere n is percent of view to show (5-100).\n");
2777         }
2778         
2779         if ( Dc_status ) {
2780                 dc_printf("View is set to %d%%\n", View_percent );
2781         }
2782 }
2783
2784
2785 // Set the clip region for the 3d rendering window
2786 void game_set_view_clip()
2787 {
2788         if ((Game_mode & GM_DEAD) || (supernova_active() >= 2)) {
2789                 // Set the clip region for the letterbox "dead view"
2790                 int yborder = gr_screen.max_h/4;
2791
2792                 //      Numeric constants encouraged by J "pig farmer" S, who shall remain semi-anonymous.
2793                 // J.S. I've changed my ways!! See the new "no constants" code!!!
2794                 gr_set_clip(0, yborder, gr_screen.max_w, gr_screen.max_h - yborder*2 ); 
2795         } else {
2796                 // Set the clip region for normal view
2797                 if ( View_percent >= 100 )      {
2798                         gr_reset_clip();
2799                 } else {
2800                         int xborder, yborder;
2801
2802                         if ( View_percent < 5 ) {
2803                                 View_percent = 5;
2804                         }
2805
2806                         float fp = i2fl(View_percent)/100.0f;
2807                         int fi = fl2i(fl_sqrt(fp)*100.0f);
2808                         if ( fi > 100 ) fi=100;
2809                         
2810                         xborder = ( gr_screen.max_w*(100-fi) )/200;
2811                         yborder = ( gr_screen.max_h*(100-fi) )/200;
2812
2813                         gr_set_clip(xborder, yborder, gr_screen.max_w-xborder*2,gr_screen.max_h-yborder*2 );
2814                 }
2815         }
2816 }
2817
2818
2819 void show_debug_stuff()
2820 {
2821         int     i;
2822         int     laser_count = 0, missile_count = 0;
2823
2824         for (i=0; i<MAX_OBJECTS; i++) {
2825                 if (Objects[i].type == OBJ_WEAPON){
2826                         if (Weapon_info[Weapons[Objects[i].instance].weapon_info_index].subtype == WP_LASER){
2827                                 laser_count++;
2828                         } else if (Weapon_info[Weapons[Objects[i].instance].weapon_info_index].subtype == WP_MISSILE){
2829                                 missile_count++;
2830                         }
2831                 }
2832         }
2833
2834         nprintf(("Mike", "Frame: %i Lasers: %4i, Missiles: %4i\n", Framecount, laser_count, missile_count));
2835 }
2836
2837 extern int Tool_enabled;
2838 int tst = 0;
2839 time_t tst_time = 0;
2840 int tst_big = 0;
2841 vector tst_pos;
2842 int tst_bitmap = -1;
2843 float tst_x, tst_y;
2844 float tst_offset, tst_offset_total;
2845 int tst_mode;
2846 int tst_stamp;
2847 void game_tst_frame_pre()
2848 {
2849         // start tst
2850         if(tst == 3){
2851                 tst = 0;
2852
2853                 // screen position
2854                 vertex v;
2855                 g3_rotate_vertex(&v, &tst_pos);
2856                 g3_project_vertex(&v);  
2857         
2858                 // offscreen
2859                 if(!((v.sx >= 0) && (v.sx <= gr_screen.max_w) && (v.sy >= 0) && (v.sy <= gr_screen.max_h))){
2860                         return;
2861                 }       
2862
2863                 // big ship? always tst
2864                 if(tst_big){
2865                         // within 3000 meters
2866                         if( vm_vec_dist_quick(&tst_pos, &Eye_position) <= 3000.0f){
2867                                 tst = 2;                                
2868                         }
2869                 } else {                        
2870                         // within 300 meters
2871                         if( (vm_vec_dist_quick(&tst_pos, &Eye_position) <= 300.0f) && ((tst_time == 0) || ((time(NULL) - tst_time) >= 10)) ){
2872                                 tst = 2;                                
2873                         } 
2874                 }                       
2875         }
2876
2877 }
2878 void game_tst_frame()
2879 {
2880         int left = 0;
2881
2882         if(!Tool_enabled){
2883                 return;
2884         }
2885         
2886         // setup tst
2887         if(tst == 2){           
2888                 tst_time = time(NULL);
2889
2890                 // load the tst bitmap          
2891                 switch((int)frand_range(0.0f, 3.0)){
2892                 case 0:                 
2893                         tst_bitmap = bm_load("ig_jim");
2894                         left = 1;
2895                         mprintf(("TST 0\n"));
2896                         break;
2897
2898                 case 1:
2899                         tst_bitmap = bm_load("ig_kan");
2900                         left = 0;
2901                         mprintf(("TST 1\n"));
2902                         break;
2903
2904                 case 2:
2905                         tst_bitmap = bm_load("ig_jim");
2906                         left = 1;
2907                         mprintf(("TST 2\n"));
2908                         break;
2909                         
2910                 default:                        
2911                         tst_bitmap = bm_load("ig_kan");
2912                         left = 0;
2913                         mprintf(("TST 3\n"));
2914                         break;
2915                 }
2916
2917                 if(tst_bitmap < 0){
2918                         tst = 0;
2919                         return;
2920                 }               
2921
2922                 // get the tst bitmap dimensions
2923                 int w, h;
2924                 bm_get_info(tst_bitmap, &w, &h);
2925
2926                 // tst y
2927                 tst_y = frand_range(0.0f, (float)gr_screen.max_h - h);
2928
2929                 snd_play(&Snds[SND_VASUDAN_BUP]);
2930
2931                 // tst x and direction
2932                 tst_mode = 0;
2933                 if(left){
2934                         tst_x = (float)-w;
2935                         tst_offset_total = (float)w;
2936                         tst_offset = (float)w;
2937                 } else {
2938                         tst_x = (float)gr_screen.max_w;
2939                         tst_offset_total = (float)-w;
2940                         tst_offset = (float)w;
2941                 }
2942
2943                 tst = 1;
2944         }
2945
2946         // run tst
2947         if(tst == 1){
2948                 float diff = (tst_offset_total / 0.5f) * flFrametime;
2949
2950                 // move the bitmap
2951                 if(tst_mode == 0){
2952                         tst_x += diff;
2953                         
2954                         tst_offset -= fl_abs(diff);
2955                 } else if(tst_mode == 2){
2956                         tst_x -= diff;
2957                         
2958                         tst_offset -= fl_abs(diff);
2959                 }
2960
2961                 // draw the bitmap
2962                 gr_set_bitmap(tst_bitmap, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
2963                 gr_bitmap((int)tst_x, (int)tst_y);
2964
2965                 if(tst_mode == 1){
2966                         if(timestamp_elapsed_safe(tst_stamp, 1100)){
2967                                 tst_mode = 2;
2968                         }
2969                 } else {
2970                         // if we passed the switch point
2971                         if(tst_offset <= 0.0f){
2972                                 // switch modes
2973                                 switch(tst_mode){
2974                                 case 0:
2975                                         tst_mode = 1;
2976                                         tst_stamp = timestamp(1000);
2977                                         tst_offset = fl_abs(tst_offset_total);
2978                                         break;                          
2979
2980                                 case 2:                         
2981                                         tst = 0;
2982                                         return;
2983                                 }
2984                         }                               
2985                 }
2986         }
2987 }
2988 void game_tst_mark(object *objp, ship *shipp)
2989 {
2990         ship_info *sip; 
2991
2992         if(!Tool_enabled){
2993                 return;
2994         }
2995
2996         // bogus
2997         if((objp == NULL) || (shipp == NULL) || (shipp->ship_info_index < 0) || (shipp->ship_info_index >= Num_ship_types)){
2998                 return;
2999         }
3000         sip = &Ship_info[shipp->ship_info_index];
3001
3002         // already tst
3003         if(tst){
3004                 return;
3005         }
3006
3007         tst_pos = objp->pos;
3008         if(sip->flags & (SIF_BIG_SHIP | SIF_HUGE_SHIP)){
3009                 tst_big = 1;
3010         }
3011         tst = 3;
3012 }
3013
3014 extern void render_shields();
3015
3016 void player_repair_frame(float frametime)
3017 {
3018         if((Game_mode & GM_MULTIPLAYER) && (Net_player->flags & NETINFO_FLAG_AM_MASTER)){
3019                 int idx;
3020                 for(idx=0;idx<MAX_PLAYERS;idx++){
3021                         net_player *np;
3022
3023                         np = &Net_players[idx];
3024
3025                         if(MULTI_CONNECTED(Net_players[idx]) && (Net_player != NULL) && (Net_player->player_id != Net_players[idx].player_id) && (Net_players[idx].player != NULL) && (Net_players[idx].player->objnum >= 0) && (Net_players[idx].player->objnum < MAX_OBJECTS)){
3026
3027                                 // don't rearm/repair if the player is dead or dying/departing
3028                                 if ( !NETPLAYER_IS_DEAD(np) && !(Ships[Objects[np->player->objnum].instance].flags & (SF_DYING|SF_DEPARTING)) ) {
3029                                         ai_do_repair_frame(&Objects[Net_players[idx].player->objnum],&Ai_info[Ships[Objects[Net_players[idx].player->objnum].instance].ai_index],frametime);
3030                                 }
3031                         }
3032                 }
3033         }       
3034         if ( (Player_obj != NULL) && (Player_obj->type == OBJ_SHIP) && !(Game_mode & GM_STANDALONE_SERVER) && (Player_ship != NULL) && !(Player_ship->flags & SF_DYING) ) {
3035                 ai_do_repair_frame(Player_obj, &Ai_info[Ships[Player_obj->instance].ai_index], frametime);
3036         }
3037 }
3038
3039
3040 #ifndef NDEBUG
3041 #define NUM_FRAMES_TEST         300
3042 #define NUM_MIXED_SOUNDS        16
3043 void do_timing_test(float frametime)
3044 {
3045         static int framecount = 0;
3046         static int test_running = 0;
3047         static float test_time = 0.0f;
3048
3049         static int snds[NUM_MIXED_SOUNDS];
3050         int i;
3051
3052         if ( test_running ) {
3053                 framecount++;
3054                 test_time += frametime;
3055                 if ( framecount >= NUM_FRAMES_TEST ) {
3056                         test_running = 0;
3057                         nprintf(("General", "%d frames took %.3f seconds\n", NUM_FRAMES_TEST, test_time));
3058                         for ( i = 0; i < NUM_MIXED_SOUNDS; i++ )
3059                                 snd_stop(snds[i]);
3060                 }
3061         }
3062
3063         if ( Test_begin == 1 ) {
3064                 framecount = 0;
3065                 test_running = 1;
3066                 test_time = 0.0f;
3067                 Test_begin = 0;
3068
3069                 for ( i = 0; i < NUM_MIXED_SOUNDS; i++ )
3070                         snds[i] = -1;
3071
3072                 // start looping digital sounds
3073                 for ( i = 0; i < NUM_MIXED_SOUNDS; i++ )
3074                         snds[i] = snd_play_looping( &Snds[i], 0.0f);
3075         }
3076         
3077
3078 }
3079 #endif
3080
3081 DCF(dcf_fov, "Change the field of view")
3082 {
3083         if ( Dc_command )       {
3084                 dc_get_arg(ARG_FLOAT|ARG_NONE);
3085                 if ( Dc_arg_type & ARG_NONE )   {
3086                         Viewer_zoom = VIEWER_ZOOM_DEFAULT;
3087                         dc_printf( "Zoom factor reset\n" );
3088                 }
3089                 if ( Dc_arg_type & ARG_FLOAT )  {
3090                         if (Dc_arg_float < 0.25f) {
3091                                 Viewer_zoom = 0.25f;
3092                                 dc_printf("Zoom factor pinned at 0.25.\n");
3093                         } else if (Dc_arg_float > 1.25f) {
3094                                 Viewer_zoom = 1.25f;
3095                                 dc_printf("Zoom factor pinned at 1.25.\n");
3096                         } else {
3097                                 Viewer_zoom = Dc_arg_float;
3098                         }
3099                 }
3100         }
3101
3102         if ( Dc_help )  
3103                 dc_printf( "Usage: fov [factor]\nFactor is the zoom factor btwn .25 and 1.25\nNo parameter resets it to default.\n" );
3104
3105         if ( Dc_status )                                
3106                 dc_printf("Zoom factor set to %6.3f (original = 0.5, John = 0.75)", Viewer_zoom);
3107 }
3108
3109
3110 DCF(framerate_cap, "Sets the framerate cap")
3111 {
3112         if ( Dc_command ) {
3113                 dc_get_arg(ARG_INT);
3114                 if ( (Dc_arg_int >= 1 ) || (Dc_arg_int <= 120) ) {
3115                         Framerate_cap = Dc_arg_int;
3116                 } else {
3117                         dc_printf( "Illegal value for framerate cap. (Must be from 1-120) \n\n");
3118                         Dc_help = 1;
3119                 }
3120         }
3121
3122         if ( Dc_help ) {
3123                 dc_printf("Usage: framerate_cap [n]\nwhere n is the frames per second to cap framerate at.\n");
3124                 dc_printf("If n is 0 or omitted, then the framerate cap is removed\n");
3125                 dc_printf("[n] must be from 1 to 120.\n");
3126         }
3127         
3128         if ( Dc_status ) {
3129                 if ( Framerate_cap )
3130                         dc_printf("Framerate cap is set to %d fps\n", Framerate_cap );
3131                 else
3132                         dc_printf("There is no framerate cap currently active.\n");
3133         }
3134 }
3135
3136 #define MIN_DIST_TO_DEAD_CAMERA         50.0f
3137 int Show_viewing_from_self = 0;
3138
3139 void say_view_target()
3140 {
3141         object  *view_target;
3142
3143         if ((Viewer_mode & VM_OTHER_SHIP) && (Player_ai->target_objnum != -1))
3144                 view_target = &Objects[Player_ai->target_objnum];
3145         else
3146                 view_target = Player_obj;
3147
3148         if (Game_mode & GM_DEAD) {
3149                 if (Player_ai->target_objnum != -1)
3150                         view_target = &Objects[Player_ai->target_objnum];
3151         }
3152
3153         if (!(Game_mode & GM_DEAD_DIED) && ((Game_mode & (GM_DEAD_BLEW_UP)) || ((Last_view_target != NULL) && (Last_view_target != view_target)))) {
3154                 if (view_target != Player_obj){
3155
3156                         char *view_target_name = NULL;
3157                         switch(Objects[Player_ai->target_objnum].type) {
3158                         case OBJ_SHIP:
3159                                 view_target_name = Ships[Objects[Player_ai->target_objnum].instance].ship_name;
3160                                 break;
3161                         case OBJ_WEAPON:
3162                                 view_target_name = Weapon_info[Weapons[Objects[Player_ai->target_objnum].instance].weapon_info_index].name;
3163                                 Viewer_mode &= ~VM_OTHER_SHIP;
3164                                 break;
3165                         case OBJ_JUMP_NODE: {
3166                                 char    jump_node_name[128];
3167                                 SDL_strlcpy(jump_node_name, XSTR( "jump node", 184), SDL_arraysize(jump_node_name));
3168                                 view_target_name = jump_node_name;
3169                                 Viewer_mode &= ~VM_OTHER_SHIP;
3170                                 break;
3171                                 }
3172
3173                         default:
3174                                 Int3();
3175                                 break;
3176                         }
3177
3178                         if ( view_target_name ) {
3179                                 HUD_fixed_printf(0.0f, XSTR( "Viewing %s%s\n", 185), (Viewer_mode & VM_OTHER_SHIP) ? XSTR( "from ", 186) : "", view_target_name);
3180                                 Show_viewing_from_self = 1;
3181                         }
3182                 } else {
3183                         if((Game_mode & GM_MULTIPLAYER) && (Net_player->flags & NETINFO_FLAG_OBSERVER) && (Player_obj->type == OBJ_OBSERVER)){
3184                                 HUD_fixed_printf(2.0f,XSTR( "Viewing from observer\n", 187));
3185                                 Show_viewing_from_self = 1;
3186                         } else {
3187                                 if (Show_viewing_from_self)
3188                                         HUD_fixed_printf(2.0f, XSTR( "Viewing from self\n", 188));
3189                         }
3190                 }
3191         }
3192
3193         Last_view_target = view_target;
3194 }
3195
3196
3197 float Game_hit_x = 0.0f;
3198 float Game_hit_y = 0.0f;
3199
3200 // Reset at the beginning of each frame
3201 void game_whack_reset()
3202 {
3203         Game_hit_x = 0.0f;
3204         Game_hit_y = 0.0f;
3205 }
3206
3207 // Apply a 2d whack to the player
3208 void game_whack_apply( float x, float y )
3209 {
3210         // Do some force feedback
3211         joy_ff_play_dir_effect(x * 80.0f, y * 80.0f);
3212
3213         // Move the eye 
3214         Game_hit_x += x;
3215         Game_hit_y += y;
3216
3217 //      mprintf(( "WHACK = %.1f, %.1f\n", Game_hit_x, Game_hit_y ));
3218 }
3219
3220 // call to apply a "shudder"
3221 void game_shudder_apply(int time, float intensity)
3222 {
3223         Game_shudder_time = timestamp(time);
3224         Game_shudder_total = time;
3225         Game_shudder_intensity = intensity;
3226 }
3227
3228 #define FF_SCALE        10000
3229 void apply_hud_shake(matrix *eye_orient)
3230 {
3231         if (Viewer_obj == Player_obj) {
3232                 physics_info    *pi = &Player_obj->phys_info;
3233
3234                 angles  tangles;
3235
3236                 tangles.p = 0.0f;
3237                 tangles.h = 0.0f;
3238                 tangles.b = 0.0f;
3239
3240                 //      Make eye shake due to afterburner
3241                 if ( !timestamp_elapsed(pi->afterburner_decay) ) {                      
3242                         int             dtime;
3243
3244                         dtime = timestamp_until(pi->afterburner_decay);
3245                         
3246                         int r1 = myrand();
3247                         int r2 = myrand();
3248                         tangles.p += 0.07f * (float) (r1-MY_RAND_MAX/2)/MY_RAND_MAX * (0.5f - fl_abs(0.5f - (float) dtime/ABURN_DECAY_TIME));
3249                         tangles.h += 0.07f * (float) (r2-MY_RAND_MAX/2)/MY_RAND_MAX * (0.5f - fl_abs(0.5f - (float) dtime/ABURN_DECAY_TIME));
3250                 }
3251
3252                 // Make eye shake due to engine wash
3253                 extern int Wash_on;
3254                 if (Player_obj->type == OBJ_SHIP && (Ships[Player_obj->instance].wash_intensity > 0) && Wash_on ) {
3255                         int r1 = myrand();
3256                         int r2 = myrand();
3257                         tangles.p += 0.07f * Ships[Player_obj->instance].wash_intensity * (float) (r1-MY_RAND_MAX/2)/MY_RAND_MAX;
3258                         tangles.h += 0.07f * Ships[Player_obj->instance].wash_intensity * (float) (r2-MY_RAND_MAX/2)/MY_RAND_MAX;
3259
3260                         // get the   intensity
3261                         float intensity = FF_SCALE * Ships[Player_obj->instance].wash_intensity;
3262
3263                         // vector rand_vec
3264                         vector rand_vec;
3265                         vm_vec_rand_vec_quick(&rand_vec);
3266
3267                         // play the effect
3268                         joy_ff_play_dir_effect(intensity*rand_vec.xyz.x, intensity*rand_vec.xyz.y);
3269                 }
3270
3271         
3272                 // make hud shake due to shuddering
3273                 if(Game_shudder_time != -1){
3274                         // if the timestamp has elapsed
3275                         if(timestamp_elapsed(Game_shudder_time)){
3276                                 Game_shudder_time = -1;
3277                         } 
3278                         // otherwise apply some shudder
3279                         else {
3280                                 int dtime;
3281
3282                                 dtime = timestamp_until(Game_shudder_time);
3283                         
3284                                 int r1 = myrand();
3285                                 int r2 = myrand();
3286                                 tangles.p += (Game_shudder_intensity / 200.0f) * (float) (r1-MY_RAND_MAX/2)/MY_RAND_MAX * (0.5f - fl_abs(0.5f - (float) dtime/(float)Game_shudder_total));
3287                                 tangles.h += (Game_shudder_intensity / 200.0f) * (float) (r2-MY_RAND_MAX/2)/MY_RAND_MAX * (0.5f - fl_abs(0.5f - (float) dtime/(float)Game_shudder_total));
3288                         }
3289                 }
3290
3291                 matrix  tm, tm2;
3292                 vm_angles_2_matrix(&tm, &tangles);
3293                 SDL_assert(vm_vec_mag(&tm.v.fvec) > 0.0f);
3294                 SDL_assert(vm_vec_mag(&tm.v.rvec) > 0.0f);
3295                 SDL_assert(vm_vec_mag(&tm.v.uvec) > 0.0f);
3296                 vm_matrix_x_matrix(&tm2, eye_orient, &tm);
3297                 *eye_orient = tm2;
3298         }
3299 }
3300
3301 extern void compute_slew_matrix(matrix *orient, angles *a);     // TODO: move code to proper place and extern in header file
3302
3303 //      Player's velocity just before he blew up.  Used to keep camera target moving.
3304 vector  Dead_player_last_vel = { { { 1.0f, 1.0f, 1.0f } } };
3305
3306 //      Set eye_pos and eye_orient based on view mode.
3307 void game_render_frame_setup(vector *eye_pos, matrix *eye_orient)
3308 {
3309         vector  eye_dir;
3310
3311         static int last_Viewer_mode = 0;
3312         static int last_Game_mode = 0;
3313         static int last_Viewer_objnum = -1;
3314
3315         // This code is supposed to detect camera "cuts"... like going between
3316         // different views.
3317
3318         // determine if we need to regenerate the nebula
3319         if(     (!(last_Viewer_mode & VM_EXTERNAL) && (Viewer_mode & VM_EXTERNAL)) ||                                                   // internal to external 
3320                         ((last_Viewer_mode & VM_EXTERNAL) && !(Viewer_mode & VM_EXTERNAL)) ||                                                   // external to internal
3321                         (!(last_Viewer_mode & VM_DEAD_VIEW) && (Viewer_mode & VM_DEAD_VIEW)) ||                                                 // non dead-view to dead-view
3322                         ((last_Viewer_mode & VM_DEAD_VIEW) && !(Viewer_mode & VM_DEAD_VIEW)) ||                                                 // dead-view to non dead-view
3323                         (!(last_Viewer_mode & VM_WARP_CHASE) && (Viewer_mode & VM_WARP_CHASE)) ||                                               // non warp-chase to warp-chase
3324                         ((last_Viewer_mode & VM_WARP_CHASE) && !(Viewer_mode & VM_WARP_CHASE)) ||                                               // warp-chase to non warp-chase
3325                         (!(last_Viewer_mode & VM_OTHER_SHIP) && (Viewer_mode & VM_OTHER_SHIP)) ||                                               // non other-ship to other-ship
3326                         ((last_Viewer_mode & VM_OTHER_SHIP) && !(Viewer_mode & VM_OTHER_SHIP)) ||                                               // other-ship to non-other ship
3327                         ((Viewer_mode & VM_OTHER_SHIP) && (last_Viewer_objnum != Player_ai->target_objnum))             // other ship mode, but targets changes
3328                         ) {
3329
3330                 // regenerate the nebula
3331                 neb2_eye_changed();
3332         }               
3333
3334         if ( (last_Viewer_mode != Viewer_mode) || (last_Game_mode != Game_mode) )       {
3335                 //mprintf(( "************** Camera cut! ************\n" ));
3336                 last_Viewer_mode = Viewer_mode;
3337                 last_Game_mode = Game_mode;
3338
3339                 // Camera moved.  Tell stars & debris to not do blurring.
3340                 stars_camera_cut();             
3341         }
3342
3343         say_view_target();
3344
3345         if ( Viewer_mode & VM_PADLOCK_ANY ) {
3346                 player_display_packlock_view();
3347         }
3348         
3349         game_set_view_clip();
3350
3351         if (Game_mode & GM_DEAD) {
3352                 vector  vec_to_deader, view_pos;
3353                 float           dist;
3354
3355                 Viewer_mode |= VM_DEAD_VIEW;
3356
3357                 if (Player_ai->target_objnum != -1) {
3358                         int view_from_player = 1;
3359
3360                         if (Viewer_mode & VM_OTHER_SHIP) {
3361                                 //      View from target.
3362                                 Viewer_obj = &Objects[Player_ai->target_objnum];
3363
3364                                 last_Viewer_objnum = Player_ai->target_objnum;
3365
3366                                 if ( Viewer_obj->type == OBJ_SHIP ) {
3367                                         ship_get_eye( eye_pos, eye_orient, Viewer_obj );
3368                                         view_from_player = 0;
3369                                 }
3370                         } else {
3371                                 last_Viewer_objnum = -1;
3372                         }
3373
3374                         if ( view_from_player ) {
3375                                 //      View target from player ship.
3376                                 Viewer_obj = NULL;
3377                                 *eye_pos = Player_obj->pos;
3378                                 vm_vec_normalized_dir(&eye_dir, &Objects[Player_ai->target_objnum].pos, eye_pos);
3379                                 vm_vector_2_matrix(eye_orient, &eye_dir, NULL, NULL);
3380                         }
3381                 } else {
3382                         dist = vm_vec_normalized_dir(&vec_to_deader, &Player_obj->pos, &Dead_camera_pos);
3383                         
3384                         if (dist < MIN_DIST_TO_DEAD_CAMERA)
3385                                 dist += flFrametime * 16.0f;
3386
3387                         vm_vec_scale(&vec_to_deader, -dist);
3388                         vm_vec_add(&Dead_camera_pos, &Player_obj->pos, &vec_to_deader);
3389                         
3390                         view_pos = Player_obj->pos;
3391
3392                         if (!(Game_mode & GM_DEAD_BLEW_UP)) {
3393                                 Viewer_mode &= ~(VM_EXTERNAL | VM_CHASE);
3394                                 vm_vec_scale_add2(&Dead_camera_pos, &Original_vec_to_deader, 25.0f * flFrametime);
3395                                 Dead_player_last_vel = Player_obj->phys_info.vel;
3396                                 //nprintf(("AI", "Player death roll vel = %7.3f %7.3f %7.3f\n", Player_obj->phys_info.vel.xyz.x, Player_obj->phys_info.vel.xyz.y, Player_obj->phys_info.vel.xyz.z));
3397                         } else if (Player_ai->target_objnum != -1) {
3398                                 view_pos = Objects[Player_ai->target_objnum].pos;
3399                         } else {
3400                                 //      Make camera follow explosion, but gradually slow down.
3401                                 vm_vec_scale_add2(&Player_obj->pos, &Dead_player_last_vel, flFrametime);
3402                                 view_pos = Player_obj->pos;
3403                                 vm_vec_scale(&Dead_player_last_vel, 0.99f);
3404                                 vm_vec_scale_add2(&Dead_camera_pos, &Original_vec_to_deader, SDL_min(25.0f, vm_vec_mag_quick(&Dead_player_last_vel)) * flFrametime);
3405                         }
3406
3407                         *eye_pos = Dead_camera_pos;
3408
3409                         vm_vec_normalized_dir(&eye_dir, &Player_obj->pos, eye_pos);
3410
3411                         vm_vector_2_matrix(eye_orient, &eye_dir, NULL, NULL);
3412                         Viewer_obj = NULL;
3413                 }
3414         } 
3415
3416         // if supernova shockwave
3417         if(supernova_camera_cut()){
3418                 // no viewer obj
3419                 Viewer_obj = NULL;
3420
3421                 // call it dead view
3422                 Viewer_mode |= VM_DEAD_VIEW;
3423
3424                 // set eye pos and orient
3425                 supernova_set_view(eye_pos, eye_orient);
3426         } else {        
3427                 //      If already blown up, these other modes can override.
3428                 if (!(Game_mode & (GM_DEAD | GM_DEAD_BLEW_UP))) {
3429                         Viewer_mode &= ~VM_DEAD_VIEW;
3430
3431                         Viewer_obj = Player_obj;
3432  
3433                         if (Viewer_mode & VM_OTHER_SHIP) {
3434                                 if (Player_ai->target_objnum != -1){
3435                                         Viewer_obj = &Objects[Player_ai->target_objnum];
3436                                         last_Viewer_objnum = Player_ai->target_objnum;
3437                                 } else {
3438                                         Viewer_mode &= ~VM_OTHER_SHIP;
3439                                         last_Viewer_objnum = -1;
3440                                 }
3441                         } else {
3442                                 last_Viewer_objnum = -1;
3443                         }
3444
3445                         if (Viewer_mode & VM_EXTERNAL) {
3446                                 matrix  tm, tm2;
3447
3448                                 vm_angles_2_matrix(&tm2, &Viewer_external_info.angles);
3449                                 vm_matrix_x_matrix(&tm, &Viewer_obj->orient, &tm2);
3450
3451                                 vm_vec_scale_add(eye_pos, &Viewer_obj->pos, &tm.v.fvec, 2.0f * Viewer_obj->radius + Viewer_external_info.distance);
3452
3453                                 vm_vec_sub(&eye_dir, &Viewer_obj->pos, eye_pos);
3454                                 vm_vec_normalize(&eye_dir);
3455                                 vm_vector_2_matrix(eye_orient, &eye_dir, &Viewer_obj->orient.v.uvec, NULL);
3456                                 Viewer_obj = NULL;
3457
3458                                 //      Modify the orientation based on head orientation.
3459                                 compute_slew_matrix(eye_orient, &Viewer_slew_angles);
3460
3461                         } else if ( Viewer_mode & VM_CHASE ) {
3462                                 vector  move_dir;
3463
3464                                 if ( Viewer_obj->phys_info.speed < 0.1 )
3465                                         move_dir = Viewer_obj->orient.v.fvec;
3466                                 else {
3467                                         move_dir = Viewer_obj->phys_info.vel;
3468                                         vm_vec_normalize(&move_dir);
3469                                 }
3470
3471                                 vm_vec_scale_add(eye_pos, &Viewer_obj->pos, &move_dir, -3.0f * Viewer_obj->radius - Viewer_chase_info.distance);
3472                                 vm_vec_scale_add2(eye_pos, &Viewer_obj->orient.v.uvec, 0.75f * Viewer_obj->radius);
3473                                 vm_vec_sub(&eye_dir, &Viewer_obj->pos, eye_pos);
3474                                 vm_vec_normalize(&eye_dir);
3475
3476                                 // JAS: I added the following code because if you slew up using
3477                                 // Descent-style physics, eye_dir and Viewer_obj->orient.v.uvec are
3478                                 // equal, which causes a zero-length vector in the vm_vector_2_matrix
3479                                 // call because the up and the forward vector are the same.   I fixed
3480                                 // it by adding in a fraction of the right vector all the time to the
3481                                 // up vector.
3482                                 vector tmp_up = Viewer_obj->orient.v.uvec;
3483                                 vm_vec_scale_add2( &tmp_up, &Viewer_obj->orient.v.rvec, 0.00001f );
3484
3485                                 vm_vector_2_matrix(eye_orient, &eye_dir, &tmp_up, NULL);
3486                                 Viewer_obj = NULL;
3487
3488                                 //      Modify the orientation based on head orientation.
3489                                 compute_slew_matrix(eye_orient, &Viewer_slew_angles);
3490                         } else if ( Viewer_mode & VM_WARP_CHASE ) {
3491                                         *eye_pos = Camera_pos;
3492
3493                                         ship * shipp = &Ships[Player_obj->instance];
3494
3495                                         vm_vec_sub(&eye_dir, &shipp->warp_effect_pos, eye_pos);
3496                                         vm_vec_normalize(&eye_dir);
3497                                         vm_vector_2_matrix(eye_orient, &eye_dir, &Player_obj->orient.v.uvec, NULL);
3498                                         Viewer_obj = NULL;
3499                         } else {
3500                                 // get an eye position based upon the correct type of object
3501                                 switch(Viewer_obj->type){
3502                                 case OBJ_SHIP:
3503                                         // make a call to get the eye point for the player object
3504                                         ship_get_eye( eye_pos, eye_orient, Viewer_obj );
3505                                         break;
3506                                 case OBJ_OBSERVER:
3507                                         // make a call to get the eye point for the player object
3508                                         observer_get_eye( eye_pos, eye_orient, Viewer_obj );                            
3509                                         break;
3510                                 default :
3511                                         Int3();
3512                                 }
3513
3514                                 #ifdef JOHNS_DEBUG_CODE
3515                                 john_debug_stuff(&eye_pos, &eye_orient);
3516                                 #endif
3517                         }
3518                 }
3519         }
3520
3521         apply_hud_shake(eye_orient);
3522
3523         // setup neb2 rendering
3524         neb2_render_setup(eye_pos, eye_orient);
3525 }
3526
3527 #ifndef NDEBUG
3528 extern void ai_debug_render_stuff();
3529 #endif