Update to ZDoom r1552:

- Gave the intermission screen sounds their own SNDINFO entries.
- Removed obsolete snd_surround cvar.
- Changing screen resolution now adjusts the automap scale to be constant
  relative to screen resolution.
- Fixed: When FMultiPatchTexture::MakeTexture() needed to work in RGB
  colorspace, it didn't zero out the temporary buffer.
- Fixed memory leak from leftover code for 7z loading and added the
  LUMPF_ZIPFILE flag to their contents so they have the same semantics
  as zips.
- Added support for 7z archives.
- Added -noautoload option.
- Added default Raven automap colors set. Needs to be tested because I can't
  compare against the DOS version myself.
- Extened A_PlaySound and A_StopSound to be able to set all parameters of the
  internal sound code.
- Changed gravity doubling so that it only happens when you run off a ledge.
- Fixed: World panning was ignored for the X offset of masked midtextures.
- Extended MF5_MOVEWITHSECTOR so that it always keeps the actor on the ground
  of a moving floor, regardless of movement speed. For NOBLOCKMAP items this
  is necessary because otherwise they can be left in the air and it also adds 
  some options for other things.
- Changed A_FreezeDeathChunks() so that instead of directly destroying an
  actor, it sets it to the "Null" state, which will make it invisible and
  destroy it one tic later.
- Added a NULL pointer check to A_Fire() and copied the target to a local
  variable inside A_VileAttack() so that if P_DamageMobj() destroys the
  target, the function will still have a valid pointer to it (since reading
  it from the actor's instance data invokes the read barrier, which would
  return NULL).
- Added NOBLOCKMAP/MOVEWITHSECTOR combination to a few items that had their
  NOBLOCKMAP flag taken away previously to make them move with a sector.
  This should fix the performance problem Claustrophobia had with recent
  ZDoom versions.
- Added MF5_MOVEWITHSECTOR flag, so you can have the benefits of MF_NOBLOCKMAP
  but still have actors that will move up and down with the floor. IceChunk
  now uses both of these flags.
- Performance optimization for FBlockThingsIterator::Next(): Actors that
  exist in only one block don't need to be added to the CheckArray or
  scanned for in it. Also changed the array used to keep track of visited
  actors into a hash table.
- added some default definitions for constants that may miss in some headers.
- replaced __va_copy with va_copy per Chris's suggestion.
- replaced #include <malloc.h> with #include <stdlib.h> where possible.


git-svn-id: http://mancubus.net/svn/hosted/gzdoom/trunk@322 b0f79afe-0144-0410-b225-9a4edf0717df
This commit is contained in:
Christoph Oelckers 2009-04-19 06:46:53 +00:00
parent 4c1cbcedfa
commit 83639c7877
57 changed files with 1073 additions and 397 deletions

View file

@ -1,4 +1,71 @@
April 6, 2009 (Changes by Graf Zahl)
April 17, 2009
- Gave the intermission screen sounds their own SNDINFO entries.
April 16, 2009
- Removed obsolete snd_surround cvar.
April 15, 2009
- Changing screen resolution now adjusts the automap scale to be constant
relative to screen resolution.
- Fixed: When FMultiPatchTexture::MakeTexture() needed to work in RGB
colorspace, it didn't zero out the temporary buffer.
- Fixed memory leak from leftover code for 7z loading and added the
LUMPF_ZIPFILE flag to their contents so they have the same semantics
as zips.
April 14, 2009
- Added support for 7z archives.
April 13, 2009 (Changes by Graf Zahl)
- Added -noautoload option.
- Added default Raven automap colors set. Needs to be tested because I can't
compare against the DOS version myself.
- Extened A_PlaySound and A_StopSound to be able to set all parameters of the
internal sound code.
April 13, 2009
- Changed gravity doubling so that it only happens when you run off a ledge.
April 10, 2009
- Fixed: World panning was ignored for the X offset of masked midtextures.
April 10, 2009 (Changes by Graf Zahl)
- Extended MF5_MOVEWITHSECTOR so that it always keeps the actor on the ground
of a moving floor, regardless of movement speed. For NOBLOCKMAP items this
is necessary because otherwise they can be left in the air and it also adds
some options for other things.
April 9, 2009
- Changed A_FreezeDeathChunks() so that instead of directly destroying an
actor, it sets it to the "Null" state, which will make it invisible and
destroy it one tic later.
- Added a NULL pointer check to A_Fire() and copied the target to a local
variable inside A_VileAttack() so that if P_DamageMobj() destroys the
target, the function will still have a valid pointer to it (since reading
it from the actor's instance data invokes the read barrier, which would
return NULL).
April 9, 2009 (Changes by Graf Zahl)
- Added NOBLOCKMAP/MOVEWITHSECTOR combination to a few items that had their
NOBLOCKMAP flag taken away previously to make them move with a sector.
This should fix the performance problem Claustrophobia had with recent
ZDoom versions.
April 8, 2009
- Added MF5_MOVEWITHSECTOR flag, so you can have the benefits of MF_NOBLOCKMAP
but still have actors that will move up and down with the floor. IceChunk
now uses both of these flags.
- Performance optimization for FBlockThingsIterator::Next(): Actors that
exist in only one block don't need to be added to the CheckArray or
scanned for in it. Also changed the array used to keep track of visited
actors into a hash table.
April 7, 2009 (Changes by Graf Zahl)
- added some default definitions for constants that may miss in some headers.
- replaced __va_copy with va_copy per Chris's suggestion.
- replaced #include <malloc.h> with #include <stdlib.h> where possible.
April 6, 2009 (Changes by Graf Zahl)
- Fixed: The UDMF textmap readbuffer was never freed.
April 4, 2009

View file

@ -56,7 +56,7 @@
FavorSizeOrSpeed="1"
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;bzip2;lzma\C"
PreprocessorDefinitions="NDEBUG,WIN32,_WIN32,_WINDOWS,USEASM,NO_MANIFEST"
PreprocessorDefinitions="NDEBUG,WIN32,_WIN32,_WINDOWS,USEASM,NO_MANIFEST,NO_VA_COPY"
StringPooling="true"
RuntimeLibrary="0"
EnableFunctionLevelLinking="true"
@ -173,7 +173,7 @@
Optimization="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;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,NO_VA_COPY"
MinimalRebuild="true"
RuntimeLibrary="1"
EnableFunctionLevelLinking="true"
@ -281,7 +281,7 @@
FavorSizeOrSpeed="1"
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;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,NO_VA_COPY"
StringPooling="true"
RuntimeLibrary="0"
EnableFunctionLevelLinking="false"
@ -391,7 +391,7 @@
Name="VCCLCompilerTool"
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;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,NO_VA_COPY"
MinimalRebuild="true"
RuntimeLibrary="1"
EnableFunctionLevelLinking="true"

View file

@ -6,6 +6,10 @@
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
#define SZ_OK 0
#define SZ_ERROR_DATA 1
@ -197,4 +201,8 @@ typedef struct
#define IAlloc_Alloc(p, size) (p)->Alloc((p), size)
#define IAlloc_Free(p, a) (p)->Free((p), a)
#ifdef __cplusplus
}
#endif
#endif

View file

@ -5,7 +5,17 @@ if( CMAKE_COMPILER_IS_GNUC )
endif( CMAKE_COMPILER_IS_GNUC )
set( LZMA_FILES
C/Archive/7z/7zDecode.c
C/Archive/7z/7zExtract.c
C/Archive/7z/7zHeader.c
C/Archive/7z/7zIn.c
C/Archive/7z/7zItem.c
C/7zBuf.c
C/7zCrc.c
C/7zStream.c
C/Alloc.c
C/Bcj2.c
C/Bra86.c
C/LzFind.c
C/LzFindMt.c
C/LzmaDec.c

View file

@ -286,10 +286,30 @@
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
>
<File
RelativePath=".\C\7zBuf.c"
>
</File>
<File
RelativePath=".\C\7zCrc.c"
>
</File>
<File
RelativePath=".\C\7zStream.c"
>
</File>
<File
RelativePath=".\C\Alloc.c"
>
</File>
<File
RelativePath=".\C\Bcj2.c"
>
</File>
<File
RelativePath=".\C\Bra86.c"
>
</File>
<File
RelativePath=".\C\LzFind.c"
>
@ -320,6 +340,14 @@
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
>
<File
RelativePath=".\C\7zBuf.h"
>
</File>
<File
RelativePath=".\C\7zCrc.h"
>
</File>
<File
RelativePath=".\C\7zVersion.h"
>
@ -328,6 +356,18 @@
RelativePath=".\C\Alloc.h"
>
</File>
<File
RelativePath=".\C\Bcj2.h"
>
</File>
<File
RelativePath=".\C\Bra.h"
>
</File>
<File
RelativePath=".\C\CpuArch.h"
>
</File>
<File
RelativePath=".\C\LzFind.h"
>
@ -361,6 +401,50 @@
>
</File>
</Filter>
<Filter
Name="7z"
>
<File
RelativePath=".\C\Archive\7z\7zDecode.c"
>
</File>
<File
RelativePath=".\C\Archive\7z\7zDecode.h"
>
</File>
<File
RelativePath=".\C\Archive\7z\7zExtract.c"
>
</File>
<File
RelativePath=".\C\Archive\7z\7zExtract.h"
>
</File>
<File
RelativePath=".\C\Archive\7z\7zHeader.c"
>
</File>
<File
RelativePath=".\C\Archive\7z\7zHeader.h"
>
</File>
<File
RelativePath=".\C\Archive\7z\7zIn.c"
>
</File>
<File
RelativePath=".\C\Archive\7z\7zIn.h"
>
</File>
<File
RelativePath=".\C\Archive\7z\7zItem.c"
>
</File>
<File
RelativePath=".\C\Archive\7z\7zItem.h"
>
</File>
</Filter>
<File
RelativePath=".\CMakeLists.txt"
>

View file

@ -4,6 +4,7 @@ if( COMMAND cmake_policy )
cmake_policy( SET CMP0003 NEW )
endif( COMMAND cmake_policy )
include( CheckCXXSourceCompiles )
include( CheckFunctionExists )
include( FindPkgConfig )
include( FindOpenGL )
@ -316,7 +317,10 @@ endif( NOT NO_ASM )
# Set up flags for GCC
if( CMAKE_COMPILER_IS_GNUCXX )
set( REL_CXX_FLAGS "-fno-rtti -fomit-frame-pointer" )
set( REL_CXX_FLAGS "-fno-rtti" )
if( NOT PROFILE )
set( REL_CXX_FLAGS "${REL_CXX_FLAGS} -fomit-frame-pointer" )
endif( NOT PROFILE )
set( CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${REL_CXX_FLAGS}" )
set( CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL} ${REL_CXX_FLAGS}" )
set( CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} ${REL_CXX_FLAGS}" )
@ -368,7 +372,23 @@ if( UNIX )
endif( NOT CLOCK_GETTIME_IN_RT )
endif( UNIX )
# Update svnrevision_gz.h
CHECK_CXX_SOURCE_COMPILES(
"#include <stdarg.h>
int main() { va_list list1, list2; va_copy(list1, list2); return 0; }"
HAS_VA_COPY )
if( NOT HAS_VA_COPY )
CHECK_CXX_SOURCE_COMPILES(
"#include <stdarg.h>
int main() { va_list list1, list2; __va_copy(list1, list2); return 0; }"
HAS___VA_COPY )
if( HAS___VA_COPY )
add_definitions( -Dva_copy=__va_copy )
else( HAS___VA_COPY )
add_definitions( -DNO_VA_COPY )
endif( HAS___VA_COPY )
endif( NOT HAS_VA_COPY )
# Update svnrevision.h
add_custom_target( revision_check ALL
COMMAND ${CMAKE_BINARY_DIR}/tools/updaterevision/updaterevision . src/svnrevision_gz.h

View file

@ -308,6 +308,7 @@ enum
MF5_CANTSEEK = 0x10000000, // seeker missiles cannot home in on this actor
MF5_INCONVERSATION = 0x20000000, // Actor is having a conversation
MF5_PAINLESS = 0x40000000, // Actor always inflicts painless damage.
MF5_MOVEWITHSECTOR = 0x80000000, // P_ChangeSector() will still process this actor if it has MF_NOBLOCKMAP
// --- mobj.renderflags ---

View file

@ -104,6 +104,15 @@ static BYTE StrifePaletteVals[11*3] =
187, 59, 0, 219, 171, 0
};
static AMColor RavenColors[11];
static BYTE RavenPaletteVals[11*3] =
{
0x6c,0x54,0x40, 255, 255, 255, 0x74,0x5c,0x48,
75, 50, 16, 88, 93, 86, 208, 176, 133,
103, 59, 31, 236, 236, 236, 0, 0, 0,
0, 0, 0, 0, 0, 0,
};
#define MAPBITS 12
#define MapDiv SafeDivScale12
#define MapMul MulScale12
@ -361,6 +370,7 @@ static fixed_t mapxstart=0; //x-value for the bitmap.
static bool stopped = true;
static void AM_calcMinMaxMtoF();
void AM_rotatePoint (fixed_t *x, fixed_t *y);
void AM_rotate (fixed_t *x, fixed_t *y, angle_t an);
@ -386,7 +396,7 @@ void AM_getIslope (mline_t *ml, islope_t *is)
}
*/
void AM_GetPosition(fixed_t & x, fixed_t & y)
void AM_GetPosition(fixed_t &x, fixed_t &y)
{
x = (m_x + m_w/2) << FRACTOMAPBITS;
y = (m_y + m_h/2) << FRACTOMAPBITS;
@ -463,14 +473,10 @@ bool AM_addMark ()
//
static void AM_findMinMaxBoundaries ()
{
int i;
fixed_t a;
fixed_t b;
min_x = min_y = FIXED_MAX;
max_x = max_y = FIXED_MIN;
for (i = 0; i < numvertexes; i++)
for (int i = 0; i < numvertexes; i++)
{
if (vertexes[i].x < min_x)
min_x = vertexes[i].x;
@ -489,8 +495,13 @@ static void AM_findMinMaxBoundaries ()
min_w = 2*PLAYERRADIUS; // const? never changed?
min_h = 2*PLAYERRADIUS;
a = MapDiv (SCREENWIDTH << MAPBITS, max_w);
b = MapDiv (::ST_Y << MAPBITS, max_h);
AM_calcMinMaxMtoF();
}
static void AM_calcMinMaxMtoF()
{
fixed_t a = MapDiv (SCREENWIDTH << MAPBITS, max_w);
fixed_t b = MapDiv (::ST_Y << MAPBITS, max_h);
min_scale_mtof = a < b ? a : b;
max_scale_mtof = MapDiv (SCREENHEIGHT << MAPBITS, 2*PLAYERRADIUS);
@ -683,6 +694,7 @@ static void AM_initColors (bool overlayed)
{
DoomColors[i].FromRGB(DoomPaletteVals[j], DoomPaletteVals[j+1], DoomPaletteVals[j+2]);
StrifeColors[i].FromRGB(StrifePaletteVals[j], StrifePaletteVals[j+1], StrifePaletteVals[j+2]);
RavenColors[i].FromRGB(RavenPaletteVals[j], RavenPaletteVals[j+1], RavenPaletteVals[j+2]);
}
}
@ -784,6 +796,28 @@ static void AM_initColors (bool overlayed)
XHairColor = DoomColors[9];
NotSeenColor = DoomColors[10];
break;
case 3: // Raven
// Use colors corresponding to the original Raven's
Background = RavenColors[0];
YourColor = RavenColors[1];
AlmostBackground = DoomColors[2];
SecretSectorColor =
SecretWallColor =
WallColor = RavenColors[3];
TSWallColor = RavenColors[4];
FDWallColor = RavenColors[5];
LockedColor =
CDWallColor = RavenColors[6];
ThingColor =
ThingColor_Item =
ThingColor_Friend =
ThingColor_Monster = RavenColors[7];
GridColor = RavenColors[4];
XHairColor = RavenColors[9];
NotSeenColor = RavenColors[10];
break;
}
lastpal = palette;
@ -832,9 +866,6 @@ void AM_LevelInit ()
scale_ftom = MapDiv(MAPUNIT, scale_mtof);
}
//
//
//
@ -857,6 +888,8 @@ void AM_Start ()
AM_loadPics();
}
//
// set the window scale to the maximum size
//
@ -875,6 +908,24 @@ void AM_maxOutWindowScale ()
scale_ftom = MapDiv(MAPUNIT, scale_mtof);
}
//
// Called right after the resolution has changed
//
void AM_NewResolution()
{
fixed_t oldmin = min_scale_mtof;
AM_calcMinMaxMtoF();
scale_mtof = Scale(scale_mtof, min_scale_mtof, oldmin);
scale_ftom = MapDiv(MAPUNIT, scale_mtof);
if (scale_mtof < min_scale_mtof)
AM_minOutWindowScale();
else if (scale_mtof > max_scale_mtof)
AM_maxOutWindowScale();
f_w = screen->GetWidth();
f_h = ST_Y;
AM_activateNewScale();
}
CCMD (togglemap)
{
@ -1433,7 +1484,7 @@ void AM_drawWalls (bool allmap)
lines[i].special == ACS_LockedExecuteDoor ||
(lines[i].special == Generic_Door && lines[i].args[4] !=0 ))
{
if (am_colorset == 0)
if (am_colorset == 0 || am_colorset == 3) // Raven games show door colors
{
int P_GetMapColorForLock(int lock);
int lock;

View file

@ -39,6 +39,7 @@ void AM_Drawer (void);
// if the level is completed while it is up.
void AM_Stop (void);
void AM_NewResolution ();
void AM_ToggleMap ();
void AM_LevelInit ();
void AM_SerializeMarkers(FArchive &arc);

View file

@ -5,7 +5,7 @@
* bot need to work *
*******************************/
#include <malloc.h>
#include <stdlib.h>
#include "doomtype.h"
#include "doomdef.h"

View file

@ -894,7 +894,7 @@ static int PatchThing (int thingy)
// don't specify a new height.
if (info->flags & MF_SPAWNCEILING &&
!hadHeight &&
thingy <= OrgHeights.Size() && thingy > 0)
thingy <= (int)OrgHeights.Size() && thingy > 0)
{
info->height = OrgHeights[thingy - 1] * FRACUNIT;
info->projectilepassheight = 0;
@ -1069,7 +1069,7 @@ static int PatchFrame (int frameNum)
{
unsigned int i;
if (val < OrgSprNames.Size())
if (val < (int)OrgSprNames.Size())
{
for (i = 0; i < sprites.Size(); i++)
{

View file

@ -540,6 +540,7 @@ void D_Display ()
C_NewModeAdjust ();
// Reload crosshair if transitioned to a different size
crosshair.Callback ();
AM_NewResolution ();
}
}
@ -1605,7 +1606,7 @@ void D_DoomMain (void)
GameConfig->DoGameSetup (GameNames[gameinfo.gametype]);
if (!(gameinfo.flags & GI_SHAREWARE))
if (!(gameinfo.flags & GI_SHAREWARE) && !Args->CheckParm("-noautoload"))
{
FString file;

View file

@ -25,7 +25,7 @@
#include <ctype.h>
#include <math.h>
#include <malloc.h>
#include <stdlib.h>
#include "i_system.h"
#include "m_swap.h"

View file

@ -43,7 +43,7 @@
#include <stddef.h>
#include <string.h>
#include <zlib.h>
#include <malloc.h>
#include <stdlib.h>
#include "doomtype.h"
#include "farchive.h"

View file

@ -364,7 +364,7 @@ extern "C" void bz_internal_error (int errcode)
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 };
ISzAlloc g_Alloc = { SzAlloc, SzFree };
FileReaderLZMA::FileReaderLZMA (FileReader &file, size_t uncompressed_size, bool zip)
: File(file), SawEOF(false)

View file

@ -55,7 +55,7 @@ void A_Fire(AActor *self, int height)
angle_t an;
dest = self->tracer;
if (!dest)
if (dest == NULL || self->target == NULL)
return;
// don't move it if the vile lost sight
@ -103,33 +103,33 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_VileTarget)
//
DEFINE_ACTION_FUNCTION(AActor, A_VileAttack)
{
AActor *fire;
AActor *fire, *target;
int an;
if (!self->target)
if (NULL == (target = self->target))
return;
A_FaceTarget (self);
if (!P_CheckSight (self, self->target, 0) )
if (!P_CheckSight (self, target, 0) )
return;
S_Sound (self, CHAN_WEAPON, "vile/stop", 1, ATTN_NORM);
P_DamageMobj (self->target, self, self, 20, NAME_None);
P_TraceBleed (20, self->target);
self->target->momz = 1000 * FRACUNIT / self->target->Mass;
P_TraceBleed (20, target);
P_DamageMobj (target, self, self, 20, NAME_None);
target->momz = 1000 * FRACUNIT / target->Mass;
an = self->angle >> ANGLETOFINESHIFT;
fire = self->tracer;
if (!fire)
return;
// move the fire between the vile and the player
fire->SetOrigin (self->target->x - FixedMul (24*FRACUNIT, finecosine[an]),
self->target->y - FixedMul (24*FRACUNIT, finesine[an]),
self->target->z);
P_RadiusAttack (fire, self, 70, 70, NAME_Fire, false);
if (fire != NULL)
{
// move the fire between the vile and the player
fire->SetOrigin (target->x - FixedMul (24*FRACUNIT, finecosine[an]),
target->y - FixedMul (24*FRACUNIT, finesine[an]),
target->z);
P_RadiusAttack (fire, self, 70, 70, NAME_Fire, false);
}
}

View file

@ -294,9 +294,9 @@ DEFINE_ACTION_FUNCTION(AActor, A_FreezeDeathChunks)
{
CALL_ACTION(A_BossDeath, self);
}
CALL_ACTION(A_NoBlocking, self);
CALL_ACTION(A_NoBlocking, self);
self->Destroy ();
self->SetState(self->FindState(NAME_Null));
}
//----------------------------------------------------------------------------

View file

@ -81,8 +81,11 @@ typedef int SOCKET;
#define WSAGetLastError() errno
#endif
#ifdef __WIN32__
#ifndef IPPORT_USERRESERVED
#define IPPORT_USERRESERVED 5000
#endif
#ifdef __WIN32__
typedef int socklen_t;
#endif

View file

@ -32,7 +32,12 @@
**
*/
#ifdef __FreeBSD__
#include <stdlib.h>
#include <malloc_np.h>
#else
#include <malloc.h>
#endif
#include "i_system.h"
#include "dobject.h"

View file

@ -29,7 +29,7 @@
#include <fcntl.h>
#include <stdlib.h>
#include <errno.h>
#include <malloc.h>
#include <stdlib.h>
#include <time.h>
#include "doomtype.h"

View file

@ -584,7 +584,8 @@ EXTERN_CVAR (Bool, am_drawmapback)
static value_t MapColorTypes[] = {
{ 0, "Custom" },
{ 1, "Traditional Doom" },
{ 2, "Traditional Strife" }
{ 2, "Traditional Strife" },
{ 3, "Traditional Raven" }
};
static value_t SecretTypes[] = {
@ -606,7 +607,7 @@ static value_t OverlayTypes[] = {
};
static menuitem_t AutomapItems[] = {
{ discrete, "Map color set", {&am_colorset}, {3.0}, {0.0}, {0.0}, {MapColorTypes} },
{ discrete, "Map color set", {&am_colorset}, {4.0}, {0.0}, {0.0}, {MapColorTypes} },
{ more, "Set custom colors", {NULL}, {0.0}, {0.0}, {0.0}, {(value_t*)StartMapColorsMenu} },
{ redtext, " ", {NULL}, {0.0}, {0.0}, {0.0}, {NULL} },
{ discrete, "Rotate automap", {&am_rotate}, {3.0}, {0.0}, {0.0}, {RotateTypes} },

View file

@ -1,5 +1,6 @@
// 'None' must always be the first name.
xx(None)
xx(Null)
xx(Super)
xx(Object)

View file

@ -39,7 +39,7 @@
#include <stdlib.h>
#include <assert.h>
#include <malloc.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <math.h>

View file

@ -43,7 +43,7 @@
* Added modulation wheel (vibrato) support
*/
#include <malloc.h>
#include <stdlib.h>
#include <string.h>
#ifdef _WIN32
#include <io.h>

View file

@ -256,32 +256,39 @@ public:
class FBlockThingsIterator
{
static TArray<AActor *> CheckArray;
int minx, maxx;
int miny, maxy;
int curx, cury;
bool dontfreecheck;
int checkindex;
FBlockNode *block;
void StartBlock(int x, int y);
int Buckets[32];
// The following 3 functions are only for use in the path traverser
struct HashEntry
{
AActor *Actor;
int Next;
};
HashEntry FixedHash[10];
int NumFixedHash;
TArray<HashEntry> DynHash;
HashEntry *GetHashEntry(int i) { return i < (int)countof(FixedHash) ? &FixedHash[i] : &DynHash[i - countof(FixedHash)]; }
void StartBlock(int x, int y);
void SwitchBlock(int x, int y);
void ClearHash();
// The following is only for use in the path traverser
// and therefore declared private.
static int GetCheckIndex();
static void SetCheckIndex(int newvalue);
FBlockThingsIterator(int x, int y, int checkindex);
FBlockThingsIterator();
friend class FPathTraverse;
public:
FBlockThingsIterator(int minx, int miny, int maxx, int maxy);
FBlockThingsIterator(const FBoundingBox &box);
~FBlockThingsIterator();
AActor *Next();
void Reset() { StartBlock(minx, miny); }
};
@ -297,7 +304,7 @@ class FPathTraverse
unsigned int count;
void AddLineIntercepts(int bx, int by);
void AddThingIntercepts(int bx, int by, int checkindex);
void AddThingIntercepts(int bx, int by, FBlockThingsIterator &it);
public:
intercept_t *Next();
@ -417,9 +424,10 @@ const secplane_t * P_CheckSlopeWalk (AActor *actor, fixed_t &xmove, fixed_t &ymo
// (For ZDoom itself this doesn't make any difference here but for GZDoom it does.)
//
//----------------------------------------------------------------------------------
subsector_t *P_PointInSubsector (fixed_t x, fixed_t y);
inline sector_t *P_PointInSector(fixed_t x, fixed_t y)
{
return R_PointInSubsector(x,y)->sector;
return P_PointInSubsector(x,y)->sector;
}
//

View file

@ -4442,7 +4442,7 @@ void PIT_FloorDrop (AActor *thing, FChangePosition *cpos)
thing->z = thing->z - oldfloorz + thing->floorz;
P_CheckFakeFloorTriggers (thing, oldz);
}
else if ((thing->flags & MF_NOGRAVITY) ||
else if ((thing->flags & MF_NOGRAVITY) || (thing->flags5 & MF5_MOVEWITHSECTOR) ||
(((cpos->sector->Flags & SECF_FLOORDROP) || cpos->moveamt < 9*FRACUNIT)
&& thing->z - thing->floorz <= cpos->moveamt))
{
@ -4634,7 +4634,11 @@ bool P_ChangeSector (sector_t *sector, int crunch, int amt, int floorOrCeil, boo
if (!n->visited)
{
n->visited = true;
if (!(n->m_thing->flags&MF_NOBLOCKMAP)) iterator(n->m_thing, &cpos);
if (!(n->m_thing->flags & MF_NOBLOCKMAP) || //jff 4/7/98 don't do these
(n->m_thing->flags5 & MF5_MOVEWITHSECTOR))
{
iterator(n->m_thing, &cpos);
}
break;
}
}
@ -4647,7 +4651,7 @@ bool P_ChangeSector (sector_t *sector, int crunch, int amt, int floorOrCeil, boo
// [RH] Use different functions for the four different types of sector
// movement. Also update the soundorg's z-coordinate for 3D sound.
// movement.
switch (floorOrCeil)
{
case 0:
@ -4694,7 +4698,8 @@ bool P_ChangeSector (sector_t *sector, int crunch, int amt, int floorOrCeil, boo
if (!n->visited) // unprocessed thing found
{
n->visited = true; // mark thing as processed
if (!(n->m_thing->flags & MF_NOBLOCKMAP)) //jff 4/7/98 don't do these
if (!(n->m_thing->flags & MF_NOBLOCKMAP) || //jff 4/7/98 don't do these
(n->m_thing->flags5 & MF5_MOVEWITHSECTOR))
{
iterator (n->m_thing, &cpos); // process it
if (iterator2 != NULL) iterator2 (n->m_thing, &cpos);

View file

@ -736,70 +736,54 @@ line_t *FBlockLinesIterator::Next()
}
}
//===========================================================================
//
// FBlockThingsIterator :: CheckArray
//
//===========================================================================
TArray<AActor *> FBlockThingsIterator::CheckArray(32);
int FBlockThingsIterator::GetCheckIndex()
{
return CheckArray.Size();
}
void FBlockThingsIterator::SetCheckIndex(int newvalue)
{
CheckArray.Resize(newvalue);
}
//===========================================================================
//
// FBlockThingsIterator :: FBlockThingsIterator
//
//===========================================================================
FBlockThingsIterator::FBlockThingsIterator(int x, int y, int check)
FBlockThingsIterator::FBlockThingsIterator()
: DynHash(0)
{
checkindex = check;
dontfreecheck = true;
minx = maxx = x;
miny = maxy = y;
Reset();
minx = maxx = 0;
miny = maxy = 0;
ClearHash();
block = NULL;
}
FBlockThingsIterator::FBlockThingsIterator(int _minx, int _miny, int _maxx, int _maxy)
: DynHash(0)
{
checkindex = CheckArray.Size();
dontfreecheck = false;
minx = _minx;
maxx = _maxx;
miny = _miny;
maxy = _maxy;
ClearHash();
Reset();
}
FBlockThingsIterator::FBlockThingsIterator(const FBoundingBox &box)
: DynHash(0)
{
checkindex = CheckArray.Size();
dontfreecheck = false;
maxy = (box.Top() - bmaporgy) >> MAPBLOCKSHIFT;
miny = (box.Bottom() - bmaporgy) >> MAPBLOCKSHIFT;
maxx = (box.Right() - bmaporgx) >> MAPBLOCKSHIFT;
minx = (box.Left() - bmaporgx) >> MAPBLOCKSHIFT;
ClearHash();
Reset();
}
//===========================================================================
//
// FBlockThingsIterator :: FreeCheckArray
// FBlockThingsIterator :: ClearHash
//
//===========================================================================
FBlockThingsIterator::~FBlockThingsIterator()
void FBlockThingsIterator::ClearHash()
{
if (!dontfreecheck) CheckArray.Resize(checkindex);
clearbuf(Buckets, countof(Buckets), -1);
NumFixedHash = 0;
DynHash.Clear();
}
//===========================================================================
@ -823,6 +807,19 @@ void FBlockThingsIterator::StartBlock(int x, int y)
}
}
//===========================================================================
//
// FBlockThingsIterator :: SwitchBlock
//
//===========================================================================
void FBlockThingsIterator::SwitchBlock(int x, int y)
{
minx = maxx = x;
miny = maxy = y;
StartBlock(x, y);
}
//===========================================================================
//
// FBlockThingsIterator :: Next
@ -831,25 +828,51 @@ void FBlockThingsIterator::StartBlock(int x, int y)
AActor *FBlockThingsIterator::Next()
{
while (true)
for (;;)
{
while (block != NULL)
{
AActor *me = block->Me;
FBlockNode *mynode = block;
HashEntry *entry;
int i;
block = block->NextActor;
// Don't recheck things that were already checked
for (i = (int)CheckArray.Size() - 1; i >= checkindex; --i)
if (mynode->NextBlock == NULL && mynode->PrevBlock == &me->BlockNode)
{ // This actor doesn't span blocks, so we know it can only ever be checked once.
return me;
}
size_t hash = ((size_t)me >> 3) % countof(Buckets);
for (i = Buckets[hash]; i >= 0; )
{
if (CheckArray[i] == me)
{
entry = GetHashEntry(i);
if (entry->Actor == me)
{ // I've already been checked. Skip to the next actor.
break;
}
i = entry->Next;
}
if (i < checkindex)
{
CheckArray.Push (me);
if (i < 0)
{ // Add me to the hash table and return me.
if (NumFixedHash < (int)countof(FixedHash))
{
entry = &FixedHash[NumFixedHash];
entry->Next = Buckets[hash];
Buckets[hash] = NumFixedHash++;
}
else
{
if (DynHash.Size() == 0)
{
DynHash.Grow(50);
}
i = DynHash.Reserve(1);
entry = &DynHash[i];
entry->Next = Buckets[hash];
Buckets[hash] = i + countof(FixedHash);
}
entry->Actor = me;
return me;
}
}
@ -937,11 +960,11 @@ void FPathTraverse::AddLineIntercepts(int bx, int by)
//
//===========================================================================
void FPathTraverse::AddThingIntercepts (int bx, int by, int checkindex)
void FPathTraverse::AddThingIntercepts (int bx, int by, FBlockThingsIterator &it)
{
FBlockThingsIterator it(bx, by, checkindex);
AActor *thing;
it.SwitchBlock(bx, by);
while ((thing = it.Next()))
{
int numfronts = 0;
@ -1176,7 +1199,7 @@ FPathTraverse::FPathTraverse (fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2, in
mapy = yt1;
// we want to use one list of checked actors for the entire operation
int BTI_CheckIndex = FBlockThingsIterator::GetCheckIndex();
FBlockThingsIterator btit;
for (count = 0 ; count < 100 ; count++)
{
if (flags & PT_ADDLINES)
@ -1186,7 +1209,7 @@ FPathTraverse::FPathTraverse (fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2, in
if (flags & PT_ADDTHINGS)
{
AddThingIntercepts(mapx, mapy, BTI_CheckIndex);
AddThingIntercepts(mapx, mapy, btit);
}
if (mapx == xt2 && mapy == yt2)
@ -1224,8 +1247,8 @@ FPathTraverse::FPathTraverse (fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2, in
if (flags & PT_ADDTHINGS)
{
AddThingIntercepts(mapx + mapxstep, mapy, BTI_CheckIndex);
AddThingIntercepts(mapx, mapy + mapystep, BTI_CheckIndex);
AddThingIntercepts(mapx + mapxstep, mapy, btit);
AddThingIntercepts(mapx, mapy + mapystep, btit);
}
xintercept += xstep;
yintercept += ystep;
@ -1234,7 +1257,6 @@ FPathTraverse::FPathTraverse (fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2, in
break;
}
}
FBlockThingsIterator::SetCheckIndex(BTI_CheckIndex);
maxfrac = FRACUNIT;
}

View file

@ -1331,13 +1331,15 @@ bool P_SeekerMissile (AActor *actor, angle_t thresh, angle_t turnMax)
}
//
// P_XYMovement
// P_XYMovement
//
// Returns the actor's old floorz.
//
#define STOPSPEED 0x1000
#define FRICTION 0xe800
#define CARRYSTOPSPEED (STOPSPEED*32/3)
void P_XYMovement (AActor *mo, fixed_t scrollx, fixed_t scrolly)
fixed_t P_XYMovement (AActor *mo, fixed_t scrollx, fixed_t scrolly)
{
bool bForceSlide = scrollx || scrolly;
angle_t angle;
@ -1348,6 +1350,7 @@ void P_XYMovement (AActor *mo, fixed_t scrollx, fixed_t scrolly)
static const int windTab[3] = {2048*5, 2048*10, 2048*25};
int steps, step, totalsteps;
fixed_t startx, starty;
fixed_t oldfloorz = mo->floorz;
fixed_t maxmove = (mo->waterlevel < 1) || (mo->flags & MF_MISSILE) ||
(mo->player && mo->player->crouchoffset<-10*FRACUNIT) ? MAXMOVE : MAXMOVE/4;
@ -1433,7 +1436,7 @@ void P_XYMovement (AActor *mo, fixed_t scrollx, fixed_t scrolly)
mo->tics = -1;
}
}
return;
return oldfloorz;
}
player = mo->player;
@ -1616,12 +1619,12 @@ void P_XYMovement (AActor *mo, fixed_t scrollx, fixed_t scrolly)
{
S_Sound (mo, CHAN_VOICE, mo->SeeSound, 1, ATTN_IDLE);
}
return;
return oldfloorz;
}
else
{ // Struck a player/creature
P_ExplodeMissile (mo, NULL, BlockingMobj);
return;
return oldfloorz;
}
}
}
@ -1634,7 +1637,7 @@ void P_XYMovement (AActor *mo, fixed_t scrollx, fixed_t scrolly)
{
S_Sound (mo, CHAN_VOICE, mo->SeeSound, 1, ATTN_IDLE);
}
return;
return oldfloorz;
}
}
if (BlockingMobj &&
@ -1661,7 +1664,7 @@ void P_XYMovement (AActor *mo, fixed_t scrollx, fixed_t scrolly)
mo->tracer = mo->target;
}
mo->target = BlockingMobj;
return;
return oldfloorz;
}
explode:
// explode a missile
@ -1674,16 +1677,16 @@ explode:
// Hack to prevent missiles exploding against the sky.
// Does not handle sky floors.
mo->Destroy ();
return;
return oldfloorz;
}
// [RH] Don't explode on horizon lines.
if (mo->BlockingLine != NULL && mo->BlockingLine->special == Line_Horizon)
{
mo->Destroy ();
return;
return oldfloorz;
}
P_ExplodeMissile (mo, mo->BlockingLine, BlockingMobj);
return;
return oldfloorz;
}
else
{
@ -1718,12 +1721,12 @@ explode:
{ // debug option for no sliding at all
mo->momx = mo->momy = 0;
player->momx = player->momy = 0;
return;
return oldfloorz;
}
if (mo->flags & (MF_MISSILE | MF_SKULLFLY))
{ // no friction for missiles
return;
return oldfloorz;
}
if (mo->z > mo->floorz && !(mo->flags2 & MF2_ONMOBJ) &&
@ -1740,7 +1743,7 @@ explode:
player->momy = FixedMul (player->momy, level.airfriction);
}
}
return;
return oldfloorz;
}
if (mo->flags & MF_CORPSE)
@ -1764,7 +1767,7 @@ explode:
}
if (i==mo->Sector->e->XFloor.ffloors.Size())
#endif
return;
return oldfloorz;
}
}
}
@ -1823,6 +1826,7 @@ explode:
player->momy = FixedMul (player->momy, ORIG_FRICTION);
}
}
return oldfloorz;
}
// Move this to p_inter ***
@ -1852,7 +1856,7 @@ void P_MonsterFallingDamage (AActor *mo)
//
// P_ZMovement
//
void P_ZMovement (AActor *mo)
void P_ZMovement (AActor *mo, fixed_t oldfloorz)
{
fixed_t dist;
fixed_t delta;
@ -1867,7 +1871,10 @@ void P_ZMovement (AActor *mo)
mo->player->deltaviewheight = mo->player->GetDeltaViewHeight();
}
if (!(mo->flags2&MF2_FLOATBOB)) mo->z += mo->momz;
if (!(mo->flags2 & MF2_FLOATBOB))
{
mo->z += mo->momz;
}
//
// apply gravity
@ -1882,8 +1889,16 @@ void P_ZMovement (AActor *mo)
fixed_t grav = (fixed_t)(level.gravity * mo->Sector->gravity *
FIXED2FLOAT(mo->gravity) * 81.92);
if (mo->momz == 0) mo->momz -= grav + grav;
else mo->momz -= grav;
// [RH] Double gravity only if running off a ledge. Coming down from
// an upward thrust (e.g. a jump) should not double it.
if (mo->momz == 0 && oldfloorz > mo->floorz && mo->z == oldfloorz)
{
mo->momz -= grav + grav;
}
else
{
mo->momz -= grav;
}
}
if (mo->waterlevel > 1)
{
@ -1901,7 +1916,10 @@ void P_ZMovement (AActor *mo)
}
}
if (mo->flags2&MF2_FLOATBOB) mo->z += mo->momz;
if (mo->flags2 & MF2_FLOATBOB)
{
mo->z += mo->momz;
}
//
// adjust height
@ -2933,7 +2951,7 @@ void AActor::Tick ()
// Handle X and Y momemtums
BlockingMobj = NULL;
P_XYMovement (this, cummx, cummy);
fixed_t oldfloorz = P_XYMovement (this, cummx, cummy);
if (ObjectFlags & OF_EuthanizeMe)
{ // actor was destroyed
return;
@ -2956,7 +2974,7 @@ void AActor::Tick ()
{
if (!(onmo = P_CheckOnmobj (this)))
{
P_ZMovement (this);
P_ZMovement (this, oldfloorz);
flags2 &= ~MF2_ONMOBJ;
}
else
@ -2989,7 +3007,7 @@ void AActor::Tick ()
}
else
{
P_ZMovement (this);
P_ZMovement (this, oldfloorz);
}
if (ObjectFlags & OF_EuthanizeMe)

View file

@ -643,15 +643,12 @@ bool P_CheckSight (const AActor *t1, const AActor *t2, int flags)
bool res;
#ifdef _DEBUG
assert (t1 != NULL);
assert (t2 != NULL);
#else
if (t1 == NULL || t2 == NULL)
{
return false;
}
#endif
const sector_t *s1 = t1->Sector;
const sector_t *s2 = t2->Sector;

View file

@ -268,7 +268,7 @@ void R_RenderMaskedSegRange (drawseg_t *ds, int x1, int x2)
dc_texturemid = MIN (frontsector->GetPlaneTexZ(sector_t::ceiling), backsector->GetPlaneTexZ(sector_t::ceiling));
}
{ // encapsilate the lifetime of rowoffset
{ // encapsulate the lifetime of rowoffset
fixed_t rowoffset = curline->sidedef->GetTextureYOffset(side_t::mid);
if (tex->bWorldPanning)
{
@ -1629,8 +1629,15 @@ void R_StoreWallRange (int start, int stop)
lwal = (fixed_t *)(openings + ds_p->maskedtexturecol);
swal = (fixed_t *)(openings + ds_p->swall);
int scaley = TexMan(sidedef->GetTexture(side_t::mid))->yScale;
FTexture *pic = TexMan(sidedef->GetTexture(side_t::mid));
int scaley = pic->yScale;
int xoffset = sidedef->GetTextureXOffset(side_t::mid);
if (pic->bWorldPanning)
{
xoffset = MulScale16 (xoffset, pic->xScale);
}
for (i = start; i < stop; i++)
{
*lwal++ = lwall[i] + xoffset;

View file

@ -23,7 +23,6 @@
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include "templates.h"
#include "doomdef.h"

View file

@ -131,7 +131,6 @@ FRolloffInfo S_Rolloff;
BYTE *S_SoundCurve;
int S_SoundCurveSize;
CVAR (Bool, snd_surround, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) // [RH] Use surround sounds?
FBoolCVar noisedebug ("noise", false, 0); // [RH] Print sound debugging info?
CVAR (Int, snd_channels, 32, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) // number of channels available
CVAR (Bool, snd_flipstereo, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)

View file

@ -14,7 +14,6 @@
#define FALSE 0
#define TRUE 1
#endif
#include <fmod.h>
#include "tempfiles.h"
#include "oplsynth/opl_mus_player.h"
#include "c_cvars.h"

View file

@ -34,6 +34,7 @@ private:
#include <sys/types.h>
#include <sys/wait.h>
#include <wordexp.h>
#include <signal.h>
int ChildQuit;

View file

@ -33,7 +33,11 @@
// HEADER FILES ------------------------------------------------------------
#ifndef __FreeBSD__
#include <malloc.h>
#else
#include <stdlib.h>
#endif
#include "i_musicinterns.h"
#include "templates.h"
#include "doomdef.h"

View file

@ -3,5 +3,5 @@
// This file was automatically generated by the
// updaterevision tool. Do not edit by hand.
#define ZD_SVN_REVISION_STRING "1523"
#define ZD_SVN_REVISION_NUMBER 1523
#define ZD_SVN_REVISION_STRING "1552"
#define ZD_SVN_REVISION_NUMBER 1552

View file

@ -33,7 +33,7 @@
*/
#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>
#include "tempfiles.h"
FTempFileName::FTempFileName (const char *prefix)

View file

@ -339,8 +339,8 @@ static const CopyFunc copyfuncs[][9]={
//
//===========================================================================
bool ClipCopyPixelRect(int texwidth, int texheight, int &originx, int &originy,
const BYTE *&patch, int &srcwidth, int &srcheight,
int &pstep_x, int &pstep_y, int rotate)
const BYTE *&patch, int &srcwidth, int &srcheight,
int &pstep_x, int &pstep_y, int rotate)
{
int pixxoffset;
int pixyoffset;

View file

@ -489,7 +489,6 @@ void FMultiPatchTexture::MakeTexture ()
// a power of 2, in case somebody accidentally makes it repeat vertically.
int numpix = Width * Height + (1 << HeightBits) - Height;
BYTE blendwork[256];
static BYTE NullMap[256] = {0};
bool hasTranslucent = false;
Pixels = new BYTE[numpix];
@ -503,18 +502,20 @@ void FMultiPatchTexture::MakeTexture ()
// and merge these pixels in.
for (int i = 0; i < NumParts; ++i)
{
BYTE *trans = Parts[i].Translation? Parts[i].Translation->Remap : NULL;
BYTE *trans = Parts[i].Translation ? Parts[i].Translation->Remap : NULL;
if (Parts[i].op != OP_COPY)
{
trans = NullMap;
hasTranslucent = true;
}
else if (Parts[i].Blend != 0)
else
{
trans = GetBlendMap(Parts[i].Blend, blendwork);
if (Parts[i].Blend != 0)
{
trans = GetBlendMap(Parts[i].Blend, blendwork);
}
Parts[i].Texture->CopyToBlock (Pixels, Width, Height,
Parts[i].OriginX, Parts[i].OriginY, Parts[i].Rotate, trans);
}
Parts[i].Texture->CopyToBlock (Pixels, Width, Height,
Parts[i].OriginX, Parts[i].OriginY, Parts[i].Rotate, trans);
}
if (hasTranslucent)
@ -522,6 +523,7 @@ void FMultiPatchTexture::MakeTexture ()
// In case there are translucent patches let's do the composition in
// True color to keep as much precision as possible before downconverting to the palette.
BYTE *buffer = new BYTE[Width * Height * 4];
memset(buffer, 0, Width * Height * 4);
FillBuffer(buffer, Width * 4, Height, TEX_RGB);
for(int y = 0; y < Height; y++)
{

View file

@ -108,7 +108,9 @@ FTexture * FTexture::CreateTexture (int lumpnum, int usetype)
int w = tex->GetWidth();
int h = tex->GetHeight();
// Auto-scale flats with dimensions 128x128 and 256x256
// Auto-scale flats with dimensions 128x128 and 256x256.
// In hindsight, a bad idea, but RandomLag made it sound better than it really is.
// Now we're stuck with this stupid behaviour.
if (w==128 && h==128)
{
tex->xScale = tex->yScale = 2*FRACUNIT;

View file

@ -238,20 +238,49 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_BasicAttack)
//==========================================================================
//
// Custom sound functions. These use misc1 and misc2 in the state structure
// This has been changed to use the parameter array instead of using the
// misc field directly so they can be used in weapon states
// Custom sound functions.
//
//==========================================================================
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_PlaySound)
{
ACTION_PARAM_START(1);
ACTION_PARAM_START(5);
ACTION_PARAM_SOUND(soundid, 0);
ACTION_PARAM_INT(channel, 1);
ACTION_PARAM_FLOAT(volume, 2);
ACTION_PARAM_BOOL(looping, 3);
ACTION_PARAM_FLOAT(attenuation, 4);
S_Sound (self, CHAN_BODY, soundid, 1, ATTN_NORM);
if (!looping)
{
S_Sound (self, channel, soundid, volume, attenuation);
}
else
{
if (!S_IsActorPlayingSomething (self, channel&7, soundid))
{
S_Sound (self, channel | CHAN_LOOP, soundid, volume, attenuation);
}
}
}
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_StopSound)
{
ACTION_PARAM_START(1);
ACTION_PARAM_INT(slot, 0);
S_StopSound(self, slot);
}
//==========================================================================
//
// These come from a time when DECORATE constants did not exist yet and
// the sound interface was less flexible. As a result the parameters are
// not optimal and these functions have been deprecated in favor of extending
// A_PlaySound and A_StopSound.
//
//==========================================================================
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_PlayWeaponSound)
{
ACTION_PARAM_START(1);
@ -260,11 +289,6 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_PlayWeaponSound)
S_Sound (self, CHAN_WEAPON, soundid, 1, ATTN_NORM);
}
DEFINE_ACTION_FUNCTION(AActor, A_StopSound)
{
S_StopSound(self, CHAN_VOICE);
}
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_PlaySoundEx)
{
ACTION_PARAM_START(4);

View file

@ -208,6 +208,7 @@ static FFlagDef ActorFlags[]=
DEFINE_FLAG(MF5, BRIGHT, AActor, flags5),
DEFINE_FLAG(MF5, CANTSEEK, AActor, flags5),
DEFINE_FLAG(MF5, PAINLESS, AActor, flags5),
DEFINE_FLAG(MF5, MOVEWITHSECTOR, AActor, flags5),
// Effect flags
DEFINE_FLAG(FX, VISIBILITYPULSE, AActor, effects),

View file

@ -23,7 +23,7 @@
#include <math.h>
#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>
#include "timidity.h"
#include "c_cvars.h"

View file

@ -300,12 +300,14 @@ bool DCanvas::ParseDrawTextureTags (FTexture *img, int x, int y, DWORD tag, va_l
if (img == NULL || img->UseType == FTexture::TEX_Null)
{
va_end(tags);
return false;
}
// Do some sanity checks on the coordinates.
if (x < -16383 || x > 16383 || y < -16383 || y > 16383)
{
va_end(tags);
return false;
}
@ -359,8 +361,8 @@ bool DCanvas::ParseDrawTextureTags (FTexture *img, int x, int y, DWORD tag, va_l
case TAG_MORE:
more_p = va_arg (tags, va_list *);
va_end (tags);
#ifdef __GNUC__
__va_copy (tags, *more_p);
#ifndef NO_VA_COPY
va_copy (tags, *more_p);
#else
tags = *more_p;
#endif

View file

@ -136,8 +136,8 @@ void STACK_ARGS DCanvas::DrawText (FFont *font, int normalcolor, int x, int y, c
case TAG_MORE:
more_p = va_arg (tags, va_list*);
va_end (tags);
#ifdef __GNUC__
__va_copy (tags, *more_p);
#ifndef NO_VA_COPY
va_copy (tags, *more_p);
#else
tags = *more_p;
#endif

View file

@ -30,10 +30,21 @@
#include "templates.h"
#include "gi.h"
extern "C" {
#include "Archive/7z/7zHeader.h"
#include "Archive/7z/7zExtract.h"
#include "Archive/7z/7zIn.h"
#include "7zCrc.h"
}
// MACROS ------------------------------------------------------------------
#define NULL_INDEX (0xffff)
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
extern ISzAlloc g_Alloc;
// TYPES -------------------------------------------------------------------
struct rffinfo_t
@ -81,6 +92,7 @@ union MergedHeader
wadinfo_t wad;
rffinfo_t rff;
grpinfo_t grp;
BYTE sevenzip[k7zSignatureSize];
};
@ -92,32 +104,149 @@ struct FWadCollection::LumpRecord
char * fullname; // only valid for files loaded from a .zip file
char name[9];
BYTE method; // zip compression method
BYTE flags;
short wadnum;
WORD flags;
int position;
int size;
int namespc;
int compressedsize;
void ZipNameSetup(char *name);
};
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;
}
};
class FWadCollection::WadFileRecord : public FileReader
{
public:
WadFileRecord (FILE *file);
WadFileRecord (const char * buffer, int length);
WadFileRecord (const char *buffer, int length);
~WadFileRecord ();
long Seek (long offset, int origin);
long Read (void *buffer, long len);
const char * MemoryData;
const char *MemoryData;
C7zArchive *Archive;
char *Name;
FString Name;
DWORD FirstLump;
DWORD LastLump;
};
struct FEmbeddedWAD
{
union
{
C7zArchive *Archive;
FZipCentralDirectoryInfo *Zip;
};
int Position;
};
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
@ -129,8 +258,6 @@ void W_SysWadInit ();
static void PrintLastError ();
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
// PUBLIC DATA DEFINITIONS -------------------------------------------------
FWadCollection Wads;
@ -285,7 +412,7 @@ int FWadCollection::AddExternalFile(const char *filename)
lump.fullname = copystring(filename);
memset(lump.name, 0, sizeof(lump.name));
lump.wadnum=-1;
lump.wadnum = -1;
lump.flags = LUMPF_EXTERNAL;
lump.position = 0;
lump.namespc = ns_global;
@ -365,7 +492,7 @@ int STACK_ARGS FWadCollection::lumpcmp(const void * a, const void * b)
}
void FWadCollection::AddFile (const char *filename, const char * data, int length)
void FWadCollection::AddFile (const char *filename, const char *data, int length)
{
WadFileRecord *wadinfo;
MergedHeader header;
@ -375,10 +502,10 @@ void FWadCollection::AddFile (const char *filename, const char * data, int lengt
int startlump;
wadlump_t* fileinfo = NULL, *fileinfo2free = NULL;
wadlump_t singleinfo;
TArray<FZipCentralDirectoryInfo *> EmbeddedWADs;
void * directory = NULL;
TArray<FEmbeddedWAD> EmbeddedWADs;
void *directory = NULL;
if (length==-1)
if (length == -1)
{
// open the file and add to directory
handle = fopen (filename, "rb");
@ -409,7 +536,7 @@ void FWadCollection::AddFile (const char *filename, const char * data, int lengt
return;
}
wadinfo->Name = copystring (filename);
wadinfo->Name = filename;
if (header.magic[0] == IWAD_ID || header.magic[0] == PWAD_ID)
{ // This is a WAD file
@ -516,6 +643,7 @@ void FWadCollection::AddFile (const char *filename, const char * data, int lengt
if (centraldir == 0)
{
Printf("\n%s: ZIP file corrupt!\n", filename);
delete wadinfo;
return;
}
@ -528,6 +656,7 @@ void FWadCollection::AddFile (const char *filename, const char * data, int lengt
info.FirstDisk != 0 || info.DiskNumber != 0)
{
Printf("\n%s: Multipart Zip files are not supported.\n", filename);
delete wadinfo;
return;
}
@ -546,7 +675,6 @@ void FWadCollection::AddFile (const char *filename, const char * data, int lengt
FZipCentralDirectoryInfo *zip_fh = (FZipCentralDirectoryInfo *)dirptr;
char name[256];
char base[256];
int len = LittleShort(zip_fh->NameLength);
strncpy(name, dirptr + sizeof(FZipCentralDirectoryInfo), MIN<int>(len, 255));
@ -589,68 +717,24 @@ void FWadCollection::AddFile (const char *filename, const char * data, int lengt
// They must be extracted and added separately to the lump list.
// WADs in subdirectories are added to the lump directory.
// Embedded .zips are ignored for now. But they should be allowed later!
char * c = strstr(name, ".wad");
if (c && strlen(c)==4 && !strchr(name, '/'))
char *c = strstr(name, ".wad");
if (c && strlen(c) == 4 && !strchr(name, '/'))
{
EmbeddedWADs.Push(zip_fh);
FEmbeddedWAD embed;
embed.Zip = zip_fh;
embed.Position = -1;
EmbeddedWADs.Push(embed);
skipped++;
continue;
}
//ExtractFileBase(name, base);
char *lname = strrchr(name,'/');
if (!lname) lname = name;
else lname++;
strcpy(base, lname);
char *dot = strrchr(base, '.');
if (dot) *dot = 0;
uppercopy(lump_p->name, base);
lump_p->name[8] = 0;
lump_p->fullname = copystring(name);
lump_p->ZipNameSetup(name);
lump_p->size = LittleLong(zip_fh->UncompressedSize);
// 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.
lump_p->namespc = !strncmp(name, "flats/", 6) ? ns_flats :
!strncmp(name, "textures/", 9) ? ns_newtextures :
!strncmp(name, "hires/", 6) ? ns_hires :
!strncmp(name, "sprites/", 8) ? ns_sprites :
!strncmp(name, "colormaps/", 10) ? ns_colormaps :
!strncmp(name, "acs/", 4) ? ns_acslibrary :
!strncmp(name, "voices/", 7) ? ns_strifevoices :
!strncmp(name, "patches/", 8) ? ns_patches :
!strncmp(name, "graphics/", 9) ? ns_graphics :
!strncmp(name, "sounds/", 7) ? ns_sounds :
!strncmp(name, "music/", 6) ? ns_music :
!strchr(name, '/') ? 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 (lump_p->namespc == -1)
{
memset(lump_p->name, 0, 8);
}
lump_p->wadnum = (WORD)Wads.Size();
lump_p->flags = (zip_fh->Method != METHOD_STORED) ? LUMPF_COMPRESSED|LUMPF_ZIPFILE : LUMPF_ZIPFILE;
lump_p->method = zip_fh->Method;
lump_p->compressedsize = LittleLong(zip_fh->CompressedSize);
// 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.
if (lump_p->namespc == ns_sprites)
{
char * c;
while ((c = (char*)memchr(lump_p->name, '^', 8)))
{
*c = '\\';
}
}
// The start of the file will be determined the first time it is accessed.
lump_p->flags |= LUMPF_NEEDFILESTART;
lump_p->position = LittleLong(zip_fh->LocalHeaderOffset);
@ -659,10 +743,91 @@ void FWadCollection::AddFile (const char *filename, const char * data, int lengt
// Resize the lump record array to its actual size
NumLumps -= skipped;
LumpInfo.Resize(NumLumps);
Printf (" (%d files)", LittleShort(info.NumEntries) - skipped);
// Entries in Zips are sorted alphabetically.
qsort(&LumpInfo[startlump], NumLumps - startlump, sizeof(LumpRecord), lumpcmp);
}
else if (memcmp(header.sevenzip, k7zSignature, k7zSignatureSize) == 0)
{
C7zArchive *arc = new C7zArchive(wadinfo);
int skipped = 0;
SRes res;
res = arc->Open();
if (res != SZ_OK)
{
delete arc;
delete wadinfo;
Printf("\n%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;
}
wadinfo->Archive = arc;
NumLumps += arc->DB.db.NumFiles;
LumpInfo.Resize(NumLumps);
lump_p = &LumpInfo[startlump];
for (int i = 0; i < arc->DB.db.NumFiles; ++i)
{
CSzFileItem *file = &arc->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);
// Check for embedded WADs in the root directory.
char *c = strstr(name, ".wad");
if (c && strlen(c) == 4 && !strchr(name, '/'))
{
FEmbeddedWAD embed;
embed.Archive = arc;
embed.Position = i;
EmbeddedWADs.Push(embed);
skipped++;
continue;
}
lump_p->ZipNameSetup(name);
lump_p->size = file->Size;
lump_p->wadnum = (WORD)Wads.Size();
lump_p->flags = LUMPF_7ZFILE | LUMPF_ZIPFILE;
lump_p->position = i;
lump_p->compressedsize = -1;
lump_p++;
}
// Resize the lump record array to its actual size
NumLumps -= skipped;
LumpInfo.Resize(NumLumps);
Printf (" (%u files)", arc->DB.db.NumFiles - skipped);
// Entries in archives are sorted alphabetically
qsort(&LumpInfo[startlump], NumLumps - startlump, sizeof(LumpRecord), lumpcmp);
}
else
{ // This is just a single lump file
fileinfo2free = NULL;
@ -678,7 +843,8 @@ void FWadCollection::AddFile (const char *filename, const char * data, int lengt
// Fill in lumpinfo
if (header.magic[0] != RFF_ID &&
header.magic[0] != ZIP_ID &&
(header.magic[0] != GRP_ID_0 || header.magic[1] != GRP_ID_1 || header.magic[2] != GRP_ID_2))
(header.magic[0] != GRP_ID_0 || header.magic[1] != GRP_ID_1 || header.magic[2] != GRP_ID_2) &&
memcmp(header.sevenzip, k7zSignature, k7zSignatureSize))
{
LumpInfo.Resize(NumLumps);
lump_p = &LumpInfo[startlump];
@ -717,54 +883,147 @@ void FWadCollection::AddFile (const char *filename, const char * data, int lengt
if (EmbeddedWADs.Size())
{
char path[256];
size_t len;
char *buffer;
mysnprintf(path, countof(path), "%s:", filename);
char * wadstr = path+strlen(path);
char *wadstr = path + strlen(path);
for(unsigned int i = 0; i < EmbeddedWADs.Size(); i++)
{
FZipCentralDirectoryInfo *zip_fh = EmbeddedWADs[i];
FZipLocalFileHeader localHeader;
FEmbeddedWAD *embed = &EmbeddedWADs[i];
*wadstr = 0;
size_t len = LittleShort(zip_fh->NameLength);
if (len + strlen(path) > 255) len = 255 - strlen(path);
strncpy(wadstr, ((char*)zip_fh) + sizeof(FZipCentralDirectoryInfo), len);
wadstr[len] = 0;
DWORD size = LittleLong(zip_fh->UncompressedSize);
char *buffer = new char[size];
int position = LittleLong(zip_fh->LocalHeaderOffset) ;
wadinfo->Seek(position, SEEK_SET);
wadinfo->Read(&localHeader, sizeof(localHeader));
position += sizeof(FZipLocalFileHeader) + LittleShort(localHeader.ExtraLength) + LittleShort(zip_fh->NameLength);
wadinfo->Seek(position, SEEK_SET);
if (LittleShort(zip_fh->Method) == METHOD_DEFLATE)
if (embed->Position == -1)
{
FileReaderZ frz(*wadinfo, true);
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);
FZipCentralDirectoryInfo *zip_fh = embed->Zip;
FZipLocalFileHeader localHeader;
*wadstr = 0;
len = LittleShort(zip_fh->NameLength);
if (len + strlen(path) > 255)
{
len = 255 - strlen(path);
}
strncpy(wadstr, ((char*)zip_fh) + sizeof(FZipCentralDirectoryInfo), len);
wadstr[len] = 0;
DWORD size = LittleLong(zip_fh->UncompressedSize);
buffer = new char[size];
int position = LittleLong(zip_fh->LocalHeaderOffset);
wadinfo->Seek(position, SEEK_SET);
wadinfo->Read(&localHeader, sizeof(localHeader));
position += sizeof(FZipLocalFileHeader) + LittleShort(localHeader.ExtraLength) + LittleShort(zip_fh->NameLength);
wadinfo->Seek(position, SEEK_SET);
if (LittleShort(zip_fh->Method) == METHOD_DEFLATE)
{
FileReaderZ frz(*wadinfo, true);
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
{
wadinfo->Read(buffer, size);
}
AddFile(path, buffer, size);
}
else
{
wadinfo->Read(buffer, size);
CSzFileItem *file = &embed->Archive->DB.db.Files[embed->Position];
len = strlen(file->Name);
if (len + strlen(path) > 255)
{
len = 255 - strlen(path);
}
strncpy(wadstr, file->Name, len);
wadstr[len] = 0;
buffer = new char[file->Size];
if (embed->Archive->Extract(embed->Position, buffer) == SZ_OK)
{
AddFile(path, buffer, file->Size);
}
}
AddFile(path, buffer, size);
}
}
if (directory != NULL) free(directory);
if (directory != NULL)
{
free(directory);
}
}
//==========================================================================
//
// FWadCollection :: LumpRecord :: ZipNameSetup
//
// For lumps from an archive, determine this lump's wad-compatible name,
// namespace, and set the fullname.
//
//==========================================================================
void FWadCollection::LumpRecord::ZipNameSetup(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.
namespc = !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 (namespc == -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 (namespc == ns_sprites)
{
char *c;
while ((c = (char*)memchr(name, '^', 8)))
{
*c = '\\';
}
}
}
//==========================================================================
@ -1797,39 +2056,22 @@ FWadLump FWadCollection::OpenLumpNum (int lump)
}
l = &LumpInfo[lump];
wad = l->wadnum >= 0? Wads[l->wadnum] : NULL;
wad = l->wadnum >= 0 ? Wads[l->wadnum] : NULL;
if (l->flags & LUMPF_NEEDFILESTART)
{
SetLumpAddress(l);
}
if (wad != NULL) wad->Seek (l->position, SEEK_SET);
if (wad != NULL)
{
wad->Seek (l->position, SEEK_SET);
}
if (l->flags & LUMPF_COMPRESSED)
if (l->flags & (LUMPF_COMPRESSED | LUMPF_7ZFILE))
{
// 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;
if (l->method == METHOD_DEFLATE)
{
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
}
char *buffer = ReadZipLump(l);
return FWadLump(buffer, l->size, true);
}
else if (l->flags & LUMPF_EXTERNAL)
@ -1841,7 +2083,7 @@ FWadLump FWadCollection::OpenLumpNum (int lump)
{
FString name;
name.Format("%s/%s", wad->Name, l->fullname);
name << wad->Name << '/' << l->fullname;
f = fopen(name, "rb");
}
else
@ -1898,38 +2140,18 @@ FWadLump *FWadCollection::ReopenLumpNum (int lump)
}
l = &LumpInfo[lump];
wad = l->wadnum >= 0? Wads[l->wadnum] : NULL;
wad = l->wadnum >= 0 ? Wads[l->wadnum] : NULL;
if (l->flags & LUMPF_NEEDFILESTART)
{
SetLumpAddress(l);
}
if (l->flags & LUMPF_COMPRESSED)
if (l->flags & (LUMPF_COMPRESSED | LUMPF_7ZFILE))
{
// A compressed entry in a .zip file
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
wad->Seek(l->position, SEEK_SET);
if (l->method == METHOD_DEFLATE)
{
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
}
char *buffer = ReadZipLump(l);
wad->Seek(address, SEEK_SET);
return new FWadLump(buffer, l->size, true); //... but restore the file pointer afterward!
}
@ -1942,7 +2164,7 @@ FWadLump *FWadCollection::ReopenLumpNum (int lump)
{
FString name;
name.Format("%s/%s", wad->Name, l->fullname);
name << wad->Name << '/' << l->fullname;
f = fopen(name, "rb");
}
else
@ -1977,7 +2199,7 @@ FWadLump *FWadCollection::ReopenLumpNum (int lump)
f = fopen (wad->Name, "rb");
if (f == NULL)
{
I_Error ("Could not reopen %s\n", wad->Name);
I_Error ("Could not reopen %s\n", wad->Name.GetChars());
}
fseek (f, l->position, SEEK_SET);
@ -1986,6 +2208,50 @@ FWadLump *FWadCollection::ReopenLumpNum (int lump)
}
//==========================================================================
//
// FWadCollection :: ReadZipLump
//
// Extracts a compressed file from a zip into memory.
//
//==========================================================================
char *FWadCollection::ReadZipLump(LumpRecord *l)
{
WadFileRecord *wad = Wads[l->wadnum];
char *buffer = new char[l->size + 1]; // the last byte is used as a reference counter
buffer[l->size] = 0;
if (!(l->flags & LUMPF_7ZFILE))
{
wad->Seek(l->position, SEEK_SET);
if (l->method == METHOD_DEFLATE)
{
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
}
}
else
{
wad->Archive->Extract(l->position, buffer);
}
return buffer;
}
//==========================================================================
//
// GetFileReader
@ -2142,7 +2408,7 @@ void FWadCollection::SkinHack (int baselump)
"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",
Wads[LumpInfo[baselump].wadnum]->Name);
Wads[LumpInfo[baselump].wadnum]->Name.GetChars());
}
}
@ -2165,13 +2431,12 @@ void BloodCrypt (void *data, int key, int len)
// WadFileRecord ------------------------------------------------------------
FWadCollection::WadFileRecord::WadFileRecord (FILE *file)
: FileReader(file), Name(NULL), FirstLump(0), LastLump(0)
: FileReader(file), MemoryData(NULL), Archive(NULL), FirstLump(0), LastLump(0)
{
MemoryData=NULL;
}
FWadCollection::WadFileRecord::WadFileRecord (const char * mem, int len)
: FileReader(), MemoryData(mem), Name(NULL), FirstLump(0), LastLump(0)
FWadCollection::WadFileRecord::WadFileRecord (const char *mem, int len)
: FileReader(), MemoryData(mem), Archive(NULL), FirstLump(0), LastLump(0)
{
Length = len;
FilePos = StartPos = 0;
@ -2179,55 +2444,62 @@ FWadCollection::WadFileRecord::WadFileRecord (const char * mem, int len)
FWadCollection::WadFileRecord::~WadFileRecord ()
{
if (Name != NULL)
{
delete[] Name;
}
if (MemoryData != NULL)
{
delete [] MemoryData;
delete[] MemoryData;
}
if (Archive != NULL)
{
delete Archive;
}
}
long FWadCollection::WadFileRecord::Seek (long offset, int origin)
{
if (MemoryData==NULL) return FileReader::Seek(offset, origin);
if (MemoryData == NULL)
{
return FileReader::Seek(offset, origin);
}
else
{
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<long>(offset, 0, Length);
return 0;
}
}
long FWadCollection::WadFileRecord::Read (void *buffer, long len)
{
if (MemoryData==NULL) return FileReader::Read(buffer, len);
if (MemoryData == NULL)
{
return FileReader::Read(buffer, len);
}
else
{
if (FilePos+len>Length) len=Length-FilePos;
memcpy(buffer, MemoryData+FilePos, len);
FilePos+=len;
if (FilePos + len > Length)
{
len = Length - FilePos;
}
memcpy(buffer, MemoryData + FilePos, len);
FilePos += len;
return len;
}
}
// FWadLump -----------------------------------------------------------------
// FWadLump -----------------------------------------------------------------
FWadLump::FWadLump ()
: FileReader(), SourceData(NULL), DestroySource(false), Encrypted(false)
{

View file

@ -69,6 +69,7 @@ enum
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
};
@ -168,7 +169,7 @@ public:
enum { IWAD_FILENUM = 1 };
void InitMultipleFiles (wadlist_t **filenames);
void AddFile (const char *filename, const char * data=NULL,int length=-1);
void AddFile (const char *filename, const char *data=NULL, int length=-1);
int CheckIfWadLoaded (const char *name);
const char *GetWadName (int wadnum) const;
@ -235,7 +236,7 @@ protected:
TArray<LumpRecord> LumpInfo;
TArray<WadFileRecord *>Wads;
TArray<WadFileRecord *> Wads;
DWORD NumLumps; // Not necessarily the same as LumpInfo.Size()
DWORD NumWads;
@ -247,6 +248,8 @@ protected:
bool IsMarker (const LumpRecord *lump, const char *marker) const;
void FindStrifeTeaserVoices ();
char *ReadZipLump(LumpRecord *l);
private:
static int STACK_ARGS lumpcmp(const void * a, const void * b);
void ScanForFlatHack (int startlump);

View file

@ -65,9 +65,6 @@ CVAR (Bool, wi_noautostartmap, false, CVAR_ARCHIVE)
void WI_loadData ();
void WI_unloadData ();
#define NEXTSTAGE (gameinfo.gametype & GAME_DoomChex ? "weapons/rocklx" : "doors/dr1_clos")
#define PASTSTATS (gameinfo.gametype & GAME_DoomChex ? "weapons/shotgr" : "plats/pt1_stop")
// GLOBAL LOCATIONS
#define WI_TITLEY 2
#define WI_SPACINGY 33
@ -1185,7 +1182,7 @@ void WI_updateDeathmatchStats ()
}
}
S_Sound (CHAN_VOICE | CHAN_UI, NEXTSTAGE, 1, ATTN_NONE);
S_Sound (CHAN_VOICE | CHAN_UI, "intermission/nextstage", 1, ATTN_NONE);
*/
dm_state = 4;
}
@ -1195,7 +1192,7 @@ void WI_updateDeathmatchStats ()
{
/*
if (!(bcnt&3))
S_Sound (CHAN_VOICE | CHAN_UI, "weapons/pistol", 1, ATTN_NONE);
S_Sound (CHAN_VOICE | CHAN_UI, "intermission/tick", 1, ATTN_NONE);
stillticking = false;
@ -1234,7 +1231,7 @@ void WI_updateDeathmatchStats ()
}
if (!stillticking)
{
S_Sound (CHAN_VOICE | CHAN_UI, NEXTSTAGE, 1, ATTN_NONE);
S_Sound (CHAN_VOICE | CHAN_UI, "intermission/nextstage", 1, ATTN_NONE);
dm_state++;
}
*/
@ -1244,7 +1241,7 @@ void WI_updateDeathmatchStats ()
{
if (acceleratestage)
{
S_Sound (CHAN_VOICE | CHAN_UI, "players/male/gibbed", 1, ATTN_NONE);
S_Sound (CHAN_VOICE | CHAN_UI, "intermission/pastdmstats", 1, ATTN_NONE);
WI_initShowNextLoc();
}
}
@ -1402,14 +1399,14 @@ void WI_updateNetgameStats ()
if (dofrags)
cnt_frags[i] = WI_fragSum (i);
}
S_Sound (CHAN_VOICE | CHAN_UI, NEXTSTAGE, 1, ATTN_NONE);
S_Sound (CHAN_VOICE | CHAN_UI, "intermission/nextstage", 1, ATTN_NONE);
ng_state = 10;
}
if (ng_state == 2)
{
if (!(bcnt&3))
S_Sound (CHAN_VOICE | CHAN_UI, "weapons/pistol", 1, ATTN_NONE);
S_Sound (CHAN_VOICE | CHAN_UI, "intermission/tick", 1, ATTN_NONE);
stillticking = false;
@ -1428,14 +1425,14 @@ void WI_updateNetgameStats ()
if (!stillticking)
{
S_Sound (CHAN_VOICE | CHAN_UI, NEXTSTAGE, 1, ATTN_NONE);
S_Sound (CHAN_VOICE | CHAN_UI, "intermission/nextstage", 1, ATTN_NONE);
ng_state++;
}
}
else if (ng_state == 4)
{
if (!(bcnt&3))
S_Sound (CHAN_VOICE | CHAN_UI, "weapons/pistol", 1, ATTN_NONE);
S_Sound (CHAN_VOICE | CHAN_UI, "intermission/tick", 1, ATTN_NONE);
stillticking = false;
@ -1452,14 +1449,14 @@ void WI_updateNetgameStats ()
}
if (!stillticking)
{
S_Sound (CHAN_VOICE | CHAN_UI, NEXTSTAGE, 1, ATTN_NONE);
S_Sound (CHAN_VOICE | CHAN_UI, "intermission/nextstage", 1, ATTN_NONE);
ng_state++;
}
}
else if (ng_state == 6)
{
if (!(bcnt&3))
S_Sound (CHAN_VOICE | CHAN_UI, "weapons/pistol", 1, ATTN_NONE);
S_Sound (CHAN_VOICE | CHAN_UI, "intermission/tick", 1, ATTN_NONE);
stillticking = false;
@ -1478,14 +1475,14 @@ void WI_updateNetgameStats ()
if (!stillticking)
{
S_Sound (CHAN_VOICE | CHAN_UI, NEXTSTAGE, 1, ATTN_NONE);
S_Sound (CHAN_VOICE | CHAN_UI, "intermission/nextstage", 1, ATTN_NONE);
ng_state += 1 + 2*!dofrags;
}
}
else if (ng_state == 8)
{
if (!(bcnt&3))
S_Sound (CHAN_VOICE | CHAN_UI, "weapons/pistol", 1, ATTN_NONE);
S_Sound (CHAN_VOICE | CHAN_UI, "intermission/tick", 1, ATTN_NONE);
stillticking = false;
@ -1504,7 +1501,7 @@ void WI_updateNetgameStats ()
if (!stillticking)
{
S_Sound (CHAN_VOICE | CHAN_UI, "player/male/death1", 1, ATTN_NONE);
S_Sound (CHAN_VOICE | CHAN_UI, "intermission/cooptotal", 1, ATTN_NONE);
ng_state++;
}
}
@ -1512,7 +1509,7 @@ void WI_updateNetgameStats ()
{
if (acceleratestage)
{
S_Sound (CHAN_VOICE | CHAN_UI, PASTSTATS, 1, ATTN_NONE);
S_Sound (CHAN_VOICE | CHAN_UI, "intermission/pastcoopstats", 1, ATTN_NONE);
WI_initShowNextLoc();
}
}
@ -1658,7 +1655,7 @@ void WI_updateStats ()
{
acceleratestage = 0;
sp_state = 10;
S_Sound (CHAN_VOICE | CHAN_UI, NEXTSTAGE, 1, ATTN_NONE);
S_Sound (CHAN_VOICE | CHAN_UI, "intermission/nextstage", 1, ATTN_NONE);
}
cnt_kills[0] = plrs[me].skills;
cnt_items[0] = plrs[me].sitems;
@ -1675,12 +1672,12 @@ void WI_updateStats ()
cnt_kills[0] += 2;
if (!(bcnt&3))
S_Sound (CHAN_VOICE | CHAN_UI, "weapons/pistol", 1, ATTN_NONE);
S_Sound (CHAN_VOICE | CHAN_UI, "intermission/tick", 1, ATTN_NONE);
}
if (cnt_kills[0] >= plrs[me].skills)
{
cnt_kills[0] = plrs[me].skills;
S_Sound (CHAN_VOICE | CHAN_UI, NEXTSTAGE, 1, ATTN_NONE);
S_Sound (CHAN_VOICE | CHAN_UI, "intermission/nextstage", 1, ATTN_NONE);
sp_state++;
}
}
@ -1691,12 +1688,12 @@ void WI_updateStats ()
cnt_items[0] += 2;
if (!(bcnt&3))
S_Sound (CHAN_VOICE | CHAN_UI, "weapons/pistol", 1, ATTN_NONE);
S_Sound (CHAN_VOICE | CHAN_UI, "intermission/tick", 1, ATTN_NONE);
}
if (cnt_items[0] >= plrs[me].sitems)
{
cnt_items[0] = plrs[me].sitems;
S_Sound (CHAN_VOICE | CHAN_UI, NEXTSTAGE, 1, ATTN_NONE);
S_Sound (CHAN_VOICE | CHAN_UI, "intermission/nextstage", 1, ATTN_NONE);
sp_state++;
}
}
@ -1707,12 +1704,12 @@ void WI_updateStats ()
cnt_secret[0] += 2;
if (!(bcnt&3))
S_Sound (CHAN_VOICE | CHAN_UI, "weapons/pistol", 1, ATTN_NONE);
S_Sound (CHAN_VOICE | CHAN_UI, "intermission/tick", 1, ATTN_NONE);
}
if (cnt_secret[0] >= plrs[me].ssecret)
{
cnt_secret[0] = plrs[me].ssecret;
S_Sound (CHAN_VOICE | CHAN_UI, NEXTSTAGE, 1, ATTN_NONE);
S_Sound (CHAN_VOICE | CHAN_UI, "intermission/nextstage", 1, ATTN_NONE);
sp_state++;
}
}
@ -1721,7 +1718,7 @@ void WI_updateStats ()
if (gameinfo.gametype & GAME_DoomChex)
{
if (!(bcnt&3))
S_Sound (CHAN_VOICE | CHAN_UI, "weapons/pistol", 1, ATTN_NONE);
S_Sound (CHAN_VOICE | CHAN_UI, "intermission/tick", 1, ATTN_NONE);
cnt_time += 3;
cnt_par += 3;
@ -1741,7 +1738,7 @@ void WI_updateStats ()
if (cnt_time >= plrs[me].stime / TICRATE)
{
cnt_total_time = wbs->totaltime / TICRATE;
S_Sound (CHAN_VOICE | CHAN_UI, NEXTSTAGE, 1, ATTN_NONE);
S_Sound (CHAN_VOICE | CHAN_UI, "intermission/nextstage", 1, ATTN_NONE);
sp_state++;
}
}
@ -1750,7 +1747,7 @@ void WI_updateStats ()
{
if (acceleratestage)
{
S_Sound (CHAN_VOICE | CHAN_UI, PASTSTATS, 1, ATTN_NONE);
S_Sound (CHAN_VOICE | CHAN_UI, "intermission/paststats", 1, ATTN_NONE);
WI_initShowNextLoc();
}
}

View file

@ -45,7 +45,7 @@
//#include <wtsapi32.h>
#define NOTIFY_FOR_THIS_SESSION 0
#include <malloc.h>
#include <stdlib.h>
#ifdef _MSC_VER
#include <eh.h>
#include <new.h>

View file

@ -86,7 +86,7 @@
#include <stddef.h>
#include <stdlib.h>
#include <math.h>
#include <malloc.h>
#include <stdlib.h>
#include <locale.h>
#include "zstring.h"

View file

@ -160,11 +160,11 @@ ACTOR Actor native //: Thinker
action native A_MeleeAttack();
action native A_ComboAttack();
action native A_BulletAttack();
action native A_PlaySound(sound whattoplay);
action native A_PlaySound(sound whattoplay, int slot = CHAN_BODY, float volume = 1.0, bool looping = false, float attenuation = ATTN_NORM);
action native A_PlayWeaponSound(sound whattoplay);
action native A_FLoopActiveSound();
action native A_LoopActiveSound();
action native A_StopSound();
action native A_StopSound(int slot = CHAN_VOICE); // Bad default but that's what is originally was...
action native A_PlaySoundEx(sound whattoplay, coerce name slot, bool looping = false, int attenuation = 0);
action native A_StopSoundEx(coerce name slot);
action native A_SeekerMissile(int threshold, int turnmax);

View file

@ -44,5 +44,28 @@ const int MRF_UNDOBYDEATH = 512;
const int MRF_UNDOBYDEATHFORCED = 1024;
const int MRF_UNDOBYDEATHSAVES = 2048;
// constants for A_PlaySound
enum
{
CHAN_AUTO = 0,
CHAN_WEAPON = 1,
CHAN_VOICE = 2,
CHAN_ITEM = 3,
CHAN_BODY = 4,
// modifier flags
CHAN_LISTENERZ = 8,
CHAN_MAYBE_LOCAL = 16,
CHAN_UI = 32,
CHAN_NOPAUSE = 64
};
// sound attenuation values
const float ATTN_NONE = 0;
const float ATTN_NORM = 1;
const float ATTN_IDLE = 1.001;
const float ATTN_STATIC = 3;
// This is only here to provide one global variable for testing.
native int testglobalvar;

View file

@ -741,6 +741,8 @@ ACTOR ColonGibs 79
SpawnID 147
Radius 20
Height 4
+NOBLOCKMAP
+MOVEWITHSECTOR
States
{
Spawn:
@ -757,6 +759,8 @@ ACTOR SmallBloodPool 80
SpawnID 148
Radius 20
Height 1
+NOBLOCKMAP
+MOVEWITHSECTOR
States
{
Spawn:
@ -773,6 +777,8 @@ ACTOR BrainStem 81
SpawnID 150
Radius 20
Height 4
+NOBLOCKMAP
+MOVEWITHSECTOR
States
{
Spawn:

View file

@ -101,6 +101,8 @@ ACTOR HereticImpChunk1
{
Mass 5
Radius 4
+NOBLOCKMAP
+MOVEWITHSECTOR
States
{
Spawn:
@ -116,6 +118,8 @@ ACTOR HereticImpChunk2
{
Mass 5
Radius 4
+NOBLOCKMAP
+MOVEWITHSECTOR
States
{
Spawn:

View file

@ -16,6 +16,8 @@ ACTOR IceChunk
+CANNOTPUSH
+FLOORCLIP
+NOTELEPORT
+NOBLOCKMAP
+MOVEWITHSECTOR
action native A_IceSetTics ();

View file

@ -1,5 +1,5 @@
#include "actors/actor.txt"
#include "actors/constants.txt"
#include "actors/actor.txt"
#include "actors/shared/inventory.txt"
#include "actors/shared/player.txt"

View file

@ -50,11 +50,11 @@ misc/icebreak icebrk1a
// Retail Doom and Strife use 200.
$rolloff * 200 1200
/***************************************************************************/
/* */
/* DOOM SOUNDS */
/* */
/***************************************************************************/
/****************************************************************************/
/* */
/* DOOM SOUNDS */
/* */
/****************************************************************************/
$ifdoom
@ -495,16 +495,22 @@ menu/clear dsswtchx // Close top menu
$random menu/quit1 { player/male/death1 demon/pain grunt/pain misc/gibbed misc/teleport grunt/sight1 grunt/sight3 demon/melee }
$random menu/quit2 { vile/active misc/p_pkup brain/cube misc/gibbed skeleton/swing knight/death baby/active demon/melee }
$alias intermission/tick weapons/pistol
$alias intermission/cooptotal *death
$alias intermission/nextstage weapons/rocklx
$alias intermission/paststats weapons/shotgr
$alias intermission/pastcoopstats weapons/shotgr
$alias intermission/pastdmstats *gibbed
$endif // ifdoom
/***************************************************************************/
/* */
/* HERETIC SOUNDS */
/* */
/***************************************************************************/
/****************************************************************************/
/* */
/* HERETIC SOUNDS */
/* */
/****************************************************************************/
$ifheretic
@ -784,14 +790,21 @@ menu/clear dorcls
misc/secret dssecret
$alias intermission/cooptotal *death
$alias intermission/nextstage doors/dr1_clos
$alias intermission/paststats plats/pt1_stop
$alias intermission/pastcoopstats plats/pt1_stop
$alias intermission/pastdmstats *gibbed
$endif // ifheretic
/***************************************************************************/
/* */
/* HEXEN SOUNDS */
/* */
/***************************************************************************/
/****************************************************************************/
/* */
/* HEXEN SOUNDS */
/* */
/****************************************************************************/
$ifhexen
@ -952,6 +965,12 @@ $alias menu/clear PlatformStop
// Hexen does not have ripslop sound like Heretic
misc/ripslop dsempty
$alias intermission/cooptotal *death
$alias intermission/nextstage DoorCloseLight
$alias intermission/paststats PlatformStop
$alias intermission/pastcoopstats PlatformStop
$alias intermission/pastdmstats *gibbed
$limit DoorCloseLight 4
$limit PuppyBeat 0
@ -968,11 +987,11 @@ $limit DragonPain 0
$endif // ifhexen
//===========================================================================
//
// Strife
//
//===========================================================================
/****************************************************************************/
/* */
/* STRIFE SOUNDS */
/* */
/****************************************************************************/
$ifstrife
@ -1275,4 +1294,11 @@ entity/pain dsalnpn
entity/death dsmnaldt
entity/active dsalnact
$alias intermission/tick weapons/assaultgun
$alias intermission/cooptotal *death
$alias intermission/nextstage misc/explosion
$alias intermission/paststats world/barrelx
$alias intermission/pastcoopstats world/barrelx
$alias intermission/pastdmstats *gibbed
$endif