diff --git a/docs/rh-log.txt b/docs/rh-log.txt index f166999008..9807e265a6 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,4 +1,8 @@ June 14, 2006 +- Fixed loading of Build/Blood maps. +- FWadLump::Read() now handles Blood decryption directly. +- Fixed: A fatal error thrown during map loading after the sectors have been + counted but before they are allocated crashed in PointerSubstitution(). - Removed my "backwards compatibility fix" for APROP_Speed. It turns out that in all the public versions where monster speed is not fixed point, you couldn't modify the monster's speed due to a bug in P_Move() anyway. So diff --git a/src/dobject.cpp b/src/dobject.cpp index cf404e6fff..221cd2227e 100644 --- a/src/dobject.cpp +++ b/src/dobject.cpp @@ -499,11 +499,14 @@ void DObject::PointerSubstitution (DObject *old, DObject *notOld) players[i].FixPointers (old, notOld); } - for (i = 0; i < (unsigned int)numsectors; ++i) + if (sectors != NULL) { - if (sectors[i].SoundTarget == old) + for (i = 0; i < (unsigned int)numsectors; ++i) { - sectors[i].SoundTarget = static_cast(notOld); + if (sectors[i].SoundTarget == old) + { + sectors[i].SoundTarget = static_cast(notOld); + } } } } diff --git a/src/p_buildmap.cpp b/src/p_buildmap.cpp index 36519a8136..b7b3fc76c5 100644 --- a/src/p_buildmap.cpp +++ b/src/p_buildmap.cpp @@ -742,6 +742,8 @@ static void CalcPlane (SlopeWork &slope, secplane_t &plane) // // Decrypt // +// Note that this is different from the general RFF encryption. +// //========================================================================== static void Decrypt (void *to_, const void *from_, int len, int key) @@ -749,13 +751,9 @@ static void Decrypt (void *to_, const void *from_, int len, int key) BYTE *to = (BYTE *)to_; const BYTE *from = (const BYTE *)from_; - while (len > 0) + for (int i = 0; i < len; ++i, ++key) { - *to = *from ^ key; - to++; - from++; - key++; - len--; + to[i] = from[i] ^ key; } } diff --git a/src/p_setup.cpp b/src/p_setup.cpp index ff7ec8c1ce..25855def88 100644 --- a/src/p_setup.cpp +++ b/src/p_setup.cpp @@ -181,30 +181,33 @@ static void P_SetSideNum (DWORD *sidenum_p, WORD sidenum); // // GetMapIndex // -// Gets the type of map lump or -1 if invalid +// Gets the type of map lump or -1 if invalid or -2 if required and not found. // //=========================================================================== -static int GetMapIndex(const char * mapname, int lastindex, const char * lumpname) +struct checkstruct { - static struct checkstruct + char *lumpname; + bool required; +}; + +static int GetMapIndex(const char *mapname, int lastindex, const char *lumpname, bool needrequired) +{ + static const checkstruct check[] = { - char * lumpname; - bool required; - } check[]={ - {NULL, true}, - {"THINGS", true}, + {NULL, true}, + {"THINGS", true}, {"LINEDEFS", true}, {"SIDEDEFS", true}, {"VERTEXES", true}, - {"SEGS", false}, + {"SEGS", false}, {"SSECTORS", false}, - {"NODES", false}, - {"SECTORS", true}, - {"REJECT", false}, + {"NODES", false}, + {"SECTORS", true}, + {"REJECT", false}, {"BLOCKMAP", false}, {"BEHAVIOR", false}, - {"SCRIPTS", false}, + {"SCRIPTS", false}, }; if (lumpname==NULL) lumpname=""; @@ -216,7 +219,11 @@ static int GetMapIndex(const char * mapname, int lastindex, const char * lumpnam if (check[i].required) { - I_Error("'%s' not found in %s\n", check[i].lumpname, mapname); + if (needrequired) + { + I_Error("'%s' not found in %s\n", check[i].lumpname, mapname); + } + return -2; } } @@ -229,7 +236,7 @@ static int GetMapIndex(const char * mapname, int lastindex, const char * lumpnam // //=========================================================================== -MapData * P_OpenMapData(const char * mapname) +MapData *P_OpenMapData(const char * mapname) { MapData * map = new MapData; bool externalfile = !strnicmp(mapname, "file:", 5); @@ -237,7 +244,7 @@ MapData * P_OpenMapData(const char * mapname) if (externalfile) { - mapname+=5; + mapname += 5; if (!FileExists(mapname)) { delete map; @@ -269,14 +276,20 @@ MapData * P_OpenMapData(const char * mapname) map->MapLumps[0].FilePos = Wads.GetLumpOffset(lump_name); map->MapLumps[0].Size = Wads.LumpLength(lump_name); + map->Encrypted = Wads.IsEncryptedFile(lump_name); - int index=0; - for(int i=1;;i++) + if (map->Encrypted) + { // If it's encrypted, then it's a Blood file, presumably a map. + return map; + } + + int index = 0; + for(int i = 1;; i++) { // Since levels must be stored in WADs they can't really have full // names and for any valid level lump this always returns the short name. const char * lumpname = Wads.GetLumpFullName(lump_name + i); - index = GetMapIndex(mapname, index, lumpname); + index = GetMapIndex(mapname, index, lumpname, i != 1 || map->MapLumps[0].Size == 0); // The next lump is not part of this map anymore if (index < 0) break; @@ -325,7 +338,7 @@ MapData * P_OpenMapData(const char * mapname) if (i>0) { - index = GetMapIndex(maplabel, index, lumpname); + index = GetMapIndex(maplabel, index, lumpname, true); // The next lump is not part of this map anymore if (index < 0) break; @@ -468,7 +481,6 @@ void P_FloodZones () void P_LoadVertexes (MapData * map) { - FWadLump data; int i; // Determine number of vertices: @@ -3362,7 +3374,18 @@ void P_SetupLevel (char *lumpname, int position) if (map->MapLumps[0].Size > 0) { BYTE *mapdata = new BYTE[map->MapLumps[0].Size]; + map->Seek(0); map->file->Read(mapdata, map->MapLumps[0].Size); + if (map->Encrypted) + { + // Why can't the linker find this function? Ugh. + //BloodCrypt (mapdata, 0, MIN (map->MapLumps[0].Size, 256)); + int len = MIN (map->MapLumps[0].Size, 256); + for (int i = 0; i < len; ++i) + { + mapdata[i] ^= i >> 1; + } + } buildmap = P_LoadBuildMap (mapdata, map->MapLumps[0].Size, &buildthings, &numbuildthings); delete[] mapdata; } diff --git a/src/p_setup.h b/src/p_setup.h index 5a31669423..f6c97c92c8 100644 --- a/src/p_setup.h +++ b/src/p_setup.h @@ -33,6 +33,7 @@ struct MapData wadlump_t MapLumps[ML_BEHAVIOR+1]; bool HasBehavior; bool CloseOnDestruct; + bool Encrypted; int lumpnum; FileReader * file; @@ -40,9 +41,10 @@ struct MapData { memset(MapLumps, 0, sizeof(MapLumps)); file = NULL; - lumpnum=-1; - HasBehavior=false; - CloseOnDestruct=true; + lumpnum = -1; + HasBehavior = false; + CloseOnDestruct = true; + Encrypted = false; } ~MapData() diff --git a/src/w_wad.cpp b/src/w_wad.cpp index 98dbed1f2f..ce56e67d3f 100644 --- a/src/w_wad.cpp +++ b/src/w_wad.cpp @@ -1603,10 +1603,6 @@ void FWadCollection::ReadLump (int lump, void *dest) I_Error ("W_ReadLump: only read %ld of %ld on lump %i\n", numread, size, lump); } - if (LumpInfo[lump].flags & LUMPF_BLOODCRYPT) - { - BloodCrypt (dest, 0, MIN (size, 256)); - } } //========================================================================== @@ -1629,10 +1625,6 @@ FMemLump FWadCollection::ReadLump (int lump) I_Error ("W_ReadLump: only read %ld of %ld on lump %i\n", numread, size, lump); } - if (LumpInfo[lump].flags & LUMPF_BLOODCRYPT) - { - BloodCrypt (dest, 0, MIN (size, 256)); - } return FMemLump (dest); } @@ -1657,40 +1649,29 @@ FWadLump FWadCollection::OpenLumpNum (int lump) l = &LumpInfo[lump]; wad = Wads[l->wadnum]; - -#if 0 - // Blood encryption? - if (writeable || l->flags & LUMPF_BLOODCRYPT) - { - ptr = Malloc (l->size); - NonMappedPointers.insert (ptr); - W_ReadLump (lump, ptr); - return ptr; - } -#endif - wad->Seek (l->position, SEEK_SET); if (l->flags & LUMPF_COMPRESSED) { // A compressed entry in a .zip file char * buffer = new char[l->size+1]; // the last byte is used as a reference counter + buffer[l->size] = 0; FileReaderZ frz(*wad, true); frz.Read(buffer, l->size); return FWadLump(buffer, l->size, true); } - else if (wad->MemoryData!=NULL) + else if (wad->MemoryData != NULL) { // A lump from an embedded WAD // Handling this here creates less overhead than trying // to do it inside the FWadLump class. - return FWadLump((char*)wad->MemoryData+l->position, l->size, false); + return FWadLump((char*)wad->MemoryData + l->position, l->size, false); } else { // An uncompressed lump in a .wad or .zip - return FWadLump (*wad, l->size); + return FWadLump (*wad, l->size, !!(l->flags & LUMPF_BLOODCRYPT)); } } @@ -1835,6 +1816,23 @@ bool FWadCollection::IsUncompressedFile(int lump) const else return true; } +//========================================================================== +// +// IsEncryptedFile +// +// Returns true if the first 256 bytes of the lump are encrypted for Blood. +// +//========================================================================== + +bool FWadCollection::IsEncryptedFile(int lump) const +{ + if ((unsigned)lump >= (unsigned)NumLumps) + { + return false; + } + return !!(LumpInfo[lump].flags & LUMPF_BLOODCRYPT); +} + //========================================================================== // // W_SkinHack @@ -1901,7 +1899,7 @@ void FWadCollection::SkinHack (int baselump) // //========================================================================== -static void BloodCrypt (void *data, int key, int len) +void BloodCrypt (void *data, int key, int len) { int p = (BYTE)key, i; @@ -2013,7 +2011,7 @@ long FWadCollection::WadFileRecord::Read (void *buffer, long len) // FWadLump ----------------------------------------------------------------- FWadLump::FWadLump () -: FileReader (), sourceData(NULL) +: FileReader(), SourceData(NULL), DestroySource(false), Encrypted(false) { } @@ -2021,17 +2019,16 @@ FWadLump::FWadLump (const FWadLump ©) { // This must be defined isn't called. File = copy.File; - Length=copy.Length; - FilePos=copy.FilePos; - StartPos=copy.StartPos; - CloseOnDestruct=false; - if (copy.sourceData!=NULL) + Length = copy.Length; + FilePos = copy.FilePos; + StartPos = copy.StartPos; + CloseOnDestruct = false; + SourceData = copy.SourceData; + DestroySource = copy.DestroySource; + if (SourceData != NULL && DestroySource) { - sourceData=copy.sourceData; - destroySource=copy.destroySource; - if (destroySource) sourceData[copy.Length]++; + SourceData[copy.Length]++; } - else sourceData=NULL; } #ifdef _DEBUG @@ -2039,83 +2036,113 @@ FWadLump & FWadLump::operator= (const FWadLump ©) { // Only the debug build actually calls this! File = copy.File; - Length=copy.Length; - FilePos=copy.FilePos; - StartPos=copy.StartPos; - CloseOnDestruct=false; // For WAD lumps this is always false! - if (copy.sourceData!=NULL) + Length = copy.Length; + FilePos = copy.FilePos; + StartPos = copy.StartPos; + CloseOnDestruct = false; // For WAD lumps this is always false! + SourceData = copy.SourceData; + DestroySource = copy.DestroySource; + if (SourceData != NULL && DestroySource) { - sourceData=copy.sourceData; - destroySource=copy.destroySource; - if (destroySource) sourceData[copy.Length]++; + SourceData[copy.Length]++; } - else sourceData=NULL; return *this; } #endif -FWadLump::FWadLump (const FileReader &other, long length) -: FileReader (other, length), sourceData(NULL) +FWadLump::FWadLump (const FileReader &other, long length, bool encrypted) +: FileReader(other, length), SourceData(NULL), DestroySource(false), Encrypted(encrypted) { } FWadLump::FWadLump (FILE *file, long length) -: FileReader (file, length), sourceData(NULL) +: FileReader(file, length), SourceData(NULL), DestroySource(false), Encrypted(false) { } -FWadLump::FWadLump (char * data, long length, bool destroy) -: FileReader (), sourceData(data) +FWadLump::FWadLump (char *data, long length, bool destroy) +: FileReader(), SourceData(data), DestroySource(destroy), Encrypted(false) { FilePos = StartPos = 0; - Length=length; - destroySource=destroy; - if (destroySource) data[length]=0; + Length = length; + if (destroy) + { + data[length] = 0; + } } FWadLump::~FWadLump() { - if (sourceData && destroySource) + if (SourceData && DestroySource) { - if (sourceData[Length]==0) delete [] sourceData; - else sourceData[Length]--; + if (SourceData[Length] == 0) + { + delete[] SourceData; + } + else + { + SourceData[Length]--; + } } } long FWadLump::Seek (long offset, int origin) { - if (sourceData) + if (SourceData) { switch (origin) { case SEEK_CUR: - offset+=FilePos; + offset += FilePos; break; case SEEK_END: - offset+=Length; + offset += Length; break; + default: break; } - if (offset<0) offset=0; - else if (offset>Length) offset=Length; - FilePos=offset; + FilePos = clamp (offset, 0, Length); return 0; } - else return FileReader::Seek(offset, origin); + return FileReader::Seek(offset, origin); } long FWadLump::Read (void *buffer, long len) { - if (sourceData) + long numread; + long startread = FilePos; + + if (SourceData != NULL) { - if (FilePos+len>Length) len=Length-FilePos; - memcpy(buffer, sourceData+FilePos, len); - FilePos+=len; - return len; + if (FilePos + len > Length) + { + len = Length - FilePos; + } + memcpy(buffer, SourceData + FilePos, len); + FilePos += len; + numread = len; } - else return FileReader::Read(buffer, len); + else + { + numread = FileReader::Read(buffer, len); + } + + // Blood, you are so mean to me with your encryption. + if (Encrypted && startread - StartPos < 256) + { + int cryptstart = startread - StartPos; + int cryptlen = MIN (FilePos - StartPos, 256); + BYTE *data = (BYTE *)buffer - cryptstart; + + for (int i = cryptstart; i < cryptlen; ++i) + { + data[i] ^= i >> 1; + } + } + + return numread; } // FMemLump ----------------------------------------------------------------- diff --git a/src/w_wad.h b/src/w_wad.h index 8e3c7a3487..b462495d51 100644 --- a/src/w_wad.h +++ b/src/w_wad.h @@ -79,6 +79,9 @@ typedef enum { // [RH] Copy an 8-char string and uppercase it. void uppercopy (char *to, const char *from); +// Perform Blood encryption/decryption. +void BloodCrypt (void *data, int key, int len); + // 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 // the two lumps from the same wad share the same FILE, you cannot read from @@ -97,12 +100,13 @@ public: long Read (void *buffer, long len); private: - FWadLump (const FileReader &reader, long length); + FWadLump (const FileReader &reader, long length, bool encrypted); FWadLump (FILE *file, long length); FWadLump (char * data, long length, bool destroy); - char * sourceData; - bool destroySource; + char *SourceData; + bool DestroySource; + bool Encrypted; friend class FWadCollection; }; @@ -189,7 +193,7 @@ public: bool CheckLumpName (int lump, const char *name) const; // [RH] Returns true if the names match bool IsUncompressedFile(int lump) const; - + bool IsEncryptedFile(int lump) const; int GetNumLumps () const;