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