mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-11 15:21:51 +00:00
Merge branch 'floatcvt' of https://github.com/rheit/zdoom into floatcvt
This commit is contained in:
commit
7486e24cd9
13 changed files with 1221 additions and 102 deletions
101
src/dobject.cpp
101
src/dobject.cpp
|
@ -257,46 +257,50 @@ DObject::DObject (PClass *inClass)
|
||||||
|
|
||||||
DObject::~DObject ()
|
DObject::~DObject ()
|
||||||
{
|
{
|
||||||
if (!(ObjectFlags & OF_Cleanup) && !PClass::bShutdown)
|
if (!PClass::bShutdown)
|
||||||
{
|
{
|
||||||
DObject **probe;
|
|
||||||
PClass *type = GetClass();
|
PClass *type = GetClass();
|
||||||
|
if (!(ObjectFlags & OF_Cleanup) && !PClass::bShutdown)
|
||||||
if (!(ObjectFlags & OF_YesReallyDelete))
|
|
||||||
{
|
{
|
||||||
Printf ("Warning: '%s' is freed outside the GC process.\n",
|
DObject **probe;
|
||||||
type != NULL ? type->TypeName.GetChars() : "==some object==");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find all pointers that reference this object and NULL them.
|
if (!(ObjectFlags & OF_YesReallyDelete))
|
||||||
StaticPointerSubstitution(this, NULL);
|
|
||||||
|
|
||||||
// Now unlink this object from the GC list.
|
|
||||||
for (probe = &GC::Root; *probe != NULL; probe = &((*probe)->ObjNext))
|
|
||||||
{
|
|
||||||
if (*probe == this)
|
|
||||||
{
|
{
|
||||||
*probe = ObjNext;
|
Printf("Warning: '%s' is freed outside the GC process.\n",
|
||||||
if (&ObjNext == GC::SweepPos)
|
type != NULL ? type->TypeName.GetChars() : "==some object==");
|
||||||
{
|
|
||||||
GC::SweepPos = probe;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// If it's gray, also unlink it from the gray list.
|
// Find all pointers that reference this object and NULL them.
|
||||||
if (this->IsGray())
|
StaticPointerSubstitution(this, NULL);
|
||||||
{
|
|
||||||
for (probe = &GC::Gray; *probe != NULL; probe = &((*probe)->GCNext))
|
// Now unlink this object from the GC list.
|
||||||
|
for (probe = &GC::Root; *probe != NULL; probe = &((*probe)->ObjNext))
|
||||||
{
|
{
|
||||||
if (*probe == this)
|
if (*probe == this)
|
||||||
{
|
{
|
||||||
*probe = GCNext;
|
*probe = ObjNext;
|
||||||
|
if (&ObjNext == GC::SweepPos)
|
||||||
|
{
|
||||||
|
GC::SweepPos = probe;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If it's gray, also unlink it from the gray list.
|
||||||
|
if (this->IsGray())
|
||||||
|
{
|
||||||
|
for (probe = &GC::Gray; *probe != NULL; probe = &((*probe)->GCNext))
|
||||||
|
{
|
||||||
|
if (*probe == this)
|
||||||
|
{
|
||||||
|
*probe = GCNext;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
type->DestroySpecials(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -417,46 +421,15 @@ void DObject::SerializeUserVars(FArchive &arc)
|
||||||
|
|
||||||
if (arc.IsStoring())
|
if (arc.IsStoring())
|
||||||
{
|
{
|
||||||
// Write all user variables.
|
// Write all fields that aren't serialized by native code.
|
||||||
for (; symt != NULL; symt = symt->ParentSymbolTable)
|
GetClass()->WriteValue(arc, this);
|
||||||
{
|
}
|
||||||
PSymbolTable::MapType::Iterator it(symt->Symbols);
|
else if (SaveVersion >= 4535)
|
||||||
PSymbolTable::MapType::Pair *pair;
|
{
|
||||||
|
GetClass()->ReadValue(arc, this);
|
||||||
while (it.NextPair(pair))
|
|
||||||
{
|
|
||||||
PField *var = dyn_cast<PField>(pair->Value);
|
|
||||||
if (var != NULL && !(var->Flags & VARF_Native))
|
|
||||||
{
|
|
||||||
PType *type = var->Type;
|
|
||||||
PArray *arraytype = dyn_cast<PArray>(type);
|
|
||||||
if (arraytype == NULL)
|
|
||||||
{
|
|
||||||
count = 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
count = arraytype->ElementCount;
|
|
||||||
type = arraytype->ElementType;
|
|
||||||
}
|
|
||||||
assert(type == TypeSInt32);
|
|
||||||
varloc = (int *)(reinterpret_cast<BYTE *>(this) + var->Offset);
|
|
||||||
|
|
||||||
arc << var->SymbolName;
|
|
||||||
arc.WriteCount(count);
|
|
||||||
for (j = 0; j < count; ++j)
|
|
||||||
{
|
|
||||||
arc << varloc[j];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Write terminator.
|
|
||||||
varname = NAME_None;
|
|
||||||
arc << varname;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{ // Old version that only deals with ints
|
||||||
// Read user variables until 'None' is encountered.
|
// Read user variables until 'None' is encountered.
|
||||||
arc << varname;
|
arc << varname;
|
||||||
while (varname != NAME_None)
|
while (varname != NAME_None)
|
||||||
|
|
979
src/dobjtype.cpp
979
src/dobjtype.cpp
File diff suppressed because it is too large
Load diff
111
src/dobjtype.h
111
src/dobjtype.h
|
@ -7,6 +7,8 @@
|
||||||
|
|
||||||
#include "vm.h"
|
#include "vm.h"
|
||||||
|
|
||||||
|
typedef std::pair<const class PType *, unsigned> FTypeAndOffset;
|
||||||
|
|
||||||
// Variable/parameter/field flags -------------------------------------------
|
// Variable/parameter/field flags -------------------------------------------
|
||||||
|
|
||||||
// Making all these different storage types use a common set of flags seems
|
// Making all these different storage types use a common set of flags seems
|
||||||
|
@ -186,6 +188,36 @@ public:
|
||||||
|
|
||||||
int FindConversion(PType *target, const Conversion **slots, int numslots);
|
int FindConversion(PType *target, const Conversion **slots, int numslots);
|
||||||
|
|
||||||
|
// Writes the value of a variable of this type at (addr) to an archive, preceded by
|
||||||
|
// a tag indicating its type. The tag is there so that variable types can be changed
|
||||||
|
// without completely breaking savegames, provided that the change isn't between
|
||||||
|
// totally unrelated types.
|
||||||
|
virtual void WriteValue(FArchive &ar, const void *addr) const;
|
||||||
|
|
||||||
|
// Returns true if the stored value was compatible. False otherwise.
|
||||||
|
// If the value was incompatible, then the memory at *addr is unchanged.
|
||||||
|
virtual bool ReadValue(FArchive &ar, void *addr) const;
|
||||||
|
|
||||||
|
// Skips over a value written with WriteValue
|
||||||
|
static void SkipValue(FArchive &ar);
|
||||||
|
static void SkipValue(FArchive &ar, int tag);
|
||||||
|
|
||||||
|
// Sets the default value for this type at (base + offset)
|
||||||
|
// If the default value is binary 0, then this function doesn't need
|
||||||
|
// to do anything, because PClass::Extend() takes care of that.
|
||||||
|
//
|
||||||
|
// The stroffs array is so that types that need special initialization
|
||||||
|
// and destruction (e.g. strings) can add their offsets to it for special
|
||||||
|
// initialization when the object is created and destruction when the
|
||||||
|
// object is destroyed.
|
||||||
|
virtual void SetDefaultValue(void *base, unsigned offset, TArray<FTypeAndOffset> *special=NULL) const;
|
||||||
|
|
||||||
|
// Initialize the value, if needed (e.g. strings)
|
||||||
|
virtual void InitializeValue(void *addr, const void *def) const;
|
||||||
|
|
||||||
|
// Destroy the value, if needed (e.g. strings)
|
||||||
|
virtual void DestroyValue(void *addr) const;
|
||||||
|
|
||||||
// Sets the value of a variable of this type at (addr)
|
// Sets the value of a variable of this type at (addr)
|
||||||
virtual void SetValue(void *addr, int val);
|
virtual void SetValue(void *addr, int val);
|
||||||
virtual void SetValue(void *addr, double val);
|
virtual void SetValue(void *addr, double val);
|
||||||
|
@ -321,6 +353,9 @@ class PInt : public PBasicType
|
||||||
public:
|
public:
|
||||||
PInt(unsigned int size, bool unsign);
|
PInt(unsigned int size, bool unsign);
|
||||||
|
|
||||||
|
void WriteValue(FArchive &ar, const void *addr) const override;
|
||||||
|
bool ReadValue(FArchive &ar, void *addr) const override;
|
||||||
|
|
||||||
virtual void SetValue(void *addr, int val);
|
virtual void SetValue(void *addr, int val);
|
||||||
virtual void SetValue(void *addr, double val);
|
virtual void SetValue(void *addr, double val);
|
||||||
virtual int GetValueInt(void *addr) const;
|
virtual int GetValueInt(void *addr) const;
|
||||||
|
@ -347,6 +382,9 @@ class PFloat : public PBasicType
|
||||||
public:
|
public:
|
||||||
PFloat(unsigned int size);
|
PFloat(unsigned int size);
|
||||||
|
|
||||||
|
void WriteValue(FArchive &ar, const void *addr) const override;
|
||||||
|
bool ReadValue(FArchive &ar, void *addr) const override;
|
||||||
|
|
||||||
virtual void SetValue(void *addr, int val);
|
virtual void SetValue(void *addr, int val);
|
||||||
virtual void SetValue(void *addr, double val);
|
virtual void SetValue(void *addr, double val);
|
||||||
virtual int GetValueInt(void *addr) const;
|
virtual int GetValueInt(void *addr) const;
|
||||||
|
@ -381,6 +419,12 @@ public:
|
||||||
PString();
|
PString();
|
||||||
|
|
||||||
virtual int GetRegType() const;
|
virtual int GetRegType() const;
|
||||||
|
|
||||||
|
void WriteValue(FArchive &ar, const void *addr) const override;
|
||||||
|
bool ReadValue(FArchive &ar, void *addr) const override;
|
||||||
|
void SetDefaultValue(void *base, unsigned offset, TArray<FTypeAndOffset> *special=NULL) const override;
|
||||||
|
void InitializeValue(void *addr, const void *def) const override;
|
||||||
|
void DestroyValue(void *addr) const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Variations of integer types ----------------------------------------------
|
// Variations of integer types ----------------------------------------------
|
||||||
|
@ -390,6 +434,9 @@ class PName : public PInt
|
||||||
DECLARE_CLASS(PName, PInt);
|
DECLARE_CLASS(PName, PInt);
|
||||||
public:
|
public:
|
||||||
PName();
|
PName();
|
||||||
|
|
||||||
|
void WriteValue(FArchive &ar, const void *addr) const override;
|
||||||
|
bool ReadValue(FArchive &ar, void *addr) const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class PSound : public PInt
|
class PSound : public PInt
|
||||||
|
@ -397,6 +444,9 @@ class PSound : public PInt
|
||||||
DECLARE_CLASS(PSound, PInt);
|
DECLARE_CLASS(PSound, PInt);
|
||||||
public:
|
public:
|
||||||
PSound();
|
PSound();
|
||||||
|
|
||||||
|
void WriteValue(FArchive &ar, const void *addr) const override;
|
||||||
|
bool ReadValue(FArchive &ar, void *addr) const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class PColor : public PInt
|
class PColor : public PInt
|
||||||
|
@ -414,6 +464,9 @@ class PStatePointer : public PBasicType
|
||||||
public:
|
public:
|
||||||
PStatePointer();
|
PStatePointer();
|
||||||
|
|
||||||
|
void WriteValue(FArchive &ar, const void *addr) const override;
|
||||||
|
bool ReadValue(FArchive &ar, void *addr) const override;
|
||||||
|
|
||||||
virtual int GetStoreOp() const;
|
virtual int GetStoreOp() const;
|
||||||
virtual int GetLoadOp() const;
|
virtual int GetLoadOp() const;
|
||||||
virtual int GetRegType() const;
|
virtual int GetRegType() const;
|
||||||
|
@ -434,6 +487,10 @@ public:
|
||||||
|
|
||||||
virtual bool IsMatch(intptr_t id1, intptr_t id2) const;
|
virtual bool IsMatch(intptr_t id1, intptr_t id2) const;
|
||||||
virtual void GetTypeIDs(intptr_t &id1, intptr_t &id2) const;
|
virtual void GetTypeIDs(intptr_t &id1, intptr_t &id2) const;
|
||||||
|
|
||||||
|
void WriteValue(FArchive &ar, const void *addr) const override;
|
||||||
|
bool ReadValue(FArchive &ar, void *addr) const override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
PPointer();
|
PPointer();
|
||||||
};
|
};
|
||||||
|
@ -500,6 +557,12 @@ public:
|
||||||
|
|
||||||
virtual bool IsMatch(intptr_t id1, intptr_t id2) const;
|
virtual bool IsMatch(intptr_t id1, intptr_t id2) const;
|
||||||
virtual void GetTypeIDs(intptr_t &id1, intptr_t &id2) const;
|
virtual void GetTypeIDs(intptr_t &id1, intptr_t &id2) const;
|
||||||
|
|
||||||
|
void WriteValue(FArchive &ar, const void *addr) const override;
|
||||||
|
bool ReadValue(FArchive &ar, void *addr) const override;
|
||||||
|
|
||||||
|
void SetDefaultValue(void *base, unsigned offset, TArray<FTypeAndOffset> *special) const override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
PArray();
|
PArray();
|
||||||
};
|
};
|
||||||
|
@ -554,9 +617,16 @@ public:
|
||||||
|
|
||||||
TArray<PField *> Fields;
|
TArray<PField *> Fields;
|
||||||
|
|
||||||
PField *AddField(FName name, PType *type, DWORD flags=0);
|
virtual PField *AddField(FName name, PType *type, DWORD flags=0);
|
||||||
|
|
||||||
size_t PropagateMark();
|
size_t PropagateMark();
|
||||||
|
|
||||||
|
void WriteValue(FArchive &ar, const void *addr) const override;
|
||||||
|
bool ReadValue(FArchive &ar, void *addr) const override;
|
||||||
|
void SetDefaultValue(void *base, unsigned offset, TArray<FTypeAndOffset> *specials) const override;
|
||||||
|
|
||||||
|
static void WriteFields(FArchive &ar, const void *addr, const TArray<PField *> &fields);
|
||||||
|
bool ReadFields(FArchive &ar, void *addr) const;
|
||||||
protected:
|
protected:
|
||||||
PStruct();
|
PStruct();
|
||||||
};
|
};
|
||||||
|
@ -614,11 +684,16 @@ class PClass : public PStruct
|
||||||
protected:
|
protected:
|
||||||
// We unravel _WITH_META here just as we did for PType.
|
// We unravel _WITH_META here just as we did for PType.
|
||||||
enum { MetaClassNum = CLASSREG_PClassClass };
|
enum { MetaClassNum = CLASSREG_PClassClass };
|
||||||
|
TArray<FTypeAndOffset> SpecialInits;
|
||||||
virtual void Derive(PClass *newclass);
|
virtual void Derive(PClass *newclass);
|
||||||
|
void InitializeSpecials(void *addr) const;
|
||||||
public:
|
public:
|
||||||
typedef PClassClass MetaClass;
|
typedef PClassClass MetaClass;
|
||||||
MetaClass *GetClass() const;
|
MetaClass *GetClass() const;
|
||||||
|
|
||||||
|
void WriteValue(FArchive &ar, const void *addr) const override;
|
||||||
|
bool ReadValue(FArchive &ar, void *addr) const override;
|
||||||
|
|
||||||
virtual void DeriveData(PClass *newclass) {}
|
virtual void DeriveData(PClass *newclass) {}
|
||||||
static void StaticInit();
|
static void StaticInit();
|
||||||
static void StaticShutdown();
|
static void StaticShutdown();
|
||||||
|
@ -639,10 +714,10 @@ public:
|
||||||
void InsertIntoHash();
|
void InsertIntoHash();
|
||||||
DObject *CreateNew() const;
|
DObject *CreateNew() const;
|
||||||
PClass *CreateDerivedClass(FName name, unsigned int size);
|
PClass *CreateDerivedClass(FName name, unsigned int size);
|
||||||
unsigned int Extend(unsigned int extension, unsigned int alignment);
|
PField *AddField(FName name, PType *type, DWORD flags=0) override;
|
||||||
unsigned int Extend(const PType *type) { return Extend(type->Size, type->Align); }
|
|
||||||
void InitializeActorInfo();
|
void InitializeActorInfo();
|
||||||
void BuildFlatPointers();
|
void BuildFlatPointers();
|
||||||
|
void DestroySpecials(void *addr) const;
|
||||||
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.
|
||||||
|
@ -662,6 +737,9 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find a type, given its name.
|
// Find a type, given its name.
|
||||||
|
const PClass *FindParentClass(FName name) const;
|
||||||
|
PClass *FindParentClass(FName name) { return const_cast<PClass *>(const_cast<const PClass *>(this)->FindParentClass(name)); }
|
||||||
|
|
||||||
static PClass *FindClass(const char *name) { return FindClass(FName(name, true)); }
|
static PClass *FindClass(const char *name) { return FindClass(FName(name, true)); }
|
||||||
static PClass *FindClass(const FString &name) { return FindClass(FName(name, true)); }
|
static PClass *FindClass(const FString &name) { return FindClass(FName(name, true)); }
|
||||||
static PClass *FindClass(ENamedName name) { return FindClass(FName(name)); }
|
static PClass *FindClass(ENamedName name) { return FindClass(FName(name)); }
|
||||||
|
@ -810,4 +888,31 @@ public:
|
||||||
|
|
||||||
void ReleaseGlobalSymbols();
|
void ReleaseGlobalSymbols();
|
||||||
|
|
||||||
|
// Enumerations for serializing types in an archive -------------------------
|
||||||
|
|
||||||
|
enum ETypeVal : BYTE
|
||||||
|
{
|
||||||
|
VAL_Int8,
|
||||||
|
VAL_UInt8,
|
||||||
|
VAL_Int16,
|
||||||
|
VAL_UInt16,
|
||||||
|
VAL_Int32,
|
||||||
|
VAL_UInt32,
|
||||||
|
VAL_Int64,
|
||||||
|
VAL_UInt64,
|
||||||
|
VAL_Zero,
|
||||||
|
VAL_One,
|
||||||
|
VAL_Float32,
|
||||||
|
VAL_Float64,
|
||||||
|
VAL_Fixed,
|
||||||
|
VAL_BAM,
|
||||||
|
VAL_String,
|
||||||
|
VAL_Name,
|
||||||
|
VAL_Struct,
|
||||||
|
VAL_Array,
|
||||||
|
VAL_Object,
|
||||||
|
VAL_State,
|
||||||
|
VAL_Class,
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -721,6 +721,29 @@ void FArchive::Close ()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FArchive::WriteByte(BYTE val)
|
||||||
|
{
|
||||||
|
m_File->Write(&val, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FArchive::WriteInt16(WORD val)
|
||||||
|
{
|
||||||
|
WORD out = LittleShort(val);
|
||||||
|
m_File->Write(&out, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FArchive::WriteInt32(DWORD val)
|
||||||
|
{
|
||||||
|
int out = LittleLong(val);
|
||||||
|
m_File->Write(&out, 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FArchive::WriteInt64(QWORD val)
|
||||||
|
{
|
||||||
|
long long out = SWAP_QWORD(val);
|
||||||
|
m_File->Write(&out, 8);
|
||||||
|
}
|
||||||
|
|
||||||
void FArchive::WriteCount (DWORD count)
|
void FArchive::WriteCount (DWORD count)
|
||||||
{
|
{
|
||||||
BYTE out;
|
BYTE out;
|
||||||
|
@ -832,6 +855,14 @@ void FArchive::WriteString (const char *str)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FArchive::WriteString(const FString &str)
|
||||||
|
{
|
||||||
|
// The count includes the '\0' terminator, but we don't
|
||||||
|
// actually write it out.
|
||||||
|
WriteCount(str.Len() + 1);
|
||||||
|
Write(str, str.Len());
|
||||||
|
}
|
||||||
|
|
||||||
FArchive &FArchive::operator<< (char *&str)
|
FArchive &FArchive::operator<< (char *&str)
|
||||||
{
|
{
|
||||||
if (m_Storing)
|
if (m_Storing)
|
||||||
|
@ -868,7 +899,7 @@ FArchive &FArchive::operator<< (FString &str)
|
||||||
{
|
{
|
||||||
if (m_Storing)
|
if (m_Storing)
|
||||||
{
|
{
|
||||||
WriteString (str.GetChars());
|
WriteString (str);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -883,8 +914,7 @@ FArchive &FArchive::operator<< (FString &str)
|
||||||
char *str2 = (char *)alloca(size*sizeof(char));
|
char *str2 = (char *)alloca(size*sizeof(char));
|
||||||
size--;
|
size--;
|
||||||
Read (str2, size);
|
Read (str2, size);
|
||||||
str2[size] = 0;
|
str = FString(str2, size);
|
||||||
str = str2;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
|
|
|
@ -166,7 +166,14 @@ public:
|
||||||
virtual void Write (const void *mem, unsigned int len);
|
virtual void Write (const void *mem, unsigned int len);
|
||||||
virtual void Read (void *mem, unsigned int len);
|
virtual void Read (void *mem, unsigned int len);
|
||||||
|
|
||||||
|
void WriteString(const FString &str);
|
||||||
void WriteString (const char *str);
|
void WriteString (const char *str);
|
||||||
|
|
||||||
|
void WriteByte(BYTE val);
|
||||||
|
void WriteInt16(WORD val);
|
||||||
|
void WriteInt32(DWORD val);
|
||||||
|
void WriteInt64(QWORD val);
|
||||||
|
|
||||||
void WriteCount (DWORD count);
|
void WriteCount (DWORD count);
|
||||||
DWORD ReadCount ();
|
DWORD ReadCount ();
|
||||||
|
|
||||||
|
|
|
@ -82,6 +82,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FirePistol)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
P_SetPsprite (self->player, ps_flash, weapon->FindState(NAME_Flash));
|
P_SetPsprite (self->player, ps_flash, weapon->FindState(NAME_Flash));
|
||||||
|
self->player->psprites[ps_flash].processPending = true;
|
||||||
}
|
}
|
||||||
self->player->mo->PlayAttacking2 ();
|
self->player->mo->PlayAttacking2 ();
|
||||||
|
|
||||||
|
@ -274,6 +275,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireShotgun)
|
||||||
if (!weapon->DepleteAmmo (weapon->bAltFire, true, 1))
|
if (!weapon->DepleteAmmo (weapon->bAltFire, true, 1))
|
||||||
return 0;
|
return 0;
|
||||||
P_SetPsprite (player, ps_flash, weapon->FindState(NAME_Flash));
|
P_SetPsprite (player, ps_flash, weapon->FindState(NAME_Flash));
|
||||||
|
self->player->psprites[ps_flash].processPending = true;
|
||||||
}
|
}
|
||||||
player->mo->PlayAttacking2 ();
|
player->mo->PlayAttacking2 ();
|
||||||
|
|
||||||
|
@ -310,6 +312,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireShotgun2)
|
||||||
if (!weapon->DepleteAmmo (weapon->bAltFire, true, 2))
|
if (!weapon->DepleteAmmo (weapon->bAltFire, true, 2))
|
||||||
return 0;
|
return 0;
|
||||||
P_SetPsprite (player, ps_flash, weapon->FindState(NAME_Flash));
|
P_SetPsprite (player, ps_flash, weapon->FindState(NAME_Flash));
|
||||||
|
self->player->psprites[ps_flash].processPending = true;
|
||||||
}
|
}
|
||||||
player->mo->PlayAttacking2 ();
|
player->mo->PlayAttacking2 ();
|
||||||
|
|
||||||
|
@ -382,12 +385,14 @@ void P_SetSafeFlash(AWeapon *weapon, player_t *player, FState *flashstate, int i
|
||||||
{
|
{
|
||||||
// we're ok so set the state
|
// we're ok so set the state
|
||||||
P_SetPsprite (player, ps_flash, flashstate + index);
|
P_SetPsprite (player, ps_flash, flashstate + index);
|
||||||
|
player->psprites[ps_flash].processPending = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// oh, no! The state is beyond the end of the state table so use the original flash state.
|
// oh, no! The state is beyond the end of the state table so use the original flash state.
|
||||||
P_SetPsprite (player, ps_flash, flashstate);
|
P_SetPsprite (player, ps_flash, flashstate);
|
||||||
|
player->psprites[ps_flash].processPending = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -404,6 +409,7 @@ void P_SetSafeFlash(AWeapon *weapon, player_t *player, FState *flashstate, int i
|
||||||
index = 0;
|
index = 0;
|
||||||
}
|
}
|
||||||
P_SetPsprite (player, ps_flash, flashstate + index);
|
P_SetPsprite (player, ps_flash, flashstate + index);
|
||||||
|
player->psprites[ps_flash].processPending = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
|
@ -708,6 +708,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FireGrenade)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
P_SetPsprite (player, ps_flash, flash);
|
P_SetPsprite (player, ps_flash, flash);
|
||||||
|
self->player->psprites[ps_flash].processPending = true;
|
||||||
|
|
||||||
if (grenadetype != NULL)
|
if (grenadetype != NULL)
|
||||||
{
|
{
|
||||||
|
|
|
@ -5144,7 +5144,7 @@ void P_RadiusAttack(AActor *bombspot, AActor *bombsource, int bombdamage, int bo
|
||||||
points *= thing->GetClass()->RDFactor;
|
points *= thing->GetClass()->RDFactor;
|
||||||
|
|
||||||
// points and bombdamage should be the same sign
|
// points and bombdamage should be the same sign
|
||||||
if (((points * bombdamage) > 0) && P_CheckSight(thing, bombspot, SF_IGNOREVISIBILITY | SF_IGNOREWATERBOUNDARY))
|
if (((int(points) * bombdamage) > 0) && P_CheckSight(thing, bombspot, SF_IGNOREVISIBILITY | SF_IGNOREWATERBOUNDARY))
|
||||||
{ // OK to damage; target is in direct path
|
{ // OK to damage; target is in direct path
|
||||||
double vz;
|
double vz;
|
||||||
double thrust;
|
double thrust;
|
||||||
|
|
14
src/tarray.h
14
src/tarray.h
|
@ -94,17 +94,23 @@ public:
|
||||||
{
|
{
|
||||||
return &Array[0];
|
return &Array[0];
|
||||||
}
|
}
|
||||||
|
const_iterator begin() const
|
||||||
|
{
|
||||||
|
return &Array[0];
|
||||||
|
}
|
||||||
|
const_iterator cbegin() const
|
||||||
|
{
|
||||||
|
return &Array[0];
|
||||||
|
}
|
||||||
|
|
||||||
iterator end()
|
iterator end()
|
||||||
{
|
{
|
||||||
return &Array[Count];
|
return &Array[Count];
|
||||||
}
|
}
|
||||||
|
const_iterator end() const
|
||||||
const_iterator cbegin() const
|
|
||||||
{
|
{
|
||||||
return &Array[0];
|
return &Array[Count];
|
||||||
}
|
}
|
||||||
|
|
||||||
const_iterator cend() const
|
const_iterator cend() const
|
||||||
{
|
{
|
||||||
return &Array[Count];
|
return &Array[Count];
|
||||||
|
|
|
@ -2745,6 +2745,22 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_LogInt)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//=========================================================================
|
||||||
|
//
|
||||||
|
// A_LogFloat
|
||||||
|
//
|
||||||
|
//===========================================================================
|
||||||
|
|
||||||
|
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_LogFloat)
|
||||||
|
{
|
||||||
|
PARAM_ACTION_PROLOGUE;
|
||||||
|
PARAM_FLOAT(num);
|
||||||
|
IGNORE_FORMAT_PRE
|
||||||
|
Printf("%H\n", num);
|
||||||
|
IGNORE_FORMAT_POST
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
//
|
//
|
||||||
// A_SetTranslucent
|
// A_SetTranslucent
|
||||||
|
|
|
@ -2995,10 +2995,10 @@ FxExpression *FxArrayElement::Resolve(FCompileContext &ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
ValueType = arraytype->ElementType;
|
ValueType = arraytype->ElementType;
|
||||||
if (ValueType->GetRegType() != REGT_INT)
|
if (ValueType->GetRegType() != REGT_INT && ValueType->GetRegType() != REGT_FLOAT)
|
||||||
{
|
{
|
||||||
// int arrays only for now
|
// int arrays only for now
|
||||||
ScriptPosition.Message(MSG_ERROR, "Only integer arrays are supported.");
|
ScriptPosition.Message(MSG_ERROR, "Only numeric arrays are supported.");
|
||||||
delete this;
|
delete this;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -3015,7 +3015,10 @@ FxExpression *FxArrayElement::Resolve(FCompileContext &ctx)
|
||||||
ExpEmit FxArrayElement::Emit(VMFunctionBuilder *build)
|
ExpEmit FxArrayElement::Emit(VMFunctionBuilder *build)
|
||||||
{
|
{
|
||||||
ExpEmit start = Array->Emit(build);
|
ExpEmit start = Array->Emit(build);
|
||||||
ExpEmit dest(build, REGT_INT);
|
PArray *const arraytype = static_cast<PArray*>(Array->ValueType);
|
||||||
|
PType *const elementtype = arraytype->ElementType;
|
||||||
|
ExpEmit dest(build, elementtype->GetRegType());
|
||||||
|
|
||||||
if (start.Konst)
|
if (start.Konst)
|
||||||
{
|
{
|
||||||
ExpEmit tmpstart(build, REGT_POINTER);
|
ExpEmit tmpstart(build, REGT_POINTER);
|
||||||
|
@ -3025,19 +3028,30 @@ ExpEmit FxArrayElement::Emit(VMFunctionBuilder *build)
|
||||||
if (index->isConstant())
|
if (index->isConstant())
|
||||||
{
|
{
|
||||||
unsigned indexval = static_cast<FxConstant *>(index)->GetValue().GetInt();
|
unsigned indexval = static_cast<FxConstant *>(index)->GetValue().GetInt();
|
||||||
if (indexval >= static_cast<PArray*>(Array->ValueType)->ElementCount)
|
if (indexval >= arraytype->ElementCount)
|
||||||
{
|
{
|
||||||
I_Error("Array index out of bounds");
|
I_Error("Array index out of bounds");
|
||||||
}
|
}
|
||||||
indexval <<= 2;
|
indexval *= arraytype->ElementSize;
|
||||||
build->Emit(OP_LW, dest.RegNum, start.RegNum, build->GetConstantInt(indexval));
|
build->Emit(arraytype->ElementType->GetLoadOp(), dest.RegNum,
|
||||||
|
start.RegNum, build->GetConstantInt(indexval));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ExpEmit indexv(index->Emit(build));
|
ExpEmit indexv(index->Emit(build));
|
||||||
build->Emit(OP_SLL_RI, indexv.RegNum, indexv.RegNum, 2);
|
int shiftbits = 0;
|
||||||
build->Emit(OP_BOUND, indexv.RegNum, static_cast<PArray*>(Array->ValueType)->ElementCount);
|
while (1u << shiftbits < arraytype->ElementSize)
|
||||||
build->Emit(OP_LW_R, dest.RegNum, start.RegNum, indexv.RegNum);
|
{
|
||||||
|
shiftbits++;
|
||||||
|
}
|
||||||
|
assert(1 << shiftbits == arraytype->ElementSize && "Element sizes other than power of 2 are not implemented");
|
||||||
|
build->Emit(OP_BOUND, indexv.RegNum, arraytype->ElementCount);
|
||||||
|
if (shiftbits > 0)
|
||||||
|
{
|
||||||
|
build->Emit(OP_SLL_RI, indexv.RegNum, indexv.RegNum, shiftbits);
|
||||||
|
}
|
||||||
|
build->Emit(arraytype->ElementType->GetLoadOp() + 1, // added 1 to use the *_R version that
|
||||||
|
dest.RegNum, start.RegNum, indexv.RegNum); // takes the offset from a register
|
||||||
indexv.Free(build);
|
indexv.Free(build);
|
||||||
}
|
}
|
||||||
start.Free(build);
|
start.Free(build);
|
||||||
|
|
|
@ -525,12 +525,17 @@ static void ParseUserVariable (FScanner &sc, PSymbolTable *symt, PClassActor *cl
|
||||||
|
|
||||||
// Read the type and make sure it's acceptable.
|
// Read the type and make sure it's acceptable.
|
||||||
sc.MustGetAnyToken();
|
sc.MustGetAnyToken();
|
||||||
if (sc.TokenType != TK_Int && sc.TokenType != TK_Float)
|
switch (sc.TokenType)
|
||||||
{
|
{
|
||||||
sc.ScriptMessage("User variables must be of type 'int' or 'float'");
|
case TK_Int: type = TypeSInt32; break;
|
||||||
|
case TK_Float: type = TypeFloat64; break;
|
||||||
|
case TK_String: type = TypeString; break;
|
||||||
|
default:
|
||||||
|
type = TypeError;
|
||||||
|
sc.ScriptMessage("User variables must be of type 'int' or 'float' or 'string'");
|
||||||
FScriptPosition::ErrorCounter++;
|
FScriptPosition::ErrorCounter++;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
type = sc.TokenType == TK_Int ? (PType *)TypeSInt32 : (PType *)TypeFloat64;
|
|
||||||
|
|
||||||
sc.MustGetToken(TK_Identifier);
|
sc.MustGetToken(TK_Identifier);
|
||||||
// For now, restrict user variables to those that begin with "user_" to guarantee
|
// For now, restrict user variables to those that begin with "user_" to guarantee
|
||||||
|
@ -576,11 +581,9 @@ static void ParseUserVariable (FScanner &sc, PSymbolTable *symt, PClassActor *cl
|
||||||
}
|
}
|
||||||
sc.MustGetToken(';');
|
sc.MustGetToken(';');
|
||||||
|
|
||||||
PField *sym = new PField(symname, type, 0);
|
PField *sym = cls->AddField(symname, type, 0);
|
||||||
sym->Offset = cls->Extend(type);
|
if (cls == NULL)
|
||||||
if (symt->AddSymbol(sym) == NULL)
|
|
||||||
{
|
{
|
||||||
delete sym;
|
|
||||||
sc.ScriptMessage ("'%s' is already defined in '%s'.",
|
sc.ScriptMessage ("'%s' is already defined in '%s'.",
|
||||||
symname.GetChars(), cls ? cls->TypeName.GetChars() : "Global");
|
symname.GetChars(), cls ? cls->TypeName.GetChars() : "Global");
|
||||||
FScriptPosition::ErrorCounter++;
|
FScriptPosition::ErrorCounter++;
|
||||||
|
|
|
@ -203,6 +203,7 @@ ACTOR Actor native //: Thinker
|
||||||
action native A_PrintBold(string whattoprint, float time = 0, name fontname = "");
|
action native A_PrintBold(string whattoprint, float time = 0, name fontname = "");
|
||||||
action native A_Log(string whattoprint);
|
action native A_Log(string whattoprint);
|
||||||
action native A_LogInt(int whattoprint);
|
action native A_LogInt(int whattoprint);
|
||||||
|
action native A_LogFloat(float whattoprint);
|
||||||
action native A_SetTranslucent(float alpha, int style = 0);
|
action native A_SetTranslucent(float alpha, int style = 0);
|
||||||
action native A_FadeIn(float reduce = 0.1, int flags = 0);
|
action native A_FadeIn(float reduce = 0.1, int flags = 0);
|
||||||
action native A_FadeOut(float reduce = 0.1, int flags = 1); //bool remove == true
|
action native A_FadeOut(float reduce = 0.1, int flags = 1); //bool remove == true
|
||||||
|
|
Loading…
Reference in a new issue