]> icculus.org git repositories - theoddone33/hheretic.git/blob - base/d_main.c
Initial revision
[theoddone33/hheretic.git] / base / d_main.c
1
2 // D_main.c
3
4 #ifdef __WATCOMC__
5 #include <dos.h>
6 #include <graph.h>
7 #include <sys\types.h>
8 #include <direct.h>
9 #endif
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include "doomdef.h"
13 #include "p_local.h"
14 #include "soundst.h"
15
16 #ifdef RENDER3D
17 #include "ogl_def.h"
18 #define W_CacheLumpName(a,b)        W_GetNumForName(a)
19 #define V_DrawPatch(x,y,p)          OGL_DrawPatch(x,y,p)
20 #define V_DrawRawScreen(a)          OGL_DrawRawScreen(a)
21 #endif
22
23 boolean shareware = false;              // true if only episode 1 present
24 boolean ExtendedWAD = false;    // true if episodes 4 and 5 present
25
26 boolean nomonsters;                     // checkparm of -nomonsters
27 boolean respawnparm;                    // checkparm of -respawn
28 boolean debugmode;                      // checkparm of -debug
29 boolean ravpic;                         // checkparm of -ravpic
30 boolean cdrom;                                  // true if cd-rom mode active
31 boolean singletics;                     // debug flag to cancel adaptiveness
32 boolean noartiskip;                     // whether shift-enter skips an artifact
33
34 skill_t startskill;
35 int startepisode;
36 int startmap;
37 boolean autostart;
38 extern boolean automapactive;
39
40 boolean advancedemo;
41
42 FILE *debugfile;
43
44 void D_CheckNetGame(void);
45 void D_ProcessEvents(void);
46 void G_BuildTiccmd(ticcmd_t *cmd);
47 void D_DoAdvanceDemo(void);
48 void D_PageDrawer (void);
49 void D_AdvanceDemo (void);
50 void F_Drawer(void);
51 boolean F_Responder(event_t *ev);
52
53 //---------------------------------------------------------------------------
54 //
55 // FUNC FixedDiv
56 //
57 //---------------------------------------------------------------------------
58
59 fixed_t FixedDiv(fixed_t a, fixed_t b)
60 {
61         if((abs(a)>>14) >= abs(b))
62         {
63                 return((a^b)<0 ? MININT : MAXINT);
64         }
65         return(FixedDiv2(a, b));
66 }
67
68 /*
69 ===============================================================================
70
71                                                         EVENT HANDLING
72
73 Events are asyncronous inputs generally generated by the game user.
74
75 Events can be discarded if no responder claims them
76
77 ===============================================================================
78 */
79
80 event_t events[MAXEVENTS];
81 int eventhead;
82 int eventtail;
83
84 //---------------------------------------------------------------------------
85 //
86 // PROC D_PostEvent
87 //
88 // Called by the I/O functions when input is detected.
89 //
90 //---------------------------------------------------------------------------
91
92 void D_PostEvent(event_t *ev)
93 {
94         events[eventhead] = *ev;
95         eventhead = (++eventhead)&(MAXEVENTS-1);
96 }
97
98 //---------------------------------------------------------------------------
99 //
100 // PROC D_ProcessEvents
101 //
102 // Send all the events of the given timestamp down the responder chain.
103 //
104 //---------------------------------------------------------------------------
105
106 void D_ProcessEvents(void)
107 {
108         event_t *ev;
109
110         for(; eventtail != eventhead; eventtail = (++eventtail)&(MAXEVENTS-1))
111         {
112                 ev = &events[eventtail];
113                 if(F_Responder(ev))
114                 {
115                         continue;
116                 }
117                 if(MN_Responder(ev))
118                 {
119                         continue;
120                 }
121                 G_Responder(ev);
122         }
123 }
124
125 //---------------------------------------------------------------------------
126 //
127 // PROC DrawMessage
128 //
129 //---------------------------------------------------------------------------
130
131 void DrawMessage(void)
132 {
133         player_t *player;
134
135         player = &players[consoleplayer];
136         if(player->messageTics <= 0 || !player->message)
137         { // No message
138                 return;
139         }
140         MN_DrTextA(player->message, 160-MN_TextAWidth(player->message)/2, 1);
141 }
142
143 //---------------------------------------------------------------------------
144 //
145 // PROC D_Display
146 //
147 // Draw current display, possibly wiping it from the previous.
148 //
149 //---------------------------------------------------------------------------
150
151 void R_ExecuteSetViewSize(void);
152
153 extern boolean finalestage;
154
155 void D_Display(void)
156 {
157         extern boolean MenuActive;
158         extern boolean askforquit;
159
160         // Change the view size if needed
161         if(setsizeneeded)
162         {
163                 R_ExecuteSetViewSize();
164         }
165
166 //
167 // do buffered drawing
168 //
169         switch (gamestate)
170         {
171         case GS_LEVEL:
172                 if (!gametic)
173                         break;
174                 if (automapactive)
175                         AM_Drawer ();
176                 else
177                         R_RenderPlayerView (&players[displayplayer]);
178                 CT_Drawer();
179                 UpdateState |= I_FULLVIEW;
180                 SB_Drawer();
181                 break;
182         case GS_INTERMISSION:
183                 IN_Drawer ();
184                 break;
185         case GS_FINALE:
186                 F_Drawer ();
187                 break;
188         case GS_DEMOSCREEN:
189                 D_PageDrawer ();
190                 break;
191         }
192
193         if(paused && !MenuActive && !askforquit)
194         {
195                 if(!netgame)
196                 {
197                         V_DrawPatch(160, viewwindowy+5, W_CacheLumpName("PAUSED",
198                                 PU_CACHE));
199                 }
200                 else
201                 {
202                         V_DrawPatch(160, 70, W_CacheLumpName("PAUSED",
203                                 PU_CACHE));
204                 }
205         }
206
207 #ifdef RENDER3D
208     if( OGL_DrawFilter() )
209         BorderNeedRefresh = true;
210 #endif
211
212         // Handle player messages
213         DrawMessage();
214
215         // Menu drawing
216         MN_Drawer();
217
218         // Send out any new accumulation
219         NetUpdate();
220
221         // Flush buffered stuff to screen
222         I_Update();
223 }
224
225 //---------------------------------------------------------------------------
226 //
227 // PROC D_DoomLoop
228 //
229 //---------------------------------------------------------------------------
230
231 void D_DoomLoop(void)
232 {
233         if(M_CheckParm("-debugfile"))
234         {
235                 char filename[20];
236                 sprintf(filename, "debug%i.txt", consoleplayer);
237                 debugfile = fopen(filename,"w");
238         }
239         I_InitGraphics();
240         while(1)
241         {
242                 // Frame syncronous IO operations
243                 I_StartFrame();
244
245                 // Process one or more tics
246                 if(singletics)
247                 {
248                         I_StartTic();
249                         D_ProcessEvents();
250                         G_BuildTiccmd(&netcmds[consoleplayer][maketic%BACKUPTICS]);
251                         if (advancedemo)
252                                 D_DoAdvanceDemo ();
253                         G_Ticker();
254                         gametic++;
255                         maketic++;
256                 }
257                 else
258                 {
259                         // Will run at least one tic
260                         TryRunTics();
261                 }
262
263                 // Move positional sounds
264                 S_UpdateSounds(players[consoleplayer].mo);
265                 D_Display();
266         }
267 }
268
269 /*
270 ===============================================================================
271
272                                                 DEMO LOOP
273
274 ===============================================================================
275 */
276
277 int             demosequence;
278 int             pagetic;
279 char            *pagename;
280
281
282 /*
283 ================
284 =
285 = D_PageTicker
286 =
287 = Handles timing for warped projection
288 =
289 ================
290 */
291
292 void D_PageTicker (void)
293 {
294         if (--pagetic < 0)
295                 D_AdvanceDemo ();
296 }
297
298
299 /*
300 ================
301 =
302 = D_PageDrawer
303 =
304 ================
305 */
306
307 extern boolean MenuActive;
308
309 void D_PageDrawer(void)
310 {
311         V_DrawRawScreen(W_CacheLumpName(pagename, PU_CACHE));
312         if(demosequence == 1)
313         {
314                 V_DrawPatch(4, 160, W_CacheLumpName("ADVISOR", PU_CACHE));
315         }
316         UpdateState |= I_FULLSCRN;
317 }
318
319 /*
320 =================
321 =
322 = D_AdvanceDemo
323 =
324 = Called after each demo or intro demosequence finishes
325 =================
326 */
327
328 void D_AdvanceDemo (void)
329 {
330         advancedemo = true;
331 }
332
333 void D_DoAdvanceDemo (void)
334 {
335         players[consoleplayer].playerstate = PST_LIVE;  // don't reborn
336         advancedemo = false;
337         usergame = false;               // can't save / end game here
338         paused = false;
339         gameaction = ga_nothing;
340         demosequence = (demosequence+1)%7;
341         switch (demosequence)
342         {
343                 case 0:
344                         pagetic = 210;
345                         gamestate = GS_DEMOSCREEN;
346                         pagename = "TITLE";
347                         S_StartSong(mus_titl, false);
348                         break;
349                 case 1:
350                         pagetic = 140;
351                         gamestate = GS_DEMOSCREEN;
352                         pagename = "TITLE";
353                         break;
354                 case 2:
355                         BorderNeedRefresh = true;
356                         UpdateState |= I_FULLSCRN;
357                         G_DeferedPlayDemo ("demo1");
358                         break;
359                 case 3:
360                         pagetic = 200;
361                         gamestate = GS_DEMOSCREEN;
362                         pagename = "CREDIT";
363                         break;
364                 case 4:
365                         BorderNeedRefresh = true;
366                         UpdateState |= I_FULLSCRN;
367                         G_DeferedPlayDemo ("demo2");
368                         break;
369                 case 5:
370                         pagetic = 200;
371                         gamestate = GS_DEMOSCREEN;
372                         if(shareware)
373                         {
374                                 pagename = "ORDER";
375                         }
376                         else
377                         {
378                                 pagename = "CREDIT";
379                         }
380                         break;
381                 case 6:
382                         BorderNeedRefresh = true;
383                         UpdateState |= I_FULLSCRN;
384                         G_DeferedPlayDemo ("demo3");
385                         break;
386         }
387 }
388
389
390 /*
391 =================
392 =
393 = D_StartTitle
394 =
395 =================
396 */
397
398 void D_StartTitle (void)
399 {
400         gameaction = ga_nothing;
401         demosequence = -1;
402         D_AdvanceDemo ();
403 }
404
405
406 /*
407 ==============
408 =
409 = D_CheckRecordFrom
410 =
411 = -recordfrom <savegame num> <demoname>
412 ==============
413 */
414
415 void D_CheckRecordFrom (void)
416 {
417         int     p;
418         char    file[256];
419
420         p = M_CheckParm ("-recordfrom");
421         if (!p || p > myargc-2)
422                 return;
423
424         if(cdrom)
425         {
426                 sprintf(file, SAVEGAMENAMECD"%c.hsg",myargv[p+1][0]);
427         }
428         else
429         {
430                 sprintf(file, SAVEGAMENAME"%c.hsg",myargv[p+1][0]);
431         }
432         G_LoadGame (file);
433         G_DoLoadGame ();    // load the gameskill etc info from savegame
434
435         G_RecordDemo (gameskill, 1, gameepisode, gamemap, myargv[p+2]);
436         D_DoomLoop ();  // never returns
437 }
438
439 /*
440 ===============
441 =
442 = D_AddFile
443 =
444 ===============
445 */
446
447 #define MAXWADFILES 20
448
449 // MAPDIR should be defined as the directory that holds development maps
450 // for the -wart # # command
451
452 #ifdef __NeXT__
453
454 #define MAPDIR "/Novell/Heretic/data/"
455
456 #define SHAREWAREWADNAME "/Novell/Heretic/source/heretic1.wad"
457
458 char *wadfiles[MAXWADFILES] =
459 {
460         "/Novell/Heretic/source/heretic.wad",
461         "/Novell/Heretic/data/texture1.lmp",
462         "/Novell/Heretic/data/texture2.lmp",
463         "/Novell/Heretic/data/pnames.lmp"
464 };
465
466 #else
467
468 #define MAPDIR "\\data\\"
469
470 #define SHAREWAREWADNAME "heretic1.wad"
471
472 char *wadfiles[MAXWADFILES] =
473 {
474         "heretic.wad",
475         "texture1.lmp",
476         "texture2.lmp",
477         "pnames.lmp"
478 };
479
480 #endif
481
482 char *basedefault = "heretic.cfg";
483
484 char exrnwads[80];
485 char exrnwads2[80];
486
487 void wadprintf(void)
488 {
489         if(debugmode)
490         {
491                 return;
492         }
493         #ifdef __WATCOMC__
494         _settextposition(23, 2);
495         _setbkcolor(1);
496         _settextcolor(0);
497         _outtext(exrnwads);
498         _settextposition(24, 2);
499         _outtext(exrnwads2);
500         #endif
501 }
502
503 void D_AddFile(char *file)
504 {
505         int numwadfiles;
506         char *new;
507 //      char text[256];
508
509         for(numwadfiles = 0; wadfiles[numwadfiles]; numwadfiles++);
510         new = malloc(strlen(file)+1);
511         strcpy(new, file);
512         if(strlen(exrnwads)+strlen(file) < 78)
513         {
514                 if(strlen(exrnwads))
515                 {
516                         strcat(exrnwads, ", ");
517                 }
518                 else
519                 {
520                         strcpy(exrnwads, "External Wadfiles: ");
521                 }
522                 strcat(exrnwads, file);
523         }
524         else if(strlen(exrnwads2)+strlen(file) < 79)
525         {
526                 if(strlen(exrnwads2))
527                 {
528                         strcat(exrnwads2, ", ");
529                 }
530                 else
531                 {
532                         strcpy(exrnwads2, "     ");
533                         strcat(exrnwads, ",");
534                 }
535                 strcat(exrnwads2, file);
536         }
537         wadfiles[numwadfiles] = new;
538 }
539
540 //==========================================================
541 //
542 //  Startup Thermo code
543 //
544 //==========================================================
545 #define MSG_Y       9
546 //#define THERM_X 15
547 //#define THERM_Y 16
548 //#define THERMCOLOR  3
549 #define THERM_X     14
550 #define THERM_Y     14
551
552 int thermMax;
553 int thermCurrent;
554 char    *startup;           // * to text screen
555 char smsg[80];      // status bar line
556
557 //
558 //  Heretic startup screen shit
559 //
560
561 byte *hscreen;
562
563 void hgotoxy(int x,int y)
564 {
565         hscreen = (byte *)(0xb8000 + y*160 + x*2);
566 }
567
568 void hput(unsigned char c, unsigned char a)
569 {
570         *hscreen++ = c;
571         *hscreen++ = a;
572 }
573
574 void hprintf(char *string, unsigned char a)
575 {
576 #ifdef __WATCOMC__
577         int i;
578
579         if(debugmode)
580         {
581                 puts(string);
582                 return;
583         }
584         for(i = 0; i < strlen(string); i++)
585         {
586                 hput(string[i], a);
587         }
588 #endif
589 }
590
591 void drawstatus(void)
592 {
593         if(debugmode)
594         {
595                 return;
596         }
597         #ifdef __WATCOMC__
598         _settextposition(25, 2);
599         _setbkcolor(1);
600         _settextcolor(15);
601         _outtext(smsg);
602         _settextposition(25, 1);
603         #endif
604 }
605
606 void status(char *string)
607 {
608         strcat(smsg,string);
609         drawstatus();
610 }
611
612 void DrawThermo(void)
613 {
614         #ifdef __WATCOMC__
615         unsigned char       *screen;
616         int     progress;
617         int     i;
618
619         if(debugmode)
620         {
621                 return;
622         }
623 #if 0
624         progress = (98*thermCurrent)/thermMax;
625         screen = (char *)0xb8000 + (THERM_Y*160 + THERM_X*2);
626         for (i = 0;i < progress/2; i++)
627         {
628                 switch(i)
629                 {
630                         case 4:
631                         case 9:
632                         case 14:
633                         case 19:
634                         case 29:
635                         case 34:
636                         case 39:
637                         case 44:
638                                 *screen++ = 0xb3;
639                                 *screen++ = (THERMCOLOR<<4)+15;
640                                 break;
641                         case 24:
642                                 *screen++ = 0xba;
643                                 *screen++ = (THERMCOLOR<<4)+15;
644                                 break;
645                         default:
646                                 *screen++ = 0xdb;
647                                 *screen++ = 0x40 + THERMCOLOR;
648                                 break;
649                 }
650         }
651         if (progress&1)
652         {
653                 *screen++ = 0xdd;
654                 *screen++ = 0x40 + THERMCOLOR;
655         }
656 #else
657         progress = (50*thermCurrent)/thermMax+2;
658 //  screen = (char *)0xb8000 + (THERM_Y*160 + THERM_X*2);
659         hgotoxy(THERM_X,THERM_Y);
660         for (i = 0; i < progress; i++)
661         {
662 //      *screen++ = 0xdb;
663 //      *screen++ = 0x2a;
664                 hput(0xdb,0x2a);
665         }
666 #endif
667         #endif
668 }
669
670 #ifdef __WATCOMC__
671 void blitStartup(void)
672 {
673         byte *textScreen;
674
675         if(debugmode)
676         {
677                 return;
678         }
679
680         // Blit main screen
681         textScreen = (byte *)0xb8000;
682         memcpy(textScreen, startup, 4000);
683
684         // Print version string
685         _setbkcolor(4); // Red
686         _settextcolor(14); // Yellow
687         _settextposition(3, 47);
688         _outtext(VERSION_TEXT);
689
690         // Hide cursor
691         _settextcursor(0x2000);
692 }
693 #endif
694
695 char tmsg[300];
696 void tprintf(char *msg,int initflag)
697 {
698         #ifdef __WATCOMC__
699         char    temp[80];
700         int start;
701         int add;
702         int i;
703         #endif
704
705         if(debugmode)
706         {
707                 printf(msg);
708                 return;
709         }
710         #ifdef __WATCOMC__
711         if (initflag)
712                 tmsg[0] = 0;
713         strcat(tmsg,msg);
714         blitStartup();
715         DrawThermo();
716         _setbkcolor(4);
717         _settextcolor(15);
718         for (add = start = i = 0; i <= strlen(tmsg); i++)
719                 if ((tmsg[i] == '\n') || (!tmsg[i]))
720                 {
721                         memset(temp,0,80);
722                         strncpy(temp,tmsg+start,i-start);
723                         _settextposition(MSG_Y+add,40-strlen(temp)/2);
724                         _outtext(temp);
725                         start = i+1;
726                         add++;
727                 }
728         _settextposition(25,1);
729         drawstatus();
730         #else
731         printf(msg);
732         #endif
733 }
734
735 void CheckAbortStartup(void)
736 {
737 #ifdef __WATCOMC__
738         extern int lastpress;
739
740         if(lastpress == 1)
741         { // Abort if escape pressed
742                 CleanExit();
743         }
744 #endif
745 }
746
747 void IncThermo(void)
748 {
749         thermCurrent++;
750         DrawThermo();
751         CheckAbortStartup();
752 }
753
754 void InitThermo(int max)
755 {
756         thermMax = max;
757         thermCurrent = 0;
758 }
759
760 #ifdef __WATCOMC__
761 void CleanExit(void)
762 {
763         union REGS regs;
764
765         I_ShutdownKeyboard();
766         regs.x.eax = 0x3;
767         int386(0x10, &regs, &regs);
768         printf("Exited from HERETIC.\n");
769         exit(1);
770 }
771 #endif
772
773 //---------------------------------------------------------------------------
774 //
775 // PROC D_DoomMain
776 //
777 //---------------------------------------------------------------------------
778
779 void D_DoomMain(void)
780 {
781         int p;
782         int e;
783         int m;
784         char file[256];
785         FILE *fp;
786         boolean devMap;
787         //char *screen;
788
789         M_FindResponseFile();
790         setbuf(stdout, NULL);
791         nomonsters = M_CheckParm("-nomonsters");
792         respawnparm = M_CheckParm("-respawn");
793         ravpic = M_CheckParm("-ravpic");
794         noartiskip = M_CheckParm("-noartiskip");
795         debugmode = M_CheckParm("-debug");
796         startskill = sk_medium;
797         startepisode = 1;
798         startmap = 1;
799         autostart = false;
800
801         // wadfiles[0] is a char * to the main wad
802         fp = fopen(wadfiles[0], "rb");
803         if(fp)
804         {
805                 fclose(fp);
806         }
807         else
808         { // Change to look for shareware wad
809                 wadfiles[0] = SHAREWAREWADNAME;
810         }
811
812         // Check for -CDROM
813         cdrom = false;
814 #ifdef __WATCOMC__
815         if(M_CheckParm("-cdrom"))
816         {
817                 cdrom = true;
818                 mkdir("c:\\heretic.cd");
819         }
820 #endif
821
822         // -FILE [filename] [filename] ...
823         // Add files to the wad list.
824         p = M_CheckParm("-file");
825         if(p)
826         {       // the parms after p are wadfile/lump names, until end of parms
827                 // or another - preceded parm
828                 while(++p != myargc && myargv[p][0] != '-')
829                 {
830                         D_AddFile(myargv[p]);
831                 }
832         }
833
834         // -DEVMAP <episode> <map>
835         // Adds a map wad from the development directory to the wad list,
836         // and sets the start episode and the start map.
837         devMap = false;
838         p = M_CheckParm("-devmap");
839         if(p && p < myargc-2)
840         {
841                 e = myargv[p+1][0];
842                 m = myargv[p+2][0];
843                 sprintf(file, MAPDIR"E%cM%c.wad", e, m);
844                 D_AddFile(file);
845                 printf("DEVMAP: Episode %c, Map %c.\n", e, m);
846                 startepisode = e-'0';
847                 startmap = m-'0';
848                 autostart = true;
849                 devMap = true;
850         }
851
852         p = M_CheckParm("-playdemo");
853         if(!p)
854         {
855                 p = M_CheckParm("-timedemo");
856         }
857         if (p && p < myargc-1)
858         {
859                 sprintf(file, "%s.lmp", myargv[p+1]);
860                 D_AddFile(file);
861                 printf("Playing demo %s.lmp.\n", myargv[p+1]);
862         }
863
864 //
865 // get skill / episode / map from parms
866 //
867         if(M_CheckParm("-deathmatch"))
868         {
869                 deathmatch = true;
870         }
871
872         p = M_CheckParm("-skill");
873         if(p && p < myargc-1)
874         {
875                 startskill = myargv[p+1][0]-'1';
876                 autostart = true;
877         }
878
879         p = M_CheckParm("-episode");
880         if(p && p < myargc-1)
881         {
882                 startepisode = myargv[p+1][0]-'0';
883                 startmap = 1;
884                 autostart = true;
885         }
886
887         p = M_CheckParm("-warp");
888         if(p && p < myargc-2)
889         {
890                 startepisode = myargv[p+1][0]-'0';
891                 startmap = myargv[p+2][0]-'0';
892                 autostart = true;
893         }
894
895 //
896 // init subsystems
897 //
898         printf("V_Init: allocate screens.\n");
899         V_Init();
900
901         // Load defaults before initing other systems
902         printf("M_LoadDefaults: Load system defaults.\n");
903         M_LoadDefaults();
904
905         printf("Z_Init: Init zone memory allocation daemon.\n");
906         Z_Init();
907
908         printf("W_Init: Init WADfiles.\n");
909         W_InitMultipleFiles(wadfiles);
910
911         if(W_CheckNumForName("E2M1") == -1)
912         { // Can't find episode 2 maps, must be the shareware WAD
913                 shareware = true;
914         }
915         else if(W_CheckNumForName("EXTENDED") != -1)
916         { // Found extended lump, must be the extended WAD
917                 ExtendedWAD = true;
918         }
919
920 #ifdef __WATCOMC__
921         I_StartupKeyboard();
922         I_StartupJoystick();
923 #endif
924         #ifdef __WATCOMC__
925         // No use caching this if we're not going to use it - DDOI
926         startup = W_CacheLumpName("LOADING", PU_CACHE);
927         blitStartup();
928         #endif
929
930         //
931         //  Build status bar line!
932         //
933         smsg[0] = 0;
934         if (deathmatch)
935                 status("DeathMatch...");
936         if (nomonsters)
937                 status("No Monsters...");
938         if (respawnparm)
939                 status("Respawning...");
940         if (autostart)
941         {
942                 char temp[64];
943                 sprintf(temp, "Warp to Episode %d, Map %d, Skill %d ",
944                         startepisode, startmap, startskill+1);
945                 status(temp);
946         }
947         wadprintf(); // print the added wadfiles
948
949         tprintf("MN_Init: Init menu system.\n",1);
950         MN_Init();
951
952         CT_Init();
953
954         tprintf("R_Init: Init Heretic refresh daemon.",1);
955         hgotoxy(17,7);
956         hprintf("Loading graphics",0x3f);
957         R_Init();
958
959         tprintf("P_Init: Init Playloop state.",1);
960         hgotoxy(17,8);
961         hprintf("Init game engine.",0x3f);
962         P_Init();
963         IncThermo();
964
965         tprintf("I_Init: Setting up machine state.\n",1);
966         I_Init();
967         IncThermo();
968
969         tprintf("D_CheckNetGame: Checking network game status.\n",1);
970         hgotoxy(17,9);
971         hprintf("Checking network game status.", 0x3f);
972         D_CheckNetGame();
973         IncThermo();
974
975 #ifdef __WATCOMC__
976         I_CheckExternDriver(); // Check for an external device driver
977 #endif
978
979         tprintf("SB_Init: Loading patches.\n",1);
980         SB_Init();
981         IncThermo();
982
983 //
984 // start the apropriate game based on parms
985 //
986
987         D_CheckRecordFrom();
988
989         p = M_CheckParm("-record");
990         if(p && p < myargc-1)
991         {
992                 G_RecordDemo(startskill, 1, startepisode, startmap, myargv[p+1]);
993                 D_DoomLoop(); // Never returns
994         }
995
996         p = M_CheckParm("-playdemo");
997         if(p && p < myargc-1)
998         {
999                 singledemo = true; // Quit after one demo
1000                 G_DeferedPlayDemo(myargv[p+1]);
1001                 D_DoomLoop(); // Never returns
1002         }
1003
1004         p = M_CheckParm("-timedemo");
1005         if(p && p < myargc-1)
1006         {
1007                 G_TimeDemo(myargv[p+1]);
1008                 D_DoomLoop(); // Never returns
1009         }
1010
1011         p = M_CheckParm("-loadgame");
1012         if(p && p < myargc-1)
1013         {
1014                 if(cdrom)
1015                 {
1016                         sprintf(file, SAVEGAMENAMECD"%c.hsg", myargv[p+1][0]);
1017                 }
1018                 else
1019                 {
1020                         sprintf(file, SAVEGAMENAME"%c.hsg", myargv[p+1][0]);
1021                 }
1022                 G_LoadGame(file);
1023         }
1024
1025         // Check valid episode and map
1026         if((autostart || netgame) && (devMap == false))
1027         {
1028                 if(M_ValidEpisodeMap(startepisode, startmap) == false)
1029                 {
1030                         startepisode = 1;
1031                         startmap = 1;
1032                 }
1033         }
1034
1035         if(gameaction != ga_loadgame)
1036         {
1037                 UpdateState |= I_FULLSCRN;
1038                 BorderNeedRefresh = true;
1039                 if(autostart || netgame)
1040                 {
1041                         G_InitNew(startskill, startepisode, startmap);
1042                 }
1043                 else
1044                 {
1045                         D_StartTitle();
1046                 }
1047         }
1048 #ifdef __WATCOMC__
1049         _settextcursor(0x0607); // bring the cursor back
1050 #endif
1051         D_DoomLoop(); // Never returns
1052 }