mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-12-03 01:13:22 +00:00
- implemented the basics of a working metadata system.
This will store class meta properties in a separate memory block so that it won't have to muck around with PClass - which made the implementation from the scripting branch relatively useless because extending the data wasn't particularly easy and also not well implemented. This can now be handled just like the defaults.
This commit is contained in:
parent
d5d383ee93
commit
f343d36ea9
9 changed files with 128 additions and 41 deletions
|
@ -2910,6 +2910,11 @@ PClass::~PClass()
|
||||||
M_Free(Defaults);
|
M_Free(Defaults);
|
||||||
Defaults = nullptr;
|
Defaults = nullptr;
|
||||||
}
|
}
|
||||||
|
if (Meta != nullptr)
|
||||||
|
{
|
||||||
|
M_Free(Meta);
|
||||||
|
Meta = nullptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -3047,7 +3052,7 @@ PClass *PClass::FindClass (FName zaname)
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
DObject *PClass::CreateNew() const
|
DObject *PClass::CreateNew()
|
||||||
{
|
{
|
||||||
BYTE *mem = (BYTE *)M_Malloc (Size);
|
BYTE *mem = (BYTE *)M_Malloc (Size);
|
||||||
assert (mem != nullptr);
|
assert (mem != nullptr);
|
||||||
|
@ -3064,7 +3069,7 @@ DObject *PClass::CreateNew() const
|
||||||
}
|
}
|
||||||
ConstructNative (mem);
|
ConstructNative (mem);
|
||||||
((DObject *)mem)->SetClass (const_cast<PClass *>(this));
|
((DObject *)mem)->SetClass (const_cast<PClass *>(this));
|
||||||
InitializeSpecials(mem, Defaults);
|
InitializeSpecials(mem, Defaults, &PClass::SpecialInits);
|
||||||
return (DObject *)mem;
|
return (DObject *)mem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3076,7 +3081,7 @@ DObject *PClass::CreateNew() const
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
void PClass::InitializeSpecials(void *addr, void *defaults) const
|
void PClass::InitializeSpecials(void *addr, void *defaults, TArray<FTypeAndOffset> PClass::*Inits)
|
||||||
{
|
{
|
||||||
// Once we reach a native class, we can stop going up the family tree,
|
// Once we reach a native class, we can stop going up the family tree,
|
||||||
// since native classes handle initialization natively.
|
// since native classes handle initialization natively.
|
||||||
|
@ -3085,8 +3090,8 @@ void PClass::InitializeSpecials(void *addr, void *defaults) const
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
assert(ParentClass != nullptr);
|
assert(ParentClass != nullptr);
|
||||||
ParentClass->InitializeSpecials(addr, defaults);
|
ParentClass->InitializeSpecials(addr, defaults, Inits);
|
||||||
for (auto tao : SpecialInits)
|
for (auto tao : (this->*Inits))
|
||||||
{
|
{
|
||||||
tao.first->InitializeValue((char*)addr + tao.second, defaults == nullptr? nullptr : ((char*)defaults) + tao.second);
|
tao.first->InitializeValue((char*)addr + tao.second, defaults == nullptr? nullptr : ((char*)defaults) + tao.second);
|
||||||
}
|
}
|
||||||
|
@ -3101,7 +3106,7 @@ void PClass::InitializeSpecials(void *addr, void *defaults) const
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
void PClass::DestroySpecials(void *addr) const
|
void PClass::DestroySpecials(void *addr)
|
||||||
{
|
{
|
||||||
// Once we reach a native class, we can stop going up the family tree,
|
// Once we reach a native class, we can stop going up the family tree,
|
||||||
// since native classes handle deinitialization natively.
|
// since native classes handle deinitialization natively.
|
||||||
|
@ -3160,7 +3165,6 @@ void PClass::InitializeDefaults()
|
||||||
optr->ObjNext = nullptr;
|
optr->ObjNext = nullptr;
|
||||||
optr->SetClass(this);
|
optr->SetClass(this);
|
||||||
|
|
||||||
|
|
||||||
// Copy the defaults from the parent but leave the DObject part alone because it contains important data.
|
// Copy the defaults from the parent but leave the DObject part alone because it contains important data.
|
||||||
if (ParentClass->Defaults != nullptr)
|
if (ParentClass->Defaults != nullptr)
|
||||||
{
|
{
|
||||||
|
@ -3174,19 +3178,31 @@ void PClass::InitializeDefaults()
|
||||||
{
|
{
|
||||||
memset(Defaults + sizeof(DObject), 0, Size - sizeof(DObject));
|
memset(Defaults + sizeof(DObject), 0, Size - sizeof(DObject));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (MetaSize != 0)
|
||||||
|
{
|
||||||
|
Meta = (BYTE*)M_Malloc(MetaSize);
|
||||||
|
memset(Meta, 0, MetaSize);
|
||||||
|
if (ParentClass->MetaSize > 0) memcpy(Meta, ParentClass->Meta, ParentClass->MetaSize);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bRuntimeClass)
|
if (bRuntimeClass)
|
||||||
{
|
{
|
||||||
// Copy parent values from the parent defaults.
|
// Copy parent values from the parent defaults.
|
||||||
assert(ParentClass != nullptr);
|
assert(ParentClass != nullptr);
|
||||||
if (Defaults != nullptr) ParentClass->InitializeSpecials(Defaults, ParentClass->Defaults);
|
if (Defaults != nullptr) ParentClass->InitializeSpecials(Defaults, ParentClass->Defaults, &PClass::SpecialInits);
|
||||||
|
if (Meta != nullptr) ParentClass->InitializeSpecials(Meta, ParentClass->Meta, &PClass::MetaInits);
|
||||||
for (const PField *field : Fields)
|
for (const PField *field : Fields)
|
||||||
{
|
{
|
||||||
if (!(field->Flags & VARF_Native))
|
if (!(field->Flags & VARF_Native) && !(field->Flags & VARF_Meta))
|
||||||
{
|
{
|
||||||
field->Type->SetDefaultValue(Defaults, unsigned(field->Offset), &SpecialInits);
|
field->Type->SetDefaultValue(Defaults, unsigned(field->Offset), &SpecialInits);
|
||||||
}
|
}
|
||||||
|
if (!(field->Flags & VARF_Native) && (field->Flags & VARF_Meta))
|
||||||
|
{
|
||||||
|
field->Type->SetDefaultValue(Meta, unsigned(field->Offset), &MetaInits);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3264,6 +3280,39 @@ PClass *PClass::CreateDerivedClass(FName name, unsigned int size)
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// PStruct :: AddField
|
||||||
|
//
|
||||||
|
// Appends a new metadata field to the end of a struct. Returns either the new field
|
||||||
|
// or nullptr if a symbol by that name already exists.
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
PField *PClass::AddMetaField(FName name, PType *type, DWORD flags)
|
||||||
|
{
|
||||||
|
PField *field = new PField(name, type, flags);
|
||||||
|
|
||||||
|
// The new field is added to the end of this struct, alignment permitting.
|
||||||
|
field->Offset = (MetaSize + (type->Align - 1)) & ~(type->Align - 1);
|
||||||
|
|
||||||
|
// Enlarge this struct to enclose the new field.
|
||||||
|
MetaSize = unsigned(field->Offset + type->Size);
|
||||||
|
|
||||||
|
// This struct's alignment is the same as the largest alignment of any of
|
||||||
|
// its fields.
|
||||||
|
Align = MAX(Align, type->Align);
|
||||||
|
|
||||||
|
if (Symbols.AddSymbol(field) == nullptr)
|
||||||
|
{ // name is already in use
|
||||||
|
field->Destroy();
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
Fields.Push(field);
|
||||||
|
|
||||||
|
return field;
|
||||||
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// PClass :: AddField
|
// PClass :: AddField
|
||||||
|
@ -3272,6 +3321,8 @@ PClass *PClass::CreateDerivedClass(FName name, unsigned int size)
|
||||||
|
|
||||||
PField *PClass::AddField(FName name, PType *type, DWORD flags)
|
PField *PClass::AddField(FName name, PType *type, DWORD flags)
|
||||||
{
|
{
|
||||||
|
if (!(flags & VARF_Meta))
|
||||||
|
{
|
||||||
unsigned oldsize = Size;
|
unsigned oldsize = Size;
|
||||||
PField *field = Super::AddField(name, type, flags);
|
PField *field = Super::AddField(name, type, flags);
|
||||||
|
|
||||||
|
@ -3284,6 +3335,22 @@ PField *PClass::AddField(FName name, PType *type, DWORD flags)
|
||||||
memset(Defaults + oldsize, 0, Size - oldsize);
|
memset(Defaults + oldsize, 0, Size - oldsize);
|
||||||
}
|
}
|
||||||
return field;
|
return field;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
unsigned oldsize = MetaSize;
|
||||||
|
PField *field = AddMetaField(name, type, flags);
|
||||||
|
|
||||||
|
// Only initialize the defaults if they have already been created.
|
||||||
|
// For ZScript this is not the case, it will first define all fields before
|
||||||
|
// setting up any defaults for any class.
|
||||||
|
if (field != nullptr && !(flags & VARF_Native) && Meta != nullptr)
|
||||||
|
{
|
||||||
|
Meta = (BYTE *)M_Realloc(Meta, MetaSize);
|
||||||
|
memset(Meta + oldsize, 0, MetaSize - oldsize);
|
||||||
|
}
|
||||||
|
return field;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
|
@ -557,12 +557,13 @@ enum
|
||||||
class PClass : public PNativeStruct
|
class PClass : public PNativeStruct
|
||||||
{
|
{
|
||||||
DECLARE_CLASS(PClass, PNativeStruct);
|
DECLARE_CLASS(PClass, PNativeStruct);
|
||||||
protected:
|
|
||||||
// We unravel _WITH_META here just as we did for PType.
|
// We unravel _WITH_META here just as we did for PType.
|
||||||
TArray<FTypeAndOffset> SpecialInits;
|
protected:
|
||||||
|
TArray<FTypeAndOffset> MetaInits;
|
||||||
void Derive(PClass *newclass, FName name);
|
void Derive(PClass *newclass, FName name);
|
||||||
void InitializeSpecials(void *addr, void *defaults) const;
|
void InitializeSpecials(void *addr, void *defaults, TArray<FTypeAndOffset> PClass::*Inits);
|
||||||
void SetSuper();
|
void SetSuper();
|
||||||
|
PField *AddMetaField(FName name, PType *type, DWORD flags);
|
||||||
public:
|
public:
|
||||||
void WriteValue(FSerializer &ar, const char *key,const void *addr) const override;
|
void WriteValue(FSerializer &ar, const char *key,const void *addr) const override;
|
||||||
void WriteAllFields(FSerializer &ar, const void *addr) const;
|
void WriteAllFields(FSerializer &ar, const void *addr) const;
|
||||||
|
@ -577,11 +578,14 @@ public:
|
||||||
static void StaticBootstrap();
|
static void StaticBootstrap();
|
||||||
|
|
||||||
// Per-class information -------------------------------------
|
// Per-class information -------------------------------------
|
||||||
|
TArray<FTypeAndOffset> SpecialInits;
|
||||||
PClass *ParentClass; // the class this class derives from
|
PClass *ParentClass; // the class this class derives from
|
||||||
const size_t *Pointers; // object pointers defined by this class *only*
|
const size_t *Pointers; // object pointers defined by this class *only*
|
||||||
const size_t *FlatPointers; // object pointers defined by this class and all its superclasses; not initialized by default
|
const size_t *FlatPointers; // object pointers defined by this class and all its superclasses; not initialized by default
|
||||||
const size_t *ArrayPointers; // dynamic arrays containing object pointers.
|
const size_t *ArrayPointers; // dynamic arrays containing object pointers.
|
||||||
BYTE *Defaults;
|
BYTE *Defaults;
|
||||||
|
BYTE *Meta; // Per-class static script data
|
||||||
|
unsigned MetaSize;
|
||||||
bool bRuntimeClass; // class was defined at run-time, not compile-time
|
bool bRuntimeClass; // class was defined at run-time, not compile-time
|
||||||
bool bExported; // This type has been declared in a script
|
bool bExported; // This type has been declared in a script
|
||||||
bool bDecorateClass; // may be subject to some idiosyncracies due to DECORATE backwards compatibility
|
bool bDecorateClass; // may be subject to some idiosyncracies due to DECORATE backwards compatibility
|
||||||
|
@ -593,13 +597,13 @@ public:
|
||||||
PClass();
|
PClass();
|
||||||
~PClass();
|
~PClass();
|
||||||
void InsertIntoHash();
|
void InsertIntoHash();
|
||||||
DObject *CreateNew() const;
|
DObject *CreateNew();
|
||||||
PClass *CreateDerivedClass(FName name, unsigned int size);
|
PClass *CreateDerivedClass(FName name, unsigned int size);
|
||||||
PField *AddField(FName name, PType *type, DWORD flags=0) override;
|
PField *AddField(FName name, PType *type, DWORD flags=0) override;
|
||||||
void InitializeActorInfo();
|
void InitializeActorInfo();
|
||||||
void BuildFlatPointers();
|
void BuildFlatPointers();
|
||||||
void BuildArrayPointers();
|
void BuildArrayPointers();
|
||||||
void DestroySpecials(void *addr) const;
|
void DestroySpecials(void *addr);
|
||||||
const PClass *NativeClass() const;
|
const PClass *NativeClass() const;
|
||||||
|
|
||||||
// Returns true if this type is an ancestor of (or same as) the passed type.
|
// Returns true if this type is an ancestor of (or same as) the passed type.
|
||||||
|
|
|
@ -58,15 +58,15 @@ enum EScrollDir
|
||||||
};
|
};
|
||||||
|
|
||||||
// actions that don't create objects
|
// actions that don't create objects
|
||||||
#define WIPER_ID ((const PClass*)intptr_t(-1))
|
#define WIPER_ID ((PClass*)intptr_t(-1))
|
||||||
#define TITLE_ID ((const PClass*)intptr_t(-2))
|
#define TITLE_ID ((PClass*)intptr_t(-2))
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
struct FIntermissionAction
|
struct FIntermissionAction
|
||||||
{
|
{
|
||||||
int mSize;
|
int mSize;
|
||||||
const PClass *mClass;
|
PClass *mClass;
|
||||||
FString mMusic;
|
FString mMusic;
|
||||||
int mMusicOrder;
|
int mMusicOrder;
|
||||||
int mCdTrack;
|
int mCdTrack;
|
||||||
|
|
|
@ -472,7 +472,7 @@ void M_SetMenu(FName menu, int param)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
const PClass *menuclass = PClass::FindClass(menu);
|
PClass *menuclass = PClass::FindClass(menu);
|
||||||
if (menuclass != nullptr)
|
if (menuclass != nullptr)
|
||||||
{
|
{
|
||||||
if (menuclass->IsDescendantOf("GenericMenu"))
|
if (menuclass->IsDescendantOf("GenericMenu"))
|
||||||
|
|
|
@ -6371,7 +6371,7 @@ ExpEmit FxClassDefaults::Emit(VMFunctionBuilder *build)
|
||||||
ExpEmit ob = obj->Emit(build);
|
ExpEmit ob = obj->Emit(build);
|
||||||
ob.Free(build);
|
ob.Free(build);
|
||||||
ExpEmit meta(build, REGT_POINTER);
|
ExpEmit meta(build, REGT_POINTER);
|
||||||
build->Emit(OP_META, meta.RegNum, ob.RegNum);
|
build->Emit(OP_CLSS, meta.RegNum, ob.RegNum);
|
||||||
build->Emit(OP_LOS, meta.RegNum, meta.RegNum, build->GetConstantInt(myoffsetof(PClass, Defaults)));
|
build->Emit(OP_LOS, meta.RegNum, meta.RegNum, build->GetConstantInt(myoffsetof(PClass, Defaults)));
|
||||||
return meta;
|
return meta;
|
||||||
|
|
||||||
|
@ -6805,7 +6805,7 @@ ExpEmit FxStructMember::Emit(VMFunctionBuilder *build)
|
||||||
{
|
{
|
||||||
obj.Free(build);
|
obj.Free(build);
|
||||||
ExpEmit meta(build, REGT_POINTER);
|
ExpEmit meta(build, REGT_POINTER);
|
||||||
build->Emit(OP_META, meta.RegNum, obj.RegNum);
|
build->Emit(membervar->Flags & VARF_Native? OP_CLSS : OP_META, meta.RegNum, obj.RegNum);
|
||||||
obj = meta;
|
obj = meta;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8832,7 +8832,7 @@ ExpEmit FxGetClass::Emit(VMFunctionBuilder *build)
|
||||||
ExpEmit op = Self->Emit(build);
|
ExpEmit op = Self->Emit(build);
|
||||||
op.Free(build);
|
op.Free(build);
|
||||||
ExpEmit to(build, REGT_POINTER);
|
ExpEmit to(build, REGT_POINTER);
|
||||||
build->Emit(OP_META, to.RegNum, op.RegNum);
|
build->Emit(OP_CLSS, to.RegNum, op.RegNum);
|
||||||
return to;
|
return to;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8873,7 +8873,7 @@ ExpEmit FxGetParentClass::Emit(VMFunctionBuilder *build)
|
||||||
if (Self->IsObject())
|
if (Self->IsObject())
|
||||||
{
|
{
|
||||||
ExpEmit to(build, REGT_POINTER);
|
ExpEmit to(build, REGT_POINTER);
|
||||||
build->Emit(OP_META, to.RegNum, op.RegNum);
|
build->Emit(OP_CLSS, to.RegNum, op.RegNum);
|
||||||
op = to;
|
op = to;
|
||||||
op.Free(build);
|
op.Free(build);
|
||||||
}
|
}
|
||||||
|
|
|
@ -826,10 +826,17 @@ static void DispatchScriptProperty(FScanner &sc, PProperty *prop, AActor *defaul
|
||||||
|
|
||||||
if (i > 0) sc.MustGetStringName(",");
|
if (i > 0) sc.MustGetStringName(",");
|
||||||
if (f->Flags & VARF_Meta)
|
if (f->Flags & VARF_Meta)
|
||||||
|
{
|
||||||
|
if (f->Flags & VARF_Native)
|
||||||
{
|
{
|
||||||
addr = ((char*)bag.Info) + f->Offset;
|
addr = ((char*)bag.Info) + f->Offset;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
addr = ((char*)bag.Info->Meta) + f->Offset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
addr = ((char*)defaults) + f->Offset;
|
addr = ((char*)defaults) + f->Offset;
|
||||||
}
|
}
|
||||||
|
|
|
@ -109,12 +109,18 @@ begin:
|
||||||
reg.atag[a] = ATAG_GENERIC; // using ATAG_FRAMEPOINTER will cause endless asserts.
|
reg.atag[a] = ATAG_GENERIC; // using ATAG_FRAMEPOINTER will cause endless asserts.
|
||||||
NEXTOP;
|
NEXTOP;
|
||||||
|
|
||||||
OP(META):
|
OP(CLSS):
|
||||||
ASSERTA(a); ASSERTO(B);
|
ASSERTA(a); ASSERTO(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;
|
reg.atag[a] = ATAG_OBJECT;
|
||||||
NEXTOP;
|
NEXTOP;
|
||||||
|
|
||||||
|
OP(META):
|
||||||
|
ASSERTA(a); ASSERTO(B);
|
||||||
|
reg.a[a] = ((DObject*)reg.a[B])->GetClass()->Meta; // I wish this could be done without a special opcode but there's really no good way to guarantee initialization of the Class pointer...
|
||||||
|
reg.atag[a] = ATAG_OBJECT;
|
||||||
|
NEXTOP;
|
||||||
|
|
||||||
OP(LB):
|
OP(LB):
|
||||||
ASSERTD(a); ASSERTA(B); ASSERTKD(C);
|
ASSERTD(a); ASSERTA(B); ASSERTKD(C);
|
||||||
GETADDR(PB,KC,X_READ_NIL);
|
GETADDR(PB,KC,X_READ_NIL);
|
||||||
|
|
|
@ -23,7 +23,8 @@ xx(LKF_R, lk, RFRII8, NOP, 0, 0), // load float constant indexed
|
||||||
xx(LKS_R, lk, RSRII8, NOP, 0, 0), // load string constant indexed
|
xx(LKS_R, lk, RSRII8, NOP, 0, 0), // load string constant indexed
|
||||||
xx(LKP_R, lk, RPRII8, NOP, 0, 0), // load pointer constant indexed
|
xx(LKP_R, lk, RPRII8, NOP, 0, 0), // load pointer constant indexed
|
||||||
xx(LFP, lf, LFP, NOP, 0, 0), // load frame pointer
|
xx(LFP, lf, LFP, NOP, 0, 0), // load frame pointer
|
||||||
xx(META, meta, RPRP, NOP, 0, 0), // load a class's meta class address
|
xx(META, meta, RPRP, NOP, 0, 0), // load a class's meta data address
|
||||||
|
xx(CLSS, clss, RPRP, NOP, 0, 0), // load a class's descriptor address
|
||||||
|
|
||||||
// Load from memory. rA = *(rB + rkC)
|
// Load from memory. rA = *(rB + rkC)
|
||||||
xx(LB, lb, RIRPKI, LB_R, 4, REGT_INT), // load byte
|
xx(LB, lb, RIRPKI, LB_R, 4, REGT_INT), // load byte
|
||||||
|
|
|
@ -1070,11 +1070,6 @@ bool ZCCCompiler::CompileFields(PStruct *type, TArray<ZCC_VarDeclarator *> &Fiel
|
||||||
if (field->Flags & ZCC_Meta)
|
if (field->Flags & ZCC_Meta)
|
||||||
{
|
{
|
||||||
varflags |= VARF_Meta | VARF_Static | VARF_ReadOnly; // metadata implies readonly
|
varflags |= VARF_Meta | VARF_Static | VARF_ReadOnly; // metadata implies readonly
|
||||||
if (!(field->Flags & ZCC_Native))
|
|
||||||
{
|
|
||||||
// Non-native meta data is not implemented yet and requires some groundwork in the class copy code.
|
|
||||||
Error(field, "Metadata member %s must be native", FName(field->Names->Name).GetChars());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (field->Type->ArraySize != nullptr)
|
if (field->Type->ArraySize != nullptr)
|
||||||
|
@ -1691,10 +1686,17 @@ void ZCCCompiler::DispatchScriptProperty(PProperty *prop, ZCC_PropertyStmt *prop
|
||||||
void *addr;
|
void *addr;
|
||||||
|
|
||||||
if (f->Flags & VARF_Meta)
|
if (f->Flags & VARF_Meta)
|
||||||
|
{
|
||||||
|
if (f->Flags & VARF_Native)
|
||||||
{
|
{
|
||||||
addr = ((char*)bag.Info) + f->Offset;
|
addr = ((char*)bag.Info) + f->Offset;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
addr = ((char*)bag.Info->Meta) + f->Offset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
addr = ((char*)defaults) + f->Offset;
|
addr = ((char*)defaults) + f->Offset;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue