Update to ZDoom r1476:

- Moved weapon slot initialization into APlayerPawn::PostBeginPlay() so that
  they can be initialized when players respawn in multiplayer.
- Added a Check for the Vavoom namespace to the UDMF parser. Functionally
  it's 100% identical with ZDoom's own but needs to be checked for in
  case Vavoom compatible UDMF maps are released.
- Added an SDL output plugin, so FMOD can produce sound using SDL's audio
  support instead of its own OSS/ALSA/ESD support. This is selectable by
  setting snd_output to "sdl".
- Fixed: On Linux systems with ALSA but no OSS support, trying to start
  the sound system with snd_output "default" would fail instead of trying
  to use ALSA.
- Added sdl_nokeyrepeat to disable key repeating in the menus and console
  on Linux.
- Added support for zip/pk3 files with LZMA and bzip2 compression to ZDoom.
- Added more output to zipdir and a -q option to turn it off.
- Added -u option to zipdir to only recompress those files in a zip that have
  changed. 
- Added -d and -f options to zipdir. -d forces deflate compression, and -f
  forces a write of the zip, even if it's newer than all the files it contains.

git-svn-id: http://mancubus.net/svn/hosted/gzdoom/trunk@307 b0f79afe-0144-0410-b225-9a4edf0717df
This commit is contained in:
Christoph Oelckers 2009-03-12 20:59:09 +00:00
parent 8d22dbb5af
commit 42f732ac66
23 changed files with 782 additions and 179 deletions

View file

@ -1,4 +1,77 @@
February 28, 2009 March 11, 2009
- Moved weapon slot initialization into APlayerPawn::PostBeginPlay() so that
they can be initialized when players respawn in multiplayer.
March 11, 2009 (Changes by Graf Zahl)
- Added a Check for the Vavoom namespace to the UDMF parser. Functionally
it's 100% identical with ZDoom's own but needs to be checked for in
case Vavoom compatible UDMF maps are released.
March 10, 2009
- Added an SDL output plugin, so FMOD can produce sound using SDL's audio
support instead of its own OSS/ALSA/ESD support. This is selectable by
setting snd_output to "sdl".
- Fixed: On Linux systems with ALSA but no OSS support, trying to start
the sound system with snd_output "default" would fail instead of trying
to use ALSA.
- Added sdl_nokeyrepeat to disable key repeating in the menus and console
on Linux.
- Added support for zip/pk3 files with LZMA and bzip2 compression to ZDoom.
- Added more output to zipdir and a -q option to turn it off.
- Added -u option to zipdir to only recompress those files in a zip that have
changed.
March 7, 2009
- Added -d and -f options to zipdir. -d forces deflate compression, and -f
forces a write of the zip, even if it's newer than all the files it contains.
March 7, 2009 (Changes by Graf Zahl)
- Fixed: P_CompleteWeaponSetup was missing a NULL pointer check for the player.
- Adjusted some gravity related thresholds for the fix from Feb 28. Also removed
some unnecessary floating point math from this code.
March 6, 2009
- Added support for bzip2 and LZMA compression to zipdir.
March 6, 2009 (Changes by Graf Zahl)
- Added Hirogen2's patch for unlimited ammo CVAR.
March 4, 2009
- Fixed: You couldn't easily play with the compatibility options menu during
the title screen, because the demo loop reset the server cvars after each
attempt to play a demo, even though the demos never actually played. The
proper long-term solution would be to make shadow copies of all cvars
touched by demos and use those for the demo and the real things for
everything else, but this should do for now and is a lot easier.
- Fixed: When using BOOM-style sector flags and specials together, the
special was ignored unless it was "secret".
- Fixed: One byte is too short for DUMB_IT_SIGRENDERER to store song tempo.
Changed it to a word.
- Went back to using RDTSC for timing on Win32. Ironically,
QueryPerformanceCounter() is obviously using the TSC for its timing on my
machine, yet the overhead it has to do to keep the timer sane is apparently
noticeable on a few maps. I suppose I should at some time check
clock_gettime() and see if it has similar issues on Linux.
March 3, 2009 (Changes by Graf Zahl)
- changed: If a monster with the BOSSDEATH flag is crushed A_BossDeath will
be called now.
- fixed: D'Sparil's second form was missing the BOSSDEATH flag.
- fixed: D'Sparil's first form requires the DONTGIB flag.
- fixed: Heretic doesn't crush monsters. To handle this in a more generic
fashion this depends on the presence of a gib sprite now.
March 1, 2009 (Changes by Graf Zahl)
- Changed burn and Acolyte death sequences so that they leave corpses that
don't vanish.
- Fixed: AActor::SetOrigin must call P_FindFloorCeiling to get the true
floor and ceiling heights. Otherwise the actor will fall right through
3DMidtex textures (and 3D-floors.)
February 29, 2008
- Version bump to 2.3.0.
February 28, 2009
- Fixed: The TeleporterBeacon tried to enter its See state rather than its - Fixed: The TeleporterBeacon tried to enter its See state rather than its
Drop state. Also changed it to fade out when it's done rather than Drop state. Also changed it to fade out when it's done rather than
disappearing abruptly. disappearing abruptly.

View file

@ -51,6 +51,10 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zipdir", "tools\zipdir\zipd
EndProject EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gdtoa", "gdtoa\gdtoa.vcproj", "{B68E0ABF-B627-48A3-A92F-D8F827A75054}" Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gdtoa", "gdtoa\gdtoa.vcproj", "{B68E0ABF-B627-48A3-A92F-D8F827A75054}"
EndProject EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "lzmalib", "lzma\lzmalib.vcproj", "{6EB27E78-7C7A-4F08-8E19-957E8EB3A20F}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bzip2", "bzip2\bzip2.vcproj", "{A7DE5C73-D623-4118-A48A-BDFD1FAE97D4}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32 Debug|Win32 = Debug|Win32

View file

@ -55,7 +55,7 @@
EnableIntrinsicFunctions="true" EnableIntrinsicFunctions="true"
FavorSizeOrSpeed="1" FavorSizeOrSpeed="1"
OmitFramePointers="true" OmitFramePointers="true"
AdditionalIncludeDirectories="src\win32,src\sound,src,zlib,src\g_shared,src\g_doom,src\g_raven,src\g_heretic,src\g_hexen,src\g_strife;flac;jpeg-6b;snes_spc\snes_spc;gdtoa" AdditionalIncludeDirectories="src\win32,src\sound,src,zlib,src\g_shared,src\g_doom,src\g_raven,src\g_heretic,src\g_hexen,src\g_strife;flac;jpeg-6b;snes_spc\snes_spc;gdtoa;bzip2;lzma\C"
PreprocessorDefinitions="NDEBUG,WIN32,_WIN32,_WINDOWS,USEASM,NO_MANIFEST" PreprocessorDefinitions="NDEBUG,WIN32,_WIN32,_WINDOWS,USEASM,NO_MANIFEST"
StringPooling="true" StringPooling="true"
RuntimeLibrary="0" RuntimeLibrary="0"
@ -172,7 +172,7 @@
Name="VCCLCompilerTool" Name="VCCLCompilerTool"
Optimization="0" Optimization="0"
InlineFunctionExpansion="0" InlineFunctionExpansion="0"
AdditionalIncludeDirectories="src\win32;src\sound;src;zlib;src\g_shared;src\g_doom;src\g_raven;src\g_heretic;src\g_hexen;src\g_strife;flac;jpeg-6b;snes_spc\snes_spc;gdtoa" AdditionalIncludeDirectories="src\win32;src\sound;src;zlib;src\g_shared;src\g_doom;src\g_raven;src\g_heretic;src\g_hexen;src\g_strife;flac;jpeg-6b;snes_spc\snes_spc;gdtoa;bzip2;lzma\C"
PreprocessorDefinitions="WIN32,_DEBUG,_WIN32,_WINDOWS,USEASM,_CRTDBG_MAP_ALLOC,NO_MANIFEST" PreprocessorDefinitions="WIN32,_DEBUG,_WIN32,_WINDOWS,USEASM,_CRTDBG_MAP_ALLOC,NO_MANIFEST"
MinimalRebuild="true" MinimalRebuild="true"
RuntimeLibrary="1" RuntimeLibrary="1"
@ -280,7 +280,7 @@
EnableIntrinsicFunctions="true" EnableIntrinsicFunctions="true"
FavorSizeOrSpeed="1" FavorSizeOrSpeed="1"
OmitFramePointers="true" OmitFramePointers="true"
AdditionalIncludeDirectories="src\win32;src\sound;src;zlib;src\g_shared;src\g_doom;src\g_raven;src\g_heretic;src\g_hexen;src\g_strife;jpeg-6b;snes_spc\snes_spc" AdditionalIncludeDirectories="src\win32;src\sound;src;zlib;src\g_shared;src\g_doom;src\g_raven;src\g_heretic;src\g_hexen;src\g_strife;jpeg-6b;snes_spc\snes_spc;bzip2;lzma\C"
PreprocessorDefinitions="NDEBUG,WIN32,_WIN32,_WINDOWS,USEASM,HAVE_STRUPR,HAVE_FILELENGTH,NOASM" PreprocessorDefinitions="NDEBUG,WIN32,_WIN32,_WINDOWS,USEASM,HAVE_STRUPR,HAVE_FILELENGTH,NOASM"
StringPooling="true" StringPooling="true"
RuntimeLibrary="0" RuntimeLibrary="0"
@ -390,7 +390,7 @@
<Tool <Tool
Name="VCCLCompilerTool" Name="VCCLCompilerTool"
Optimization="0" Optimization="0"
AdditionalIncludeDirectories="src\win32;src\sound;src;zlib;src\g_shared;src\g_doom;src\g_raven;src\g_heretic;src\g_hexen;src\g_strife;flac" AdditionalIncludeDirectories="src\win32;src\sound;src;zlib;src\g_shared;src\g_doom;src\g_raven;src\g_heretic;src\g_hexen;src\g_strife;flac;bzip2;lzma\C"
PreprocessorDefinitions="WIN32,_DEBUG,_WIN32,_WINDOWS,USEASM,_CRTDBG_MAP_ALLOC,HAVE_STRUPR,HAVE_FILELENGTH,NOASM" PreprocessorDefinitions="WIN32,_DEBUG,_WIN32,_WINDOWS,USEASM,_CRTDBG_MAP_ALLOC,HAVE_STRUPR,HAVE_FILELENGTH,NOASM"
MinimalRebuild="true" MinimalRebuild="true"
RuntimeLibrary="1" RuntimeLibrary="1"

View file

@ -761,7 +761,7 @@ add_executable( zdoom WIN32
set_source_files_properties( xlat/parse_xlat.cpp PROPERTIES OBJECT_DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/xlat_parser.c" ) set_source_files_properties( xlat/parse_xlat.cpp PROPERTIES OBJECT_DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/xlat_parser.c" )
set_source_files_properties( sc_man.cpp PROPERTIES OBJECT_DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/sc_man_scanner.h" ) set_source_files_properties( sc_man.cpp PROPERTIES OBJECT_DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/sc_man_scanner.h" )
target_link_libraries( zdoom ${ZDOOM_LIBS} snes_spc gdtoa dumb ) target_link_libraries( zdoom ${ZDOOM_LIBS} snes_spc gdtoa dumb bzip2 lzma )
include_directories( . include_directories( .
g_doom g_doom
g_heretic g_heretic

View file

@ -144,6 +144,7 @@ void ParseCompatibility()
} }
else else
{ {
x = 0;
sc.ScriptError("MD5 signature must be a hexadecimal value"); sc.ScriptError("MD5 signature must be a hexadecimal value");
} }
} }

View file

@ -82,6 +82,7 @@ class APlayerPawn : public AActor
public: public:
virtual void Serialize (FArchive &arc); virtual void Serialize (FArchive &arc);
virtual void PostBeginPlay();
virtual void Tick(); virtual void Tick();
virtual void AddInventory (AInventory *item); virtual void AddInventory (AInventory *item);
virtual void RemoveInventory (AInventory *item); virtual void RemoveInventory (AInventory *item);

View file

@ -266,6 +266,205 @@ void FileReaderZ::FillBuffer ()
Stream.avail_in = numread; Stream.avail_in = numread;
} }
//==========================================================================
//
// FileReaderZ
//
// The bzip2 wrapper
// reads data from a libbzip2 compressed stream
//
//==========================================================================
FileReaderBZ2::FileReaderBZ2 (FileReader &file)
: File(file), SawEOF(false)
{
int err;
FillBuffer ();
Stream.bzalloc = NULL;
Stream.bzfree = NULL;
Stream.opaque = NULL;
err = BZ2_bzDecompressInit(&Stream, 0, 0);
if (err != BZ_OK)
{
I_Error ("FileReaderBZ2: bzDecompressInit failed: %d\n", err);
}
}
FileReaderBZ2::~FileReaderBZ2 ()
{
BZ2_bzDecompressEnd (&Stream);
}
long FileReaderBZ2::Read (void *buffer, long len)
{
int err;
Stream.next_out = (char *)buffer;
Stream.avail_out = len;
do
{
err = BZ2_bzDecompress(&Stream);
if (Stream.avail_in == 0 && !SawEOF)
{
FillBuffer ();
}
} while (err == BZ_OK && Stream.avail_out != 0);
if (err != BZ_OK && err != BZ_STREAM_END)
{
I_Error ("Corrupt bzip2 stream");
}
if (Stream.avail_out != 0)
{
I_Error ("Ran out of data in bzip2 stream");
}
return len - Stream.avail_out;
}
void FileReaderBZ2::FillBuffer ()
{
long numread = File.Read(InBuff, BUFF_SIZE);
if (numread < BUFF_SIZE)
{
SawEOF = true;
}
Stream.next_in = (char *)InBuff;
Stream.avail_in = numread;
}
//==========================================================================
//
// bz_internal_error
//
// libbzip2 wants this, since we build it with BZ_NO_STDIO set.
//
//==========================================================================
extern "C" void bz_internal_error (int errcode)
{
I_FatalError("libbzip2: internal error number %d\n", errcode);
}
//==========================================================================
//
// FileReaderLZMA
//
// The lzma wrapper
// reads data from a LZMA compressed stream
//
//==========================================================================
static void *SzAlloc(void *p, size_t size) { p = p; return malloc(size); }
static void SzFree(void *p, void *address) { p = p; free(address); }
static ISzAlloc g_Alloc = { SzAlloc, SzFree };
FileReaderLZMA::FileReaderLZMA (FileReader &file, size_t uncompressed_size, bool zip)
: File(file), SawEOF(false)
{
BYTE header[4 + LZMA_PROPS_SIZE];
int err;
assert(zip == true);
Size = uncompressed_size;
OutProcessed = 0;
// Read zip LZMA properties header
if (File.Read(header, sizeof(header)) < (long)sizeof(header))
{
I_Error("FileReaderLZMA: File too shart\n");
}
if (header[2] + header[3] * 256 != LZMA_PROPS_SIZE)
{
I_Error("FileReaderLZMA: LZMA props size is %d (expected %d)\n",
header[2] + header[3] * 256, LZMA_PROPS_SIZE);
}
FillBuffer();
LzmaDec_Construct(&Stream);
err = LzmaDec_Allocate(&Stream, header + 4, LZMA_PROPS_SIZE, &g_Alloc);
if (err != SZ_OK)
{
I_Error("FileReaderLZMA: LzmaDec_Allocate failed: %d\n", err);
}
LzmaDec_Init(&Stream);
}
FileReaderLZMA::~FileReaderLZMA ()
{
LzmaDec_Free(&Stream, &g_Alloc);
}
long FileReaderLZMA::Read (void *buffer, long len)
{
int err;
Byte *next_out = (Byte *)buffer;
do
{
ELzmaFinishMode finish_mode = LZMA_FINISH_ANY;
ELzmaStatus status;
size_t out_processed = len;
size_t in_processed = InSize;
err = LzmaDec_DecodeToBuf(&Stream, next_out, &out_processed, InBuff + InPos, &in_processed, finish_mode, &status);
InPos += in_processed;
InSize -= in_processed;
next_out += out_processed;
len = (long)(len - out_processed);
if (err != SZ_OK)
{
I_Error ("Corrupt LZMA stream");
}
if (in_processed == 0 && out_processed == 0)
{
if (status != LZMA_STATUS_FINISHED_WITH_MARK)
{
I_Error ("Corrupt LZMA stream");
}
}
if (InSize == 0 && !SawEOF)
{
FillBuffer ();
}
} while (err == SZ_OK && len != 0);
if (err != Z_OK && err != Z_STREAM_END)
{
I_Error ("Corrupt LZMA stream");
}
if (len != 0)
{
I_Error ("Ran out of data in LZMA stream");
}
return (long)(next_out - (Byte *)buffer);
}
void FileReaderLZMA::FillBuffer ()
{
long numread = File.Read(InBuff, BUFF_SIZE);
if (numread < BUFF_SIZE)
{
SawEOF = true;
}
InPos = 0;
InSize = numread;
}
//========================================================================== //==========================================================================
// //
// MemoryReader // MemoryReader
@ -320,4 +519,3 @@ char *MemoryReader::Gets(char *strbuf, int len)
{ {
return GetsFromBuffer(bufptr, strbuf, len); return GetsFromBuffer(bufptr, strbuf, len);
} }

View file

@ -3,6 +3,8 @@
#include <stdio.h> #include <stdio.h>
#include <zlib.h> #include <zlib.h>
#include "bzlib.h"
#include "LzmaDec.h"
#include "doomtype.h" #include "doomtype.h"
#include "m_swap.h" #include "m_swap.h"
@ -140,6 +142,132 @@ private:
FileReaderZ &operator= (const FileReaderZ &) { return *this; } FileReaderZ &operator= (const FileReaderZ &) { return *this; }
}; };
// Wraps around a FileReader to decompress a bzip2 stream
class FileReaderBZ2
{
public:
FileReaderBZ2 (FileReader &file);
~FileReaderBZ2 ();
long Read (void *buffer, long len);
FileReaderBZ2 &operator>> (BYTE &v)
{
Read (&v, 1);
return *this;
}
FileReaderBZ2 &operator>> (SBYTE &v)
{
Read (&v, 1);
return *this;
}
FileReaderBZ2 &operator>> (WORD &v)
{
Read (&v, 2);
v = LittleShort(v);
return *this;
}
FileReaderBZ2 &operator>> (SWORD &v)
{
Read (&v, 2);
v = LittleShort(v);
return *this;
}
FileReaderBZ2 &operator>> (DWORD &v)
{
Read (&v, 4);
v = LittleLong(v);
return *this;
}
FileReaderBZ2 &operator>> (fixed_t &v)
{
Read (&v, 4);
v = LittleLong(v);
return *this;
}
private:
enum { BUFF_SIZE = 4096 };
FileReader &File;
bool SawEOF;
bz_stream Stream;
BYTE InBuff[BUFF_SIZE];
void FillBuffer ();
FileReaderBZ2 &operator= (const FileReaderBZ2 &) { return *this; }
};
// Wraps around a FileReader to decompress a lzma stream
class FileReaderLZMA
{
public:
FileReaderLZMA (FileReader &file, size_t uncompressed_size, bool zip);
~FileReaderLZMA ();
long Read (void *buffer, long len);
FileReaderLZMA &operator>> (BYTE &v)
{
Read (&v, 1);
return *this;
}
FileReaderLZMA &operator>> (SBYTE &v)
{
Read (&v, 1);
return *this;
}
FileReaderLZMA &operator>> (WORD &v)
{
Read (&v, 2);
v = LittleShort(v);
return *this;
}
FileReaderLZMA &operator>> (SWORD &v)
{
Read (&v, 2);
v = LittleShort(v);
return *this;
}
FileReaderLZMA &operator>> (DWORD &v)
{
Read (&v, 4);
v = LittleLong(v);
return *this;
}
FileReaderLZMA &operator>> (fixed_t &v)
{
Read (&v, 4);
v = LittleLong(v);
return *this;
}
private:
enum { BUFF_SIZE = 4096 };
FileReader &File;
bool SawEOF;
CLzmaDec Stream;
size_t Size;
size_t InPos, InSize;
size_t OutProcessed;
BYTE InBuff[BUFF_SIZE];
void FillBuffer ();
FileReaderLZMA &operator= (const FileReaderLZMA &) { return *this; }
};
class MemoryReader : public FileReader class MemoryReader : public FileReader
{ {

View file

@ -941,7 +941,6 @@ void G_DoLoadLevel (int position, bool autosave)
} }
P_SetupLevel (level.mapname, position); P_SetupLevel (level.mapname, position);
P_CompleteWeaponSetup();
AM_LevelInit(); AM_LevelInit();

View file

@ -16,13 +16,15 @@ class AWeapon;
class FWeaponSlot class FWeaponSlot
{ {
public: public:
FWeaponSlot() { Clear(); }
FWeaponSlot(const FWeaponSlot &other) { Weapons = other.Weapons; }
FWeaponSlot &operator= (const FWeaponSlot &other) { Weapons = other.Weapons; return *this; } FWeaponSlot &operator= (const FWeaponSlot &other) { Weapons = other.Weapons; return *this; }
void Clear() { Weapons.Clear(); } void Clear() { Weapons.Clear(); }
bool AddWeapon (const char *type); bool AddWeapon (const char *type);
bool AddWeapon (const PClass *type); bool AddWeapon (const PClass *type);
void AddWeaponList (const char *list, bool clear); void AddWeaponList (const char *list, bool clear);
AWeapon *PickWeapon (player_t *player); AWeapon *PickWeapon (player_t *player);
int Size () { return (int)Weapons.Size(); } int Size () const { return (int)Weapons.Size(); }
int LocateWeapon (const PClass *type); int LocateWeapon (const PClass *type);
inline const PClass *GetWeapon (int index) const inline const PClass *GetWeapon (int index) const
@ -59,6 +61,9 @@ enum ESlotDef
struct FWeaponSlots struct FWeaponSlots
{ {
FWeaponSlots() { Clear(); }
FWeaponSlots(const FWeaponSlots &other);
FWeaponSlot Slots[NUM_WEAPON_SLOTS]; FWeaponSlot Slots[NUM_WEAPON_SLOTS];
AWeapon *PickNextWeapon (player_t *player); AWeapon *PickNextWeapon (player_t *player);
@ -69,7 +74,9 @@ struct FWeaponSlots
ESlotDef AddDefaultWeapon (int slot, const PClass *type); ESlotDef AddDefaultWeapon (int slot, const PClass *type);
void AddExtraWeapons(); void AddExtraWeapons();
void SetFromPlayer(const PClass *type); void SetFromPlayer(const PClass *type);
void CompleteSetup(const PClass *type); void StandardSetup(const PClass *type);
void LocalSetup(const PClass *type);
void SendDifferences(const FWeaponSlots &other);
int RestoreSlots (FConfigFile *config, const char *section); int RestoreSlots (FConfigFile *config, const char *section);
void PrintSettings(); void PrintSettings();
@ -78,8 +85,7 @@ struct FWeaponSlots
}; };
void P_PlaybackKeyConfWeapons(); void P_PlaybackKeyConfWeapons(FWeaponSlots *slots);
void P_CompleteWeaponSetup();
void Net_WriteWeapon(const PClass *type); void Net_WriteWeapon(const PClass *type);
const PClass *Net_ReadWeapon(BYTE **stream); const PClass *Net_ReadWeapon(BYTE **stream);

View file

@ -28,7 +28,7 @@ END_POINTERS
FString WeaponSection; FString WeaponSection;
TArray<FString> KeyConfWeapons; TArray<FString> KeyConfWeapons;
bool PlayingKeyConf; FWeaponSlots *PlayingKeyConf;
TArray<const PClass *> Weapons_ntoh; TArray<const PClass *> Weapons_ntoh;
TMap<const PClass *, int> Weapons_hton; TMap<const PClass *, int> Weapons_hton;
@ -642,8 +642,6 @@ bool AWeaponGiver::TryPickup(AActor *&toucher)
/* Weapon slots ***********************************************************/ /* Weapon slots ***********************************************************/
FWeaponSlots LocalWeapons;
//=========================================================================== //===========================================================================
// //
// FWeaponSlot :: AddWeapon // FWeaponSlot :: AddWeapon
@ -756,7 +754,7 @@ AWeapon *FWeaponSlot::PickWeapon(player_t *player)
} }
if (player->ReadyWeapon != NULL) if (player->ReadyWeapon != NULL)
{ {
for (i = 0; i < Weapons.Size(); i++) for (i = 0; (unsigned)i < Weapons.Size(); i++)
{ {
if (Weapons[i].Type == player->ReadyWeapon->GetClass() || if (Weapons[i].Type == player->ReadyWeapon->GetClass() ||
(player->ReadyWeapon->WeaponFlags & WIF_POWERED_UP && (player->ReadyWeapon->WeaponFlags & WIF_POWERED_UP &&
@ -844,6 +842,20 @@ void FWeaponSlot::Sort()
} }
} }
//===========================================================================
//
// FWeaponSlots - Copy Constructor
//
//===========================================================================
FWeaponSlots::FWeaponSlots(const FWeaponSlots &other)
{
for (int i = 0; i < NUM_WEAPON_SLOTS; ++i)
{
Slots[i] = other.Slots[i];
}
}
//=========================================================================== //===========================================================================
// //
// FWeaponSlots :: Clear // FWeaponSlots :: Clear
@ -1105,24 +1117,36 @@ void FWeaponSlots::AddExtraWeapons()
//=========================================================================== //===========================================================================
// //
// FWeaponSlots :: CompleteSetup // FWeaponSlots :: StandardSetup
// //
// Sets up local weapon slots in this order: // Setup weapons in this order:
// 1. Use slots from player class. // 1. Use slots from player class.
// 2. Add extra weapons that specify their own slot. // 2. Add extra weapons that specify their own slots.
// 3. Run KEYCONF weapon commands, affecting slots accordingly. //
// 4. Read config slots, overriding current slots. If WeaponSection is set, //===========================================================================
void FWeaponSlots::StandardSetup(const PClass *type)
{
SetFromPlayer(type);
AddExtraWeapons();
}
//===========================================================================
//
// FWeaponSlots :: LocalSetup
//
// Setup weapons in this order:
// 1. Run KEYCONF weapon commands, affecting slots accordingly.
// 2. Read config slots, overriding current slots. If WeaponSection is set,
// then [<WeaponSection>.<PlayerClass>.Weapons] is tried, followed by // then [<WeaponSection>.<PlayerClass>.Weapons] is tried, followed by
// [<WeaponSection>.Weapons] if that did not exist. If WeaponSection is // [<WeaponSection>.Weapons] if that did not exist. If WeaponSection is
// empty, then the slots are read from [<PlayerClass>.Weapons]. // empty, then the slots are read from [<PlayerClass>.Weapons].
// //
//=========================================================================== //===========================================================================
void FWeaponSlots::CompleteSetup(const PClass *type) void FWeaponSlots::LocalSetup(const PClass *type)
{ {
SetFromPlayer(type); P_PlaybackKeyConfWeapons(this);
AddExtraWeapons();
P_PlaybackKeyConfWeapons();
if (WeaponSection.IsNotEmpty()) if (WeaponSection.IsNotEmpty())
{ {
FString sectionclass(WeaponSection); FString sectionclass(WeaponSection);
@ -1138,25 +1162,41 @@ void FWeaponSlots::CompleteSetup(const PClass *type)
} }
} }
void P_CompleteWeaponSetup() //===========================================================================
//
// FWeaponSlots :: SendDifferences
//
// Sends the weapon slots from this instance that differ from other's.
//
//===========================================================================
void FWeaponSlots::SendDifferences(const FWeaponSlots &other)
{ {
if (players[consoleplayer].mo != NULL) int i, j;
for (i = 0; i < NUM_WEAPON_SLOTS; ++i)
{ {
// Set up the weapon slots locally if (other.Slots[i].Size() == Slots[i].Size())
LocalWeapons.CompleteSetup(players[consoleplayer].mo->GetClass());
// Now transmit them across the network
for (int i = 0; i < NUM_WEAPON_SLOTS; ++i)
{ {
if (LocalWeapons.Slots[i].Size() > 0) for (j = (int)Slots[i].Size(); j-- > 0; )
{ {
Net_WriteByte(DEM_SETSLOT); if (other.Slots[i].GetWeapon(j) != Slots[i].GetWeapon(j))
Net_WriteByte(i);
Net_WriteByte(LocalWeapons.Slots[i].Size());
for(int j = 0; j < LocalWeapons.Slots[i].Size(); j++)
{ {
Net_WriteWeapon(LocalWeapons.Slots[i].GetWeapon(j)); break;
} }
} }
if (j < 0)
{ // The two slots are the same.
continue;
}
}
// The slots differ. Send mine.
Net_WriteByte(DEM_SETSLOT);
Net_WriteByte(i);
Net_WriteByte(Slots[i].Size());
for (j = 0; j < Slots[i].Size(); ++j)
{
Net_WriteWeapon(Slots[i].GetWeapon(j));
} }
} }
} }
@ -1268,12 +1308,12 @@ CCMD (setslot)
{ {
KeyConfWeapons.Push(argv.args()); KeyConfWeapons.Push(argv.args());
} }
else if (PlayingKeyConf) else if (PlayingKeyConf != NULL)
{ {
LocalWeapons.Slots[slot].Clear(); PlayingKeyConf->Slots[slot].Clear();
for (int i = 2; i < argv.argc(); ++i) for (int i = 2; i < argv.argc(); ++i)
{ {
LocalWeapons.Slots[slot].AddWeapon(argv[i]); PlayingKeyConf->Slots[slot].AddWeapon(argv[i]);
} }
} }
else else
@ -1303,7 +1343,7 @@ void FWeaponSlots::AddSlot(int slot, const PClass *type, bool feedback)
{ {
if (type != NULL && !Slots[slot].AddWeapon(type) && feedback) if (type != NULL && !Slots[slot].AddWeapon(type) && feedback)
{ {
Printf ("Could not add %s to slot %zu\n", type->TypeName.GetChars(), slot); Printf ("Could not add %s to slot %d\n", type->TypeName.GetChars(), slot);
} }
} }
@ -1321,9 +1361,9 @@ CCMD (addslot)
{ {
KeyConfWeapons.Push(argv.args()); KeyConfWeapons.Push(argv.args());
} }
else if (PlayingKeyConf) else if (PlayingKeyConf != NULL)
{ {
LocalWeapons.AddSlot(int(slot), PClass::FindClass(argv[2]), false); PlayingKeyConf->AddSlot(int(slot), PClass::FindClass(argv[2]), false);
} }
else else
{ {
@ -1397,9 +1437,9 @@ CCMD (addslotdefault)
{ {
KeyConfWeapons.Push(argv.args()); KeyConfWeapons.Push(argv.args());
} }
else if (PlayingKeyConf) else if (PlayingKeyConf != NULL)
{ {
LocalWeapons.AddSlotDefault(int(slot), PClass::FindClass(argv[2]), false); PlayingKeyConf->AddSlotDefault(int(slot), PClass::FindClass(argv[2]), false);
} }
else else
{ {
@ -1417,15 +1457,15 @@ CCMD (addslotdefault)
// //
//=========================================================================== //===========================================================================
void P_PlaybackKeyConfWeapons() void P_PlaybackKeyConfWeapons(FWeaponSlots *slots)
{ {
PlayingKeyConf = true; PlayingKeyConf = slots;
for (unsigned int i = 0; i < KeyConfWeapons.Size(); ++i) for (unsigned int i = 0; i < KeyConfWeapons.Size(); ++i)
{ {
FString cmd(KeyConfWeapons[i]); FString cmd(KeyConfWeapons[i]);
AddCommandString(cmd.LockBuffer()); AddCommandString(cmd.LockBuffer());
} }
PlayingKeyConf = false; PlayingKeyConf = NULL;
} }
//=========================================================================== //===========================================================================
@ -1593,7 +1633,7 @@ const PClass *Net_ReadWeapon(BYTE **stream)
{ {
index = (index & 0x7F) | (ReadByte(stream) << 7); index = (index & 0x7F) | (ReadByte(stream) << 7);
} }
if (index >= Weapons_ntoh.Size()) if ((unsigned)index >= Weapons_ntoh.Size())
{ {
return NULL; return NULL;
} }

View file

@ -1234,6 +1234,7 @@ static valueenum_t Outputs[] =
#elif defined(unix) #elif defined(unix)
{ "OSS", "OSS" }, { "OSS", "OSS" },
{ "ALSA", "ALSA" }, { "ALSA", "ALSA" },
{ "SDL", "SDL" },
{ "ESD", "ESD" }, { "ESD", "ESD" },
#elif defined(__APPLE__) #elif defined(__APPLE__)
{ "Sound Manager", "Sound Manager" }, { "Sound Manager", "Sound Manager" },

View file

@ -491,7 +491,26 @@ void APlayerPawn::Tick()
Super::Tick(); Super::Tick();
} }
//===========================================================================
//
// APlayerPawn :: PostBeginPlay
//
//===========================================================================
void APlayerPawn::PostBeginPlay()
{
// If we're not a voodoo doll, set up our weapons.
if (player != NULL && player->mo == this)
{
player->weapons.StandardSetup(GetClass());
if (player - players == consoleplayer)
{ // If we're the local player, then there's a bit more work to do.
FWeaponSlots local_slots(player->weapons);
local_slots.LocalSetup(GetClass());
local_slots.SendDifferences(player->weapons);
}
}
}
//=========================================================================== //===========================================================================
// //

View file

@ -1122,6 +1122,7 @@ void STACK_ARGS FScriptPosition::Message (int severity, const char *message, ...
case MSG_FATAL: case MSG_FATAL:
I_Error ("Script error, \"%s\" line %d:\n%s\n", I_Error ("Script error, \"%s\" line %d:\n%s\n",
FileName.GetChars(), ScriptLine, composed.GetChars()); FileName.GetChars(), ScriptLine, composed.GetChars());
return;
} }
Printf (level, "%sScript %s, \"%s\" line %d:\n%s%s\n", Printf (level, "%sScript %s, \"%s\" line %d:\n%s%s\n",
color, type, FileName.GetChars(), ScriptLine, color, composed.GetChars()); color, type, FileName.GetChars(), ScriptLine, color, composed.GetChars());

View file

@ -29,6 +29,7 @@ extern int paused;
CVAR (Bool, use_mouse, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) CVAR (Bool, use_mouse, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
CVAR (Bool, m_noprescale, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) CVAR (Bool, m_noprescale, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
CVAR (Bool, m_filter, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) CVAR (Bool, m_filter, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
CVAR (Bool, sdl_nokeyrepeat, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
float JoyAxes[6]; float JoyAxes[6];
//static int JoyActive; //static int JoyActive;
@ -200,6 +201,10 @@ static void InitKeySymMap ()
static void I_CheckGUICapture () static void I_CheckGUICapture ()
{ {
bool wantCapt; bool wantCapt;
bool repeat;
int oldrepeat, interval;
SDL_GetKeyRepeat(&oldrepeat, &interval);
if (menuactive == MENU_Off) if (menuactive == MENU_Off)
{ {
@ -217,15 +222,34 @@ static void I_CheckGUICapture ()
{ {
FlushDIKState (); FlushDIKState ();
memset (DownState, 0, sizeof(DownState)); memset (DownState, 0, sizeof(DownState));
SDL_EnableKeyRepeat (SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL); repeat = !sdl_nokeyrepeat;
SDL_EnableUNICODE (1); SDL_EnableUNICODE (1);
} }
else else
{ {
SDL_EnableKeyRepeat (0, 0); repeat = false;
SDL_EnableUNICODE (0); SDL_EnableUNICODE (0);
} }
} }
if (wantCapt)
{
repeat = !sdl_nokeyrepeat;
}
else
{
repeat = false;
}
if (repeat != (oldrepeat != 0))
{
if (repeat)
{
SDL_EnableKeyRepeat (SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
}
else
{
SDL_EnableKeyRepeat (0, 0);
}
}
} }
static void CenterMouse () static void CenterMouse ()

View file

@ -167,16 +167,14 @@ namespace FMOD
FMOD_RESULT getDSPClock (unsigned int *hi, unsigned int *lo) { return FMOD_System_GetDSPClock(this, hi, lo); } FMOD_RESULT getDSPClock (unsigned int *hi, unsigned int *lo) { return FMOD_System_GetDSPClock(this, hi, lo); }
// Recording API. // Recording API.
FMOD_RESULT setRecordDriver (int driver) { return FMOD_System_SetRecordDriver(this, driver); }
FMOD_RESULT getRecordDriver (int *driver) { return FMOD_System_GetRecordDriver(this, driver); }
FMOD_RESULT getRecordNumDrivers (int *numdrivers) { return FMOD_System_GetRecordNumDrivers(this, numdrivers); } FMOD_RESULT getRecordNumDrivers (int *numdrivers) { return FMOD_System_GetRecordNumDrivers(this, numdrivers); }
FMOD_RESULT getRecordDriverInfo (int id, char *name, int namelen, FMOD_GUID *guid) { return FMOD_System_GetRecordDriverInfo(this, id, name, namelen, guid); } FMOD_RESULT getRecordDriverInfo (int id, char *name, int namelen, FMOD_GUID *guid) { return FMOD_System_GetRecordDriverInfo(this, id, name, namelen, guid); }
FMOD_RESULT getRecordDriverCaps (int id, FMOD_CAPS *caps, int *minfrequency, int *maxfrequency) { return FMOD_System_GetRecordDriverCaps(this, id, caps, minfrequency, maxfrequency); } FMOD_RESULT getRecordDriverCaps (int id, FMOD_CAPS *caps, int *minfrequency, int *maxfrequency) { return FMOD_System_GetRecordDriverCaps(this, id, caps, minfrequency, maxfrequency); }
FMOD_RESULT getRecordPosition (unsigned int *position) { return FMOD_System_GetRecordPosition(this, position); } FMOD_RESULT getRecordPosition (int id, unsigned int *position) { return FMOD_System_GetRecordPosition(this, id, position); }
FMOD_RESULT recordStart (Sound *sound, bool loop) { return FMOD_System_RecordStart(this, (FMOD_SOUND *)sound, loop); } FMOD_RESULT recordStart (int id, Sound *sound, bool loop) { return FMOD_System_RecordStart(this, id, (FMOD_SOUND *)sound, loop); }
FMOD_RESULT recordStop () { return FMOD_System_RecordStop(this); } FMOD_RESULT recordStop (int id) { return FMOD_System_RecordStop(this, id); }
FMOD_RESULT isRecording (bool *recording) { FMOD_BOOL b; FMOD_RESULT res = FMOD_System_IsRecording(this, &b); *recording = b; return res; } FMOD_RESULT isRecording (int id, bool *recording) { FMOD_BOOL b; FMOD_RESULT res = FMOD_System_IsRecording(this, id, &b); *recording = b; return res; }
// Geometry API. // Geometry API.
FMOD_RESULT createGeometry (int maxpolygons, int maxvertices, Geometry **geometry) { return FMOD_System_CreateGeometry(this, maxpolygons, maxvertices, (FMOD_GEOMETRY **)geometry); } FMOD_RESULT createGeometry (int maxpolygons, int maxvertices, Geometry **geometry) { return FMOD_System_CreateGeometry(this, maxpolygons, maxvertices, (FMOD_GEOMETRY **)geometry); }

View file

@ -54,6 +54,7 @@ extern HWND Window;
#include "v_text.h" #include "v_text.h"
#include "v_video.h" #include "v_video.h"
#include "v_palette.h" #include "v_palette.h"
#include "cmdlib.h"
// MACROS ------------------------------------------------------------------ // MACROS ------------------------------------------------------------------
@ -159,6 +160,7 @@ static const FEnumList OutputNames[] =
{ "OSS", FMOD_OUTPUTTYPE_OSS }, { "OSS", FMOD_OUTPUTTYPE_OSS },
{ "ALSA", FMOD_OUTPUTTYPE_ALSA }, { "ALSA", FMOD_OUTPUTTYPE_ALSA },
{ "ESD", FMOD_OUTPUTTYPE_ESD }, { "ESD", FMOD_OUTPUTTYPE_ESD },
{ "SDL", 666 },
// Mac // Mac
{ "Sound Manager", FMOD_OUTPUTTYPE_SOUNDMANAGER }, { "Sound Manager", FMOD_OUTPUTTYPE_SOUNDMANAGER },
@ -612,6 +614,7 @@ bool FMODSoundRenderer::Init()
ChannelGroupTargetUnit = NULL; ChannelGroupTargetUnit = NULL;
SfxReverbHooked = false; SfxReverbHooked = false;
SfxReverbPlaceholder = NULL; SfxReverbPlaceholder = NULL;
OutputPlugin = 0;
Printf("I_InitSound: Initializing FMOD\n"); Printf("I_InitSound: Initializing FMOD\n");
@ -692,21 +695,65 @@ bool FMODSoundRenderer::Init()
} }
#endif #endif
#ifndef _WIN32
// Try to load SDL output plugin
result = Sys->setPluginPath(progdir); // Should we really look for it in the program directory?
result = Sys->loadPlugin("liboutput_sdl.so", &OutputPlugin);
if (result != FMOD_OK)
{
OutputPlugin = 0;
}
#endif
// Set the user specified output mode. // Set the user specified output mode.
eval = Enum_NumForName(OutputNames, snd_output); eval = Enum_NumForName(OutputNames, snd_output);
if (eval >= 0) if (eval >= 0)
{ {
result = Sys->setOutput(FMOD_OUTPUTTYPE(eval)); if (eval == 666 && OutputPlugin != 0)
{
result = Sys->setOutputByPlugin(OutputPlugin);
}
else
{
result = Sys->setOutput(FMOD_OUTPUTTYPE(eval));
}
if (result != FMOD_OK) if (result != FMOD_OK)
{ {
Printf(TEXTCOLOR_BLUE"Setting output type '%s' failed. Using default instead. (Error %d)\n", *snd_output, result); Printf(TEXTCOLOR_BLUE"Setting output type '%s' failed. Using default instead. (Error %d)\n", *snd_output, result);
eval = FMOD_OUTPUTTYPE_AUTODETECT;
Sys->setOutput(FMOD_OUTPUTTYPE_AUTODETECT); Sys->setOutput(FMOD_OUTPUTTYPE_AUTODETECT);
} }
} }
result = Sys->getNumDrivers(&driver); result = Sys->getNumDrivers(&driver);
#ifdef unix
if (result == FMOD_OK) if (result == FMOD_OK)
{ {
// On Linux, FMOD defaults to OSS. If OSS is not present, it doesn't
// try ALSA, it just fails. We'll try for it, but only if OSS wasn't
// explicitly specified for snd_output.
if (driver == 0 && eval == FMOD_OUTPUTTYPE_AUTODETECT)
{
FMOD_OUTPUTTYPE output;
if (FMOD_OK == Sys->getOutput(&output))
{
if (output == FMOD_OUTPUTTYPE_OSS)
{
Printf(TEXTCOLOR_BLUE"OSS could not be initialized. Trying ALSA.\n");
Sys->setOutput(FMOD_OUTPUTTYPE_ALSA);
result = Sys->getNumDrivers(&driver);
}
}
}
}
#endif
if (result == FMOD_OK)
{
if (driver == 0)
{
Printf(TEXTCOLOR_ORANGE"No working sound devices found. Try a different snd_output?\n");
return false;
}
if (snd_driver >= driver) if (snd_driver >= driver)
{ {
Printf(TEXTCOLOR_BLUE"Driver %d does not exist. Using 0.\n", *snd_driver); Printf(TEXTCOLOR_BLUE"Driver %d does not exist. Using 0.\n", *snd_driver);
@ -1056,6 +1103,11 @@ void FMODSoundRenderer::Shutdown()
} }
Sys->close(); Sys->close();
if (OutputPlugin != 0)
{
Sys->unloadPlugin(OutputPlugin);
OutputPlugin = 0;
}
Sys->release(); Sys->release();
Sys = NULL; Sys = NULL;
} }

View file

@ -98,6 +98,7 @@ private:
FMOD::DSP *SfxReverbPlaceholder; FMOD::DSP *SfxReverbPlaceholder;
bool SfxReverbHooked; bool SfxReverbHooked;
float LastWaterLP; float LastWaterLP;
unsigned int OutputPlugin;
// Just for snd_status display // Just for snd_status display
int Driver_MinFrequency; int Driver_MinFrequency;

View file

@ -131,7 +131,7 @@ inline volatile unsigned long long rdtsc()
#endif #endif
{ {
register unsigned long long tsc asm("eax"); register unsigned long long tsc asm("eax");
asm volatile ("\trdtsc\n" : : : "eax, "edx"); asm volatile ("\trdtsc\n" : : : "eax", "edx");
return tsc; return tsc;
} }
return 0; return 0;

View file

@ -325,7 +325,7 @@ do_stop:
sc.ScriptError("Negative jump offsets are not allowed"); sc.ScriptError("Negative jump offsets are not allowed");
} }
if (x > 0) if (v > 0)
{ {
x = new FxStateByIndex(bag.statedef.GetStateCount() + v, sc); x = new FxStateByIndex(bag.statedef.GetStateCount() + v, sc);
} }

View file

@ -91,6 +91,7 @@ struct FWadCollection::LumpRecord
{ {
char * fullname; // only valid for files loaded from a .zip file char * fullname; // only valid for files loaded from a .zip file
char name[9]; char name[9];
BYTE method; // zip compression method
short wadnum; short wadnum;
WORD flags; WORD flags;
int position; int position;
@ -299,7 +300,7 @@ int FWadCollection::AddExternalFile(const char *filename)
static DWORD Zip_FindCentralDir(FileReader * fin) static DWORD Zip_FindCentralDir(FileReader * fin)
{ {
unsigned char* buf; unsigned char buf[BUFREADCOMMENT + 4];
DWORD FileSize; DWORD FileSize;
DWORD uBackRead; DWORD uBackRead;
DWORD uMaxBack; // maximum size of global comment DWORD uMaxBack; // maximum size of global comment
@ -310,38 +311,35 @@ static DWORD Zip_FindCentralDir(FileReader * fin)
FileSize = fin->Tell(); FileSize = fin->Tell();
uMaxBack = MIN<DWORD>(0xffff, FileSize); uMaxBack = MIN<DWORD>(0xffff, FileSize);
buf = (unsigned char*)malloc(BUFREADCOMMENT+4);
if (buf == NULL) return 0;
uBackRead = 4; uBackRead = 4;
while (uBackRead < uMaxBack) while (uBackRead < uMaxBack)
{ {
DWORD uReadSize, uReadPos; DWORD uReadSize, uReadPos;
int i; int i;
if (uBackRead +BUFREADCOMMENT > uMaxBack) if (uBackRead + BUFREADCOMMENT > uMaxBack)
uBackRead = uMaxBack; uBackRead = uMaxBack;
else else
uBackRead += BUFREADCOMMENT; uBackRead += BUFREADCOMMENT;
uReadPos = FileSize - uBackRead ; uReadPos = FileSize - uBackRead;
uReadSize = MIN<DWORD>((BUFREADCOMMENT+4) , (FileSize-uReadPos)); uReadSize = MIN<DWORD>((BUFREADCOMMENT + 4), (FileSize - uReadPos));
if (fin->Seek(uReadPos,SEEK_SET) != 0) break; if (fin->Seek(uReadPos, SEEK_SET) != 0) break;
if (fin->Read(buf, (SDWORD)uReadSize) != (SDWORD)uReadSize) break; if (fin->Read(buf, (SDWORD)uReadSize) != (SDWORD)uReadSize) break;
for (i=(int)uReadSize-3; (i--)>0;) for (i = (int)uReadSize - 3; (i--) > 0;)
if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) && {
((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06)) if (buf[i] == 'P' && buf[i+1] == 'K' && buf[i+2] == 5 && buf[i+3] == 6)
{ {
uPosFound = uReadPos+i; uPosFound = uReadPos + i;
break; break;
} }
}
if (uPosFound!=0) if (uPosFound != 0)
break; break;
} }
free(buf);
return uPosFound; return uPosFound;
} }
@ -373,7 +371,7 @@ void FWadCollection::AddFile (const char *filename, const char * data, int lengt
int startlump; int startlump;
wadlump_t* fileinfo = NULL, *fileinfo2free = NULL; wadlump_t* fileinfo = NULL, *fileinfo2free = NULL;
wadlump_t singleinfo; wadlump_t singleinfo;
TArray<FZipFileInfo *> EmbeddedWADs; TArray<FZipCentralDirectoryInfo *> EmbeddedWADs;
void * directory = NULL; void * directory = NULL;
if (length==-1) if (length==-1)
@ -508,10 +506,10 @@ void FWadCollection::AddFile (const char *filename, const char * data, int lengt
else if (header.magic[0] == ZIP_ID) else if (header.magic[0] == ZIP_ID)
{ {
DWORD centraldir = Zip_FindCentralDir(wadinfo); DWORD centraldir = Zip_FindCentralDir(wadinfo);
FZipCentralInfo info; FZipEndOfCentralDirectory info;
int skipped = 0; int skipped = 0;
if (centraldir==0) if (centraldir == 0)
{ {
Printf("\n%s: ZIP file corrupt!\n", filename); Printf("\n%s: ZIP file corrupt!\n", filename);
return; return;
@ -519,56 +517,61 @@ void FWadCollection::AddFile (const char *filename, const char * data, int lengt
// Read the central directory info. // Read the central directory info.
wadinfo->Seek(centraldir, SEEK_SET); wadinfo->Seek(centraldir, SEEK_SET);
wadinfo->Read(&info, sizeof(FZipCentralInfo)); wadinfo->Read(&info, sizeof(FZipEndOfCentralDirectory));
// No multi-disk zips! // No multi-disk zips!
if (info.wEntryCount != info.wTotalEntryCount || if (info.NumEntries != info.NumEntriesOnAllDisks ||
info.wNumberDiskWithCD != 0 || info.wNumberDisk != 0) info.FirstDisk != 0 || info.DiskNumber != 0)
{ {
Printf("\n%s: Multipart Zip files are not supported.\n", filename); Printf("\n%s: Multipart Zip files are not supported.\n", filename);
return; return;
} }
NumLumps += LittleShort(info.wEntryCount); NumLumps += LittleShort(info.NumEntries);
LumpInfo.Resize(NumLumps); LumpInfo.Resize(NumLumps);
lump_p = &LumpInfo[startlump]; lump_p = &LumpInfo[startlump];
// Load the entire central directory. Too bad that this contains variable length entries... // Load the entire central directory. Too bad that this contains variable length entries...
directory = malloc(LittleLong(info.dwCDSize)); directory = malloc(LittleLong(info.DirectorySize));
wadinfo->Seek(LittleLong(info.dwCDOffset), SEEK_SET); wadinfo->Seek(LittleLong(info.DirectoryOffset), SEEK_SET);
wadinfo->Read(directory, LittleLong(info.dwCDSize)); wadinfo->Read(directory, LittleLong(info.DirectorySize));
char * dirptr =(char*)directory; char *dirptr = (char*)directory;
for (int i = 0; i < LittleShort(info.wEntryCount); i++) for (int i = 0; i < LittleShort(info.NumEntries); i++)
{ {
FZipFileInfo * zip_fh = (FZipFileInfo*)dirptr; FZipCentralDirectoryInfo *zip_fh = (FZipCentralDirectoryInfo *)dirptr;
char name[256]; char name[256];
char base[256]; char base[256];
int len = LittleShort(zip_fh->wFileNameSize); int len = LittleShort(zip_fh->NameLength);
strncpy(name, dirptr + sizeof(FZipFileInfo), MIN<int>(len, 255)); strncpy(name, dirptr + sizeof(FZipCentralDirectoryInfo), MIN<int>(len, 255));
name[len]=0; name[len] = 0;
dirptr += sizeof(FZipFileInfo) + dirptr += sizeof(FZipCentralDirectoryInfo) +
LittleShort(zip_fh->wFileNameSize) + LittleShort(zip_fh->NameLength) +
LittleShort(zip_fh->wExtraSize) + LittleShort(zip_fh->ExtraLength) +
LittleShort(zip_fh->wCommentSize); LittleShort(zip_fh->CommentLength);
// skip Directories // skip Directories
if(name[len - 1] == '/' && LittleLong(zip_fh->dwSize) == 0) if(name[len - 1] == '/' && LittleLong(zip_fh->UncompressedSize) == 0)
{ {
skipped++; skipped++;
continue; continue;
} }
// Ignore obsolete compression formats // Ignore unknown compression formats
if(LittleShort(zip_fh->wCompression) != 0 && LittleShort(zip_fh->wCompression) != Z_DEFLATED) 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.\n", filename, name); Printf("\n: %s: '%s' uses an unsupported compression algorithm (#%d).\n", filename, name, zip_fh->Method);
skipped++; skipped++;
continue; continue;
} }
// Also ignore encrypted entries // Also ignore encrypted entries
if(LittleShort(zip_fh->wFlags) & ZF_ENCRYPTED) if(LittleShort(zip_fh->Flags) & ZF_ENCRYPTED)
{ {
Printf("\n%s: '%s' is encrypted. Encryption is not supported.\n", filename, name); Printf("\n%s: '%s' is encrypted. Encryption is not supported.\n", filename, name);
skipped++; skipped++;
@ -591,16 +594,16 @@ void FWadCollection::AddFile (const char *filename, const char * data, int lengt
} }
//ExtractFileBase(name, base); //ExtractFileBase(name, base);
char * lname=strrchr(name,'/'); char *lname = strrchr(name,'/');
if (!lname) lname=name; if (!lname) lname = name;
else lname++; else lname++;
strcpy(base, lname); strcpy(base, lname);
char * dot = strrchr(base,'.'); char *dot = strrchr(base, '.');
if (dot) *dot=0; if (dot) *dot = 0;
uppercopy(lump_p->name, base); uppercopy(lump_p->name, base);
lump_p->name[8] = 0; lump_p->name[8] = 0;
lump_p->fullname = copystring(name); lump_p->fullname = copystring(name);
lump_p->size = zip_fh->dwSize; lump_p->size = LittleLong(zip_fh->UncompressedSize);
// Map some directories to WAD namespaces. // Map some directories to WAD namespaces.
// Note that some of these namespaces don't exist in WADS. // Note that some of these namespaces don't exist in WADS.
@ -621,15 +624,15 @@ void FWadCollection::AddFile (const char *filename, const char * data, int lengt
// Anything that is not in one of these subdirectories or the main directory // 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 // should not be accessible through the standard WAD functions but only through
// the ones which look for the full name. // the ones which look for the full name.
if (lump_p->namespc==-1) if (lump_p->namespc == -1)
{ {
memset(lump_p->name, 0, 8); memset(lump_p->name, 0, 8);
} }
lump_p->wadnum = (WORD)Wads.Size(); lump_p->wadnum = (WORD)Wads.Size();
lump_p->flags = LittleShort(zip_fh->wCompression) == Z_DEFLATED? lump_p->flags = (zip_fh->Method != METHOD_STORED) ? LUMPF_COMPRESSED|LUMPF_ZIPFILE : LUMPF_ZIPFILE;
LUMPF_COMPRESSED|LUMPF_ZIPFILE : LUMPF_ZIPFILE; lump_p->method = zip_fh->Method;
lump_p->compressedsize = LittleLong(zip_fh->dwCompressedSize); lump_p->compressedsize = LittleLong(zip_fh->CompressedSize);
// Since '\' can't be used as a file name's part inside a ZIP // 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 // we have to work around this for sprites because it is a valid
@ -638,15 +641,15 @@ void FWadCollection::AddFile (const char *filename, const char * data, int lengt
{ {
char * c; char * c;
while ((c=(char*)memchr(lump_p->name, '^', 8))) while ((c = (char*)memchr(lump_p->name, '^', 8)))
{ {
*c='\\'; *c = '\\';
} }
} }
// The start of the file will be determined the first time it is accessed. // The start of the file will be determined the first time it is accessed.
lump_p->flags |= LUMPF_NEEDFILESTART; lump_p->flags |= LUMPF_NEEDFILESTART;
lump_p->position = LittleLong(zip_fh->dwFileOffset); lump_p->position = LittleLong(zip_fh->LocalHeaderOffset);
lump_p++; lump_p++;
} }
// Resize the lump record array to its actual size // Resize the lump record array to its actual size
@ -716,30 +719,40 @@ void FWadCollection::AddFile (const char *filename, const char * data, int lengt
for(unsigned int i = 0; i < EmbeddedWADs.Size(); i++) for(unsigned int i = 0; i < EmbeddedWADs.Size(); i++)
{ {
FZipFileInfo * zip_fh = EmbeddedWADs[i]; FZipCentralDirectoryInfo *zip_fh = EmbeddedWADs[i];
FZipLocalHeader localHeader; FZipLocalFileHeader localHeader;
*wadstr=0; *wadstr = 0;
size_t len = LittleShort(zip_fh->wFileNameSize); size_t len = LittleShort(zip_fh->NameLength);
if (len+strlen(path) > 255) len = 255-strlen(path); if (len + strlen(path) > 255) len = 255 - strlen(path);
strncpy(wadstr, ((char*)zip_fh) + sizeof(FZipFileInfo), len); strncpy(wadstr, ((char*)zip_fh) + sizeof(FZipCentralDirectoryInfo), len);
wadstr[len]=0; wadstr[len] = 0;
DWORD size = LittleLong(zip_fh->dwSize); DWORD size = LittleLong(zip_fh->UncompressedSize);
char * buffer = new char[size]; char *buffer = new char[size];
int position = LittleLong(zip_fh->dwFileOffset) ; int position = LittleLong(zip_fh->LocalHeaderOffset) ;
wadinfo->Seek(position, SEEK_SET); wadinfo->Seek(position, SEEK_SET);
wadinfo->Read(&localHeader, sizeof(localHeader)); wadinfo->Read(&localHeader, sizeof(localHeader));
position += LittleShort(localHeader.wExtraSize) + sizeof(FZipLocalHeader) + LittleShort(zip_fh->wFileNameSize); position += sizeof(FZipLocalFileHeader) + LittleShort(localHeader.ExtraLength) + LittleShort(zip_fh->NameLength);
wadinfo->Seek(position, SEEK_SET); wadinfo->Seek(position, SEEK_SET);
if (zip_fh->wCompression == Z_DEFLATED) if (LittleShort(zip_fh->Method) == METHOD_DEFLATE)
{ {
FileReaderZ frz(*wadinfo, true); FileReaderZ frz(*wadinfo, true);
frz.Read(buffer, size); frz.Read(buffer, size);
} }
else if (LittleShort(zip_fh->Method) == METHOD_LZMA)
{
FileReaderLZMA frz(*wadinfo, size, true);
frz.Read(buffer, size);
}
else if (LittleShort(zip_fh->Method) == METHOD_BZIP2)
{
FileReaderBZ2 frz(*wadinfo);
frz.Read(buffer, size);
}
else else
{ {
wadinfo->Read(buffer, size); wadinfo->Read(buffer, size);
@ -1746,16 +1759,16 @@ void FWadCollection::SetLumpAddress(LumpRecord *l)
// This file is inside a zip and has not been opened before. // 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 // 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. // read and skip so that we can get to the actual file data.
FZipLocalHeader localHeader; FZipLocalFileHeader localHeader;
int skiplen; int skiplen;
int address; int address;
WadFileRecord *wad = Wads[l->wadnum]; WadFileRecord *wad = Wads[l->wadnum];
address = wad->Tell(); address = wad->Tell();
wad->Seek (l->position, SEEK_SET); wad->Seek(l->position, SEEK_SET);
wad->Read (&localHeader, sizeof(localHeader)); wad->Read(&localHeader, sizeof(localHeader));
skiplen = LittleShort(localHeader.wFileNameSize) + LittleShort(localHeader.wExtraSize); skiplen = LittleShort(localHeader.NameLength) + LittleShort(localHeader.ExtraLength);
l->position += sizeof(localHeader) + skiplen; l->position += sizeof(localHeader) + skiplen;
l->flags &= ~LUMPF_NEEDFILESTART; l->flags &= ~LUMPF_NEEDFILESTART;
} }
@ -1792,10 +1805,27 @@ FWadLump FWadCollection::OpenLumpNum (int lump)
if (l->flags & LUMPF_COMPRESSED) if (l->flags & LUMPF_COMPRESSED)
{ {
// A compressed entry in a .zip file // A compressed entry in a .zip file
char * buffer = new char[l->size+1]; // the last byte is used as a reference counter char *buffer = new char[l->size + 1]; // the last byte is used as a reference counter
buffer[l->size] = 0; buffer[l->size] = 0;
FileReaderZ frz(*wad, true); if (l->method == METHOD_DEFLATE)
frz.Read(buffer, l->size); {
FileReaderZ frz(*wad, true);
frz.Read(buffer, l->size);
}
else if (l->method == METHOD_LZMA)
{
FileReaderLZMA frz(*wad, l->size, true);
frz.Read(buffer, l->size);
}
else if (l->method == METHOD_BZIP2)
{
FileReaderBZ2 frz(*wad);
frz.Read(buffer, l->size);
}
else
{
assert(0); // Should not get here
}
return FWadLump(buffer, l->size, true); return FWadLump(buffer, l->size, true);
} }
else if (l->flags & LUMPF_EXTERNAL) else if (l->flags & LUMPF_EXTERNAL)
@ -1875,10 +1905,27 @@ FWadLump *FWadCollection::ReopenLumpNum (int lump)
{ {
// A compressed entry in a .zip file // A compressed entry in a .zip file
int address = wad->Tell(); // read from the existing WadFileRecord without reopening int address = wad->Tell(); // read from the existing WadFileRecord without reopening
char * buffer = new char[l->size+1]; // the last byte is used as a reference counter char *buffer = new char[l->size + 1]; // the last byte is used as a reference counter
wad->Seek(l->position, SEEK_SET); wad->Seek(l->position, SEEK_SET);
FileReaderZ frz(*wad, true); if (l->method == METHOD_DEFLATE)
frz.Read(buffer, l->size); {
FileReaderZ frz(*wad, true);
frz.Read(buffer, l->size);
}
else if (l->method == METHOD_LZMA)
{
FileReaderLZMA frz(*wad, l->size, true);
frz.Read(buffer, l->size);
}
else if (l->method == METHOD_BZIP2)
{
FileReaderBZ2 frz(*wad);
frz.Read(buffer, l->size);
}
else
{
assert(0); // Should not get here
}
wad->Seek(address, SEEK_SET); wad->Seek(address, SEEK_SET);
return new FWadLump(buffer, l->size, true); //... but restore the file pointer afterward! return new FWadLump(buffer, l->size, true); //... but restore the file pointer afterward!
} }

View file

@ -1,62 +1,72 @@
#ifndef __W_ZIP #ifndef __W_ZIP
#define __W_ZIP #define __W_ZIP
#pragma pack(1) #pragma pack(push, 1)
struct FZipCentralInfo // FZipCentralInfo
struct FZipEndOfCentralDirectory
{ {
// patched together from information from Q3's unzip.c DWORD Magic;
DWORD dwSignature; WORD DiskNumber;
WORD wNumberDisk; WORD FirstDisk;
WORD wNumberDiskWithCD; WORD NumEntries;
WORD wEntryCount; WORD NumEntriesOnAllDisks;
WORD wTotalEntryCount; DWORD DirectorySize;
DWORD dwCDSize; DWORD DirectoryOffset;
DWORD dwCDOffset; WORD ZipCommentLength;
WORD wCommentSize;
}; };
struct FZipFileInfo // FZipFileInfo
struct FZipCentralDirectoryInfo
{ {
// patched together from information from Q3's unzip.c DWORD Magic;
DWORD dwSignature; BYTE VersionMadeBy[2];
WORD wVersion; BYTE VersionToExtract[2];
WORD wRequiredVersion; WORD Flags;
WORD wFlags; WORD Method;
WORD wCompression; WORD ModTime;
DWORD dwLastModified; WORD ModDate;
DWORD dwCrc; DWORD CRC32;
DWORD dwCompressedSize; DWORD CompressedSize;
DWORD dwSize; DWORD UncompressedSize;
WORD wFileNameSize; WORD NameLength;
WORD wExtraSize; WORD ExtraLength;
WORD wCommentSize; WORD CommentLength;
WORD wDiskStart; WORD StartingDiskNumber;
WORD wInternalAttributes; WORD InternalAttributes;
DWORD wExternalAttributes; DWORD ExternalAttributes;
DWORD dwFileOffset; DWORD LocalHeaderOffset;
// file name and other variable length info follows // file name and other variable length info follows
}; };
struct FZipLocalHeader // FZipLocalHeader
struct FZipLocalFileHeader
{ {
// patched together from information from Q3's unzip.c DWORD Magic;
DWORD dwSignature; BYTE VersionToExtract[2];
WORD wRequiredVersion; WORD Flags;
WORD wFlags; WORD Method;
WORD wCompression; WORD ModTime;
DWORD dwLastModified; WORD ModDate;
DWORD dwCrc; DWORD CRC32;
DWORD dwCompressedSize; DWORD CompressedSize;
DWORD dwSize; DWORD UncompressedSize;
WORD wFileNameSize; WORD NameLength;
WORD wExtraSize; WORD ExtraLength;
// file name and other variable length info follows // file name and other variable length info follows
}; };
#pragma pack() #pragma pack(pop)
#define Z_DEFLATED 8 #define ZIP_LOCALFILE MAKE_ID('P','K',3,4)
#define ZIP_CENTRALFILE MAKE_ID('P','K',1,2)
#define ZIP_ENDOFDIR MAKE_ID('P','K',5,6)
#define METHOD_STORED 0
#define METHOD_DEFLATE 8
#define METHOD_BZIP2 12
#define METHOD_LZMA 14
#define METHOD_PPMD 98
// File header flags. // File header flags.
#define ZF_ENCRYPTED 0x1 #define ZF_ENCRYPTED 0x1

View file

@ -1004,7 +1004,7 @@ static void StackWalk (HANDLE file, void *dumpaddress, DWORD *topOfStack, DWORD
const BYTE *bytep = (BYTE *)code; const BYTE *bytep = (BYTE *)code;
BYTE peekb; BYTE peekb;
#define chkbyte(x,m,v) SafeReadMemory(x, &peekb, 1) && ((peekb & m) == v) #define chkbyte(x,m,v) (SafeReadMemory(x, &peekb, 1) && ((peekb & m) == v))
if (chkbyte(bytep - 5, 0xFF, 0xE8) || chkbyte(bytep - 5, 0xFF, 0xE9)) if (chkbyte(bytep - 5, 0xFF, 0xE8) || chkbyte(bytep - 5, 0xFF, 0xE9))
{ {