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 { "mouse_sensitivity", &mouseSensitivity, 5 },
457 { "sfx_volume", &snd_MaxVolume, 10},
458 { "music_volume", &snd_MusicVolume, 10},
460 #define SC_INSERT 0x52
461 #define SC_DELETE 0x53
462 #define SC_PAGEUP 0x49
463 #define SC_PAGEDOWN 0x51
467 { "key_right", &key_right, KEY_RIGHTARROW },
468 { "key_left", &key_left, KEY_LEFTARROW },
469 { "key_up", &key_up, KEY_UPARROW },
470 { "key_down", &key_down, KEY_DOWNARROW },
471 { "key_strafeleft", &key_strafeleft, ',' },
472 { "key_straferight", &key_straferight, '.' },
473 { "key_jump", &key_jump, '/'},
474 { "key_flyup", &key_flyup, SC_PAGEUP },
475 { "key_flydown", &key_flydown, SC_INSERT },
476 { "key_flycenter", &key_flycenter, SC_HOME },
477 { "key_lookup", &key_lookup, SC_PAGEDOWN },
478 { "key_lookdown", &key_lookdown, SC_DELETE },
479 { "key_lookcenter", &key_lookcenter, SC_END },
480 { "key_invleft", &key_invleft, '[' },
481 { "key_invright", &key_invright, ']' },
482 { "key_useartifact", &key_useartifact, 13 },
483 { "key_fire", &key_fire, KEY_RCTRL, 1 },
484 { "key_use", &key_use, ' ', 1 },
485 { "key_strafe", &key_strafe, KEY_RALT, 1 },
486 { "key_speed", &key_speed, KEY_RSHIFT, 1 },
487 { "use_mouse", &usemouse, 1 },
488 { "mouseb_fire", &mousebfire, 0 },
489 { "mouseb_strafe", &mousebstrafe, 1 },
490 { "mouseb_forward", &mousebforward, 2 },
491 { "mouseb_jump", &mousebjump, -1 },
492 { "use_joystick", &usejoystick, 0 },
493 { "joyb_fire", &joybfire, 0 },
494 { "joyb_strafe", &joybstrafe, 1 },
495 { "joyb_use", &joybuse, 3 },
496 { "joyb_speed", &joybspeed, 2 },
497 { "joyb_jump", &joybjump, -1 },
498 { "screenblocks", &screenblocks, 10 },
499 { "snd_channels", &snd_Channels, 3 },
500 { "snd_musicdevice", &snd_DesiredMusicDevice, 0 },
501 { "snd_sfxdevice", &snd_DesiredSfxDevice, 0 },
502 { "snd_sbport", &snd_SBport, 544 },
503 { "snd_sbirq", &snd_SBirq, -1 },
504 { "snd_sbdma", &snd_SBdma, -1 },
505 { "snd_mport", &snd_Mport, -1 },
507 { "usegamma", &usegamma, 0 },
509 { "messageson", (int *) &messageson, 1 },
511 { "chatmacro0", (int *) &chat_macros[0], (int) HUSTR_CHATMACRO0 },
512 { "chatmacro1", (int *) &chat_macros[1], (int) HUSTR_CHATMACRO1 },
513 { "chatmacro2", (int *) &chat_macros[2], (int) HUSTR_CHATMACRO2 },
514 { "chatmacro3", (int *) &chat_macros[3], (int) HUSTR_CHATMACRO3 },
515 { "chatmacro4", (int *) &chat_macros[4], (int) HUSTR_CHATMACRO4 },
516 { "chatmacro5", (int *) &chat_macros[5], (int) HUSTR_CHATMACRO5 },
517 { "chatmacro6", (int *) &chat_macros[6], (int) HUSTR_CHATMACRO6 },
518 { "chatmacro7", (int *) &chat_macros[7], (int) HUSTR_CHATMACRO7 },
519 { "chatmacro8", (int *) &chat_macros[8], (int) HUSTR_CHATMACRO8 },
520 { "chatmacro9", (int *) &chat_macros[9], (int) HUSTR_CHATMACRO9 },
521 { "mouselook", &mouselook, 0 },
522 { "cdaudio", (int *) &cdaudio, false }, /* jim cast added (warning) */
523 { "alwaysrun", (int *) &alwaysrun, false }
527 char defaultfile[128];
537 void M_SaveDefaults (void)
542 f = fopen (defaultfile, "w");
544 return; // can't write the file, but don't complain
546 for (i=0 ; i<numdefaults ; i++)
548 if (defaults[i].defaultvalue > -0xfff
549 && defaults[i].defaultvalue < 0xfff)
551 v = *defaults[i].location;
552 fprintf (f,"%s\t\t%i\n",defaults[i].name,v);
554 fprintf (f,"%s\t\t\"%s\"\n",defaults[i].name,
555 * (char **) (defaults[i].location));
562 //==========================================================================
566 //==========================================================================
568 extern byte scantokey[128];
570 void M_LoadDefaults(char *fileName)
577 char *newstring = NULL; /* jim initialiser added */
581 // Set everything to base values
582 numdefaults = sizeof(defaults)/sizeof(defaults[0]);
583 ST_Message("M_LoadDefaults: %d default settings loaded\n", numdefaults);
584 for(i = 0; i < numdefaults; i++)
586 *defaults[i].location = defaults[i].defaultvalue;
589 // Check for a custom config file
590 i = M_CheckParm("-config");
591 if(i && i < myargc-1)
593 strncpy(defaultfile, myargv[i+1], 128);
594 defaultfile[127] = '\0';
595 ST_Message("config file: %s\n", defaultfile);
599 strncpy(defaultfile, strcat(basePath,fileName), 128);
600 defaultfile[127] = '\0';
603 // Scan the config file
604 f = fopen(defaultfile, "r");
610 if(fscanf(f, "%79s %[^\n]\n", def, strparm) == 2)
612 if(strparm[0] == '"')
614 // Get a string default
616 len = strlen(strparm);
617 newstring = (char *)malloc(len);
618 if (newstring == NULL) I_Error("can't malloc newstring");
620 strcpy(newstring, strparm+1);
622 else if(strparm[0] == '0' && strparm[1] == 'x')
624 sscanf(strparm+2, "%x", &parm);
628 sscanf(strparm, "%i", &parm);
630 for(i = 0; i < numdefaults; i++)
632 if(!strcmp(def, defaults[i].name))
636 *defaults[i].location = parm;
640 *defaults[i].location = (int)newstring;
653 ==============================================================================
657 ==============================================================================
667 unsigned short xmin,ymin,xmax,ymax;
668 unsigned short hres,vres;
669 unsigned char palette[48];
672 unsigned short bytes_per_line;
673 unsigned short palette_type;
675 unsigned char data; // unbounded
686 void WritePCXfile (char *filename, byte *data, int width, int height, byte *palette)
692 pcx = Z_Malloc (width*height*2+1000, PU_STATIC, NULL);
694 pcx->manufacturer = 0x0a; // PCX id
695 pcx->version = 5; // 256 color
696 pcx->encoding = 1; // uncompressed
697 pcx->bits_per_pixel = 8; // 256 color
700 pcx->xmax = SHORT(width-1);
701 pcx->ymax = SHORT(height-1);
702 pcx->hres = SHORT(width);
703 pcx->vres = SHORT(height);
704 memset (pcx->palette,0,sizeof(pcx->palette));
705 pcx->color_planes = 1; // chunky image
706 pcx->bytes_per_line = SHORT(width);
707 pcx->palette_type = SHORT(2); // not a grey scale
708 memset (pcx->filler,0,sizeof(pcx->filler));
715 for (i=0 ; i<width*height ; i++)
716 if ( (*data & 0xc0) != 0xc0)
727 *pack++ = 0x0c; // palette ID byte
728 for (i=0 ; i<768 ; i++)
729 *pack++ = *palette++;
734 length = pack - (byte *)pcx;
735 M_WriteFile (filename, pcx, length);
741 //==============================================================================
751 void M_ScreenShot (void)
756 void M_ScreenShot (void)
764 // munge planar buffer to linear
768 // find a file name to save it to
770 strcpy(lbmname,"HEXEN00.pcx");
772 for (i=0 ; i<=99 ; i++)
774 lbmname[5] = i/10 + '0';
775 lbmname[6] = i%10 + '0';
776 if (access(lbmname,0) == -1)
777 break; // file doesn't exist
780 I_Error ("M_ScreenShot: Couldn't create a PCX");
785 pal = (byte *)W_CacheLumpName("PLAYPAL", PU_CACHE);
787 WritePCXfile (lbmname, linear, SCREENWIDTH, SCREENHEIGHT
790 P_SetMessage(&players[consoleplayer], "SCREEN SHOT", false);