home *** CD-ROM | disk | FTP | other *** search
/ Doom I/II Collection / DM12.ISO / edit / dmps_13a / dmps.c next >
C/C++ Source or Header  |  1994-07-17  |  24KB  |  769 lines

  1. /*
  2.  
  3.   DMPS: The Doom PostScript Map Generator, Version SWB 1.3a
  4.   ---------------------------------------------------------
  5.   Original program for Unix and copyright (c) James Bonfield, March 3, 1994.
  6.   Modified for PC by Gerhard Karnik, March 29, 1994.
  7.   Extensive modifications & enhancements by Steve W Brewer, May 2, 1994.
  8.  
  9.   Description
  10.   -----------
  11.   This program produces PostScript maps of Doom levels, extracted from the WAD
  12.   file.
  13.   
  14.   Thick lines represent solid walls on the map.
  15.   Black circles represent objects.  The letters inside represent what kind of
  16.   object it is.
  17.   White circles with arrows represent the enemy. The direction of the arrow is
  18.   the direction the creature is initially facing.
  19.   Grey lines represent secret areas.
  20.  
  21.   Usage
  22.   -----
  23.   
  24.   DMPS [options]
  25.   
  26.     /D                 Enable debugging.
  27.     /W wadfile[.WAD]   Wadfile to read from.  (Default: DOOM.WAD)
  28.     /L level           Level to draw.  (Default: E1M1)
  29.     /S1                Draw things present at skills 1 & 2.
  30.     /S3                Draw things present at skill 3.
  31.     /S4                Draw things present at skills 4 & 5.
  32.     /MUL               Draw things present in multiple player mode.
  33.     /NO                Don't draw objects.
  34.     /NM                Don't draw monsters.
  35.     /NS                Don't draw player start positions.
  36.     /?                 Display command line options.
  37.  
  38.   The PostScript will then be displayed to stdout.
  39.  
  40.   Compiled using Borland C++ 3.1 using 'bcc -mh'
  41.  
  42. */
  43.  
  44. #define L_MOD_JB   "March 3, 1994"
  45. #define L_MOD_GK   "March 29, 1994"
  46. #define L_MOD_SWB  "May 2, 1994"
  47. #define VERSION    "SWB 1.3a"
  48.  
  49. #define LI_IMPASS 0x01                  /* Linedef attribute bits */
  50. #define LI_SECRET 0x20
  51.  
  52. #define TH_SKILL1 0x01                  /* Thing type bits */
  53. #define TH_SKILL2 0x01
  54. #define TH_SKILL3 0x02
  55. #define TH_SKILL4 0x04
  56. #define TH_MULTI  0x10
  57.  
  58. #define PAPER_X      (72 * 8.5)         /* Paper width  */
  59. #define PAPER_Y      (72 * 11 )         /* Paper height */
  60. #define PAPER_BORDER (72 * 0.5)         /* Paper margin */
  61.  
  62. #include <io.h>
  63. #include <stdio.h>
  64. #include <stdlib.h>
  65. #include <errno.h>
  66. #include <string.h>
  67. #include <share.h>
  68. #include <fcntl.h>
  69. #include <dos.h>
  70. #include <alloc.h>
  71.  
  72. unsigned nread;                        /* throw away variable for _dos_read() */
  73.  
  74. typedef long int4;
  75. typedef short int2;
  76.  
  77. struct wad_header {
  78.   int4 magic;
  79.   int4 dir_size;
  80.   int4 dir_off;
  81.   };
  82.  
  83. struct directory {
  84.   int4 start;
  85.   int4 length;
  86.   char name[8];
  87.   };
  88.  
  89. typedef
  90.   struct linedef_ {
  91.     int2 from_vertex;
  92.     int2 to_vertex;
  93.     int2 attrib;
  94.     int2 type;
  95.     int2 trigger;
  96.     int2 sidedef1;
  97.     int2 sidedef2;
  98.     }
  99.   linedef;
  100.  
  101. typedef
  102.   struct vertex_ {
  103.     int2 x;
  104.     int2 y;
  105.     }
  106.   vertex;
  107.  
  108. typedef
  109.   struct sidedef_ {
  110.     int2 x;
  111.     int2 y;
  112.     char wall_above[8];
  113.     char wall_below[8];
  114.     char wall_part[8];
  115.     int2 sector;
  116.     }
  117.   sidedef;
  118.  
  119. typedef
  120.   struct ssector_ {
  121.     int2 num;
  122.     int2 seg;
  123.     }
  124.   ssector;
  125.  
  126. typedef
  127.   struct sector_ {
  128.     int2 bot_pos;
  129.     int2 top_pos;
  130.     char bot_texture[8];
  131.     char top_texture[8];
  132.     int2 brightness;
  133.     int2 special;
  134.     int2 trigger;
  135.     }
  136.   sector;
  137.  
  138. typedef
  139.   struct thing_ {
  140.     int2 x;
  141.     int2 y;
  142.     int2 angle;
  143.     int2 type;
  144.     int2 attrib;
  145.     }
  146.   thing;
  147.  
  148. typedef int2 blockmap;
  149.  
  150. struct directory *open_wad(char *file, int *fd, long *size);
  151. long get_index(struct directory *d, long size, char *name, long st);
  152.  
  153. linedef  *read_linedefs(int fd, struct directory *d, long size, long start, long *num);
  154. vertex   *read_vertexes(int fd, struct directory *d, long size, long start, long *num);
  155. blockmap *read_blockmap(int fd, struct directory *d, long size, long start, long *num);
  156. sidedef  *read_sidedefs(int fd, struct directory *d, long size, long start, long *num);
  157. sector   *read_sectors (int fd, struct directory *d, long size, long start, long *num);
  158. thing    *read_things  (int fd, struct directory *d, long size, long start, long *num);
  159.  
  160. void doit(int fd, struct directory *dir, long size, char *wadfile, char *lev_name,
  161.   long objs, long mons, long strt, long lev1, long lev3, long lev4, long mult);
  162.  
  163. void dump_dir(struct directory *d, long size) {
  164.   int i;
  165.  
  166.   for(i=0; i<size; i++) {
  167.     printf("Item=%5d, Start=%8ld, Len=%8ld, Name=%.8s\n", i, d[i].start, d[i].length, d[i].name);
  168.   }
  169. }
  170.  
  171. int main(int argc, char **argv) {
  172.   struct directory *d;
  173.   int fd;
  174.   long size, c;
  175.   long objs = 1, mons = 1, strt = 1, lev1 = 0, lev3 = 0, lev4 = 0, mult = 0, dump = 0, help = 0;
  176.   char *level = "E1M1";
  177.   char *wadfile = "doom.wad";
  178.   int i;
  179.  
  180.   for(i=1; i<=argc; i++) {
  181.     if(!strcmpi(argv[i], "/D")   || !strcmpi(argv[i], "-D"))   dump = 1;
  182.     if(!strcmpi(argv[i], "/W")   || !strcmpi(argv[i], "-W"))   wadfile = argv[(i++)+1];
  183.     if(!strcmpi(argv[i], "/L")   || !strcmpi(argv[i], "-L"))   level = strupr(argv[(i++)+1]);
  184.     if(!strcmpi(argv[i], "/S1")  || !strcmpi(argv[i], "-S1"))  lev1 = 1;
  185.     if(!strcmpi(argv[i], "/S3")  || !strcmpi(argv[i], "-S3"))  lev3 = 1;
  186.     if(!strcmpi(argv[i], "/S4")  || !strcmpi(argv[i], "-S4"))  lev4 = 1;
  187.     if(!strcmpi(argv[i], "/MUL") || !strcmpi(argv[i], "-MUL")) mult = 1;
  188.     if(!strcmpi(argv[i], "/NO")  || !strcmpi(argv[i], "-NO"))  objs = 0;
  189.     if(!strcmpi(argv[i], "/NM")  || !strcmpi(argv[i], "-NM"))  mons = 0;
  190.     if(!strcmpi(argv[i], "/NS")  || !strcmpi(argv[i], "-NS"))  strt = 0;
  191.     if(!strcmpi(argv[i], "/?")   || !strcmpi(argv[i], "-?"))   help = 1;
  192.   }
  193.  
  194.   /*if (NULL == strchr(wadfile, 46)) strcat(wadfile, ".WAD");*/
  195.  
  196.   if (help) {
  197.     fprintf(stderr, "\nDMPS: The Doom PostScript Map Generator, Version %s\n", VERSION);
  198.     fprintf(stderr, "---------------------------------------------------------\n");
  199.     fprintf(stderr, "Produces PostScript map of Doom level on stdout.\n\n");
  200.     fprintf(stderr, "DMPS [options]\n");
  201.     fprintf(stderr, "\n");
  202.     fprintf(stderr, "  /W wadfile.WAD     Wadfile to read from.  (Default: DOOM.WAD)\n");
  203.     fprintf(stderr, "  /L level           Level to draw.  (Default: E1M1)\n");
  204.     fprintf(stderr, "  /S1                Draw things present at skills 1 & 2.\n");
  205.     fprintf(stderr, "  /S3                Draw things present at skill 3.\n");
  206.     fprintf(stderr, "  /S4                Draw things present at skills 4 & 5.\n");
  207.     fprintf(stderr, "  /MUL               Draw things present in multi-player mode.\n");
  208.     fprintf(stderr, "  /NO                Don't draw objects.\n");
  209.     fprintf(stderr, "  /NM                Don't draw monsters.\n");
  210.     fprintf(stderr, "  /NS                Don't draw player start positions.\n");
  211.     fprintf(stderr, "  /?                 Display command-line options.\n\n");
  212.     fprintf(stderr, "Original program for Unix and copyright (c) James Bonfield, %s.\n", L_MOD_JB);
  213.     fprintf(stderr, "Modified for PC by Gerhard Karnik, %s.\n", L_MOD_GK);
  214.     fprintf(stderr, "Extensive modifications & enhancements by Steve W Brewer, %s.\n", L_MOD_SWB);
  215.     return 1;
  216.   }
  217.  
  218.   if (NULL == (d = open_wad(wadfile, &fd, &size))) {
  219.     fprintf(stderr, "Type DMPS /? for help.\n");
  220.     return 1;
  221.   }
  222.  
  223.   if(dump) {
  224.     dump_dir(d, size);
  225.     return 0;
  226.   }
  227.  
  228.   doit(fd, d, size, wadfile, level, objs, mons, strt, lev1, lev3, lev4, mult);
  229.  
  230.   return 0;
  231. }
  232.  
  233. void doit(int fd, struct directory *dir, long size, char *wadfile, char *lev_name,
  234.   long objs, long mons, long strt, long lev1, long lev3, long lev4, long mult) {
  235.  
  236.   linedef *linedefs;
  237.   vertex *vertexes;
  238.   blockmap *blocks;
  239.   sidedef *sidedefs;
  240.   sector *sectors;
  241.   thing *things;
  242.   long numline, numvert, numblock, numside, numsect, numthing;
  243.   long lev_index;
  244.   long xorigin, yorigin, xsize, ysize;
  245.   int2 sector;
  246.   double xscale, yscale, xscalelnd, yscalelnd, xscaleprt, yscaleprt;
  247.   long landscape = 0;
  248.   long found = 0;
  249.   long i, j;
  250.   char nametag[2];
  251.         
  252.   /* find level index */
  253.  
  254.   lev_index = get_index(dir, size, lev_name, 0);
  255.  
  256.   if(lev_index == -1) {
  257.     fprintf(stderr, "Unknown level: %s\n", lev_name);
  258.     exit(1);
  259.   }
  260.  
  261.   /* load relevent arrays for this level */
  262.  
  263.   linedefs = read_linedefs(fd, dir, size, lev_index, &numline );
  264.   vertexes = read_vertexes(fd, dir, size, lev_index, &numvert );
  265.   blocks   = read_blockmap(fd, dir, size, lev_index, &numblock);
  266.   sidedefs = read_sidedefs(fd, dir, size, lev_index, &numside );
  267.   sectors  = read_sectors (fd, dir, size, lev_index, &numsect );
  268.   things   = read_things  (fd, dir, size, lev_index, &numthing);
  269.  
  270.   /* calculate scaling info */
  271.  
  272.   xorigin = blocks[0];
  273.   yorigin = blocks[1];
  274.   xsize = blocks[2] * 0x80;
  275.   ysize = blocks[3] * 0x80;
  276.  
  277.   xscalelnd = (double) (PAPER_Y - 2*PAPER_BORDER)/xsize;
  278.   yscalelnd = (double) (PAPER_X - 2*PAPER_BORDER)/ysize;
  279.  
  280.   if (xscalelnd > yscalelnd)
  281.     xscalelnd = yscalelnd;
  282.    else
  283.     yscalelnd = xscalelnd;
  284.  
  285.   xscaleprt = (double) (PAPER_X - 2*PAPER_BORDER)/xsize;
  286.   yscaleprt = (double) (PAPER_Y - 2*PAPER_BORDER)/ysize;
  287.  
  288.   if (xscaleprt > yscaleprt) 
  289.     xscaleprt = yscaleprt;
  290.    else
  291.     yscaleprt = xscaleprt;
  292.  
  293.   if (xscaleprt > xscalelnd) {
  294.     xscale = xscaleprt;
  295.     yscale = xscaleprt;
  296.     }
  297.    else {
  298.     xscale = xscalelnd;
  299.     yscale = xscalelnd;
  300.     landscape = 1;
  301.   }
  302.  
  303.   /* output postscript header */
  304.  
  305.   printf("%%!\n");
  306.   printf("%%\n");
  307.   printf("%%  Doom Map: %s Episode %c Mission %c\n", strupr(wadfile), lev_name[1], lev_name[3]);
  308.   printf("%%  ------------------------------------------\n");
  309.   printf("%%  Created by DMPS: The Doom PostScript Map Generator, Version %s\n", VERSION);
  310.   printf("%%\n");
  311.   printf("%%  Original program for Unix and copyright (c) James Bonfield, %s.\n", L_MOD_JB);
  312.   printf("%%  Modified for MS-DOS by Gerhard Karnik, %s.\n", L_MOD_GK);
  313.   printf("%%  Extensive modifications & enhancements by Steve W Brewer, %s.\n", L_MOD_SWB);
  314.   printf("%%\n");
  315.   printf("%%  Options in effect:\n");
  316.   printf("%%  ------------------\n");
  317.   if (lev1) printf("%%    Draw things present at skills 1 & 2.\n");
  318.   if (lev3) printf("%%    Draw things present at skill 3.\n");
  319.   if (lev4) printf("%%    Draw things present at skills 4 & 5.\n");
  320.   if (mult) printf("%%    Draw things present in multi-player mode.\n");
  321.   if (objs) printf("%%    Draw objects.\n");
  322.   if (mons) printf("%%    Draw monsters.\n");
  323.   if (strt) printf("%%    Draw player start positions.\n");
  324.   printf("%%\n");
  325.   printf("currentscreen 3 1 roll pop pop 120 45 3 -1 roll setscreen\n");
  326.   printf("newpath\n");
  327.   printf("1 setlinecap\n");
  328.   printf("%f %f translate\n", PAPER_BORDER, landscape ? (PAPER_Y - PAPER_BORDER) : PAPER_BORDER);
  329.   if (landscape) printf("-90 rotate\n");
  330.   printf("%f %f scale\n", xscale, yscale);
  331.   printf("%ld %ld translate\n", -xorigin, -yorigin);
  332.   printf("%f setlinewidth\n", (double) .5 / xscale);
  333.   printf("\n");
  334.   printf("/l {\n");
  335.   printf("    setgray setlinewidth moveto lineto stroke\n");
  336.   printf("} def\n");
  337.   printf("\n");
  338.   printf("/a {%% Draw Object (Arguments: tag xcenter ycenter)\n");
  339.   printf("    gsave\n");
  340.   printf("    translate\n");
  341.   printf("    20 20 scale\n");
  342.   printf("    /tag exch def\n");
  343.   printf("    1 setgray\n");
  344.   printf("    0 setlinewidth\n");
  345.   printf("    0 0 1.01 0 360 arc fill\n");
  346.   printf("    0 setgray\n");
  347.   printf("    0 0 1 0 360 arc fill\n");
  348.   printf("    1 setgray\n");
  349.   printf("    0 0 moveto\n");
  350.   printf("    /Helvetica-Bold findfont [1.2 0 0 1.7 0 0] makefont setfont\n");
  351.   printf("    -.1 0 tag dup stringwidth pop neg 2 div .105 add -.55 rmoveto ashow\n");
  352.   printf("    grestore\n");
  353.   printf("} def\n");
  354.   printf("\n");
  355.   printf("/m {%% Draw Monster (Arguments: tag radius angle xcenter ycenter)\n");
  356.   printf("    gsave\n");
  357.   printf("    translate\n");
  358.   printf("    /angle exch 90 sub def\n");
  359.   printf("    dup scale\n");
  360.   printf("    /tag exch def\n");
  361.   printf("    1 setgray\n");
  362.   printf("    0 setlinewidth\n");
  363.   printf("    0 0 1.01 0 360 arc fill\n");
  364.   printf("    0 setgray\n");
  365.   printf("    0 0 1 0 360 arc fill\n");
  366.   printf("    1 setgray\n");
  367.   printf("    0 0 .95 0 360 arc fill\n");
  368.   printf("    0 setgray\n");
  369.   printf("    0 0 .9 0 360 arc fill\n");
  370.   printf("    1 setgray\n");
  371.   printf("    0 0 moveto\n");
  372.   printf("    /Helvetica-Bold findfont [1 0 0 1.6 0 0] makefont setfont\n");
  373.   printf("    -.1 0 tag dup stringwidth pop neg 2 div .10 add -.55 rmoveto ashow\n");
  374.   printf("    0 0 moveto\n");
  375.   printf("    angle rotate\n");
  376.   printf("    0 setgray\n");
  377.   printf("    newpath\n");
  378.   printf("    0 1.3 moveto\n");
  379.   printf("    0 0 .97 80 100 arc\n");
  380.   printf("    0 1.3 lineto\n");
  381.   printf("    fill\n");
  382.   printf("    grestore\n");
  383.   printf("} def\n");
  384.  
  385.   /* Display the walls. Secret passages are done in grey. */
  386.  
  387.   for (i = 0; i < numline; i++) {
  388.     sector = sidedefs[linedefs[i].sidedef1].sector;
  389.  
  390.     printf("%d %d %d %d ",
  391.       vertexes[linedefs[i].to_vertex].x,
  392.       vertexes[linedefs[i].to_vertex].y,
  393.       vertexes[linedefs[i].from_vertex].x,
  394.       vertexes[linedefs[i].from_vertex].y);
  395.  
  396.     if (linedefs[i].attrib & LI_IMPASS) {
  397.       printf("%f ", 1.2/xscale); }
  398.      else {
  399.       printf("%f ", 0.5/xscale);
  400.     }
  401.  
  402.     if (linedefs[i].attrib & LI_SECRET || sectors[sector].special == 9) {
  403.       printf(".8 l\n"); } 
  404.      else {
  405.       printf("0 l\n");
  406.     }
  407.   }
  408.  
  409.   for(i=0; i<numthing; i++) {
  410.  
  411.     /* filter out unwanted stuff */
  412.  
  413.     if(!(((things[i].attrib & 0x1) && lev1)
  414.       || ((things[i].attrib & 0x2) && lev3)
  415.       || ((things[i].attrib & 0x4) && lev4))) continue;
  416.  
  417.     if(!(!(things[i].attrib & 0x10) || mult)) continue;
  418.  
  419.     /* Draw monsters */
  420.  
  421.     if (mons) {
  422.       found=1;
  423.       
  424.       switch(things[i].type) {
  425.         case    7:            /* Spider Demon          */
  426.           printf("(SP) 128");
  427.           break;
  428.         case    9:            /* Former Human Sergeant */
  429.           printf("(SR)  20");
  430.           break;
  431.         case   16:            /* Cyber-Demon           */
  432.           printf("(CD)  40");
  433.           break;
  434.         case   58:            /* Spectre               */
  435.           printf("(SE)  30");
  436.           break;
  437.         case 3001:            /* Imp                   */
  438.           printf("(IM)  20");
  439.           break;
  440.         case 3002:            /* Demon                 */
  441.           printf("(DM)  30");
  442.           break;
  443.         case 3003:            /* Baron of Hell         */
  444.           printf("(BR)  24");
  445.           break;
  446.         case 3004:            /* Former Human          */
  447.           printf("(HM)  20");
  448.           break;
  449.         case 3005:            /* Cacodemon             */
  450.           printf("(TM)  31");
  451.           break;
  452.         case 3006:            /* Lost Soul             */
  453.           printf("(LS)  16");
  454.           break;
  455.         default:
  456.           found=0;
  457.           break;
  458.       }
  459.     
  460.       if (found) printf(" %d %d %d m\n", things[i].angle, things[i].x, things[i].y);
  461.     }
  462.  
  463.     /* Draw player start positions */
  464.     
  465.     if (strt) {
  466.       found=1;
  467.       
  468.       switch(things[i].type) {
  469.         case 1:               /* Player 1 Start        */
  470.           printf("(P1)");
  471.           break;
  472.         case 2:               /* Player 2 Start        */
  473.           if (mult) printf("(P2)"); else found=0;
  474.           break;
  475.         case 3:               /* Player 3 Start        */
  476.           if (mult) printf("(P3)"); else found=0;
  477.           break;
  478.         case 4:               /* Player 4 Start        */
  479.           if (mult) printf("(P4)"); else found=0;
  480.           break;
  481.         case 11:              /* Deathmatch Start      */
  482.       if (mult) printf("(DS)"); else found=0;
  483.           break;
  484.         case 14:              /* Teleport Exit         */
  485.           printf("(TX)");
  486.           break;
  487.         default:
  488.           found=0;
  489.           break;
  490.       }
  491.     
  492.       if (found) printf(" 16 %d %d %d m\n", things[i].angle, things[i].x, things[i].y);
  493.     }
  494.  
  495.     /* Draw objects */
  496.     
  497.     if(objs) {
  498.       found=1;
  499.       
  500.       switch(things[i].type) {
  501.         case 5:               /* Blue keycard          */
  502.           printf("(BK)");
  503.           break;
  504.         case 6:               /* Yellow keycard        */
  505.           printf("(YK)");
  506.           break;
  507.         case 13:              /* Red keycard           */
  508.           printf("(RK)");
  509.           break;
  510.         case 38:              /* Red skullkey          */
  511.           printf("(RK)");
  512.           break;
  513.         case 39:              /* Yellow skullkey       */
  514.           printf("(YK)");
  515.           break;
  516.         case 40:              /* Blue skullkey         */
  517.           printf("(BK)");
  518.           break;
  519.         case 2001:            /* Shotgun               */
  520.           printf("(SG)");
  521.           break;
  522.         case 2002:            /* Chaingun              */
  523.           printf("(CG)");
  524.           break;
  525.         case 2003:            /* Rocket launcher       */
  526.           printf("(RL)");
  527.           break;
  528.         case 2004:            /* Plasma gun            */
  529.           printf("(PG)");
  530.           break;
  531.         case 2005:            /* Chainsaw              */
  532.           printf("(CH)");
  533.           break;
  534.         case 2006:            /* BFG9000               */
  535.           printf("(BG)");
  536.           break;
  537.         case 8   :            /* Backpack              */
  538.           printf("(BP)");
  539.           break;
  540.         case 17  :            /* Cell charge pack      */
  541.           printf("(CL)");
  542.           break;
  543.         case 2007:            /* Ammo clip             */
  544.           printf("(CP)");
  545.           break;
  546.         case 2008:            /* 4 shotgun shells      */
  547.           printf("(SH)");
  548.           break;
  549.         case 2010:            /* 1 rocket              */
  550.           printf("(RT)");
  551.           break;
  552.         case 2046:            /* Box of Rockets        */
  553.           printf("(BT)");
  554.           break;
  555.         case 2047:            /* Cell charge           */
  556.           printf("(CC)");
  557.           break;
  558.         case 2048:            /* Box of Ammo           */
  559.           printf("(BB)");
  560.           break;
  561.         case 2049:            /* Box of Shells         */
  562.           printf("(BH)");
  563.           break;
  564.         case 2011:            /* Stimpak               */
  565.           printf("(SM)");
  566.           break;
  567.         case 2012:            /* Medikit               */
  568.           printf("(MK)");
  569.           break;
  570.         case 2013:            /* Soulsphere            */
  571.           printf("(SS)");
  572.           break;
  573.         case 2014:            /* Health bonus          */
  574.           printf("(HL)");
  575.           break;
  576.         case 2015:            /* Armor bonus           */
  577.           printf("(AM)");
  578.           break;
  579.         case 2018:            /* Green armor 100%      */
  580.           printf("(GA)");
  581.           break;
  582.         case 2019:            /* Blue armor 200%       */
  583.           printf("(BA)");
  584.           break;
  585.         case 2022:            /* Invulnerability       */
  586.           printf("(IL)");
  587.           break;
  588.         case 2023:            /* Berserk Strength      */
  589.           printf("(BR)");
  590.           break;
  591.         case 2024:            /* Invisibility          */
  592.           printf("(IS)");
  593.           break;
  594.         case 2025:            /* Radiation suit        */
  595.           printf("(RD)");
  596.           break;
  597.         case 2026:            /* Computer map          */
  598.           printf("(MP)");
  599.           break;
  600.         case 2045:            /* Lite goggles          */
  601.           printf("(LT)");
  602.           break;
  603.         default:
  604.           found=0;
  605.           break;
  606.       }
  607.     
  608.       if (found) printf(" %d %d a\n", things[i].x, things[i].y);
  609.     }
  610.   }
  611.  
  612.   /*printf("/Times-Roman findfont %f scalefont setfont\n", 20 / xscale); */
  613.   /*printf("0 setgray 0 %ld moveto (%s) show\n", yorigin, lev_name);     */
  614.  
  615.   puts("showpage");
  616.   return;
  617. }
  618.  
  619. struct directory *open_wad(char *file, int *fd, long *size) {
  620.   struct wad_header h;
  621.   struct directory *d;
  622.  
  623.   if (_dos_open(file, O_RDONLY, fd) != 0) {
  624.     fprintf(stderr, "Could not open ");
  625.     perror(strupr(file));
  626.     return (struct directory *)0;
  627.   }
  628.  
  629.   _dos_read(*fd, &h, sizeof(h), &nread);
  630.  
  631.   if(NULL == (d = (struct directory *)farcalloc(h.dir_size, sizeof(*d)))) {
  632.     fprintf(stderr, "Error: Could not allocate %ld bytes.\n", h.dir_size * sizeof(*d));
  633.     return (struct directory *) 0;
  634.   }
  635.  
  636.   *size = h.dir_size;
  637.  
  638.   lseek(*fd, h.dir_off, SEEK_SET);
  639.   _dos_read(*fd, d, *size * sizeof(*d), &nread);
  640.  
  641.   return d;
  642. }
  643.  
  644. long get_index(struct directory *d, long size, char *name, long start) {
  645.   long i;
  646.  
  647.   for(i=start; i<size; i++) {
  648.  
  649.     if(_fstrncmp(d[i].name, name, 8) == 0)
  650.       return i;
  651.   }
  652.  
  653.   return -1;
  654. }
  655.  
  656. linedef *read_linedefs(int fd, struct directory *d, long size, long start, long *num) {
  657.   long index;
  658.   linedef *indexp;
  659.   long i;
  660.  
  661.   index = get_index(d, size, "LINEDEFS", start);
  662.  
  663.   if(!(indexp = (linedef *) farmalloc(d[index].length))) {
  664.     printf("Error: Could not allocate %ld bytes\n",d[index].length);
  665.     exit(-1);
  666.   }
  667.  
  668.   lseek(fd, d[index].start, SEEK_SET);
  669.   _dos_read(fd, indexp, d[index].length, &nread);
  670.   *num = d[index].length / sizeof(linedef);
  671.  
  672.   return indexp;
  673. }
  674.  
  675. vertex *read_vertexes(int fd, struct directory *d, long size, long start, long *num) {
  676.   long index;
  677.   vertex *indexp;
  678.   long i;
  679.  
  680.   index = get_index(d, size, "VERTEXES", start);
  681.  
  682.   if(!(indexp = (vertex *) farmalloc(d[index].length))) {
  683.     printf("Error: Could not allocate %ld bytes\n",d[index].length);
  684.     exit(-1);
  685.   }
  686.  
  687.   lseek(fd, d[index].start, SEEK_SET);
  688.   _dos_read(fd, indexp, d[index].length, &nread);
  689.   *num = d[index].length / sizeof(vertex);
  690.  
  691.   return indexp;
  692. }
  693.  
  694. blockmap *read_blockmap(int fd, struct directory *d, long size, long start, long *num) {
  695.   long index;
  696.   blockmap *indexp;
  697.   long i;
  698.  
  699.   index = get_index(d, size, "BLOCKMAP", start);
  700.  
  701.   if(!(indexp = (blockmap *) farmalloc(d[index].length))) {
  702.     printf("Error: Could not allocate %ld bytes\n",d[index].length);
  703.     exit(-1);
  704.   }
  705.  
  706.   lseek(fd, d[index].start, SEEK_SET);
  707.   _dos_read(fd, indexp, d[index].length, &nread);
  708.   *num = d[index].length / sizeof(blockmap);
  709.  
  710.   return indexp;
  711. }
  712.  
  713. sidedef *read_sidedefs(int fd, struct directory *d, long size, long start, long *num) {
  714.   long index;
  715.   sidedef *indexp;
  716.   long i;
  717.  
  718.   index = get_index(d, size, "SIDEDEFS", start);
  719.  
  720.   if(!(indexp = (sidedef *) farmalloc(d[index].length))) {
  721.     printf("Error: Could not allocate %ld bytes\n",d[index].length);
  722.     exit(-1);
  723.  }
  724.  
  725.   lseek(fd, d[index].start, SEEK_SET);
  726.   _dos_read(fd, indexp, d[index].length, &nread);
  727.   *num = d[index].length / sizeof(sidedef);
  728.  
  729.   return indexp;
  730. }
  731.  
  732. sector *read_sectors(int fd, struct directory *d, long size, long start, long *num) {
  733.   long index;
  734.   sector *indexp;
  735.   long i;
  736.  
  737.   index = get_index(d, size, "SECTORS", start);
  738.  
  739.   if(!(indexp = (sector *) farmalloc(d[index].length))) {
  740.     printf("Error: Could not allocate %ld bytes\n",d[index].length);
  741.     exit(-1);
  742.   }
  743.  
  744.   lseek(fd, d[index].start, SEEK_SET);
  745.   _dos_read(fd, indexp, d[index].length, &nread);
  746.   *num = d[index].length / sizeof(sector);
  747.  
  748.   return indexp;
  749. }
  750.  
  751. thing *read_things(int fd, struct directory *d, long size, long start, long *num) {
  752.   long index;
  753.   thing *indexp;
  754.   long i;
  755.  
  756.   index = get_index(d, size, "THINGS", start);
  757.  
  758.   if(!(indexp = (thing *) farmalloc(d[index].length))) {
  759.     printf("Error: Could not allocate %ld bytes\n",d[index].length);
  760.     exit(-1);
  761.   }
  762.  
  763.   lseek(fd, d[index].start, SEEK_SET);
  764.   _dos_read(fd, indexp, d[index].length, &nread);
  765.   *num = d[index].length / sizeof(thing);
  766.  
  767.   return indexp;
  768. }
  769.