mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-28 23:12:24 +00:00
110 lines
2.8 KiB
C++
110 lines
2.8 KiB
C++
//-----------------------------------------------------------------------------
|
|
//
|
|
// Copyright 2018 Christoph Oelckers
|
|
//
|
|
// This program is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
// (at your option) any later version.
|
|
//
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with this program. If not, see http://www.gnu.org/licenses/
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
//
|
|
// DESCRIPTION: generalized interface for implementing ACS/FS functions
|
|
// in ZScript.
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
#include "i_system.h"
|
|
#include "tarray.h"
|
|
#include "dobject.h"
|
|
#include "vm.h"
|
|
#include "scriptutil.h"
|
|
#include "p_acs.h"
|
|
#include "actorinlines.h"
|
|
|
|
|
|
static TArray<VMValue> parameters;
|
|
static TMap<FName, VMFunction*> functions;
|
|
|
|
void ScriptUtil::Clear()
|
|
{
|
|
parameters.Clear();
|
|
functions.Clear();
|
|
}
|
|
|
|
void ScriptUtil::BuildParameters(va_list ap)
|
|
{
|
|
for(int type = va_arg(ap, int); type != End; type = va_arg(ap, int))
|
|
{
|
|
switch (type)
|
|
{
|
|
case Int:
|
|
parameters.Push(VMValue(va_arg(ap, int)));
|
|
break;
|
|
|
|
case Pointer:
|
|
case Class: // this is just a pointer.
|
|
case String: // must be passed by reference to a persistent location!
|
|
parameters.Push(VMValue(va_arg(ap, void*)));
|
|
break;
|
|
|
|
case Float:
|
|
parameters.Push(VMValue(va_arg(ap, double)));
|
|
break;
|
|
|
|
case ACSClass:
|
|
parameters.Push(VMValue(PClass::FindActor(FBehavior::StaticLookupString(va_arg(ap, int)))));
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void ScriptUtil::RunFunction(FName functionname, unsigned paramstart, VMReturn &returns)
|
|
{
|
|
VMFunction *func = nullptr;
|
|
auto check = functions.CheckKey(functionname);
|
|
if (!check)
|
|
{
|
|
func = PClass::FindFunction(NAME_ScriptUtil, functionname);
|
|
if (func == nullptr)
|
|
{
|
|
I_Error("Call to undefined function ScriptUtil.%s", functionname.GetChars());
|
|
}
|
|
functions.Insert(functionname, func);
|
|
}
|
|
else func = *check;
|
|
|
|
VMCall(func, ¶meters[paramstart], parameters.Size() - paramstart, &returns, 1);
|
|
}
|
|
|
|
int ScriptUtil::Exec(FName functionname, ...)
|
|
{
|
|
unsigned paramstart = parameters.Size();
|
|
va_list ap;
|
|
va_start(ap, functionname);
|
|
try
|
|
{
|
|
BuildParameters(ap);
|
|
int ret = 0;
|
|
VMReturn returns(&ret);
|
|
RunFunction(functionname, paramstart, returns);
|
|
va_end(ap);
|
|
parameters.Clamp(paramstart);
|
|
return ret;
|
|
}
|
|
catch(...)
|
|
{
|
|
va_end(ap);
|
|
parameters.Clamp(paramstart);
|
|
throw;
|
|
}
|
|
}
|