home *** CD-ROM | disk | FTP | other *** search
/ CD Actual Thematic 7: Programming / CDAT7.iso / Share / Codigo / hh / rsource.exe / Hexen Source / M_MISC.C < prev    next >
Encoding:
C/C++ Source or Header  |  1996-03-22  |  20.1 KB  |  879 lines

  1.  
  2. //**************************************************************************
  3. //**
  4. //** m_misc.c : Heretic 2 : Raven Software, Corp.
  5. //**
  6. //** $RCSfile: m_misc.c,v $
  7. //** $Revision: 1.18 $
  8. //** $Date: 96/01/07 16:51:18 $
  9. //** $Author: bgokey $
  10. //**
  11. //**************************************************************************
  12.  
  13. // HEADER FILES ------------------------------------------------------------
  14.  
  15. #ifdef __NeXT__
  16.     #include <libc.h>
  17. #else
  18.     #include <sys/stat.h>
  19.     #include <sys/types.h>
  20.     #include <direct.h>
  21.     #include <fcntl.h>
  22.     #include <stdlib.h>
  23.     #include <io.h>
  24.     #include <conio.h>
  25. #endif
  26. #include <ctype.h>
  27. #include "h2def.h"
  28. #include "p_local.h"
  29. #include "soundst.h"
  30.  
  31. // MACROS ------------------------------------------------------------------
  32.  
  33. #define MALLOC_CLIB 1
  34. #define MALLOC_ZONE 2
  35.  
  36. // TYPES -------------------------------------------------------------------
  37.  
  38. // EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
  39.  
  40. // PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
  41.  
  42. // PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
  43.  
  44. static int ReadFile(char const *name, byte **buffer, int mallocType);
  45.  
  46. // EXTERNAL DATA DECLARATIONS ----------------------------------------------
  47. extern char *SavePath;
  48.  
  49. // PUBLIC DATA DEFINITIONS -------------------------------------------------
  50.  
  51. int myargc;
  52. char **myargv;
  53.  
  54. // PRIVATE DATA DEFINITIONS ------------------------------------------------
  55.  
  56. // CODE --------------------------------------------------------------------
  57.  
  58. //==========================================================================
  59. //
  60. // M_CheckParm
  61. //
  62. // Checks for the given parameter in the program's command line arguments.
  63. // Returns the argument number (1 to argc-1) or 0 if not present.
  64. //
  65. //==========================================================================
  66.  
  67. int M_CheckParm(char *check)
  68. {
  69.     int i;
  70.  
  71.     for(i = 1; i < myargc; i++)
  72.     {
  73.         if(!strcasecmp(check, myargv[i]))
  74.         {
  75.             return i;
  76.         }
  77.     }
  78.     return 0;
  79. }
  80.  
  81. //==========================================================================
  82. //
  83. // M_ParmExists
  84. //
  85. // Returns true if the given parameter exists in the program's command
  86. // line arguments, false if not.
  87. //
  88. //==========================================================================
  89.  
  90. boolean M_ParmExists(char *check)
  91. {
  92.     return M_CheckParm(check) != 0 ? true : false;
  93. }
  94.  
  95. //==========================================================================
  96. //
  97. // M_ExtractFileBase
  98. //
  99. //==========================================================================
  100.  
  101. void M_ExtractFileBase(char *path, char *dest)
  102. {
  103.     char *src;
  104.     int length;
  105.  
  106.     src = path+strlen(path)-1;
  107.  
  108.     // Back up until a \ or the start
  109.     while(src != path && *(src-1) != '\\' && *(src-1) != '/')
  110.     {
  111.         src--;
  112.     }
  113.  
  114.     // Copy up to eight characters
  115.     memset(dest, 0, 8);
  116.     length = 0;
  117.     while(*src && *src != '.')
  118.     {
  119.         if(++length == 9)
  120.         {
  121.             I_Error("Filename base of %s > 8 chars", path);
  122.         }
  123.         *dest++ = toupper((int)*src++);
  124.     }
  125. }
  126.  
  127. /*
  128. ===============
  129. =
  130. = M_Random
  131. =
  132. = Returns a 0-255 number
  133. =
  134. ===============
  135. */
  136.  
  137.  
  138. // This is the new flat distribution table
  139. unsigned char rndtable[256] = {
  140.     201,  1,243, 19, 18, 42,183,203,101,123,154,137, 34,118, 10,216,
  141.     135,246,  0,107,133,229, 35,113,177,211,110, 17,139, 84,251,235,
  142.     182,166,161,230,143, 91, 24, 81, 22, 94,  7, 51,232,104,122,248,
  143.     175,138,127,171,222,213, 44, 16,  9, 33, 88,102,170,150,136,114,
  144.      62,  3,142,237,  6,252,249, 56, 74, 30, 13, 21,180,199, 32,132,
  145.     187,234, 78,210, 46,131,197,  8,206,244, 73,  4,236,178,195, 70,
  146.     121, 97,167,217,103, 40,247,186,105, 39, 95,163, 99,149,253, 29,
  147.     119, 83,254, 26,202, 65,130,155, 60, 64,184,106,221, 93,164,196,
  148.     112,108,179,141, 54,109, 11,126, 75,165,191,227, 87,225,156, 15,
  149.      98,162,116, 79,169,140,190,205,168,194, 41,250, 27, 20, 14,241,
  150.      50,214, 72,192,220,233, 67,148, 96,185,176,181,215,207,172, 85,
  151.      89, 90,209,128,124,  2, 55,173, 66,152, 47,129, 59, 43,159,240,
  152.     239, 12,189,212,144, 28,200, 77,219,198,134,228, 45, 92,125,151,
  153.       5, 53,255, 52, 68,245,160,158, 61, 86, 58, 82,117, 37,242,145,
  154.      69,188,115, 76, 63,100, 49,111,153, 80, 38, 57,174,224, 71,231,
  155.      23, 25, 48,218,120,147,208, 36,226,223,193,238,157,204,146, 31
  156. };
  157.  
  158.  
  159. int rndindex = 0;
  160. int prndindex = 0;
  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.  
  322.                 printf("\nNo such response file!");
  323.                 exit(1);
  324.             }
  325.             ST_Message("Found response file %s!\n",&myargv[i][1]);
  326.             fseek (handle,0,SEEK_END);
  327.             size = ftell(handle);
  328.             fseek (handle,0,SEEK_SET);
  329.             file = malloc (size);
  330.             fread (file,size,1,handle);
  331.             fclose (handle);
  332.  
  333.             // KEEP ALL CMDLINE ARGS FOLLOWING @RESPONSEFILE ARG
  334.             for (index = 0,k = i+1; k < myargc; k++)
  335.                 moreargs[index++] = myargv[k];
  336.             
  337.             firstargv = myargv[0];
  338.             myargv = malloc(sizeof(char *)*MAXARGVS);
  339.             memset(myargv,0,sizeof(char *)*MAXARGVS);
  340.             myargv[0] = firstargv;
  341.             
  342.             infile = file;
  343.             indexinfile = k = 0;
  344.             indexinfile++;  // SKIP PAST ARGV[0] (KEEP IT)
  345.             do
  346.             {
  347.                 myargv[indexinfile++] = infile+k;
  348.                 while(k < size &&  
  349.  
  350.                     ((*(infile+k)>= ' '+1) && (*(infile+k)<='z')))
  351.                     k++;
  352.                 *(infile+k) = 0;
  353.                 while(k < size &&
  354.                     ((*(infile+k)<= ' ') || (*(infile+k)>'z')))
  355.                     k++;
  356.             } while(k < size);
  357.             
  358.             for (k = 0;k < index;k++)
  359.                 myargv[indexinfile++] = moreargs[k];
  360.             myargc = indexinfile;
  361.             // DISPLAY ARGS
  362.             if(M_CheckParm("-debug"))
  363.             {
  364.                 ST_Message("%d command-line args:\n", myargc);
  365.                 for(k = 1; k < myargc; k++)
  366.                 {
  367.                     ST_Message("%s\n", myargv[k]);
  368.                 }
  369.             }
  370.             break;
  371.         }
  372.     }
  373. }
  374.  
  375. //---------------------------------------------------------------------------
  376. //
  377. // PROC M_ForceUppercase
  378. //
  379. // Change string to uppercase.
  380. //
  381. //---------------------------------------------------------------------------
  382.  
  383. void M_ForceUppercase(char *text)
  384. {
  385.     char c;
  386.  
  387.     while((c = *text) != 0)
  388.     {
  389.         if(c >= 'a' && c <= 'z')
  390.         {
  391.             *text++ = c-('a'-'A');
  392.         }
  393.         else
  394.         {
  395.             text++;
  396.         }
  397.     }
  398. }
  399.  
  400. /*
  401. ==============================================================================
  402.  
  403.                             DEFAULTS
  404.  
  405. ==============================================================================
  406. */
  407.  
  408. int     usemouse;
  409. int     usejoystick;
  410.  
  411. extern int key_right, key_left, key_up, key_down;
  412. extern int key_strafeleft, key_straferight, key_jump;
  413. extern int key_fire, key_use, key_strafe, key_speed;
  414. extern int key_flyup, key_flydown, key_flycenter;
  415. extern int key_lookup, key_lookdown, key_lookcenter;
  416. extern int key_invleft, key_invright, key_useartifact;
  417.  
  418. extern int mousebfire;
  419. extern int mousebstrafe;
  420. extern int mousebforward;
  421. extern int mousebjump;
  422.  
  423. extern int joybfire;
  424. extern int joybstrafe;
  425. extern int joybuse;
  426. extern int joybspeed;
  427. extern int joybjump;
  428.  
  429. extern boolean messageson;
  430.  
  431. extern  int     viewwidth, viewheight;
  432.  
  433. int mouseSensitivity;
  434.  
  435. extern  int screenblocks;
  436.  
  437. extern char *chat_macros[10];
  438.  
  439. typedef struct
  440. {
  441.     char    *name;
  442.     int     *location;
  443.     int     defaultvalue;
  444.     int     scantranslate;      // PC scan code hack
  445.     int     untranslated;       // lousy hack
  446. } default_t;
  447.  
  448. #ifndef __NeXT__
  449. extern int snd_Channels;
  450. extern int snd_DesiredMusicDevice, snd_DesiredSfxDevice;
  451. extern int snd_MusicDevice, // current music card # (index to dmxCodes)
  452.     snd_SfxDevice; // current sfx card # (index to dmxCodes)
  453.  
  454. extern int     snd_SBport, snd_SBirq, snd_SBdma;       // sound blaster variables
  455. extern int     snd_Mport;                              // midi variables
  456. #endif
  457.  
  458. default_t defaults[] =
  459. {
  460.     { "mouse_sensitivity", &mouseSensitivity, 5 },
  461.  
  462. #ifndef __NeXT__
  463.     { "sfx_volume", &snd_MaxVolume, 10},
  464.     { "music_volume", &snd_MusicVolume, 10},
  465. #endif
  466.  
  467. #ifdef __WATCOMC__
  468. #define SC_UPARROW              0x48
  469. #define SC_DOWNARROW            0x50
  470. #define SC_LEFTARROW            0x4b
  471. #define SC_RIGHTARROW           0x4d
  472. #define SC_RCTRL                0x1d
  473. #define SC_RALT                 0x38
  474. #define SC_RSHIFT               0x36
  475. #define SC_SPACE                0x39
  476. #define SC_COMMA                0x33
  477. #define SC_PERIOD               0x34
  478. #define SC_PAGEUP                0x49
  479. #define SC_INSERT                0x52
  480. #define SC_HOME                    0x47
  481. #define SC_PAGEDOWN                0x51
  482. #define SC_DELETE                0x53
  483. #define SC_END                    0x4f
  484. #define SC_ENTER                0x1c
  485. #define SC_SLASH                0X35
  486.  
  487.     { "key_right", &key_right, SC_RIGHTARROW, 1 },
  488.     { "key_left", &key_left, SC_LEFTARROW, 1 },
  489.     { "key_up", &key_up, SC_UPARROW, 1 },
  490.     { "key_down", &key_down, SC_DOWNARROW, 1 },
  491.     { "key_strafeleft", &key_strafeleft, SC_COMMA, 1 },
  492.     { "key_straferight", &key_straferight, SC_PERIOD, 1 },
  493.     { "key_jump", &key_jump, SC_SLASH, 1},
  494.     { "key_flyup", &key_flyup, SC_PAGEUP, 1 },
  495.     { "key_flydown", &key_flydown, SC_INSERT, 1 },
  496.     { "key_flycenter", &key_flycenter, SC_HOME, 1 },
  497.     { "key_lookup", &key_lookup, SC_PAGEDOWN, 1 },
  498.     { "key_lookdown", &key_lookdown, SC_DELETE, 1 },
  499.     { "key_lookcenter", &key_lookcenter, SC_END, 1 },
  500.     { "key_invleft", &key_invleft, 0x1a, 1 },
  501.     { "key_invright", &key_invright, 0x1b, 1 },
  502.     { "key_useartifact", &key_useartifact, SC_ENTER, 1 },
  503.  
  504.     { "key_fire", &key_fire, SC_RCTRL, 1 },
  505.     { "key_use", &key_use, SC_SPACE, 1 },
  506.     { "key_strafe", &key_strafe, SC_RALT, 1 },
  507.     { "key_speed", &key_speed, SC_RSHIFT, 1 },
  508. #endif
  509.  
  510. #ifdef __NeXT__
  511.     { "key_right", &key_right, KEY_RIGHTARROW },
  512.     { "key_left", &key_left, KEY_LEFTARROW },
  513.     { "key_up", &key_up, KEY_UPARROW },
  514.     { "key_down", &key_down, KEY_DOWNARROW },
  515.     { "key_strafeleft", &key_strafeleft, ',' },
  516.     { "key_straferight", &key_straferight, '.' },
  517.     { "key_jump", &key_jump, '/'},
  518.     { "key_flyup", &key_flyup, 'u' },
  519.     { "key_flydown", &key_flydown, 'j' },
  520.     { "key_flycenter", &key_flycenter, 'k' },
  521.     { "key_lookup", &key_lookup, 'm' },
  522.     { "key_lookdown", &key_lookdown, 'b' },
  523.     { "key_lookcenter", &key_lookcenter, 'n' },
  524.     { "key_invleft", &key_invleft, '[' },
  525.     { "key_invright", &key_invright, ']' },
  526.     { "key_useartifact", &key_useartifact, 13 },
  527.  
  528.     { "key_fire", &key_fire, ' ', 1 },
  529.     { "key_use", &key_use, 'x', 1 },
  530.     { "key_strafe", &key_strafe, 'c', 1 },
  531.     { "key_speed", &key_speed, 'z', 1 },
  532. #endif
  533.  
  534.     { "use_mouse", &usemouse, 1 },
  535.     { "mouseb_fire", &mousebfire, 0 },
  536.     { "mouseb_strafe", &mousebstrafe, 1 },
  537.     { "mouseb_forward", &mousebforward, 2 },
  538.     { "mouseb_jump", &mousebjump, -1 },
  539.  
  540.     { "use_joystick", &usejoystick, 0 },
  541.     { "joyb_fire", &joybfire, 0 },
  542.     { "joyb_strafe", &joybstrafe, 1 },
  543.     { "joyb_use", &joybuse, 3 },
  544.     { "joyb_speed", &joybspeed, 2 },
  545.     { "joyb_jump", &joybjump, -1 },
  546.  
  547.     { "screenblocks", &screenblocks, 10 },
  548.  
  549. #ifndef __NeXT__
  550.     { "snd_channels", &snd_Channels, 3 },
  551.     { "snd_musicdevice", &snd_DesiredMusicDevice, 0 },
  552.     { "snd_sfxdevice", &snd_DesiredSfxDevice, 0 },
  553.     { "snd_sbport", &snd_SBport, 544 },
  554.     { "snd_sbirq", &snd_SBirq, -1 },
  555.     { "snd_sbdma", &snd_SBdma, -1 },
  556.     { "snd_mport", &snd_Mport, -1 },
  557. #endif
  558.  
  559.     { "usegamma", &usegamma, 0 },
  560.  
  561. #ifdef __NeXT__
  562.     #define DEFAULT_SAVEPATH        "hexndata/"
  563. #endif
  564. #ifdef __WATCOMC__
  565.     #define DEFAULT_SAVEPATH        "hexndata\\"
  566. #endif
  567.     { "savedir", (int *) &SavePath, (int) DEFAULT_SAVEPATH },
  568.  
  569.     { "messageson", (int *) &messageson, 1 },
  570.  
  571.     { "chatmacro0", (int *) &chat_macros[0], (int) HUSTR_CHATMACRO0 },
  572.     { "chatmacro1", (int *) &chat_macros[1], (int) HUSTR_CHATMACRO1 },
  573.     { "chatmacro2", (int *) &chat_macros[2], (int) HUSTR_CHATMACRO2 },
  574.     { "chatmacro3", (int *) &chat_macros[3], (int) HUSTR_CHATMACRO3 },
  575.     { "chatmacro4", (int *) &chat_macros[4], (int) HUSTR_CHATMACRO4 },
  576.     { "chatmacro5", (int *) &chat_macros[5], (int) HUSTR_CHATMACRO5 },
  577.     { "chatmacro6", (int *) &chat_macros[6], (int) HUSTR_CHATMACRO6 },
  578.     { "chatmacro7", (int *) &chat_macros[7], (int) HUSTR_CHATMACRO7 },
  579.     { "chatmacro8", (int *) &chat_macros[8], (int) HUSTR_CHATMACRO8 },
  580.     { "chatmacro9", (int *) &chat_macros[9], (int) HUSTR_CHATMACRO9 }
  581. };
  582.  
  583. int numdefaults;
  584. char defaultfile[128];
  585.  
  586. /*
  587. ==============
  588. =
  589. = M_SaveDefaults
  590. =
  591. ==============
  592. */
  593.  
  594. void M_SaveDefaults (void)
  595. {
  596.     int     i,v;
  597.     FILE    *f;
  598.  
  599.     f = fopen (defaultfile, "w");
  600.     if (!f)
  601.         return;         // can't write the file, but don't complain
  602.  
  603.     for (i=0 ; i<numdefaults ; i++)
  604.     {
  605. #ifdef __WATCOMC__
  606.         if (defaults[i].scantranslate)
  607.             defaults[i].location = &defaults[i].untranslated;
  608. #endif
  609.         if (defaults[i].defaultvalue > -0xfff
  610.           && defaults[i].defaultvalue < 0xfff)
  611.         {
  612.             v = *defaults[i].location;
  613.             fprintf (f,"%s\t\t%i\n",defaults[i].name,v);
  614.         } else {
  615.             fprintf (f,"%s\t\t\"%s\"\n",defaults[i].name,
  616.               * (char **) (defaults[i].location));
  617.         }
  618.     }
  619.  
  620.     fclose (f);
  621. }
  622.  
  623. //==========================================================================
  624. //
  625. // M_LoadDefaults
  626. //
  627. //==========================================================================
  628.  
  629. extern byte scantokey[128];
  630.  
  631. void M_LoadDefaults(char *fileName)
  632. {
  633.     int i;
  634.     int len;
  635.     FILE *f;
  636.     char def[80];
  637.     char strparm[100];
  638.     char *newstring;
  639.     int parm;
  640.     boolean isstring;
  641.  
  642.     // Set everything to base values
  643.     numdefaults = sizeof(defaults)/sizeof(defaults[0]);
  644.     for(i = 0; i < numdefaults; i++)
  645.     {
  646.         *defaults[i].location = defaults[i].defaultvalue;
  647.     }
  648.  
  649.     // Check for a custom config file
  650.     i = M_CheckParm("-config");
  651.     if(i && i < myargc-1)
  652.     {
  653.         strcpy(defaultfile, myargv[i+1]);
  654.         ST_Message("config file: %s\n", defaultfile);
  655.     }
  656.     else if(cdrom)
  657.     {
  658.         sprintf(defaultfile, "c:\\hexndata\\%s", fileName);
  659.     }
  660.     else
  661.     {
  662.         strcpy(defaultfile, fileName);
  663.     }
  664.  
  665.     // Scan the config file
  666.     f = fopen(defaultfile, "r");
  667.     if(f)
  668.     {
  669.         while(!feof(f))
  670.         {
  671.             isstring = false;
  672.             if(fscanf(f, "%79s %[^\n]\n", def, strparm) == 2)
  673.             {
  674.                 if(strparm[0] == '"')
  675.                 {
  676.                      // Get a string default
  677.                      isstring = true;
  678.                      len = strlen(strparm);
  679.                      newstring = (char *)malloc(len);
  680.                      if (newstring == NULL) I_Error("can't malloc newstring");
  681.                      strparm[len-1] = 0;
  682.                      strcpy(newstring, strparm+1);
  683.                 }
  684.                 else if(strparm[0] == '0' && strparm[1] == 'x')
  685.                 {
  686.                     sscanf(strparm+2, "%x", &parm);
  687.                 }
  688.                 else
  689.                 {
  690.                     sscanf(strparm, "%i", &parm);
  691.                 }
  692.                 for(i = 0; i < numdefaults; i++)
  693.                 {
  694.                     if(!strcmp(def, defaults[i].name))
  695.                     {
  696.                         if(!isstring)
  697.                         {
  698.                             *defaults[i].location = parm;
  699.                         }
  700.                         else
  701.                         {
  702.                             *defaults[i].location = (int)newstring;
  703.                         }
  704.                         break;
  705.                     }
  706.                 }
  707.             }
  708.         }
  709.  
  710.         fclose (f);
  711.     }
  712.  
  713. #ifdef __WATCOMC__
  714.     // Translate the key scancodes
  715.     for(i = 0; i < numdefaults; i++)
  716.     {
  717.         if(defaults[i].scantranslate)
  718.         {
  719.             parm = *defaults[i].location;
  720.             defaults[i].untranslated = parm;
  721.             *defaults[i].location = scantokey[parm];
  722.         }
  723.     }
  724. #endif
  725. }
  726.  
  727. /*
  728. ==============================================================================
  729.  
  730.                         SCREEN SHOTS
  731.  
  732. ==============================================================================
  733. */
  734.  
  735.  
  736. typedef struct
  737. {
  738.     char    manufacturer;
  739.     char    version;
  740.     char    encoding;
  741.     char    bits_per_pixel;
  742.     unsigned short  xmin,ymin,xmax,ymax;
  743.     unsigned short  hres,vres;
  744.     unsigned char   palette[48];
  745.     char    reserved;
  746.     char    color_planes;
  747.     unsigned short  bytes_per_line;
  748.     unsigned short  palette_type;
  749.     char    filler[58];
  750.     unsigned char   data;           // unbounded
  751. } pcx_t;
  752.  
  753. /*
  754. ==============
  755. =
  756. = WritePCXfile
  757. =
  758. ==============
  759. */
  760.  
  761. void WritePCXfile (char *filename, byte *data, int width, int height, byte *palette)
  762. {
  763.     int     i, length;
  764.     pcx_t   *pcx;
  765.     byte        *pack;
  766.     
  767.     pcx = Z_Malloc (width*height*2+1000, PU_STATIC, NULL);
  768.  
  769.     pcx->manufacturer = 0x0a;   // PCX id
  770.     pcx->version = 5;           // 256 color
  771.     pcx->encoding = 1;      // uncompressed
  772.     pcx->bits_per_pixel = 8;        // 256 color
  773.     pcx->xmin = 0;
  774.     pcx->ymin = 0;
  775.     pcx->xmax = SHORT(width-1);
  776.     pcx->ymax = SHORT(height-1);
  777.     pcx->hres = SHORT(width);
  778.     pcx->vres = SHORT(height);
  779.     memset (pcx->palette,0,sizeof(pcx->palette));
  780.     pcx->color_planes = 1;      // chunky image
  781.     pcx->bytes_per_line = SHORT(width);
  782.     pcx->palette_type = SHORT(2);       // not a grey scale
  783.     memset (pcx->filler,0,sizeof(pcx->filler));
  784.  
  785. //
  786. // pack the image
  787. //
  788.     pack = &pcx->data;
  789.  
  790.     for (i=0 ; i<width*height ; i++)
  791.         if ( (*data & 0xc0) != 0xc0)
  792.             *pack++ = *data++;
  793.         else
  794.         {
  795.             *pack++ = 0xc1;
  796.             *pack++ = *data++;
  797.         }
  798.  
  799. //
  800. // write the palette
  801. //
  802.     *pack++ = 0x0c; // palette ID byte
  803.     for (i=0 ; i<768 ; i++)
  804.         *pack++ = *palette++;
  805.  
  806. //
  807. // write output file
  808. //
  809.     length = pack - (byte *)pcx;
  810.     M_WriteFile (filename, pcx, length);
  811.  
  812.     Z_Free (pcx);
  813. }
  814.  
  815.  
  816. //==============================================================================
  817.  
  818. /*
  819. ==================
  820. =
  821. = M_ScreenShot
  822. =
  823. ==================
  824. */
  825.  
  826. void M_ScreenShot (void)
  827. {
  828.     int     i;
  829.     byte    *linear;
  830.     char    lbmname[12];
  831.     byte *pal;
  832.  
  833. #ifdef _WATCOMC_
  834.     extern  byte *pcscreen;
  835. #endif
  836. //
  837. // munge planar buffer to linear
  838. //
  839. #ifdef _WATCOMC_
  840.     linear = pcscreen;
  841. #else
  842.     linear = screen;
  843. #endif
  844. //
  845. // find a file name to save it to
  846. //
  847.     strcpy(lbmname,"HEXEN00.pcx");
  848.  
  849.     for (i=0 ; i<=99 ; i++)
  850.     {
  851.         lbmname[5] = i/10 + '0';
  852.         lbmname[6] = i%10 + '0';
  853.         if (access(lbmname,0) == -1)
  854.             break;  // file doesn't exist
  855.     }
  856.     if (i==100)
  857.         I_Error ("M_ScreenShot: Couldn't create a PCX");
  858.  
  859. //
  860. // save the pcx file
  861. //
  862. #ifdef __WATCOMC__
  863.     pal = (byte *)Z_Malloc(768, PU_STATIC, NULL);
  864.     outp(0x3c7, 0);
  865.     for(i = 0; i < 768; i++)
  866.     {
  867.         *(pal+i) = inp(0x3c9)<<2;
  868.     }
  869. #else
  870.     pal = (byte *)W_CacheLumpName("PLAYPAL", PU_CACHE);
  871. #endif
  872.  
  873.     WritePCXfile (lbmname, linear, SCREENWIDTH, SCREENHEIGHT
  874.         , pal);
  875.  
  876.     P_SetMessage(&players[consoleplayer], "SCREEN SHOT", false);
  877. #ifdef __WATCOMC__
  878.     Z_Free(pal);
  879. #endif
  880. }
  881.