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