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