Updated Visplane Explorer plugin to v1.0. Visplanes of Hexen maps can now be explored.

Map Options Form: example map name now uses current game's naming scheme.
This commit is contained in:
MaxED 2014-09-11 08:26:01 +00:00
parent 422c605bc7
commit a7488939af
33 changed files with 8103 additions and 7726 deletions

View file

@ -701,7 +701,7 @@ namespace CodeImp.DoomBuilder.Windows
}
// Check if we have at least one activation flag when there's an action in UDMF map format (mxd)
if (General.Map.UDMF && !action.Empty && action.Value != 0)
if (General.Map.UDMF && action.Value != 0)
{
bool haveactivationflag = false;
foreach (CheckBox c in udmfactivates.Checkboxes)

View file

@ -42,6 +42,7 @@ namespace CodeImp.DoomBuilder.Windows
this.panelres = new System.Windows.Forms.GroupBox();
this.strictpatches = new System.Windows.Forms.CheckBox();
this.datalocations = new CodeImp.DoomBuilder.Controls.ResourceListEditor();
this.examplelabel = new System.Windows.Forms.Label();
label3 = new System.Windows.Forms.Label();
label2 = new System.Windows.Forms.Label();
label1 = new System.Windows.Forms.Label();
@ -56,9 +57,9 @@ namespace CodeImp.DoomBuilder.Windows
label3.AutoSize = true;
label3.Location = new System.Drawing.Point(239, 83);
label3.Name = "label3";
label3.Size = new System.Drawing.Size(90, 14);
label3.Size = new System.Drawing.Size(53, 14);
label3.TabIndex = 9;
label3.Text = "example: MAP01";
label3.Text = "example: ";
//
// label2
//
@ -82,6 +83,7 @@ namespace CodeImp.DoomBuilder.Windows
//
panelsettings.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
panelsettings.Controls.Add(this.examplelabel);
panelsettings.Controls.Add(this.scriptcompiler);
panelsettings.Controls.Add(this.scriptcompilerlabel);
panelsettings.Controls.Add(label3);
@ -206,6 +208,15 @@ namespace CodeImp.DoomBuilder.Windows
this.datalocations.Size = new System.Drawing.Size(368, 130);
this.datalocations.TabIndex = 0;
//
// examplelabel
//
this.examplelabel.AutoSize = true;
this.examplelabel.Location = new System.Drawing.Point(288, 83);
this.examplelabel.Name = "examplelabel";
this.examplelabel.Size = new System.Drawing.Size(41, 14);
this.examplelabel.TabIndex = 12;
this.examplelabel.Text = "MAP01";
//
// MapOptionsForm
//
this.AcceptButton = this.apply;
@ -247,6 +258,7 @@ namespace CodeImp.DoomBuilder.Windows
private System.Windows.Forms.CheckBox strictpatches;
private System.Windows.Forms.ComboBox scriptcompiler;
private System.Windows.Forms.Label scriptcompilerlabel;
private System.Windows.Forms.Label examplelabel;
}

View file

@ -293,6 +293,7 @@ namespace CodeImp.DoomBuilder.Windows
{
// Get default lump name from configuration
levelname.Text = ci.DefaultLumpName;
examplelabel.Text = ci.DefaultLumpName; //mxd
}
//mxd

View file

@ -50,7 +50,7 @@ namespace CodeImp.DoomBuilder.Plugins.VisplaneExplorer
private delegate int VPO_LoadWAD(string filename);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate int VPO_OpenMap(string mapname);
private delegate int VPO_OpenMap(string mapname, ref bool isHexen);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate void VPO_FreeWAD();
@ -151,8 +151,9 @@ namespace CodeImp.DoomBuilder.Plugins.VisplaneExplorer
try
{
// Load the map
bool isHexen = (General.Map.Config.FormatInterface == "HexenMapSetIO");
if(LoadWAD(filename) != 0) throw new Exception("VPO is unable to read this file.");
if(OpenMap(mapname) != 0) throw new Exception("VPO is unable to open this map.");
if(OpenMap(mapname, ref isHexen) != 0) throw new Exception("VPO is unable to open this map.");
// Processing
Queue<TilePoint> todo = new Queue<TilePoint>(POINTS_PER_ITERATION);

View file

@ -25,7 +25,7 @@ namespace CodeImp.DoomBuilder.Plugins.VisplaneExplorer
ButtonGroup = "002_tools",
Volatile = true,
UseByDefault = true,
SupportedMapFormats = new[] { "DoomMapSetIO" }, //mxd
SupportedMapFormats = new[] { "DoomMapSetIO", "HexenMapSetIO" }, //mxd
AllowCopyPaste = false)]
public class VisplaneExplorerMode : ClassicMode
{

View file

@ -57,7 +57,9 @@ enum
ML_NODES, // BSP nodes
ML_SECTORS, // Sectors, from editing
ML_REJECT, // LUT, sector-sector visibility
ML_BLOCKMAP // LUT, motion clipping, walls/grid element
ML_BLOCKMAP, // LUT, motion clipping, walls/grid element
ML_BEHAVIOR // HEXEN ONLY: compiled ACS scripts
};
@ -98,6 +100,18 @@ typedef struct
} PACKEDATTR maplinedef_t;
// the Hexen LineDef structure [andrewj: added this]
typedef struct
{
short v1;
short v2;
short flags;
unsigned char special;
unsigned char args[5];
short sidenum[2];
} PACKEDATTR maplinedef_hexen_t;
//
// LineDef attributes.
//

File diff suppressed because it is too large Load diff

View file

@ -1,4 +1,3 @@
// Emacs style mode select -*- C++ -*-
//-----------------------------------------------------------------------------
//
// Copyright(C) 1993-1996 Id Software, Inc.
@ -35,13 +34,16 @@
#define SIL_TOP 2
#define SIL_BOTH 3
// #define MAXDRAWSEGS 256
#define MAXDRAWSEGS 1024 // andrewj: increased for Visplane Explorer
// andrewj: increased for Visplane Explorer (was 256)
#define MAXDRAWSEGS 1024
#define skyflatnum 2
extern fixed_t Map_bbox[4];
//
// INTERNAL MAP TYPES
// used by play and refresh
@ -50,12 +52,12 @@
//
// Your plain vanilla vertex.
// Note: transformed values not buffered locally,
// like some DOOM-alikes ("wt", "WebView") did.
// like some DOOM-alikes ("wt", "WebView") did.
//
typedef struct
{
fixed_t x;
fixed_t y;
fixed_t x;
fixed_t y;
} vertex_t;
@ -70,123 +72,115 @@ struct line_s;
//
typedef struct
{
fixed_t floorheight;
fixed_t ceilingheight;
fixed_t floorheight;
fixed_t ceilingheight;
short floorpic;
short ceilingpic;
short lightlevel;
short special;
short tag;
short floorpic;
short ceilingpic;
short lightlevel;
short special;
short tag;
// 0 = untraversed, 1,2 = sndlines -1
int soundtraversed;
// 0 = untraversed, 1,2 = sndlines -1
int soundtraversed;
/// // thing that made a sound (or null)
/// mobj_t* soundtarget;
// if == validcount, already checked
int validcount;
/// // mapblock bounding box for height changes
/// int blockbox[4];
// thinker_t for reversable actions
void* specialdata;
// origin for any sounds played by the sector
/// degenmobj_t soundorg;
int linecount;
struct line_s** lines; // [linecount] size
// if == validcount, already checked
int validcount;
/// // list of mobjs in sector
/// mobj_t* thinglist;
// thinker_t for reversable actions
void* specialdata;
int linecount;
struct line_s** lines; // [linecount] size
// andrewj: added these two field for Visplane Explorer.
// is_door is normally 0,
// can be +1 for a door (ceiling goes up)
// or -1 for a lowering floor (e.g. MAP12 of DOOM 2)
int is_door;
fixed_t alt_height;
} sector_t;
//
// The SideDef.
//
typedef struct
{
// add this to the calculated texture column
fixed_t textureoffset;
// add this to the calculated texture column
fixed_t textureoffset;
// add this to the calculated texture top
fixed_t rowoffset;
// add this to the calculated texture top
fixed_t rowoffset;
// Texture indices.
// We do not maintain names here.
short toptexture;
short bottomtexture;
short midtexture;
// Texture indices.
// We do not maintain names here.
short toptexture;
short bottomtexture;
short midtexture;
// Sector the SideDef is facing.
sector_t* sector;
// Sector the SideDef is facing.
sector_t* sector;
} side_t;
//
// Move clipping aid for LineDefs.
//
typedef enum
{
ST_HORIZONTAL,
ST_VERTICAL,
ST_POSITIVE,
ST_NEGATIVE
ST_HORIZONTAL,
ST_VERTICAL,
ST_POSITIVE,
ST_NEGATIVE
} slopetype_t;
typedef struct line_s
{
// Vertices, from v1 to v2.
vertex_t* v1;
vertex_t* v2;
// Vertices, from v1 to v2.
vertex_t* v1;
vertex_t* v2;
// Precalculated v2 - v1 for side checking.
fixed_t dx;
fixed_t dy;
// Precalculated v2 - v1 for side checking.
fixed_t dx;
fixed_t dy;
// Animation related.
short flags;
short special;
short tag;
// Animation related.
short flags;
short special;
short tag;
// Visual appearance: SideDefs.
// sidenum[1] will be -1 if one sided
short sidenum[2];
// Visual appearance: SideDefs.
// sidenum[1] will be -1 if one sided
short sidenum[2];
// Neat. Another bounding box, for the extent
// of the LineDef.
fixed_t bbox[4];
// Neat. Another bounding box, for the extent
// of the LineDef.
fixed_t bbox[4];
// To aid move clipping.
slopetype_t slopetype;
// To aid move clipping.
slopetype_t slopetype;
// Front and back sector.
// Note: redundant? Can be retrieved from SideDefs.
sector_t* frontsector;
sector_t* backsector;
// Front and back sector.
// Note: redundant? Can be retrieved from SideDefs.
sector_t* frontsector;
sector_t* backsector;
// if == validcount, already checked
int validcount;
// if == validcount, already checked
int validcount;
// thinker_t for reversable actions
void* specialdata;
// thinker_t for reversable actions
void* specialdata;
// andrewj: added the following Hexen stuff
unsigned char args[5];
} line_t;
//
// A SubSector.
// References a Sector.
@ -196,126 +190,119 @@ typedef struct line_s
//
typedef struct subsector_s
{
sector_t* sector;
sector_t* sector;
short numlines;
short firstline;
short numlines;
short firstline;
} subsector_t;
//
// The LineSeg.
//
typedef struct
{
vertex_t* v1;
vertex_t* v2;
vertex_t* v1;
vertex_t* v2;
fixed_t offset;
fixed_t offset;
angle_t angle;
angle_t angle;
side_t* sidedef;
line_t* linedef;
side_t* sidedef;
line_t* linedef;
// Sector references.
// Could be retrieved from linedef, too.
// backsector is NULL for one sided lines
sector_t* frontsector;
sector_t* backsector;
// Sector references.
// Could be retrieved from linedef, too.
// backsector is NULL for one sided lines
sector_t* frontsector;
sector_t* backsector;
} seg_t;
//
// BSP node.
//
typedef struct
{
// Partition line.
fixed_t x;
fixed_t y;
fixed_t dx;
fixed_t dy;
// Partition line.
fixed_t x;
fixed_t y;
fixed_t dx;
fixed_t dy;
// Bounding box for each child.
fixed_t bbox[2][4];
// Bounding box for each child.
fixed_t bbox[2][4];
// If NF_SUBSECTOR its a subsector.
unsigned short children[2];
// If NF_SUBSECTOR its a subsector.
unsigned short children[2];
} node_t;
//
// OTHER TYPES
//
//
// ?
//
typedef struct drawseg_s
{
seg_t* curline;
int x1;
int x2;
seg_t* curline;
int x1;
int x2;
fixed_t scale1;
fixed_t scale2;
fixed_t scalestep;
fixed_t scale1;
fixed_t scale2;
fixed_t scalestep;
// 0=none, 1=bottom, 2=top, 3=both
int silhouette;
// 0=none, 1=bottom, 2=top, 3=both
int silhouette;
// do not clip sprites above this
fixed_t bsilheight;
// do not clip sprites above this
fixed_t bsilheight;
// do not clip sprites below this
fixed_t tsilheight;
// do not clip sprites below this
fixed_t tsilheight;
// Pointers to lists for sprite clipping,
// all three adjusted so [x1] is first value.
short* sprtopclip;
short* sprbottomclip;
short* maskedtexturecol;
// Pointers to lists for sprite clipping,
// all three adjusted so [x1] is first value.
short* sprtopclip;
short* sprbottomclip;
short* maskedtexturecol;
} drawseg_t;
//
// Now what is a visplane, anyway?
//
typedef struct
{
fixed_t height;
int picnum;
int lightlevel;
int minx;
int maxx;
fixed_t height;
int picnum;
int lightlevel;
int minx;
int maxx;
// leave pads for [minx-1]/[maxx+1]
// leave pads for [minx-1]/[maxx+1]
byte pad1;
// Here lies the rub for all
// dynamic resize/change of resolution.
byte top[SCREENWIDTH];
byte pad2;
byte pad3;
// See above.
byte bottom[SCREENWIDTH];
byte pad4;
byte pad1;
// Here lies the rub for all
// dynamic resize/change of resolution.
byte top[SCREENWIDTH];
byte pad2;
byte pad3;
// See above.
byte bottom[SCREENWIDTH];
byte pad4;
} visplane_t;
#endif
#endif /* __R_DEFS__ */
//--- editor settings ---
// vi:ts=4:sw=4:noexpandtab
// Emacs style mode select -*- C++ -*-

View file

@ -3,8 +3,8 @@
//------------------------------------------------------------------------
//
// Copyright (C) 1993-1996 Id Software, Inc.
// Copyright (C) 2005 Simon Howard
// Copyright (C) 2012 Andrew Apted
// Copyright (C) 2005 Simon Howard
// Copyright (C) 2012-2014 Andrew Apted
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
@ -25,35 +25,49 @@
// return error message when something fails
// (this will be a static buffer, so is not guaranteed to remain valid
// after any other API call)
const char* APIENTRY VPO_GetError(void);
const char *VPO_GetError(void);
// try to load a wad file
// returns 0 on success, negative value on error
int APIENTRY VPO_LoadWAD(const char *wad_filename);
int VPO_LoadWAD(const char *wad_filename);
// free all data associated with the wad file
// can be safely called without any loaded wad file
void APIENTRY VPO_FreeWAD(void);
void VPO_FreeWAD(void);
// retrieve the map names in the wad, one at a time
// index starts at 0
// returns NULL when index is past the end of the list
// NOTE: return pointer may be a static buffer, not guaranteed to
// NOTE: return pointer is a static buffer, and is NOT guaranteed to
// remain valid once this function is called again
const char* APIENTRY VPO_GetMapName(unsigned int index);
const char * VPO_GetMapName(unsigned int index, bool *is_hexen = NULL);
// try to open a map from the current wad file
// returns 0 on success, negative value on error
int APIENTRY VPO_OpenMap(const char *map_name);
int VPO_OpenMap(const char *map_name, bool *is_hexen = NULL);
// free all data associated with a map
// can be safely called without any opened map
void APIENTRY VPO_CloseMap(void);
void VPO_CloseMap(void);
// retrieve the linedefs in the current map, one at a time
// index starts at 0
// returns number of sides (0 to 2), or -1 for invalid index
int APIENTRY VPO_GetLinedef(unsigned int index, int *x1, int *y1, int *x2, int *y2);
int VPO_GetLinedef(unsigned int index, int *x1, int *y1, int *x2, int *y2);
// retrieve a seg for the current map
// index starts at 0
// side value will be 0 for front/right, 1 for back/left
// returns a value >= 0 if valid, otherwise -1
int VPO_GetSeg(unsigned int index, int *linedef, int *side,
int *x1, int *y1, int *x2, int *y2);
// retrieve the bounding box of the map
void VPO_GetBBox(int *x1, int *y1, int *x2, int *y2);
// open or close all sectors which seem to be doors
// dir must be > 0 to open them, or -1 to close them
void VPO_OpenDoorSectors(int dir);
// test a spot and angle, returning the number of visplanes
// dz is the height above the floor (or offset from ceiling if < 0)
@ -74,7 +88,7 @@ int APIENTRY VPO_GetLinedef(unsigned int index, int *x1, int *y1, int *x2, int *
#define RESULT_IN_VOID -2
#define RESULT_OVERFLOW -3
int APIENTRY VPO_TestSpot(int x, int y, int dz, int angle,
int VPO_TestSpot(int x, int y, int dz, int angle,
int *num_visplanes,
int *num_drawsegs,
int *num_openings,

View file

@ -21,8 +21,6 @@
#ifndef __VPO_LOCAL_H__
#define __VPO_LOCAL_H__
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
@ -61,7 +59,7 @@ namespace vpo
#define SHORT(x) LE_S16(x)
#define LONG(x) LE_S32(x)
void P_SetupLevel (const char *lumpname );
const char * P_SetupLevel (const char *lumpname, bool *is_hexen );
void P_FreeLevelData (void);
void I_Error (const char *error, ...);

View file

@ -3,8 +3,8 @@
//------------------------------------------------------------------------
//
// Copyright (C) 1993-1996 Id Software, Inc.
// Copyright (C) 2005 Simon Howard
// Copyright (C) 2012 Andrew Apted
// Copyright (C) 2005 Simon Howard
// Copyright (C) 2012-2014 Andrew Apted
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
@ -45,7 +45,7 @@ static void SetError(const char *msg, ...)
}
const char* APIENTRY VPO_GetError(void)
const char *VPO_GetError(void)
{
return error_buffer;
}
@ -53,7 +53,7 @@ const char* APIENTRY VPO_GetError(void)
//------------------------------------------------------------------------
int APIENTRY VPO_LoadWAD(const char *wad_filename)
int VPO_LoadWAD(const char *wad_filename)
{
ClearError();
@ -64,7 +64,7 @@ int APIENTRY VPO_LoadWAD(const char *wad_filename)
if (! vpo::W_AddFile(wad_filename))
{
SetError("Could not open/read the file: %s", wad_filename);
SetError("Missing or invalid wad file: %s", wad_filename);
return -1;
}
@ -72,12 +72,12 @@ int APIENTRY VPO_LoadWAD(const char *wad_filename)
}
int APIENTRY VPO_OpenMap(const char *map_name)
int VPO_OpenMap(const char *map_name, bool *is_hexen)
{
// check a wad is loaded
if (vpo::numlumps <= 0)
{
SetError("VPO_OpenMap called without any loaded map");
SetError("VPO_OpenMap called without any loaded wad");
return -1;
}
@ -86,19 +86,19 @@ int APIENTRY VPO_OpenMap(const char *map_name)
// close any previously loaded map
VPO_CloseMap();
if (vpo::W_CheckNumForName(map_name) < 0)
const char *err_msg = vpo::P_SetupLevel(map_name, is_hexen);
if (err_msg)
{
SetError("No such map in wad: %s", map_name);
SetError("%s", err_msg);
return -1;
}
vpo::P_SetupLevel(map_name);
return 0; // OK !
}
void APIENTRY VPO_FreeWAD(void)
void VPO_FreeWAD(void)
{
VPO_CloseMap();
@ -106,7 +106,7 @@ void APIENTRY VPO_FreeWAD(void)
}
void APIENTRY VPO_CloseMap(void)
void VPO_CloseMap(void)
{
ClearError();
@ -118,11 +118,11 @@ void APIENTRY VPO_CloseMap(void)
}
const char* APIENTRY VPO_GetMapName(unsigned int index)
const char * VPO_GetMapName(unsigned int index, bool *is_hexen)
{
static char buffer[16];
for (unsigned int lump_i = 0 ; lump_i < vpo::numlumps ; lump_i++)
for (int lump_i = 0 ; lump_i < vpo::numlumps ; lump_i++)
{
if (! vpo::lumpinfo[lump_i].is_map_header)
continue;
@ -133,6 +133,9 @@ const char* APIENTRY VPO_GetMapName(unsigned int index)
memcpy(buffer, vpo::lumpinfo[lump_i].name, 8);
buffer[8] = 0;
if (is_hexen)
*is_hexen = vpo::lumpinfo[lump_i].is_hexen;
return buffer;
}
@ -144,7 +147,7 @@ const char* APIENTRY VPO_GetMapName(unsigned int index)
}
int APIENTRY VPO_GetLinedef(unsigned int index, int *x1, int *y1, int *x2, int *y2)
int VPO_GetLinedef(unsigned int index, int *x1, int *y1, int *x2, int *y2)
{
if (index >= (unsigned int)vpo::numlines)
return -1;
@ -161,9 +164,70 @@ int APIENTRY VPO_GetLinedef(unsigned int index, int *x1, int *y1, int *x2, int *
}
int VPO_GetSeg(unsigned int index, int *linedef, int *side,
int *x1, int *y1, int *x2, int *y2)
{
if (index >= (unsigned int)vpo::numsegs)
return -1;
const vpo::seg_t *seg = &vpo::segs[index];
const vpo::line_t *L = seg->linedef;
*x1 = seg->v1->x >> FRACBITS;
*y1 = seg->v1->y >> FRACBITS;
*x2 = seg->v2->x >> FRACBITS;
*y2 = seg->v2->y >> FRACBITS;
*linedef = (L - vpo::lines);
*side = 0;
if (L->sidenum[1] >= 0 && seg->sidedef == &vpo::sides[L->sidenum[1]])
*side = 1;
return 0;
}
void VPO_GetBBox(int *x1, int *y1, int *x2, int *y2)
{
*x1 = (vpo::Map_bbox[vpo::BOXLEFT] >> FRACBITS);
*y1 = (vpo::Map_bbox[vpo::BOXBOTTOM] >> FRACBITS);
*x2 = (vpo::Map_bbox[vpo::BOXRIGHT] >> FRACBITS);
*y2 = (vpo::Map_bbox[vpo::BOXTOP] >> FRACBITS);
}
void VPO_OpenDoorSectors(int dir)
{
for (int i = 0 ; i < vpo::numsectors ; i++)
{
vpo::sector_t *sec = &vpo::sectors[i];
if (sec->is_door == 0)
continue;
if (dir > 0) // open them
{
if (sec->is_door > 0)
sec->ceilingheight = sec->alt_height;
else
sec->floorheight = sec->alt_height;
}
else if (dir < 0) // close them
{
if (sec->is_door > 0)
sec->ceilingheight = sec->floorheight;
else
sec->floorheight = sec->ceilingheight;
}
}
}
//------------------------------------------------------------------------
int APIENTRY VPO_TestSpot(int x, int y, int dz, int angle,
int VPO_TestSpot(int x, int y, int dz, int angle,
int *num_visplanes, int *num_drawsegs,
int *num_openings, int *num_solidsegs)
{
@ -173,9 +237,18 @@ int APIENTRY VPO_TestSpot(int x, int y, int dz, int angle,
vpo::fixed_t rx = (x << FRACBITS) + (FRACUNIT / 2);
vpo::fixed_t ry = (y << FRACBITS) + (FRACUNIT / 2);
vpo::sector_t *sec;
// check if spot is outside the map
if (rx < vpo::Map_bbox[vpo::BOXLEFT] ||
rx > vpo::Map_bbox[vpo::BOXRIGHT] ||
ry < vpo::Map_bbox[vpo::BOXBOTTOM] ||
ry > vpo::Map_bbox[vpo::BOXTOP])
{
return RESULT_IN_VOID;
}
// optimization: we cache the last sector lookup
vpo::sector_t *sec;
if (x == last_x && y == last_y)
sec = last_sector;
else
@ -231,7 +304,9 @@ int APIENTRY VPO_TestSpot(int x, int y, int dz, int angle,
//------------------------------------------------------------------------
#ifdef VPO_TEST_PROGRAM
#if 0 // VPO_TEST_PROGRAM
// NOTE: this is out of date and will not compile
#define EYE_HEIGHT 41

View file

@ -1,4 +1,3 @@
// Emacs style mode select -*- C++ -*-
//-----------------------------------------------------------------------------
//
// Copyright(C) 1993-1996 Id Software, Inc.
@ -32,18 +31,20 @@ namespace vpo
typedef struct
{
// Should be "IWAD" or "PWAD".
char identification[4];
int numlumps;
int infotableofs;
// Should be "IWAD" or "PWAD".
char identification[4];
int numlumps;
int infotableofs;
} PACKEDATTR wadinfo_t;
typedef struct
{
int filepos;
int size;
char name[8];
int filepos;
int size;
char name[8];
} PACKEDATTR filelump_t;
//
@ -53,8 +54,12 @@ typedef struct
// Location of each lump on disk.
lumpinfo_t *lumpinfo;
unsigned int numlumps = 0;
int numlumps = 0;
static char * wad_filename;
static wad_file_t * current_file;
@ -63,51 +68,38 @@ unsigned int numlumps = 0;
//
// andrewj: added this to find level names
bool CheckMapHeader(filelump_t *lumps, int num_after)
// returns 0 if not a level, 1 for DOOM, 2 for HEXEN format
static int CheckMapHeader(filelump_t *lumps, int num_after)
{
static const char *level_lumps[] =
{
"THINGS", "LINEDEFS", "SIDEDEFS", "VERTEXES",
"SEGS", "SSECTORS", "NODES", "SECTORS",
static const char *level_lumps[] =
{
"THINGS", "LINEDEFS", "SIDEDEFS", "VERTEXES",
"SEGS", "SSECTORS", "NODES", "SECTORS",
"REJECT", "BLOCKMAP"
};
NULL // end of list
};
if (num_after < 10)
return 0;
if (num_after < 4)
return false;
for (int i = 0 ; i < 10 ; i++)
{
const char *name = level_lumps[i];
int seen_mask = 0;
int seen_count = 0;
// level lumps are never valid map header names
if (strncmp(lumps[0].name, name, 8) == 0)
return 0;
for (int i = 0 ; level_lumps[i] ; i++)
{
const char *name = level_lumps[i];
// require a one-to-one correspondence
// (anything else would crash DOOM)
if (strncmp(lumps[1 + i].name, name, 8) != 0)
return 0;
}
// level lumps are never valid map header names
if (strncmp(lumps[0].name, name, 8) == 0)
return false;
// hexen format is distinguished by a following BEHAVIOR lump
if (num_after >= 11 && strncmp(lumps[11].name, "BEHAVIOR", 8) == 0)
return 2;
for (int pos = 1 ; pos <= 4 ; pos++)
{
if (strncmp(lumps[pos].name, name, 8) == 0)
{
int mask = 1 << i;
// check if name was duplicated
if (seen_mask & mask)
return false;
seen_mask |= mask;
seen_count += 1;
}
}
// found enough level lumps
if (seen_count >= 4)
return true;
}
return false;
return 1;
}
@ -121,41 +113,44 @@ bool CheckMapHeader(filelump_t *lumps, int num_after)
// Other files are single lumps with the base filename
// for the lump name.
wad_file_t *W_AddFile (const char *filename)
bool W_AddFile (const char *filename)
{
wadinfo_t header;
lumpinfo_t *lump_p;
unsigned int i;
wad_file_t *wad_file;
int length;
int startlump;
filelump_t *fileinfo;
filelump_t *filerover;
wadinfo_t header;
lumpinfo_t *lump_p;
wad_file_t *wad_file;
// open the file and add to directory
int i;
int length;
int startlump;
wad_file = W_OpenFile(filename);
filelump_t *fileinfo;
filelump_t *filerover;
if (wad_file == NULL)
{
/// printf (" couldn't open %s\n", filename);
return NULL;
}
// open the file and add to directory
startlump = numlumps;
wad_file = W_OpenFile(filename);
W_Read(wad_file, 0, &header, sizeof(header));
if (strncmp(header.identification,"IWAD",4))
if (wad_file == NULL)
{
// Homebrew levels?
if (strncmp(header.identification,"PWAD",4))
{
I_Error ("Wad file %s doesn't have IWAD "
"or PWAD id\n", filename);
}
return false;
}
// ???modifiedgame = true;
startlump = numlumps;
W_Read(wad_file, 0, &header, sizeof(header));
if (strncmp(header.identification,"IWAD",4) != 0)
{
// Homebrew levels?
if (strncmp(header.identification,"PWAD",4) != 0)
{
/// I_Error ("Wad file %s doesn't have IWAD "
/// "or PWAD id\n", filename);
W_CloseFile(wad_file);
return false;
}
}
header.numlumps = LONG(header.numlumps);
@ -165,64 +160,74 @@ wad_file_t *W_AddFile (const char *filename)
fileinfo = new filelump_t[header.numlumps];
W_Read(wad_file, header.infotableofs, fileinfo, length);
W_Read(wad_file, header.infotableofs, fileinfo, length);
numlumps += header.numlumps;
// Fill in lumpinfo
lumpinfo = (lumpinfo_t *)realloc(lumpinfo, numlumps * sizeof(lumpinfo_t));
// Fill in lumpinfo
lumpinfo = (lumpinfo_t *)realloc(lumpinfo, numlumps * sizeof(lumpinfo_t));
if (lumpinfo == NULL)
{
I_Error ("Couldn't realloc lumpinfo");
}
if (! lumpinfo)
I_Error ("Out of memory -- could not realloc lumpinfo");
lump_p = &lumpinfo[startlump];
lump_p = &lumpinfo[startlump];
filerover = fileinfo;
filerover = fileinfo;
for (i=startlump; i<numlumps; ++i)
{
lump_p->wad_file = wad_file;
lump_p->position = LONG(filerover->filepos);
lump_p->size = LONG(filerover->size);
for (i=startlump; i < numlumps; ++i)
{
int map_header;
strncpy(lump_p->name, filerover->name, 8);
lump_p->position = LONG(filerover->filepos);
lump_p->size = LONG(filerover->size);
lump_p->is_map_header = CheckMapHeader(filerover, numlumps - i - 1);
strncpy(lump_p->name, filerover->name, 8);
++lump_p;
++filerover;
}
map_header = CheckMapHeader(filerover, numlumps - i - 1);
delete[] fileinfo;
lump_p->is_map_header = (map_header >= 1);
lump_p->is_hexen = (map_header == 2);
return wad_file;
++lump_p;
++filerover;
}
delete[] fileinfo;
// close the file now, we re-open it later to load the map
W_CloseFile(wad_file);
wad_filename = strdup(filename);
if (! wad_filename)
I_Error ("Out of memory -- could not strdup filename");
return true;
}
void W_RemoveFile(void)
{
if (lumpinfo)
{
// andrewj: horrible hack, assumes a single wad file
W_CloseFile(lumpinfo[0].wad_file);
if (wad_filename)
{
free(wad_filename);
free(lumpinfo);
wad_filename = NULL;
lumpinfo = NULL;
numlumps = 0;
}
free(lumpinfo);
lumpinfo = NULL;
numlumps = 0;
}
}
//
// W_NumLumps
//
int W_NumLumps (void)
{
return numlumps;
return numlumps;
}
@ -230,45 +235,23 @@ int W_NumLumps (void)
// W_CheckNumForName
// Returns -1 if name not found.
//
int W_CheckNumForName (const char* name)
{
int i;
int i;
{
// scan backwards so patch lump files take precedence
// scan backwards so patch lump files take precedence
for (i=numlumps-1; i >= 0; --i)
{
if (!strncasecmp(lumpinfo[i].name, name, 8))
{
return i;
}
}
}
for (i=numlumps-1; i >= 0; --i)
{
if (strncasecmp(lumpinfo[i].name, name, 8) == 0)
{
return i;
}
}
// TFB. Not found.
// TFB. Not found.
return -1;
}
//
// W_GetNumForName
// Calls W_CheckNumForName, but bombs out if not found.
//
int W_GetNumForName (const char* name)
{
int i;
i = W_CheckNumForName (name);
if (i < 0)
{
I_Error ("W_GetNumForName: %s not found!", name);
}
return i;
return -1;
}
@ -276,84 +259,108 @@ int W_GetNumForName (const char* name)
// W_LumpLength
// Returns the buffer size needed to load the given lump.
//
int W_LumpLength (unsigned int lump)
int W_LumpLength (int lumpnum)
{
if (lump >= numlumps)
{
I_Error ("W_LumpLength: %i >= numlumps", lump);
}
if (lumpnum >= numlumps)
{
I_Error ("W_LumpLength: %i >= numlumps", lumpnum);
}
return lumpinfo[lump].size;
return lumpinfo[lumpnum].size;
}
//
// W_ReadLump
// Loads the lump into the given buffer,
// which must be >= W_LumpLength().
//
void W_ReadLump(unsigned int lump, void *dest)
static void W_ReadLump(int lump, void *dest)
{
int c;
lumpinfo_t *l;
int c;
lumpinfo_t *l;
if (lump >= numlumps)
{
I_Error ("W_ReadLump: %i >= numlumps", lump);
}
if (lump >= numlumps)
{
I_Error ("W_ReadLump: %i >= numlumps", lump);
}
l = lumpinfo+lump;
l = lumpinfo+lump;
/// I_BeginRead ();
c = W_Read(current_file, l->position, dest, l->size);
c = W_Read(l->wad_file, l->position, dest, l->size);
if (c < l->size)
{
I_Error ("W_ReadLump: only read %i of %i on lump %i",
c, l->size, lump);
}
/// I_EndRead ();
if (c < l->size)
{
I_Error ("W_ReadLump: only read %i of %i on lump %i", c, l->size, lump);
}
}
//
// W_LoadLump
//
// Load a lump into memory and return a pointer to a buffer containing
// the lump data.
//
byte * W_LoadLump(int lumpnum)
{
byte *result;
lumpinfo_t *lump;
byte *result;
if ((unsigned)lumpnum >= numlumps)
{
I_Error ("W_LoadLump: %i >= numlumps", lumpnum);
}
if (lumpnum < 0 || lumpnum >= numlumps)
{
I_Error ("W_LoadLump: %i >= numlumps", lumpnum);
}
lump = &lumpinfo[lumpnum];
if (! current_file)
I_Error ("W_LoadLump: no current file (W_BeginRead not called)");
// load it now
// load it now
result = new byte[W_LumpLength(lumpnum) + 1];
result = new byte[W_LumpLength(lumpnum) + 1];
W_ReadLump (lumpnum, result);
W_ReadLump (lumpnum, result);
return result;
return result;
}
void W_FreeLump(byte * data)
{
delete[] data;
delete[] data;
}
void W_BeginRead(void)
{
// check API usage
if (! wad_filename)
I_Error("W_BeginRead called without any wad file!");
if (current_file)
I_Error("W_BeginRead called twice without W_EndRead.");
current_file = W_OpenFile(wad_filename);
// it should normally succeed, as it is unlikely the file suddenly
// disappears between reading the directory and loading a map.
if (! current_file)
I_Error("Could not re-open the wad file -- deleted?");
}
void W_EndRead()
{
if (! current_file)
I_Error("W_EndRead called without a previous W_BeginRead.");
W_CloseFile(current_file);
current_file = NULL;
}
} // namespace vpo
//--- editor settings ---
// vi:ts=4:sw=4:noexpandtab
// Emacs style mode select -*- C++ -*-

View file

@ -1,4 +1,3 @@
// Emacs style mode select -*- C++ -*-
//-----------------------------------------------------------------------------
//
// Copyright(C) 1993-1996 Id Software, Inc.
@ -24,7 +23,6 @@
//
//-----------------------------------------------------------------------------
#ifndef __W_WAD__
#define __W_WAD__
@ -46,34 +44,41 @@ typedef struct lumpinfo_s lumpinfo_t;
struct lumpinfo_s
{
char name[8];
wad_file_t *wad_file;
int position;
int size;
bool is_map_header; // e.g. MAP01 or E1M1
char name[8];
// Used for hash table lookups
int position;
int size;
lumpinfo_t *next;
bool is_map_header; // e.g. MAP01 or E1M1
bool is_hexen;
};
extern lumpinfo_t *lumpinfo;
extern unsigned int numlumps;
extern int numlumps;
wad_file_t *W_AddFile (const char *filename);
// andrewj: only a single file can be added now
bool W_AddFile (const char *filename);
void W_RemoveFile(void);
int W_CheckNumForName (const char* name);
int W_GetNumForName (const char* name);
int W_CheckNumForName (const char *name);
int W_LumpLength (unsigned int lump);
int W_LumpLength (int lumpnum);
// andrewj: all lump loading must occur between these calls
void W_BeginRead(void);
void W_EndRead();
byte * W_LoadLump(int lumpnum);
void W_FreeLump(byte * data);
#endif // __W_WAD__
#endif /* __W_WAD__ */
//--- editor settings ---
// vi:ts=4:sw=4:noexpandtab
// Emacs style mode select -*- C++ -*-