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
134 // This is the new flat distribution table
135 unsigned char rndtable[256] = {
136 201, 1,243, 19, 18, 42,183,203,101,123,154,137, 34,118, 10,216,
137 135,246, 0,107,133,229, 35,113,177,211,110, 17,139, 84,251,235,
138 182,166,161,230,143, 91, 24, 81, 22, 94, 7, 51,232,104,122,248,
139 175,138,127,171,222,213, 44, 16, 9, 33, 88,102,170,150,136,114,
140 62, 3,142,237, 6,252,249, 56, 74, 30, 13, 21,180,199, 32,132,
141 187,234, 78,210, 46,131,197, 8,206,244, 73, 4,236,178,195, 70,
142 121, 97,167,217,103, 40,247,186,105, 39, 95,163, 99,149,253, 29,
143 119, 83,254, 26,202, 65,130,155, 60, 64,184,106,221, 93,164,196,
144 112,108,179,141, 54,109, 11,126, 75,165,191,227, 87,225,156, 15,
145 98,162,116, 79,169,140,190,205,168,194, 41,250, 27, 20, 14,241,
146 50,214, 72,192,220,233, 67,148, 96,185,176,181,215,207,172, 85,
147 89, 90,209,128,124, 2, 55,173, 66,152, 47,129, 59, 43,159,240,
148 239, 12,189,212,144, 28,200, 77,219,198,134,228, 45, 92,125,151,
149 5, 53,255, 52, 68,245,160,158, 61, 86, 58, 82,117, 37,242,145,
150 69,188,115, 76, 63,100, 49,111,153, 80, 38, 57,174,224, 71,231,
151 23, 25, 48,218,120,147,208, 36,226,223,193,238,157,204,146, 31
160 rndindex = (rndindex+1)&0xff;
161 return rndtable[rndindex];
164 void M_ClearRandom (void)
166 rndindex = prndindex = 0;
170 void M_ClearBox (fixed_t *box)
172 box[BOXTOP] = box[BOXRIGHT] = MININT;
173 box[BOXBOTTOM] = box[BOXLEFT] = MAXINT;
176 void M_AddToBox (fixed_t *box, fixed_t x, fixed_t y)
180 else if (x>box[BOXRIGHT])
182 if (y<box[BOXBOTTOM])
184 else if (y>box[BOXTOP])
200 boolean M_WriteFile (char const *name, void *source, int length)
204 handle = open (name, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666);
207 count = write (handle, source, length);
216 //==========================================================================
220 // Read a file into a buffer allocated using Z_Malloc().
222 //==========================================================================
224 int M_ReadFile(char const *name, byte **buffer)
226 return ReadFile(name, buffer, MALLOC_ZONE);
229 //==========================================================================
233 // Read a file into a buffer allocated using malloc().
235 //==========================================================================
237 int M_ReadFileCLib(char const *name, byte **buffer)
239 return ReadFile(name, buffer, MALLOC_CLIB);
242 //==========================================================================
246 //==========================================================================
248 static int ReadFile(char const *name, byte **buffer, int mallocType)
250 int handle, count, length;
251 struct stat fileinfo;
254 handle = open(name, O_RDONLY|O_BINARY, 0666);
257 I_Error("Couldn't read file %s", name);
259 if(fstat(handle, &fileinfo) == -1)
261 I_Error("Couldn't read file %s", name);
263 length = fileinfo.st_size;
264 if(mallocType == MALLOC_ZONE)
265 { // Use zone memory allocation
266 buf = Z_Malloc(length, PU_STATIC, NULL);
269 { // Use c library memory allocation
270 buf = malloc(length);
273 I_Error("Couldn't malloc buffer %d for file %s.",
277 count = read(handle, buf, length);
281 I_Error("Couldn't read file %s", name);
287 //---------------------------------------------------------------------------
289 // PROC M_FindResponseFile
291 //---------------------------------------------------------------------------
295 void M_FindResponseFile(void)
299 for(i = 1; i < myargc; i++)
301 if(myargv[i][0] == '@')
313 // READ THE RESPONSE FILE INTO MEMORY
314 handle = fopen(&myargv[i][1], "rb");
317 printf("\nNo such response file!");
320 ST_Message("Found response file %s!\n",&myargv[i][1]);
321 fseek (handle,0,SEEK_END);
322 size = ftell(handle);
323 fseek (handle,0,SEEK_SET);
324 file = malloc (size);
325 fread (file,size,1,handle);
328 // KEEP ALL CMDLINE ARGS FOLLOWING @RESPONSEFILE ARG
329 for (index = 0,k = i+1; k < myargc; k++)
330 moreargs[index++] = myargv[k];
332 firstargv = myargv[0];
333 myargv = malloc(sizeof(char *)*MAXARGVS);
334 memset(myargv,0,sizeof(char *)*MAXARGVS);
335 myargv[0] = firstargv;
339 indexinfile++; // SKIP PAST ARGV[0] (KEEP IT)
342 myargv[indexinfile++] = infile+k;
345 ((*(infile+k)>= ' '+1) && (*(infile+k)<='z')))
349 ((*(infile+k)<= ' ') || (*(infile+k)>'z')))
353 for (k = 0;k < index;k++)
354 myargv[indexinfile++] = moreargs[k];
355 myargc = indexinfile;
357 if(M_CheckParm("-debug"))
359 ST_Message("%d command-line args:\n", myargc);
360 for(k = 1; k < myargc; k++)
362 ST_Message("%s\n", myargv[k]);
370 //---------------------------------------------------------------------------
372 // PROC M_ForceUppercase
374 // Change string to uppercase.
376 //---------------------------------------------------------------------------
378 void M_ForceUppercase(char *text)
382 while((c = *text) != 0)
384 if(c >= 'a' && c <= 'z')
386 *text++ = c-('a'-'A');
396 ==============================================================================
400 ==============================================================================
406 extern int mouselook;
407 extern boolean cdaudio;
408 extern boolean alwaysrun;
410 extern int key_right, key_left, key_up, key_down;
411 extern int key_strafeleft, key_straferight, key_jump;
412 extern int key_fire, key_use, key_strafe, key_speed;
413 extern int key_flyup, key_flydown, key_flycenter;
414 extern int key_lookup, key_lookdown, key_lookcenter;
415 extern int key_invleft, key_invright, key_useartifact;
417 extern int mousebfire;
418 extern int mousebstrafe;
419 extern int mousebforward;
420 extern int mousebjump;
423 extern int joybstrafe;
425 extern int joybspeed;
428 extern boolean messageson;
430 extern int viewwidth, viewheight;
432 int mouseSensitivity;
434 extern int screenblocks;
436 extern char *chat_macros[10];
441 extern int snd_Channels;
442 extern int snd_DesiredMusicDevice, snd_DesiredSfxDevice;
443 extern int snd_MusicDevice, // current music card # (index to dmxCodes)
444 snd_SfxDevice; // current sfx card # (index to dmxCodes)
446 extern int snd_SBport, snd_SBirq, snd_SBdma; // sound blaster variables
447 extern int snd_Mport; // midi variables
450 default_t defaults[] =
452 { "mouse_sensitivity", &mouseSensitivity, 5 },
453 { "sfx_volume", &snd_MaxVolume, 10},
454 { "music_volume", &snd_MusicVolume, 10},
456 #define SC_INSERT 0x52
457 #define SC_DELETE 0x53
458 #define SC_PAGEUP 0x49
459 #define SC_PAGEDOWN 0x51
463 { "key_right", &key_right, KEY_RIGHTARROW },
464 { "key_left", &key_left, KEY_LEFTARROW },
465 { "key_up", &key_up, KEY_UPARROW },
466 { "key_down", &key_down, KEY_DOWNARROW },
467 { "key_strafeleft", &key_strafeleft, ',' },
468 { "key_straferight", &key_straferight, '.' },
469 { "key_jump", &key_jump, '/'},
470 { "key_flyup", &key_flyup, SC_PAGEUP },
471 { "key_flydown", &key_flydown, SC_INSERT },
472 { "key_flycenter", &key_flycenter, SC_HOME },
473 { "key_lookup", &key_lookup, SC_PAGEDOWN },
474 { "key_lookdown", &key_lookdown, SC_DELETE },
475 { "key_lookcenter", &key_lookcenter, SC_END },
476 { "key_invleft", &key_invleft, '[' },
477 { "key_invright", &key_invright, ']' },
478 { "key_useartifact", &key_useartifact, 13 },
479 { "key_fire", &key_fire, KEY_RCTRL, 1 },
480 { "key_use", &key_use, ' ', 1 },
481 { "key_strafe", &key_strafe, KEY_RALT, 1 },
482 { "key_speed", &key_speed, KEY_RSHIFT, 1 },
483 { "use_mouse", &usemouse, 1 },
484 { "mouseb_fire", &mousebfire, 0 },
485 { "mouseb_strafe", &mousebstrafe, 1 },
486 { "mouseb_forward", &mousebforward, 2 },
487 { "mouseb_jump", &mousebjump, -1 },
488 { "use_joystick", &usejoystick, 0 },
489 { "joyb_fire", &joybfire, 0 },
490 { "joyb_strafe", &joybstrafe, 1 },
491 { "joyb_use", &joybuse, 3 },
492 { "joyb_speed", &joybspeed, 2 },
493 { "joyb_jump", &joybjump, -1 },
494 { "screenblocks", &screenblocks, 10 },
495 { "snd_channels", &snd_Channels, 3 },
496 { "snd_musicdevice", &snd_DesiredMusicDevice, 0 },
497 { "snd_sfxdevice", &snd_DesiredSfxDevice, 0 },
498 { "snd_sbport", &snd_SBport, 544 },
499 { "snd_sbirq", &snd_SBirq, -1 },
500 { "snd_sbdma", &snd_SBdma, -1 },
501 { "snd_mport", &snd_Mport, -1 },
503 { "usegamma", &usegamma, 0 },
505 { "messageson", (int *) &messageson, 1 },
507 { "chatmacro0", (int *) &chat_macros[0], (int) HUSTR_CHATMACRO0 },
508 { "chatmacro1", (int *) &chat_macros[1], (int) HUSTR_CHATMACRO1 },
509 { "chatmacro2", (int *) &chat_macros[2], (int) HUSTR_CHATMACRO2 },
510 { "chatmacro3", (int *) &chat_macros[3], (int) HUSTR_CHATMACRO3 },
511 { "chatmacro4", (int *) &chat_macros[4], (int) HUSTR_CHATMACRO4 },
512 { "chatmacro5", (int *) &chat_macros[5], (int) HUSTR_CHATMACRO5 },
513 { "chatmacro6", (int *) &chat_macros[6], (int) HUSTR_CHATMACRO6 },
514 { "chatmacro7", (int *) &chat_macros[7], (int) HUSTR_CHATMACRO7 },
515 { "chatmacro8", (int *) &chat_macros[8], (int) HUSTR_CHATMACRO8 },
516 { "chatmacro9", (int *) &chat_macros[9], (int) HUSTR_CHATMACRO9 },
517 { "mouselook", &mouselook, 0 },
518 { "cdaudio", (int *) &cdaudio, false }, /* jim cast added (warning) */
519 { "alwaysrun", (int *) &alwaysrun, false }
523 char defaultfile[128];
533 void M_SaveDefaults (void)
538 f = fopen (defaultfile, "w");
540 return; // can't write the file, but don't complain
542 for (i=0 ; i<numdefaults ; i++)
544 if (defaults[i].defaultvalue > -0xfff
545 && defaults[i].defaultvalue < 0xfff)
547 v = *defaults[i].location;
548 fprintf (f,"%s\t\t%i\n",defaults[i].name,v);
550 fprintf (f,"%s\t\t\"%s\"\n",defaults[i].name,
551 * (char **) (defaults[i].location));
558 //==========================================================================
562 //==========================================================================
564 extern byte scantokey[128];
566 void M_LoadDefaults(char *fileName)
573 char *newstring = NULL; /* jim initialiser added */
577 // Set everything to base values
578 numdefaults = sizeof(defaults)/sizeof(defaults[0]);
579 ST_Message("M_LoadDefaults: %d default settings loaded\n", numdefaults);
580 for(i = 0; i < numdefaults; i++)
582 *defaults[i].location = defaults[i].defaultvalue;
585 // Check for a custom config file
586 i = M_CheckParm("-config");
587 if(i && i < myargc-1)
589 strncpy(defaultfile, myargv[i+1], 128);
590 defaultfile[127] = '\0';
591 ST_Message("config file: %s\n", defaultfile);
595 strncpy(defaultfile, strcat(basePath,fileName), 128);
596 defaultfile[127] = '\0';
599 // Scan the config file
600 f = fopen(defaultfile, "r");
606 if(fscanf(f, "%79s %[^\n]\n", def, strparm) == 2)
608 if(strparm[0] == '"')
610 // Get a string default
612 len = strlen(strparm);
613 newstring = (char *)malloc(len);
614 if (newstring == NULL) I_Error("can't malloc newstring");
616 strcpy(newstring, strparm+1);
618 else if(strparm[0] == '0' && strparm[1] == 'x')
620 sscanf(strparm+2, "%x", &parm);
624 sscanf(strparm, "%i", &parm);
626 for(i = 0; i < numdefaults; i++)
628 if(!strcmp(def, defaults[i].name))
632 *defaults[i].location = parm;
636 *defaults[i].location = (int)newstring;
649 ==============================================================================
653 ==============================================================================
663 unsigned short xmin,ymin,xmax,ymax;
664 unsigned short hres,vres;
665 unsigned char palette[48];
668 unsigned short bytes_per_line;
669 unsigned short palette_type;
671 unsigned char data; // unbounded
682 void WritePCXfile (char *filename, byte *data, int width, int height, byte *palette)
688 pcx = Z_Malloc (width*height*2+1000, PU_STATIC, NULL);
690 pcx->manufacturer = 0x0a; // PCX id
691 pcx->version = 5; // 256 color
692 pcx->encoding = 1; // uncompressed
693 pcx->bits_per_pixel = 8; // 256 color
696 pcx->xmax = SHORT(width-1);
697 pcx->ymax = SHORT(height-1);
698 pcx->hres = SHORT(width);
699 pcx->vres = SHORT(height);
700 memset (pcx->palette,0,sizeof(pcx->palette));
701 pcx->color_planes = 1; // chunky image
702 pcx->bytes_per_line = SHORT(width);
703 pcx->palette_type = SHORT(2); // not a grey scale
704 memset (pcx->filler,0,sizeof(pcx->filler));
711 for (i=0 ; i<width*height ; i++)
712 if ( (*data & 0xc0) != 0xc0)
723 *pack++ = 0x0c; // palette ID byte
724 for (i=0 ; i<768 ; i++)
725 *pack++ = *palette++;
730 length = pack - (byte *)pcx;
731 M_WriteFile (filename, pcx, length);
737 //==============================================================================
747 void M_ScreenShot (void)
752 void M_ScreenShot (void)
760 // munge planar buffer to linear
764 // find a file name to save it to
766 strcpy(lbmname,"HEXEN00.pcx");
768 for (i=0 ; i<=99 ; i++)
770 lbmname[5] = i/10 + '0';
771 lbmname[6] = i%10 + '0';
772 if (access(lbmname,0) == -1)
773 break; // file doesn't exist
776 I_Error ("M_ScreenShot: Couldn't create a PCX");
781 pal = (byte *)W_CacheLumpName("PLAYPAL", PU_CACHE);
783 WritePCXfile (lbmname, linear, SCREENWIDTH, SCREENHEIGHT
786 P_SetMessage(&players[consoleplayer], "SCREEN SHOT", false);