This commit is contained in:
Rachael Alexanderson 2017-04-11 14:06:13 -04:00
commit 7040bc2156
33 changed files with 294 additions and 406 deletions

View file

@ -671,7 +671,7 @@ static int CreateSpawnFunc(VMFunctionBuilder &buildit, int value1, int value2)
I_Error("No class found for dehackednum %d!\n", value1+1);
return 0;
}
int typereg = buildit.GetConstantAddress(InfoNames[value1-1], ATAG_OBJECT);
int typereg = buildit.GetConstantAddress(InfoNames[value1-1]);
int heightreg = buildit.GetConstantFloat(value2);
buildit.Emit(OP_PARAM, 0, REGT_POINTER | REGT_KONST, typereg); // itemtype
@ -724,7 +724,7 @@ static int CreatePlaySoundFunc(VMFunctionBuilder &buildit, int value1, int value
// misc1 = state, misc2 = probability
static int CreateRandomJumpFunc(VMFunctionBuilder &buildit, int value1, int value2)
{ // A_Jump
int statereg = buildit.GetConstantAddress(FindState(value1), ATAG_STATE);
int statereg = buildit.GetConstantAddress(FindState(value1));
buildit.EmitParamInt(value2); // maxchance
buildit.Emit(OP_PARAM, 0, REGT_POINTER | REGT_KONST, statereg); // jumpto
@ -813,7 +813,7 @@ void SetDehParams(FState *state, int codepointer)
}
// Emit code for action parameters.
int argcount = MBFCodePointerFactories[codepointer](buildit, value1, value2);
buildit.Emit(OP_TAIL_K, buildit.GetConstantAddress(sym->Variants[0].Implementation, ATAG_OBJECT), numargs + argcount, 0);
buildit.Emit(OP_TAIL_K, buildit.GetConstantAddress(sym->Variants[0].Implementation), numargs + argcount, 0);
// Attach it to the state.
VMScriptFunction *sfunc = new VMScriptFunction;
buildit.MakeFunction(sfunc);

View file

@ -200,6 +200,14 @@ protected:
enum { MetaClassNum = CLASSREG_PClass };
// Per-instance variables. There are four.
#ifdef _DEBUG
public:
enum
{
MAGIC_ID = 0x1337cafe
};
uint32_t MagicID = MAGIC_ID; // only used by the VM for checking native function parameter types.
#endif
private:
PClass *Class; // This object's type
public:

View file

@ -780,6 +780,15 @@ PFloat::PFloat(unsigned int size)
mDescriptiveName.Format("Float%d", size);
if (size == 8)
{
#ifdef __i386__
// According to System V i386 ABI alignment of double type is 4
// GCC and Clang for 32-bit Intel targets follow this requirement
// However GCC has -malign-double option to enable 8-byte alignment
// So calculation of the actual alignment is needed
struct AlignmentCheck { uint8_t i; double d; };
Align = static_cast<unsigned int>(offsetof(AlignmentCheck, d));
#endif // __i386__
SetDoubleSymbols();
}
else

View file

@ -363,7 +363,7 @@ static PClassActor * T_GetAmmo(const svalue_t &t)
p=DefAmmo[ammonum];
}
auto am = PClass::FindActor(p);
if (am == NULL || !am->IsKindOf(PClass::FindClass(NAME_Ammo)))
if (am == NULL || !am->IsDescendantOf(PClass::FindClass(NAME_Ammo)))
{
script_error("unknown ammo type : %s", p);
return NULL;
@ -2436,7 +2436,7 @@ static void FS_GiveInventory (AActor *actor, const char * type, int amount)
type = "BasicArmorPickup";
}
auto info = PClass::FindActor (type);
if (info == NULL || !info->IsKindOf(RUNTIME_CLASS(AInventory)))
if (info == NULL || !info->IsDescendantOf(RUNTIME_CLASS(AInventory)))
{
Printf ("Unknown inventory item: %s\n", type);
return;

View file

@ -484,43 +484,6 @@ bool AInventory::CallTryPickup(AActor *toucher, AActor **toucher_return)
return !!res;
}
//===========================================================================
//
// AInventory :: CanPickup
//
//===========================================================================
DEFINE_ACTION_FUNCTION(AInventory, CanPickup)
{
PARAM_SELF_PROLOGUE(AInventory);
PARAM_OBJECT(toucher, AActor);
if (!toucher)
ACTION_RETURN_BOOL(false);
auto ai = self->GetClass();
// Is the item restricted to certain player classes?
if (ai->RestrictedToPlayerClass.Size() != 0)
{
for (unsigned i = 0; i < ai->RestrictedToPlayerClass.Size(); ++i)
{
if (toucher->IsKindOf(ai->RestrictedToPlayerClass[i]))
ACTION_RETURN_BOOL(true);
}
ACTION_RETURN_BOOL(false);
}
// Or is it forbidden to certain other classes?
else
{
for (unsigned i = 0; i < ai->ForbiddenToPlayerClass.Size(); ++i)
{
if (toucher->IsKindOf(ai->ForbiddenToPlayerClass[i]))
ACTION_RETURN_BOOL(false);
}
}
ACTION_RETURN_BOOL(true);
}
//===========================================================================
//
// CCMD printinv

View file

@ -635,7 +635,7 @@ void InitAllPowerupEffects(AInventory *item)
{
if (item->IsKindOf(ptype))
{
IFVIRTUALPTRNAME(item, NAME_Powerup, EndEffect)
IFVIRTUALPTRNAME(item, NAME_Powerup, InitEffect)
{
VMValue params[1] = { item };
VMFrameStack stack;

View file

@ -38,7 +38,7 @@ void FLinearDepthShader::Bind()
if (!mShader)
{
mShader = std::make_unique<FShaderProgram>();
mShader.reset(new FShaderProgram());
mShader->Compile(FShaderProgram::Vertex, "shaders/glsl/screenquad.vp", "", 330);
mShader->Compile(FShaderProgram::Fragment, "shaders/glsl/lineardepth.fp", multisample ? "#define MULTISAMPLE\n" : "", 330);
mShader->SetFragDataLocation(0, "FragColor");
@ -66,7 +66,7 @@ void FSSAOShader::Bind()
if (!mShader)
{
mShader = std::make_unique<FShaderProgram>();
mShader.reset(new FShaderProgram());
mShader->Compile(FShaderProgram::Vertex, "shaders/glsl/screenquad.vp", "", 330);
mShader->Compile(FShaderProgram::Fragment, "shaders/glsl/ssao.fp", GetDefines(gl_ssao, multisample), 330);
mShader->SetFragDataLocation(0, "FragColor");
@ -142,7 +142,7 @@ void FSSAOCombineShader::Bind()
if (!mShader)
{
mShader = std::make_unique<FShaderProgram>();
mShader.reset(new FShaderProgram());
mShader->Compile(FShaderProgram::Vertex, "shaders/glsl/screenquad.vp", "", 330);
mShader->Compile(FShaderProgram::Fragment, "shaders/glsl/ssaocombine.fp", multisample ? "#define MULTISAMPLE\n" : "", 330);
mShader->SetFragDataLocation(0, "FragColor");

View file

@ -316,7 +316,7 @@ OpenGLSWFrameBuffer::HWPixelShader::~HWPixelShader()
bool OpenGLSWFrameBuffer::CreateFrameBuffer(const FString &name, int width, int height, HWFrameBuffer **outFramebuffer)
{
auto fb = std::make_unique<HWFrameBuffer>();
std::unique_ptr<HWFrameBuffer> fb(new HWFrameBuffer());
GLint format = GL_RGBA16F;
if (gl.es) format = GL_RGB;
@ -357,7 +357,7 @@ bool OpenGLSWFrameBuffer::CreateFrameBuffer(const FString &name, int width, int
bool OpenGLSWFrameBuffer::CreatePixelShader(FString vertexsrc, FString fragmentsrc, const FString &defines, HWPixelShader **outShader)
{
auto shader = std::make_unique<HWPixelShader>();
std::unique_ptr<HWPixelShader> shader(new HWPixelShader());
shader->Program = glCreateProgram();
if (shader->Program == 0) { Printf("glCreateProgram failed. Disabling OpenGL hardware acceleration.\n"); return false; }
@ -443,7 +443,7 @@ bool OpenGLSWFrameBuffer::CreatePixelShader(FString vertexsrc, FString fragments
bool OpenGLSWFrameBuffer::CreateVertexBuffer(int size, HWVertexBuffer **outVertexBuffer)
{
auto obj = std::make_unique<HWVertexBuffer>();
std::unique_ptr<HWVertexBuffer> obj(new HWVertexBuffer());
obj->Size = size;
@ -474,7 +474,7 @@ bool OpenGLSWFrameBuffer::CreateVertexBuffer(int size, HWVertexBuffer **outVerte
bool OpenGLSWFrameBuffer::CreateIndexBuffer(int size, HWIndexBuffer **outIndexBuffer)
{
auto obj = std::make_unique<HWIndexBuffer>();
std::unique_ptr<HWIndexBuffer> obj(new HWIndexBuffer());
obj->Size = size;
@ -494,7 +494,7 @@ bool OpenGLSWFrameBuffer::CreateIndexBuffer(int size, HWIndexBuffer **outIndexBu
bool OpenGLSWFrameBuffer::CreateTexture(const FString &name, int width, int height, int levels, int format, HWTexture **outTexture)
{
auto obj = std::make_unique<HWTexture>();
std::unique_ptr<HWTexture> obj(new HWTexture());
obj->Format = format;
@ -532,7 +532,7 @@ bool OpenGLSWFrameBuffer::CreateTexture(const FString &name, int width, int heig
OpenGLSWFrameBuffer::HWTexture *OpenGLSWFrameBuffer::CopyCurrentScreen()
{
auto obj = std::make_unique<HWTexture>();
std::unique_ptr<HWTexture> obj(new HWTexture());
obj->Format = GL_RGBA16F;
GLint oldBinding = 0;
@ -611,7 +611,7 @@ void OpenGLSWFrameBuffer::DrawTriangleFans(int count, const FBVERTEX *vertices)
if (!StreamVertexBuffer)
{
StreamVertexBuffer = std::make_unique<HWVertexBuffer>();
StreamVertexBuffer.reset(new HWVertexBuffer());
glGenVertexArrays(1, (GLuint*)&StreamVertexBuffer->VertexArray);
glGenBuffers(1, (GLuint*)&StreamVertexBuffer->Buffer);
glBindVertexArray(StreamVertexBuffer->VertexArray);
@ -648,7 +648,7 @@ void OpenGLSWFrameBuffer::DrawTriangleFans(int count, const BURNVERTEX *vertices
if (!StreamVertexBufferBurn)
{
StreamVertexBufferBurn = std::make_unique<HWVertexBuffer>();
StreamVertexBufferBurn.reset(new HWVertexBuffer());
glGenVertexArrays(1, (GLuint*)&StreamVertexBufferBurn->VertexArray);
glGenBuffers(1, (GLuint*)&StreamVertexBufferBurn->Buffer);
glBindVertexArray(StreamVertexBufferBurn->VertexArray);
@ -679,7 +679,7 @@ void OpenGLSWFrameBuffer::DrawPoints(int count, const FBVERTEX *vertices)
if (!StreamVertexBuffer)
{
StreamVertexBuffer = std::make_unique<HWVertexBuffer>();
StreamVertexBuffer.reset(new HWVertexBuffer());
glGenVertexArrays(1, (GLuint*)&StreamVertexBuffer->VertexArray);
glGenBuffers(1, (GLuint*)&StreamVertexBuffer->Buffer);
glBindVertexArray(StreamVertexBuffer->VertexArray);

View file

@ -76,7 +76,7 @@ bool FState::CallAction(AActor *self, AActor *stateowner, FStateParamInfo *info,
{
ActionCycles.Clock();
VMValue params[3] = { self, stateowner, VMValue(info, ATAG_GENERIC) };
VMValue params[3] = { self, stateowner, VMValue(info) };
// If the function returns a state, store it at *stateret.
// If it doesn't return a state but stateret is non-NULL, we need
// to set *stateret to NULL.
@ -314,10 +314,6 @@ void PClassActor::DeriveData(PClass *newclass)
*newa->PainChances = *PainChances;
}
// Inventory stuff
newa->ForbiddenToPlayerClass = ForbiddenToPlayerClass;
newa->RestrictedToPlayerClass = RestrictedToPlayerClass;
newa->DisplayName = DisplayName;
}
@ -589,49 +585,6 @@ void PClassActor::SetPainChance(FName type, int chance)
}
}
//==========================================================================
//
// PClassActor :: ReplaceClassRef
//
//==========================================================================
size_t PClassActor::PointerSubstitution(DObject *oldclass, DObject *newclass)
{
auto changed = Super::PointerSubstitution(oldclass, newclass);
for (unsigned i = 0; i < VisibleToPlayerClass.Size(); i++)
{
if (VisibleToPlayerClass[i] == oldclass)
{
VisibleToPlayerClass[i] = static_cast<PClassActor*>(newclass);
changed++;
}
}
for (unsigned i = 0; i < ForbiddenToPlayerClass.Size(); i++)
{
if (ForbiddenToPlayerClass[i] == oldclass)
{
ForbiddenToPlayerClass[i] = static_cast<PClassActor*>(newclass);
changed++;
}
}
for (unsigned i = 0; i < RestrictedToPlayerClass.Size(); i++)
{
if (RestrictedToPlayerClass[i] == oldclass)
{
RestrictedToPlayerClass[i] = static_cast<PClassActor*>(newclass);
changed++;
}
}
AInventory *def = dyn_cast<AInventory>((AActor*)Defaults);
if (def != NULL)
{
if (def->PickupFlash == oldclass) def->PickupFlash = static_cast<PClassActor *>(newclass);
}
return changed;
}
//==========================================================================
//
// DmgFactors :: CheckFactor

View file

@ -248,7 +248,6 @@ public:
PClassActor();
~PClassActor();
virtual size_t PointerSubstitution(DObject *oldclass, DObject *newclass);
void BuildDefaults();
void ApplyDefaults(uint8_t *defaults);
void RegisterIDs();
@ -292,10 +291,6 @@ public:
FString SourceLumpName;
FIntCVar *distancecheck;
// These are only valid for inventory items.
TArray<PClassActor *> RestrictedToPlayerClass;
TArray<PClassActor *> ForbiddenToPlayerClass;
// This is from PClassPlayerPawn
FString DisplayName;

View file

@ -576,7 +576,7 @@ bool M_ReadIDAT (FileReader *file, uint8_t *buffer, int width, int height, int p
if (stream.avail_in == 0 && chunklen > 0)
{
stream.next_in = chunkbuffer;
stream.avail_in = (uInt)file->Read (chunkbuffer, MIN<long>(chunklen,sizeof(chunkbuffer)));
stream.avail_in = (uInt)file->Read (chunkbuffer, MIN<uint32_t>(chunklen,sizeof(chunkbuffer)));
chunklen -= stream.avail_in;
}

View file

@ -902,3 +902,5 @@ xx(Player6)
xx(Player7)
xx(Player8)
xx(PlayerChunk)
xx(RestrictedToPlayerClass)
xx(ForbiddenToPlayerClass)

View file

@ -153,7 +153,7 @@ bool AStateProvider::CallStateChain (AActor *actor, FState *state)
VMReturn *wantret;
FStateParamInfo stp = { state, STATE_StateChain, PSP_WEAPON };
params[2] = VMValue(&stp, ATAG_GENERIC);
params[2] = VMValue(&stp);
retval = true; // assume success
wantret = NULL; // assume no return value wanted
numret = 0;
@ -2723,7 +2723,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_SpawnItem)
PARAM_BOOL_DEF (useammo)
PARAM_BOOL_DEF (transfer_translation);
if (numret > 1) ret[1].SetPointer(nullptr, ATAG_OBJECT);
if (numret > 1) ret[1].SetObject(nullptr);
if (missile == NULL)
{
@ -2760,7 +2760,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_SpawnItem)
int flags = (transfer_translation ? SIXF_TRANSFERTRANSLATION : 0) + (useammo ? SIXF_SETMASTER : 0);
bool res = InitSpawnedItem(self, mo, flags); // for an inventory item's use state
if (numret > 0) ret[0].SetInt(res);
if (numret > 1) ret[1].SetPointer(mo, ATAG_OBJECT);
if (numret > 1) ret[1].SetObject(mo);
return MIN(numret, 2);
}
@ -2787,7 +2787,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_SpawnItemEx)
PARAM_INT_DEF (chance)
PARAM_INT_DEF (tid)
if (numret > 1) ret[1].SetPointer(nullptr, ATAG_OBJECT);
if (numret > 1) ret[1].SetObject(nullptr);
if (missile == NULL)
{
@ -2852,7 +2852,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_SpawnItemEx)
mo->Angles.Yaw = angle;
}
if (numret > 0) ret[0].SetInt(res);
if (numret > 1) ret[1].SetPointer(mo, ATAG_OBJECT);
if (numret > 1) ret[1].SetObject(mo);
return MIN(numret, 2);
}
@ -2872,7 +2872,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_ThrowGrenade)
PARAM_FLOAT_DEF (zvel)
PARAM_BOOL_DEF (useammo)
if (numret > 1) ret[1].SetPointer(nullptr, ATAG_OBJECT);
if (numret > 1) ret[1].SetObject(nullptr);
if (missile == NULL)
{
@ -2934,7 +2934,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_ThrowGrenade)
if (!P_CheckMissileSpawn(bo, self->radius)) bo = nullptr;
if (numret > 0) ret[0].SetInt(true);
if (numret > 1) ret[1].SetPointer(bo, ATAG_OBJECT);
if (numret > 1) ret[1].SetObject(bo);
return MIN(numret, 2);
}
else
@ -4363,7 +4363,7 @@ DEFINE_ACTION_FUNCTION(AStateProvider, A_CheckForReload)
if (numret > 0)
{
ret->SetPointer(NULL, ATAG_STATE);
ret->SetPointer(NULL);
numret = 1;
}
@ -4381,7 +4381,7 @@ DEFINE_ACTION_FUNCTION(AStateProvider, A_CheckForReload)
// Go back to the refire frames, instead of continuing on to the reload frames.
if (numret != 0)
{
ret->SetPointer(jump, ATAG_STATE);
ret->SetPointer(jump);
}
}
else
@ -4903,7 +4903,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_Teleport)
}
if (numret > 0)
{
ret[0].SetPointer(NULL, ATAG_STATE);
ret[0].SetPointer(NULL);
}
if (!ref)
@ -5039,7 +5039,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_Teleport)
}
if (numret > 0)
{
ret[0].SetPointer(teleport_state, ATAG_STATE);
ret[0].SetPointer(teleport_state);
}
return numret;
}
@ -5337,7 +5337,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_Warp)
}
if (numret > 0)
{
ret[0].SetPointer(NULL, ATAG_STATE);
ret[0].SetPointer(NULL);
}
if ((flags & WARPF_USETID))
@ -5363,7 +5363,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_Warp)
// in this case, you have the statejump to help you handle all the success anyway.
if (numret > 0)
{
ret[0].SetPointer(success_state, ATAG_STATE);
ret[0].SetPointer(success_state);
}
}
else if (numret > 1)

View file

@ -2054,7 +2054,7 @@ DEFINE_ACTION_FUNCTION(AActor, TestMobjZ)
if (numret > 1)
{
numret = 2;
ret[1].SetPointer(on, ATAG_OBJECT);
ret[1].SetObject(on);
}
if (numret > 0)
{
@ -4685,7 +4685,7 @@ DEFINE_ACTION_FUNCTION(AActor, LineAttack)
int acdmg;
if (puffType == nullptr) puffType = PClass::FindActor("BulletPuff"); // P_LineAttack does not work without a puff to take info from.
auto puff = P_LineAttack(self, angle, distance, pitch, damage, damageType, puffType, flags, victim, &acdmg);
if (numret > 0) ret[0].SetPointer(puff, ATAG_OBJECT);
if (numret > 0) ret[0].SetObject(puff);
if (numret > 1) ret[1].SetInt(acdmg), numret = 2;
return numret;
}

View file

@ -7247,8 +7247,8 @@ DEFINE_ACTION_FUNCTION(AActor, SpawnPlayerMissile)
AActor *missileactor;
if (numparam == 2) angle = self->Angles.Yaw;
AActor *misl = P_SpawnPlayerMissile(self, x, y, z, type, angle, lt, &missileactor, nofreeaim, noautoaim, aimflags);
if (numret > 0) ret[0].SetPointer(misl, ATAG_OBJECT);
if (numret > 1) ret[1].SetPointer(missileactor, ATAG_OBJECT), numret = 2;
if (numret > 0) ret[0].SetObject(misl);
if (numret > 1) ret[1].SetObject(missileactor), numret = 2;
return numret;
}
@ -7695,7 +7695,7 @@ FDropItem *AActor::GetDropItems() const
DEFINE_ACTION_FUNCTION(AActor, GetDropItems)
{
PARAM_SELF_PROLOGUE(AActor);
ACTION_RETURN_OBJECT(self->GetDropItems());
ACTION_RETURN_POINTER(self->GetDropItems());
}
double AActor::GetGravity() const

View file

@ -112,7 +112,7 @@ DEFINE_ACTION_FUNCTION(_Sector, FindLowestFloorSurrounding)
vertex_t *v;
double h = self->FindLowestFloorSurrounding(&v);
if (numret > 0) ret[0].SetFloat(h);
if (numret > 1) ret[1].SetPointer(v, ATAG_GENERIC);
if (numret > 1) ret[1].SetPointer(v);
return numret;
}
@ -161,7 +161,7 @@ DEFINE_ACTION_FUNCTION(_Sector, FindHighestFloorSurrounding)
vertex_t *v;
double h = self->FindHighestFloorSurrounding(&v);
if (numret > 0) ret[0].SetFloat(h);
if (numret > 1) ret[1].SetPointer(v, ATAG_GENERIC);
if (numret > 1) ret[1].SetPointer(v);
return numret;
}
@ -224,7 +224,7 @@ DEFINE_ACTION_FUNCTION(_Sector, FindNextHighestFloor)
vertex_t *v;
double h = self->FindNextHighestFloor(&v);
if (numret > 0) ret[0].SetFloat(h);
if (numret > 1) ret[1].SetPointer(v, ATAG_GENERIC);
if (numret > 1) ret[1].SetPointer(v);
return numret;
}
@ -286,7 +286,7 @@ DEFINE_ACTION_FUNCTION(_Sector, FindNextLowestFloor)
vertex_t *v;
double h = self->FindNextLowestFloor(&v);
if (numret > 0) ret[0].SetFloat(h);
if (numret > 1) ret[1].SetPointer(v, ATAG_GENERIC);
if (numret > 1) ret[1].SetPointer(v);
return numret;
}
@ -348,7 +348,7 @@ DEFINE_ACTION_FUNCTION(_Sector, FindNextLowestCeiling)
vertex_t *v;
double h = self->FindNextLowestCeiling(&v);
if (numret > 0) ret[0].SetFloat(h);
if (numret > 1) ret[1].SetPointer(v, ATAG_GENERIC);
if (numret > 1) ret[1].SetPointer(v);
return numret;
}
@ -411,7 +411,7 @@ DEFINE_ACTION_FUNCTION(_Sector, FindNextHighestCeiling)
vertex_t *v;
double h = self->FindNextHighestCeiling(&v);
if (numret > 0) ret[0].SetFloat(h);
if (numret > 1) ret[1].SetPointer(v, ATAG_GENERIC);
if (numret > 1) ret[1].SetPointer(v);
return numret;
}
@ -459,7 +459,7 @@ DEFINE_ACTION_FUNCTION(_Sector, FindLowestCeilingSurrounding)
vertex_t *v;
double h = self->FindLowestCeilingSurrounding(&v);
if (numret > 0) ret[0].SetFloat(h);
if (numret > 1) ret[1].SetPointer(v, ATAG_GENERIC);
if (numret > 1) ret[1].SetPointer(v);
return numret;
}
@ -508,7 +508,7 @@ DEFINE_ACTION_FUNCTION(_Sector, FindHighestCeilingSurrounding)
vertex_t *v;
double h = self->FindHighestCeilingSurrounding(&v);
if (numret > 0) ret[0].SetFloat(h);
if (numret > 1) ret[1].SetPointer(v, ATAG_GENERIC);
if (numret > 1) ret[1].SetPointer(v);
return numret;
}
@ -744,7 +744,7 @@ DEFINE_ACTION_FUNCTION(_Sector, FindHighestFloorPoint)
vertex_t *v;
double h = self->FindHighestFloorPoint(&v);
if (numret > 0) ret[0].SetFloat(h);
if (numret > 1) ret[1].SetPointer(v, ATAG_GENERIC);
if (numret > 1) ret[1].SetPointer(v);
return numret;
}
@ -793,7 +793,7 @@ DEFINE_ACTION_FUNCTION(_Sector, FindLowestCeilingPoint)
vertex_t *v;
double h = self->FindLowestCeilingPoint(&v);
if (numret > 0) ret[0].SetFloat(h);
if (numret > 1) ret[1].SetPointer(v, ATAG_GENERIC);
if (numret > 1) ret[1].SetPointer(v);
return numret;
}
@ -1207,7 +1207,7 @@ DEFINE_ACTION_FUNCTION(_Sector, HighestCeilingAt)
sector_t *s;
double h = self->HighestCeilingAt(DVector2(x, y), &s);
if (numret > 0) ret[0].SetFloat(h);
if (numret > 1) ret[1].SetPointer(s, ATAG_GENERIC);
if (numret > 1) ret[1].SetPointer(s);
return numret;
}
@ -1242,7 +1242,7 @@ DEFINE_ACTION_FUNCTION(_Sector, LowestFloorAt)
sector_t *s;
double h = self->LowestFloorAt(DVector2(x, y), &s);
if (numret > 0) ret[0].SetFloat(h);
if (numret > 1) ret[1].SetPointer(s, ATAG_GENERIC);
if (numret > 1) ret[1].SetPointer(s);
return numret;
}
@ -1309,12 +1309,12 @@ DEFINE_ACTION_FUNCTION(_Sector, NextHighestCeilingAt)
if (numret > 2)
{
ret[2].SetPointer(resultff, ATAG_GENERIC);
ret[2].SetPointer(resultff);
numret = 3;
}
if (numret > 1)
{
ret[1].SetPointer(resultsec, ATAG_GENERIC);
ret[1].SetPointer(resultsec);
}
if (numret > 0)
{
@ -1387,12 +1387,12 @@ DEFINE_ACTION_FUNCTION(_Sector, NextLowestFloorAt)
if (numret > 2)
{
ret[2].SetPointer(resultff, ATAG_GENERIC);
ret[2].SetPointer(resultff);
numret = 3;
}
if (numret > 1)
{
ret[1].SetPointer(resultsec, ATAG_GENERIC);
ret[1].SetPointer(resultsec);
}
if (numret > 0)
{

View file

@ -505,12 +505,13 @@ private:
{
// Load bgcolor
uint32_t desttmp[2];
if (mask0 & (1 << 31)) desttmp[0] = dest[x * 2];
if (mask0 & (1 << 30)) desttmp[1] = dest[x * 2 + 1];
__m128i bgcolor;
if (BlendT::Mode != (int)BlendModes::Opaque)
{
if (mask0 & (1 << 31)) desttmp[0] = dest[x * 2];
if (mask0 & (1 << 30)) desttmp[1] = dest[x * 2 + 1];
bgcolor = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)desttmp), _mm_setzero_si128());
}
else
bgcolor = _mm_setzero_si128();
@ -593,12 +594,13 @@ private:
{
// Load bgcolor
uint32_t desttmp[2];
if (mask1 & (1 << 31)) desttmp[0] = dest[x * 2];
if (mask1 & (1 << 30)) desttmp[1] = dest[x * 2 + 1];
__m128i bgcolor;
if (BlendT::Mode != (int)BlendModes::Opaque)
{
if (mask1 & (1 << 31)) desttmp[0] = dest[x * 2];
if (mask1 & (1 << 30)) desttmp[1] = dest[x * 2 + 1];
bgcolor = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)desttmp), _mm_setzero_si128());
}
else
bgcolor = _mm_setzero_si128();

View file

@ -249,7 +249,7 @@ void RenderPolyPlane::Render(const TriMatrix &worldToClip, const PolyClipPlane &
}
if (!polyportal)
{
sectorPortals.push_back(std::make_unique<PolyDrawSectorPortal>(portal, ceiling));
sectorPortals.push_back(std::unique_ptr<PolyDrawSectorPortal>(new PolyDrawSectorPortal(portal, ceiling)));
polyportal = sectorPortals.back().get();
}

View file

@ -44,7 +44,7 @@ bool RenderPolyWall::RenderLine(const TriMatrix &worldToClip, const PolyClipPlan
{
if (PolyRenderer::Instance()->InsertSeenMirror(line->linedef))
{
linePortals.push_back(std::make_unique<PolyDrawLinePortal>(line->linedef));
linePortals.push_back(std::unique_ptr<PolyDrawLinePortal>(new PolyDrawLinePortal(line->linedef)));
polyportal = linePortals.back().get();
}
}
@ -63,7 +63,7 @@ bool RenderPolyWall::RenderLine(const TriMatrix &worldToClip, const PolyClipPlan
}
if (!polyportal)
{
linePortals.push_back(std::make_unique<PolyDrawLinePortal>(portal));
linePortals.push_back(std::unique_ptr<PolyDrawLinePortal>(new PolyDrawLinePortal(portal)));
polyportal = linePortals.back().get();
}
}

View file

@ -385,7 +385,7 @@ void FxExpression::EmitCompare(VMFunctionBuilder *build, bool invert, TArray<siz
break;
case REGT_POINTER:
build->Emit(OP_EQA_K, !invert, op.RegNum, build->GetConstantAddress(0, ATAG_GENERIC));
build->Emit(OP_EQA_K, !invert, op.RegNum, build->GetConstantAddress(0));
break;
case REGT_STRING:
@ -587,16 +587,7 @@ ExpEmit FxConstant::Emit(VMFunctionBuilder *build)
}
else if (regtype == REGT_POINTER)
{
VM_ATAG tag = ATAG_GENERIC;
if (value.Type == TypeState)
{
tag = ATAG_STATE;
}
else if (value.Type->GetLoadOp() != OP_LP)
{
tag = ATAG_OBJECT;
}
out.RegNum = build->GetConstantAddress(value.pointer, tag);
out.RegNum = build->GetConstantAddress(value.pointer);
}
else if (regtype == REGT_STRING)
{
@ -2998,7 +2989,7 @@ texcheck:
auto * countptr = &ptr->Count;
ExpEmit bndp(build, REGT_POINTER);
ExpEmit bndc(build, REGT_INT);
build->Emit(OP_LKP, bndp.RegNum, build->GetConstantAddress(countptr, ATAG_GENERIC));
build->Emit(OP_LKP, bndp.RegNum, build->GetConstantAddress(countptr));
build->Emit(OP_LW, bndc.RegNum, bndp.RegNum, build->GetConstantInt(0));
build->Emit(OP_BOUND_R, to.RegNum, bndc.RegNum);
bndp.Free(build);
@ -4638,7 +4629,7 @@ void FxTypeCheck::EmitCompare(VMFunctionBuilder *build, bool invert, TArray<size
{
ExpEmit ares = EmitCommon(build);
ares.Free(build);
build->Emit(OP_EQA_K, !invert, ares.RegNum, build->GetConstantAddress(nullptr, ATAG_OBJECT));
build->Emit(OP_EQA_K, !invert, ares.RegNum, build->GetConstantAddress(nullptr));
patchspots_no.Push(build->Emit(OP_JMP, 0));
}
@ -4706,7 +4697,7 @@ ExpEmit FxDynamicCast::Emit(VMFunctionBuilder *build)
ExpEmit castee = expr->Emit(build);
castee.Free(build);
ExpEmit ares(build, REGT_POINTER);
build->Emit(OP_DYNCAST_K, ares.RegNum, castee.RegNum, build->GetConstantAddress(CastType, ATAG_OBJECT));
build->Emit(OP_DYNCAST_K, ares.RegNum, castee.RegNum, build->GetConstantAddress(CastType));
return ares;
}
@ -5536,16 +5527,16 @@ ExpEmit FxRandom::Emit(VMFunctionBuilder *build)
if (build->FramePointer.Fixed) EmitTail = false; // do not tail call if the stack is in use
int opcode = (EmitTail ? OP_TAIL_K : OP_CALL_K);
build->Emit(OP_PARAM, 0, REGT_POINTER | REGT_KONST, build->GetConstantAddress(rng, ATAG_RNG));
build->Emit(OP_PARAM, 0, REGT_POINTER | REGT_KONST, build->GetConstantAddress(rng));
if (min != nullptr && max != nullptr)
{
EmitParameter(build, min, ScriptPosition);
EmitParameter(build, max, ScriptPosition);
build->Emit(opcode, build->GetConstantAddress(callfunc, ATAG_OBJECT), 3, 1);
build->Emit(opcode, build->GetConstantAddress(callfunc), 3, 1);
}
else
{
build->Emit(opcode, build->GetConstantAddress(callfunc, ATAG_OBJECT), 1, 1);
build->Emit(opcode, build->GetConstantAddress(callfunc), 1, 1);
}
if (EmitTail)
@ -5657,10 +5648,10 @@ ExpEmit FxRandomPick::Emit(VMFunctionBuilder *build)
assert(((PSymbolVMFunction *)sym)->Function != nullptr);
callfunc = ((PSymbolVMFunction *)sym)->Function;
build->Emit(OP_PARAM, 0, REGT_POINTER | REGT_KONST, build->GetConstantAddress(rng, ATAG_RNG));
build->Emit(OP_PARAM, 0, REGT_POINTER | REGT_KONST, build->GetConstantAddress(rng));
build->EmitParamInt(0);
build->EmitParamInt(choices.Size() - 1);
build->Emit(OP_CALL_K, build->GetConstantAddress(callfunc, ATAG_OBJECT), 3, 1);
build->Emit(OP_CALL_K, build->GetConstantAddress(callfunc), 3, 1);
ExpEmit resultreg(build, REGT_INT);
build->Emit(OP_RESULT, 0, REGT_INT, resultreg.RegNum);
@ -5787,16 +5778,16 @@ ExpEmit FxFRandom::Emit(VMFunctionBuilder *build)
if (build->FramePointer.Fixed) EmitTail = false; // do not tail call if the stack is in use
int opcode = (EmitTail ? OP_TAIL_K : OP_CALL_K);
build->Emit(OP_PARAM, 0, REGT_POINTER | REGT_KONST, build->GetConstantAddress(rng, ATAG_RNG));
build->Emit(OP_PARAM, 0, REGT_POINTER | REGT_KONST, build->GetConstantAddress(rng));
if (min != nullptr && max != nullptr)
{
EmitParameter(build, min, ScriptPosition);
EmitParameter(build, max, ScriptPosition);
build->Emit(opcode, build->GetConstantAddress(callfunc, ATAG_OBJECT), 3, 1);
build->Emit(opcode, build->GetConstantAddress(callfunc), 3, 1);
}
else
{
build->Emit(opcode, build->GetConstantAddress(callfunc, ATAG_OBJECT), 1, 1);
build->Emit(opcode, build->GetConstantAddress(callfunc), 1, 1);
}
if (EmitTail)
@ -5882,9 +5873,9 @@ ExpEmit FxRandom2::Emit(VMFunctionBuilder *build)
if (build->FramePointer.Fixed) EmitTail = false; // do not tail call if the stack is in use
int opcode = (EmitTail ? OP_TAIL_K : OP_CALL_K);
build->Emit(OP_PARAM, 0, REGT_POINTER | REGT_KONST, build->GetConstantAddress(rng, ATAG_RNG));
build->Emit(OP_PARAM, 0, REGT_POINTER | REGT_KONST, build->GetConstantAddress(rng));
EmitParameter(build, mask, ScriptPosition);
build->Emit(opcode, build->GetConstantAddress(callfunc, ATAG_OBJECT), 2, 1);
build->Emit(opcode, build->GetConstantAddress(callfunc), 2, 1);
if (EmitTail)
{
@ -6661,7 +6652,7 @@ ExpEmit FxGlobalVariable::Emit(VMFunctionBuilder *build)
{
ExpEmit obj(build, REGT_POINTER);
build->Emit(OP_LKP, obj.RegNum, build->GetConstantAddress((void*)(intptr_t)membervar->Offset, ATAG_GENERIC));
build->Emit(OP_LKP, obj.RegNum, build->GetConstantAddress((void*)(intptr_t)membervar->Offset));
if (AddressRequested)
{
return obj;
@ -6744,34 +6735,34 @@ ExpEmit FxCVar::Emit(VMFunctionBuilder *build)
switch (CVar->GetRealType())
{
case CVAR_Int:
build->Emit(OP_LKP, addr.RegNum, build->GetConstantAddress(&static_cast<FIntCVar *>(CVar)->Value, ATAG_GENERIC));
build->Emit(OP_LKP, addr.RegNum, build->GetConstantAddress(&static_cast<FIntCVar *>(CVar)->Value));
build->Emit(OP_LW, dest.RegNum, addr.RegNum, nul);
break;
case CVAR_Color:
build->Emit(OP_LKP, addr.RegNum, build->GetConstantAddress(&static_cast<FColorCVar *>(CVar)->Value, ATAG_GENERIC));
build->Emit(OP_LKP, addr.RegNum, build->GetConstantAddress(&static_cast<FColorCVar *>(CVar)->Value));
build->Emit(OP_LW, dest.RegNum, addr.RegNum, nul);
break;
case CVAR_Float:
build->Emit(OP_LKP, addr.RegNum, build->GetConstantAddress(&static_cast<FFloatCVar *>(CVar)->Value, ATAG_GENERIC));
build->Emit(OP_LKP, addr.RegNum, build->GetConstantAddress(&static_cast<FFloatCVar *>(CVar)->Value));
build->Emit(OP_LSP, dest.RegNum, addr.RegNum, nul);
break;
case CVAR_Bool:
build->Emit(OP_LKP, addr.RegNum, build->GetConstantAddress(&static_cast<FBoolCVar *>(CVar)->Value, ATAG_GENERIC));
build->Emit(OP_LKP, addr.RegNum, build->GetConstantAddress(&static_cast<FBoolCVar *>(CVar)->Value));
build->Emit(OP_LBU, dest.RegNum, addr.RegNum, nul);
break;
case CVAR_String:
build->Emit(OP_LKP, addr.RegNum, build->GetConstantAddress(&static_cast<FStringCVar *>(CVar)->Value, ATAG_GENERIC));
build->Emit(OP_LKP, addr.RegNum, build->GetConstantAddress(&static_cast<FStringCVar *>(CVar)->Value));
build->Emit(OP_LCS, dest.RegNum, addr.RegNum, nul);
break;
case CVAR_DummyBool:
{
auto cv = static_cast<FFlagCVar *>(CVar);
build->Emit(OP_LKP, addr.RegNum, build->GetConstantAddress(&cv->ValueVar.Value, ATAG_GENERIC));
build->Emit(OP_LKP, addr.RegNum, build->GetConstantAddress(&cv->ValueVar.Value));
build->Emit(OP_LW, dest.RegNum, addr.RegNum, nul);
build->Emit(OP_SRL_RI, dest.RegNum, dest.RegNum, cv->BitNum);
build->Emit(OP_AND_RK, dest.RegNum, dest.RegNum, build->GetConstantInt(1));
@ -6781,7 +6772,7 @@ ExpEmit FxCVar::Emit(VMFunctionBuilder *build)
case CVAR_DummyInt:
{
auto cv = static_cast<FMaskCVar *>(CVar);
build->Emit(OP_LKP, addr.RegNum, build->GetConstantAddress(&cv->ValueVar.Value, ATAG_GENERIC));
build->Emit(OP_LKP, addr.RegNum, build->GetConstantAddress(&cv->ValueVar.Value));
build->Emit(OP_LW, dest.RegNum, addr.RegNum, nul);
build->Emit(OP_AND_RK, dest.RegNum, dest.RegNum, build->GetConstantInt(cv->BitVal));
build->Emit(OP_SRL_RI, dest.RegNum, dest.RegNum, cv->BitNum);
@ -6923,13 +6914,13 @@ FxStructMember::~FxStructMember()
bool FxStructMember::RequestAddress(FCompileContext &ctx, bool *writable)
{
// Cannot take the address of metadata variables.
AddressRequested = true;
if (membervar->Flags & VARF_Meta)
{
return false;
// Meta variables are read only.
*writable = false;
}
AddressRequested = true;
if (writable != nullptr)
else if (writable != nullptr)
{
// [ZZ] original check.
bool bWritable = (AddressWritable && !ctx.CheckWritable(membervar->Flags) &&
@ -7323,11 +7314,13 @@ ExpEmit FxArrayElement::Emit(VMFunctionBuilder *build)
if (SizeAddr != ~0u)
{
bool ismeta = Array->ExprType == EFX_ClassMember && static_cast<FxClassMember*>(Array)->membervar->Flags & VARF_Meta;
arrayvar.Free(build);
start = ExpEmit(build, REGT_POINTER);
build->Emit(OP_LP, start.RegNum, arrayvar.RegNum, build->GetConstantInt(0));
auto f = new PField(NAME_None, TypeUInt32, 0, SizeAddr);
auto f = new PField(NAME_None, TypeUInt32, ismeta? VARF_Meta : 0, SizeAddr);
static_cast<FxMemberBase *>(Array)->membervar = f;
static_cast<FxMemberBase *>(Array)->AddressRequested = false;
Array->ValueType = TypeUInt32;
@ -8544,14 +8537,14 @@ ExpEmit FxActionSpecialCall::Emit(VMFunctionBuilder *build)
if (build->FramePointer.Fixed) EmitTail = false; // do not tail call if the stack is in use
if (EmitTail)
{
build->Emit(OP_TAIL_K, build->GetConstantAddress(callfunc, ATAG_OBJECT), 2 + i, 0);
build->Emit(OP_TAIL_K, build->GetConstantAddress(callfunc), 2 + i, 0);
ExpEmit call;
call.Final = true;
return call;
}
ExpEmit dest(build, REGT_INT);
build->Emit(OP_CALL_K, build->GetConstantAddress(callfunc, ATAG_OBJECT), 2 + i, 1);
build->Emit(OP_CALL_K, build->GetConstantAddress(callfunc), 2 + i, 1);
build->Emit(OP_RESULT, 0, REGT_INT, dest.RegNum);
return dest;
}
@ -8941,7 +8934,7 @@ ExpEmit FxVMFunctionCall::Emit(VMFunctionBuilder *build)
if (selfside == FScopeBarrier::Side_PlainData)
{
// Check the self object against the calling function's flags at run time
build->Emit(OP_SCOPE, selfemit.RegNum, outerside + 1, build->GetConstantAddress(vmfunc, ATAG_OBJECT));
build->Emit(OP_SCOPE, selfemit.RegNum, outerside + 1, build->GetConstantAddress(vmfunc));
}
}
@ -8967,7 +8960,7 @@ ExpEmit FxVMFunctionCall::Emit(VMFunctionBuilder *build)
{
// pass self as stateowner, otherwise all attempts of the subfunction to retrieve a state from a name would fail.
build->Emit(OP_PARAM, 0, selfemit.RegType, selfemit.RegNum);
build->Emit(OP_PARAM, 0, REGT_POINTER | REGT_KONST, build->GetConstantAddress(nullptr, ATAG_GENERIC));
build->Emit(OP_PARAM, 0, REGT_POINTER | REGT_KONST, build->GetConstantAddress(nullptr));
}
count += 2;
}
@ -8985,7 +8978,7 @@ ExpEmit FxVMFunctionCall::Emit(VMFunctionBuilder *build)
// Get a constant register for this function
if (staticcall)
{
int funcaddr = build->GetConstantAddress(vmfunc, ATAG_OBJECT);
int funcaddr = build->GetConstantAddress(vmfunc);
// Emit the call
if (EmitTail)
{ // Tail call
@ -10503,7 +10496,7 @@ ExpEmit FxReturnStatement::Emit(VMFunctionBuilder *build)
ExpEmit reg(build, REGT_POINTER);
build->Emit(OP_ADDA_RK, reg.RegNum, build->FramePointer.RegNum, build->GetConstantInt(build->ConstructedStructs[i]->StackOffset));
build->Emit(OP_PARAM, 0, reg.RegType, reg.RegNum);
build->Emit(OP_CALL_K, build->GetConstantAddress(pstr->mDestructor, ATAG_OBJECT), 1, 0);
build->Emit(OP_CALL_K, build->GetConstantAddress(pstr->mDestructor), 1, 0);
reg.Free(build);
}
@ -10690,9 +10683,9 @@ int BuiltinNameToClass(VMValue *param, TArray<VMValue> &defaultparam, int numpar
// Let the caller check this. Making this an error with a message is only taking away options from the user.
cls = nullptr;
}
ret->SetPointer(const_cast<PClass *>(cls), ATAG_OBJECT);
ret->SetObject(const_cast<PClass *>(cls));
}
else ret->SetPointer(nullptr, ATAG_OBJECT);
else ret->SetObject(nullptr);
return 1;
}
@ -10700,13 +10693,13 @@ ExpEmit FxClassTypeCast::Emit(VMFunctionBuilder *build)
{
if (basex->ValueType != TypeName)
{
return ExpEmit(build->GetConstantAddress(nullptr, ATAG_OBJECT), REGT_POINTER, true);
return ExpEmit(build->GetConstantAddress(nullptr), REGT_POINTER, true);
}
ExpEmit clsname = basex->Emit(build);
assert(!clsname.Konst);
ExpEmit dest(build, REGT_POINTER);
build->Emit(OP_PARAM, 0, clsname.RegType, clsname.RegNum);
build->Emit(OP_PARAM, 0, REGT_POINTER | REGT_KONST, build->GetConstantAddress(const_cast<PClass *>(desttype), ATAG_OBJECT));
build->Emit(OP_PARAM, 0, REGT_POINTER | REGT_KONST, build->GetConstantAddress(const_cast<PClass *>(desttype)));
// Call the BuiltinNameToClass function to convert from 'name' to class.
VMFunction *callfunc;
@ -10716,7 +10709,7 @@ ExpEmit FxClassTypeCast::Emit(VMFunctionBuilder *build)
assert(((PSymbolVMFunction *)sym)->Function != nullptr);
callfunc = ((PSymbolVMFunction *)sym)->Function;
build->Emit(OP_CALL_K, build->GetConstantAddress(callfunc, ATAG_OBJECT), 2, 1);
build->Emit(OP_CALL_K, build->GetConstantAddress(callfunc), 2, 1);
build->Emit(OP_RESULT, 0, REGT_POINTER, dest.RegNum);
clsname.Free(build);
return dest;
@ -10815,7 +10808,7 @@ ExpEmit FxClassPtrCast::Emit(VMFunctionBuilder *build)
ExpEmit clsname = basex->Emit(build);
build->Emit(OP_PARAM, 0, clsname.RegType, clsname.RegNum);
build->Emit(OP_PARAM, 0, REGT_POINTER | REGT_KONST, build->GetConstantAddress(desttype, ATAG_OBJECT));
build->Emit(OP_PARAM, 0, REGT_POINTER | REGT_KONST, build->GetConstantAddress(desttype));
VMFunction *callfunc;
PSymbol *sym = FindBuiltinFunction(NAME_BuiltinClassCast, BuiltinClassCast);
@ -10825,7 +10818,7 @@ ExpEmit FxClassPtrCast::Emit(VMFunctionBuilder *build)
callfunc = ((PSymbolVMFunction *)sym)->Function;
clsname.Free(build);
ExpEmit dest(build, REGT_POINTER);
build->Emit(OP_CALL_K, build->GetConstantAddress(callfunc, ATAG_OBJECT), 2, 1);
build->Emit(OP_CALL_K, build->GetConstantAddress(callfunc), 2, 1);
build->Emit(OP_RESULT, 0, REGT_POINTER, dest.RegNum);
return dest;
}
@ -11164,7 +11157,7 @@ ExpEmit FxLocalVariableDeclaration::Emit(VMFunctionBuilder *build)
case REGT_POINTER:
{
build->Emit(OP_LKP, RegNum, build->GetConstantAddress(constval->GetValue().GetPointer(), ValueType->GetLoadOp() != OP_LP ? ATAG_OBJECT : ATAG_GENERIC));
build->Emit(OP_LKP, RegNum, build->GetConstantAddress(constval->GetValue().GetPointer()));
break;
}
case REGT_STRING:
@ -11196,7 +11189,7 @@ ExpEmit FxLocalVariableDeclaration::Emit(VMFunctionBuilder *build)
ExpEmit reg(build, REGT_POINTER);
build->Emit(OP_ADDA_RK, reg.RegNum, build->FramePointer.RegNum, build->GetConstantInt(StackOffset));
build->Emit(OP_PARAM, 0, reg.RegType, reg.RegNum);
build->Emit(OP_CALL_K, build->GetConstantAddress(pstr->mConstructor, ATAG_OBJECT), 1, 0);
build->Emit(OP_CALL_K, build->GetConstantAddress(pstr->mConstructor), 1, 0);
reg.Free(build);
}
if (pstr->mDestructor != nullptr) build->ConstructedStructs.Push(this);
@ -11222,7 +11215,7 @@ void FxLocalVariableDeclaration::Release(VMFunctionBuilder *build)
ExpEmit reg(build, REGT_POINTER);
build->Emit(OP_ADDA_RK, reg.RegNum, build->FramePointer.RegNum, build->GetConstantInt(StackOffset));
build->Emit(OP_PARAM, 0, reg.RegType, reg.RegNum);
build->Emit(OP_CALL_K, build->GetConstantAddress(pstr->mDestructor, ATAG_OBJECT), 1, 0);
build->Emit(OP_CALL_K, build->GetConstantAddress(pstr->mDestructor), 1, 0);
reg.Free(build);
}
build->ConstructedStructs.Delete(build->ConstructedStructs.Find(this));
@ -11304,7 +11297,7 @@ ExpEmit FxStaticArray::Emit(VMFunctionBuilder *build)
{
TArray<void*> cvalues;
for (auto v : values) cvalues.Push(static_cast<FxConstant *>(v)->GetValue().GetPointer());
StackOffset = build->AllocConstantsAddress(cvalues.Size(), &cvalues[0], ElementType->GetLoadOp() != OP_LP ? ATAG_OBJECT : ATAG_GENERIC);
StackOffset = build->AllocConstantsAddress(cvalues.Size(), &cvalues[0]);
break;
}
}

View file

@ -126,7 +126,7 @@ void VMFunctionBuilder::MakeFunction(VMScriptFunction *func)
}
if (AddressConstantList.Size() > 0)
{
FillAddressConstants(func->KonstA, func->KonstATags());
FillAddressConstants(func->KonstA);
}
if (StringConstantList.Size() > 0)
{
@ -175,10 +175,9 @@ void VMFunctionBuilder::FillFloatConstants(double *konst)
//
//==========================================================================
void VMFunctionBuilder::FillAddressConstants(FVoidObj *konst, VM_ATAG *tags)
void VMFunctionBuilder::FillAddressConstants(FVoidObj *konst)
{
memcpy(konst, &AddressConstantList[0], sizeof(void*) * AddressConstantList.Size());
memcpy(tags, &AtagConstantList[0], sizeof(VM_ATAG) * AtagConstantList.Size());
}
//==========================================================================
@ -258,7 +257,7 @@ unsigned VMFunctionBuilder::GetConstantString(FString val)
}
else
{
int loc = StringConstantList.Push(val);
unsigned loc = StringConstantList.Push(val);
StringConstantMap.Insert(val, loc);
return loc;
}
@ -273,27 +272,18 @@ unsigned VMFunctionBuilder::GetConstantString(FString val)
//
//==========================================================================
unsigned VMFunctionBuilder::GetConstantAddress(void *ptr, VM_ATAG tag)
unsigned VMFunctionBuilder::GetConstantAddress(void *ptr)
{
if (ptr == NULL)
{ // Make all NULL pointers generic. (Or should we allow typed NULLs?)
tag = ATAG_GENERIC;
}
AddrKonst *locp = AddressConstantMap.CheckKey(ptr);
unsigned *locp = AddressConstantMap.CheckKey(ptr);
if (locp != NULL)
{
// There should only be one tag associated with a memory location. Exceptions are made for null pointers that got allocated through constant arrays.
assert(ptr == nullptr || locp->Tag == tag);
return locp->KonstNum;
return *locp;
}
else
{
unsigned locc = AddressConstantList.Push(ptr);
AtagConstantList.Push(tag);
AddrKonst loc = { locc, tag };
unsigned loc = AddressConstantList.Push(ptr);
AddressConstantMap.Insert(ptr, loc);
return loc.KonstNum;
return loc;
}
}
@ -327,16 +317,13 @@ unsigned VMFunctionBuilder::AllocConstantsFloat(unsigned count, double *values)
return addr;
}
unsigned VMFunctionBuilder::AllocConstantsAddress(unsigned count, void **ptrs, VM_ATAG tag)
unsigned VMFunctionBuilder::AllocConstantsAddress(unsigned count, void **ptrs)
{
unsigned addr = AddressConstantList.Reserve(count);
AtagConstantList.Reserve(count);
memcpy(&AddressConstantList[addr], ptrs, count * sizeof(void *));
for (unsigned i = 0; i < count; i++)
{
AtagConstantList[addr + i] = tag;
AddrKonst loc = { addr+i, tag };
AddressConstantMap.Insert(ptrs[i], loc);
AddressConstantMap.Insert(ptrs[i], addr+i);
}
return addr;
}

View file

@ -51,12 +51,12 @@ public:
// Returns the constant register holding the value.
unsigned GetConstantInt(int val);
unsigned GetConstantFloat(double val);
unsigned GetConstantAddress(void *ptr, VM_ATAG tag);
unsigned GetConstantAddress(void *ptr);
unsigned GetConstantString(FString str);
unsigned AllocConstantsInt(unsigned int count, int *values);
unsigned AllocConstantsFloat(unsigned int count, double *values);
unsigned AllocConstantsAddress(unsigned int count, void **ptrs, VM_ATAG tag);
unsigned AllocConstantsAddress(unsigned int count, void **ptrs);
unsigned AllocConstantsString(unsigned int count, FString *ptrs);
@ -79,7 +79,7 @@ public:
// Write out complete constant tables.
void FillIntConstants(int *konst);
void FillFloatConstants(double *konst);
void FillAddressConstants(FVoidObj *konst, VM_ATAG *tags);
void FillAddressConstants(FVoidObj *konst);
void FillStringConstants(FString *strings);
// PARAM increases ActiveParam; CALL decreases it.
@ -96,24 +96,17 @@ public:
TArray<FxLocalVariableDeclaration *> ConstructedStructs;
private:
struct AddrKonst
{
unsigned KonstNum;
VM_ATAG Tag;
};
TArray<FStatementInfo> LineNumbers;
TArray<FxExpression *> StatementStack;
TArray<int> IntConstantList;
TArray<double> FloatConstantList;
TArray<void *> AddressConstantList;
TArray<VM_ATAG> AtagConstantList;
TArray<FString> StringConstantList;
// These map from the constant value to its position in the constant table.
TMap<int, unsigned> IntConstantMap;
TMap<double, unsigned> FloatConstantMap;
TMap<void *, AddrKonst> AddressConstantMap;
TMap<void *, unsigned> AddressConstantMap;
TMap<FString, unsigned> StringConstantMap;
int MaxParam;

View file

@ -243,7 +243,7 @@ void VMDumpConstants(FILE *out, const VMScriptFunction *func)
{
for (j = 0, k = i; j < 4 && k < func->NumKonstA; j++, k += kk)
{
mysnprintf(tmp, countof(tmp), "%3d. %p:%d", k, func->KonstA[k].v, func->KonstATags()[k]);
mysnprintf(tmp, countof(tmp), "%3d. %p", k, func->KonstA[k].v);
printf_wrapper(out, "%-22s", tmp);
}
printf_wrapper(out, "\n");
@ -320,7 +320,7 @@ void VMDisasm(FILE *out, const VMOP *code, int codesize, const VMScriptFunction
switch (code[i].op)
{
case OP_JMP:
case OP_TRY:
//case OP_TRY:
col = printf_wrapper(out, "%08x", (i + 1 + code[i].i24) << 2);
break;
@ -498,7 +498,7 @@ void VMDisasm(FILE *out, const VMOP *code, int codesize, const VMScriptFunction
col = 30;
}
printf_wrapper(out, "%*c", 30 - col, ';');
if (!cmp && (code[i].op == OP_JMP || code[i].op == OP_TRY || code[i].op == OP_PARAMI))
if (!cmp && (code[i].op == OP_JMP || /*code[i].op == OP_TRY ||*/ code[i].op == OP_PARAMI))
{
printf_wrapper(out, "%d\n", code[i].i24);
}

View file

@ -1090,12 +1090,14 @@ DEFINE_PROPERTY(distancecheck, S, Actor)
//==========================================================================
DEFINE_CLASS_PROPERTY(restrictedto, Ssssssssssssssssssss, Inventory)
{
static_cast<PClassActor*>(info)->RestrictedToPlayerClass.Clear();
auto restrictarray = (TArray<PClassActor*>*)defaults->ScriptVar(NAME_RestrictedToPlayerClass, nullptr);
restrictarray->Clear();
for(int i = 0;i < PROP_PARM_COUNT;++i)
{
PROP_STRING_PARM(n, i);
if (*n != 0)
static_cast<PClassActor*>(info)->RestrictedToPlayerClass.Push(FindClassTentative(n, RUNTIME_CLASS(APlayerPawn)));
restrictarray->Push(FindClassTentative(n, RUNTIME_CLASS(APlayerPawn)));
}
}
@ -1104,12 +1106,14 @@ DEFINE_CLASS_PROPERTY(restrictedto, Ssssssssssssssssssss, Inventory)
//==========================================================================
DEFINE_CLASS_PROPERTY(forbiddento, Ssssssssssssssssssss, Inventory)
{
static_cast<PClassActor*>(info)->ForbiddenToPlayerClass.Clear();
auto forbidarray = (TArray<PClassActor*>*)defaults->ScriptVar(NAME_ForbiddenToPlayerClass, nullptr);
forbidarray->Clear();
for(int i = 0;i < PROP_PARM_COUNT;++i)
{
PROP_STRING_PARM(n, i);
if (*n != 0)
static_cast<PClassActor*>(info)->ForbiddenToPlayerClass.Push(FindClassTentative(n, RUNTIME_CLASS(APlayerPawn)));
forbidarray->Push(FindClassTentative(n, RUNTIME_CLASS(APlayerPawn)));
}
}

View file

@ -23,7 +23,6 @@ typedef unsigned short VM_UHALF;
typedef signed short VM_SHALF;
typedef unsigned int VM_UWORD;
typedef signed int VM_SWORD;
typedef VM_UBYTE VM_ATAG;
#define VM_EPSILON (1/65536.0)
@ -176,27 +175,6 @@ enum
#define RET_FINAL (0x80) // Used with RET and RETI in the destination slot: this is the final return value
// Tags for address registers
enum
{
ATAG_GENERIC, // pointer to something; we don't care what
ATAG_OBJECT, // pointer to an object; will be followed by GC
// The following are all for documentation during debugging and are
// functionally no different than ATAG_GENERIC (meaning they are useless because they trigger asserts all over the place.)
/*
ATAG_FRAMEPOINTER, // pointer to extra stack frame space for this function
ATAG_DREGISTER, // pointer to a data register
ATAG_FREGISTER, // pointer to a float register
ATAG_SREGISTER, // pointer to a string register
ATAG_AREGISTER, // pointer to an address register
*/
ATAG_RNG, // pointer to FRandom
ATAG_STATE = ATAG_GENERIC, // pointer to FState (cannot have its own type because there's no means to track inside the VM.)
};
enum EVMAbortException
{
X_OTHER,
@ -322,7 +300,6 @@ extern const VMOpInfo OpInfo[NUM_OPS];
struct VMReturn
{
void *Location;
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
void SetInt(int val)
@ -366,38 +343,37 @@ struct VMReturn
assert(RegType == REGT_STRING);
*(FString *)Location = val;
}
void SetPointer(void *val, int tag)
void SetPointer(void *val)
{
assert(RegType == REGT_POINTER);
*(void **)Location = val;
}
void SetObject(DObject *val)
{
assert(RegType == REGT_POINTER);
*(void **)Location = val;
if (TagOfs != 0)
{
*((VM_ATAG *)Location + TagOfs) = tag;
}
}
void IntAt(int *loc)
{
Location = loc;
TagOfs = 0;
RegType = REGT_INT;
}
void FloatAt(double *loc)
{
Location = loc;
TagOfs = 0;
RegType = REGT_FLOAT;
}
void StringAt(FString *loc)
{
Location = loc;
TagOfs = 0;
RegType = REGT_STRING;
}
void PointerAt(void **loc)
{
Location = loc;
TagOfs = 0;
RegType = REGT_POINTER;
}
VMReturn() { }
@ -415,7 +391,7 @@ struct VMValue
union
{
int i;
struct { void *a; int atag; };
void *a;
double f;
struct { int pad[3]; VM_UBYTE Type; };
struct { int foo[4]; } biggest;
@ -456,19 +432,11 @@ struct VMValue
VMValue(DObject *v)
{
a = v;
atag = ATAG_OBJECT;
Type = REGT_POINTER;
}
VMValue(void *v)
{
a = v;
atag = ATAG_GENERIC;
Type = REGT_POINTER;
}
VMValue(void *v, int tag)
{
a = v;
atag = tag;
Type = REGT_POINTER;
}
VMValue &operator=(const VMValue &o)
@ -499,7 +467,6 @@ struct VMValue
VMValue &operator=(DObject *v)
{
a = v;
atag = ATAG_OBJECT;
Type = REGT_POINTER;
return *this;
}
@ -602,7 +569,7 @@ struct VMFrame
int size = (sizeof(VMFrame) + 15) & ~15;
size += numparam * sizeof(VMValue);
size += numregf * sizeof(double);
size += numrega * (sizeof(void *) + sizeof(VM_UBYTE));
size += numrega * sizeof(void *);
size += numregs * sizeof(FString);
size += numregd * sizeof(int);
if (numextra != 0)
@ -613,9 +580,10 @@ struct VMFrame
return size;
}
int *GetRegD() const
VMValue *GetParam() const
{
return (int *)(GetRegA() + NumRegA);
assert(((size_t)this & 15) == 0 && "VM frame is unaligned");
return (VMValue *)(((size_t)(this + 1) + 15) & ~15);
}
double *GetRegF() const
@ -633,25 +601,19 @@ struct VMFrame
return (void **)(GetRegS() + NumRegS);
}
VM_ATAG *GetRegATag() const
int *GetRegD() const
{
return (VM_ATAG *)(GetRegD() + NumRegD);
}
VMValue *GetParam() const
{
assert(((size_t)this & 15) == 0 && "VM frame is unaligned");
return (VMValue *)(((size_t)(this + 1) + 15) & ~15);
return (int *)(GetRegA() + NumRegA);
}
void *GetExtra() const
{
VM_ATAG *ptag = GetRegATag();
ptrdiff_t ofs = ptag - (VM_ATAG *)this;
return (VM_UBYTE *)this + ((ofs + NumRegA + 15) & ~15);
uint8_t *pbeg = (uint8_t*)(GetRegD() + NumRegD);
ptrdiff_t ofs = pbeg - (uint8_t *)this;
return (VM_UBYTE *)this + ((ofs + 15) & ~15);
}
void GetAllRegs(int *&d, double *&f, FString *&s, void **&a, VM_ATAG *&atag, VMValue *&param) const
void GetAllRegs(int *&d, double *&f, FString *&s, void **&a, VMValue *&param) const
{
// Calling the individual functions produces suboptimal code. :(
param = GetParam();
@ -659,7 +621,6 @@ struct VMFrame
s = (FString *)(f + NumRegF);
a = (void **)(s + NumRegS);
d = (int *)(a + NumRegA);
atag = (VM_ATAG *)(d + NumRegD);
}
void InitRegS();
@ -669,18 +630,17 @@ struct VMRegisters
{
VMRegisters(const VMFrame *frame)
{
frame->GetAllRegs(d, f, s, a, atag, param);
frame->GetAllRegs(d, f, s, a, param);
}
VMRegisters(const VMRegisters &o)
: d(o.d), f(o.f), s(o.s), a(o.a), atag(o.atag), param(o.param)
: d(o.d), f(o.f), s(o.s), a(o.a), param(o.param)
{ }
int *d;
double *f;
FString *s;
void **a;
VM_ATAG *atag;
VMValue *param;
};
@ -703,9 +663,6 @@ public:
~VMScriptFunction();
void Alloc(int numops, int numkonstd, int numkonstf, int numkonsts, int numkonsta, int numlinenumbers);
VM_ATAG *KonstATags() { return (VM_UBYTE *)(KonstA + NumKonstA); }
const VM_ATAG *KonstATags() const { return (VM_UBYTE *)(KonstA + NumKonstA); }
VMOP *Code;
FStatementInfo *LineInfo;
FString SourceFileName;
@ -810,14 +767,12 @@ public:
void ParamObject(DObject *obj)
{
Reg.a[RegA] = obj;
Reg.atag[RegA] = ATAG_OBJECT;
RegA++;
}
void ParamPointer(void *ptr, VM_ATAG atag)
void ParamPointer(void *ptr)
{
Reg.a[RegA] = ptr;
Reg.atag[RegA] = atag;
RegA++;
}
@ -852,8 +807,18 @@ void VMDisasm(FILE *out, const VMOP *code, int codesize, const VMScriptFunction
// variable name <x> at position <p>
void NullParam(const char *varname);
#ifdef _DEBUG
bool AssertObject(void * ob);
#endif
#define PARAM_NULLCHECK(ptr, var) (ptr == nullptr? NullParam(#var), ptr : ptr)
#define ASSERTINT(p) assert((p).Type == REGT_INT)
#define ASSERTFLOAT(p) assert((p).Type == REGT_FLOAT)
#define ASSERTSTRING(p) assert((p).Type == REGT_STRING)
#define ASSERTOBJECT(p) assert((p).Type == REGT_POINTER && AssertObject(p.a))
#define ASSERTPOINTER(p) assert((p).Type == REGT_POINTER)
// For required parameters.
#define PARAM_INT_AT(p,x) assert((p) < numparam); assert(param[p].Type == REGT_INT); int x = param[p].i;
#define PARAM_UINT_AT(p,x) assert((p) < numparam); assert(param[p].Type == REGT_INT); unsigned x = param[p].i;
@ -868,19 +833,13 @@ void NullParam(const char *varname);
#define PARAM_STATE_ACTION_AT(p,x) assert((p) < numparam); assert(param[p].Type == REGT_INT); FState *x = (FState *)StateLabels.GetState(param[p].i, stateowner->GetClass());
#define PARAM_POINTER_AT(p,x,type) assert((p) < numparam); assert(param[p].Type == REGT_POINTER); type *x = (type *)param[p].a;
#define PARAM_POINTERTYPE_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; 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)); base::MetaClass *x = (base::MetaClass *)param[p].a; assert(x == NULL || x->IsDescendantOf(RUNTIME_CLASS(base)));
#define PARAM_OBJECT_AT(p,x,type) assert((p) < numparam); assert(param[p].Type == REGT_POINTER && AssertObject(param[p].a)); 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 && AssertObject(param[p].a)); base::MetaClass *x = (base::MetaClass *)param[p].a; assert(x == NULL || x->IsDescendantOf(RUNTIME_CLASS(base)));
#define PARAM_POINTER_NOT_NULL_AT(p,x,type) assert((p) < numparam); assert(param[p].Type == REGT_POINTER); type *x = (type *)PARAM_NULLCHECK(param[p].a, #x);
#define PARAM_OBJECT_NOT_NULL_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_NULLCHECK(param[p].a, #x); assert(x == NULL || x->IsKindOf(RUNTIME_CLASS(type)));
#define PARAM_CLASS_NOT_NULL_AT(p,x,base) assert((p) < numparam); assert(param[p].Type == REGT_POINTER && (param[p].atag == ATAG_OBJECT || param[p].a == NULL)); base::MetaClass *x = (base::MetaClass *)PARAM_NULLCHECK(param[p].a, #x); assert(x == NULL || x->IsDescendantOf(RUNTIME_CLASS(base)));
#define PARAM_OBJECT_NOT_NULL_AT(p,x,type) assert((p) < numparam); assert(param[p].Type == REGT_POINTER && (AssertObject(param[p].a))); type *x = (type *)PARAM_NULLCHECK(param[p].a, #x); assert(x == NULL || x->IsKindOf(RUNTIME_CLASS(type)));
#define PARAM_CLASS_NOT_NULL_AT(p,x,base) assert((p) < numparam); assert(param[p].Type == REGT_POINTER && (AssertObject(param[p].a))); base::MetaClass *x = (base::MetaClass *)PARAM_NULLCHECK(param[p].a, #x); assert(x == NULL || x->IsDescendantOf(RUNTIME_CLASS(base)));
#define PARAM_EXISTS(p) ((p) < numparam)
#define ASSERTINT(p) assert((p).Type == REGT_INT)
#define ASSERTFLOAT(p) assert((p).Type == REGT_FLOAT)
#define ASSERTSTRING(p) assert((p).Type == REGT_STRING)
#define ASSERTOBJECT(p) assert((p).Type == REGT_POINTER && ((p).atag == ATAG_OBJECT || (p).a == nullptr))
#define ASSERTPOINTER(p) assert((p).Type == REGT_POINTER && (p).atag == ATAG_GENERIC)
#define ASSERTSTATE(p) assert((p).Type == REGT_POINTER && ((p).atag == ATAG_GENERIC || (p).atag == ATAG_STATE))
#define PARAM_INT_DEF_AT(p,x) int x; if (PARAM_EXISTS(p)) { ASSERTINT(param[p]); x = param[p].i; } else { ASSERTINT(defaultparam[p]); x = defaultparam[p].i; }
#define PARAM_BOOL_DEF_AT(p,x) bool x; if (PARAM_EXISTS(p)) { ASSERTINT(param[p]); x = !!param[p].i; } else { ASSERTINT(defaultparam[p]); x = !!defaultparam[p].i; }
@ -1030,9 +989,9 @@ struct AFuncDesc
class AActor;
#define ACTION_RETURN_STATE(v) do { FState *state = v; if (numret > 0) { assert(ret != NULL); ret->SetPointer(state, ATAG_STATE); return 1; } return 0; } while(0)
#define ACTION_RETURN_POINTER(v) do { void *state = v; if (numret > 0) { assert(ret != NULL); ret->SetPointer(state, ATAG_GENERIC); return 1; } return 0; } while(0)
#define ACTION_RETURN_OBJECT(v) do { auto state = v; if (numret > 0) { assert(ret != NULL); ret->SetPointer(state, ATAG_OBJECT); return 1; } return 0; } while(0)
#define ACTION_RETURN_STATE(v) do { FState *state = v; if (numret > 0) { assert(ret != NULL); ret->SetPointer(state); return 1; } return 0; } while(0)
#define ACTION_RETURN_POINTER(v) do { void *state = v; if (numret > 0) { assert(ret != NULL); ret->SetPointer(state); return 1; } return 0; } while(0)
#define ACTION_RETURN_OBJECT(v) do { auto state = v; if (numret > 0) { assert(ret != NULL); ret->SetObject(state); return 1; } return 0; } while(0)
#define ACTION_RETURN_FLOAT(v) do { double u = v; if (numret > 0) { assert(ret != nullptr); ret->SetFloat(u); return 1; } return 0; } while(0)
#define ACTION_RETURN_VEC2(v) do { DVector2 u = v; if (numret > 0) { assert(ret != nullptr); ret[0].SetVector2(u); return 1; } return 0; } while(0)
#define ACTION_RETURN_VEC3(v) do { DVector3 u = v; if (numret > 0) { assert(ret != nullptr); ret[0].SetVector(u); return 1; } return 0; } while(0)
@ -1062,7 +1021,7 @@ class AActor;
PARAM_PROLOGUE; \
PARAM_OBJECT(self, type);
// for structs we need to check for ATAG_GENERIC instead of ATAG_OBJECT
// for structs we cannot do a class validation
#define PARAM_SELF_STRUCT_PROLOGUE(type) \
PARAM_PROLOGUE; \
PARAM_POINTER(self, type);

View file

@ -82,7 +82,6 @@ void ThrowVMException(VMException *x);
#define ASSERTF(x) assert((unsigned)(x) < f->NumRegF)
#define ASSERTA(x) assert((unsigned)(x) < f->NumRegA)
#define ASSERTS(x) assert((unsigned)(x) < f->NumRegS)
#define ASSERTO(x) assert((unsigned)(x) < f->NumRegA && reg.atag[x] == ATAG_OBJECT)
#define ASSERTKD(x) assert(sfunc != NULL && (unsigned)(x) < sfunc->NumKonstD)
#define ASSERTKF(x) assert(sfunc != NULL && (unsigned)(x) < sfunc->NumKonstF)
@ -228,10 +227,29 @@ void VMFillParams(VMValue *params, VMFrame *callee, int numparam)
else
{
assert(p.Type == REGT_POINTER);
calleereg.a[rega] = p.a;
calleereg.atag[rega++] = p.atag;
calleereg.a[rega++] = p.a;
}
}
}
#ifdef _DEBUG
bool AssertObject(void * ob)
{
auto obj = (DObject*)ob;
if (obj == nullptr) return true;
#ifdef _MSC_VER
__try
{
return obj->MagicID == DObject::MAGIC_ID;
}
__except (1)
{
return false;
}
#else
// No SEH on non-Microsoft compilers. :(
return obj->MagicID == DObject::MAGIC_ID;
#endif
}
#endif

View file

@ -11,8 +11,8 @@ static int Exec(VMFrameStack *stack, const VMOP *pc, VMReturn *ret, int numret)
#include "vmops.h"
};
#endif
const VMOP *exception_frames[MAX_TRY_DEPTH];
int try_depth = 0;
//const VMOP *exception_frames[MAX_TRY_DEPTH];
//int try_depth = 0;
VMFrame *f = stack->TopFrame();
VMScriptFunction *sfunc;
const VMRegisters reg(f);
@ -20,7 +20,6 @@ static int Exec(VMFrameStack *stack, const VMOP *pc, VMReturn *ret, int numret)
const double *konstf;
const FString *konsts;
const FVoidObj *konsta;
const VM_ATAG *konstatag;
if (f->Func != NULL && !(f->Func->VarFlags & VARF_Native))
{
@ -29,7 +28,6 @@ static int Exec(VMFrameStack *stack, const VMOP *pc, VMReturn *ret, int numret)
konstf = sfunc->KonstF;
konsts = sfunc->KonstS;
konsta = sfunc->KonstA;
konstatag = sfunc->KonstATags();
}
else
{
@ -38,7 +36,6 @@ static int Exec(VMFrameStack *stack, const VMOP *pc, VMReturn *ret, int numret)
konstf = NULL;
konsts = NULL;
konsta = NULL;
konstatag = NULL;
}
void *ptr;
@ -46,7 +43,7 @@ static int Exec(VMFrameStack *stack, const VMOP *pc, VMReturn *ret, int numret)
const double *fbp, *fcp;
int a, b, c;
begin:
//begin:
try
{
#if !COMPGOTO
@ -81,7 +78,6 @@ begin:
OP(LKP):
ASSERTA(a); ASSERTKA(BC);
reg.a[a] = konsta[BC].v;
reg.atag[a] = konstatag[BC];
NEXTOP;
OP(LK_R) :
@ -100,25 +96,21 @@ begin:
ASSERTA(a); ASSERTD(B);
b = reg.d[B] + C;
reg.a[a] = konsta[b].v;
reg.atag[a] = konstatag[b];
NEXTOP;
OP(LFP):
ASSERTA(a); assert(sfunc != NULL); assert(sfunc->ExtraSpace > 0);
reg.a[a] = f->GetExtra();
reg.atag[a] = ATAG_GENERIC; // using ATAG_FRAMEPOINTER will cause endless asserts.
NEXTOP;
OP(CLSS):
ASSERTA(a); ASSERTO(B);
ASSERTA(a); ASSERTA(B);
reg.a[a] = ((DObject*)reg.a[B])->GetClass(); // I wish this could be done without a special opcode but there's really no good way to guarantee initialization of the Class pointer...
reg.atag[a] = ATAG_OBJECT;
NEXTOP;
OP(META):
ASSERTA(a); ASSERTO(B);
ASSERTA(a); ASSERTA(B);
reg.a[a] = ((DObject*)reg.a[B])->GetClass()->Meta; // I wish this could be done without a special opcode but there's really no good way to guarantee initialization of the Class pointer...
reg.atag[a] = ATAG_OBJECT;
NEXTOP;
OP(LB):
@ -217,37 +209,31 @@ begin:
ASSERTA(a); ASSERTA(B); ASSERTKD(C);
GETADDR(PB,KC,X_READ_NIL);
reg.a[a] = GC::ReadBarrier(*(DObject **)ptr);
reg.atag[a] = ATAG_OBJECT;
NEXTOP;
OP(LO_R):
ASSERTA(a); ASSERTA(B); ASSERTD(C);
GETADDR(PB,RC,X_READ_NIL);
reg.a[a] = GC::ReadBarrier(*(DObject **)ptr);
reg.atag[a] = ATAG_OBJECT;
NEXTOP;
OP(LOS):
ASSERTA(a); ASSERTA(B); ASSERTKD(C);
GETADDR(PB,KC,X_READ_NIL);
reg.a[a] = *(DObject **)ptr;
reg.atag[a] = ATAG_OBJECT;
NEXTOP;
OP(LOS_R):
ASSERTA(a); ASSERTA(B); ASSERTD(C);
GETADDR(PB,RC,X_READ_NIL);
reg.a[a] = *(DObject **)ptr;
reg.atag[a] = ATAG_OBJECT;
NEXTOP;
OP(LP):
ASSERTA(a); ASSERTA(B); ASSERTKD(C);
GETADDR(PB,KC,X_READ_NIL);
reg.a[a] = *(void **)ptr;
reg.atag[a] = ATAG_GENERIC;
NEXTOP;
OP(LP_R):
ASSERTA(a); ASSERTA(B); ASSERTD(C);
GETADDR(PB,RC,X_READ_NIL);
reg.a[a] = *(void **)ptr;
reg.atag[a] = ATAG_GENERIC;
NEXTOP;
OP(LV2):
ASSERTF(a+1); ASSERTA(B); ASSERTKD(C);
@ -442,7 +428,6 @@ begin:
ASSERTA(a); ASSERTA(B);
b = B;
reg.a[a] = reg.a[b];
reg.atag[a] = reg.atag[b];
NEXTOP;
}
OP(MOVEV2):
@ -466,25 +451,21 @@ begin:
ASSERTA(a); ASSERTA(B); ASSERTA(C);
b = B;
reg.a[a] = (reg.a[b] && ((DObject*)(reg.a[b]))->IsKindOf((PClass*)(reg.a[C]))) ? reg.a[b] : nullptr;
reg.atag[a] = ATAG_OBJECT;
NEXTOP;
OP(DYNCAST_K) :
ASSERTA(a); ASSERTA(B); ASSERTKA(C);
b = B;
reg.a[a] = (reg.a[b] && ((DObject*)(reg.a[b]))->IsKindOf((PClass*)(konsta[C].o))) ? reg.a[b] : nullptr;
reg.atag[a] = ATAG_OBJECT;
NEXTOP;
OP(DYNCASTC_R) :
ASSERTA(a); ASSERTA(B); ASSERTA(C);
b = B;
reg.a[a] = (reg.a[b] && ((PClass*)(reg.a[b]))->IsDescendantOf((PClass*)(reg.a[C]))) ? reg.a[b] : nullptr;
reg.atag[a] = ATAG_OBJECT;
NEXTOP;
OP(DYNCASTC_K) :
ASSERTA(a); ASSERTA(B); ASSERTKA(C);
b = B;
reg.a[a] = (reg.a[b] && ((PClass*)(reg.a[b]))->IsDescendantOf((PClass*)(konsta[C].o))) ? reg.a[b] : nullptr;
reg.atag[a] = ATAG_OBJECT;
NEXTOP;
OP(CAST):
if (C == CAST_I2F)
@ -575,7 +556,7 @@ begin:
break;
case REGT_INT | REGT_ADDROF:
assert(C < f->NumRegD);
::new(param) VMValue(&reg.d[C], ATAG_GENERIC);
::new(param) VMValue(&reg.d[C]);
break;
case REGT_INT | REGT_KONST:
assert(C < sfunc->NumKonstD);
@ -587,7 +568,7 @@ begin:
break;
case REGT_STRING | REGT_ADDROF:
assert(C < f->NumRegS);
::new(param) VMValue(&reg.s[C], ATAG_GENERIC);
::new(param) VMValue((void*)&reg.s[C]); // Note that this may not use the FString* version of the constructor!
break;
case REGT_STRING | REGT_KONST:
assert(C < sfunc->NumKonstS);
@ -595,15 +576,15 @@ begin:
break;
case REGT_POINTER:
assert(C < f->NumRegA);
::new(param) VMValue(reg.a[C], reg.atag[C]);
::new(param) VMValue(reg.a[C]);
break;
case REGT_POINTER | REGT_ADDROF:
assert(C < f->NumRegA);
::new(param) VMValue(&reg.a[C], ATAG_GENERIC);
::new(param) VMValue(&reg.a[C]);
break;
case REGT_POINTER | REGT_KONST:
assert(C < sfunc->NumKonstA);
::new(param) VMValue(konsta[C].v, konstatag[C]);
::new(param) VMValue(konsta[C].v);
break;
case REGT_FLOAT:
assert(C < f->NumRegF);
@ -626,7 +607,7 @@ begin:
break;
case REGT_FLOAT | REGT_ADDROF:
assert(C < f->NumRegF);
::new(param) VMValue(&reg.f[C], ATAG_GENERIC);
::new(param) VMValue(&reg.f[C]);
break;
case REGT_FLOAT | REGT_KONST:
assert(C < sfunc->NumKonstF);
@ -657,7 +638,6 @@ begin:
OP(CALL_K):
ASSERTKA(a);
assert(konstatag[a] == ATAG_OBJECT);
ptr = konsta[a].o;
goto Do_CALL;
OP(CALL):
@ -713,7 +693,6 @@ begin:
NEXTOP;
OP(TAIL_K):
ASSERTKA(a);
assert(konstatag[a] == ATAG_OBJECT);
ptr = konsta[a].o;
goto Do_TAILCALL;
OP(TAIL):
@ -825,10 +804,10 @@ begin:
c = C;
if (c) FScopeBarrier::ValidateNew(cls, c - 1);
reg.a[a] = cls->CreateNew();
reg.atag[a] = ATAG_OBJECT;
NEXTOP;
}
#if 0
OP(TRY):
assert(try_depth < MAX_TRY_DEPTH);
if (try_depth >= MAX_TRY_DEPTH)
@ -842,7 +821,9 @@ begin:
assert(a <= try_depth);
try_depth -= a;
NEXTOP;
#endif
OP(THROW):
#if 0
if (a == 0)
{
ASSERTA(B);
@ -851,19 +832,22 @@ begin:
else if (a == 1)
{
ASSERTKA(B);
assert(konstatag[B] == ATAG_OBJECT);
assert(AssertObject(konsta[B].o));
ThrowVMException((VMException *)konsta[B].o);
}
else
#endif
{
ThrowAbortException(EVMAbortException(BC), nullptr);
}
NEXTOP;
#if 0
OP(CATCH):
// This instruction is handled by our own catch handler and should
// not be executed by the normal VM code.
assert(0);
NEXTOP;
#endif
OP(BOUND):
if (reg.d[a] >= BC)
@ -1658,7 +1642,6 @@ begin:
c = 0;
}
reg.a[a] = (VM_UBYTE *)reg.a[B] + c;
reg.atag[a] = c == 0 ? reg.atag[B] : (int)ATAG_GENERIC;
NEXTOP;
OP(ADDA_RK):
ASSERTA(a); ASSERTA(B); ASSERTKD(C);
@ -1683,6 +1666,7 @@ begin:
NEXTOP;
}
}
#if 0
catch(VMException *exception)
{
// Try to find a handler for the exception.
@ -1709,7 +1693,6 @@ begin:
{
assert(pc->a == 3);
ASSERTKA(b);
assert(konstatag[b] == ATAG_OBJECT);
type = (PClass *)konsta[b].o;
}
ASSERTA(pc->c);
@ -1718,7 +1701,6 @@ begin:
// Found a handler. Store the exception in pC, skip the JMP,
// and begin executing its code.
reg.a[pc->c] = exception;
reg.atag[pc->c] = ATAG_OBJECT;
pc += 2;
goto begin;
}
@ -1731,7 +1713,6 @@ begin:
// Catch any type of VMException. This terminates the chain.
ASSERTA(pc->c);
reg.a[pc->c] = exception;
reg.atag[pc->c] = ATAG_OBJECT;
pc += 1;
goto begin;
}
@ -1740,6 +1721,7 @@ begin:
// Nothing caught it. Rethrow and let somebody else deal with it.
throw;
}
#endif
catch (CVMAbortException &err)
{
err.MaybePrintMessage();
@ -1831,16 +1813,7 @@ static void DoCast(const VMRegisters &reg, const VMFrame *f, int a, int b, int c
{
ASSERTS(a); ASSERTA(b);
if (reg.a[b] == nullptr) reg.s[a] = "null";
else if (reg.atag[b] == ATAG_OBJECT)
{
auto op = static_cast<DObject*>(reg.a[b]);
if (op->IsKindOf(RUNTIME_CLASS(PClass))) reg.s[a].Format("Class<%s>", static_cast<PClass*>(op)->TypeName.GetChars());
else reg.s[a].Format("Object<%p>", ((DObject*)reg.a[b])->GetClass()->TypeName.GetChars());
}
else
{
reg.s[a].Format("%s<%p>", "Pointer", reg.a[b]);
}
else reg.s[a].Format("%p", reg.a[b]);
break;
}
@ -1922,7 +1895,6 @@ static void FillReturns(const VMRegisters &reg, VMFrame *frame, VMReturn *return
for (i = 0, ret = returns; i < numret; ++i, ++ret, ++retval)
{
assert(retval->op == OP_RESULT); // opcode
ret->TagOfs = 0;
ret->RegType = type = retval->b;
regnum = retval->c;
assert(!(type & REGT_KONST));
@ -1950,7 +1922,6 @@ static void FillReturns(const VMRegisters &reg, VMFrame *frame, VMReturn *return
assert(type == REGT_POINTER);
assert(regnum < frame->NumRegA);
ret->Location = &reg.a[regnum];
ret->TagOfs = (VM_SHALF)(&frame->GetRegATag()[regnum] - (VM_ATAG *)ret->Location);
}
}
}
@ -2033,12 +2004,12 @@ static void SetReturn(const VMRegisters &reg, VMFrame *frame, VMReturn *ret, VM_
if (regtype & REGT_KONST)
{
assert(regnum < func->NumKonstA);
ret->SetPointer(func->KonstA[regnum].v, func->KonstATags()[regnum]);
ret->SetPointer(func->KonstA[regnum].v);
}
else
{
assert(regnum < frame->NumRegA);
ret->SetPointer(reg.a[regnum], reg.atag[regnum]);
ret->SetPointer(reg.a[regnum]);
}
break;
}

View file

@ -97,7 +97,7 @@ void VMScriptFunction::Alloc(int numops, int numkonstd, int numkonstf, int numko
numkonstd * sizeof(int) +
numkonstf * sizeof(double) +
numkonsts * sizeof(FString) +
numkonsta * (sizeof(FVoidObj) + 1) +
numkonsta * sizeof(FVoidObj) +
numlinenumbers * sizeof(FStatementInfo));
Code = (VMOP *)mem;
mem = (void *)((VMOP *)mem + numops);

View file

@ -114,12 +114,12 @@ xx(RET, ret, I8BCP, NOP, 0, 0), // Copy value from register encoded in BC to
xx(RETI, reti, I8I16, NOP, 0, 0), // Copy immediate from BC to return value A, possibly returning
xx(NEW, new, RPRPI8, NOP, 0, 0),
xx(NEW_K, new, RPKP, NOP, 0, 0),
xx(TRY, try, I24, NOP, 0, 0), // When an exception is thrown, start searching for a handler at pc + ABC
xx(UNTRY, untry, I8, NOP, 0, 0), // Pop A entries off the exception stack
//xx(TRY, try, I24, NOP, 0, 0), // When an exception is thrown, start searching for a handler at pc + ABC
//xx(UNTRY, untry, I8, NOP, 0, 0), // Pop A entries off the exception stack
xx(THROW, throw, THROW, NOP, 0, 0), // A == 0: Throw exception object pB
// A == 1: Throw exception object pkB
// A >= 2: Throw VM exception of type BC
xx(CATCH, catch, CATCH, NOP, 0, 0), // A == 0: continue search on next try
//xx(CATCH, catch, CATCH, NOP, 0, 0), // A == 0: continue search on next try
// A == 1: continue execution at instruction immediately following CATCH (catches any exception)
// A == 2: (pB == <type of exception thrown>) then pc++ ; next instruction must JMP to another CATCH
// A == 3: (pkB == <type of exception thrown>) then pc++ ; next instruction must JMP to another CATCH

View file

@ -46,7 +46,7 @@ void *RenderMemory::AllocBytes(int size)
}
else
{
UsedBlocks.push_back(std::make_unique<MemoryBlock>());
UsedBlocks.push_back(std::unique_ptr<MemoryBlock>(new MemoryBlock()));
}
}

View file

@ -60,21 +60,21 @@ namespace swrenderer
{
Scene = scene;
MainThread = mainThread;
FrameMemory = std::make_unique<RenderMemory>();
Viewport = std::make_unique<RenderViewport>();
Light = std::make_unique<LightVisibility>();
DrawQueue = std::make_shared<DrawerCommandQueue>(FrameMemory.get());
OpaquePass = std::make_unique<RenderOpaquePass>(this);
TranslucentPass = std::make_unique<RenderTranslucentPass>(this);
SpriteList = std::make_unique<VisibleSpriteList>();
Portal = std::make_unique<RenderPortal>(this);
Clip3D = std::make_unique<Clip3DFloors>(this);
PlayerSprites = std::make_unique<RenderPlayerSprites>(this);
PlaneList = std::make_unique<VisiblePlaneList>(this);
DrawSegments = std::make_unique<DrawSegmentList>(this);
ClipSegments = std::make_unique<RenderClipSegment>();
tc_drawers = std::make_unique<SWTruecolorDrawers>(DrawQueue);
pal_drawers = std::make_unique<SWPalDrawers>(DrawQueue);
FrameMemory.reset(new RenderMemory());
Viewport.reset(new RenderViewport());
Light.reset(new LightVisibility());
DrawQueue.reset(new DrawerCommandQueue(FrameMemory.get()));
OpaquePass.reset(new RenderOpaquePass(this));
TranslucentPass.reset(new RenderTranslucentPass(this));
SpriteList.reset(new VisibleSpriteList());
Portal.reset(new RenderPortal(this));
Clip3D.reset(new Clip3DFloors(this));
PlayerSprites.reset(new RenderPlayerSprites(this));
PlaneList.reset(new VisiblePlaneList(this));
DrawSegments.reset(new DrawSegmentList(this));
ClipSegments.reset(new RenderClipSegment());
tc_drawers.reset(new SWTruecolorDrawers(DrawQueue));
pal_drawers.reset(new SWPalDrawers(DrawQueue));
}
RenderThread::~RenderThread()

View file

@ -61,7 +61,7 @@ namespace swrenderer
RenderScene::RenderScene()
{
Threads.push_back(std::make_unique<RenderThread>(this));
Threads.push_back(std::unique_ptr<RenderThread>(new RenderThread(this)));
}
RenderScene::~RenderScene()
@ -289,7 +289,7 @@ namespace swrenderer
{
while (Threads.size() < (size_t)numThreads)
{
auto thread = std::make_unique<RenderThread>(this, false);
std::unique_ptr<RenderThread> thread(new RenderThread(this, false));
auto renderthread = thread.get();
int start_run_id = run_id;
thread->thread = std::thread([=]()

View file

@ -25,6 +25,8 @@ class Inventory : Actor native
native bool bInitEffectFailed;
meta String PickupMsg;
meta int GiveQuest;
meta array<class<Actor> > ForbiddenToPlayerClass;
meta array<class<Actor> > RestrictedToPlayerClass;
property PickupMessage: PickupMsg;
property GiveQuest: GiveQuest;
@ -46,7 +48,6 @@ class Inventory : Actor native
Inventory.PickupMessage "$TXT_DEFAULTPICKUPMSG";
}
native bool CanPickup(Actor toucher);
native bool DoRespawn();
native void BecomeItem();
native void BecomePickup();
@ -330,6 +331,36 @@ class Inventory : Actor native
}
}
//===========================================================================
//
// AInventory :: CanPickup
//
//===========================================================================
virtual bool CanPickup(Actor toucher)
{
if (toucher == null) return false;
int rsize = RestrictedToPlayerClass.Size();
if (rsize > 0)
{
for (int i=0; i < rsize; i++)
{
if (toucher is RestrictedToPlayerClass[i]) return true;
}
return false;
}
rsize = ForbiddenToPlayerClass.Size();
if (rsize > 0)
{
for (int i=0; i < rsize; i++)
{
if (toucher is ForbiddenToPlayerClass[i]) return false;
}
}
return true;
}
//===========================================================================
//
// AInventory :: CallTryPickup