- 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:
Randy Heit 2009-10-15 03:58:23 +00:00
parent 4fa94390d0
commit 85cc335725
11 changed files with 250 additions and 85 deletions

View file

@ -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)

View file

@ -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;
} }
//========================================================================== //==========================================================================

View file

@ -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];

View file

@ -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;

View file

@ -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);
}; };
//========================================================================== //==========================================================================

View file

@ -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);

View file

@ -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
} }

View file

@ -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

View file

@ -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)
{ {

View file

@ -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

View file

@ -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;
} }