Merge remote-tracking branch 'gzdoom/master' into ssao

This commit is contained in:
Magnus Norddahl 2016-10-21 23:48:30 +02:00
commit be2c50f11c
83 changed files with 1706 additions and 484 deletions

View file

@ -87,14 +87,16 @@ conversation // Starts a dialog.
page // Starts a new page. Pages are automatically numbered starting at 1. page // Starts a new page. Pages are automatically numbered starting at 1.
{ {
name = <string>; // Name that goes in the upper left hand corner name = <string>; // Name that goes in the upper left hand corner
panel = <string>; // Name of lump to render as the background. panel = <string>; // Name of lump to render as the background.
voice = <string>; // Narration sound lump. voice = <string>; // Narration sound lump.
dialog = <string>; // Dialog of the page. dialog = <string>; // Dialog of the page.
drop = <integer>; // mobj for the object to drop if the actor is goodbye = <string>; // Custom goodbye message. If omitted then the
// killed. // generic goodbyes will be displayed instead.
link = <integer>; // Page to jump to if all ifitem conditions are drop = <integer>; // mobj for the object to drop if the actor is
// satisified. // killed.
link = <integer>; // Page to jump to if all ifitem conditions are
// satisified.
// jumps to the specified page if the player has the specified amount // jumps to the specified page if the player has the specified amount
// or more of item in their inventory. This can be repeated as many // or more of item in their inventory. This can be repeated as many

View file

@ -1235,6 +1235,7 @@ set (PCH_SOURCES
p_3dfloors.cpp p_3dfloors.cpp
p_3dmidtex.cpp p_3dmidtex.cpp
p_acs.cpp p_acs.cpp
p_actionfunctions.cpp
p_buildmap.cpp p_buildmap.cpp
p_ceiling.cpp p_ceiling.cpp
p_conversation.cpp p_conversation.cpp
@ -1373,7 +1374,6 @@ set (PCH_SOURCES
textures/warptexture.cpp textures/warptexture.cpp
thingdef/olddecorations.cpp thingdef/olddecorations.cpp
thingdef/thingdef.cpp thingdef/thingdef.cpp
thingdef/thingdef_codeptr.cpp
thingdef/thingdef_data.cpp thingdef/thingdef_data.cpp
thingdef/thingdef_exp.cpp thingdef/thingdef_exp.cpp
thingdef/thingdef_expression.cpp thingdef/thingdef_expression.cpp

View file

@ -2985,9 +2985,11 @@ static bool LoadDehSupp ()
void FinishDehPatch () void FinishDehPatch ()
{ {
unsigned int touchedIndex; unsigned int touchedIndex;
unsigned int nameindex = 0;
for (touchedIndex = 0; touchedIndex < TouchedActors.Size(); ++touchedIndex) for (touchedIndex = 0; touchedIndex < TouchedActors.Size(); ++touchedIndex)
{ {
PClassActor *subclass;
PClassActor *type = TouchedActors[touchedIndex]; PClassActor *type = TouchedActors[touchedIndex];
AActor *defaults1 = GetDefaultByType (type); AActor *defaults1 = GetDefaultByType (type);
if (!(defaults1->flags & MF_SPECIAL)) if (!(defaults1->flags & MF_SPECIAL))
@ -2997,9 +2999,16 @@ void FinishDehPatch ()
// Create a new class that will serve as the actual pickup // Create a new class that will serve as the actual pickup
char typeNameBuilder[32]; char typeNameBuilder[32];
mysnprintf (typeNameBuilder, countof(typeNameBuilder), "DehackedPickup%d", touchedIndex); //
PClassActor *subclass = static_cast<PClassActor *>(RUNTIME_CLASS(ADehackedPickup)-> do
CreateDerivedClass(typeNameBuilder, sizeof(ADehackedPickup))); {
// Retry until we find a free name. This is unlikely to happen but not impossible.
mysnprintf(typeNameBuilder, countof(typeNameBuilder), "DehackedPickup%d", nameindex++);
subclass = static_cast<PClassActor *>(RUNTIME_CLASS(ADehackedPickup)->
CreateDerivedClass(typeNameBuilder, sizeof(ADehackedPickup)));
}
while (subclass == nullptr);
AActor *defaults2 = GetDefaultByType (subclass); AActor *defaults2 = GetDefaultByType (subclass);
memcpy ((void *)defaults2, (void *)defaults1, sizeof(AActor)); memcpy ((void *)defaults2, (void *)defaults1, sizeof(AActor));

View file

@ -201,6 +201,7 @@ enum EObjectFlags
OF_EuthanizeMe = 1 << 5, // Object wants to die OF_EuthanizeMe = 1 << 5, // Object wants to die
OF_Cleanup = 1 << 6, // Object is now being deleted by the collector OF_Cleanup = 1 << 6, // Object is now being deleted by the collector
OF_YesReallyDelete = 1 << 7, // Object is being deleted outside the collector, and this is okay, so don't print a warning OF_YesReallyDelete = 1 << 7, // Object is being deleted outside the collector, and this is okay, so don't print a warning
OF_Transient = 1 << 11, // Object should not be archived (references to it will be nulled on disk)
OF_WhiteBits = OF_White0 | OF_White1, OF_WhiteBits = OF_White0 | OF_White1,
OF_MarkBits = OF_WhiteBits | OF_Black, OF_MarkBits = OF_WhiteBits | OF_Black,
@ -573,6 +574,9 @@ protected:
} }
}; };
// When you write to a pointer to an Object, you must call this for
// proper bookkeeping in case the Object holding this pointer has
// already been processed by the GC.
static inline void GC::WriteBarrier(DObject *pointing, DObject *pointed) static inline void GC::WriteBarrier(DObject *pointing, DObject *pointed)
{ {
if (pointed != NULL && pointed->IsWhite() && pointing->IsBlack()) if (pointed != NULL && pointed->IsWhite() && pointing->IsBlack())

View file

@ -670,6 +670,20 @@ void PNamedType::GetTypeIDs(intptr_t &id1, intptr_t &id2) const
id2 = TypeName; id2 = TypeName;
} }
//==========================================================================
//
// PNamedType :: QualifiedName
//
//==========================================================================
FString PNamedType::QualifiedName() const
{
FString out;
if (Outer != nullptr) out = Outer->QualifiedName();
out << "::" << TypeName;
return out;
}
/* PInt *******************************************************************/ /* PInt *******************************************************************/
IMPLEMENT_CLASS(PInt) IMPLEMENT_CLASS(PInt)
@ -1752,7 +1766,7 @@ PEnum::PEnum()
// //
//========================================================================== //==========================================================================
PEnum::PEnum(FName name, DObject *outer) PEnum::PEnum(FName name, PTypeBase *outer)
: PNamedType(name, outer), ValueType(NULL) : PNamedType(name, outer), ValueType(NULL)
{ {
} }
@ -1766,7 +1780,7 @@ PEnum::PEnum(FName name, DObject *outer)
// //
//========================================================================== //==========================================================================
PEnum *NewEnum(FName name, DObject *outer) PEnum *NewEnum(FName name, PTypeBase *outer)
{ {
size_t bucket; size_t bucket;
PType *etype = TypeTable.FindType(RUNTIME_CLASS(PEnum), (intptr_t)outer, (intptr_t)name, &bucket); PType *etype = TypeTable.FindType(RUNTIME_CLASS(PEnum), (intptr_t)outer, (intptr_t)name, &bucket);
@ -2149,7 +2163,7 @@ PStruct::PStruct()
// //
//========================================================================== //==========================================================================
PStruct::PStruct(FName name, DObject *outer) PStruct::PStruct(FName name, PTypeBase *outer)
: PNamedType(name, outer) : PNamedType(name, outer)
{ {
} }
@ -2310,7 +2324,7 @@ size_t PStruct::PropagateMark()
// //
//========================================================================== //==========================================================================
PStruct *NewStruct(FName name, DObject *outer) PStruct *NewStruct(FName name, PTypeBase *outer)
{ {
size_t bucket; size_t bucket;
PType *stype = TypeTable.FindType(RUNTIME_CLASS(PStruct), (intptr_t)outer, (intptr_t)name, &bucket); PType *stype = TypeTable.FindType(RUNTIME_CLASS(PStruct), (intptr_t)outer, (intptr_t)name, &bucket);
@ -2847,10 +2861,7 @@ void PClass::InsertIntoHash ()
found = TypeTable.FindType(RUNTIME_CLASS(PClass), (intptr_t)Outer, TypeName, &bucket); found = TypeTable.FindType(RUNTIME_CLASS(PClass), (intptr_t)Outer, TypeName, &bucket);
if (found != NULL) if (found != NULL)
{ // This type has already been inserted { // This type has already been inserted
// ... but there is no need whatsoever to make it a fatal error! I_Error("Tried to register class '%s' more than once.\n", TypeName.GetChars());
if (!strictdecorate) Printf (TEXTCOLOR_RED"Tried to register class '%s' more than once.\n", TypeName.GetChars());
else I_Error("Tried to register class '%s' more than once.\n", TypeName.GetChars());
TypeTable.ReplaceType(this, found, bucket);
} }
else else
{ {
@ -3015,15 +3026,23 @@ PClass *PClass::CreateDerivedClass(FName name, unsigned int size)
PClass *existclass = static_cast<PClass *>(TypeTable.FindType(RUNTIME_CLASS(PClass), /*FIXME:Outer*/0, name, &bucket)); PClass *existclass = static_cast<PClass *>(TypeTable.FindType(RUNTIME_CLASS(PClass), /*FIXME:Outer*/0, name, &bucket));
// This is a placeholder so fill it in // This is a placeholder so fill it in
if (existclass != NULL && (existclass->Size == TentativeClass)) if (existclass != nullptr)
{ {
type = const_cast<PClass*>(existclass); if (existclass->Size == TentativeClass)
if (!IsDescendantOf(type->ParentClass))
{ {
I_Error("%s must inherit from %s but doesn't.", name.GetChars(), type->ParentClass->TypeName.GetChars()); type = const_cast<PClass*>(existclass);
if (!IsDescendantOf(type->ParentClass))
{
I_Error("%s must inherit from %s but doesn't.", name.GetChars(), type->ParentClass->TypeName.GetChars());
}
DPrintf(DMSG_SPAMMY, "Defining placeholder class %s\n", name.GetChars());
notnew = true;
}
else
{
// a different class with the same name already exists. Let the calling code deal with this.
return nullptr;
} }
DPrintf(DMSG_SPAMMY, "Defining placeholder class %s\n", name.GetChars());
notnew = true;
} }
else else
{ {
@ -3360,6 +3379,7 @@ CCMD(typetable)
// Symbol tables ------------------------------------------------------------ // Symbol tables ------------------------------------------------------------
IMPLEMENT_ABSTRACT_CLASS(PTypeBase);
IMPLEMENT_ABSTRACT_CLASS(PSymbol); IMPLEMENT_ABSTRACT_CLASS(PSymbol);
IMPLEMENT_CLASS(PSymbolConst); IMPLEMENT_CLASS(PSymbolConst);
IMPLEMENT_CLASS(PSymbolConstNumeric); IMPLEMENT_CLASS(PSymbolConstNumeric);

View file

@ -22,12 +22,28 @@ typedef std::pair<const class PType *, unsigned> FTypeAndOffset;
// Symbol information ------------------------------------------------------- // Symbol information -------------------------------------------------------
class PSymbol : public DObject class PTypeBase : public DObject
{ {
DECLARE_ABSTRACT_CLASS(PSymbol, DObject); DECLARE_ABSTRACT_CLASS(PTypeBase, DObject)
public:
virtual FString QualifiedName() const
{
return "";
}
};
class PSymbol : public PTypeBase
{
DECLARE_ABSTRACT_CLASS(PSymbol, PTypeBase);
public: public:
virtual ~PSymbol(); virtual ~PSymbol();
virtual FString QualifiedName() const
{
return SymbolName.GetChars();
}
FName SymbolName; FName SymbolName;
protected: protected:
@ -153,13 +169,13 @@ extern PSymbolTable GlobalSymbols;
struct ZCC_ExprConstant; struct ZCC_ExprConstant;
class PClassType; class PClassType;
class PType : public DObject class PType : public PTypeBase
{ {
//DECLARE_ABSTRACT_CLASS_WITH_META(PType, DObject, PClassType); //DECLARE_ABSTRACT_CLASS_WITH_META(PType, DObject, PClassType);
// We need to unravel the _WITH_META macro, since PClassType isn't defined yet, // We need to unravel the _WITH_META macro, since PClassType isn't defined yet,
// and we can't define it until we've defined PClass. But we can't define that // and we can't define it until we've defined PClass. But we can't define that
// without defining PType. // without defining PType.
DECLARE_ABSTRACT_CLASS(PType, DObject) DECLARE_ABSTRACT_CLASS(PType, PTypeBase)
HAS_OBJECT_POINTERS; HAS_OBJECT_POINTERS;
protected: protected:
enum { MetaClassNum = CLASSREG_PClassType }; enum { MetaClassNum = CLASSREG_PClassType };
@ -332,14 +348,15 @@ class PNamedType : public PCompoundType
DECLARE_ABSTRACT_CLASS(PNamedType, PCompoundType); DECLARE_ABSTRACT_CLASS(PNamedType, PCompoundType);
HAS_OBJECT_POINTERS; HAS_OBJECT_POINTERS;
public: public:
DObject *Outer; // object this type is contained within PTypeBase *Outer; // object this type is contained within
FName TypeName; // this type's name FName TypeName; // this type's name
PNamedType() : Outer(NULL) {} PNamedType() : Outer(NULL) {}
PNamedType(FName name, DObject *outer) : Outer(outer), TypeName(name) {} PNamedType(FName name, PTypeBase *outer) : Outer(outer), TypeName(name) {}
virtual bool IsMatch(intptr_t id1, intptr_t id2) const; virtual bool IsMatch(intptr_t id1, intptr_t id2) const;
virtual void GetTypeIDs(intptr_t &id1, intptr_t &id2) const; virtual void GetTypeIDs(intptr_t &id1, intptr_t &id2) const;
virtual FString QualifiedName() const;
}; };
// Basic types -------------------------------------------------------------- // Basic types --------------------------------------------------------------
@ -533,7 +550,7 @@ class PEnum : public PNamedType
DECLARE_CLASS(PEnum, PNamedType); DECLARE_CLASS(PEnum, PNamedType);
HAS_OBJECT_POINTERS; HAS_OBJECT_POINTERS;
public: public:
PEnum(FName name, DObject *outer); PEnum(FName name, PTypeBase *outer);
PType *ValueType; PType *ValueType;
TMap<FName, int> Values; TMap<FName, int> Values;
@ -610,7 +627,7 @@ class PStruct : public PNamedType
{ {
DECLARE_CLASS(PStruct, PNamedType); DECLARE_CLASS(PStruct, PNamedType);
public: public:
PStruct(FName name, DObject *outer); PStruct(FName name, PTypeBase *outer);
TArray<PField *> Fields; TArray<PField *> Fields;
@ -822,8 +839,8 @@ PDynArray *NewDynArray(PType *type);
PPointer *NewPointer(PType *type); PPointer *NewPointer(PType *type);
PClassPointer *NewClassPointer(PClass *restrict); PClassPointer *NewClassPointer(PClass *restrict);
PClassWaitingForParent *NewUnknownClass(FName myname, FName parentname); PClassWaitingForParent *NewUnknownClass(FName myname, FName parentname);
PEnum *NewEnum(FName name, DObject *outer); PEnum *NewEnum(FName name, PTypeBase *outer);
PStruct *NewStruct(FName name, DObject *outer); PStruct *NewStruct(FName name, PTypeBase *outer);
PPrototype *NewPrototype(const TArray<PType *> &rettypes, const TArray<PType *> &argtypes); PPrototype *NewPrototype(const TArray<PType *> &rettypes, const TArray<PType *> &argtypes);
// Built-in types ----------------------------------------------------------- // Built-in types -----------------------------------------------------------

View file

@ -497,7 +497,7 @@ DFsSection *FParser::looping_section()
if(!best || (current->start_index > best->start_index)) if(!best || (current->start_index > best->start_index))
best = current; // save it best = current; // save it
} }
current = current->next; current = current->next;
} }
} }

View file

@ -1999,7 +1999,7 @@ void G_DoLoadGame ()
{ {
// delete the resource file if anything goes wrong in here. // delete the resource file if anything goes wrong in here.
if (resfile != nullptr) delete resfile; if (resfile != nullptr) delete resfile;
return; throw;
} }
} }

View file

@ -1512,7 +1512,11 @@ void G_UnSnapshotLevel (bool hubLoad)
if (level.info->isValid()) if (level.info->isValid())
{ {
FSerializer arc; FSerializer arc;
if (!arc.OpenReader(&level.info->Snapshot)) return; if (!arc.OpenReader(&level.info->Snapshot))
{
I_Error("Failed to load savegame");
return;
}
G_SerializeLevel (arc, hubLoad); G_SerializeLevel (arc, hubLoad);
level.FromSnapshot = true; level.FromSnapshot = true;

View file

@ -1081,6 +1081,7 @@ void gl_AttachLight(AActor *actor, unsigned int count, const FLightDefaults *lig
light = Spawn<ADynamicLight>(actor->Pos(), NO_REPLACE); light = Spawn<ADynamicLight>(actor->Pos(), NO_REPLACE);
light->target = actor; light->target = actor;
light->owned = true; light->owned = true;
light->ObjectFlags |= OF_Transient;
actor->dynamiclights.Push(light); actor->dynamiclights.Push(light);
} }
light->flags2&=~MF2_DORMANT; light->flags2&=~MF2_DORMANT;

View file

@ -314,12 +314,12 @@ void FVoxelModel::MakeSlabPolys(int x, int y, kvxslab_t *voxptr, FVoxelMap &chec
} }
if (cull & 4) if (cull & 4)
{ {
AddFace(x, y, z, x+1, y, z, x, y, z+c, x+1, y, z+c, *col, check); AddFace(x+1, y, z, x, y, z, x+1, y, z+c, x, y, z+c, *col, check);
} }
if (cull & 8) if (cull & 8)
{ {
AddFace(x+1, y+1, z, x, y+1, z, x+1, y+1, z+c, x, y+1, z+c, *col, check); AddFace(x, y+1, z, x+1, y+1, z, x, y+1, z+c, x+1, y+1, z+c, *col, check);
} }
z+=c; z+=c;
col+=c; col+=c;
} }

View file

@ -2,7 +2,6 @@
#define __GL_RENDERBUFFERS_H #define __GL_RENDERBUFFERS_H
#include "gl/shaders/gl_shader.h" #include "gl/shaders/gl_shader.h"
#include "gl/renderer/gl_renderer.h"
class FGLBloomTextureLevel class FGLBloomTextureLevel
{ {

View file

@ -106,6 +106,8 @@ FGLRenderer::FGLRenderer(OpenGLFrameBuffer *fb)
mTonemapPalette = nullptr; mTonemapPalette = nullptr;
mBuffers = nullptr; mBuffers = nullptr;
mPresentShader = nullptr; mPresentShader = nullptr;
mPresent3dCheckerShader = nullptr;
mPresent3dColumnShader = nullptr;
mPresent3dRowShader = nullptr; mPresent3dRowShader = nullptr;
mBloomExtractShader = nullptr; mBloomExtractShader = nullptr;
mBloomCombineShader = nullptr; mBloomCombineShader = nullptr;
@ -148,6 +150,8 @@ void FGLRenderer::Initialize(int width, int height)
mFXAAShader = new FFXAAShader; mFXAAShader = new FFXAAShader;
mFXAALumaShader = new FFXAALumaShader; mFXAALumaShader = new FFXAALumaShader;
mPresentShader = new FPresentShader(); mPresentShader = new FPresentShader();
mPresent3dCheckerShader = new FPresent3DCheckerShader();
mPresent3dColumnShader = new FPresent3DColumnShader();
mPresent3dRowShader = new FPresent3DRowShader(); mPresent3dRowShader = new FPresent3DRowShader();
m2DDrawer = new F2DDrawer; m2DDrawer = new F2DDrawer;
@ -205,6 +209,8 @@ FGLRenderer::~FGLRenderer()
if (mDepthBlurShader) delete mDepthBlurShader; if (mDepthBlurShader) delete mDepthBlurShader;
if (mSSAOShader) delete mSSAOShader; if (mSSAOShader) delete mSSAOShader;
if (mSSAOCombineShader) delete mSSAOCombineShader; if (mSSAOCombineShader) delete mSSAOCombineShader;
if (mPresent3dCheckerShader) delete mPresent3dCheckerShader;
if (mPresent3dColumnShader) delete mPresent3dColumnShader;
if (mPresent3dRowShader) delete mPresent3dRowShader; if (mPresent3dRowShader) delete mPresent3dRowShader;
if (mBloomExtractShader) delete mBloomExtractShader; if (mBloomExtractShader) delete mBloomExtractShader;
if (mBloomCombineShader) delete mBloomCombineShader; if (mBloomCombineShader) delete mBloomCombineShader;

View file

@ -35,6 +35,8 @@ class FLensShader;
class FFXAALumaShader; class FFXAALumaShader;
class FFXAAShader; class FFXAAShader;
class FPresentShader; class FPresentShader;
class FPresent3DCheckerShader;
class FPresent3DColumnShader;
class FPresent3DRowShader; class FPresent3DRowShader;
class F2DDrawer; class F2DDrawer;
class FHardwareTexture; class FHardwareTexture;
@ -117,6 +119,8 @@ public:
FFXAALumaShader *mFXAALumaShader; FFXAALumaShader *mFXAALumaShader;
FFXAAShader *mFXAAShader; FFXAAShader *mFXAAShader;
FPresentShader *mPresentShader; FPresentShader *mPresentShader;
FPresent3DCheckerShader *mPresent3dCheckerShader;
FPresent3DColumnShader *mPresent3dColumnShader;
FPresent3DRowShader *mPresent3dRowShader; FPresent3DRowShader *mPresent3dRowShader;
FTexture *gllight; FTexture *gllight;

View file

@ -187,21 +187,18 @@ void GLFlat::DrawSubsector(subsector_t * sub)
unsigned int vi[4]; unsigned int vi[4];
vi[0] = 0; vi[0] = 0;
for (unsigned int i = 1; i < sub->numlines-1; i += 2) for (unsigned int i = 0; i < sub->numlines - 2; i += 2)
{ {
if (i < sub->numlines - 3) for (unsigned int j = 1; j < 4; j++)
{ {
for (unsigned int j = 1; j < 4; j++) vi[j] = MIN(i + j, sub->numlines - 1);
{
vi[j] = MIN(i + j, sub->numlines - 1);
}
for (unsigned int x = 0; x < 4; x++)
{
vertex_t *vt = sub->firstline[vi[x]].v1;
qd.Set(x, vt->fX(), plane.plane.ZatPoint(vt) + dz, vt->fY(), vt->fX() / 64.f, -vt->fY() / 64.f);
}
qd.Render(GL_TRIANGLE_FAN);
} }
for (unsigned int x = 0; x < 4; x++)
{
vertex_t *vt = sub->firstline[vi[x]].v1;
qd.Set(x, vt->fX(), plane.plane.ZatPoint(vt) + dz, vt->fY(), vt->fX() / 64.f, -vt->fY() / 64.f);
}
qd.Render(GL_TRIANGLE_FAN);
} }
} }

View file

@ -1230,7 +1230,6 @@ void FGLInterface::StateChanged(AActor *actor)
void FGLInterface::StartSerialize(FSerializer &arc) void FGLInterface::StartSerialize(FSerializer &arc)
{ {
gl_DeleteAllAttachedLights();
if (arc.BeginObject("glinfo")) if (arc.BeginObject("glinfo"))
{ {
arc("fogdensity", fogdensity) arc("fogdensity", fogdensity)
@ -1242,8 +1241,11 @@ void FGLInterface::StartSerialize(FSerializer &arc)
void FGLInterface::EndSerialize(FSerializer &arc) void FGLInterface::EndSerialize(FSerializer &arc)
{ {
gl_RecreateAllAttachedLights(); if (arc.isReading())
if (arc.isReading()) gl_InitPortals(); {
gl_RecreateAllAttachedLights();
gl_InitPortals();
}
} }
//=========================================================================== //===========================================================================

View file

@ -138,10 +138,10 @@ void GLSprite::CalculateVertices(FVector3 *v)
mat.Rotate(0, 1, 0, - actor->Angles.Roll.Degrees); mat.Rotate(0, 1, 0, - actor->Angles.Roll.Degrees);
mat.Translate(-x, -z, -y); mat.Translate(-x, -z, -y);
} }
v[0] = mat * FVector3(x1, z, y2); v[0] = mat * FVector3(x2, z, y2);
v[1] = mat * FVector3(x2, z, y2); v[1] = mat * FVector3(x1, z, y2);
v[2] = mat * FVector3(x1, z, y1); v[2] = mat * FVector3(x2, z, y1);
v[3] = mat * FVector3(x2, z, y1); v[3] = mat * FVector3(x1, z, y1);
return; return;
} }

View file

@ -129,19 +129,20 @@ void FGLRenderer::DrawPSprite (player_t * player,DPSprite *psp, float sx, float
y1 = viewwindowy + vh / 2 - (ftexturemid * scale); y1 = viewwindowy + vh / 2 - (ftexturemid * scale);
y2 = y1 + (r.height * scale) + 1; y2 = y1 + (r.height * scale) + 1;
if (!mirror) if (!(mirror) != !(psp->Flags & PSPF_FLIP))
{ {
fU1=tex->GetSpriteUL(); fU2 = tex->GetSpriteUL();
fV1=tex->GetSpriteVT(); fV1 = tex->GetSpriteVT();
fU2=tex->GetSpriteUR(); fU1 = tex->GetSpriteUR();
fV2=tex->GetSpriteVB(); fV2 = tex->GetSpriteVB();
} }
else else
{ {
fU2=tex->GetSpriteUL(); fU1 = tex->GetSpriteUL();
fV1=tex->GetSpriteVT(); fV1 = tex->GetSpriteVT();
fU1=tex->GetSpriteUR(); fU2 = tex->GetSpriteUR();
fV2=tex->GetSpriteVB(); fV2 = tex->GetSpriteVB();
} }
if (tex->GetTransparent() || OverrideShader != -1) if (tex->GetTransparent() || OverrideShader != -1)

View file

@ -38,23 +38,37 @@
#include "gl/system/gl_cvars.h" #include "gl/system/gl_cvars.h"
#include "gl/shaders/gl_present3dRowshader.h" #include "gl/shaders/gl_present3dRowshader.h"
void FPresentStereoShaderBase::Init(const char * vtx_shader_name, const char * program_name)
{
FPresentShaderBase::Init(vtx_shader_name, program_name);
LeftEyeTexture.Init(mShader, "LeftEyeTexture");
RightEyeTexture.Init(mShader, "RightEyeTexture");
WindowPositionParity.Init(mShader, "WindowPositionParity");
}
void FPresent3DCheckerShader::Bind()
{
if (!mShader)
{
Init("shaders/glsl/present_checker3d.fp", "shaders/glsl/presentChecker3d");
}
mShader.Bind();
}
void FPresent3DColumnShader::Bind()
{
if (!mShader)
{
Init("shaders/glsl/present_column3d.fp", "shaders/glsl/presentColumn3d");
}
mShader.Bind();
}
void FPresent3DRowShader::Bind() void FPresent3DRowShader::Bind()
{ {
if (!mShader) if (!mShader)
{ {
mShader.Compile(FShaderProgram::Vertex, "shaders/glsl/screenquadscale.vp", "", 330); Init("shaders/glsl/present_row3d.fp", "shaders/glsl/presentRow3d");
mShader.Compile(FShaderProgram::Fragment, "shaders/glsl/present_row3d.fp", "", 330);
mShader.SetFragDataLocation(0, "FragColor");
mShader.Link("shaders/glsl/presentRow3d");
mShader.SetAttribLocation(0, "PositionInProjection");
mShader.SetAttribLocation(1, "UV");
LeftEyeTexture.Init(mShader, "LeftEyeTexture");
RightEyeTexture.Init(mShader, "RightEyeTexture");
InvGamma.Init(mShader, "InvGamma");
Contrast.Init(mShader, "Contrast");
Brightness.Init(mShader, "Brightness");
Scale.Init(mShader, "UVScale");
VerticalPixelOffset.Init(mShader, "VerticalPixelOffset");
} }
mShader.Bind(); mShader.Bind();
} }

View file

@ -29,22 +29,35 @@
#define GL_PRESENT3DROWSHADER_H_ #define GL_PRESENT3DROWSHADER_H_
#include "gl_shaderprogram.h" #include "gl_shaderprogram.h"
#include "gl_presentshader.h"
class FPresent3DRowShader class FPresentStereoShaderBase : public FPresentShaderBase
{ {
public: public:
void Bind();
FBufferedUniformSampler LeftEyeTexture; FBufferedUniformSampler LeftEyeTexture;
FBufferedUniformSampler RightEyeTexture; FBufferedUniformSampler RightEyeTexture;
FBufferedUniform1f InvGamma; FBufferedUniform1i WindowPositionParity;
FBufferedUniform1f Contrast;
FBufferedUniform1f Brightness;
FBufferedUniform2f Scale;
FBufferedUniform1i VerticalPixelOffset;
private: protected:
FShaderProgram mShader; void Init(const char * vtx_shader_name, const char * program_name) override;
};
class FPresent3DCheckerShader : public FPresentStereoShaderBase
{
public:
void Bind() override;
};
class FPresent3DColumnShader : public FPresentStereoShaderBase
{
public:
void Bind() override;
};
class FPresent3DRowShader : public FPresentStereoShaderBase
{
public:
void Bind() override;
}; };
// GL_PRESENT3DROWSHADER_H_ // GL_PRESENT3DROWSHADER_H_

View file

@ -36,21 +36,26 @@
#include "gl/system/gl_cvars.h" #include "gl/system/gl_cvars.h"
#include "gl/shaders/gl_presentshader.h" #include "gl/shaders/gl_presentshader.h"
void FPresentShaderBase::Init(const char * vtx_shader_name, const char * program_name)
{
mShader.Compile(FShaderProgram::Vertex, "shaders/glsl/screenquadscale.vp", "", 330);
mShader.Compile(FShaderProgram::Fragment, vtx_shader_name, "", 330);
mShader.SetFragDataLocation(0, "FragColor");
mShader.Link(program_name);
mShader.SetAttribLocation(0, "PositionInProjection");
mShader.SetAttribLocation(1, "UV");
InvGamma.Init(mShader, "InvGamma");
Contrast.Init(mShader, "Contrast");
Brightness.Init(mShader, "Brightness");
Scale.Init(mShader, "UVScale");
}
void FPresentShader::Bind() void FPresentShader::Bind()
{ {
if (!mShader) if (!mShader)
{ {
mShader.Compile(FShaderProgram::Vertex, "shaders/glsl/screenquadscale.vp", "", 330); Init("shaders/glsl/present.fp", "shaders/glsl/present");
mShader.Compile(FShaderProgram::Fragment, "shaders/glsl/present.fp", "", 330);
mShader.SetFragDataLocation(0, "FragColor");
mShader.Link("shaders/glsl/present");
mShader.SetAttribLocation(0, "PositionInProjection");
mShader.SetAttribLocation(1, "UV");
InputTexture.Init(mShader, "InputTexture"); InputTexture.Init(mShader, "InputTexture");
InvGamma.Init(mShader, "InvGamma");
Contrast.Init(mShader, "Contrast");
Brightness.Init(mShader, "Brightness");
Scale.Init(mShader, "UVScale");
} }
mShader.Bind(); mShader.Bind();
} }

View file

@ -3,19 +3,27 @@
#include "gl_shaderprogram.h" #include "gl_shaderprogram.h"
class FPresentShader class FPresentShaderBase
{ {
public: public:
void Bind(); virtual void Bind() = 0;
FBufferedUniformSampler InputTexture;
FBufferedUniform1f InvGamma; FBufferedUniform1f InvGamma;
FBufferedUniform1f Contrast; FBufferedUniform1f Contrast;
FBufferedUniform1f Brightness; FBufferedUniform1f Brightness;
FBufferedUniform2f Scale; FBufferedUniform2f Scale;
private: protected:
virtual void Init(const char * vtx_shader_name, const char * program_name);
FShaderProgram mShader; FShaderProgram mShader;
}; };
class FPresentShader : public FPresentShaderBase
{
public:
void Bind() override;
FBufferedUniformSampler InputTexture;
};
#endif #endif

View file

@ -43,10 +43,25 @@
EXTERN_CVAR(Float, vid_brightness) EXTERN_CVAR(Float, vid_brightness)
EXTERN_CVAR(Float, vid_contrast) EXTERN_CVAR(Float, vid_contrast)
EXTERN_CVAR(Bool, fullscreen) EXTERN_CVAR(Bool, fullscreen)
EXTERN_CVAR(Int, win_y) // pixel position of top of display window EXTERN_CVAR(Int, win_x) // screen pixel position of left of display window
EXTERN_CVAR(Int, win_y) // screen pixel position of top of display window
namespace s3d { namespace s3d {
/* static */
const CheckerInterleaved3D& CheckerInterleaved3D::getInstance(float ipd)
{
static CheckerInterleaved3D instance(ipd);
return instance;
}
/* static */
const ColumnInterleaved3D& ColumnInterleaved3D::getInstance(float ipd)
{
static ColumnInterleaved3D instance(ipd);
return instance;
}
/* static */ /* static */
const RowInterleaved3D& RowInterleaved3D::getInstance(float ipd) const RowInterleaved3D& RowInterleaved3D::getInstance(float ipd)
{ {
@ -54,11 +69,7 @@ const RowInterleaved3D& RowInterleaved3D::getInstance(float ipd)
return instance; return instance;
} }
RowInterleaved3D::RowInterleaved3D(double ipdMeters) static void prepareInterleavedPresent(FPresentStereoShaderBase& shader)
: TopBottom3D(ipdMeters)
{}
void RowInterleaved3D::Present() const
{ {
GLRenderer->mBuffers->BindOutputFB(); GLRenderer->mBuffers->BindOutputFB();
GLRenderer->ClearBorders(); GLRenderer->ClearBorders();
@ -79,27 +90,102 @@ void RowInterleaved3D::Present() const
const GL_IRECT& box = GLRenderer->mOutputLetterbox; const GL_IRECT& box = GLRenderer->mOutputLetterbox;
glViewport(box.left, box.top, box.width, box.height); glViewport(box.left, box.top, box.width, box.height);
bool applyGamma = true; shader.Bind();
shader.LeftEyeTexture.Set(0);
shader.RightEyeTexture.Set(1);
GLRenderer->mPresent3dRowShader->Bind(); if ( GLRenderer->framebuffer->IsHWGammaActive() )
GLRenderer->mPresent3dRowShader->LeftEyeTexture.Set(0);
GLRenderer->mPresent3dRowShader->RightEyeTexture.Set(1);
if (!applyGamma || GLRenderer->framebuffer->IsHWGammaActive())
{ {
GLRenderer->mPresent3dRowShader->InvGamma.Set(1.0f); shader.InvGamma.Set(1.0f);
GLRenderer->mPresent3dRowShader->Contrast.Set(1.0f); shader.Contrast.Set(1.0f);
GLRenderer->mPresent3dRowShader->Brightness.Set(0.0f); shader.Brightness.Set(0.0f);
} }
else else
{ {
GLRenderer->mPresent3dRowShader->InvGamma.Set(1.0f / clamp<float>(Gamma, 0.1f, 4.f)); shader.InvGamma.Set(1.0f / clamp<float>(Gamma, 0.1f, 4.f));
GLRenderer->mPresent3dRowShader->Contrast.Set(clamp<float>(vid_contrast, 0.1f, 3.f)); shader.Contrast.Set(clamp<float>(vid_contrast, 0.1f, 3.f));
GLRenderer->mPresent3dRowShader->Brightness.Set(clamp<float>(vid_brightness, -0.8f, 0.8f)); shader.Brightness.Set(clamp<float>(vid_brightness, -0.8f, 0.8f));
} }
GLRenderer->mPresent3dRowShader->Scale.Set( shader.Scale.Set(
GLRenderer->mScreenViewport.width / (float)GLRenderer->mBuffers->GetWidth(), GLRenderer->mScreenViewport.width / (float)GLRenderer->mBuffers->GetWidth(),
GLRenderer->mScreenViewport.height / (float)GLRenderer->mBuffers->GetHeight()); GLRenderer->mScreenViewport.height / (float)GLRenderer->mBuffers->GetHeight());
}
// fixme: I don't know how to get absolute window position on Mac and Linux
// fixme: I don't know how to get window border decoration size anywhere
// So for now I'll hard code the border effect on my test machine.
// Workaround for others is to fuss with vr_swap_eyes CVAR until it looks right.
// Presumably the top/left window border on my test machine has an odd number of pixels
// in the horizontal direction, and an even number in the vertical direction.
#define WINDOW_BORDER_HORIZONTAL_PARITY 1
#define WINDOW_BORDER_VERTICAL_PARITY 0
void CheckerInterleaved3D::Present() const
{
prepareInterleavedPresent(*GLRenderer->mPresent3dCheckerShader);
// Compute absolute offset from top of screen to top of current display window
// because we need screen-relative, not window-relative, scan line parity
int windowVOffset = 0;
int windowHOffset = 0;
#ifdef _WIN32
if (!fullscreen) {
I_SaveWindowedPos(); // update win_y CVAR
windowHOffset = (win_x + WINDOW_BORDER_HORIZONTAL_PARITY) % 2;
windowVOffset = (win_y + WINDOW_BORDER_VERTICAL_PARITY) % 2;
}
#endif // _WIN32
GLRenderer->mPresent3dCheckerShader->WindowPositionParity.Set(
(windowVOffset
+ windowHOffset
+ GLRenderer->mOutputLetterbox.height + 1 // +1 because of origin at bottom
) % 2 // because we want the top pixel offset, but gl_FragCoord.y is the bottom pixel offset
);
GLRenderer->RenderScreenQuad();
}
void s3d::CheckerInterleaved3D::AdjustViewports() const
{
// decrease the total pixel count by 2, but keep the same aspect ratio
const float sqrt2 = 1.41421356237f;
// Change size of renderbuffer, and align to screen
GLRenderer->mSceneViewport.height /= sqrt2;
GLRenderer->mSceneViewport.top /= sqrt2;
GLRenderer->mSceneViewport.width /= sqrt2;
GLRenderer->mSceneViewport.left /= sqrt2;
GLRenderer->mScreenViewport.height /= sqrt2;
GLRenderer->mScreenViewport.top /= sqrt2;
GLRenderer->mScreenViewport.width /= sqrt2;
GLRenderer->mScreenViewport.left /= sqrt2;
}
void ColumnInterleaved3D::Present() const
{
prepareInterleavedPresent(*GLRenderer->mPresent3dColumnShader);
// Compute absolute offset from top of screen to top of current display window
// because we need screen-relative, not window-relative, scan line parity
int windowHOffset = 0;
#ifdef _WIN32
if (!fullscreen) {
I_SaveWindowedPos(); // update win_y CVAR
windowHOffset = (win_x + WINDOW_BORDER_HORIZONTAL_PARITY) % 2;
}
#endif // _WIN32
GLRenderer->mPresent3dColumnShader->WindowPositionParity.Set(windowHOffset);
GLRenderer->RenderScreenQuad();
}
void RowInterleaved3D::Present() const
{
prepareInterleavedPresent(*GLRenderer->mPresent3dRowShader);
// Compute absolute offset from top of screen to top of current display window // Compute absolute offset from top of screen to top of current display window
// because we need screen-relative, not window-relative, scan line parity // because we need screen-relative, not window-relative, scan line parity
@ -108,13 +194,14 @@ void RowInterleaved3D::Present() const
#ifdef _WIN32 #ifdef _WIN32
if (! fullscreen) { if (! fullscreen) {
I_SaveWindowedPos(); // update win_y CVAR I_SaveWindowedPos(); // update win_y CVAR
windowVOffset = win_y; windowVOffset = (win_y + WINDOW_BORDER_VERTICAL_PARITY) % 2;
} }
#endif // _WIN32 #endif // _WIN32
GLRenderer->mPresent3dRowShader->VerticalPixelOffset.Set( GLRenderer->mPresent3dRowShader->WindowPositionParity.Set(
windowVOffset // fixme: vary with window location (windowVOffset
+ box.height % 2 // because we want the top pixel offset, but gl_FragCoord.y is the bottom pixel offset + GLRenderer->mOutputLetterbox.height + 1 // +1 because of origin at bottom
) % 2
); );
GLRenderer->RenderScreenQuad(); GLRenderer->RenderScreenQuad();

View file

@ -42,15 +42,30 @@
#include "gl/system/gl_system.h" #include "gl/system/gl_system.h"
#include "gl/renderer/gl_renderstate.h" #include "gl/renderer/gl_renderstate.h"
class FPresent3DRowShader;
namespace s3d { namespace s3d {
class CheckerInterleaved3D : public SideBySideSquished
{
public:
static const CheckerInterleaved3D& getInstance(float ipd);
CheckerInterleaved3D(double ipdMeters) : SideBySideSquished(ipdMeters) {}
void Present() const override;
void AdjustViewports() const override;
};
class ColumnInterleaved3D : public SideBySideSquished
{
public:
static const ColumnInterleaved3D& getInstance(float ipd);
ColumnInterleaved3D(double ipdMeters) : SideBySideSquished(ipdMeters) {}
void Present() const override;
};
class RowInterleaved3D : public TopBottom3D class RowInterleaved3D : public TopBottom3D
{ {
public: public:
static const RowInterleaved3D& getInstance(float ipd); static const RowInterleaved3D& getInstance(float ipd);
RowInterleaved3D(double ipdMeters); RowInterleaved3D(double ipdMeters) : TopBottom3D(ipdMeters) {}
void Present() const override; void Present() const override;
}; };

View file

@ -107,6 +107,12 @@ const Stereo3DMode& Stereo3DMode::getCurrentMode()
case 12: case 12:
setCurrentMode(RowInterleaved3D::getInstance(vr_ipd)); setCurrentMode(RowInterleaved3D::getInstance(vr_ipd));
break; break;
case 13:
setCurrentMode(ColumnInterleaved3D::getInstance(vr_ipd));
break;
case 14:
setCurrentMode(CheckerInterleaved3D::getInstance(vr_ipd));
break;
case 0: case 0:
default: default:
setCurrentMode(MonoView::getInstance()); setCurrentMode(MonoView::getInstance());

View file

@ -46,6 +46,17 @@
#include "gl/xbr/xbrz.h" #include "gl/xbr/xbrz.h"
#include "gl/xbr/xbrz_old.h" #include "gl/xbr/xbrz_old.h"
#ifdef __APPLE__
# include <AvailabilityMacros.h>
# if MAC_OS_X_VERSION_MAX_ALLOWED >= 1060
# define GZ_USE_LIBDISPATCH
# endif // MAC_OS_X_VERSION_MAX_ALLOWED >= 1060
#endif // __APPLE__
#ifdef GZ_USE_LIBDISPATCH
# include <dispatch/dispatch.h>
#endif // GZ_USE_LIBDISPATCH
CUSTOM_CVAR(Int, gl_texture_hqresize, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL) CUSTOM_CVAR(Int, gl_texture_hqresize, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL)
{ {
if (self < 0 || self > 16) if (self < 0 || self > 16)
@ -76,6 +87,22 @@ CVAR (Flag, gl_texture_hqresize_textures, gl_texture_hqresize_targets, 1);
CVAR (Flag, gl_texture_hqresize_sprites, gl_texture_hqresize_targets, 2); CVAR (Flag, gl_texture_hqresize_sprites, gl_texture_hqresize_targets, 2);
CVAR (Flag, gl_texture_hqresize_fonts, gl_texture_hqresize_targets, 4); CVAR (Flag, gl_texture_hqresize_fonts, gl_texture_hqresize_targets, 4);
#ifdef GZ_USE_LIBDISPATCH
CVAR(Bool, gl_texture_hqresize_multithread, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG);
CUSTOM_CVAR(Int, gl_texture_hqresize_mt_width, 16, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
{
if (self < 2) self = 2;
if (self > 1024) self = 1024;
}
CUSTOM_CVAR(Int, gl_texture_hqresize_mt_height, 4, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
{
if (self < 2) self = 2;
if (self > 1024) self = 1024;
}
#endif // GZ_USE_LIBDISPATCH
static void scale2x ( uint32* inputBuffer, uint32* outputBuffer, int inWidth, int inHeight ) static void scale2x ( uint32* inputBuffer, uint32* outputBuffer, int inWidth, int inHeight )
{ {
@ -261,26 +288,38 @@ static unsigned char *xbrzHelper( void (*xbrzFunction) ( size_t, const uint32_t*
outHeight = N *inHeight; outHeight = N *inHeight;
unsigned char * newBuffer = new unsigned char[outWidth*outHeight*4]; unsigned char * newBuffer = new unsigned char[outWidth*outHeight*4];
xbrzFunction(N, reinterpret_cast<uint32_t*>(inputBuffer), reinterpret_cast<uint32_t*>(newBuffer), inWidth, inHeight, xbrz::ARGB, xbrz::ScalerCfg(), 0, std::numeric_limits<int>::max());
#ifdef GZ_USE_LIBDISPATCH
const int thresholdWidth = gl_texture_hqresize_mt_width;
const int thresholdHeight = gl_texture_hqresize_mt_height;
if (gl_texture_hqresize_multithread
&& inWidth > thresholdWidth
&& inHeight > thresholdHeight)
{
const dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_apply(inHeight / thresholdHeight + 1, queue, ^(size_t sliceY)
{
xbrzFunction(N, reinterpret_cast<uint32_t*>(inputBuffer), reinterpret_cast<uint32_t*>(newBuffer),
inWidth, inHeight, xbrz::ARGB, xbrz::ScalerCfg(), sliceY * thresholdHeight, (sliceY + 1) * thresholdHeight);
});
}
else
#endif // GZ_USE_LIBDISPATCH
{
xbrzFunction(N, reinterpret_cast<uint32_t*>(inputBuffer), reinterpret_cast<uint32_t*>(newBuffer),
inWidth, inHeight, xbrz::ARGB, xbrz::ScalerCfg(), 0, std::numeric_limits<int>::max());
}
delete[] inputBuffer; delete[] inputBuffer;
return newBuffer; return newBuffer;
} }
static unsigned char *xbrzoldHelper( void (*xbrzFunction) ( size_t factor, const uint32_t* src, uint32_t* trg, int srcWidth, int srcHeight, const xbrz_old::ScalerCfg& cfg, int yFirst, int yLast ), static void xbrzOldScale(size_t factor, const uint32_t* src, uint32_t* trg, int srcWidth, int srcHeight, xbrz::ColorFormat colFmt, const xbrz::ScalerCfg& cfg, int yFirst, int yLast)
const int N,
unsigned char *inputBuffer,
const int inWidth,
const int inHeight,
int &outWidth,
int &outHeight )
{ {
outWidth = N * inWidth; static_assert(sizeof(xbrz::ScalerCfg) == sizeof(xbrz_old::ScalerCfg), "ScalerCfg classes have different layout");
outHeight = N *inHeight; xbrz_old::scale(factor, src, trg, srcWidth, srcHeight, reinterpret_cast<const xbrz_old::ScalerCfg&>(cfg), yFirst, yLast);
unsigned char * newBuffer = new unsigned char[outWidth*outHeight*4];
xbrzFunction(N, reinterpret_cast<uint32_t*>(inputBuffer), reinterpret_cast<uint32_t*>(newBuffer), inWidth, inHeight, xbrz_old::ScalerCfg(), 0, std::numeric_limits<int>::max());
delete[] inputBuffer;
return newBuffer;
} }
@ -372,7 +411,7 @@ unsigned char *gl_CreateUpsampledTextureBuffer ( const FTexture *inputTexture, u
case 13: case 13:
case 14: case 14:
case 15: case 15:
return xbrzoldHelper(xbrz_old::scale, type - 11, inputBuffer, inWidth, inHeight, outWidth, outHeight ); return xbrzHelper(xbrzOldScale, type - 11, inputBuffer, inWidth, inHeight, outWidth, outHeight );
} }
} }

View file

@ -167,7 +167,7 @@ void gl_GenerateGlobalBrightmapFromColormap()
// component becomes one. // component becomes one.
// //
//=========================================================================== //===========================================================================
PalEntry averageColor(const DWORD *data, int size, int maxout) static PalEntry averageColor(const DWORD *data, int size, int maxout)
{ {
int i; int i;
unsigned int r, g, b; unsigned int r, g, b;
@ -216,10 +216,7 @@ FTexture::MiscGLInfo::MiscGLInfo() throw()
GlowColor = 0; GlowColor = 0;
GlowHeight = 128; GlowHeight = 128;
bSkybox = false; bSkybox = false;
FloorSkyColor = 0;
CeilingSkyColor = 0;
bFullbright = false; bFullbright = false;
bSkyColorDone = false;
bBrightmapChecked = false; bBrightmapChecked = false;
bDisableFullbright = false; bDisableFullbright = false;
bNoFilter = false; bNoFilter = false;
@ -326,38 +323,6 @@ void FTexture::GetGlowColor(float *data)
data[2]=gl_info.GlowColor.b/255.0f; data[2]=gl_info.GlowColor.b/255.0f;
} }
//===========================================================================
//
// Gets the average color of a texture for use as a sky cap color
//
//===========================================================================
PalEntry FTexture::GetSkyCapColor(bool bottom)
{
PalEntry col;
int w;
int h;
if (!gl_info.bSkyColorDone)
{
gl_info.bSkyColorDone = true;
unsigned char *buffer = GLRenderer->GetTextureBuffer(this, w, h);
if (buffer)
{
gl_info.CeilingSkyColor = averageColor((DWORD *) buffer, w * MIN(30, h), 0);
if (h>30)
{
gl_info.FloorSkyColor = averageColor(((DWORD *) buffer)+(h-30)*w, w * 30, 0);
}
else gl_info.FloorSkyColor = gl_info.CeilingSkyColor;
delete[] buffer;
}
}
return bottom? gl_info.FloorSkyColor : gl_info.CeilingSkyColor;
}
//=========================================================================== //===========================================================================
// //
// Finds gaps in the texture which can be skipped by the renderer // Finds gaps in the texture which can be skipped by the renderer

View file

@ -24,7 +24,6 @@ protected:
void gl_GenerateGlobalBrightmapFromColormap(); void gl_GenerateGlobalBrightmapFromColormap();
PalEntry averageColor(const DWORD *data, int size, int maxout);

View file

@ -123,7 +123,8 @@ int M_ReadFile (char const *name, BYTE **buffer)
handle = open (name, O_RDONLY | O_BINARY, 0666); handle = open (name, O_RDONLY | O_BINARY, 0666);
if (handle == -1) if (handle == -1)
I_Error ("Couldn't read file %s", name); I_Error ("Couldn't read file %s", name);
if (fstat (handle,&fileinfo) == -1) // [BL] Use stat instead of fstat for v140_xp hack
if (stat (name,&fileinfo) == -1)
I_Error ("Couldn't read file %s", name); I_Error ("Couldn't read file %s", name);
length = fileinfo.st_size; length = fileinfo.st_size;
buf = new BYTE[length]; buf = new BYTE[length];
@ -149,7 +150,8 @@ int M_ReadFileMalloc (char const *name, BYTE **buffer)
handle = open (name, O_RDONLY | O_BINARY, 0666); handle = open (name, O_RDONLY | O_BINARY, 0666);
if (handle == -1) if (handle == -1)
I_Error ("Couldn't read file %s", name); I_Error ("Couldn't read file %s", name);
if (fstat (handle,&fileinfo) == -1) // [BL] Use stat instead of fstat for v140_xp hack
if (stat (name,&fileinfo) == -1)
I_Error ("Couldn't read file %s", name); I_Error ("Couldn't read file %s", name);
length = fileinfo.st_size; length = fileinfo.st_size;
buf = (BYTE*)M_Malloc(length); buf = (BYTE*)M_Malloc(length);

View file

@ -331,6 +331,10 @@ void FRandom::StaticReadRNGState(FSerializer &arc)
FRandom *rng; FRandom *rng;
arc("rngseed", rngseed); arc("rngseed", rngseed);
// Call StaticClearRandom in order to ensure that SFMT is initialized
FRandom::StaticClearRandom ();
if (arc.BeginArray("rngs")) if (arc.BeginArray("rngs"))
{ {
int count = arc.ArraySize(); int count = arc.ArraySize();

View file

@ -584,6 +584,7 @@ xx(Dialog)
xx(Ifitem) xx(Ifitem)
xx(Choice) xx(Choice)
xx(Link) xx(Link)
xx(Goodbye)
// Special menus // Special menus
xx(Mainmenu) xx(Mainmenu)

View file

@ -1616,7 +1616,7 @@ void FBehavior::StaticSerializeModuleStates (FSerializer &arc)
{ {
if (arc.isReading()) if (arc.isReading())
{ {
int modnum = arc.ArraySize(); auto modnum = arc.ArraySize();
if (modnum != StaticModules.Size()) if (modnum != StaticModules.Size())
{ {
I_Error("Level was saved with a different number of ACS modules. (Have %d, save has %d)", StaticModules.Size(), modnum); I_Error("Level was saved with a different number of ACS modules. (Have %d, save has %d)", StaticModules.Size(), modnum);
@ -2933,7 +2933,7 @@ void DACSThinker::Serialize(FSerializer &arc)
if (arc.BeginArray("runningscripts")) if (arc.BeginArray("runningscripts"))
{ {
auto cnt = arc.ArraySize(); auto cnt = arc.ArraySize();
for (int i = 0; i < cnt; i++) for (unsigned i = 0; i < cnt; i++)
{ {
SavingRunningscript srs; SavingRunningscript srs;
arc(nullptr, srs); arc(nullptr, srs);
@ -5821,43 +5821,54 @@ doplaysound: if (funcIndex == ACSF_PlayActorSound)
// [ZK] A_Warp in ACS // [ZK] A_Warp in ACS
case ACSF_Warp: case ACSF_Warp:
{ {
int tid_dest = args[0]; if (nullptr == activator)
int xofs = args[1];
int yofs = args[2];
int zofs = args[3];
int angle = args[4];
int flags = args[5];
const char *statename = argCount > 6 ? FBehavior::StaticLookupString(args[6]) : "";
bool exact = argCount > 7 ? !!args[7] : false;
int heightoffset = argCount > 8 ? args[8] : 0;
int radiusoffset = argCount > 9 ? args[9] : 0;
int pitch = argCount > 10 ? args[10] : 0;
FState *state = argCount > 6 ? activator->GetClass()->FindStateByString(statename, exact) : 0;
AActor *reference;
if((flags & WARPF_USEPTR) && tid_dest != AAPTR_DEFAULT)
{ {
reference = COPY_AAPTR(activator, tid_dest);
}
else
{
reference = SingleActorFromTID(tid_dest, activator);
}
// If there is no activator or actor to warp to, fail.
if (activator == NULL || !reference)
return false; return false;
if (P_Thing_Warp(activator, reference, ACSToDouble(xofs), ACSToDouble(yofs), ACSToDouble(zofs), ACSToAngle(angle), flags, ACSToDouble(heightoffset), ACSToDouble(radiusoffset), ACSToAngle(pitch)))
{
if (state && argCount > 6)
{
activator->SetState(state);
}
return true;
} }
return false;
const int dest = args[0];
const int flags = args[5];
AActor* const reference = ((flags & WARPF_USEPTR) && (AAPTR_DEFAULT != dest))
? COPY_AAPTR(activator, dest)
: SingleActorFromTID(dest, activator);
if (nullptr == reference)
{
// there is no actor to warp to
return false;
}
const double xofs = ACSToDouble(args[1]);
const double yofs = ACSToDouble(args[2]);
const double zofs = ACSToDouble(args[3]);
const DAngle angle = ACSToAngle(args[4]);
const double heightoffset = argCount > 8 ? ACSToDouble(args[8]) : 0.0;
const double radiusoffset = argCount > 9 ? ACSToDouble(args[9]) : 0.0;
const DAngle pitch = ACSToAngle(argCount > 10 ? args[10] : 0);
if (!P_Thing_Warp(activator, reference, xofs, yofs, zofs, angle, flags, heightoffset, radiusoffset, pitch))
{
return false;
}
if (argCount > 6)
{
const char* const statename = FBehavior::StaticLookupString(args[6]);
if (nullptr != statename)
{
const bool exact = argCount > 7 && !!args[7];
FState* const state = activator->GetClass()->FindStateByString(statename, exact);
if (nullptr != state)
{
activator->SetState(state);
}
}
}
return true;
} }
case ACSF_GetMaxInventory: case ACSF_GetMaxInventory:
actor = SingleActorFromTID(args[0], activator); actor = SingleActorFromTID(args[0], activator);

View file

@ -2622,6 +2622,92 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_GiveToSiblings)
ACTION_RETURN_INT(count); ACTION_RETURN_INT(count);
} }
//===========================================================================
//
// A_SetInventory
//
//===========================================================================
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetInventory)
{
PARAM_ACTION_PROLOGUE;
PARAM_CLASS(itemtype, AInventory);
PARAM_INT(amount);
PARAM_INT_OPT(ptr) { ptr = AAPTR_DEFAULT; }
PARAM_BOOL_OPT(beyondMax) { beyondMax = false; }
bool res = false;
if (itemtype == nullptr)
{
ACTION_RETURN_BOOL(false);
}
AActor *mobj = COPY_AAPTR(self, ptr);
if (mobj == nullptr)
{
ACTION_RETURN_BOOL(false);
}
AInventory *item = mobj->FindInventory(itemtype);
if (item != nullptr)
{
// A_SetInventory sets the absolute amount.
// Subtract or set the appropriate amount as necessary.
if (amount == item->Amount)
{
// Nothing was changed.
ACTION_RETURN_BOOL(false);
}
else if (amount <= 0)
{
//Remove it all.
res = (mobj->TakeInventory(itemtype, item->Amount, true, false));
ACTION_RETURN_BOOL(res);
}
else if (amount < item->Amount)
{
int amt = abs(item->Amount - amount);
res = (mobj->TakeInventory(itemtype, amt, true, false));
ACTION_RETURN_BOOL(res);
}
else
{
item->Amount = (beyondMax ? amount : clamp(amount, 0, item->MaxAmount));
ACTION_RETURN_BOOL(true);
}
}
else
{
if (amount <= 0)
{
ACTION_RETURN_BOOL(false);
}
item = static_cast<AInventory *>(Spawn(itemtype));
if (item == nullptr)
{
ACTION_RETURN_BOOL(false);
}
else
{
item->Amount = amount;
item->flags |= MF_DROPPED;
item->ItemFlags |= IF_IGNORESKILL;
item->ClearCounters();
if (!item->CallTryPickup(mobj))
{
item->Destroy();
ACTION_RETURN_BOOL(false);
}
ACTION_RETURN_BOOL(true);
}
}
ACTION_RETURN_BOOL(false);
}
//=========================================================================== //===========================================================================
// //
// A_TakeInventory // A_TakeInventory

View file

@ -184,7 +184,7 @@ void DCeiling::Tick ()
case DCeiling::ceilLowerAndCrush: case DCeiling::ceilLowerAndCrush:
if (m_CrushMode == ECrushMode::crushSlowdown) if (m_CrushMode == ECrushMode::crushSlowdown)
m_Speed = 1. / 8; m_Speed = 1. / 8;
break; break;
default: default:
break; break;
@ -214,6 +214,12 @@ DCeiling::DCeiling (sector_t *sec, double speed1, double speed2, int silent)
m_Speed = m_Speed1 = speed1; m_Speed = m_Speed1 = speed1;
m_Speed2 = speed2; m_Speed2 = speed2;
m_Silent = silent; m_Silent = silent;
m_BottomHeight = 0;
m_TopHeight = 0;
m_Direction = 0;
m_Texture = FNullTextureID();
m_Tag = 0;
m_OldDirection = 0;
} }
//============================================================================ //============================================================================

View file

@ -556,6 +556,7 @@ FStrifeDialogueNode::~FStrifeDialogueNode ()
{ {
if (SpeakerName != NULL) delete[] SpeakerName; if (SpeakerName != NULL) delete[] SpeakerName;
if (Dialogue != NULL) delete[] Dialogue; if (Dialogue != NULL) delete[] Dialogue;
if (Goodbye != nullptr) delete[] Goodbye;
FStrifeDialogueReply *tokill = Children; FStrifeDialogueReply *tokill = Children;
while (tokill != NULL) while (tokill != NULL)
{ {
@ -743,10 +744,25 @@ public:
++i; ++i;
V_FreeBrokenLines (ReplyLines); V_FreeBrokenLines (ReplyLines);
} }
char goodbye[25]; const char *goodbyestr = CurNode->Goodbye;
mysnprintf(goodbye, countof(goodbye), "TXT_RANDOMGOODBYE_%d", 1+(pr_randomspeech() % NUM_RANDOM_GOODBYES)); if (goodbyestr == nullptr)
const char *goodbyestr = GStrings[goodbye]; {
if (goodbyestr == NULL) goodbyestr = "Bye."; char goodbye[25];
mysnprintf(goodbye, countof(goodbye), "TXT_RANDOMGOODBYE_%d", 1 + (pr_randomspeech() % NUM_RANDOM_GOODBYES));
goodbyestr = GStrings[goodbye];
}
else if (strncmp(goodbyestr, "RANDOM_", 7) == 0)
{
FString byetext;
byetext.Format("TXT_%s_%02d", goodbyestr, 1 + (pr_randomspeech() % NUM_RANDOM_LINES));
goodbyestr = GStrings[byetext];
}
else if (goodbyestr[0] == '$')
{
goodbyestr = GStrings(goodbyestr + 1);
}
if (goodbyestr == nullptr) goodbyestr = "Bye.";
mResponses.Push(mResponseLines.Size()); mResponses.Push(mResponseLines.Size());
mResponseLines.Push(FString(goodbyestr)); mResponseLines.Push(FString(goodbyestr));

View file

@ -30,6 +30,7 @@ struct FStrifeDialogueNode
FSoundID SpeakerVoice; FSoundID SpeakerVoice;
FTextureID Backdrop; FTextureID Backdrop;
char *Dialogue; char *Dialogue;
char *Goodbye = nullptr; // must init to null for binary scripts to work as intended
FStrifeDialogueReply *Children; FStrifeDialogueReply *Children;
}; };

View file

@ -634,6 +634,7 @@ void AActor::RemoveInventory(AInventory *item)
bool AActor::TakeInventory(PClassActor *itemclass, int amount, bool fromdecorate, bool notakeinfinite) bool AActor::TakeInventory(PClassActor *itemclass, int amount, bool fromdecorate, bool notakeinfinite)
{ {
amount = abs(amount);
AInventory *item = FindInventory(itemclass); AInventory *item = FindInventory(itemclass);
if (item == NULL) if (item == NULL)
@ -666,6 +667,7 @@ bool AActor::TakeInventory(PClassActor *itemclass, int amount, bool fromdecorate
item->IsKindOf(RUNTIME_CLASS(AAmmo))) item->IsKindOf(RUNTIME_CLASS(AAmmo)))
{ {
// Nothing to do here, except maybe res = false;? Would it make sense? // Nothing to do here, except maybe res = false;? Would it make sense?
result = false;
} }
else if (!amount || amount>=item->Amount) else if (!amount || amount>=item->Amount)
{ {
@ -685,11 +687,30 @@ bool AActor::TakeInventory(PClassActor *itemclass, int amount, bool fromdecorate
void AActor::DestroyAllInventory () void AActor::DestroyAllInventory ()
{ {
while (Inventory != NULL) AInventory *inv = Inventory;
if (inv != nullptr)
{ {
AInventory *item = Inventory; TArray<AInventory *> toDelete;
item->Destroy ();
assert (item != Inventory); // Delete the list in a two stage approach.
// This is necessary because an item may destroy another item (e.g. sister weapons)
// which would break the list and leave parts of it undestroyed, maybe doing bad things later.
while (inv != nullptr)
{
toDelete.Push(inv);
AInventory *item = inv->Inventory;
inv->Inventory = nullptr;
inv->Owner = nullptr;
inv = item;
}
for (auto p : toDelete)
{
// the item may already have been deleted by another one, so check this here to avoid problems.
if (!(p->ObjectFlags & OF_EuthanizeMe))
{
p->Destroy();
}
}
} }
} }
@ -3778,6 +3799,8 @@ void AActor::Tick ()
else if (Z() <= floorz) else if (Z() <= floorz)
{ {
Crash(); Crash();
if (ObjectFlags & OF_EuthanizeMe)
return; // actor was destroyed
} }
CheckPortalTransition(true); CheckPortalTransition(true);

View file

@ -1006,7 +1006,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_OverlayOffset)
PARAM_FLOAT_OPT(wx) { wx = 0.; } PARAM_FLOAT_OPT(wx) { wx = 0.; }
PARAM_FLOAT_OPT(wy) { wy = 32.; } PARAM_FLOAT_OPT(wy) { wy = 32.; }
PARAM_INT_OPT(flags) { flags = 0; } PARAM_INT_OPT(flags) { flags = 0; }
A_OverlayOffset(self, layer, wx, wy, flags); A_OverlayOffset(self, ((layer != 0) ? layer : stateinfo->mPSPIndex), wx, wy, flags);
return 0; return 0;
} }
@ -1033,10 +1033,10 @@ DEFINE_ACTION_FUNCTION(AActor, A_OverlayFlags)
PARAM_INT(flags); PARAM_INT(flags);
PARAM_BOOL(set); PARAM_BOOL(set);
if (self->player == nullptr) if (!ACTION_CALL_FROM_PSPRITE())
return 0; return 0;
DPSprite *pspr = self->player->FindPSprite(layer); DPSprite *pspr = self->player->FindPSprite(((layer != 0) ? layer : stateinfo->mPSPIndex));
if (pspr == nullptr) if (pspr == nullptr)
return 0; return 0;
@ -1049,6 +1049,52 @@ DEFINE_ACTION_FUNCTION(AActor, A_OverlayFlags)
return 0; return 0;
} }
//---------------------------------------------------------------------------
//
// PROC OverlayX/Y
// Action function to return the X/Y of an overlay.
//---------------------------------------------------------------------------
static double GetOverlayPosition(AActor *self, int layer, bool gety)
{
if (layer)
{
DPSprite *pspr = self->player->FindPSprite(layer);
if (pspr != nullptr)
{
return gety ? (pspr->y) : (pspr->x);
}
}
return 0.;
}
DEFINE_ACTION_FUNCTION(AActor, OverlayX)
{
PARAM_ACTION_PROLOGUE;
PARAM_INT_OPT(layer) { layer = 0; }
if (ACTION_CALL_FROM_PSPRITE())
{
double res = GetOverlayPosition(self, ((layer != 0) ? layer : stateinfo->mPSPIndex), false);
ACTION_RETURN_FLOAT(res);
}
ACTION_RETURN_FLOAT(0.);
}
DEFINE_ACTION_FUNCTION(AActor, OverlayY)
{
PARAM_ACTION_PROLOGUE;
PARAM_INT_OPT(layer) { layer = 0; }
if (ACTION_CALL_FROM_PSPRITE())
{
double res = GetOverlayPosition(self, ((layer != 0) ? layer : stateinfo->mPSPIndex), true);
ACTION_RETURN_FLOAT(res);
}
ACTION_RETURN_FLOAT(0.);
}
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
// //
// PROC OverlayID // PROC OverlayID

View file

@ -57,6 +57,7 @@ enum PSPFlags
PSPF_ADDBOB = 1 << 1, PSPF_ADDBOB = 1 << 1,
PSPF_POWDOUBLE = 1 << 2, PSPF_POWDOUBLE = 1 << 2,
PSPF_CVARFAST = 1 << 3, PSPF_CVARFAST = 1 << 3,
PSPF_FLIP = 1 << 6,
}; };
class DPSprite : public DObject class DPSprite : public DObject

View file

@ -890,10 +890,10 @@ void G_SerializeLevel(FSerializer &arc, bool hubload)
// deep down in the deserializer or just a crash if the few insufficient safeguards were not triggered. // deep down in the deserializer or just a crash if the few insufficient safeguards were not triggered.
BYTE chk[16] = { 0 }; BYTE chk[16] = { 0 };
arc.Array("checksum", chk, 16); arc.Array("checksum", chk, 16);
if (arc.GetSize("linedefs") != numlines || if (arc.GetSize("linedefs") != (unsigned)numlines ||
arc.GetSize("sidedefs") != numsides || arc.GetSize("sidedefs") != (unsigned)numsides ||
arc.GetSize("sectors") != numsectors || arc.GetSize("sectors") != (unsigned)numsectors ||
arc.GetSize("polyobjs") != po_NumPolyobjs || arc.GetSize("polyobjs") != (unsigned)po_NumPolyobjs ||
memcmp(chk, level.md5, 16)) memcmp(chk, level.md5, 16))
{ {
I_Error("Savegame is from a different level"); I_Error("Savegame is from a different level");

View file

@ -286,6 +286,7 @@ class USDFParser : public UDMFParserBase
FString SpeakerName; FString SpeakerName;
FString Dialogue; FString Dialogue;
FString Goodbye;
while (!sc.CheckToken('}')) while (!sc.CheckToken('}'))
{ {
@ -331,7 +332,9 @@ class USDFParser : public UDMFParserBase
node->ItemCheckNode = CheckInt(key); node->ItemCheckNode = CheckInt(key);
break; break;
case NAME_Goodbye:
Goodbye = CheckString(key);
break;
} }
} }
else else
@ -354,6 +357,7 @@ class USDFParser : public UDMFParserBase
} }
node->SpeakerName = ncopystring(SpeakerName); node->SpeakerName = ncopystring(SpeakerName);
node->Dialogue = ncopystring(Dialogue); node->Dialogue = ncopystring(Dialogue);
node->Goodbye = ncopystring(Goodbye);
return true; return true;
} }

View file

@ -265,7 +265,6 @@ void DMovePoly::Serialize(FSerializer &arc)
{ {
Super::Serialize (arc); Super::Serialize (arc);
arc("angle", m_Angle) arc("angle", m_Angle)
("speed", m_Speed);
("speedv", m_Speedv); ("speedv", m_Speedv);
} }

View file

@ -130,6 +130,53 @@ void Mac_I_FatalError(const char* const message)
} }
static void I_DetectOS()
{
SInt32 majorVersion = 0;
Gestalt(gestaltSystemVersionMajor, &majorVersion);
SInt32 minorVersion = 0;
Gestalt(gestaltSystemVersionMinor, &minorVersion);
SInt32 bugFixVersion = 0;
Gestalt(gestaltSystemVersionBugFix, &bugFixVersion);
const char* name = "Unknown version";
if (10 == majorVersion) switch (minorVersion)
{
case 4: name = "Mac OS X Tiger"; break;
case 5: name = "Mac OS X Leopard"; break;
case 6: name = "Mac OS X Snow Leopard"; break;
case 7: name = "Mac OS X Lion"; break;
case 8: name = "OS X Mountain Lion"; break;
case 9: name = "OS X Mavericks"; break;
case 10: name = "OS X Yosemite"; break;
case 11: name = "OS X El Capitan"; break;
case 12: name = "macOS Sierra"; break;
}
char release[16] = {};
size_t size = sizeof release - 1;
sysctlbyname("kern.osversion", release, &size, nullptr, 0);
const char* const architecture =
#ifdef __i386__
"32-bit Intel";
#elif defined __x86_64__
"64-bit Intel";
#elif defined __ppc__
"32-bit PowerPC";
#elif defined __ppc64__
"64-bit PowerPC";
#else
"Unknown";
#endif
Printf("OS: %s %d.%d.%d (%s) %s\n", name, majorVersion, minorVersion, bugFixVersion, release, architecture);
}
DArgs* Args; // command line arguments DArgs* Args; // command line arguments
@ -165,6 +212,8 @@ void OriginalMainTry(int argc, char** argv)
progdir += "/"; progdir += "/";
C_InitConsole(80 * 8, 25 * 8, false); C_InitConsole(80 * 8, 25 * 8, false);
I_DetectOS();
D_DoomMain(); D_DoomMain();
} }

View file

@ -1216,6 +1216,10 @@ int R_FindCustomTranslation(const char *name)
{ {
return TRANSLATION(TRANSLATION_Standard, 7); return TRANSLATION(TRANSLATION_Standard, 7);
} }
else if (!stricmp(name, "None"))
{
return 0;
}
int *t = customTranslationMap.CheckKey(FName(name, true)); int *t = customTranslationMap.CheckKey(FName(name, true));
return (t != nullptr)? *t : -1; return (t != nullptr)? *t : -1;
} }

View file

@ -110,6 +110,8 @@ DWORD vplce[4];
DWORD vince[4]; DWORD vince[4];
BYTE* palookupoffse[4]; BYTE* palookupoffse[4];
const BYTE* bufplce[4]; const BYTE* bufplce[4];
const BYTE* bufplce2[4];
uint32_t bufheight[4];
// just for profiling // just for profiling
int dccount; int dccount;
@ -2142,6 +2144,245 @@ void tmvline4_revsubclamp ()
} while (--count); } while (--count);
} }
void R_DrawSingleSkyCol1(uint32_t solid_top, uint32_t solid_bottom)
{
uint8_t *dest = dc_dest;
int count = dc_count;
int pitch = dc_pitch;
const uint8_t *source0 = bufplce[0];
int textureheight0 = bufheight[0];
int32_t frac = vplce[0];
int32_t fracstep = vince[0];
int start_fade = 2; // How fast it should fade out
int solid_top_r = RPART(solid_top);
int solid_top_g = GPART(solid_top);
int solid_top_b = BPART(solid_top);
int solid_bottom_r = RPART(solid_bottom);
int solid_bottom_g = GPART(solid_bottom);
int solid_bottom_b = BPART(solid_bottom);
for (int index = 0; index < count; index++)
{
uint32_t sample_index = (((((uint32_t)frac) << 8) >> FRACBITS) * textureheight0) >> FRACBITS;
uint8_t fg = source0[sample_index];
int alpha_top = MAX(MIN(frac >> (16 - start_fade), 256), 0);
int alpha_bottom = MAX(MIN(((2 << 24) - frac) >> (16 - start_fade), 256), 0);
if (alpha_top == 256 && alpha_bottom == 256)
{
*dest = fg;
}
else
{
int inv_alpha_top = 256 - alpha_top;
int inv_alpha_bottom = 256 - alpha_bottom;
const auto &c = GPalette.BaseColors[fg];
int c_red = c.r;
int c_green = c.g;
int c_blue = c.b;
c_red = (c_red * alpha_top + solid_top_r * inv_alpha_top) >> 8;
c_green = (c_green * alpha_top + solid_top_g * inv_alpha_top) >> 8;
c_blue = (c_blue * alpha_top + solid_top_b * inv_alpha_top) >> 8;
c_red = (c_red * alpha_bottom + solid_bottom_r * inv_alpha_bottom) >> 8;
c_green = (c_green * alpha_bottom + solid_bottom_g * inv_alpha_bottom) >> 8;
c_blue = (c_blue * alpha_bottom + solid_bottom_b * inv_alpha_bottom) >> 8;
*dest = RGB32k.RGB[(c_red >> 3)][(c_green >> 3)][(c_blue >> 3)];
}
frac += fracstep;
dest += pitch;
}
}
void R_DrawSingleSkyCol4(uint32_t solid_top, uint32_t solid_bottom)
{
for (int col = 0; col < 4; col++)
{
uint8_t *dest = dc_dest + col;
int count = dc_count;
int pitch = dc_pitch;
const uint8_t *source0 = bufplce[col];
int textureheight0 = bufheight[0];
int32_t frac = vplce[col];
int32_t fracstep = vince[col];
int start_fade = 2; // How fast it should fade out
int solid_top_r = RPART(solid_top);
int solid_top_g = GPART(solid_top);
int solid_top_b = BPART(solid_top);
int solid_bottom_r = RPART(solid_bottom);
int solid_bottom_g = GPART(solid_bottom);
int solid_bottom_b = BPART(solid_bottom);
for (int index = 0; index < count; index++)
{
uint32_t sample_index = (((((uint32_t)frac) << 8) >> FRACBITS) * textureheight0) >> FRACBITS;
uint8_t fg = source0[sample_index];
int alpha_top = MAX(MIN(frac >> (16 - start_fade), 256), 0);
int alpha_bottom = MAX(MIN(((2 << 24) - frac) >> (16 - start_fade), 256), 0);
if (alpha_top == 256 && alpha_bottom == 256)
{
*dest = fg;
}
else
{
int inv_alpha_top = 256 - alpha_top;
int inv_alpha_bottom = 256 - alpha_bottom;
const auto &c = GPalette.BaseColors[fg];
int c_red = c.r;
int c_green = c.g;
int c_blue = c.b;
c_red = (c_red * alpha_top + solid_top_r * inv_alpha_top) >> 8;
c_green = (c_green * alpha_top + solid_top_g * inv_alpha_top) >> 8;
c_blue = (c_blue * alpha_top + solid_top_b * inv_alpha_top) >> 8;
c_red = (c_red * alpha_bottom + solid_bottom_r * inv_alpha_bottom) >> 8;
c_green = (c_green * alpha_bottom + solid_bottom_g * inv_alpha_bottom) >> 8;
c_blue = (c_blue * alpha_bottom + solid_bottom_b * inv_alpha_bottom) >> 8;
*dest = RGB32k.RGB[(c_red >> 3)][(c_green >> 3)][(c_blue >> 3)];
}
frac += fracstep;
dest += pitch;
}
}
}
void R_DrawDoubleSkyCol1(uint32_t solid_top, uint32_t solid_bottom)
{
uint8_t *dest = dc_dest;
int count = dc_count;
int pitch = dc_pitch;
const uint8_t *source0 = bufplce[0];
const uint8_t *source1 = bufplce2[0];
int textureheight0 = bufheight[0];
uint32_t maxtextureheight1 = bufheight[1] - 1;
int32_t frac = vplce[0];
int32_t fracstep = vince[0];
int start_fade = 2; // How fast it should fade out
int solid_top_r = RPART(solid_top);
int solid_top_g = GPART(solid_top);
int solid_top_b = BPART(solid_top);
int solid_bottom_r = RPART(solid_bottom);
int solid_bottom_g = GPART(solid_bottom);
int solid_bottom_b = BPART(solid_bottom);
for (int index = 0; index < count; index++)
{
uint32_t sample_index = (((((uint32_t)frac) << 8) >> FRACBITS) * textureheight0) >> FRACBITS;
uint8_t fg = source0[sample_index];
if (fg == 0)
{
uint32_t sample_index2 = MIN(sample_index, maxtextureheight1);
fg = source1[sample_index2];
}
int alpha_top = MAX(MIN(frac >> (16 - start_fade), 256), 0);
int alpha_bottom = MAX(MIN(((2 << 24) - frac) >> (16 - start_fade), 256), 0);
if (alpha_top == 256 && alpha_bottom == 256)
{
*dest = fg;
}
else
{
int inv_alpha_top = 256 - alpha_top;
int inv_alpha_bottom = 256 - alpha_bottom;
const auto &c = GPalette.BaseColors[fg];
int c_red = c.r;
int c_green = c.g;
int c_blue = c.b;
c_red = (c_red * alpha_top + solid_top_r * inv_alpha_top) >> 8;
c_green = (c_green * alpha_top + solid_top_g * inv_alpha_top) >> 8;
c_blue = (c_blue * alpha_top + solid_top_b * inv_alpha_top) >> 8;
c_red = (c_red * alpha_bottom + solid_bottom_r * inv_alpha_bottom) >> 8;
c_green = (c_green * alpha_bottom + solid_bottom_g * inv_alpha_bottom) >> 8;
c_blue = (c_blue * alpha_bottom + solid_bottom_b * inv_alpha_bottom) >> 8;
*dest = RGB32k.RGB[(c_red >> 3)][(c_green >> 3)][(c_blue >> 3)];
}
frac += fracstep;
dest += pitch;
}
}
void R_DrawDoubleSkyCol4(uint32_t solid_top, uint32_t solid_bottom)
{
for (int col = 0; col < 4; col++)
{
uint8_t *dest = dc_dest + col;
int count = dc_count;
int pitch = dc_pitch;
const uint8_t *source0 = bufplce[col];
const uint8_t *source1 = bufplce2[col];
int textureheight0 = bufheight[0];
uint32_t maxtextureheight1 = bufheight[1] - 1;
int32_t frac = vplce[col];
int32_t fracstep = vince[col];
int start_fade = 2; // How fast it should fade out
int solid_top_r = RPART(solid_top);
int solid_top_g = GPART(solid_top);
int solid_top_b = BPART(solid_top);
int solid_bottom_r = RPART(solid_bottom);
int solid_bottom_g = GPART(solid_bottom);
int solid_bottom_b = BPART(solid_bottom);
for (int index = 0; index < count; index++)
{
uint32_t sample_index = (((((uint32_t)frac) << 8) >> FRACBITS) * textureheight0) >> FRACBITS;
uint8_t fg = source0[sample_index];
if (fg == 0)
{
uint32_t sample_index2 = MIN(sample_index, maxtextureheight1);
fg = source1[sample_index2];
}
int alpha_top = MAX(MIN(frac >> (16 - start_fade), 256), 0);
int alpha_bottom = MAX(MIN(((2 << 24) - frac) >> (16 - start_fade), 256), 0);
if (alpha_top == 256 && alpha_bottom == 256)
{
*dest = fg;
}
else
{
int inv_alpha_top = 256 - alpha_top;
int inv_alpha_bottom = 256 - alpha_bottom;
const auto &c = GPalette.BaseColors[fg];
int c_red = c.r;
int c_green = c.g;
int c_blue = c.b;
c_red = (c_red * alpha_top + solid_top_r * inv_alpha_top) >> 8;
c_green = (c_green * alpha_top + solid_top_g * inv_alpha_top) >> 8;
c_blue = (c_blue * alpha_top + solid_top_b * inv_alpha_top) >> 8;
c_red = (c_red * alpha_bottom + solid_bottom_r * inv_alpha_bottom) >> 8;
c_green = (c_green * alpha_bottom + solid_bottom_g * inv_alpha_bottom) >> 8;
c_blue = (c_blue * alpha_bottom + solid_bottom_b * inv_alpha_bottom) >> 8;
*dest = RGB32k.RGB[(c_red >> 3)][(c_green >> 3)][(c_blue >> 3)];
}
frac += fracstep;
dest += pitch;
}
}
}
//========================================================================== //==========================================================================
// //

View file

@ -51,6 +51,8 @@ extern "C" DWORD vplce[4];
extern "C" DWORD vince[4]; extern "C" DWORD vince[4];
extern "C" BYTE* palookupoffse[4]; extern "C" BYTE* palookupoffse[4];
extern "C" const BYTE* bufplce[4]; extern "C" const BYTE* bufplce[4];
extern "C" const BYTE* bufplce2[4];
extern "C" uint32_t bufheight[4];
// [RH] Temporary buffer for column drawing // [RH] Temporary buffer for column drawing
extern "C" BYTE *dc_temp; extern "C" BYTE *dc_temp;
@ -293,4 +295,9 @@ void maskwallscan (int x1, int x2, short *uwal, short *dwal, float *swal, fixed_
// transmaskwallscan is like maskwallscan, but it can also blend to the background // transmaskwallscan is like maskwallscan, but it can also blend to the background
void transmaskwallscan (int x1, int x2, short *uwal, short *dwal, float *swal, fixed_t *lwal, double yrepeat, const BYTE *(*getcol)(FTexture *tex, int col)=R_GetColumn); void transmaskwallscan (int x1, int x2, short *uwal, short *dwal, float *swal, fixed_t *lwal, double yrepeat, const BYTE *(*getcol)(FTexture *tex, int col)=R_GetColumn);
void R_DrawSingleSkyCol1(uint32_t solid_top, uint32_t solid_bottom);
void R_DrawSingleSkyCol4(uint32_t solid_top, uint32_t solid_bottom);
void R_DrawDoubleSkyCol1(uint32_t solid_top, uint32_t solid_bottom);
void R_DrawDoubleSkyCol4(uint32_t solid_top, uint32_t solid_bottom);
#endif #endif

View file

@ -63,6 +63,8 @@
#pragma warning(disable:4244) #pragma warning(disable:4244)
#endif #endif
EXTERN_CVAR(Int, r_skymode)
//EXTERN_CVAR (Int, tx) //EXTERN_CVAR (Int, tx)
//EXTERN_CVAR (Int, ty) //EXTERN_CVAR (Int, ty)
@ -898,8 +900,171 @@ static const BYTE *R_GetTwoSkyColumns (FTexture *fronttex, int x)
return composite; return composite;
} }
static void R_DrawSkyColumnStripe(int start_x, int y1, int y2, int columns, double scale, double texturemid, double yrepeat)
{
uint32_t height = frontskytex->GetHeight();
for (int i = 0; i < columns; i++)
{
double uv_stepd = skyiscale * yrepeat;
double v = (texturemid + uv_stepd * (y1 - CenterY + 0.5)) / height;
double v_step = uv_stepd / height;
uint32_t uv_pos = (uint32_t)(v * 0x01000000);
uint32_t uv_step = (uint32_t)(v_step * 0x01000000);
int x = start_x + i;
if (MirrorFlags & RF_XFLIP)
x = (viewwidth - x);
DWORD ang, angle1, angle2;
ang = (skyangle + xtoviewangle[x]) ^ skyflip;
angle1 = (DWORD)((UMulScale16(ang, frontcyl) + frontpos) >> FRACBITS);
angle2 = (DWORD)((UMulScale16(ang, backcyl) + backpos) >> FRACBITS);
bufplce[i] = (const BYTE *)frontskytex->GetColumn(angle1, nullptr);
bufplce2[i] = backskytex ? (const BYTE *)backskytex->GetColumn(angle2, nullptr) : nullptr;
vince[i] = uv_step;
vplce[i] = uv_pos;
}
bufheight[0] = height;
bufheight[1] = backskytex ? backskytex->GetHeight() : height;
dc_dest = (ylookup[y1] + start_x) + dc_destorg;
dc_count = y2 - y1;
uint32_t solid_top = frontskytex->GetSkyCapColor(false);
uint32_t solid_bottom = frontskytex->GetSkyCapColor(true);
if (columns == 4)
if (!backskytex)
R_DrawSingleSkyCol4(solid_top, solid_bottom);
else
R_DrawDoubleSkyCol4(solid_top, solid_bottom);
else
if (!backskytex)
R_DrawSingleSkyCol1(solid_top, solid_bottom);
else
R_DrawDoubleSkyCol1(solid_top, solid_bottom);
}
static void R_DrawSkyColumn(int start_x, int y1, int y2, int columns)
{
if (1 << frontskytex->HeightBits == frontskytex->GetHeight())
{
double texturemid = skymid * frontskytex->Scale.Y + frontskytex->GetHeight();
R_DrawSkyColumnStripe(start_x, y1, y2, columns, frontskytex->Scale.Y, texturemid, frontskytex->Scale.Y);
}
else
{
double yrepeat = frontskytex->Scale.Y;
double scale = frontskytex->Scale.Y * skyscale;
double iscale = 1 / scale;
short drawheight = short(frontskytex->GetHeight() * scale);
double topfrac = fmod(skymid + iscale * (1 - CenterY), frontskytex->GetHeight());
if (topfrac < 0) topfrac += frontskytex->GetHeight();
double texturemid = topfrac - iscale * (1 - CenterY);
R_DrawSkyColumnStripe(start_x, y1, y2, columns, scale, texturemid, yrepeat);
}
}
static void R_DrawCapSky(visplane_t *pl)
{
int x1 = pl->left;
int x2 = pl->right;
short *uwal = (short *)pl->top;
short *dwal = (short *)pl->bottom;
// Calculate where 4 column alignment begins and ends:
int aligned_x1 = clamp((x1 + 3) / 4 * 4, x1, x2);
int aligned_x2 = clamp(x2 / 4 * 4, x1, x2);
// First unaligned columns:
for (int x = x1; x < aligned_x1; x++)
{
int y1 = uwal[x];
int y2 = dwal[x];
if (y2 <= y1)
continue;
R_DrawSkyColumn(x, y1, y2, 1);
}
// The aligned columns
for (int x = aligned_x1; x < aligned_x2; x += 4)
{
// Find y1, y2, light and uv values for four columns:
int y1[4] = { uwal[x], uwal[x + 1], uwal[x + 2], uwal[x + 3] };
int y2[4] = { dwal[x], dwal[x + 1], dwal[x + 2], dwal[x + 3] };
// Figure out where we vertically can start and stop drawing 4 columns in one go
int middle_y1 = y1[0];
int middle_y2 = y2[0];
for (int i = 1; i < 4; i++)
{
middle_y1 = MAX(y1[i], middle_y1);
middle_y2 = MIN(y2[i], middle_y2);
}
// If we got an empty column in our set we cannot draw 4 columns in one go:
bool empty_column_in_set = false;
for (int i = 0; i < 4; i++)
{
if (y2[i] <= y1[i])
empty_column_in_set = true;
}
if (empty_column_in_set || middle_y2 <= middle_y1)
{
for (int i = 0; i < 4; i++)
{
if (y2[i] <= y1[i])
continue;
R_DrawSkyColumn(x + i, y1[i], y2[i], 1);
}
continue;
}
// Draw the first rows where not all 4 columns are active
for (int i = 0; i < 4; i++)
{
if (y1[i] < middle_y1)
R_DrawSkyColumn(x + i, y1[i], middle_y1, 1);
}
// Draw the area where all 4 columns are active
R_DrawSkyColumn(x, middle_y1, middle_y2, 4);
// Draw the last rows where not all 4 columns are active
for (int i = 0; i < 4; i++)
{
if (middle_y2 < y2[i])
R_DrawSkyColumn(x + i, middle_y2, y2[i], 1);
}
}
// The last unaligned columns:
for (int x = aligned_x2; x < x2; x++)
{
int y1 = uwal[x];
int y2 = dwal[x];
if (y2 <= y1)
continue;
R_DrawSkyColumn(x, y1, y2, 1);
}
}
static void R_DrawSky (visplane_t *pl) static void R_DrawSky (visplane_t *pl)
{ {
if (r_skymode == 2)
{
R_DrawCapSky(pl);
return;
}
int x; int x;
float swal; float swal;
@ -1314,7 +1479,7 @@ void R_DrawPortals ()
vissprite_p = firstvissprite; vissprite_p = firstvissprite;
visplaneStack.Pop (pl); visplaneStack.Pop (pl);
if (pl->Alpha > 0) if (pl->Alpha > 0 && pl->picnum != skyflatnum)
{ {
R_DrawSinglePlane (pl, pl->Alpha, pl->Additive, true); R_DrawSinglePlane (pl, pl->Alpha, pl->Additive, true);
} }

View file

@ -48,12 +48,19 @@ bool skystretch;
fixed_t sky1cyl, sky2cyl; fixed_t sky1cyl, sky2cyl;
double sky1pos, sky2pos; double sky1pos, sky2pos;
CUSTOM_CVAR(Int, testskyoffset, 0, 0)
{
R_InitSkyMap();
}
// [RH] Stretch sky texture if not taller than 128 pixels? // [RH] Stretch sky texture if not taller than 128 pixels?
CUSTOM_CVAR (Bool, r_stretchsky, true, CVAR_ARCHIVE) // Also now controls capped skies. 0 = normal, 1 = stretched, 2 = capped
CUSTOM_CVAR (Int, r_skymode, 2, CVAR_ARCHIVE)
{ {
R_InitSkyMap (); R_InitSkyMap ();
} }
int freelookviewheight; int freelookviewheight;
//========================================================================== //==========================================================================
@ -99,7 +106,7 @@ void R_InitSkyMap ()
skytexturemid = 0; skytexturemid = 0;
if (skyheight >= 128 && skyheight < 200) if (skyheight >= 128 && skyheight < 200)
{ {
skystretch = (r_stretchsky skystretch = (r_skymode == 1
&& skyheight >= 128 && skyheight >= 128
&& level.IsFreelookAllowed() && level.IsFreelookAllowed()
&& !(level.flags & LEVEL_FORCENOSKYSTRETCH)) ? 1 : 0; && !(level.flags & LEVEL_FORCENOSKYSTRETCH)) ? 1 : 0;
@ -107,7 +114,7 @@ void R_InitSkyMap ()
} }
else if (skyheight > 200) else if (skyheight > 200)
{ {
skytexturemid = (200 - skyheight) * skytex1->Scale.Y; skytexturemid = (200 - skyheight) * skytex1->Scale.Y +(r_skymode == 2 ? skytex1->SkyOffset + testskyoffset : 0);
} }
if (viewwidth != 0 && viewheight != 0) if (viewwidth != 0 && viewheight != 0)

View file

@ -408,7 +408,7 @@ void R_DrawVisSprite (vissprite_t *vis)
ESPSResult mode; ESPSResult mode;
bool ispsprite = (!vis->sector && vis->gpos != FVector3(0, 0, 0)); bool ispsprite = (!vis->sector && vis->gpos != FVector3(0, 0, 0));
if (vis->xscale == 0 || vis->yscale == 0) if (vis->xscale == 0 || fabs(vis->yscale) < (1.0f / 32000.0f))
{ // scaled to 0; can't see { // scaled to 0; can't see
return; return;
} }
@ -1404,7 +1404,7 @@ void R_DrawPSprite(DPSprite *pspr, AActor *owner, float bobx, float boby, double
vis->pic = tex; vis->pic = tex;
vis->ColormapNum = 0; vis->ColormapNum = 0;
if (flip) if (!(flip) != !(pspr->Flags & PSPF_FLIP))
{ {
vis->xiscale = -FLOAT2FIXED(pspritexiscale * tex->Scale.X); vis->xiscale = -FLOAT2FIXED(pspritexiscale * tex->Scale.X);
vis->startfrac = (tex->GetWidth() << FRACBITS) - 1; vis->startfrac = (tex->GetWidth() << FRACBITS) - 1;
@ -2097,7 +2097,7 @@ void R_DrawSprite (vissprite_t *spr)
{ // seen below floor: clip top { // seen below floor: clip top
if (!spr->bIsVoxel && h > topclip) if (!spr->bIsVoxel && h > topclip)
{ {
topclip = MIN<short> (h, viewheight); topclip = short(MIN(h, viewheight));
} }
hzt = MIN(hzt, hz); hzt = MIN(hzt, hz);
} }
@ -2127,7 +2127,7 @@ void R_DrawSprite (vissprite_t *spr)
{ // seen in the middle: clip top { // seen in the middle: clip top
if (!spr->bIsVoxel && h > topclip) if (!spr->bIsVoxel && h > topclip)
{ {
topclip = MIN<short> (h, viewheight); topclip = MIN(h, viewheight);
} }
hzt = MIN(hzt, hz); hzt = MIN(hzt, hz);
} }
@ -2181,7 +2181,7 @@ void R_DrawSprite (vissprite_t *spr)
int h = xs_RoundToInt(CenterY - (hz - ViewPos.Z) * scale); int h = xs_RoundToInt(CenterY - (hz - ViewPos.Z) * scale);
if (h > topclip) if (h > topclip)
{ {
topclip = MIN<short>(h, viewheight); topclip = short(MIN(h, viewheight));
} }
} }
hzt = MIN(hzt, sclipTop); hzt = MIN(hzt, sclipTop);
@ -2204,7 +2204,7 @@ void R_DrawSprite (vissprite_t *spr)
h = (centeryfrac - FixedMul (h-viewz, scale)) >> FRACBITS; h = (centeryfrac - FixedMul (h-viewz, scale)) >> FRACBITS;
if (h > topclip) if (h > topclip)
{ {
topclip = MIN<short> (h, viewheight); topclip = short(MIN(h, viewheight));
} }
} }
#endif #endif

View file

@ -392,7 +392,8 @@ int FZipLump::FillCache()
int FZipLump::GetFileOffset() int FZipLump::GetFileOffset()
{ {
if (Method != METHOD_STORED) return -1; if (Method != METHOD_STORED) return -1;
if (Flags & LUMPFZIP_NEEDFILESTART) SetLumpAddress(); return Position; if (Flags & LUMPFZIP_NEEDFILESTART) SetLumpAddress();
return Position;
} }
//========================================================================== //==========================================================================

View file

@ -442,7 +442,7 @@ IMPLEMENT_CLASS (DSeqPolyNode)
void DSeqPolyNode::Serialize(FSerializer &arc) void DSeqPolyNode::Serialize(FSerializer &arc)
{ {
Super::Serialize (arc); Super::Serialize (arc);
//arc << m_Poly; arc("poly", m_Poly);
} }
IMPLEMENT_CLASS (DSeqSectorNode) IMPLEMENT_CLASS (DSeqSectorNode)

View file

@ -381,7 +381,7 @@ void FSerializer::Close()
// //
//========================================================================== //==========================================================================
int FSerializer::ArraySize() unsigned FSerializer::ArraySize()
{ {
if (r != nullptr && r->mObjects.Last().mObject->IsArray()) if (r != nullptr && r->mObjects.Last().mObject->IsArray())
{ {
@ -709,7 +709,7 @@ FSerializer &FSerializer::Sprite(const char *key, int32_t &spritenum, int32_t *d
{ {
if (val->IsString()) if (val->IsString())
{ {
int name = *reinterpret_cast<const int*>(val->GetString()); uint32_t name = *reinterpret_cast<const uint32_t*>(val->GetString());
for (auto hint = NumStdSprites; hint-- != 0; ) for (auto hint = NumStdSprites; hint-- != 0; )
{ {
if (sprites[hint].dwName == name) if (sprites[hint].dwName == name)
@ -1451,7 +1451,7 @@ FSerializer &Serialize(FSerializer &arc, const char *key, DObject *&value, DObje
{ {
ndx = -1; ndx = -1;
} }
else if (value->ObjectFlags & OF_EuthanizeMe) else if (value->ObjectFlags & (OF_EuthanizeMe | OF_Transient))
{ {
return arc; return arc;
} }

View file

@ -60,7 +60,7 @@ public:
FWriter *w = nullptr; FWriter *w = nullptr;
FReader *r = nullptr; FReader *r = nullptr;
int ArraySize(); unsigned ArraySize();
void WriteKey(const char *key); void WriteKey(const char *key);
void WriteObjects(); void WriteObjects();

View file

@ -145,8 +145,8 @@ HMISong::HMISong (FileReader &reader, EMidiDevice type, const char *args)
MusHeader = new BYTE[len]; MusHeader = new BYTE[len];
SongLen = len; SongLen = len;
NumTracks = 0; NumTracks = 0;
if (reader.Read(MusHeader, len) != len) if (reader.Read(MusHeader, len) != len)
return; return;
// Do some validation of the MIDI file // Do some validation of the MIDI file
if (memcmp(MusHeader, HMI_SONG_MAGIC, sizeof(HMI_SONG_MAGIC)) == 0) if (memcmp(MusHeader, HMI_SONG_MAGIC, sizeof(HMI_SONG_MAGIC)) == 0)
@ -657,7 +657,7 @@ DWORD *HMISong::SendCommand (DWORD *events, TrackInfo *track, DWORD delay, ptrdi
if (event == MIDI_SYSEX || event == MIDI_SYSEXEND) if (event == MIDI_SYSEX || event == MIDI_SYSEXEND)
{ {
len = ReadVarLen(track); len = ReadVarLen(track);
if (len >= (MAX_EVENTS-1)*3*4) if (len >= (MAX_EVENTS-1)*3*4 || DeviceType == MDEV_SNDSYS)
{ // This message will never fit. Throw it away. { // This message will never fit. Throw it away.
track->TrackP += len; track->TrackP += len;
} }

View file

@ -114,10 +114,10 @@ MIDISong2::MIDISong2 (FileReader &reader, EMidiDevice type, const char *args)
return; return;
} }
#endif #endif
SongLen = reader.GetLength(); SongLen = reader.GetLength();
MusHeader = new BYTE[SongLen]; MusHeader = new BYTE[SongLen];
if (reader.Read(MusHeader, SongLen) != SongLen) if (reader.Read(MusHeader, SongLen) != SongLen)
return; return;
// Do some validation of the MIDI file // Do some validation of the MIDI file
if (MusHeader[4] != 0 || MusHeader[5] != 0 || MusHeader[6] != 0 || MusHeader[7] != 6) if (MusHeader[4] != 0 || MusHeader[5] != 0 || MusHeader[6] != 0 || MusHeader[7] != 6)
@ -598,7 +598,7 @@ DWORD *MIDISong2::SendCommand (DWORD *events, TrackInfo *track, DWORD delay, ptr
if (event == MIDI_SYSEX || event == MIDI_SYSEXEND) if (event == MIDI_SYSEX || event == MIDI_SYSEXEND)
{ {
len = track->ReadVarLen(); len = track->ReadVarLen();
if (len >= (MAX_EVENTS-1)*3*4) if (len >= (MAX_EVENTS-1)*3*4 || DeviceType == MDEV_SNDSYS)
{ // This message will never fit. Throw it away. { // This message will never fit. Throw it away.
track->TrackP += len; track->TrackP += len;
} }

View file

@ -117,10 +117,10 @@ XMISong::XMISong (FileReader &reader, EMidiDevice type, const char *args)
return; return;
} }
#endif #endif
SongLen = reader.GetLength(); SongLen = reader.GetLength();
MusHeader = new BYTE[SongLen]; MusHeader = new BYTE[SongLen];
if (reader.Read(MusHeader, SongLen) != SongLen) if (reader.Read(MusHeader, SongLen) != SongLen)
return; return;
// Find all the songs in this file. // Find all the songs in this file.
NumSongs = FindXMIDforms(MusHeader, SongLen, NULL); NumSongs = FindXMIDforms(MusHeader, SongLen, NULL);
@ -528,7 +528,7 @@ DWORD *XMISong::SendCommand (DWORD *events, EventSource due, DWORD delay, ptrdif
if (event == MIDI_SYSEX || event == MIDI_SYSEXEND) if (event == MIDI_SYSEX || event == MIDI_SYSEXEND)
{ {
len = track->ReadVarLen(); len = track->ReadVarLen();
if (len >= (MAX_EVENTS-1)*3*4) if (len >= (MAX_EVENTS-1)*3*4 || DeviceType == MDEV_SNDSYS)
{ // This message will never fit. Throw it away. { // This message will never fit. Throw it away.
track->EventP += len; track->EventP += len;
} }

View file

@ -161,6 +161,16 @@ FAnimDef *FTextureManager::AddComplexAnim (FTextureID picnum, const TArray<FAnim
// [RH] Rewritten to support BOOM ANIMATED lump but also make absolutely // [RH] Rewritten to support BOOM ANIMATED lump but also make absolutely
// no assumptions about how the compiler packs the animdefs array. // no assumptions about how the compiler packs the animdefs array.
// //
// Since animdef_t no longer exists in ZDoom, here is some documentation
// of the format:
//
// This is an array of <n> entries, terminated by a 0xFF byte. Each entry
// is 23 bytes long and consists of the following fields:
// Byte 0: Bit 1 set for wall texture, clear for flat texture.
// Bytes 1-9: '\0'-terminated name of first texture.
// Bytes 10-18: '\0'-terminated name of last texture.
// Bytes 19-22: Tics per frame (stored in little endian order).
//
//========================================================================== //==========================================================================
CVAR(Bool, debuganimated, false, 0) CVAR(Bool, debuganimated, false, 0)

View file

@ -45,6 +45,7 @@
#include "v_video.h" #include "v_video.h"
#include "m_fixed.h" #include "m_fixed.h"
#include "textures/textures.h" #include "textures/textures.h"
#include "v_palette.h"
typedef bool (*CheckFunc)(FileReader & file); typedef bool (*CheckFunc)(FileReader & file);
typedef FTexture * (*CreateFunc)(FileReader & file, int lumpnum); typedef FTexture * (*CreateFunc)(FileReader & file, int lumpnum);
@ -569,6 +570,78 @@ void FTexture::SetScaledSize(int fitwidth, int fitheight)
if (int(Scale.Y * fitheight) != Height) Scale.Y += (1 / 65536.); if (int(Scale.Y * fitheight) != Height) Scale.Y += (1 / 65536.);
} }
//===========================================================================
//
// Gets the average color of a texture for use as a sky cap color
//
//===========================================================================
namespace
{
PalEntry averageColor(const DWORD *data, int size, int maxout)
{
int i;
unsigned int r, g, b;
// First clear them.
r = g = b = 0;
if (size == 0)
{
return PalEntry(255, 255, 255);
}
for (i = 0; i < size; i++)
{
b += BPART(data[i]);
g += GPART(data[i]);
r += RPART(data[i]);
}
r = r / size;
g = g / size;
b = b / size;
int maxv = MAX(MAX(r, g), b);
if (maxv && maxout)
{
r = Scale(r, maxout, maxv);
g = Scale(g, maxout, maxv);
b = Scale(b, maxout, maxv);
}
return PalEntry(255, r, g, b);
}
}
PalEntry FTexture::GetSkyCapColor(bool bottom)
{
PalEntry col;
int w;
int h;
if (!bSWSkyColorDone)
{
bSWSkyColorDone = true;
FBitmap bitmap;
bitmap.Create(GetWidth(), GetHeight());
CopyTrueColorPixels(&bitmap, 0, 0);
int w = GetWidth();
int h = GetHeight();
const uint32_t *buffer = (const uint32_t *)bitmap.GetPixels();
if (buffer)
{
CeilingSkyColor = averageColor((DWORD *)buffer, w * MIN(30, h), 0);
if (h>30)
{
FloorSkyColor = averageColor(((DWORD *)buffer) + (h - 30)*w, w * 30, 0);
}
else FloorSkyColor = CeilingSkyColor;
}
}
return bottom ? FloorSkyColor : CeilingSkyColor;
}
FDummyTexture::FDummyTexture () FDummyTexture::FDummyTexture ()
{ {

View file

@ -262,6 +262,7 @@ public:
} }
void SetScaledSize(int fitwidth, int fitheight); void SetScaledSize(int fitwidth, int fitheight);
PalEntry GetSkyCapColor(bool bottom);
virtual void HackHack (int newheight); // called by FMultipatchTexture to discover corrupt patches. virtual void HackHack (int newheight); // called by FMultipatchTexture to discover corrupt patches.
@ -285,6 +286,11 @@ protected:
gl_info.areas = NULL; gl_info.areas = NULL;
} }
private:
bool bSWSkyColorDone = false;
PalEntry FloorSkyColor;
PalEntry CeilingSkyColor;
public: public:
static void FlipSquareBlock (BYTE *block, int x, int y); static void FlipSquareBlock (BYTE *block, int x, int y);
static void FlipSquareBlockRemap (BYTE *block, int x, int y, const BYTE *remap); static void FlipSquareBlockRemap (BYTE *block, int x, int y, const BYTE *remap);
@ -301,8 +307,6 @@ public:
FGLTexture *SystemTexture[2]; FGLTexture *SystemTexture[2];
FTexture *Brightmap; FTexture *Brightmap;
PalEntry GlowColor; PalEntry GlowColor;
PalEntry FloorSkyColor;
PalEntry CeilingSkyColor;
int GlowHeight; int GlowHeight;
FloatRect *areas; FloatRect *areas;
int areacount; int areacount;
@ -312,7 +316,6 @@ public:
bool bGlowing:1; // Texture glows bool bGlowing:1; // Texture glows
bool bFullbright:1; // always draw fullbright bool bFullbright:1; // always draw fullbright
bool bSkybox:1; // This is a skybox bool bSkybox:1; // This is a skybox
bool bSkyColorDone:1; // Fill color for sky
char bBrightmapChecked:1; // Set to 1 if brightmap has been checked char bBrightmapChecked:1; // Set to 1 if brightmap has been checked
bool bDisableFullbright:1; // This texture will not be displayed as fullbright sprite bool bDisableFullbright:1; // This texture will not be displayed as fullbright sprite
bool bNoFilter:1; bool bNoFilter:1;
@ -325,7 +328,6 @@ public:
MiscGLInfo gl_info; MiscGLInfo gl_info;
void GetGlowColor(float *data); void GetGlowColor(float *data);
PalEntry GetSkyCapColor(bool bottom);
bool isGlowing() { return gl_info.bGlowing; } bool isGlowing() { return gl_info.bGlowing; }
bool isFullbright() { return gl_info.bFullbright; } bool isFullbright() { return gl_info.bFullbright; }
void CreateDefaultBrightmap(); void CreateDefaultBrightmap();

View file

@ -140,6 +140,7 @@ DEFINE_CLASS_PROPERTY(respawns, 0, FakeInventory)
// Reads an old style decoration object // Reads an old style decoration object
// //
//========================================================================== //==========================================================================
PClassActor *DecoDerivedClass(const FScriptPosition &sc, PClassActor *parent, FName typeName);
void ParseOldDecoration(FScanner &sc, EDefinitionType def) void ParseOldDecoration(FScanner &sc, EDefinitionType def)
{ {
@ -154,7 +155,7 @@ void ParseOldDecoration(FScanner &sc, EDefinitionType def)
sc.MustGetString(); sc.MustGetString();
typeName = FName(sc.String); typeName = FName(sc.String);
type = static_cast<PClassActor *>(parent->CreateDerivedClass (typeName, parent->Size)); type = DecoDerivedClass(FScriptPosition(sc), parent, typeName);
ResetBaggage(&bag, parent); ResetBaggage(&bag, parent);
bag.Info = type; bag.Info = type;
#ifdef _DEBUG #ifdef _DEBUG

View file

@ -68,13 +68,44 @@
TDeletingArray<class FxExpression *> ActorDamageFuncs; TDeletingArray<class FxExpression *> ActorDamageFuncs;
// EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
void InitThingdef(); void InitThingdef();
void ParseDecorate (FScanner &sc); void ParseDecorate(FScanner &ctx);
// STATIC FUNCTION PROTOTYPES -------------------------------------------- // STATIC FUNCTION PROTOTYPES --------------------------------------------
PClassActor *QuestItemClasses[31]; PClassActor *QuestItemClasses[31];
EXTERN_CVAR(Bool, strictdecorate);
PClassActor *DecoDerivedClass(const FScriptPosition &sc, PClassActor *parent, FName typeName)
{
PClassActor *type = static_cast<PClassActor *>(parent->CreateDerivedClass(typeName, parent->Size));
if (type == nullptr)
{
FString newname = typeName.GetChars();
FString sourcefile = sc.FileName;
sourcefile.Substitute(":", "@");
newname << '@' << sourcefile;
if (strictdecorate)
{
sc.Message(MSG_ERROR, "Tried to define class '%s' more than once.", typeName.GetChars());
}
else
{
// Due to backwards compatibility issues this cannot be an unconditional error.
sc.Message(MSG_WARNING, "Tried to define class '%s' more than once. Renaming class to '%s'", typeName.GetChars(), newname.GetChars());
}
type = static_cast<PClassActor *>(parent->CreateDerivedClass(newname, parent->Size));
if (type == nullptr)
{
// This we cannot handle cleanly anymore. Let's just abort and forget about the odd mod out that was this careless.
sc.Message(MSG_FATAL, "Tried to define class '%s' more than twice in the same file.", typeName.GetChars());
}
}
return type;
}
//========================================================================== //==========================================================================
// //
// Starts a new actor definition // Starts a new actor definition
@ -141,7 +172,7 @@ PClassActor *CreateNewActor(const FScriptPosition &sc, FName typeName, FName par
else else
{ {
create: create:
ti = static_cast<PClassActor *>(parent->CreateDerivedClass (typeName, parent->Size)); ti = DecoDerivedClass(sc, parent, typeName);
} }
ti->Replacee = ti->Replacement = NULL; ti->Replacee = ti->Replacement = NULL;
@ -428,6 +459,16 @@ void LoadActors ()
while ((lump = Wads.FindLump ("DECORATE", &lastlump)) != -1) while ((lump = Wads.FindLump ("DECORATE", &lastlump)) != -1)
{ {
FScanner sc(lump); FScanner sc(lump);
if (Wads.GetLumpFile(lump) == 0)
{
// define namespace 'zdoom'
}
else
{
// use namespace 'zdoom'
}
ParseDecorate (sc); ParseDecorate (sc);
} }
FinishThingdef(); FinishThingdef();
@ -439,32 +480,3 @@ void LoadActors ()
if (!batchrun) Printf("DECORATE parsing took %.2f ms\n", timer.TimeMS()); if (!batchrun) Printf("DECORATE parsing took %.2f ms\n", timer.TimeMS());
// Base time: ~52 ms // Base time: ~52 ms
} }
//==========================================================================
//
// CreateDamageFunction
//
// Creates a damage function suitable for a constant, non-expressioned
// value.
//
//==========================================================================
VMScriptFunction *CreateDamageFunction(int dmg)
{
if (dmg == 0)
{
// For zero damage, do not create a function so that the special collision detection case still works as before.
return NULL;
}
else
{
VMFunctionBuilder build;
build.Registers[REGT_POINTER].Get(1); // The self pointer
build.EmitRetInt(0, false, dmg);
build.EmitRetInt(1, true, 0);
VMScriptFunction *sfunc = build.MakeFunction();
sfunc->NumArgs = 1;
return sfunc;
}
}

View file

@ -164,14 +164,6 @@ inline void ResetBaggage (Baggage *bag, PClassActor *stateclass)
bag->statedef.MakeStateDefines(stateclass); bag->statedef.MakeStateDefines(stateclass);
} }
//==========================================================================
//
// Damage function creation
//
//==========================================================================
VMScriptFunction *CreateDamageFunction(int dmg);
//========================================================================== //==========================================================================
// //
// Action function lookup // Action function lookup

View file

@ -91,7 +91,7 @@ static const FLOP FxFlops[] =
// //
//========================================================================== //==========================================================================
FCompileContext::FCompileContext(PClassActor *cls, PPrototype *ret) : Class(cls), ReturnProto(ret) FCompileContext::FCompileContext(PClassActor *cls, PPrototype *ret) : ReturnProto(ret), Class(cls)
{ {
} }
@ -959,7 +959,7 @@ ExpEmit FxUnaryNotBoolean::Emit(VMFunctionBuilder *build)
//========================================================================== //==========================================================================
FxPreIncrDecr::FxPreIncrDecr(FxExpression *base, int token) FxPreIncrDecr::FxPreIncrDecr(FxExpression *base, int token)
: FxExpression(base->ScriptPosition), Base(base), Token(token) : FxExpression(base->ScriptPosition), Token(token), Base(base)
{ {
AddressRequested = false; AddressRequested = false;
AddressWritable = false; AddressWritable = false;
@ -1045,7 +1045,7 @@ ExpEmit FxPreIncrDecr::Emit(VMFunctionBuilder *build)
//========================================================================== //==========================================================================
FxPostIncrDecr::FxPostIncrDecr(FxExpression *base, int token) FxPostIncrDecr::FxPostIncrDecr(FxExpression *base, int token)
: FxExpression(base->ScriptPosition), Base(base), Token(token) : FxExpression(base->ScriptPosition), Token(token), Base(base)
{ {
} }
@ -4956,6 +4956,25 @@ FxExpression *FxRuntimeStateIndex::Resolve(FCompileContext &ctx)
return this; return this;
} }
static bool VerifyJumpTarget(AActor *stateowner, FStateParamInfo *stateinfo, int index)
{
PClassActor *cls = stateowner->GetClass();
while (cls != RUNTIME_CLASS(AActor))
{
// both calling and target state need to belong to the same class.
if (cls->OwnsState(stateinfo->mCallingState))
{
return cls->OwnsState(stateinfo->mCallingState + index);
}
// We can safely assume the ParentClass is of type PClassActor
// since we stop when we see the Actor base class.
cls = static_cast<PClassActor *>(cls->ParentClass);
}
return false;
}
static int DecoHandleRuntimeState(VMFrameStack *stack, VMValue *param, int numparam, VMReturn *ret, int numret) static int DecoHandleRuntimeState(VMFrameStack *stack, VMValue *param, int numparam, VMReturn *ret, int numret)
{ {
PARAM_PROLOGUE; PARAM_PROLOGUE;
@ -4963,7 +4982,7 @@ static int DecoHandleRuntimeState(VMFrameStack *stack, VMValue *param, int numpa
PARAM_POINTER(stateinfo, FStateParamInfo); PARAM_POINTER(stateinfo, FStateParamInfo);
PARAM_INT(index); PARAM_INT(index);
if (index == 0 || !stateowner->GetClass()->OwnsState(stateinfo->mCallingState + index)) if (index == 0 || !VerifyJumpTarget(stateowner, stateinfo, index))
{ {
// Null is returned if the location was invalid which means that no jump will be performed // Null is returned if the location was invalid which means that no jump will be performed
// if used as return value // if used as return value

View file

@ -1435,7 +1435,7 @@ DEFINE_PROPERTY(spriterotation, F, Actor)
//========================================================================== //==========================================================================
// //
//========================================================================== //==========================================================================
DEFINE_PROPERTY(visibleangles, Ff, Actor) DEFINE_PROPERTY(visibleangles, FF, Actor)
{ {
PROP_DOUBLE_PARM(visstart, 0); PROP_DOUBLE_PARM(visstart, 0);
PROP_DOUBLE_PARM(visend, 1); PROP_DOUBLE_PARM(visend, 1);
@ -1446,7 +1446,7 @@ DEFINE_PROPERTY(visibleangles, Ff, Actor)
//========================================================================== //==========================================================================
// //
//========================================================================== //==========================================================================
DEFINE_PROPERTY(visiblepitch, Ff, Actor) DEFINE_PROPERTY(visiblepitch, FF, Actor)
{ {
PROP_DOUBLE_PARM(visstart, 0); PROP_DOUBLE_PARM(visstart, 0);
PROP_DOUBLE_PARM(visend, 1); PROP_DOUBLE_PARM(visend, 1);

View file

@ -52,7 +52,8 @@
#include "v_palette.h" #include "v_palette.h"
#include "d_player.h" #include "d_player.h"
CVAR( Float, blood_fade_scalar, 1.0f, CVAR_ARCHIVE ) // [SP] Pulled from Skulltag - changed default from 0.5 to 1.0
CVAR( Float, pickup_fade_scalar, 1.0f, CVAR_ARCHIVE ) // [SP] Uses same logic as blood_fade_scalar except for pickups
// [RH] Amount of red flash for up to 114 damage points. Calculated by hand // [RH] Amount of red flash for up to 114 damage points. Calculated by hand
// using a logarithmic scale and my trusty HP48G. // using a logarithmic scale and my trusty HP48G.
@ -113,6 +114,9 @@ void V_AddPlayerBlend (player_t *CPlayer, float blend[4], float maxinvalpha, int
if (CPlayer->bonuscount) if (CPlayer->bonuscount)
{ {
cnt = CPlayer->bonuscount << 3; cnt = CPlayer->bonuscount << 3;
// [SP] Allow player to tone down intensity of pickup flash.
cnt = (int)( cnt * pickup_fade_scalar );
V_AddBlend (RPART(gameinfo.pickupcolor)/255.f, GPART(gameinfo.pickupcolor)/255.f, V_AddBlend (RPART(gameinfo.pickupcolor)/255.f, GPART(gameinfo.pickupcolor)/255.f,
BPART(gameinfo.pickupcolor)/255.f, cnt > 128 ? 0.5f : cnt / 255.f, blend); BPART(gameinfo.pickupcolor)/255.f, cnt > 128 ? 0.5f : cnt / 255.f, blend);
@ -124,7 +128,10 @@ void V_AddPlayerBlend (player_t *CPlayer, float blend[4], float maxinvalpha, int
if (painFlash.a != 0) if (painFlash.a != 0)
{ {
cnt = DamageToAlpha[MIN (113, CPlayer->damagecount * painFlash.a / 255)]; cnt = DamageToAlpha[MIN (113, CPlayer->damagecount * painFlash.a / 255)];
// [BC] Allow users to tone down the intensity of the blood on the screen.
cnt = (int)( cnt * blood_fade_scalar );
if (cnt) if (cnt)
{ {
if (cnt > maxpainblend) if (cnt > maxpainblend)

View file

@ -77,7 +77,7 @@ static void SetNodeLine(ZCC_TreeNode *name, int line)
FString unexpected, expecting; FString unexpected, expecting;
int i; int i;
int stateno = yypParser->yystack[yypParser->yyidx].stateno; int stateno = yypParser->yytos->stateno;
unexpected << "Unexpected " << ZCCTokenName(yymajor); unexpected << "Unexpected " << ZCCTokenName(yymajor);

View file

@ -162,11 +162,11 @@ ZCC_OpProto *ZCC_OpInfoType::FindBestProto(
// [[float32 (op) int]] will choose the integer version instead of the floating point // [[float32 (op) int]] will choose the integer version instead of the floating point
// version, which we do not want. // version, which we do not want.
int test_dist1 = dist1, test_dist2 = dist2; int test_dist1 = dist1, test_dist2 = dist2;
if (routes[0][cur_route1][0]->ConvertConstant == FtoD) if (test_dist1 > 0 && routes[0][cur_route1][0]->ConvertConstant == FtoD)
{ {
test_dist1--; test_dist1--;
} }
if (routes[1][cur_route2][0]->ConvertConstant == FtoD) if (test_dist2 > 0 && routes[1][cur_route2][0]->ConvertConstant == FtoD)
{ {
test_dist2--; test_dist2--;
} }

View file

@ -167,7 +167,8 @@ struct symbol {
int useCnt; /* Number of times used */ int useCnt; /* Number of times used */
char *destructor; /* Code which executes whenever this symbol is char *destructor; /* Code which executes whenever this symbol is
** popped from the stack during error processing */ ** popped from the stack during error processing */
int destLineno; /* Line number for start of destructor */ int destLineno; /* Line number for start of destructor. Set to
** -1 for duplicate destructors. */
char *datatype; /* The data type of information held by this char *datatype; /* The data type of information held by this
** object. Only used if type==NONTERMINAL */ ** object. Only used if type==NONTERMINAL */
int dtnum; /* The data type number. In the parser, the value int dtnum; /* The data type number. In the parser, the value
@ -192,10 +193,15 @@ struct rule {
const char *code; /* The code executed when this rule is reduced */ const char *code; /* The code executed when this rule is reduced */
const char *codePrefix; /* Setup code before code[] above */ const char *codePrefix; /* Setup code before code[] above */
const char *codeSuffix; /* Breakdown code after code[] above */ const char *codeSuffix; /* Breakdown code after code[] above */
int noCode; /* True if this rule has no associated C code */
int codeEmitted; /* True if the code has been emitted already */
struct symbol *precsym; /* Precedence symbol for this rule */ struct symbol *precsym; /* Precedence symbol for this rule */
int index; /* An index number for this rule */ int index; /* An index number for this rule */
int iRule; /* Rule number as used in the generated tables */ int iRule; /* Rule number as used in the generated tables */
Boolean canReduce; /* True if this rule is ever reduced */ Boolean canReduce; /* True if this rule is ever reduced */
#if 0
Boolean doesReduce; /* Reduce actions occur after optimization */
#endif
struct rule *nextlhs; /* Next rule with the same LHS */ struct rule *nextlhs; /* Next rule with the same LHS */
struct rule *next; /* Next rule in the global list */ struct rule *next; /* Next rule in the global list */
}; };
@ -243,6 +249,7 @@ struct action {
struct state *stp; /* The new state, if a shift */ struct state *stp; /* The new state, if a shift */
struct rule *rp; /* The rule, if a reduce */ struct rule *rp; /* The rule, if a reduce */
} x; } x;
struct symbol *spOpt; /* SHIFTREDUCE optimization to this symbol */
struct action *next; /* Next action for this state */ struct action *next; /* Next action for this state */
struct action *collide; /* Next action with the same hash */ struct action *collide; /* Next action with the same hash */
}; };
@ -253,7 +260,7 @@ struct state {
struct config *bp; /* The basis configurations for this state */ struct config *bp; /* The basis configurations for this state */
struct config *cfp; /* All configurations in this set */ struct config *cfp; /* All configurations in this set */
int statenum; /* Sequential number for this state */ int statenum; /* Sequential number for this state */
struct action *ap; /* Array of actions for this state */ struct action *ap; /* List of actions for this state */
int nTknAct, nNtAct; /* Number of actions on terminals and nonterminals */ int nTknAct, nNtAct; /* Number of actions on terminals and nonterminals */
int iTknOfst, iNtOfst; /* yy_action[] offset for terminals and nonterms */ int iTknOfst, iNtOfst; /* yy_action[] offset for terminals and nonterms */
int iDfltReduce; /* Default action is to REDUCE by this rule */ int iDfltReduce; /* Default action is to REDUCE by this rule */
@ -433,6 +440,7 @@ void Action_add(
*app = newaction; *app = newaction;
newaction->type = type; newaction->type = type;
newaction->sp = sp; newaction->sp = sp;
newaction->spOpt = 0;
if( type==SHIFT ){ if( type==SHIFT ){
newaction->x.stp = (struct state *)arg; newaction->x.stp = (struct state *)arg;
}else{ }else{
@ -1483,7 +1491,7 @@ static void handle_C_option(char *z){
} }
} }
/* Merge together to lists of rules order by rule.iRule */ /* Merge together to lists of rules ordered by rule.iRule */
static struct rule *Rule_merge(struct rule *pA, struct rule *pB){ static struct rule *Rule_merge(struct rule *pA, struct rule *pB){
struct rule *pFirst = 0; struct rule *pFirst = 0;
struct rule **ppPrev = &pFirst; struct rule **ppPrev = &pFirst;
@ -1627,7 +1635,10 @@ int main(int argc, char **argv)
for(i=1; ISUPPER(lem.symbols[i]->name[0]); i++); for(i=1; ISUPPER(lem.symbols[i]->name[0]); i++);
lem.nterminal = i; lem.nterminal = i;
/* Assign sequential rule numbers */ /* Assign sequential rule numbers. Start with 0. Put rules that have no
** reduce action C-code associated with them last, so that the switch()
** statement that selects reduction actions will have a smaller jump table.
*/
for(i=0, rp=lem.rule; rp; rp=rp->next){ for(i=0, rp=lem.rule; rp; rp=rp->next){
rp->iRule = rp->code ? i++ : -1; rp->iRule = rp->code ? i++ : -1;
} }
@ -2179,7 +2190,7 @@ static void parseonetoken(struct pstate *psp)
"There is no prior rule upon which to attach the code \ "There is no prior rule upon which to attach the code \
fragment which begins on this line."); fragment which begins on this line.");
psp->errorcnt++; psp->errorcnt++;
}else if( psp->prevrule->code!=0 ){ }else if( psp->prevrule->code!=0 ){
ErrorMsg(psp->filename,psp->tokenlineno, ErrorMsg(psp->filename,psp->tokenlineno,
"Code fragment beginning on this line is not the first \ "Code fragment beginning on this line is not the first \
to follow the previous rule."); to follow the previous rule.");
@ -2187,7 +2198,8 @@ to follow the previous rule.");
}else{ }else{
psp->prevrule->line = psp->tokenlineno; psp->prevrule->line = psp->tokenlineno;
psp->prevrule->code = &x[1]; psp->prevrule->code = &x[1];
} psp->prevrule->noCode = 0;
}
}else if( x[0]=='[' ){ }else if( x[0]=='[' ){
psp->state = PRECEDENCE_MARK_1; psp->state = PRECEDENCE_MARK_1;
}else{ }else{
@ -2293,6 +2305,7 @@ to follow the previous rule.");
rp->lhsalias = psp->lhsalias; rp->lhsalias = psp->lhsalias;
rp->nrhs = psp->nrhs; rp->nrhs = psp->nrhs;
rp->code = 0; rp->code = 0;
rp->noCode = 1;
rp->precsym = 0; rp->precsym = 0;
rp->index = psp->gp->nrule++; rp->index = psp->gp->nrule++;
rp->nextlhs = rp->lhs->rule; rp->nextlhs = rp->lhs->rule;
@ -3153,6 +3166,9 @@ int PrintAction(
result = 0; result = 0;
break; break;
} }
if( result && ap->spOpt ){
fprintf(fp," /* because %s==%s */", ap->sp->name, ap->spOpt->name);
}
return result; return result;
} }
@ -3531,9 +3547,8 @@ PRIVATE char *append_str(const char *zText, int n, int p1, int p2, int bNoSubst)
} }
/* /*
** zCode is a string that is the action associated with a rule. Expand ** Write and transform the rp->code string so that symbols are expanded.
** the symbols in this string so that the refer to elements of the parser ** Populate the rp->codePrefix and rp->codeSuffix strings, as appropriate.
** stack.
** **
** Return 1 if the expanded code requires that "yylhsminor" local variable ** Return 1 if the expanded code requires that "yylhsminor" local variable
** to be defined. ** to be defined.
@ -3557,12 +3572,12 @@ PRIVATE int translate_code(struct lemon *lemp, struct rule *rp){
static char newlinestr[2] = { '\n', '\0' }; static char newlinestr[2] = { '\n', '\0' };
rp->code = newlinestr; rp->code = newlinestr;
rp->line = rp->ruleline; rp->line = rp->ruleline;
rp->noCode = 1;
}else{
rp->noCode = 0;
} }
if( rp->lhsalias==0 ){ if( rp->nrhs==0 ){
/* There is no LHS value symbol. */
lhsdirect = 1;
}else if( rp->nrhs==0 ){
/* If there are no RHS symbols, then writing directly to the LHS is ok */ /* If there are no RHS symbols, then writing directly to the LHS is ok */
lhsdirect = 1; lhsdirect = 1;
}else if( rp->rhsalias[0]==0 ){ }else if( rp->rhsalias[0]==0 ){
@ -3574,7 +3589,11 @@ PRIVATE int translate_code(struct lemon *lemp, struct rule *rp){
append_str(" yy_destructor(yypParser,%d,&yymsp[%d].minor);\n", 0, append_str(" yy_destructor(yypParser,%d,&yymsp[%d].minor);\n", 0,
rp->rhs[0]->index,1-rp->nrhs,0); rp->rhs[0]->index,1-rp->nrhs,0);
rp->codePrefix = Strsafe(append_str(0,0,0,0,0)); rp->codePrefix = Strsafe(append_str(0,0,0,0,0));
rp->noCode = 0;
} }
}else if( rp->lhsalias==0 ){
/* There is no LHS value symbol. */
lhsdirect = 1;
}else if( strcmp(rp->lhsalias,rp->rhsalias[0])==0 ){ }else if( strcmp(rp->lhsalias,rp->rhsalias[0])==0 ){
/* The LHS symbol and the left-most RHS symbol are the same, so /* The LHS symbol and the left-most RHS symbol are the same, so
** direct writing is allowed */ ** direct writing is allowed */
@ -3717,7 +3736,10 @@ PRIVATE int translate_code(struct lemon *lemp, struct rule *rp){
/* Suffix code generation complete */ /* Suffix code generation complete */
cp = append_str(0,0,0,0,0); cp = append_str(0,0,0,0,0);
if( cp ) rp->codeSuffix = Strsafe(cp); if( cp && cp[0] ){
rp->codeSuffix = Strsafe(cp);
rp->noCode = 0;
}
return rc; return rc;
} }
@ -4136,6 +4158,21 @@ void ReportTable(
} }
free(ax); free(ax);
#if 0
/* Mark rules that are actually used for reduce actions after all
** optimizations have been applied
*/
for(rp=lemp->rule; rp; rp=rp->next) rp->doesReduce = LEMON_FALSE;
for(i=0; i<lemp->nxstate; i++){
struct action *ap;
for(ap=lemp->sorted[i]->ap; ap; ap=ap->next){
if( ap->type==REDUCE || ap->type==SHIFTREDUCE ){
ap->x.rp->doesReduce = i;
}
}
}
#endif
/* Finish rendering the constants now that the action table has /* Finish rendering the constants now that the action table has
** been computed */ ** been computed */
fprintf(out,"#define YYNSTATE %d\n",lemp->nxstate); lineno++; fprintf(out,"#define YYNSTATE %d\n",lemp->nxstate); lineno++;
@ -4201,20 +4238,21 @@ void ReportTable(
fprintf(out, "};\n"); lineno++; fprintf(out, "};\n"); lineno++;
/* Output the yy_shift_ofst[] table */ /* Output the yy_shift_ofst[] table */
fprintf(out, "#define YY_SHIFT_USE_DFLT (%d)\n", mnTknOfst-1); lineno++;
n = lemp->nxstate; n = lemp->nxstate;
while( n>0 && lemp->sorted[n-1]->iTknOfst==NO_OFFSET ) n--; while( n>0 && lemp->sorted[n-1]->iTknOfst==NO_OFFSET ) n--;
fprintf(out, "#define YY_SHIFT_COUNT (%d)\n", n-1); lineno++; fprintf(out, "#define YY_SHIFT_USE_DFLT (%d)\n", lemp->nactiontab); lineno++;
fprintf(out, "#define YY_SHIFT_MIN (%d)\n", mnTknOfst); lineno++; fprintf(out, "#define YY_SHIFT_COUNT (%d)\n", n-1); lineno++;
fprintf(out, "#define YY_SHIFT_MAX (%d)\n", mxTknOfst); lineno++; fprintf(out, "#define YY_SHIFT_MIN (%d)\n", mnTknOfst); lineno++;
fprintf(out, "#define YY_SHIFT_MAX (%d)\n", mxTknOfst); lineno++;
fprintf(out, "static const %s yy_shift_ofst[] = {\n", fprintf(out, "static const %s yy_shift_ofst[] = {\n",
minimum_size_type(mnTknOfst-1, mxTknOfst, &sz)); lineno++; minimum_size_type(mnTknOfst, lemp->nterminal+lemp->nactiontab, &sz));
lineno++;
lemp->tablesize += n*sz; lemp->tablesize += n*sz;
for(i=j=0; i<n; i++){ for(i=j=0; i<n; i++){
int ofst; int ofst;
stp = lemp->sorted[i]; stp = lemp->sorted[i];
ofst = stp->iTknOfst; ofst = stp->iTknOfst;
if( ofst==NO_OFFSET ) ofst = mnTknOfst - 1; if( ofst==NO_OFFSET ) ofst = lemp->nactiontab;
if( j==0 ) fprintf(out," /* %5d */ ", i); if( j==0 ) fprintf(out," /* %5d */ ", i);
fprintf(out, " %4d,", ofst); fprintf(out, " %4d,", ofst);
if( j==9 || i==n-1 ){ if( j==9 || i==n-1 ){
@ -4354,6 +4392,7 @@ void ReportTable(
for(i=0; i<lemp->nsymbol; i++){ for(i=0; i<lemp->nsymbol; i++){
struct symbol *sp = lemp->symbols[i]; struct symbol *sp = lemp->symbols[i];
if( sp==0 || sp->type==TERMINAL || sp->destructor==0 ) continue; if( sp==0 || sp->type==TERMINAL || sp->destructor==0 ) continue;
if( sp->destLineno<0 ) continue; /* Already emitted */
fprintf(out," case %d: /* %s */\n", sp->index, sp->name); lineno++; fprintf(out," case %d: /* %s */\n", sp->index, sp->name); lineno++;
/* Combine duplicate destructors into a single case */ /* Combine duplicate destructors into a single case */
@ -4364,7 +4403,7 @@ void ReportTable(
&& strcmp(sp->destructor,sp2->destructor)==0 ){ && strcmp(sp->destructor,sp2->destructor)==0 ){
fprintf(out," case %d: /* %s */\n", fprintf(out," case %d: /* %s */\n",
sp2->index, sp2->name); lineno++; sp2->index, sp2->name); lineno++;
sp2->destructor = 0; sp2->destLineno = -1; /* Avoid emitting this destructor again */
} }
} }
@ -4398,32 +4437,45 @@ void ReportTable(
/* First output rules other than the default: rule */ /* First output rules other than the default: rule */
for(rp=lemp->rule; rp; rp=rp->next){ for(rp=lemp->rule; rp; rp=rp->next){
struct rule *rp2; /* Other rules with the same action */ struct rule *rp2; /* Other rules with the same action */
if( rp->code==0 ) continue; if( rp->codeEmitted ) continue;
if( rp->code[0]=='\n' && rp->code[1]==0 ) continue; /* Will be default: */ if( rp->noCode ){
/* No C code actions, so this will be part of the "default:" rule */
continue;
}
fprintf(out," case %d: /* ",rp->iRule); fprintf(out," case %d: /* ",rp->iRule);
writeRuleText(out, rp); writeRuleText(out, rp);
fprintf(out," */\n"); lineno++; fprintf(out," */\n"); lineno++;
for(rp2=rp->next; rp2; rp2=rp2->next){ for(rp2=rp->next; rp2; rp2=rp2->next){
if( rp2->code==rp->code ){ if( rp2->code==rp->code && rp2->codePrefix==rp->codePrefix
&& rp2->codeSuffix == rp->codeSuffix ){
fprintf(out," case %d: /*",rp2->iRule); fprintf(out," case %d: /*",rp2->iRule);
writeRuleText(out, rp2); writeRuleText(out, rp2);
fprintf(out, " */ yytestcase(yyruleno==%d);\n", rp2->iRule); lineno++; fprintf(out, " */ yytestcase(yyruleno==%d);\n", rp2->iRule); lineno++;
rp2->code = 0; rp2->codeEmitted = 1;
} }
} }
emit_code(out,rp,lemp,&lineno); emit_code(out,rp,lemp,&lineno);
fprintf(out," break;\n"); lineno++; fprintf(out," break;\n"); lineno++;
rp->code = 0; rp->codeEmitted = 1;
} }
/* Finally, output the default: rule. We choose as the default: all /* Finally, output the default: rule. We choose as the default: all
** empty actions. */ ** empty actions. */
fprintf(out," default:\n"); lineno++; fprintf(out," default:\n"); lineno++;
for(rp=lemp->rule; rp; rp=rp->next){ for(rp=lemp->rule; rp; rp=rp->next){
if( rp->code==0 ) continue; if( rp->codeEmitted ) continue;
assert( rp->code[0]=='\n' && rp->code[1]==0 ); assert( rp->noCode );
fprintf(out," /* (%d) ", rp->iRule); fprintf(out," /* (%d) ", rp->iRule);
writeRuleText(out, rp); writeRuleText(out, rp);
fprintf(out," */ yytestcase(yyruleno==%d);\n", rp->iRule); lineno++; #if 0
if( rp->doesReduce ){
#endif
fprintf(out, " */ yytestcase(yyruleno==%d);\n", rp->iRule); lineno++;
#if 0
}else{
fprintf(out, " (OPTIMIZED OUT) */ assert(yyruleno!=%d);\n",
rp->iRule); lineno++;
}
#endif
} }
fprintf(out," break;\n"); lineno++; fprintf(out," break;\n"); lineno++;
tplt_xfer(lemp->name,in,out,&lineno); tplt_xfer(lemp->name,in,out,&lineno);
@ -4496,7 +4548,7 @@ void ReportHeader(struct lemon *lemp)
void CompressTables(struct lemon *lemp) void CompressTables(struct lemon *lemp)
{ {
struct state *stp; struct state *stp;
struct action *ap, *ap2; struct action *ap, *ap2, *nextap;
struct rule *rp, *rp2, *rbest; struct rule *rp, *rp2, *rbest;
int nbest, n; int nbest, n;
int i; int i;
@ -4573,6 +4625,36 @@ void CompressTables(struct lemon *lemp)
} }
} }
} }
/* If a SHIFTREDUCE action specifies a rule that has a single RHS term
** (meaning that the SHIFTREDUCE will land back in the state where it
** started) and if there is no C-code associated with the reduce action,
** then we can go ahead and convert the action to be the same as the
** action for the RHS of the rule.
*/
for(i=0; i<lemp->nstate; i++){
stp = lemp->sorted[i];
for(ap=stp->ap; ap; ap=nextap){
nextap = ap->next;
if( ap->type!=SHIFTREDUCE ) continue;
rp = ap->x.rp;
if( rp->noCode==0 ) continue;
if( rp->nrhs!=1 ) continue;
#if 1
/* Only apply this optimization to non-terminals. It would be OK to
** apply it to terminal symbols too, but that makes the parser tables
** larger. */
if( ap->sp->index<lemp->nterminal ) continue;
#endif
/* If we reach this point, it means the optimization can be applied */
nextap = ap;
for(ap2=stp->ap; ap2 && (ap2==ap || ap2->sp!=rp->lhs); ap2=ap2->next){}
assert( ap2!=0 );
ap->spOpt = ap2->sp;
ap->type = ap2->type;
ap->x = ap2->x;
}
}
} }

View file

@ -41,6 +41,7 @@
***************** Begin makeheaders token definitions *************************/ ***************** Begin makeheaders token definitions *************************/
%% %%
/**************** End makeheaders token definitions ***************************/ /**************** End makeheaders token definitions ***************************/
/* The next section is a series of control #defines. /* The next section is a series of control #defines.
** various aspects of the generated parser. ** various aspects of the generated parser.
** YYCODETYPE is the data type used to store the integer codes ** YYCODETYPE is the data type used to store the integer codes
@ -50,8 +51,6 @@
** YYNOCODE is a number of type YYCODETYPE that is not used for ** YYNOCODE is a number of type YYCODETYPE that is not used for
** any terminal or nonterminal symbol. ** any terminal or nonterminal symbol.
** YYFALLBACK If defined, this indicates that one or more tokens ** YYFALLBACK If defined, this indicates that one or more tokens
** have fall-back values which should be used if the
** original value of the token will not parse.
** (also known as: "terminal symbols") have fall-back ** (also known as: "terminal symbols") have fall-back
** values which should be used if the original symbol ** values which should be used if the original symbol
** would not parse. This permits keywords to sometimes ** would not parse. This permits keywords to sometimes
@ -126,7 +125,7 @@
** **
** N between YY_MIN_REDUCE Reduce by rule N-YY_MIN_REDUCE ** N between YY_MIN_REDUCE Reduce by rule N-YY_MIN_REDUCE
** and YY_MAX_REDUCE ** and YY_MAX_REDUCE
**
** N == YY_ERROR_ACTION A syntax error has occurred. ** N == YY_ERROR_ACTION A syntax error has occurred.
** **
** N == YY_ACCEPT_ACTION The parser accepts its input. ** N == YY_ACCEPT_ACTION The parser accepts its input.
@ -135,16 +134,20 @@
** slots in the yy_action[] table. ** slots in the yy_action[] table.
** **
** The action table is constructed as a single large table named yy_action[]. ** The action table is constructed as a single large table named yy_action[].
** Given state S and lookahead X, the action is computed as ** Given state S and lookahead X, the action is computed as either:
** **
** yy_action[ yy_shift_ofst[S] + X ] ** (A) N = yy_action[ yy_shift_ofst[S] + X ]
** (B) N = yy_default[S]
** **
** If the index value yy_shift_ofst[S]+X is out of range or if the value ** The (A) formula is preferred. The B formula is used instead if:
** yy_lookahead[yy_shift_ofst[S]+X] is not equal to X or if yy_shift_ofst[S] ** (1) The yy_shift_ofst[S]+X value is out of range, or
** is equal to YY_SHIFT_USE_DFLT, it means that the action is not in the table ** (2) yy_lookahead[yy_shift_ofst[S]+X] is not equal to X, or
** and that yy_default[S] should be used instead. ** (3) yy_shift_ofst[S] equal YY_SHIFT_USE_DFLT.
** (Implementation note: YY_SHIFT_USE_DFLT is chosen so that
** YY_SHIFT_USE_DFLT+X will be out of range for all possible lookaheads X.
** Hence only tests (1) and (2) need to be evaluated.)
** **
** The formula above is for computing the action when the lookahead is ** The formulas above are for computing the action when the lookahead is
** a terminal symbol. If the lookahead is a non-terminal (as occurs after ** a terminal symbol. If the lookahead is a non-terminal (as occurs after
** a reduce action) then the yy_reduce_ofst[] array is used in place of ** a reduce action) then the yy_reduce_ofst[] array is used in place of
** the yy_shift_ofst[] array and YY_REDUCE_USE_DFLT is used in place of ** the yy_shift_ofst[] array and YY_REDUCE_USE_DFLT is used in place of
@ -213,9 +216,9 @@ typedef struct yyStackEntry yyStackEntry;
/* The state of the parser is completely contained in an instance of /* The state of the parser is completely contained in an instance of
** the following structure */ ** the following structure */
struct yyParser { struct yyParser {
int yyidx; /* Index of top element in stack */ yyStackEntry *yytos; /* Pointer to top element of the stack */
#ifdef YYTRACKMAXSTACKDEPTH #ifdef YYTRACKMAXSTACKDEPTH
int yyidxMax; /* Maximum value of yyidx */ int yyhwm; /* High-water mark of the stack */
#endif #endif
#ifndef YYNOERRORRECOVERY #ifndef YYNOERRORRECOVERY
int yyerrcnt; /* Shifts left before out of the error */ int yyerrcnt; /* Shifts left before out of the error */
@ -224,6 +227,7 @@ struct yyParser {
#if YYSTACKDEPTH<=0 #if YYSTACKDEPTH<=0
int yystksz; /* Current side of the stack */ int yystksz; /* Current side of the stack */
yyStackEntry *yystack; /* The parser's stack */ yyStackEntry *yystack; /* The parser's stack */
yyStackEntry yystk0; /* First stack entry */
#else #else
yyStackEntry yystack[YYSTACKDEPTH]; /* The parser's stack */ yyStackEntry yystack[YYSTACKDEPTH]; /* The parser's stack */
#endif #endif
@ -278,26 +282,38 @@ static const char *const yyRuleName[] = {
}; };
#endif /* NDEBUG */ #endif /* NDEBUG */
#if YYSTACKDEPTH<=0 #if YYSTACKDEPTH<=0
/* /*
** Try to increase the size of the parser stack. ** Try to increase the size of the parser stack. Return the number
** of errors. Return 0 on success.
*/ */
static void yyGrowStack(yyParser *p){ static int yyGrowStack(yyParser *p){
int newSize; int newSize;
int idx;
yyStackEntry *pNew; yyStackEntry *pNew;
newSize = p->yystksz*2 + 100; newSize = p->yystksz*2 + 100;
pNew = realloc(p->yystack, newSize*sizeof(pNew[0])); idx = p->yytos ? (int)(p->yytos - p->yystack) : 0;
if( p->yystack==&p->yystk0 ){
pNew = malloc(newSize*sizeof(pNew[0]));
if( pNew ) pNew[0] = p->yystk0;
}else{
pNew = realloc(p->yystack, newSize*sizeof(pNew[0]));
}
if( pNew ){ if( pNew ){
p->yystack = pNew; p->yystack = pNew;
p->yystksz = newSize; p->yytos = &p->yystack[idx];
#ifndef NDEBUG #ifndef NDEBUG
if( yyTraceFILE ){ if( yyTraceFILE ){
fprintf(yyTraceFILE,"%sStack grows to %d entries!\n", fprintf(yyTraceFILE,"%sStack grows from %d to %d entries.\n",
yyTracePrompt, p->yystksz); yyTracePrompt, p->yystksz, newSize);
fflush(yyTraceFILE);
} }
#endif #endif
p->yystksz = newSize;
} }
return pNew==0;
} }
#endif #endif
@ -326,15 +342,24 @@ void *ParseAlloc(void *(CDECL *mallocProc)(YYMALLOCARGTYPE)){
yyParser *pParser; yyParser *pParser;
pParser = (yyParser*)(*mallocProc)( (YYMALLOCARGTYPE)sizeof(yyParser) ); pParser = (yyParser*)(*mallocProc)( (YYMALLOCARGTYPE)sizeof(yyParser) );
if( pParser ){ if( pParser ){
pParser->yyidx = -1;
#ifdef YYTRACKMAXSTACKDEPTH #ifdef YYTRACKMAXSTACKDEPTH
pParser->yyidxMax = 0; pParser->yyhwm = 0;
#endif #endif
#if YYSTACKDEPTH<=0 #if YYSTACKDEPTH<=0
pParser->yytos = NULL;
pParser->yystack = NULL; pParser->yystack = NULL;
pParser->yystksz = 0; pParser->yystksz = 0;
yyGrowStack(pParser); if( yyGrowStack(pParser) ){
pParser->yystack = &pParser->yystk0;
pParser->yystksz = 1;
}
#endif #endif
#ifndef YYNOERRORRECOVERY
pParser->yyerrcnt = -1;
#endif
pParser->yytos = pParser->yystack;
pParser->yystack[0].stateno = 0;
pParser->yystack[0].major = 0;
} }
return pParser; return pParser;
} }
@ -378,22 +403,24 @@ static void yy_destructor(
*/ */
static void yy_pop_parser_stack(yyParser *pParser){ static void yy_pop_parser_stack(yyParser *pParser){
yyStackEntry *yytos; yyStackEntry *yytos;
assert( pParser->yyidx>=0 ); assert( pParser->yytos!=0 );
yytos = &pParser->yystack[pParser->yyidx--]; assert( pParser->yytos > pParser->yystack );
yytos = pParser->yytos--;
#ifndef NDEBUG #ifndef NDEBUG
if( yyTraceFILE ){ if( yyTraceFILE ){
fprintf(yyTraceFILE,"%sPopping %s\n", fprintf(yyTraceFILE,"%sPopping %s\n",
yyTracePrompt, yyTracePrompt,
yyTokenName[yytos->major]); yyTokenName[yytos->major]);
fflush(yyTraceFILE);
} }
#endif #endif
yy_destructor(pParser, yytos->major, &yytos->minor); yy_destructor(pParser, yytos->major, &yytos->minor);
} }
/* /*
** Deallocate and destroy a parser. Destructors are called for ** Deallocate and destroy a parser. Destructors are called for
** all stack elements before shutting the parser down. ** all stack elements before shutting the parser down.
* **
** If the YYPARSEFREENEVERNULL macro exists (for example because it ** If the YYPARSEFREENEVERNULL macro exists (for example because it
** is defined in a %include section of the input grammar) then it is ** is defined in a %include section of the input grammar) then it is
** assumed that the input pointer is never NULL. ** assumed that the input pointer is never NULL.
@ -406,9 +433,9 @@ void ParseFree(
#ifndef YYPARSEFREENEVERNULL #ifndef YYPARSEFREENEVERNULL
if( pParser==0 ) return; if( pParser==0 ) return;
#endif #endif
while( pParser->yyidx>=0 ) yy_pop_parser_stack(pParser); while( pParser->yytos>pParser->yystack ) yy_pop_parser_stack(pParser);
#if YYSTACKDEPTH<=0 #if YYSTACKDEPTH<=0
free(pParser->yystack); if( pParser->yystack!=&pParser->yystk0 ) free(pParser->yystack);
#endif #endif
(*freeProc)((void*)pParser); (*freeProc)((void*)pParser);
} }
@ -419,7 +446,7 @@ void ParseFree(
#ifdef YYTRACKMAXSTACKDEPTH #ifdef YYTRACKMAXSTACKDEPTH
int ParseStackPeak(void *p){ int ParseStackPeak(void *p){
yyParser *pParser = (yyParser*)p; yyParser *pParser = (yyParser*)p;
return pParser->yyidxMax; return pParser->yyhwm;
} }
#endif #endif
@ -432,56 +459,55 @@ static unsigned int yy_find_shift_action(
YYCODETYPE iLookAhead /* The look-ahead token */ YYCODETYPE iLookAhead /* The look-ahead token */
){ ){
int i; int i;
int stateno = pParser->yystack[pParser->yyidx].stateno; int stateno = pParser->yytos->stateno;
if( stateno>=YY_MIN_REDUCE ) return stateno; if( stateno>=YY_MIN_REDUCE ) return stateno;
assert( stateno <= YY_SHIFT_COUNT ); assert( stateno <= YY_SHIFT_COUNT );
do{ do{
i = yy_shift_ofst[stateno]; i = yy_shift_ofst[stateno];
if( i==YY_SHIFT_USE_DFLT ) return yy_default[stateno];
assert( iLookAhead!=YYNOCODE ); assert( iLookAhead!=YYNOCODE );
i += iLookAhead; i += iLookAhead;
if( i<0 || i>=YY_ACTTAB_COUNT || yy_lookahead[i]!=iLookAhead ){ if( i<0 || i>=YY_ACTTAB_COUNT || yy_lookahead[i]!=iLookAhead ){
if( iLookAhead>0 ){
#ifdef YYFALLBACK #ifdef YYFALLBACK
YYCODETYPE iFallback; /* Fallback token */ YYCODETYPE iFallback; /* Fallback token */
if( iLookAhead<sizeof(yyFallback)/sizeof(yyFallback[0]) if( iLookAhead<sizeof(yyFallback)/sizeof(yyFallback[0])
&& (iFallback = yyFallback[iLookAhead])!=0 ){ && (iFallback = yyFallback[iLookAhead])!=0 ){
#ifndef NDEBUG #ifndef NDEBUG
if( yyTraceFILE ){ if( yyTraceFILE ){
fprintf(yyTraceFILE, "%sFALLBACK %s => %s\n", fprintf(yyTraceFILE, "%sFALLBACK %s => %s\n",
yyTracePrompt, yyTokenName[iLookAhead], yyTokenName[iFallback]); yyTracePrompt, yyTokenName[iLookAhead], yyTokenName[iFallback]);
} fflush(yyTraceFILE);
#endif
assert( yyFallback[iFallback]==0 ); /* Fallback loop must terminate */
iLookAhead = iFallback;
continue;
} }
#endif
assert( yyFallback[iFallback]==0 ); /* Fallback loop must terminate */
iLookAhead = iFallback;
continue;
}
#endif #endif
#ifdef YYWILDCARD #ifdef YYWILDCARD
{ {
int j = i - iLookAhead + YYWILDCARD; int j = i - iLookAhead + YYWILDCARD;
if( if(
#if YY_SHIFT_MIN+YYWILDCARD<0 #if YY_SHIFT_MIN+YYWILDCARD<0
j>=0 && j>=0 &&
#endif #endif
#if YY_SHIFT_MAX+YYWILDCARD>=YY_ACTTAB_COUNT #if YY_SHIFT_MAX+YYWILDCARD>=YY_ACTTAB_COUNT
j<YY_ACTTAB_COUNT && j<YY_ACTTAB_COUNT &&
#endif #endif
yy_lookahead[j]==YYWILDCARD yy_lookahead[j]==YYWILDCARD && iLookAhead>0
){ ){
#ifndef NDEBUG #ifndef NDEBUG
if( yyTraceFILE ){ if( yyTraceFILE ){
fprintf(yyTraceFILE, "%sWILDCARD %s => %s\n", fprintf(yyTraceFILE, "%sWILDCARD %s => %s\n",
yyTracePrompt, yyTokenName[iLookAhead], yyTracePrompt, yyTokenName[iLookAhead],
yyTokenName[YYWILDCARD]); yyTokenName[YYWILDCARD]);
} fflush(yyTraceFILE);
#endif /* NDEBUG */
return yy_action[j];
} }
#endif /* NDEBUG */
return yy_action[j];
} }
#endif /* YYWILDCARD */
} }
#endif /* YYWILDCARD */
return yy_default[stateno]; return yy_default[stateno];
}else{ }else{
return yy_action[i]; return yy_action[i];
@ -500,7 +526,7 @@ static int yy_find_reduce_action(
int i; int i;
#ifdef YYERRORSYMBOL #ifdef YYERRORSYMBOL
if( stateno>YY_REDUCE_COUNT ){ if( stateno>YY_REDUCE_COUNT ){
return yy_default[stateno]; return yy_default[stateno];
} }
#else #else
assert( stateno<=YY_REDUCE_COUNT ); assert( stateno<=YY_REDUCE_COUNT );
@ -525,15 +551,16 @@ static int yy_find_reduce_action(
*/ */
static void yyStackOverflow(yyParser *yypParser){ static void yyStackOverflow(yyParser *yypParser){
ParseARG_FETCH; ParseARG_FETCH;
yypParser->yyidx--; yypParser->yytos--;
#ifndef NDEBUG #ifndef NDEBUG
if( yyTraceFILE ){ if( yyTraceFILE ){
fprintf(yyTraceFILE,"%sStack Overflow!\n",yyTracePrompt); fprintf(yyTraceFILE,"%sStack Overflow!\n",yyTracePrompt);
fflush(yyTraceFILE);
} }
#endif #endif
while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser); while( yypParser->yytos>yypParser->yystack ) yy_pop_parser_stack(yypParser);
/* Here code is inserted which will execute if the parser /* Here code is inserted which will execute if the parser
** stack ever overflows */ ** stack every overflows */
/******** Begin %stack_overflow code ******************************************/ /******** Begin %stack_overflow code ******************************************/
%% %%
/******** End %stack_overflow code ********************************************/ /******** End %stack_overflow code ********************************************/
@ -548,12 +575,13 @@ static void yyTraceShift(yyParser *yypParser, int yyNewState){
if( yyTraceFILE ){ if( yyTraceFILE ){
if( yyNewState<YYNSTATE ){ if( yyNewState<YYNSTATE ){
fprintf(yyTraceFILE,"%sShift '%s', go to state %d\n", fprintf(yyTraceFILE,"%sShift '%s', go to state %d\n",
yyTracePrompt,yyTokenName[yypParser->yystack[yypParser->yyidx].major], yyTracePrompt,yyTokenName[yypParser->yytos->major],
yyNewState); yyNewState);
}else{ }else{
fprintf(yyTraceFILE,"%sShift '%s'\n", fprintf(yyTraceFILE,"%sShift '%s'\n",
yyTracePrompt,yyTokenName[yypParser->yystack[yypParser->yyidx].major]); yyTracePrompt,yyTokenName[yypParser->yytos->major]);
} }
fflush(yyTraceFILE);
} }
} }
#else #else
@ -570,27 +598,30 @@ static void yy_shift(
ParseTOKENTYPE yyMinor /* The minor token to shift in */ ParseTOKENTYPE yyMinor /* The minor token to shift in */
){ ){
yyStackEntry *yytos; yyStackEntry *yytos;
yypParser->yyidx++; yypParser->yytos++;
#ifdef YYTRACKMAXSTACKDEPTH #ifdef YYTRACKMAXSTACKDEPTH
if( yypParser->yyidx>yypParser->yyidxMax ){ if( (int)(yypParser->yytos - yypParser->yystack)>yypParser->yyhwm ){
yypParser->yyidxMax = yypParser->yyidx; yypParser->yyhwm++;
assert( yypParser->yyhwm == (int)(yypParser->yytos - yypParser->yystack) );
} }
#endif #endif
#if YYSTACKDEPTH>0 #if YYSTACKDEPTH>0
if( yypParser->yyidx>=YYSTACKDEPTH ){ if( yypParser->yytos>=&yypParser->yystack[YYSTACKDEPTH] ){
yyStackOverflow(yypParser); yyStackOverflow(yypParser);
return; return;
} }
#else #else
if( yypParser->yyidx>=yypParser->yystksz ){ if( yypParser->yytos>=&yypParser->yystack[yypParser->yystksz] ){
yyGrowStack(yypParser); if( yyGrowStack(yypParser) ){
if( yypParser->yyidx>=yypParser->yystksz ){
yyStackOverflow(yypParser); yyStackOverflow(yypParser);
return; return;
} }
} }
#endif #endif
yytos = &yypParser->yystack[yypParser->yyidx]; if( yyNewState > YY_MAX_SHIFT ){
yyNewState += YY_MIN_REDUCE - YY_MIN_SHIFTREDUCE;
}
yytos = yypParser->yytos;
yytos->stateno = (YYACTIONTYPE)yyNewState; yytos->stateno = (YYACTIONTYPE)yyNewState;
yytos->major = (YYCODETYPE)yyMajor; yytos->major = (YYCODETYPE)yyMajor;
yytos->minor.yy0 = yyMinor; yytos->minor.yy0 = yyMinor;
@ -622,12 +653,13 @@ static void yy_reduce(
yyStackEntry *yymsp; /* The top of the parser's stack */ yyStackEntry *yymsp; /* The top of the parser's stack */
int yysize; /* Amount to pop the stack */ int yysize; /* Amount to pop the stack */
ParseARG_FETCH; ParseARG_FETCH;
yymsp = &yypParser->yystack[yypParser->yyidx]; yymsp = yypParser->yytos;
#ifndef NDEBUG #ifndef NDEBUG
if( yyTraceFILE && yyruleno<(int)(sizeof(yyRuleName)/sizeof(yyRuleName[0])) ){ if( yyTraceFILE && yyruleno<(int)(sizeof(yyRuleName)/sizeof(yyRuleName[0])) ){
yysize = yyRuleInfo[yyruleno].nrhs; yysize = yyRuleInfo[yyruleno].nrhs;
fprintf(yyTraceFILE, "%sReduce [%s], go to state %d.\n", yyTracePrompt, fprintf(yyTraceFILE, "%sReduce [%s], go to state %d.\n", yyTracePrompt,
yyRuleName[yyruleno], yymsp[-yysize].stateno); yyRuleName[yyruleno], yymsp[-yysize].stateno);
fflush(yyTraceFILE);
} }
#endif /* NDEBUG */ #endif /* NDEBUG */
@ -636,22 +668,23 @@ static void yy_reduce(
** enough on the stack to push the LHS value */ ** enough on the stack to push the LHS value */
if( yyRuleInfo[yyruleno].nrhs==0 ){ if( yyRuleInfo[yyruleno].nrhs==0 ){
#ifdef YYTRACKMAXSTACKDEPTH #ifdef YYTRACKMAXSTACKDEPTH
if( yypParser->yyidx>yypParser->yyidxMax ){ if( (int)(yypParser->yytos - yypParser->yystack)>yypParser->yyhwm ){
yypParser->yyidxMax = yypParser->yyidx; yypParser->yyhwm++;
assert( yypParser->yyhwm == (int)(yypParser->yytos - yypParser->yystack));
} }
#endif #endif
#if YYSTACKDEPTH>0 #if YYSTACKDEPTH>0
if( yypParser->yyidx>=YYSTACKDEPTH-1 ){ if( yypParser->yytos>=&yypParser->yystack[YYSTACKDEPTH-1] ){
yyStackOverflow(yypParser); yyStackOverflow(yypParser);
return; return;
} }
#else #else
if( yypParser->yyidx>=yypParser->yystksz-1 ){ if( yypParser->yytos>=&yypParser->yystack[yypParser->yystksz-1] ){
yyGrowStack(yypParser); if( yyGrowStack(yypParser) ){
if( yypParser->yyidx>=yypParser->yystksz-1 ){
yyStackOverflow(yypParser); yyStackOverflow(yypParser);
return; return;
} }
yymsp = yypParser->yytos;
} }
#endif #endif
} }
@ -674,15 +707,17 @@ static void yy_reduce(
yysize = yyRuleInfo[yyruleno].nrhs; yysize = yyRuleInfo[yyruleno].nrhs;
yyact = yy_find_reduce_action(yymsp[-yysize].stateno,(YYCODETYPE)yygoto); yyact = yy_find_reduce_action(yymsp[-yysize].stateno,(YYCODETYPE)yygoto);
if( yyact <= YY_MAX_SHIFTREDUCE ){ if( yyact <= YY_MAX_SHIFTREDUCE ){
if( yyact>YY_MAX_SHIFT ) yyact += YY_MIN_REDUCE - YY_MIN_SHIFTREDUCE; if( yyact>YY_MAX_SHIFT ){
yypParser->yyidx -= yysize - 1; yyact += YY_MIN_REDUCE - YY_MIN_SHIFTREDUCE;
}
yymsp -= yysize-1; yymsp -= yysize-1;
yypParser->yytos = yymsp;
yymsp->stateno = (YYACTIONTYPE)yyact; yymsp->stateno = (YYACTIONTYPE)yyact;
yymsp->major = (YYCODETYPE)yygoto; yymsp->major = (YYCODETYPE)yygoto;
yyTraceShift(yypParser, yyact); yyTraceShift(yypParser, yyact);
}else{ }else{
assert( yyact == YY_ACCEPT_ACTION ); assert( yyact == YY_ACCEPT_ACTION );
yypParser->yyidx -= yysize; yypParser->yytos -= yysize;
yy_accept(yypParser); yy_accept(yypParser);
} }
} }
@ -698,9 +733,10 @@ static void yy_parse_failed(
#ifndef NDEBUG #ifndef NDEBUG
if( yyTraceFILE ){ if( yyTraceFILE ){
fprintf(yyTraceFILE,"%sFail!\n",yyTracePrompt); fprintf(yyTraceFILE,"%sFail!\n",yyTracePrompt);
fflush(yyTraceFILE);
} }
#endif #endif
while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser); while( yypParser->yytos>yypParser->yystack ) yy_pop_parser_stack(yypParser);
/* Here code is inserted which will be executed whenever the /* Here code is inserted which will be executed whenever the
** parser fails */ ** parser fails */
/************ Begin %parse_failure code ***************************************/ /************ Begin %parse_failure code ***************************************/
@ -736,9 +772,17 @@ static void yy_accept(
#ifndef NDEBUG #ifndef NDEBUG
if( yyTraceFILE ){ if( yyTraceFILE ){
fprintf(yyTraceFILE,"%sAccept!\n",yyTracePrompt); fprintf(yyTraceFILE,"%sAccept!\n",yyTracePrompt);
fflush(yyTraceFILE);
} }
#endif #endif
while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser); #ifndef YYNOERRORRECOVERY
yypParser->yyerrcnt = -1;
#endif
#if 0
assert( yypParser->yytos==yypParser->yystack );
#else
while (yypParser->yytos>yypParser->yystack) yy_pop_parser_stack(yypParser);
#endif
/* Here code is inserted which will be executed whenever the /* Here code is inserted which will be executed whenever the
** parser accepts */ ** parser accepts */
/*********** Begin %parse_accept code *****************************************/ /*********** Begin %parse_accept code *****************************************/
@ -782,28 +826,8 @@ void Parse(
#endif #endif
yyParser *yypParser; /* The parser */ yyParser *yypParser; /* The parser */
/* (re)initialize the parser, if necessary */
yypParser = (yyParser*)yyp; yypParser = (yyParser*)yyp;
if( yypParser->yyidx<0 ){ assert( yypParser->yytos!=0 );
#if YYSTACKDEPTH<=0
if( yypParser->yystksz <=0 ){
yyStackOverflow(yypParser);
return;
}
#endif
yypParser->yyidx = 0;
#ifndef YYNOERRORRECOVERY
yypParser->yyerrcnt = -1;
#endif
yypParser->yystack[0].stateno = 0;
yypParser->yystack[0].major = 0;
#ifndef NDEBUG
if( yyTraceFILE ){
fprintf(yyTraceFILE,"%sInitialize. Empty stack. State 0\n",
yyTracePrompt);
}
#endif
}
#if !defined(YYERRORSYMBOL) && !defined(YYNOERRORRECOVERY) #if !defined(YYERRORSYMBOL) && !defined(YYNOERRORRECOVERY)
yyendofinput = (yymajor==0); yyendofinput = (yymajor==0);
#endif #endif
@ -812,13 +836,13 @@ void Parse(
#ifndef NDEBUG #ifndef NDEBUG
if( yyTraceFILE ){ if( yyTraceFILE ){
fprintf(yyTraceFILE,"%sInput '%s'\n",yyTracePrompt,yyTokenName[yymajor]); fprintf(yyTraceFILE,"%sInput '%s'\n",yyTracePrompt,yyTokenName[yymajor]);
fflush(yyTraceFILE);
} }
#endif #endif
do{ do{
yyact = yy_find_shift_action(yypParser,(YYCODETYPE)yymajor); yyact = yy_find_shift_action(yypParser,(YYCODETYPE)yymajor);
if( yyact <= YY_MAX_SHIFTREDUCE ){ if( yyact <= YY_MAX_SHIFTREDUCE ){
if( yyact > YY_MAX_SHIFT ) yyact += YY_MIN_REDUCE - YY_MIN_SHIFTREDUCE;
yy_shift(yypParser,yyact,yymajor,yyminor); yy_shift(yypParser,yyact,yymajor,yyminor);
#ifndef YYNOERRORRECOVERY #ifndef YYNOERRORRECOVERY
yypParser->yyerrcnt--; yypParser->yyerrcnt--;
@ -827,20 +851,21 @@ void Parse(
}else if( yyact <= YY_MAX_REDUCE ){ }else if( yyact <= YY_MAX_REDUCE ){
yy_reduce(yypParser,yyact-YY_MIN_REDUCE); yy_reduce(yypParser,yyact-YY_MIN_REDUCE);
}else{ }else{
assert( yyact == YY_ERROR_ACTION );
yyminorunion.yy0 = yyminor;
#ifdef YYERRORSYMBOL #ifdef YYERRORSYMBOL
int yymx; int yymx;
#endif #endif
assert( yyact == YY_ERROR_ACTION );
yyminorunion.yy0 = yyminor;
#ifndef NDEBUG #ifndef NDEBUG
if( yyTraceFILE ){ if( yyTraceFILE ){
fprintf(yyTraceFILE,"%sSyntax Error!\n",yyTracePrompt); fprintf(yyTraceFILE,"%sSyntax Error!\n",yyTracePrompt);
fflush(yyTraceFILE);
} }
#endif #endif
#ifdef YYERRORSYMBOL #ifdef YYERRORSYMBOL
/* A syntax error has occurred. /* A syntax error has occurred.
** The response to an error depends upon whether or not the ** The response to an error depends upon whether or not the
** grammar defines an error token "ERROR". ** grammar defines an error token "ERROR".
** **
** This is what we do if the grammar does define ERROR: ** This is what we do if the grammar does define ERROR:
** **
@ -860,29 +885,32 @@ void Parse(
if( yypParser->yyerrcnt<0 ){ if( yypParser->yyerrcnt<0 ){
yy_syntax_error(yypParser,yymajor,yyminor); yy_syntax_error(yypParser,yymajor,yyminor);
} }
yymx = yypParser->yystack[yypParser->yyidx].major; yymx = yypParser->yytos->major;
if( yymx==YYERRORSYMBOL || yyerrorhit ){ if( yymx==YYERRORSYMBOL || yyerrorhit ){
#ifndef NDEBUG #ifndef NDEBUG
if( yyTraceFILE ){ if( yyTraceFILE ){
fprintf(yyTraceFILE,"%sDiscard input token %s\n", fprintf(yyTraceFILE,"%sDiscard input token %s\n",
yyTracePrompt,yyTokenName[yymajor]); yyTracePrompt,yyTokenName[yymajor]);
fflush(yyTraceFILE);
} }
#endif #endif
yy_destructor(yypParser, (YYCODETYPE)yymajor, &yyminorunion); yy_destructor(yypParser, (YYCODETYPE)yymajor, &yyminorunion);
yymajor = YYNOCODE; yymajor = YYNOCODE;
}else{ }else{
while( while( yypParser->yytos >= yypParser->yystack
yypParser->yyidx >= 0 && && yymx != YYERRORSYMBOL
yymx != YYERRORSYMBOL && && (yyact = yy_find_reduce_action(
(yyact = yy_find_reduce_action( yypParser->yytos->stateno,
yypParser->yystack[yypParser->yyidx].stateno,
YYERRORSYMBOL)) >= YY_MIN_REDUCE YYERRORSYMBOL)) >= YY_MIN_REDUCE
){ ){
yy_pop_parser_stack(yypParser); yy_pop_parser_stack(yypParser);
} }
if( yypParser->yyidx < 0 || yymajor==0 ){ if( yypParser->yytos < yypParser->yystack || yymajor==0 ){
yy_destructor(yypParser,(YYCODETYPE)yymajor,&yyminorunion); yy_destructor(yypParser,(YYCODETYPE)yymajor,&yyminorunion);
yy_parse_failed(yypParser); yy_parse_failed(yypParser);
#ifndef YYNOERRORRECOVERY
yypParser->yyerrcnt = -1;
#endif
yymajor = YYNOCODE; yymajor = YYNOCODE;
}else if( yymx!=YYERRORSYMBOL ){ }else if( yymx!=YYERRORSYMBOL ){
yy_shift(yypParser,yyact,YYERRORSYMBOL,yyminor); yy_shift(yypParser,yyact,YYERRORSYMBOL,yyminor);
@ -901,7 +929,7 @@ void Parse(
yy_syntax_error(yypParser,yymajor, yyminor); yy_syntax_error(yypParser,yymajor, yyminor);
yy_destructor(yypParser,(YYCODETYPE)yymajor,&yyminorunion); yy_destructor(yypParser,(YYCODETYPE)yymajor,&yyminorunion);
yymajor = YYNOCODE; yymajor = YYNOCODE;
#else /* YYERRORSYMBOL is not defined */ #else /* YYERRORSYMBOL is not defined */
/* This is what we do if the grammar does not define ERROR: /* This is what we do if the grammar does not define ERROR:
** **
@ -919,19 +947,25 @@ void Parse(
yy_destructor(yypParser,(YYCODETYPE)yymajor,&yyminorunion); yy_destructor(yypParser,(YYCODETYPE)yymajor,&yyminorunion);
if( yyendofinput ){ if( yyendofinput ){
yy_parse_failed(yypParser); yy_parse_failed(yypParser);
#ifndef YYNOERRORRECOVERY
yypParser->yyerrcnt = -1;
#endif
} }
yymajor = YYNOCODE; yymajor = YYNOCODE;
#endif #endif
} }
}while( yymajor!=YYNOCODE && yypParser->yyidx>=0 ); }while( yymajor!=YYNOCODE && yypParser->yytos>yypParser->yystack );
#ifndef NDEBUG #ifndef NDEBUG
if( yyTraceFILE ){ if( yyTraceFILE ){
int i; yyStackEntry *i;
char cDiv = '[';
fprintf(yyTraceFILE,"%sReturn. Stack=",yyTracePrompt); fprintf(yyTraceFILE,"%sReturn. Stack=",yyTracePrompt);
for(i=1; i<=yypParser->yyidx; i++) for(i=&yypParser->yystack[1]; i<=yypParser->yytos; i++){
fprintf(yyTraceFILE,"%c%s", i==1 ? '[' : ' ', fprintf(yyTraceFILE,"%c%s", cDiv, yyTokenName[i->major]);
yyTokenName[yypParser->yystack[i].major]); cDiv = ' ';
}
fprintf(yyTraceFILE,"]\n"); fprintf(yyTraceFILE,"]\n");
fflush(yyTraceFILE);
} }
#endif #endif
return; return;

View file

@ -58,6 +58,8 @@ ACTOR Actor native //: Thinker
native float GetSpriteRotation(int ptr = AAPTR_DEFAULT); native float GetSpriteRotation(int ptr = AAPTR_DEFAULT);
native int GetMissileDamage(int mask, int add, int ptr = AAPTR_DEFAULT); native int GetMissileDamage(int mask, int add, int ptr = AAPTR_DEFAULT);
action native int OverlayID(); action native int OverlayID();
action native float OverlayX(int layer = 0);
action native float OverlayY(int layer = 0);
// Action functions // Action functions
// Meh, MBF redundant functions. Only for DeHackEd support. // Meh, MBF redundant functions. Only for DeHackEd support.
@ -209,6 +211,7 @@ ACTOR Actor native //: Thinker
native state A_JumpIfTargetInsideMeleeRange(state label); native state A_JumpIfTargetInsideMeleeRange(state label);
native state A_JumpIfInventory(class<Inventory> itemtype, int itemamount, state label, int owner = AAPTR_DEFAULT); native state A_JumpIfInventory(class<Inventory> itemtype, int itemamount, state label, int owner = AAPTR_DEFAULT);
native state A_JumpIfArmorType(name Type, state label, int amount = 1); native state A_JumpIfArmorType(name Type, state label, int amount = 1);
action native bool A_SetInventory(class<Inventory> itemtype, int amount, int ptr = AAPTR_DEFAULT, bool beyondMax = false);
native bool A_GiveInventory(class<Inventory> itemtype, int amount = 0, int giveto = AAPTR_DEFAULT); native bool A_GiveInventory(class<Inventory> itemtype, int amount = 0, int giveto = AAPTR_DEFAULT);
native bool A_TakeInventory(class<Inventory> itemtype, int amount = 0, int flags = 0, int giveto = AAPTR_DEFAULT); native bool A_TakeInventory(class<Inventory> itemtype, int amount = 0, int flags = 0, int giveto = AAPTR_DEFAULT);
action native bool A_SpawnItem(class<Actor> itemtype = "Unknown", float distance = 0, float zheight = 0, bool useammo = true, bool transfer_translation = false); action native bool A_SpawnItem(class<Actor> itemtype = "Unknown", float distance = 0, float zheight = 0, bool useammo = true, bool transfer_translation = false);

View file

@ -598,6 +598,7 @@ enum
PSPF_ADDBOB = 1 << 1, PSPF_ADDBOB = 1 << 1,
PSPF_POWDOUBLE = 1 << 2, PSPF_POWDOUBLE = 1 << 2,
PSPF_CVARFAST = 1 << 3, PSPF_CVARFAST = 1 << 3,
PSPF_FLIP = 1 << 6,
}; };
// Default psprite layers // Default psprite layers

View file

@ -52,7 +52,8 @@ ACTOR DoomImp
TROO U -1 TROO U -1
Stop Stop
Raise: Raise:
TROO MLKJI 8 TROO ML 8
TROO KJI 6
Goto See Goto See
} }
} }

View file

@ -75,12 +75,14 @@ ACTOR PointPusher
{ {
+NOBLOCKMAP +NOBLOCKMAP
+INVISIBLE +INVISIBLE
+NOCLIP
} }
ACTOR PointPuller ACTOR PointPuller
{ {
+NOBLOCKMAP +NOBLOCKMAP
+INVISIBLE +INVISIBLE
+NOCLIP
} }
// Bloody gibs ------------------------------------------------------------- // Bloody gibs -------------------------------------------------------------

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -1782,9 +1782,11 @@ DSPLYMNU_CAPFPS = "Rendering Interpolation";
DSPLYMNU_COLUMNMETHOD = "Column render mode"; DSPLYMNU_COLUMNMETHOD = "Column render mode";
DSPLYMNU_WIPETYPE = "Screen wipe style"; DSPLYMNU_WIPETYPE = "Screen wipe style";
DSPLYMNU_SHOWENDOOM = "Show ENDOOM screen"; DSPLYMNU_SHOWENDOOM = "Show ENDOOM screen";
DSPLYMNU_BLOODFADE = "Blood Flash Intensity";
DSPLYMNU_PICKUPFADE = "Pickup Flash Intensity";
DSPLYMNU_PALLETEHACK = "DirectDraw palette hack"; // Not used DSPLYMNU_PALLETEHACK = "DirectDraw palette hack"; // Not used
DSPLYMNU_ATTACHEDSURFACES = "Use attached surfaces"; // Not used DSPLYMNU_ATTACHEDSURFACES = "Use attached surfaces"; // Not used
DSPLYMNU_STRETCHSKY = "Stretch short skies"; DSPLYMNU_SKYMODE = "Sky render mode";
DSPLYMNU_DRAWFUZZ = "Use fuzz effect"; DSPLYMNU_DRAWFUZZ = "Use fuzz effect";
DSPLYMNU_TRANSSOUL = "Lost Soul translucency"; DSPLYMNU_TRANSSOUL = "Lost Soul translucency";
DSPLYMNU_FAKECONTRAST = "Use fake contrast"; DSPLYMNU_FAKECONTRAST = "Use fake contrast";
@ -2188,6 +2190,9 @@ OPTVAL_INVERTED = "Inverted";
OPTVAL_NOTINVERTED = "Not Inverted"; OPTVAL_NOTINVERTED = "Not Inverted";
OPTVAL_ORIGINAL = "Original"; OPTVAL_ORIGINAL = "Original";
OPTVAL_OPTIMIZED = "Optimized"; OPTVAL_OPTIMIZED = "Optimized";
OPTVAL_NORMAL = "Normal";
OPTVAL_STRETCH = "Stretch";
OPTVAL_CAPPED = "Capped";
OPTVAL_PARTICLES = "Particles"; OPTVAL_PARTICLES = "Particles";
OPTVAL_SPRITES = "Sprites"; OPTVAL_SPRITES = "Sprites";
OPTVAL_SPRITESPARTICLES = "Sprites & Particles"; OPTVAL_SPRITESPARTICLES = "Sprites & Particles";
@ -2711,6 +2716,8 @@ OPTVAL_SBSFULL = "Side-by-side Full";
OPTVAL_SBSNARROW = "Side-by-side Narrow"; OPTVAL_SBSNARROW = "Side-by-side Narrow";
OPTVAL_TOPBOTTOM = "Top/Bottom"; OPTVAL_TOPBOTTOM = "Top/Bottom";
OPTVAL_ROWINTERLEAVED = "Row Interleaved"; OPTVAL_ROWINTERLEAVED = "Row Interleaved";
OPTVAL_COLUMNINTERLEAVED = "Column Interleaved";
OPTVAL_CHECKERBOARD = "Checkerboard";
OPTVAL_QUADBUFFERED = "Quad-buffered"; OPTVAL_QUADBUFFERED = "Quad-buffered";
OPTVAL_UNCHARTED2 = "Uncharted 2"; OPTVAL_UNCHARTED2 = "Uncharted 2";
OPTVAL_HEJLDAWSON = "Hejl Dawson"; OPTVAL_HEJLDAWSON = "Hejl Dawson";

View file

@ -600,6 +600,13 @@ OptionValue ColumnMethods
1.0, "$OPTVAL_OPTIMIZED" 1.0, "$OPTVAL_OPTIMIZED"
} }
OptionValue SkyModes
{
0.0, "$OPTVAL_NORMAL"
1.0, "$OPTVAL_STRETCH"
2.0, "$OPTVAL_CAPPED"
}
OptionValue RocketTrailTypes OptionValue RocketTrailTypes
{ {
0.0, "$OPTVAL_OFF" 0.0, "$OPTVAL_OFF"
@ -674,6 +681,9 @@ OptionMenu "VideoOptions"
Option "$DSPLYMNU_VSYNC", "vid_vsync", "OnOff" Option "$DSPLYMNU_VSYNC", "vid_vsync", "OnOff"
Option "$DSPLYMNU_CAPFPS", "cl_capfps", "OffOn" Option "$DSPLYMNU_CAPFPS", "cl_capfps", "OffOn"
Slider "$DSPLYMNU_BLOODFADE", "blood_fade_scalar", 0.0, 1.0, 0.05, 1
Slider "$DSPLYMNU_PICKUPFADE", "pickup_fade_scalar", 0.0, 1.0, 0.05, 1
Option "$DSPLYMNU_COLUMNMETHOD", "r_columnmethod", "ColumnMethods"
StaticText " " StaticText " "
Option "$DSPLYMNU_WIPETYPE", "wipetype", "Wipes" Option "$DSPLYMNU_WIPETYPE", "wipetype", "Wipes"
@ -685,7 +695,7 @@ OptionMenu "VideoOptions"
//Option "$DSPLYMNU_ATTACHEDSURFACES", "vid_attachedsurfaces", "OnOff" //Option "$DSPLYMNU_ATTACHEDSURFACES", "vid_attachedsurfaces", "OnOff"
} }
Option "$DSPLYMNU_STRETCHSKY", "r_stretchsky", "OnOff" Option "$DSPLYMNU_SKYMODE", "r_skymode", "SkyModes"
Option "$DSPLYMNU_DRAWFUZZ", "r_drawfuzz", "Fuzziness" Option "$DSPLYMNU_DRAWFUZZ", "r_drawfuzz", "Fuzziness"
Slider "$DSPLYMNU_TRANSSOUL", "transsouls", 0.25, 1.0, 0.05, 2 Slider "$DSPLYMNU_TRANSSOUL", "transsouls", 0.25, 1.0, 0.05, 2
Option "$DSPLYMNU_FAKECONTRAST", "r_fakecontrast", "Contrast" Option "$DSPLYMNU_FAKECONTRAST", "r_fakecontrast", "Contrast"
@ -704,6 +714,7 @@ OptionMenu "VideoOptions"
Slider "$DSPLYMNU_MOVEBOB", "movebob", 0, 1.0, 0.05, 2 Slider "$DSPLYMNU_MOVEBOB", "movebob", 0, 1.0, 0.05, 2
Slider "$DSPLYMNU_STILLBOB", "stillbob", 0, 1.0, 0.05, 2 Slider "$DSPLYMNU_STILLBOB", "stillbob", 0, 1.0, 0.05, 2
Slider "$DSPLYMNU_BOBSPEED", "wbobspeed", 0, 2.0, 0.1, 2 Slider "$DSPLYMNU_BOBSPEED", "wbobspeed", 0, 2.0, 0.1, 2
} }
//------------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------------

View file

@ -188,6 +188,8 @@ OptionValue VRMode
4, "$OPTVAL_SBSNARROW" 4, "$OPTVAL_SBSNARROW"
11, "$OPTVAL_TOPBOTTOM" 11, "$OPTVAL_TOPBOTTOM"
12, "$OPTVAL_ROWINTERLEAVED" 12, "$OPTVAL_ROWINTERLEAVED"
13, "$OPTVAL_COLUMNINTERLEAVED"
14, "$OPTVAL_CHECKERBOARD"
5, "$OPTVAL_LEFTEYE" 5, "$OPTVAL_LEFTEYE"
6, "$OPTVAL_RIGHTEYE" 6, "$OPTVAL_RIGHTEYE"
7, "$OPTVAL_QUADBUFFERED" 7, "$OPTVAL_QUADBUFFERED"

View file

@ -0,0 +1,37 @@
in vec2 TexCoord;
out vec4 FragColor;
uniform sampler2D LeftEyeTexture;
uniform sampler2D RightEyeTexture;
uniform float InvGamma;
uniform float Contrast;
uniform float Brightness;
uniform int WindowPositionParity; // top-of-window might not be top-of-screen
vec4 ApplyGamma(vec4 c)
{
vec3 val = c.rgb * Contrast - (Contrast - 1.0) * 0.5;
val += Brightness * 0.5;
val = pow(max(val, vec3(0.0)), vec3(InvGamma));
return vec4(val, c.a);
}
void main()
{
int thisVerticalPixel = int(gl_FragCoord.y); // Bottom row is typically the right eye, when WindowHeight is even
int thisHorizontalPixel = int(gl_FragCoord.x); // column
bool isLeftEye = (thisVerticalPixel // because we want to alternate eye view on each row
+ thisHorizontalPixel // and each column
+ WindowPositionParity // because the window might not be aligned to the screen
) % 2 == 0;
vec4 inputColor;
if (isLeftEye) {
inputColor = texture(LeftEyeTexture, TexCoord);
}
else {
// inputColor = vec4(0, 1, 0, 1);
inputColor = texture(RightEyeTexture, TexCoord);
}
FragColor = ApplyGamma(inputColor);
}

View file

@ -0,0 +1,35 @@
in vec2 TexCoord;
out vec4 FragColor;
uniform sampler2D LeftEyeTexture;
uniform sampler2D RightEyeTexture;
uniform float InvGamma;
uniform float Contrast;
uniform float Brightness;
uniform int WindowPositionParity; // top-of-window might not be top-of-screen
vec4 ApplyGamma(vec4 c)
{
vec3 val = c.rgb * Contrast - (Contrast - 1.0) * 0.5;
val += Brightness * 0.5;
val = pow(max(val, vec3(0.0)), vec3(InvGamma));
return vec4(val, c.a);
}
void main()
{
int thisHorizontalPixel = int(gl_FragCoord.x); // zero-based column index from left
bool isLeftEye = (thisHorizontalPixel // because we want to alternate eye view on each column
+ WindowPositionParity // because the window might not be aligned to the screen
) % 2 == 0;
vec4 inputColor;
if (isLeftEye) {
inputColor = texture(LeftEyeTexture, TexCoord);
}
else {
// inputColor = vec4(0, 1, 0, 1);
inputColor = texture(RightEyeTexture, TexCoord);
}
FragColor = ApplyGamma(inputColor);
}

View file

@ -7,7 +7,7 @@ uniform sampler2D RightEyeTexture;
uniform float InvGamma; uniform float InvGamma;
uniform float Contrast; uniform float Contrast;
uniform float Brightness; uniform float Brightness;
uniform int VerticalPixelOffset; // top-of-window might not be top-of-screen uniform int WindowPositionParity; // top-of-window might not be top-of-screen
vec4 ApplyGamma(vec4 c) vec4 ApplyGamma(vec4 c)
{ {
@ -19,9 +19,9 @@ vec4 ApplyGamma(vec4 c)
void main() void main()
{ {
int thisVerticalPixel = int(gl_FragCoord.y + 1.0); // Bottom row is typically the right eye, when WindowHeight is even int thisVerticalPixel = int(gl_FragCoord.y); // Bottom row is typically the right eye, when WindowHeight is even
bool isLeftEye = (thisVerticalPixel // because we want to alternate eye view on each row bool isLeftEye = (thisVerticalPixel // because we want to alternate eye view on each row
+ VerticalPixelOffset // because the window might not be aligned to the screen + WindowPositionParity // because the window might not be aligned to the screen
) % 2 == 0; ) % 2 == 0;
vec4 inputColor; vec4 inputColor;
if (isLeftEye) { if (isLeftEye) {