Subversion Repositories Kolibri OS

Rev

Rev 298 | Blame | Last modification | View Log | Download | RSS feed

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