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