summaryrefslogtreecommitdiff
path: root/wad.c
diff options
context:
space:
mode:
Diffstat (limited to 'wad.c')
-rw-r--r--wad.c1144
1 files changed, 1144 insertions, 0 deletions
diff --git a/wad.c b/wad.c
new file mode 100644
index 0000000..fbd89e2
--- /dev/null
+++ b/wad.c
@@ -0,0 +1,1144 @@
+/*
+
+ viDOOM - level editor for DOOM
+
+ Copyright (C) 2000 Ian Cowburn (ianc@noddybox.demon.co.uk)
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ -------------------------------------------------------------------------
+
+ WAD file definitions and readers
+
+*/
+static const char rcs_id[]="$Id$";
+
+#include "config.h"
+#include "globals.h"
+
+#include <stdio.h>
+#include <string.h>
+
+#include "wad.h"
+#include "gfx.h"
+#include "mem.h"
+#include "file.h"
+#include "util.h"
+
+/* ---------------------------------------- TYPES
+*/
+
+typedef struct WadEnt
+ {
+ DirName name;
+ Long off;
+ Long size;
+ } WadEnt;
+
+typedef struct WadDirTable
+ {
+ int no;
+ WadEnt *ent;
+ } WadDirTable;
+
+typedef struct WadFile
+ {
+ FILE *fp;
+ char path[PATH_MAX+1];
+ } WadFile;
+
+
+/* ---------------------------------------- VARS
+*/
+
+#define NO_MAP_LUMPS 7
+
+#define NOT_MAP_LUMP -2
+#define IGNORE_LUMP -1
+#define THING_LUMP 0
+#define VERTEX_LUMP 1
+#define LINEDEF_LUMP 2
+#define SIDEDEF_LUMP 3
+#define SECTOR_LUMP 4
+#define BEHAVIOR_LUMP 5
+#define SCRIPTS_LUMP 6
+
+
+#define ERR(e,r) do {wad_err=e;return(r);} while(0)
+static const char *wad_errstr[WAD_NOERROR]=
+ {
+ "no error",
+ "File not found",
+ "File not an IWAD or PWAD",
+ "File not an IWAD",
+ "File not a PWAD",
+ "Map not found",
+ "Lump not found",
+ "Could not create file",
+ "Could not create MAPINFO.WAD",
+ "MAP mangled - spread over more than one file",
+ __FILE__ " - ??? BROKEN ???",
+ };
+
+static int wad_err=WAD_OK;
+
+static List waddir=NULL;
+static List wadlist=NULL;
+
+
+/* ---------------------------------------- MACROS
+*/
+#define ERR(e,r) do {wad_err=e;return(r);} while(0)
+
+
+/* ---------------------------------------- PREDICATE FUNCTIONS
+*/
+static int FindDirEnt(void *a,void *b)
+{
+ WadDir *aa;
+
+ aa=(WadDir *)a;
+
+ return(STREQ(aa->name,b));
+}
+
+
+static int FindWAD(void *a,void *b)
+{
+ WadFile *aa;
+
+ aa=a;
+
+ return(FilenamesEqual(aa->path,b));
+}
+
+
+/* ---------------------------------------- PRIVATE FUNCTIONS
+*/
+static char *GetName(FILE *fp)
+{
+ static DirName d;
+
+ FRead(fp,d,8);
+ d[sizeof(d)-1]=0;
+ return(d);
+}
+
+
+static void PutName(FILE *fp,char *p)
+{
+ int f;
+
+ f=0;
+ while(f<8)
+ {
+ fputc(*p,fp);
+
+ if (*p)
+ p++;
+
+ f++;
+ }
+}
+
+
+static void PutDirEnt(FILE *fp,Long off,Long size,char *p)
+{
+ PutLong(fp,off);
+ PutLong(fp,size);
+ PutName(fp,p);
+}
+
+
+static int HandledMapLump(char *n)
+{
+ static struct
+ {
+ char *name;
+ int lump;
+ } lump[]= {
+ {"THINGS",THING_LUMP},
+ {"VERTEXES",VERTEX_LUMP},
+ {"SIDEDEFS",SIDEDEF_LUMP},
+ {"LINEDEFS",LINEDEF_LUMP},
+ {"SECTORS",SECTOR_LUMP},
+ {"BEHAVIOR",BEHAVIOR_LUMP},
+ {"SCRIPTS",SCRIPTS_LUMP},
+ {"SEGS",IGNORE_LUMP},
+ {"SSECTORS",IGNORE_LUMP},
+ {"NODES",IGNORE_LUMP},
+ {"REJECT",IGNORE_LUMP},
+ {"BLOCKMAP",IGNORE_LUMP},
+ {NULL,NOT_MAP_LUMP},
+ };
+
+ int f;
+
+ f=0;
+ while(lump[f].name)
+ {
+ if (STREQ(lump[f].name,n))
+ return(lump[f].lump);
+
+ f++;
+ }
+
+ return(NOT_MAP_LUMP);
+}
+
+
+static void GetMapLumps(Iterator i, WadDir *l[])
+{
+ WadDir *dir;
+ int lc;
+ int f;
+
+ for(f=0;f<NO_MAP_LUMPS;f++)
+ l[f]=NULL;
+
+ /* Skip map entry
+ */
+ i=IteratorNext(i);
+
+ while(i)
+ {
+ dir=IteratorData(i);
+
+ lc=HandledMapLump(dir->name);
+
+ switch(lc)
+ {
+ case IGNORE_LUMP:
+ break;
+
+ case NOT_MAP_LUMP:
+ i=IteratorClear(i);
+ break;
+
+ default:
+ l[lc]=dir;
+ break;
+ }
+
+ if (i)
+ i=IteratorNext(i);
+ }
+}
+
+
+static WadDir *GetDir(char *name)
+{
+ Iterator i;
+ WadDir *w;
+
+ if (!(i=ListFindElem(waddir,FindDirEnt,name)))
+ return(NULL);
+
+ w=IteratorData(i);
+ IteratorClear(i);
+
+ return(w);
+}
+
+
+static WadFile *GetWADFile(char *name)
+{
+ Iterator i;
+ WadFile *w;
+
+ if (!(i=ListFindElem(wadlist,FindWAD,name)))
+ return(NULL);
+
+ w=IteratorData(i);
+ IteratorClear(i);
+
+ return(w);
+}
+
+
+static void *LoadDirEnt(WadDir *d,Long *size)
+{
+ void *ret;
+ WadFile *wf;
+
+ if (!(wf=GetWADFile(d->wad)))
+ return(NULL);
+
+ ret=Grab(d->size);
+ fseek(wf->fp,(long)d->off,SEEK_SET);
+ FRead(wf->fp,ret,d->size);
+
+ if (size)
+ *size=d->size;
+
+ return(ret);
+}
+
+
+static WadDirTable *ReadDir(char *wad, char *expect)
+{
+ char type[4];
+ WadDirTable *d;
+ int f;
+ FILE *fp;
+
+ if (!(fp=fopen(wad,"rb")))
+ ERR(WAD_FILE_NOT_FOUND,NULL);
+
+ FRead(fp,type,4);
+
+ if (STRNEQ("IWAD",expect)&&(!STRNEQ("IWAD",type)))
+ {
+ fclose(fp);
+ ERR(WAD_NOT_IWAD,NULL);
+ }
+ else if (STRNEQ("PWAD",expect)&&(!STRNEQ("PWAD",type)))
+ {
+ ERR(WAD_NOT_PWAD,NULL);
+ fclose(fp);
+ }
+
+ d=Grab(sizeof(WadDirTable));
+ d->no=GetLong(fp);
+
+ d->ent=Grab(sizeof(WadEnt)*d->no);
+
+ fseek(fp,(long)GetLong(fp),SEEK_SET);
+
+ for(f=0;f<d->no;f++)
+ {
+ d->ent[f].off=GetLong(fp);
+ d->ent[f].size=GetLong(fp);
+ strcpy(d->ent[f].name,GetName(fp));
+ }
+
+ fclose(fp);
+ return(d);
+}
+
+
+static int AddWAD(char *wad,char *type)
+{
+ Iterator i;
+ WadDirTable *d;
+ WadDir w;
+ int f;
+ char *wadname;
+ WadFile wf;
+ int check;
+ int e2m1;
+ int map01;
+
+ /* Read in the directory from the WAD
+ */
+ if (!waddir)
+ {
+ waddir=ListNew(sizeof(WadDir));
+ wadlist=ListNew(sizeof(WadFile));
+ }
+
+ if (!(d=ReadDir(wad,type)))
+ return(wad_err);
+
+ /* Find the WAD name in the WAD list
+ */
+ if ((i=ListFindElem(wadlist,FindWAD,wad)))
+ {
+ wadname=((WadFile *)IteratorData(i))->path;
+ IteratorClear(i);
+ }
+ else
+ {
+ if (!(wf.fp=fopen(wad,"rb")))
+ GFX_exit(EXIT_FAILURE,"BIZARRE: WAD opening failed after "
+ "first open succeeded on\n\t%s\n",wad);
+
+ strcpy(wf.path,wad);
+ wadname=Strdup(wf.path);
+ ListInsert(wadlist,&wf);
+ }
+
+ /* Add the directory entries to the global dir
+ */
+ e2m1=FALSE;
+ map01=FALSE;
+ check=STRNEQ("IWAD",type);
+
+ for(f=d->no-1;f>=0;f--)
+ {
+ w.wad=wadname;
+ w.off=d->ent[f].off;
+ w.size=d->ent[f].size;
+ strcpy(w.name,d->ent[f].name);
+
+ if (check)
+ {
+ if (STREQ("E2M1",d->ent[f].name))
+ e2m1=TRUE;
+
+ if (STREQ("MAP01",d->ent[f].name))
+ map01=TRUE;
+ }
+
+ ListInsert(waddir,&w);
+ }
+
+ /* Shareware checks fo IWAD files
+ */
+ if (check)
+ switch(level_style)
+ {
+ case DOOM_LEVELS:
+ case ULTIMATE_DOOM_LEVELS:
+ if (e2m1)
+ break;
+ case DOOM_2_LEVELS:
+ if (map01)
+ break;
+ default:
+ GFX_exit(EXIT_FAILURE,
+ "You MUST have an IWAD from the registered "
+ "version of\nDOOM, ULTIMATE DOOM, DOOM II "
+ "or FINAL DOOM\n");
+ break;
+ }
+
+ Release(d->ent);
+ Release(d);
+
+ ERR(WAD_OK,WAD_OK);
+}
+
+
+/* ---------------------------------------- MAPINFO FUNCTIONS
+*/
+static char *LoadMAPINFO(void)
+{
+ char path[PATH_MAX+1];
+ char *lump;
+ Long size;
+
+ strcpy(path,PWAD_dir);
+ strcat(path,"mapinfo.wad");
+
+ if (AddPWAD(path)!=WAD_OK)
+ return(NULL);
+
+ lump=GetLump("MAPINFO",&size);
+ CloseWad(path);
+
+ if (lump)
+ {
+ lump=ReGrab(lump,size+1);
+ lump[size]=0;
+ }
+
+ return(lump);
+}
+
+
+int SaveMAPINFO(char *info)
+{
+ char path[PATH_MAX+1];
+ FILE *fp;
+ Long off;
+
+ strcpy(path,PWAD_dir);
+ strcat(path,"mapinfo.wad");
+
+ if (!(fp=fopen(path,"wb")))
+ return(FALSE);
+
+ off=strlen(info)+12;
+
+ /* Put PWAD header
+ */
+ fputs("PWAD",fp);
+ PutLong(fp,1);
+ PutLong(fp,off);
+
+ /* Put MAPINFO
+ */
+ fputs(info,fp);
+
+ /* Create directory
+ */
+ PutDirEnt(fp,12,strlen(info),"MAPINFO");
+ fclose(fp);
+
+ return(TRUE);
+}
+
+
+/* ---------------------------------------- EXPORTED FUNCTIONS
+*/
+
+int AddIWAD(char *wad)
+{
+ return (AddWAD(wad,"IWAD"));
+}
+
+
+int AddPWAD(char *wad)
+{
+ return (AddWAD(wad,"PWAD"));
+}
+
+
+int CloseWad(char *wad)
+{
+ WadDir *w;
+ WadFile *wf;
+ Iterator i;
+ char *p=NULL;
+
+ if (!(i=ListFindElem(wadlist,FindWAD,wad)))
+ ERR(WAD_FILE_NOT_FOUND,WAD_FILE_NOT_FOUND);
+
+ wf=IteratorData(i);
+
+ if (wf->fp)
+ fclose(wf->fp);
+
+ i=IteratorDelete(i);
+ IteratorClear(i);
+
+ i=ListIterator(waddir);
+
+ while(i)
+ {
+ w=IteratorData(i);
+
+ if (FilenamesEqual(w->wad,wad))
+ {
+ p=w->wad;
+ i=IteratorDelete(i);
+ }
+ else
+ i=IteratorNext(i);
+ }
+
+ if (p)
+ Release(p);
+
+ IteratorClear(i);
+
+ ERR(WAD_OK,WAD_OK);
+}
+
+
+char *OpenWads(void)
+{
+ Iterator i;
+ WadFile *w;
+ char *ret;
+
+ if (!(i=ListIterator(wadlist)))
+ ret=Strdup("");
+ else
+ {
+ w=IteratorData(i);
+ ret=Grab(PATH_MAX+1);
+ strcpy(ret,w->path);
+ i=IteratorNext(i);
+
+ while(i)
+ {
+ strcat(ret,"|");
+ w=IteratorData(i);
+ ret=ReGrab(ret,strlen(ret)+PATH_MAX+1);
+ strcat(ret,w->path);
+ i=IteratorNext(i);
+ }
+ }
+
+ return(ret);
+}
+
+
+Iterator GetWadDir(void)
+{
+ return(ListIterator(waddir));
+}
+
+
+int GetWadDirSize(void)
+{
+ return(ListSize(waddir));
+}
+
+
+void *GetLump(char *name, Long *size)
+{
+ WadDir *d;
+ void *ret;
+
+ if (size)
+ *size=0;
+
+ if (!(d=GetDir(name)))
+ ERR(WAD_LUMP_NOT_FOUND,NULL);
+
+ if ((ret=LoadDirEnt(d,size)))
+ ERR(WAD_OK,ret);
+ else
+ ERR(WAD_FILE_NOT_FOUND,NULL);
+}
+
+
+void *GetLumpFrom(WadDir *d, Long *size)
+{
+ void *ret;
+
+ if (size)
+ *size=0;
+
+ if ((ret=LoadDirEnt(d,size)))
+ ERR(WAD_OK,ret);
+ else
+ ERR(WAD_FILE_NOT_FOUND,NULL);
+}
+
+
+WadMap *LoadMap(char *name)
+{
+ Iterator i;
+ WadMap *map;
+ WadDir *dir;
+ WadFile *wf;
+ Thing thing;
+ Vertex vertex;
+ Sidedef sidedef;
+ Linedef linedef;
+ Sector sector;
+ int f;
+ int lc;
+ WadDir *lump[NO_MAP_LUMPS];
+
+ if (!(i=ListFindElem(waddir,FindDirEnt,name)))
+ ERR(WAD_MAP_NOT_FOUND,NULL);
+
+ dir=IteratorData(i);
+
+ if (!(wf=GetWADFile(dir->wad)))
+ ERR(WAD_FILE_NOT_FOUND,NULL);
+
+ GetMapLumps(i,lump);
+
+ /* Check for a mangled map
+ */
+ for(f=0;f<NO_MAP_LUMPS;f++)
+ if ((lump[f])&&(!FilenamesEqual(wf->path,lump[f]->wad)))
+ ERR(WAD_MAP_MANGLED,NULL);
+
+ map=Grab(sizeof(WadMap));
+ map->thing=MapNew(sizeof(Thing));
+ map->vertex=MapNew(sizeof(Vertex));
+ map->sidedef=MapNew(sizeof(Sidedef));
+ map->linedef=MapNew(sizeof(Linedef));
+ map->sector=MapNew(sizeof(Sector));
+
+ map->scripts=NULL;
+ map->behavior=NULL;
+ map->mapinfo=NULL;
+
+ if (lump[BEHAVIOR_LUMP])
+ map->hexen=TRUE;
+ else
+ map->hexen=FALSE;
+
+ for(lc=0;lc<NO_MAP_LUMPS;lc++)
+ {
+ dir=lump[lc];
+
+ if (dir)
+ switch (lc)
+ {
+ case THING_LUMP:
+ fseek(wf->fp,(long)dir->off,SEEK_SET);
+
+ if (map->hexen)
+ for(f=0;f<dir->size/THING_SIZE_HEXEN;f++)
+ {
+ int a;
+
+ thing.id=GetUShort(wf->fp);
+ thing.x=GetShort(wf->fp);
+ thing.y=GetShort(wf->fp);
+ thing.z=GetShort(wf->fp);
+ thing.ang=GetShort(wf->fp);
+ thing.type=GetShort(wf->fp);
+ thing.flags=GetShort(wf->fp);
+ thing.special=GetByte(wf->fp);
+
+ for(a=0;a<5;a++)
+ thing.args[a]=GetByte(wf->fp);
+
+ MapAdd(map->thing,f,&thing);
+ }
+ else
+ for(f=0;f<dir->size/THING_SIZE;f++)
+ {
+ thing.x=GetShort(wf->fp);
+ thing.y=GetShort(wf->fp);
+ thing.ang=GetShort(wf->fp);
+ thing.type=GetShort(wf->fp);
+ thing.flags=GetShort(wf->fp);
+
+ MapAdd(map->thing,f,&thing);
+ }
+ break;
+
+ case VERTEX_LUMP:
+ fseek(wf->fp,(long)dir->off,SEEK_SET);
+
+ for(f=0;f<dir->size/VERTEX_SIZE;f++)
+ {
+ vertex.x=GetShort(wf->fp);
+ vertex.y=GetShort(wf->fp);
+ MapAdd(map->vertex,f,&vertex);
+ }
+ break;
+
+ case SIDEDEF_LUMP:
+ fseek(wf->fp,(long)dir->off,SEEK_SET);
+
+ for(f=0;f<dir->size/SIDEDEF_SIZE;f++)
+ {
+ sidedef.x=GetShort(wf->fp);
+ sidedef.y=GetShort(wf->fp);
+ strcpy(sidedef.upper,GetName(wf->fp));
+ strcpy(sidedef.lower,GetName(wf->fp));
+ strcpy(sidedef.middle,GetName(wf->fp));
+ sidedef.sector=GetShort(wf->fp);
+ MapAdd(map->sidedef,f,&sidedef);
+ }
+ break;
+
+ case LINEDEF_LUMP:
+ fseek(wf->fp,(long)dir->off,SEEK_SET);
+
+ if (map->hexen)
+ for(f=0;f<dir->size/LINEDEF_SIZE_HEXEN;f++)
+ {
+ int a;
+
+ linedef.from=GetShort(wf->fp);
+ linedef.to=GetShort(wf->fp);
+ linedef.flags=GetShort(wf->fp);
+ linedef.type=GetByte(wf->fp);
+
+ for(a=0;a<5;a++)
+ linedef.args[a]=GetByte(wf->fp);
+
+ linedef.right=GetShort(wf->fp);
+ linedef.left=GetShort(wf->fp);
+ MapAdd(map->linedef,f,&linedef);
+ }
+ else
+ for(f=0;f<dir->size/LINEDEF_SIZE;f++)
+ {
+ linedef.from=GetShort(wf->fp);
+ linedef.to=GetShort(wf->fp);
+ linedef.flags=GetShort(wf->fp);
+ linedef.type=GetShort(wf->fp);
+ linedef.tag=GetShort(wf->fp);
+ linedef.right=GetShort(wf->fp);
+ linedef.left=GetShort(wf->fp);
+ MapAdd(map->linedef,f,&linedef);
+ }
+ break;
+
+ case SECTOR_LUMP:
+ fseek(wf->fp,(long)dir->off,SEEK_SET);
+
+ for(f=0;f<dir->size/SECTOR_SIZE;f++)
+ {
+ sector.floor=GetShort(wf->fp);
+ sector.ceiling=GetShort(wf->fp);
+ strcpy(sector.floor_t,GetName(wf->fp));
+ strcpy(sector.ceiling_t,GetName(wf->fp));
+ sector.light=GetShort(wf->fp);
+ sector.special=GetShort(wf->fp);
+ sector.tag=GetShort(wf->fp);
+ MapAdd(map->sector,f,&sector);
+ }
+ break;
+
+ /* No action yet for these - will simply be written back
+ */
+ case BEHAVIOR_LUMP:
+ map->behavior_size=dir->size;
+ map->behavior=Grab(dir->size);
+ fseek(wf->fp,(long)dir->off,SEEK_SET);
+ FRead(wf->fp,map->behavior,dir->size);
+ break;
+
+ case SCRIPTS_LUMP:
+ map->scripts_size=dir->size;
+ map->scripts=Grab(dir->size+1);
+ fseek(wf->fp,(long)dir->off,SEEK_SET);
+ FRead(wf->fp,map->scripts,dir->size);
+ map->scripts[map->scripts_size]=0;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ /* Locate the MAPINFO lump if config says so
+ */
+ if (mapinfo_lump)
+ map->mapinfo=UnMSDOS(LoadMAPINFO());
+
+ ERR(WAD_OK,map);
+}
+
+
+WadMap *NewMap(int hexen)
+{
+ WadMap *map;
+
+ map=Grab(sizeof(WadMap));
+
+ map->hexen=hexen;
+
+ map->thing=MapNew(sizeof(Thing));
+ map->vertex=MapNew(sizeof(Vertex));
+ map->sidedef=MapNew(sizeof(Sidedef));
+ map->linedef=MapNew(sizeof(Linedef));
+ map->sector=MapNew(sizeof(Sector));
+
+ if (mapinfo_lump)
+ map->mapinfo=UnMSDOS(LoadMAPINFO());
+ else
+ map->mapinfo=NULL;
+
+ map->behavior_size=0;
+ map->behavior=NULL;
+ map->scripts_size=0;
+ map->scripts=NULL;
+
+ return(map);
+}
+
+
+WadMap *ClearMap(WadMap *map)
+{
+ MapClear(map->thing);
+ MapClear(map->vertex);
+ MapClear(map->sidedef);
+ MapClear(map->linedef);
+ MapClear(map->sector);
+
+ if (map->mapinfo)
+ Release(map->mapinfo);
+
+ if (map->behavior)
+ Release(map->behavior);
+
+ if (map->scripts)
+ Release(map->scripts);
+
+ Release(map);
+ return(NULL);
+}
+
+
+int SaveMap(WadMap *map, char *name, char *wad)
+{
+ FILE *fp;
+ Long off;
+ int f;
+ Long no;
+
+ if (!(fp=fopen(wad,"wb")))
+ ERR(WAD_COULD_NOT_CREATE,WAD_COULD_NOT_CREATE);
+
+ /* Calc number of entries in MAP
+ */
+ if (map->hexen)
+ no=13;
+ else
+ no=11;
+
+ /* Calc offset for directory
+ */
+ off=12;
+
+ off+=MapSize(map->vertex)*VERTEX_SIZE+
+ MapSize(map->sidedef)*SIDEDEF_SIZE+
+ MapSize(map->sector)*SECTOR_SIZE;
+
+ if (map->hexen)
+ {
+ off+=MapSize(map->linedef)*LINEDEF_SIZE_HEXEN+
+ MapSize(map->thing)*THING_SIZE_HEXEN;
+
+ off+=map->behavior_size+map->scripts_size;
+ }
+ else
+ {
+ off+=MapSize(map->linedef)*LINEDEF_SIZE+
+ MapSize(map->thing)*THING_SIZE;
+ }
+
+ /* Save MAPINFO.WAD
+ */
+ if ((map->mapinfo)&&(strlen(map->mapinfo)))
+ {
+ char *info;
+
+ info=ApplyMSDOS(map->mapinfo,FALSE);
+
+ if (!SaveMAPINFO(info))
+ {
+ Release(info);
+ ERR(WAD_MAPINFO_FAILED,WAD_MAPINFO_FAILED);
+ }
+
+ Release(info);
+ }
+
+ /* Put PWAD header
+ */
+ fputs("PWAD",fp);
+ PutLong(fp,no);
+ PutLong(fp,off);
+
+ /* Put THINGS
+ */
+ for(f=0;f<MapSize(map->thing);f++)
+ {
+ Thing *t;
+
+ t=MapElem(map->thing,f);
+
+ if (map->hexen)
+ {
+ int i;
+
+ PutUShort(fp,t->id);
+ PutShort(fp,t->x);
+ PutShort(fp,t->y);
+ PutShort(fp,t->z);
+ PutShort(fp,t->ang);
+ PutShort(fp,t->type);
+ PutShort(fp,t->flags);
+ PutByte(fp,t->special);
+
+ for(i=0;i<5;i++)
+ PutByte(fp,t->args[i]);
+ }
+ else
+ {
+ PutShort(fp,t->x);
+ PutShort(fp,t->y);
+ PutShort(fp,t->ang);
+ PutShort(fp,t->type);
+ PutShort(fp,t->flags);
+ }
+ }
+
+ /* Put LINEDEFS
+ */
+ for(f=0;f<MapSize(map->linedef);f++)
+ {
+ Linedef *l;
+
+ l=MapElem(map->linedef,f);
+
+ if (map->hexen)
+ {
+ int i;
+
+ PutShort(fp,l->from);
+ PutShort(fp,l->to);
+ PutShort(fp,l->flags);
+ PutByte(fp,(Byte)l->type);
+
+ for(i=0;i<5;i++)
+ PutByte(fp,l->args[i]);
+
+ PutShort(fp,l->right);
+ PutShort(fp,l->left);
+ }
+ else
+ {
+ PutShort(fp,l->from);
+ PutShort(fp,l->to);
+ PutShort(fp,l->flags);
+ PutShort(fp,l->type);
+ PutShort(fp,l->tag);
+ PutShort(fp,l->right);
+ PutShort(fp,l->left);
+ }
+ }
+
+ /* Put SIDEDEFS
+ */
+ for(f=0;f<MapSize(map->sidedef);f++)
+ {
+ Sidedef *s;
+
+ s=MapElem(map->sidedef,f);
+ PutShort(fp,s->x);
+ PutShort(fp,s->y);
+ PutName(fp,s->upper);
+ PutName(fp,s->lower);
+ PutName(fp,s->middle);
+ PutShort(fp,s->sector);
+ }
+
+ /* Put VERTEXES
+ */
+ for(f=0;f<MapSize(map->vertex);f++)
+ {
+ Vertex *v;
+
+ v=MapElem(map->vertex,f);
+ PutShort(fp,v->x);
+ PutShort(fp,v->y);
+ }
+
+ /* Skip SEGS, SSECTORS, NODE
+ */
+
+ /* Put SECTORS
+ */
+ for(f=0;f<MapSize(map->sector);f++)
+ {
+ Sector *s;
+
+ s=MapElem(map->sector,f);
+ PutShort(fp,s->floor);
+ PutShort(fp,s->ceiling);
+ PutName(fp,s->floor_t);
+ PutName(fp,s->ceiling_t);
+ PutShort(fp,s->light);
+ PutShort(fp,s->special);
+ PutShort(fp,s->tag);
+ }
+
+ /* Skip REJECT, BLOCKMAP
+ */
+
+ /* Put BEHAVIOR and SCRIPTS
+ */
+ if (map->hexen)
+ {
+ int f;
+
+ if (map->behavior)
+ for(f=0;f<map->behavior_size;f++)
+ PutByte(fp,map->behavior[f]);
+
+ if (map->scripts)
+ for(f=0;f<map->scripts_size;f++)
+ PutByte(fp,map->scripts[f]);
+ }
+
+ /* Create directory
+ */
+ off=12;
+ PutDirEnt(fp,off,0,name);
+
+ if (map->hexen)
+ {
+ PutDirEnt(fp,off,MapSize(map->thing)*THING_SIZE_HEXEN,"THINGS");
+ off+=MapSize(map->thing)*THING_SIZE_HEXEN;
+ }
+ else
+ {
+ PutDirEnt(fp,off,MapSize(map->thing)*THING_SIZE,"THINGS");
+ off+=MapSize(map->thing)*THING_SIZE;
+ }
+
+ if (map->hexen)
+ {
+ PutDirEnt(fp,off,MapSize(map->linedef)*LINEDEF_SIZE_HEXEN,"LINEDEFS");
+ off+=MapSize(map->linedef)*LINEDEF_SIZE_HEXEN;
+ }
+ else
+ {
+ PutDirEnt(fp,off,MapSize(map->linedef)*LINEDEF_SIZE,"LINEDEFS");
+ off+=MapSize(map->linedef)*LINEDEF_SIZE;
+ }
+
+ PutDirEnt(fp,off,MapSize(map->sidedef)*SIDEDEF_SIZE,"SIDEDEFS");
+ off+=MapSize(map->sidedef)*SIDEDEF_SIZE;
+
+ PutDirEnt(fp,off,MapSize(map->vertex)*VERTEX_SIZE,"VERTEXES");
+ off+=MapSize(map->vertex)*VERTEX_SIZE;
+
+ PutDirEnt(fp,off,0,"SEGS");
+ PutDirEnt(fp,off,0,"SSECTORS");
+ PutDirEnt(fp,off,0,"NODES");
+
+ PutDirEnt(fp,off,MapSize(map->sector)*SECTOR_SIZE,"SECTORS");
+ off+=MapSize(map->sector)*SECTOR_SIZE;
+
+ PutDirEnt(fp,off,0,"REJECT");
+ PutDirEnt(fp,off,0,"BLOCKMAP");
+
+ if (map->hexen)
+ {
+ PutDirEnt(fp,off,map->behavior_size,"BEHAVIOR");
+ off+=map->behavior_size;
+
+ PutDirEnt(fp,off,map->scripts_size,"SCRIPTS");
+ off+=map->scripts_size;
+ }
+
+ fclose(fp);
+
+ ERR(WAD_OK,WAD_OK);
+}
+
+
+int WadError(void)
+{
+ return(wad_err);
+}
+
+
+const char *WadErrorString(void)
+{
+ return(wad_errstr[wad_err]);
+}
+
+
+int WadFileType(char *wad)
+{
+ FILE *fp;
+ char type[4];
+
+ if (!(fp=fopen(wad,"rb")))
+ return(FILE_IS_NOT_WAD);
+
+ FRead(fp,type,4);
+ fclose(fp);
+
+ if (STRNEQ("PWAD",type))
+ return(FILE_IS_PWAD);
+
+ if (STRNEQ("IWAD",type))
+ return(FILE_IS_IWAD);
+
+ return(FILE_IS_NOT_WAD);
+}
+
+/* END OF FILE */