aboutsummaryrefslogtreecommitdiff
path: root/src/d_main.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/d_main.c')
-rw-r--r--src/d_main.c1725
1 files changed, 1725 insertions, 0 deletions
diff --git a/src/d_main.c b/src/d_main.c
new file mode 100644
index 0000000..6d8493e
--- /dev/null
+++ b/src/d_main.c
@@ -0,0 +1,1725 @@
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-2004 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 * Copyright 2005, 2006 by
12 * Florian Schulze, Colin Phipps, Neil Stevens, Andrey Budko
13 *
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
18 *
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
27 * 02111-1307, USA.
28 *
29 * DESCRIPTION:
30 * DOOM main program (D_DoomMain) and game loop (D_DoomLoop),
31 * plus functions to determine game mode (shareware, registered),
32 * parse command line parameters, configure game parameters (turbo),
33 * and call the startup functions.
34 *
35 *-----------------------------------------------------------------------------
36 */
37
38
39#ifdef _MSC_VER
40#define F_OK 0 /* Check for file existence */
41#define W_OK 2 /* Check for write permission */
42#define R_OK 4 /* Check for read permission */
43#include <io.h>
44#include <direct.h>
45#else
46#include <unistd.h>
47#endif
48#include <sys/types.h>
49#include <sys/stat.h>
50#include <fcntl.h>
51
52#include "doomdef.h"
53#include "doomtype.h"
54#include "doomstat.h"
55#include "d_net.h"
56#include "dstrings.h"
57#include "sounds.h"
58#include "z_zone.h"
59#include "w_wad.h"
60#include "s_sound.h"
61#include "v_video.h"
62#include "f_finale.h"
63#include "f_wipe.h"
64#include "m_argv.h"
65#include "m_misc.h"
66#include "m_menu.h"
67#include "p_checksum.h"
68#include "i_main.h"
69#include "i_system.h"
70#include "i_sound.h"
71#include "i_video.h"
72#include "g_game.h"
73#include "hu_stuff.h"
74#include "wi_stuff.h"
75#include "st_stuff.h"
76#include "am_map.h"
77#include "p_setup.h"
78#include "r_draw.h"
79#include "r_main.h"
80#include "r_fps.h"
81#include "d_main.h"
82#include "d_deh.h" // Ty 04/08/98 - Externalizations
83#include "lprintf.h" // jff 08/03/98 - declaration of lprintf
84#include "am_map.h"
85
86void GetFirstMap(int *ep, int *map); // Ty 08/29/98 - add "-warp x" functionality
87static void D_PageDrawer(void);
88
89// CPhipps - removed wadfiles[] stuff
90
91boolean devparm; // started game with -devparm
92
93// jff 1/24/98 add new versions of these variables to remember command line
94boolean clnomonsters; // checkparm of -nomonsters
95boolean clrespawnparm; // checkparm of -respawn
96boolean clfastparm; // checkparm of -fast
97// jff 1/24/98 end definition of command line version of play mode switches
98
99boolean nomonsters; // working -nomonsters
100boolean respawnparm; // working -respawn
101boolean fastparm; // working -fast
102
103boolean singletics = false; // debug flag to cancel adaptiveness
104
105//jff 1/22/98 parms for disabling music and sound
106boolean nosfxparm;
107boolean nomusicparm;
108
109//jff 4/18/98
110extern boolean inhelpscreens;
111
112skill_t startskill;
113int startepisode;
114int startmap;
115boolean autostart;
116FILE *debugfile;
117int ffmap;
118
119boolean advancedemo;
120
121char wadfile[PATH_MAX+1]; // primary wad file
122char mapdir[PATH_MAX+1]; // directory of development maps
123char baseiwad[PATH_MAX+1]; // jff 3/23/98: iwad directory
124char basesavegame[PATH_MAX+1]; // killough 2/16/98: savegame directory
125
126//jff 4/19/98 list of standard IWAD names
127const char *const standard_iwads[]=
128{
129 "doom2f.wad",
130 "doom2.wad",
131 "plutonia.wad",
132 "tnt.wad",
133 "doom.wad",
134 "doom1.wad",
135 "doomu.wad", /* CPhipps - alow doomu.wad */
136 "freedoom.wad", /* wart@kobold.org: added freedoom for Fedora Extras */
137};
138static const int nstandard_iwads = sizeof standard_iwads/sizeof*standard_iwads;
139
140/*
141 * D_PostEvent - Event handling
142 *
143 * Called by I/O functions when an event is received.
144 * Try event handlers for each code area in turn.
145 * cph - in the true spirit of the Boom source, let the
146 * short ciruit operator madness begin!
147 */
148
149void D_PostEvent(event_t *ev)
150{
151 /* cph - suppress all input events at game start
152 * FIXME: This is a lousy kludge */
153 if (gametic < 3) return;
154 M_Responder(ev) ||
155 (gamestate == GS_LEVEL && (
156 HU_Responder(ev) ||
157 ST_Responder(ev) ||
158 AM_Responder(ev)
159 )
160 ) ||
161 G_Responder(ev);
162}
163
164//
165// D_Wipe
166//
167// CPhipps - moved the screen wipe code from D_Display to here
168// The screens to wipe between are already stored, this just does the timing
169// and screen updating
170
171static void D_Wipe(void)
172{
173 boolean done;
174 int wipestart = I_GetTime () - 1;
175
176 do
177 {
178 int nowtime, tics;
179 do
180 {
181 I_uSleep(5000); // CPhipps - don't thrash cpu in this loop
182 nowtime = I_GetTime();
183 tics = nowtime - wipestart;
184 }
185 while (!tics);
186 wipestart = nowtime;
187 done = wipe_ScreenWipe(tics);
188 I_UpdateNoBlit();
189 M_Drawer(); // menu is drawn even on top of wipes
190 I_FinishUpdate(); // page flip or blit buffer
191 }
192 while (!done);
193}
194
195//
196// D_Display
197// draw current display, possibly wiping it from the previous
198//
199
200// wipegamestate can be set to -1 to force a wipe on the next draw
201gamestate_t wipegamestate = GS_DEMOSCREEN;
202extern boolean setsizeneeded;
203extern int showMessages;
204
205void D_Display (void)
206{
207 static boolean inhelpscreensstate = false;
208 static boolean isborderstate = false;
209 static boolean borderwillneedredraw = false;
210 static gamestate_t oldgamestate = -1;
211 boolean wipe;
212 boolean viewactive = false, isborder = false;
213
214 if (nodrawers) // for comparative timing / profiling
215 return;
216
217 if (!I_StartDisplay())
218 return;
219
220 // save the current screen if about to wipe
221 if ((wipe = gamestate != wipegamestate) && (V_GetMode() != VID_MODEGL))
222 wipe_StartScreen();
223
224 if (gamestate != GS_LEVEL) { // Not a level
225 switch (oldgamestate) {
226 case -1:
227 case GS_LEVEL:
228 V_SetPalette(0); // cph - use default (basic) palette
229 default:
230 break;
231 }
232
233 switch (gamestate) {
234 case GS_INTERMISSION:
235 WI_Drawer();
236 break;
237 case GS_FINALE:
238 F_Drawer();
239 break;
240 case GS_DEMOSCREEN:
241 D_PageDrawer();
242 break;
243 default:
244 break;
245 }
246 } else if (gametic != basetic) { // In a level
247 boolean redrawborderstuff;
248
249 HU_Erase();
250
251 if (setsizeneeded) { // change the view size if needed
252 R_ExecuteSetViewSize();
253 oldgamestate = -1; // force background redraw
254 }
255
256 // Work out if the player view is visible, and if there is a border
257 viewactive = (!(automapmode & am_active) || (automapmode & am_overlay)) && !inhelpscreens;
258 isborder = viewactive ? (viewheight != SCREENHEIGHT) : (!inhelpscreens && (automapmode & am_active));
259
260 if (oldgamestate != GS_LEVEL) {
261 R_FillBackScreen (); // draw the pattern into the back screen
262 redrawborderstuff = isborder;
263 } else {
264 // CPhipps -
265 // If there is a border, and either there was no border last time,
266 // or the border might need refreshing, then redraw it.
267 redrawborderstuff = isborder && (!isborderstate || borderwillneedredraw);
268 // The border may need redrawing next time if the border surrounds the screen,
269 // and there is a menu being displayed
270 borderwillneedredraw = menuactive && isborder && viewactive && (viewwidth != SCREENWIDTH);
271 }
272 if (redrawborderstuff || (V_GetMode() == VID_MODEGL))
273 R_DrawViewBorder();
274
275 // Now do the drawing
276 if (viewactive)
277 R_RenderPlayerView (&players[displayplayer]);
278 if (automapmode & am_active)
279 AM_Drawer();
280 ST_Drawer((viewheight != SCREENHEIGHT) || ((automapmode & am_active) && !(automapmode & am_overlay)), redrawborderstuff);
281 if (V_GetMode() != VID_MODEGL)
282 R_DrawViewBorder();
283 HU_Drawer();
284 }
285
286 inhelpscreensstate = inhelpscreens;
287 isborderstate = isborder;
288 oldgamestate = wipegamestate = gamestate;
289
290 // draw pause pic
291 if (paused) {
292 // Simplified the "logic" here and no need for x-coord caching - POPE
293 V_DrawNamePatch((320 - V_NamePatchWidth("M_PAUSE"))/2, 4,
294 0, "M_PAUSE", CR_DEFAULT, VPT_STRETCH);
295 }
296
297 // menus go directly to the screen
298 M_Drawer(); // menu is drawn even on top of everything
299#ifdef HAVE_NET
300 NetUpdate(); // send out any new accumulation
301#else
302 D_BuildNewTiccmds();
303#endif
304
305 // normal update
306 if (!wipe || (V_GetMode() == VID_MODEGL))
307 I_FinishUpdate (); // page flip or blit buffer
308 else {
309 // wipe update
310 wipe_EndScreen();
311 D_Wipe();
312 }
313
314 I_EndDisplay();
315
316 //e6y: don't thrash cpu during pausing
317 if (paused) {
318 I_uSleep(1000);
319 }
320}
321
322// CPhipps - Auto screenshot Variables
323
324static int auto_shot_count, auto_shot_time;
325static const char *auto_shot_fname;
326
327//
328// D_DoomLoop()
329//
330// Not a globally visible function,
331// just included for source reference,
332// called by D_DoomMain, never exits.
333// Manages timing and IO,
334// calls all ?_Responder, ?_Ticker, and ?_Drawer,
335// calls I_GetTime, I_StartFrame, and I_StartTic
336//
337
338static void D_DoomLoop(void)
339{
340 for (;;)
341 {
342 WasRenderedInTryRunTics = false;
343 // frame syncronous IO operations
344 I_StartFrame ();
345
346 if (ffmap == gamemap) ffmap = 0;
347
348 // process one or more tics
349 if (singletics)
350 {
351 I_StartTic ();
352 G_BuildTiccmd (&netcmds[consoleplayer][maketic%BACKUPTICS]);
353 if (advancedemo)
354 D_DoAdvanceDemo ();
355 M_Ticker ();
356 G_Ticker ();
357 P_Checksum(gametic);
358 gametic++;
359 maketic++;
360 }
361 else
362 TryRunTics (); // will run at least one tic
363
364 // killough 3/16/98: change consoleplayer to displayplayer
365 if (players[displayplayer].mo) // cph 2002/08/10
366 S_UpdateSounds(players[displayplayer].mo);// move positional sounds
367
368 if (V_GetMode() == VID_MODEGL ?
369 !movement_smooth || !WasRenderedInTryRunTics :
370 !movement_smooth || !WasRenderedInTryRunTics || gamestate != wipegamestate
371 )
372 {
373 // Update display, next frame, with current state.
374 D_Display();
375 }
376
377 // CPhipps - auto screenshot
378 if (auto_shot_fname && !--auto_shot_count) {
379 auto_shot_count = auto_shot_time;
380 M_DoScreenShot(auto_shot_fname);
381 }
382 }
383}
384
385//
386// DEMO LOOP
387//
388
389static int demosequence; // killough 5/2/98: made static
390static int pagetic;
391static const char *pagename; // CPhipps - const
392
393//
394// D_PageTicker
395// Handles timing for warped projection
396//
397void D_PageTicker(void)
398{
399 if (--pagetic < 0)
400 D_AdvanceDemo();
401}
402
403//
404// D_PageDrawer
405//
406static void D_PageDrawer(void)
407{
408 // proff/nicolas 09/14/98 -- now stretchs bitmaps to fullscreen!
409 // CPhipps - updated for new patch drawing
410 // proff - added M_DrawCredits
411 if (pagename)
412 {
413 V_DrawNamePatch(0, 0, 0, pagename, CR_DEFAULT, VPT_STRETCH);
414 }
415 else
416 M_DrawCredits();
417}
418
419//
420// D_AdvanceDemo
421// Called after each demo or intro demosequence finishes
422//
423void D_AdvanceDemo (void)
424{
425 advancedemo = true;
426}
427
428/* killough 11/98: functions to perform demo sequences
429 * cphipps 10/99: constness fixes
430 */
431
432static void D_SetPageName(const char *name)
433{
434 pagename = name;
435}
436
437static void D_DrawTitle1(const char *name)
438{
439 S_StartMusic(mus_intro);
440 pagetic = (TICRATE*170)/35;
441 D_SetPageName(name);
442}
443
444static void D_DrawTitle2(const char *name)
445{
446 S_StartMusic(mus_dm2ttl);
447 D_SetPageName(name);
448}
449
450/* killough 11/98: tabulate demo sequences
451 */
452
453static struct
454{
455 void (*func)(const char *);
456 const char *name;
457} const demostates[][4] =
458 {
459 {
460 {D_DrawTitle1, "TITLEPIC"},
461 {D_DrawTitle1, "TITLEPIC"},
462 {D_DrawTitle2, "TITLEPIC"},
463 {D_DrawTitle1, "TITLEPIC"},
464 },
465
466 {
467 {G_DeferedPlayDemo, "demo1"},
468 {G_DeferedPlayDemo, "demo1"},
469 {G_DeferedPlayDemo, "demo1"},
470 {G_DeferedPlayDemo, "demo1"},
471 },
472 {
473 {D_SetPageName, NULL},
474 {D_SetPageName, NULL},
475 {D_SetPageName, NULL},
476 {D_SetPageName, NULL},
477 },
478
479 {
480 {G_DeferedPlayDemo, "demo2"},
481 {G_DeferedPlayDemo, "demo2"},
482 {G_DeferedPlayDemo, "demo2"},
483 {G_DeferedPlayDemo, "demo2"},
484 },
485
486 {
487 {D_SetPageName, "HELP2"},
488 {D_SetPageName, "HELP2"},
489 {D_SetPageName, "CREDIT"},
490 {D_DrawTitle1, "TITLEPIC"},
491 },
492
493 {
494 {G_DeferedPlayDemo, "demo3"},
495 {G_DeferedPlayDemo, "demo3"},
496 {G_DeferedPlayDemo, "demo3"},
497 {G_DeferedPlayDemo, "demo3"},
498 },
499
500 {
501 {NULL},
502 {NULL},
503 {NULL},
504 {D_SetPageName, "CREDIT"},
505 },
506
507 {
508 {NULL},
509 {NULL},
510 {NULL},
511 {G_DeferedPlayDemo, "demo4"},
512 },
513
514 {
515 {NULL},
516 {NULL},
517 {NULL},
518 {NULL},
519 }
520 };
521
522/*
523 * This cycles through the demo sequences.
524 * killough 11/98: made table-driven
525 */
526
527void D_DoAdvanceDemo(void)
528{
529 players[consoleplayer].playerstate = PST_LIVE; /* not reborn */
530 advancedemo = usergame = paused = false;
531 gameaction = ga_nothing;
532
533 pagetic = TICRATE * 11; /* killough 11/98: default behavior */
534 gamestate = GS_DEMOSCREEN;
535
536 if (netgame && !demoplayback) {
537 demosequence = 0;
538 } else
539 if (!demostates[++demosequence][gamemode].func)
540 demosequence = 0;
541 demostates[demosequence][gamemode].func
542 (demostates[demosequence][gamemode].name);
543}
544
545//
546// D_StartTitle
547//
548void D_StartTitle (void)
549{
550 gameaction = ga_nothing;
551 demosequence = -1;
552 D_AdvanceDemo();
553}
554
555//
556// D_AddFile
557//
558// Rewritten by Lee Killough
559//
560// Ty 08/29/98 - add source parm to indicate where this came from
561// CPhipps - static, const char* parameter
562// - source is an enum
563// - modified to allocate & use new wadfiles array
564void D_AddFile (const char *file, wad_source_t source)
565{
566 char *gwa_filename=NULL;
567
568 wadfiles = realloc(wadfiles, sizeof(*wadfiles)*(numwadfiles+1));
569 wadfiles[numwadfiles].name =
570 AddDefaultExtension(strcpy(malloc(strlen(file)+5), file), ".wad");
571 wadfiles[numwadfiles].src = source; // Ty 08/29/98
572 numwadfiles++;
573 // proff: automatically try to add the gwa files
574 // proff - moved from w_wad.c
575 gwa_filename=AddDefaultExtension(strcpy(malloc(strlen(file)+5), file), ".wad");
576 if (strlen(gwa_filename)>4)
577 if (!strcasecmp(gwa_filename+(strlen(gwa_filename)-4),".wad"))
578 {
579 char *ext;
580 ext = &gwa_filename[strlen(gwa_filename)-4];
581 ext[1] = 'g'; ext[2] = 'w'; ext[3] = 'a';
582 wadfiles = realloc(wadfiles, sizeof(*wadfiles)*(numwadfiles+1));
583 wadfiles[numwadfiles].name = gwa_filename;
584 wadfiles[numwadfiles].src = source; // Ty 08/29/98
585 numwadfiles++;
586 }
587}
588
589// killough 10/98: support -dehout filename
590// cph - made const, don't cache results
591static const char *D_dehout(void)
592{
593 int p = M_CheckParm("-dehout");
594 if (!p)
595 p = M_CheckParm("-bexout");
596 return (p && ++p < myargc ? myargv[p] : NULL);
597}
598
599//
600// CheckIWAD
601//
602// Verify a file is indeed tagged as an IWAD
603// Scan its lumps for levelnames and return gamemode as indicated
604// Detect missing wolf levels in DOOM II
605//
606// The filename to check is passed in iwadname, the gamemode detected is
607// returned in gmode, hassec returns the presence of secret levels
608//
609// jff 4/19/98 Add routine to test IWAD for validity and determine
610// the gamemode from it. Also note if DOOM II, whether secret levels exist
611// CPhipps - const char* for iwadname, made static
612static void CheckIWAD(const char *iwadname,GameMode_t *gmode,boolean *hassec)
613{
614 if ( !access (iwadname,R_OK) )
615 {
616 int ud=0,rg=0,sw=0,cm=0,sc=0;
617 FILE* fp;
618
619 // Identify IWAD correctly
620 if ((fp = fopen(iwadname, "rb")))
621 {
622 wadinfo_t header;
623
624 // read IWAD header
625 if (fread(&header, sizeof(header), 1, fp) == 1 && !strncmp(header.identification, "IWAD", 4))
626 {
627 size_t length;
628 filelump_t *fileinfo;
629
630 // read IWAD directory
631 header.numlumps = LONG(header.numlumps);
632 header.infotableofs = LONG(header.infotableofs);
633 length = header.numlumps;
634 fileinfo = malloc(length*sizeof(filelump_t));
635 if (fseek (fp, header.infotableofs, SEEK_SET) ||
636 fread (fileinfo, sizeof(filelump_t), length, fp) != length ||
637 fclose(fp))
638 I_Error("CheckIWAD: failed to read directory %s",iwadname);
639
640 // scan directory for levelname lumps
641 while (length--)
642 if (fileinfo[length].name[0] == 'E' &&
643 fileinfo[length].name[2] == 'M' &&
644 fileinfo[length].name[4] == 0)
645 {
646 if (fileinfo[length].name[1] == '4')
647 ++ud;
648 else if (fileinfo[length].name[1] == '3')
649 ++rg;
650 else if (fileinfo[length].name[1] == '2')
651 ++rg;
652 else if (fileinfo[length].name[1] == '1')
653 ++sw;
654 }
655 else if (fileinfo[length].name[0] == 'M' &&
656 fileinfo[length].name[1] == 'A' &&
657 fileinfo[length].name[2] == 'P' &&
658 fileinfo[length].name[5] == 0)
659 {
660 ++cm;
661 if (fileinfo[length].name[3] == '3')
662 if (fileinfo[length].name[4] == '1' ||
663 fileinfo[length].name[4] == '2')
664 ++sc;
665 }
666
667 free(fileinfo);
668 }
669 else // missing IWAD tag in header
670 I_Error("CheckIWAD: IWAD tag %s not present", iwadname);
671 }
672 else // error from open call
673 I_Error("CheckIWAD: Can't open IWAD %s", iwadname);
674
675 // Determine game mode from levels present
676 // Must be a full set for whichever mode is present
677 // Lack of wolf-3d levels also detected here
678
679 *gmode = indetermined;
680 *hassec = false;
681 if (cm>=30)
682 {
683 *gmode = commercial;
684 *hassec = sc>=2;
685 }
686 else if (ud>=9)
687 *gmode = retail;
688 else if (rg>=18)
689 *gmode = registered;
690 else if (sw>=9)
691 *gmode = shareware;
692 }
693 else // error from access call
694 I_Error("CheckIWAD: IWAD %s not readable", iwadname);
695}
696
697
698
699// NormalizeSlashes
700//
701// Remove trailing slashes, translate backslashes to slashes
702// The string to normalize is passed and returned in str
703//
704// jff 4/19/98 Make killoughs slash fixer a subroutine
705//
706static void NormalizeSlashes(char *str)
707{
708 int l;
709
710 // killough 1/18/98: Neater / \ handling.
711 // Remove trailing / or \ to prevent // /\ \/ \\, and change \ to /
712
713 if (!str || !(l = strlen(str)))
714 return;
715 if (str[--l]=='/' || str[l]=='\\') // killough 1/18/98
716 str[l]=0;
717 while (l--)
718 if (str[l]=='\\')
719 str[l]='/';
720}
721
722/*
723 * FindIWADFIle
724 *
725 * Search for one of the standard IWADs
726 * CPhipps - static, proper prototype
727 * - 12/1999 - rewritten to use I_FindFile
728 */
729static char *FindIWADFile(void)
730{
731 int i;
732 char * iwad = NULL;
733
734 i = M_CheckParm("-iwad");
735 if (i && (++i < myargc)) {
736 iwad = I_FindFile(myargv[i], ".wad");
737 } else {
738 for (i=0; !iwad && i<nstandard_iwads; i++)
739 iwad = I_FindFile(standard_iwads[i], ".wad");
740 }
741 return iwad;
742}
743
744//
745// IdentifyVersion
746//
747// Set the location of the defaults file and the savegame root
748// Locate and validate an IWAD file
749// Determine gamemode from the IWAD
750//
751// supports IWADs with custom names. Also allows the -iwad parameter to
752// specify which iwad is being searched for if several exist in one dir.
753// The -iwad parm may specify:
754//
755// 1) a specific pathname, which must exist (.wad optional)
756// 2) or a directory, which must contain a standard IWAD,
757// 3) or a filename, which must be found in one of the standard places:
758// a) current dir,
759// b) exe dir
760// c) $DOOMWADDIR
761// d) or $HOME
762//
763// jff 4/19/98 rewritten to use a more advanced search algorithm
764
765static void IdentifyVersion (void)
766{
767 int i; //jff 3/24/98 index of args on commandline
768 struct stat sbuf; //jff 3/24/98 used to test save path for existence
769 char *iwad;
770
771 // set save path to -save parm or current dir
772
773 //jff 3/27/98 default to current dir
774 //V.Aguilar (5/30/99): In LiNUX, default to $HOME/.lxdoom
775 {
776 // CPhipps - use DOOMSAVEDIR if defined
777 char* p = getenv("DOOMSAVEDIR");
778
779 if (p != NULL)
780 if (strlen(p) > PATH_MAX-12) p = NULL;
781
782 strcpy(basesavegame,(p == NULL) ? I_DoomExeDir() : p);
783 }
784 if ((i=M_CheckParm("-save")) && i<myargc-1) //jff 3/24/98 if -save present
785 {
786 if (!stat(myargv[i+1],&sbuf) && S_ISDIR(sbuf.st_mode)) // and is a dir
787 {
788 strcpy(basesavegame,myargv[i+1]); //jff 3/24/98 use that for savegame
789 NormalizeSlashes(basesavegame); //jff 9/22/98 fix c:\ not working
790 }
791 //jff 9/3/98 use logical output routine
792 else lprintf(LO_ERROR,"Error: -save path does not exist, using %s\n", basesavegame);
793 }
794
795 // locate the IWAD and determine game mode from it
796
797 iwad = FindIWADFile();
798
799#if (defined(GL_DOOM) && defined(_DEBUG))
800 // proff 11/99: used for debugging
801 {
802 FILE *f;
803 f=fopen("levelinfo.txt","w");
804 if (f)
805 {
806 fprintf(f,"%s\n",iwad);
807 fclose(f);
808 }
809 }
810#endif
811
812 if (iwad && *iwad)
813 {
814 //jff 9/3/98 use logical output routine
815 lprintf(LO_CONFIRM,"IWAD found: %s\n",iwad); //jff 4/20/98 print only if found
816 CheckIWAD(iwad,&gamemode,&haswolflevels);
817
818 /* jff 8/23/98 set gamemission global appropriately in all cases
819 * cphipps 12/1999 - no version output here, leave that to the caller
820 */
821 switch(gamemode)
822 {
823 case retail:
824 case registered:
825 case shareware:
826 gamemission = doom;
827 break;
828 case commercial:
829 i = strlen(iwad);
830 gamemission = doom2;
831 if (i>=10 && !strnicmp(iwad+i-10,"doom2f.wad",10))
832 language=french;
833 else if (i>=7 && !strnicmp(iwad+i-7,"tnt.wad",7))
834 gamemission = pack_tnt;
835 else if (i>=12 && !strnicmp(iwad+i-12,"plutonia.wad",12))
836 gamemission = pack_plut;
837 break;
838 default:
839 gamemission = none;
840 break;
841 }
842 if (gamemode == indetermined)
843 //jff 9/3/98 use logical output routine
844 lprintf(LO_WARN,"Unknown Game Version, may not work\n");
845 D_AddFile(iwad,source_iwad);
846 free(iwad);
847 }
848 else
849 I_Error("IdentifyVersion: IWAD not found\n");
850}
851
852
853
854// killough 5/3/98: old code removed
855//
856// Find a Response File
857//
858
859#define MAXARGVS 100
860
861static void FindResponseFile (void)
862{
863 int i;
864
865 for (i = 1;i < myargc;i++)
866 if (myargv[i][0] == '@')
867 {
868 int size;
869 int index;
870 int indexinfile;
871 byte *file = NULL;
872 const char **moreargs = malloc(myargc * sizeof(const char*));
873 const char **newargv;
874 // proff 04/05/2000: Added for searching responsefile
875 char fname[PATH_MAX+1];
876
877 strcpy(fname,&myargv[i][1]);
878 AddDefaultExtension(fname,".rsp");
879
880 // READ THE RESPONSE FILE INTO MEMORY
881 // proff 04/05/2000: changed for searching responsefile
882 // cph 2002/08/09 - use M_ReadFile for simplicity
883 size = M_ReadFile(fname, &file);
884 // proff 04/05/2000: Added for searching responsefile
885 if (size < 0)
886 {
887 strcat(strcpy(fname,I_DoomExeDir()),&myargv[i][1]);
888 AddDefaultExtension(fname,".rsp");
889 size = M_ReadFile(fname, &file);
890 }
891 if (size < 0)
892 {
893 /* proff 04/05/2000: Changed from LO_FATAL
894 * proff 04/05/2000: Simply removed the exit(1);
895 * cph - made fatal, don't drop through and SEGV
896 */
897 I_Error("No such response file: %s",fname);
898 }
899 //jff 9/3/98 use logical output routine
900 lprintf(LO_CONFIRM,"Found response file %s\n",fname);
901 // proff 04/05/2000: Added check for empty rsp file
902 if (size<=0)
903 {
904 int k;
905 lprintf(LO_ERROR,"\nResponse file empty!\n");
906
907 newargv = calloc(sizeof(char *),MAXARGVS);
908 newargv[0] = myargv[0];
909 for (k = 1,index = 1;k < myargc;k++)
910 {
911 if (i!=k)
912 newargv[index++] = myargv[k];
913 }
914 myargc = index; myargv = newargv;
915 return;
916 }
917
918 // KEEP ALL CMDLINE ARGS FOLLOWING @RESPONSEFILE ARG
919 memcpy((void *)moreargs,&myargv[i+1],(index = myargc - i - 1) * sizeof(myargv[0]));
920
921 {
922 const char *firstargv = myargv[0];
923 newargv = calloc(sizeof(char *),MAXARGVS);
924 newargv[0] = firstargv;
925 }
926
927 {
928 byte *infile = file;
929 indexinfile = 0;
930 indexinfile++; // SKIP PAST ARGV[0] (KEEP IT)
931 do {
932 while (size > 0 && isspace(*infile)) { infile++; size--; }
933 if (size > 0) {
934 char *s = malloc(size+1);
935 char *p = s;
936 int quoted = 0;
937
938 while (size > 0) {
939 // Whitespace terminates the token unless quoted
940 if (!quoted && isspace(*infile)) break;
941 if (*infile == '\"') {
942 // Quotes are removed but remembered
943 infile++; size--; quoted ^= 1;
944 } else {
945 *p++ = *infile++; size--;
946 }
947 }
948 if (quoted) I_Error("Runaway quoted string in response file");
949
950 // Terminate string, realloc and add to argv
951 *p = 0;
952 newargv[indexinfile++] = realloc(s,strlen(s)+1);
953 }
954 } while(size > 0);
955 }
956 free(file);
957
958 memcpy((void *)&newargv[indexinfile],moreargs,index*sizeof(moreargs[0]));
959 free((void *)moreargs);
960
961 myargc = indexinfile+index; myargv = newargv;
962
963 // DISPLAY ARGS
964 //jff 9/3/98 use logical output routine
965 lprintf(LO_CONFIRM,"%d command-line args:\n",myargc);
966 for (index=1;index<myargc;index++)
967 //jff 9/3/98 use logical output routine
968 lprintf(LO_CONFIRM,"%s\n",myargv[index]);
969 break;
970 }
971}
972
973//
974// DoLooseFiles
975//
976// Take any file names on the command line before the first switch parm
977// and insert the appropriate -file, -deh or -playdemo switch in front
978// of them.
979//
980// Note that more than one -file, etc. entry on the command line won't
981// work, so we have to go get all the valid ones if any that show up
982// after the loose ones. This means that boom fred.wad -file wilma
983// will still load fred.wad and wilma.wad, in that order.
984// The response file code kludges up its own version of myargv[] and
985// unfortunately we have to do the same here because that kludge only
986// happens if there _is_ a response file. Truth is, it's more likely
987// that there will be a need to do one or the other so it probably
988// isn't important. We'll point off to the original argv[], or the
989// area allocated in FindResponseFile, or our own areas from strdups.
990//
991// CPhipps - OUCH! Writing into *myargv is too dodgy, damn
992
993static void DoLooseFiles(void)
994{
995 char *wads[MAXARGVS]; // store the respective loose filenames
996 char *lmps[MAXARGVS];
997 char *dehs[MAXARGVS];
998 int wadcount = 0; // count the loose filenames
999 int lmpcount = 0;
1000 int dehcount = 0;
1001 int i,j,p;
1002 const char **tmyargv; // use these to recreate the argv array
1003 int tmyargc;
1004 boolean skip[MAXARGVS]; // CPhipps - should these be skipped at the end
1005
1006 for (i=0; i<MAXARGVS; i++)
1007 skip[i] = false;
1008
1009 for (i=1;i<myargc;i++)
1010 {
1011 if (*myargv[i] == '-') break; // quit at first switch
1012
1013 // so now we must have a loose file. Find out what kind and store it.
1014 j = strlen(myargv[i]);
1015 if (!stricmp(&myargv[i][j-4],".wad"))
1016 wads[wadcount++] = strdup(myargv[i]);
1017 if (!stricmp(&myargv[i][j-4],".lmp"))
1018 lmps[lmpcount++] = strdup(myargv[i]);
1019 if (!stricmp(&myargv[i][j-4],".deh"))
1020 dehs[dehcount++] = strdup(myargv[i]);
1021 if (!stricmp(&myargv[i][j-4],".bex"))
1022 dehs[dehcount++] = strdup(myargv[i]);
1023 if (myargv[i][j-4] != '.') // assume wad if no extension
1024 wads[wadcount++] = strdup(myargv[i]);
1025 skip[i] = true; // nuke that entry so it won't repeat later
1026 }
1027
1028 // Now, if we didn't find any loose files, we can just leave.
1029 if (wadcount+lmpcount+dehcount == 0) return; // ******* early return ****
1030
1031 if ((p = M_CheckParm ("-file")))
1032 {
1033 skip[p] = true; // nuke the entry
1034 while (++p != myargc && *myargv[p] != '-')
1035 {
1036 wads[wadcount++] = strdup(myargv[p]);
1037 skip[p] = true; // null any we find and save
1038 }
1039 }
1040
1041 if ((p = M_CheckParm ("-deh")))
1042 {
1043 skip[p] = true; // nuke the entry
1044 while (++p != myargc && *myargv[p] != '-')
1045 {
1046 dehs[dehcount++] = strdup(myargv[p]);
1047 skip[p] = true; // null any we find and save
1048 }
1049 }
1050
1051 if ((p = M_CheckParm ("-playdemo")))
1052 {
1053 skip[p] = true; // nuke the entry
1054 while (++p != myargc && *myargv[p] != '-')
1055 {
1056 lmps[lmpcount++] = strdup(myargv[p]);
1057 skip[p] = true; // null any we find and save
1058 }
1059 }
1060
1061 // Now go back and redo the whole myargv array with our stuff in it.
1062 // First, create a new myargv array to copy into
1063 tmyargv = calloc(sizeof(char *),MAXARGVS);
1064 tmyargv[0] = myargv[0]; // invocation
1065 tmyargc = 1;
1066
1067 // put our stuff into it
1068 if (wadcount > 0)
1069 {
1070 tmyargv[tmyargc++] = strdup("-file"); // put the switch in
1071 for (i=0;i<wadcount;)
1072 tmyargv[tmyargc++] = wads[i++]; // allocated by strdup above
1073 }
1074
1075 // for -deh
1076 if (dehcount > 0)
1077 {
1078 tmyargv[tmyargc++] = strdup("-deh");
1079 for (i=0;i<dehcount;)
1080 tmyargv[tmyargc++] = dehs[i++];
1081 }
1082
1083 // for -playdemo
1084 if (lmpcount > 0)
1085 {
1086 tmyargv[tmyargc++] = strdup("-playdemo");
1087 for (i=0;i<lmpcount;)
1088 tmyargv[tmyargc++] = lmps[i++];
1089 }
1090
1091 // then copy everything that's there now
1092 for (i=1;i<myargc;i++)
1093 {
1094 if (!skip[i]) // skip any zapped entries
1095 tmyargv[tmyargc++] = myargv[i]; // pointers are still valid
1096 }
1097 // now make the global variables point to our array
1098 myargv = tmyargv;
1099 myargc = tmyargc;
1100}
1101
1102/* cph - MBF-like wad/deh/bex autoload code */
1103const char *wad_files[MAXLOADFILES], *deh_files[MAXLOADFILES];
1104
1105// CPhipps - misc screen stuff
1106unsigned int desired_screenwidth, desired_screenheight;
1107
1108static void L_SetupConsoleMasks(void) {
1109 int p;
1110 int i;
1111 const char *cena="ICWEFDA",*pos; //jff 9/3/98 use this for parsing console masks // CPhipps - const char*'s
1112
1113 //jff 9/3/98 get mask for console output filter
1114 if ((p = M_CheckParm ("-cout"))) {
1115 lprintf(LO_DEBUG, "mask for stdout console output: ");
1116 if (++p != myargc && *myargv[p] != '-')
1117 for (i=0,cons_output_mask=0;(size_t)i<strlen(myargv[p]);i++)
1118 if ((pos = strchr(cena,toupper(myargv[p][i])))) {
1119 cons_output_mask |= (1<<(pos-cena));
1120 lprintf(LO_DEBUG, "%c", toupper(myargv[p][i]));
1121 }
1122 lprintf(LO_DEBUG, "\n");
1123 }
1124
1125 //jff 9/3/98 get mask for redirected console error filter
1126 if ((p = M_CheckParm ("-cerr"))) {
1127 lprintf(LO_DEBUG, "mask for stderr console output: ");
1128 if (++p != myargc && *myargv[p] != '-')
1129 for (i=0,cons_error_mask=0;(size_t)i<strlen(myargv[p]);i++)
1130 if ((pos = strchr(cena,toupper(myargv[p][i])))) {
1131 cons_error_mask |= (1<<(pos-cena));
1132 lprintf(LO_DEBUG, "%c", toupper(myargv[p][i]));
1133 }
1134 lprintf(LO_DEBUG, "\n");
1135 }
1136}
1137
1138//
1139// D_DoomMainSetup
1140//
1141// CPhipps - the old contents of D_DoomMain, but moved out of the main
1142// line of execution so its stack space can be freed
1143
1144static void D_DoomMainSetup(void)
1145{
1146 int p,slot;
1147
1148 L_SetupConsoleMasks();
1149
1150 setbuf(stdout,NULL);
1151
1152 // proff 04/05/2000: Added support for include response files
1153 /* proff 2001/7/1 - Moved up, so -config can be in response files */
1154 {
1155 boolean rsp_found;
1156 int i;
1157
1158 do {
1159 rsp_found=false;
1160 for (i=0; i<myargc; i++)
1161 if (myargv[i][0]=='@')
1162 rsp_found=true;
1163 FindResponseFile();
1164 } while (rsp_found==true);
1165 }
1166
1167 lprintf(LO_INFO,"M_LoadDefaults: Load system defaults.\n");
1168 M_LoadDefaults(); // load before initing other systems
1169
1170 // figgi 09/18/00-- added switch to force classic bsp nodes
1171 if (M_CheckParm ("-forceoldbsp"))
1172 {
1173 extern boolean forceOldBsp;
1174 forceOldBsp = true;
1175 }
1176
1177 DoLooseFiles(); // Ty 08/29/98 - handle "loose" files on command line
1178 IdentifyVersion();
1179
1180 // e6y: DEH files preloaded in wrong order
1181 // http://sourceforge.net/tracker/index.php?func=detail&aid=1418158&group_id=148658&atid=772943
1182 // The dachaked stuff has been moved below an autoload
1183
1184 // jff 1/24/98 set both working and command line value of play parms
1185 nomonsters = clnomonsters = M_CheckParm ("-nomonsters");
1186 respawnparm = clrespawnparm = M_CheckParm ("-respawn");
1187 fastparm = clfastparm = M_CheckParm ("-fast");
1188 // jff 1/24/98 end of set to both working and command line value
1189
1190 devparm = M_CheckParm ("-devparm");
1191
1192 if (M_CheckParm ("-altdeath"))
1193 deathmatch = 2;
1194 else
1195 if (M_CheckParm ("-deathmatch"))
1196 deathmatch = 1;
1197
1198 {
1199 // CPhipps - localise title variable
1200 // print title for every printed line
1201 // cph - code cleaned and made smaller
1202 const char* doomverstr;
1203
1204 switch ( gamemode ) {
1205 case retail:
1206 doomverstr = "The Ultimate DOOM";
1207 break;
1208 case shareware:
1209 doomverstr = "DOOM Shareware";
1210 break;
1211 case registered:
1212 doomverstr = "DOOM Registered";
1213 break;
1214 case commercial: // Ty 08/27/98 - fixed gamemode vs gamemission
1215 switch (gamemission)
1216 {
1217 case pack_plut:
1218 doomverstr = "DOOM 2: Plutonia Experiment";
1219 break;
1220 case pack_tnt:
1221 doomverstr = "DOOM 2: TNT - Evilution";
1222 break;
1223 default:
1224 doomverstr = "DOOM 2: Hell on Earth";
1225 break;
1226 }
1227 break;
1228 default:
1229 doomverstr = "Public DOOM";
1230 break;
1231 }
1232
1233 /* cphipps - the main display. This shows the build date, copyright, and game type */
1234 lprintf(LO_ALWAYS,"PrBoom (built %s), playing: %s\n"
1235 "PrBoom is released under the GNU General Public license v2.0.\n"
1236 "You are welcome to redistribute it under certain conditions.\n"
1237 "It comes with ABSOLUTELY NO WARRANTY. See the file COPYING for details.\n",
1238 version_date, doomverstr);
1239 }
1240
1241 if (devparm)
1242 //jff 9/3/98 use logical output routine
1243 lprintf(LO_CONFIRM,"%s",D_DEVSTR);
1244
1245 // turbo option
1246 if ((p=M_CheckParm ("-turbo")))
1247 {
1248 int scale = 200;
1249 extern int forwardmove[2];
1250 extern int sidemove[2];
1251
1252 if (p<myargc-1)
1253 scale = atoi(myargv[p+1]);
1254 if (scale < 10)
1255 scale = 10;
1256 if (scale > 400)
1257 scale = 400;
1258 //jff 9/3/98 use logical output routine
1259 lprintf (LO_CONFIRM,"turbo scale: %i%%\n",scale);
1260 forwardmove[0] = forwardmove[0]*scale/100;
1261 forwardmove[1] = forwardmove[1]*scale/100;
1262 sidemove[0] = sidemove[0]*scale/100;
1263 sidemove[1] = sidemove[1]*scale/100;
1264 }
1265
1266 modifiedgame = false;
1267
1268 // get skill / episode / map from parms
1269
1270 startskill = sk_none; // jff 3/24/98 was sk_medium, just note not picked
1271 startepisode = 1;
1272 startmap = 1;
1273 autostart = false;
1274
1275 if ((p = M_CheckParm ("-skill")) && p < myargc-1)
1276 {
1277 startskill = myargv[p+1][0]-'1';
1278 autostart = true;
1279 }
1280
1281 if ((p = M_CheckParm ("-episode")) && p < myargc-1)
1282 {
1283 startepisode = myargv[p+1][0]-'0';
1284 startmap = 1;
1285 autostart = true;
1286 }
1287
1288 if ((p = M_CheckParm ("-timer")) && p < myargc-1 && deathmatch)
1289 {
1290 int time = atoi(myargv[p+1]);
1291 //jff 9/3/98 use logical output routine
1292 lprintf(LO_CONFIRM,"Levels will end after %d minute%s.\n", time, time>1 ? "s" : "");
1293 }
1294
1295 if ((p = M_CheckParm ("-avg")) && p < myargc-1 && deathmatch)
1296 //jff 9/3/98 use logical output routine
1297 lprintf(LO_CONFIRM,"Austin Virtual Gaming: Levels will end after 20 minutes\n");
1298
1299 if ((p = M_CheckParm ("-warp")) || // killough 5/2/98
1300 (p = M_CheckParm ("-wart")))
1301 // Ty 08/29/98 - moved this check later so we can have -warp alone: && p < myargc-1)
1302 {
1303 startmap = 0; // Ty 08/29/98 - allow "-warp x" to go to first map in wad(s)
1304 autostart = true; // Ty 08/29/98 - move outside the decision tree
1305 if (gamemode == commercial)
1306 {
1307 if (p < myargc-1)
1308 startmap = atoi(myargv[p+1]); // Ty 08/29/98 - add test if last parm
1309 }
1310 else // 1/25/98 killough: fix -warp xxx from crashing Doom 1 / UD
1311 {
1312 if (p < myargc-2)
1313 {
1314 startepisode = atoi(myargv[++p]);
1315 startmap = atoi(myargv[p+1]);
1316 }
1317 }
1318 }
1319 // Ty 08/29/98 - later we'll check for startmap=0 and autostart=true
1320 // as a special case that -warp * was used. Actually -warp with any
1321 // non-numeric will do that but we'll only document "*"
1322
1323 //jff 1/22/98 add command line parms to disable sound and music
1324 {
1325 int nosound = M_CheckParm("-nosound");
1326 nomusicparm = nosound || M_CheckParm("-nomusic");
1327 nosfxparm = nosound || M_CheckParm("-nosfx");
1328 }
1329 //jff end of sound/music command line parms
1330
1331 // killough 3/2/98: allow -nodraw -noblit generally
1332 nodrawers = M_CheckParm ("-nodraw");
1333 noblit = M_CheckParm ("-noblit");
1334
1335 //proff 11/22/98: Added setting of viewangleoffset
1336 p = M_CheckParm("-viewangle");
1337 if (p)
1338 {
1339 viewangleoffset = atoi(myargv[p+1]);
1340 viewangleoffset = viewangleoffset<0 ? 0 : (viewangleoffset>7 ? 7 : viewangleoffset);
1341 viewangleoffset = (8-viewangleoffset) * ANG45;
1342 }
1343
1344 // init subsystems
1345
1346 G_ReloadDefaults(); // killough 3/4/98: set defaults just loaded.
1347 // jff 3/24/98 this sets startskill if it was -1
1348
1349 // Video stuff
1350 if ((p = M_CheckParm("-width")))
1351 if (myargv[p+1])
1352 desired_screenwidth = atoi(myargv[p+1]);
1353
1354 if ((p = M_CheckParm("-height")))
1355 if (myargv[p+1])
1356 desired_screenheight = atoi(myargv[p+1]);
1357
1358 if ((p = M_CheckParm("-fullscreen")))
1359 use_fullscreen = 1;
1360
1361 if ((p = M_CheckParm("-nofullscreen")))
1362 use_fullscreen = 0;
1363
1364 // e6y
1365 // New command-line options for setting a window (-window)
1366 // or fullscreen (-nowindow) mode temporarily which is not saved in cfg.
1367 // It works like "-geom" switch
1368 desired_fullscreen = use_fullscreen;
1369 if ((p = M_CheckParm("-window")))
1370 desired_fullscreen = 0;
1371
1372 if ((p = M_CheckParm("-nowindow")))
1373 desired_fullscreen = 1;
1374
1375 { // -geometry handling, change screen size for this session only
1376 // e6y: new code by me
1377 int w, h;
1378
1379 if (!(p = M_CheckParm("-geom")))
1380 p = M_CheckParm("-geometry");
1381
1382 if (!(p && (p+1<myargc) && sscanf(myargv[p+1], "%dx%d", &w, &h) == 2))
1383 {
1384 w = desired_screenwidth;
1385 h = desired_screenheight;
1386 }
1387 I_CalculateRes(w, h);
1388 }
1389
1390#ifdef GL_DOOM
1391 // proff 04/05/2000: for GL-specific switches
1392 gld_InitCommandLine();
1393#endif
1394
1395 //jff 9/3/98 use logical output routine
1396 lprintf(LO_INFO,"V_Init: allocate screens.\n");
1397 V_Init();
1398
1399 // CPhipps - autoloading of wads
1400 // Designed to be general, instead of specific to boomlump.wad
1401 // Some people might find this useful
1402 // cph - support MBF -noload parameter
1403 if (!M_CheckParm("-noload")) {
1404 int i;
1405
1406 for (i=0; i<MAXLOADFILES*2; i++) {
1407 const char *fname = (i < MAXLOADFILES) ? wad_files[i]
1408 : deh_files[i - MAXLOADFILES];
1409 char *fpath;
1410
1411 if (!(fname && *fname)) continue;
1412 // Filename is now stored as a zero terminated string
1413 fpath = I_FindFile(fname, (i < MAXLOADFILES) ? ".wad" : ".bex");
1414 if (!fpath)
1415 lprintf(LO_WARN, "Failed to autoload %s\n", fname);
1416 else {
1417 if (i >= MAXLOADFILES)
1418 ProcessDehFile(fpath, D_dehout(), 0);
1419 else {
1420 D_AddFile(fpath,source_auto_load);
1421 }
1422 modifiedgame = true;
1423 free(fpath);
1424 }
1425 }
1426 }
1427
1428 // e6y: DEH files preloaded in wrong order
1429 // http://sourceforge.net/tracker/index.php?func=detail&aid=1418158&group_id=148658&atid=772943
1430 // The dachaked stuff has been moved from above
1431
1432 // ty 03/09/98 do dehacked stuff
1433 // Note: do this before any other since it is expected by
1434 // the deh patch author that this is actually part of the EXE itself
1435 // Using -deh in BOOM, others use -dehacked.
1436 // Ty 03/18/98 also allow .bex extension. .bex overrides if both exist.
1437
1438 D_BuildBEXTables(); // haleyjd
1439
1440 p = M_CheckParm ("-deh");
1441 if (p)
1442 {
1443 char file[PATH_MAX+1]; // cph - localised
1444 // the parms after p are deh/bex file names,
1445 // until end of parms or another - preceded parm
1446 // Ty 04/11/98 - Allow multiple -deh files in a row
1447
1448 while (++p != myargc && *myargv[p] != '-')
1449 {
1450 AddDefaultExtension(strcpy(file, myargv[p]), ".bex");
1451 if (access(file, F_OK)) // nope
1452 {
1453 AddDefaultExtension(strcpy(file, myargv[p]), ".deh");
1454 if (access(file, F_OK)) // still nope
1455 I_Error("D_DoomMainSetup: Cannot find .deh or .bex file named %s",myargv[p]);
1456 }
1457 // during the beta we have debug output to dehout.txt
1458 ProcessDehFile(file,D_dehout(),0);
1459 }
1460 }
1461 // ty 03/09/98 end of do dehacked stuff
1462
1463 // add any files specified on the command line with -file wadfile
1464 // to the wad list
1465
1466 // killough 1/31/98, 5/2/98: reload hack removed, -wart same as -warp now.
1467
1468 if ((p = M_CheckParm ("-file")))
1469 {
1470 // the parms after p are wadfile/lump names,
1471 // until end of parms or another - preceded parm
1472 modifiedgame = true; // homebrew levels
1473 while (++p != myargc && *myargv[p] != '-')
1474 D_AddFile(myargv[p],source_pwad);
1475 }
1476
1477 if (!(p = M_CheckParm("-playdemo")) || p >= myargc-1) { /* killough */
1478 if ((p = M_CheckParm ("-fastdemo")) && p < myargc-1) /* killough */
1479 fastdemo = true; // run at fastest speed possible
1480 else
1481 p = M_CheckParm ("-timedemo");
1482 }
1483
1484 if (p && p < myargc-1)
1485 {
1486 char file[PATH_MAX+1]; // cph - localised
1487 strcpy(file,myargv[p+1]);
1488 AddDefaultExtension(file,".lmp"); // killough
1489 D_AddFile (file,source_lmp);
1490 //jff 9/3/98 use logical output routine
1491 lprintf(LO_CONFIRM,"Playing demo %s\n",file);
1492 if ((p = M_CheckParm ("-ffmap")) && p < myargc-1) {
1493 ffmap = atoi(myargv[p+1]);
1494 }
1495
1496 }
1497
1498 // internal translucency set to config file value // phares
1499 general_translucency = default_translucency; // phares
1500
1501 // 1/18/98 killough: Z_Init() call moved to i_main.c
1502
1503 // CPhipps - move up netgame init
1504 //jff 9/3/98 use logical output routine
1505 lprintf(LO_INFO,"D_InitNetGame: Checking for network game.\n");
1506 D_InitNetGame();
1507
1508 //jff 9/3/98 use logical output routine
1509 lprintf(LO_INFO,"W_Init: Init WADfiles.\n");
1510 W_Init(); // CPhipps - handling of wadfiles init changed
1511
1512 lprintf(LO_INFO,"\n"); // killough 3/6/98: add a newline, by popular demand :)
1513
1514 // e6y
1515 // option to disable automatic loading of dehacked-in-wad lump
1516 if (!M_CheckParm ("-nodeh"))
1517 if ((p = W_CheckNumForName("DEHACKED")) != -1) // cph - add dehacked-in-a-wad support
1518 ProcessDehFile(NULL, D_dehout(), p);
1519
1520 V_InitColorTranslation(); //jff 4/24/98 load color translation lumps
1521
1522 // killough 2/22/98: copyright / "modified game" / SPA banners removed
1523
1524 // Ty 04/08/98 - Add 5 lines of misc. data, only if nonblank
1525 // The expectation is that these will be set in a .bex file
1526 //jff 9/3/98 use logical output routine
1527 if (*startup1) lprintf(LO_INFO,"%s",startup1);
1528 if (*startup2) lprintf(LO_INFO,"%s",startup2);
1529 if (*startup3) lprintf(LO_INFO,"%s",startup3);
1530 if (*startup4) lprintf(LO_INFO,"%s",startup4);
1531 if (*startup5) lprintf(LO_INFO,"%s",startup5);
1532 // End new startup strings
1533
1534 //jff 9/3/98 use logical output routine
1535 lprintf(LO_INFO,"M_Init: Init miscellaneous info.\n");
1536 M_Init();
1537
1538#ifdef HAVE_NET
1539 // CPhipps - now wait for netgame start
1540 D_CheckNetGame();
1541#endif
1542
1543 //jff 9/3/98 use logical output routine
1544 lprintf(LO_INFO,"R_Init: Init DOOM refresh daemon - ");
1545 R_Init();
1546
1547 //jff 9/3/98 use logical output routine
1548 lprintf(LO_INFO,"\nP_Init: Init Playloop state.\n");
1549 P_Init();
1550
1551 //jff 9/3/98 use logical output routine
1552 lprintf(LO_INFO,"I_Init: Setting up machine state.\n");
1553 I_Init();
1554
1555 //jff 9/3/98 use logical output routine
1556 lprintf(LO_INFO,"S_Init: Setting up sound.\n");
1557 S_Init(snd_SfxVolume /* *8 */, snd_MusicVolume /* *8*/ );
1558
1559 //jff 9/3/98 use logical output routine
1560 lprintf(LO_INFO,"HU_Init: Setting up heads up display.\n");
1561 HU_Init();
1562
1563 if (!(M_CheckParm("-nodraw") && M_CheckParm("-nosound")))
1564 I_InitGraphics();
1565
1566 //jff 9/3/98 use logical output routine
1567 lprintf(LO_INFO,"ST_Init: Init status bar.\n");
1568 ST_Init();
1569
1570 idmusnum = -1; //jff 3/17/98 insure idmus number is blank
1571
1572 // CPhipps - auto screenshots
1573 if ((p = M_CheckParm("-autoshot")) && (p < myargc-2))
1574 if ((auto_shot_count = auto_shot_time = atoi(myargv[p+1])))
1575 auto_shot_fname = myargv[p+2];
1576
1577 // start the apropriate game based on parms
1578
1579 // killough 12/98:
1580 // Support -loadgame with -record and reimplement -recordfrom.
1581
1582 if ((slot = M_CheckParm("-recordfrom")) && (p = slot+2) < myargc)
1583 G_RecordDemo(myargv[p]);
1584 else
1585 {
1586 slot = M_CheckParm("-loadgame");
1587 if ((p = M_CheckParm("-record")) && ++p < myargc)
1588 {
1589 autostart = true;
1590 G_RecordDemo(myargv[p]);
1591 }
1592 }
1593
1594 if ((p = M_CheckParm ("-checksum")) && ++p < myargc)
1595 {
1596 P_RecordChecksum (myargv[p]);
1597 }
1598
1599 if ((p = M_CheckParm ("-fastdemo")) && ++p < myargc)
1600 { // killough
1601 fastdemo = true; // run at fastest speed possible
1602 timingdemo = true; // show stats after quit
1603 G_DeferedPlayDemo(myargv[p]);
1604 singledemo = true; // quit after one demo
1605 }
1606 else
1607 if ((p = M_CheckParm("-timedemo")) && ++p < myargc)
1608 {
1609 singletics = true;
1610 timingdemo = true; // show stats after quit
1611 G_DeferedPlayDemo(myargv[p]);
1612 singledemo = true; // quit after one demo
1613 }
1614 else
1615 if ((p = M_CheckParm("-playdemo")) && ++p < myargc)
1616 {
1617 G_DeferedPlayDemo(myargv[p]);
1618 singledemo = true; // quit after one demo
1619 }
1620
1621 if (slot && ++slot < myargc)
1622 {
1623 slot = atoi(myargv[slot]); // killough 3/16/98: add slot info
1624 G_LoadGame(slot, true); // killough 5/15/98: add command flag // cph - no filename
1625 }
1626 else
1627 if (!singledemo) { /* killough 12/98 */
1628 if (autostart || netgame)
1629 {
1630 G_InitNew(startskill, startepisode, startmap);
1631 if (demorecording)
1632 G_BeginRecording();
1633 }
1634 else
1635 D_StartTitle(); // start up intro loop
1636 }
1637}
1638
1639//
1640// D_DoomMain
1641//
1642
1643void D_DoomMain(void)
1644{
1645 D_DoomMainSetup(); // CPhipps - setup out of main execution stack
1646
1647 D_DoomLoop (); // never returns
1648}
1649
1650//
1651// GetFirstMap
1652//
1653// Ty 08/29/98 - determine first available map from the loaded wads and run it
1654//
1655
1656void GetFirstMap(int *ep, int *map)
1657{
1658 int i,j; // used to generate map name
1659 boolean done = false; // Ty 09/13/98 - to exit inner loops
1660 char test[6]; // MAPxx or ExMx plus terminator for testing
1661 char name[6]; // MAPxx or ExMx plus terminator for display
1662 boolean newlevel = false; // Ty 10/04/98 - to test for new level
1663 int ix; // index for lookup
1664
1665 strcpy(name,""); // initialize
1666 if (*map == 0) // unknown so go search for first changed one
1667 {
1668 *ep = 1;
1669 *map = 1; // default E1M1 or MAP01
1670 if (gamemode == commercial)
1671 {
1672 for (i=1;!done && i<33;i++) // Ty 09/13/98 - add use of !done
1673 {
1674 sprintf(test,"MAP%02d",i);
1675 ix = W_CheckNumForName(test);
1676 if (ix != -1) // Ty 10/04/98 avoid -1 subscript
1677 {
1678 if (lumpinfo[ix].source == source_pwad)
1679 {
1680 *map = i;
1681 strcpy(name,test); // Ty 10/04/98
1682 done = true; // Ty 09/13/98
1683 newlevel = true; // Ty 10/04/98
1684 }
1685 else
1686 {
1687 if (!*name) // found one, not pwad. First default.
1688 strcpy(name,test);
1689 }
1690 }
1691 }
1692 }
1693 else // one of the others
1694 {
1695 strcpy(name,"E1M1"); // Ty 10/04/98 - default for display
1696 for (i=1;!done && i<5;i++) // Ty 09/13/98 - add use of !done
1697 {
1698 for (j=1;!done && j<10;j++) // Ty 09/13/98 - add use of !done
1699 {
1700 sprintf(test,"E%dM%d",i,j);
1701 ix = W_CheckNumForName(test);
1702 if (ix != -1) // Ty 10/04/98 avoid -1 subscript
1703 {
1704 if (lumpinfo[ix].source == source_pwad)
1705 {
1706 *ep = i;
1707 *map = j;
1708 strcpy(name,test); // Ty 10/04/98
1709 done = true; // Ty 09/13/98
1710 newlevel = true; // Ty 10/04/98
1711 }
1712 else
1713 {
1714 if (!*name) // found one, not pwad. First default.
1715 strcpy(name,test);
1716 }
1717 }
1718 }
1719 }
1720 }
1721 //jff 9/3/98 use logical output routine
1722 lprintf(LO_CONFIRM,"Auto-warping to first %slevel: %s\n",
1723 newlevel ? "new " : "", name); // Ty 10/04/98 - new level test
1724 }
1725}