home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 28 / amigaformatcd28.iso / -screenplay- / otherstuff / adoomppc_src / d_main.c < prev    next >
C/C++ Source or Header  |  1998-04-23  |  32KB  |  1,242 lines

  1. // Emacs style mode select   -*- C++ -*- 
  2. //-----------------------------------------------------------------------------
  3. //
  4. // $Id:$
  5. //
  6. // Copyright (C) 1993-1996 by id Software, Inc.
  7. //
  8. // This source is available for distribution and/or modification
  9. // only under the terms of the DOOM Source Code License as
  10. // published by id Software. All rights reserved.
  11. //
  12. // The source is distributed in the hope that it will be useful,
  13. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. // FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
  15. // for more details.
  16. //
  17. // $Log:$
  18. //
  19. // DESCRIPTION:
  20. //      DOOM main program (D_DoomMain) and game loop (D_DoomLoop),
  21. //      plus functions to determine game mode (shareware, registered),
  22. //      parse command line parameters, configure game parameters (turbo),
  23. //      and call the startup functions.
  24. //
  25. //-----------------------------------------------------------------------------
  26.  
  27.  
  28. static const char rcsid[] = "$Id: d_main.c,v 1.8 1997/02/03 22:45:09 b1 Exp $";
  29.  
  30. #define BGCOLOR         7
  31. #define FGCOLOR         8
  32.  
  33.  
  34. #ifdef NORMALUNIX
  35. #include <stdio.h>
  36. #include <stdlib.h>
  37. #include <unistd.h>
  38. #include <sys/types.h>
  39. #include <sys/stat.h>
  40. #include <fcntl.h>
  41. #endif
  42.  
  43.  
  44. #include "doomdef.h"
  45. #include "doomstat.h"
  46.  
  47. #include "dstrings.h"
  48. #include "sounds.h"
  49.  
  50.  
  51. #include "z_zone.h"
  52. #include "w_wad.h"
  53. #include "s_sound.h"
  54. #include "v_video.h"
  55.  
  56. #include "f_finale.h"
  57. #include "f_wipe.h"
  58.  
  59. #include "m_argv.h"
  60. #include "m_misc.h"
  61. #include "m_menu.h"
  62.  
  63. #include "i_system.h"
  64. #include "i_sound.h"
  65. #include "i_video.h"
  66.  
  67. #include "g_game.h"
  68.  
  69. #include "hu_stuff.h"
  70. #include "wi_stuff.h"
  71. #include "st_stuff.h"
  72. #include "am_map.h"
  73.  
  74. #include "p_setup.h"
  75. #include "r_local.h"
  76.  
  77. /* DeHacked Patch !!! */
  78. #include "dehacked.h"
  79.  
  80. #include "d_main.h"
  81.  
  82. //
  83. // D-DoomLoop()
  84. // Not a globally visible function,
  85. //  just included for source reference,
  86. //  called by D_DoomMain, never exits.
  87. // Manages timing and IO,
  88. //  calls all ?_Responder, ?_Ticker, and ?_Drawer,
  89. //  calls I_GetTime, I_StartFrame, and I_StartTic
  90. //
  91. void D_DoomLoop (void);
  92.  
  93.  
  94. char*           wadfiles[MAXWADFILES];
  95.  
  96.  
  97. boolean         devparm;        // started game with -devparm
  98. boolean         nomonsters;     // checkparm of -nomonsters
  99. boolean         respawnparm;    // checkparm of -respawn
  100. boolean         fastparm;       // checkparm of -fast
  101. boolean         rotatemap;      // checkparm of -rotatemap
  102. boolean         maponhu;        // checkparm of -maponhu
  103.  
  104. boolean         drone;
  105.  
  106. boolean         singletics = false; // debug flag to cancel adaptiveness
  107.  
  108.  
  109.  
  110. //extern int soundVolume;
  111. //extern  int   sfxVolume;
  112. //extern  int   musicVolume;
  113.  
  114. extern  boolean inhelpscreens;
  115. extern  boolean maponhu;
  116.  
  117. skill_t         startskill;
  118. int             startepisode;
  119. int             startmap;
  120. boolean         autostart;
  121.  
  122. FILE*           debugfile;
  123.  
  124. boolean         advancedemo;
  125.  
  126.  
  127.  
  128.  
  129. char            wadfile[1024];          // primary wad file
  130. char            mapdir[1024];           // directory of development maps
  131. char            basedefault[1024];      // default file
  132.  
  133.  
  134. void D_CheckNetGame (void);
  135. void D_ProcessEvents (void);
  136. void G_BuildTiccmd (ticcmd_t* cmd);
  137. void D_DoAdvanceDemo (void);
  138.  
  139.  
  140. //
  141. // EVENT HANDLING
  142. //
  143. // Events are asynchronous inputs generally generated by the game user.
  144. // Events can be discarded if no responder claims them
  145. //
  146. event_t         events[MAXEVENTS];
  147. int             eventhead;
  148. int             eventtail;
  149.  
  150.  
  151. //
  152. // D_PostEvent
  153. // Called by the I/O functions when input is detected
  154. //
  155. void D_PostEvent (event_t* ev)
  156. {
  157.     events[eventhead] = *ev;
  158.     eventhead = (++eventhead)&(MAXEVENTS-1);
  159. }
  160.  
  161.  
  162. //
  163. // D_ProcessEvents
  164. // Send all the events of the given timestamp down the responder chain
  165. //
  166. void D_ProcessEvents (void)
  167. {
  168.     event_t*    ev;
  169.         
  170.     // IF STORE DEMO, DO NOT ACCEPT INPUT
  171.     if ( ( gamemode == commercial )
  172.          && (W_CheckNumForName("map01")<0) )
  173.       return;
  174.         
  175.     for ( ; eventtail != eventhead ; eventtail = (++eventtail)&(MAXEVENTS-1) )
  176.     {
  177.         ev = &events[eventtail];
  178.         if (M_Responder (ev))
  179.             continue;               // menu ate the event
  180.         G_Responder (ev);
  181.     }
  182. }
  183.  
  184.  
  185.  
  186.  
  187. //
  188. // D_Display
  189. //  draw current display, possibly wiping it from the previous
  190. //
  191.  
  192. // wipegamestate can be set to -1 to force a wipe on the next draw
  193. gamestate_t     wipegamestate = GS_DEMOSCREEN;
  194. extern  boolean setsizeneeded;
  195. extern  int             showMessages;
  196. void R_ExecuteSetViewSize (void);
  197.  
  198. void D_Display (void)
  199. {
  200.     static  boolean             maponhustate = false;
  201.     static  boolean             viewactivestate = false;
  202.     static  boolean             menuactivestate = false;
  203.     static  boolean             inhelpscreensstate = false;
  204.     static  boolean             fullscreen = false;
  205.     static  gamestate_t         oldgamestate = -1;
  206.     static  int                 borderdrawcount;
  207.     int                         nowtime;
  208.     int                         tics;
  209.     int                         wipestart;
  210.     int                         y;
  211.     boolean                     done;
  212.     boolean                     wipe;
  213.     boolean                     redrawsbar;
  214.  
  215.     if (nodrawers)
  216.         return;                    // for comparative timing / profiling
  217.                 
  218.     redrawsbar = false;
  219.     
  220.     // change the view size if needed
  221.     if (setsizeneeded)
  222.     {
  223.         R_ExecuteSetViewSize ();
  224.         oldgamestate = -1;                      // force background redraw
  225.         borderdrawcount = 3;
  226.     }
  227.  
  228.     // force redraw border if we changed maponhu type
  229.     if (maponhu > 0 && maponhustate == 0)
  230.     {
  231.         oldgamestate = -1;                      // force background redraw
  232.         borderdrawcount = 3;
  233.     }
  234.  
  235.     // save the current screen if about to wipe
  236.     if (gamestate != wipegamestate)
  237.     {
  238.         wipe = true;
  239.         wipe_StartScreen(0, 0, SCREENWIDTH, SCREENHEIGHT);
  240.     }
  241.     else
  242.         wipe = false;
  243.  
  244.     // start updating gfx in screens[0] here
  245.     I_StartUpdate ();
  246.  
  247.     if (gamestate == GS_LEVEL && gametic)
  248.         HU_Erase();
  249.     
  250.     // do buffered drawing
  251.     switch (gamestate)
  252.     {
  253.       case GS_LEVEL:
  254.         if (!gametic)
  255.             break;
  256.         /* Map On Headup Patch - CDE - 97'
  257.         if (automapactive)
  258.             AM_Drawer ();
  259.         */
  260.         if (wipe || (viewheight != SCREENHEIGHT && fullscreen) )
  261.             redrawsbar = true;
  262.         if (inhelpscreensstate && !inhelpscreens)
  263.             redrawsbar = true;              // just put away the help screen
  264.         ST_Drawer (viewheight == SCREENHEIGHT, redrawsbar );
  265.         fullscreen = viewheight == SCREENHEIGHT;
  266.         break;
  267.  
  268.       case GS_INTERMISSION:
  269.         WI_Drawer ();
  270.         break;
  271.  
  272.       case GS_FINALE:
  273.         F_Drawer ();
  274.         break;
  275.  
  276.       case GS_DEMOSCREEN:
  277.         D_PageDrawer ();
  278.         break;
  279.     }
  280.     
  281.     // draw buffered stuff to screen
  282.     I_UpdateNoBlit ();
  283.     
  284.     // draw the view directly
  285.     if (gamestate == GS_LEVEL && (!automapactive || maponhu) && gametic)
  286.         R_RenderPlayerView (&players[displayplayer]);
  287.  
  288.     /* Map On HeadUp Patch - CDE 98' */
  289.     if (gamestate == GS_LEVEL && automapactive)
  290.         AM_Drawer ();
  291.  
  292.     if (gamestate == GS_LEVEL && gametic)
  293.         HU_Drawer ();
  294.     
  295.     // clean up border stuff
  296.     if (gamestate != oldgamestate && gamestate != GS_LEVEL)
  297.         I_SetPalette (W_CacheLumpName ("PLAYPAL",PU_CACHE), 0);
  298.  
  299.     // see if the border needs to be initially drawn
  300.     if (gamestate == GS_LEVEL && oldgamestate != GS_LEVEL)
  301.     {
  302.         viewactivestate = false;        // view was not active
  303.         R_FillBackScreen ();    // draw the pattern into the back screen
  304.     }
  305.  
  306.     // see if the border needs to be updated to the screen
  307.     if (gamestate == GS_LEVEL && (maponhu || !automapactive) /* && scaledviewwidth != 320 */)
  308.     {
  309.         if (menuactive || menuactivestate || !viewactivestate)
  310.             borderdrawcount = 3;
  311.         if (borderdrawcount)
  312.         {
  313.             R_DrawViewBorder ();    // erase old menu stuff
  314.             borderdrawcount--;
  315.         }
  316.     }
  317.  
  318.     maponhustate = maponhu; // CDE'98
  319.     menuactivestate = menuactive;
  320.     viewactivestate = viewactive;
  321.     inhelpscreensstate = inhelpscreens;
  322.     oldgamestate = wipegamestate = gamestate;
  323.     
  324.     // draw pause pic
  325.     if (paused)
  326.     {
  327.         if (automapactive)
  328.             y = 4;
  329.         else
  330.             y = viewwindowy+4;
  331.         V_DrawPatchDirect(viewwindowx+(scaledviewwidth-68)/2,
  332.                           y,0,W_CacheLumpName ("M_PAUSE", PU_CACHE));
  333.     }
  334.  
  335.  
  336.     // menus go directly to the screen
  337.     M_Drawer ();          // menu is drawn even on top of everything
  338.     NetUpdate ();         // send out any new accumulation
  339.  
  340.  
  341.     // normal update
  342.     if (!wipe)
  343.     {
  344.         I_FinishUpdate ();              // page flip or blit buffer
  345.         return;
  346.     }
  347.     
  348.     // wipe update
  349.     wipe_EndScreen(0, 0, SCREENWIDTH, SCREENHEIGHT);
  350.  
  351.     wipestart = I_GetTime () - 1;
  352.  
  353.     do
  354.     {
  355.         do
  356.         {
  357.             nowtime = I_GetTime ();
  358.             tics = nowtime - wipestart;
  359.         } while (!tics);
  360.         wipestart = nowtime;
  361.         done = wipe_ScreenWipe(wipe_Melt
  362.                                , 0, 0, SCREENWIDTH, SCREENHEIGHT, tics);
  363.         I_StartUpdate ();
  364.         I_UpdateNoBlit ();
  365.         M_Drawer ();                   // menu is drawn even on top of wipes
  366.         I_FinishUpdate ();             // page flip or blit buffer
  367.     } while (!done);
  368. }
  369.  
  370.  
  371.  
  372. //
  373. //  D_DoomLoop
  374. //
  375. extern  boolean         demorecording;
  376.  
  377. void D_DoomLoop (void)
  378. {
  379.     if (demorecording)
  380.         G_BeginRecording ();
  381.                 
  382.     if (M_CheckParm ("-debugfile"))
  383.     {
  384.         char    filename[20];
  385.         sprintf (filename,"debug%i.txt",consoleplayer);
  386.         printf ("debug output to: %s\n",filename);
  387.         debugfile = fopen (filename,"w");
  388.     }
  389.         
  390.     I_InitGraphics ();
  391.  
  392.     while (1)
  393.     {
  394.         // frame syncronous IO operations
  395.         I_StartFrame ();                
  396.         
  397.         // process one or more tics
  398.         if (singletics)
  399.         {
  400.             I_StartTic ();
  401.             D_ProcessEvents ();
  402.             G_BuildTiccmd (&netcmds[consoleplayer][maketic%BACKUPTICS]);
  403.             if (advancedemo)
  404.                 D_DoAdvanceDemo ();
  405.             M_Ticker ();
  406.             G_Ticker ();
  407.             gametic++;
  408.             maketic++;
  409.         }
  410.         else
  411.         {
  412.             TryRunTics (); // will run at least one tic
  413.         }
  414.                 
  415.         S_UpdateSounds (players[consoleplayer].mo);// move positional sounds
  416.  
  417.         // Update display, next frame, with current state.
  418.         D_Display ();
  419.  
  420. #if 0
  421. #ifndef SNDSERV
  422.         // Sound mixing for the buffer is snychronous.
  423.         I_UpdateSound();
  424. #endif  
  425.         // Synchronous sound output is explicitly called.
  426. #ifndef SNDINTR
  427.         // Update sound output.
  428.         I_SubmitSound();
  429. #endif
  430. #endif
  431.     }
  432. }
  433.  
  434.  
  435.  
  436. //
  437. //  DEMO LOOP
  438. //
  439. int             demosequence;
  440. int             pagetic;
  441. char                    *pagename;
  442.  
  443.  
  444. //
  445. // D_PageTicker
  446. // Handles timing for warped projection
  447. //
  448. void D_PageTicker (void)
  449. {
  450.     if (--pagetic < 0)
  451.         D_AdvanceDemo ();
  452. }
  453.  
  454.  
  455.  
  456. //
  457. // D_PageDrawer
  458. //
  459. void D_PageDrawer (void)
  460. {
  461.     V_DrawPatchInDirect (0,0, 0, W_CacheLumpName(pagename, PU_CACHE));
  462. }
  463.  
  464.  
  465. //
  466. // D_AdvanceDemo
  467. // Called after each demo or intro demosequence finishes
  468. //
  469. void D_AdvanceDemo (void)
  470. {
  471.     advancedemo = true;
  472. }
  473.  
  474.  
  475. //
  476. // This cycles through the demo sequences.
  477. // FIXME - version dependend demo numbers?
  478. //
  479.  void D_DoAdvanceDemo (void)
  480. {
  481.     players[consoleplayer].playerstate = PST_LIVE;  // not reborn
  482.     advancedemo = false;
  483.     usergame = false;               // no save / end game here
  484.     paused = false;
  485.     gameaction = ga_nothing;
  486.  
  487.     if ( gamemode == retail )
  488.       demosequence = (demosequence+1)%7;
  489.     else
  490.       demosequence = (demosequence+1)%6;
  491.     
  492.     switch (demosequence)
  493.     {
  494.       case 0:
  495.         if ( gamemode == commercial )
  496.             pagetic = 35 * 11;
  497.         else
  498.             pagetic = 170;
  499.         gamestate = GS_DEMOSCREEN;
  500.         pagename = "TITLEPIC";
  501.         if ( gamemode == commercial )
  502.           S_StartMusic(mus_dm2ttl);
  503.         else
  504.           S_StartMusic (mus_intro);
  505.         break;
  506.       case 1:
  507.         G_DeferedPlayDemo ("demo1");
  508.         break;
  509.       case 2:
  510.         pagetic = 200;
  511.         gamestate = GS_DEMOSCREEN;
  512.         pagename = "CREDIT";
  513.         break;
  514.       case 3:
  515.         G_DeferedPlayDemo ("demo2");
  516.         break;
  517.       case 4:
  518.         gamestate = GS_DEMOSCREEN;
  519.         if ( gamemode == commercial)
  520.         {
  521.             pagetic = 35 * 11;
  522.             pagename = "TITLEPIC";
  523.             S_StartMusic(mus_dm2ttl);
  524.         }
  525.         else
  526.         {
  527.             pagetic = 200;
  528.  
  529.             if ( gamemode == retail )
  530.               pagename = "CREDIT";
  531.             else
  532.               pagename = "HELP2";
  533.         }
  534.         break;
  535.       case 5:
  536.         G_DeferedPlayDemo ("demo3");
  537.         break;
  538.         // THE DEFINITIVE DOOM Special Edition demo
  539.       case 6:
  540.         G_DeferedPlayDemo ("demo4");
  541.         break;
  542.     }
  543. }
  544.  
  545.  
  546.  
  547. //
  548. // D_StartTitle
  549. //
  550. void D_StartTitle (void)
  551. {
  552.     gameaction = ga_nothing;
  553.     demosequence = -1;
  554.     D_AdvanceDemo ();
  555. }
  556.  
  557.  
  558.  
  559.  
  560. //      print title for every printed line
  561. char            title[128];
  562.  
  563.  
  564.  
  565. //
  566. // D_AddFile
  567. //
  568. void D_AddFile (char *file)
  569. {
  570.     int     numwadfiles;
  571.     char    *newfile;
  572.         
  573.     for (numwadfiles = 0 ; wadfiles[numwadfiles] ; numwadfiles++)
  574.         ;
  575.  
  576.     newfile = malloc (strlen(file)+1);
  577.     strcpy (newfile, file);
  578.         
  579.     wadfiles[numwadfiles] = newfile;
  580. }
  581.  
  582.  
  583. #ifdef DEBUGGING
  584. #define DIRSTRING ""
  585. #else
  586. #define DIRSTRING "PROGDIR:"
  587. #endif
  588.  
  589. //
  590. // IdentifyVersion
  591. // Checks availability of IWAD files by name,
  592. // to determine whether registered/commercial features
  593. // should be executed (notably loading PWAD's).
  594. //
  595. void IdentifyVersion (void)
  596. {
  597.     int         p;
  598.  
  599.     char*       doom1wad;
  600.     char*       doomwad;
  601.     char*       doomuwad;
  602.     char*       doom2wad;
  603.  
  604.     char*       doom2fwad;
  605.     char*       plutoniawad;
  606.     char*       tntwad;
  607.  
  608. #ifdef NORMALUNIX
  609.     static char home[256];
  610.     static char doomwaddir[256];
  611.  
  612.     if (getenv ("DOOMWADDIR") != NULL) {
  613.       strcpy (doomwaddir, getenv("DOOMWADDIR"));
  614.       if (doomwaddir[strlen(doomwaddir)-1] != '/' && doomwaddir[strlen(doomwaddir)-1] != ':')
  615.         strcat (doomwaddir, "/");
  616.     } else {
  617.       strcpy (doomwaddir, DIRSTRING);
  618.       p = M_CheckParm ("-waddir");
  619.       if (p) {
  620.         strcpy(doomwaddir, myargv[p+1]);
  621.         if (doomwaddir[strlen(doomwaddir)-1] != '/' && doomwaddir[strlen(doomwaddir)-1] != ':')
  622.           strcat (doomwaddir, "/");
  623.       }
  624.     }
  625.  
  626.     // Commercial.
  627.     doom2wad = malloc(strlen(doomwaddir)+1+9+1);
  628.     sprintf(doom2wad, "%sdoom2.wad", doomwaddir);
  629.  
  630.     // Retail.
  631.     doomuwad = malloc(strlen(doomwaddir)+1+8+1);
  632.     sprintf(doomuwad, "%sdoomu.wad", doomwaddir);
  633.     
  634.     // Registered.
  635.     doomwad = malloc(strlen(doomwaddir)+1+8+1);
  636.     sprintf(doomwad, "%sdoom.wad", doomwaddir);
  637.     
  638.     // Shareware.
  639.     doom1wad = malloc(strlen(doomwaddir)+1+9+1);
  640.     sprintf(doom1wad, "%sdoom1.wad", doomwaddir);
  641.  
  642.      // Bug, dear Shawn.
  643.     // Insufficient malloc, caused spurious realloc errors.
  644.     plutoniawad = malloc(strlen(doomwaddir)+1+/*9*/12+1);
  645.     sprintf(plutoniawad, "%splutonia.wad", doomwaddir);
  646.  
  647.     tntwad = malloc(strlen(doomwaddir)+1+9+1);
  648.     sprintf(tntwad, "%stnt.wad", doomwaddir);
  649.  
  650.  
  651.     // French stuff.
  652.     doom2fwad = malloc(strlen(doomwaddir)+1+10+1);
  653.     sprintf(doom2fwad, "%sdoom2f.wad", doomwaddir);
  654.  
  655. #ifdef __SASC
  656.     if (getenv ("HOME") != NULL) {
  657.       strcpy (home, getenv("HOME"));
  658.       if (home[strlen(home)-1] != '/' && home[strlen(home)-1] != ':')
  659.         strcat (home, "/");
  660.     } else
  661.       home[0] = '\0';
  662. #else
  663.     home = getenv ("HOME");
  664.     if (!home)
  665.       I_Error("Please set $HOME to your home directory");
  666. #endif
  667.     sprintf(basedefault, "%s.doomrc", home);
  668. #endif
  669.  
  670.     if (M_CheckParm ("-shdev"))
  671.     {
  672.         gamemode = shareware;
  673.         devparm = true;
  674.         D_AddFile (DEVDATA"doom1.wad");
  675.         D_AddFile (DEVMAPS"data_se/texture1.lmp");
  676.         D_AddFile (DEVMAPS"data_se/pnames.lmp");
  677.         strcpy (basedefault,DEVDATA"default.cfg");
  678.         return;
  679.     }
  680.  
  681.     if (M_CheckParm ("-regdev"))
  682.     {
  683.         gamemode = registered;
  684.         devparm = true;
  685.         D_AddFile (DEVDATA"doom.wad");
  686.         D_AddFile (DEVMAPS"data_se/texture1.lmp");
  687.         D_AddFile (DEVMAPS"data_se/texture2.lmp");
  688.         D_AddFile (DEVMAPS"data_se/pnames.lmp");
  689.         strcpy (basedefault,DEVDATA"default.cfg");
  690.         return;
  691.     }
  692.  
  693.     if (M_CheckParm ("-comdev"))
  694.     {
  695.         gamemode = commercial;
  696.         devparm = true;
  697.         /* I don't bother
  698.         if(plutonia)
  699.             D_AddFile (DEVDATA"plutonia.wad");
  700.         else if(tnt)
  701.             D_AddFile (DEVDATA"tnt.wad");
  702.         else*/
  703.             D_AddFile (DEVDATA"doom2.wad");
  704.             
  705.         D_AddFile (DEVMAPS"cdata/texture1.lmp");
  706.         D_AddFile (DEVMAPS"cdata/pnames.lmp");
  707.         strcpy (basedefault,DEVDATA"default.cfg");
  708.         return;
  709.     }
  710.  
  711.     if ( !access (doom2fwad,R_OK) )
  712.     {
  713.         gamemode = commercial;
  714.         // C'est ridicule!
  715.         // Let's handle languages in config files, okay?
  716.         language = french;
  717.         printf("French version\n");
  718.         D_AddFile (doom2fwad);
  719.         return;
  720.     }
  721.  
  722.     if ( !access (doom2wad,R_OK) )
  723.     {
  724.         gamemode = commercial;
  725.         D_AddFile (doom2wad);
  726.         return;
  727.     }
  728.  
  729.     if ( !access (plutoniawad, R_OK ) )
  730.     {
  731.       gamemode = commercial;
  732.       D_AddFile (plutoniawad);
  733.       return;
  734.     }
  735.  
  736.     if ( !access ( tntwad, R_OK ) )
  737.     {
  738.       gamemode = commercial;
  739.       D_AddFile (tntwad);
  740.       return;
  741.     }
  742.  
  743.     if ( !access (doomuwad,R_OK) )
  744.     {
  745.       gamemode = retail;
  746.       D_AddFile (doomuwad);
  747.       return;
  748.     }
  749.  
  750.     if ( !access (doomwad,R_OK) )
  751.     {
  752.       gamemode = registered;
  753.       D_AddFile (doomwad);
  754.       return;
  755.     }
  756.  
  757.     if ( !access (doom1wad,R_OK) )
  758.     {
  759.       gamemode = shareware;
  760.       D_AddFile (doom1wad);
  761.       return;
  762.     }
  763.  
  764.     printf("Game mode indeterminate.\n");
  765.     gamemode = indetermined;
  766.  
  767.     // We don't abort. Let's see what the PWAD contains.
  768.     //exit(1);
  769.     //I_Error ("Game mode indeterminate\n");
  770. }
  771.  
  772. //
  773. // Find a Response File
  774. //
  775. void FindResponseFile (void)
  776. {
  777.     int             i;
  778.         
  779.     for (i = 1;i < myargc;i++)
  780.         if (myargv[i][0] == '@')
  781.         {
  782.             FILE *          handle;
  783.             int             size;
  784.             int             k;
  785.             int             index;
  786.             int             indexinfile;
  787.             char    *infile;
  788.             char    *file;
  789.             char    *moreargs[20];
  790.             char    *firstargv;
  791.                         
  792.             // READ THE RESPONSE FILE INTO MEMORY
  793.             handle = fopen (&myargv[i][1],"rb");
  794.             if (!handle)
  795.             {
  796.                 printf ("\nNo such response file!");
  797.                 exit(1);
  798.             }
  799.             printf("Found response file %s!\n",&myargv[i][1]);
  800.             fseek (handle,0,SEEK_END);
  801.             size = ftell(handle);
  802.             fseek (handle,0,SEEK_SET);
  803.             file = malloc (size);
  804.             fread (file,size,1,handle);
  805.             fclose (handle);
  806.                         
  807.             // KEEP ALL CMDLINE ARGS FOLLOWING @RESPONSEFILE ARG
  808.             for (index = 0,k = i+1; k < myargc; k++)
  809.                 moreargs[index++] = myargv[k];
  810.                         
  811.             firstargv = myargv[0];
  812.             myargv = malloc(sizeof(char *)*MAXARGVS);
  813.             memset(myargv,0,sizeof(char *)*MAXARGVS);
  814.             myargv[0] = firstargv;
  815.                         
  816.             infile = file;
  817.             indexinfile = k = 0;
  818.             indexinfile++;  // SKIP PAST ARGV[0] (KEEP IT)
  819.             do
  820.             {
  821.                 myargv[indexinfile++] = infile+k;
  822.                 while(k < size &&
  823.                       ((*(infile+k)>= ' '+1) && (*(infile+k)<='z')))
  824.                     k++;
  825.                 *(infile+k) = 0;
  826.                 while(k < size &&
  827.                       ((*(infile+k)<= ' ') || (*(infile+k)>'z')))
  828.                     k++;
  829.             } while(k < size);
  830.                         
  831.             for (k = 0;k < index;k++)
  832.                 myargv[indexinfile++] = moreargs[k];
  833.             myargc = indexinfile;
  834.         
  835.             // DISPLAY ARGS
  836.             printf("%d command-line args:\n",myargc);
  837.             for (k=1;k<myargc;k++)
  838.                 printf("%s\n",myargv[k]);
  839.  
  840.             break;
  841.         }
  842. }
  843.  
  844.  
  845. //
  846. // D_DoomMain
  847. //
  848. void D_DoomMain (void)
  849. {
  850.     int             p;
  851.     char            file[256];
  852.  
  853.     FindResponseFile ();
  854.         
  855.     IdentifyVersion ();
  856.         
  857.     setbuf (stdout, NULL);
  858.     modifiedgame = false;
  859.         
  860.     nomonsters = M_CheckParm ("-nomonsters");
  861.     respawnparm = M_CheckParm ("-respawn");
  862.     fastparm = M_CheckParm ("-fast");
  863.     rotatemap = M_CheckParm ("-rotatemap");
  864.     devparm = M_CheckParm ("-devparm");
  865.     maponhu = (M_CheckParm ("-maponhu") != 0);
  866.  
  867.     if (M_CheckParm ("-altdeath"))
  868.         deathmatch = 2;
  869.     else if (M_CheckParm ("-deathmatch"))
  870.         deathmatch = 1;
  871.  
  872.     switch ( gamemode )
  873.     {
  874.       case retail:
  875.         sprintf (title,
  876.                  "                         "
  877.                  "The Ultimate DOOM Startup v%i.%i"
  878.                  "                           ",
  879.                  VERSION/100,VERSION%100);
  880.         break;
  881.       case shareware:
  882.         sprintf (title,
  883.                  "                            "
  884.                  "DOOM Shareware Startup v%i.%i"
  885.                  "                           ",
  886.                  VERSION/100,VERSION%100);
  887.         break;
  888.       case registered:
  889.         sprintf (title,
  890.                  "                            "
  891.                  "DOOM Registered Startup v%i.%i"
  892.                  "                           ",
  893.                  VERSION/100,VERSION%100);
  894.         break;
  895.       case commercial:
  896.         sprintf (title,
  897.                  "                         "
  898.                  "DOOM 2: Hell on Earth v%i.%i"
  899.                  "                           ",
  900.                  VERSION/100,VERSION%100);
  901.         break;
  902. /*FIXME
  903.        case pack_plut:
  904.         sprintf (title,
  905.                  "                   "
  906.                  "DOOM 2: Plutonia Experiment v%i.%i"
  907.                  "                           ",
  908.                  VERSION/100,VERSION%100);
  909.         break;
  910.       case pack_tnt:
  911.         sprintf (title,
  912.                  "                     "
  913.                  "DOOM 2: TNT - Evilution v%i.%i"
  914.                  "                           ",
  915.                  VERSION/100,VERSION%100);
  916.         break;
  917. */
  918.       default:
  919.         sprintf (title,
  920.                  "                     "
  921.                  "Public DOOM - v%i.%i"
  922.                  "                           ",
  923.                  VERSION/100,VERSION%100);
  924.         break;
  925.     }
  926.     
  927.     printf ("%s\n",title);
  928.  
  929.     if (devparm)
  930.         printf(D_DEVSTR);
  931.     
  932.     if (M_CheckParm("-cdrom"))
  933.     {
  934.         printf(D_CDROM);
  935. #ifdef __SASC
  936.         mkdir("c:\\doomdata");
  937. #else
  938.         mkdir("c:\\doomdata",0);
  939. #endif
  940.         strcpy (basedefault,"c:/doomdata/default.cfg");
  941.     }   
  942.     
  943.     // turbo option
  944.     if ( (p=M_CheckParm ("-turbo")) )
  945.     {
  946.         int     scale = 200;
  947.         extern int forwardmove[2];
  948.         extern int sidemove[2];
  949.         
  950.         if (p<myargc-1)
  951.             scale = atoi (myargv[p+1]);
  952.         if (scale < 10)
  953.             scale = 10;
  954.         if (scale > 400)
  955.             scale = 400;
  956.         printf ("turbo scale: %i%%\n",scale);
  957.         forwardmove[0] = forwardmove[0]*scale/100;
  958.         forwardmove[1] = forwardmove[1]*scale/100;
  959.         sidemove[0] = sidemove[0]*scale/100;
  960.         sidemove[1] = sidemove[1]*scale/100;
  961.     }
  962.     
  963.     // add any files specified on the command line with -file wadfile
  964.     // to the wad list
  965.     //
  966.     // convenience hack to allow -wart e m to add a wad file
  967.     // prepend a tilde to the filename so wadfile will be reloadable
  968.     p = M_CheckParm ("-wart");
  969.     if (p)
  970.     {
  971.         myargv[p][4] = 'p';     // big hack, change to -warp
  972.  
  973.         // Map name handling.
  974.         switch (gamemode )
  975.         {
  976.           case shareware:
  977.           case retail:
  978.           case registered:
  979.             sprintf (file,"~"DEVMAPS"E%cM%c.wad",
  980.                      myargv[p+1][0], myargv[p+2][0]);
  981.             printf("Warping to Episode %s, Map %s.\n",
  982.                    myargv[p+1],myargv[p+2]);
  983.             break;
  984.             
  985.           case commercial:
  986.           default:
  987.             p = atoi (myargv[p+1]);
  988.             if (p<10)
  989.               sprintf (file,"~"DEVMAPS"cdata/map0%i.wad", p);
  990.             else
  991.               sprintf (file,"~"DEVMAPS"cdata/map%i.wad", p);
  992.             break;
  993.         }
  994.         D_AddFile (file);
  995.     }
  996.         
  997.     p = M_CheckParm ("-file");
  998.     if (p)
  999.     {
  1000.         // the parms after p are wadfile/lump names,
  1001.         // until end of parms or another - preceded parm
  1002.         modifiedgame = true;            // homebrew levels
  1003.         while (++p != myargc && myargv[p][0] != '-')
  1004.             D_AddFile (myargv[p]);
  1005.     }
  1006.  
  1007.     /* DeHacked Patch !! */
  1008.     p = M_CheckParm ("-deh");
  1009.     if (p)
  1010.     {
  1011.         // the parms after p are wadfile/lump names,
  1012.         // until end of parms or another - preceded parm
  1013.         //modifiedgame = true;            // homebrew levels
  1014.         while (++p != myargc && myargv[p][0] != '-')
  1015.             DE_AddDeh(myargv[p]);
  1016.     }
  1017.  
  1018.     p = M_CheckParm ("-playdemo");
  1019.  
  1020.     if (!p)
  1021.         p = M_CheckParm ("-timedemo");
  1022.  
  1023.     if (p && p < myargc-1)
  1024.     {
  1025.         sprintf (file,"%s.lmp", myargv[p+1]);
  1026.         D_AddFile (file);
  1027.         printf("Playing demo %s.lmp.\n",myargv[p+1]);
  1028.     }
  1029.     
  1030.     // get skill / episode / map from parms
  1031.     startskill = sk_medium;
  1032.     startepisode = 1;
  1033.     startmap = 1;
  1034.     autostart = false;
  1035.  
  1036.                 
  1037.     p = M_CheckParm ("-skill");
  1038.     if (p && p < myargc-1)
  1039.     {
  1040.         startskill = myargv[p+1][0]-'1';
  1041.         autostart = true;
  1042.     }
  1043.  
  1044.     p = M_CheckParm ("-episode");
  1045.     if (p && p < myargc-1)
  1046.     {
  1047.         startepisode = myargv[p+1][0]-'0';
  1048.         startmap = 1;
  1049.         autostart = true;
  1050.     }
  1051.         
  1052.     p = M_CheckParm ("-timer");
  1053.     if (p && p < myargc-1 && deathmatch)
  1054.     {
  1055.         int     time;
  1056.         time = atoi(myargv[p+1]);
  1057.         printf("Levels will end after %d minute",time);
  1058.         if (time>1)
  1059.             printf("s");
  1060.         printf(".\n");
  1061.     }
  1062.  
  1063.     p = M_CheckParm ("-avg");
  1064.     if (p && p < myargc-1 && deathmatch)
  1065.         printf("Austin Virtual Gaming: Levels will end after 20 minutes\n");
  1066.  
  1067.     p = M_CheckParm ("-warp");
  1068.     if (p && p < myargc-1)
  1069.     {
  1070.         if (gamemode == commercial)
  1071.             startmap = atoi (myargv[p+1]);
  1072.         else
  1073.         {
  1074.             startepisode = myargv[p+1][0]-'0';
  1075.             startmap = myargv[p+2][0]-'0';
  1076.         }
  1077.         autostart = true;
  1078.     }
  1079.     
  1080.     // init subsystems
  1081.     printf ("V_Init: allocate screens.\n");
  1082.     V_Init ();
  1083.  
  1084.     printf ("M_LoadDefaults: Load system defaults.\n");
  1085.     M_LoadDefaults ();              // load before initing other systems
  1086.  
  1087.     printf ("Z_Init: Init zone memory allocation daemon. \n");
  1088.     Z_Init ();
  1089.  
  1090.     printf ("W_Init: Init WADfiles.\n");
  1091.     W_InitMultipleFiles (wadfiles);
  1092.     
  1093.  
  1094.     // Check for -file in shareware
  1095.     if (modifiedgame)
  1096.     {
  1097.         // These are the lumps that will be checked in IWAD,
  1098.         // if any one is not present, execution will be aborted.
  1099.         char name[23][8]=
  1100.         {
  1101.             "e2m1","e2m2","e2m3","e2m4","e2m5","e2m6","e2m7","e2m8","e2m9",
  1102.             "e3m1","e3m3","e3m3","e3m4","e3m5","e3m6","e3m7","e3m8","e3m9",
  1103.             "dphoof","bfgga0","heada1","cybra1","spida1d1"
  1104.         };
  1105.         int i;
  1106.         
  1107.         if ( gamemode == shareware)
  1108.             I_Error("\nYou cannot -file with the shareware "
  1109.                     "version. Register!");
  1110.  
  1111.         // Check for fake IWAD with right name,
  1112.         // but w/o all the lumps of the registered version. 
  1113.         if (gamemode == registered)
  1114.             for (i = 0;i < 23; i++)
  1115.                 if (W_CheckNumForName(name[i])<0)
  1116.                     I_Error("\nThis is not the registered version.");
  1117.     }
  1118.     
  1119.     // Iff additonal PWAD files are used, print modified banner
  1120.     if (modifiedgame)
  1121.     {
  1122.         /*m*/printf (
  1123.             "===========================================================================\n"
  1124.             "ATTENTION:  This version of DOOM has been modified.  If you would like to\n"
  1125.             "get a copy of the original game, call 1-800-IDGAMES or see the readme file.\n"
  1126.             "        You will not receive technical support for modified games.\n"
  1127.             "                      press enter to continue\n"
  1128.             "===========================================================================\n"
  1129.             );
  1130.         getchar ();
  1131.     }
  1132.         
  1133.  
  1134.     // Check and print which version is executed.
  1135.     switch ( gamemode )
  1136.     {
  1137.       case shareware:
  1138.       case indetermined:
  1139.         printf (
  1140.             "===========================================================================\n"
  1141.             "                                Shareware!\n"
  1142.             "===========================================================================\n"
  1143.         );
  1144.         break;
  1145.       case registered:
  1146.       case retail:
  1147.       case commercial:
  1148.         printf (
  1149.             "===========================================================================\n"
  1150.             "                 Commercial product - do not distribute!\n"
  1151.             "         Please report software piracy to the SPA: 1-800-388-PIR8\n"
  1152.             "===========================================================================\n"
  1153.         );
  1154.         break;
  1155.         
  1156.       default:
  1157.         // Ouch.
  1158.         break;
  1159.     }
  1160.  
  1161.     printf ("M_Init: Init miscellaneous info.\n");
  1162.     M_Init ();
  1163.  
  1164.     printf ("R_Init: Init DOOM refresh daemon - ");
  1165.     R_Init ();
  1166.  
  1167.     printf ("\nP_Init: Init Playloop state.\n");
  1168.     P_Init ();
  1169.  
  1170.     printf ("I_Init: Setting up machine state.\n");
  1171.     I_Init ();
  1172.  
  1173.     printf ("D_CheckNetGame: Checking network game status.\n");
  1174.     D_CheckNetGame ();
  1175.  
  1176.     printf ("S_Init: Setting up sound.\n");
  1177.     S_Init (snd_SfxVolume /* *8 */, snd_MusicVolume /* *8*/ );
  1178.  
  1179.     printf ("HU_Init: Setting up heads up display.\n");
  1180.     HU_Init ();
  1181.  
  1182.     printf ("ST_Init: Init status bar.\n");
  1183.     ST_Init ();
  1184.  
  1185.     // check for a driver that wants intermission stats
  1186.     p = M_CheckParm ("-statcopy");
  1187.     if (p && p<myargc-1)
  1188.     {
  1189.         // for statistics driver
  1190.         extern  void*   statcopy;                            
  1191.  
  1192.         statcopy = (void*)atoi(myargv[p+1]);
  1193.         printf ("External statistics registered.\n");
  1194.     }
  1195.     
  1196.     // start the apropriate game based on parms
  1197.     p = M_CheckParm ("-record");
  1198.  
  1199.     if (p && p < myargc-1)
  1200.     {
  1201.         G_RecordDemo (myargv[p+1]);
  1202.         autostart = true;
  1203.     }
  1204.         
  1205.     p = M_CheckParm ("-playdemo");
  1206.     if (p && p < myargc-1)
  1207.     {
  1208.         singledemo = true;              // quit after one demo
  1209.         G_DeferedPlayDemo (myargv[p+1]);
  1210.         D_DoomLoop ();  // never returns
  1211.     }
  1212.         
  1213.     p = M_CheckParm ("-timedemo");
  1214.     if (p && p < myargc-1)
  1215.     {
  1216.         G_TimeDemo (myargv[p+1]);
  1217.         D_DoomLoop ();  // never returns
  1218.     }
  1219.         
  1220.     p = M_CheckParm ("-loadgame");
  1221.     if (p && p < myargc-1)
  1222.     {
  1223.         if (M_CheckParm("-cdrom"))
  1224.             sprintf(file, "c:\\doomdata\\"SAVEGAMENAME"%c.dsg",myargv[p+1][0]);
  1225.         else
  1226.             sprintf(file, SAVEGAMENAME"%c.dsg",myargv[p+1][0]);
  1227.         G_LoadGame (file);
  1228.     }
  1229.         
  1230.  
  1231.     if ( gameaction != ga_loadgame )
  1232.     {
  1233.         if (autostart || netgame)
  1234.             G_InitNew (startskill, startepisode, startmap);
  1235.         else
  1236.             D_StartTitle ();                // start up intro loop
  1237.  
  1238.     }
  1239.  
  1240.     D_DoomLoop ();  // never returns
  1241. }
  1242.