- complete restructuring of resource file handling for more flexibility and future

extensions.
- Removed merging of special namespaces. For the texture manager this has
  become totally useless so there is no need to do this anymore. Not merging
  the namespaces also allows a much more reliable detection of lumps belonging
  to special namespaces so the ScanForFlatHack function is no longer needed.
  Instead, any lump up to F_END with a length of 4096 will be marked for 
  inclusion as a flat texture if no F_START marker is found.
- Made the counting of intermission stats in Doom a GAMEINFO option so that
  it can be activated in all games.


SVN r1555 (trunk)
This commit is contained in:
Christoph Oelckers 2009-04-23 22:49:38 +00:00
parent a2a69765eb
commit cc066bc409
27 changed files with 2868 additions and 2143 deletions

View File

@ -1,4 +1,21 @@
April 17, 2009 April 23, 2009 (Changes by Graf Zahl)
- complete restructuring of resource file handling for more flexibility and future
extensions.
- Removed merging of special namespaces. For the texture manager this has
become totally useless so there is no need to do this anymore. Not merging
the namespaces also allows a much more reliable detection of lumps belonging
to special namespaces so the ScanForFlatHack function is no longer needed.
Instead, any lump up to F_END with a length of 4096 will be marked for
inclusion as a flat texture if no F_START marker is found.
April 21, 2009 (Changes by Graf Zahl)
- fixed MustConfirm parsing in MAPINFO
April 19, 2009 (Changes by Graf Zahl)
- Made the counting of intermission stats in Doom a GAMEINFO option so that
it can be activated in all games.
April 17, 2009
- Gave the intermission screen sounds their own SNDINFO entries. - Gave the intermission screen sounds their own SNDINFO entries.
April 16, 2009 April 16, 2009

View File

@ -656,6 +656,14 @@ add_executable( zdoom WIN32
oplsynth/music_opldumper_mididevice.cpp oplsynth/music_opldumper_mididevice.cpp
oplsynth/music_opl_mididevice.cpp oplsynth/music_opl_mididevice.cpp
oplsynth/opl_mus_player.cpp oplsynth/opl_mus_player.cpp
resourcefiles/file_7z.cpp
resourcefiles/file_grp.cpp
resourcefiles/file_lump.cpp
resourcefiles/file_rff.cpp
resourcefiles/file_wad.cpp
resourcefiles/file.zip.cpp
resourcefiles/file_pak.cpp
resourcefiles/resourcefile.cpp
sfmt/SFMT.cpp sfmt/SFMT.cpp
sound/fmodsound.cpp sound/fmodsound.cpp
sound/i_music.cpp sound/i_music.cpp

View File

@ -29,6 +29,7 @@ public:
void ResetFilePtr (); void ResetFilePtr ();
FILE *GetFile () const { return File; } FILE *GetFile () const { return File; }
virtual const char *GetBuffer() const { return NULL; }
FileReader &operator>> (BYTE &v) FileReader &operator>> (BYTE &v)
{ {
@ -279,6 +280,7 @@ public:
virtual long Seek (long offset, int origin); virtual long Seek (long offset, int origin);
virtual long Read (void *buffer, long len); virtual long Read (void *buffer, long len);
virtual char *Gets(char *strbuf, int len); virtual char *Gets(char *strbuf, int len);
virtual const char *GetBuffer() const { return bufptr; }
protected: protected:
const char * bufptr; const char * bufptr;

View File

@ -260,6 +260,7 @@ void FMapInfoParser::ParseGameInfo()
GAMEINFOKEY_STRING(intermissionMusic, "intermissionMusic") GAMEINFOKEY_STRING(intermissionMusic, "intermissionMusic")
GAMEINFOKEY_BOOL(noloopfinalemusic, "noloopfinalemusic") GAMEINFOKEY_BOOL(noloopfinalemusic, "noloopfinalemusic")
GAMEINFOKEY_BOOL(drawreadthis, "drawreadthis") GAMEINFOKEY_BOOL(drawreadthis, "drawreadthis")
GAMEINFOKEY_BOOL(intermissioncounter, "intermissioncounter")
else else
{ {
// ignore unkown keys. // ignore unkown keys.

View File

@ -69,6 +69,7 @@ struct gameinfo_t
char titlePage[9]; char titlePage[9];
bool drawreadthis; bool drawreadthis;
bool noloopfinalemusic; bool noloopfinalemusic;
bool intermissioncounter;
TArray<FName> creditPages; TArray<FName> creditPages;
TArray<FName> finalePages; TArray<FName> finalePages;
TArray<FName> infoPages; TArray<FName> infoPages;

View File

@ -68,6 +68,7 @@
void P_SpawnSlopeMakers (FMapThing *firstmt, FMapThing *lastmt); void P_SpawnSlopeMakers (FMapThing *firstmt, FMapThing *lastmt);
void P_SetSlopes (); void P_SetSlopes ();
void BloodCrypt (void *data, int key, int len);
extern AActor *P_SpawnMapThing (FMapThing *mthing, int position); extern AActor *P_SpawnMapThing (FMapThing *mthing, int position);
extern bool P_LoadBuildMap (BYTE *mapdata, size_t len, FMapThing **things, int *numthings); extern bool P_LoadBuildMap (BYTE *mapdata, size_t len, FMapThing **things, int *numthings);

View File

@ -48,22 +48,22 @@
#include "v_palette.h" #include "v_palette.h"
static int R_CountGroup (const char *start, const char *end);
static int R_CountTexturesX (); static int R_CountTexturesX ();
static int R_CountLumpTextures (int lumpnum); static int R_CountLumpTextures (int lumpnum);
extern void R_DeinitBuildTiles(); extern void R_DeinitBuildTiles();
extern int R_CountBuildTiles(); extern int R_CountBuildTiles();
static struct FakeCmap struct FakeCmap
{ {
char name[8]; char name[8];
PalEntry blend; PalEntry blend;
} *fakecmaps; int lump;
};
size_t numfakecmaps; TArray<FakeCmap> fakecmaps;
int firstfakecmap;
BYTE *realcolormaps; BYTE *realcolormaps;
size_t numfakecmaps;
//========================================================================== //==========================================================================
// //
@ -138,24 +138,39 @@ void R_InitColormaps ()
// [RH] Try and convert BOOM colormaps into blending values. // [RH] Try and convert BOOM colormaps into blending values.
// This is a really rough hack, but it's better than // This is a really rough hack, but it's better than
// not doing anything with them at all (right?) // not doing anything with them at all (right?)
int lastfakecmap = Wads.CheckNumForName ("C_END");
firstfakecmap = Wads.CheckNumForName ("C_START");
if (firstfakecmap == -1 || lastfakecmap == -1) FakeCmap cm;
numfakecmaps = 1;
else
numfakecmaps = lastfakecmap - firstfakecmap;
realcolormaps = new BYTE[256*NUMCOLORMAPS*numfakecmaps];
fakecmaps = new FakeCmap[numfakecmaps];
fakecmaps[0].name[0] = 0; cm.name[0] = 0;
cm.blend = 0;
fakecmaps.Push(cm);
DWORD NumLumps = Wads.GetNumLumps();
for (DWORD i = 0; i < NumLumps; i++)
{
if (Wads.GetLumpNamespace(i) == ns_colormaps)
{
char name[9];
name[8] = 0;
Wads.GetLumpName (name, ns_colormaps);
if (Wads.CheckNumForName (name, ns_colormaps) == i)
{
strncpy(cm.name, name, 8);
cm.blend = 0;
fakecmaps.Push(cm);
}
}
}
realcolormaps = new BYTE[256*NUMCOLORMAPS*fakecmaps.Size()];
R_SetDefaultColormap ("COLORMAP"); R_SetDefaultColormap ("COLORMAP");
if (numfakecmaps > 1) if (fakecmaps.Size() > 1)
{ {
BYTE unremap[256], remap[256], mapin[256]; BYTE unremap[256], remap[256], mapin[256];
int i; int i;
size_t j; unsigned j;
memcpy (remap, GPalette.Remap, 256); memcpy (remap, GPalette.Remap, 256);
memset (unremap, 0, 256); memset (unremap, 0, 256);
@ -164,12 +179,12 @@ void R_InitColormaps ()
unremap[remap[i]] = i; unremap[remap[i]] = i;
} }
remap[0] = 0; remap[0] = 0;
for (i = ++firstfakecmap, j = 1; j < numfakecmaps; i++, j++) for (j = 1; j < fakecmaps.Size(); j++)
{ {
if (Wads.LumpLength (i) >= (NUMCOLORMAPS+1)*256) if (Wads.LumpLength (fakecmaps[j].lump) >= (NUMCOLORMAPS+1)*256)
{ {
int k, r, g, b; int k, r, g, b;
FWadLump lump = Wads.OpenLumpNum (i); FWadLump lump = Wads.OpenLumpNum (fakecmaps[j].lump);
BYTE *const map = realcolormaps + NUMCOLORMAPS*256*j; BYTE *const map = realcolormaps + NUMCOLORMAPS*256*j;
for (k = 0; k < NUMCOLORMAPS; ++k) for (k = 0; k < NUMCOLORMAPS; ++k)
@ -191,12 +206,12 @@ void R_InitColormaps ()
g += GPalette.BaseColors[map[k]].g; g += GPalette.BaseColors[map[k]].g;
b += GPalette.BaseColors[map[k]].b; b += GPalette.BaseColors[map[k]].b;
} }
Wads.GetLumpName (fakecmaps[j].name, i);
fakecmaps[j].blend = PalEntry (255, r/256, g/256, b/256); fakecmaps[j].blend = PalEntry (255, r/256, g/256, b/256);
} }
} }
} }
NormalLight.Maps = realcolormaps; NormalLight.Maps = realcolormaps;
numfakecmaps = fakecmaps.Size();
} }
//========================================================================== //==========================================================================
@ -207,11 +222,6 @@ void R_InitColormaps ()
void R_DeinitColormaps () void R_DeinitColormaps ()
{ {
if (fakecmaps != NULL)
{
delete[] fakecmaps;
fakecmaps = NULL;
}
if (realcolormaps != NULL) if (realcolormaps != NULL)
{ {
delete[] realcolormaps; delete[] realcolormaps;
@ -229,18 +239,20 @@ void R_DeinitColormaps ()
DWORD R_ColormapNumForName (const char *name) DWORD R_ColormapNumForName (const char *name)
{ {
int lump;
DWORD blend = 0;
if (strnicmp (name, "COLORMAP", 8)) if (strnicmp (name, "COLORMAP", 8))
{ // COLORMAP always returns 0 { // COLORMAP always returns 0
if (-1 != (lump = Wads.CheckNumForName (name, ns_colormaps)) ) for(int i=fakecmaps.Size()-1; i > 0; i++)
blend = lump - firstfakecmap + 1; {
else if (!strnicmp (name, "WATERMAP", 8)) if (!strnicmp(name, fakecmaps[i].name, 8))
blend = MAKEARGB (128,0,0x4f,0xa5); {
return i;
}
} }
return blend; if (!strnicmp (name, "WATERMAP", 8))
return MAKEARGB (128,0,0x4f,0xa5);
}
return 0;
} }
//========================================================================== //==========================================================================
@ -252,7 +264,7 @@ DWORD R_ColormapNumForName (const char *name)
DWORD R_BlendForColormap (DWORD map) DWORD R_BlendForColormap (DWORD map)
{ {
return APART(map) ? map : return APART(map) ? map :
map < numfakecmaps ? DWORD(fakecmaps[map].blend) : 0; map < fakecmaps.Size() ? DWORD(fakecmaps[map].blend) : 0;
} }
//========================================================================== //==========================================================================
@ -284,38 +296,34 @@ void R_InitData ()
int R_GuesstimateNumTextures () int R_GuesstimateNumTextures ()
{ {
int numtex; int numtex = 0;
for(int i = Wads.GetNumLumps()-1; i>=0; i--)
{
int space = Wads.GetLumpNamespace(i);
switch(space)
{
case ns_flats:
case ns_sprites:
case ns_newtextures:
case ns_hires:
case ns_patches:
case ns_graphics:
numtex++;
break;
default:
if (Wads.GetLumpFlags(i) & LUMPF_MAYBEFLAT) numtex++;
break;
}
}
numtex = R_CountGroup ("S_START", "S_END");
numtex += R_CountGroup ("F_START", "F_END");
numtex += R_CountGroup ("TX_START", "TX_END");
numtex += R_CountGroup ("HI_START", "HI_END");
numtex += R_CountBuildTiles (); numtex += R_CountBuildTiles ();
numtex += R_CountTexturesX (); numtex += R_CountTexturesX ();
return numtex; return numtex;
} }
//===========================================================================
//
// R_CountGroup
//
//===========================================================================
static int R_CountGroup (const char *start, const char *end)
{
int startl = Wads.CheckNumForName (start);
int endl = Wads.CheckNumForName (end);
if (startl < 0 || endl < 0)
{
return 0;
}
else
{
return endl - startl - 1;
}
}
//=========================================================================== //===========================================================================
// //
// R_CountTexturesX // R_CountTexturesX

View File

@ -0,0 +1,350 @@
/*
** file_7z.cpp
**
**---------------------------------------------------------------------------
** Copyright 2009 Randy Heit
** Copyright 2009 Christoph Oelckers
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions
** are met:
**
** 1. Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** 2. Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution.
** 3. The name of the author may not be used to endorse or promote products
** derived from this software without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**---------------------------------------------------------------------------
**
**
*/
#include "resourcefile.h"
#include "cmdlib.h"
#include "templates.h"
#include "v_text.h"
#include "w_zip.h"
#include "i_system.h"
#include "w_wad.h"
extern "C" {
#include "Archive/7z/7zHeader.h"
#include "Archive/7z/7zExtract.h"
#include "Archive/7z/7zIn.h"
#include "7zCrc.h"
}
//-----------------------------------------------------------------------
//
// Interface classes to 7z library
//
//-----------------------------------------------------------------------
extern ISzAlloc g_Alloc;
struct CZDFileInStream
{
ISeekInStream s;
FileReader *File;
CZDFileInStream(FileReader *_file)
{
s.Read = Read;
s.Seek = Seek;
File = _file;
}
static SRes Read(void *pp, void *buf, size_t *size)
{
CZDFileInStream *p = (CZDFileInStream *)pp;
long numread = p->File->Read(buf, (long)*size);
if (numread < 0)
{
*size = 0;
return SZ_ERROR_READ;
}
*size = numread;
return SZ_OK;
}
static SRes Seek(void *pp, Int64 *pos, ESzSeek origin)
{
CZDFileInStream *p = (CZDFileInStream *)pp;
int move_method;
int res;
if (origin == SZ_SEEK_SET)
{
move_method = SEEK_SET;
}
else if (origin == SZ_SEEK_CUR)
{
move_method = SEEK_CUR;
}
else if (origin == SZ_SEEK_END)
{
move_method = SEEK_END;
}
else
{
return 1;
}
res = p->File->Seek((long)*pos, move_method);
*pos = p->File->Tell();
return res;
}
};
struct C7zArchive
{
CSzArEx DB;
CZDFileInStream ArchiveStream;
CLookToRead LookStream;
UInt32 BlockIndex;
Byte *OutBuffer;
size_t OutBufferSize;
C7zArchive(FileReader *file) : ArchiveStream(file)
{
if (g_CrcTable[1] == 0)
{
CrcGenerateTable();
}
file->Seek(0, SEEK_SET);
LookToRead_CreateVTable(&LookStream, false);
LookStream.realStream = &ArchiveStream.s;
LookToRead_Init(&LookStream);
SzArEx_Init(&DB);
BlockIndex = 0xFFFFFFFF;
OutBuffer = NULL;
OutBufferSize = 0;
}
~C7zArchive()
{
if (OutBuffer != NULL)
{
IAlloc_Free(&g_Alloc, OutBuffer);
}
SzArEx_Free(&DB, &g_Alloc);
}
SRes Open()
{
return SzArEx_Open(&DB, &LookStream.s, &g_Alloc, &g_Alloc);
}
SRes Extract(UInt32 file_index, char *buffer)
{
size_t offset, out_size_processed;
SRes res = SzAr_Extract(&DB, &LookStream.s, file_index,
&BlockIndex, &OutBuffer, &OutBufferSize,
&offset, &out_size_processed,
&g_Alloc, &g_Alloc);
if (res == SZ_OK)
{
memcpy(buffer, OutBuffer + offset, out_size_processed);
}
return res;
}
};
//==========================================================================
//
// Zip Lump
//
//==========================================================================
struct F7ZLump : public FResourceLump
{
int Position;
virtual int FillCache();
};
//==========================================================================
//
// Zip file
//
//==========================================================================
class F7ZFile : public FResourceFile
{
friend struct F7ZLump;
F7ZLump *Lumps;
C7zArchive *Archive;
static int STACK_ARGS lumpcmp(const void * a, const void * b);
public:
F7ZFile(const char * filename, FileReader *filer);
bool Open();
virtual ~F7ZFile();
virtual FResourceLump *GetLump(int no) { return ((unsigned)no < NumLumps)? &Lumps[no] : NULL; }
};
int STACK_ARGS F7ZFile::lumpcmp(const void * a, const void * b)
{
F7ZLump * rec1 = (F7ZLump *)a;
F7ZLump * rec2 = (F7ZLump *)b;
return stricmp(rec1->FullName, rec2->FullName);
}
//==========================================================================
//
// 7Z file
//
//==========================================================================
F7ZFile::F7ZFile(const char * filename, FileReader *filer)
: FResourceFile(filename, filer)
{
Lumps = NULL;
Archive = NULL;
}
//==========================================================================
//
// Open it
//
//==========================================================================
bool F7ZFile::Open()
{
Archive = new C7zArchive(Reader);
int skipped = 0;
SRes res;
res = Archive->Open();
if (res != SZ_OK)
{
delete Archive;
Archive = NULL;
Printf("\n"TEXTCOLOR_RED"%s: ", Filename);
if (res == SZ_ERROR_UNSUPPORTED)
{
Printf("Decoder does not support this archive\n");
}
else if (res == SZ_ERROR_MEM)
{
Printf("Cannot allocate memory\n");
}
else if (res == SZ_ERROR_CRC)
{
Printf("CRC error\n");
}
else
{
Printf("error #%d\n", res);
}
return false;
}
NumLumps = Archive->DB.db.NumFiles;
Lumps = new F7ZLump[NumLumps];
F7ZLump *lump_p = Lumps;
for (int i = 0; i < NumLumps; ++i)
{
CSzFileItem *file = &Archive->DB.db.Files[i];
char name[256];
// skip Directories
if (file->IsDir)
{
skipped++;
continue;
}
strncpy(name, file->Name, countof(name)-1);
name[countof(name)-1] = 0;
FixPathSeperator(name);
strlwr(name);
lump_p->LumpNameSetup(name);
lump_p->LumpSize = file->Size;
lump_p->Owner = this;
lump_p->Flags = LUMPF_ZIPFILE;
lump_p->Position = i;
lump_p->CheckEmbedded();
lump_p++;
}
// Resize the lump record array to its actual size
NumLumps -= skipped;
Printf(", %d lumps\n", NumLumps);
// Entries in archives are sorted alphabetically
qsort(&Lumps[0], NumLumps, sizeof(F7ZLump), lumpcmp);
return true;
}
//==========================================================================
//
//
//
//==========================================================================
F7ZFile::~F7ZFile()
{
if (Lumps != NULL) delete [] Lumps;
}
//==========================================================================
//
// Fills the lump cache and performs decompression
//
//==========================================================================
int F7ZLump::FillCache()
{
Cache = new char[LumpSize];
static_cast<F7ZFile*>(Owner)->Archive->Extract(Position, Cache);
RefCount = 1;
return 1;
}
//==========================================================================
//
// File open
//
//==========================================================================
FResourceFile *Check7Z(const char *filename, FileReader *file)
{
char head[k7zSignatureSize];
file->Seek(0, SEEK_SET);
file->Read(&head, k7zSignatureSize);
file->Seek(0, SEEK_SET);
if (!memcmp(head, k7zSignature, k7zSignatureSize))
{
FResourceFile *rf = new F7ZFile(filename, file);
if (rf->Open()) return rf;
delete rf;
}
return NULL;
}

View File

@ -0,0 +1,152 @@
/*
** file_grp.cpp
**
**---------------------------------------------------------------------------
** Copyright 1998-2009 Randy Heit
** Copyright 2005-2009 Christoph Oelckers
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions
** are met:
**
** 1. Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** 2. Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution.
** 3. The name of the author may not be used to endorse or promote products
** derived from this software without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**---------------------------------------------------------------------------
**
**
*/
#include "resourcefile.h"
#include "cmdlib.h"
#include "v_text.h"
#include "w_wad.h"
//==========================================================================
//
//
//
//==========================================================================
struct GrpInfo
{
DWORD Magic[3];
DWORD NumLumps;
};
struct GrpLump
{
union
{
struct
{
char Name[12];
DWORD Size;
};
char NameWithZero[13];
};
};
//==========================================================================
//
// Build GRP file
//
//==========================================================================
class FGrpFile : public FUncompressedFile
{
public:
FGrpFile(const char * filename, FileReader *file);
bool Open();
};
//==========================================================================
//
// Initializes a Build GRP file
//
//==========================================================================
FGrpFile::FGrpFile(const char *filename, FileReader *file)
: FUncompressedFile(filename, file)
{
Lumps = NULL;
}
//==========================================================================
//
// Open it
//
//==========================================================================
bool FGrpFile::Open()
{
GrpInfo header;
Reader->Read(&header, sizeof(header));
NumLumps = LittleLong(header.NumLumps);
GrpLump *fileinfo = new GrpLump[NumLumps];
Reader->Read (fileinfo, NumLumps * sizeof(GrpLump));
Lumps = new FUncompressedLump[NumLumps];
int Position = sizeof(GrpInfo) + NumLumps * sizeof(GrpLump);
for(DWORD i = 0; i < NumLumps; i++)
{
Lumps[i].Owner = this;
Lumps[i].Position = Position;
Lumps[i].LumpSize = LittleLong(fileinfo[i].Size);
Position += fileinfo[i].Size;
Lumps[i].Namespace = ns_global;
Lumps[i].Flags = 0;
fileinfo[i].NameWithZero[12] = '\0'; // Be sure filename is null-terminated
Lumps[i].LumpNameSetup(fileinfo[i].NameWithZero);
}
Printf(", %d lumps\n", NumLumps);
delete[] fileinfo;
return true;
}
//==========================================================================
//
// File open
//
//==========================================================================
FResourceFile *CheckGRP(const char *filename, FileReader *file)
{
char head[12];
file->Seek(0, SEEK_SET);
file->Read(&head, 12);
file->Seek(0, SEEK_SET);
if (!memcmp(head, "KenSilverman", 12))
{
FResourceFile *rf = new FGrpFile(filename, file);
if (rf->Open()) return rf;
delete rf;
}
return NULL;
}

View File

@ -0,0 +1,100 @@
/*
** file_lump.cpp
**
**---------------------------------------------------------------------------
** Copyright 2009 Christoph Oelckers
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions
** are met:
**
** 1. Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** 2. Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution.
** 3. The name of the author may not be used to endorse or promote products
** derived from this software without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**---------------------------------------------------------------------------
**
**
*/
#include "resourcefile.h"
#include "cmdlib.h"
#include "v_text.h"
#include "w_wad.h"
//==========================================================================
//
// Single lump
//
//==========================================================================
class FLumpFile : public FUncompressedFile
{
public:
FLumpFile(const char * filename, FileReader *file);
bool Open();
};
//==========================================================================
//
// FLumpFile::FLumpFile
//
//==========================================================================
FLumpFile::FLumpFile(const char *filename, FileReader *file) : FUncompressedFile(filename, file)
{
}
//==========================================================================
//
// Open it
//
//==========================================================================
bool FLumpFile::Open()
{
FString name(ExtractFileBase (Filename));
Lumps = new FUncompressedLump[1]; // must use array allocator
uppercopy(Lumps->Name, name);
Lumps->Name[8] = 0;
Lumps->Owner = this;
Lumps->Position = 0;
Lumps->LumpSize = Reader->GetLength();
Lumps->Namespace = ns_global;
Lumps->Flags = 0;
Lumps->FullName = NULL;
return true;
}
//==========================================================================
//
// File open
//
//==========================================================================
FResourceFile *CheckLump(const char *filename, FileReader *file)
{
// always succeeds
FResourceFile *rf = new FLumpFile(filename, file);
if (rf->Open()) return rf;
delete rf;
return NULL;
}

View File

@ -0,0 +1 @@
// not implemented yet

View File

@ -0,0 +1,251 @@
/*
** file_rff.cpp
**
**---------------------------------------------------------------------------
** Copyright 1998-2009 Randy Heit
** Copyright 2005-2009 Christoph Oelckers
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions
** are met:
**
** 1. Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** 2. Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution.
** 3. The name of the author may not be used to endorse or promote products
** derived from this software without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**---------------------------------------------------------------------------
**
**
*/
#include "resourcefile.h"
#include "cmdlib.h"
#include "templates.h"
#include "v_text.h"
#include "w_wad.h"
//==========================================================================
//
//
//
//==========================================================================
struct RFFInfo
{
// Should be "RFF\x18"
DWORD Magic;
DWORD Version;
DWORD DirOfs;
DWORD NumLumps;
};
struct RFFLump
{
BYTE IDontKnow[16];
DWORD FilePos;
DWORD Size;
BYTE IStillDontKnow[8];
BYTE Flags;
char Extension[3];
char Name[8+4]; // 4 bytes that I don't know what they are for
};
//==========================================================================
//
// Blood RFF lump (uncompressed lump with encryption)
//
//==========================================================================
struct FRFFLump : public FUncompressedLump
{
virtual FileReader *GetReader();
virtual int FillCache();
};
//==========================================================================
//
// BloodCrypt
//
//==========================================================================
void BloodCrypt (void *data, int key, int len)
{
int p = (BYTE)key, i;
for (i = 0; i < len; ++i)
{
((BYTE *)data)[i] ^= (unsigned char)(p+(i>>1));
}
}
//==========================================================================
//
// Blood RFF file
//
//==========================================================================
class FRFFFile : public FResourceFile
{
FRFFLump *Lumps;
public:
FRFFFile(const char * filename, FileReader *file);
virtual ~FRFFFile();
virtual bool Open();
virtual FResourceLump *GetLump(int no) { return ((unsigned)no < NumLumps)? &Lumps[no] : NULL; }
};
//==========================================================================
//
// Initializes a Blood RFF file
//
//==========================================================================
FRFFFile::FRFFFile(const char *filename, FileReader *file)
: FResourceFile(filename, file)
{
Lumps = NULL;
}
//==========================================================================
//
// Initializes a Blood RFF file
//
//==========================================================================
bool FRFFFile::Open()
{
RFFLump *lumps;
RFFInfo header;
Reader->Read(&header, sizeof(header));
NumLumps = LittleLong(header.NumLumps);
header.DirOfs = LittleLong(header.DirOfs);
lumps = new RFFLump[header.NumLumps];
Reader->Seek (header.DirOfs, SEEK_SET);
Reader->Read (lumps, header.NumLumps * sizeof(RFFLump));
BloodCrypt (lumps, header.DirOfs, header.NumLumps * sizeof(RFFLump));
Lumps = new FRFFLump[NumLumps];
Printf(", %d lumps\n", NumLumps);
for (DWORD i = 0; i < NumLumps; ++i)
{
if (lumps[i].Extension[0] == 'S' && lumps[i].Extension[1] == 'F' &&
lumps[i].Extension[2] == 'X')
{
Lumps[i].Namespace = ns_bloodsfx;
}
else if (lumps[i].Extension[0] == 'R' && lumps[i].Extension[1] == 'A' &&
lumps[i].Extension[2] == 'W')
{
Lumps[i].Namespace = ns_bloodraw;
}
else
{
Lumps[i].Namespace = ns_global;
}
Lumps[i].Position = LittleLong(lumps[i].FilePos);
Lumps[i].LumpSize = LittleLong(lumps[i].Size);
Lumps[i].Owner = this;
if (lumps[i].Flags & 0x10) Lumps[i].Flags |= LUMPF_BLOODCRYPT;
// Rearrange the name and extension in a part of the lump record
// that I don't have any use for in order to cnstruct the fullname.
lumps[i].Name[8] = '\0';
strcpy ((char *)lumps[i].IDontKnow, lumps[i].Name);
strcat ((char *)lumps[i].IDontKnow, ".");
strcat ((char *)lumps[i].IDontKnow, lumps[i].Extension);
Lumps[i].LumpNameSetup((char *)lumps[i].IDontKnow);
}
delete[] lumps;
return true;
}
FRFFFile::~FRFFFile()
{
if (Lumps != NULL) delete [] Lumps;
}
//==========================================================================
//
// Get reader (only returns non-NULL if not encrypted)
//
//==========================================================================
FileReader *FRFFLump::GetReader()
{
// Don't return the reader if this lump is encrypted
// In that case always force caching of the lump
if (!(Flags & LUMPF_BLOODCRYPT)) return FUncompressedLump::GetReader();
else return NULL;
}
//==========================================================================
//
// Fills the lump cache and performs decryption
//
//==========================================================================
int FRFFLump::FillCache()
{
int res = FUncompressedLump::FillCache();
if (Flags & LUMPF_BLOODCRYPT)
{
int cryptlen = MIN<int> (LumpSize, 256);
BYTE *data = (BYTE *)Cache;
for (int i = 0; i < cryptlen; ++i)
{
data[i] ^= i >> 1;
}
}
return res;
}
//==========================================================================
//
// File open
//
//==========================================================================
FResourceFile *CheckRFF(const char *filename, FileReader *file)
{
char head[4];
file->Seek(0, SEEK_SET);
file->Read(&head, 4);
file->Seek(0, SEEK_SET);
if (!memcmp(head, "RFF\x1a", 4))
{
FResourceFile *rf = new FRFFFile(filename, file);
if (rf->Open()) return rf;
delete rf;
}
return NULL;
}

View File

@ -0,0 +1,332 @@
/*
** file_wad.cpp
**
**---------------------------------------------------------------------------
** Copyright 1998-2009 Randy Heit
** Copyright 2005-2009 Christoph Oelckers
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions
** are met:
**
** 1. Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** 2. Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution.
** 3. The name of the author may not be used to endorse or promote products
** derived from this software without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**---------------------------------------------------------------------------
**
**
*/
#include "resourcefile.h"
#include "cmdlib.h"
#include "v_text.h"
#include "w_wad.h"
//==========================================================================
//
// Wad file
//
//==========================================================================
class FWadFile : public FUncompressedFile
{
bool IsMarker(int lump, const char *marker);
void SetNamespace(const char *startmarker, const char *endmarker, namespace_t space, bool flathack=false);
void SkinHack ();
public:
FWadFile(const char * filename, FileReader *file);
void FindStrifeTeaserVoices ();
bool Open();
};
//==========================================================================
//
// FWadFile::FWadFile
//
// Initializes a WAD file
//
//==========================================================================
FWadFile::FWadFile(const char *filename, FileReader *file) : FUncompressedFile(filename, file)
{
Lumps = NULL;
}
//==========================================================================
//
// Open it
//
//==========================================================================
bool FWadFile::Open()
{
wadinfo_t header;
Reader->Read(&header, sizeof(header));
NumLumps = LittleLong(header.NumLumps);
header.InfoTableOfs = LittleLong(header.InfoTableOfs);
wadlump_t *fileinfo = new wadlump_t[NumLumps];
Reader->Seek (header.InfoTableOfs, SEEK_SET);
Reader->Read (fileinfo, NumLumps * sizeof(wadlump_t));
Lumps = new FUncompressedLump[NumLumps];
Printf(", %d lumps\n", NumLumps);
for(DWORD i = 0; i < NumLumps; i++)
{
uppercopy (Lumps[i].Name, fileinfo[i].Name);
Lumps[i].Name[8] = 0;
Lumps[i].Owner = this;
Lumps[i].Position = LittleLong(fileinfo[i].FilePos);
Lumps[i].LumpSize = LittleLong(fileinfo[i].Size);
Lumps[i].Namespace = ns_global;
Lumps[i].Flags = 0;
Lumps[i].FullName = NULL;
}
SetNamespace("S_START", "S_END", ns_sprites);
SetNamespace("F_START", "F_END", ns_flats, true);
SetNamespace("C_START", "C_END", ns_colormaps);
SetNamespace("A_START", "A_END", ns_acslibrary);
SetNamespace("TX_START", "TX_END", ns_newtextures);
SetNamespace("V_START", "V_END", ns_strifevoices);
SetNamespace("HI_START", "HI_END", ns_hires);
SkinHack();
delete [] fileinfo;
return true;
}
//==========================================================================
//
// IsMarker
//
// (from BOOM)
//
//==========================================================================
inline bool FWadFile::IsMarker(int lump, const char *marker)
{
if (Lumps[lump].Name[0] == marker[0])
{
return (!strcmp(Lumps[lump].Name, marker) ||
(marker[1] == '_' && !strcmp(Lumps[lump].Name+1, marker)));
}
else return false;
}
//==========================================================================
//
// SetNameSpace
//
// Sets namespace information for the lumps. It always looks for the first
// x_START and the last x_END lump, except when loading flats. In this case
// F_START may be absent and if that is the case all lumps with a size of
// 4096 will be flagged appropriately.
//
//==========================================================================
void FWadFile::SetNamespace(const char *startmarker, const char *endmarker, namespace_t space, bool flathack)
{
int start=-1, end=-1;
bool warned = false;
int i;
for(i = 0; i < (int)NumLumps; i++)
{
if (IsMarker(i, startmarker))
{
start = i;
break;
}
}
if (!flathack && start == -1) return;
for(i = NumLumps-1; i > start; i--)
{
if (IsMarker(i, endmarker))
{
end = i;
break;
}
}
if (end == -1) return;
if (start != -1)
{
for(int i = start+1; i < end; i++)
{
if (Lumps[i].Namespace != ns_global)
{
if (!warned)
{
Printf(TEXTCOLOR_YELLOW"WARNING: Overlapping namespaces found.\n");
}
warned = true;
}
else if (IsMarker(i, startmarker))
{
Printf(TEXTCOLOR_YELLOW"WARNING: Multiple %s markers found.\n", startmarker);
}
else if (IsMarker(i, endmarker))
{
Printf(TEXTCOLOR_YELLOW"WARNING: Multiple %s markers found.\n", endmarker);
}
else
{
Lumps[i].Namespace = space;
}
}
}
else if (flathack)
{
Printf(TEXTCOLOR_YELLOW"WARNING: %s marker without corresponding %s found.\n", endmarker, startmarker);
for(int i = 0; i < end; i++)
{
if (Lumps[i].LumpSize == 4096)
{
// We can't add this to the flats namespace but
// it needs to be flagged for the texture manager.
Lumps[i].Flags |= LUMPF_MAYBEFLAT;
}
}
}
}
//==========================================================================
//
// W_SkinHack
//
// Tests a wad file to see if it contains an S_SKIN marker. If it does,
// every lump in the wad is moved into a new namespace. Because skins are
// only supposed to replace player sprites, sounds, or faces, this should
// not be a problem. Yes, there are skins that replace more than that, but
// they are such a pain, and breaking them like this was done on purpose.
// This also renames any S_SKINxx lumps to just S_SKIN.
//
//==========================================================================
void FWadFile::SkinHack ()
{
static int namespc = ns_firstskin;
bool skinned = false;
bool hasmap = false;
DWORD i;
for (i = 0; i < NumLumps; i++)
{
FResourceLump *lump = &Lumps[i];
if (lump->Name[0] == 'S' &&
lump->Name[1] == '_' &&
lump->Name[2] == 'S' &&
lump->Name[3] == 'K' &&
lump->Name[4] == 'I' &&
lump->Name[5] == 'N')
{ // Wad has at least one skin.
lump->Name[6] = lump->Name[7] = 0;
if (!skinned)
{
skinned = true;
DWORD j;
for (j = 0; j < NumLumps; j++)
{
Lumps[j].Namespace = namespc;
}
namespc++;
}
}
if (lump->Name[0] == 'M' &&
lump->Name[1] == 'A' &&
lump->Name[2] == 'P')
{
hasmap = true;
}
}
if (skinned && hasmap)
{
Printf (TEXTCOLOR_BLUE
"The maps in %s will not be loaded because it has a skin.\n"
TEXTCOLOR_BLUE
"You should remove the skin from the wad to play these maps.\n",
Filename);
}
}
//==========================================================================
//
// FindStrifeTeaserVoices
//
// Strife0.wad does not have the voices between V_START/V_END markers, so
// figure out which lumps are voices based on their names.
//
//==========================================================================
void FWadFile::FindStrifeTeaserVoices ()
{
for (DWORD i = 0; i <= NumLumps; ++i)
{
if (Lumps[i].Name[0] == 'V' &&
Lumps[i].Name[1] == 'O' &&
Lumps[i].Name[2] == 'C')
{
int j;
for (j = 3; j < 8; ++j)
{
if (Lumps[i].Name[j] != 0 && !isdigit(Lumps[i].Name[j]))
break;
}
if (j == 8)
{
Lumps[i].Namespace = ns_strifevoices;
}
}
}
}
//==========================================================================
//
// File open
//
//==========================================================================
FResourceFile *CheckWad(const char *filename, FileReader *file)
{
char head[4];
file->Seek(0, SEEK_SET);
file->Read(&head, 4);
file->Seek(0, SEEK_SET);
if (!memcmp(head, "IWAD", 4) || !memcmp(head, "PWAD", 4))
{
FResourceFile *rf = new FWadFile(filename, file);
if (rf->Open()) return rf;
delete rf;
}
return NULL;
}

View File

@ -0,0 +1,407 @@
/*
** file_zip.cpp
**
**---------------------------------------------------------------------------
** Copyright 1998-2009 Randy Heit
** Copyright 2005-2009 Christoph Oelckers
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions
** are met:
**
** 1. Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** 2. Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution.
** 3. The name of the author may not be used to endorse or promote products
** derived from this software without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**---------------------------------------------------------------------------
**
**
*/
#include "resourcefile.h"
#include "cmdlib.h"
#include "templates.h"
#include "v_text.h"
#include "w_wad.h"
#include "w_zip.h"
#include "i_system.h"
#define BUFREADCOMMENT (0x400)
//-----------------------------------------------------------------------
//
// Finds the central directory end record in the end of the file.
// Taken from Quake3 source but the file in question is not GPL'ed. ;)
//
//-----------------------------------------------------------------------
static DWORD Zip_FindCentralDir(FileReader * fin)
{
unsigned char buf[BUFREADCOMMENT + 4];
DWORD FileSize;
DWORD uBackRead;
DWORD uMaxBack; // maximum size of global comment
DWORD uPosFound=0;
fin->Seek(0, SEEK_END);
FileSize = fin->Tell();
uMaxBack = MIN<DWORD>(0xffff, FileSize);
uBackRead = 4;
while (uBackRead < uMaxBack)
{
DWORD uReadSize, uReadPos;
int i;
if (uBackRead + BUFREADCOMMENT > uMaxBack)
uBackRead = uMaxBack;
else
uBackRead += BUFREADCOMMENT;
uReadPos = FileSize - uBackRead;
uReadSize = MIN<DWORD>((BUFREADCOMMENT + 4), (FileSize - uReadPos));
if (fin->Seek(uReadPos, SEEK_SET) != 0) break;
if (fin->Read(buf, (SDWORD)uReadSize) != (SDWORD)uReadSize) break;
for (i = (int)uReadSize - 3; (i--) > 0;)
{
if (buf[i] == 'P' && buf[i+1] == 'K' && buf[i+2] == 5 && buf[i+3] == 6)
{
uPosFound = uReadPos + i;
break;
}
}
if (uPosFound != 0)
break;
}
return uPosFound;
}
enum
{
LUMPFZIP_NEEDFILESTART = 128
};
//==========================================================================
//
// Zip Lump
//
//==========================================================================
struct FZipLump : public FResourceLump
{
BYTE Method;
int CompressedSize;
int Position;
virtual FileReader *GetReader();
virtual int FillCache();
private:
void SetLumpAddress();
virtual int GetFileOffset()
{
if (Method != METHOD_STORED) return -1;
if (Flags & LUMPFZIP_NEEDFILESTART) SetLumpAddress(); return Position;
}
};
//==========================================================================
//
// Zip file
//
//==========================================================================
class FZipFile : public FResourceFile
{
FZipLump *Lumps;
static int STACK_ARGS lumpcmp(const void * a, const void * b);
public:
FZipFile(const char * filename, FileReader *file);
virtual ~FZipFile();
bool Open();
virtual FResourceLump *GetLump(int no) { return ((unsigned)no < NumLumps)? &Lumps[no] : NULL; }
};
int STACK_ARGS FZipFile::lumpcmp(const void * a, const void * b)
{
FZipLump * rec1 = (FZipLump *)a;
FZipLump * rec2 = (FZipLump *)b;
return stricmp(rec1->FullName, rec2->FullName);
}
//==========================================================================
//
// Zip file
//
//==========================================================================
FZipFile::FZipFile(const char * filename, FileReader *file)
: FResourceFile(filename, file)
{
Lumps = NULL;
}
bool FZipFile::Open()
{
DWORD centraldir = Zip_FindCentralDir(Reader);
FZipEndOfCentralDirectory info;
int skipped = 0;
Lumps = NULL;
if (centraldir == 0)
{
Printf("\n%s: ZIP file corrupt!\n", Filename);
return false;
}
// Read the central directory info.
Reader->Seek(centraldir, SEEK_SET);
Reader->Read(&info, sizeof(FZipEndOfCentralDirectory));
// No multi-disk zips!
if (info.NumEntries != info.NumEntriesOnAllDisks ||
info.FirstDisk != 0 || info.DiskNumber != 0)
{
Printf("\n%s: Multipart Zip files are not supported.\n", Filename);
return false;
}
NumLumps = LittleShort(info.NumEntries);
Lumps = new FZipLump[NumLumps];
// Load the entire central directory. Too bad that this contains variable length entries...
void *directory = malloc(LittleLong(info.DirectorySize));
Reader->Seek(LittleLong(info.DirectoryOffset), SEEK_SET);
Reader->Read(directory, LittleLong(info.DirectorySize));
char *dirptr = (char*)directory;
FZipLump *lump_p = Lumps;
for (int i = 0; i < NumLumps; i++)
{
FZipCentralDirectoryInfo *zip_fh = (FZipCentralDirectoryInfo *)dirptr;
char name[256];
int len = LittleShort(zip_fh->NameLength);
strncpy(name, dirptr + sizeof(FZipCentralDirectoryInfo), MIN<int>(len, 255));
name[len] = 0;
dirptr += sizeof(FZipCentralDirectoryInfo) +
LittleShort(zip_fh->NameLength) +
LittleShort(zip_fh->ExtraLength) +
LittleShort(zip_fh->CommentLength);
// skip Directories
if(name[len - 1] == '/' && LittleLong(zip_fh->UncompressedSize) == 0)
{
skipped++;
continue;
}
// Ignore unknown compression formats
zip_fh->Method = LittleShort(zip_fh->Method);
if (zip_fh->Method != METHOD_STORED &&
zip_fh->Method != METHOD_DEFLATE &&
zip_fh->Method != METHOD_LZMA &&
zip_fh->Method != METHOD_BZIP2)
{
Printf("\n%s: '%s' uses an unsupported compression algorithm (#%d).\n", Filename, name, zip_fh->Method);
skipped++;
continue;
}
// Also ignore encrypted entries
if(LittleShort(zip_fh->Flags) & ZF_ENCRYPTED)
{
Printf("\n%s: '%s' is encrypted. Encryption is not supported.\n", Filename, name);
skipped++;
continue;
}
FixPathSeperator(name);
strlwr(name);
lump_p->LumpNameSetup(name);
lump_p->LumpSize = LittleLong(zip_fh->UncompressedSize);
lump_p->Owner = this;
// The start of the Reader will be determined the first time it is accessed.
lump_p->Flags = LUMPF_ZIPFILE | LUMPFZIP_NEEDFILESTART;
lump_p->Method = zip_fh->Method;
lump_p->CompressedSize = LittleLong(zip_fh->CompressedSize);
lump_p->Position = LittleLong(zip_fh->LocalHeaderOffset);
lump_p->CheckEmbedded();
lump_p++;
}
// Resize the lump record array to its actual size
NumLumps -= skipped;
free(directory);
//LumpInfo.Resize(NumLumps);
Printf(", %d lumps\n", NumLumps);
// Entries in Zips are sorted alphabetically.
qsort(Lumps, NumLumps, sizeof(FZipLump), lumpcmp);
return true;
}
//==========================================================================
//
// Zip file
//
//==========================================================================
FZipFile::~FZipFile()
{
if (Lumps != NULL) delete [] Lumps;
}
//==========================================================================
//
// SetLumpAddress
//
//==========================================================================
void FZipLump::SetLumpAddress()
{
// This file is inside a zip and has not been opened before.
// Position points to the start of the local file header, which we must
// read and skip so that we can get to the actual file data.
FZipLocalFileHeader localHeader;
int skiplen;
FileReader *file = Owner->Reader;
file->Seek(Position, SEEK_SET);
file->Read(&localHeader, sizeof(localHeader));
skiplen = LittleShort(localHeader.NameLength) + LittleShort(localHeader.ExtraLength);
Position += sizeof(localHeader) + skiplen;
Flags &= ~LUMPFZIP_NEEDFILESTART;
}
//==========================================================================
//
// Get reader (only returns non-NULL if not encrypted)
//
//==========================================================================
FileReader *FZipLump::GetReader()
{
// Don't return the reader if this lump is encrypted
// In that case always force caching of the lump
if (Method == METHOD_STORED)
{
if (Flags & LUMPFZIP_NEEDFILESTART) SetLumpAddress();
Owner->Reader->Seek(Position, SEEK_SET);
return Owner->Reader;
}
else return NULL;
}
//==========================================================================
//
// Fills the lump cache and performs decompression
//
//==========================================================================
int FZipLump::FillCache()
{
if (Flags & LUMPFZIP_NEEDFILESTART) SetLumpAddress();
const char *buffer;
if (Method == METHOD_STORED && (buffer = Owner->Reader->GetBuffer()) != NULL)
{
// This is an in-memory file so the cache can point directly to the file's data.
Cache = const_cast<char*>(buffer) + Position;
RefCount = -1;
return -1;
}
Owner->Reader->Seek(Position, SEEK_SET);
Cache = new char[LumpSize];
switch (Method)
{
case METHOD_STORED:
{
Owner->Reader->Read(Cache, LumpSize);
break;
}
case METHOD_DEFLATE:
{
FileReaderZ frz(*Owner->Reader, true);
frz.Read(Cache, LumpSize);
break;
}
case METHOD_BZIP2:
{
FileReaderBZ2 frz(*Owner->Reader);
frz.Read(Cache, LumpSize);
break;
}
case METHOD_LZMA:
{
FileReaderLZMA frz(*Owner->Reader, LumpSize, true);
frz.Read(Cache, LumpSize);
break;
}
default:
assert(0);
return 0;
}
RefCount = 1;
return 1;
}
//==========================================================================
//
// File open
//
//==========================================================================
FResourceFile *CheckZip(const char *filename, FileReader *file)
{
char head[4];
file->Seek(0, SEEK_SET);
file->Read(&head, 4);
file->Seek(0, SEEK_SET);
if (!memcmp(head, "PK\x3\x4", 4))
{
FResourceFile *rf = new FZipFile(filename, file);
if (rf->Open()) return rf;
delete rf;
}
return NULL;
}

View File

@ -0,0 +1,384 @@
/*
** resourcefile.cpp
**
** Base classes for resource file management
**
**---------------------------------------------------------------------------
** Copyright 2009 Christoph Oelckers
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions
** are met:
**
** 1. Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** 2. Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution.
** 3. The name of the author may not be used to endorse or promote products
** derived from this software without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**---------------------------------------------------------------------------
**
**
*/
#include "resourcefile.h"
#include "cmdlib.h"
#include "w_wad.h"
//==========================================================================
//
// FileReader that reads from a lump's cache
//
//==========================================================================
class FLumpReader : public MemoryReader
{
FResourceLump *source;
public:
FLumpReader(FResourceLump *src)
: MemoryReader(NULL, src->LumpSize), source(src)
{
src->CacheLump();
bufptr = src->Cache;
}
~FLumpReader()
{
source->ReleaseCache();
}
};
//==========================================================================
//
// Base class for resource lumps
//
//==========================================================================
FResourceLump::~FResourceLump()
{
if (FullName != NULL)
{
delete [] FullName;
FullName = NULL;
}
if (Cache != NULL)
{
delete [] Cache;
Cache = NULL;
}
Owner = NULL;
}
//==========================================================================
//
// Sets up the lump name information for anything not coming from a WAD file.
//
//==========================================================================
void FResourceLump::LumpNameSetup(char *iname)
{
char base[256];
char *lname = strrchr(iname,'/');
lname = (lname == NULL) ? iname : lname + 1;
strcpy(base, lname);
char *dot = strrchr(base, '.');
if (dot != NULL)
{
*dot = 0;
}
uppercopy(Name, base);
Name[8] = 0;
FullName = copystring(iname);
// Map some directories to WAD namespaces.
// Note that some of these namespaces don't exist in WADS.
// CheckNumForName will handle any request for these namespaces accordingly.
Namespace = !strncmp(iname, "flats/", 6) ? ns_flats :
!strncmp(iname, "textures/", 9) ? ns_newtextures :
!strncmp(iname, "hires/", 6) ? ns_hires :
!strncmp(iname, "sprites/", 8) ? ns_sprites :
!strncmp(iname, "colormaps/", 10) ? ns_colormaps :
!strncmp(iname, "acs/", 4) ? ns_acslibrary :
!strncmp(iname, "voices/", 7) ? ns_strifevoices :
!strncmp(iname, "patches/", 8) ? ns_patches :
!strncmp(iname, "graphics/", 9) ? ns_graphics :
!strncmp(iname, "sounds/", 7) ? ns_sounds :
!strncmp(iname, "music/", 6) ? ns_music :
!strchr(iname, '/') ? ns_global :
-1;
// Anything that is not in one of these subdirectories or the main directory
// should not be accessible through the standard WAD functions but only through
// the ones which look for the full name.
if (Namespace == -1)
{
memset(Name, 0, 8);
}
// Since '\' can't be used as a file name's part inside a ZIP
// we have to work around this for sprites because it is a valid
// frame character.
else if (Namespace == ns_sprites)
{
char *c;
while ((c = (char*)memchr(Name, '^', 8)))
{
*c = '\\';
}
}
}
void FResourceLump::CheckEmbedded()
{
// Checks for embedded archives
const char *c = strstr(Name, ".wad");
if (c && strlen(c) == 4 && !strchr(Name, '/'))
{
// Mark all embedded WADs
Flags |= LUMPF_EMBEDDED;
}
/* later
else
{
if (c==NULL) c = strstr(Name, ".zip");
if (c==NULL) c = strstr(Name, ".pk3");
if (c==NULL) c = strstr(Name, ".7z");
if (c && strlen(c) <= 4)
{
// Mark all embedded archives in any directory
Flags |= LUMPF_EMBEDDED;
}
}
*/
}
//==========================================================================
//
// Returns the owner's FileReader if it can be used to access this lump
//
//==========================================================================
FileReader *FResourceLump::GetReader()
{
return NULL;
}
//==========================================================================
//
// Returns a file reader to the lump's cache
//
//==========================================================================
FileReader *FResourceLump::NewReader()
{
return new FLumpReader(this);
}
//==========================================================================
//
// Caches a lump's content and increases the reference counter
//
//==========================================================================
void *FResourceLump::CacheLump()
{
if (Cache != NULL)
{
if (RefCount > 0) RefCount++;
}
else if (LumpSize > 0)
{
FillCache();
}
return Cache;
}
//==========================================================================
//
// Decrements reference counter and frees lump if counter reaches 0
//
//==========================================================================
int FResourceLump::ReleaseCache()
{
if (LumpSize > 0 && RefCount > 0)
{
if (--RefCount == 0)
{
delete [] Cache;
Cache = NULL;
}
}
return RefCount;
}
//==========================================================================
//
// Resource file base class
//
//==========================================================================
FResourceFile::FResourceFile(const char *filename, FileReader *r)
{
Filename = copystring(filename);
Reader = r;
}
FResourceFile::~FResourceFile()
{
delete [] Filename;
delete Reader;
}
//==========================================================================
//
// Needs to be virtual in the base class. Implemented only for WADs
//
//==========================================================================
void FResourceFile::FindStrifeTeaserVoices ()
{
}
//==========================================================================
//
// Caches a lump's content and increases the reference counter
//
//==========================================================================
FileReader *FUncompressedLump::GetReader()
{
Owner->Reader->Seek(Position, SEEK_SET);
return Owner->Reader;
}
//==========================================================================
//
// Caches a lump's content and increases the reference counter
//
//==========================================================================
int FUncompressedLump::FillCache()
{
const char * buffer = Owner->Reader->GetBuffer();
if (buffer != NULL)
{
// This is an in-memory file so the cache can point directly to the file's data.
Cache = const_cast<char*>(buffer) + Position;
RefCount = -1;
return -1;
}
Owner->Reader->Seek(Position, SEEK_SET);
Cache = new char[LumpSize];
Owner->Reader->Read(Cache, LumpSize);
RefCount = 1;
return 1;
}
//==========================================================================
//
// Base class for uncompressed resource files
//
//==========================================================================
FUncompressedFile::FUncompressedFile(const char *filename, FileReader *r)
: FResourceFile(filename, r)
{
Lumps = NULL;
}
FUncompressedFile::~FUncompressedFile()
{
if (Lumps != NULL) delete [] Lumps;
}
//==========================================================================
//
// external lump
//
//==========================================================================
FExternalLump::FExternalLump(const char *_filename, int filesize)
{
filename = _filename? copystring(_filename) : NULL;
if (filesize == -1)
{
FILE *f = fopen(_filename,"rb");
if (f != NULL)
{
fseek(f, 0, SEEK_END);
LumpSize = ftell(f);
fclose(f);
}
else
{
LumpSize = 0;
}
}
else
{
LumpSize = filesize;
}
}
FExternalLump::~FExternalLump()
{
if (filename != NULL) delete [] filename;
}
//==========================================================================
//
// Caches a lump's content and increases the reference counter
// For external lumps this reopens the file each time it is accessed
//
//==========================================================================
int FExternalLump::FillCache()
{
Cache = new char[LumpSize];
FILE *f = fopen(filename, "rb");
if (f != NULL)
{
fread(Cache, 1, LumpSize, f);
fclose(f);
}
else
{
memset(Cache, 0, LumpSize);
}
RefCount = 1;
return 1;
}

View File

@ -0,0 +1,115 @@
#ifndef __RESFILE_H
#define __RESFILE_H
#include "files.h"
class FResourceFile;
struct FResourceLump
{
friend class FResourceFile;
int LumpSize;
char * FullName; // only valid for files loaded from a .zip file
char Name[9];
BYTE Flags;
BYTE RefCount;
char * Cache;
FResourceFile * Owner;
int Namespace;
FResourceLump()
{
FullName = NULL;
Cache = NULL;
Owner = NULL;
Flags = 0;
RefCount = 0;
Namespace = 0; // ns_global
*Name = 0;
}
virtual ~FResourceLump();
virtual FileReader *GetReader();
virtual FileReader *NewReader();
virtual int GetFileOffset() { return -1; }
void LumpNameSetup(char *iname);
void CheckEmbedded();
void *CacheLump();
int ReleaseCache();
protected:
virtual int FillCache() = 0;
};
class FResourceFile
{
public:
FileReader *Reader;
const char *Filename;
protected:
DWORD NumLumps;
FResourceFile(const char *filename, FileReader *r);
private:
DWORD FirstLump;
public:
virtual ~FResourceFile();
FileReader *GetReader() const { return Reader; }
DWORD LumpCount() const { return NumLumps; }
DWORD GetFirstLump() const { return FirstLump; }
void SetFirstLump(DWORD f) { FirstLump = f; }
virtual void FindStrifeTeaserVoices ();
virtual bool Open() = 0;
virtual FResourceLump *GetLump(int no) = 0;
};
struct FUncompressedLump : public FResourceLump
{
int Position;
virtual FileReader *GetReader();
virtual int FillCache();
virtual int GetFileOffset() { return Position; }
};
// Base class for uncompressed resource files (WAD, GRP, PAK and single lumps)
class FUncompressedFile : public FResourceFile
{
protected:
FUncompressedLump * Lumps;
FUncompressedFile(const char *filename, FileReader *r);
virtual ~FUncompressedFile();
virtual FResourceLump *GetLump(int no) { return ((unsigned)no < NumLumps)? &Lumps[no] : NULL; }
public:
};
struct FExternalLump : public FResourceLump
{
const char *filename; // the actual file name. This is not necessarily the same as the lump name!
FExternalLump(const char *_filename, int filesize = -1);
~FExternalLump();
virtual int FillCache();
};
#endif

View File

@ -377,30 +377,12 @@ void FTextureManager::ReplaceTexture (FTextureID picnum, FTexture *newtexture, b
// //
//========================================================================== //==========================================================================
void FTextureManager::AddGroup(int wadnum, const char * startlump, const char * endlump, int ns, int usetype) void FTextureManager::AddGroup(int wadnum, int ns, int usetype)
{ {
int firsttx; int firsttx = Wads.GetFirstLump(wadnum);
int lasttx; int lasttx = Wads.GetLastLump(wadnum);
if (startlump && endlump)
{
firsttx = Wads.CheckNumForName (startlump);
lasttx = Wads.CheckNumForName (endlump);
}
else
{
// If there are no markers we have to search the entire lump directory... :(
firsttx = 0;
lasttx = Wads.GetNumLumps() - 1;
}
char name[9]; char name[9];
if (firsttx == -1 || lasttx == -1)
{
return;
}
name[8] = 0; name[8] = 0;
// Go from first to last so that ANIMDEFS work as expected. However, // Go from first to last so that ANIMDEFS work as expected. However,
@ -408,9 +390,9 @@ void FTextureManager::AddGroup(int wadnum, const char * startlump, const char *
// later ones), the texture is only inserted if it is the one returned // later ones), the texture is only inserted if it is the one returned
// by doing a check by name in the list of wads. // by doing a check by name in the list of wads.
for (firsttx += 1; firsttx < lasttx; ++firsttx) for (; firsttx <= lasttx; ++firsttx)
{ {
if (Wads.GetLumpFile(firsttx) == wadnum && Wads.GetLumpNamespace(firsttx) == ns) if (Wads.GetLumpNamespace(firsttx) == ns)
{ {
Wads.GetLumpName (name, firsttx); Wads.GetLumpName (name, firsttx);
@ -420,6 +402,14 @@ void FTextureManager::AddGroup(int wadnum, const char * startlump, const char *
} }
StartScreen->Progress(); StartScreen->Progress();
} }
else if (ns == ns_flats && Wads.GetLumpFlags(firsttx) & LUMPF_MAYBEFLAT)
{
if (Wads.CheckNumForName (name, ns) < firsttx)
{
CreateTexture (firsttx, usetype);
}
StartScreen->Progress();
}
} }
} }
@ -431,8 +421,9 @@ void FTextureManager::AddGroup(int wadnum, const char * startlump, const char *
void FTextureManager::AddHiresTextures (int wadnum) void FTextureManager::AddHiresTextures (int wadnum)
{ {
int firsttx = Wads.CheckNumForName ("HI_START"); int firsttx = Wads.GetFirstLump(wadnum);
int lasttx = Wads.CheckNumForName ("HI_END"); int lasttx = Wads.GetLastLump(wadnum);
char name[9]; char name[9];
TArray<FTextureID> tlist; TArray<FTextureID> tlist;
@ -443,15 +434,15 @@ void FTextureManager::AddHiresTextures (int wadnum)
name[8] = 0; name[8] = 0;
for (firsttx += 1; firsttx < lasttx; ++firsttx) for (;firsttx <= lasttx; ++firsttx)
{ {
if (Wads.GetLumpFile(firsttx) == wadnum) if (Wads.GetLumpNamespace(firsttx) == ns_hires)
{ {
tlist.Clear();
Wads.GetLumpName (name, firsttx); Wads.GetLumpName (name, firsttx);
if (Wads.CheckNumForName (name, ns_hires) == firsttx) if (Wads.CheckNumForName (name, ns_hires) == firsttx)
{ {
tlist.Clear();
int amount = ListTextures(name, tlist); int amount = ListTextures(name, tlist);
if (amount == 0) if (amount == 0)
{ {
@ -717,28 +708,27 @@ void FTextureManager::AddTexturesForWad(int wadnum)
int lumpcount = Wads.GetNumLumps(); int lumpcount = Wads.GetNumLumps();
// First step: Load sprites // First step: Load sprites
AddGroup(wadnum, "S_START", "S_END", ns_sprites, FTexture::TEX_Sprite); AddGroup(wadnum, ns_sprites, FTexture::TEX_Sprite);
// When loading a Zip, all graphics in the patches/ directory should be // When loading a Zip, all graphics in the patches/ directory should be
// added as well. // added as well.
AddGroup(wadnum, NULL, NULL, ns_patches, FTexture::TEX_WallPatch); AddGroup(wadnum, ns_patches, FTexture::TEX_WallPatch);
// Second step: TEXTUREx lumps // Second step: TEXTUREx lumps
LoadTextureX(wadnum); LoadTextureX(wadnum);
// Third step: Flats // Third step: Flats
AddGroup(wadnum, "F_START", "F_END", ns_flats, FTexture::TEX_Flat); AddGroup(wadnum, ns_flats, FTexture::TEX_Flat);
// Fourth step: Textures (TX_) // Fourth step: Textures (TX_)
AddGroup(wadnum, "TX_START", "TX_END", ns_newtextures, FTexture::TEX_Override); AddGroup(wadnum, ns_newtextures, FTexture::TEX_Override);
// Sixth step: Try to find any lump in the WAD that may be a texture and load as a TEX_MiscPatch // Sixth step: Try to find any lump in the WAD that may be a texture and load as a TEX_MiscPatch
for (int i = 0; i < lumpcount; i++) int firsttx = Wads.GetFirstLump(wadnum);
{ int lasttx = Wads.GetLastLump(wadnum);
int file = Wads.GetLumpFile(i);
if (file > wadnum) break; // lumps in the global namespace are ordered by WAD
if (file < wadnum) continue;
for (int i= firsttx; i <= lasttx; i++)
{
char name[9]; char name[9];
Wads.GetLumpName(name, i); Wads.GetLumpName(name, i);
name[8]=0; name[8]=0;
@ -766,7 +756,7 @@ void FTextureManager::AddTexturesForWad(int wadnum)
if (Wads.CheckLumpName(i, "BLOCKMAP")) continue; if (Wads.CheckLumpName(i, "BLOCKMAP")) continue;
if (Wads.CheckLumpName(i, "BEHAVIOR")) continue; if (Wads.CheckLumpName(i, "BEHAVIOR")) continue;
// Don't bother looking this lump if something later overrides it. // Don't bother looking at this lump if something later overrides it.
if (Wads.CheckNumForName(name, ns_graphics) != i) continue; if (Wads.CheckNumForName(name, ns_graphics) != i) continue;
// skip this if it has already been added as a wall patch. // skip this if it has already been added as a wall patch.

View File

@ -300,7 +300,7 @@ public:
void AddTexturesLump (const void *lumpdata, int lumpsize, int deflumpnum, int patcheslump, int firstdup=0, bool texture1=false); void AddTexturesLump (const void *lumpdata, int lumpsize, int deflumpnum, int patcheslump, int firstdup=0, bool texture1=false);
void AddTexturesLumps (int lump1, int lump2, int patcheslump); void AddTexturesLumps (int lump1, int lump2, int patcheslump);
void AddGroup(int wadnum, const char * startlump, const char * endlump, int ns, int usetype); void AddGroup(int wadnum, int ns, int usetype);
void AddPatches (int lumpnum); void AddPatches (int lumpnum);
void AddTiles (void *tileFile); void AddTiles (void *tileFile);
void AddHiresTextures (int wadnum); void AddHiresTextures (int wadnum);

File diff suppressed because it is too large Load Diff

View File

@ -27,26 +27,9 @@
#include "doomdef.h" #include "doomdef.h"
#include "tarray.h" #include "tarray.h"
// [RH] Compare wad header as ints instead of chars class FResourceFile;
#define IWAD_ID MAKE_ID('I','W','A','D') struct FResourceLump;
#define PWAD_ID MAKE_ID('P','W','A','D')
#define RFF_ID MAKE_ID('R','F','F',0x1a)
#define ZIP_ID MAKE_ID('P','K',3,4)
#define GRP_ID_0 MAKE_ID('K','e','n','S')
#define GRP_ID_1 MAKE_ID('i','l','v','e')
#define GRP_ID_2 MAKE_ID('r','m','a','n')
// [RH] Remove limit on number of WAD files
struct wadlist_t
{
wadlist_t *next;
char name[1]; // +size of string
};
extern wadlist_t *wadfiles;
//
// TYPES
//
struct wadinfo_t struct wadinfo_t
{ {
// Should be "IWAD" or "PWAD". // Should be "IWAD" or "PWAD".
@ -62,17 +45,18 @@ struct wadlump_t
char Name[8]; char Name[8];
}; };
enum #define IWAD_ID MAKE_ID('I','W','A','D')
{ #define PWAD_ID MAKE_ID('P','W','A','D')
LUMPF_BLOODCRYPT = 1, // Lump uses Blood-style encryption
LUMPF_COMPRESSED = 2, // Zip-compressed
LUMPF_ZIPFILE = 4, // Inside a Zip file - used to enforce use of special directories insize Zips
LUMPF_NEEDFILESTART = 8, // Still need to process local file header to find file start inside a zip
LUMPF_EXTERNAL = 16, // Lump is from an external file that won't be kept open permanently
LUMPF_7ZFILE = 32, // Inside a 7z archive; position is its index in the archive
};
// [RH] Remove limit on number of WAD files
struct wadlist_t
{
wadlist_t *next;
char name[1]; // +size of string
};
extern wadlist_t *wadfiles;
// [RH] Namespaces from BOOM. // [RH] Namespaces from BOOM.
typedef enum { typedef enum {
ns_global = 0, ns_global = 0,
@ -96,17 +80,22 @@ typedef enum {
ns_patches, ns_patches,
ns_graphics, ns_graphics,
ns_music, ns_music,
ns_firstskin,
} namespace_t; } namespace_t;
enum ELumpFlags
{
LUMPF_MAYBEFLAT=1,
LUMPF_ZIPFILE=2,
LUMPF_EMBEDDED=4,
LUMPF_BLOODCRYPT = 8,
};
// [RH] Copy an 8-char string and uppercase it. // [RH] Copy an 8-char string and uppercase it.
void uppercopy (char *to, const char *from); void uppercopy (char *to, const char *from);
// Perform Blood encryption/decryption.
void BloodCrypt (void *data, int key, int len);
// Locate central directory in a zip file.
DWORD Zip_FindCentralDir(FileReader * fin);
// A very loose reference to a lump on disk. This is really just a wrapper // A very loose reference to a lump on disk. This is really just a wrapper
// around the main wad's FILE object with a different length recorded. Since // around the main wad's FILE object with a different length recorded. Since
// two lumps from the same wad share the same FILE, you cannot read from // two lumps from the same wad share the same FILE, you cannot read from
@ -126,13 +115,9 @@ public:
char *Gets(char *strbuf, int len); char *Gets(char *strbuf, int len);
private: private:
FWadLump (const FileReader &reader, long length, bool encrypted); FWadLump (FResourceLump *Lump, bool alwayscache = false);
FWadLump (FILE *file, long length);
FWadLump (char * data, long length, bool destroy);
char *SourceData; FResourceLump *Lump;
bool DestroySource;
bool Encrypted;
friend class FWadCollection; friend class FWadCollection;
}; };
@ -169,12 +154,15 @@ public:
enum { IWAD_FILENUM = 1 }; enum { IWAD_FILENUM = 1 };
void InitMultipleFiles (wadlist_t **filenames); void InitMultipleFiles (wadlist_t **filenames);
void AddFile (const char *filename, const char *data=NULL, int length=-1); void AddFile (const char *filename, FileReader *wadinfo = NULL);
int CheckIfWadLoaded (const char *name); int CheckIfWadLoaded (const char *name);
const char *GetWadName (int wadnum) const; const char *GetWadName (int wadnum) const;
const char *GetWadFullName (int wadnum) const; const char *GetWadFullName (int wadnum) const;
int GetFirstLump(int wadnum) const;
int GetLastLump(int wadnum) const;
int CheckNumForName (const char *name, int namespc); int CheckNumForName (const char *name, int namespc);
int CheckNumForName (const char *name, int namespc, int wadfile, bool exact = true); int CheckNumForName (const char *name, int namespc, int wadfile, bool exact = true);
int GetNumForName (const char *name, int namespc); int GetNumForName (const char *name, int namespc);
@ -225,36 +213,26 @@ public:
int AddExternalFile(const char *filename); int AddExternalFile(const char *filename);
protected: protected:
class WadFileRecord;
struct LumpRecord; struct LumpRecord;
TArray<FResourceFile *> Files;
TArray<LumpRecord> LumpInfo;
DWORD *FirstLumpIndex; // [RH] Hashing stuff moved out of lumpinfo structure DWORD *FirstLumpIndex; // [RH] Hashing stuff moved out of lumpinfo structure
DWORD *NextLumpIndex; DWORD *NextLumpIndex;
DWORD *FirstLumpIndex_FullName; // The same information for fully qualified paths from .zips DWORD *FirstLumpIndex_FullName; // The same information for fully qualified paths from .zips
DWORD *NextLumpIndex_FullName; DWORD *NextLumpIndex_FullName;
TArray<LumpRecord> LumpInfo;
TArray<WadFileRecord *> Wads;
DWORD NumLumps; // Not necessarily the same as LumpInfo.Size() DWORD NumLumps; // Not necessarily the same as LumpInfo.Size()
DWORD NumWads; DWORD NumWads;
void SkinHack (int baselump); void SkinHack (int baselump);
void InitHashChains (); // [RH] Set up the lumpinfo hashing void InitHashChains (); // [RH] Set up the lumpinfo hashing
// [RH] Combine multiple marked ranges of lumps into one.
int MergeLumps (const char *start, const char *end, int name_space);
bool IsMarker (const LumpRecord *lump, const char *marker) const;
void FindStrifeTeaserVoices ();
char *ReadZipLump(LumpRecord *l);
private: private:
static int STACK_ARGS lumpcmp(const void * a, const void * b);
void ScanForFlatHack (int startlump);
void RenameSprites (int startlump); void RenameSprites (int startlump);
void SetLumpAddress(LumpRecord *l);
void DeleteAll(); void DeleteAll();
}; };

View File

@ -1648,8 +1648,7 @@ void WI_updateStats ()
{ {
WI_updateAnimatedBack (); WI_updateAnimatedBack ();
if ((!(gameinfo.gametype & GAME_DoomChex) || acceleratestage) if ((!gameinfo.intermissioncounter || acceleratestage) && sp_state != 10)
&& sp_state != 10)
{ {
if (acceleratestage) if (acceleratestage)
{ {
@ -1667,7 +1666,7 @@ void WI_updateStats ()
if (sp_state == 2) if (sp_state == 2)
{ {
if (gameinfo.gametype & GAME_DoomChex) if (gameinfo.intermissioncounter)
{ {
cnt_kills[0] += 2; cnt_kills[0] += 2;
@ -1683,7 +1682,7 @@ void WI_updateStats ()
} }
else if (sp_state == 4) else if (sp_state == 4)
{ {
if (gameinfo.gametype & GAME_DoomChex) if (gameinfo.intermissioncounter)
{ {
cnt_items[0] += 2; cnt_items[0] += 2;
@ -1699,7 +1698,7 @@ void WI_updateStats ()
} }
else if (sp_state == 6) else if (sp_state == 6)
{ {
if (gameinfo.gametype & GAME_DoomChex) if (gameinfo.intermissioncounter)
{ {
cnt_secret[0] += 2; cnt_secret[0] += 2;
@ -1715,7 +1714,7 @@ void WI_updateStats ()
} }
else if (sp_state == 8) else if (sp_state == 8)
{ {
if (gameinfo.gametype & GAME_DoomChex) if (gameinfo.intermissioncounter)
{ {
if (!(bcnt&3)) if (!(bcnt&3))
S_Sound (CHAN_VOICE | CHAN_UI, "intermission/tick", 1, ATTN_NONE); S_Sound (CHAN_VOICE | CHAN_UI, "intermission/tick", 1, ATTN_NONE);

View File

@ -25,6 +25,7 @@ gameinfo
backpacktype = "ZorchPack" backpacktype = "ZorchPack"
statusbar = "sbarinfo/doom.txt" statusbar = "sbarinfo/doom.txt"
intermissionmusic = "$MUSIC_INTER" intermissionmusic = "$MUSIC_INTER"
intermissioncounter = true
weaponslot = 1, "Bootspoon", "SuperBootspork" weaponslot = 1, "Bootspoon", "SuperBootspork"
weaponslot = 2, "MiniZorcher" weaponslot = 2, "MiniZorcher"
weaponslot = 3, "LargeZorcher", "SuperLargeZorcher" weaponslot = 3, "LargeZorcher", "SuperLargeZorcher"

View File

@ -25,6 +25,7 @@ gameinfo
backpacktype = "Backpack" backpacktype = "Backpack"
statusbar = "sbarinfo/doom.txt" statusbar = "sbarinfo/doom.txt"
intermissionmusic = "$MUSIC_DM2INT" intermissionmusic = "$MUSIC_DM2INT"
intermissioncounter = true
weaponslot = 1, "Fist", "Chainsaw" weaponslot = 1, "Fist", "Chainsaw"
weaponslot = 2, "Pistol" weaponslot = 2, "Pistol"
weaponslot = 3, "Shotgun", "SuperShotgun" weaponslot = 3, "Shotgun", "SuperShotgun"

View File

@ -25,6 +25,7 @@ gameinfo
backpacktype = "BagOfHolding" backpacktype = "BagOfHolding"
statusbar = "" statusbar = ""
intermissionmusic = "mus_intr" intermissionmusic = "mus_intr"
intermissioncounter = false
weaponslot = 1, "Staff", "Gauntlets" weaponslot = 1, "Staff", "Gauntlets"
weaponslot = 2, "GoldWand" weaponslot = 2, "GoldWand"
weaponslot = 3, "Crossbow" weaponslot = 3, "Crossbow"

View File

@ -28,6 +28,7 @@ gameinfo
backpacktype = "BagOfHolding" // Hexen doesn't have a backpack so use Heretic's. backpacktype = "BagOfHolding" // Hexen doesn't have a backpack so use Heretic's.
statusbar = "" statusbar = ""
intermissionmusic = "hub" intermissionmusic = "hub"
intermissioncounter = false
weaponslot = 1, "FWeapFist", "CWeapMace", "MWeapWand" weaponslot = 1, "FWeapFist", "CWeapMace", "MWeapWand"
weaponslot = 2, "FWeapAxe", "CWeapStaff", "MWeapFrost" weaponslot = 2, "FWeapAxe", "CWeapStaff", "MWeapFrost"
weaponslot = 3, "FWeapHammer", "CWeapFlame", "MWeapLightning" weaponslot = 3, "FWeapHammer", "CWeapFlame", "MWeapLightning"

View File

@ -25,6 +25,7 @@ gameinfo
backpacktype = "AmmoSatchel" backpacktype = "AmmoSatchel"
statusbar = "" statusbar = ""
intermissionmusic = "d_slide" intermissionmusic = "d_slide"
intermissioncounter = false
weaponslot = 1, "PunchDagger" weaponslot = 1, "PunchDagger"
weaponslot = 2, "StrifeCrossbow2", "StrifeCrossbow" weaponslot = 2, "StrifeCrossbow2", "StrifeCrossbow"
weaponslot = 3, "AssaultGun" weaponslot = 3, "AssaultGun"

File diff suppressed because it is too large Load Diff