diff --git a/src/info.cpp b/src/info.cpp index 5e2593bb9f..402f74c37f 100644 --- a/src/info.cpp +++ b/src/info.cpp @@ -175,13 +175,13 @@ bool FState::CallAction(AActor *self, AActor *stateowner, FStateParamInfo *info, if (stateret == nullptr) { - VMCallWithDefaults(ActionFunc, params, ActionFunc->ImplicitArgs, nullptr, 0); + VMCallAction(ActionFunc, params, ActionFunc->ImplicitArgs, nullptr, 0); } else { VMReturn ret; ret.PointerAt((void **)stateret); - VMCallWithDefaults(ActionFunc, params, ActionFunc->ImplicitArgs, &ret, 1); + VMCallAction(ActionFunc, params, ActionFunc->ImplicitArgs, &ret, 1); } } catch (CVMAbortException &err) diff --git a/src/menu/menudef.cpp b/src/menu/menudef.cpp index 333d463017..43c703900e 100644 --- a/src/menu/menudef.cpp +++ b/src/menu/menudef.cpp @@ -477,7 +477,7 @@ static void ParseListMenuBody(FScanner &sc, DListMenuDescriptor *desc) } DMenuItemBase *item = (DMenuItemBase*)cls->CreateNew(); params[0] = item; - VMCallWithDefaults(func->Variants[0].Implementation, ¶ms[0], params.Size(), nullptr, 0); + VMCallWithDefaults(func->Variants[0].Implementation, params, nullptr, 0); desc->mItems.Push((DMenuItemBase*)item); if (cls->IsDescendantOf("ListMenuItemSelectable")) @@ -917,7 +917,7 @@ static void ParseOptionMenuBody(FScanner &sc, DOptionMenuDescriptor *desc) DMenuItemBase *item = (DMenuItemBase*)cls->CreateNew(); params[0] = item; - VMCallWithDefaults(func->Variants[0].Implementation, ¶ms[0], params.Size(), nullptr, 0); + VMCallWithDefaults(func->Variants[0].Implementation, params, nullptr, 0); desc->mItems.Push((DMenuItemBase*)item); success = true; diff --git a/src/p_acs.cpp b/src/p_acs.cpp index 47a508995c..808b724e19 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -5448,7 +5448,7 @@ static int ScriptCall(AActor *activator, unsigned argc, int32_t *args) // The return value can be the same types as the parameter types, plus void if (func->Proto->ReturnTypes.Size() == 0) { - VMCallWithDefaults(func, ¶ms[0], params.Size(), nullptr, 0); + VMCallWithDefaults(func, params, nullptr, 0); } else { @@ -5470,20 +5470,20 @@ static int ScriptCall(AActor *activator, unsigned argc, int32_t *args) { double d; VMReturn ret(&d); - VMCallWithDefaults(func, ¶ms[0], params.Size(), &ret, 1); + VMCallWithDefaults(func, params, &ret, 1); retval = DoubleToACS(d); } else if (rettype == TypeString) { FString d; VMReturn ret(&d); - VMCallWithDefaults(func, ¶ms[0], params.Size(), &ret, 1); + VMCallWithDefaults(func, params, &ret, 1); retval = GlobalACSStrings.AddString(d); } else { // All other return values can not be handled so ignore them. - VMCallWithDefaults(func, ¶ms[0], params.Size(), nullptr, 0); + VMCallWithDefaults(func, params, nullptr, 0); } } } diff --git a/src/p_actionfunctions.cpp b/src/p_actionfunctions.cpp index d412bf2947..7bb55b6fb1 100644 --- a/src/p_actionfunctions.cpp +++ b/src/p_actionfunctions.cpp @@ -170,7 +170,7 @@ bool AStateProvider::CallStateChain (AActor *actor, FState *state) try { state->CheckCallerType(actor, this); - VMCallWithDefaults(state->ActionFunc, params, state->ActionFunc->ImplicitArgs, wantret, numret); + VMCallAction(state->ActionFunc, params, state->ActionFunc->ImplicitArgs, wantret, numret); } catch (CVMAbortException &err) { diff --git a/src/scripting/vm/vm.h b/src/scripting/vm/vm.h index 4b8bb74509..e498d4c14e 100644 --- a/src/scripting/vm/vm.h +++ b/src/scripting/vm/vm.h @@ -209,8 +209,6 @@ struct VMValue const FString *sp; }; - // Unfortunately, FString cannot be used directly. - // Fortunately, it is relatively simple. const FString &s() const { return *sp; } VMValue() @@ -376,8 +374,9 @@ private: }; int VMCall(VMFunction *func, VMValue *params, int numparams, VMReturn *results, int numresults/*, VMException **trap = NULL*/); +int VMCallWithDefaults(VMFunction *func, TArray ¶ms, VMReturn *results, int numresults/*, VMException **trap = NULL*/); -inline int VMCallWithDefaults(VMFunction *func, VMValue *params, int numparams, VMReturn *results, int numresults/*, VMException **trap = NULL*/) +inline int VMCallAction(VMFunction *func, VMValue *params, int numparams, VMReturn *results, int numresults/*, VMException **trap = NULL*/) { return VMCall(func, params, numparams, results, numresults); } diff --git a/src/scripting/vm/vmframe.cpp b/src/scripting/vm/vmframe.cpp index 374911ec66..8d36494905 100644 --- a/src/scripting/vm/vmframe.cpp +++ b/src/scripting/vm/vmframe.cpp @@ -577,6 +577,18 @@ int VMCall(VMFunction *func, VMValue *params, int numparams, VMReturn *results, #endif } +int VMCallWithDefaults(VMFunction *func, TArray ¶ms, VMReturn *results, int numresults/*, VMException **trap = NULL*/) +{ + if (func->DefaultArgs.Size() > params.Size()) + { + auto oldp = params.Size(); + params.Resize(func->DefaultArgs.Size()); + memcpy(¶ms[oldp], &func->DefaultArgs[oldp], (params.Size() - oldp) * sizeof(VMValue)); + } + return VMCall(func, params.Data(), params.Size(), results, numresults); +} + + // Exception stuff for the VM is intentionally placed there, because having this in vmexec.cpp would subject it to inlining // which we do not want because it increases the local stack requirements of Exec which are already too high. FString CVMAbortException::stacktrace;