d_main.c
上传用户:xuyinpeng
上传日期:2021-05-12
资源大小:455k
文件大小:35k
源码类别:

射击游戏

开发平台:

Visual C++

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