mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-25 05:21:02 +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
|
||||
};
|
||||
|
||||
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.
|
||||
|
||||
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
|
||||
|
||||
// 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",
|
||||
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.
|
||||
Printf("Unmanaged dehacked codepointer alias num %i\n", codepointer);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static int PatchThing (int thingy)
|
||||
|
|
|
@ -817,13 +817,16 @@ bool FStateDefinitions::SetLoop()
|
|||
//==========================================================================
|
||||
//
|
||||
// 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;
|
||||
int count = 0;
|
||||
while (*framechars)
|
||||
{
|
||||
int frame;
|
||||
|
@ -834,17 +837,18 @@ bool FStateDefinitions::AddStates(FState *state, const char *framechars)
|
|||
frame = ((*framechars)&223)-'A';
|
||||
|
||||
framechars++;
|
||||
if (frame<0 || frame>28)
|
||||
if (frame < 0 || frame > 28)
|
||||
{
|
||||
frame = 0;
|
||||
error = true;
|
||||
}
|
||||
|
||||
state->Frame=(state->Frame&(SF_FULLBRIGHT))|frame;
|
||||
state->Frame = (state->Frame&(SF_FULLBRIGHT)) | frame;
|
||||
StateArray.Push(*state);
|
||||
++count;
|
||||
}
|
||||
laststate = &StateArray[StateArray.Size() - 1];
|
||||
return !error;
|
||||
return !error ? count : -count;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
|
|
@ -64,6 +64,7 @@
|
|||
#include "thingdef.h"
|
||||
#include "thingdef_exp.h"
|
||||
#include "a_sharedglobal.h"
|
||||
#include "vmbuilder.h"
|
||||
|
||||
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
|
||||
void InitThingdef();
|
||||
|
@ -279,8 +280,42 @@ void FinishActor(const FScriptPosition &sc, FActorInfo *info, Baggage &bag)
|
|||
static void FinishThingdef()
|
||||
{
|
||||
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];
|
||||
|
||||
|
|
|
@ -99,9 +99,8 @@ public:
|
|||
bool SetStop();
|
||||
bool SetWait();
|
||||
bool SetLoop();
|
||||
bool AddStates(FState *state, const char *framechars);
|
||||
int AddStates(FState *state, const char *framechars);
|
||||
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
|
||||
{
|
||||
FxExpression *expr;
|
||||
|
|
|
@ -314,6 +314,7 @@ public:
|
|||
return true;
|
||||
}
|
||||
ExpVal EvalExpression (AActor *self);
|
||||
ExpEmit Emit(VMFunctionBuilder *build);
|
||||
};
|
||||
|
||||
|
||||
|
@ -439,7 +440,7 @@ public:
|
|||
FxBinary(int, FxExpression*, FxExpression*);
|
||||
~FxBinary();
|
||||
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)
|
||||
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
|
@ -390,11 +390,15 @@ ExpEmit FxParameter::Emit(VMFunctionBuilder *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");
|
||||
build->Emit(OP_PARAM, 0, where.RegType, where.RegNum);
|
||||
}
|
||||
else
|
||||
{
|
||||
build->Emit(OP_PARAM, 0, where.RegType, where.RegNum);
|
||||
}
|
||||
}
|
||||
return ExpEmit();
|
||||
}
|
||||
|
@ -445,6 +449,40 @@ FxExpression *FxConstant::MakeConstant(PSymbol *sym, const FScriptPosition &pos)
|
|||
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);
|
||||
assert(!from.Konst);
|
||||
assert(basex->ValueType == VAL_Int);
|
||||
build->FreeReg(from.RegType, from.RegNum);
|
||||
ExpEmit to(build, REGT_FLOAT);
|
||||
build->Emit(OP_CAST, to.RegNum, from.RegNum, CAST_I2F);
|
||||
return to;
|
||||
|
@ -1033,15 +1072,15 @@ bool FxBinary::ResolveLR(FCompileContext& ctx, bool castnumeric)
|
|||
return true;
|
||||
}
|
||||
|
||||
void FxBinary::Promote()
|
||||
void FxBinary::Promote(FCompileContext &ctx)
|
||||
{
|
||||
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)
|
||||
{
|
||||
left = new FxFloatCast(left);
|
||||
left = (new FxFloatCast(left))->Resolve(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1103,7 +1142,7 @@ FxExpression *FxAddSub::Resolve(FCompileContext& ctx)
|
|||
|
||||
}
|
||||
}
|
||||
Promote();
|
||||
Promote(ctx);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -1280,7 +1319,7 @@ FxExpression *FxMulDiv::Resolve(FCompileContext& ctx)
|
|||
|
||||
}
|
||||
}
|
||||
Promote();
|
||||
Promote(ctx);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -1342,6 +1381,7 @@ ExpEmit FxMulDiv::Emit(VMFunctionBuilder *build)
|
|||
swap(op1, op2);
|
||||
}
|
||||
assert(!op1.Konst);
|
||||
build->FreeReg(op1.RegType, op1.RegNum);
|
||||
if (!op2.Konst)
|
||||
{
|
||||
build->FreeReg(op2.RegType, op2.RegNum);
|
||||
|
@ -1451,7 +1491,7 @@ FxExpression *FxCompareRel::Resolve(FCompileContext& ctx)
|
|||
delete this;
|
||||
return e;
|
||||
}
|
||||
Promote();
|
||||
Promote(ctx);
|
||||
ValueType = VAL_Int;
|
||||
return this;
|
||||
}
|
||||
|
@ -1604,7 +1644,7 @@ cont:
|
|||
delete this;
|
||||
return e;
|
||||
}
|
||||
Promote();
|
||||
Promote(ctx);
|
||||
ValueType = VAL_Int;
|
||||
return this;
|
||||
}
|
||||
|
@ -2357,6 +2397,14 @@ FxExpression *FxRandom::Resolve(FCompileContext &ctx)
|
|||
CHECKRESOLVED();
|
||||
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(max, ctx);
|
||||
ABORT(min && max);
|
||||
|
|
|
@ -56,18 +56,7 @@
|
|||
#include "colormatcher.h"
|
||||
#include "thingdef_exp.h"
|
||||
|
||||
//==========================================================================
|
||||
//***
|
||||
// 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;
|
||||
}
|
||||
TDeletingArray<FStateTempCall *> StateTempCalls;
|
||||
|
||||
//==========================================================================
|
||||
//***
|
||||
|
@ -75,7 +64,7 @@ int PrepareStateParameters(FState * state, int numparams, const PClass *cls)
|
|||
// 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 min_args, max_args;
|
||||
|
@ -85,17 +74,14 @@ bool DoActionSpecials(FScanner &sc, FState & state, Baggage &bag)
|
|||
|
||||
if (special > 0 && min_args >= 0)
|
||||
{
|
||||
|
||||
int paramindex=PrepareStateParameters(&state, 6, bag.Info->Class);
|
||||
|
||||
StateParams.Set(paramindex, new FxConstant(special, sc));
|
||||
tcall->Parameters.Push(new FxParameter(new FxConstant(special, sc)));
|
||||
|
||||
// Make this consistent with all other parameter parsing
|
||||
if (sc.CheckToken('('))
|
||||
{
|
||||
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++;
|
||||
if (!sc.CheckToken (',')) break;
|
||||
}
|
||||
|
@ -153,7 +139,8 @@ void ParseStates(FScanner &sc, FActorInfo * actor, AActor * defaults, Baggage &b
|
|||
{
|
||||
FString statestring;
|
||||
FState state;
|
||||
char lastsprite[5]="";
|
||||
char lastsprite[5] = "";
|
||||
FStateTempCall *tcall = NULL;
|
||||
|
||||
sc.MustGetStringName ("{");
|
||||
sc.SetEscape(false); // disable escape sequences in the state parser
|
||||
|
@ -238,6 +225,10 @@ do_stop:
|
|||
|
||||
sc.MustGetNumber();
|
||||
state.Tics = clamp<int>(sc.Number, -1, 32767);
|
||||
if (tcall == NULL)
|
||||
{
|
||||
tcall = new FStateTempCall;
|
||||
}
|
||||
|
||||
while (sc.GetString() && !sc.Crossed)
|
||||
{
|
||||
|
@ -262,7 +253,7 @@ do_stop:
|
|||
// Make the action name lowercase to satisfy the gperf hashers
|
||||
strlwr (sc.String);
|
||||
|
||||
if (DoActionSpecials(sc, state, bag))
|
||||
if (DoActionSpecials(sc, state, bag, tcall))
|
||||
{
|
||||
goto endofstate;
|
||||
}
|
||||
|
@ -292,19 +283,19 @@ do_stop:
|
|||
}
|
||||
}
|
||||
|
||||
int paramindex = PrepareStateParameters(&state, numparams, bag.Info->Class);
|
||||
int paramstart = paramindex;
|
||||
// int paramindex = PrepareStateParameters(&state, numparams, bag.Info->Class);
|
||||
// int paramstart = paramindex;
|
||||
bool varargs = params[numparams - 1] == '+';
|
||||
int varargcount=0;
|
||||
int argcount = 0;
|
||||
|
||||
|
||||
if (varargs)
|
||||
{
|
||||
paramindex++;
|
||||
// paramindex++;
|
||||
}
|
||||
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)
|
||||
|
@ -338,19 +329,17 @@ do_stop:
|
|||
// Use the generic parameter parser for everything else
|
||||
x = ParseParameter(sc, bag.Info->Class, *params, false);
|
||||
}
|
||||
StateParams.Set(paramindex++, x);
|
||||
// StateParams.Set(paramindex++, x);
|
||||
tcall->Parameters.Push(new FxParameter(x));
|
||||
params++;
|
||||
if (varargs)
|
||||
{
|
||||
varargcount++;
|
||||
}
|
||||
argcount++;
|
||||
if (*params)
|
||||
{
|
||||
if (*params == '+')
|
||||
{
|
||||
if (sc.CheckString(")"))
|
||||
{
|
||||
StateParams.Set(paramstart, new FxConstant(varargcount, sc));
|
||||
// StateParams.Set(paramstart, new FxConstant(argcount, sc));
|
||||
goto endofstate;
|
||||
}
|
||||
params--;
|
||||
|
@ -380,12 +369,26 @@ do_stop:
|
|||
}
|
||||
sc.UnGet();
|
||||
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());
|
||||
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
|
||||
}
|
||||
|
||||
|
|
|
@ -812,6 +812,7 @@ void VMSelectEngine(EVMEngine engine);
|
|||
extern int (*VMExec)(VMFrameStack *stack, const VM_UBYTE *pc, VMReturn *ret, int numret);
|
||||
void VMFillParams(VMValue *params, VMFrame *callee, int numparam);
|
||||
|
||||
void VMDumpConstants(const VMScriptFunction *func);
|
||||
void VMDisasm(const VM_UBYTE *code, int codesize, const VMScriptFunction *func);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -227,6 +227,10 @@ int VMFunctionBuilder::GetConstantString(FString val)
|
|||
|
||||
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);
|
||||
if (locp != NULL)
|
||||
{
|
||||
|
|
|
@ -51,7 +51,7 @@ public:
|
|||
RegAvailability Registers[4];
|
||||
|
||||
// Free a register.
|
||||
void FreeReg(int regtype, int regnum);
|
||||
void FreeReg(int regtype, int regnum) { Registers[regtype].Return(regnum, 1); }
|
||||
|
||||
private:
|
||||
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);
|
||||
|
||||
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)
|
||||
{
|
||||
const char *name;
|
||||
|
@ -129,13 +186,13 @@ void VMDisasm(const VM_UBYTE *code, int codesize, const VMScriptFunction *func)
|
|||
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;
|
||||
switch (code[i])
|
||||
{
|
||||
case OP_JMP:
|
||||
case OP_TRY:
|
||||
col = printf("%08x", i + 4 + JMPOFS(&code[i]));
|
||||
col = Printf("%08x", i + 4 + JMPOFS(&code[i]));
|
||||
break;
|
||||
|
||||
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);
|
||||
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;
|
||||
}
|
||||
printf("%*c", 30 - col, ';');
|
||||
Printf("%*c", 30 - col, ';');
|
||||
if (code[i] == OP_JMP || code[i] == OP_TRY)
|
||||
{
|
||||
printf("%d\n", JMPOFS(&code[i]) >> 2);
|
||||
Printf("%d\n", JMPOFS(&code[i]) >> 2);
|
||||
}
|
||||
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)
|
||||
{
|
||||
col = printf(",");
|
||||
col = Printf(",");
|
||||
}
|
||||
switch(mode)
|
||||
{
|
||||
case MODE_I:
|
||||
return col+printf("d%d", arg);
|
||||
return col+Printf("d%d", arg);
|
||||
case MODE_F:
|
||||
return col+printf("f%d", arg);
|
||||
return col+Printf("f%d", arg);
|
||||
case MODE_S:
|
||||
return col+printf("s%d", arg);
|
||||
return col+Printf("s%d", arg);
|
||||
case MODE_P:
|
||||
return col+printf("a%d", arg);
|
||||
return col+Printf("a%d", arg);
|
||||
case MODE_V:
|
||||
return col+printf("v%d", arg);
|
||||
return col+Printf("v%d", arg);
|
||||
|
||||
case MODE_KI:
|
||||
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:
|
||||
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:
|
||||
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:
|
||||
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:
|
||||
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:
|
||||
return col+printf("%d", (arg << immshift) >> immshift);
|
||||
return col+Printf("%d", (arg << immshift) >> immshift);
|
||||
|
||||
case MODE_IMMZ:
|
||||
return col+printf("%d", arg);
|
||||
return col+Printf("%d", arg);
|
||||
|
||||
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))
|
||||
{
|
||||
case REGT_INT:
|
||||
return col+printf("d%d", p.RegNum);
|
||||
return col+Printf("d%d", p.RegNum);
|
||||
case REGT_FLOAT:
|
||||
return col+printf("f%d", p.RegNum);
|
||||
return col+Printf("f%d", p.RegNum);
|
||||
case REGT_STRING:
|
||||
return col+printf("s%d", p.RegNum);
|
||||
return col+Printf("s%d", p.RegNum);
|
||||
case REGT_POINTER:
|
||||
return col+printf("a%d", p.RegNum);
|
||||
return col+Printf("a%d", p.RegNum);
|
||||
case REGT_FLOAT | REGT_MULTIREG:
|
||||
return col+printf("v%d", p.RegNum);
|
||||
return col+Printf("v%d", p.RegNum);
|
||||
case REGT_INT | REGT_KONST:
|
||||
return col+print_reg(0, p.RegNum, MODE_KI, 0, func);
|
||||
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:
|
||||
return col+print_reg(0, p.RegNum, MODE_KV, 0, func);
|
||||
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_KONST ? 'k' : 'r',
|
||||
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:
|
||||
return col+printf("$%d", arg);
|
||||
return col+Printf("$%d", arg);
|
||||
}
|
||||
return col;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue