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

View file

@ -200,6 +200,14 @@ protected:
enum { MetaClassNum = CLASSREG_PClass }; enum { MetaClassNum = CLASSREG_PClass };
// Per-instance variables. There are four. // 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: private:
PClass *Class; // This object's type PClass *Class; // This object's type
public: public:

View file

@ -780,6 +780,15 @@ PFloat::PFloat(unsigned int size)
mDescriptiveName.Format("Float%d", size); mDescriptiveName.Format("Float%d", size);
if (size == 8) 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(); SetDoubleSymbols();
} }
else else

View file

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

View file

@ -484,43 +484,6 @@ bool AInventory::CallTryPickup(AActor *toucher, AActor **toucher_return)
return !!res; 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 // CCMD printinv

View file

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

View file

@ -38,7 +38,7 @@ void FLinearDepthShader::Bind()
if (!mShader) if (!mShader)
{ {
mShader = std::make_unique<FShaderProgram>(); mShader.reset(new FShaderProgram());
mShader->Compile(FShaderProgram::Vertex, "shaders/glsl/screenquad.vp", "", 330); mShader->Compile(FShaderProgram::Vertex, "shaders/glsl/screenquad.vp", "", 330);
mShader->Compile(FShaderProgram::Fragment, "shaders/glsl/lineardepth.fp", multisample ? "#define MULTISAMPLE\n" : "", 330); mShader->Compile(FShaderProgram::Fragment, "shaders/glsl/lineardepth.fp", multisample ? "#define MULTISAMPLE\n" : "", 330);
mShader->SetFragDataLocation(0, "FragColor"); mShader->SetFragDataLocation(0, "FragColor");
@ -66,7 +66,7 @@ void FSSAOShader::Bind()
if (!mShader) if (!mShader)
{ {
mShader = std::make_unique<FShaderProgram>(); mShader.reset(new FShaderProgram());
mShader->Compile(FShaderProgram::Vertex, "shaders/glsl/screenquad.vp", "", 330); mShader->Compile(FShaderProgram::Vertex, "shaders/glsl/screenquad.vp", "", 330);
mShader->Compile(FShaderProgram::Fragment, "shaders/glsl/ssao.fp", GetDefines(gl_ssao, multisample), 330); mShader->Compile(FShaderProgram::Fragment, "shaders/glsl/ssao.fp", GetDefines(gl_ssao, multisample), 330);
mShader->SetFragDataLocation(0, "FragColor"); mShader->SetFragDataLocation(0, "FragColor");
@ -142,7 +142,7 @@ void FSSAOCombineShader::Bind()
if (!mShader) if (!mShader)
{ {
mShader = std::make_unique<FShaderProgram>(); mShader.reset(new FShaderProgram());
mShader->Compile(FShaderProgram::Vertex, "shaders/glsl/screenquad.vp", "", 330); mShader->Compile(FShaderProgram::Vertex, "shaders/glsl/screenquad.vp", "", 330);
mShader->Compile(FShaderProgram::Fragment, "shaders/glsl/ssaocombine.fp", multisample ? "#define MULTISAMPLE\n" : "", 330); mShader->Compile(FShaderProgram::Fragment, "shaders/glsl/ssaocombine.fp", multisample ? "#define MULTISAMPLE\n" : "", 330);
mShader->SetFragDataLocation(0, "FragColor"); 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) 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; GLint format = GL_RGBA16F;
if (gl.es) format = GL_RGB; 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) 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(); shader->Program = glCreateProgram();
if (shader->Program == 0) { Printf("glCreateProgram failed. Disabling OpenGL hardware acceleration.\n"); return false; } 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) bool OpenGLSWFrameBuffer::CreateVertexBuffer(int size, HWVertexBuffer **outVertexBuffer)
{ {
auto obj = std::make_unique<HWVertexBuffer>(); std::unique_ptr<HWVertexBuffer> obj(new HWVertexBuffer());
obj->Size = size; obj->Size = size;
@ -474,7 +474,7 @@ bool OpenGLSWFrameBuffer::CreateVertexBuffer(int size, HWVertexBuffer **outVerte
bool OpenGLSWFrameBuffer::CreateIndexBuffer(int size, HWIndexBuffer **outIndexBuffer) bool OpenGLSWFrameBuffer::CreateIndexBuffer(int size, HWIndexBuffer **outIndexBuffer)
{ {
auto obj = std::make_unique<HWIndexBuffer>(); std::unique_ptr<HWIndexBuffer> obj(new HWIndexBuffer());
obj->Size = size; 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) 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; obj->Format = format;
@ -532,7 +532,7 @@ bool OpenGLSWFrameBuffer::CreateTexture(const FString &name, int width, int heig
OpenGLSWFrameBuffer::HWTexture *OpenGLSWFrameBuffer::CopyCurrentScreen() OpenGLSWFrameBuffer::HWTexture *OpenGLSWFrameBuffer::CopyCurrentScreen()
{ {
auto obj = std::make_unique<HWTexture>(); std::unique_ptr<HWTexture> obj(new HWTexture());
obj->Format = GL_RGBA16F; obj->Format = GL_RGBA16F;
GLint oldBinding = 0; GLint oldBinding = 0;
@ -611,7 +611,7 @@ void OpenGLSWFrameBuffer::DrawTriangleFans(int count, const FBVERTEX *vertices)
if (!StreamVertexBuffer) if (!StreamVertexBuffer)
{ {
StreamVertexBuffer = std::make_unique<HWVertexBuffer>(); StreamVertexBuffer.reset(new HWVertexBuffer());
glGenVertexArrays(1, (GLuint*)&StreamVertexBuffer->VertexArray); glGenVertexArrays(1, (GLuint*)&StreamVertexBuffer->VertexArray);
glGenBuffers(1, (GLuint*)&StreamVertexBuffer->Buffer); glGenBuffers(1, (GLuint*)&StreamVertexBuffer->Buffer);
glBindVertexArray(StreamVertexBuffer->VertexArray); glBindVertexArray(StreamVertexBuffer->VertexArray);
@ -648,7 +648,7 @@ void OpenGLSWFrameBuffer::DrawTriangleFans(int count, const BURNVERTEX *vertices
if (!StreamVertexBufferBurn) if (!StreamVertexBufferBurn)
{ {
StreamVertexBufferBurn = std::make_unique<HWVertexBuffer>(); StreamVertexBufferBurn.reset(new HWVertexBuffer());
glGenVertexArrays(1, (GLuint*)&StreamVertexBufferBurn->VertexArray); glGenVertexArrays(1, (GLuint*)&StreamVertexBufferBurn->VertexArray);
glGenBuffers(1, (GLuint*)&StreamVertexBufferBurn->Buffer); glGenBuffers(1, (GLuint*)&StreamVertexBufferBurn->Buffer);
glBindVertexArray(StreamVertexBufferBurn->VertexArray); glBindVertexArray(StreamVertexBufferBurn->VertexArray);
@ -679,7 +679,7 @@ void OpenGLSWFrameBuffer::DrawPoints(int count, const FBVERTEX *vertices)
if (!StreamVertexBuffer) if (!StreamVertexBuffer)
{ {
StreamVertexBuffer = std::make_unique<HWVertexBuffer>(); StreamVertexBuffer.reset(new HWVertexBuffer());
glGenVertexArrays(1, (GLuint*)&StreamVertexBuffer->VertexArray); glGenVertexArrays(1, (GLuint*)&StreamVertexBuffer->VertexArray);
glGenBuffers(1, (GLuint*)&StreamVertexBuffer->Buffer); glGenBuffers(1, (GLuint*)&StreamVertexBuffer->Buffer);
glBindVertexArray(StreamVertexBuffer->VertexArray); glBindVertexArray(StreamVertexBuffer->VertexArray);

View file

@ -76,7 +76,7 @@ bool FState::CallAction(AActor *self, AActor *stateowner, FStateParamInfo *info,
{ {
ActionCycles.Clock(); 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 the function returns a state, store it at *stateret.
// If it doesn't return a state but stateret is non-NULL, we need // If it doesn't return a state but stateret is non-NULL, we need
// to set *stateret to NULL. // to set *stateret to NULL.
@ -314,10 +314,6 @@ void PClassActor::DeriveData(PClass *newclass)
*newa->PainChances = *PainChances; *newa->PainChances = *PainChances;
} }
// Inventory stuff
newa->ForbiddenToPlayerClass = ForbiddenToPlayerClass;
newa->RestrictedToPlayerClass = RestrictedToPlayerClass;
newa->DisplayName = DisplayName; 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 // DmgFactors :: CheckFactor

View file

@ -248,7 +248,6 @@ public:
PClassActor(); PClassActor();
~PClassActor(); ~PClassActor();
virtual size_t PointerSubstitution(DObject *oldclass, DObject *newclass);
void BuildDefaults(); void BuildDefaults();
void ApplyDefaults(uint8_t *defaults); void ApplyDefaults(uint8_t *defaults);
void RegisterIDs(); void RegisterIDs();
@ -292,10 +291,6 @@ public:
FString SourceLumpName; FString SourceLumpName;
FIntCVar *distancecheck; FIntCVar *distancecheck;
// These are only valid for inventory items.
TArray<PClassActor *> RestrictedToPlayerClass;
TArray<PClassActor *> ForbiddenToPlayerClass;
// This is from PClassPlayerPawn // This is from PClassPlayerPawn
FString DisplayName; 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) if (stream.avail_in == 0 && chunklen > 0)
{ {
stream.next_in = chunkbuffer; 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; chunklen -= stream.avail_in;
} }

View file

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

View file

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

View file

@ -2054,7 +2054,7 @@ DEFINE_ACTION_FUNCTION(AActor, TestMobjZ)
if (numret > 1) if (numret > 1)
{ {
numret = 2; numret = 2;
ret[1].SetPointer(on, ATAG_OBJECT); ret[1].SetObject(on);
} }
if (numret > 0) if (numret > 0)
{ {
@ -4685,7 +4685,7 @@ DEFINE_ACTION_FUNCTION(AActor, LineAttack)
int acdmg; int acdmg;
if (puffType == nullptr) puffType = PClass::FindActor("BulletPuff"); // P_LineAttack does not work without a puff to take info from. 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); 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; if (numret > 1) ret[1].SetInt(acdmg), numret = 2;
return numret; return numret;
} }

View file

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

View file

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

View file

@ -505,12 +505,13 @@ private:
{ {
// Load bgcolor // Load bgcolor
uint32_t desttmp[2]; 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; __m128i bgcolor;
if (BlendT::Mode != (int)BlendModes::Opaque) 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()); bgcolor = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)desttmp), _mm_setzero_si128());
}
else else
bgcolor = _mm_setzero_si128(); bgcolor = _mm_setzero_si128();
@ -593,12 +594,13 @@ private:
{ {
// Load bgcolor // Load bgcolor
uint32_t desttmp[2]; 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; __m128i bgcolor;
if (BlendT::Mode != (int)BlendModes::Opaque) 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()); bgcolor = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)desttmp), _mm_setzero_si128());
}
else else
bgcolor = _mm_setzero_si128(); bgcolor = _mm_setzero_si128();

View file

@ -249,7 +249,7 @@ void RenderPolyPlane::Render(const TriMatrix &worldToClip, const PolyClipPlane &
} }
if (!polyportal) 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(); polyportal = sectorPortals.back().get();
} }

View file

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

View file

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

View file

@ -126,7 +126,7 @@ void VMFunctionBuilder::MakeFunction(VMScriptFunction *func)
} }
if (AddressConstantList.Size() > 0) if (AddressConstantList.Size() > 0)
{ {
FillAddressConstants(func->KonstA, func->KonstATags()); FillAddressConstants(func->KonstA);
} }
if (StringConstantList.Size() > 0) 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(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 else
{ {
int loc = StringConstantList.Push(val); unsigned loc = StringConstantList.Push(val);
StringConstantMap.Insert(val, loc); StringConstantMap.Insert(val, loc);
return 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) unsigned *locp = AddressConstantMap.CheckKey(ptr);
{ // Make all NULL pointers generic. (Or should we allow typed NULLs?)
tag = ATAG_GENERIC;
}
AddrKonst *locp = AddressConstantMap.CheckKey(ptr);
if (locp != NULL) 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. return *locp;
assert(ptr == nullptr || locp->Tag == tag);
return locp->KonstNum;
} }
else else
{ {
unsigned locc = AddressConstantList.Push(ptr); unsigned loc = AddressConstantList.Push(ptr);
AtagConstantList.Push(tag);
AddrKonst loc = { locc, tag };
AddressConstantMap.Insert(ptr, loc); AddressConstantMap.Insert(ptr, loc);
return loc.KonstNum; return loc;
} }
} }
@ -327,16 +317,13 @@ unsigned VMFunctionBuilder::AllocConstantsFloat(unsigned count, double *values)
return addr; return addr;
} }
unsigned VMFunctionBuilder::AllocConstantsAddress(unsigned count, void **ptrs, VM_ATAG tag) unsigned VMFunctionBuilder::AllocConstantsAddress(unsigned count, void **ptrs)
{ {
unsigned addr = AddressConstantList.Reserve(count); unsigned addr = AddressConstantList.Reserve(count);
AtagConstantList.Reserve(count);
memcpy(&AddressConstantList[addr], ptrs, count * sizeof(void *)); memcpy(&AddressConstantList[addr], ptrs, count * sizeof(void *));
for (unsigned i = 0; i < count; i++) for (unsigned i = 0; i < count; i++)
{ {
AtagConstantList[addr + i] = tag; AddressConstantMap.Insert(ptrs[i], addr+i);
AddrKonst loc = { addr+i, tag };
AddressConstantMap.Insert(ptrs[i], loc);
} }
return addr; return addr;
} }

View file

@ -51,12 +51,12 @@ public:
// Returns the constant register holding the value. // Returns the constant register holding the value.
unsigned GetConstantInt(int val); unsigned GetConstantInt(int val);
unsigned GetConstantFloat(double val); unsigned GetConstantFloat(double val);
unsigned GetConstantAddress(void *ptr, VM_ATAG tag); unsigned GetConstantAddress(void *ptr);
unsigned GetConstantString(FString str); unsigned GetConstantString(FString str);
unsigned AllocConstantsInt(unsigned int count, int *values); unsigned AllocConstantsInt(unsigned int count, int *values);
unsigned AllocConstantsFloat(unsigned int count, double *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); unsigned AllocConstantsString(unsigned int count, FString *ptrs);
@ -79,7 +79,7 @@ public:
// Write out complete constant tables. // Write out complete constant tables.
void FillIntConstants(int *konst); void FillIntConstants(int *konst);
void FillFloatConstants(double *konst); void FillFloatConstants(double *konst);
void FillAddressConstants(FVoidObj *konst, VM_ATAG *tags); void FillAddressConstants(FVoidObj *konst);
void FillStringConstants(FString *strings); void FillStringConstants(FString *strings);
// PARAM increases ActiveParam; CALL decreases it. // PARAM increases ActiveParam; CALL decreases it.
@ -96,24 +96,17 @@ public:
TArray<FxLocalVariableDeclaration *> ConstructedStructs; TArray<FxLocalVariableDeclaration *> ConstructedStructs;
private: private:
struct AddrKonst
{
unsigned KonstNum;
VM_ATAG Tag;
};
TArray<FStatementInfo> LineNumbers; TArray<FStatementInfo> LineNumbers;
TArray<FxExpression *> StatementStack; TArray<FxExpression *> StatementStack;
TArray<int> IntConstantList; TArray<int> IntConstantList;
TArray<double> FloatConstantList; TArray<double> FloatConstantList;
TArray<void *> AddressConstantList; TArray<void *> AddressConstantList;
TArray<VM_ATAG> AtagConstantList;
TArray<FString> StringConstantList; TArray<FString> StringConstantList;
// These map from the constant value to its position in the constant table. // These map from the constant value to its position in the constant table.
TMap<int, unsigned> IntConstantMap; TMap<int, unsigned> IntConstantMap;
TMap<double, unsigned> FloatConstantMap; TMap<double, unsigned> FloatConstantMap;
TMap<void *, AddrKonst> AddressConstantMap; TMap<void *, unsigned> AddressConstantMap;
TMap<FString, unsigned> StringConstantMap; TMap<FString, unsigned> StringConstantMap;
int MaxParam; 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) 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, "%-22s", tmp);
} }
printf_wrapper(out, "\n"); printf_wrapper(out, "\n");
@ -320,7 +320,7 @@ void VMDisasm(FILE *out, const VMOP *code, int codesize, const VMScriptFunction
switch (code[i].op) switch (code[i].op)
{ {
case OP_JMP: case OP_JMP:
case OP_TRY: //case OP_TRY:
col = printf_wrapper(out, "%08x", (i + 1 + code[i].i24) << 2); col = printf_wrapper(out, "%08x", (i + 1 + code[i].i24) << 2);
break; break;
@ -498,7 +498,7 @@ void VMDisasm(FILE *out, const VMOP *code, int codesize, const VMScriptFunction
col = 30; col = 30;
} }
printf_wrapper(out, "%*c", 30 - col, ';'); 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); 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) 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) for(int i = 0;i < PROP_PARM_COUNT;++i)
{ {
PROP_STRING_PARM(n, i); PROP_STRING_PARM(n, i);
if (*n != 0) 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) 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) for(int i = 0;i < PROP_PARM_COUNT;++i)
{ {
PROP_STRING_PARM(n, i); PROP_STRING_PARM(n, i);
if (*n != 0) 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 signed short VM_SHALF;
typedef unsigned int VM_UWORD; typedef unsigned int VM_UWORD;
typedef signed int VM_SWORD; typedef signed int VM_SWORD;
typedef VM_UBYTE VM_ATAG;
#define VM_EPSILON (1/65536.0) #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 #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 enum EVMAbortException
{ {
X_OTHER, X_OTHER,
@ -322,7 +300,6 @@ extern const VMOpInfo OpInfo[NUM_OPS];
struct VMReturn struct VMReturn
{ {
void *Location; 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 VM_UBYTE RegType; // Same as VMParam RegType, except REGT_KONST is invalid; only used by asserts
void SetInt(int val) void SetInt(int val)
@ -366,38 +343,37 @@ struct VMReturn
assert(RegType == REGT_STRING); assert(RegType == REGT_STRING);
*(FString *)Location = val; *(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); 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;
TagOfs = 0;
RegType = REGT_INT; RegType = REGT_INT;
} }
void FloatAt(double *loc) void FloatAt(double *loc)
{ {
Location = loc; Location = loc;
TagOfs = 0;
RegType = REGT_FLOAT; RegType = REGT_FLOAT;
} }
void StringAt(FString *loc) void StringAt(FString *loc)
{ {
Location = loc; Location = loc;
TagOfs = 0;
RegType = REGT_STRING; RegType = REGT_STRING;
} }
void PointerAt(void **loc) void PointerAt(void **loc)
{ {
Location = loc; Location = loc;
TagOfs = 0;
RegType = REGT_POINTER; RegType = REGT_POINTER;
} }
VMReturn() { } VMReturn() { }
@ -415,7 +391,7 @@ struct VMValue
union union
{ {
int i; int i;
struct { void *a; int atag; }; void *a;
double f; double f;
struct { int pad[3]; VM_UBYTE Type; }; struct { int pad[3]; VM_UBYTE Type; };
struct { int foo[4]; } biggest; struct { int foo[4]; } biggest;
@ -456,19 +432,11 @@ struct VMValue
VMValue(DObject *v) VMValue(DObject *v)
{ {
a = v; a = v;
atag = ATAG_OBJECT;
Type = REGT_POINTER; Type = REGT_POINTER;
} }
VMValue(void *v) VMValue(void *v)
{ {
a = v; a = v;
atag = ATAG_GENERIC;
Type = REGT_POINTER;
}
VMValue(void *v, int tag)
{
a = v;
atag = tag;
Type = REGT_POINTER; Type = REGT_POINTER;
} }
VMValue &operator=(const VMValue &o) VMValue &operator=(const VMValue &o)
@ -499,7 +467,6 @@ struct VMValue
VMValue &operator=(DObject *v) VMValue &operator=(DObject *v)
{ {
a = v; a = v;
atag = ATAG_OBJECT;
Type = REGT_POINTER; Type = REGT_POINTER;
return *this; return *this;
} }
@ -602,7 +569,7 @@ struct VMFrame
int size = (sizeof(VMFrame) + 15) & ~15; int size = (sizeof(VMFrame) + 15) & ~15;
size += numparam * sizeof(VMValue); size += numparam * sizeof(VMValue);
size += numregf * sizeof(double); size += numregf * sizeof(double);
size += numrega * (sizeof(void *) + sizeof(VM_UBYTE)); size += numrega * sizeof(void *);
size += numregs * sizeof(FString); size += numregs * sizeof(FString);
size += numregd * sizeof(int); size += numregd * sizeof(int);
if (numextra != 0) if (numextra != 0)
@ -613,9 +580,10 @@ struct VMFrame
return size; 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 double *GetRegF() const
@ -633,25 +601,19 @@ struct VMFrame
return (void **)(GetRegS() + NumRegS); return (void **)(GetRegS() + NumRegS);
} }
VM_ATAG *GetRegATag() const int *GetRegD() const
{ {
return (VM_ATAG *)(GetRegD() + NumRegD); return (int *)(GetRegA() + NumRegA);
}
VMValue *GetParam() const
{
assert(((size_t)this & 15) == 0 && "VM frame is unaligned");
return (VMValue *)(((size_t)(this + 1) + 15) & ~15);
} }
void *GetExtra() const void *GetExtra() const
{ {
VM_ATAG *ptag = GetRegATag(); uint8_t *pbeg = (uint8_t*)(GetRegD() + NumRegD);
ptrdiff_t ofs = ptag - (VM_ATAG *)this; ptrdiff_t ofs = pbeg - (uint8_t *)this;
return (VM_UBYTE *)this + ((ofs + NumRegA + 15) & ~15); 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. :( // Calling the individual functions produces suboptimal code. :(
param = GetParam(); param = GetParam();
@ -659,7 +621,6 @@ struct VMFrame
s = (FString *)(f + NumRegF); s = (FString *)(f + NumRegF);
a = (void **)(s + NumRegS); a = (void **)(s + NumRegS);
d = (int *)(a + NumRegA); d = (int *)(a + NumRegA);
atag = (VM_ATAG *)(d + NumRegD);
} }
void InitRegS(); void InitRegS();
@ -669,18 +630,17 @@ struct VMRegisters
{ {
VMRegisters(const VMFrame *frame) VMRegisters(const VMFrame *frame)
{ {
frame->GetAllRegs(d, f, s, a, atag, param); frame->GetAllRegs(d, f, s, a, param);
} }
VMRegisters(const VMRegisters &o) 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; int *d;
double *f; double *f;
FString *s; FString *s;
void **a; void **a;
VM_ATAG *atag;
VMValue *param; VMValue *param;
}; };
@ -703,9 +663,6 @@ public:
~VMScriptFunction(); ~VMScriptFunction();
void Alloc(int numops, int numkonstd, int numkonstf, int numkonsts, int numkonsta, int numlinenumbers); 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; VMOP *Code;
FStatementInfo *LineInfo; FStatementInfo *LineInfo;
FString SourceFileName; FString SourceFileName;
@ -810,14 +767,12 @@ public:
void ParamObject(DObject *obj) void ParamObject(DObject *obj)
{ {
Reg.a[RegA] = obj; Reg.a[RegA] = obj;
Reg.atag[RegA] = ATAG_OBJECT;
RegA++; RegA++;
} }
void ParamPointer(void *ptr, VM_ATAG atag) void ParamPointer(void *ptr)
{ {
Reg.a[RegA] = ptr; Reg.a[RegA] = ptr;
Reg.atag[RegA] = atag;
RegA++; RegA++;
} }
@ -852,8 +807,18 @@ void VMDisasm(FILE *out, const VMOP *code, int codesize, const VMScriptFunction
// variable name <x> at position <p> // variable name <x> at position <p>
void NullParam(const char *varname); void NullParam(const char *varname);
#ifdef _DEBUG
bool AssertObject(void * ob);
#endif
#define PARAM_NULLCHECK(ptr, var) (ptr == nullptr? NullParam(#var), ptr : ptr) #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. // 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_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; #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_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_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_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_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 && (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_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_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_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 && (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_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 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_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; } #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; 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_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, ATAG_GENERIC); 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->SetPointer(state, ATAG_OBJECT); 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_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_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) #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_PROLOGUE; \
PARAM_OBJECT(self, type); 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) \ #define PARAM_SELF_STRUCT_PROLOGUE(type) \
PARAM_PROLOGUE; \ PARAM_PROLOGUE; \
PARAM_POINTER(self, type); PARAM_POINTER(self, type);

View file

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

View file

@ -97,7 +97,7 @@ void VMScriptFunction::Alloc(int numops, int numkonstd, int numkonstf, int numko
numkonstd * sizeof(int) + numkonstd * sizeof(int) +
numkonstf * sizeof(double) + numkonstf * sizeof(double) +
numkonsts * sizeof(FString) + numkonsts * sizeof(FString) +
numkonsta * (sizeof(FVoidObj) + 1) + numkonsta * sizeof(FVoidObj) +
numlinenumbers * sizeof(FStatementInfo)); numlinenumbers * sizeof(FStatementInfo));
Code = (VMOP *)mem; Code = (VMOP *)mem;
mem = (void *)((VMOP *)mem + numops); 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(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, new, RPRPI8, NOP, 0, 0),
xx(NEW_K, new, RPKP, 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(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(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 xx(THROW, throw, THROW, NOP, 0, 0), // A == 0: Throw exception object pB
// A == 1: Throw exception object pkB // A == 1: Throw exception object pkB
// A >= 2: Throw VM exception of type BC // 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 == 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 == 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 // 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 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; Scene = scene;
MainThread = mainThread; MainThread = mainThread;
FrameMemory = std::make_unique<RenderMemory>(); FrameMemory.reset(new RenderMemory());
Viewport = std::make_unique<RenderViewport>(); Viewport.reset(new RenderViewport());
Light = std::make_unique<LightVisibility>(); Light.reset(new LightVisibility());
DrawQueue = std::make_shared<DrawerCommandQueue>(FrameMemory.get()); DrawQueue.reset(new DrawerCommandQueue(FrameMemory.get()));
OpaquePass = std::make_unique<RenderOpaquePass>(this); OpaquePass.reset(new RenderOpaquePass(this));
TranslucentPass = std::make_unique<RenderTranslucentPass>(this); TranslucentPass.reset(new RenderTranslucentPass(this));
SpriteList = std::make_unique<VisibleSpriteList>(); SpriteList.reset(new VisibleSpriteList());
Portal = std::make_unique<RenderPortal>(this); Portal.reset(new RenderPortal(this));
Clip3D = std::make_unique<Clip3DFloors>(this); Clip3D.reset(new Clip3DFloors(this));
PlayerSprites = std::make_unique<RenderPlayerSprites>(this); PlayerSprites.reset(new RenderPlayerSprites(this));
PlaneList = std::make_unique<VisiblePlaneList>(this); PlaneList.reset(new VisiblePlaneList(this));
DrawSegments = std::make_unique<DrawSegmentList>(this); DrawSegments.reset(new DrawSegmentList(this));
ClipSegments = std::make_unique<RenderClipSegment>(); ClipSegments.reset(new RenderClipSegment());
tc_drawers = std::make_unique<SWTruecolorDrawers>(DrawQueue); tc_drawers.reset(new SWTruecolorDrawers(DrawQueue));
pal_drawers = std::make_unique<SWPalDrawers>(DrawQueue); pal_drawers.reset(new SWPalDrawers(DrawQueue));
} }
RenderThread::~RenderThread() RenderThread::~RenderThread()

View file

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

View file

@ -25,6 +25,8 @@ class Inventory : Actor native
native bool bInitEffectFailed; native bool bInitEffectFailed;
meta String PickupMsg; meta String PickupMsg;
meta int GiveQuest; meta int GiveQuest;
meta array<class<Actor> > ForbiddenToPlayerClass;
meta array<class<Actor> > RestrictedToPlayerClass;
property PickupMessage: PickupMsg; property PickupMessage: PickupMsg;
property GiveQuest: GiveQuest; property GiveQuest: GiveQuest;
@ -46,7 +48,6 @@ class Inventory : Actor native
Inventory.PickupMessage "$TXT_DEFAULTPICKUPMSG"; Inventory.PickupMessage "$TXT_DEFAULTPICKUPMSG";
} }
native bool CanPickup(Actor toucher);
native bool DoRespawn(); native bool DoRespawn();
native void BecomeItem(); native void BecomeItem();
native void BecomePickup(); 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 // AInventory :: CallTryPickup