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