- Fixed: Saving on maps that don't contain a MAPINFO definition didn't work.

- Fixed: The Zip loader loaded all WADs inside a Zip into the lump directory.
  This is only supposed to be done for WADs in the root directory.
- Complete restructuring of the map loading code. Previously the only way
  to put maps into Zips was to load them as embedded WADs which caused
  some problems, most importantly that the map's file name was irrelevant
  and the internal map label was used instead. With the new code there
  is now a properly defined way to add maps to Zips:
  * Maps are placed in a subdirectory called 'maps'.
  * Maps are stored as WADs that contain all map related lumps.
  * The first lump in the map's WAD directory must be the map label.
  * All lumps not belonging to the first map are ignored.
  * The map's file name determines the name the map is identified with. 
    For maps stored this way the internal map label is ignored so with this 
    method renaming maps is as easy as renaming a file and it is no longer 
    necessary to manipulate the map label.
  With the new code it is also possible to load external maps without
  adding them to the WAD list. Type 'open mapfile.wad' in the console
  to start such a map.
  The new code also performs stricter lump name checks to prevent accidental
  loading of non-map data.


SVN r188 (trunk)
This commit is contained in:
Christoph Oelckers 2006-06-14 15:56:56 +00:00
parent 2a0216cf6f
commit fd79fac52c
11 changed files with 648 additions and 195 deletions

View file

@ -1,3 +1,28 @@
June 14, 2006 (Changes by Graf Zahl)
- Fixed: Saving on maps that don't contain a MAPINFO definition didn't work.
- Fixed: The Zip loader loaded all WADs inside a Zip into the lump directory.
This is only supposed to be done for WADs in the root directory.
June 12-14, 2006 (Changes by Graf Zahl)
- Complete restructuring of the map loading code. Previously the only way
to put maps into Zips was to load them as embedded WADs which caused
some problems, most importantly that the map's file name was irrelevant
and the internal map label was used instead. With the new code there
is now a properly defined way to add maps to Zips:
* Maps are placed in a subdirectory called 'maps'.
* Maps are stored as WADs that contain all map related lumps.
* The first lump in the map's WAD directory must be the map label.
* All lumps not belonging to the first map are ignored.
* The map's file name determines the name the map is identified with.
For maps stored this way the internal map label is ignored so with this
method renaming maps is as easy as renaming a file and it is no longer
necessary to manipulate the map label.
With the new code it is also possible to load external maps without
adding them to the WAD list. Type 'open mapfile.wad' in the console
to start such a map.
The new code also performs stricter lump name checks to prevent accidental
loading of non-map data.
June 13, 2006
- Fixed: In the past, ZDoom worked like Doom and used integral values for
monster speeds. Now it uses fixed point so that an actor's speed property

View file

@ -65,6 +65,7 @@
#include "templates.h"
#include "p_local.h"
#include "r_sky.h"
#include "p_setup.h"
extern FILE *Logfile;
extern bool insave;
@ -308,12 +309,14 @@ CCMD (changemap)
if (argv.argc() > 1)
{
if (Wads.CheckNumForName (argv[1]) == -1)
MapData * map = P_OpenMapData(argv[1]);
if (map == NULL)
{
Printf ("No map %s\n", argv[1]);
}
else
{
delete map;
if (argv.argc() > 2)
{
Net_WriteByte (DEM_CHANGEMAP2);

View file

@ -1852,7 +1852,7 @@ static void PutSaveWads (FILE *file)
M_AppendPNGText (file, "Game WAD", name);
// Name of wad the map resides in
if (Wads.GetLumpFile (level.lumpnum) != 1)
if (Wads.GetLumpFile (level.lumpnum) > 1)
{
name = Wads.GetWadName (Wads.GetLumpFile (level.lumpnum));
M_AppendPNGText (file, "Map WAD", name);
@ -2064,6 +2064,14 @@ void G_DoSaveGame (bool okForQuicksave)
BackupSaveName = savegamefile;
savegamefile = "";
// We don't need the snapshot any longer.
if (level.info->snapshot != NULL)
{
delete level.info->snapshot;
level.info->snapshot = NULL;
}
insave = false;
}

View file

@ -85,6 +85,7 @@ EXTERN_CVAR (Int, disableautosave)
#define cioffset(x) ((size_t)&((cluster_info_t*)1)->x - 1)
#define SNAP_ID MAKE_ID('s','n','A','p')
#define DSNP_ID MAKE_ID('d','s','N','p')
#define VIST_ID MAKE_ID('v','i','S','t')
#define ACSD_ID MAKE_ID('a','c','S','d')
#define RCLS_ID MAKE_ID('r','c','L','s')
@ -1298,7 +1299,7 @@ bool CheckWarpTransMap (char mapname[9], bool substitute)
// Can be called by the startup code or the menu task,
// consoleplayer, playeringame[] should be set.
//
static char d_mapname[9];
static char d_mapname[256];
void G_DeferedInitNew (char *mapname)
{
@ -1317,17 +1318,47 @@ CCMD (map)
}
if (argv.argc() > 1)
{
if (Wads.CheckNumForName (argv[1]) == -1)
MapData * map = P_OpenMapData(argv[1]);
if (map == NULL)
Printf ("No map %s\n", argv[1]);
else
{
delete map;
G_DeferedInitNew (argv[1]);
}
}
else
{
Printf ("Usage: map <map name>\n");
}
}
CCMD (open)
{
if (netgame)
{
Printf ("You cannot use open in multiplayer games.\n");
return;
}
if (argv.argc() > 1)
{
sprintf(d_mapname, "file:%s", argv[1]);
MapData * map = P_OpenMapData(d_mapname);
if (map == NULL)
Printf ("No map %s\n", d_mapname);
else
{
delete map;
gameaction = ga_newgame2;
}
}
else
{
Printf ("Usage: open <map file>\n");
}
}
void G_NewInit ()
{
int i;
@ -1431,10 +1462,12 @@ void G_InitNew (char *mapname, bool bTitleLevel)
}
// [RH] If this map doesn't exist, bomb out
if (Wads.CheckNumForName (mapname) == -1)
MapData * map = P_OpenMapData(mapname);
if (!map)
{
I_Error ("Could not find map %s\n", mapname);
}
delete map;
if (dmflags & DF_MONSTERS_RESPAWN)
{
@ -1504,8 +1537,7 @@ void G_InitNew (char *mapname, bool bTitleLevel)
bglobal.Init ();
}
strncpy (level.mapname, mapname, 8);
level.mapname[8] = 0;
strcpy (level.mapname, mapname);
if (bTitleLevel)
{
gamestate = GS_TITLELEVEL;
@ -2560,7 +2592,7 @@ void G_SnapshotLevel ()
if (level.info->snapshot)
delete level.info->snapshot;
if (level.info->mapname[0] != 0)
if (level.info->mapname[0] != 0 || level.info == &TheDefaultLevelInfo)
{
level.info->snapshotVer = SAVEVER;
level.info->snapshot = new FCompressedMemFile;
@ -2580,7 +2612,7 @@ void G_UnSnapshotLevel (bool hubLoad)
if (level.info->snapshot == NULL)
return;
if (level.info->mapname[0] != 0)
if (level.info->mapname[0] != 0 || level.info == &TheDefaultLevelInfo)
{
SaveVersion = level.info->snapshotVer;
level.info->snapshot->Reopen ();
@ -2654,6 +2686,11 @@ void G_WriteSnapshots (FILE *file)
writeSnapShot (arc, (level_info_t *)&wadlevelinfos[i]);
}
}
if (TheDefaultLevelInfo.snapshot != NULL)
{
FPNGChunkArchive arc (file, DSNP_ID);
writeSnapShot(arc, &TheDefaultLevelInfo);
}
FPNGChunkArchive *arc = NULL;
@ -2730,6 +2767,20 @@ void G_ReadSnapshots (PNGHandle *png)
chunkLen = (DWORD)M_NextPNGChunk (png, SNAP_ID);
}
chunkLen = (DWORD)M_FindPNGChunk (png, DSNP_ID);
if (chunkLen != 0)
{
FPNGChunkArchive arc (png->File->GetFile(), DSNP_ID, chunkLen);
DWORD snapver;
arc << snapver;
arc << namelen;
arc.Read (mapname, namelen);
TheDefaultLevelInfo.snapshotVer = snapver;
TheDefaultLevelInfo.snapshot = new FCompressedMemFile;
TheDefaultLevelInfo.snapshot->Serialize (arc);
}
chunkLen = (DWORD)M_FindPNGChunk (png, VIST_ID);
if (chunkLen != 0)
{

View file

@ -193,7 +193,7 @@ struct level_locals_s
int levelnum;
int lumpnum;
char level_name[64]; // the descriptive name (Outer Base, etc)
char mapname[9]; // the server name (base1, etc)
char mapname[256]; // the server name (base1, etc)
char nextmap[9]; // go here when fraglimit is hit
char secretmap[9]; // map to go to when used secret exit

View file

@ -490,7 +490,7 @@ void FBehavior::StaticLoadDefaultModules ()
}
}
FBehavior *FBehavior::StaticLoadModule (int lumpnum)
FBehavior *FBehavior::StaticLoadModule (int lumpnum, FileReader * fr, int len)
{
for (unsigned int i = 0; i < StaticModules.Size(); ++i)
{
@ -500,7 +500,7 @@ FBehavior *FBehavior::StaticLoadModule (int lumpnum)
}
}
return new FBehavior (lumpnum);
return new FBehavior (lumpnum, fr, len);
}
bool FBehavior::StaticCheckAllGood ()
@ -653,10 +653,9 @@ void FBehavior::SerializeVarSet (FArchive &arc, SDWORD *vars, int max)
}
}
FBehavior::FBehavior (int lumpnum)
FBehavior::FBehavior (int lumpnum, FileReader * fr, int len)
{
BYTE *object;
int len;
int i;
NumScripts = 0;
@ -673,7 +672,7 @@ FBehavior::FBehavior (int lumpnum)
memset (MapVarStore, 0, sizeof(MapVarStore));
ModuleName[0] = 0;
len = Wads.LumpLength (lumpnum);
if (fr == NULL) len = Wads.LumpLength (lumpnum);
// Any behaviors smaller than 32 bytes cannot possibly contain anything useful.
// (16 bytes for a completely empty behavior + 12 bytes for one script header
@ -685,7 +684,14 @@ FBehavior::FBehavior (int lumpnum)
}
object = new byte[len];
if (fr == NULL)
{
Wads.ReadLump (lumpnum, object);
}
else
{
fr->Read (object, len);
}
if (object[0] != 'A' || object[1] != 'C' || object[2] != 'S')
{
@ -707,8 +713,16 @@ FBehavior::FBehavior (int lumpnum)
return;
}
if (fr == NULL)
{
Wads.GetLumpName (ModuleName, lumpnum);
ModuleName[8] = 0;
}
else
{
strcpy(ModuleName, "BEHAVIOR");
}
Data = object;
DataSize = len;

View file

@ -42,6 +42,7 @@
#define NUM_MAPVARS 128
class FFont;
class FileReader;
// The in-memory version
struct ScriptPtr
@ -123,7 +124,7 @@ enum ACSFormat { ACS_Old, ACS_Enhanced, ACS_LittleEnhanced, ACS_Unknown };
class FBehavior
{
public:
FBehavior (int lumpnum);
FBehavior (int lumpnum, FileReader * fr=NULL, int len=0);
~FBehavior ();
bool IsGood ();
@ -145,7 +146,7 @@ public:
SDWORD *MapVars[NUM_MAPVARS];
static FBehavior *StaticLoadModule (int lumpnum);
static FBehavior *StaticLoadModule (int lumpnum, FileReader * fr=NULL, int len=0);
static void StaticLoadDefaultModules ();
static void StaticUnloadModules ();
static bool StaticCheckAllGood ();

File diff suppressed because it is too large Load diff

View file

@ -23,8 +23,63 @@
#ifndef __P_SETUP__
#define __P_SETUP__
#include "w_wad.h"
#include "files.h"
#include "doomdata.h"
struct MapData
{
wadlump_t MapLumps[ML_BEHAVIOR+1];
bool HasBehavior;
bool CloseOnDestruct;
int lumpnum;
FileReader * file;
MapData()
{
memset(MapLumps, 0, sizeof(MapLumps));
file = NULL;
lumpnum=-1;
HasBehavior=false;
CloseOnDestruct=true;
}
~MapData()
{
if (CloseOnDestruct && file != NULL) delete file;
file = NULL;
}
void Seek(int lumpindex)
{
if (lumpindex>=0 && lumpindex<countof(MapLumps))
{
file->Seek(MapLumps[lumpindex].FilePos, SEEK_SET);
}
}
void Read(int lumpindex, void * buffer)
{
if (lumpindex>=0 && lumpindex<countof(MapLumps))
{
file->Seek(MapLumps[lumpindex].FilePos, SEEK_SET);
file->Read(buffer, MapLumps[lumpindex].Size);
}
}
DWORD Size(int lumpindex)
{
if (lumpindex>=0 && lumpindex<countof(MapLumps))
{
return MapLumps[lumpindex].Size;
}
return 0;
}
};
MapData * P_OpenMapData(const char * mapname);
// NOT called by W_Ticker. Fixme. [RH] Is that bad?
//
// [RH] The only parameter used is mapname, so I removed playermask and skill.

View file

@ -569,10 +569,12 @@ void FWadCollection::AddFile (const char *filename, const char * data, int lengt
FixPathSeperator(name);
strlwr(name);
// Check for embedded WADs. They must be extracted and added separately to the lump list.
// Check for embedded WADs in the root directory.
// They must be extracted and added separately to the lump list.
// WADs in subdirectories are added to the lump directory.
// Embedded .zips are ignored for now. But they should be allowed later!
char * c = strstr(name, ".wad");
if (c && strlen(c)==4)
if (c && strlen(c)==4 && !strchr(name, '/'))
{
EmbeddedWADs.Push(zip_fh);
skipped++;
@ -969,7 +971,7 @@ int FWadCollection::GetLumpOffset (int lump) const
{
if ((size_t)lump >= NumLumps)
{
I_Error ("W_LumpLength: %i >= NumLumps",lump);
I_Error ("GetLumpOffset: %i >= NumLumps",lump);
}
return LumpInfo[lump].position;
@ -1751,6 +1753,23 @@ FWadLump *FWadCollection::ReopenLumpNum (int lump)
}
//==========================================================================
//
// GetFileReader
//
// Retrieves the FileReader object to access the given WAD
//
//==========================================================================
FileReader *FWadCollection::GetFileReader(int wadnum)
{
if ((DWORD)wadnum >= NumWads)
{
return NULL;
}
return Wads[wadnum];
}
//==========================================================================
//
// W_GetWadName

View file

@ -171,7 +171,9 @@ public:
FWadLump OpenLumpNum (int lump);
FWadLump OpenLumpName (const char *name) { return OpenLumpNum (GetNumForName (name)); }
FWadLump *ReopenLumpNum (int lump); // Opens a new, independant FILE
FWadLump *ReopenLumpNum (int lump); // Opens a new, independent FILE
FileReader * GetFileReader(int wadnum); // Gets a FileReader object to the entire WAD
int FindLump (const char *name, int *lastlump, bool anyns=false); // [RH] Find lumps with duplication
bool CheckLumpName (int lump, const char *name); // [RH] True if lump's name == name