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