mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-11 15:21:51 +00:00
- Added dummy code generation for states that pass parameters to action functions.
Currently, they're only good for disassembly and pasting into a proper text editor for viewing. - Fixed some problems with the FxExpression emitters that were revealed by actually using them on the standard actors. SVN r1911 (scripting)
This commit is contained in:
parent
4fa94390d0
commit
85cc335725
11 changed files with 250 additions and 85 deletions
|
@ -611,8 +611,6 @@ enum MBFCodePointers
|
||||||
SMMU_NailBomb, // No misc, but it's basically A_Explode with an added effect
|
SMMU_NailBomb, // No misc, but it's basically A_Explode with an added effect
|
||||||
};
|
};
|
||||||
|
|
||||||
int PrepareStateParameters(FState * state, int numparams, const PClass *cls);// Should probably be in a .h file.
|
|
||||||
|
|
||||||
// Hacks the parameter list for the given state so as to convert MBF-args (misc1 and misc2) into real args.
|
// Hacks the parameter list for the given state so as to convert MBF-args (misc1 and misc2) into real args.
|
||||||
|
|
||||||
void SetDehParams(FState * state, int codepointer)
|
void SetDehParams(FState * state, int codepointer)
|
||||||
|
@ -636,6 +634,7 @@ void SetDehParams(FState * state, int codepointer)
|
||||||
// Bleargh! This will all have to be redone once scripting works
|
// Bleargh! This will all have to be redone once scripting works
|
||||||
|
|
||||||
// Not sure exactly why the index for a state is greater by one point than the index for a symbol.
|
// Not sure exactly why the index for a state is greater by one point than the index for a symbol.
|
||||||
|
#if 0
|
||||||
DPrintf("SetDehParams: Paramindex is %d, default is %d.\n",
|
DPrintf("SetDehParams: Paramindex is %d, default is %d.\n",
|
||||||
state->ParameterIndex-1, sym->defaultparameterindex);
|
state->ParameterIndex-1, sym->defaultparameterindex);
|
||||||
if (state->ParameterIndex-1 == sym->defaultparameterindex)
|
if (state->ParameterIndex-1 == sym->defaultparameterindex)
|
||||||
|
@ -716,6 +715,7 @@ void SetDehParams(FState * state, int codepointer)
|
||||||
// This simply should not happen.
|
// This simply should not happen.
|
||||||
Printf("Unmanaged dehacked codepointer alias num %i\n", codepointer);
|
Printf("Unmanaged dehacked codepointer alias num %i\n", codepointer);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static int PatchThing (int thingy)
|
static int PatchThing (int thingy)
|
||||||
|
|
|
@ -817,13 +817,16 @@ bool FStateDefinitions::SetLoop()
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// AddStates
|
// AddStates
|
||||||
// adds some state to the current definition set
|
//
|
||||||
|
// Adds some state to the current definition set. Returns the number of
|
||||||
|
// states added. Positive = no errors, negative = errors.
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
bool FStateDefinitions::AddStates(FState *state, const char *framechars)
|
int FStateDefinitions::AddStates(FState *state, const char *framechars)
|
||||||
{
|
{
|
||||||
bool error = false;
|
bool error = false;
|
||||||
|
int count = 0;
|
||||||
while (*framechars)
|
while (*framechars)
|
||||||
{
|
{
|
||||||
int frame;
|
int frame;
|
||||||
|
@ -834,17 +837,18 @@ bool FStateDefinitions::AddStates(FState *state, const char *framechars)
|
||||||
frame = ((*framechars)&223)-'A';
|
frame = ((*framechars)&223)-'A';
|
||||||
|
|
||||||
framechars++;
|
framechars++;
|
||||||
if (frame<0 || frame>28)
|
if (frame < 0 || frame > 28)
|
||||||
{
|
{
|
||||||
frame = 0;
|
frame = 0;
|
||||||
error = true;
|
error = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
state->Frame=(state->Frame&(SF_FULLBRIGHT))|frame;
|
state->Frame = (state->Frame&(SF_FULLBRIGHT)) | frame;
|
||||||
StateArray.Push(*state);
|
StateArray.Push(*state);
|
||||||
|
++count;
|
||||||
}
|
}
|
||||||
laststate = &StateArray[StateArray.Size() - 1];
|
laststate = &StateArray[StateArray.Size() - 1];
|
||||||
return !error;
|
return !error ? count : -count;
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
|
@ -64,6 +64,7 @@
|
||||||
#include "thingdef.h"
|
#include "thingdef.h"
|
||||||
#include "thingdef_exp.h"
|
#include "thingdef_exp.h"
|
||||||
#include "a_sharedglobal.h"
|
#include "a_sharedglobal.h"
|
||||||
|
#include "vmbuilder.h"
|
||||||
|
|
||||||
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
|
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
|
||||||
void InitThingdef();
|
void InitThingdef();
|
||||||
|
@ -279,8 +280,42 @@ void FinishActor(const FScriptPosition &sc, FActorInfo *info, Baggage &bag)
|
||||||
static void FinishThingdef()
|
static void FinishThingdef()
|
||||||
{
|
{
|
||||||
int errorcount = StateParams.ResolveAll();
|
int errorcount = StateParams.ResolveAll();
|
||||||
|
unsigned i, j;
|
||||||
|
|
||||||
for (unsigned i = 0;i < PClass::m_Types.Size(); i++)
|
for (i = 0; i < StateTempCalls.Size(); ++i)
|
||||||
|
{
|
||||||
|
FStateTempCall *tcall = StateTempCalls[i];
|
||||||
|
FCompileContext ctx(tcall->ActorInfo->Class, true);
|
||||||
|
for (j = 0; j < tcall->Parameters.Size(); ++j)
|
||||||
|
{
|
||||||
|
tcall->Parameters[j]->Resolve(ctx);
|
||||||
|
}
|
||||||
|
VMFunctionBuilder buildit;
|
||||||
|
for (j = 0; j < tcall->Parameters.Size(); ++j)
|
||||||
|
{
|
||||||
|
FxExpression *p = /*new FxParameter*/(tcall->Parameters[j]);
|
||||||
|
p->Emit(&buildit);
|
||||||
|
delete p;
|
||||||
|
}
|
||||||
|
// FIXME: Call a real function
|
||||||
|
buildit.Emit(OP_CALL_K, buildit.GetConstantAddress(NULL, ATAG_OBJECT), j, 0);
|
||||||
|
VMScriptFunction *func = buildit.MakeFunction();
|
||||||
|
#if 1
|
||||||
|
const char *marks = "=======================================================";
|
||||||
|
char label[40];
|
||||||
|
int labellen = mysnprintf(label, countof(label), "Function %s.States[%d] (*%d)",
|
||||||
|
tcall->ActorInfo->Class->TypeName.GetChars(),
|
||||||
|
tcall->FirstState, tcall->NumStates);
|
||||||
|
Printf("\n%.*s %s %.*s", MAX(3, 38 - labellen / 2), marks, label, MAX(3, 38 - labellen / 2), marks);
|
||||||
|
VMDumpConstants(func);
|
||||||
|
Printf("\nDisassembly:\n");
|
||||||
|
VMDisasm(func->Code, func->NumCodeBytes / 4, func);
|
||||||
|
#endif
|
||||||
|
//if(i==6) I_Error("Poop");
|
||||||
|
}
|
||||||
|
I_Error("Poop");
|
||||||
|
|
||||||
|
for (i = 0; i < PClass::m_Types.Size(); i++)
|
||||||
{
|
{
|
||||||
PClass * ti = PClass::m_Types[i];
|
PClass * ti = PClass::m_Types[i];
|
||||||
|
|
||||||
|
|
|
@ -99,9 +99,8 @@ public:
|
||||||
bool SetStop();
|
bool SetStop();
|
||||||
bool SetWait();
|
bool SetWait();
|
||||||
bool SetLoop();
|
bool SetLoop();
|
||||||
bool AddStates(FState *state, const char *framechars);
|
int AddStates(FState *state, const char *framechars);
|
||||||
int GetStateCount() const { return StateArray.Size(); }
|
int GetStateCount() const { return StateArray.Size(); }
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -110,6 +109,15 @@ public:
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
|
struct FStateTempCall
|
||||||
|
{
|
||||||
|
FActorInfo *ActorInfo;
|
||||||
|
int FirstState;
|
||||||
|
int NumStates;
|
||||||
|
TArray<FxExpression *> Parameters;
|
||||||
|
};
|
||||||
|
extern TDeletingArray<FStateTempCall *> StateTempCalls;
|
||||||
|
|
||||||
struct FStateExpression
|
struct FStateExpression
|
||||||
{
|
{
|
||||||
FxExpression *expr;
|
FxExpression *expr;
|
||||||
|
|
|
@ -314,6 +314,7 @@ public:
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
ExpVal EvalExpression (AActor *self);
|
ExpVal EvalExpression (AActor *self);
|
||||||
|
ExpEmit Emit(VMFunctionBuilder *build);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -439,7 +440,7 @@ public:
|
||||||
FxBinary(int, FxExpression*, FxExpression*);
|
FxBinary(int, FxExpression*, FxExpression*);
|
||||||
~FxBinary();
|
~FxBinary();
|
||||||
bool ResolveLR(FCompileContext& ctx, bool castnumeric);
|
bool ResolveLR(FCompileContext& ctx, bool castnumeric);
|
||||||
void Promote();
|
void Promote(FCompileContext &ctx);
|
||||||
};
|
};
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
|
@ -79,7 +79,7 @@ DEFINE_MEMBER_VARIABLE(Score, AActor)
|
||||||
DEFINE_MEMBER_VARIABLE(uservar, AActor)
|
DEFINE_MEMBER_VARIABLE(uservar, AActor)
|
||||||
|
|
||||||
ExpEmit::ExpEmit(VMFunctionBuilder *build, int type)
|
ExpEmit::ExpEmit(VMFunctionBuilder *build, int type)
|
||||||
: RegNum(build->Registers[type].Get(1)), RegType(type)
|
: RegNum(build->Registers[type].Get(1)), RegType(type), Konst(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -371,7 +371,7 @@ ExpEmit FxParameter::Emit(VMFunctionBuilder *build)
|
||||||
}
|
}
|
||||||
else if (val.Type == VAL_Float)
|
else if (val.Type == VAL_Float)
|
||||||
{
|
{
|
||||||
build->Emit(OP_PARAM, 0, REGT_FLOAT | REGT_KONST, build->GetConstantFloat(val.Int));
|
build->Emit(OP_PARAM, 0, REGT_FLOAT | REGT_KONST, build->GetConstantFloat(val.Float));
|
||||||
}
|
}
|
||||||
else if (val.Type == VAL_Class || val.Type == VAL_Object)
|
else if (val.Type == VAL_Class || val.Type == VAL_Object)
|
||||||
{
|
{
|
||||||
|
@ -390,11 +390,15 @@ ExpEmit FxParameter::Emit(VMFunctionBuilder *build)
|
||||||
{
|
{
|
||||||
ExpEmit where = Operand->Emit(build);
|
ExpEmit where = Operand->Emit(build);
|
||||||
|
|
||||||
if (where.RegNum == REGT_NIL)
|
if (where.RegType == REGT_NIL)
|
||||||
{
|
{
|
||||||
ScriptPosition.Message(MSG_ERROR, "Attempted to pass a non-value");
|
ScriptPosition.Message(MSG_ERROR, "Attempted to pass a non-value");
|
||||||
build->Emit(OP_PARAM, 0, where.RegType, where.RegNum);
|
build->Emit(OP_PARAM, 0, where.RegType, where.RegNum);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
build->Emit(OP_PARAM, 0, where.RegType, where.RegNum);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return ExpEmit();
|
return ExpEmit();
|
||||||
}
|
}
|
||||||
|
@ -445,6 +449,40 @@ FxExpression *FxConstant::MakeConstant(PSymbol *sym, const FScriptPosition &pos)
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ExpEmit FxConstant::Emit(VMFunctionBuilder *build)
|
||||||
|
{
|
||||||
|
ExpEmit out;
|
||||||
|
|
||||||
|
out.Konst = true;
|
||||||
|
if (value.Type == VAL_Int || value.Type == VAL_Sound || value.Type == VAL_Name || value.Type == VAL_Color)
|
||||||
|
{
|
||||||
|
out.RegType = REGT_INT;
|
||||||
|
out.RegNum = build->GetConstantInt(value.Int);
|
||||||
|
}
|
||||||
|
else if (value.Type == VAL_Float)
|
||||||
|
{
|
||||||
|
out.RegType = REGT_FLOAT;
|
||||||
|
out.RegNum = build->GetConstantFloat(value.Float);
|
||||||
|
}
|
||||||
|
else if (value.Type == VAL_Class || value.Type == VAL_Object)
|
||||||
|
{
|
||||||
|
out.RegType = REGT_POINTER;
|
||||||
|
out.RegNum = build->GetConstantAddress(value.pointer, ATAG_OBJECT);
|
||||||
|
}
|
||||||
|
else if (value.Type == VAL_State)
|
||||||
|
{
|
||||||
|
out.RegType = REGT_POINTER;
|
||||||
|
out.RegNum = build->GetConstantAddress(value.pointer, ATAG_STATE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ScriptPosition.Message(MSG_ERROR, "Cannot emit needed constant");
|
||||||
|
out.RegType = REGT_NIL;
|
||||||
|
out.RegNum = 0;
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
|
@ -610,6 +648,7 @@ ExpEmit FxFloatCast::Emit(VMFunctionBuilder *build)
|
||||||
ExpEmit from = basex->Emit(build);
|
ExpEmit from = basex->Emit(build);
|
||||||
assert(!from.Konst);
|
assert(!from.Konst);
|
||||||
assert(basex->ValueType == VAL_Int);
|
assert(basex->ValueType == VAL_Int);
|
||||||
|
build->FreeReg(from.RegType, from.RegNum);
|
||||||
ExpEmit to(build, REGT_FLOAT);
|
ExpEmit to(build, REGT_FLOAT);
|
||||||
build->Emit(OP_CAST, to.RegNum, from.RegNum, CAST_I2F);
|
build->Emit(OP_CAST, to.RegNum, from.RegNum, CAST_I2F);
|
||||||
return to;
|
return to;
|
||||||
|
@ -1033,15 +1072,15 @@ bool FxBinary::ResolveLR(FCompileContext& ctx, bool castnumeric)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FxBinary::Promote()
|
void FxBinary::Promote(FCompileContext &ctx)
|
||||||
{
|
{
|
||||||
if (left->ValueType == VAL_Float && right->ValueType == VAL_Int)
|
if (left->ValueType == VAL_Float && right->ValueType == VAL_Int)
|
||||||
{
|
{
|
||||||
right = new FxFloatCast(right);
|
right = (new FxFloatCast(right))->Resolve(ctx);
|
||||||
}
|
}
|
||||||
else if (left->ValueType == VAL_Int && right->ValueType == VAL_Float)
|
else if (left->ValueType == VAL_Int && right->ValueType == VAL_Float)
|
||||||
{
|
{
|
||||||
left = new FxFloatCast(left);
|
left = (new FxFloatCast(left))->Resolve(ctx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1103,7 +1142,7 @@ FxExpression *FxAddSub::Resolve(FCompileContext& ctx)
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Promote();
|
Promote(ctx);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1280,7 +1319,7 @@ FxExpression *FxMulDiv::Resolve(FCompileContext& ctx)
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Promote();
|
Promote(ctx);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1342,6 +1381,7 @@ ExpEmit FxMulDiv::Emit(VMFunctionBuilder *build)
|
||||||
swap(op1, op2);
|
swap(op1, op2);
|
||||||
}
|
}
|
||||||
assert(!op1.Konst);
|
assert(!op1.Konst);
|
||||||
|
build->FreeReg(op1.RegType, op1.RegNum);
|
||||||
if (!op2.Konst)
|
if (!op2.Konst)
|
||||||
{
|
{
|
||||||
build->FreeReg(op2.RegType, op2.RegNum);
|
build->FreeReg(op2.RegType, op2.RegNum);
|
||||||
|
@ -1451,7 +1491,7 @@ FxExpression *FxCompareRel::Resolve(FCompileContext& ctx)
|
||||||
delete this;
|
delete this;
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
Promote();
|
Promote(ctx);
|
||||||
ValueType = VAL_Int;
|
ValueType = VAL_Int;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
@ -1604,7 +1644,7 @@ cont:
|
||||||
delete this;
|
delete this;
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
Promote();
|
Promote(ctx);
|
||||||
ValueType = VAL_Int;
|
ValueType = VAL_Int;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
@ -2357,6 +2397,14 @@ FxExpression *FxRandom::Resolve(FCompileContext &ctx)
|
||||||
CHECKRESOLVED();
|
CHECKRESOLVED();
|
||||||
if (min && max)
|
if (min && max)
|
||||||
{
|
{
|
||||||
|
if (min->ValueType != VAL_Int)
|
||||||
|
{
|
||||||
|
min = new FxIntCast(min);
|
||||||
|
}
|
||||||
|
if (max->ValueType != VAL_Int)
|
||||||
|
{
|
||||||
|
max = new FxIntCast(max);
|
||||||
|
}
|
||||||
RESOLVE(min, ctx);
|
RESOLVE(min, ctx);
|
||||||
RESOLVE(max, ctx);
|
RESOLVE(max, ctx);
|
||||||
ABORT(min && max);
|
ABORT(min && max);
|
||||||
|
|
|
@ -56,18 +56,7 @@
|
||||||
#include "colormatcher.h"
|
#include "colormatcher.h"
|
||||||
#include "thingdef_exp.h"
|
#include "thingdef_exp.h"
|
||||||
|
|
||||||
//==========================================================================
|
TDeletingArray<FStateTempCall *> StateTempCalls;
|
||||||
//***
|
|
||||||
// PrepareStateParameters
|
|
||||||
// creates an empty parameter list for a parameterized function call
|
|
||||||
//
|
|
||||||
//==========================================================================
|
|
||||||
int PrepareStateParameters(FState * state, int numparams, const PClass *cls)
|
|
||||||
{
|
|
||||||
int paramindex=StateParams.Reserve(numparams, cls);
|
|
||||||
state->ParameterIndex = paramindex+1;
|
|
||||||
return paramindex;
|
|
||||||
}
|
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//***
|
//***
|
||||||
|
@ -75,7 +64,7 @@ int PrepareStateParameters(FState * state, int numparams, const PClass *cls)
|
||||||
// handles action specials as code pointers
|
// handles action specials as code pointers
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
bool DoActionSpecials(FScanner &sc, FState & state, Baggage &bag)
|
bool DoActionSpecials(FScanner &sc, FState & state, Baggage &bag, FStateTempCall *tcall)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
int min_args, max_args;
|
int min_args, max_args;
|
||||||
|
@ -85,17 +74,14 @@ bool DoActionSpecials(FScanner &sc, FState & state, Baggage &bag)
|
||||||
|
|
||||||
if (special > 0 && min_args >= 0)
|
if (special > 0 && min_args >= 0)
|
||||||
{
|
{
|
||||||
|
tcall->Parameters.Push(new FxParameter(new FxConstant(special, sc)));
|
||||||
int paramindex=PrepareStateParameters(&state, 6, bag.Info->Class);
|
|
||||||
|
|
||||||
StateParams.Set(paramindex, new FxConstant(special, sc));
|
|
||||||
|
|
||||||
// Make this consistent with all other parameter parsing
|
// Make this consistent with all other parameter parsing
|
||||||
if (sc.CheckToken('('))
|
if (sc.CheckToken('('))
|
||||||
{
|
{
|
||||||
for (i = 0; i < 5;)
|
for (i = 0; i < 5;)
|
||||||
{
|
{
|
||||||
StateParams.Set(paramindex+i+1, ParseExpression (sc, bag.Info->Class));
|
tcall->Parameters.Push(new FxParameter(ParseExpression(sc, bag.Info->Class)));
|
||||||
i++;
|
i++;
|
||||||
if (!sc.CheckToken (',')) break;
|
if (!sc.CheckToken (',')) break;
|
||||||
}
|
}
|
||||||
|
@ -153,7 +139,8 @@ void ParseStates(FScanner &sc, FActorInfo * actor, AActor * defaults, Baggage &b
|
||||||
{
|
{
|
||||||
FString statestring;
|
FString statestring;
|
||||||
FState state;
|
FState state;
|
||||||
char lastsprite[5]="";
|
char lastsprite[5] = "";
|
||||||
|
FStateTempCall *tcall = NULL;
|
||||||
|
|
||||||
sc.MustGetStringName ("{");
|
sc.MustGetStringName ("{");
|
||||||
sc.SetEscape(false); // disable escape sequences in the state parser
|
sc.SetEscape(false); // disable escape sequences in the state parser
|
||||||
|
@ -238,6 +225,10 @@ do_stop:
|
||||||
|
|
||||||
sc.MustGetNumber();
|
sc.MustGetNumber();
|
||||||
state.Tics = clamp<int>(sc.Number, -1, 32767);
|
state.Tics = clamp<int>(sc.Number, -1, 32767);
|
||||||
|
if (tcall == NULL)
|
||||||
|
{
|
||||||
|
tcall = new FStateTempCall;
|
||||||
|
}
|
||||||
|
|
||||||
while (sc.GetString() && !sc.Crossed)
|
while (sc.GetString() && !sc.Crossed)
|
||||||
{
|
{
|
||||||
|
@ -262,7 +253,7 @@ do_stop:
|
||||||
// Make the action name lowercase to satisfy the gperf hashers
|
// Make the action name lowercase to satisfy the gperf hashers
|
||||||
strlwr (sc.String);
|
strlwr (sc.String);
|
||||||
|
|
||||||
if (DoActionSpecials(sc, state, bag))
|
if (DoActionSpecials(sc, state, bag, tcall))
|
||||||
{
|
{
|
||||||
goto endofstate;
|
goto endofstate;
|
||||||
}
|
}
|
||||||
|
@ -292,19 +283,19 @@ do_stop:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int paramindex = PrepareStateParameters(&state, numparams, bag.Info->Class);
|
// int paramindex = PrepareStateParameters(&state, numparams, bag.Info->Class);
|
||||||
int paramstart = paramindex;
|
// int paramstart = paramindex;
|
||||||
bool varargs = params[numparams - 1] == '+';
|
bool varargs = params[numparams - 1] == '+';
|
||||||
int varargcount=0;
|
int argcount = 0;
|
||||||
|
|
||||||
|
|
||||||
if (varargs)
|
if (varargs)
|
||||||
{
|
{
|
||||||
paramindex++;
|
// paramindex++;
|
||||||
}
|
}
|
||||||
else if (afd->defaultparameterindex > -1)
|
else if (afd->defaultparameterindex > -1)
|
||||||
{
|
{
|
||||||
StateParams.Copy(paramindex, afd->defaultparameterindex, int(afd->Arguments.Len()));
|
// StateParams.Copy(paramindex, afd->defaultparameterindex, int(afd->Arguments.Len()));
|
||||||
}
|
}
|
||||||
|
|
||||||
while (*params)
|
while (*params)
|
||||||
|
@ -338,19 +329,17 @@ do_stop:
|
||||||
// Use the generic parameter parser for everything else
|
// Use the generic parameter parser for everything else
|
||||||
x = ParseParameter(sc, bag.Info->Class, *params, false);
|
x = ParseParameter(sc, bag.Info->Class, *params, false);
|
||||||
}
|
}
|
||||||
StateParams.Set(paramindex++, x);
|
// StateParams.Set(paramindex++, x);
|
||||||
|
tcall->Parameters.Push(new FxParameter(x));
|
||||||
params++;
|
params++;
|
||||||
if (varargs)
|
argcount++;
|
||||||
{
|
|
||||||
varargcount++;
|
|
||||||
}
|
|
||||||
if (*params)
|
if (*params)
|
||||||
{
|
{
|
||||||
if (*params == '+')
|
if (*params == '+')
|
||||||
{
|
{
|
||||||
if (sc.CheckString(")"))
|
if (sc.CheckString(")"))
|
||||||
{
|
{
|
||||||
StateParams.Set(paramstart, new FxConstant(varargcount, sc));
|
// StateParams.Set(paramstart, new FxConstant(argcount, sc));
|
||||||
goto endofstate;
|
goto endofstate;
|
||||||
}
|
}
|
||||||
params--;
|
params--;
|
||||||
|
@ -380,12 +369,26 @@ do_stop:
|
||||||
}
|
}
|
||||||
sc.UnGet();
|
sc.UnGet();
|
||||||
endofstate:
|
endofstate:
|
||||||
if (!bag.statedef.AddStates(&state, statestring))
|
int count = bag.statedef.AddStates(&state, statestring);
|
||||||
|
if (count < 0)
|
||||||
{
|
{
|
||||||
sc.ScriptError ("Invalid frame character string '%s'", statestring.GetChars());
|
sc.ScriptError ("Invalid frame character string '%s'", statestring.GetChars());
|
||||||
|
count = -count;
|
||||||
|
}
|
||||||
|
if (tcall->Parameters.Size() != 0)
|
||||||
|
{
|
||||||
|
tcall->ActorInfo = actor;
|
||||||
|
tcall->FirstState = bag.statedef.GetStateCount() - count;
|
||||||
|
tcall->NumStates = count;
|
||||||
|
StateTempCalls.Push(tcall);
|
||||||
|
tcall = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (tcall != NULL)
|
||||||
|
{
|
||||||
|
delete tcall;
|
||||||
|
}
|
||||||
sc.SetEscape(true); // re-enable escape sequences
|
sc.SetEscape(true); // re-enable escape sequences
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -812,6 +812,7 @@ void VMSelectEngine(EVMEngine engine);
|
||||||
extern int (*VMExec)(VMFrameStack *stack, const VM_UBYTE *pc, VMReturn *ret, int numret);
|
extern int (*VMExec)(VMFrameStack *stack, const VM_UBYTE *pc, VMReturn *ret, int numret);
|
||||||
void VMFillParams(VMValue *params, VMFrame *callee, int numparam);
|
void VMFillParams(VMValue *params, VMFrame *callee, int numparam);
|
||||||
|
|
||||||
|
void VMDumpConstants(const VMScriptFunction *func);
|
||||||
void VMDisasm(const VM_UBYTE *code, int codesize, const VMScriptFunction *func);
|
void VMDisasm(const VM_UBYTE *code, int codesize, const VMScriptFunction *func);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -227,6 +227,10 @@ int VMFunctionBuilder::GetConstantString(FString val)
|
||||||
|
|
||||||
int VMFunctionBuilder::GetConstantAddress(void *ptr, VM_ATAG tag)
|
int VMFunctionBuilder::GetConstantAddress(void *ptr, VM_ATAG tag)
|
||||||
{
|
{
|
||||||
|
if (ptr == NULL)
|
||||||
|
{ // Make all NULL pointers generic. (Or should we allow typed NULLs?)
|
||||||
|
tag = ATAG_GENERIC;
|
||||||
|
}
|
||||||
AddrKonst *locp = AddressConstants.CheckKey(ptr);
|
AddrKonst *locp = AddressConstants.CheckKey(ptr);
|
||||||
if (locp != NULL)
|
if (locp != NULL)
|
||||||
{
|
{
|
||||||
|
|
|
@ -51,7 +51,7 @@ public:
|
||||||
RegAvailability Registers[4];
|
RegAvailability Registers[4];
|
||||||
|
|
||||||
// Free a register.
|
// Free a register.
|
||||||
void FreeReg(int regtype, int regnum);
|
void FreeReg(int regtype, int regnum) { Registers[regtype].Return(regnum, 1); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct AddrKonst
|
struct AddrKonst
|
||||||
|
|
|
@ -101,6 +101,63 @@ const VMOpInfo OpInfo[NUM_OPS] =
|
||||||
|
|
||||||
static int print_reg(int col, int arg, int mode, int immshift, const VMScriptFunction *func);
|
static int print_reg(int col, int arg, int mode, int immshift, const VMScriptFunction *func);
|
||||||
|
|
||||||
|
void VMDumpConstants(const VMScriptFunction *func)
|
||||||
|
{
|
||||||
|
char tmp[21];
|
||||||
|
int i, j, k, kk;
|
||||||
|
|
||||||
|
if (func->KonstD != NULL && func->NumKonstD != 0)
|
||||||
|
{
|
||||||
|
Printf("\nConstant integers:\n");
|
||||||
|
kk = (func->NumKonstD + 3) / 4;
|
||||||
|
for (i = 0; i < kk; ++i)
|
||||||
|
{
|
||||||
|
for (j = 0, k = i; j < 4 && k < func->NumKonstD; j++, k += kk)
|
||||||
|
{
|
||||||
|
mysnprintf(tmp, countof(tmp), "%3d. %d", k, func->KonstD[k]);
|
||||||
|
Printf("%-20s", tmp);
|
||||||
|
}
|
||||||
|
Printf("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (func->KonstF != NULL && func->NumKonstF != 0)
|
||||||
|
{
|
||||||
|
Printf("\nConstant floats:\n");
|
||||||
|
kk = (func->NumKonstF + 3) / 4;
|
||||||
|
for (i = 0; i < kk; ++i)
|
||||||
|
{
|
||||||
|
for (j = 0, k = i; j < 4 && k < func->NumKonstF; j++, k += kk)
|
||||||
|
{
|
||||||
|
mysnprintf(tmp, countof(tmp), "%3d. %.16f", k, func->KonstF[k]);
|
||||||
|
Printf("%-20s", tmp);
|
||||||
|
}
|
||||||
|
Printf("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (func->KonstA != NULL && func->NumKonstA != 0)
|
||||||
|
{
|
||||||
|
Printf("\nConstant addresses:\n");
|
||||||
|
kk = (func->NumKonstA + 3) / 4;
|
||||||
|
for (i = 0; i < kk; ++i)
|
||||||
|
{
|
||||||
|
for (j = 0, k = i; j < 4 && k < func->NumKonstA; j++, k += kk)
|
||||||
|
{
|
||||||
|
mysnprintf(tmp, countof(tmp), "%3d. %p", k, func->KonstA[k]);
|
||||||
|
Printf("%-20s", tmp);
|
||||||
|
}
|
||||||
|
Printf("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (func->KonstS != NULL && func->NumKonstS != 0)
|
||||||
|
{
|
||||||
|
Printf("\nConstant strings:\n");
|
||||||
|
for (i = 0; i < func->NumKonstS; ++i)
|
||||||
|
{
|
||||||
|
Printf("%3d. %s\n", func->KonstS[k].GetChars());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void VMDisasm(const VM_UBYTE *code, int codesize, const VMScriptFunction *func)
|
void VMDisasm(const VM_UBYTE *code, int codesize, const VMScriptFunction *func)
|
||||||
{
|
{
|
||||||
const char *name;
|
const char *name;
|
||||||
|
@ -129,13 +186,13 @@ void VMDisasm(const VM_UBYTE *code, int codesize, const VMScriptFunction *func)
|
||||||
a &= CMP_CHECK | CMP_APPROX;
|
a &= CMP_CHECK | CMP_APPROX;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("%08x: %02x%02x%02x%02x %-8s", i, code[i], code[i+1], code[i+2], code[i+3], name);
|
Printf("%08x: %02x%02x%02x%02x %-8s", i, code[i], code[i+1], code[i+2], code[i+3], name);
|
||||||
col = 0;
|
col = 0;
|
||||||
switch (code[i])
|
switch (code[i])
|
||||||
{
|
{
|
||||||
case OP_JMP:
|
case OP_JMP:
|
||||||
case OP_TRY:
|
case OP_TRY:
|
||||||
col = printf("%08x", i + 4 + JMPOFS(&code[i]));
|
col = Printf("%08x", i + 4 + JMPOFS(&code[i]));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OP_RET:
|
case OP_RET:
|
||||||
|
@ -151,7 +208,7 @@ void VMDisasm(const VM_UBYTE *code, int codesize, const VMScriptFunction *func)
|
||||||
col += print_reg(col, *(VM_UHALF *)&code[i+2], MODE_PARAM, 16, func);
|
col += print_reg(col, *(VM_UHALF *)&code[i+2], MODE_PARAM, 16, func);
|
||||||
if (code[i+2] & REGT_FINAL)
|
if (code[i+2] & REGT_FINAL)
|
||||||
{
|
{
|
||||||
col += printf(" [final]");
|
col += Printf(" [final]");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -229,14 +286,14 @@ void VMDisasm(const VM_UBYTE *code, int codesize, const VMScriptFunction *func)
|
||||||
{
|
{
|
||||||
col = 30;
|
col = 30;
|
||||||
}
|
}
|
||||||
printf("%*c", 30 - col, ';');
|
Printf("%*c", 30 - col, ';');
|
||||||
if (code[i] == OP_JMP || code[i] == OP_TRY)
|
if (code[i] == OP_JMP || code[i] == OP_TRY)
|
||||||
{
|
{
|
||||||
printf("%d\n", JMPOFS(&code[i]) >> 2);
|
Printf("%d\n", JMPOFS(&code[i]) >> 2);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
printf("%d,%d,%d\n", code[i+1], code[i+2], code[i+3]);
|
Printf("%d,%d,%d\n", code[i+1], code[i+2], code[i+3]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -249,57 +306,57 @@ static int print_reg(int col, int arg, int mode, int immshift, const VMScriptFun
|
||||||
}
|
}
|
||||||
if (col > 0)
|
if (col > 0)
|
||||||
{
|
{
|
||||||
col = printf(",");
|
col = Printf(",");
|
||||||
}
|
}
|
||||||
switch(mode)
|
switch(mode)
|
||||||
{
|
{
|
||||||
case MODE_I:
|
case MODE_I:
|
||||||
return col+printf("d%d", arg);
|
return col+Printf("d%d", arg);
|
||||||
case MODE_F:
|
case MODE_F:
|
||||||
return col+printf("f%d", arg);
|
return col+Printf("f%d", arg);
|
||||||
case MODE_S:
|
case MODE_S:
|
||||||
return col+printf("s%d", arg);
|
return col+Printf("s%d", arg);
|
||||||
case MODE_P:
|
case MODE_P:
|
||||||
return col+printf("a%d", arg);
|
return col+Printf("a%d", arg);
|
||||||
case MODE_V:
|
case MODE_V:
|
||||||
return col+printf("v%d", arg);
|
return col+Printf("v%d", arg);
|
||||||
|
|
||||||
case MODE_KI:
|
case MODE_KI:
|
||||||
if (func != NULL)
|
if (func != NULL)
|
||||||
{
|
{
|
||||||
return col+printf("%d", func->KonstD[arg]);
|
return col+Printf("%d", func->KonstD[arg]);
|
||||||
}
|
}
|
||||||
return printf("kd%d", arg);
|
return Printf("kd%d", arg);
|
||||||
case MODE_KF:
|
case MODE_KF:
|
||||||
if (func != NULL)
|
if (func != NULL)
|
||||||
{
|
{
|
||||||
return col+printf("%f", func->KonstF[arg]);
|
return col+Printf("%f", func->KonstF[arg]);
|
||||||
}
|
}
|
||||||
return col+printf("kf%d", arg);
|
return col+Printf("kf%d", arg);
|
||||||
case MODE_KS:
|
case MODE_KS:
|
||||||
if (func != NULL)
|
if (func != NULL)
|
||||||
{
|
{
|
||||||
return col+printf("\"%s\"", func->KonstS[arg].GetChars());
|
return col+Printf("\"%s\"", func->KonstS[arg].GetChars());
|
||||||
}
|
}
|
||||||
return col+printf("ks%d", arg);
|
return col+Printf("ks%d", arg);
|
||||||
case MODE_KP:
|
case MODE_KP:
|
||||||
if (func != NULL)
|
if (func != NULL)
|
||||||
{
|
{
|
||||||
return col+printf("%p", func->KonstA[arg]);
|
return col+Printf("%p", func->KonstA[arg]);
|
||||||
}
|
}
|
||||||
return col+printf("ka%d", arg);
|
return col+Printf("ka%d", arg);
|
||||||
case MODE_KV:
|
case MODE_KV:
|
||||||
if (func != NULL)
|
if (func != NULL)
|
||||||
{
|
{
|
||||||
return col+printf("(%f,%f,%f)", func->KonstF[arg], func->KonstF[arg+1], func->KonstF[arg+2]);
|
return col+Printf("(%f,%f,%f)", func->KonstF[arg], func->KonstF[arg+1], func->KonstF[arg+2]);
|
||||||
}
|
}
|
||||||
return col+printf("kv%d", arg);
|
return col+Printf("kv%d", arg);
|
||||||
|
|
||||||
case MODE_IMMS:
|
case MODE_IMMS:
|
||||||
return col+printf("%d", (arg << immshift) >> immshift);
|
return col+Printf("%d", (arg << immshift) >> immshift);
|
||||||
|
|
||||||
case MODE_IMMZ:
|
case MODE_IMMZ:
|
||||||
return col+printf("%d", arg);
|
return col+Printf("%d", arg);
|
||||||
|
|
||||||
case MODE_PARAM:
|
case MODE_PARAM:
|
||||||
{
|
{
|
||||||
|
@ -308,15 +365,15 @@ static int print_reg(int col, int arg, int mode, int immshift, const VMScriptFun
|
||||||
switch (p.RegType & (REGT_TYPE | REGT_KONST | REGT_MULTIREG))
|
switch (p.RegType & (REGT_TYPE | REGT_KONST | REGT_MULTIREG))
|
||||||
{
|
{
|
||||||
case REGT_INT:
|
case REGT_INT:
|
||||||
return col+printf("d%d", p.RegNum);
|
return col+Printf("d%d", p.RegNum);
|
||||||
case REGT_FLOAT:
|
case REGT_FLOAT:
|
||||||
return col+printf("f%d", p.RegNum);
|
return col+Printf("f%d", p.RegNum);
|
||||||
case REGT_STRING:
|
case REGT_STRING:
|
||||||
return col+printf("s%d", p.RegNum);
|
return col+Printf("s%d", p.RegNum);
|
||||||
case REGT_POINTER:
|
case REGT_POINTER:
|
||||||
return col+printf("a%d", p.RegNum);
|
return col+Printf("a%d", p.RegNum);
|
||||||
case REGT_FLOAT | REGT_MULTIREG:
|
case REGT_FLOAT | REGT_MULTIREG:
|
||||||
return col+printf("v%d", p.RegNum);
|
return col+Printf("v%d", p.RegNum);
|
||||||
case REGT_INT | REGT_KONST:
|
case REGT_INT | REGT_KONST:
|
||||||
return col+print_reg(0, p.RegNum, MODE_KI, 0, func);
|
return col+print_reg(0, p.RegNum, MODE_KI, 0, func);
|
||||||
case REGT_FLOAT | REGT_KONST:
|
case REGT_FLOAT | REGT_KONST:
|
||||||
|
@ -328,7 +385,11 @@ static int print_reg(int col, int arg, int mode, int immshift, const VMScriptFun
|
||||||
case REGT_FLOAT | REGT_MULTIREG | REGT_KONST:
|
case REGT_FLOAT | REGT_MULTIREG | REGT_KONST:
|
||||||
return col+print_reg(0, p.RegNum, MODE_KV, 0, func);
|
return col+print_reg(0, p.RegNum, MODE_KV, 0, func);
|
||||||
default:
|
default:
|
||||||
return col+printf("param[t=%d,%c,%c,n=%d]",
|
if (p.RegType == REGT_NIL)
|
||||||
|
{
|
||||||
|
return col+Printf("nil");
|
||||||
|
}
|
||||||
|
return col+Printf("param[t=%d,%c,%c,n=%d]",
|
||||||
p.RegType & REGT_TYPE,
|
p.RegType & REGT_TYPE,
|
||||||
p.RegType & REGT_KONST ? 'k' : 'r',
|
p.RegType & REGT_KONST ? 'k' : 'r',
|
||||||
p.RegType & REGT_MULTIREG ? 'm' : 's',
|
p.RegType & REGT_MULTIREG ? 'm' : 's',
|
||||||
|
@ -337,7 +398,7 @@ static int print_reg(int col, int arg, int mode, int immshift, const VMScriptFun
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return col+printf("$%d", arg);
|
return col+Printf("$%d", arg);
|
||||||
}
|
}
|
||||||
return col;
|
return col;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue