- State code now properly calls action functions and has a RET instruction. As expected,

running with the checked VM can be quite slow, since it has asserts everywhere. Some other
  fixes were needed before the code actually worked:
  - A_CallSpecial needs to have its arguments cast to ints.
  - Some functions that set pnum/paramnum directly did not decrement it by 1. This also applies
    to A_Jump, though it just uses the value of paramnum instead of changing it.
  - Renamed pnum in the PARAM macros to paramnum, since pnum is already used in a few other
    places for something different, so this makes searching for it easier.
  This has not been tested especially thoroughly, but a first glance seems to indicate success.

SVN r2163 (scripting)
This commit is contained in:
Randy Heit 2010-02-14 19:59:21 +00:00
parent 739e684549
commit 6f1bf257e9
9 changed files with 128 additions and 106 deletions

View file

@ -286,42 +286,59 @@ static void FinishThingdef()
for (i = 0; i < StateTempCalls.Size(); ++i) for (i = 0; i < StateTempCalls.Size(); ++i)
{ {
FStateTempCall *tcall = StateTempCalls[i]; FStateTempCall *tcall = StateTempCalls[i];
FCompileContext ctx(tcall->ActorInfo->Class, true); VMFunction *func;
for (j = 0; j < tcall->Parameters.Size(); ++j)
assert(tcall->Function != NULL);
if (tcall->Parameters.Size() == 0)
{ {
tcall->Parameters[j]->Resolve(ctx); func = tcall->Function;
} }
VMFunctionBuilder buildit; else
// Allocate registers used to pass parameters in.
// self, stateowner, state, statecalldata (all are pointers)
buildit.Registers[REGT_POINTER].Get(4);
// Emit code for action parameters.
for (j = 0; j < tcall->Parameters.Size(); ++j)
{ {
FxExpression *p = /*new FxParameter*/(tcall->Parameters[j]); FCompileContext ctx(tcall->ActorInfo->Class, true);
p->Emit(&buildit); for (j = 0; j < tcall->Parameters.Size(); ++j)
delete p; {
tcall->Parameters[j]->Resolve(ctx);
}
VMFunctionBuilder buildit;
// Allocate registers used to pass parameters in.
// self, stateowner, state, statecalldata (all are pointers)
buildit.Registers[REGT_POINTER].Get(4);
// Emit code to pass the standard action function parameters.
buildit.Emit(OP_PARAM, 0, REGT_POINTER, 0);
buildit.Emit(OP_PARAM, 0, REGT_POINTER, 1);
buildit.Emit(OP_PARAM, 0, REGT_POINTER, 2);
buildit.Emit(OP_PARAM, 0, REGT_POINTER, 3);
// Emit code for action parameters.
for (j = 0; j < tcall->Parameters.Size(); ++j)
{
FxExpression *p = /*new FxParameter*/(tcall->Parameters[j]);
p->Emit(&buildit);
delete p;
}
buildit.Emit(OP_CALL_K, buildit.GetConstantAddress(tcall->Function, ATAG_OBJECT), NAP + j, 0);
buildit.Emit(OP_RET, 0, REGT_NIL, 0);
VMScriptFunction *sfunc = buildit.MakeFunction();
sfunc->NumArgs = NAP;
func = sfunc;
#if 1
const char *marks = "=======================================================";
char label[64];
int labellen = mysnprintf(label, countof(label), "Function %s.States[%d] (*%d)",
tcall->ActorInfo->Class->TypeName.GetChars(),
tcall->FirstState, tcall->NumStates);
fprintf(dump, "\n%.*s %s %.*s", MAX(3, 38 - labellen / 2), marks, label, MAX(3, 38 - labellen / 2), marks);
fprintf(dump, "\nInteger regs: %-3d Float regs: %-3d Address regs: %-3d String regs: %-3d\nStack size: %d\n",
sfunc->NumRegD, sfunc->NumRegF, sfunc->NumRegA, sfunc->NumRegS, sfunc->MaxParam);
VMDumpConstants(dump, sfunc);
fprintf(dump, "\nDisassembly @ %p:\n", sfunc->Code);
VMDisasm(dump, sfunc->Code, sfunc->CodeSize, sfunc);
#endif
} }
buildit.Emit(OP_CALL_K, buildit.GetConstantAddress(NULL, ATAG_OBJECT), j, 0);
VMScriptFunction *func = buildit.MakeFunction();
func->NumArgs = tcall->Parameters.Size();
for (int k = 0; k < tcall->NumStates; ++k) for (int k = 0; k < tcall->NumStates; ++k)
{ {
tcall->ActorInfo->OwnedStates[tcall->FirstState + k].SetAction(func); tcall->ActorInfo->OwnedStates[tcall->FirstState + k].SetAction(func);
} }
#if 1
const char *marks = "=======================================================";
char label[64];
int labellen = mysnprintf(label, countof(label), "Function %s.States[%d] (*%d)",
tcall->ActorInfo->Class->TypeName.GetChars(),
tcall->FirstState, tcall->NumStates);
fprintf(dump, "\n%.*s %s %.*s", MAX(3, 38 - labellen / 2), marks, label, MAX(3, 38 - labellen / 2), marks);
fprintf(dump, "\nInteger regs: %-3d Float regs: %-3d Address regs: %-3d String regs: %-3d\nStack size: %d\n",
func->NumRegD, func->NumRegF, func->NumRegA, func->NumRegS, func->MaxParam);
VMDumpConstants(dump, func);
fprintf(dump, "\nDisassembly:\n");
VMDisasm(dump, func->Code, func->CodeSize, func);
#endif
} }
fclose(dump); fclose(dump);

View file

@ -111,10 +111,13 @@ public:
struct FStateTempCall struct FStateTempCall
{ {
FStateTempCall() : ActorInfo(NULL), Function(NULL), FirstState(0), NumStates(0) {}
FActorInfo *ActorInfo; FActorInfo *ActorInfo;
VMFunction *Function;
TArray<FxExpression *> Parameters;
int FirstState; int FirstState;
int NumStates; int NumStates;
TArray<FxExpression *> Parameters;
}; };
extern TDeletingArray<FStateTempCall *> StateTempCalls; extern TDeletingArray<FStateTempCall *> StateTempCalls;
@ -386,7 +389,7 @@ struct StateCallData
//#define PUSH_PARAMINFO self, stateowner, CallingState, ParameterIndex, statecall //#define PUSH_PARAMINFO self, stateowner, CallingState, ParameterIndex, statecall
#define CALL_ACTION(name,self) { /*AF_##name(self, self, NULL, 0, NULL)*/ \ #define CALL_ACTION(name,self) { /*AF_##name(self, self, NULL, 0, NULL)*/ \
VMValue params[5] = { self, self, NULL, VMValue(NULL, ATAG_STATE) }; \ VMValue params[5] = { self, self, VMValue(NULL, ATAG_STATE), VMValue(NULL, ATAG_GENERIC) }; \
stack->Call(name##_VMPtr, params, countof(params), NULL, 0, NULL); \ stack->Call(name##_VMPtr, params, countof(params), NULL, 0, NULL); \
} }

View file

@ -452,11 +452,12 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Jump)
PARAM_ACTION_PROLOGUE; PARAM_ACTION_PROLOGUE;
PARAM_INT_OPT(maxchance) { maxchance = 256; } PARAM_INT_OPT(maxchance) { maxchance = 256; }
int count = numparam - pnum; paramnum++; // Increment paramnum to point at the first jump target
int count = numparam - paramnum;
if (count > 0 && (maxchance >= 256 || pr_cajump() < maxchance)) if (count > 0 && (maxchance >= 256 || pr_cajump() < maxchance))
{ {
int jumpnum = (count == 1 ? 0 : (pr_cajump() % count)); int jumpnum = (count == 1 ? 0 : (pr_cajump() % count));
PARAM_STATE_AT(pnum + jumpnum, jumpto); PARAM_STATE_AT(paramnum + jumpnum, jumpto);
ACTION_JUMP(jumpto); ACTION_JUMP(jumpto);
} }
ACTION_SET_RESULT(false); // Jumps should never set the result for inventory state chains! ACTION_SET_RESULT(false); // Jumps should never set the result for inventory state chains!
@ -529,7 +530,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfCloser)
//========================================================================== //==========================================================================
void DoJumpIfInventory(AActor *owner, AActor *self, StateCallData *statecall, FState *callingstate, VMValue *param, int numparam) void DoJumpIfInventory(AActor *owner, AActor *self, StateCallData *statecall, FState *callingstate, VMValue *param, int numparam)
{ {
int pnum = NAP; int paramnum = NAP-1;
PARAM_CLASS (itemtype, AInventory); PARAM_CLASS (itemtype, AInventory);
PARAM_INT (itemamount); PARAM_INT (itemamount);
PARAM_STATE (label); PARAM_STATE (label);
@ -1314,7 +1315,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomRailgun)
static void DoGiveInventory(AActor *receiver, StateCallData *statecall, VM_ARGS) static void DoGiveInventory(AActor *receiver, StateCallData *statecall, VM_ARGS)
{ {
int pnum = NAP; int paramnum = NAP-1;
PARAM_CLASS (mi, AInventory); PARAM_CLASS (mi, AInventory);
PARAM_INT_OPT (amount) { amount = 1; } PARAM_INT_OPT (amount) { amount = 1; }
@ -1381,7 +1382,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_GiveToTarget)
void DoTakeInventory(AActor *receiver, StateCallData *statecall, VM_ARGS) void DoTakeInventory(AActor *receiver, StateCallData *statecall, VM_ARGS)
{ {
int pnum = NAP; int paramnum = NAP-1;
PARAM_CLASS (itemtype, AInventory); PARAM_CLASS (itemtype, AInventory);
PARAM_INT_OPT (amount) { amount = 0; } PARAM_INT_OPT (amount) { amount = 0; }

View file

@ -3735,7 +3735,7 @@ int DecoNameToClass(VMFrameStack *stack, VMValue *param, int numparam, VMReturn
Printf("class '%s' is not compatible with '%s'", clsname.GetChars(), desttype->TypeName.GetChars()); Printf("class '%s' is not compatible with '%s'", clsname.GetChars(), desttype->TypeName.GetChars());
cls = NULL; cls = NULL;
} }
ret->SetPointer(const_cast<PClass *>(cls)); ret->SetPointer(const_cast<PClass *>(cls), ATAG_OBJECT);
return 1; return 1;
} }
@ -3923,15 +3923,15 @@ int DecoFindMultiNameState(VMFrameStack *stack, VMValue *param, int numparam, VM
{ {
assert(numparam > 1); assert(numparam > 1);
assert(numret == 1); assert(numret == 1);
assert(param[0].Type == REGT_POINTER);
assert(ret->RegType == REGT_POINTER); assert(ret->RegType == REGT_POINTER);
FName *names = (FName *)alloca((numparam - 1) * sizeof(FName)); FName *names = (FName *)alloca((numparam - 1) * sizeof(FName));
for (int i = 1; i < numparam; ++i) for (int i = 1; i < numparam; ++i)
{ {
names[i - 1] = ENamedName(param[i].i); PARAM_NAME_AT(i, zaname);
names[i - 1] = zaname;
} }
AActor *self = reinterpret_cast<AActor *>(param[0].a); PARAM_OBJECT_AT(0, self, AActor);
FState *state = self->GetClass()->ActorInfo->FindState(numparam - 1, names); FState *state = self->GetClass()->ActorInfo->FindState(numparam - 1, names);
if (state == NULL) if (state == NULL)
{ {
@ -3944,14 +3944,14 @@ int DecoFindMultiNameState(VMFrameStack *stack, VMValue *param, int numparam, VM
} }
Printf("' not found in %s\n", self->GetClass()->TypeName.GetChars()); Printf("' not found in %s\n", self->GetClass()->TypeName.GetChars());
} }
ret->SetPointer(state); ret->SetPointer(state, ATAG_STATE);
return 1; return 1;
} }
ExpEmit FxMultiNameState::Emit(VMFunctionBuilder *build) ExpEmit FxMultiNameState::Emit(VMFunctionBuilder *build)
{ {
ExpEmit dest(build, REGT_POINTER); ExpEmit dest(build, REGT_POINTER);
build->Emit(OP_PARAM, 0, REGT_POINTER, 0); // pass self build->Emit(OP_PARAM, 0, REGT_POINTER, 1); // pass stateowner
for (unsigned i = 0; i < names.Size(); ++i) for (unsigned i = 0; i < names.Size(); ++i)
{ {
EmitConstantInt(build, names[i]); EmitConstantInt(build, names[i]);

View file

@ -81,7 +81,7 @@ bool DoActionSpecials(FScanner &sc, FState & state, Baggage &bag, FStateTempCall
{ {
for (i = 0; i < 5;) for (i = 0; i < 5;)
{ {
tcall->Parameters.Push(new FxParameter(ParseExpression(sc, bag.Info->Class))); tcall->Parameters.Push(new FxParameter(new FxIntCast(ParseExpression(sc, bag.Info->Class))));
i++; i++;
if (!sc.CheckToken (',')) break; if (!sc.CheckToken (',')) break;
} }
@ -98,8 +98,7 @@ bool DoActionSpecials(FScanner &sc, FState & state, Baggage &bag, FStateTempCall
sc.ScriptError ("Too many arguments to %s", specname.GetChars()); sc.ScriptError ("Too many arguments to %s", specname.GetChars());
} }
//FIXME tcall->Function = FindGlobalActionFunction("A_CallSpecial")->Function;
//state.SetAction(FindGlobalActionFunction("A_CallSpecial"), false);
return true; return true;
} }
return false; return false;
@ -262,6 +261,7 @@ do_stop:
if (sym != NULL && sym->SymbolType == SYM_ActionFunction) if (sym != NULL && sym->SymbolType == SYM_ActionFunction)
{ {
PSymbolActionFunction *afd = static_cast<PSymbolActionFunction *>(sym); PSymbolActionFunction *afd = static_cast<PSymbolActionFunction *>(sym);
tcall->Function = afd->Function;
if (!afd->Arguments.IsEmpty()) if (!afd->Arguments.IsEmpty())
{ {
const char *params = afd->Arguments.GetChars(); const char *params = afd->Arguments.GetChars();
@ -374,7 +374,7 @@ endofstate:
sc.ScriptError ("Invalid frame character string '%s'", statestring.GetChars()); sc.ScriptError ("Invalid frame character string '%s'", statestring.GetChars());
count = -count; count = -count;
} }
if (tcall->Parameters.Size() != 0) if (tcall->Function != NULL)
{ {
tcall->ActorInfo = actor; tcall->ActorInfo = actor;
tcall->FirstState = bag.statedef.GetStateCount() - count; tcall->FirstState = bag.statedef.GetStateCount() - count;

View file

@ -251,54 +251,63 @@ extern const VMOpInfo OpInfo[NUM_OPS];
struct VMReturn struct VMReturn
{ {
void *Location; void *Location;
VM_SHALF RegNum; // Used to find ObjFlag index for pointers; set negative if the caller is native code and doesn't care VM_SHALF TagOfs; // for pointers: Offset from Location to ATag; set to 0 if the caller is native code and doesn't care
VM_UBYTE RegType; // Same as VMParam RegType, except REGT_KONST is invalid; only used by asserts VM_UBYTE RegType; // Same as VMParam RegType, except REGT_KONST is invalid; only used by asserts
void SetInt(int val) void SetInt(int val)
{ {
assert(RegType == REGT_INT);
*(int *)Location = val; *(int *)Location = val;
} }
void SetFloat(double val) void SetFloat(double val)
{ {
assert(RegType == REGT_FLOAT);
*(double *)Location = val; *(double *)Location = val;
} }
void SetVector(const double val[3]) void SetVector(const double val[3])
{ {
//assert(RegType == REGT_FLOAT);
((double *)Location)[0] = val[0]; ((double *)Location)[0] = val[0];
((double *)Location)[1] = val[1]; ((double *)Location)[1] = val[1];
((double *)Location)[2] = val[2]; ((double *)Location)[2] = val[2];
} }
void SetString(const FString &val) void SetString(const FString &val)
{ {
assert(RegType == REGT_STRING);
*(FString *)Location = val; *(FString *)Location = val;
} }
void SetPointer(void *val) void SetPointer(void *val, int tag)
{ {
assert(RegType == REGT_POINTER);
*(void **)Location = val; *(void **)Location = val;
if (TagOfs != 0)
{
*((VM_ATAG *)Location + TagOfs) = tag;
}
} }
void IntAt(int *loc) void IntAt(int *loc)
{ {
Location = loc; Location = loc;
RegNum = -1; TagOfs = 0;
RegType = REGT_INT; RegType = REGT_INT;
} }
void FloatAt(double *loc) void FloatAt(double *loc)
{ {
Location = loc; Location = loc;
RegNum = -1; TagOfs = 0;
RegType = REGT_FLOAT; RegType = REGT_FLOAT;
} }
void StringAt(FString *loc) void StringAt(FString *loc)
{ {
Location = loc; Location = loc;
RegNum = -1; TagOfs = 0;
RegType = REGT_STRING; RegType = REGT_STRING;
} }
void PointerAt(void **loc) void PointerAt(void **loc)
{ {
Location = loc; Location = loc;
RegNum = -1; TagOfs = 0;
RegType = REGT_POINTER; RegType = REGT_POINTER;
} }
}; };
@ -863,8 +872,8 @@ void VMDisasm(FILE *out, const VMOP *code, int codesize, const VMScriptFunction
#define PARAM_STRING_AT(p,x) assert((p) < numparam); assert(param[p].Type == REGT_STRING); FString x = param[p].s(); #define PARAM_STRING_AT(p,x) assert((p) < numparam); assert(param[p].Type == REGT_STRING); FString x = param[p].s();
#define PARAM_STATE_AT(p,x) assert((p) < numparam); assert(param[p].Type == REGT_POINTER && (param[p].atag == ATAG_STATE || param[p].a == NULL)); FState *x = (FState *)param[p].a; #define PARAM_STATE_AT(p,x) assert((p) < numparam); assert(param[p].Type == REGT_POINTER && (param[p].atag == ATAG_STATE || param[p].a == NULL)); FState *x = (FState *)param[p].a;
#define PARAM_POINTER_AT(p,x,type) assert((p) < numparam); assert(param[p].Type == REGT_POINTER); type *x = (type *)param[p].a; #define PARAM_POINTER_AT(p,x,type) assert((p) < numparam); assert(param[p].Type == REGT_POINTER); type *x = (type *)param[p].a;
#define PARAM_OBJECT_AT(p,x,type) assert((p) < numparam); assert(param[p].Type == REGT_POINTER && (param[p].atag == ATAG_OBJECT || param[p].a == NULL)); type *x = (type *)param[p].a; #define PARAM_OBJECT_AT(p,x,type) assert((p) < numparam); assert(param[p].Type == REGT_POINTER && (param[p].atag == ATAG_OBJECT || param[p].a == NULL)); type *x = (type *)param[p].a; assert(x == NULL || x->IsKindOf(RUNTIME_CLASS(type)));
#define PARAM_CLASS_AT(p,x,base) assert((p) < numparam); assert(param[p].Type == REGT_POINTER && (param[p].atag == ATAG_OBJECT || param[p].a == NULL)); PClass *x = (PClass *)param[p].a; assert(x->IsDescendantOf(RUNTIME_CLASS(base))); #define PARAM_CLASS_AT(p,x,base) assert((p) < numparam); assert(param[p].Type == REGT_POINTER && (param[p].atag == ATAG_OBJECT || param[p].a == NULL)); PClass *x = (PClass *)param[p].a; assert(x != NULL && x->IsDescendantOf(RUNTIME_CLASS(base)));
// For optional paramaters. These have dangling elses for you to fill in the default assignment. e.g.: // For optional paramaters. These have dangling elses for you to fill in the default assignment. e.g.:
// PARAM_INT_OPT(0,myint) { myint = 55; } // PARAM_INT_OPT(0,myint) { myint = 55; }
@ -881,38 +890,38 @@ void VMDisasm(FILE *out, const VMOP *code, int codesize, const VMScriptFunction
#define PARAM_STRING_OPT_AT(p,x) FString x; if ((p) < numparam && param[p].Type != REGT_NIL) { assert(param[p].Type == REGT_STRING); x = param[p].s(); } else #define PARAM_STRING_OPT_AT(p,x) FString x; if ((p) < numparam && param[p].Type != REGT_NIL) { assert(param[p].Type == REGT_STRING); x = param[p].s(); } else
#define PARAM_STATE_OPT_AT(p,x) FState *x; if ((p) < numparam && param[p].Type != REGT_NIL) { assert(param[p].Type == REGT_POINTER && (param[p].atag == ATAG_STATE || param[p].a == NULL)); x = (FState *)param[p].a; } else #define PARAM_STATE_OPT_AT(p,x) FState *x; if ((p) < numparam && param[p].Type != REGT_NIL) { assert(param[p].Type == REGT_POINTER && (param[p].atag == ATAG_STATE || param[p].a == NULL)); x = (FState *)param[p].a; } else
#define PARAM_POINTER_OPT_AT(p,x,type) type *x; if ((p) < numparam && param[p].Type != REGT_NIL) { assert(param[p].Type == REGT_POINTER); x = (type *)param[p].a; } else #define PARAM_POINTER_OPT_AT(p,x,type) type *x; if ((p) < numparam && param[p].Type != REGT_NIL) { assert(param[p].Type == REGT_POINTER); x = (type *)param[p].a; } else
#define PARAM_OBJECT_OPT_AT(p,x,type) type *x; if ((p) < numparam && param[p].Type != REGT_NIL) { assert(param[p].Type == REGT_POINTER && (param[p].atag == ATAG_OBJECT || param[p].a == NULL)); x = (type *)param[p].a; } else #define PARAM_OBJECT_OPT_AT(p,x,type) type *x; if ((p) < numparam && param[p].Type != REGT_NIL) { assert(param[p].Type == REGT_POINTER && (param[p].atag == ATAG_OBJECT || param[p].a == NULL)); x = (type *)param[p].a; assert(x == NULL || x->IsKindOf(RUNTIME_CLASS(type))); } else
#define PARAM_CLASS_OPT_AT(p,x,base) PClass *x; if ((p) < numparam && param[p].Type != REGT_NIL) { assert(param[p].Type == REGT_POINTER && (param[p].atag == ATAG_OBJECT || param[p].a == NULL)); x = (PClass *)param[p].a; assert(x->IsKindOf(RUNTIME_CLASS(base))); } else #define PARAM_CLASS_OPT_AT(p,x,base) PClass *x; if ((p) < numparam && param[p].Type != REGT_NIL) { assert(param[p].Type == REGT_POINTER && (param[p].atag == ATAG_OBJECT || param[p].a == NULL)); x = (PClass *)param[p].a; assert(x != NULL && x->IsDescendantOf(RUNTIME_CLASS(base))); } else
// The above, but with an automatically increasing position index. // The above, but with an automatically increasing position index.
#define PARAM_PROLOGUE int pnum = -1; #define PARAM_PROLOGUE int paramnum = -1;
#define PARAM_INT(x) ++pnum; PARAM_INT_AT(pnum,x) #define PARAM_INT(x) ++paramnum; PARAM_INT_AT(paramnum,x)
#define PARAM_BOOL(x) ++pnum; PARAM_BOOL_AT(pnum,x) #define PARAM_BOOL(x) ++paramnum; PARAM_BOOL_AT(paramnum,x)
#define PARAM_NAME(x) ++pnum; PARAM_NAME_AT(pnum,x) #define PARAM_NAME(x) ++paramnum; PARAM_NAME_AT(paramnum,x)
#define PARAM_SOUND(x) ++pnum; PARAM_SOUND_AT(pnum,x) #define PARAM_SOUND(x) ++paramnum; PARAM_SOUND_AT(paramnum,x)
#define PARAM_COLOR(x) ++pnum; PARAM_COLOR_AT(pnum,x) #define PARAM_COLOR(x) ++paramnum; PARAM_COLOR_AT(paramnum,x)
#define PARAM_FLOAT(x) ++pnum; PARAM_FLOAT_AT(pnum,x) #define PARAM_FLOAT(x) ++paramnum; PARAM_FLOAT_AT(paramnum,x)
#define PARAM_FIXED(x) ++pnum; PARAM_FIXED_AT(pnum,x) #define PARAM_FIXED(x) ++paramnum; PARAM_FIXED_AT(paramnum,x)
#define PARAM_ANGLE(x) ++pnum; PARAM_ANGLE_AT(pnum,x) #define PARAM_ANGLE(x) ++paramnum; PARAM_ANGLE_AT(paramnum,x)
#define PARAM_STRING(x) ++pnum; PARAM_STRING_AT(pnum,x) #define PARAM_STRING(x) ++paramnum; PARAM_STRING_AT(paramnum,x)
#define PARAM_STATE(x) ++pnum; PARAM_STATE_AT(pnum,x) #define PARAM_STATE(x) ++paramnum; PARAM_STATE_AT(paramnum,x)
#define PARAM_POINTER(x,type) ++pnum; PARAM_POINTER_AT(pnum,x,type) #define PARAM_POINTER(x,type) ++paramnum; PARAM_POINTER_AT(paramnum,x,type)
#define PARAM_OBJECT(x,type) ++pnum; PARAM_OBJECT_AT(pnum,x,type) #define PARAM_OBJECT(x,type) ++paramnum; PARAM_OBJECT_AT(paramnum,x,type)
#define PARAM_CLASS(x,base) ++pnum; PARAM_CLASS_AT(pnum,x,base) #define PARAM_CLASS(x,base) ++paramnum; PARAM_CLASS_AT(paramnum,x,base)
#define PARAM_INT_OPT(x) ++pnum; PARAM_INT_OPT_AT(pnum,x) #define PARAM_INT_OPT(x) ++paramnum; PARAM_INT_OPT_AT(paramnum,x)
#define PARAM_BOOL_OPT(x) ++pnum; PARAM_BOOL_OPT_AT(pnum,x) #define PARAM_BOOL_OPT(x) ++paramnum; PARAM_BOOL_OPT_AT(paramnum,x)
#define PARAM_NAME_OPT(x) ++pnum; PARAM_NAME_OPT_AT(pnum,x) #define PARAM_NAME_OPT(x) ++paramnum; PARAM_NAME_OPT_AT(paramnum,x)
#define PARAM_SOUND_OPT(x) ++pnum; PARAM_SOUND_OPT_AT(pnum,x) #define PARAM_SOUND_OPT(x) ++paramnum; PARAM_SOUND_OPT_AT(paramnum,x)
#define PARAM_COLOR_OPT(x) ++pnum; PARAM_COLOR_OPT_AT(pnum,x) #define PARAM_COLOR_OPT(x) ++paramnum; PARAM_COLOR_OPT_AT(paramnum,x)
#define PARAM_FLOAT_OPT(x) ++pnum; PARAM_FLOAT_OPT_AT(pnum,x) #define PARAM_FLOAT_OPT(x) ++paramnum; PARAM_FLOAT_OPT_AT(paramnum,x)
#define PARAM_FIXED_OPT(x) ++pnum; PARAM_FIXED_OPT_AT(pnum,x) #define PARAM_FIXED_OPT(x) ++paramnum; PARAM_FIXED_OPT_AT(paramnum,x)
#define PARAM_ANGLE_OPT(x) ++pnum; PARAM_ANGLE_OPT_AT(pnum,x) #define PARAM_ANGLE_OPT(x) ++paramnum; PARAM_ANGLE_OPT_AT(paramnum,x)
#define PARAM_STRING_OPT(x) ++pnum; PARAM_STRING_OPT_AT(pnum,x) #define PARAM_STRING_OPT(x) ++paramnum; PARAM_STRING_OPT_AT(paramnum,x)
#define PARAM_STATE_OPT(x) ++pnum; PARAM_STATE_OPT_AT(pnum,x) #define PARAM_STATE_OPT(x) ++paramnum; PARAM_STATE_OPT_AT(paramnum,x)
#define PARAM_POINTER_OPT(x,type) ++pnum; PARAM_POINTER_OPT_AT(pnum,x,type) #define PARAM_POINTER_OPT(x,type) ++paramnum; PARAM_POINTER_OPT_AT(paramnum,x,type)
#define PARAM_OBJECT_OPT(x,type) ++pnum; PARAM_OBJECT_OPT_AT(pnum,x,type) #define PARAM_OBJECT_OPT(x,type) ++paramnum; PARAM_OBJECT_OPT_AT(paramnum,x,type)
#define PARAM_CLASS_OPT(x,base) ++pnum; PARAM_CLASS_OPT_AT(pnum,x,base) #define PARAM_CLASS_OPT(x,base) ++paramnum; PARAM_CLASS_OPT_AT(paramnum,x,base)
#endif #endif

View file

@ -155,7 +155,7 @@ void VMDumpConstants(FILE *out, const VMScriptFunction *func)
{ {
for (j = 0, k = i; j < 4 && k < func->NumKonstA; j++, k += kk) for (j = 0, k = i; j < 4 && k < func->NumKonstA; j++, k += kk)
{ {
mysnprintf(tmp, countof(tmp), "%3d. %p", k, func->KonstA[k]); mysnprintf(tmp, countof(tmp), "%3d. %p:%d", k, func->KonstA[k], func->KonstATags()[k]);
printf_wrapper(out, "%-20s", tmp); printf_wrapper(out, "%-20s", tmp);
} }
printf_wrapper(out, "\n"); printf_wrapper(out, "\n");

View file

@ -1384,7 +1384,7 @@ static void DoCast(const VMRegisters &reg, const VMFrame *f, int a, int b, int c
static void FillReturns(const VMRegisters &reg, VMFrame *frame, VMReturn *returns, const VMOP *retval, int numret) static void FillReturns(const VMRegisters &reg, VMFrame *frame, VMReturn *returns, const VMOP *retval, int numret)
{ {
int i, type, num; int i, type, regnum;
VMReturn *ret; VMReturn *ret;
assert(REGT_INT == 0 && REGT_FLOAT == 1 && REGT_STRING == 2 && REGT_POINTER == 3); assert(REGT_INT == 0 && REGT_FLOAT == 1 && REGT_STRING == 2 && REGT_POINTER == 3);
@ -1392,33 +1392,35 @@ static void FillReturns(const VMRegisters &reg, VMFrame *frame, VMReturn *return
for (i = 0, ret = returns; i < numret; ++i, ++ret, ++retval) for (i = 0, ret = returns; i < numret; ++i, ++ret, ++retval)
{ {
assert(retval->op == OP_RESULT); // opcode assert(retval->op == OP_RESULT); // opcode
ret->TagOfs = 0;
ret->RegType = type = retval->b; ret->RegType = type = retval->b;
ret->RegNum = num = retval->c; regnum = retval->c;
assert(!(type & REGT_KONST)); assert(!(type & REGT_KONST));
type &= REGT_TYPE; type &= REGT_TYPE;
if (type < REGT_STRING) if (type < REGT_STRING)
{ {
if (type == REGT_INT) if (type == REGT_INT)
{ {
assert(num < frame->NumRegD); assert(regnum < frame->NumRegD);
ret->Location = &reg.d[num]; ret->Location = &reg.d[regnum];
} }
else // type == REGT_FLOAT else // type == REGT_FLOAT
{ {
assert(num < frame->NumRegF); assert(regnum < frame->NumRegF);
ret->Location = &reg.f[num]; ret->Location = &reg.f[regnum];
} }
} }
else if (type == REGT_STRING) else if (type == REGT_STRING)
{ {
assert(num < frame->NumRegS); assert(regnum < frame->NumRegS);
ret->Location = &reg.s[num]; ret->Location = &reg.s[regnum];
} }
else else
{ {
assert(type == REGT_POINTER); assert(type == REGT_POINTER);
assert(num < frame->NumRegA); assert(regnum < frame->NumRegA);
ret->Location = &reg.a[num]; ret->Location = &reg.a[regnum];
ret->TagOfs = (VM_SHALF)(&frame->GetRegATag()[regnum] - (VM_ATAG *)ret->Location);
} }
} }
} }
@ -1434,7 +1436,6 @@ static void FillReturns(const VMRegisters &reg, VMFrame *frame, VMReturn *return
static void SetReturn(const VMRegisters &reg, VMFrame *frame, VMReturn *ret, VM_UBYTE regtype, int regnum) static void SetReturn(const VMRegisters &reg, VMFrame *frame, VMReturn *ret, VM_UBYTE regtype, int regnum)
{ {
const void *src; const void *src;
VM_ATAG atag;
VMScriptFunction *func = static_cast<VMScriptFunction *>(frame->Func); VMScriptFunction *func = static_cast<VMScriptFunction *>(frame->Func);
assert(func != NULL && !func->Native); assert(func != NULL && !func->Native);
@ -1498,20 +1499,12 @@ static void SetReturn(const VMRegisters &reg, VMFrame *frame, VMReturn *ret, VM_
if (regtype & REGT_KONST) if (regtype & REGT_KONST)
{ {
assert(regnum < func->NumKonstA); assert(regnum < func->NumKonstA);
ret->SetPointer(func->KonstA[regnum].v); ret->SetPointer(func->KonstA[regnum].v, func->KonstATags()[regnum]);
atag = func->KonstATags()[regnum];
} }
else else
{ {
assert(regnum < frame->NumRegA); assert(regnum < frame->NumRegA);
ret->SetPointer(reg.a[regnum]); ret->SetPointer(reg.a[regnum], reg.atag[regnum]);
atag = reg.atag[regnum];
}
if (ret->RegNum >= 0)
{
VMFrame *parent = frame->ParentFrame;
assert(parent != NULL);
parent->GetRegATag()[ret->RegNum] = atag;
} }
break; break;
} }

View file

@ -26,7 +26,6 @@ ACTOR Actor native //: Thinker
native fixed_t alpha; native fixed_t alpha;
native angle_t angle; native angle_t angle;
native int args[5]; native int args[5];
native int uservar[10];
native fixed_t ceilingz; native fixed_t ceilingz;
native fixed_t floorz; native fixed_t floorz;
native int health; native int health;