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 // this is broken: basePath should not be changed here. S.A.
600 // strncpy(defaultfile, strcat(basePath,fileName), 128);
601 strncpy(defaultfile, basePath, 128);
602 strcat (defaultfile, fileName);
603 defaultfile[127] = '\0';
606 // Scan the config file
607 f = fopen(defaultfile, "r");
613 if(fscanf(f, "%79s %[^\n]\n", def, strparm) == 2)
615 if(strparm[0] == '"')
617 // Get a string default
619 len = strlen(strparm);
620 newstring = (char *)malloc(len);
621 if (newstring == NULL) I_Error("can't malloc newstring");
623 strcpy(newstring, strparm+1);
625 else if(strparm[0] == '0' && strparm[1] == 'x')
627 sscanf(strparm+2, "%x", &parm);
631 sscanf(strparm, "%i", &parm);
633 for(i = 0; i < numdefaults; i++)
635 if(!strcmp(def, defaults[i].name))
639 *defaults[i].location = parm;
643 *defaults[i].location = (int)newstring;
656 ==============================================================================
660 ==============================================================================
670 unsigned short xmin,ymin,xmax,ymax;
671 unsigned short hres,vres;
672 unsigned char palette[48];
675 unsigned short bytes_per_line;
676 unsigned short palette_type;
678 unsigned char data; // unbounded
689 void WritePCXfile (char *filename, byte *data, int width, int height, byte *palette)
695 pcx = Z_Malloc (width*height*2+1000, PU_STATIC, NULL);
697 pcx->manufacturer = 0x0a; // PCX id
698 pcx->version = 5; // 256 color
699 pcx->encoding = 1; // uncompressed
700 pcx->bits_per_pixel = 8; // 256 color
703 pcx->xmax = SHORT(width-1);
704 pcx->ymax = SHORT(height-1);
705 pcx->hres = SHORT(width);
706 pcx->vres = SHORT(height);
707 memset (pcx->palette,0,sizeof(pcx->palette));
708 pcx->color_planes = 1; // chunky image
709 pcx->bytes_per_line = SHORT(width);
710 pcx->palette_type = SHORT(2); // not a grey scale
711 memset (pcx->filler,0,sizeof(pcx->filler));
718 for (i=0 ; i<width*height ; i++)
719 if ( (*data & 0xc0) != 0xc0)
730 *pack++ = 0x0c; // palette ID byte
731 for (i=0 ; i<768 ; i++)
732 *pack++ = *palette++;
737 length = pack - (byte *)pcx;
738 M_WriteFile (filename, pcx, length);
744 //==============================================================================
754 void M_ScreenShot (void)
759 void M_ScreenShot (void)
767 // munge planar buffer to linear
771 // find a file name to save it to
773 strcpy(lbmname,"HEXEN00.pcx");
775 for (i=0 ; i<=99 ; i++)
777 lbmname[5] = i/10 + '0';
778 lbmname[6] = i%10 + '0';
779 if (access(lbmname,0) == -1)
780 break; // file doesn't exist
783 I_Error ("M_ScreenShot: Couldn't create a PCX");
788 pal = (byte *)W_CacheLumpName("PLAYPAL", PU_CACHE);
790 WritePCXfile (lbmname, linear, SCREENWIDTH, SCREENHEIGHT
793 P_SetMessage(&players[consoleplayer], "SCREEN SHOT", false);