From 62e91b23bdb246f784e22f76bbfdee3b7fcd832f Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Wed, 1 Nov 2017 15:24:05 +0200 Subject: [PATCH 01/29] Extended String.LastIndexOf() with endIndex parameter https://forum.zdoom.org/viewtopic.php?t=57326 --- src/scripting/thingdef_data.cpp | 3 ++- wadsrc/static/zscript/base.txt | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/scripting/thingdef_data.cpp b/src/scripting/thingdef_data.cpp index a90cb3566..540b61a36 100644 --- a/src/scripting/thingdef_data.cpp +++ b/src/scripting/thingdef_data.cpp @@ -1264,7 +1264,8 @@ DEFINE_ACTION_FUNCTION(FStringStruct, LastIndexOf) { PARAM_SELF_STRUCT_PROLOGUE(FString); PARAM_STRING(substr); - ACTION_RETURN_INT(self->LastIndexOf(substr)); + PARAM_INT_DEF(endIndex); + ACTION_RETURN_INT(self->LastIndexOf(substr, endIndex)); } DEFINE_ACTION_FUNCTION(FStringStruct, ToUpper) diff --git a/wadsrc/static/zscript/base.txt b/wadsrc/static/zscript/base.txt index a6866f0ff..9cba0cb09 100644 --- a/wadsrc/static/zscript/base.txt +++ b/wadsrc/static/zscript/base.txt @@ -688,7 +688,7 @@ struct StringStruct native native int CharCodeAt(int pos) const; native String Filter(); native int IndexOf(String substr, int startIndex = 0) const; - native int LastIndexOf(String substr) const; + native int LastIndexOf(String substr, int endIndex = 2147483647) const; native void ToUpper(); native void ToLower(); native int ToInt(int base = 0) const; From de7d8995d5a2e2d69b3a73a21090f391511df198 Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Thu, 2 Nov 2017 14:45:35 +0200 Subject: [PATCH 02/29] Added string representation of 'static const' token No more 'Unknown(-141)' in 'Expecting ...' error message --- src/sc_man_tokens.h | 1 + src/scripting/zscript/zcc_parser.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/src/sc_man_tokens.h b/src/sc_man_tokens.h index b24cb369d..33be1c6ae 100644 --- a/src/sc_man_tokens.h +++ b/src/sc_man_tokens.h @@ -147,4 +147,5 @@ xx(TK_Offset, "'offset'") xx(TK_Slow, "'slow'") xx(TK_Bright, "'bright'") xx(TK_Let, "'let'") +xx(TK_StaticConst, "'static const'") #undef xx diff --git a/src/scripting/zscript/zcc_parser.cpp b/src/scripting/zscript/zcc_parser.cpp index e843b70de..a0af21c14 100644 --- a/src/scripting/zscript/zcc_parser.cpp +++ b/src/scripting/zscript/zcc_parser.cpp @@ -211,6 +211,7 @@ static void InitTokenMap() TOKENDEF2(TK_Color, ZCC_COLOR, NAME_Color); TOKENDEF2(TK_Sound, ZCC_SOUND, NAME_Sound); TOKENDEF2(TK_Let, ZCC_LET, NAME_let); + TOKENDEF2(TK_StaticConst, ZCC_STATICCONST,NAME_Staticconst); TOKENDEF (TK_Identifier, ZCC_IDENTIFIER); TOKENDEF (TK_StringConst, ZCC_STRCONST); From 587f6f0f91277f25f4ebc1f4c929df96fc39e560 Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Thu, 2 Nov 2017 14:49:08 +0200 Subject: [PATCH 03/29] Added wait for debugger feature to Cocoa backend Use -wait_for_debugger command line switch to display message box on startup It's available in Debug configuration only --- src/posix/cocoa/i_main.mm | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/posix/cocoa/i_main.mm b/src/posix/cocoa/i_main.mm index 4ac42261a..fd3e9a737 100644 --- a/src/posix/cocoa/i_main.mm +++ b/src/posix/cocoa/i_main.mm @@ -551,6 +551,16 @@ int main(int argc, char** argv) { s_restartedFromWADPicker = true; } +#if _DEBUG + else if (0 == strcmp(argument, "-wait_for_debugger")) + { + NSAlert* alert = [[NSAlert alloc] init]; + [alert setMessageText:@GAMENAME]; + [alert setInformativeText:@"Waiting for debugger..."]; + [alert addButtonWithTitle:@"Continue"]; + [alert runModal]; + } +#endif // _DEBUG else { s_argvStorage.Push(argument); From 57de598e4824d53a29acb69e706f559bcb3f420a Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Thu, 2 Nov 2017 15:51:13 +0200 Subject: [PATCH 04/29] Added implicit scope for if/else, while and do/while statements in ZScript Scope is added only for variable or constant definition so it will no longer leak to outer scope https://forum.zdoom.org/viewtopic.php?t=57848 --- src/scripting/zscript/zcc_compile.cpp | 49 +++++++++++++++++++++++++-- src/scripting/zscript/zcc_compile.h | 1 + 2 files changed, 47 insertions(+), 3 deletions(-) diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index 71f8e6d35..597180605 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -3495,7 +3495,9 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast) case AST_IfStmt: { auto iff = static_cast(ast); - return new FxIfStatement(ConvertNode(iff->Condition), ConvertNode(iff->TruePath), ConvertNode(iff->FalsePath), *ast); + FxExpression *const truePath = ConvertImplicitScopeNode(ast, iff->TruePath); + FxExpression *const falsePath = ConvertImplicitScopeNode(ast, iff->FalsePath); + return new FxIfStatement(ConvertNode(iff->Condition), truePath, falsePath, *ast); } case AST_IterationStmt: @@ -3504,7 +3506,8 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast) if (iter->CheckAt == ZCC_IterationStmt::End) { assert(iter->LoopBumper == nullptr); - return new FxDoWhileLoop(ConvertNode(iter->LoopCondition), ConvertNode(iter->LoopStatement), *ast); + FxExpression *const loop = ConvertImplicitScopeNode(ast, iter->LoopStatement); + return new FxDoWhileLoop(ConvertNode(iter->LoopCondition), loop, *ast); } else if (iter->LoopBumper != nullptr) { @@ -3520,7 +3523,8 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast) } else { - return new FxWhileLoop(ConvertNode(iter->LoopCondition), ConvertNode(iter->LoopStatement), *ast); + FxExpression *const loop = ConvertImplicitScopeNode(ast, iter->LoopStatement); + return new FxWhileLoop(ConvertNode(iter->LoopCondition), loop, *ast); } } @@ -3584,6 +3588,45 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast) return nullptr; } +//========================================================================== +// +// Wrapper around ConvertNode() that adds a scope (a compound statement) +// when needed to avoid leaking of variable or contant to an outer scope: +// +// if (true) int i; else bool b[1]; +// while (false) readonly a; +// do static const float f[] = {0}; while (false); +// +// Accessing such variables outside of their statements is now an error +// +//========================================================================== + +FxExpression *ZCCCompiler::ConvertImplicitScopeNode(ZCC_TreeNode *node, ZCC_Statement *nested) +{ + assert(nullptr != node); + + if (nullptr == nested) + { + return nullptr; + } + + FxExpression *nestedExpr = ConvertNode(nested); + assert(nullptr != nestedExpr); + + const EZCCTreeNodeType nestedType = nested->NodeType; + const bool needScope = AST_LocalVarStmt == nestedType || AST_StaticArrayStatement == nestedType; + + if (needScope) + { + FxCompoundStatement *implicitCompound = new FxCompoundStatement(*node); + implicitCompound->Add(nestedExpr); + + nestedExpr = implicitCompound; + } + + return nestedExpr; +} + FArgumentList &ZCCCompiler::ConvertNodeList(FArgumentList &args, ZCC_TreeNode *head) { diff --git a/src/scripting/zscript/zcc_compile.h b/src/scripting/zscript/zcc_compile.h index baa5c89f6..9a4a0af8b 100644 --- a/src/scripting/zscript/zcc_compile.h +++ b/src/scripting/zscript/zcc_compile.h @@ -145,6 +145,7 @@ private: FxExpression *ConvertAST(PContainerType *cclass, ZCC_TreeNode *ast); FxExpression *ConvertNode(ZCC_TreeNode *node); + FxExpression *ConvertImplicitScopeNode(ZCC_TreeNode *node, ZCC_Statement *nested); FArgumentList &ConvertNodeList(FArgumentList &, ZCC_TreeNode *head); DObject *Outer; From 81ea9fb372d0c677be4d8883f83c1164d98713af Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Thu, 2 Nov 2017 18:01:13 +0200 Subject: [PATCH 05/29] Added runtime check for negative array indices in VM https://forum.zdoom.org/viewtopic.php?t=57886 --- src/scripting/vm/vmexec.h | 15 +++++++++++++++ src/scripting/vm/vmops.h | 6 +++--- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/src/scripting/vm/vmexec.h b/src/scripting/vm/vmexec.h index ec5da180f..37c0093fa 100644 --- a/src/scripting/vm/vmexec.h +++ b/src/scripting/vm/vmexec.h @@ -899,6 +899,11 @@ static int Exec(VMFrameStack *stack, const VMOP *pc, VMReturn *ret, int numret) ThrowAbortException(X_ARRAY_OUT_OF_BOUNDS, "Max.index = %u, current index = %u\n", BC, reg.d[a]); return 0; } + else if (reg.d[a] < 0) + { + ThrowAbortException(X_ARRAY_OUT_OF_BOUNDS, "Negative current index = %i\n", reg.d[a]); + return 0; + } NEXTOP; OP(BOUND_K): @@ -908,6 +913,11 @@ static int Exec(VMFrameStack *stack, const VMOP *pc, VMReturn *ret, int numret) ThrowAbortException(X_ARRAY_OUT_OF_BOUNDS, "Max.index = %u, current index = %u\n", konstd[BC], reg.d[a]); return 0; } + else if (reg.d[a] < 0) + { + ThrowAbortException(X_ARRAY_OUT_OF_BOUNDS, "Negative current index = %i\n", reg.d[a]); + return 0; + } NEXTOP; OP(BOUND_R): @@ -917,6 +927,11 @@ static int Exec(VMFrameStack *stack, const VMOP *pc, VMReturn *ret, int numret) ThrowAbortException(X_ARRAY_OUT_OF_BOUNDS, "Max.index = %u, current index = %u\n", reg.d[B], reg.d[a]); return 0; } + else if (reg.d[a] < 0) + { + ThrowAbortException(X_ARRAY_OUT_OF_BOUNDS, "Negative current index = %i\n", reg.d[a]); + return 0; + } NEXTOP; OP(CONCAT): diff --git a/src/scripting/vm/vmops.h b/src/scripting/vm/vmops.h index 97102f5de..cfdf3fce2 100644 --- a/src/scripting/vm/vmops.h +++ b/src/scripting/vm/vmops.h @@ -122,9 +122,9 @@ xx(THROW, throw, THROW, NOP, 0, 0), // A == 0: Throw exception object pB // A == 2: (pB == ) then pc++ ; next instruction must JMP to another CATCH // A == 3: (pkB == ) then pc++ ; next instruction must JMP to another CATCH // for A > 0, exception is stored in pC -xx(BOUND, bound, RII16, NOP, 0, 0), // if rA >= BC, throw exception -xx(BOUND_K, bound, LKI, NOP, 0, 0), // if rA >= const[BC], throw exception -xx(BOUND_R, bound, RIRI, NOP, 0, 0), // if rA >= rB, throw exception +xx(BOUND, bound, RII16, NOP, 0, 0), // if rA < 0 or rA >= BC, throw exception +xx(BOUND_K, bound, LKI, NOP, 0, 0), // if rA < 0 or rA >= const[BC], throw exception +xx(BOUND_R, bound, RIRI, NOP, 0, 0), // if rA < 0 or rA >= rB, throw exception // String instructions. xx(CONCAT, concat, RSRSRS, NOP, 0, 0), // sA = sB..sC From dac5777a7095d457ea296b9bd9dc14b525d60665 Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Fri, 3 Nov 2017 12:44:28 +0200 Subject: [PATCH 06/29] Removed obsolete declarations from codegen.h --- src/scripting/backend/codegen.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/scripting/backend/codegen.h b/src/scripting/backend/codegen.h index 58ac84d85..8ee32423f 100644 --- a/src/scripting/backend/codegen.h +++ b/src/scripting/backend/codegen.h @@ -319,8 +319,6 @@ protected: } public: - FxExpression *CheckIntForName(); - virtual ~FxExpression() {} virtual FxExpression *Resolve(FCompileContext &ctx); @@ -2132,7 +2130,6 @@ class FxLocalVariableDeclaration : public FxExpression public: int StackOffset = -1; int RegNum = -1; - bool constructed = false; FxLocalVariableDeclaration(PType *type, FName name, FxExpression *initval, int varflags, const FScriptPosition &p); ~FxLocalVariableDeclaration(); From 8104ef5189bd2dd42745e47c15d2f984b4213ec3 Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Fri, 3 Nov 2017 13:33:36 +0200 Subject: [PATCH 07/29] Added warning for uninitialized variables in ZScript https://forum.zdoom.org/viewtopic.php?t=57868 --- src/scripting/backend/codegen.cpp | 36 +++++++++++++++++++++++++++---- src/scripting/backend/codegen.h | 9 ++++++-- 2 files changed, 39 insertions(+), 6 deletions(-) diff --git a/src/scripting/backend/codegen.cpp b/src/scripting/backend/codegen.cpp index 564240203..1de09e741 100644 --- a/src/scripting/backend/codegen.cpp +++ b/src/scripting/backend/codegen.cpp @@ -2692,6 +2692,7 @@ FxExpression *FxMultiAssign::Resolve(FCompileContext &ctx) for (unsigned i = 0; i < Base.Size(); i++) { auto singlevar = new FxLocalVariableDeclaration(rets[i], NAME_None, nullptr, 0, ScriptPosition); + singlevar->IsInitialized = true; LocalVarContainer->Add(singlevar); Base[i] = Base[i]->Resolve(ctx); ABORT(Base[i]); @@ -6031,7 +6032,7 @@ FxExpression *FxIdentifier::Resolve(FCompileContext& ctx) } else { - auto x = new FxStackVariable(local->ValueType, local->StackOffset, ScriptPosition); + auto x = new FxStackVariable(local, ScriptPosition); delete this; return x->Resolve(ctx); } @@ -6520,6 +6521,7 @@ FxLocalVariable::FxLocalVariable(FxLocalVariableDeclaration *var, const FScriptP FxExpression *FxLocalVariable::Resolve(FCompileContext &ctx) { CHECKRESOLVED(); + IsLocalVariable = ctx.FunctionArgs.Find(Variable) == ctx.FunctionArgs.Size(); return this; } @@ -6553,7 +6555,16 @@ ExpEmit FxLocalVariable::Emit(VMFunctionBuilder *build) { ExpEmit ret(Variable->RegNum + RegOffset, Variable->ValueType->GetRegType(), false, true); ret.RegCount = ValueType->GetRegCount(); - if (AddressRequested) ret.Target = true; + if (AddressRequested) + { + Variable->IsInitialized = true; + ret.Target = true; + } + else if (IsLocalVariable) + { + Variable->WarnIfUninitialized(ScriptPosition); + } + return ret; } } @@ -6895,8 +6906,9 @@ ExpEmit FxCVar::Emit(VMFunctionBuilder *build) // //========================================================================== -FxStackVariable::FxStackVariable(PType *type, int offset, const FScriptPosition &pos) - : FxMemberBase(EFX_StackVariable, Create(NAME_None, type, 0, offset), pos) +FxStackVariable::FxStackVariable(FxLocalVariableDeclaration *var, const FScriptPosition &pos) + : FxMemberBase(EFX_StackVariable, Create(NAME_None, var->ValueType, 0, var->StackOffset), pos) + , Variable(var) { } @@ -6947,6 +6959,8 @@ ExpEmit FxStackVariable::Emit(VMFunctionBuilder *build) if (AddressRequested) { + Variable->IsInitialized = true; + if (offsetreg >= 0) { ExpEmit obj(build, REGT_POINTER); @@ -6958,6 +6972,10 @@ ExpEmit FxStackVariable::Emit(VMFunctionBuilder *build) return build->FramePointer; } } + else + { + Variable->WarnIfUninitialized(ScriptPosition); + } ExpEmit loc(build, membervar->Type->GetRegType(), membervar->Type->GetRegCount()); if (membervar->BitValue == -1) @@ -11403,6 +11421,16 @@ void FxLocalVariableDeclaration::Release(VMFunctionBuilder *build) // For that all local stack variables need to live for the entire execution of a function. } +void FxLocalVariableDeclaration::WarnIfUninitialized(const FScriptPosition &varPos) const +{ + if (!IsInitialized && nullptr == Init) + { + varPos.Message(MSG_WARNING, + "Usage of uninitialized variable '%s' defined at line %i", + Name.GetChars(), ScriptPosition.ScriptLine); + } +} + FxStaticArray::FxStaticArray(PType *type, FName name, FArgumentList &args, const FScriptPosition &pos) : FxLocalVariableDeclaration(NewArray(type, args.Size()), name, nullptr, VARF_Static|VARF_ReadOnly, pos) diff --git a/src/scripting/backend/codegen.h b/src/scripting/backend/codegen.h index 8ee32423f..f035039e2 100644 --- a/src/scripting/backend/codegen.h +++ b/src/scripting/backend/codegen.h @@ -1425,6 +1425,7 @@ class FxLocalVariable : public FxExpression public: FxLocalVariableDeclaration *Variable; bool AddressRequested; + bool IsLocalVariable; // false for function parameter and true otherwise int RegOffset; FxLocalVariable(FxLocalVariableDeclaration*, const FScriptPosition&); @@ -1442,7 +1443,9 @@ public: class FxStackVariable : public FxMemberBase { public: - FxStackVariable(PType *type, int offset, const FScriptPosition&); + FxLocalVariableDeclaration *Variable; + + FxStackVariable(FxLocalVariableDeclaration*, const FScriptPosition&); ~FxStackVariable(); FxExpression *Resolve(FCompileContext&); bool RequestAddress(FCompileContext &ctx, bool *writable); @@ -2121,6 +2124,7 @@ class FxLocalVariableDeclaration : public FxExpression { friend class FxCompoundStatement; friend class FxLocalVariable; + friend class FxStackVariable; friend class FxStaticArrayVariable; FName Name; @@ -2130,6 +2134,7 @@ class FxLocalVariableDeclaration : public FxExpression public: int StackOffset = -1; int RegNum = -1; + bool IsInitialized = false; FxLocalVariableDeclaration(PType *type, FName name, FxExpression *initval, int varflags, const FScriptPosition &p); ~FxLocalVariableDeclaration(); @@ -2137,7 +2142,7 @@ public: ExpEmit Emit(VMFunctionBuilder *build); void Release(VMFunctionBuilder *build); void SetReg(ExpEmit reginfo); - + void WarnIfUninitialized(const FScriptPosition &varPos) const; }; //========================================================================== From fafc636476f3b8ddd97fd2585d3a6f9f217eee20 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 3 Nov 2017 17:27:32 +0100 Subject: [PATCH 08/29] - allow allocating constructor of TArray to also reserve the allocated data and use this to properly handle the precalc arrays for the texture resizer. --- src/gl/textures/gl_hwtexture.cpp | 4 ++-- src/tarray.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/gl/textures/gl_hwtexture.cpp b/src/gl/textures/gl_hwtexture.cpp index ac789504e..f6edec687 100644 --- a/src/gl/textures/gl_hwtexture.cpp +++ b/src/gl/textures/gl_hwtexture.cpp @@ -93,8 +93,8 @@ void FHardwareTexture::Resize(int width, int height, unsigned char *src_data, un // down we will need to gather a grid of pixels of the size of the scale // factor in each direction and then do an averaging of the pixels. - TArray vPrecalcs(height); - TArray hPrecalcs(width); + TArray vPrecalcs(height, true); + TArray hPrecalcs(width, true); ResampleBoxPrecalc(vPrecalcs, texheight); ResampleBoxPrecalc(hPrecalcs, texwidth); diff --git a/src/tarray.h b/src/tarray.h index 92a456550..acc080012 100644 --- a/src/tarray.h +++ b/src/tarray.h @@ -132,10 +132,10 @@ public: Count = 0; Array = NULL; } - TArray (int max) + TArray (int max, bool reserve = false) { Most = max; - Count = 0; + Count = reserve? max : 0; Array = (T *)M_Malloc (sizeof(T)*max); } TArray (const TArray &other) From a1562c5a767fd372d80e1834872b6e9af8592470 Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Sun, 5 Nov 2017 10:11:43 +0200 Subject: [PATCH 09/29] Use Xcode 9.1 for Travis builds --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 17dcd24b7..39893dd2b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,7 +11,7 @@ git: matrix: include: - os: osx - osx_image: xcode9 + osx_image: xcode9.1 env: - CMAKE_OPTIONS="-DCMAKE_BUILD_TYPE=Release -DCMAKE_OSX_DEPLOYMENT_TARGET=10.7" From ba298ccd6e7414a4f425c21e8ad5b0d8cf434ab7 Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Sun, 5 Nov 2017 10:12:02 +0200 Subject: [PATCH 10/29] Added GCC 4.9 to Travis configuration --- .travis.yml | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/.travis.yml b/.travis.yml index 39893dd2b..c7ff08eaa 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,6 +15,19 @@ matrix: env: - CMAKE_OPTIONS="-DCMAKE_BUILD_TYPE=Release -DCMAKE_OSX_DEPLOYMENT_TARGET=10.7" + - os: linux + compiler: gcc + env: + - GCC_VERSION=4.9 + - CMAKE_OPTIONS="-DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_FLAGS=-Wno-maybe-uninitialized" + addons: + apt: + sources: + - ubuntu-toolchain-r-test + packages: + - g++-4.9 + - libsdl2-dev + - os: linux compiler: gcc env: From bd08568b90f9227055761f893565d4c886710b7c Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Sun, 5 Nov 2017 13:28:56 +0100 Subject: [PATCH 11/29] - Fix wrong math for model/light distance check --- src/gl/scene/gl_spritelight.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/gl/scene/gl_spritelight.cpp b/src/gl/scene/gl_spritelight.cpp index 8853f0c19..e348956bf 100644 --- a/src/gl/scene/gl_spritelight.cpp +++ b/src/gl/scene/gl_spritelight.cpp @@ -209,12 +209,12 @@ void gl_SetDynModelLight(AActor *self, bool hudmodel) { int group = subsector->sector->PortalGroup; DVector3 pos = light->PosRelative(group); - float radius = light->GetRadius(); + float radius = light->GetRadius() + self->renderradius; double dx = pos.X - x; double dy = pos.Y - y; double dz = pos.Z - z; double distSquared = dx * dx + dy * dy + dz * dz; - if (distSquared < radiusSquared + radius * radius) // Light and actor touches + if (distSquared < radius * radius) // Light and actor touches { if (std::find(addedLights.begin(), addedLights.end(), light) == addedLights.end()) // Check if we already added this light from a different subsector { From 274951839aa0d7fdb74b119fa83ff28215a5ea3b Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Sun, 5 Nov 2017 13:15:42 +0200 Subject: [PATCH 12/29] Removed unused parameter from several functions in FStateDefinitions class MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit src/p_states.cpp:724:54: warning: parameter ‘actor’ set but not used [-Wunused-but-set-parameter] https://forum.zdoom.org/viewtopic.php?t=58364 --- src/info.cpp | 6 ++---- src/p_states.cpp | 18 ++++++++---------- src/scripting/thingdef.h | 6 +++--- 3 files changed, 13 insertions(+), 17 deletions(-) diff --git a/src/info.cpp b/src/info.cpp index 94b263105..28feeb826 100644 --- a/src/info.cpp +++ b/src/info.cpp @@ -322,18 +322,16 @@ bool PClassActor::SetReplacement(FName replaceName) void AActor::Finalize(FStateDefinitions &statedef) { - AActor *defaults = this; - try { - statedef.FinishStates(GetClass(), defaults); + statedef.FinishStates(GetClass()); } catch (CRecoverableError &) { statedef.MakeStateDefines(nullptr); throw; } - statedef.InstallStates(GetClass(), defaults); + statedef.InstallStates(GetClass(), this); statedef.MakeStateDefines(nullptr); } diff --git a/src/p_states.cpp b/src/p_states.cpp index 8ec19e653..a330bec76 100644 --- a/src/p_states.cpp +++ b/src/p_states.cpp @@ -721,7 +721,7 @@ void FStateDefinitions::RetargetStates (intptr_t count, const char *target) // //========================================================================== -FState *FStateDefinitions::ResolveGotoLabel (AActor *actor, PClassActor *mytype, char *name) +FState *FStateDefinitions::ResolveGotoLabel (PClassActor *mytype, char *name) { PClassActor *type = mytype; FState *state; @@ -741,7 +741,6 @@ FState *FStateDefinitions::ResolveGotoLabel (AActor *actor, PClassActor *mytype, if (stricmp (classname, "Super") == 0) { type = ValidateActor(type->ParentClass); - actor = GetDefaultByType(type); } else { @@ -763,7 +762,6 @@ FState *FStateDefinitions::ResolveGotoLabel (AActor *actor, PClassActor *mytype, if (type != stype) { type = static_cast(stype); - actor = GetDefaultByType (type); } } } @@ -836,16 +834,16 @@ void FStateDefinitions::FixStatePointers (PClassActor *actor, TArray & list) +void FStateDefinitions::ResolveGotoLabels (PClassActor *actor, TArray & list) { for (unsigned i = 0; i < list.Size(); i++) { if (list[i].State != NULL && list[i].DefineFlags == SDF_LABEL) { // It's not a valid state, so it must be a label string. Resolve it. - list[i].State = ResolveGotoLabel (defaults, actor, (char *)list[i].State); + list[i].State = ResolveGotoLabel (actor, (char *)list[i].State); list[i].DefineFlags = SDF_STATE; } - if (list[i].Children.Size() > 0) ResolveGotoLabels(actor, defaults, list[i].Children); + if (list[i].Children.Size() > 0) ResolveGotoLabels(actor, list[i].Children); } } @@ -1004,7 +1002,7 @@ int FStateDefinitions::AddStates(FState *state, const char *framechars, const FS // //========================================================================== -int FStateDefinitions::FinishStates(PClassActor *actor, AActor *defaults) +int FStateDefinitions::FinishStates(PClassActor *actor) { int count = StateArray.Size(); @@ -1023,7 +1021,7 @@ int FStateDefinitions::FinishStates(PClassActor *actor, AActor *defaults) FixStatePointers(actor, StateLabels); // Fix state pointers that are gotos - ResolveGotoLabels(actor, defaults, StateLabels); + ResolveGotoLabels(actor, StateLabels); for (i = 0; i < count; i++) { @@ -1047,7 +1045,7 @@ int FStateDefinitions::FinishStates(PClassActor *actor, AActor *defaults) break; case SDF_LABEL: - realstates[i].NextState = ResolveGotoLabel(defaults, actor, (char *)realstates[i].NextState); + realstates[i].NextState = ResolveGotoLabel(actor, (char *)realstates[i].NextState); break; } } @@ -1055,7 +1053,7 @@ int FStateDefinitions::FinishStates(PClassActor *actor, AActor *defaults) else { // Fix state pointers that are gotos - ResolveGotoLabels(actor, defaults, StateLabels); + ResolveGotoLabels(actor, StateLabels); } return count; } diff --git a/src/scripting/thingdef.h b/src/scripting/thingdef.h index 29e648797..0d59dce5c 100644 --- a/src/scripting/thingdef.h +++ b/src/scripting/thingdef.h @@ -113,9 +113,9 @@ class FStateDefinitions FStateDefine *FindStateAddress(const char *name); FState *FindState(const char *name); - FState *ResolveGotoLabel(AActor *actor, PClassActor *mytype, char *name); + FState *ResolveGotoLabel(PClassActor *mytype, char *name); static void FixStatePointers(PClassActor *actor, TArray & list); - void ResolveGotoLabels(PClassActor *actor, AActor *defaults, TArray & list); + void ResolveGotoLabels(PClassActor *actor, TArray & list); public: FStateDefinitions() @@ -129,7 +129,7 @@ public: void AddStateLabel(const char *statename); int GetStateLabelIndex (FName statename); void InstallStates(PClassActor *info, AActor *defaults); - int FinishStates(PClassActor *actor, AActor *defaults); + int FinishStates(PClassActor *actor); void MakeStateDefines(const PClassActor *cls); void AddStateDefines(const FStateLabels *list); From 61ead4f4701a79b5f4d4f53fa73d534ebe15b244 Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Sun, 5 Nov 2017 13:18:22 +0200 Subject: [PATCH 13/29] Better STL compatibility for array iterator Extended iterator with types and functions required to use array objects in STL algorithms --- src/tarray.h | 33 +++++++++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/src/tarray.h b/src/tarray.h index acc080012..63eeb4eed 100644 --- a/src/tarray.h +++ b/src/tarray.h @@ -39,6 +39,7 @@ #include #include #include +#include #if !defined(_WIN32) #include // for intptr_t @@ -48,13 +49,37 @@ #include "m_alloc.h" -template class TIterator +template class TIterator : public std::iterator { public: + typedef typename TIterator::value_type value_type; + typedef typename TIterator::difference_type difference_type; + typedef typename TIterator::pointer pointer; + typedef typename TIterator::reference reference; + typedef typename TIterator::iterator_category iterator_category; + TIterator(T* ptr = nullptr) { m_ptr = ptr; } - bool operator==(const TIterator& other) const { return (m_ptr == other.m_ptr); } - bool operator!=(const TIterator& other) const { return (m_ptr != other.m_ptr); } - TIterator &operator++() { ++m_ptr; return (*this); } + + // Comparison operators + bool operator==(const TIterator &other) const { return m_ptr == other.m_ptr; } + bool operator!=(const TIterator &other) const { return m_ptr != other.m_ptr; } + bool operator< (const TIterator &other) const { return m_ptr < other.m_ptr; } + bool operator<=(const TIterator &other) const { return m_ptr <= other.m_ptr; } + bool operator> (const TIterator &other) const { return m_ptr > other.m_ptr; } + bool operator>=(const TIterator &other) const { return m_ptr >= other.m_ptr; } + + // Arithmetic operators + TIterator &operator++() { ++m_ptr; return *this; } + TIterator operator++(int) { pointer tmp = m_ptr; ++*this; return TIterator(tmp); } + TIterator &operator--() { --m_ptr; return *this; } + TIterator operator--(int) { pointer tmp = m_ptr; --*this; return TIterator(tmp); } + TIterator &operator+=(difference_type offset) { m_ptr += offset; return *this; } + TIterator operator+(difference_type offset) const { return TIterator(m_ptr + offset); } + friend TIterator operator+(difference_type offset, const TIterator &other) { return TIterator(offset + other.m_ptr); } + TIterator &operator-=(difference_type offset) { m_ptr -= offset; return *this; } + TIterator operator-(difference_type offset) const { return TIterator(m_ptr - offset); } + difference_type operator-(const TIterator &other) const { return m_ptr - other.m_ptr; } + T &operator*() { return *m_ptr; } const T &operator*() const { return *m_ptr; } T* operator->() { return m_ptr; } From 23e5d817469c2b3e84739b3b5a9ced44cca29d6f Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Sun, 5 Nov 2017 15:32:42 +0100 Subject: [PATCH 14/29] - Implement VSMatrix::inverseMatrix --- src/gl/data/gl_matrix.cpp | 210 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 210 insertions(+) diff --git a/src/gl/data/gl_matrix.cpp b/src/gl/data/gl_matrix.cpp index 115882857..9063fc59b 100644 --- a/src/gl/data/gl_matrix.cpp +++ b/src/gl/data/gl_matrix.cpp @@ -484,3 +484,213 @@ VSMatrix::multMatrix(FLOATTYPE *resMat, const FLOATTYPE *aMatrix) } memcpy(resMat, res, 16 * sizeof(FLOATTYPE)); } + +static double mat3Determinant(const FLOATTYPE *mMat3x3) +{ + return mMat3x3[0] * (mMat3x3[4] * mMat3x3[8] - mMat3x3[5] * mMat3x3[7]) + + mMat3x3[1] * (mMat3x3[5] * mMat3x3[6] - mMat3x3[8] * mMat3x3[3]) + + mMat3x3[2] * (mMat3x3[3] * mMat3x3[7] - mMat3x3[4] * mMat3x3[6]); +} + +static double mat4Determinant(const FLOATTYPE *matrix) +{ + FLOATTYPE mMat3x3_a[9] = + { + matrix[1 * 4 + 1], matrix[2 * 4 + 1], matrix[3 * 4 + 1], + matrix[1 * 4 + 2], matrix[2 * 4 + 2], matrix[3 * 4 + 2], + matrix[1 * 4 + 3], matrix[2 * 4 + 3], matrix[3 * 4 + 3] + }; + + FLOATTYPE mMat3x3_b[9] = + { + matrix[1 * 4 + 0], matrix[2 * 4 + 0], matrix[3 * 4 + 0], + matrix[1 * 4 + 2], matrix[2 * 4 + 2], matrix[3 * 4 + 2], + matrix[1 * 4 + 3], matrix[2 * 4 + 3], matrix[3 * 4 + 3] + }; + + FLOATTYPE mMat3x3_c[9] = + { + matrix[1 * 4 + 0], matrix[2 * 4 + 0], matrix[3 * 4 + 0], + matrix[1 * 4 + 1], matrix[2 * 4 + 1], matrix[3 * 4 + 1], + matrix[1 * 4 + 3], matrix[2 * 4 + 3], matrix[3 * 4 + 3] + }; + + FLOATTYPE mMat3x3_d[9] = + { + matrix[1 * 4 + 0], matrix[2 * 4 + 0], matrix[3 * 4 + 0], + matrix[1 * 4 + 1], matrix[2 * 4 + 1], matrix[3 * 4 + 1], + matrix[1 * 4 + 2], matrix[2 * 4 + 2], matrix[3 * 4 + 2] + }; + + FLOATTYPE a, b, c, d; + FLOATTYPE value; + + a = mat3Determinant(mMat3x3_a); + b = mat3Determinant(mMat3x3_b); + c = mat3Determinant(mMat3x3_c); + d = mat3Determinant(mMat3x3_d); + + value = matrix[0 * 4 + 0] * a; + value -= matrix[0 * 4 + 1] * b; + value += matrix[0 * 4 + 2] * c; + value -= matrix[0 * 4 + 3] * d; + + return value; +} + +static void mat4Adjoint(const FLOATTYPE *matrix, FLOATTYPE *result) +{ + FLOATTYPE mMat3x3_a[9] = + { + matrix[1 * 4 + 1], matrix[2 * 4 + 1], matrix[3 * 4 + 1], + matrix[1 * 4 + 2], matrix[2 * 4 + 2], matrix[3 * 4 + 2], + matrix[1 * 4 + 3], matrix[2 * 4 + 3], matrix[3 * 4 + 3] + }; + + FLOATTYPE mMat3x3_b[9] = + { + matrix[1 * 4 + 0], matrix[2 * 4 + 0], matrix[3 * 4 + 0], + matrix[1 * 4 + 2], matrix[2 * 4 + 2], matrix[3 * 4 + 2], + matrix[1 * 4 + 3], matrix[2 * 4 + 3], matrix[3 * 4 + 3] + }; + + FLOATTYPE mMat3x3_c[9] = + { + matrix[1 * 4 + 0], matrix[2 * 4 + 0], matrix[3 * 4 + 0], + matrix[1 * 4 + 1], matrix[2 * 4 + 1], matrix[3 * 4 + 1], + matrix[1 * 4 + 3], matrix[2 * 4 + 3], matrix[3 * 4 + 3] + }; + + FLOATTYPE mMat3x3_d[9] = + { + matrix[1 * 4 + 0], matrix[2 * 4 + 0], matrix[3 * 4 + 0], + matrix[1 * 4 + 1], matrix[2 * 4 + 1], matrix[3 * 4 + 1], + matrix[1 * 4 + 2], matrix[2 * 4 + 2], matrix[3 * 4 + 2] + }; + + FLOATTYPE mMat3x3_e[9] = + { + matrix[0 * 4 + 1], matrix[2 * 4 + 1], matrix[3 * 4 + 1], + matrix[0 * 4 + 2], matrix[2 * 4 + 2], matrix[3 * 4 + 2], + matrix[0 * 4 + 3], matrix[2 * 4 + 3], matrix[3 * 4 + 3] + }; + + FLOATTYPE mMat3x3_f[9] = + { + matrix[0 * 4 + 0], matrix[2 * 4 + 0], matrix[3 * 4 + 0], + matrix[0 * 4 + 2], matrix[2 * 4 + 2], matrix[3 * 4 + 2], + matrix[0 * 4 + 3], matrix[2 * 4 + 3], matrix[3 * 4 + 3] + }; + + FLOATTYPE mMat3x3_g[9] = + { + matrix[0 * 4 + 0], matrix[2 * 4 + 0], matrix[3 * 4 + 0], + matrix[0 * 4 + 1], matrix[2 * 4 + 1], matrix[3 * 4 + 1], + matrix[0 * 4 + 3], matrix[2 * 4 + 3], matrix[3 * 4 + 3] + }; + + FLOATTYPE mMat3x3_h[9] = + { + matrix[0 * 4 + 0], matrix[2 * 4 + 0], matrix[3 * 4 + 0], + matrix[0 * 4 + 1], matrix[2 * 4 + 1], matrix[3 * 4 + 1], + matrix[0 * 4 + 2], matrix[2 * 4 + 2], matrix[3 * 4 + 2] + }; + + FLOATTYPE mMat3x3_i[9] = + { + matrix[0 * 4 + 1], matrix[1 * 4 + 1], matrix[3 * 4 + 1], + matrix[0 * 4 + 2], matrix[1 * 4 + 2], matrix[3 * 4 + 2], + matrix[0 * 4 + 3], matrix[1 * 4 + 3], matrix[3 * 4 + 3] + }; + + FLOATTYPE mMat3x3_j[9] = + { + matrix[0 * 4 + 0], matrix[1 * 4 + 0], matrix[3 * 4 + 0], + matrix[0 * 4 + 2], matrix[1 * 4 + 2], matrix[3 * 4 + 2], + matrix[0 * 4 + 3], matrix[1 * 4 + 3], matrix[3 * 4 + 3] + }; + + FLOATTYPE mMat3x3_k[9] = + { + matrix[0 * 4 + 0], matrix[1 * 4 + 0], matrix[3 * 4 + 0], + matrix[0 * 4 + 1], matrix[1 * 4 + 1], matrix[3 * 4 + 1], + matrix[0 * 4 + 3], matrix[1 * 4 + 3], matrix[3 * 4 + 3] + }; + + FLOATTYPE mMat3x3_l[9] = + { + matrix[0 * 4 + 0], matrix[1 * 4 + 0], matrix[3 * 4 + 0], + matrix[0 * 4 + 1], matrix[1 * 4 + 1], matrix[3 * 4 + 1], + matrix[0 * 4 + 2], matrix[1 * 4 + 2], matrix[3 * 4 + 2] + }; + + FLOATTYPE mMat3x3_m[9] = + { + matrix[0 * 4 + 1], matrix[1 * 4 + 1], matrix[2 * 4 + 1], + matrix[0 * 4 + 2], matrix[1 * 4 + 2], matrix[2 * 4 + 2], + matrix[0 * 4 + 3], matrix[1 * 4 + 3], matrix[2 * 4 + 3] + }; + + FLOATTYPE mMat3x3_n[9] = + { + matrix[0 * 4 + 0], matrix[1 * 4 + 0], matrix[2 * 4 + 0], + matrix[0 * 4 + 2], matrix[1 * 4 + 2], matrix[2 * 4 + 2], + matrix[0 * 4 + 3], matrix[1 * 4 + 3], matrix[2 * 4 + 3] + }; + + FLOATTYPE mMat3x3_o[9] = + { + matrix[0 * 4 + 0], matrix[1 * 4 + 0], matrix[2 * 4 + 0], + matrix[0 * 4 + 1], matrix[1 * 4 + 1], matrix[2 * 4 + 1], + matrix[0 * 4 + 3], matrix[1 * 4 + 3], matrix[2 * 4 + 3] + }; + + FLOATTYPE mMat3x3_p[9] = + { + matrix[0 * 4 + 0], matrix[1 * 4 + 0], matrix[2 * 4 + 0], + matrix[0 * 4 + 1], matrix[1 * 4 + 1], matrix[2 * 4 + 1], + matrix[0 * 4 + 2], matrix[1 * 4 + 2], matrix[2 * 4 + 2] + }; + + result[0 * 4 + 0] = mat3Determinant(mMat3x3_a); + result[1 * 4 + 0] = -mat3Determinant(mMat3x3_b); + result[2 * 4 + 0] = mat3Determinant(mMat3x3_c); + result[3 * 4 + 0] = -mat3Determinant(mMat3x3_d); + result[0 * 4 + 1] = -mat3Determinant(mMat3x3_e); + result[1 * 4 + 1] = mat3Determinant(mMat3x3_f); + result[2 * 4 + 1] = -mat3Determinant(mMat3x3_g); + result[3 * 4 + 1] = mat3Determinant(mMat3x3_h); + result[0 * 4 + 2] = mat3Determinant(mMat3x3_i); + result[1 * 4 + 2] = -mat3Determinant(mMat3x3_j); + result[2 * 4 + 2] = mat3Determinant(mMat3x3_k); + result[3 * 4 + 2] = -mat3Determinant(mMat3x3_l); + result[0 * 4 + 3] = -mat3Determinant(mMat3x3_m); + result[1 * 4 + 3] = mat3Determinant(mMat3x3_n); + result[2 * 4 + 3] = -mat3Determinant(mMat3x3_o); + result[3 * 4 + 3] = mat3Determinant(mMat3x3_p); +} + +bool VSMatrix::inverseMatrix(VSMatrix &result) +{ + // Calculate mat4 determinant + FLOATTYPE det = mat4Determinant(mMatrix); + + // Inverse unknown when determinant is close to zero + if (fabs(det) < 1e-15) + { + for (int i = 0; i < 16; i++) + result.mMatrix[i] = FLOATTYPE(0.0); + return false; + } + else + { + mat4Adjoint(mMatrix, result.mMatrix); + + FLOATTYPE invDet = FLOATTYPE(1.0) / det; + for (int i = 0; i < 16; i++) + { + result.mMatrix[i] = result.mMatrix[i] * invDet; + } + } + return true; +} From d4ebe51e837303007cf9dac4423c9d637412ece4 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Sun, 5 Nov 2017 15:35:03 +0100 Subject: [PATCH 15/29] - Place the HUD model correctly in the world so that shader light calculations work --- src/gl/dynlights/gl_dynlight.h | 2 +- src/gl/dynlights/gl_dynlight1.cpp | 29 ++--------------------------- src/gl/models/gl_models.cpp | 30 +++++++++++++++--------------- src/gl/scene/gl_sprite.cpp | 2 +- src/gl/scene/gl_spritelight.cpp | 4 ++-- src/gl/scene/gl_wall.h | 2 +- src/gl/scene/gl_weapon.cpp | 2 +- 7 files changed, 23 insertions(+), 48 deletions(-) diff --git a/src/gl/dynlights/gl_dynlight.h b/src/gl/dynlights/gl_dynlight.h index a85814b6b..1ecdca4ce 100644 --- a/src/gl/dynlights/gl_dynlight.h +++ b/src/gl/dynlights/gl_dynlight.h @@ -59,7 +59,7 @@ struct FDynLightData bool gl_GetLight(int group, Plane & p, ADynamicLight * light, bool checkside, FDynLightData &data); -void gl_AddLightToList(int group, ADynamicLight * light, FDynLightData &ldata, bool hudmodel); +void gl_AddLightToList(int group, ADynamicLight * light, FDynLightData &ldata); void gl_UploadLights(FDynLightData &data); diff --git a/src/gl/dynlights/gl_dynlight1.cpp b/src/gl/dynlights/gl_dynlight1.cpp index 92a503c8d..e42f89ac4 100644 --- a/src/gl/dynlights/gl_dynlight1.cpp +++ b/src/gl/dynlights/gl_dynlight1.cpp @@ -77,7 +77,7 @@ bool gl_GetLight(int group, Plane & p, ADynamicLight * light, bool checkside, FD return false; } - gl_AddLightToList(group, light, ldata, false); + gl_AddLightToList(group, light, ldata); return true; } @@ -86,38 +86,13 @@ bool gl_GetLight(int group, Plane & p, ADynamicLight * light, bool checkside, FD // Add one dynamic light to the light data list // //========================================================================== -void gl_AddLightToList(int group, ADynamicLight * light, FDynLightData &ldata, bool hudmodel) +void gl_AddLightToList(int group, ADynamicLight * light, FDynLightData &ldata) { int i = 0; DVector3 pos = light->PosRelative(group); float radius = light->GetRadius(); - if (hudmodel) - { - // HUD model is already translated and rotated. We must rotate the lights into that view space. - - DVector3 rotation; - DVector3 localpos = pos - r_viewpoint.Pos; - - rotation.X = localpos.X * r_viewpoint.Angles.Yaw.Sin() - localpos.Y * r_viewpoint.Angles.Yaw.Cos(); - rotation.Y = localpos.X * r_viewpoint.Angles.Yaw.Cos() + localpos.Y * r_viewpoint.Angles.Yaw.Sin(); - rotation.Z = localpos.Z; - localpos = rotation; - - rotation.X = localpos.X; - rotation.Y = localpos.Y * r_viewpoint.Angles.Pitch.Sin() - localpos.Z * r_viewpoint.Angles.Pitch.Cos(); - rotation.Z = localpos.Y * r_viewpoint.Angles.Pitch.Cos() + localpos.Z * r_viewpoint.Angles.Pitch.Sin(); - localpos = rotation; - - rotation.Y = localpos.Y; - rotation.Z = localpos.Z * r_viewpoint.Angles.Roll.Sin() - localpos.X * r_viewpoint.Angles.Roll.Cos(); - rotation.X = localpos.Z * r_viewpoint.Angles.Roll.Cos() + localpos.X * r_viewpoint.Angles.Roll.Sin(); - localpos = rotation; - - pos = localpos; - } - float cs; if (light->IsAdditive()) { diff --git a/src/gl/models/gl_models.cpp b/src/gl/models/gl_models.cpp index 45b955b56..fcad2a95b 100644 --- a/src/gl/models/gl_models.cpp +++ b/src/gl/models/gl_models.cpp @@ -1095,33 +1095,33 @@ void gl_RenderHUDModel(DPSprite *psp, float ofsX, float ofsY) glFrontFace(GL_CCW); } - // [BB] The model has to be drawn independently from the position of the player, - // so we have to reset the view matrix. - gl_RenderState.mViewMatrix.loadIdentity(); - - // Need to reset the normal matrix too - gl_RenderState.mNormalViewMatrix.loadIdentity(); + // The model position and orientation has to be drawn independently from the position of the player, + // but we need to position it correctly in the world for light to work properly. + VSMatrix objectToWorldMatrix; + gl_RenderState.mViewMatrix.inverseMatrix(objectToWorldMatrix); // Scaling model (y scale for a sprite means height, i.e. z in the world!). - gl_RenderState.mViewMatrix.scale(smf->xscale, smf->zscale, smf->yscale); + objectToWorldMatrix.scale(smf->xscale, smf->zscale, smf->yscale); // Aplying model offsets (model offsets do not depend on model scalings). - gl_RenderState.mViewMatrix.translate(smf->xoffset / smf->xscale, smf->zoffset / smf->zscale, smf->yoffset / smf->yscale); + objectToWorldMatrix.translate(smf->xoffset / smf->xscale, smf->zoffset / smf->zscale, smf->yoffset / smf->yscale); // [BB] Weapon bob, very similar to the normal Doom weapon bob. - gl_RenderState.mViewMatrix.rotate(ofsX/4, 0, 1, 0); - gl_RenderState.mViewMatrix.rotate((ofsY-WEAPONTOP)/-4., 1, 0, 0); + objectToWorldMatrix.rotate(ofsX/4, 0, 1, 0); + objectToWorldMatrix.rotate((ofsY-WEAPONTOP)/-4., 1, 0, 0); // [BB] For some reason the jDoom models need to be rotated. - gl_RenderState.mViewMatrix.rotate(90.f, 0, 1, 0); + objectToWorldMatrix.rotate(90.f, 0, 1, 0); // Applying angleoffset, pitchoffset, rolloffset. - gl_RenderState.mViewMatrix.rotate(-smf->angleoffset, 0, 1, 0); - gl_RenderState.mViewMatrix.rotate(smf->pitchoffset, 0, 0, 1); - gl_RenderState.mViewMatrix.rotate(-smf->rolloffset, 1, 0, 0); - gl_RenderState.ApplyMatrices(); + objectToWorldMatrix.rotate(-smf->angleoffset, 0, 1, 0); + objectToWorldMatrix.rotate(smf->pitchoffset, 0, 0, 1); + objectToWorldMatrix.rotate(-smf->rolloffset, 1, 0, 0); + gl_RenderState.mModelMatrix = objectToWorldMatrix; + gl_RenderState.EnableModelMatrix(true); gl_RenderFrameModels( smf, psp->GetState(), psp->GetTics(), playermo->player->ReadyWeapon->GetClass(), nullptr, 0 ); + gl_RenderState.EnableModelMatrix(false); glDepthFunc(GL_LESS); if (!( playermo->RenderStyle == LegacyRenderStyles[STYLE_Normal] )) diff --git a/src/gl/scene/gl_sprite.cpp b/src/gl/scene/gl_sprite.cpp index 5ca2cd65d..154720022 100644 --- a/src/gl/scene/gl_sprite.cpp +++ b/src/gl/scene/gl_sprite.cpp @@ -335,7 +335,7 @@ void GLSprite::Draw(int pass) if (gl_lights && GLRenderer->mLightCount && mDrawer->FixedColormap == CM_DEFAULT && !fullbright) { if (modelframe && !particle) - gl_SetDynModelLight(gl_light_sprites ? actor : NULL, false); + gl_SetDynModelLight(gl_light_sprites ? actor : NULL); else gl_SetDynSpriteLight(gl_light_sprites ? actor : NULL, gl_light_particles ? particle : NULL); } diff --git a/src/gl/scene/gl_spritelight.cpp b/src/gl/scene/gl_spritelight.cpp index e348956bf..2d2e65b76 100644 --- a/src/gl/scene/gl_spritelight.cpp +++ b/src/gl/scene/gl_spritelight.cpp @@ -177,7 +177,7 @@ void BSPWalkCircle(float x, float y, float radiusSquared, const Callback &callba BSPNodeWalkCircle(level.HeadNode(), x, y, radiusSquared, callback); } -void gl_SetDynModelLight(AActor *self, bool hudmodel) +void gl_SetDynModelLight(AActor *self) { // Legacy and deferred render paths gets the old flat model light if (gl.lightmethod != LM_DIRECT) @@ -218,7 +218,7 @@ void gl_SetDynModelLight(AActor *self, bool hudmodel) { if (std::find(addedLights.begin(), addedLights.end(), light) == addedLights.end()) // Check if we already added this light from a different subsector { - gl_AddLightToList(group, light, modellightdata, hudmodel); + gl_AddLightToList(group, light, modellightdata); addedLights.push_back(light); } } diff --git a/src/gl/scene/gl_wall.h b/src/gl/scene/gl_wall.h index 47cf5654c..aa0bbaed4 100644 --- a/src/gl/scene/gl_wall.h +++ b/src/gl/scene/gl_wall.h @@ -422,6 +422,6 @@ inline float Dist2(float x1,float y1,float x2,float y2) void gl_SetDynSpriteLight(AActor *self, float x, float y, float z, subsector_t *subsec); void gl_SetDynSpriteLight(AActor *actor, particle_t *particle); -void gl_SetDynModelLight(AActor *self, bool hudmodel); +void gl_SetDynModelLight(AActor *self); #endif diff --git a/src/gl/scene/gl_weapon.cpp b/src/gl/scene/gl_weapon.cpp index 551f34cbd..3d4224520 100644 --- a/src/gl/scene/gl_weapon.cpp +++ b/src/gl/scene/gl_weapon.cpp @@ -422,7 +422,7 @@ void GLSceneDrawer::DrawPlayerSprites(sector_t * viewsector, bool hudModelStep) { FSpriteModelFrame *smf = playermo->player->ReadyWeapon ? gl_FindModelFrame(playermo->player->ReadyWeapon->GetClass(), psp->GetState()->sprite, psp->GetState()->GetFrame(), false) : nullptr; if (smf) - gl_SetDynModelLight(playermo, true); + gl_SetDynModelLight(playermo); else gl_SetDynSpriteLight(playermo, NULL); } From 4beefb70075df5cfa3a923ef7c19fb9d6926b6de Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Mon, 6 Nov 2017 15:37:26 +0200 Subject: [PATCH 16/29] Removed warning for uninitialized variables in ZScript This reverts commit 8104ef5189bd2dd42745e47c15d2f984b4213ec3 --- src/scripting/backend/codegen.cpp | 36 ++++--------------------------- src/scripting/backend/codegen.h | 9 ++------ 2 files changed, 6 insertions(+), 39 deletions(-) diff --git a/src/scripting/backend/codegen.cpp b/src/scripting/backend/codegen.cpp index 1de09e741..564240203 100644 --- a/src/scripting/backend/codegen.cpp +++ b/src/scripting/backend/codegen.cpp @@ -2692,7 +2692,6 @@ FxExpression *FxMultiAssign::Resolve(FCompileContext &ctx) for (unsigned i = 0; i < Base.Size(); i++) { auto singlevar = new FxLocalVariableDeclaration(rets[i], NAME_None, nullptr, 0, ScriptPosition); - singlevar->IsInitialized = true; LocalVarContainer->Add(singlevar); Base[i] = Base[i]->Resolve(ctx); ABORT(Base[i]); @@ -6032,7 +6031,7 @@ FxExpression *FxIdentifier::Resolve(FCompileContext& ctx) } else { - auto x = new FxStackVariable(local, ScriptPosition); + auto x = new FxStackVariable(local->ValueType, local->StackOffset, ScriptPosition); delete this; return x->Resolve(ctx); } @@ -6521,7 +6520,6 @@ FxLocalVariable::FxLocalVariable(FxLocalVariableDeclaration *var, const FScriptP FxExpression *FxLocalVariable::Resolve(FCompileContext &ctx) { CHECKRESOLVED(); - IsLocalVariable = ctx.FunctionArgs.Find(Variable) == ctx.FunctionArgs.Size(); return this; } @@ -6555,16 +6553,7 @@ ExpEmit FxLocalVariable::Emit(VMFunctionBuilder *build) { ExpEmit ret(Variable->RegNum + RegOffset, Variable->ValueType->GetRegType(), false, true); ret.RegCount = ValueType->GetRegCount(); - if (AddressRequested) - { - Variable->IsInitialized = true; - ret.Target = true; - } - else if (IsLocalVariable) - { - Variable->WarnIfUninitialized(ScriptPosition); - } - + if (AddressRequested) ret.Target = true; return ret; } } @@ -6906,9 +6895,8 @@ ExpEmit FxCVar::Emit(VMFunctionBuilder *build) // //========================================================================== -FxStackVariable::FxStackVariable(FxLocalVariableDeclaration *var, const FScriptPosition &pos) - : FxMemberBase(EFX_StackVariable, Create(NAME_None, var->ValueType, 0, var->StackOffset), pos) - , Variable(var) +FxStackVariable::FxStackVariable(PType *type, int offset, const FScriptPosition &pos) + : FxMemberBase(EFX_StackVariable, Create(NAME_None, type, 0, offset), pos) { } @@ -6959,8 +6947,6 @@ ExpEmit FxStackVariable::Emit(VMFunctionBuilder *build) if (AddressRequested) { - Variable->IsInitialized = true; - if (offsetreg >= 0) { ExpEmit obj(build, REGT_POINTER); @@ -6972,10 +6958,6 @@ ExpEmit FxStackVariable::Emit(VMFunctionBuilder *build) return build->FramePointer; } } - else - { - Variable->WarnIfUninitialized(ScriptPosition); - } ExpEmit loc(build, membervar->Type->GetRegType(), membervar->Type->GetRegCount()); if (membervar->BitValue == -1) @@ -11421,16 +11403,6 @@ void FxLocalVariableDeclaration::Release(VMFunctionBuilder *build) // For that all local stack variables need to live for the entire execution of a function. } -void FxLocalVariableDeclaration::WarnIfUninitialized(const FScriptPosition &varPos) const -{ - if (!IsInitialized && nullptr == Init) - { - varPos.Message(MSG_WARNING, - "Usage of uninitialized variable '%s' defined at line %i", - Name.GetChars(), ScriptPosition.ScriptLine); - } -} - FxStaticArray::FxStaticArray(PType *type, FName name, FArgumentList &args, const FScriptPosition &pos) : FxLocalVariableDeclaration(NewArray(type, args.Size()), name, nullptr, VARF_Static|VARF_ReadOnly, pos) diff --git a/src/scripting/backend/codegen.h b/src/scripting/backend/codegen.h index f035039e2..8ee32423f 100644 --- a/src/scripting/backend/codegen.h +++ b/src/scripting/backend/codegen.h @@ -1425,7 +1425,6 @@ class FxLocalVariable : public FxExpression public: FxLocalVariableDeclaration *Variable; bool AddressRequested; - bool IsLocalVariable; // false for function parameter and true otherwise int RegOffset; FxLocalVariable(FxLocalVariableDeclaration*, const FScriptPosition&); @@ -1443,9 +1442,7 @@ public: class FxStackVariable : public FxMemberBase { public: - FxLocalVariableDeclaration *Variable; - - FxStackVariable(FxLocalVariableDeclaration*, const FScriptPosition&); + FxStackVariable(PType *type, int offset, const FScriptPosition&); ~FxStackVariable(); FxExpression *Resolve(FCompileContext&); bool RequestAddress(FCompileContext &ctx, bool *writable); @@ -2124,7 +2121,6 @@ class FxLocalVariableDeclaration : public FxExpression { friend class FxCompoundStatement; friend class FxLocalVariable; - friend class FxStackVariable; friend class FxStaticArrayVariable; FName Name; @@ -2134,7 +2130,6 @@ class FxLocalVariableDeclaration : public FxExpression public: int StackOffset = -1; int RegNum = -1; - bool IsInitialized = false; FxLocalVariableDeclaration(PType *type, FName name, FxExpression *initval, int varflags, const FScriptPosition &p); ~FxLocalVariableDeclaration(); @@ -2142,7 +2137,7 @@ public: ExpEmit Emit(VMFunctionBuilder *build); void Release(VMFunctionBuilder *build); void SetReg(ExpEmit reginfo); - void WarnIfUninitialized(const FScriptPosition &varPos) const; + }; //========================================================================== From d422392b94154a46bb36892f0480705ad9027151 Mon Sep 17 00:00:00 2001 From: Major Cooke Date: Fri, 3 Nov 2017 13:57:44 -0500 Subject: [PATCH 17/29] Extended LineAttack() with offsets and new flags Added forward and side offsets for LineAttack() function Added absolute offset and absolute position flags for LineAttack() function --- src/p_local.h | 16 ++++++----- src/p_map.cpp | 41 +++++++++++++++++++++++++---- wadsrc/static/zscript/actor.txt | 2 +- wadsrc/static/zscript/constants.txt | 13 +++++---- 4 files changed, 54 insertions(+), 18 deletions(-) diff --git a/src/p_local.h b/src/p_local.h index 21c5db78b..c3fd29520 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -324,15 +324,17 @@ enum // P_AimLineAttack flags enum // P_LineAttack flags { LAF_ISMELEEATTACK = 1, - LAF_NORANDOMPUFFZ = 2, - LAF_NOIMPACTDECAL = 4, - LAF_NOINTERACT = 8, - LAF_TARGETISSOURCE = 16, - LAF_OVERRIDEZ = 32, + LAF_NORANDOMPUFFZ = 1 << 1, + LAF_NOIMPACTDECAL = 1 << 2, + LAF_NOINTERACT = 1 << 3, + LAF_TARGETISSOURCE= 1 << 4, + LAF_OVERRIDEZ = 1 << 5, + LAF_ABSOFFSET = 1 << 6, + LAF_ABSPOSITION = 1 << 7, }; -AActor *P_LineAttack(AActor *t1, DAngle angle, double distance, DAngle pitch, int damage, FName damageType, PClassActor *pufftype, int flags = 0, FTranslatedLineTarget *victim = NULL, int *actualdamage = NULL, double sz = 0.0); -AActor *P_LineAttack(AActor *t1, DAngle angle, double distance, DAngle pitch, int damage, FName damageType, FName pufftype, int flags = 0, FTranslatedLineTarget *victim = NULL, int *actualdamage = NULL, double sz = 0.0); +AActor *P_LineAttack(AActor *t1, DAngle angle, double distance, DAngle pitch, int damage, FName damageType, PClassActor *pufftype, int flags = 0, FTranslatedLineTarget *victim = NULL, int *actualdamage = NULL, double sz = 0.0, double offsetforward = 0.0, double offsetside = 0.0); +AActor *P_LineAttack(AActor *t1, DAngle angle, double distance, DAngle pitch, int damage, FName damageType, FName pufftype, int flags = 0, FTranslatedLineTarget *victim = NULL, int *actualdamage = NULL, double sz = 0.0, double offsetforward = 0.0, double offsetside = 0.0); void P_TraceBleed(int damage, const DVector3 &pos, AActor *target, DAngle angle, DAngle pitch); void P_TraceBleed(int damage, AActor *target, DAngle angle, DAngle pitch); diff --git a/src/p_map.cpp b/src/p_map.cpp index 569df7f2c..d71b22d85 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -4395,7 +4395,8 @@ static ETraceStatus CheckForActor(FTraceResults &res, void *userdata) //========================================================================== AActor *P_LineAttack(AActor *t1, DAngle angle, double distance, - DAngle pitch, int damage, FName damageType, PClassActor *pufftype, int flags, FTranslatedLineTarget*victim, int *actualdamage, double sz) + DAngle pitch, int damage, FName damageType, PClassActor *pufftype, int flags, FTranslatedLineTarget*victim, int *actualdamage, + double sz, double offsetforward, double offsetside) { bool nointeract = !!(flags & LAF_NOINTERACT); DVector3 direction; @@ -4496,7 +4497,34 @@ AActor *P_LineAttack(AActor *t1, DAngle angle, double distance, if (nointeract || (puffDefaults && puffDefaults->flags6 & MF6_NOTRIGGER)) tflags = TRACE_NoSky; else tflags = TRACE_NoSky | TRACE_Impact; - if (!Trace(t1->PosAtZ(shootz), t1->Sector, direction, distance, MF_SHOOTABLE, + // [MC] Check the flags and set the position according to what is desired. + // LAF_ABSPOSITION: Treat the offset parameters as direct coordinates. + // LAF_ABSOFFSET: Ignore the angle. + + DVector3 tempos; + + if (flags & LAF_ABSPOSITION) + { + tempos = DVector3(offsetforward, offsetside, sz); + } + else if (flags & LAF_ABSOFFSET) + { + tempos = t1->Vec2OffsetZ(offsetforward, offsetside, shootz); + } + else if (0.0 == offsetforward && 0.0 == offsetside) + { + // Default case so exact comparison is enough + tempos = t1->PosAtZ(shootz); + } + else + { + const double s = angle.Sin(); + const double c = angle.Cos(); + tempos = t1->Vec2OffsetZ(offsetforward * c + offsetside * s, offsetforward * s - offsetside * c, shootz); + } + + // Perform the trace. + if (!Trace(tempos, t1->Sector, direction, distance, MF_SHOOTABLE, ML_BLOCKEVERYTHING | ML_BLOCKHITSCAN, t1, trace, tflags, CheckForActor, &TData)) { // hit nothing if (!nointeract && puffDefaults && puffDefaults->ActiveSound) @@ -4702,7 +4730,8 @@ AActor *P_LineAttack(AActor *t1, DAngle angle, double distance, } AActor *P_LineAttack(AActor *t1, DAngle angle, double distance, - DAngle pitch, int damage, FName damageType, FName pufftype, int flags, FTranslatedLineTarget *victim, int *actualdamage, double sz) + DAngle pitch, int damage, FName damageType, FName pufftype, int flags, FTranslatedLineTarget *victim, int *actualdamage, + double sz, double offsetforward, double offsetside) { PClassActor *type = PClass::FindActor(pufftype); if (type == NULL) @@ -4716,7 +4745,7 @@ AActor *P_LineAttack(AActor *t1, DAngle angle, double distance, } else { - return P_LineAttack(t1, angle, distance, pitch, damage, damageType, type, flags, victim, actualdamage, sz); + return P_LineAttack(t1, angle, distance, pitch, damage, damageType, type, flags, victim, actualdamage, sz, offsetforward, offsetside); } } @@ -4732,10 +4761,12 @@ DEFINE_ACTION_FUNCTION(AActor, LineAttack) PARAM_INT_DEF(flags); PARAM_POINTER_DEF(victim, FTranslatedLineTarget); PARAM_FLOAT_DEF(offsetz); + PARAM_FLOAT_DEF(offsetforward); + PARAM_FLOAT_DEF(offsetside); int acdmg; if (puffType == nullptr) puffType = PClass::FindActor("BulletPuff"); // P_LineAttack does not work without a puff to take info from. - auto puff = P_LineAttack(self, angle, distance, pitch, damage, damageType, puffType, flags, victim, &acdmg, offsetz); + auto puff = P_LineAttack(self, angle, distance, pitch, damage, damageType, puffType, flags, victim, &acdmg, offsetz, offsetforward, offsetside); if (numret > 0) ret[0].SetObject(puff); if (numret > 1) ret[1].SetInt(acdmg), numret = 2; return numret; diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 682c70af6..3d272b05d 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -598,7 +598,7 @@ class Actor : Thinker native native virtual int DamageMobj(Actor inflictor, Actor source, int damage, Name mod, int flags = 0, double angle = 0); native void PoisonMobj (Actor inflictor, Actor source, int damage, int duration, int period, Name type); native double AimLineAttack(double angle, double distance, out FTranslatedLineTarget pLineTarget = null, double vrange = 0., int flags = 0, Actor target = null, Actor friender = null); - native Actor, int LineAttack(double angle, double distance, double pitch, int damage, Name damageType, class pufftype, int flags = 0, out FTranslatedLineTarget victim = null, double offsetz = 0.); + native Actor, int LineAttack(double angle, double distance, double pitch, int damage, Name damageType, class pufftype, int flags = 0, out FTranslatedLineTarget victim = null, double offsetz = 0., double offsetforward = 0., double offsetside = 0.); native bool CheckSight(Actor target, int flags = 0); native bool IsVisible(Actor other, bool allaround, LookExParams params = null); native bool HitFriend(); diff --git a/wadsrc/static/zscript/constants.txt b/wadsrc/static/zscript/constants.txt index 8fac0a22a..a8aea4123 100644 --- a/wadsrc/static/zscript/constants.txt +++ b/wadsrc/static/zscript/constants.txt @@ -878,11 +878,14 @@ enum EAimFlags enum ELineAttackFlags { - LAF_ISMELEEATTACK = 1, - LAF_NORANDOMPUFFZ = 2, - LAF_NOIMPACTDECAL = 4, - LAF_NOINTERACT = 8, - LAF_OVERRIDEZ = 32, + LAF_ISMELEEATTACK = 1, + LAF_NORANDOMPUFFZ = 1 << 1, + LAF_NOIMPACTDECAL = 1 << 2, + LAF_NOINTERACT = 1 << 3, + LAF_TARGETISSOURCE = 1 << 4, + LAF_OVERRIDEZ = 1 << 5, + LAF_ABSOFFSET = 1 << 6, + LAF_ABSPOSITION = 1 << 7, } const DEFMELEERANGE = 64; From f353f8b5aa5b486af048b7b969e6fcb0803f88bb Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Tue, 7 Nov 2017 09:55:57 +0200 Subject: [PATCH 18/29] Improved OpenGL profile selection in SDL backend https://forum.zdoom.org/viewtopic.php?t=56852 --- src/posix/sdl/sdlglvideo.cpp | 93 +++++++++++++++++++++++------------- src/posix/sdl/sdlglvideo.h | 3 +- 2 files changed, 62 insertions(+), 34 deletions(-) diff --git a/src/posix/sdl/sdlglvideo.cpp b/src/posix/sdl/sdlglvideo.cpp index f09767f58..5b48c1c4c 100644 --- a/src/posix/sdl/sdlglvideo.cpp +++ b/src/posix/sdl/sdlglvideo.cpp @@ -38,6 +38,7 @@ #include "templates.h" #include "i_system.h" #include "i_video.h" +#include "m_argv.h" #include "v_video.h" #include "v_pfx.h" #include "stats.h" @@ -343,7 +344,7 @@ bool SDLGLVideo::SetResolution (int width, int height, int bits) // //========================================================================== -bool SDLGLVideo::SetupPixelFormat(bool allowsoftware, int multisample) +void SDLGLVideo::SetupPixelFormat(bool allowsoftware, int multisample, const int *glver) { SDL_GL_SetAttribute( SDL_GL_RED_SIZE, 8 ); SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, 8 ); @@ -365,24 +366,18 @@ bool SDLGLVideo::SetupPixelFormat(bool allowsoftware, int multisample) SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0); } - - return true; -} - -//========================================================================== -// -// -// -//========================================================================== - -bool SDLGLVideo::InitHardware (bool allowsoftware, int multisample) -{ - if (!SetupPixelFormat(allowsoftware, multisample)) + else if (glver[0] > 2) { - Printf ("R_OPENGL: Reverting to software mode...\n"); - return false; + SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, glver[0]); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, glver[1]); + } + else + { + SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_COMPATIBILITY); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0); } - return true; } @@ -391,32 +386,66 @@ bool SDLGLVideo::InitHardware (bool allowsoftware, int multisample) SDLGLFB::SDLGLFB (void *, int width, int height, int, int, bool fullscreen, bool bgra) : SDLBaseFB (width, height, bgra) { + // NOTE: Core profiles were added with GL 3.2, so there's no sense trying + // to set core 3.1 or 3.0. We could try a forward-compatible context + // instead, but that would be too restrictive (w.r.t. shaders). + static const int glvers[][2] = { + { 4, 5 }, { 4, 4 }, { 4, 3 }, { 4, 2 }, { 4, 1 }, { 4, 0 }, + { 3, 3 }, { 3, 2 }, { 2, 0 }, + { 0, 0 }, + }; + int glveridx = 0; int i; - - m_Lock=0; + m_Lock=0; UpdatePending = false; - - if (!static_cast(Video)->InitHardware(false, 0)) + + const char *version = Args->CheckValue("-glversion"); + if (version != NULL) { - vid_renderer = 0; - return; + double gl_version = strtod(version, NULL) + 0.01; + int vermaj = (int)gl_version; + int vermin = (int)(gl_version*10.0) % 10; + + while (glvers[glveridx][0] > vermaj || (glvers[glveridx][0] == vermaj && + glvers[glveridx][1] > vermin)) + { + glveridx++; + if (glvers[glveridx][0] == 0) + { + glveridx = 0; + break; + } + } } FString caption; caption.Format(GAMESIG " %s (%s)", GetVersionString(), GetGitTime()); - Screen = SDL_CreateWindow (caption, - SDL_WINDOWPOS_UNDEFINED_DISPLAY(vid_adapter), SDL_WINDOWPOS_UNDEFINED_DISPLAY(vid_adapter), - width, height, (fullscreen ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0)|SDL_WINDOW_OPENGL); - if (Screen == NULL) - return; + for ( ; glvers[glveridx][0] > 0; ++glveridx) + { + static_cast(Video)->SetupPixelFormat(false, 0, glvers[glveridx]); - GLContext = SDL_GL_CreateContext(Screen); - if (GLContext == NULL) - return; + Screen = SDL_CreateWindow (caption, + SDL_WINDOWPOS_UNDEFINED_DISPLAY(vid_adapter), + SDL_WINDOWPOS_UNDEFINED_DISPLAY(vid_adapter), + width, height, (fullscreen ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0)|SDL_WINDOW_OPENGL + ); + if (Screen != NULL) + { + GLContext = SDL_GL_CreateContext(Screen); + if (GLContext != NULL) + { + m_supportsGamma = -1 != SDL_GetWindowGammaRamp(Screen, + m_origGamma[0], m_origGamma[1], m_origGamma[2] + ); + return; + } - m_supportsGamma = -1 != SDL_GetWindowGammaRamp(Screen, m_origGamma[0], m_origGamma[1], m_origGamma[2]); + SDL_DestroyWindow(Screen); + Screen = NULL; + } + } } SDLGLFB::~SDLGLFB () diff --git a/src/posix/sdl/sdlglvideo.h b/src/posix/sdl/sdlglvideo.h index 3d6de5c73..2dce3aeed 100644 --- a/src/posix/sdl/sdlglvideo.h +++ b/src/posix/sdl/sdlglvideo.h @@ -27,8 +27,7 @@ class SDLGLVideo : public IVideo bool NextMode (int *width, int *height, bool *letterbox); bool SetResolution (int width, int height, int bits); - bool SetupPixelFormat(bool allowsoftware, int multisample); - bool InitHardware (bool allowsoftware, int multisample); + void SetupPixelFormat(bool allowsoftware, int multisample, const int *glver); private: int IteratorMode; From e60c6d35c3b6a33ccbff6844f1be29ce880fa318 Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Sat, 4 Nov 2017 12:52:33 +0200 Subject: [PATCH 19/29] Added tmpfileplus 2.0.0 https://www.di-mgt.com.au/c_function_to_create_temp_file.html https://www.di-mgt.com.au/tmpfileplus-2.0.0.zip --- docs/licenses/mpl.txt | 373 ++++++++++++++++++++++++++++++++++++++++++ src/tmpfileplus.c | 337 ++++++++++++++++++++++++++++++++++++++ src/tmpfileplus.h | 53 ++++++ 3 files changed, 763 insertions(+) create mode 100644 docs/licenses/mpl.txt create mode 100644 src/tmpfileplus.c create mode 100644 src/tmpfileplus.h diff --git a/docs/licenses/mpl.txt b/docs/licenses/mpl.txt new file mode 100644 index 000000000..14e2f777f --- /dev/null +++ b/docs/licenses/mpl.txt @@ -0,0 +1,373 @@ +Mozilla Public License Version 2.0 +================================== + +1. Definitions +-------------- + +1.1. "Contributor" + means each individual or legal entity that creates, contributes to + the creation of, or owns Covered Software. + +1.2. "Contributor Version" + means the combination of the Contributions of others (if any) used + by a Contributor and that particular Contributor's Contribution. + +1.3. "Contribution" + means Covered Software of a particular Contributor. + +1.4. "Covered Software" + means Source Code Form to which the initial Contributor has attached + the notice in Exhibit A, the Executable Form of such Source Code + Form, and Modifications of such Source Code Form, in each case + including portions thereof. + +1.5. "Incompatible With Secondary Licenses" + means + + (a) that the initial Contributor has attached the notice described + in Exhibit B to the Covered Software; or + + (b) that the Covered Software was made available under the terms of + version 1.1 or earlier of the License, but not also under the + terms of a Secondary License. + +1.6. "Executable Form" + means any form of the work other than Source Code Form. + +1.7. "Larger Work" + means a work that combines Covered Software with other material, in + a separate file or files, that is not Covered Software. + +1.8. "License" + means this document. + +1.9. "Licensable" + means having the right to grant, to the maximum extent possible, + whether at the time of the initial grant or subsequently, any and + all of the rights conveyed by this License. + +1.10. "Modifications" + means any of the following: + + (a) any file in Source Code Form that results from an addition to, + deletion from, or modification of the contents of Covered + Software; or + + (b) any new file in Source Code Form that contains any Covered + Software. + +1.11. "Patent Claims" of a Contributor + means any patent claim(s), including without limitation, method, + process, and apparatus claims, in any patent Licensable by such + Contributor that would be infringed, but for the grant of the + License, by the making, using, selling, offering for sale, having + made, import, or transfer of either its Contributions or its + Contributor Version. + +1.12. "Secondary License" + means either the GNU General Public License, Version 2.0, the GNU + Lesser General Public License, Version 2.1, the GNU Affero General + Public License, Version 3.0, or any later versions of those + licenses. + +1.13. "Source Code Form" + means the form of the work preferred for making modifications. + +1.14. "You" (or "Your") + means an individual or a legal entity exercising rights under this + License. For legal entities, "You" includes any entity that + controls, is controlled by, or is under common control with You. For + purposes of this definition, "control" means (a) the power, direct + or indirect, to cause the direction or management of such entity, + whether by contract or otherwise, or (b) ownership of more than + fifty percent (50%) of the outstanding shares or beneficial + ownership of such entity. + +2. License Grants and Conditions +-------------------------------- + +2.1. Grants + +Each Contributor hereby grants You a world-wide, royalty-free, +non-exclusive license: + +(a) under intellectual property rights (other than patent or trademark) + Licensable by such Contributor to use, reproduce, make available, + modify, display, perform, distribute, and otherwise exploit its + Contributions, either on an unmodified basis, with Modifications, or + as part of a Larger Work; and + +(b) under Patent Claims of such Contributor to make, use, sell, offer + for sale, have made, import, and otherwise transfer either its + Contributions or its Contributor Version. + +2.2. Effective Date + +The licenses granted in Section 2.1 with respect to any Contribution +become effective for each Contribution on the date the Contributor first +distributes such Contribution. + +2.3. Limitations on Grant Scope + +The licenses granted in this Section 2 are the only rights granted under +this License. No additional rights or licenses will be implied from the +distribution or licensing of Covered Software under this License. +Notwithstanding Section 2.1(b) above, no patent license is granted by a +Contributor: + +(a) for any code that a Contributor has removed from Covered Software; + or + +(b) for infringements caused by: (i) Your and any other third party's + modifications of Covered Software, or (ii) the combination of its + Contributions with other software (except as part of its Contributor + Version); or + +(c) under Patent Claims infringed by Covered Software in the absence of + its Contributions. + +This License does not grant any rights in the trademarks, service marks, +or logos of any Contributor (except as may be necessary to comply with +the notice requirements in Section 3.4). + +2.4. Subsequent Licenses + +No Contributor makes additional grants as a result of Your choice to +distribute the Covered Software under a subsequent version of this +License (see Section 10.2) or under the terms of a Secondary License (if +permitted under the terms of Section 3.3). + +2.5. Representation + +Each Contributor represents that the Contributor believes its +Contributions are its original creation(s) or it has sufficient rights +to grant the rights to its Contributions conveyed by this License. + +2.6. Fair Use + +This License is not intended to limit any rights You have under +applicable copyright doctrines of fair use, fair dealing, or other +equivalents. + +2.7. Conditions + +Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted +in Section 2.1. + +3. Responsibilities +------------------- + +3.1. Distribution of Source Form + +All distribution of Covered Software in Source Code Form, including any +Modifications that You create or to which You contribute, must be under +the terms of this License. You must inform recipients that the Source +Code Form of the Covered Software is governed by the terms of this +License, and how they can obtain a copy of this License. You may not +attempt to alter or restrict the recipients' rights in the Source Code +Form. + +3.2. Distribution of Executable Form + +If You distribute Covered Software in Executable Form then: + +(a) such Covered Software must also be made available in Source Code + Form, as described in Section 3.1, and You must inform recipients of + the Executable Form how they can obtain a copy of such Source Code + Form by reasonable means in a timely manner, at a charge no more + than the cost of distribution to the recipient; and + +(b) You may distribute such Executable Form under the terms of this + License, or sublicense it under different terms, provided that the + license for the Executable Form does not attempt to limit or alter + the recipients' rights in the Source Code Form under this License. + +3.3. Distribution of a Larger Work + +You may create and distribute a Larger Work under terms of Your choice, +provided that You also comply with the requirements of this License for +the Covered Software. If the Larger Work is a combination of Covered +Software with a work governed by one or more Secondary Licenses, and the +Covered Software is not Incompatible With Secondary Licenses, this +License permits You to additionally distribute such Covered Software +under the terms of such Secondary License(s), so that the recipient of +the Larger Work may, at their option, further distribute the Covered +Software under the terms of either this License or such Secondary +License(s). + +3.4. Notices + +You may not remove or alter the substance of any license notices +(including copyright notices, patent notices, disclaimers of warranty, +or limitations of liability) contained within the Source Code Form of +the Covered Software, except that You may alter any license notices to +the extent required to remedy known factual inaccuracies. + +3.5. Application of Additional Terms + +You may choose to offer, and to charge a fee for, warranty, support, +indemnity or liability obligations to one or more recipients of Covered +Software. However, You may do so only on Your own behalf, and not on +behalf of any Contributor. You must make it absolutely clear that any +such warranty, support, indemnity, or liability obligation is offered by +You alone, and You hereby agree to indemnify every Contributor for any +liability incurred by such Contributor as a result of warranty, support, +indemnity or liability terms You offer. You may include additional +disclaimers of warranty and limitations of liability specific to any +jurisdiction. + +4. Inability to Comply Due to Statute or Regulation +--------------------------------------------------- + +If it is impossible for You to comply with any of the terms of this +License with respect to some or all of the Covered Software due to +statute, judicial order, or regulation then You must: (a) comply with +the terms of this License to the maximum extent possible; and (b) +describe the limitations and the code they affect. Such description must +be placed in a text file included with all distributions of the Covered +Software under this License. Except to the extent prohibited by statute +or regulation, such description must be sufficiently detailed for a +recipient of ordinary skill to be able to understand it. + +5. Termination +-------------- + +5.1. The rights granted under this License will terminate automatically +if You fail to comply with any of its terms. However, if You become +compliant, then the rights granted under this License from a particular +Contributor are reinstated (a) provisionally, unless and until such +Contributor explicitly and finally terminates Your grants, and (b) on an +ongoing basis, if such Contributor fails to notify You of the +non-compliance by some reasonable means prior to 60 days after You have +come back into compliance. Moreover, Your grants from a particular +Contributor are reinstated on an ongoing basis if such Contributor +notifies You of the non-compliance by some reasonable means, this is the +first time You have received notice of non-compliance with this License +from such Contributor, and You become compliant prior to 30 days after +Your receipt of the notice. + +5.2. If You initiate litigation against any entity by asserting a patent +infringement claim (excluding declaratory judgment actions, +counter-claims, and cross-claims) alleging that a Contributor Version +directly or indirectly infringes any patent, then the rights granted to +You by any and all Contributors for the Covered Software under Section +2.1 of this License shall terminate. + +5.3. In the event of termination under Sections 5.1 or 5.2 above, all +end user license agreements (excluding distributors and resellers) which +have been validly granted by You or Your distributors under this License +prior to termination shall survive termination. + +************************************************************************ +* * +* 6. Disclaimer of Warranty * +* ------------------------- * +* * +* Covered Software is provided under this License on an "as is" * +* basis, without warranty of any kind, either expressed, implied, or * +* statutory, including, without limitation, warranties that the * +* Covered Software is free of defects, merchantable, fit for a * +* particular purpose or non-infringing. The entire risk as to the * +* quality and performance of the Covered Software is with You. * +* Should any Covered Software prove defective in any respect, You * +* (not any Contributor) assume the cost of any necessary servicing, * +* repair, or correction. This disclaimer of warranty constitutes an * +* essential part of this License. No use of any Covered Software is * +* authorized under this License except under this disclaimer. * +* * +************************************************************************ + +************************************************************************ +* * +* 7. Limitation of Liability * +* -------------------------- * +* * +* Under no circumstances and under no legal theory, whether tort * +* (including negligence), contract, or otherwise, shall any * +* Contributor, or anyone who distributes Covered Software as * +* permitted above, be liable to You for any direct, indirect, * +* special, incidental, or consequential damages of any character * +* including, without limitation, damages for lost profits, loss of * +* goodwill, work stoppage, computer failure or malfunction, or any * +* and all other commercial damages or losses, even if such party * +* shall have been informed of the possibility of such damages. This * +* limitation of liability shall not apply to liability for death or * +* personal injury resulting from such party's negligence to the * +* extent applicable law prohibits such limitation. Some * +* jurisdictions do not allow the exclusion or limitation of * +* incidental or consequential damages, so this exclusion and * +* limitation may not apply to You. * +* * +************************************************************************ + +8. Litigation +------------- + +Any litigation relating to this License may be brought only in the +courts of a jurisdiction where the defendant maintains its principal +place of business and such litigation shall be governed by laws of that +jurisdiction, without reference to its conflict-of-law provisions. +Nothing in this Section shall prevent a party's ability to bring +cross-claims or counter-claims. + +9. Miscellaneous +---------------- + +This License represents the complete agreement concerning the subject +matter hereof. If any provision of this License is held to be +unenforceable, such provision shall be reformed only to the extent +necessary to make it enforceable. Any law or regulation which provides +that the language of a contract shall be construed against the drafter +shall not be used to construe this License against a Contributor. + +10. Versions of the License +--------------------------- + +10.1. New Versions + +Mozilla Foundation is the license steward. Except as provided in Section +10.3, no one other than the license steward has the right to modify or +publish new versions of this License. Each version will be given a +distinguishing version number. + +10.2. Effect of New Versions + +You may distribute the Covered Software under the terms of the version +of the License under which You originally received the Covered Software, +or under the terms of any subsequent version published by the license +steward. + +10.3. Modified Versions + +If you create software not governed by this License, and you want to +create a new license for such software, you may create and use a +modified version of this License if you rename the license and remove +any references to the name of the license steward (except to note that +such modified license differs from this License). + +10.4. Distributing Source Code Form that is Incompatible With Secondary +Licenses + +If You choose to distribute Source Code Form that is Incompatible With +Secondary Licenses under the terms of this version of the License, the +notice described in Exhibit B of this License must be attached. + +Exhibit A - Source Code Form License Notice +------------------------------------------- + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. + +If it is not possible or desirable to put the notice in a particular +file, then You may include the notice in a location (such as a LICENSE +file in a relevant directory) where a recipient would be likely to look +for such a notice. + +You may add additional accurate notices of copyright ownership. + +Exhibit B - "Incompatible With Secondary Licenses" Notice +--------------------------------------------------------- + + This Source Code Form is "Incompatible With Secondary Licenses", as + defined by the Mozilla Public License, v. 2.0. diff --git a/src/tmpfileplus.c b/src/tmpfileplus.c new file mode 100644 index 000000000..9af0260b3 --- /dev/null +++ b/src/tmpfileplus.c @@ -0,0 +1,337 @@ +/* $Id: tmpfileplus.c $ */ +/* + * $Date: 2016-06-01 03:31Z $ + * $Revision: 2.0.0 $ + * $Author: dai $ + */ + +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * Copyright (c) 2012-16 David Ireland, DI Management Services Pty Ltd + * . + */ + + +/* +* NAME +* tmpfileplus - create a unique temporary file +* +* SYNOPSIS +* FILE *tmpfileplus(const char *dir, const char *prefix, char **pathname, int keep) +* +* DESCRIPTION +* The tmpfileplus() function opens a unique temporary file in binary +* read/write (w+b) mode. The file is opened with the O_EXCL flag, +* guaranteeing that the caller is the only user. The filename will consist +* of the string given by `prefix` followed by 10 random characters. If +* `prefix` is NULL, then the string "tmp." will be used instead. The file +* will be created in an appropriate directory chosen by the first +* successful attempt in the following sequence: +* +* a) The directory given by the `dir` argument (so the caller can specify +* a secure directory to take precedence). +* +* b) The directory name in the environment variables: +* +* (i) "TMP" [Windows only] +* (ii) "TEMP" [Windows only] +* (iii) "TMPDIR" [Unix only] +* +* c) `P_tmpdir` as defined in [Unix only] (in Windows, this is +* usually "\", which is no good). +* +* d) The current working directory. +* +* If a file cannot be created in any of the above directories, then the +* function fails and NULL is returned. +* +* If the argument `pathname` is not a null pointer, then it will point to +* the full pathname of the file. The pathname is allocated using `malloc` +* and therefore should be freed by `free`. +* +* If `keep` is nonzero and `pathname` is not a null pointer, then the file +* will be kept after it is closed. Otherwise the file will be +* automatically deleted when it is closed or the program terminates. +* +* +* RETURN VALUE +* The tmpfileplus() function returns a pointer to the open file stream, +* or NULL if a unique file cannot be opened. +* +* +* ERRORS +* ENOMEM Not enough memory to allocate filename. +* +*/ + +/* ADDED IN v2.0 */ + +/* +* NAME +* tmpfileplus_f - create a unique temporary file with filename stored in a fixed-length buffer +* +* SYNOPSIS +* FILE *tmpfileplus_f(const char *dir, const char *prefix, char *pathnamebuf, size_t pathsize, int keep); +* +* DESCRIPTION +* Same as tmpfileplus() except receives filename in a fixed-length buffer. No allocated memory to free. + +* ERRORS +* E2BIG Resulting filename is too big for the buffer `pathnamebuf`. + +*/ + +#include "tmpfileplus.h" + +#include +#include +#include +#include +#include + +/* Non-ANSI include files that seem to work in both MSVC and Linux */ +#include +#include +#include + +#ifdef _WIN32 +#include +#endif + +#ifdef _WIN32 +/* MSVC nags to enforce ISO C++ conformant function names with leading "_", + * so we define our own function names to avoid whingeing compilers... + */ +#define OPEN_ _open +#define FDOPEN_ _fdopen +#else +#define OPEN_ open +#define FDOPEN_ fdopen +#endif + + +/* DEBUGGING STUFF */ +#if defined(_DEBUG) && defined(SHOW_DPRINTF) +#define DPRINTF1(s, a1) printf(s, a1) +#else +#define DPRINTF1(s, a1) +#endif + + +#ifdef _WIN32 +#define FILE_SEPARATOR "\\" +#else +#define FILE_SEPARATOR "/" +#endif + +#define RANDCHARS "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" +#define NRANDCHARS (sizeof(RANDCHARS) - 1) + +/** Replace each byte in string s with a random character from TEMPCHARS */ +static char *set_randpart(char *s) +{ + size_t i; + unsigned int r; + static unsigned int seed; /* NB static */ + + if (seed == 0) + { /* First time set our seed using current time and clock */ + seed = ((unsigned)time(NULL)<<8) ^ (unsigned)clock(); + } + srand(seed++); + for (i = 0; i < strlen(s); i++) + { + r = rand() % NRANDCHARS; + s[i] = (RANDCHARS)[r]; + } + return s; +} + +/** Return 1 if path is a valid directory otherwise 0 */ +static int is_valid_dir(const char *path) +{ + struct stat st; + if ((stat(path, &st) == 0) && (st.st_mode & S_IFDIR)) + return 1; + + return 0; +} + +/** Call getenv and save a copy in buf */ +static char *getenv_save(const char *varname, char *buf, size_t bufsize) +{ + char *ptr = getenv(varname); + buf[0] = '\0'; + if (ptr) + { + strncpy(buf, ptr, bufsize); + buf[bufsize-1] = '\0'; + return buf; + } + return NULL; +} + +/** + * Try and create a randomly-named file in directory `tmpdir`. + * If successful, allocate memory and set `tmpname_ptr` to full filepath, and return file pointer; + * otherwise return NULL. + * If `keep` is zero then create the file as temporary and it should not exist once closed. + */ +static FILE *mktempfile_internal(const char *tmpdir, const char *pfx, char **tmpname_ptr, int keep) +/* PRE: + * pfx is not NULL and points to a valid null-terminated string + * tmpname_ptr is not NULL. + */ +{ + FILE *fp; + int fd; + char randpart[] = "1234567890"; + size_t lentempname; + int i; + char *tmpname = NULL; + int oflag, pmode; + +/* In Windows, we use the _O_TEMPORARY flag with `open` to ensure the file is deleted when closed. + * In Unix, we use the unlink function after opening the file. (This does not work in Windows, + * which does not allow an open file to be unlinked.) + */ +#ifdef _WIN32 + /* MSVC flags */ + oflag = _O_BINARY|_O_CREAT|_O_EXCL|_O_RDWR; + if (!keep) + oflag |= _O_TEMPORARY; + pmode = _S_IREAD | _S_IWRITE; +#else + /* Standard POSIX flags */ + oflag = O_CREAT|O_EXCL|O_RDWR; + pmode = S_IRUSR|S_IWUSR; +#endif + + if (!tmpdir || !is_valid_dir(tmpdir)) { + errno = ENOENT; + return NULL; + } + + lentempname = strlen(tmpdir) + strlen(FILE_SEPARATOR) + strlen(pfx) + strlen(randpart); + DPRINTF1("lentempname=%d\n", lentempname); + tmpname = malloc(lentempname + 1); + if (!tmpname) + { + errno = ENOMEM; + return NULL; + } + /* If we don't manage to create a file after 10 goes, there is something wrong... */ + for (i = 0; i < 10; i++) + { + sprintf(tmpname, "%s%s%s%s", tmpdir, FILE_SEPARATOR, pfx, set_randpart(randpart)); + DPRINTF1("[%s]\n", tmpname); + fd = OPEN_(tmpname, oflag, pmode); + if (fd != -1) break; + } + DPRINTF1("strlen(tmpname)=%d\n", strlen(tmpname)); + if (fd != -1) + { /* Success, so return user a proper ANSI C file pointer */ + fp = FDOPEN_(fd, "w+b"); + errno = 0; + +#ifndef _WIN32 + /* [Unix only] And make sure the file will be deleted once closed */ + if (!keep) unlink(tmpname); +#endif + + } + else + { /* We failed */ + fp = NULL; + } + if (!fp) + { + free(tmpname); + tmpname = NULL; + } + + *tmpname_ptr = tmpname; + return fp; +} + +/**********************/ +/* EXPORTED FUNCTIONS */ +/**********************/ + +FILE *tmpfileplus(const char *dir, const char *prefix, char **pathname, int keep) +{ + FILE *fp = NULL; + char *tmpname = NULL; + char *tmpdir = NULL; + const char *pfx = (prefix ? prefix : "tmp."); + char *tempdirs[12] = { 0 }; + char env1[FILENAME_MAX+1] = { 0 }; + char env2[FILENAME_MAX+1] = { 0 }; + char env3[FILENAME_MAX+1] = { 0 }; + int ntempdirs = 0; + int i; + + /* Set up a list of temp directories we will try in order */ + i = 0; + tempdirs[i++] = (char *)dir; +#ifdef _WIN32 + tempdirs[i++] = getenv_save("TMP", env1, sizeof(env1)); + tempdirs[i++] = getenv_save("TEMP", env2, sizeof(env2)); +#else + tempdirs[i++] = getenv_save("TMPDIR", env3, sizeof(env3)); + tempdirs[i++] = P_tmpdir; +#endif + tempdirs[i++] = "."; + ntempdirs = i; + + errno = 0; + + /* Work through list we set up before, and break once we are successful */ + for (i = 0; i < ntempdirs; i++) + { + tmpdir = tempdirs[i]; + DPRINTF1("Trying tmpdir=[%s]\n", tmpdir); + fp = mktempfile_internal(tmpdir, pfx, &tmpname, keep); + if (fp) break; + } + /* If we succeeded and the user passed a pointer, set it to the alloc'd pathname: the user must free this */ + if (fp && pathname) + *pathname = tmpname; + else /* Otherwise, free the alloc'd memory */ + free(tmpname); + + return fp; +} + +/* Same as tmpfileplus() but with fixed length buffer for output filename and no memory allocation */ +FILE *tmpfileplus_f(const char *dir, const char *prefix, char *pathnamebuf, size_t pathsize, int keep) +{ + char *tmpbuf = NULL; + FILE *fp; + + /* If no buffer provided, do the normal way */ + if (!pathnamebuf || (int)pathsize <= 0) { + return tmpfileplus(dir, prefix, NULL, keep); + } + /* Call with a temporary buffer */ + fp = tmpfileplus(dir, prefix, &tmpbuf, keep); + if (fp && strlen(tmpbuf) > pathsize - 1) { + /* Succeeded but not enough room in output buffer, so clean up and return an error */ + pathnamebuf[0] = 0; + fclose(fp); + if (keep) remove(tmpbuf); + free(tmpbuf); + errno = E2BIG; + return NULL; + } + /* Copy name into buffer */ + strcpy(pathnamebuf, tmpbuf); + free(tmpbuf); + + return fp; +} + + diff --git a/src/tmpfileplus.h b/src/tmpfileplus.h new file mode 100644 index 000000000..6c6ac38a7 --- /dev/null +++ b/src/tmpfileplus.h @@ -0,0 +1,53 @@ +/* $Id: tmpfileplus.h $ */ +/* + * $Date: 2016-06-01 03:31Z $ + * $Revision: 2.0.0 $ + * $Author: dai $ + */ + +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * Copyright (c) 2012-16 David Ireland, DI Management Services Pty Ltd + * . + */ + +#if _MSC_VER > 1000 +#pragma once +#endif + +#ifndef TMPFILEPLUS_H_ +#define TMPFILEPLUS_H_ + +#include + +/** Create a unique temporary file. +@param dir (optional) directory to create file. If NULL use default TMP directory. +@param prefix (optional) prefix for file name. If NULL use "tmp.". +@param pathname (optional) pointer to a buffer to receive the temp filename. + Allocated using `malloc()`; user to free. Ignored if NULL. +@param keep If `keep` is nonzero and `pathname` is not NULL, then keep the file after closing. + Otherwise file is automatically deleted when closed. +@return Pointer to stream opened in binary read/write (w+b) mode, or a null pointer on error. +@exception ENOMEM Not enough memory to allocate filename. +*/ +FILE *tmpfileplus(const char *dir, const char *prefix, char **pathname, int keep); + + +/** Create a unique temporary file with filename stored in a fixed-length buffer. +@param dir (optional) directory to create file. If NULL use default directory. +@param prefix (optional) prefix for file name. If NULL use "tmp.". +@param pathnamebuf (optional) buffer to receive full pathname of temporary file. Ignored if NULL. +@param pathsize Size of buffer to receive filename and its terminating null character. +@param keep If `keep` is nonzero and `pathname` is not NULL, then keep the file after closing. + Otherwise file is automatically deleted when closed. +@return Pointer to stream opened in binary read/write (w+b) mode, or a null pointer on error. +@exception E2BIG Resulting filename is too big for the buffer `pathnamebuf`. +*/ +FILE *tmpfileplus_f(const char *dir, const char *prefix, char *pathnamebuf, size_t pathsize, int keep); + +#define TMPFILE_KEEP 1 + +#endif /* end TMPFILEPLUS_H_ */ From e6c9ccf3a1a4ce2c39b859352065c4206b0b404f Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Sat, 4 Nov 2017 13:12:13 +0200 Subject: [PATCH 20/29] Changed tmpfileplus() to our needs Removed exclusive flag, made it C++ friendly, replaced unlink() with remove() --- src/tmpfileplus.c | 6 +++--- src/tmpfileplus.h | 8 ++++++++ 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/tmpfileplus.c b/src/tmpfileplus.c index 9af0260b3..ddb71de09 100644 --- a/src/tmpfileplus.c +++ b/src/tmpfileplus.c @@ -200,13 +200,13 @@ static FILE *mktempfile_internal(const char *tmpdir, const char *pfx, char **tmp */ #ifdef _WIN32 /* MSVC flags */ - oflag = _O_BINARY|_O_CREAT|_O_EXCL|_O_RDWR; + oflag = _O_BINARY|_O_CREAT|_O_RDWR; if (!keep) oflag |= _O_TEMPORARY; pmode = _S_IREAD | _S_IWRITE; #else /* Standard POSIX flags */ - oflag = O_CREAT|O_EXCL|O_RDWR; + oflag = O_CREAT|O_RDWR; pmode = S_IRUSR|S_IWUSR; #endif @@ -239,7 +239,7 @@ static FILE *mktempfile_internal(const char *tmpdir, const char *pfx, char **tmp #ifndef _WIN32 /* [Unix only] And make sure the file will be deleted once closed */ - if (!keep) unlink(tmpname); + if (!keep) remove(tmpname); #endif } diff --git a/src/tmpfileplus.h b/src/tmpfileplus.h index 6c6ac38a7..e32ff5042 100644 --- a/src/tmpfileplus.h +++ b/src/tmpfileplus.h @@ -23,6 +23,10 @@ #include +#ifdef __cplusplus +extern "C" { +#endif + /** Create a unique temporary file. @param dir (optional) directory to create file. If NULL use default TMP directory. @param prefix (optional) prefix for file name. If NULL use "tmp.". @@ -50,4 +54,8 @@ FILE *tmpfileplus_f(const char *dir, const char *prefix, char *pathnamebuf, size #define TMPFILE_KEEP 1 +#ifdef __cplusplus +} +#endif + #endif /* end TMPFILEPLUS_H_ */ From 0e706bfecfd063f7c2a0bdf77fcdd43f577ff72e Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Sat, 4 Nov 2017 13:15:53 +0200 Subject: [PATCH 21/29] Use tmpfileplus() instead of tempnam() Finally get rid of security or deprecated warnings cause by tempnam() function usage --- src/CMakeLists.txt | 2 +- src/sound/i_music.cpp | 1 - src/sound/i_musicinterns.h | 1 - .../music_timiditypp_mididevice.cpp | 60 +++++++----------- src/sound/oalsound.cpp | 1 - src/tempfiles.cpp | 57 ----------------- src/tempfiles.h | 61 ------------------- 7 files changed, 24 insertions(+), 159 deletions(-) delete mode 100644 src/tempfiles.cpp delete mode 100644 src/tempfiles.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 222a39d36..7ede5128b 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -958,7 +958,6 @@ set (PCH_SOURCES stats.cpp stringtable.cpp teaminfo.cpp - tempfiles.cpp v_blend.cpp v_collection.cpp v_draw.cpp @@ -1179,6 +1178,7 @@ add_executable( zdoom WIN32 MACOSX_BUNDLE ${PCH_SOURCES} x86.cpp strnatcmp.c + tmpfileplus.c zstring.cpp math/asin.c math/atan.c diff --git a/src/sound/i_music.cpp b/src/sound/i_music.cpp index b66e5d096..19db0161d 100644 --- a/src/sound/i_music.cpp +++ b/src/sound/i_music.cpp @@ -59,7 +59,6 @@ extern void ChildSigHandler (int signum); #include "s_sound.h" #include "m_swap.h" #include "i_cd.h" -#include "tempfiles.h" #include "templates.h" #include "stats.h" #include "timidity/timidity.h" diff --git a/src/sound/i_musicinterns.h b/src/sound/i_musicinterns.h index 9bf9f8aed..7bc5a31e5 100644 --- a/src/sound/i_musicinterns.h +++ b/src/sound/i_musicinterns.h @@ -1,5 +1,4 @@ -#include "tempfiles.h" #include "oplsynth/opl_mus_player.h" #include "c_cvars.h" #include "mus2midi.h" diff --git a/src/sound/mididevices/music_timiditypp_mididevice.cpp b/src/sound/mididevices/music_timiditypp_mididevice.cpp index b0ce41ead..d4c03534d 100644 --- a/src/sound/mididevices/music_timiditypp_mididevice.cpp +++ b/src/sound/mididevices/music_timiditypp_mididevice.cpp @@ -42,6 +42,7 @@ #include "cmdlib.h" #include "templates.h" #include "version.h" +#include "tmpfileplus.h" #ifndef _WIN32 #include @@ -81,13 +82,12 @@ public: protected: bool LaunchTimidity(); - FTempFileName DiskName; + char* DiskName; #ifdef _WIN32 HANDLE ReadWavePipe; HANDLE WriteWavePipe; HANDLE ChildProcess; FString CommandLine; - size_t LoopPos; bool Validated; bool ValidateTimidity(); #else // _WIN32 @@ -166,7 +166,7 @@ CUSTOM_CVAR (Int, timidity_frequency, 44100, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) //========================================================================== TimidityPPMIDIDevice::TimidityPPMIDIDevice(const char *args) - : DiskName("zmid"), + : DiskName(nullptr), #ifdef _WIN32 ReadWavePipe(INVALID_HANDLE_VALUE), WriteWavePipe(INVALID_HANDLE_VALUE), ChildProcess(INVALID_HANDLE_VALUE), @@ -194,12 +194,6 @@ TimidityPPMIDIDevice::TimidityPPMIDIDevice(const char *args) CommandLine += "\" "; } #endif - - if (DiskName == NULL) - { - Printf(PRINT_BOLD, "Could not create temp music file\n"); - return; - } } //========================================================================== @@ -210,6 +204,12 @@ TimidityPPMIDIDevice::TimidityPPMIDIDevice(const char *args) TimidityPPMIDIDevice::~TimidityPPMIDIDevice () { + if (nullptr != DiskName) + { + remove(DiskName); + free(DiskName); + } + #if _WIN32 if (WriteWavePipe != INVALID_HANDLE_VALUE) { @@ -252,17 +252,12 @@ bool TimidityPPMIDIDevice::Preprocess(MIDIStreamer *song, bool looping) return false; } - // Tell TiMidity++ whether it should loop or not -#ifdef _WIN32 - CommandLine.LockBuffer()[LoopPos] = looping ? 'l' : ' '; - CommandLine.UnlockBuffer(); -#endif Looping = looping; // Write MIDI song to temporary file song->CreateSMF(midi, looping ? 0 : 1); - f = fopen(DiskName, "wb"); + f = tmpfileplus(nullptr, "zmid", &DiskName, 1); if (f == NULL) { Printf(PRINT_BOLD, "Could not open temp music file\n"); @@ -275,6 +270,16 @@ bool TimidityPPMIDIDevice::Preprocess(MIDIStreamer *song, bool looping) { Printf(PRINT_BOLD, "Could not write temp music file\n"); } + +#ifdef _WIN32 + CommandLine.AppendFormat("-o - -Ors%c%c%c -id%c %s", + timidity_stereo ? 'S' : 'M', + timidity_8bit ? '8' : '1', + timidity_byteswap ? 'x' : ' ', + looping ? 'l' : ' ', + DiskName); +#endif + return false; } @@ -342,20 +347,6 @@ int TimidityPPMIDIDevice::Open(MidiCallback callback, void *userdata) } } -#ifdef _WIN32 - CommandLine += "-o - -Ors"; - CommandLine += timidity_stereo ? 'S' : 'M'; - CommandLine += timidity_8bit ? '8' : '1'; - if (timidity_byteswap) - { - CommandLine += 'x'; - } - - LoopPos = CommandLine.Len() + 4; - - CommandLine += " -idl "; - CommandLine += DiskName.GetName(); -#endif return 0; } @@ -463,12 +454,12 @@ bool TimidityPPMIDIDevice::ValidateTimidity() bool TimidityPPMIDIDevice::LaunchTimidity () { -#ifdef _WIN32 - if (CommandLine.IsEmpty()) + if (ExeName.IsEmpty() || nullptr == DiskName) { return false; } +#ifdef _WIN32 DPrintf (DMSG_NOTIFY, "cmd: \x1cG%s\n", CommandLine.GetChars()); STARTUPINFO startup = { sizeof(startup), }; @@ -516,11 +507,6 @@ bool TimidityPPMIDIDevice::LaunchTimidity () } return false; #else - if (ExeName.IsEmpty()) - { - return false; - } - if (WavePipe[0] != -1 && WavePipe[1] == -1 && Stream != NULL) { // Timidity was previously launched, so the write end of the pipe @@ -579,7 +565,7 @@ bool TimidityPPMIDIDevice::LaunchTimidity () arglist.push_back("-"); arglist.push_back(outmodearg.c_str()); arglist.push_back(ifacearg.c_str()); - arglist.push_back(DiskName.GetName()); + arglist.push_back(DiskName); DPrintf(DMSG_NOTIFY, "Timidity EXE: \x1cG%s\n", exename); int i = 1; diff --git a/src/sound/oalsound.cpp b/src/sound/oalsound.cpp index b9b0a1b10..c2867804d 100644 --- a/src/sound/oalsound.cpp +++ b/src/sound/oalsound.cpp @@ -57,7 +57,6 @@ #include "i_module.h" #include "i_music.h" #include "i_musicinterns.h" -#include "tempfiles.h" #include "cmdlib.h" FModule OpenALModule{"OpenAL"}; diff --git a/src/tempfiles.cpp b/src/tempfiles.cpp deleted file mode 100644 index 6ac782ccf..000000000 --- a/src/tempfiles.cpp +++ /dev/null @@ -1,57 +0,0 @@ -/* -** tempfiles.cpp -** Temporary name generator. Deletes the temporary file when deconstructed. -** -**--------------------------------------------------------------------------- -** Copyright 1998-2006 Randy Heit -** All rights reserved. -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions -** are met: -** -** 1. Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** 2. Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in the -** documentation and/or other materials provided with the distribution. -** 3. The name of the author may not be used to endorse or promote products -** derived from this software without specific prior written permission. -** -** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR -** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -**--------------------------------------------------------------------------- -** -*/ - -#include -#include -#include "tempfiles.h" - -FTempFileName::FTempFileName (const char *prefix) -{ -// Under Linux, ld will complain that tempnam is dangerous, and -// mkstemp should be used instead. However, there is no mkstemp -// under VC++, and even if there was, I still need to know the -// file name so that it can be used as input to Timidity. - - Name = tempnam (NULL, prefix); -} - -FTempFileName::~FTempFileName () -{ - if (Name != NULL) - { - remove (Name); - free (Name); - Name = NULL; - } -} diff --git a/src/tempfiles.h b/src/tempfiles.h deleted file mode 100644 index fe267d71a..000000000 --- a/src/tempfiles.h +++ /dev/null @@ -1,61 +0,0 @@ -/* -** tempfiles.h -** -**--------------------------------------------------------------------------- -** Copyright 1998-2006 Randy Heit -** All rights reserved. -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions -** are met: -** -** 1. Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** 2. Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in the -** documentation and/or other materials provided with the distribution. -** 3. The name of the author may not be used to endorse or promote products -** derived from this software without specific prior written permission. -** -** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR -** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -**--------------------------------------------------------------------------- -** -*/ - -#ifndef __TEMPFILES_H__ -#define __TEMPFILES_H__ - -#ifdef _MSC_VER -#pragma once -#endif - -#include - -// Returns a file name suitable for use as a temp file. -// If you create a file with this name (and presumably you -// will), it will be deleted automatically by this class's -// destructor. - -class FTempFileName -{ -public: - FTempFileName (const char *prefix=NULL); - ~FTempFileName (); - - operator const char * () { return Name; } - const char * GetName () const { return Name; } - -private: - char *Name; -}; - -#endif //__TEMPFILES_H__ From 5716dfe0502073ac7d7bd67a02ec166df3c51247 Mon Sep 17 00:00:00 2001 From: Rachael Alexanderson Date: Fri, 10 Nov 2017 08:21:28 -0500 Subject: [PATCH 22/29] - put limits on A_SoundVolume --- src/s_sound.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/s_sound.cpp b/src/s_sound.cpp index ea12fe97e..fede842b1 100644 --- a/src/s_sound.cpp +++ b/src/s_sound.cpp @@ -1761,6 +1761,12 @@ void S_RelinkSound (AActor *from, AActor *to) bool S_ChangeSoundVolume(AActor *actor, int channel, float volume) { + // don't let volume get out of bounds + if (volume < 0.0) + volume = 0.0; + else if (volume > 1.0) + volume = 1.0; + for (FSoundChan *chan = Channels; chan != NULL; chan = chan->NextChan) { if (chan->SourceType == SOURCE_Actor && From cdf0733c8bee50f551b2e9e2a85303708d85061d Mon Sep 17 00:00:00 2001 From: Rachael Alexanderson Date: Sat, 11 Nov 2017 09:37:41 -0500 Subject: [PATCH 23/29] - added latching CVARs to CVARINFO --- src/d_main.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/d_main.cpp b/src/d_main.cpp index 06a772066..29cc82a16 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -1439,6 +1439,10 @@ void ParseCVarInfo() { cvarflags |= CVAR_CHEAT; } + else if (stricmp(sc.String, "latch") == 0) + { + cvarflags |= CVAR_LATCH; + } else { sc.ScriptError("Unknown cvar attribute '%s'", sc.String); From 1088c60add8f278af21dff564317da5ebd5c8242 Mon Sep 17 00:00:00 2001 From: Rachael Alexanderson Date: Sat, 11 Nov 2017 15:54:42 -0500 Subject: [PATCH 24/29] - add doom e1m6 to rebuildnodes list. https://forum.zdoom.org/viewtopic.php?f=15&t=58430 --- wadsrc/static/compatibility.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/wadsrc/static/compatibility.txt b/wadsrc/static/compatibility.txt index ee676b051..f76ffebf6 100644 --- a/wadsrc/static/compatibility.txt +++ b/wadsrc/static/compatibility.txt @@ -345,6 +345,7 @@ F481922F4881F74760F3C0437FD5EDD0 // map03 8B2AC8D4DB4A49A5DCCBB067E04434D6 // The Hell Factory Hub One, map04 65A1EB4C87386F290816660A52932FF1 // Master Levels, garrison.wad 3DEE4EFEFAF3260C800A30734F54CE75 // Hellbound, map14 +5FAA25F5A6AAB3409CAE0AF87F910341 // DOOM.wad e1m6 { rebuildnodes } From 285834ae5b66eb66723a8b430ef65997cf1c7ba6 Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Sun, 12 Nov 2017 11:03:08 +0200 Subject: [PATCH 25/29] Fixed return state of player entered event https://forum.zdoom.org/viewtopic.php?t=58433 --- src/g_level.cpp | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/src/g_level.cpp b/src/g_level.cpp index d5044942e..701d35b53 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -128,7 +128,7 @@ int starttime; extern FString BackupSaveName; bool savegamerestore; -int finishstate; +int finishstate = FINISH_NoHub; extern int mousex, mousey; extern bool sendpause, sendsave, sendturn180, SendLand; @@ -851,6 +851,8 @@ void G_DoCompleted (void) level.maptime = 0; } + finishstate = mode; + if (!deathmatch && ((level.flags & LEVEL_NOINTERMISSION) || ((nextcluster == thiscluster) && (thiscluster->flags & CLUSTER_HUB) && !(thiscluster->flags & CLUSTER_ALLOWINTERMISSION)))) @@ -860,7 +862,6 @@ void G_DoCompleted (void) } gamestate = GS_INTERMISSION; - finishstate = mode; viewactive = false; automapactive = false; @@ -1038,12 +1039,20 @@ void G_DoLoadLevel (int position, bool autosave) { players[ii].camera = players[ii].mo; } - if (!savegamerestore) + + if (savegamerestore) { - E_PlayerEntered(ii, finishstate == FINISH_SameHub); + continue; + } + + const bool fromSnapshot = level.FromSnapshot; + E_PlayerEntered(ii, fromSnapshot && finishstate == FINISH_SameHub); + + if (fromSnapshot) + { + // ENTER scripts are being handled when the player gets spawned, this cannot be changed due to its effect on voodoo dolls. + FBehavior::StaticStartTypedScripts(SCRIPT_Return, players[ii].mo, true); } - // ENTER scripts are being handled when the player gets spawned, this cannot be changed due to its effect on voodoo dolls. - if (level.FromSnapshot && !savegamerestore) FBehavior::StaticStartTypedScripts(SCRIPT_Return, players[ii].mo, true); } } From 5d83ee5e891d4da3be95a1d7eb9f74e69f856786 Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Sun, 12 Nov 2017 14:44:21 +0200 Subject: [PATCH 26/29] Exposed String.Remove() function to ZScript https://forum.zdoom.org/viewtopic.php?t=58402 --- src/scripting/thingdef_data.cpp | 9 +++++++++ wadsrc/static/zscript/base.txt | 1 + 2 files changed, 10 insertions(+) diff --git a/src/scripting/thingdef_data.cpp b/src/scripting/thingdef_data.cpp index 540b61a36..c746c536d 100644 --- a/src/scripting/thingdef_data.cpp +++ b/src/scripting/thingdef_data.cpp @@ -1225,6 +1225,15 @@ DEFINE_ACTION_FUNCTION(FStringStruct, Truncate) return 0; } +DEFINE_ACTION_FUNCTION(FStringStruct, Remove) +{ + PARAM_SELF_STRUCT_PROLOGUE(FString); + PARAM_UINT(index); + PARAM_UINT(remlen); + self->Remove(index, remlen); + return 0; +} + // CharAt and CharCodeAt is how JS does it, and JS is similar here in that it doesn't have char type as int. DEFINE_ACTION_FUNCTION(FStringStruct, CharAt) { diff --git a/wadsrc/static/zscript/base.txt b/wadsrc/static/zscript/base.txt index 9cba0cb09..89dd0ab7d 100644 --- a/wadsrc/static/zscript/base.txt +++ b/wadsrc/static/zscript/base.txt @@ -684,6 +684,7 @@ struct StringStruct native native String Left(int len) const; native String Mid(int pos = 0, int len = 2147483647) const; native void Truncate(int newlen); + native void Remove(int index, int remlen); native String CharAt(int pos) const; native int CharCodeAt(int pos) const; native String Filter(); From 5935e14c098b8321d98a9cf67d36873370bf3614 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 13 Nov 2017 21:00:17 +0100 Subject: [PATCH 27/29] - exported P_Thing_Warp to ZScript. --- src/p_things.cpp | 22 ++++++++++++++++++++++ wadsrc/static/zscript/actor.txt | 1 + 2 files changed, 23 insertions(+) diff --git a/src/p_things.cpp b/src/p_things.cpp index 06a0252ab..0ff35bdcc 100644 --- a/src/p_things.cpp +++ b/src/p_things.cpp @@ -945,3 +945,25 @@ int P_Thing_Warp(AActor *caller, AActor *reference, double xofs, double yofs, do caller->SetOrigin(old, true); return false; } + +//========================================================================== +// +// A_Warp +// +//========================================================================== + +DEFINE_ACTION_FUNCTION(AActor, Warp) +{ + PARAM_SELF_PROLOGUE(AActor) + PARAM_OBJECT_DEF(destination, AActor) + PARAM_FLOAT_DEF(xofs) + PARAM_FLOAT_DEF(yofs) + PARAM_FLOAT_DEF(zofs) + PARAM_ANGLE_DEF(angle) + PARAM_INT_DEF(flags) + PARAM_FLOAT_DEF(heightoffset) + PARAM_FLOAT_DEF(radiusoffset) + PARAM_ANGLE_DEF(pitch) + + ACTION_RETURN_INT(!!P_Thing_Warp(self, destination, xofs, yofs, zofs, angle, flags, heightoffset, radiusoffset, pitch)); +} diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 3d272b05d..28b4039c0 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -683,6 +683,7 @@ class Actor : Thinker native native float AccuracyFactor(); native bool MorphMonster (Class spawntype, int duration, int style, Class enter_flash, Class exit_flash); action native void SetCamera(Actor cam, bool revert = false); + native bool Warp(AActor *dest, double xofs = 0, double yofs = 0, double zofs = 0, double angle = 0, int flags = 0, double heightoffset = 0, double radiusoffset = 0, double pitch = 0); // DECORATE compatible functions native clearscope int CountInv(class itemtype, int ptr_select = AAPTR_DEFAULT) const; From 0dcb1fe74ce338613081c98e5be3e93935bc0192 Mon Sep 17 00:00:00 2001 From: Rachael Alexanderson Date: Tue, 14 Nov 2017 18:42:36 -0500 Subject: [PATCH 28/29] - fix zscript-side definition for Warp --- wadsrc/static/zscript/actor.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 28b4039c0..13f5140c9 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -683,7 +683,7 @@ class Actor : Thinker native native float AccuracyFactor(); native bool MorphMonster (Class spawntype, int duration, int style, Class enter_flash, Class exit_flash); action native void SetCamera(Actor cam, bool revert = false); - native bool Warp(AActor *dest, double xofs = 0, double yofs = 0, double zofs = 0, double angle = 0, int flags = 0, double heightoffset = 0, double radiusoffset = 0, double pitch = 0); + native bool Warp(Actor dest, double xofs = 0, double yofs = 0, double zofs = 0, double angle = 0, int flags = 0, double heightoffset = 0, double radiusoffset = 0, double pitch = 0); // DECORATE compatible functions native clearscope int CountInv(class itemtype, int ptr_select = AAPTR_DEFAULT) const; From 80b47cafb4dbdc18387aeab737602c2d08807c1a Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Sat, 18 Nov 2017 14:35:45 +0200 Subject: [PATCH 29/29] Fixed detection of the first entry from internal IWADINFO https://forum.zdoom.org/viewtopic.php?t=58333 --- src/d_iwad.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/d_iwad.cpp b/src/d_iwad.cpp index f10d48fb7..fadb9e65b 100644 --- a/src/d_iwad.cpp +++ b/src/d_iwad.cpp @@ -583,7 +583,7 @@ int FIWadManager::IdentifyVersion (TArray &wadfiles, const char *iwad, // We have a -iwad parameter. Pick the first usable IWAD we found through that. for (unsigned i = numFoundWads; i < mFoundWads.Size(); i++) { - if (mFoundWads[i].mInfoIndex > 0) + if (mFoundWads[i].mInfoIndex >= 0) { picks.Push(mFoundWads[i]); break;