- refined wall sprite check so that orthogonally aligned sprites are only aligned to orthogonal walls.

Here even the slightest deviation can create problems.
This commit is contained in:
Christoph Oelckers 2022-08-03 14:13:42 +02:00
parent cac54d42e9
commit 7debab7ff4
17 changed files with 233 additions and 41 deletions

View file

@ -12,19 +12,19 @@ struct VersionInfo
uint16_t minor; uint16_t minor;
uint32_t revision; uint32_t revision;
bool operator <=(const VersionInfo& o) const constexpr bool operator <=(const VersionInfo& o) const
{ {
return o.major > this->major || (o.major == this->major && o.minor > this->minor) || (o.major == this->major && o.minor == this->minor && o.revision >= this->revision); return o.major > this->major || (o.major == this->major && o.minor > this->minor) || (o.major == this->major && o.minor == this->minor && o.revision >= this->revision);
} }
bool operator >=(const VersionInfo& o) const constexpr bool operator >=(const VersionInfo& o) const
{ {
return o.major < this->major || (o.major == this->major && o.minor < this->minor) || (o.major == this->major && o.minor == this->minor && o.revision <= this->revision); return o.major < this->major || (o.major == this->major && o.minor < this->minor) || (o.major == this->major && o.minor == this->minor && o.revision <= this->revision);
} }
bool operator > (const VersionInfo& o) const constexpr bool operator > (const VersionInfo& o) const
{ {
return o.major < this->major || (o.major == this->major && o.minor < this->minor) || (o.major == this->major && o.minor == this->minor && o.revision < this->revision); return o.major < this->major || (o.major == this->major && o.minor < this->minor) || (o.major == this->major && o.minor == this->minor && o.revision < this->revision);
} }
bool operator < (const VersionInfo& o) const constexpr bool operator < (const VersionInfo& o) const
{ {
return o.major > this->major || (o.major == this->major && o.minor > this->minor) || (o.major == this->major && o.minor == this->minor && o.revision > this->revision); return o.major > this->major || (o.major == this->major && o.minor > this->minor) || (o.major == this->major && o.minor == this->minor && o.revision > this->revision);
} }
@ -32,7 +32,7 @@ struct VersionInfo
}; };
// Cannot be a constructor because Lemon would puke on it. // Cannot be a constructor because Lemon would puke on it.
inline VersionInfo MakeVersion(unsigned int ma, unsigned int mi, unsigned int re = 0) constexpr VersionInfo MakeVersion(unsigned int ma, unsigned int mi, unsigned int re = 0)
{ {
return{ (uint16_t)ma, (uint16_t)mi, (uint32_t)re }; return{ (uint16_t)ma, (uint16_t)mi, (uint32_t)re };
} }

View file

@ -484,6 +484,7 @@ void OpenGLFrameBuffer::SetSaveBuffers(bool yes)
void OpenGLFrameBuffer::BeginFrame() void OpenGLFrameBuffer::BeginFrame()
{ {
SetViewportRects(nullptr); SetViewportRects(nullptr);
mViewpoints->Clear();
if (GLRenderer != nullptr) if (GLRenderer != nullptr)
GLRenderer->BeginFrame(); GLRenderer->BeginFrame();
} }

View file

@ -44,7 +44,8 @@
static TArray<FString> m_Extensions; static TArray<FString> m_Extensions;
RenderContext gl; RenderContext gl;
static double realglversion; // this is public so the statistics code can access it. static double realglversion;
static bool bindless;
//========================================================================== //==========================================================================
// //
@ -156,7 +157,7 @@ void gl_LoadExtensions()
#ifdef _WIN32 #ifdef _WIN32
if (strstr(gl.vendorstring, "ATI Tech")) if (strstr(gl.vendorstring, "ATI Tech"))
{ {
gl.flags |= RFL_NO_CLIP_PLANES; // gl_ClipDistance is horribly broken on ATI GL3 drivers for Windows. (TBD: Relegate to vintage build? Maybe after the next survey.) gl.flags |= RFL_NO_CLIP_PLANES; // gl_ClipDistance is horribly broken on ATI GL3 drivers for Windows.
} }
#endif #endif
gl.glslversion = 3.31f; // Force GLSL down to 3.3. gl.glslversion = 3.31f; // Force GLSL down to 3.3.
@ -201,6 +202,8 @@ void gl_LoadExtensions()
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &gl.max_texturesize); glGetIntegerv(GL_MAX_TEXTURE_SIZE, &gl.max_texturesize);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
bindless = CheckExtension("GL_ARB_bindless_texture");
} }
//========================================================================== //==========================================================================
@ -247,9 +250,14 @@ void gl_PrintStartupLog()
} }
} }
void setGlVersion(double glv)
{
realglversion = glv;
}
std::pair<double, bool> gl_getInfo() std::pair<double, bool> gl_getInfo()
{ {
// gl_ARB_bindless_texture is the closest we can get to determine Vulkan support from OpenGL. // gl_ARB_bindless_texture is the closest we can get to determine Vulkan support from OpenGL.
// This isn't foolproof because Intel doesn't support it but for NVidia and AMD support of this extension means Vulkan support. // This isn't foolproof because Intel doesn't support it but for NVidia and AMD support of this extension means Vulkan support.
return std::make_pair(realglversion, CheckExtension("GL_ARB_bindless_texture")); return std::make_pair(realglversion, bindless);
} }

View file

@ -369,6 +369,7 @@ void OpenGLFrameBuffer::WaitForCommands(bool finish)
void OpenGLFrameBuffer::BeginFrame() void OpenGLFrameBuffer::BeginFrame()
{ {
SetViewportRects(nullptr); SetViewportRects(nullptr);
mViewpoints->Clear();
if (GLRenderer != nullptr) if (GLRenderer != nullptr)
GLRenderer->BeginFrame(); GLRenderer->BeginFrame();
} }

View file

@ -22,6 +22,7 @@ public:
explicit OpenGLFrameBuffer() {} explicit OpenGLFrameBuffer() {}
OpenGLFrameBuffer(void *hMonitor, bool fullscreen) ; OpenGLFrameBuffer(void *hMonitor, bool fullscreen) ;
~OpenGLFrameBuffer(); ~OpenGLFrameBuffer();
int Backend() override { return 0; }
void InitializeState() override; void InitializeState() override;
void Update() override; void Update() override;

View file

@ -9,6 +9,7 @@ CVAR(Bool, gles_use_mapped_buffer, false, 0);
CVAR(Bool, gles_force_glsl_v100, false, 0); CVAR(Bool, gles_force_glsl_v100, false, 0);
CVAR(Int, gles_max_lights_per_surface, 32, 0); CVAR(Int, gles_max_lights_per_surface, 32, 0);
EXTERN_CVAR(Bool, gl_customshader); EXTERN_CVAR(Bool, gl_customshader);
void setGlVersion(double glv);
#if USE_GLES2 #if USE_GLES2
@ -191,5 +192,9 @@ namespace OpenGLESRenderer
#endif #endif
gles.numlightvectors = (gles.maxlights * LIGHT_VEC4_NUM); gles.numlightvectors = (gles.maxlights * LIGHT_VEC4_NUM);
const char* glversion = (const char*)glGetString(GL_VERSION);
setGlVersion( strtod(glversion, NULL));
} }
} }

View file

@ -117,11 +117,16 @@ int HWViewpointBuffer::SetViewpoint(FRenderState &di, HWViewpointUniforms *vp)
void HWViewpointBuffer::Clear() void HWViewpointBuffer::Clear()
{ {
bool needNewPipeline = mUploadIndex > 0; // Clear might be called multiple times before any actual rendering
mUploadIndex = 0; mUploadIndex = 0;
mClipPlaneInfo.Clear(); mClipPlaneInfo.Clear();
mPipelinePos++; if (needNewPipeline)
mPipelinePos %= mPipelineNbr; {
mPipelinePos++;
mPipelinePos %= mPipelineNbr;
}
mBuffer = mBufferPipeline[mPipelinePos]; mBuffer = mBufferPipeline[mPipelinePos];
} }

View file

@ -419,6 +419,7 @@ TArray<uint8_t> VulkanFrameBuffer::GetScreenshotBuffer(int &pitch, ESSType &colo
void VulkanFrameBuffer::BeginFrame() void VulkanFrameBuffer::BeginFrame()
{ {
SetViewportRects(nullptr); SetViewportRects(nullptr);
mViewpoints->Clear();
mCommands->BeginFrame(); mCommands->BeginFrame();
mTextureManager->BeginFrame(); mTextureManager->BeginFrame();
mScreenBuffers->BeginFrame(screen->mScreenViewport.width, screen->mScreenViewport.height, screen->mSceneViewport.width, screen->mSceneViewport.height); mScreenBuffers->BeginFrame(screen->mScreenViewport.width, screen->mScreenViewport.height, screen->mSceneViewport.width, screen->mSceneViewport.height);

View file

@ -104,8 +104,8 @@ FCompileContext::FCompileContext(PNamespace *cg, PFunction *fnc, PPrototype *ret
if (fnc != nullptr) Class = fnc->OwningClass; if (fnc != nullptr) Class = fnc->OwningClass;
} }
FCompileContext::FCompileContext(PNamespace *cg, PContainerType *cls, bool fromdecorate) FCompileContext::FCompileContext(PNamespace *cg, PContainerType *cls, bool fromdecorate, const VersionInfo& info)
: ReturnProto(nullptr), Function(nullptr), Class(cls), FromDecorate(fromdecorate), StateIndex(-1), StateCount(0), Lump(-1), CurGlobals(cg) : ReturnProto(nullptr), Function(nullptr), Class(cls), FromDecorate(fromdecorate), StateIndex(-1), StateCount(0), Lump(-1), CurGlobals(cg), Version(info)
{ {
} }
@ -2678,13 +2678,26 @@ FxBinary::~FxBinary()
// //
//========================================================================== //==========================================================================
bool FxBinary::Promote(FCompileContext &ctx, bool forceint) bool FxBinary::Promote(FCompileContext &ctx, bool forceint, bool shiftop)
{ {
// math operations of unsigned ints results in an unsigned int. (16 and 8 bit values never get here, they get promoted to regular ints elsewhere already.) // math operations of unsigned ints results in an unsigned int. (16 and 8 bit values never get here, they get promoted to regular ints elsewhere already.)
if (left->ValueType == TypeUInt32 && right->ValueType == TypeUInt32) if (left->ValueType == TypeUInt32 && right->ValueType == TypeUInt32)
{ {
ValueType = TypeUInt32; ValueType = TypeUInt32;
} }
// If one side is an unsigned 32-bit int and the other side is a signed 32-bit int, the signed side is implicitly converted to unsigned,
else if (!ctx.FromDecorate && left->ValueType == TypeUInt32 && right->ValueType == TypeSInt32 && !shiftop && ctx.Version >= MakeVersion(4, 9, 0))
{
right = new FxIntCast(right, false, false, true);
right = right->Resolve(ctx);
ValueType = TypeUInt32;
}
else if (!ctx.FromDecorate && left->ValueType == TypeSInt32 && right->ValueType == TypeUInt32 && !shiftop && ctx.Version >= MakeVersion(4, 9, 0))
{
left = new FxIntCast(left, false, false, true);
left = left->Resolve(ctx);
ValueType = TypeUInt32;
}
else if (left->IsInteger() && right->IsInteger()) else if (left->IsInteger() && right->IsInteger())
{ {
ValueType = TypeSInt32; // Addition and subtraction forces all integer-derived types to signed int. ValueType = TypeSInt32; // Addition and subtraction forces all integer-derived types to signed int.
@ -2728,6 +2741,15 @@ bool FxBinary::Promote(FCompileContext &ctx, bool forceint)
delete this; delete this;
return false; return false;
} }
// shift operators are different: The left operand defines the type and the right operand must always be made unsigned
if (shiftop)
{
ValueType = left->ValueType == TypeUInt32 ? TypeUInt32 : TypeSInt32;
right = new FxIntCast(right, false, false, true);
right = right->Resolve(ctx);
}
return true; return true;
} }
@ -3324,6 +3346,59 @@ FxExpression *FxCompareRel::Resolve(FCompileContext& ctx)
} }
else if (left->IsNumeric() && right->IsNumeric()) else if (left->IsNumeric() && right->IsNumeric())
{ {
if (left->IsInteger() && right->IsInteger())
{
if (ctx.Version >= MakeVersion(4, 9, 0))
{
// We need to do more checks here to catch problem cases.
if (left->ValueType == TypeUInt32 && right->ValueType == TypeSInt32)
{
if (left->isConstant() && !right->isConstant())
{
auto val = static_cast<FxConstant*>(left)->GetValue().GetUInt();
if (val > INT_MAX)
{
ScriptPosition.Message(MSG_WARNING, "Comparison of signed value with out of range unsigned constant");
}
}
else if (right->isConstant() && !left->isConstant())
{
auto val = static_cast<FxConstant*>(right)->GetValue().GetInt();
if (val < 0)
{
ScriptPosition.Message(MSG_WARNING, "Comparison of unsigned value with negative constant");
}
}
else if (!left->isConstant() && !right->isConstant())
{
ScriptPosition.Message(MSG_WARNING, "Comparison between signed and unsigned value");
}
}
else if (left->ValueType == TypeSInt32 && right->ValueType == TypeUInt32)
{
if (left->isConstant() && !right->isConstant())
{
auto val = static_cast<FxConstant*>(left)->GetValue().GetInt();
if (val < 0)
{
ScriptPosition.Message(MSG_WARNING, "Comparison of unsigned value with negative constant");
}
}
else if (right->isConstant() && !left->isConstant())
{
auto val = static_cast<FxConstant*>(right)->GetValue().GetUInt();
if (val > INT_MAX)
{
ScriptPosition.Message(MSG_WARNING, "Comparison of signed value with out of range unsigned constant");
}
}
else if (!left->isConstant() && !right->isConstant())
{
ScriptPosition.Message(MSG_WARNING, "Comparison between signed and unsigned value");
}
}
}
}
Promote(ctx); Promote(ctx);
} }
else else
@ -3929,7 +4004,7 @@ FxExpression *FxShift::Resolve(FCompileContext& ctx)
if (left->IsNumeric() && right->IsNumeric()) if (left->IsNumeric() && right->IsNumeric())
{ {
if (!Promote(ctx, true)) return nullptr; if (!Promote(ctx, true, true)) return nullptr;
if ((left->ValueType == TypeUInt32 && ctx.Version >= MakeVersion(3, 7)) && Operator == TK_RShift) Operator = TK_URShift; if ((left->ValueType == TypeUInt32 && ctx.Version >= MakeVersion(3, 7)) && Operator == TK_RShift) Operator = TK_URShift;
} }
else else
@ -8233,7 +8308,7 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx)
member->membervar = newfield; member->membervar = newfield;
Self = nullptr; Self = nullptr;
delete this; delete this;
member->ValueType = TypeUInt32; member->ValueType = TypeSInt32;
return member; return member;
} }
else else

View file

@ -93,7 +93,7 @@ struct FCompileContext
FString VersionString; FString VersionString;
FCompileContext(PNamespace *spc, PFunction *func, PPrototype *ret, bool fromdecorate, int stateindex, int statecount, int lump, const VersionInfo &ver); FCompileContext(PNamespace *spc, PFunction *func, PPrototype *ret, bool fromdecorate, int stateindex, int statecount, int lump, const VersionInfo &ver);
FCompileContext(PNamespace *spc, PContainerType *cls, bool fromdecorate); // only to be used to resolve constants! FCompileContext(PNamespace *spc, PContainerType *cls, bool fromdecorate, const VersionInfo& ver); // only to be used to resolve constants!
PSymbol *FindInClass(FName identifier, PSymbolTable *&symt); PSymbol *FindInClass(FName identifier, PSymbolTable *&symt);
PSymbol *FindInSelfClass(FName identifier, PSymbolTable *&symt); PSymbol *FindInSelfClass(FName identifier, PSymbolTable *&symt);
@ -910,7 +910,7 @@ public:
FxBinary(int, FxExpression*, FxExpression*); FxBinary(int, FxExpression*, FxExpression*);
~FxBinary(); ~FxBinary();
bool Promote(FCompileContext &ctx, bool forceint = false); bool Promote(FCompileContext &ctx, bool forceint = false, bool shiftop = false);
}; };
//========================================================================== //==========================================================================

View file

@ -334,6 +334,7 @@ void PType::StaticInit()
TypeVector2->moveOp = OP_MOVEV2; TypeVector2->moveOp = OP_MOVEV2;
TypeVector2->RegType = REGT_FLOAT; TypeVector2->RegType = REGT_FLOAT;
TypeVector2->RegCount = 2; TypeVector2->RegCount = 2;
TypeVector2->isOrdered = true;
TypeVector3 = new PStruct(NAME_Vector3, nullptr); TypeVector3 = new PStruct(NAME_Vector3, nullptr);
TypeVector3->AddField(NAME_X, TypeFloat64); TypeVector3->AddField(NAME_X, TypeFloat64);
@ -347,6 +348,7 @@ void PType::StaticInit()
TypeVector3->moveOp = OP_MOVEV3; TypeVector3->moveOp = OP_MOVEV3;
TypeVector3->RegType = REGT_FLOAT; TypeVector3->RegType = REGT_FLOAT;
TypeVector3->RegCount = 3; TypeVector3->RegCount = 3;
TypeVector3->isOrdered = true;
TypeFVector2 = new PStruct(NAME_FVector2, nullptr); TypeFVector2 = new PStruct(NAME_FVector2, nullptr);
@ -358,6 +360,7 @@ void PType::StaticInit()
TypeFVector2->moveOp = OP_MOVEV2; TypeFVector2->moveOp = OP_MOVEV2;
TypeFVector2->RegType = REGT_FLOAT; TypeFVector2->RegType = REGT_FLOAT;
TypeFVector2->RegCount = 2; TypeFVector2->RegCount = 2;
TypeFVector2->isOrdered = true;
TypeFVector3 = new PStruct(NAME_FVector3, nullptr); TypeFVector3 = new PStruct(NAME_FVector3, nullptr);
TypeFVector3->AddField(NAME_X, TypeFloat32); TypeFVector3->AddField(NAME_X, TypeFloat32);
@ -371,6 +374,7 @@ void PType::StaticInit()
TypeFVector3->moveOp = OP_MOVEV3; TypeFVector3->moveOp = OP_MOVEV3;
TypeFVector3->RegType = REGT_FLOAT; TypeFVector3->RegType = REGT_FLOAT;
TypeFVector3->RegCount = 3; TypeFVector3->RegCount = 3;
TypeFVector3->isOrdered = true;
Namespaces.GlobalNamespace->Symbols.AddSymbol(Create<PSymbolType>(NAME_sByte, TypeSInt8)); Namespaces.GlobalNamespace->Symbols.AddSymbol(Create<PSymbolType>(NAME_sByte, TypeSInt8));
Namespaces.GlobalNamespace->Symbols.AddSymbol(Create<PSymbolType>(NAME_Byte, TypeUInt8)); Namespaces.GlobalNamespace->Symbols.AddSymbol(Create<PSymbolType>(NAME_Byte, TypeUInt8));

View file

@ -537,6 +537,7 @@ public:
PStruct(FName name, PTypeBase *outer, bool isnative = false); PStruct(FName name, PTypeBase *outer, bool isnative = false);
bool isNative; bool isNative;
bool isOrdered = false;
// Some internal structs require explicit construction and destruction of fields the VM cannot handle directly so use these two functions for it. // Some internal structs require explicit construction and destruction of fields the VM cannot handle directly so use these two functions for it.
VMFunction *mConstructor = nullptr; VMFunction *mConstructor = nullptr;
VMFunction *mDestructor = nullptr; VMFunction *mDestructor = nullptr;

View file

@ -68,7 +68,7 @@ const char * ZCCCompiler::GetStringConst(FxExpression *ex, FCompileContext &ctx)
int ZCCCompiler::IntConstFromNode(ZCC_TreeNode *node, PContainerType *cls) int ZCCCompiler::IntConstFromNode(ZCC_TreeNode *node, PContainerType *cls)
{ {
FCompileContext ctx(OutNamespace, cls, false); FCompileContext ctx(OutNamespace, cls, false, mVersion);
FxExpression *ex = new FxIntCast(ConvertNode(node), false); FxExpression *ex = new FxIntCast(ConvertNode(node), false);
ex = ex->Resolve(ctx); ex = ex->Resolve(ctx);
if (ex == nullptr) return 0; if (ex == nullptr) return 0;
@ -82,7 +82,7 @@ int ZCCCompiler::IntConstFromNode(ZCC_TreeNode *node, PContainerType *cls)
FString ZCCCompiler::StringConstFromNode(ZCC_TreeNode *node, PContainerType *cls) FString ZCCCompiler::StringConstFromNode(ZCC_TreeNode *node, PContainerType *cls)
{ {
FCompileContext ctx(OutNamespace, cls, false); FCompileContext ctx(OutNamespace, cls, false, mVersion);
FxExpression *ex = new FxStringCast(ConvertNode(node)); FxExpression *ex = new FxStringCast(ConvertNode(node));
ex = ex->Resolve(ctx); ex = ex->Resolve(ctx);
if (ex == nullptr) return ""; if (ex == nullptr) return "";
@ -1144,7 +1144,7 @@ void ZCCCompiler::AddConstant(ZCC_ConstantWork &constant)
bool ZCCCompiler::CompileConstant(ZCC_ConstantWork *work) bool ZCCCompiler::CompileConstant(ZCC_ConstantWork *work)
{ {
FCompileContext ctx(OutNamespace, work->cls, false); FCompileContext ctx(OutNamespace, work->cls, false, mVersion);
FxExpression *exp = ConvertNode(work->node->Value); FxExpression *exp = ConvertNode(work->node->Value);
try try
{ {
@ -1185,7 +1185,7 @@ void ZCCCompiler::CompileArrays(ZCC_StructWork *work)
ConvertNodeList(values, sas->Values); ConvertNodeList(values, sas->Values);
bool fail = false; bool fail = false;
FCompileContext ctx(OutNamespace, work->Type(), false); FCompileContext ctx(OutNamespace, work->Type(), false, mVersion);
char *destmem = (char *)ClassDataAllocator.Alloc(values.Size() * ztype->Align); char *destmem = (char *)ClassDataAllocator.Alloc(values.Size() * ztype->Align);
memset(destmem, 0, values.Size() * ztype->Align); memset(destmem, 0, values.Size() * ztype->Align);
@ -1325,7 +1325,7 @@ void ZCCCompiler::CompileAllFields()
{ {
// Create copies of the arrays which can be altered // Create copies of the arrays which can be altered
auto Classes = this->Classes; auto Classes = this->Classes;
auto Structs = this->Structs; auto Structs = OrderStructs();
TMap<FName, bool> HasNativeChildren; TMap<FName, bool> HasNativeChildren;
// first step: Look for native classes with native children. // first step: Look for native classes with native children.
@ -1612,6 +1612,83 @@ bool ZCCCompiler::CompileFields(PContainerType *type, TArray<ZCC_VarDeclarator *
return Fields.Size() == 0; return Fields.Size() == 0;
} }
//==========================================================================
//
// ZCCCompiler :: OrderStructs
//
// Order the Structs array so that the least-dependant structs come first
//
//==========================================================================
TArray<ZCC_StructWork *> ZCCCompiler::OrderStructs()
{
TArray<ZCC_StructWork *> new_order;
for (auto struct_def : Structs)
{
if (std::find(new_order.begin(), new_order.end(), struct_def) != new_order.end())
{
continue;
}
AddStruct(new_order, struct_def);
}
return new_order;
}
//==========================================================================
//
// ZCCCompiler :: AddStruct
//
// Adds a struct to the Structs array, preceded by all its dependant structs
//
//==========================================================================
void ZCCCompiler::AddStruct(TArray<ZCC_StructWork *> &new_order, ZCC_StructWork *my_def)
{
PStruct *my_type = static_cast<PStruct *>(my_def->Type());
if (my_type)
{
if (my_type->isOrdered)
{
return;
}
my_type->isOrdered = true;
}
// Find all struct fields and add them before this one
for (const auto field : my_def->Fields)
{
PType *fieldtype = DetermineType(my_type, field, field->Names->Name, field->Type, true, true);
if (fieldtype->isStruct() && !static_cast<PStruct *>(fieldtype)->isOrdered)
{
AddStruct(new_order, StructTypeToWork(static_cast<PStruct *>(fieldtype)));
}
}
new_order.Push(my_def);
}
//==========================================================================
//
// ZCCCompiler :: StructTypeToWork
//
// Find the ZCC_StructWork that corresponds to a PStruct
//
//==========================================================================
ZCC_StructWork *ZCCCompiler::StructTypeToWork(const PStruct *type) const
{
assert(type->isStruct());
for (auto &def : Structs)
{
if (def->Type() == type)
{
return def;
}
}
assert(false && "Struct not found");
return nullptr;
}
//========================================================================== //==========================================================================
// //
// ZCCCompiler :: FieldFlagsToString // ZCCCompiler :: FieldFlagsToString
@ -1937,7 +2014,7 @@ PType *ZCCCompiler::ResolveArraySize(PType *baseType, ZCC_Expression *arraysize,
indices = std::move(fixedIndices); indices = std::move(fixedIndices);
} }
FCompileContext ctx(OutNamespace, cls, false); FCompileContext ctx(OutNamespace, cls, false, mVersion);
for (auto index : indices) for (auto index : indices)
{ {
// There is no float->int casting here. // There is no float->int casting here.
@ -2270,7 +2347,7 @@ void ZCCCompiler::CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool
FxExpression *x = new FxTypeCast(ConvertNode(p->Default), type, false); FxExpression *x = new FxTypeCast(ConvertNode(p->Default), type, false);
FCompileContext ctx(OutNamespace, c->Type(), false); FCompileContext ctx(OutNamespace, c->Type(), false, mVersion);
x = x->Resolve(ctx); x = x->Resolve(ctx);
if (x != nullptr) if (x != nullptr)
@ -2731,7 +2808,14 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast, bool substitute)
} }
else if (cnst->Type->isInt()) else if (cnst->Type->isInt())
{ {
return new FxConstant(cnst->IntVal, *ast); if (cnst->Type == TypeUInt32)
{
return new FxConstant((unsigned)cnst->IntVal, *ast);
}
else
{
return new FxConstant(cnst->IntVal, *ast);
}
} }
else if (cnst->Type == TypeBool) else if (cnst->Type == TypeBool)
{ {

View file

@ -135,6 +135,9 @@ protected:
PType *DetermineType(PType *outertype, ZCC_TreeNode *field, FName name, ZCC_Type *ztype, bool allowarraytypes, bool formember); PType *DetermineType(PType *outertype, ZCC_TreeNode *field, FName name, ZCC_Type *ztype, bool allowarraytypes, bool formember);
PType *ResolveArraySize(PType *baseType, ZCC_Expression *arraysize, PContainerType *cls, bool *nosize); PType *ResolveArraySize(PType *baseType, ZCC_Expression *arraysize, PContainerType *cls, bool *nosize);
PType *ResolveUserType(ZCC_BasicType *type, PSymbolTable *sym, bool nativetype); PType *ResolveUserType(ZCC_BasicType *type, PSymbolTable *sym, bool nativetype);
TArray<ZCC_StructWork *> OrderStructs();
void AddStruct(TArray<ZCC_StructWork *> &new_order, ZCC_StructWork *struct_def);
ZCC_StructWork *StructTypeToWork(const PStruct *type) const;
void CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool forclass); void CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool forclass);

View file

@ -998,7 +998,7 @@ DEFINE_ACTION_FUNCTION(DOptionMenuItemCommand, DoCommand)
} }
UnsafeExecutionScope scope(unsafe); UnsafeExecutionScope scope(unsafe);
C_DoCommand(cmd); AddCommandString(cmd);
return 0; return 0;
} }

View file

@ -70,24 +70,27 @@ static walltype* IsOnWall(tspritetype* tspr, int height, DVector2& outpos)
// angle of the sprite must either be the wall's normal or the negative wall's normal to be aligned. // angle of the sprite must either be the wall's normal or the negative wall's normal to be aligned.
if (deltaang >= 512 - maxangdelta && deltaang <= 512 + maxangdelta) if (deltaang >= 512 - maxangdelta && deltaang <= 512 + maxangdelta)
{ {
// orthogonal lines do not check the actual position so that certain off-sector sprites get handled properly. if (!((tspr->ang) & 510))
// In Wanton Destruction's airplane level there's such a sprite assigned to the wrong sector.
if (d.X == 0)
{ {
double newdist = fabs(tx - wal.pos.X); // orthogonal lines do not check the actual position so that certain off-sector sprites get handled properly.
if (newdist < maxorthdist) // In Wanton Destruction's airplane level there's such a sprite assigned to the wrong sector.
if (d.X == 0)
{ {
maxorthdist = newdist; double newdist = fabs(tx - wal.pos.X);
best = &wal; if (newdist < maxorthdist)
{
maxorthdist = newdist;
best = &wal;
}
} }
} else if (d.Y == 0)
else if (d.Y == 0)
{
double newdist = fabs(ty - wal.pos.Y);
if (newdist < maxorthdist)
{ {
maxorthdist = newdist; double newdist = fabs(ty - wal.pos.Y);
best = &wal; if (newdist < maxorthdist)
{
maxorthdist = newdist;
best = &wal;
}
} }
} }
else else

View file

@ -49,7 +49,7 @@ const char *GetVersionString();
#define RC_PRODUCTVERSION2 VERSIONSTR #define RC_PRODUCTVERSION2 VERSIONSTR
// These are for content versioning. // These are for content versioning.
#define VER_MAJOR 4 #define VER_MAJOR 4
#define VER_MINOR 7 #define VER_MINOR 9
#define VER_REVISION 0 #define VER_REVISION 0
#define ENG_MAJOR 1 #define ENG_MAJOR 1