1 
2 //**************************************************************************
3 //**
4 //** h2_main.c : Heretic 2 : Raven Software, Corp.
5 //**
6 //** $RCSfile: h2_main.c,v $
7 //** $Revision: 1.50 $
8 //** $Date: 96/01/16 13:02:28 $
9 //** $Author: bgokey $
10 //**
11 //**************************************************************************
12 
13 // HEADER FILES ------------------------------------------------------------
14 
15 #ifndef MUSTDIE
16 #include <sys/types.h>
17 #include <sys/stat.h>
18 #endif
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <time.h>
22 #include "h2def.h"
23 #include "p_local.h"
24 #include "soundst.h"
25 
26 // MACROS ------------------------------------------------------------------
27 
28 #define CONFIG_FILE_NAME "hexen.cfg"
29 #define MAXWADFILES 20
30 
31 // TYPES -------------------------------------------------------------------
32 
33 typedef struct
34 {
35 	char *name;
36 	void (*func)(char **args, int tag);
37 	int requiredArgs;
38 	int tag;
39 } execOpt_t;
40 
41 // EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
42 
43 void R_ExecuteSetViewSize(void);
44 void D_CheckNetGame(void);
45 void G_BuildTiccmd(ticcmd_t *cmd);
46 void F_Drawer(void);
47 boolean F_Responder(event_t *ev);
48 void I_StartupKeyboard(void);
49 void I_StartupJoystick(void);
50 void I_ShutdownKeyboard(void);
51 void S_InitScript(void);
52 
53 // PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
54 
55 void H2_ProcessEvents(void);
56 void H2_DoAdvanceDemo(void);
57 void H2_AdvanceDemo(void);
58 void H2_StartTitle(void);
59 void H2_PageTicker(void);
60 
61 // PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
62 
63 static void DrawMessage(void);
64 static void PageDrawer(void);
65 static void HandleArgs(void);
66 static void CheckRecordFrom(void);
67 static void AddWADFile(char *file);
68 static void DrawAndBlit(void);
69 static void ExecOptionFILE(char **args, int tag);
70 static void ExecOptionSCRIPTS(char **args, int tag);
71 static void ExecOptionDEVMAPS(char **args, int tag);
72 static void ExecOptionSKILL(char **args, int tag);
73 static void ExecOptionPLAYDEMO(char **args, int tag);
74 static void ExecOptionMAXZONE(char **args, int tag);
75 static void CreateSavePath(void);
76 static void WarpCheck(void);
77 
78 #ifdef TIMEBOMB
79 static void DoTimeBomb(void);
80 #endif
81 
82 // EXTERNAL DATA DECLARATIONS ----------------------------------------------
83 
84 extern boolean automapactive;
85 extern boolean MenuActive;
86 extern boolean askforquit;
87 extern char *SavePath;
88 
89 // PUBLIC DATA DEFINITIONS -------------------------------------------------
90 
91 boolean DevMaps;			// true = Map development mode
92 char *DevMapsDir = "";		// development maps directory
93 boolean shareware;			// true if only episode 1 present
94 boolean nomonsters;			// checkparm of -nomonsters
95 boolean respawnparm;		// checkparm of -respawn
96 boolean randomclass;		// checkparm of -randclass
97 boolean debugmode;			// checkparm of -debug
98 boolean ravpic;				// checkparm of -ravpic
99 boolean cdrom;				// true if cd-rom mode active
100 boolean cmdfrag;			// true if a CMD_FRAG packet should be sent out
101 boolean singletics;			// debug flag to cancel adaptiveness
102 boolean artiskip;			// whether shift-enter skips an artifact
103 int maxzone = 0x800000;		// Maximum allocated for zone heap (8meg default)
104 skill_t startskill;
105 int startepisode;
106 int startmap;
107 boolean autostart;
108 boolean advancedemo;
109 FILE *debugfile;
110 event_t events[MAXEVENTS];
111 int eventhead;
112 int eventtail;
113 
114 // PRIVATE DATA DEFINITIONS ------------------------------------------------
115 
116 static int WarpMap;
117 static int demosequence;
118 static int pagetic;
119 static char *pagename;
120 #ifdef __NeXT__
121 static char *wadfiles[MAXWADFILES] =
122 {
123 	"/Novell/H2/source/hexen.wad"
124 };
125 #else
126 #ifndef MUSTDIE
127 static char *wadfiles[MAXWADFILES] =
128 {
129 	"hexen.wad",
130 	PREFIX "/share/doom/hexen.wad"
131 };
132 #else
133 static char *wadfiles[MAXWADFILES] =
134 {
135 	"HEXEN.WAD"
136 };
137 #endif
138 #endif
139 static execOpt_t ExecOptions[] =
140 {
141 	{ "-file", ExecOptionFILE, 1, 0 },
142 	{ "-scripts", ExecOptionSCRIPTS, 1, 0 },
143 	{ "-devmaps", ExecOptionDEVMAPS, 1, 0 },
144 	{ "-skill", ExecOptionSKILL, 1, 0 },
145 	{ "-playdemo", ExecOptionPLAYDEMO, 1, 0 },
146 	{ "-timedemo", ExecOptionPLAYDEMO, 1, 0 },
147 	{ "-maxzone", ExecOptionMAXZONE, 1, 0 },
148 	{ NULL, NULL, 0, 0 } // Terminator
149 };
150 
151 // CODE --------------------------------------------------------------------
152 
153 //==========================================================================
154 //
155 // H2_Main
156 //
157 //==========================================================================
158 void InitMapMusicInfo(void);
159 
H2_Main(void)160 void H2_Main(void)
161 {
162 	int p;
163 
164 	M_FindResponseFile();
165 	setbuf(stdout, NULL);
166 	startepisode = 1;
167 	autostart = false;
168 	startskill = sk_medium;
169 	startmap = 1;
170 	shareware = false; // Always false for Hexen
171 
172 	HandleArgs();
173 
174 	// Initialize subsystems
175 
176 	ST_Message("V_Init: allocate screens.\n");
177 	V_Init();
178 
179 	// Load defaults before initing other systems
180 	ST_Message("M_LoadDefaults: Load system defaults.\n");
181 	M_LoadDefaults(CONFIG_FILE_NAME);
182 
183 	// Now that the savedir is loaded from .CFG, make sure it exists
184 	CreateSavePath();
185 
186 	// HEXEN MODIFICATION:
187 	// There is a realloc() in W_AddFile() that might fail if the zone
188 	// heap has been previously allocated, so we need to initialize the
189 	// WAD files BEFORE the zone memory initialization.
190 	ST_Message("W_Init: Init WADfiles.\n");
191 	W_InitMultipleFiles(wadfiles);
192 
193 #ifdef TIMEBOMB
194 	DoTimeBomb();
195 #endif
196 
197 	ST_Message("Z_Init: Init zone memory allocation daemon.\n");
198 	Z_Init();
199 
200 #ifdef __WATCOMC__
201 	I_StartupKeyboard();
202 	I_StartupJoystick();
203 #endif
204 
205 	ST_Message("MN_Init: Init menu system.\n");
206 	MN_Init();
207 
208 	ST_Message("CT_Init: Init chat mode data.\n");
209 	CT_Init();
210 
211 	InitMapMusicInfo();		// Init music fields in mapinfo
212 
213 //#ifdef __WATCOMC__
214 	ST_Message("S_InitScript\n");
215 	S_InitScript();
216 //#endif
217 
218 	ST_Message("SN_InitSequenceScript: Registering sound sequences.\n");
219 	SN_InitSequenceScript();
220 	ST_Message("I_Init: Setting up machine state.\n");
221 	I_Init();
222 
223 	ST_Message("ST_Init: Init startup screen.\n");
224 	ST_Init();
225 
226 	S_StartSongName("orb", true);
227 
228 	// Show version message now, so it's visible during R_Init()
229 	ST_Message("Executable: "VERSIONTEXT".\n");
230 
231 	ST_Message("R_Init: Init Hexen refresh daemon");
232 	R_Init();
233 	ST_Message("\n");
234 
235 	if (M_CheckParm("-net")) ST_NetProgress();	// Console player found
236 
237 	ST_Message("P_Init: Init Playloop state.\n");
238 	P_Init();
239 
240 	// Check for command line warping. Follows P_Init() because the
241 	// MAPINFO.TXT script must be already processed.
242 	WarpCheck();
243 
244 	if(autostart)
245 	{
246 		ST_Message("Warp to Map %d (\"%s\":%d), Skill %d\n",
247 			WarpMap, P_GetMapName(startmap), startmap, startskill+1);
248 	}
249 
250 	ST_Message("D_CheckNetGame: Checking network game status.\n");
251 	D_CheckNetGame();
252 
253 	ST_Message("SB_Init: Loading patches.\n");
254 	SB_Init();
255 
256 	CheckRecordFrom();
257 
258 	p = M_CheckParm("-record");
259 	if(p && p < myargc-1)
260 	{
261 		G_RecordDemo(startskill, 1, startepisode, startmap, myargv[p+1]);
262 		H2_GameLoop(); // Never returns
263 	}
264 
265 	p = M_CheckParm("-playdemo");
266 	if(p && p < myargc-1)
267 	{
268 		singledemo = true; // Quit after one demo
269 		G_DeferedPlayDemo(myargv[p+1]);
270 		H2_GameLoop(); // Never returns
271 	}
272 
273 	p = M_CheckParm("-timedemo");
274 	if(p && p < myargc-1)
275 	{
276 		G_TimeDemo(myargv[p+1]);
277 		H2_GameLoop(); // Never returns
278 	}
279 
280 	p = M_CheckParm("-loadgame");
281 	if(p && p < myargc-1)
282 	{
283 		G_LoadGame(atoi(myargv[p+1]));
284 	}
285 
286 	if(gameaction != ga_loadgame)
287 	{
288 		UpdateState |= I_FULLSCRN;
289 		BorderNeedRefresh = true;
290 		if(autostart || netgame)
291 		{
292 			G_StartNewInit();
293 			G_InitNew(startskill, startepisode, startmap);
294 		}
295 		else
296 		{
297 			H2_StartTitle();
298 		}
299 	}
300 	H2_GameLoop(); // Never returns
301 }
302 
303 //==========================================================================
304 //
305 // HandleArgs
306 //
307 //==========================================================================
308 
HandleArgs(void)309 static void HandleArgs(void)
310 {
311 	int p;
312 	execOpt_t *opt;
313 
314 	nomonsters = M_ParmExists("-nomonsters");
315 	respawnparm = M_ParmExists("-respawn");
316 	randomclass = M_ParmExists("-randclass");
317 	ravpic = M_ParmExists("-ravpic");
318 	artiskip = M_ParmExists("-artiskip");
319 	debugmode = M_ParmExists("-debug");
320 	deathmatch = M_ParmExists("-deathmatch");
321 	cdrom = M_ParmExists("-cdrom");
322 	cmdfrag = M_ParmExists("-cmdfrag");
323 
324 	// Process command line options
325 	for(opt = ExecOptions; opt->name != NULL; opt++)
326 	{
327 		p = M_CheckParm(opt->name);
328 		if(p && p < myargc-opt->requiredArgs)
329 		{
330 			opt->func(&myargv[p], opt->tag);
331 		}
332 	}
333 
334 	// Look for an external device driver
335 	//I_CheckExternDriver();
336 }
337 
338 //==========================================================================
339 //
340 // WarpCheck
341 //
342 //==========================================================================
343 
WarpCheck(void)344 static void WarpCheck(void)
345 {
346 	int p;
347 	int map;
348 
349 	p = M_CheckParm("-warp");
350 	if(p && p < myargc-1)
351 	{
352 		WarpMap = atoi(myargv[p+1]);
353 		map = P_TranslateMap(WarpMap);
354 		if(map == -1)
355 		{ // Couldn't find real map number
356 			startmap = 1;
357 			ST_Message("-WARP: Invalid map number.\n");
358 		}
359 		else
360 		{ // Found a valid startmap
361 			startmap = map;
362 			autostart = true;
363 		}
364 	}
365 	else
366 	{
367 		WarpMap = 1;
368 		startmap = P_TranslateMap(1);
369 		if(startmap == -1)
370 		{
371 			startmap = 1;
372 		}
373 	}
374 }
375 
376 //==========================================================================
377 //
378 // ExecOptionSKILL
379 //
380 //==========================================================================
381 
ExecOptionSKILL(char ** args,int tag)382 static void ExecOptionSKILL(char **args, int tag)
383 {
384 	startskill = args[1][0]-'1';
385 	autostart = true;
386 }
387 
388 //==========================================================================
389 //
390 // ExecOptionFILE
391 //
392 //==========================================================================
393 
ExecOptionFILE(char ** args,int tag)394 static void ExecOptionFILE(char **args, int tag)
395 {
396 	int p;
397 
398 	p = M_CheckParm("-file");
399 	while(++p != myargc && myargv[p][0] != '-')
400 	{
401 		AddWADFile(myargv[p]);
402 	}
403 }
404 
405 
406 //==========================================================================
407 //
408 // ExecOptionPLAYDEMO
409 //
410 //==========================================================================
411 
ExecOptionPLAYDEMO(char ** args,int tag)412 static void ExecOptionPLAYDEMO(char **args, int tag)
413 {
414 	char file[256];
415 
416 	sprintf(file, "%s.lmp", args[1]);
417 	AddWADFile(file);
418 	ST_Message("Playing demo %s.lmp.\n", args[1]);
419 }
420 
421 //==========================================================================
422 //
423 // ExecOptionSCRIPTS
424 //
425 //==========================================================================
426 
ExecOptionSCRIPTS(char ** args,int tag)427 static void ExecOptionSCRIPTS(char **args, int tag)
428 {
429 	sc_FileScripts = true;
430 	sc_ScriptsDir = args[1];
431 }
432 
433 //==========================================================================
434 //
435 // ExecOptionDEVMAPS
436 //
437 //==========================================================================
438 
ExecOptionDEVMAPS(char ** args,int tag)439 static void ExecOptionDEVMAPS(char **args, int tag)
440 {
441 	DevMaps = true;
442 	ST_Message("Map development mode enabled:\n");
443 	ST_Message("[config    ] = %s\n", args[1]);
444 	SC_OpenFileCLib(args[1]);
445 	SC_MustGetStringName("mapsdir");
446 	SC_MustGetString();
447 	ST_Message("[mapsdir   ] = %s\n", sc_String);
448 	DevMapsDir = malloc(strlen(sc_String)+1);
449 	strcpy(DevMapsDir, sc_String);
450 	SC_MustGetStringName("scriptsdir");
451 	SC_MustGetString();
452 	ST_Message("[scriptsdir] = %s\n", sc_String);
453 	sc_FileScripts = true;
454 	sc_ScriptsDir = malloc(strlen(sc_String)+1);
455 	strcpy(sc_ScriptsDir, sc_String);
456 	while(SC_GetString())
457 	{
458 		if(SC_Compare("file"))
459 		{
460 			SC_MustGetString();
461 			AddWADFile(sc_String);
462 		}
463 		else
464 		{
465 			SC_ScriptError(NULL);
466 		}
467 	}
468 	SC_Close();
469 }
470 
471 
superatol(char * s)472 long superatol(char *s)
473 {
474 	long int n=0, r=10, x, mul=1;
475 	char *c=s;
476 
477 	for (; *c; c++)
478 	{
479 		x = (*c & 223) - 16;
480 
481 		if (x == -3)
482 		{
483 			mul = -mul;
484 		}
485 		else if (x == 72 && r == 10)
486 		{
487 			n -= (r=n);
488 			if (!r) r=16;
489 			if (r<2 || r>36) return -1;
490 		}
491 		else
492 		{
493 			if (x>10) x-=39;
494 			if (x >= r) return -1;
495 			n = (n*r) + x;
496 		}
497 	}
498 	return(mul*n);
499 }
500 
501 
ExecOptionMAXZONE(char ** args,int tag)502 static void ExecOptionMAXZONE(char **args, int tag)
503 {
504 	int size;
505 
506 	size = superatol(args[1]);
507 	if (size < MINIMUM_HEAP_SIZE) size = MINIMUM_HEAP_SIZE;
508 	if (size > MAXIMUM_HEAP_SIZE) size = MAXIMUM_HEAP_SIZE;
509 	maxzone = size;
510 }
511 
512 //==========================================================================
513 //
514 // H2_GameLoop
515 //
516 //==========================================================================
517 
H2_GameLoop(void)518 void H2_GameLoop(void)
519 {
520 	if(M_CheckParm("-debugfile"))
521 	{
522 		char filename[20];
523 		sprintf(filename, "debug%i.txt", consoleplayer);
524 		debugfile = fopen(filename,"w");
525 	}
526 
527 	I_InitGraphics();
528 
529 	I_SetPalette(W_CacheLumpName("PLAYPAL", PU_CACHE));
530 
531 	while(1)
532 	{
533 		// Frame syncronous IO operations
534 		I_StartFrame();
535 
536 		// Process one or more tics
537 		if(singletics)
538 		{
539 			I_StartTic();
540 			H2_ProcessEvents();
541 			G_BuildTiccmd(&netcmds[consoleplayer][maketic%BACKUPTICS]);
542 			if(advancedemo)
543 			{
544 				H2_DoAdvanceDemo();
545 			}
546 			G_Ticker();
547 			gametic++;
548 			maketic++;
549 		}
550 		else
551 		{
552 			// Will run at least one tic
553 			TryRunTics();
554 		}
555 
556 		// Move positional sounds
557 		S_UpdateSounds(players[displayplayer].mo);
558 
559 		DrawAndBlit();
560 	}
561 }
562 
563 //==========================================================================
564 //
565 // H2_ProcessEvents
566 //
567 // Send all the events of the given timestamp down the responder chain.
568 //
569 //==========================================================================
570 
H2_ProcessEvents(void)571 void H2_ProcessEvents(void)
572 {
573 	event_t *ev;
574 
575 	for(; eventtail != eventhead; eventtail = (++eventtail)&(MAXEVENTS-1))
576 	{
577 		ev = &events[eventtail];
578 		if(F_Responder(ev))
579 		{
580 			continue;
581 		}
582 		if(MN_Responder(ev))
583 		{
584 			continue;
585 		}
586 		G_Responder(ev);
587 	}
588 }
589 
590 //==========================================================================
591 //
592 // H2_PostEvent
593 //
594 // Called by the I/O functions when input is detected.
595 //
596 //==========================================================================
597 
H2_PostEvent(event_t * ev)598 void H2_PostEvent(event_t *ev)
599 {
600 	events[eventhead] = *ev;
601 	eventhead = (++eventhead)&(MAXEVENTS-1);
602 }
603 
604 //==========================================================================
605 //
606 // DrawAndBlit
607 //
608 //==========================================================================
609 
DrawAndBlit(void)610 static void DrawAndBlit(void)
611 {
612 	// Change the view size if needed
613 	if(setsizeneeded)
614 	{
615 		R_ExecuteSetViewSize();
616 	}
617 
618 	// Do buffered drawing
619 	switch(gamestate)
620 	{
621 		case GS_LEVEL:
622 			if(!gametic)
623 			{
624 				break;
625 			}
626 			if(automapactive)
627 			{
628 				AM_Drawer();
629 			}
630 			else
631 			{
632 				R_RenderPlayerView(&players[displayplayer]);
633 			}
634 			CT_Drawer();
635 			UpdateState |= I_FULLVIEW;
636 			SB_Drawer();
637 			break;
638 		case GS_INTERMISSION:
639 			IN_Drawer();
640 			break;
641 		case GS_FINALE:
642 			F_Drawer();
643 			break;
644 		case GS_DEMOSCREEN:
645 			PageDrawer();
646 			break;
647 	}
648 
649 	if(paused && !MenuActive && !askforquit)
650 	{
651 #if 0
652     for gl
653 	    if (use_gl)
654 	    {
655     	        if(!netgame)
656 		{
657 			OGL_DrawPatch(160, viewwindowy+5, W_GetNumForName("PAUSED"));
658 		}
659 		else
660 		{
661 			OGL_DrawPatch(160, 70, W_GetNumGorName("PAUSED"));
662 		}
663 	    }
664 	    else
665 #endif
666 	    {
667 		if(!netgame)
668 		{
669 			V_DrawPatch(160, viewwindowy+5, W_CacheLumpName("PAUSED",
670 				PU_CACHE));
671 		}
672 		else
673 		{
674 			V_DrawPatch(160, 70, W_CacheLumpName("PAUSED",
675 				PU_CACHE));
676 		}
677 	    }
678 	}
679 
680 	// Draw current message
681 	DrawMessage();
682 
683 	// Draw Menu
684 	MN_Drawer();
685 
686 	// Send out any new accumulation
687 	NetUpdate();
688 
689 	// Flush buffered stuff to screen
690 	I_UpdateNoBlit();
691 	I_FinishUpdate();
692 }
693 
694 //==========================================================================
695 //
696 // DrawMessage
697 //
698 //==========================================================================
699 
DrawMessage(void)700 static void DrawMessage(void)
701 {
702 	player_t *player;
703 
704 	player = &players[consoleplayer];
705 	if(player->messageTics <= 0 || !player->message)
706 	{ // No message
707 		return;
708 	}
709 	if(player->yellowMessage)
710 	{
711 		MN_DrTextAYellow(player->message,
712 			160-MN_TextAWidth(player->message)/2, 1);
713 	}
714 	else
715 	{
716 		MN_DrTextA(player->message, 160-MN_TextAWidth(player->message)/2, 1);
717 	}
718 }
719 
720 //==========================================================================
721 //
722 // H2_PageTicker
723 //
724 //==========================================================================
725 
H2_PageTicker(void)726 void H2_PageTicker(void)
727 {
728 	if(--pagetic < 0)
729 	{
730 		H2_AdvanceDemo();
731 	}
732 }
733 
734 //==========================================================================
735 //
736 // PageDrawer
737 //
738 //==========================================================================
739 
PageDrawer(void)740 static void PageDrawer(void)
741 {
742 #if 0
743    if (use_gl)
744    {
745     for gl
746     OGL_DrawRawScreen(W_GetNumForName(pagename));
747     if (demosequence == 1)
748     {
749 		OGL_DrawPatch(4, 160, W_GetNumForName("ADVISOR");
750     	        UpdateState |= I_FULLSCRN;
751     }
752    }
753    else
754 #endif
755    {
756 	V_DrawRawScreen(W_CacheLumpName(pagename, PU_CACHE));
757 	if(demosequence == 1)
758 	{
759 		V_DrawPatch(4, 160, W_CacheLumpName("ADVISOR", PU_CACHE));
760 	        UpdateState |= I_FULLSCRN;
761 	}
762    }
763 }
764 
765 //==========================================================================
766 //
767 // H2_AdvanceDemo
768 //
769 // Called after each demo or intro demosequence finishes.
770 //
771 //==========================================================================
772 
H2_AdvanceDemo(void)773 void H2_AdvanceDemo(void)
774 {
775 	advancedemo = true;
776 }
777 
778 //==========================================================================
779 //
780 // H2_DoAdvanceDemo
781 //
782 //==========================================================================
783 
H2_DoAdvanceDemo(void)784 void H2_DoAdvanceDemo(void)
785 {
786 	players[consoleplayer].playerstate = PST_LIVE; // don't reborn
787 	advancedemo = false;
788 	usergame = false; // can't save/end game here
789 	paused = false;
790 	gameaction = ga_nothing;
791 	demosequence = (demosequence+1)%7;
792 	switch(demosequence)
793 	{
794 		case 0:
795 			pagetic = 280;
796 			gamestate = GS_DEMOSCREEN;
797 			pagename = "TITLE";
798 			S_StartSongName("hexen", true);
799 			break;
800 		case 1:
801 			pagetic = 210;
802 			gamestate = GS_DEMOSCREEN;
803 			pagename = "TITLE";
804 			break;
805 		case 2:
806 			BorderNeedRefresh = true;
807 			UpdateState |= I_FULLSCRN;
808 			G_DeferedPlayDemo("demo1");
809 			break;
810 		case 3:
811 			pagetic = 200;
812 			gamestate = GS_DEMOSCREEN;
813 			pagename = "CREDIT";
814 			break;
815 		case 4:
816 			BorderNeedRefresh = true;
817 			UpdateState |= I_FULLSCRN;
818 			G_DeferedPlayDemo("demo2");
819 			break;
820 		case 5:
821 			pagetic = 200;
822 			gamestate = GS_DEMOSCREEN;
823 			pagename = "CREDIT";
824 			break;
825 		case 6:
826 			BorderNeedRefresh = true;
827 			UpdateState |= I_FULLSCRN;
828 			G_DeferedPlayDemo("demo3");
829 			break;
830 	}
831 }
832 
833 //==========================================================================
834 //
835 // H2_StartTitle
836 //
837 //==========================================================================
838 
H2_StartTitle(void)839 void H2_StartTitle(void)
840 {
841 	gameaction = ga_nothing;
842 	demosequence = -1;
843 	H2_AdvanceDemo();
844 }
845 
846 //==========================================================================
847 //
848 // CheckRecordFrom
849 //
850 // -recordfrom <savegame num> <demoname>
851 //
852 //==========================================================================
853 
CheckRecordFrom(void)854 static void CheckRecordFrom(void)
855 {
856 	int p;
857 
858 	p = M_CheckParm("-recordfrom");
859 	if(!p || p > myargc-2)
860 	{ // Bad args
861 		return;
862 	}
863 	G_LoadGame(atoi(myargv[p+1]));
864 	G_DoLoadGame(); // Load the gameskill etc info from savegame
865 	G_RecordDemo(gameskill, 1, gameepisode, gamemap, myargv[p+2]);
866 	H2_GameLoop(); // Never returns
867 }
868 
869 //==========================================================================
870 //
871 // AddWADFile
872 //
873 //==========================================================================
874 
AddWADFile(char * file)875 static void AddWADFile(char *file)
876 {
877 	int i;
878 	char *new;
879 
880 	ST_Message("Adding external file: %s\n", file);
881 	i = 0;
882 	while(wadfiles[i])
883 	{
884 		i++;
885 	}
886 	new = malloc(strlen(file)+1);
887 	strcpy(new, file);
888 	wadfiles[i] = new;
889 }
890 
891 #ifdef __WATCOMC__
892 /*
893 void CleanExit(void)
894 {
895 	union REGS regs;
896 
897 	I_ShutdownKeyboard();
898 	regs.x.eax = 0x3;
899 	int386(0x10, &regs, &regs);
900 	printf("Exited from HEXEN: Beyond Heretic.\n");
901 	exit(1);
902 }
903 */
904 #endif
905 
906 //==========================================================================
907 //
908 // FixedDiv
909 //
910 //==========================================================================
911 
912 /* fixed_t FixedDiv(fixed_t a, fixed_t b)
913 {
914 	if((abs(a)>>14) >= abs(b))
915 	{
916 		return((a^b)<0 ? MININT : MAXINT);
917 	}
918 	return(FixedDiv2(a, b));
919 }
920 */
921 
922 //==========================================================================
923 //
924 // CreateSavePath
925 //
926 //==========================================================================
927 
928 
929 
CreateSavePath(void)930 static void CreateSavePath(void)
931 {
932 	static char creationPath[255];
933 	int len;
934 	char *homedir;
935 
936 	if(cdrom == true)
937 	{
938 		SavePath = "/cdrom/hexndata";
939 	}
940 	len = strlen(SavePath);
941 	if (len >= 120) I_Error("Save path too long\n");
942 	strcpy(creationPath, SavePath);
943 
944 /* XXX Create a save path in home directory */
945 #ifndef MUSTDIE
946 	homedir=getenv("HOME");
947 	if (!homedir) I_Error("Cannot locate home directory!\n");
948 	strcpy(creationPath,homedir);
949 	strcat(creationPath,"/.hexendata/");
950 #else
951 	strcpy(creationPath,"HEXNDATA\\");
952 #endif
953 	mkdir(creationPath,0700);
954 	SavePath=creationPath;
955 }
956 
957 #ifdef TIMEBOMB
958 //==========================================================================
959 //
960 // DoTimeBomb
961 //
962 //==========================================================================
963 
DoTimeBomb(void)964 static void DoTimeBomb(void)
965 {
966 #ifdef __WATCOMC__
967 	time_t timeOfDay;
968 	struct tm timeBuffer;
969 
970 	timeOfDay = time(NULL);
971 	_localtime(&timeOfDay, &timeBuffer);
972 	if(timeBuffer.tm_year != TIMEBOMB_YEAR
973 	|| timeBuffer.tm_yday < TIMEBOMB_STARTDATE
974 	|| timeBuffer.tm_yday > TIMEBOMB_ENDDATE)
975 	{
976 		I_Error("W_InitWadfiles:  Wad file doesn't have IWAD or PWAD id\n");
977 	}
978 
979 	printf("\n===============================================================================\n");
980 	printf("                             Hexen:  Beyond Heretic\n\n");
981 	printf("                           Beta -- Do Not Distribute!\n");
982 	printf("                           Press any key to continue.\n");
983 	printf("===============================================================================\n");
984 
985 	getch();
986 	printf("\n");
987 #endif
988 }
989 #endif
990