mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-11 07:12:02 +00:00
- Added a RETI instruction for returning 15-bit signed immediate values.
- Changed Actor's Damage property into an actual function. All access to the damage property must now be done through GetMissileDamage. actor->GetMissileDamage(0, 1) is equivalent to the former actor->Damage, for the case where actor->Damage was not an expression. (I suppose I will probably need to make a thunk for DECORATE expressions that want to read it.) - Cleaned up some decorate expression evaluation functions that are no longer used. SVN r3919 (scripting)
This commit is contained in:
parent
5e184260ac
commit
6e88529324
23 changed files with 271 additions and 196 deletions
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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"))
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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; i<cnt; i++)
|
||||
{
|
||||
// For now set only a reference because these expressions may change when being resolved
|
||||
expressions[dest+i].expr = (FxExpression*)intptr_t(src+i);
|
||||
expressions[dest+i].cloned = true;
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
int FStateExpressions::ResolveAll()
|
||||
{
|
||||
int errorcount = 0;
|
||||
|
|
|
@ -669,16 +669,26 @@ static bool ParsePropertyParams(FScanner &sc, FPropertyInfo *prop, AActor *defau
|
|||
switch ((*p) & 223)
|
||||
{
|
||||
case 'X': // Expression in parentheses or number.
|
||||
|
||||
if (sc.CheckString ("("))
|
||||
{
|
||||
FxExpression *x = ParseExpression(sc, bag.Info);
|
||||
conv.i = 0x40000000 | StateParams.Add(x, bag.Info, false);
|
||||
FxExpression *x = NULL;
|
||||
|
||||
if (sc.CheckString ("("))
|
||||
{
|
||||
x = new FxDamageValue(new FxIntCast(ParseExpression(sc, bag.Info)), true);
|
||||
sc.MustGetStringName(")");
|
||||
}
|
||||
else
|
||||
{
|
||||
sc.MustGetNumber();
|
||||
if (sc.Number != 0)
|
||||
{
|
||||
x = new FxDamageValue(new FxConstant(sc.Number, bag.ScriptPosition), false);
|
||||
}
|
||||
}
|
||||
conv.exp = x;
|
||||
params.Push(conv);
|
||||
sc.MustGetStringName(")");
|
||||
break;
|
||||
}
|
||||
// fall through
|
||||
break;
|
||||
|
||||
case 'I':
|
||||
sc.MustGetNumber();
|
||||
|
|
|
@ -449,7 +449,7 @@ DEFINE_PROPERTY(painthreshold, I, Actor)
|
|||
//==========================================================================
|
||||
DEFINE_PROPERTY(damage, X, Actor)
|
||||
{
|
||||
PROP_INT_PARM(id, 0);
|
||||
PROP_EXP_PARM(id, 0);
|
||||
|
||||
// Damage can either be a single number, in which case it is subject
|
||||
// to the original damage calculation rules. Or, it can be an expression
|
||||
|
@ -457,7 +457,9 @@ DEFINE_PROPERTY(damage, X, Actor)
|
|||
// compatibility reasons, expressions must be enclosed within
|
||||
// parentheses.
|
||||
|
||||
defaults->Damage = 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;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue