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