M_MISC.C 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799
  1. // M_misc.c
  2. #ifdef __NeXT__
  3. #include <libc.h>
  4. #else
  5. #include <sys/stat.h>
  6. #include <sys/types.h>
  7. #include <direct.h>
  8. #include <fcntl.h>
  9. #include <stdlib.h>
  10. #endif
  11. #include <ctype.h>
  12. #include "DoomDef.h"
  13. #include "soundst.h"
  14. int myargc;
  15. char **myargv;
  16. //---------------------------------------------------------------------------
  17. //
  18. // FUNC M_ValidEpisodeMap
  19. //
  20. //---------------------------------------------------------------------------
  21. boolean M_ValidEpisodeMap(int episode, int map)
  22. {
  23. if(episode < 1 || map < 1 || map > 9)
  24. {
  25. return false;
  26. }
  27. if(shareware)
  28. { // Shareware version checks
  29. if(episode != 1)
  30. {
  31. return false;
  32. }
  33. }
  34. else if(ExtendedWAD)
  35. { // Extended version checks
  36. if(episode == 6)
  37. {
  38. if(map > 3)
  39. {
  40. return false;
  41. }
  42. }
  43. else if(episode > 5)
  44. {
  45. return false;
  46. }
  47. }
  48. else
  49. { // Registered version checks
  50. if(episode == 4)
  51. {
  52. if(map != 1)
  53. {
  54. return false;
  55. }
  56. }
  57. else if(episode > 3)
  58. {
  59. return false;
  60. }
  61. }
  62. return true;
  63. }
  64. /*
  65. =================
  66. =
  67. = M_CheckParm
  68. =
  69. = Checks for the given parameter in the program's command line arguments
  70. =
  71. = Returns the argument number (1 to argc-1) or 0 if not present
  72. =
  73. =================
  74. */
  75. int M_CheckParm (char *check)
  76. {
  77. int i;
  78. for (i = 1;i<myargc;i++)
  79. {
  80. if ( !strcasecmp(check, myargv[i]) )
  81. return i;
  82. }
  83. return 0;
  84. }
  85. /*
  86. ===============
  87. =
  88. = M_Random
  89. =
  90. = Returns a 0-255 number
  91. =
  92. ===============
  93. */
  94. unsigned char rndtable[256] = {
  95. 0, 8, 109, 220, 222, 241, 149, 107, 75, 248, 254, 140, 16, 66,
  96. 74, 21, 211, 47, 80, 242, 154, 27, 205, 128, 161, 89, 77, 36,
  97. 95, 110, 85, 48, 212, 140, 211, 249, 22, 79, 200, 50, 28, 188,
  98. 52, 140, 202, 120, 68, 145, 62, 70, 184, 190, 91, 197, 152, 224,
  99. 149, 104, 25, 178, 252, 182, 202, 182, 141, 197, 4, 81, 181, 242,
  100. 145, 42, 39, 227, 156, 198, 225, 193, 219, 93, 122, 175, 249, 0,
  101. 175, 143, 70, 239, 46, 246, 163, 53, 163, 109, 168, 135, 2, 235,
  102. 25, 92, 20, 145, 138, 77, 69, 166, 78, 176, 173, 212, 166, 113,
  103. 94, 161, 41, 50, 239, 49, 111, 164, 70, 60, 2, 37, 171, 75,
  104. 136, 156, 11, 56, 42, 146, 138, 229, 73, 146, 77, 61, 98, 196,
  105. 135, 106, 63, 197, 195, 86, 96, 203, 113, 101, 170, 247, 181, 113,
  106. 80, 250, 108, 7, 255, 237, 129, 226, 79, 107, 112, 166, 103, 241,
  107. 24, 223, 239, 120, 198, 58, 60, 82, 128, 3, 184, 66, 143, 224,
  108. 145, 224, 81, 206, 163, 45, 63, 90, 168, 114, 59, 33, 159, 95,
  109. 28, 139, 123, 98, 125, 196, 15, 70, 194, 253, 54, 14, 109, 226,
  110. 71, 17, 161, 93, 186, 87, 244, 138, 20, 52, 123, 251, 26, 36,
  111. 17, 46, 52, 231, 232, 76, 31, 221, 84, 37, 216, 165, 212, 106,
  112. 197, 242, 98, 43, 39, 175, 254, 145, 190, 84, 118, 222, 187, 136,
  113. 120, 163, 236, 249
  114. };
  115. int rndindex = 0;
  116. int prndindex = 0;
  117. int P_Random (void)
  118. {
  119. prndindex = (prndindex+1)&0xff;
  120. return rndtable[prndindex];
  121. }
  122. int M_Random (void)
  123. {
  124. rndindex = (rndindex+1)&0xff;
  125. return rndtable[rndindex];
  126. }
  127. void M_ClearRandom (void)
  128. {
  129. rndindex = prndindex = 0;
  130. }
  131. void M_ClearBox (fixed_t *box)
  132. {
  133. box[BOXTOP] = box[BOXRIGHT] = MININT;
  134. box[BOXBOTTOM] = box[BOXLEFT] = MAXINT;
  135. }
  136. void M_AddToBox (fixed_t *box, fixed_t x, fixed_t y)
  137. {
  138. if (x<box[BOXLEFT])
  139. box[BOXLEFT] = x;
  140. else if (x>box[BOXRIGHT])
  141. box[BOXRIGHT] = x;
  142. if (y<box[BOXBOTTOM])
  143. box[BOXBOTTOM] = y;
  144. else if (y>box[BOXTOP])
  145. box[BOXTOP] = y;
  146. }
  147. /*
  148. ==================
  149. =
  150. = M_WriteFile
  151. =
  152. ==================
  153. */
  154. #ifndef O_BINARY
  155. #define O_BINARY 0
  156. #endif
  157. boolean M_WriteFile (char const *name, void *source, int length)
  158. {
  159. int handle, count;
  160. handle = open (name, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666);
  161. if (handle == -1)
  162. return false;
  163. count = write (handle, source, length);
  164. close (handle);
  165. if (count < length)
  166. return false;
  167. return true;
  168. }
  169. /*
  170. ==================
  171. =
  172. = M_ReadFile
  173. =
  174. ==================
  175. */
  176. int M_ReadFile (char const *name, byte **buffer)
  177. {
  178. int handle, count, length;
  179. struct stat fileinfo;
  180. byte *buf;
  181. handle = open (name, O_RDONLY | O_BINARY, 0666);
  182. if (handle == -1)
  183. I_Error ("Couldn't read file %s", name);
  184. if (fstat (handle,&fileinfo) == -1)
  185. I_Error ("Couldn't read file %s", name);
  186. length = fileinfo.st_size;
  187. buf = Z_Malloc (length, PU_STATIC, NULL);
  188. count = read (handle, buf, length);
  189. close (handle);
  190. if (count < length)
  191. I_Error ("Couldn't read file %s", name);
  192. *buffer = buf;
  193. return length;
  194. }
  195. //---------------------------------------------------------------------------
  196. //
  197. // PROC M_FindResponseFile
  198. //
  199. //---------------------------------------------------------------------------
  200. #define MAXARGVS 100
  201. void M_FindResponseFile(void)
  202. {
  203. int i;
  204. for(i = 1; i < myargc; i++)
  205. {
  206. if(myargv[i][0] == '@')
  207. {
  208. FILE *handle;
  209. int size;
  210. int k;
  211. int index;
  212. int indexinfile;
  213. char *infile;
  214. char *file;
  215. char *moreargs[20];
  216. char *firstargv;
  217. // READ THE RESPONSE FILE INTO MEMORY
  218. handle = fopen(&myargv[i][1], "rb");
  219. if(!handle)
  220. {
  221. printf("\nNo such response file!");
  222. exit(1);
  223. }
  224. printf("Found response file %s!\n",&myargv[i][1]);
  225. fseek (handle,0,SEEK_END);
  226. size = ftell(handle);
  227. fseek (handle,0,SEEK_SET);
  228. file = malloc (size);
  229. fread (file,size,1,handle);
  230. fclose (handle);
  231. // KEEP ALL CMDLINE ARGS FOLLOWING @RESPONSEFILE ARG
  232. for (index = 0,k = i+1; k < myargc; k++)
  233. moreargs[index++] = myargv[k];
  234. firstargv = myargv[0];
  235. myargv = malloc(sizeof(char *)*MAXARGVS);
  236. memset(myargv,0,sizeof(char *)*MAXARGVS);
  237. myargv[0] = firstargv;
  238. infile = file;
  239. indexinfile = k = 0;
  240. indexinfile++; // SKIP PAST ARGV[0] (KEEP IT)
  241. do
  242. {
  243. myargv[indexinfile++] = infile+k;
  244. while(k < size &&
  245. ((*(infile+k)>= ' '+1) && (*(infile+k)<='z')))
  246. k++;
  247. *(infile+k) = 0;
  248. while(k < size &&
  249. ((*(infile+k)<= ' ') || (*(infile+k)>'z')))
  250. k++;
  251. } while(k < size);
  252. for (k = 0;k < index;k++)
  253. myargv[indexinfile++] = moreargs[k];
  254. myargc = indexinfile;
  255. // DISPLAY ARGS
  256. if(M_CheckParm("-debug"))
  257. {
  258. printf("%d command-line args:\n", myargc);
  259. for(k = 1; k < myargc; k++)
  260. {
  261. printf("%s\n", myargv[k]);
  262. }
  263. }
  264. break;
  265. }
  266. }
  267. }
  268. //---------------------------------------------------------------------------
  269. //
  270. // PROC M_ForceUppercase
  271. //
  272. // Change string to uppercase.
  273. //
  274. //---------------------------------------------------------------------------
  275. void M_ForceUppercase(char *text)
  276. {
  277. char c;
  278. while((c = *text) != 0)
  279. {
  280. if(c >= 'a' && c <= 'z')
  281. {
  282. *text++ = c-('a'-'A');
  283. }
  284. else
  285. {
  286. text++;
  287. }
  288. }
  289. }
  290. /*
  291. ==============================================================================
  292. DEFAULTS
  293. ==============================================================================
  294. */
  295. int usemouse;
  296. int usejoystick;
  297. extern int key_right, key_left, key_up, key_down;
  298. extern int key_strafeleft, key_straferight;
  299. extern int key_fire, key_use, key_strafe, key_speed;
  300. extern int key_flyup, key_flydown, key_flycenter;
  301. extern int key_lookup, key_lookdown, key_lookcenter;
  302. extern int key_invleft, key_invright, key_useartifact;
  303. extern int mousebfire;
  304. extern int mousebstrafe;
  305. extern int mousebforward;
  306. extern int joybfire;
  307. extern int joybstrafe;
  308. extern int joybuse;
  309. extern int joybspeed;
  310. extern int viewwidth, viewheight;
  311. int mouseSensitivity;
  312. extern int screenblocks;
  313. extern char *chat_macros[10];
  314. typedef struct
  315. {
  316. char *name;
  317. int *location;
  318. int defaultvalue;
  319. int scantranslate; // PC scan code hack
  320. int untranslated; // lousy hack
  321. } default_t;
  322. #ifndef __NeXT__
  323. extern int snd_Channels;
  324. extern int snd_DesiredMusicDevice, snd_DesiredSfxDevice;
  325. extern int snd_MusicDevice, // current music card # (index to dmxCodes)
  326. snd_SfxDevice; // current sfx card # (index to dmxCodes)
  327. extern int snd_SBport, snd_SBirq, snd_SBdma; // sound blaster variables
  328. extern int snd_Mport; // midi variables
  329. #endif
  330. default_t defaults[] =
  331. {
  332. { "mouse_sensitivity", &mouseSensitivity, 5 },
  333. #ifndef __NeXT__
  334. { "sfx_volume", &snd_MaxVolume, 10},
  335. { "music_volume", &snd_MusicVolume, 10},
  336. #endif
  337. #ifdef __WATCOMC__
  338. #define SC_UPARROW 0x48
  339. #define SC_DOWNARROW 0x50
  340. #define SC_LEFTARROW 0x4b
  341. #define SC_RIGHTARROW 0x4d
  342. #define SC_RCTRL 0x1d
  343. #define SC_RALT 0x38
  344. #define SC_RSHIFT 0x36
  345. #define SC_SPACE 0x39
  346. #define SC_COMMA 0x33
  347. #define SC_PERIOD 0x34
  348. #define SC_PAGEUP 0x49
  349. #define SC_INSERT 0x52
  350. #define SC_HOME 0x47
  351. #define SC_PAGEDOWN 0x51
  352. #define SC_DELETE 0x53
  353. #define SC_END 0x4f
  354. #define SC_ENTER 0x1c
  355. { "key_right", &key_right, SC_RIGHTARROW, 1 },
  356. { "key_left", &key_left, SC_LEFTARROW, 1 },
  357. { "key_up", &key_up, SC_UPARROW, 1 },
  358. { "key_down", &key_down, SC_DOWNARROW, 1 },
  359. { "key_strafeleft", &key_strafeleft, SC_COMMA, 1 },
  360. { "key_straferight", &key_straferight, SC_PERIOD, 1 },
  361. { "key_flyup", &key_flyup, SC_PAGEUP, 1 },
  362. { "key_flydown", &key_flydown, SC_INSERT, 1 },
  363. { "key_flycenter", &key_flycenter, SC_HOME, 1 },
  364. { "key_lookup", &key_lookup, SC_PAGEDOWN, 1 },
  365. { "key_lookdown", &key_lookdown, SC_DELETE, 1 },
  366. { "key_lookcenter", &key_lookcenter, SC_END, 1 },
  367. { "key_invleft", &key_invleft, 0x1a, 1 },
  368. { "key_invright", &key_invright, 0x1b, 1 },
  369. { "key_useartifact", &key_useartifact, SC_ENTER, 1 },
  370. { "key_fire", &key_fire, SC_RCTRL, 1 },
  371. { "key_use", &key_use, SC_SPACE, 1 },
  372. { "key_strafe", &key_strafe, SC_RALT, 1 },
  373. { "key_speed", &key_speed, SC_RSHIFT, 1 },
  374. #endif
  375. #ifdef __NeXT__
  376. { "key_right", &key_right, KEY_RIGHTARROW },
  377. { "key_left", &key_left, KEY_LEFTARROW },
  378. { "key_up", &key_up, KEY_UPARROW },
  379. { "key_down", &key_down, KEY_DOWNARROW },
  380. { "key_strafeleft", &key_strafeleft, ',' },
  381. { "key_straferight", &key_straferight, '.' },
  382. { "key_flyup", &key_flyup, 'u' },
  383. { "key_flydown", &key_flydown, 'j' },
  384. { "key_flycenter", &key_flycenter, 'k' },
  385. { "key_lookup", &key_lookup, 'm' },
  386. { "key_lookdown", &key_lookdown, 'b' },
  387. { "key_lookcenter", &key_lookcenter, 'n' },
  388. { "key_invleft", &key_invleft, '[' },
  389. { "key_invright", &key_invright, ']' },
  390. { "key_useartifact", &key_useartifact, 13 },
  391. { "key_fire", &key_fire, ' ', 1 },
  392. { "key_use", &key_use, 'x', 1 },
  393. { "key_strafe", &key_strafe, 'c', 1 },
  394. { "key_speed", &key_speed, 'z', 1 },
  395. #endif
  396. { "use_mouse", &usemouse, 1 },
  397. { "mouseb_fire", &mousebfire, 0 },
  398. { "mouseb_strafe", &mousebstrafe, 1 },
  399. { "mouseb_forward", &mousebforward, 2 },
  400. { "use_joystick", &usejoystick, 0 },
  401. { "joyb_fire", &joybfire, 0 },
  402. { "joyb_strafe", &joybstrafe, 1 },
  403. { "joyb_use", &joybuse, 3 },
  404. { "joyb_speed", &joybspeed, 2 },
  405. { "screenblocks", &screenblocks, 10 },
  406. #ifndef __NeXT__
  407. { "snd_channels", &snd_Channels, 3 },
  408. { "snd_musicdevice", &snd_DesiredMusicDevice, 0 },
  409. { "snd_sfxdevice", &snd_DesiredSfxDevice, 0 },
  410. { "snd_sbport", &snd_SBport, 544 },
  411. { "snd_sbirq", &snd_SBirq, -1 },
  412. { "snd_sbdma", &snd_SBdma, -1 },
  413. { "snd_mport", &snd_Mport, -1 },
  414. #endif
  415. { "usegamma", &usegamma, 0 },
  416. { "chatmacro0", (int *) &chat_macros[0], (int) HUSTR_CHATMACRO0 },
  417. { "chatmacro1", (int *) &chat_macros[1], (int) HUSTR_CHATMACRO1 },
  418. { "chatmacro2", (int *) &chat_macros[2], (int) HUSTR_CHATMACRO2 },
  419. { "chatmacro3", (int *) &chat_macros[3], (int) HUSTR_CHATMACRO3 },
  420. { "chatmacro4", (int *) &chat_macros[4], (int) HUSTR_CHATMACRO4 },
  421. { "chatmacro5", (int *) &chat_macros[5], (int) HUSTR_CHATMACRO5 },
  422. { "chatmacro6", (int *) &chat_macros[6], (int) HUSTR_CHATMACRO6 },
  423. { "chatmacro7", (int *) &chat_macros[7], (int) HUSTR_CHATMACRO7 },
  424. { "chatmacro8", (int *) &chat_macros[8], (int) HUSTR_CHATMACRO8 },
  425. { "chatmacro9", (int *) &chat_macros[9], (int) HUSTR_CHATMACRO9 }
  426. };
  427. int numdefaults;
  428. char *defaultfile;
  429. /*
  430. ==============
  431. =
  432. = M_SaveDefaults
  433. =
  434. ==============
  435. */
  436. void M_SaveDefaults (void)
  437. {
  438. int i,v;
  439. FILE *f;
  440. f = fopen (defaultfile, "w");
  441. if (!f)
  442. return; // can't write the file, but don't complain
  443. for (i=0 ; i<numdefaults ; i++)
  444. {
  445. #ifdef __WATCOMC__
  446. if (defaults[i].scantranslate)
  447. defaults[i].location = &defaults[i].untranslated;
  448. #endif
  449. if (defaults[i].defaultvalue > -0xfff
  450. && defaults[i].defaultvalue < 0xfff)
  451. {
  452. v = *defaults[i].location;
  453. fprintf (f,"%s\t\t%i\n",defaults[i].name,v);
  454. } else {
  455. fprintf (f,"%s\t\t\"%s\"\n",defaults[i].name,
  456. * (char **) (defaults[i].location));
  457. }
  458. }
  459. fclose (f);
  460. }
  461. /*
  462. ==============
  463. =
  464. = M_LoadDefaults
  465. =
  466. ==============
  467. */
  468. extern byte scantokey[128];
  469. extern char *basedefault;
  470. void M_LoadDefaults (void)
  471. {
  472. int i, len;
  473. FILE *f;
  474. char def[80];
  475. char strparm[100];
  476. char *newstring;
  477. int parm;
  478. boolean isstring;
  479. //
  480. // set everything to base values
  481. //
  482. numdefaults = sizeof(defaults)/sizeof(defaults[0]);
  483. for (i=0 ; i<numdefaults ; i++)
  484. *defaults[i].location = defaults[i].defaultvalue;
  485. //
  486. // check for a custom default file
  487. //
  488. i = M_CheckParm("-config");
  489. if(i && i<myargc-1)
  490. {
  491. defaultfile = myargv[i+1];
  492. printf("default file: %s\n", defaultfile);
  493. }
  494. else if(cdrom)
  495. {
  496. defaultfile = "c:\\heretic.cd\\heretic.cfg";
  497. }
  498. else
  499. {
  500. defaultfile = basedefault;
  501. }
  502. //
  503. // read the file in, overriding any set defaults
  504. //
  505. f = fopen (defaultfile, "r");
  506. if (f)
  507. {
  508. while (!feof(f))
  509. {
  510. isstring = false;
  511. if (fscanf (f, "%79s %[^\n]\n", def, strparm) == 2)
  512. {
  513. if (strparm[0] == '"')
  514. {
  515. // get a string default
  516. isstring = true;
  517. len = strlen(strparm);
  518. newstring = (char *) malloc(len);
  519. strparm[len-1] = 0;
  520. strcpy(newstring, strparm+1);
  521. }
  522. else if (strparm[0] == '0' && strparm[1] == 'x')
  523. sscanf(strparm+2, "%x", &parm);
  524. else
  525. sscanf(strparm, "%i", &parm);
  526. for (i=0 ; i<numdefaults ; i++)
  527. if (!strcmp(def, defaults[i].name))
  528. {
  529. if (!isstring)
  530. *defaults[i].location = parm;
  531. else
  532. *defaults[i].location =
  533. (int) newstring;
  534. break;
  535. }
  536. }
  537. }
  538. fclose (f);
  539. }
  540. #ifdef __WATCOMC__
  541. for(i = 0; i < numdefaults; i++)
  542. {
  543. if(defaults[i].scantranslate)
  544. {
  545. parm = *defaults[i].location;
  546. defaults[i].untranslated = parm;
  547. *defaults[i].location = scantokey[parm];
  548. }
  549. }
  550. #endif
  551. }
  552. /*
  553. ==============================================================================
  554. SCREEN SHOTS
  555. ==============================================================================
  556. */
  557. typedef struct
  558. {
  559. char manufacturer;
  560. char version;
  561. char encoding;
  562. char bits_per_pixel;
  563. unsigned short xmin,ymin,xmax,ymax;
  564. unsigned short hres,vres;
  565. unsigned char palette[48];
  566. char reserved;
  567. char color_planes;
  568. unsigned short bytes_per_line;
  569. unsigned short palette_type;
  570. char filler[58];
  571. unsigned char data; // unbounded
  572. } pcx_t;
  573. /*
  574. ==============
  575. =
  576. = WritePCXfile
  577. =
  578. ==============
  579. */
  580. void WritePCXfile (char *filename, byte *data, int width, int height, byte *palette)
  581. {
  582. int i, length;
  583. pcx_t *pcx;
  584. byte *pack;
  585. pcx = Z_Malloc (width*height*2+1000, PU_STATIC, NULL);
  586. pcx->manufacturer = 0x0a; // PCX id
  587. pcx->version = 5; // 256 color
  588. pcx->encoding = 1; // uncompressed
  589. pcx->bits_per_pixel = 8; // 256 color
  590. pcx->xmin = 0;
  591. pcx->ymin = 0;
  592. pcx->xmax = SHORT(width-1);
  593. pcx->ymax = SHORT(height-1);
  594. pcx->hres = SHORT(width);
  595. pcx->vres = SHORT(height);
  596. memset (pcx->palette,0,sizeof(pcx->palette));
  597. pcx->color_planes = 1; // chunky image
  598. pcx->bytes_per_line = SHORT(width);
  599. pcx->palette_type = SHORT(2); // not a grey scale
  600. memset (pcx->filler,0,sizeof(pcx->filler));
  601. //
  602. // pack the image
  603. //
  604. pack = &pcx->data;
  605. for (i=0 ; i<width*height ; i++)
  606. if ( (*data & 0xc0) != 0xc0)
  607. *pack++ = *data++;
  608. else
  609. {
  610. *pack++ = 0xc1;
  611. *pack++ = *data++;
  612. }
  613. //
  614. // write the palette
  615. //
  616. *pack++ = 0x0c; // palette ID byte
  617. for (i=0 ; i<768 ; i++)
  618. *pack++ = *palette++;
  619. //
  620. // write output file
  621. //
  622. length = pack - (byte *)pcx;
  623. M_WriteFile (filename, pcx, length);
  624. Z_Free (pcx);
  625. }
  626. //==============================================================================
  627. /*
  628. ==================
  629. =
  630. = M_ScreenShot
  631. =
  632. ==================
  633. */
  634. void M_ScreenShot (void)
  635. {
  636. int i;
  637. byte *linear;
  638. char lbmname[12];
  639. byte *pal;
  640. #ifdef _WATCOMC_
  641. extern byte *pcscreen;
  642. #endif
  643. //
  644. // munge planar buffer to linear
  645. //
  646. #ifdef _WATCOMC_
  647. linear = pcscreen;
  648. #else
  649. linear = screen;
  650. #endif
  651. //
  652. // find a file name to save it to
  653. //
  654. strcpy(lbmname,"HRTIC00.pcx");
  655. for (i=0 ; i<=99 ; i++)
  656. {
  657. lbmname[5] = i/10 + '0';
  658. lbmname[6] = i%10 + '0';
  659. if (access(lbmname,0) == -1)
  660. break; // file doesn't exist
  661. }
  662. if (i==100)
  663. I_Error ("M_ScreenShot: Couldn't create a PCX");
  664. //
  665. // save the pcx file
  666. //
  667. #ifdef __WATCOMC__
  668. pal = (byte *)Z_Malloc(768, PU_STATIC, NULL);
  669. outp(0x3c7, 0);
  670. for(i = 0; i < 768; i++)
  671. {
  672. *(pal+i) = inp(0x3c9)<<2;
  673. }
  674. #else
  675. pal = (byte *)W_CacheLumpName("PLAYPAL", PU_CACHE);
  676. #endif
  677. WritePCXfile (lbmname, linear, SCREENWIDTH, SCREENHEIGHT
  678. , pal);
  679. players[consoleplayer].message = "SCREEN SHOT";
  680. #ifdef __WATCOMC__
  681. Z_Free(pal);
  682. #endif
  683. }