osezer patch 004
[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 /* change of order here affects mn_menu.c :
457  * see, for example, Options3Items there...
458  */
459         { "mouse_sensitivity", &mouseSensitivity, 5 },
460         { "sfx_volume", &snd_MaxVolume, 10},
461         { "music_volume", &snd_MusicVolume, 10},
462
463 #define SC_INSERT                               0x52
464 #define SC_DELETE                               0x53
465 #define SC_PAGEUP                               0x49
466 #define SC_PAGEDOWN                             0x51
467 #define SC_HOME                                 0x47
468 #define SC_END                                  0x4f
469
470         { "key_right", &key_right, KEY_RIGHTARROW },
471         { "key_left", &key_left, KEY_LEFTARROW },
472         { "key_up", &key_up, KEY_UPARROW },
473         { "key_down", &key_down, KEY_DOWNARROW },
474         { "key_strafeleft", &key_strafeleft, ',' },
475         { "key_straferight", &key_straferight, '.' },
476         { "key_jump", &key_jump, '/'},
477         { "key_flyup", &key_flyup, SC_PAGEUP },
478         { "key_flydown", &key_flydown, SC_INSERT },
479         { "key_flycenter", &key_flycenter, SC_HOME },
480         { "key_lookup", &key_lookup, SC_PAGEDOWN },
481         { "key_lookdown", &key_lookdown, SC_DELETE },
482         { "key_lookcenter", &key_lookcenter, SC_END },
483         { "key_invleft", &key_invleft, '[' },
484         { "key_invright", &key_invright, ']' },
485         { "key_useartifact", &key_useartifact, 13 },
486         { "key_fire", &key_fire, KEY_RCTRL, 1 },
487         { "key_use", &key_use, ' ', 1 },
488         { "key_strafe", &key_strafe, KEY_RALT, 1 },
489         { "key_speed", &key_speed, KEY_RSHIFT, 1 },
490         { "use_mouse", &usemouse, 1 },
491         { "mouseb_fire", &mousebfire, 0 },
492         { "mouseb_strafe", &mousebstrafe, 1 },
493         { "mouseb_forward", &mousebforward, 2 },
494         { "mouseb_jump", &mousebjump, -1 },
495         { "use_joystick", &usejoystick, 0 },
496         { "joyb_fire", &joybfire, 0 },
497         { "joyb_strafe", &joybstrafe, 1 },
498         { "joyb_use", &joybuse, 3 },
499         { "joyb_speed", &joybspeed, 2 },
500         { "joyb_jump", &joybjump, -1 },
501         { "screenblocks", &screenblocks, 10 },
502         { "snd_channels", &snd_Channels, 3 },
503         { "snd_musicdevice", &snd_DesiredMusicDevice, 0 },
504         { "snd_sfxdevice", &snd_DesiredSfxDevice, 0 },
505         { "snd_sbport", &snd_SBport, 544 },
506         { "snd_sbirq", &snd_SBirq, -1 },
507         { "snd_sbdma", &snd_SBdma, -1 },
508         { "snd_mport", &snd_Mport, -1 },
509
510         { "usegamma", &usegamma, 0 },
511
512         { "messageson", (int *) &messageson, 1 },
513
514         { "chatmacro0", (int *) &chat_macros[0], (int) HUSTR_CHATMACRO0 },
515         { "chatmacro1", (int *) &chat_macros[1], (int) HUSTR_CHATMACRO1 },
516         { "chatmacro2", (int *) &chat_macros[2], (int) HUSTR_CHATMACRO2 },
517         { "chatmacro3", (int *) &chat_macros[3], (int) HUSTR_CHATMACRO3 },
518         { "chatmacro4", (int *) &chat_macros[4], (int) HUSTR_CHATMACRO4 },
519         { "chatmacro5", (int *) &chat_macros[5], (int) HUSTR_CHATMACRO5 },
520         { "chatmacro6", (int *) &chat_macros[6], (int) HUSTR_CHATMACRO6 },
521         { "chatmacro7", (int *) &chat_macros[7], (int) HUSTR_CHATMACRO7 },
522         { "chatmacro8", (int *) &chat_macros[8], (int) HUSTR_CHATMACRO8 },
523         { "chatmacro9", (int *) &chat_macros[9], (int) HUSTR_CHATMACRO9 },
524         { "mouselook", &mouselook, 0 },
525         { "cdaudio", (int *) &cdaudio, false }, /* jim cast added (warning) */
526         { "alwaysrun", (int *) &alwaysrun, false }
527 };
528
529 int numdefaults;
530 char defaultfile[128];
531
532 /*
533 ==============
534 =
535 = M_SaveDefaults
536 =
537 ==============
538 */
539
540 void M_SaveDefaults (void)
541 {
542         int     i,v;
543         FILE    *f;
544
545         f = fopen (defaultfile, "w");
546         if (!f)
547                 return;         // can't write the file, but don't complain
548
549         for (i=0 ; i<numdefaults ; i++)
550         { 
551                 if (defaults[i].defaultvalue > -0xfff
552                   && defaults[i].defaultvalue < 0xfff)
553                 {
554                         v = *defaults[i].location;
555                         fprintf (f,"%s\t\t%i\n",defaults[i].name,v);
556                 } else {
557                         fprintf (f,"%s\t\t\"%s\"\n",defaults[i].name,
558                           * (char **) (defaults[i].location));
559                 }
560         }
561
562         fclose (f);
563 }
564
565 //==========================================================================
566 //
567 // M_LoadDefaults
568 //
569 //==========================================================================
570
571 extern byte scantokey[128];
572
573 void M_LoadDefaults(char *fileName)
574 {
575         int i;
576         int len;
577         FILE *f;
578         char def[80];
579         char strparm[100];
580         char *newstring = NULL;  /* jim initialiser added */
581         int parm;
582         boolean isstring;
583
584         // Set everything to base values
585         numdefaults = sizeof(defaults)/sizeof(defaults[0]);
586         ST_Message("M_LoadDefaults: %d default settings loaded\n", numdefaults);
587         for(i = 0; i < numdefaults; i++)
588         {
589                 *defaults[i].location = defaults[i].defaultvalue;
590         }
591
592         // Check for a custom config file
593         i = M_CheckParm("-config");
594         if(i && i < myargc-1)
595         {
596                 strncpy(defaultfile, myargv[i+1], 128);
597                 defaultfile[127] = '\0';
598                 ST_Message("config file: %s\n", defaultfile);
599         }
600         else
601         {
602         // this is broken: basePath should not be changed here. S.A.
603         //      strncpy(defaultfile, strcat(basePath,fileName), 128);
604                 strncpy(defaultfile, basePath, 128);
605                 strcat (defaultfile, fileName);
606                 defaultfile[127] = '\0';
607         }
608
609         // Scan the config file
610         f = fopen(defaultfile, "r");
611         if(f)
612         {
613                 while(!feof(f))
614                 {
615                         isstring = false;
616                         if(fscanf(f, "%79s %[^\n]\n", def, strparm) == 2)
617                         {
618                                 if(strparm[0] == '"')
619                                 {
620                                          // Get a string default
621                                          isstring = true;
622                                          len = strlen(strparm);
623                                          newstring = (char *)malloc(len);
624                                          if (newstring == NULL) I_Error("can't malloc newstring");
625                                          strparm[len-1] = 0;
626                                          strcpy(newstring, strparm+1);
627                                 }
628                                 else if(strparm[0] == '0' && strparm[1] == 'x')
629                                 {
630                                         sscanf(strparm+2, "%x", &parm);
631                                 }
632                                 else
633                                 {
634                                         sscanf(strparm, "%i", &parm);
635                                 }
636                                 for(i = 0; i < numdefaults; i++)
637                                 {
638                                         if(!strcmp(def, defaults[i].name))
639                                         {
640                                                 if(!isstring)
641                                                 {
642                                                         *defaults[i].location = parm;
643                                                 }
644                                                 else
645                                                 {
646                                                         *defaults[i].location = (int)newstring;
647                                                 }
648                                                 break;
649                                         }
650                                 }
651                         }
652                 }
653                 fclose (f);
654         }
655
656 }
657
658 /*
659 ==============================================================================
660
661                                                 SCREEN SHOTS
662
663 ==============================================================================
664 */
665
666
667 typedef struct
668 {
669         char    manufacturer;
670         char    version;
671         char    encoding;
672         char    bits_per_pixel;
673         unsigned short  xmin,ymin,xmax,ymax;
674         unsigned short  hres,vres;
675         unsigned char   palette[48];
676         char    reserved;
677         char    color_planes;
678         unsigned short  bytes_per_line;
679         unsigned short  palette_type;
680         char    filler[58];
681         unsigned char   data;           // unbounded
682 } pcx_t;
683
684 /*
685 ==============
686 =
687 = WritePCXfile
688 =
689 ==============
690 */
691
692 void WritePCXfile (char *filename, byte *data, int width, int height, byte *palette)
693 {
694         int     i, length;
695         pcx_t   *pcx;
696         byte        *pack;
697         
698         pcx = Z_Malloc (width*height*2+1000, PU_STATIC, NULL);
699
700         pcx->manufacturer = 0x0a;   // PCX id
701         pcx->version = 5;           // 256 color
702         pcx->encoding = 1;      // uncompressed
703         pcx->bits_per_pixel = 8;        // 256 color
704         pcx->xmin = 0;
705         pcx->ymin = 0;
706         pcx->xmax = SHORT(width-1);
707         pcx->ymax = SHORT(height-1);
708         pcx->hres = SHORT(width);
709         pcx->vres = SHORT(height);
710         memset (pcx->palette,0,sizeof(pcx->palette));
711         pcx->color_planes = 1;      // chunky image
712         pcx->bytes_per_line = SHORT(width);
713         pcx->palette_type = SHORT(2);       // not a grey scale
714         memset (pcx->filler,0,sizeof(pcx->filler));
715
716 //
717 // pack the image
718 //
719         pack = &pcx->data;
720
721         for (i=0 ; i<width*height ; i++)
722                 if ( (*data & 0xc0) != 0xc0)
723                         *pack++ = *data++;
724                 else
725                 {
726                         *pack++ = 0xc1;
727                         *pack++ = *data++;
728                 }
729
730 //
731 // write the palette
732 //
733         *pack++ = 0x0c; // palette ID byte
734         for (i=0 ; i<768 ; i++)
735                 *pack++ = *palette++;
736
737 //
738 // write output file
739 //
740         length = pack - (byte *)pcx;
741         M_WriteFile (filename, pcx, length);
742
743         Z_Free (pcx);
744 }
745
746
747 //==============================================================================
748
749 /*
750 ==================
751 =
752 = M_ScreenShot
753 =
754 ==================
755 */
756 #ifdef RENDER3D
757 void M_ScreenShot (void)
758 {
759 //OGL_GrabScreen();
760 }
761 #else
762 void M_ScreenShot (void)
763 {
764         int     i;
765         byte    *linear;
766         char    lbmname[12];
767         byte *pal;
768
769 //
770 // munge planar buffer to linear
771 // 
772         linear = screen; 
773 //
774 // find a file name to save it to
775 //
776         strcpy(lbmname,"HEXEN00.pcx");
777
778         for (i=0 ; i<=99 ; i++)
779         {
780                 lbmname[5] = i/10 + '0';
781                 lbmname[6] = i%10 + '0';
782                 if (access(lbmname,0) == -1)
783                         break;  // file doesn't exist
784         }
785         if (i==100)
786                 I_Error ("M_ScreenShot: Couldn't create a PCX");
787
788 //
789 // save the pcx file
790 // 
791         pal = (byte *)W_CacheLumpName("PLAYPAL", PU_CACHE);
792
793         WritePCXfile (lbmname, linear, SCREENWIDTH, SCREENHEIGHT
794                 , pal);
795
796         P_SetMessage(&players[consoleplayer], "SCREEN SHOT", false);
797 }
798 #endif
799