home *** CD-ROM | disk | FTP | other *** search
/ Ultimate DOOM Companion / PowersourceMultimedia-UltimateDOOMCompanion.iso / goodies / doom_ps.zip / DOOM_PS.C < prev    next >
C/C++ Source or Header  |  1994-03-29  |  18KB  |  535 lines

  1. /*
  2.                   Doom PostScript map generator. V1.1
  3.                     Copyright James Bonfield, 3/3/94
  4.                Modified for PC by Gerhard Karnik 3/29/94
  5.  
  6. Description
  7. -----------
  8.  
  9. This program produces PostScript maps of Doom levels, extracted from the Wad
  10. file. The program is written for the UNIX operating system, and so you need a
  11. method of transfering your doom.wad file, (or perhaps having it visible by,
  12. say, mounting your DOS partition).
  13.  
  14. Thick lines represent solid walls on the map.
  15. Circles represent objects.
  16. Arrows represent the enemy. The direction of the arrow is the direction the
  17. creature is facing.
  18. Gray lines represent secret passages.
  19.  
  20.  
  21. Command line options
  22.  
  23. -d        enables debugging
  24. -w wadfile    selects another wad file (default is "doom.wad")
  25. -l level    choose another level (default is "E1M1")
  26. -o        do not display objects
  27. -m        do not display monsters
  28.  
  29. The postscript will then be displayed to stdout.
  30.  
  31. Compiled using Borland C++ 3.1 using 'bcc -mh'
  32.  
  33. */
  34.  
  35. #include <io.h>
  36. #include <stdio.h>
  37. #include <stdlib.h>
  38. #include <errno.h>
  39. #include <string.h>
  40. #include <share.h>
  41. #include <fcntl.h>
  42. #include <dos.h>
  43. #include <alloc.h>
  44.  
  45. unsigned nread;         /* throw away variable for _dos_read() */
  46.  
  47. typedef long int4;
  48. typedef short int2;
  49.  
  50. struct wad_header {
  51.         int4 magic;
  52.         int4 dir_size;
  53.         int4 dir_off;
  54. };
  55.  
  56. struct directory {
  57.         int4 start;
  58.         int4 length;
  59.         char name[8];
  60. };
  61.  
  62. typedef struct linedef_ {
  63.         int2 from_vertex;
  64.         int2 to_vertex;
  65.         int2 attrib;
  66.         int2 type;
  67.         int2 trigger;
  68.         int2 sidedef1;
  69.         int2 sidedef2;
  70. } linedef;
  71.  
  72. /* linedef attrib bits */
  73. #define LI_IMPASS 0x01
  74. #define LI_SECRET 0x20
  75.  
  76. typedef struct vertex_ {
  77.         int2 x;
  78.         int2 y;
  79. } vertex;
  80.  
  81. typedef struct sidedef_ {
  82.         int2 x;
  83.         int2 y;
  84.         char wall_above[8];
  85.         char wall_below[8];
  86.         char wall_part[8];
  87.         int2 sector;
  88. } sidedef;
  89.  
  90. typedef struct ssector_ {
  91.         int2 num;
  92.         int2 seg;
  93. } ssector;
  94.  
  95. typedef struct sector_ {
  96.         int2 bot_pos;
  97.         int2 top_pos;
  98.         char bot_texture[8];
  99.         char top_texture[8];
  100.         int2 brightness;
  101.         int2 special;
  102.         int2 trigger;
  103. } sector;
  104.  
  105. typedef struct thing_ {
  106.         int2 x;
  107.         int2 y;
  108.         int2 angle;
  109.         int2 type;
  110.         int2 attrib;
  111. } thing;
  112.  
  113. /* thing 'type' bits */
  114. #define TH_SKILL1  0x01
  115. #define TH_SKILL2  0x01
  116. #define TH_SKILL3  0x02
  117. #define TH_SKILL4  0x04
  118. #define TH_MULTI   0x10
  119.  
  120. typedef int2 blockmap;
  121.  
  122. struct directory *open_wad(char *file, int *fd, long *size);
  123. long get_index(struct directory *d, long size, char *name, long st);
  124. linedef *read_linedefs(int fd, struct directory *d, long size, long start, long *num);
  125. vertex *read_vertexes(int fd, struct directory *d, long size, long start, long *num);
  126. blockmap *read_blockmap(int fd, struct directory *d, long size, long start, long *num);
  127. sidedef *read_sidedefs(int fd, struct directory *d, long size, long start, long *num);
  128. sector *read_sectors(int fd, struct directory *d, long size, long start, long *num);
  129. thing *read_things(int fd, struct directory *d, long size, long start, long *num);
  130.  
  131. /*
  132.  * Paper is 8 1/2" by 11"
  133.  * We allow 1/2" border.
  134.  */
  135. #define PAPER_X (72 * 8.5)
  136. #define PAPER_Y (72 * 11)
  137. #define PAPER_BORDER (72 * 0.5)
  138.  
  139. void doit(int fd, struct directory *dir, long size, char *lev_name,
  140.            long objs, long mons);
  141.  
  142.  
  143. void dump_dir(struct directory *d, long size)
  144. {
  145.         int i;
  146.  
  147.         for(i=0; i<size; i++) {
  148.                 printf("Item=%5d, Start=%8ld, Len=%8ld, Name=%.8s\n",
  149.                        i, d[i].start, d[i].length, d[i].name);
  150.         }
  151. }
  152.  
  153.  
  154. int main(int argc, char **argv)
  155. {
  156.         struct directory *d;
  157.         int fd;
  158.         long size, c;
  159.         long objs = 1, mons = 1, dump = 0;
  160.         char *level = "E1M1";
  161.         char *wadfile = "doom.wad";
  162.         int i;
  163.  
  164.         for(i=1; i<=argc; i++) {
  165.                 if(!strcmpi(argv[i], "-W")) wadfile = argv[(i++)+1];
  166.                 if(!strcmpi(argv[i], "-D")) dump = 1;
  167.                 if(!strcmpi(argv[i], "-L")) level = argv[(i++)+1];
  168.                 if(!strcmpi(argv[i], "-O")) objs = 0;
  169.                 if(!strcmpi(argv[i], "-M")) mons = 0;
  170.         }
  171.  
  172.         if(NULL == (d = open_wad(wadfile, &fd, &size))) {
  173.                 fprintf(stderr, "Failed to open wad file.\n");
  174.                 return 1;
  175.         }
  176.         if(dump) {
  177.                 dump_dir(d, size);
  178.                 return 0;
  179.         }
  180.         doit(fd, d, size, level, objs, mons);
  181.  
  182.         return 0;
  183. }
  184.  
  185. void doit(int fd, struct directory *dir, long size, char *lev_name,
  186.            long objs, long mons)
  187. {
  188.         linedef *linedefs;
  189.         vertex *vertexes;
  190.         blockmap *blocks;
  191.         sidedef *sidedefs;
  192.         sector *sectors;
  193.         thing *things;
  194.         long numline, numvert, numblock, numside, numsect, numthing;
  195.         long lev_index;
  196.         long xorigin, yorigin, xsize, ysize;
  197.         int2 sector;
  198.         double xscale, yscale;
  199.         long i, j;
  200.  
  201.         /* find level index */
  202.         lev_index = get_index(dir, size, lev_name, 0);
  203.         if(lev_index == 0) {
  204.                 fprintf(stderr, "Unknown level: %s\n", lev_name);
  205.                 exit(1);
  206.         }
  207.  
  208.         /* load relevent arrays for this level */
  209.  
  210.         linedefs = read_linedefs(fd, dir, size, lev_index, &numline);
  211.         vertexes = read_vertexes(fd, dir, size, lev_index, &numvert);
  212.         blocks = read_blockmap(fd, dir, size, lev_index, &numblock);
  213.         sidedefs = read_sidedefs(fd, dir, size, lev_index, &numside);
  214.         sectors = read_sectors(fd, dir, size, lev_index, &numsect);
  215.         things = read_things(fd, dir, size, lev_index, &numthing);
  216.  
  217.         /* calculate scaling info */
  218.         xorigin = blocks[0];
  219.         yorigin = blocks[1];
  220.         xsize = blocks[2] * 0x80;
  221.         ysize = blocks[3] * 0x80;
  222.  
  223.         xscale = (double) (PAPER_Y - 2 * PAPER_BORDER) / xsize;
  224.         yscale = (double) (PAPER_X - 2 * PAPER_BORDER) / ysize;
  225.  
  226.         if (xscale > yscale)
  227.                 xscale = yscale;
  228.         else
  229.                 yscale = xscale;
  230.  
  231.         /* output postscript header */
  232.         printf("%%!\n");
  233.         printf("newpath\n");
  234.         printf("\n");
  235.         printf("1 setlinecap\n");
  236.         printf("%f %f translate\n", PAPER_BORDER, PAPER_Y - PAPER_BORDER);
  237.         printf("-90 rotate\n");
  238.         printf("%f %f scale\n", xscale, yscale);
  239.         printf("%ld %ld translate\n", -xorigin, -yorigin);
  240.         printf("%f setlinewidth\n", (double) .5 / xscale);
  241.         printf("\n");
  242.         printf("/Times-Roman findfont %f scalefont setfont\n", 5 / xscale);
  243.         printf("/Text {\n");
  244.         printf("    gsave\n");
  245.         printf("    0 setgray moveto show\n");
  246.         printf("    grestore\n");
  247.         printf("} def\n");
  248.         printf("\n");
  249.         printf("/l {\n");
  250.         printf("    setgray setlinewidth moveto lineto stroke\n");
  251.         printf("} def\n");
  252.         printf("\n");
  253.         printf("/a {\n");
  254.         printf("    0.5 setgray\n");
  255.         printf("    5 0 360 arc stroke\n");
  256.         printf("} def\n");
  257.         printf("\n");
  258.         printf("/m {\n");
  259.         printf("    gsave\n");
  260.         printf("    0 setgray\n");
  261.         printf("    1 setlinewidth\n");
  262.         printf("    moveto rotate\n");
  263.         printf("    0 -13 rmoveto\n");
  264.         printf("    0 25 rlineto\n");
  265.         printf("    -10 -10 rlineto\n");
  266.         printf("    10 10 rmoveto\n");
  267.         printf("    10 -10 rlineto\n");
  268.         printf("    stroke\n");
  269.         printf("    grestore\n");
  270.         printf("} def\n");
  271.  
  272.         /* Display the walls. Secret passages are done in grey. */
  273.         for (i = 0; i < numline; i++) {
  274.                 sector = sidedefs[linedefs[i].sidedef1].sector;
  275.  
  276.                 printf("%d %d %d %d ",
  277.                        vertexes[linedefs[i].to_vertex].x,
  278.                        vertexes[linedefs[i].to_vertex].y,
  279.                        vertexes[linedefs[i].from_vertex].x,
  280.                        vertexes[linedefs[i].from_vertex].y);
  281.  
  282.                 if (linedefs[i].attrib & LI_IMPASS) {
  283.                         printf("%f ", 1.2 / xscale);
  284.                 } else {
  285.                         printf("%f ", 0.5 / xscale);
  286.                 }
  287.  
  288.                 if (linedefs[i].attrib & LI_SECRET || sectors[sector].special == 9) {
  289.                         printf(".5 l\n");
  290.                 } else {
  291.                         printf("0 l\n");
  292.                 }
  293.         }
  294.  
  295.         /* Do we need to display objects or monsters? */
  296.         if(objs || mons) {
  297.                 printf("    %f setlinewidth\n", 1 / xscale);
  298.  
  299.                 for(i=0; i<numthing; i++) {
  300.                         /* filter out skill level 4 & 5 stuff */
  301.                         if(!(things[i].attrib & 0x3)) continue;
  302.  
  303.                         switch(things[i].type) {
  304.  
  305.                         /* monsters */
  306.                         case 7:        /* spider */
  307.                         case 9:        /* sergeant */
  308.                         case 16:       /* cyber */
  309.                         case 58:       /* invis */
  310.                         case 3001:     /* imp */
  311.                         case 3002:     /* demon */
  312.                         case 3003:     /* minotaur */
  313.                         case 3004:     /* human */
  314.                         case 3005:     /* cacodemon */
  315.                         case 3006:     /* skull */
  316.                                 if(mons) {
  317.                                         printf("%d %d %d m\n",
  318.                                                things[i].angle, things[i].x, things[i].y);
  319.                                 }
  320.                                 break;
  321.  
  322.                         /* weapons */
  323.                         case 2001:     /* Shotgun           */
  324.                                 printf("(Shotg) %d %d Text\n", things[i].x - 50, things[i].y);
  325.  
  326.                         case 2002:     /* Chaingun          */
  327.                                 printf("(ChainG) %d %d Text\n", things[i].x - 50, things[i].y);
  328.                                 break;
  329.  
  330.                         case 2003:     /* Rocket launcher   */
  331.                                 printf("(Rocket) %d %d Text\n", things[i].x - 50, things[i].y);
  332.                                 break;
  333.  
  334.                         case 2004:     /* Plasma gun        */
  335.                                 printf("(Plasma) %d %d Text\n", things[i].x - 50, things[i].y);
  336.                                 break;
  337.  
  338.                         case 2005:     /* Chainsaw          */
  339.                                 printf("(ChainS) %d %d Text\n", things[i].x - 50, things[i].y);
  340.                                 break;
  341.  
  342.                         case 2006:     /* BFG9000           */
  343.                                 printf("(BFG!) %d %d Text\n", things[i].x - 30, things[i].y);
  344.                                 break;
  345.  
  346.                         /* Ammo */
  347.                         case 8   :     /* Backpack          */
  348.                         case 17  :     /* Cell charge pack  */
  349.                         case 2007:     /* Ammo clip         */
  350.                         case 2008:     /* 4 shotgun shells  */
  351.                         case 2010:     /* 1 rocket          */
  352.                         case 2046:     /* Box of Rockets    */
  353.                         case 2047:     /* Cell charge       */
  354.                         case 2048:     /* Box of Ammo       */
  355.                         case 2049:     /* Box of Shells     */
  356.                                 if(objs) {
  357.                                         printf("%d %d a\n", things[i].x, things[i].y);
  358.                                 }
  359.  
  360.                         /* An other type of object */
  361.                         case 2011:     /* Stimpak           */
  362.                         case 2012:     /* Medikit           */
  363.                         case 2013:     /* Soulsphere        */
  364.                         case 2014:     /* Health bonus      */
  365.                         case 2015:     /* Armor bonus       */
  366.                         case 2018:     /* Green armor 100%  */
  367.                         case 2019:     /* Blue armor 200%   */
  368.                         case 2022:     /* Invulnerability   */
  369.                         case 2023:     /* Berserk Strength  */
  370.                         case 2024:     /* Invisibility      */
  371.                         case 2025:     /* Radiation suit    */
  372.                         case 2026:     /* Computer map      */
  373.                         case 2045:     /* Lite goggles      */
  374.                         default:
  375.                                 break;
  376.                         }
  377.                 }
  378.         }
  379.  
  380.         printf("/Times-Roman findfont %f scalefont setfont\n", 20 / xscale);
  381.  /*     printf("0 setgray %ld %ld moveto (%s) show\n", -xorigin, yorigin, lev_name); */
  382.         printf("0 setgray 0 %ld moveto (%s) show\n", yorigin, lev_name);
  383.  
  384.         puts("showpage");
  385.         return;
  386. }
  387.  
  388.  
  389. struct directory *open_wad(char *file, int *fd, long *size)
  390. {
  391.         struct wad_header h;
  392.         struct directory *d;
  393.  
  394.         _dos_open(file, O_RDONLY, fd);
  395.  
  396.         if(-1 == *fd) {
  397.                 perror(file);
  398.                 return (struct directory *)0;
  399.         }
  400.         _dos_read(*fd, &h, sizeof(h), &nread);
  401.  
  402.         if(NULL == (d = (struct directory *)farcalloc(h.dir_size, sizeof(*d)))) {
  403.                 fprintf(stderr, "Could not allocated %ld bytes.\n",
  404.                         h.dir_size * sizeof(*d));
  405.                 return (struct directory *) 0;
  406.         }
  407.         *size = h.dir_size;
  408.  
  409.         lseek(*fd, h.dir_off, SEEK_SET);
  410.         _dos_read(*fd, d, *size * sizeof(*d), &nread);
  411.  
  412.         return d;
  413. }
  414.  
  415. long get_index(struct directory *d, long size, char *name, long start)
  416. {
  417.         long i;
  418.  
  419.         for(i=start; i<size; i++) {
  420.                 if(_fstrncmp(d[i].name, name, 8) == 0)
  421.                         return i;
  422.         }
  423.  
  424.         return 0;
  425. }
  426.  
  427. linedef *read_linedefs(int fd, struct directory *d, long size, long start, long *num)
  428. {
  429.         long index;
  430.         linedef *indexp;
  431.         long i;
  432.  
  433.         index = get_index(d, size, "LINEDEFS", start);
  434.         if(!(indexp = (linedef *) farmalloc(d[index].length))) {
  435.                 printf("Could not allocate %ld bytes\n",d[index].length);
  436.                 exit(-1);
  437.         }
  438.         lseek(fd, d[index].start, SEEK_SET);
  439.         _dos_read(fd, indexp, d[index].length, &nread);
  440.         *num = d[index].length / sizeof(linedef);
  441.  
  442.         return indexp;
  443. }
  444.  
  445. vertex *read_vertexes(int fd, struct directory *d, long size, long start, long *num)
  446. {
  447.         long index;
  448.         vertex *indexp;
  449.         long i;
  450.  
  451.         index = get_index(d, size, "VERTEXES", start);
  452.         if(!(indexp = (vertex *) farmalloc(d[index].length))) {
  453.                 printf("Could not allocate %ld bytes\n",d[index].length);
  454.                 exit(-1);
  455.         }
  456.         lseek(fd, d[index].start, SEEK_SET);
  457.         _dos_read(fd, indexp, d[index].length, &nread);
  458.         *num = d[index].length / sizeof(vertex);
  459.  
  460.         return indexp;
  461. }
  462.  
  463. blockmap *read_blockmap(int fd, struct directory *d, long size, long start, long *num)
  464. {
  465.         long index;
  466.         blockmap *indexp;
  467.         long i;
  468.  
  469.         index = get_index(d, size, "BLOCKMAP", start);
  470.         if(!(indexp = (blockmap *) farmalloc(d[index].length))) {
  471.                 printf("Could not allocate %ld bytes\n",d[index].length);
  472.                 exit(-1);
  473.         }
  474.         lseek(fd, d[index].start, SEEK_SET);
  475.         _dos_read(fd, indexp, d[index].length, &nread);
  476.         *num = d[index].length / sizeof(blockmap);
  477.  
  478.         return indexp;
  479. }
  480.  
  481. sidedef *read_sidedefs(int fd, struct directory *d, long size, long start, long *num)
  482. {
  483.         long index;
  484.         sidedef *indexp;
  485.         long i;
  486.  
  487.         index = get_index(d, size, "SIDEDEFS", start);
  488.         if(!(indexp = (sidedef *) farmalloc(d[index].length))) {
  489.                 printf("Could not allocate %ld bytes\n",d[index].length);
  490.                 exit(-1);
  491.         }
  492.         lseek(fd, d[index].start, SEEK_SET);
  493.         _dos_read(fd, indexp, d[index].length, &nread);
  494.         *num = d[index].length / sizeof(sidedef);
  495.  
  496.         return indexp;
  497. }
  498.  
  499. sector *read_sectors(int fd, struct directory *d, long size, long start, long *num)
  500. {
  501.         long index;
  502.         sector *indexp;
  503.         long i;
  504.  
  505.         index = get_index(d, size, "SECTORS", start);
  506.         if(!(indexp = (sector *) farmalloc(d[index].length))) {
  507.                 printf("Could not allocate %ld bytes\n",d[index].length);
  508.                 exit(-1);
  509.         }
  510.         lseek(fd, d[index].start, SEEK_SET);
  511.         _dos_read(fd, indexp, d[index].length, &nread);
  512.         *num = d[index].length / sizeof(sector);
  513.  
  514.         return indexp;
  515. }
  516.  
  517. thing *read_things(int fd, struct directory *d, long size, long start, long *num)
  518. {
  519.         long index;
  520.         thing *indexp;
  521.         long i;
  522.  
  523.         index = get_index(d, size, "THINGS", start);
  524.         if(!(indexp = (thing *) farmalloc(d[index].length))) {
  525.                 printf("Could not allocate %ld bytes\n",d[index].length);
  526.                 exit(-1);
  527.         }
  528.         lseek(fd, d[index].start, SEEK_SET);
  529.         _dos_read(fd, indexp, d[index].length, &nread);
  530.         *num = d[index].length / sizeof(thing);
  531.  
  532.         return indexp;
  533. }
  534.  
  535.