]> icculus.org git repositories - theoddone33/hhexen.git/blob - base/m_misc.c
11056a18330c594214733eedd1929c9d4b4100f5
[theoddone33/hhexen.git] / base / m_misc.c
1
2 //**************************************************************************
3 //**
4 //** m_misc.c : Heretic 2 : Raven Software, Corp.
5 //**
6 //** $RCSfile$
7 //** $Revision$
8 //** $Date$
9 //** $Author$
10 //**
11 //**************************************************************************
12
13 // HEADER FILES ------------------------------------------------------------
14
15 #include <sys/stat.h>
16 #include <fcntl.h>
17 #include <unistd.h>    /* jim write() read() close() */
18 #include <ctype.h>
19 #include "h2def.h"
20 #include "p_local.h"
21 #include "soundst.h"
22
23 // MACROS ------------------------------------------------------------------
24
25 #define MALLOC_CLIB 1
26 #define MALLOC_ZONE 2
27
28 // TYPES -------------------------------------------------------------------
29
30 // EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
31
32 #ifdef RENDER3D
33 extern void OGL_GrabScreen();
34 #endif
35
36 // PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
37
38 // PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
39
40 static int ReadFile(char const *name, byte **buffer, int mallocType);
41
42 // EXTERNAL DATA DECLARATIONS ----------------------------------------------
43 extern char *basePath;
44
45 // PUBLIC DATA DEFINITIONS -------------------------------------------------
46
47 int myargc;
48 char **myargv;
49
50 // PRIVATE DATA DEFINITIONS ------------------------------------------------
51
52 // CODE --------------------------------------------------------------------
53
54 //==========================================================================
55 //
56 // M_CheckParm
57 //
58 // Checks for the given parameter in the program's command line arguments.
59 // Returns the argument number (1 to argc-1) or 0 if not present.
60 //
61 //==========================================================================
62
63 int M_CheckParm(char *check)
64 {
65         int i;
66
67         for(i = 1; i < myargc; i++)
68         {
69                 if(!strcasecmp(check, myargv[i]))
70                 {
71                         return i;
72                 }
73         }
74         return 0;
75 }
76
77 //==========================================================================
78 //
79 // M_ParmExists
80 //
81 // Returns true if the given parameter exists in the program's command
82 // line arguments, false if not.
83 //
84 //==========================================================================
85
86 boolean M_ParmExists(char *check)
87 {
88         return M_CheckParm(check) != 0 ? true : false;
89 }
90
91 //==========================================================================
92 //
93 // M_ExtractFileBase
94 //
95 //==========================================================================
96
97 void M_ExtractFileBase(char *path, char *dest)
98 {
99         char *src;
100         int length;
101
102         src = path+strlen(path)-1;
103
104         // Back up until a \ or the start
105         while(src != path && *(src-1) != '\\' && *(src-1) != '/')
106         {
107                 src--;
108         }
109
110         // Copy up to eight characters
111         memset(dest, 0, 8);
112         length = 0;
113         while(*src && *src != '.')
114         {
115                 if(++length == 9)
116                 {
117                         I_Error("Filename base of %s > 8 chars", path);
118                 }
119                 *dest++ = toupper((int)*src++);
120         }
121 }
122
123 /*
124 ===============
125 =
126 = M_Random
127 =
128 = Returns a 0-255 number
129 =
130 ===============
131 */
132
133
134 // This is the new flat distribution table
135 unsigned char rndtable[256] = {
136         201,  1,243, 19, 18, 42,183,203,101,123,154,137, 34,118, 10,216,
137         135,246,  0,107,133,229, 35,113,177,211,110, 17,139, 84,251,235,
138         182,166,161,230,143, 91, 24, 81, 22, 94,  7, 51,232,104,122,248,
139         175,138,127,171,222,213, 44, 16,  9, 33, 88,102,170,150,136,114,
140          62,  3,142,237,  6,252,249, 56, 74, 30, 13, 21,180,199, 32,132,
141         187,234, 78,210, 46,131,197,  8,206,244, 73,  4,236,178,195, 70,
142         121, 97,167,217,103, 40,247,186,105, 39, 95,163, 99,149,253, 29,
143         119, 83,254, 26,202, 65,130,155, 60, 64,184,106,221, 93,164,196,
144         112,108,179,141, 54,109, 11,126, 75,165,191,227, 87,225,156, 15,
145          98,162,116, 79,169,140,190,205,168,194, 41,250, 27, 20, 14,241,
146          50,214, 72,192,220,233, 67,148, 96,185,176,181,215,207,172, 85,
147          89, 90,209,128,124,  2, 55,173, 66,152, 47,129, 59, 43,159,240,
148         239, 12,189,212,144, 28,200, 77,219,198,134,228, 45, 92,125,151,
149           5, 53,255, 52, 68,245,160,158, 61, 86, 58, 82,117, 37,242,145,
150          69,188,115, 76, 63,100, 49,111,153, 80, 38, 57,174,224, 71,231,
151          23, 25, 48,218,120,147,208, 36,226,223,193,238,157,204,146, 31
152 };
153
154
155 int rndindex = 0;
156 int prndindex = 0;
157
158 int M_Random (void)
159 {
160         rndindex = (rndindex+1)&0xff;
161         return rndtable[rndindex];
162 }
163
164 void M_ClearRandom (void)
165 {
166         rndindex = prndindex = 0;
167 }
168
169
170 void M_ClearBox (fixed_t *box)
171 {
172         box[BOXTOP] = box[BOXRIGHT] = MININT;
173         box[BOXBOTTOM] = box[BOXLEFT] = MAXINT;
174 }
175
176 void M_AddToBox (fixed_t *box, fixed_t x, fixed_t y)
177 {
178         if (x<box[BOXLEFT])
179                 box[BOXLEFT] = x;
180         else if (x>box[BOXRIGHT])
181                 box[BOXRIGHT] = x;
182         if (y<box[BOXBOTTOM])
183                 box[BOXBOTTOM] = y;
184         else if (y>box[BOXTOP])
185                 box[BOXTOP] = y;
186 }
187
188 /*
189 ==================
190 =
191 = M_WriteFile
192 =
193 ==================
194 */
195
196 #ifndef O_BINARY
197 #define O_BINARY 0
198 #endif
199
200 boolean M_WriteFile (char const *name, void *source, int length)
201 {
202         int handle, count;
203
204         handle = open (name, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666);
205         if (handle == -1)
206                 return false;
207         count = write (handle, source, length);
208         close (handle);
209
210         if (count < length)
211                 return false;
212
213         return true;
214 }
215
216 //==========================================================================
217 //
218 // M_ReadFile
219 //
220 // Read a file into a buffer allocated using Z_Malloc().
221 //
222 //==========================================================================
223
224 int M_ReadFile(char const *name, byte **buffer)
225 {
226         return ReadFile(name, buffer, MALLOC_ZONE);
227 }
228
229 //==========================================================================
230 //
231 // M_ReadFileCLib
232 //
233 // Read a file into a buffer allocated using malloc().
234 //
235 //==========================================================================
236
237 int M_ReadFileCLib(char const *name, byte **buffer)
238 {
239         return ReadFile(name, buffer, MALLOC_CLIB);
240 }
241
242 //==========================================================================
243 //
244 // ReadFile
245 //
246 //==========================================================================
247
248 static int ReadFile(char const *name, byte **buffer, int mallocType)
249 {
250         int handle, count, length;
251         struct stat fileinfo;
252         byte *buf;
253
254         handle = open(name, O_RDONLY|O_BINARY, 0666);
255         if(handle == -1)
256         {
257                 I_Error("Couldn't read file %s", name);
258         }
259         if(fstat(handle, &fileinfo) == -1)
260         {
261                 I_Error("Couldn't read file %s", name);
262         }
263         length = fileinfo.st_size;
264         if(mallocType == MALLOC_ZONE)
265         { // Use zone memory allocation
266                 buf = Z_Malloc(length, PU_STATIC, NULL);
267         }
268         else
269         { // Use c library memory allocation
270                 buf = malloc(length);
271                 if(buf == NULL)
272                 {
273                         I_Error("Couldn't malloc buffer %d for file %s.",
274                                 length, name);
275                 }
276         }
277         count = read(handle, buf, length);
278         close(handle);
279         if(count < length)
280         {
281                 I_Error("Couldn't read file %s", name);
282         }
283         *buffer = buf;
284         return length;
285 }
286
287 //---------------------------------------------------------------------------
288 //
289 // PROC M_FindResponseFile
290 //
291 //---------------------------------------------------------------------------
292
293 #define MAXARGVS 100
294
295 void M_FindResponseFile(void)
296 {
297         int i;
298
299         for(i = 1; i < myargc; i++)
300         {
301                 if(myargv[i][0] == '@')
302                 {
303                         FILE *handle;
304                         int size;
305                         int k;
306                         int index;
307                         int indexinfile;
308                         char *infile;
309                         char *file;
310                         char *moreargs[20];
311                         char *firstargv;
312
313                         // READ THE RESPONSE FILE INTO MEMORY
314                         handle = fopen(&myargv[i][1], "rb");
315                         if(!handle)
316                         {
317                                 printf("\nNo such response file!");
318                                 exit(1);
319                         }
320                         ST_Message("Found response file %s!\n",&myargv[i][1]);
321                         fseek (handle,0,SEEK_END);
322                         size = ftell(handle);
323                         fseek (handle,0,SEEK_SET);
324                         file = malloc (size);
325                         fread (file,size,1,handle);
326                         fclose (handle);
327
328                         // KEEP ALL CMDLINE ARGS FOLLOWING @RESPONSEFILE ARG
329                         for (index = 0,k = i+1; k < myargc; k++)
330                                 moreargs[index++] = myargv[k];
331                         
332                         firstargv = myargv[0];
333                         myargv = malloc(sizeof(char *)*MAXARGVS);
334                         memset(myargv,0,sizeof(char *)*MAXARGVS);
335                         myargv[0] = firstargv;
336                         
337                         infile = file;
338                         indexinfile = k = 0;
339                         indexinfile++;  // SKIP PAST ARGV[0] (KEEP IT)
340                         do
341                         {
342                                 myargv[indexinfile++] = infile+k;
343                                 while(k < size &&  
344
345                                         ((*(infile+k)>= ' '+1) && (*(infile+k)<='z')))
346                                         k++;
347                                 *(infile+k) = 0;
348                                 while(k < size &&
349                                         ((*(infile+k)<= ' ') || (*(infile+k)>'z')))
350                                         k++;
351                         } while(k < size);
352                         
353                         for (k = 0;k < index;k++)
354                                 myargv[indexinfile++] = moreargs[k];
355                         myargc = indexinfile;
356                         // DISPLAY ARGS
357                         if(M_CheckParm("-debug"))
358                         {
359                                 ST_Message("%d command-line args:\n", myargc);
360                                 for(k = 1; k < myargc; k++)
361                                 {
362                                         ST_Message("%s\n", myargv[k]);
363                                 }
364                         }
365                         break;
366                 }
367         }
368 }
369
370 //---------------------------------------------------------------------------
371 //
372 // PROC M_ForceUppercase
373 //
374 // Change string to uppercase.
375 //
376 //---------------------------------------------------------------------------
377
378 void M_ForceUppercase(char *text)
379 {
380         char c;
381
382         while((c = *text) != 0)
383         {
384                 if(c >= 'a' && c <= 'z')
385                 {
386                         *text++ = c-('a'-'A');
387                 }
388                 else
389                 {
390                         text++;
391                 }
392         }
393 }
394
395 /*
396 ==============================================================================
397
398                                                         DEFAULTS
399
400 ==============================================================================
401 */
402
403 int     usemouse;
404 int     usejoystick;
405
406 extern int mouselook;
407 extern boolean cdaudio;
408 extern boolean alwaysrun;
409
410 extern int key_right, key_left, key_up, key_down;
411 extern int key_strafeleft, key_straferight, key_jump;
412 extern int key_fire, key_use, key_strafe, key_speed;
413 extern int key_flyup, key_flydown, key_flycenter;
414 extern int key_lookup, key_lookdown, key_lookcenter;
415 extern int key_invleft, key_invright, key_useartifact;
416
417 extern int mousebfire;
418 extern int mousebstrafe;
419 extern int mousebforward;
420 extern int mousebjump;
421
422 extern int joybfire;
423 extern int joybstrafe;
424 extern int joybuse;
425 extern int joybspeed;
426 extern int joybjump;
427
428 extern boolean messageson;
429
430 extern  int     viewwidth, viewheight;
431
432 int mouseSensitivity;
433
434 extern  int screenblocks;
435
436 extern char *chat_macros[10];
437
438
439
440 #ifndef __NeXT__
441 extern int snd_Channels;
442 extern int snd_DesiredMusicDevice, snd_DesiredSfxDevice;
443 extern int snd_MusicDevice, // current music card # (index to dmxCodes)
444         snd_SfxDevice; // current sfx card # (index to dmxCodes)
445
446 extern int     snd_SBport, snd_SBirq, snd_SBdma;       // sound blaster variables
447 extern int     snd_Mport;                              // midi variables
448 #endif
449
450 default_t defaults[] =
451 {
452         { "mouse_sensitivity", &mouseSensitivity, 5 },
453         { "sfx_volume", &snd_MaxVolume, 10},
454         { "music_volume", &snd_MusicVolume, 10},
455
456 #define SC_INSERT                               0x52
457 #define SC_DELETE                               0x53
458 #define SC_PAGEUP                               0x49
459 #define SC_PAGEDOWN                             0x51
460 #define SC_HOME                                 0x47
461 #define SC_END                                  0x4f
462
463         { "key_right", &key_right, KEY_RIGHTARROW },
464         { "key_left", &key_left, KEY_LEFTARROW },
465         { "key_up", &key_up, KEY_UPARROW },
466         { "key_down", &key_down, KEY_DOWNARROW },
467         { "key_strafeleft", &key_strafeleft, ',' },
468         { "key_straferight", &key_straferight, '.' },
469         { "key_jump", &key_jump, '/'},
470         { "key_flyup", &key_flyup, SC_PAGEUP },
471         { "key_flydown", &key_flydown, SC_INSERT },
472         { "key_flycenter", &key_flycenter, SC_HOME },
473         { "key_lookup", &key_lookup, SC_PAGEDOWN },
474         { "key_lookdown", &key_lookdown, SC_DELETE },
475         { "key_lookcenter", &key_lookcenter, SC_END },
476         { "key_invleft", &key_invleft, '[' },
477         { "key_invright", &key_invright, ']' },
478         { "key_useartifact", &key_useartifact, 13 },
479         { "key_fire", &key_fire, KEY_RCTRL, 1 },
480         { "key_use", &key_use, ' ', 1 },
481         { "key_strafe", &key_strafe, KEY_RALT, 1 },
482         { "key_speed", &key_speed, KEY_RSHIFT, 1 },
483         { "use_mouse", &usemouse, 1 },
484         { "mouseb_fire", &mousebfire, 0 },
485         { "mouseb_strafe", &mousebstrafe, 1 },
486         { "mouseb_forward", &mousebforward, 2 },
487         { "mouseb_jump", &mousebjump, -1 },
488         { "use_joystick", &usejoystick, 0 },
489         { "joyb_fire", &joybfire, 0 },
490         { "joyb_strafe", &joybstrafe, 1 },
491         { "joyb_use", &joybuse, 3 },
492         { "joyb_speed", &joybspeed, 2 },
493         { "joyb_jump", &joybjump, -1 },
494         { "screenblocks", &screenblocks, 10 },
495         { "snd_channels", &snd_Channels, 3 },
496         { "snd_musicdevice", &snd_DesiredMusicDevice, 0 },
497         { "snd_sfxdevice", &snd_DesiredSfxDevice, 0 },
498         { "snd_sbport", &snd_SBport, 544 },
499         { "snd_sbirq", &snd_SBirq, -1 },
500         { "snd_sbdma", &snd_SBdma, -1 },
501         { "snd_mport", &snd_Mport, -1 },
502
503         { "usegamma", &usegamma, 0 },
504
505         { "messageson", (int *) &messageson, 1 },
506
507         { "chatmacro0", (int *) &chat_macros[0], (int) HUSTR_CHATMACRO0 },
508         { "chatmacro1", (int *) &chat_macros[1], (int) HUSTR_CHATMACRO1 },
509         { "chatmacro2", (int *) &chat_macros[2], (int) HUSTR_CHATMACRO2 },
510         { "chatmacro3", (int *) &chat_macros[3], (int) HUSTR_CHATMACRO3 },
511         { "chatmacro4", (int *) &chat_macros[4], (int) HUSTR_CHATMACRO4 },
512         { "chatmacro5", (int *) &chat_macros[5], (int) HUSTR_CHATMACRO5 },
513         { "chatmacro6", (int *) &chat_macros[6], (int) HUSTR_CHATMACRO6 },
514         { "chatmacro7", (int *) &chat_macros[7], (int) HUSTR_CHATMACRO7 },
515         { "chatmacro8", (int *) &chat_macros[8], (int) HUSTR_CHATMACRO8 },
516         { "chatmacro9", (int *) &chat_macros[9], (int) HUSTR_CHATMACRO9 },
517         { "mouselook", &mouselook, 0 },
518         { "cdaudio", (int *) &cdaudio, false }, /* jim cast added (warning) */
519         { "alwaysrun", (int *) &alwaysrun, false }
520 };
521
522 int numdefaults;
523 char defaultfile[128];
524
525 /*
526 ==============
527 =
528 = M_SaveDefaults
529 =
530 ==============
531 */
532
533 void M_SaveDefaults (void)
534 {
535         int     i,v;
536         FILE    *f;
537
538         f = fopen (defaultfile, "w");
539         if (!f)
540                 return;         // can't write the file, but don't complain
541
542         for (i=0 ; i<numdefaults ; i++)
543         { 
544                 if (defaults[i].defaultvalue > -0xfff
545                   && defaults[i].defaultvalue < 0xfff)
546                 {
547                         v = *defaults[i].location;
548                         fprintf (f,"%s\t\t%i\n",defaults[i].name,v);
549                 } else {
550                         fprintf (f,"%s\t\t\"%s\"\n",defaults[i].name,
551                           * (char **) (defaults[i].location));
552                 }
553         }
554
555         fclose (f);
556 }
557
558 //==========================================================================
559 //
560 // M_LoadDefaults
561 //
562 //==========================================================================
563
564 extern byte scantokey[128];
565
566 void M_LoadDefaults(char *fileName)
567 {
568         int i;
569         int len;
570         FILE *f;
571         char def[80];
572         char strparm[100];
573         char *newstring = NULL;  /* jim initialiser added */
574         int parm;
575         boolean isstring;
576
577         // Set everything to base values
578         numdefaults = sizeof(defaults)/sizeof(defaults[0]);
579         ST_Message("M_LoadDefaults: %d default settings loaded\n", numdefaults);
580         for(i = 0; i < numdefaults; i++)
581         {
582                 *defaults[i].location = defaults[i].defaultvalue;
583         }
584
585         // Check for a custom config file
586         i = M_CheckParm("-config");
587         if(i && i < myargc-1)
588         {
589                 strncpy(defaultfile, myargv[i+1], 128);
590                 defaultfile[127] = '\0';
591                 ST_Message("config file: %s\n", defaultfile);
592         }
593         else
594         {
595                 strncpy(defaultfile, strcat(basePath,fileName), 128);
596                 defaultfile[127] = '\0';
597         }
598
599         // Scan the config file
600         f = fopen(defaultfile, "r");
601         if(f)
602         {
603                 while(!feof(f))
604                 {
605                         isstring = false;
606                         if(fscanf(f, "%79s %[^\n]\n", def, strparm) == 2)
607                         {
608                                 if(strparm[0] == '"')
609                                 {
610                                          // Get a string default
611                                          isstring = true;
612                                          len = strlen(strparm);
613                                          newstring = (char *)malloc(len);
614                                          if (newstring == NULL) I_Error("can't malloc newstring");
615                                          strparm[len-1] = 0;
616                                          strcpy(newstring, strparm+1);
617                                 }
618                                 else if(strparm[0] == '0' && strparm[1] == 'x')
619                                 {
620                                         sscanf(strparm+2, "%x", &parm);
621                                 }
622                                 else
623                                 {
624                                         sscanf(strparm, "%i", &parm);
625                                 }
626                                 for(i = 0; i < numdefaults; i++)
627                                 {
628                                         if(!strcmp(def, defaults[i].name))
629                                         {
630                                                 if(!isstring)
631                                                 {
632                                                         *defaults[i].location = parm;
633                                                 }
634                                                 else
635                                                 {
636                                                         *defaults[i].location = (int)newstring;
637                                                 }
638                                                 break;
639                                         }
640                                 }
641                         }
642                 }
643                 fclose (f);
644         }
645
646 }
647
648 /*
649 ==============================================================================
650
651                                                 SCREEN SHOTS
652
653 ==============================================================================
654 */
655
656
657 typedef struct
658 {
659         char    manufacturer;
660         char    version;
661         char    encoding;
662         char    bits_per_pixel;
663         unsigned short  xmin,ymin,xmax,ymax;
664         unsigned short  hres,vres;
665         unsigned char   palette[48];
666         char    reserved;
667         char    color_planes;
668         unsigned short  bytes_per_line;
669         unsigned short  palette_type;
670         char    filler[58];
671         unsigned char   data;           // unbounded
672 } pcx_t;
673
674 /*
675 ==============
676 =
677 = WritePCXfile
678 =
679 ==============
680 */
681
682 void WritePCXfile (char *filename, byte *data, int width, int height, byte *palette)
683 {
684         int     i, length;
685         pcx_t   *pcx;
686         byte        *pack;
687         
688         pcx = Z_Malloc (width*height*2+1000, PU_STATIC, NULL);
689
690         pcx->manufacturer = 0x0a;   // PCX id
691         pcx->version = 5;           // 256 color
692         pcx->encoding = 1;      // uncompressed
693         pcx->bits_per_pixel = 8;        // 256 color
694         pcx->xmin = 0;
695         pcx->ymin = 0;
696         pcx->xmax = SHORT(width-1);
697         pcx->ymax = SHORT(height-1);
698         pcx->hres = SHORT(width);
699         pcx->vres = SHORT(height);
700         memset (pcx->palette,0,sizeof(pcx->palette));
701         pcx->color_planes = 1;      // chunky image
702         pcx->bytes_per_line = SHORT(width);
703         pcx->palette_type = SHORT(2);       // not a grey scale
704         memset (pcx->filler,0,sizeof(pcx->filler));
705
706 //
707 // pack the image
708 //
709         pack = &pcx->data;
710
711         for (i=0 ; i<width*height ; i++)
712                 if ( (*data & 0xc0) != 0xc0)
713                         *pack++ = *data++;
714                 else
715                 {
716                         *pack++ = 0xc1;
717                         *pack++ = *data++;
718                 }
719
720 //
721 // write the palette
722 //
723         *pack++ = 0x0c; // palette ID byte
724         for (i=0 ; i<768 ; i++)
725                 *pack++ = *palette++;
726
727 //
728 // write output file
729 //
730         length = pack - (byte *)pcx;
731         M_WriteFile (filename, pcx, length);
732
733         Z_Free (pcx);
734 }
735
736
737 //==============================================================================
738
739 /*
740 ==================
741 =
742 = M_ScreenShot
743 =
744 ==================
745 */
746 #ifdef RENDER3D
747 void M_ScreenShot (void)
748 {
749 //OGL_GrabScreen();
750 }
751 #else
752 void M_ScreenShot (void)
753 {
754         int     i;
755         byte    *linear;
756         char    lbmname[12];
757         byte *pal;
758
759 //
760 // munge planar buffer to linear
761 // 
762         linear = screen; 
763 //
764 // find a file name to save it to
765 //
766         strcpy(lbmname,"HEXEN00.pcx");
767
768         for (i=0 ; i<=99 ; i++)
769         {
770                 lbmname[5] = i/10 + '0';
771                 lbmname[6] = i%10 + '0';
772                 if (access(lbmname,0) == -1)
773                         break;  // file doesn't exist
774         }
775         if (i==100)
776                 I_Error ("M_ScreenShot: Couldn't create a PCX");
777
778 //
779 // save the pcx file
780 // 
781         pal = (byte *)W_CacheLumpName("PLAYPAL", PU_CACHE);
782
783         WritePCXfile (lbmname, linear, SCREENWIDTH, SCREENHEIGHT
784                 , pal);
785
786         P_SetMessage(&players[consoleplayer], "SCREEN SHOT", false);
787 }
788 #endif