2 //**************************************************************************
4 //** m_misc.c : Heretic 2 : Raven Software, Corp.
11 //**************************************************************************
13 // HEADER FILES ------------------------------------------------------------
17 #include <unistd.h> /* jim write() read() close() */
23 // MACROS ------------------------------------------------------------------
28 // TYPES -------------------------------------------------------------------
30 // EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
33 extern void OGL_GrabScreen();
36 // PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
38 // PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
40 static int ReadFile(char const *name, byte **buffer, int mallocType);
42 // EXTERNAL DATA DECLARATIONS ----------------------------------------------
43 extern char *basePath;
45 // PUBLIC DATA DEFINITIONS -------------------------------------------------
50 // PRIVATE DATA DEFINITIONS ------------------------------------------------
52 // CODE --------------------------------------------------------------------
54 //==========================================================================
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.
61 //==========================================================================
63 int M_CheckParm(char *check)
67 for(i = 1; i < myargc; i++)
69 if(!strcasecmp(check, myargv[i]))
77 //==========================================================================
81 // Returns true if the given parameter exists in the program's command
82 // line arguments, false if not.
84 //==========================================================================
86 boolean M_ParmExists(char *check)
88 return M_CheckParm(check) != 0 ? true : false;
91 //==========================================================================
95 //==========================================================================
97 void M_ExtractFileBase(char *path, char *dest)
102 src = path+strlen(path)-1;
104 // Back up until a \ or the start
105 while(src != path && *(src-1) != '\\' && *(src-1) != '/')
110 // Copy up to eight characters
113 while(*src && *src != '.')
117 I_Error("Filename base of %s > 8 chars", path);
119 *dest++ = toupper((int)*src++);
128 = Returns a 0-255 number
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
157 unsigned char P_Random (void)
159 return rndtable[(++prndindex)&0xff];
164 rndindex = (rndindex+1)&0xff;
165 return rndtable[rndindex];
168 void M_ClearRandom (void)
170 rndindex = prndindex = 0;
174 void M_ClearBox (fixed_t *box)
176 box[BOXTOP] = box[BOXRIGHT] = MININT;
177 box[BOXBOTTOM] = box[BOXLEFT] = MAXINT;
180 void M_AddToBox (fixed_t *box, fixed_t x, fixed_t y)
184 else if (x>box[BOXRIGHT])
186 if (y<box[BOXBOTTOM])
188 else if (y>box[BOXTOP])
204 boolean M_WriteFile (char const *name, void *source, int length)
208 handle = open (name, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666);
211 count = write (handle, source, length);
220 //==========================================================================
224 // Read a file into a buffer allocated using Z_Malloc().
226 //==========================================================================
228 int M_ReadFile(char const *name, byte **buffer)
230 return ReadFile(name, buffer, MALLOC_ZONE);
233 //==========================================================================
237 // Read a file into a buffer allocated using malloc().
239 //==========================================================================
241 int M_ReadFileCLib(char const *name, byte **buffer)
243 return ReadFile(name, buffer, MALLOC_CLIB);
246 //==========================================================================
250 //==========================================================================
252 static int ReadFile(char const *name, byte **buffer, int mallocType)
254 int handle, count, length;
255 struct stat fileinfo;
258 handle = open(name, O_RDONLY|O_BINARY, 0666);
261 I_Error("Couldn't read file %s", name);
263 if(fstat(handle, &fileinfo) == -1)
265 I_Error("Couldn't read file %s", name);
267 length = fileinfo.st_size;
268 if(mallocType == MALLOC_ZONE)
269 { // Use zone memory allocation
270 buf = Z_Malloc(length, PU_STATIC, NULL);
273 { // Use c library memory allocation
274 buf = malloc(length);
277 I_Error("Couldn't malloc buffer %d for file %s.",
281 count = read(handle, buf, length);
285 I_Error("Couldn't read file %s", name);
291 //---------------------------------------------------------------------------
293 // PROC M_FindResponseFile
295 //---------------------------------------------------------------------------
299 void M_FindResponseFile(void)
303 for(i = 1; i < myargc; i++)
305 if(myargv[i][0] == '@')
317 // READ THE RESPONSE FILE INTO MEMORY
318 handle = fopen(&myargv[i][1], "rb");
321 printf("\nNo such response file!");
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);
332 // KEEP ALL CMDLINE ARGS FOLLOWING @RESPONSEFILE ARG
333 for (index = 0,k = i+1; k < myargc; k++)
334 moreargs[index++] = myargv[k];
336 firstargv = myargv[0];
337 myargv = malloc(sizeof(char *)*MAXARGVS);
338 memset(myargv,0,sizeof(char *)*MAXARGVS);
339 myargv[0] = firstargv;
343 indexinfile++; // SKIP PAST ARGV[0] (KEEP IT)
346 myargv[indexinfile++] = infile+k;
349 ((*(infile+k)>= ' '+1) && (*(infile+k)<='z')))
353 ((*(infile+k)<= ' ') || (*(infile+k)>'z')))
357 for (k = 0;k < index;k++)
358 myargv[indexinfile++] = moreargs[k];
359 myargc = indexinfile;
361 if(M_CheckParm("-debug"))
363 ST_Message("%d command-line args:\n", myargc);
364 for(k = 1; k < myargc; k++)
366 ST_Message("%s\n", myargv[k]);
374 //---------------------------------------------------------------------------
376 // PROC M_ForceUppercase
378 // Change string to uppercase.
380 //---------------------------------------------------------------------------
382 void M_ForceUppercase(char *text)
386 while((c = *text) != 0)
388 if(c >= 'a' && c <= 'z')
390 *text++ = c-('a'-'A');
400 ==============================================================================
404 ==============================================================================
410 extern int mouselook;
411 extern boolean cdaudio;
412 extern boolean alwaysrun;
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;
421 extern int mousebfire;
422 extern int mousebstrafe;
423 extern int mousebforward;
424 extern int mousebjump;
427 extern int joybstrafe;
429 extern int joybspeed;
432 extern boolean messageson;
434 extern int viewwidth, viewheight;
436 int mouseSensitivity;
438 extern int screenblocks;
440 extern char *chat_macros[10];
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)
450 extern int snd_SBport, snd_SBirq, snd_SBdma; // sound blaster variables
451 extern int snd_Mport; // midi variables
454 default_t defaults[] =
456 /* change of order here affects mn_menu.c :
457 * see, for example, Options3Items there...
459 { "mouse_sensitivity", &mouseSensitivity, 5 },
460 { "sfx_volume", &snd_MaxVolume, 10},
461 { "music_volume", &snd_MusicVolume, 10},
463 #define SC_INSERT 0x52
464 #define SC_DELETE 0x53
465 #define SC_PAGEUP 0x49
466 #define SC_PAGEDOWN 0x51
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 },
510 { "usegamma", &usegamma, 0 },
512 { "messageson", (int *) &messageson, 1 },
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 }
530 char defaultfile[128];
540 void M_SaveDefaults (void)
545 f = fopen (defaultfile, "w");
547 return; // can't write the file, but don't complain
549 for (i=0 ; i<numdefaults ; i++)
551 if (defaults[i].defaultvalue > -0xfff
552 && defaults[i].defaultvalue < 0xfff)
554 v = *defaults[i].location;
555 fprintf (f,"%s\t\t%i\n",defaults[i].name,v);
557 fprintf (f,"%s\t\t\"%s\"\n",defaults[i].name,
558 * (char **) (defaults[i].location));
565 //==========================================================================
569 //==========================================================================
571 extern byte scantokey[128];
573 void M_LoadDefaults(char *fileName)
580 char *newstring = NULL; /* jim initialiser added */
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++)
589 *defaults[i].location = defaults[i].defaultvalue;
592 // Check for a custom config file
593 i = M_CheckParm("-config");
594 if(i && i < myargc-1)
596 strncpy(defaultfile, myargv[i+1], 128);
597 defaultfile[127] = '\0';
598 ST_Message("config file: %s\n", defaultfile);
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';
609 // Scan the config file
610 f = fopen(defaultfile, "r");
616 if(fscanf(f, "%79s %[^\n]\n", def, strparm) == 2)
618 if(strparm[0] == '"')
620 // Get a string default
622 len = strlen(strparm);
623 newstring = (char *)malloc(len);
624 if (newstring == NULL) I_Error("can't malloc newstring");
626 strcpy(newstring, strparm+1);
628 else if(strparm[0] == '0' && strparm[1] == 'x')
630 sscanf(strparm+2, "%x", &parm);
634 sscanf(strparm, "%i", &parm);
636 for(i = 0; i < numdefaults; i++)
638 if(!strcmp(def, defaults[i].name))
642 *defaults[i].location = parm;
646 *defaults[i].location = (int)newstring;
659 ==============================================================================
663 ==============================================================================
673 unsigned short xmin,ymin,xmax,ymax;
674 unsigned short hres,vres;
675 unsigned char palette[48];
678 unsigned short bytes_per_line;
679 unsigned short palette_type;
681 unsigned char data; // unbounded
692 void WritePCXfile (char *filename, byte *data, int width, int height, byte *palette)
698 pcx = Z_Malloc (width*height*2+1000, PU_STATIC, NULL);
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
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));
721 for (i=0 ; i<width*height ; i++)
722 if ( (*data & 0xc0) != 0xc0)
733 *pack++ = 0x0c; // palette ID byte
734 for (i=0 ; i<768 ; i++)
735 *pack++ = *palette++;
740 length = pack - (byte *)pcx;
741 M_WriteFile (filename, pcx, length);
747 //==============================================================================
757 void M_ScreenShot (void)
762 void M_ScreenShot (void)
770 // munge planar buffer to linear
774 // find a file name to save it to
776 strcpy(lbmname,"HEXEN00.pcx");
778 for (i=0 ; i<=99 ; i++)
780 lbmname[5] = i/10 + '0';
781 lbmname[6] = i%10 + '0';
782 if (access(lbmname,0) == -1)
783 break; // file doesn't exist
786 I_Error ("M_ScreenShot: Couldn't create a PCX");
791 pal = (byte *)W_CacheLumpName("PLAYPAL", PU_CACHE);
793 WritePCXfile (lbmname, linear, SCREENWIDTH, SCREENHEIGHT
796 P_SetMessage(&players[consoleplayer], "SCREEN SHOT", false);