From 85cc335725d41c7777b7f819c0b0bdeb3f351298 Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Thu, 15 Oct 2009 03:58:23 +0000 Subject: [PATCH] - 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) --- src/d_dehacked.cpp | 4 +- src/p_states.cpp | 14 +-- src/thingdef/thingdef.cpp | 37 +++++++- src/thingdef/thingdef.h | 12 ++- src/thingdef/thingdef_exp.h | 3 +- src/thingdef/thingdef_expression.cpp | 68 ++++++++++++--- src/thingdef/thingdef_states.cpp | 67 ++++++++------- src/zscript/vm.h | 1 + src/zscript/vmbuilder.cpp | 4 + src/zscript/vmbuilder.h | 2 +- src/zscript/vmdisasm.cpp | 123 ++++++++++++++++++++------- 11 files changed, 250 insertions(+), 85 deletions(-) diff --git a/src/d_dehacked.cpp b/src/d_dehacked.cpp index 3c51af2b95..c2859ef780 100644 --- a/src/d_dehacked.cpp +++ b/src/d_dehacked.cpp @@ -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) diff --git a/src/p_states.cpp b/src/p_states.cpp index f3a99798f2..9d5be4a5e0 100644 --- a/src/p_states.cpp +++ b/src/p_states.cpp @@ -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; } //========================================================================== diff --git a/src/thingdef/thingdef.cpp b/src/thingdef/thingdef.cpp index 5dcab6c60b..21f17a5f34 100644 --- a/src/thingdef/thingdef.cpp +++ b/src/thingdef/thingdef.cpp @@ -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]; diff --git a/src/thingdef/thingdef.h b/src/thingdef/thingdef.h index 2f573f8e92..43b78c4bd2 100644 --- a/src/thingdef/thingdef.h +++ b/src/thingdef/thingdef.h @@ -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 Parameters; +}; +extern TDeletingArray StateTempCalls; + struct FStateExpression { FxExpression *expr; diff --git a/src/thingdef/thingdef_exp.h b/src/thingdef/thingdef_exp.h index d75000d41d..53c719de7c 100644 --- a/src/thingdef/thingdef_exp.h +++ b/src/thingdef/thingdef_exp.h @@ -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); }; //========================================================================== diff --git a/src/thingdef/thingdef_expression.cpp b/src/thingdef/thingdef_expression.cpp index eb02a18922..34f4a4080b 100644 --- a/src/thingdef/thingdef_expression.cpp +++ b/src/thingdef/thingdef_expression.cpp @@ -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); diff --git a/src/thingdef/thingdef_states.cpp b/src/thingdef/thingdef_states.cpp index d7252c4197..82f8dd28c0 100644 --- a/src/thingdef/thingdef_states.cpp +++ b/src/thingdef/thingdef_states.cpp @@ -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 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(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 } diff --git a/src/zscript/vm.h b/src/zscript/vm.h index 1436977da8..9912637dcc 100644 --- a/src/zscript/vm.h +++ b/src/zscript/vm.h @@ -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 diff --git a/src/zscript/vmbuilder.cpp b/src/zscript/vmbuilder.cpp index 3f1757828f..114f27d8e6 100644 --- a/src/zscript/vmbuilder.cpp +++ b/src/zscript/vmbuilder.cpp @@ -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) { diff --git a/src/zscript/vmbuilder.h b/src/zscript/vmbuilder.h index a1c6dfe3f3..e09b8bfe83 100644 --- a/src/zscript/vmbuilder.h +++ b/src/zscript/vmbuilder.h @@ -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 diff --git a/src/zscript/vmdisasm.cpp b/src/zscript/vmdisasm.cpp index 7ca2a3dc33..39f271084e 100644 --- a/src/zscript/vmdisasm.cpp +++ b/src/zscript/vmdisasm.cpp @@ -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; }