From 7d9955290380995af858d6f0ebd47b1aded99b4c Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 21 Nov 2016 13:45:33 +0100 Subject: [PATCH] - added two new integral types SpriteID and TextureID, both are needed to allow proper serialization as they require something different to be written out than a regular integer. --- src/dobjtype.cpp | 91 ++++++++++++++++++++++++ src/dobjtype.h | 22 ++++++ src/namedef.h | 2 + src/p_mobj.cpp | 4 +- src/scripting/codegeneration/codegen.cpp | 8 +++ src/scripting/vm/vm.h | 2 + src/scripting/vm/vmexec.cpp | 2 + src/scripting/vm/vmexec.h | 13 ++++ src/scripting/zscript/zcc_compile.cpp | 34 +++++---- src/scripting/zscript/zcc_parser.h | 3 +- 10 files changed, 164 insertions(+), 17 deletions(-) diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index e84504015..4354e0885 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -81,6 +81,8 @@ PString *TypeString; PName *TypeName; PSound *TypeSound; PColor *TypeColor; +PTextureID *TypeTextureID; +PSpriteID *TypeSpriteID; PStatePointer *TypeState; PStateLabel *TypeStateLabel; PStruct *TypeVector2; @@ -546,6 +548,8 @@ void PType::StaticInit() RUNTIME_CLASS(PString)->TypeTableType = RUNTIME_CLASS(PString); RUNTIME_CLASS(PName)->TypeTableType = RUNTIME_CLASS(PName); RUNTIME_CLASS(PSound)->TypeTableType = RUNTIME_CLASS(PSound); + RUNTIME_CLASS(PSpriteID)->TypeTableType = RUNTIME_CLASS(PSpriteID); + RUNTIME_CLASS(PTextureID)->TypeTableType = RUNTIME_CLASS(PTextureID); RUNTIME_CLASS(PColor)->TypeTableType = RUNTIME_CLASS(PColor); RUNTIME_CLASS(PPointer)->TypeTableType = RUNTIME_CLASS(PPointer); RUNTIME_CLASS(PClassPointer)->TypeTableType = RUNTIME_CLASS(PClassPointer); @@ -578,6 +582,8 @@ void PType::StaticInit() TypeTable.AddType(TypeState = new PStatePointer); TypeTable.AddType(TypeStateLabel = new PStateLabel); TypeTable.AddType(TypeNullPtr = new PPointer); + TypeTable.AddType(TypeSpriteID = new PSpriteID); + TypeTable.AddType(TypeTextureID = new PTextureID); TypeColorStruct = new PStruct("@ColorStruct", nullptr); //This name is intentionally obfuscated so that it cannot be used explicitly. The point of this type is to gain access to the single channels of a color value. #ifdef __BIG_ENDIAN__ @@ -1373,6 +1379,91 @@ bool PName::ReadValue(FSerializer &ar, const char *key, void *addr) const } } +/* PSpriteID ******************************************************************/ + +IMPLEMENT_CLASS(PSpriteID, false, false, false, false) + +//========================================================================== +// +// PName Default Constructor +// +//========================================================================== + +PSpriteID::PSpriteID() + : PInt(sizeof(int), true, true) +{ + mDescriptiveName = "SpriteID"; +} + +//========================================================================== +// +// PName :: WriteValue +// +//========================================================================== + +void PSpriteID::WriteValue(FSerializer &ar, const char *key, const void *addr) const +{ + int32_t val = *(int*)addr; + ar.Sprite(key, val, nullptr); +} + +//========================================================================== +// +// PName :: ReadValue +// +//========================================================================== + +bool PSpriteID::ReadValue(FSerializer &ar, const char *key, void *addr) const +{ + int32_t val; + ar.Sprite(key, val, nullptr); + *(int*)addr = val; + return true; +} + +/* PTextureID ******************************************************************/ + +IMPLEMENT_CLASS(PTextureID, false, false, false, false) + +//========================================================================== +// +// PTextureID Default Constructor +// +//========================================================================== + +PTextureID::PTextureID() + : PInt(sizeof(FTextureID), true, false) +{ + mDescriptiveName = "TextureID"; + assert(sizeof(FTextureID) == alignof(FTextureID)); +} + +//========================================================================== +// +// PTextureID :: WriteValue +// +//========================================================================== + +void PTextureID::WriteValue(FSerializer &ar, const char *key, const void *addr) const +{ + FTextureID val = *(FTextureID*)addr; + ar(key, val); +} + +//========================================================================== +// +// PTextureID :: ReadValue +// +//========================================================================== + +bool PTextureID::ReadValue(FSerializer &ar, const char *key, void *addr) const +{ + FTextureID val; + ar(key, val); + *(FTextureID*)addr = val; + return true; +} + /* PSound *****************************************************************/ IMPLEMENT_CLASS(PSound, false, false, false, false) diff --git a/src/dobjtype.h b/src/dobjtype.h index b8fc1cbf6..be192225b 100644 --- a/src/dobjtype.h +++ b/src/dobjtype.h @@ -515,6 +515,26 @@ public: bool ReadValue(FSerializer &ar, const char *key,void *addr) const override; }; +class PSpriteID : public PInt +{ + DECLARE_CLASS(PSpriteID, PInt); +public: + PSpriteID(); + + void WriteValue(FSerializer &ar, const char *key, const void *addr) const override; + bool ReadValue(FSerializer &ar, const char *key, void *addr) const override; +}; + +class PTextureID : public PInt +{ + DECLARE_CLASS(PTextureID, PInt); +public: + PTextureID(); + + void WriteValue(FSerializer &ar, const char *key, const void *addr) const override; + bool ReadValue(FSerializer &ar, const char *key, void *addr) const override; +}; + class PColor : public PInt { DECLARE_CLASS(PColor, PInt); @@ -917,6 +937,8 @@ extern PString *TypeString; extern PName *TypeName; extern PSound *TypeSound; extern PColor *TypeColor; +extern PTextureID *TypeTextureID; +extern PSpriteID *TypeSpriteID; extern PStruct *TypeVector2; extern PStruct *TypeVector3; extern PStruct *TypeColorStruct; diff --git a/src/namedef.h b/src/namedef.h index 0418e0f87..5ee98119a 100644 --- a/src/namedef.h +++ b/src/namedef.h @@ -737,6 +737,8 @@ xx(DamageFunction) xx(Length) xx(Unit) xx(StateLabel) +xx(SpriteID) +xx(TextureID) xx(Overlay) xx(A_Punch) diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 964736fed..313052c6b 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -191,7 +191,7 @@ void AActor::InitNativeFields() meta->AddNativeField(NAME_MomZ, TypeFloat64, myoffsetof(AActor, Vel.Z), VARF_ReadOnly | VARF_Deprecated); meta->AddNativeField(NAME_Speed, TypeFloat64, myoffsetof(AActor, Speed)); meta->AddNativeField("FloatSpeed", TypeFloat64, myoffsetof(AActor, FloatSpeed)); - meta->AddNativeField("sprite", TypeSInt32, myoffsetof(AActor, sprite)); // this is an index, not a name! + meta->AddNativeField("sprite", TypeSpriteID, myoffsetof(AActor, sprite)); meta->AddNativeField("frame", TypeUInt8, myoffsetof(AActor, frame)); meta->AddNativeField("Scale", TypeVector2, myoffsetof(AActor, Scale)); meta->AddNativeField(NAME_ScaleX, TypeFloat64, myoffsetof(AActor, Scale.X), VARF_Deprecated); @@ -206,7 +206,7 @@ void AActor::InitNativeFields() meta->AddNativeField(NAME_FloorZ, TypeFloat64, myoffsetof(AActor, floorz)); meta->AddNativeField("DropoffZ", TypeFloat64, myoffsetof(AActor, dropoffz), VARF_ReadOnly); meta->AddNativeField("floorsector", TypeSector, myoffsetof(AActor, floorsector)); - meta->AddNativeField("floorpic", TypeSInt32, myoffsetof(AActor, floorpic)); // Do we need a variable type 'texture' to do this? + meta->AddNativeField("floorpic", TypeTextureID, myoffsetof(AActor, floorpic)); meta->AddNativeField("floorterrain", TypeSInt32, myoffsetof(AActor, floorterrain)); meta->AddNativeField("ceilingsector", TypeSector, myoffsetof(AActor, ceilingsector)); meta->AddNativeField("ceilingpic", TypeSInt32, myoffsetof(AActor, ceilingpic)); // Do we need a variable type 'texture' to do this? diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index c040403d8..cae95da34 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -3825,6 +3825,8 @@ ExpEmit FxConcat::Emit(VMFunctionBuilder *build) else if (left->ValueType == TypeName) cast = CAST_N2S; else if (left->ValueType == TypeSound) cast = CAST_So2S; else if (left->ValueType == TypeColor) cast = CAST_Co2S; + else if (left->ValueType == TypeSpriteID) cast = CAST_SID2S; + else if (left->ValueType == TypeTextureID) cast = CAST_TID2S; else if (op1.RegType == REGT_POINTER) cast = CAST_P2S; else if (op1.RegType == REGT_INT) cast = CAST_I2S; else assert(false && "Bad type for string concatenation"); @@ -3856,6 +3858,8 @@ ExpEmit FxConcat::Emit(VMFunctionBuilder *build) else if (right->ValueType == TypeName) cast = CAST_N2S; else if (right->ValueType == TypeSound) cast = CAST_So2S; else if (right->ValueType == TypeColor) cast = CAST_Co2S; + else if (right->ValueType == TypeSpriteID) cast = CAST_SID2S; + else if (right->ValueType == TypeTextureID) cast = CAST_TID2S; else if (op2.RegType == REGT_POINTER) cast = CAST_P2S; else if (op2.RegType == REGT_INT) cast = CAST_I2S; else assert(false && "Bad type for string concatenation"); @@ -6880,6 +6884,8 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx) case NAME_Color: case NAME_Sound: case NAME_State: + case NAME_SpriteID: + case NAME_TextureID: if (CheckArgSize(MethodName, ArgList, 1, 1, ScriptPosition)) { PType *type = @@ -6889,6 +6895,8 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx) MethodName == NAME_Float ? TypeFloat64 : MethodName == NAME_Double ? TypeFloat64 : MethodName == NAME_Name ? TypeName : + MethodName == NAME_SpriteID ? TypeSpriteID : + MethodName == NAME_TextureID ? TypeTextureID : MethodName == NAME_State ? TypeState : MethodName == NAME_Color ? TypeColor : (PType*)TypeSound; diff --git a/src/scripting/vm/vm.h b/src/scripting/vm/vm.h index b8885e0a1..ad42ee1dd 100644 --- a/src/scripting/vm/vm.h +++ b/src/scripting/vm/vm.h @@ -127,6 +127,8 @@ enum CAST_So2S, CAST_V22S, CAST_V32S, + CAST_SID2S, + CAST_TID2S, }; // Register types for VMParam diff --git a/src/scripting/vm/vmexec.cpp b/src/scripting/vm/vmexec.cpp index 8f8559d93..24beb7f9c 100644 --- a/src/scripting/vm/vmexec.cpp +++ b/src/scripting/vm/vmexec.cpp @@ -36,6 +36,8 @@ #include #include "dobject.h" #include "xs_Float.h" +#include "r_state.h" +#include "textures/textures.h" #include "math/cmath.h" #define IMPLEMENT_VMEXEC diff --git a/src/scripting/vm/vmexec.h b/src/scripting/vm/vmexec.h index e460ef29c..2e7771680 100644 --- a/src/scripting/vm/vmexec.h +++ b/src/scripting/vm/vmexec.h @@ -1695,6 +1695,19 @@ static void DoCast(const VMRegisters ®, const VMFrame *f, int a, int b, int c reg.s[a] = S_sfx[reg.d[b]].name; break; + case CAST_SID2S: + ASSERTS(a); ASSERTD(b); + reg.s[a] = unsigned(reg.d[b]) >= sprites.Size() ? "TNT1" : sprites[reg.d[b]].name; + break; + + case CAST_TID2S: + { + ASSERTS(a); ASSERTD(b); + auto tex = TexMan[*(FTextureID*)&(reg.d[b])]; + reg.s[a] = tex == nullptr ? "(null)" : tex->Name.GetChars(); + break; + } + default: assert(0); } diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index 3d8cc18b5..27a02a919 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -1367,19 +1367,19 @@ PType *ZCCCompiler::DetermineType(PType *outertype, ZCC_TreeNode *field, FName n switch (btype->Type) { case ZCC_SInt8: - retval = TypeSInt8; + retval = formember? TypeSInt8 : (PType*)TypeError; break; case ZCC_UInt8: - retval = TypeUInt8; + retval = formember ? TypeUInt8 : (PType*)TypeError; break; case ZCC_SInt16: - retval = TypeSInt16; + retval = formember ? TypeSInt16 : (PType*)TypeError; break; case ZCC_UInt16: - retval = TypeUInt16; + retval = formember ? TypeUInt16 : (PType*)TypeError; break; case ZCC_SInt32: @@ -1395,11 +1395,9 @@ PType *ZCCCompiler::DetermineType(PType *outertype, ZCC_TreeNode *field, FName n retval = TypeBool; break; - // Do we really want to allow single precision floats, despite all the problems they cause? - // These are nearly guaranteed to desync between MSVC and GCC on x87, because GCC does not implement an IEEE compliant mode - case ZCC_Float32: case ZCC_FloatAuto: - //return TypeFloat32; + retval = formember ? TypeFloat32 : TypeFloat64; + case ZCC_Float64: retval = TypeFloat64; break; @@ -1433,14 +1431,24 @@ PType *ZCCCompiler::DetermineType(PType *outertype, ZCC_TreeNode *field, FName n break; case ZCC_UserType: - // statelabel is not a token - there really is no need to, it works just as well as an identifier. Maybe the same should be done for some other types, too? - if (btype->UserType->Id == NAME_StateLabel) + // statelabel et.al. are not tokens - there really is no need to, it works just as well as an identifier. Maybe the same should be done for some other types, too? + switch (btype->UserType->Id) { + case NAME_StateLabel: retval = TypeStateLabel; - } - else - { + break; + + case NAME_SpriteID: + retval = TypeSpriteID; + break; + + case NAME_TextureID: + retval = TypeTextureID; + break; + + default: retval = ResolveUserType(btype, &outertype->Symbols); + break; } break; } diff --git a/src/scripting/zscript/zcc_parser.h b/src/scripting/zscript/zcc_parser.h index a19249208..e000da06c 100644 --- a/src/scripting/zscript/zcc_parser.h +++ b/src/scripting/zscript/zcc_parser.h @@ -113,13 +113,12 @@ enum EZCCBuiltinType ZCC_SInt8, ZCC_UInt8, ZCC_SInt16, - ZCC_UInt16, + ZCC_UInt16, // smaller than 32 bit types are only valid in structs, classes and arrays. ZCC_SInt32, ZCC_UInt32, ZCC_IntAuto, // for enums, autoselect appropriately sized int ZCC_Bool, - ZCC_Float32, ZCC_Float64, ZCC_FloatAuto, // 32-bit in structs/classes, 64-bit everywhere else ZCC_String,