From 3798fd815f7f1c227ec6b9ca522e08fe4f4d0b32 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 3 Oct 2024 12:32:09 +0200 Subject: [PATCH] the MISSILE(EVEN)MORE flags still need to be accessible by ZScript for backwards compatibility. Since these do not exist anymore an internal interface to Handle/CheckDeprecatedFlags was added. --- src/common/engine/namedef.h | 2 + src/common/scripting/backend/codegen.cpp | 261 ++++++++++++++--------- src/scripting/thingdef_data.cpp | 12 ++ src/scripting/thingdef_properties.cpp | 16 ++ wadsrc/static/zscript/engine/base.zs | 2 + 5 files changed, 190 insertions(+), 103 deletions(-) diff --git a/src/common/engine/namedef.h b/src/common/engine/namedef.h index 7f98beba08..13827382c0 100644 --- a/src/common/engine/namedef.h +++ b/src/common/engine/namedef.h @@ -278,6 +278,8 @@ xx(BuiltinNameToClass) xx(BuiltinClassCast) xx(BuiltinFunctionPtrCast) xx(BuiltinFindTranslation) +xx(HandleDeprecatedFlags) +xx(CheckDeprecatedFlags) xx(ScreenJobRunner) xx(Action) diff --git a/src/common/scripting/backend/codegen.cpp b/src/common/scripting/backend/codegen.cpp index 5b1a975a6c..b14fb267cd 100644 --- a/src/common/scripting/backend/codegen.cpp +++ b/src/common/scripting/backend/codegen.cpp @@ -2828,83 +2828,104 @@ FxExpression *FxAssign::Resolve(FCompileContext &ctx) // Special case: Assignment to a bitfield. IsBitWrite = Base->GetBitValue(); + if (IsBitWrite >= 0x10000) + { + // internal flags - need more here + IsBitWrite &= 0xffff; + } return this; } ExpEmit FxAssign::Emit(VMFunctionBuilder *build) { - static const uint8_t loadops[] = { OP_LK, OP_LKF, OP_LKS, OP_LKP }; - assert(Base->ValueType->GetRegType() == Right->ValueType->GetRegType()); - - ExpEmit pointer = Base->Emit(build); - Address = pointer; - - ExpEmit result; - bool intconst = false; - int intconstval = 0; - - if (Right->isConstant() && Right->ValueType->GetRegType() == REGT_INT) + if (IsBitWrite < 64) { - intconst = true; - intconstval = static_cast(Right)->GetValue().GetInt(); - result.Konst = true; - result.RegType = REGT_INT; - } - else - { - result = Right->Emit(build); - } - assert(result.RegType <= REGT_TYPE); + static const uint8_t loadops[] = { OP_LK, OP_LKF, OP_LKS, OP_LKP }; + assert(Base->ValueType->GetRegType() == Right->ValueType->GetRegType()); - if (pointer.Target) - { - if (result.Konst) + ExpEmit pointer = Base->Emit(build); + Address = pointer; + + ExpEmit result; + bool intconst = false; + int intconstval = 0; + + if (Right->isConstant() && Right->ValueType->GetRegType() == REGT_INT) { - if (intconst) build->EmitLoadInt(pointer.RegNum, intconstval); - else build->Emit(loadops[result.RegType], pointer.RegNum, result.RegNum); + intconst = true; + intconstval = static_cast(Right)->GetValue().GetInt(); + result.Konst = true; + result.RegType = REGT_INT; } else { - build->Emit(Right->ValueType->GetMoveOp(), pointer.RegNum, result.RegNum); + result = Right->Emit(build); } - } - else - { - if (result.Konst) + assert(result.RegType <= REGT_TYPE); + + if (pointer.Target) + { + if (result.Konst) + { + if (intconst) build->EmitLoadInt(pointer.RegNum, intconstval); + else build->Emit(loadops[result.RegType], pointer.RegNum, result.RegNum); + } + else + { + build->Emit(Right->ValueType->GetMoveOp(), pointer.RegNum, result.RegNum); + } + } + else + { + if (result.Konst) + { + ExpEmit temp(build, result.RegType); + if (intconst) build->EmitLoadInt(temp.RegNum, intconstval); + else build->Emit(loadops[result.RegType], temp.RegNum, result.RegNum); + result.Free(build); + result = temp; + } + + if (IsBitWrite == -1) + { + build->Emit(Base->ValueType->GetStoreOp(), pointer.RegNum, result.RegNum, build->GetConstantInt(0)); + } + else + { + build->Emit(OP_SBIT, pointer.RegNum, result.RegNum, 1 << IsBitWrite); + } + } + + if (AddressRequested) { - ExpEmit temp(build, result.RegType); - if (intconst) build->EmitLoadInt(temp.RegNum, intconstval); - else build->Emit(loadops[result.RegType], temp.RegNum, result.RegNum); result.Free(build); - result = temp; + return pointer; } - if (IsBitWrite == -1) - { - build->Emit(Base->ValueType->GetStoreOp(), pointer.RegNum, result.RegNum, build->GetConstantInt(0)); + pointer.Free(build); + + if (intconst) + { //fix int constant return for assignment + return Right->Emit(build); } else { - build->Emit(OP_SBIT, pointer.RegNum, result.RegNum, 1 << IsBitWrite); + return result; } - - } - - if (AddressRequested) - { - result.Free(build); - return pointer; - } - - pointer.Free(build); - - if(intconst) - { //fix int constant return for assignment - return Right->Emit(build); } else { - return result; + VMFunction* callfunc; + auto sym = FindBuiltinFunction(NAME_HandleDeprecatedFlags); + + assert(sym); + callfunc = sym->Variants[0].Implementation; + + FunctionCallEmitter emitters(callfunc); + emitters.AddParameter(build, Base); + emitters.AddParameter(build, Right); + emitters.AddParameterIntConst(IsBitWrite - 64); + return emitters.EmitCall(build); } } @@ -2934,23 +2955,40 @@ FxExpression *FxAssignSelf::Resolve(FCompileContext &ctx) ExpEmit FxAssignSelf::Emit(VMFunctionBuilder *build) { - ExpEmit pointer = Assignment->Address; // FxAssign should have already emitted it - if (!pointer.Target) + if (Assignment->IsBitWrite < 64) { - ExpEmit out(build, ValueType->GetRegType(), ValueType->GetRegCount()); - if (Assignment->IsBitWrite != -1) + ExpEmit pointer = Assignment->Address; // FxAssign should have already emitted it + if (!pointer.Target) { - build->Emit(OP_LBIT, out.RegNum, pointer.RegNum, 1 << Assignment->IsBitWrite); + ExpEmit out(build, ValueType->GetRegType(), ValueType->GetRegCount()); + if (Assignment->IsBitWrite == -1) + { + build->Emit(ValueType->GetLoadOp(), out.RegNum, pointer.RegNum, build->GetConstantInt(0)); + } + else + { + build->Emit(OP_LBIT, out.RegNum, pointer.RegNum, 1 << Assignment->IsBitWrite); + } + return out; } else { - build->Emit(ValueType->GetLoadOp(), out.RegNum, pointer.RegNum, build->GetConstantInt(0)); + return pointer; } - return out; } else { - return pointer; + VMFunction* callfunc; + auto sym = FindBuiltinFunction(NAME_CheckDeprecatedFlags); + + assert(sym); + callfunc = sym->Variants[0].Implementation; + + FunctionCallEmitter emitters(callfunc); + emitters.AddParameter(build, Assignment->Base); + emitters.AddParameterIntConst(Assignment->IsBitWrite - 64); + emitters.AddReturn(REGT_INT); + return emitters.EmitCall(build); } } @@ -7728,56 +7766,73 @@ FxExpression *FxStructMember::Resolve(FCompileContext &ctx) ExpEmit FxStructMember::Emit(VMFunctionBuilder *build) { - ExpEmit obj = classx->Emit(build); - assert(obj.RegType == REGT_POINTER); - - if (obj.Konst) + if (membervar->BitValue < 64 || AddressRequested) { - // If the situation where we are dereferencing a constant - // pointer is common, then it would probably be worthwhile - // to add new opcodes for those. But as of right now, I - // don't expect it to be a particularly common case. - ExpEmit newobj(build, REGT_POINTER); - build->Emit(OP_LKP, newobj.RegNum, obj.RegNum); - obj = newobj; - } + ExpEmit obj = classx->Emit(build); + assert(obj.RegType == REGT_POINTER); - if (membervar->Flags & VARF_Meta) - { - obj.Free(build); - ExpEmit meta(build, REGT_POINTER); - build->Emit(OP_META, meta.RegNum, obj.RegNum); - obj = meta; - } - - if (AddressRequested) - { - if (membervar->Offset == 0) + if (obj.Konst) { - return obj; + // If the situation where we are dereferencing a constant + // pointer is common, then it would probably be worthwhile + // to add new opcodes for those. But as of right now, I + // don't expect it to be a particularly common case. + ExpEmit newobj(build, REGT_POINTER); + build->Emit(OP_LKP, newobj.RegNum, obj.RegNum); + obj = newobj; + } + + if (membervar->Flags & VARF_Meta) + { + obj.Free(build); + ExpEmit meta(build, REGT_POINTER); + build->Emit(OP_META, meta.RegNum, obj.RegNum); + obj = meta; + } + + if (AddressRequested) + { + if (membervar->Offset == 0) + { + return obj; + } + obj.Free(build); + ExpEmit out(build, REGT_POINTER); + build->Emit(OP_ADDA_RK, out.RegNum, obj.RegNum, build->GetConstantInt((int)membervar->Offset)); + return out; + } + + int offsetreg = build->GetConstantInt((int)membervar->Offset); + ExpEmit loc(build, membervar->Type->GetRegType(), membervar->Type->GetRegCount()); + + if (membervar->BitValue == -1) + { + build->Emit(membervar->Type->GetLoadOp(), loc.RegNum, obj.RegNum, offsetreg); + } + else + { + ExpEmit out(build, REGT_POINTER); + build->Emit(OP_ADDA_RK, out.RegNum, obj.RegNum, offsetreg); + build->Emit(OP_LBIT, loc.RegNum, out.RegNum, 1 << membervar->BitValue); + out.Free(build); } obj.Free(build); - ExpEmit out(build, REGT_POINTER); - build->Emit(OP_ADDA_RK, out.RegNum, obj.RegNum, build->GetConstantInt((int)membervar->Offset)); - return out; - } - - int offsetreg = build->GetConstantInt((int)membervar->Offset); - ExpEmit loc(build, membervar->Type->GetRegType(), membervar->Type->GetRegCount()); - - if (membervar->BitValue == -1) - { - build->Emit(membervar->Type->GetLoadOp(), loc.RegNum, obj.RegNum, offsetreg); + return loc; } else { - ExpEmit out(build, REGT_POINTER); - build->Emit(OP_ADDA_RK, out.RegNum, obj.RegNum, offsetreg); - build->Emit(OP_LBIT, loc.RegNum, out.RegNum, 1 << membervar->BitValue); - out.Free(build); + VMFunction* callfunc; + auto sym = FindBuiltinFunction(NAME_CheckDeprecatedFlags); + + assert(sym); + callfunc = sym->Variants[0].Implementation; + + FunctionCallEmitter emitters(callfunc); + emitters.AddParameter(build, classx); + emitters.AddParameterIntConst(membervar->BitValue - 64); + emitters.AddReturn(REGT_INT); + return emitters.EmitCall(build); } - obj.Free(build); - return loc; } diff --git a/src/scripting/thingdef_data.cpp b/src/scripting/thingdef_data.cpp index 8f19bab54c..129c06b786 100644 --- a/src/scripting/thingdef_data.cpp +++ b/src/scripting/thingdef_data.cpp @@ -920,6 +920,18 @@ void SynthesizeFlagFields() { cls->VMType->AddNativeField(FStringf("b%s", fl.Defs[i].name), (fl.Defs[i].fieldsize == 4 ? TypeSInt32 : TypeSInt16), fl.Defs[i].structoffset, fl.Defs[i].varflags, fl.Defs[i].flagbit); } + else if (fl.Defs[i].flagbit == DEPF_MISSILEMORE || fl.Defs[i].flagbit == DEPF_MISSILEEVENMORE) // these need script side emulation because they have been around for many years. + { + auto field = cls->VMType->AddNativeField(FStringf("b%s", fl.Defs[i].name), TypeSInt32, 0, VARF_Native); + if (field) + { + // these are deprecated so flag accordingly with a proper message. + field->DeprecationMessage = "Use missilechancemult property instead"; + field->mVersion = MakeVersion(4, 13, 0); + field->Flags |= VARF_Deprecated; + field->BitValue = fl.Defs[i].flagbit + 64; + } + } } } } diff --git a/src/scripting/thingdef_properties.cpp b/src/scripting/thingdef_properties.cpp index 4969765a75..2154f4db59 100644 --- a/src/scripting/thingdef_properties.cpp +++ b/src/scripting/thingdef_properties.cpp @@ -361,6 +361,15 @@ void HandleDeprecatedFlags(AActor *actor, int set, int index) } } +// the interface here works on object, but currently all deprecated flags affect subclasses of Actor only +DEFINE_ACTION_FUNCTION_NATIVE(DObject, HandleDeprecatedFlags, HandleDeprecatedFlags) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_INT(set); + PARAM_INT(index); + HandleDeprecatedFlags(self, set, index); + return 0; +} //=========================================================================== // // CheckDeprecatedFlags @@ -429,6 +438,13 @@ int CheckDeprecatedFlags(AActor *actor, int index) return false; // Any entirely unknown flag is not set } +DEFINE_ACTION_FUNCTION_NATIVE(DObject, CheckDeprecatedFlags, CheckDeprecatedFlags) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_INT(index); + ACTION_RETURN_INT(CheckDeprecatedFlags(self, index)); +} + //========================================================================== // // diff --git a/wadsrc/static/zscript/engine/base.zs b/wadsrc/static/zscript/engine/base.zs index c4322918f4..18fe1b363e 100644 --- a/wadsrc/static/zscript/engine/base.zs +++ b/wadsrc/static/zscript/engine/base.zs @@ -760,6 +760,8 @@ class Object native private native static Class BuiltinNameToClass(Name nm, Class filter); private native static Object BuiltinClassCast(Object inptr, Class test); private native static Function BuiltinFunctionPtrCast(Function inptr, voidptr newtype); + private native static void HandleDeprecatedFlags(Object obj, bool set, int index); + private native static bool CheckDeprecatedFlags(Object obj, int index); native static uint MSTime(); native static double MSTimeF();