home *** CD-ROM | disk | FTP | other *** search
- /*
- Doom PostScript map generator. V1.1
- Copyright James Bonfield, 3/3/94
- Modified for PC by Gerhard Karnik 3/29/94
-
- Description
- -----------
-
- This program produces PostScript maps of Doom levels, extracted from the Wad
- file. The program is written for the UNIX operating system, and so you need a
- method of transfering your doom.wad file, (or perhaps having it visible by,
- say, mounting your DOS partition).
-
- Thick lines represent solid walls on the map.
- Circles represent objects.
- Arrows represent the enemy. The direction of the arrow is the direction the
- creature is facing.
- Gray lines represent secret passages.
-
-
- Command line options
-
- -d enables debugging
- -w wadfile selects another wad file (default is "doom.wad")
- -l level choose another level (default is "E1M1")
- -o do not display objects
- -m do not display monsters
-
- The postscript will then be displayed to stdout.
-
- Compiled using Borland C++ 3.1 using 'bcc -mh'
-
- */
-
- #include <io.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <errno.h>
- #include <string.h>
- #include <share.h>
- #include <fcntl.h>
- #include <dos.h>
- #include <alloc.h>
-
- unsigned nread; /* throw away variable for _dos_read() */
-
- typedef long int4;
- typedef short int2;
-
- struct wad_header {
- int4 magic;
- int4 dir_size;
- int4 dir_off;
- };
-
- struct directory {
- int4 start;
- int4 length;
- char name[8];
- };
-
- typedef struct linedef_ {
- int2 from_vertex;
- int2 to_vertex;
- int2 attrib;
- int2 type;
- int2 trigger;
- int2 sidedef1;
- int2 sidedef2;
- } linedef;
-
- /* linedef attrib bits */
- #define LI_IMPASS 0x01
- #define LI_SECRET 0x20
-
- typedef struct vertex_ {
- int2 x;
- int2 y;
- } vertex;
-
- typedef struct sidedef_ {
- int2 x;
- int2 y;
- char wall_above[8];
- char wall_below[8];
- char wall_part[8];
- int2 sector;
- } sidedef;
-
- typedef struct ssector_ {
- int2 num;
- int2 seg;
- } ssector;
-
- typedef struct sector_ {
- int2 bot_pos;
- int2 top_pos;
- char bot_texture[8];
- char top_texture[8];
- int2 brightness;
- int2 special;
- int2 trigger;
- } sector;
-
- typedef struct thing_ {
- int2 x;
- int2 y;
- int2 angle;
- int2 type;
- int2 attrib;
- } thing;
-
- /* thing 'type' bits */
- #define TH_SKILL1 0x01
- #define TH_SKILL2 0x01
- #define TH_SKILL3 0x02
- #define TH_SKILL4 0x04
- #define TH_MULTI 0x10
-
- typedef int2 blockmap;
-
- struct directory *open_wad(char *file, int *fd, long *size);
- long get_index(struct directory *d, long size, char *name, long st);
- linedef *read_linedefs(int fd, struct directory *d, long size, long start, long *num);
- vertex *read_vertexes(int fd, struct directory *d, long size, long start, long *num);
- blockmap *read_blockmap(int fd, struct directory *d, long size, long start, long *num);
- sidedef *read_sidedefs(int fd, struct directory *d, long size, long start, long *num);
- sector *read_sectors(int fd, struct directory *d, long size, long start, long *num);
- thing *read_things(int fd, struct directory *d, long size, long start, long *num);
-
- /*
- * Paper is 8 1/2" by 11"
- * We allow 1/2" border.
- */
- #define PAPER_X (72 * 8.5)
- #define PAPER_Y (72 * 11)
- #define PAPER_BORDER (72 * 0.5)
-
- void doit(int fd, struct directory *dir, long size, char *lev_name,
- long objs, long mons);
-
-
- void dump_dir(struct directory *d, long size)
- {
- int i;
-
- for(i=0; i<size; i++) {
- printf("Item=%5d, Start=%8ld, Len=%8ld, Name=%.8s\n",
- i, d[i].start, d[i].length, d[i].name);
- }
- }
-
-
- int main(int argc, char **argv)
- {
- struct directory *d;
- int fd;
- long size, c;
- long objs = 1, mons = 1, dump = 0;
- char *level = "E1M1";
- char *wadfile = "doom.wad";
- int i;
-
- for(i=1; i<=argc; i++) {
- if(!strcmpi(argv[i], "-W")) wadfile = argv[(i++)+1];
- if(!strcmpi(argv[i], "-D")) dump = 1;
- if(!strcmpi(argv[i], "-L")) level = argv[(i++)+1];
- if(!strcmpi(argv[i], "-O")) objs = 0;
- if(!strcmpi(argv[i], "-M")) mons = 0;
- }
-
- if(NULL == (d = open_wad(wadfile, &fd, &size))) {
- fprintf(stderr, "Failed to open wad file.\n");
- return 1;
- }
- if(dump) {
- dump_dir(d, size);
- return 0;
- }
- doit(fd, d, size, level, objs, mons);
-
- return 0;
- }
-
- void doit(int fd, struct directory *dir, long size, char *lev_name,
- long objs, long mons)
- {
- linedef *linedefs;
- vertex *vertexes;
- blockmap *blocks;
- sidedef *sidedefs;
- sector *sectors;
- thing *things;
- long numline, numvert, numblock, numside, numsect, numthing;
- long lev_index;
- long xorigin, yorigin, xsize, ysize;
- int2 sector;
- double xscale, yscale;
- long i, j;
-
- /* find level index */
- lev_index = get_index(dir, size, lev_name, 0);
- if(lev_index == 0) {
- fprintf(stderr, "Unknown level: %s\n", lev_name);
- exit(1);
- }
-
- /* load relevent arrays for this level */
-
- linedefs = read_linedefs(fd, dir, size, lev_index, &numline);
- vertexes = read_vertexes(fd, dir, size, lev_index, &numvert);
- blocks = read_blockmap(fd, dir, size, lev_index, &numblock);
- sidedefs = read_sidedefs(fd, dir, size, lev_index, &numside);
- sectors = read_sectors(fd, dir, size, lev_index, &numsect);
- things = read_things(fd, dir, size, lev_index, &numthing);
-
- /* calculate scaling info */
- xorigin = blocks[0];
- yorigin = blocks[1];
- xsize = blocks[2] * 0x80;
- ysize = blocks[3] * 0x80;
-
- xscale = (double) (PAPER_Y - 2 * PAPER_BORDER) / xsize;
- yscale = (double) (PAPER_X - 2 * PAPER_BORDER) / ysize;
-
- if (xscale > yscale)
- xscale = yscale;
- else
- yscale = xscale;
-
- /* output postscript header */
- printf("%%!\n");
- printf("newpath\n");
- printf("\n");
- printf("1 setlinecap\n");
- printf("%f %f translate\n", PAPER_BORDER, PAPER_Y - PAPER_BORDER);
- printf("-90 rotate\n");
- printf("%f %f scale\n", xscale, yscale);
- printf("%ld %ld translate\n", -xorigin, -yorigin);
- printf("%f setlinewidth\n", (double) .5 / xscale);
- printf("\n");
- printf("/Times-Roman findfont %f scalefont setfont\n", 5 / xscale);
- printf("/Text {\n");
- printf(" gsave\n");
- printf(" 0 setgray moveto show\n");
- printf(" grestore\n");
- printf("} def\n");
- printf("\n");
- printf("/l {\n");
- printf(" setgray setlinewidth moveto lineto stroke\n");
- printf("} def\n");
- printf("\n");
- printf("/a {\n");
- printf(" 0.5 setgray\n");
- printf(" 5 0 360 arc stroke\n");
- printf("} def\n");
- printf("\n");
- printf("/m {\n");
- printf(" gsave\n");
- printf(" 0 setgray\n");
- printf(" 1 setlinewidth\n");
- printf(" moveto rotate\n");
- printf(" 0 -13 rmoveto\n");
- printf(" 0 25 rlineto\n");
- printf(" -10 -10 rlineto\n");
- printf(" 10 10 rmoveto\n");
- printf(" 10 -10 rlineto\n");
- printf(" stroke\n");
- printf(" grestore\n");
- printf("} def\n");
-
- /* Display the walls. Secret passages are done in grey. */
- for (i = 0; i < numline; i++) {
- sector = sidedefs[linedefs[i].sidedef1].sector;
-
- printf("%d %d %d %d ",
- vertexes[linedefs[i].to_vertex].x,
- vertexes[linedefs[i].to_vertex].y,
- vertexes[linedefs[i].from_vertex].x,
- vertexes[linedefs[i].from_vertex].y);
-
- if (linedefs[i].attrib & LI_IMPASS) {
- printf("%f ", 1.2 / xscale);
- } else {
- printf("%f ", 0.5 / xscale);
- }
-
- if (linedefs[i].attrib & LI_SECRET || sectors[sector].special == 9) {
- printf(".5 l\n");
- } else {
- printf("0 l\n");
- }
- }
-
- /* Do we need to display objects or monsters? */
- if(objs || mons) {
- printf(" %f setlinewidth\n", 1 / xscale);
-
- for(i=0; i<numthing; i++) {
- /* filter out skill level 4 & 5 stuff */
- if(!(things[i].attrib & 0x3)) continue;
-
- switch(things[i].type) {
-
- /* monsters */
- case 7: /* spider */
- case 9: /* sergeant */
- case 16: /* cyber */
- case 58: /* invis */
- case 3001: /* imp */
- case 3002: /* demon */
- case 3003: /* minotaur */
- case 3004: /* human */
- case 3005: /* cacodemon */
- case 3006: /* skull */
- if(mons) {
- printf("%d %d %d m\n",
- things[i].angle, things[i].x, things[i].y);
- }
- break;
-
- /* weapons */
- case 2001: /* Shotgun */
- printf("(Shotg) %d %d Text\n", things[i].x - 50, things[i].y);
-
- case 2002: /* Chaingun */
- printf("(ChainG) %d %d Text\n", things[i].x - 50, things[i].y);
- break;
-
- case 2003: /* Rocket launcher */
- printf("(Rocket) %d %d Text\n", things[i].x - 50, things[i].y);
- break;
-
- case 2004: /* Plasma gun */
- printf("(Plasma) %d %d Text\n", things[i].x - 50, things[i].y);
- break;
-
- case 2005: /* Chainsaw */
- printf("(ChainS) %d %d Text\n", things[i].x - 50, things[i].y);
- break;
-
- case 2006: /* BFG9000 */
- printf("(BFG!) %d %d Text\n", things[i].x - 30, things[i].y);
- break;
-
- /* Ammo */
- case 8 : /* Backpack */
- case 17 : /* Cell charge pack */
- case 2007: /* Ammo clip */
- case 2008: /* 4 shotgun shells */
- case 2010: /* 1 rocket */
- case 2046: /* Box of Rockets */
- case 2047: /* Cell charge */
- case 2048: /* Box of Ammo */
- case 2049: /* Box of Shells */
- if(objs) {
- printf("%d %d a\n", things[i].x, things[i].y);
- }
-
- /* An other type of object */
- case 2011: /* Stimpak */
- case 2012: /* Medikit */
- case 2013: /* Soulsphere */
- case 2014: /* Health bonus */
- case 2015: /* Armor bonus */
- case 2018: /* Green armor 100% */
- case 2019: /* Blue armor 200% */
- case 2022: /* Invulnerability */
- case 2023: /* Berserk Strength */
- case 2024: /* Invisibility */
- case 2025: /* Radiation suit */
- case 2026: /* Computer map */
- case 2045: /* Lite goggles */
- default:
- break;
- }
- }
- }
-
- printf("/Times-Roman findfont %f scalefont setfont\n", 20 / xscale);
- /* printf("0 setgray %ld %ld moveto (%s) show\n", -xorigin, yorigin, lev_name); */
- printf("0 setgray 0 %ld moveto (%s) show\n", yorigin, lev_name);
-
- puts("showpage");
- return;
- }
-
-
- struct directory *open_wad(char *file, int *fd, long *size)
- {
- struct wad_header h;
- struct directory *d;
-
- _dos_open(file, O_RDONLY, fd);
-
- if(-1 == *fd) {
- perror(file);
- return (struct directory *)0;
- }
- _dos_read(*fd, &h, sizeof(h), &nread);
-
- if(NULL == (d = (struct directory *)farcalloc(h.dir_size, sizeof(*d)))) {
- fprintf(stderr, "Could not allocated %ld bytes.\n",
- h.dir_size * sizeof(*d));
- return (struct directory *) 0;
- }
- *size = h.dir_size;
-
- lseek(*fd, h.dir_off, SEEK_SET);
- _dos_read(*fd, d, *size * sizeof(*d), &nread);
-
- return d;
- }
-
- long get_index(struct directory *d, long size, char *name, long start)
- {
- long i;
-
- for(i=start; i<size; i++) {
- if(_fstrncmp(d[i].name, name, 8) == 0)
- return i;
- }
-
- return 0;
- }
-
- linedef *read_linedefs(int fd, struct directory *d, long size, long start, long *num)
- {
- long index;
- linedef *indexp;
- long i;
-
- index = get_index(d, size, "LINEDEFS", start);
- if(!(indexp = (linedef *) farmalloc(d[index].length))) {
- printf("Could not allocate %ld bytes\n",d[index].length);
- exit(-1);
- }
- lseek(fd, d[index].start, SEEK_SET);
- _dos_read(fd, indexp, d[index].length, &nread);
- *num = d[index].length / sizeof(linedef);
-
- return indexp;
- }
-
- vertex *read_vertexes(int fd, struct directory *d, long size, long start, long *num)
- {
- long index;
- vertex *indexp;
- long i;
-
- index = get_index(d, size, "VERTEXES", start);
- if(!(indexp = (vertex *) farmalloc(d[index].length))) {
- printf("Could not allocate %ld bytes\n",d[index].length);
- exit(-1);
- }
- lseek(fd, d[index].start, SEEK_SET);
- _dos_read(fd, indexp, d[index].length, &nread);
- *num = d[index].length / sizeof(vertex);
-
- return indexp;
- }
-
- blockmap *read_blockmap(int fd, struct directory *d, long size, long start, long *num)
- {
- long index;
- blockmap *indexp;
- long i;
-
- index = get_index(d, size, "BLOCKMAP", start);
- if(!(indexp = (blockmap *) farmalloc(d[index].length))) {
- printf("Could not allocate %ld bytes\n",d[index].length);
- exit(-1);
- }
- lseek(fd, d[index].start, SEEK_SET);
- _dos_read(fd, indexp, d[index].length, &nread);
- *num = d[index].length / sizeof(blockmap);
-
- return indexp;
- }
-
- sidedef *read_sidedefs(int fd, struct directory *d, long size, long start, long *num)
- {
- long index;
- sidedef *indexp;
- long i;
-
- index = get_index(d, size, "SIDEDEFS", start);
- if(!(indexp = (sidedef *) farmalloc(d[index].length))) {
- printf("Could not allocate %ld bytes\n",d[index].length);
- exit(-1);
- }
- lseek(fd, d[index].start, SEEK_SET);
- _dos_read(fd, indexp, d[index].length, &nread);
- *num = d[index].length / sizeof(sidedef);
-
- return indexp;
- }
-
- sector *read_sectors(int fd, struct directory *d, long size, long start, long *num)
- {
- long index;
- sector *indexp;
- long i;
-
- index = get_index(d, size, "SECTORS", start);
- if(!(indexp = (sector *) farmalloc(d[index].length))) {
- printf("Could not allocate %ld bytes\n",d[index].length);
- exit(-1);
- }
- lseek(fd, d[index].start, SEEK_SET);
- _dos_read(fd, indexp, d[index].length, &nread);
- *num = d[index].length / sizeof(sector);
-
- return indexp;
- }
-
- thing *read_things(int fd, struct directory *d, long size, long start, long *num)
- {
- long index;
- thing *indexp;
- long i;
-
- index = get_index(d, size, "THINGS", start);
- if(!(indexp = (thing *) farmalloc(d[index].length))) {
- printf("Could not allocate %ld bytes\n",d[index].length);
- exit(-1);
- }
- lseek(fd, d[index].start, SEEK_SET);
- _dos_read(fd, indexp, d[index].length, &nread);
- *num = d[index].length / sizeof(thing);
-
- return indexp;
- }
-
-