summaryrefslogtreecommitdiff
path: root/apps/plugins/doom/d_main.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/doom/d_main.c')
-rw-r--r--apps/plugins/doom/d_main.c844
1 files changed, 844 insertions, 0 deletions
diff --git a/apps/plugins/doom/d_main.c b/apps/plugins/doom/d_main.c
new file mode 100644
index 0000000000..d76779cb2b
--- /dev/null
+++ b/apps/plugins/doom/d_main.c
@@ -0,0 +1,844 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
26 *
27 * DESCRIPTION:
28 * DOOM main program (D_DoomMain) and game loop (D_DoomLoop),
29 * plus functions to determine game mode (shareware, registered),
30 * parse command line parameters, configure game parameters (turbo),
31 * and call the startup functions.
32 *
33 *-----------------------------------------------------------------------------
34 */
35
36
37#include "rockmacros.h"
38
39#include "doomdef.h"
40#include "doomtype.h"
41#include "doomstat.h"
42#include "dstrings.h"
43#include "sounds.h"
44#include "z_zone.h"
45#include "w_wad.h"
46#include "s_sound.h"
47#include "v_video.h"
48#include "f_finale.h"
49#include "f_wipe.h"
50#include "m_argv.h"
51#include "m_misc.h"
52#include "m_menu.h"
53#include "i_system.h"
54#include "i_sound.h"
55#include "i_video.h"
56#include "g_game.h"
57#include "hu_stuff.h"
58#include "wi_stuff.h"
59#include "st_stuff.h"
60#include "am_map.h"
61#include "p_setup.h"
62#include "r_draw.h"
63#include "r_main.h"
64#include "d_main.h"
65#include "am_map.h"
66#include "m_swap.h"
67
68// CPhipps - removed wadfiles[] stuff
69
70boolean devparm; // started game with -devparm
71
72// jff 1/24/98 add new versions of these variables to remember command line
73boolean clnomonsters; // checkparm of -nomonsters
74boolean clrespawnparm; // checkparm of -respawn
75boolean clfastparm; // checkparm of -fast
76// jff 1/24/98 end definition of command line version of play mode switches
77
78boolean nomonsters; // working -nomonsters
79boolean respawnparm; // working -respawn
80boolean fastparm; // working -fast
81
82boolean singletics = false; // debug flag to cancel adaptiveness
83
84boolean doomexit;
85
86//jff 1/22/98 parms for disabling music and sound
87boolean nosfxparm;
88boolean nomusicparm;
89
90//jff 4/18/98
91extern boolean inhelpscreens;
92
93skill_t startskill;
94int startepisode;
95int startmap;
96boolean autostart;
97int debugfile;
98int ffmap;
99
100boolean advancedemo;
101
102extern boolean timingdemo, singledemo, demoplayback, fastdemo; // killough
103
104int basetic;
105
106void D_DoAdvanceDemo (void);
107
108/*
109 * D_PostEvent - Event handling
110 *
111 * Called by I/O functions when an event is received.
112 * Try event handlers for each code area in turn.
113 * cph - in the true spirit of the Boom source, let the
114 * short ciruit operator madness begin!
115 */
116
117void D_PostEvent(event_t *ev)
118{
119 /* cph - suppress all input events at game start
120 * FIXME: This is a lousy kludge */
121 if (gametic < 3) return;
122 M_Responder(ev) ||
123 (gamestate == GS_LEVEL && (
124 HU_Responder(ev) ||
125 ST_Responder(ev) ||
126 AM_Responder(ev)
127 )
128 ) ||
129 G_Responder(ev);
130}
131
132//
133// D_Wipe
134//
135// CPhipps - moved the screen wipe code from D_Display to here
136// The screens to wipe between are already stored, this just does the timing
137// and screen updating
138
139static void D_Wipe(void)
140{
141 boolean done;
142 int wipestart = I_GetTime () - 1;
143
144 do
145 {
146 int nowtime, tics;
147 do
148 {
149 //I_uSleep(5000); // CPhipps - don't thrash cpu in this loop
150 nowtime = I_GetTime();
151 tics = nowtime - wipestart;
152 }
153 while (!tics);
154 wipestart = nowtime;
155
156 done = wipe_ScreenWipe(0,0,SCREENWIDTH,SCREENHEIGHT,tics);
157 I_UpdateNoBlit();
158 M_Drawer(); // menu is drawn even on top of wipes
159 I_FinishUpdate(); // page flip or blit buffer
160 }
161 while (!done);
162}
163
164//
165// D_Display
166// draw current display, possibly wiping it from the previous
167//
168
169// wipegamestate can be set to -1 to force a wipe on the next draw
170gamestate_t wipegamestate = GS_DEMOSCREEN;
171extern boolean setsizeneeded;
172extern int showMessages;
173
174void D_Display (void)
175{
176 static boolean isborderstate = false;
177 static boolean borderwillneedredraw = false;
178 static boolean inhelpscreensstate = false;
179 static gamestate_t oldgamestate = -1;
180 boolean wipe;
181 boolean viewactive = false, isborder = false;
182
183 if (nodrawers) // for comparative timing / profiling
184 return;
185
186 // save the current screen if about to wipe
187 if ((wipe = gamestate != wipegamestate))
188 wipe_StartScreen(0, 0, SCREENWIDTH, SCREENHEIGHT);
189
190 if (gamestate != GS_LEVEL) { // Not a level
191 switch (oldgamestate) {
192 case -1:
193 case GS_LEVEL:
194 V_SetPalette(0); // cph - use default (basic) palette
195 default:
196 break;
197 }
198
199 switch (gamestate) {
200 case GS_INTERMISSION:
201 WI_Drawer();
202 break;
203 case GS_FINALE:
204 F_Drawer();
205 break;
206 case GS_DEMOSCREEN:
207 D_PageDrawer();
208 break;
209 default:
210 break;
211 }
212 } else if (gametic != basetic) { // In a level
213 boolean redrawborderstuff;
214
215 HU_Erase();
216
217 if (setsizeneeded) { // change the view size if needed
218 R_ExecuteSetViewSize();
219 oldgamestate = -1; // force background redraw
220 }
221
222 // Work out if the player view is visible, and if there is a border
223 viewactive = (!(automapmode & am_active) || (automapmode & am_overlay)) && !inhelpscreens;
224 isborder = viewactive ? (viewheight != SCREENHEIGHT) : (!inhelpscreens && (automapmode & am_active));
225
226 if (oldgamestate != GS_LEVEL) {
227 R_FillBackScreen (); // draw the pattern into the back screen
228 redrawborderstuff = isborder;
229 } else {
230 // CPhipps -
231 // If there is a border, and either there was no border last time,
232 // or the border might need refreshing, then redraw it.
233 redrawborderstuff = isborder && (!isborderstate || borderwillneedredraw);
234 // The border may need redrawing next time if the border surrounds the screen,
235 // and there is a menu being displayed
236 borderwillneedredraw = menuactive && isborder && viewactive && (viewwidth != SCREENWIDTH);
237 }
238
239 if (redrawborderstuff)
240 R_DrawViewBorder();
241
242 // Now do the drawing
243 if (viewactive)
244 R_RenderPlayerView (&players[displayplayer]);
245 if (automapmode & am_active)
246 AM_Drawer();
247 ST_Drawer((viewheight != SCREENHEIGHT) || ((automapmode & am_active) && !(automapmode & am_overlay)), redrawborderstuff);
248 R_DrawViewBorder();
249
250 HU_Drawer();
251 }
252
253 inhelpscreensstate = inhelpscreens;
254 isborderstate = isborder;
255 oldgamestate = wipegamestate = gamestate;
256
257 // draw pause pic
258 if (paused) {
259 static int x;
260
261 if (!x) { // Cache results of x pos calc
262 int lump = W_GetNumForName("M_PAUSE");
263 const patch_t* p = W_CacheLumpNum(lump);
264 x = (320 - SHORT(p->width))/2;
265 W_UnlockLumpNum(lump);
266 }
267
268 // CPhipps - updated for new patch drawing
269 V_DrawNamePatch(x, (!(automapmode & am_active) || (automapmode & am_overlay))
270 ? 4+(viewwindowy*200/SCREENHEIGHT) : 4, // cph - Must un-stretch viewwindowy
271 0, "M_PAUSE", CR_DEFAULT, VPT_STRETCH);
272 }
273
274 // menus go directly to the screen
275 M_Drawer(); // menu is drawn even on top of everything
276 D_BuildNewTiccmds();
277
278 // normal update
279 if (!wipe)
280 I_FinishUpdate (); // page flip or blit buffer
281 else {
282 // wipe update
283 wipe_EndScreen(0, 0, SCREENWIDTH, SCREENHEIGHT);
284 D_Wipe();
285 }
286}
287
288//
289// D_DoomLoop()
290//
291// Not a globally visible function,
292// just included for source reference,
293// called by D_DoomMain, never exits.
294// Manages timing and IO,
295// calls all ?_Responder, ?_Ticker, and ?_Drawer,
296// calls I_GetTime, I_StartFrame, and I_StartTic
297//
298
299extern boolean demorecording;
300
301static void D_DoomLoop (void)
302{
303 basetic = gametic;
304
305 I_SubmitSound();
306
307 while (!doomexit)
308 {
309 // frame syncronous IO operations
310 //I_StartFrame ();
311
312 // process one or more tics
313 if (singletics)
314 {
315 I_StartTic ();
316 G_BuildTiccmd (&netcmds[consoleplayer][maketic%BACKUPTICS]);
317 if (advancedemo)
318 D_DoAdvanceDemo ();
319 M_Ticker ();
320 G_Ticker ();
321 gametic++;
322 maketic++;
323 }
324 else
325 TryRunTics (); // will run at least one tic
326
327 // killough 3/16/98: change consoleplayer to displayplayer
328 if (players[displayplayer].mo) // cph 2002/08/10
329 S_UpdateSounds(players[displayplayer].mo);// move positional sounds
330
331 // Update display, next frame, with current state.
332 D_Display();
333
334 // Sound mixing for the buffer is snychronous.
335// I_UpdateSound();
336 rb->yield();
337 }
338}
339
340//
341// DEMO LOOP
342//
343
344static int demosequence; // killough 5/2/98: made static
345static int pagetic;
346static const char *pagename; // CPhipps - const
347
348//
349// D_PageTicker
350// Handles timing for warped projection
351//
352void D_PageTicker(void)
353{
354 if (--pagetic < 0)
355 D_AdvanceDemo();
356}
357
358//
359// D_PageDrawer
360//
361void D_PageDrawer(void)
362{
363 // CPhipps - updated for new patch drawing
364 V_DrawNamePatch(0, 0, 0, pagename, CR_DEFAULT, VPT_STRETCH);
365}
366
367//
368// D_AdvanceDemo
369// Called after each demo or intro demosequence finishes
370//
371void D_AdvanceDemo (void)
372{
373 advancedemo = true;
374}
375
376/* killough 11/98: functions to perform demo sequences
377 * cphipps 10/99: constness fixes
378 */
379
380static void D_SetPageName(const char *name)
381{
382 pagename = name;
383}
384
385static void D_DrawTitle1(const char *name)
386{
387 S_StartMusic(mus_intro);
388 pagetic = (TICRATE*170)/35;
389 D_SetPageName(name);
390}
391
392static void D_DrawTitle2(const char *name)
393{
394 S_StartMusic(mus_dm2ttl);
395 D_SetPageName(name);
396}
397
398/* killough 11/98: tabulate demo sequences
399 */
400
401static struct
402{
403 void (*func)(const char *);
404 const char *name;
405} const demostates[][4] =
406 {
407 {
408 {D_DrawTitle1, "TITLEPIC"},
409 {D_DrawTitle1, "TITLEPIC"},
410 {D_DrawTitle2, "TITLEPIC"},
411 {D_DrawTitle1, "TITLEPIC"},
412 },
413
414 {
415 {G_DeferedPlayDemo, "demo1"},
416 {G_DeferedPlayDemo, "demo1"},
417 {G_DeferedPlayDemo, "demo1"},
418 {G_DeferedPlayDemo, "demo1"},
419 },
420 {
421 {D_SetPageName, "CREDIT"},
422 {D_SetPageName, "CREDIT"},
423 {D_SetPageName, "CREDIT"},
424 {D_SetPageName, "CREDIT"},
425 },
426
427 {
428 {G_DeferedPlayDemo, "demo2"},
429 {G_DeferedPlayDemo, "demo2"},
430 {G_DeferedPlayDemo, "demo2"},
431 {G_DeferedPlayDemo, "demo2"},
432 },
433
434 {
435 {D_SetPageName, "HELP2"},
436 {D_SetPageName, "HELP2"},
437 {D_SetPageName, "CREDIT"},
438 {D_DrawTitle1, "TITLEPIC"},
439 },
440
441 {
442 {G_DeferedPlayDemo, "demo3"},
443 {G_DeferedPlayDemo, "demo3"},
444 {G_DeferedPlayDemo, "demo3"},
445 {G_DeferedPlayDemo, "demo3"},
446 },
447
448 {
449 {NULL,0},
450 {NULL,0},
451 {NULL,0},
452 {D_SetPageName, "CREDIT"},
453 },
454
455 {
456 {NULL,0},
457 {NULL,0},
458 {NULL,0},
459 {G_DeferedPlayDemo, "demo4"},
460 },
461
462 {
463 {NULL,0},
464 {NULL,0},
465 {NULL,0},
466 {NULL,0},
467 }
468 };
469
470/*
471 * This cycles through the demo sequences.
472 * killough 11/98: made table-driven
473 */
474
475void D_DoAdvanceDemo(void)
476{
477 players[consoleplayer].playerstate = PST_LIVE; /* not reborn */
478 advancedemo = usergame = paused = false;
479 gameaction = ga_nothing;
480
481 pagetic = TICRATE * 11; /* killough 11/98: default behavior */
482 gamestate = GS_DEMOSCREEN;
483
484 if (netgame && !demoplayback) {
485 demosequence = 0;
486 } else
487 if (!demostates[++demosequence][gamemode].func)
488 demosequence = 0;
489 demostates[demosequence][gamemode].func(demostates[demosequence][gamemode].name);
490}
491
492//
493// D_StartTitle
494//
495void D_StartTitle (void)
496{
497 gameaction = ga_nothing;
498 demosequence = -1;
499 D_AdvanceDemo();
500}
501
502//
503// D_AddFile
504//
505// Rewritten by Lee Killough
506//
507// Ty 08/29/98 - add source parm to indicate where this came from
508// CPhipps - static, const char* parameter
509// - source is an enum
510// - modified to allocate & use new wadfiles array
511void D_AddFile (const char *file, wad_source_t source)
512{
513 wadfiles = realloc(wadfiles, sizeof(*wadfiles)*(numwadfiles+1));
514 wadfiles[numwadfiles].name =
515 AddDefaultExtension(strcpy(malloc(strlen(file)+5), file), ".wad");
516 wadfiles[numwadfiles].src = source; // Ty 08/29/98
517 numwadfiles++;
518}
519
520//
521// CheckIWAD
522//
523// Verify a file is indeed tagged as an IWAD
524// Scan its lumps for levelnames and return gamemode as indicated
525// Detect missing wolf levels in DOOM II
526//
527// The filename to check is passed in iwadname, the gamemode detected is
528// returned in gmode, hassec returns the presence of secret levels
529//
530// jff 4/19/98 Add routine to test IWAD for validity and determine
531// the gamemode from it. Also note if DOOM II, whether secret levels exist
532// CPhipps - const char* for iwadname, made static
533#if 0
534static void CheckIWAD(const char *iwadname,GameMode_t *gmode,boolean *hassec)
535{
536 if ( !fileexists (iwadname) )
537 {
538 int ud=0,rg=0,sw=0,cm=0,sc=0;
539 int handle;
540
541 // Identify IWAD correctly
542 if ( (handle = open (iwadname,O_RDONLY)) != -1)
543 {
544 wadinfo_t header;
545
546 // read IWAD header
547 read (handle, &header, sizeof(header));
548 if (!strncmp(header.identification,"IWAD",4))
549 {
550 size_t length;
551 filelump_t *fileinfo;
552
553 // read IWAD directory
554 header.numlumps = LONG(header.numlumps);
555 header.infotableofs = LONG(header.infotableofs);
556 length = header.numlumps;
557 fileinfo = malloc(length*sizeof(filelump_t));
558 lseek (handle, header.infotableofs, SEEK_SET);
559 read (handle, fileinfo, length*sizeof(filelump_t));
560 close(handle);
561
562 // scan directory for levelname lumps
563 while (length--)
564 if (fileinfo[length].name[0] == 'E' &&
565 fileinfo[length].name[2] == 'M' &&
566 fileinfo[length].name[4] == 0)
567 {
568 if (fileinfo[length].name[1] == '4')
569 ++ud;
570 else if (fileinfo[length].name[1] == '3')
571 ++rg;
572 else if (fileinfo[length].name[1] == '2')
573 ++rg;
574 else if (fileinfo[length].name[1] == '1')
575 ++sw;
576 }
577 else if (fileinfo[length].name[0] == 'M' &&
578 fileinfo[length].name[1] == 'A' &&
579 fileinfo[length].name[2] == 'P' &&
580 fileinfo[length].name[5] == 0)
581 {
582 ++cm;
583 if (fileinfo[length].name[3] == '3')
584 if (fileinfo[length].name[4] == '1' ||
585 fileinfo[length].name[4] == '2')
586 ++sc;
587 }
588
589 free(fileinfo);
590 }
591 else // missing IWAD tag in header
592 I_Error("CheckIWAD: IWAD tag %s not present", iwadname);
593 }
594 else // error from open call
595 I_Error("CheckIWAD: Can't open IWAD %s", iwadname);
596
597 // Determine game mode from levels present
598 // Must be a full set for whichever mode is present
599 // Lack of wolf-3d levels also detected here
600
601 *gmode = indetermined;
602 *hassec = false;
603 if (cm>=30)
604 {
605 *gmode = commercial;
606 *hassec = sc>=2;
607 }
608 else if (ud>=9)
609 *gmode = retail;
610 else if (rg>=18)
611 *gmode = registered;
612 else if (sw>=9)
613 *gmode = shareware;
614 }
615 else // error from access call
616 I_Error("CheckIWAD: IWAD %s not readable", iwadname);
617}
618#endif
619void D_DoomMainSetup(void)
620{
621 int p;
622
623 nomonsters = M_CheckParm ("-nomonsters");
624 respawnparm = M_CheckParm ("-respawn");
625 fastparm = M_CheckParm ("-fast");
626 devparm = M_CheckParm ("-devparm");
627 if (M_CheckParm ("-altdeath"))
628 deathmatch = 2;
629 else if (M_CheckParm ("-deathmatch"))
630 deathmatch = 1;
631
632 printf("Welcome to Rockdoom");
633
634 switch ( gamemode )
635 {
636 case retail:
637 printf ("The Ultimate DOOM Startup v%d.%d",DVERSION/100,DVERSION%100);
638 break;
639 case shareware:
640 printf ("DOOM Shareware Startup v%d.%d",DVERSION/100,DVERSION%100);
641 break;
642 case registered:
643 printf ("DOOM Registered Startup v%d.%d",DVERSION/100,DVERSION%100);
644 break;
645 case commercial:
646 switch (gamemission)
647 {
648 case pack_plut:
649 printf ("DOOM 2: Plutonia Experiment v%d.%d",DVERSION/100,DVERSION%100);
650 break;
651 case pack_tnt:
652 printf ("DOOM 2: TNT - Evilution v%d.%d",DVERSION/100,DVERSION%100);
653 break;
654 default:
655 printf ("DOOM 2: Hell on Earth v%d.%d",DVERSION/100,DVERSION%100);
656 break;
657 }
658 break;
659 default:
660 printf ("Public DOOM v%d.%d",DVERSION/100,DVERSION%100);
661 break;
662 }
663
664 if (devparm)
665 printf(D_DEVSTR);
666
667 // turbo option
668 if ((p=M_CheckParm ("-turbo")))
669 {
670 int scale = 200;
671 extern int forwardmove[2];
672 extern int sidemove[2];
673
674 if (p<myargc-1)
675 scale = atoi (myargv[p+1]);
676 if (scale < 10)
677 scale = 10;
678 if (scale > 400)
679 scale = 400;
680 printf ("turbo scale: %d%%\n",scale);
681 forwardmove[0] = forwardmove[0]*scale/100;
682 forwardmove[1] = forwardmove[1]*scale/100;
683 sidemove[0] = sidemove[0]*scale/100;
684 sidemove[1] = sidemove[1]*scale/100;
685 }
686
687 // get skill / episode / map from parms
688 startskill = sk_medium;
689 startepisode = 1;
690 startmap = 1;
691 autostart = false;
692
693 p = M_CheckParm ("-skill");
694 if (p && p < myargc-1)
695 {
696 startskill = myargv[p+1][0]-'1';
697 autostart = true;
698 }
699
700 p = M_CheckParm ("-episode");
701 if (p && p < myargc-1)
702 {
703 startepisode = myargv[p+1][0]-'0';
704 startmap = 1;
705 autostart = true;
706 }
707
708 p = M_CheckParm ("-warp");
709 if (p && p < myargc-1)
710 {
711 if (gamemode == commercial)
712 startmap = atoi (myargv[p+1]);
713 else
714 {
715 startepisode = myargv[p+1][0]-'0';
716 startmap = myargv[p+2][0]-'0';
717 }
718 autostart = true;
719 }
720
721 // CPhipps - move up netgame init
722 printf("D_InitNetGame: Checking for network game.\n");
723 D_InitNetGame();
724
725 // init subsystems
726 printf ("V_Init: allocate screens.\n");
727 V_Init ();
728
729 printf ("W_Init: Init WADfiles.\n");
730 W_Init();
731
732 V_InitColorTranslation(); //jff 4/24/98 load color translation lumps
733
734 // Check for -file in shareware
735 if (modifiedgame)
736 {
737 // These are the lumps that will be checked in IWAD,
738 // if any one is not present, execution will be aborted.
739 char name[23][8]=
740 {
741 "e2m1","e2m2","e2m3","e2m4","e2m5","e2m6","e2m7","e2m8","e2m9",
742 "e3m1","e3m3","e3m3","e3m4","e3m5","e3m6","e3m7","e3m8","e3m9",
743 "dphoof","bfgga0","heada1","cybra1","spida1d1"
744 };
745 int i;
746
747 if ( gamemode == shareware)
748 I_Error("\nYou cannot -file with the shareware version. Register!");
749
750 // Check for fake IWAD with right name,
751 // but w/o all the lumps of the registered version.
752 if (gamemode == registered)
753 for (i = 0;i < 23; i++)
754 if (W_CheckNumForName(name[i])<0)
755 I_Error("\nThis is not the registered version.");
756 }
757
758 // Iff additonal PWAD files are used, print modified banner
759 if (modifiedgame)
760 printf ("ATTENTION: This version of DOOM has been modified.\n");
761
762 // Check and print which version is executed.
763 switch ( gamemode )
764 {
765 case shareware:
766 case indetermined:
767 printf ("Shareware!\n");
768 break;
769 case registered:
770 case retail:
771 case commercial:
772 printf ("Commercial product - do not distribute!\n");
773 break;
774 default:
775 // Ouch.
776 break;
777 }
778
779 printf ("M_Init: Init miscellaneous info.\n");
780 M_Init ();
781
782 printf ("R_Init: Init DOOM refresh daemon - ");
783 R_Init ();
784
785 printf ("P_Init: Init Playloop state.\n");
786 P_Init ();
787
788 printf ("I_Init: Setting up machine state.\n");
789 I_Init ();
790
791 printf ("S_Init: Setting up sound.\n");
792 S_Init (snd_SfxVolume /* *8 */, snd_MusicVolume /* *8*/ );
793
794 printf ("HU_Init: Setting up heads up display.\n");
795 HU_Init ();
796
797 I_InitGraphics ();
798
799 printf ("ST_Init: Init status bar.\n");
800 ST_Init ();
801
802 // check for a driver that wants intermission stats
803 p = M_CheckParm ("-statcopy");
804 if (p && p<myargc-1)
805 {
806 // for statistics driver
807 extern void* statcopy;
808
809 statcopy = (void*)atoi(myargv[p+1]);
810 printf ("External statistics registered.\n");
811 }
812
813 // start the apropriate game based on parms
814 p = M_CheckParm ("-record");
815 if (p && p < myargc-1)
816 {
817 G_RecordDemo (myargv[p+1]);
818 autostart = true;
819 }
820
821 p = M_CheckParm ("-loadgame");
822 if (p && p < myargc-1)
823 G_LoadGame (atoi(myargv[p+1]), false);
824
825 if ( gameaction != ga_loadgame )
826 {
827 if (!singledemo) { /* killough 12/98 */
828 if (autostart || netgame)
829 G_InitNew (startskill, startepisode, startmap);
830 else
831 D_StartTitle (); // start up intro loop
832 }
833 }
834}
835
836//
837// D_DoomMain
838//
839void D_DoomMain (void)
840{
841 D_DoomMainSetup(); // get this crap off the stack
842
843 D_DoomLoop (); // never returns
844}