diff --git a/src/actor.h b/src/actor.h index 995c4d0732..970397d15d 100644 --- a/src/actor.h +++ b/src/actor.h @@ -797,7 +797,7 @@ public: fixed_t velx, vely, velz; // velocity SDWORD tics; // state tic counter FState *state; - SDWORD Damage; // For missiles and monster railgun + VMFunction *Damage; // For missiles and monster railgun int projectileKickback; DWORD flags; DWORD flags2; // Heretic flags diff --git a/src/d_dehacked.cpp b/src/d_dehacked.cpp index 97f76bce64..c1e3b28000 100644 --- a/src/d_dehacked.cpp +++ b/src/d_dehacked.cpp @@ -852,7 +852,7 @@ static int PatchThing (int thingy) } else if (linelen == 14 && stricmp (Line1, "Missile damage") == 0) { - info->Damage = val; + info->Damage = CreateDamageFunction(val); } else if (linelen == 5) { diff --git a/src/g_doom/a_bossbrain.cpp b/src/g_doom/a_bossbrain.cpp index 59191032c2..51d7f0e624 100644 --- a/src/g_doom/a_bossbrain.cpp +++ b/src/g_doom/a_bossbrain.cpp @@ -47,7 +47,7 @@ static void BrainishExplosion (fixed_t x, fixed_t y, fixed_t z) boom->SetState (state); } boom->effects = 0; - boom->Damage = 0; // disables collision detection which is not wanted here + boom->Damage = NULL; // disables collision detection which is not wanted here boom->tics -= pr_brainscream() & 7; if (boom->tics < 1) boom->tics = 1; diff --git a/src/g_doom/a_fatso.cpp b/src/g_doom/a_fatso.cpp index 67ae803b9b..015e82916e 100644 --- a/src/g_doom/a_fatso.cpp +++ b/src/g_doom/a_fatso.cpp @@ -144,7 +144,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Mushroom) if (n == 0) { - n = self->Damage; // GetMissileDamage (0, 1); + n = self->GetMissileDamage(0, 1); } if (spawntype == NULL) { diff --git a/src/g_doom/a_lostsoul.cpp b/src/g_doom/a_lostsoul.cpp index 887f2d9d79..a8fb44c0ae 100644 --- a/src/g_doom/a_lostsoul.cpp +++ b/src/g_doom/a_lostsoul.cpp @@ -65,7 +65,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_BetaSkullAttack) return 0; S_Sound (self, CHAN_WEAPON, self->AttackSound, 1, ATTN_NORM); A_FaceTarget(self); - damage = (pr_oldsoul()%8+1)*self->Damage; + damage = (pr_oldsoul()%8+1)*self->GetMissileDamage(0,1); P_DamageMobj(self->target, self, self, damage, NAME_None); return 0; } diff --git a/src/g_heretic/a_ironlich.cpp b/src/g_heretic/a_ironlich.cpp index 0a345d2a6f..852f3d2582 100644 --- a/src/g_heretic/a_ironlich.cpp +++ b/src/g_heretic/a_ironlich.cpp @@ -116,7 +116,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_LichAttack) fire->velx = baseFire->velx; fire->vely = baseFire->vely; fire->velz = baseFire->velz; - fire->Damage = 0; + fire->Damage = NULL; fire->health = (i+1) * 2; P_CheckMissileSpawn (fire); } diff --git a/src/g_hexen/a_magelightning.cpp b/src/g_hexen/a_magelightning.cpp index 7010aaceb0..0a31ef1433 100644 --- a/src/g_hexen/a_magelightning.cpp +++ b/src/g_hexen/a_magelightning.cpp @@ -356,7 +356,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_LastZap) { mo->SetState (mo->FindState (NAME_Death)); mo->velz = 40*FRACUNIT; - mo->Damage = 0; + mo->Damage = NULL; } return 0; } diff --git a/src/info.cpp b/src/info.cpp index 361ba4bf02..523855084d 100644 --- a/src/info.cpp +++ b/src/info.cpp @@ -302,6 +302,9 @@ size_t PClassActor::PropagateMark() GC::Mark(OwnedStates[i].ActionFunc); } } + // Mark damage function + GC::Mark(((AActor *)Defaults)->Damage); + // marked += ActorInfo->NumOwnedStates * sizeof(FState); return Super::PropagateMark(); } diff --git a/src/p_acs.cpp b/src/p_acs.cpp index 668c4dc1b1..81da86259c 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -2832,7 +2832,7 @@ void DLevelScript::DoSetActorProperty (AActor *actor, int property, int value) break; case APROP_Damage: - actor->Damage = value; + actor->Damage = CreateDamageFunction(value); break; case APROP_Alpha: @@ -2994,7 +2994,7 @@ int DLevelScript::GetActorProperty (int tid, int property) { case APROP_Health: return actor->health; case APROP_Speed: return actor->Speed; - case APROP_Damage: return actor->Damage; // Should this call GetMissileDamage() instead? + case APROP_Damage: return actor->GetMissileDamage(0,1); case APROP_DamageFactor:return actor->DamageFactor; case APROP_Alpha: return actor->alpha; case APROP_RenderStyle: for (int style = STYLE_None; style < STYLE_Count; ++style) diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index f0fcf9b467..458ed36f0d 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -136,6 +136,7 @@ IMPLEMENT_POINTY_CLASS (AActor) DECLARE_POINTER (LastHeard) DECLARE_POINTER (master) DECLARE_POINTER (Poisoner) + DECLARE_POINTER (Damage) END_POINTERS AActor::~AActor () @@ -2778,21 +2779,34 @@ CCMD(utid) int AActor::GetMissileDamage (int mask, int add) { - if ((Damage & 0xC0000000) == 0x40000000) - { - return EvalExpressionI (Damage & 0x3FFFFFFF, this); - } - if (Damage == 0) + if (Damage == NULL) { return 0; } + VMFrameStack stack; + VMValue param = this; + VMReturn results[2]; + + int amount, calculated = false; + + results[0].IntAt(&amount); + results[1].IntAt(&calculated); + + if (stack.Call(Damage, ¶m, 1, results, 2) < 1) + { // No results + return 0; + } + if (calculated) + { + return amount; + } else if (mask == 0) { - return add * Damage; + return add * amount; } else { - return ((pr_missiledamage() & mask) + add) * Damage; + return ((pr_missiledamage() & mask) + add) * amount; } } diff --git a/src/thingdef/olddecorations.cpp b/src/thingdef/olddecorations.cpp index 78d890be07..8c1da024c1 100644 --- a/src/thingdef/olddecorations.cpp +++ b/src/thingdef/olddecorations.cpp @@ -495,7 +495,7 @@ static void ParseInsideDecoration (Baggage &bag, AActor *defaults, else if (def == DEF_Projectile && sc.Compare ("Damage")) { sc.MustGetNumber (); - defaults->Damage = sc.Number; + defaults->Damage = CreateDamageFunction(sc.Number); } else if (def == DEF_Projectile && sc.Compare ("DamageType")) { diff --git a/src/thingdef/thingdef.cpp b/src/thingdef/thingdef.cpp index b764e48abd..d162a9f107 100644 --- a/src/thingdef/thingdef.cpp +++ b/src/thingdef/thingdef.cpp @@ -261,6 +261,17 @@ void FinishActor(const FScriptPosition &sc, PClassActor *info, Baggage &bag) // //========================================================================== +static void DumpFunction(FILE *dump, VMScriptFunction *sfunc, const char *label, int labellen) +{ + const char *marks = "======================================================="; + fprintf(dump, "\n%.*s %s %.*s", MAX(3, 38 - labellen / 2), marks, label, MAX(3, 38 - labellen / 2), marks); + fprintf(dump, "\nInteger regs: %-3d Float regs: %-3d Address regs: %-3d String regs: %-3d\nStack size: %d\n", + sfunc->NumRegD, sfunc->NumRegF, sfunc->NumRegA, sfunc->NumRegS, sfunc->MaxParam); + VMDumpConstants(dump, sfunc); + fprintf(dump, "\nDisassembly @ %p:\n", sfunc->Code); + VMDisasm(dump, sfunc->Code, sfunc->CodeSize, sfunc); +} + static void FinishThingdef() { int errorcount = StateParams.ResolveAll(); @@ -305,17 +316,10 @@ static void FinishThingdef() sfunc->NumArgs = NAP; func = sfunc; #if 1 - const char *marks = "======================================================="; char label[64]; int labellen = mysnprintf(label, countof(label), "Function %s.States[%d] (*%d)", - tcall->ActorClass->TypeName.GetChars(), - tcall->FirstState, tcall->NumStates); - fprintf(dump, "\n%.*s %s %.*s", MAX(3, 38 - labellen / 2), marks, label, MAX(3, 38 - labellen / 2), marks); - fprintf(dump, "\nInteger regs: %-3d Float regs: %-3d Address regs: %-3d String regs: %-3d\nStack size: %d\n", - sfunc->NumRegD, sfunc->NumRegF, sfunc->NumRegA, sfunc->NumRegS, sfunc->MaxParam); - VMDumpConstants(dump, sfunc); - fprintf(dump, "\nDisassembly @ %p:\n", sfunc->Code); - VMDisasm(dump, sfunc->Code, sfunc->CodeSize, sfunc); + tcall->ActorClass->TypeName.GetChars(), tcall->FirstState, tcall->NumStates); + DumpFunction(dump, sfunc, label, labellen); codesize += sfunc->CodeSize; #endif } @@ -324,10 +328,6 @@ static void FinishThingdef() tcall->ActorClass->OwnedStates[tcall->FirstState + k].SetAction(func); } } -#if 1 - fprintf(dump, "\n*************************************************************************\n%i code bytes\n", codesize * 4); -#endif - fclose(dump); for (i = 0; i < PClassActor::AllActorClasses.Size(); i++) { @@ -348,7 +348,42 @@ static void FinishThingdef() errorcount++; continue; } + + if (def->Damage != NULL) + { + VMScriptFunction *sfunc; + FxDamageValue *dmg = (FxDamageValue *)def->Damage; + sfunc = dmg->GetFunction(); + if (sfunc == NULL) + { + FCompileContext ctx(ti, true); + dmg->Resolve(ctx); + VMFunctionBuilder buildit; + buildit.Registers[REGT_POINTER].Get(1); // The self pointer + dmg->Emit(&buildit); + sfunc = buildit.MakeFunction(); + sfunc->NumArgs = 1; + // Save this function in case this damage value was reused + // (which happens quite easily with inheritance). + dmg->SetFunction(sfunc); + } + def->Damage = sfunc; +#if 1 + if (sfunc != NULL) + { + char label[64]; + int labellen = mysnprintf(label, countof(label), "Function %s.Damage", + ti->TypeName.GetChars()); + DumpFunction(dump, sfunc, label, labellen); + codesize += sfunc->CodeSize; + } +#endif + } } +#if 1 + fprintf(dump, "\n*************************************************************************\n%i code bytes\n", codesize * 4); +#endif + fclose(dump); if (errorcount > 0) { I_Error("%d errors during actor postprocessing", errorcount); @@ -399,3 +434,23 @@ void LoadActors () // Base time: ~52 ms } + +//========================================================================== +// +// CreateDamageFunction +// +// Creates a damage function suitable for a constant, non-expressioned +// value. +// +//========================================================================== + +VMScriptFunction *CreateDamageFunction(int dmg) +{ + VMFunctionBuilder build; + build.Registers[REGT_POINTER].Get(1); // The self pointer + build.EmitRetInt(0, false, dmg); + build.EmitRetInt(1, true, 0); + VMScriptFunction *sfunc = build.MakeFunction(); + sfunc->NumArgs = 1; + return sfunc; +} diff --git a/src/thingdef/thingdef.h b/src/thingdef/thingdef.h index 68d16e8fc1..2eb84b0024 100644 --- a/src/thingdef/thingdef.h +++ b/src/thingdef/thingdef.h @@ -141,8 +141,8 @@ public: void Clear(); int Add(FxExpression *x, PClassActor *o, bool c); int Reserve(int num, PClassActor *cls); - void Set(int num, FxExpression *x, bool cloned = false); - void Copy(int dest, int src, int cnt); +// void Set(int num, FxExpression *x, bool cloned = false); +// void Copy(int dest, int src, int cnt); int ResolveAll(); FxExpression *Get(int no); unsigned int Size() { return expressions.Size(); } @@ -184,6 +184,14 @@ inline void ResetBaggage (Baggage *bag, PClassActor *stateclass) bag->statedef.MakeStateDefines(stateclass); } +//========================================================================== +// +// Damage function creation +// +//========================================================================== + +VMScriptFunction *CreateDamageFunction(int dmg); + //========================================================================== // // Action function lookup @@ -270,6 +278,7 @@ union FPropParam int i; float f; const char *s; + FxExpression *exp; }; typedef void (*PropHandler)(AActor *defaults, PClassActor *info, Baggage &bag, FPropParam *params); @@ -328,6 +337,9 @@ int MatchString (const char *in, const char **strings); #define PROP_STRING_PARM(var, no) \ const char *var = params[(no)+1].s; +#define PROP_EXP_PARM(var, no) \ + FxExpression *var = params[(no)+1].exp; + #define PROP_INT_PARM(var, no) \ int var = params[(no)+1].i; @@ -375,44 +387,6 @@ int MatchString (const char *in, const char **strings); } -int EvalExpressionI (DWORD x, AActor *self); -int EvalExpressionCol (DWORD x, AActor *self); -FSoundID EvalExpressionSnd (DWORD x, AActor *self); -double EvalExpressionF (DWORD x, AActor *self); -fixed_t EvalExpressionFix (DWORD x, AActor *self); -FState *EvalExpressionState (DWORD x, AActor *self); -const PClass *EvalExpressionClass (DWORD x, AActor *self); -FName EvalExpressionName (DWORD x, AActor *self); - -#if 0 -#define ACTION_PARAM_START(count) - -#define ACTION_PARAM_INT(var, i) \ - int var = EvalExpressionI(ParameterIndex+i, self); -#define ACTION_PARAM_BOOL(var,i) \ - bool var = !!EvalExpressionI(ParameterIndex+i, self); -#define ACTION_PARAM_FIXED(var,i) \ - fixed_t var = EvalExpressionFix(ParameterIndex+i, self); -#define ACTION_PARAM_FLOAT(var,i) \ - float var = float(EvalExpressionF(ParameterIndex+i, self)); -#define ACTION_PARAM_DOUBLE(var,i) \ - double var = EvalExpressionF(ParameterIndex+i, self); -#define ACTION_PARAM_CLASS(var,i) \ - const PClass *var = EvalExpressionClass(ParameterIndex+i, self); -#define ACTION_PARAM_STATE(var,i) \ - FState *var = EvalExpressionState(ParameterIndex+i, stateowner); -#define ACTION_PARAM_COLOR(var,i) \ - PalEntry var = EvalExpressionCol(ParameterIndex+i, self); -#define ACTION_PARAM_SOUND(var,i) \ - FSoundID var = EvalExpressionSnd(ParameterIndex+i, self); -#define ACTION_PARAM_STRING(var,i) \ - const char *var = EvalExpressionName(ParameterIndex+i, self); -#define ACTION_PARAM_NAME(var,i) \ - FName var = EvalExpressionName(ParameterIndex+i, self); -#define ACTION_PARAM_ANGLE(var,i) \ - angle_t var = angle_t(EvalExpressionF(ParameterIndex+i, self)*ANGLE_90/90.f); -#endif - #define ACTION_SET_RESULT(v) do { if (numret > 0) { assert(ret != NULL); ret->SetInt(v); numret = 1; } } while(0) // Checks to see what called the current action function diff --git a/src/thingdef/thingdef_exp.h b/src/thingdef/thingdef_exp.h index ccf73eb346..abca3c722c 100644 --- a/src/thingdef/thingdef_exp.h +++ b/src/thingdef/thingdef_exp.h @@ -904,6 +904,28 @@ public: ExpEmit Emit(VMFunctionBuilder *build); }; +//========================================================================== +// +// +// +//========================================================================== + +class FxDamageValue : public FxExpression +{ + FxExpression *val; + bool Calculated; + VMScriptFunction *MyFunction; + +public: + + FxDamageValue(FxExpression *v, bool calc); + ~FxDamageValue(); + FxExpression *Resolve(FCompileContext&); + + ExpEmit Emit(VMFunctionBuilder *build); + VMScriptFunction *GetFunction() const { return MyFunction; } + void SetFunction(VMScriptFunction *func) { MyFunction = func; } +}; FxExpression *ParseExpression (FScanner &sc, PClassActor *cls); diff --git a/src/thingdef/thingdef_expression.cpp b/src/thingdef/thingdef_expression.cpp index ea5c5005e5..7c68d99b5e 100644 --- a/src/thingdef/thingdef_expression.cpp +++ b/src/thingdef/thingdef_expression.cpp @@ -79,7 +79,7 @@ DEFINE_MEMBER_VARIABLE_ALIAS(momy, vely, AActor) DEFINE_MEMBER_VARIABLE_ALIAS(momz, velz, AActor) DEFINE_MEMBER_VARIABLE(scaleX, AActor) DEFINE_MEMBER_VARIABLE(scaleY, AActor) -DEFINE_MEMBER_VARIABLE(Damage, AActor) +//DEFINE_MEMBER_VARIABLE(Damage, AActor) DEFINE_MEMBER_VARIABLE(Score, AActor) DEFINE_MEMBER_VARIABLE(accuracy, AActor) DEFINE_MEMBER_VARIABLE(stamina, AActor) @@ -120,89 +120,6 @@ static PSymbol *FindDecorateBuiltinFunction(FName funcname, VMNativeFunction::Na return sym; } -//========================================================================== -// -// EvalExpression -// [GRB] Evaluates previously stored expression -// -//========================================================================== - - -int EvalExpressionI (DWORD xi, AActor *self) -{ - FxExpression *x = StateParams.Get(xi); - if (x == NULL) return 0; - - return x->EvalExpression (self).GetInt(); -} - -int EvalExpressionCol (DWORD xi, AActor *self) -{ - FxExpression *x = StateParams.Get(xi); - if (x == NULL) return 0; - - return x->EvalExpression (self).GetColor(); -} - -FSoundID EvalExpressionSnd (DWORD xi, AActor *self) -{ - FxExpression *x = StateParams.Get(xi); - if (x == NULL) return 0; - - return x->EvalExpression (self).GetSoundID(); -} - -double EvalExpressionF (DWORD xi, AActor *self) -{ - FxExpression *x = StateParams.Get(xi); - if (x == NULL) return 0; - - return x->EvalExpression (self).GetFloat(); -} - -fixed_t EvalExpressionFix (DWORD xi, AActor *self) -{ - FxExpression *x = StateParams.Get(xi); - if (x == NULL) return 0; - - ExpVal val = x->EvalExpression (self); - - switch (val.Type) - { - default: - return 0; - case VAL_Int: - return val.Int << FRACBITS; - case VAL_Float: - return fixed_t(val.Float*FRACUNIT); - } -} - -FName EvalExpressionName (DWORD xi, AActor *self) -{ - FxExpression *x = StateParams.Get(xi); - if (x == NULL) return 0; - - return x->EvalExpression (self).GetName(); -} - -const PClass * EvalExpressionClass (DWORD xi, AActor *self) -{ - FxExpression *x = StateParams.Get(xi); - if (x == NULL) return 0; - - return x->EvalExpression (self).GetClass(); -} - -FState *EvalExpressionState (DWORD xi, AActor *self) -{ - FxExpression *x = StateParams.Get(xi); - if (x == NULL) return 0; - - return x->EvalExpression (self).GetState(); -} - - //========================================================================== // // @@ -4025,6 +3942,64 @@ ExpEmit FxMultiNameState::Emit(VMFunctionBuilder *build) return dest; } +//========================================================================== +// +// +// +//========================================================================== + +FxDamageValue::FxDamageValue(FxExpression *v, bool calc) +: FxExpression(v->ScriptPosition) +{ + val = v; + ValueType = VAL_Unknown; + Calculated = calc; + MyFunction = NULL; + + if (!calc) + { + assert(v->isConstant() && "Non-calculated damage must be constant"); + } +} + +FxDamageValue::~FxDamageValue() +{ + SAFE_DELETE(val); + +} + +FxExpression *FxDamageValue::Resolve(FCompileContext &ctx) +{ + CHECKRESOLVED(); + SAFE_RESOLVE(val, ctx) + + if (!val->ValueType.isNumeric()) + { + ScriptPosition.Message(MSG_ERROR, "Numeric type expected"); + delete this; + return NULL; + } + return this; +} + +// This is a highly-specialized "expression" type that emits a complete function. +ExpEmit FxDamageValue::Emit(VMFunctionBuilder *build) +{ + if (val->isConstant()) + { + build->EmitRetInt(0, false, val->EvalExpression(NULL).Int); + } + else + { + ExpEmit emitval = val->Emit(build); + assert(emitval.RegType == REGT_INT); + build->Emit(OP_RET, 0, REGT_INT | (emitval.Konst ? REGT_KONST : 0), emitval.RegNum); + } + build->Emit(OP_RETI, 1, 0x8000 | (int)Calculated); + + return ExpEmit(); +} + //========================================================================== // @@ -4096,38 +4071,6 @@ int FStateExpressions::Reserve(int num, PClassActor *cls) // //========================================================================== -void FStateExpressions::Set(int num, FxExpression *x, bool cloned) -{ - if (num >= 0 && num < int(Size())) - { - assert(expressions[num].expr == NULL || expressions[num].cloned); - expressions[num].expr = x; - expressions[num].cloned = cloned; - } -} - -//========================================================================== -// -// -// -//========================================================================== - -void FStateExpressions::Copy(int dest, int src, int cnt) -{ - for(int i=0; iDamage = id; + // Store this expression here for now. It will be converted to a function + // later once all actors have been processed. + defaults->Damage = (VMFunction *)id; } //========================================================================== diff --git a/src/zscript/vmbuilder.cpp b/src/zscript/vmbuilder.cpp index 4cf613d8f3..78051d8160 100644 --- a/src/zscript/vmbuilder.cpp +++ b/src/zscript/vmbuilder.cpp @@ -490,6 +490,27 @@ size_t VMFunctionBuilder::EmitLoadInt(int regnum, int value) } } +//========================================================================== +// +// VMFunctionBuilder :: EmitRetInt +// +// Returns an integer, using either an immediate value or a constant +// register, as appropriate. +// +//========================================================================== + +size_t VMFunctionBuilder::EmitRetInt(int retnum, bool final, int value) +{ + if (value >= -16384 && value <= 16383) + { + return Emit(OP_RETI, retnum, value | (final << 15)); + } + else + { + return Emit(OP_RETI, retnum, REGT_INT | REGT_KONST | (final ? REGT_FINAL : 0), GetConstantInt(value)); + } +} + //========================================================================== // // VMFunctionBuilder :: Backpatch diff --git a/src/zscript/vmbuilder.h b/src/zscript/vmbuilder.h index 2399411f63..7587d1b207 100644 --- a/src/zscript/vmbuilder.h +++ b/src/zscript/vmbuilder.h @@ -37,6 +37,7 @@ public: size_t Emit(int opcode, int opa, VM_SHALF opbc); size_t Emit(int opcode, int opabc); size_t EmitLoadInt(int regnum, int value); + size_t EmitRetInt(int retnum, bool final, int value); void Backpatch(size_t addr, size_t target); void BackpatchToHere(size_t addr); diff --git a/src/zscript/vmdisasm.cpp b/src/zscript/vmdisasm.cpp index 81eb50bbac..77abf9d12e 100644 --- a/src/zscript/vmdisasm.cpp +++ b/src/zscript/vmdisasm.cpp @@ -43,6 +43,7 @@ #define RII16 MODE_AI | MODE_BCJOINT | MODE_BCIMMS #define I24 MODE_ABCJOINT #define I8 MODE_AIMMZ | MODE_BUNUSED | MODE_CUNUSED +#define I8I16 MODE_AIMMZ | MODE_BCIMMZ #define __BCP MODE_AUNUSED | MODE_BCJOINT | MODE_BCPARAM #define RPI8 MODE_AP | MODE_BIMMZ | MODE_CUNUSED #define KPI8 MODE_AKP | MODE_BIMMZ | MODE_CUNUSED @@ -246,6 +247,22 @@ void VMDisasm(FILE *out, const VMOP *code, int codesize, const VMScriptFunction } break; + case OP_RETI: + if (a == 0 && code[i].i16 & 0x8000) + { + col = printf_wrapper(out, "%d", (code[i].i16 << 17) >> 17); + } + else + { + col = print_reg(out, 0, a, (mode & MODE_ATYPE) >> MODE_ASHIFT, 24, func); + col += print_reg(out, col, (code[i].i16 << 17) >> 17, MODE_IMMS, 16, func); + if (code[i].i16 & 0x8000) + { + col += printf_wrapper(out, " [final]"); + } + } + break; + default: if ((mode & MODE_BCTYPE) == MODE_BCCAST) { diff --git a/src/zscript/vmexec.h b/src/zscript/vmexec.h index ff9b471d58..a1a22a964e 100644 --- a/src/zscript/vmexec.h +++ b/src/zscript/vmexec.h @@ -593,6 +593,18 @@ begin: return a < numret ? a + 1 : numret; } NEXTOP; + OP(RETI): + assert(ret != NULL || numret == 0); + if (a < numret) + { + // Shifting by 17 to wipe out the final bit + ret[a].SetInt(((pc[-1].i16) << 17) >> 17); + } + if (pc[-1].i16 & 0x8000) + { + return a < numret ? a + 1 : numret; + } + NEXTOP; OP(RESULT): // This instruction is just a placeholder to indicate where a return // value should be stored. It does nothing on its own and should not diff --git a/src/zscript/vmops.h b/src/zscript/vmops.h index 78ef5116f3..353dc3e85b 100644 --- a/src/zscript/vmops.h +++ b/src/zscript/vmops.h @@ -81,6 +81,7 @@ xx(TAIL, tail, RPI8), // Call+Ret in a single instruction xx(TAIL_K, tail, KPI8), xx(RESULT, result, __BCP), // Result should go in register encoded in BC (in caller, after CALL) xx(RET, ret, I8BCP), // Copy value from register encoded in BC to return value A, possibly returning +xx(RETI, reti, I8I16), // Copy immediate from BC to return value A, possibly returning xx(TRY, try, I24), // When an exception is thrown, start searching for a handler at pc + ABC xx(UNTRY, untry, I8), // Pop A entries off the exception stack xx(THROW, throw, THROW), // A == 0: Throw exception object pB diff --git a/wadsrc/static/actors/actor.txt b/wadsrc/static/actors/actor.txt index a6c7bd1c51..1f50643da8 100644 --- a/wadsrc/static/actors/actor.txt +++ b/wadsrc/static/actors/actor.txt @@ -41,7 +41,7 @@ ACTOR Actor native //: Thinker native int tid; native int TIDtoHate; native int waterlevel; - native int damage; + //native int damage; native fixed_t x; native fixed_t y; native fixed_t z;