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