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