From b9fa7626bc4fce6a5d6a3904aa032e7c49ba4f6a Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Fri, 15 May 2009 03:11:44 +0000 Subject: [PATCH] - Fixed non-POD passing in G_BuildSaveName() and other things GCC warned about. - Added support for imploded zips. SVN r1581 (trunk) --- docs/rh-log.txt | 7 +- src/CMakeLists.txt | 1 + src/g_game.cpp | 9 +- src/p_enemy.cpp | 2 +- src/p_setup.cpp | 2 +- src/r_data.cpp | 2 +- src/resourcefiles/explode.cpp | 289 +++++++++++++ src/resourcefiles/explode.h | 52 +++ src/resourcefiles/file_7z.cpp | 2 +- src/resourcefiles/file_wad.cpp | 4 +- src/resourcefiles/file_zip.cpp | 22 +- src/w_wad.cpp | 2 +- src/w_zip.h | 1 + zdoom.vcproj | 758 +++++++++++++++++---------------- 14 files changed, 759 insertions(+), 394 deletions(-) create mode 100644 src/resourcefiles/explode.cpp create mode 100644 src/resourcefiles/explode.h diff --git a/docs/rh-log.txt b/docs/rh-log.txt index d41ecf3a9..d4f5ba316 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,4 +1,9 @@ -May 11, 2009 (Changes by Graf Zahl) +May 14, 2009 +- Fixed non-POD passing in G_BuildSaveName() and other things GCC warned + about. +- Added support for imploded zips. + +May 11, 2009 (Changes by Graf Zahl) - Fixed: Some missile spawning functions ignored the FastSpeed setting. - Fixed: P_CheckSwitchRange tried to access a line's backsector without checking if it is valid. diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index c5dbb17a7..df5178e91 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -656,6 +656,7 @@ add_executable( zdoom WIN32 oplsynth/music_opldumper_mididevice.cpp oplsynth/music_opl_mididevice.cpp oplsynth/opl_mus_player.cpp + resourcefiles/explode.cpp resourcefiles/file_7z.cpp resourcefiles/file_grp.cpp resourcefiles/file_lump.cpp diff --git a/src/g_game.cpp b/src/g_game.cpp index 4bc0918c2..35aca1b1f 100644 --- a/src/g_game.cpp +++ b/src/g_game.cpp @@ -1783,13 +1783,10 @@ FString G_BuildSaveName (const char *prefix, int slot) { slash = "/"; } - if (slot < 0) + name.Format("%s%s%s", leader.GetChars(), slash, prefix); + if (slot >= 0) { - name.Format ("%s%s%s", leader, slash, prefix); - } - else - { - name.Format ("%s%s%s%d.zds", leader, slash, prefix, slot); + name.AppendFormat("%d.zds", slot); } #ifdef unix if (leader[0] == 0) diff --git a/src/p_enemy.cpp b/src/p_enemy.cpp index 933f5e9e1..4924348c1 100644 --- a/src/p_enemy.cpp +++ b/src/p_enemy.cpp @@ -833,7 +833,7 @@ void P_RandomChaseDir (AActor *actor) if (actor->FriendPlayer != 0) { - player = players[actor->FriendPlayer - 1].mo; + player = players[i = actor->FriendPlayer - 1].mo; } else { diff --git a/src/p_setup.cpp b/src/p_setup.cpp index 3a5d451e5..85a6fee5b 100644 --- a/src/p_setup.cpp +++ b/src/p_setup.cpp @@ -583,7 +583,7 @@ static void SetTexture (side_t *side, int position, const char *name8) { for(int j = 0; j < 2; j++) { - if (lines[i].sidenum[j] == side - sides) + if (lines[i].sidenum[j] == (DWORD)(side - sides)) { Printf("Unknown %s texture '%s' on %s side of linedef %d\n", positionnames[position], name, sidenames[j], i); diff --git a/src/r_data.cpp b/src/r_data.cpp index 0691dcac8..b5383236b 100644 --- a/src/r_data.cpp +++ b/src/r_data.cpp @@ -155,7 +155,7 @@ void R_InitColormaps () name[8] = 0; Wads.GetLumpName (name, ns_colormaps); - if (Wads.CheckNumForName (name, ns_colormaps) == i) + if (Wads.CheckNumForName (name, ns_colormaps) == (int)i) { strncpy(cm.name, name, 8); cm.blend = 0; diff --git a/src/resourcefiles/explode.cpp b/src/resourcefiles/explode.cpp new file mode 100644 index 000000000..23117e6eb --- /dev/null +++ b/src/resourcefiles/explode.cpp @@ -0,0 +1,289 @@ +/* + gunzip.c by Pasi Ojala, a1bert@iki.fi + http://www.iki.fi/a1bert/ + + A hopefully easier to understand guide to GZip + (deflate) decompression routine than the GZip + source code. + + */ + +/*----------------------------------------------------------------------*/ + + +#include +#include "explode.h" + + +/**************************************************************** + Bit-I/O variables and routines/macros + + These routines work in the bit level because the target + environment does not have a barrel shifter. Trying to + handle several bits at once would've only made the code + slower. + + If the environment supports multi-bit shifts, you should + write these routines again (see e.g. the GZIP sources). + + [RH] Since the target environment is not a C64, I did as + suggested and rewrote these using zlib as a reference. + + ****************************************************************/ + +int FZipExploder::READBYTE() +{ + if (InLeft) + { + unsigned char c; + InLeft--; + if (1 != In->Read(&c, 1)) + throw CExplosionError("Out of input"); + return c; + } + throw CExplosionError("Out of input"); +} + +/* Get a byte of input into the bit accumulator, or return from inflate() + if there is no input available. */ +#define PULLBYTE() \ + do { \ + int next = READBYTE(); \ + Hold += (unsigned int)(next) << Bits; \ + Bits += 8; \ + } while (0) + +/* Assure that there are at least n bits in the bit accumulator. */ +#define NEEDBITS(n) \ + do { \ + while (Bits < (unsigned)(n)) \ + PULLBYTE(); \ + } while (0) + +/* Return the low n bits of the bit accumulator (n < 16) */ +#define BITS(n) \ + ((unsigned)Hold & ((1U << (n)) - 1)) + +/* Remove n bits from the bit accumulator */ +#define DROPBITS(n) \ + do { \ + Hold >>= (n); \ + Bits -= (unsigned)(n); \ + } while (0) + +#define READBITS(c, a) \ + do { \ + NEEDBITS(a); \ + c = BITS(a); \ + DROPBITS(a); \ + } while (0) + +int FZipExploder::IsPat() +{ + for(;;) + { + if (fpos[len] >= fmax) + return -1; + if (flens[fpos[len]] == len) + return fpos[len]++; + fpos[len]++; + } +} + + +/* + A recursive routine which creates the Huffman decode tables + + No presorting of code lengths are needed, because a counting + sort is perfomed on the fly. + */ + +/* Maximum recursion depth is equal to the maximum + Huffman code length, which is 15 in the deflate algorithm. + (16 in Inflate!) */ +int FZipExploder::Rec() +{ + struct HufNode *curplace = Places; + int tmp; + + if(len == 17) + { + return -1; + } + Places++; + len++; + + tmp = IsPat(); + if(tmp >= 0) { + curplace->b0 = tmp; /* leaf cell for 0-bit */ + } else { + /* Not a Leaf cell */ + curplace->b0 = 0x8000; + if(Rec()) + return -1; + } + tmp = IsPat(); + if(tmp >= 0) { + curplace->b1 = tmp; /* leaf cell for 1-bit */ + curplace->jump = NULL; /* Just for the display routine */ + } else { + /* Not a Leaf cell */ + curplace->b1 = 0x8000; + curplace->jump = Places; + if(Rec()) + return -1; + } + len--; + return 0; +} + + +/* In C64 return the most significant bit in Carry */ +/* The same as DecodeValue(), except that 0/1 is reversed */ +int FZipExploder::DecodeSFValue(struct HufNode *currentTree) +{ + struct HufNode *X = currentTree; + int c; + + /* decode one symbol of the data */ + for(;;) + { + READBITS(c, 1); + if(!c) { /* Only the decision is reversed! */ + if(!(X->b1 & 0x8000)) + return X->b1; /* If leaf node, return data */ + X = X->jump; + } else { + if(!(X->b0 & 0x8000)) + return X->b0; /* If leaf node, return data */ + X++; + } + } + return -1; +} + + +/* + Note: + The tree create and distance code trees <= 32 entries + and could be represented with the shorter tree algorithm. + I.e. use a X/Y-indexed table for each struct member. + */ +int FZipExploder::CreateTree(struct HufNode *currentTree, int numval, int *lengths) +{ + int i; + + /* Create the Huffman decode tree/table */ + Places = currentTree; + flens = lengths; + fmax = numval; + for (i=0;i<17;i++) + fpos[i] = 0; + len = 0; + if(Rec()) { +/* fprintf(stderr, "invalid huffman tree\n");*/ + return -1; + } + +/* fprintf(stderr, "%d table entries used (max code length %d)\n", + Places-currentTree, maxlen);*/ + return 0; +} + + +int FZipExploder::DecodeSF(int *table) +{ + int i, a, n = READBYTE() + 1, v = 0; + + for (i = 0; i < n; i++) { + int nv, bl; + a = READBYTE(); + nv = ((a >> 4) & 15) + 1; + bl = (a & 15) + 1; + while (nv--) { + table[v++] = bl; + } + } + return v; /* entries used */ +} + +/* Note: Imploding could use the lighter huffman tree routines, as the + max number of entries is 256. But too much code would need to + be duplicated. + */ +int FZipExploder::Explode(unsigned char *out, unsigned int outsize, + FileReader *in, unsigned int insize, + int flags) +{ + int c, i, minMatchLen = 3, len, dist; + int ll[256]; + unsigned int bIdx = 0; + + Hold = 0; + Bits = 0; + In = in; + InLeft = insize; + + if ((flags & 4)) { + /* 3 trees: literals, lengths, distance top 6 */ + minMatchLen = 3; + if (CreateTree(LiteralTree, DecodeSF(ll), ll)) + return 1; + } else { + /* 2 trees: lengths, distance top 6 */ + minMatchLen = 2; + } + if (CreateTree(LengthTree, DecodeSF(ll), ll)) + return 1; + if (CreateTree(DistanceTree, DecodeSF(ll), ll)) + return 1; + + while (bIdx < outsize) + { + READBITS(c, 1); + if (c) { + /* literal data */ + if ((flags & 4)) { + c = DecodeSFValue(LiteralTree); + } else { + READBITS(c, 8); + } + out[bIdx++] = c; + } else { + if ((flags & 2)) { + /* 8k dictionary */ + READBITS(dist, 7); + c = DecodeSFValue(DistanceTree); + dist |= (c<<7); + } else { + /* 4k dictionary */ + READBITS(dist, 6); + c = DecodeSFValue(DistanceTree); + dist |= (c<<6); + } + len = DecodeSFValue(LengthTree); + if (len == 63) { + READBITS(c, 8); + len += c; + } + len += minMatchLen; + dist++; + if (bIdx + len > outsize) { + throw CExplosionError("Not enough output space"); + } + if ((unsigned int)dist > bIdx) { + /* Anything before the first input byte is zero. */ + int zeros = dist - bIdx; + if (len < zeros) + zeros = len; + for(i = zeros; i; i--) + out[bIdx++] = 0; + len -= zeros; + } + for(i = len; i; i--, bIdx++) { + out[bIdx] = out[bIdx - dist]; + } + } + } + return 0; +} diff --git a/src/resourcefiles/explode.h b/src/resourcefiles/explode.h new file mode 100644 index 000000000..23299c7ec --- /dev/null +++ b/src/resourcefiles/explode.h @@ -0,0 +1,52 @@ +#include "files.h" +#include "doomerrors.h" + +class FZipExploder +{ + unsigned int Hold, Bits; + FileReader *In; + unsigned int InLeft; + + int READBYTE(); + + /**************************************************************** + Huffman tree structures, variables and related routines + + These routines are one-bit-at-a-time decode routines. They + are not as fast as multi-bit routines, but maybe a bit easier + to understand and use a lot less memory. + + The tree is folded into a table. + + ****************************************************************/ + + struct HufNode { + unsigned short b0; /* 0-branch value + leaf node flag */ + unsigned short b1; /* 1-branch value + leaf node flag */ + struct HufNode *jump; /* 1-branch jump address */ + }; + + struct HufNode LiteralTree[256]; + struct HufNode DistanceTree[64]; + struct HufNode LengthTree[64]; + struct HufNode *Places; + + unsigned char len; + short fpos[17]; + int *flens; + short fmax; + + int IsPat(); + int Rec(); + int DecodeSFValue(struct HufNode *currentTree); + int CreateTree(struct HufNode *currentTree, int numval, int *lengths); + int DecodeSF(int *table); +public: + int Explode(unsigned char *out, unsigned int outsize, FileReader *in, unsigned int insize, int flags); +}; + +class CExplosionError : CRecoverableError +{ +public: + CExplosionError(const char *message) : CRecoverableError(message) {} +}; diff --git a/src/resourcefiles/file_7z.cpp b/src/resourcefiles/file_7z.cpp index b1f81c804..bb340970c 100644 --- a/src/resourcefiles/file_7z.cpp +++ b/src/resourcefiles/file_7z.cpp @@ -265,7 +265,7 @@ bool F7ZFile::Open() Lumps = new F7ZLump[NumLumps]; F7ZLump *lump_p = Lumps; - for (int i = 0; i < NumLumps; ++i) + for (DWORD i = 0; i < NumLumps; ++i) { CSzFileItem *file = &Archive->DB.db.Files[i]; char name[256]; diff --git a/src/resourcefiles/file_wad.cpp b/src/resourcefiles/file_wad.cpp index 3a2500d91..bc9e3472c 100644 --- a/src/resourcefiles/file_wad.cpp +++ b/src/resourcefiles/file_wad.cpp @@ -157,10 +157,10 @@ void FWadFile::SetNamespace(const char *startmarker, const char *endmarker, name { bool warned = false; int numstartmarkers = 0, numendmarkers = 0; - int i; + unsigned int i; TArray markers; - for(i = 0; i < (int)NumLumps; i++) + for(i = 0; i < NumLumps; i++) { if (IsMarker(i, startmarker)) { diff --git a/src/resourcefiles/file_zip.cpp b/src/resourcefiles/file_zip.cpp index 5e1bf130b..a37ae2890 100644 --- a/src/resourcefiles/file_zip.cpp +++ b/src/resourcefiles/file_zip.cpp @@ -40,6 +40,7 @@ #include "w_wad.h" #include "w_zip.h" #include "i_system.h" +#include "explode.h" #define BUFREADCOMMENT (0x400) @@ -109,6 +110,7 @@ enum struct FZipLump : public FResourceLump { + WORD GPFlags; BYTE Method; int CompressedSize; int Position; @@ -204,7 +206,7 @@ bool FZipFile::Open() char *dirptr = (char*)directory; FZipLump *lump_p = Lumps; - for (int i = 0; i < NumLumps; i++) + for (DWORD i = 0; i < NumLumps; i++) { FZipCentralDirectoryInfo *zip_fh = (FZipCentralDirectoryInfo *)dirptr; @@ -219,7 +221,7 @@ bool FZipFile::Open() LittleShort(zip_fh->CommentLength); // skip Directories - if(name[len - 1] == '/' && LittleLong(zip_fh->UncompressedSize) == 0) + if (name[len - 1] == '/' && LittleLong(zip_fh->UncompressedSize) == 0) { skipped++; continue; @@ -230,14 +232,16 @@ bool FZipFile::Open() if (zip_fh->Method != METHOD_STORED && zip_fh->Method != METHOD_DEFLATE && zip_fh->Method != METHOD_LZMA && - zip_fh->Method != METHOD_BZIP2) + zip_fh->Method != METHOD_BZIP2 && + zip_fh->Method != METHOD_IMPLODE) { 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) + zip_fh->Flags = LittleShort(zip_fh->Flags); + if (zip_fh->Flags & ZF_ENCRYPTED) { Printf("\n%s: '%s' is encrypted. Encryption is not supported.\n", Filename, name); skipped++; @@ -253,6 +257,7 @@ bool FZipFile::Open() // 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->GPFlags = zip_fh->Flags; lump_p->CompressedSize = LittleLong(zip_fh->CompressedSize); lump_p->Position = LittleLong(zip_fh->LocalHeaderOffset); lump_p->CheckEmbedded(); @@ -372,6 +377,13 @@ int FZipLump::FillCache() break; } + case METHOD_IMPLODE: + { + FZipExploder exploder; + exploder.Explode((unsigned char *)Cache, LumpSize, Owner->Reader, CompressedSize, GPFlags); + break; + } + default: assert(0); return 0; @@ -391,7 +403,7 @@ FResourceFile *CheckZip(const char *filename, FileReader *file) { char head[4]; - if (file->GetLength() >= sizeof(FZipLocalFileHeader)) + if (file->GetLength() >= (long)sizeof(FZipLocalFileHeader)) { file->Seek(0, SEEK_SET); file->Read(&head, 4); diff --git a/src/w_wad.cpp b/src/w_wad.cpp index 6c4dfbd0c..24a5ae121 100644 --- a/src/w_wad.cpp +++ b/src/w_wad.cpp @@ -262,7 +262,7 @@ void FWadCollection::AddFile (const char *filename, FileReader *wadinfo) Printf (" adding %s", filename); startlump = NumLumps; - for(int i = 0; i < countof(funcs); i++) + for(size_t i = 0; i < countof(funcs); i++) { FResourceFile * resfile = funcs[i](filename, wadinfo); if (resfile != NULL) diff --git a/src/w_zip.h b/src/w_zip.h index 0189d3c94..d4997726e 100644 --- a/src/w_zip.h +++ b/src/w_zip.h @@ -63,6 +63,7 @@ struct FZipLocalFileHeader #define ZIP_ENDOFDIR MAKE_ID('P','K',5,6) #define METHOD_STORED 0 +#define METHOD_IMPLODE 6 #define METHOD_DEFLATE 8 #define METHOD_BZIP2 12 #define METHOD_LZMA 14 diff --git a/zdoom.vcproj b/zdoom.vcproj index e5c60ec35..e098c019c 100644 --- a/zdoom.vcproj +++ b/zdoom.vcproj @@ -1,7 +1,7 @@ - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - @@ -1864,6 +1856,14 @@ Outputs="$(IntDir)/$(InputName).obj" /> + + + @@ -2029,6 +2029,14 @@ Outputs="$(IntDir)\$(InputName).obj" /> + + + @@ -2039,14 +2047,6 @@ Outputs="$(IntDir)\$(InputName).obj" /> - - - + + + - - - + + + @@ -5351,14 +5359,6 @@ AdditionalIncludeDirectories="src\win32;$(NoInherit)" /> - - - @@ -5637,7 +5637,7 @@ /> + + + +