Merge branch 'floatcvt' of https://github.com/rheit/zdoom into floatcvt

This commit is contained in:
Christoph Oelckers 2016-04-04 12:07:57 +02:00
commit 7486e24cd9
13 changed files with 1221 additions and 102 deletions

View file

@ -257,46 +257,50 @@ DObject::DObject (PClass *inClass)
DObject::~DObject ()
{
if (!(ObjectFlags & OF_Cleanup) && !PClass::bShutdown)
if (!PClass::bShutdown)
{
DObject **probe;
PClass *type = GetClass();
if (!(ObjectFlags & OF_YesReallyDelete))
if (!(ObjectFlags & OF_Cleanup) && !PClass::bShutdown)
{
Printf ("Warning: '%s' is freed outside the GC process.\n",
type != NULL ? type->TypeName.GetChars() : "==some object==");
}
DObject **probe;
// Find all pointers that reference this object and NULL them.
StaticPointerSubstitution(this, NULL);
// Now unlink this object from the GC list.
for (probe = &GC::Root; *probe != NULL; probe = &((*probe)->ObjNext))
{
if (*probe == this)
if (!(ObjectFlags & OF_YesReallyDelete))
{
*probe = ObjNext;
if (&ObjNext == GC::SweepPos)
{
GC::SweepPos = probe;
}
break;
Printf("Warning: '%s' is freed outside the GC process.\n",
type != NULL ? type->TypeName.GetChars() : "==some object==");
}
}
// If it's gray, also unlink it from the gray list.
if (this->IsGray())
{
for (probe = &GC::Gray; *probe != NULL; probe = &((*probe)->GCNext))
// Find all pointers that reference this object and NULL them.
StaticPointerSubstitution(this, NULL);
// Now unlink this object from the GC list.
for (probe = &GC::Root; *probe != NULL; probe = &((*probe)->ObjNext))
{
if (*probe == this)
{
*probe = GCNext;
*probe = ObjNext;
if (&ObjNext == GC::SweepPos)
{
GC::SweepPos = probe;
}
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())
{
// Write all user variables.
for (; symt != NULL; symt = symt->ParentSymbolTable)
{
PSymbolTable::MapType::Iterator it(symt->Symbols);
PSymbolTable::MapType::Pair *pair;
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;
// Write all fields that aren't serialized by native code.
GetClass()->WriteValue(arc, this);
}
else if (SaveVersion >= 4535)
{
GetClass()->ReadValue(arc, this);
}
else
{
{ // Old version that only deals with ints
// Read user variables until 'None' is encountered.
arc << varname;
while (varname != NAME_None)

File diff suppressed because it is too large Load diff

View file

@ -7,6 +7,8 @@
#include "vm.h"
typedef std::pair<const class PType *, unsigned> FTypeAndOffset;
// Variable/parameter/field flags -------------------------------------------
// 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);
// 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)
virtual void SetValue(void *addr, int val);
virtual void SetValue(void *addr, double val);
@ -321,6 +353,9 @@ class PInt : public PBasicType
public:
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, double val);
virtual int GetValueInt(void *addr) const;
@ -347,6 +382,9 @@ class PFloat : public PBasicType
public:
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, double val);
virtual int GetValueInt(void *addr) const;
@ -381,6 +419,12 @@ public:
PString();
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 ----------------------------------------------
@ -390,6 +434,9 @@ class PName : public PInt
DECLARE_CLASS(PName, PInt);
public:
PName();
void WriteValue(FArchive &ar, const void *addr) const override;
bool ReadValue(FArchive &ar, void *addr) const override;
};
class PSound : public PInt
@ -397,6 +444,9 @@ class PSound : public PInt
DECLARE_CLASS(PSound, PInt);
public:
PSound();
void WriteValue(FArchive &ar, const void *addr) const override;
bool ReadValue(FArchive &ar, void *addr) const override;
};
class PColor : public PInt
@ -414,6 +464,9 @@ class PStatePointer : public PBasicType
public:
PStatePointer();
void WriteValue(FArchive &ar, const void *addr) const override;
bool ReadValue(FArchive &ar, void *addr) const override;
virtual int GetStoreOp() const;
virtual int GetLoadOp() const;
virtual int GetRegType() const;
@ -434,6 +487,10 @@ public:
virtual bool IsMatch(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:
PPointer();
};
@ -500,6 +557,12 @@ public:
virtual bool IsMatch(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:
PArray();
};
@ -554,9 +617,16 @@ public:
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();
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:
PStruct();
};
@ -614,11 +684,16 @@ class PClass : public PStruct
protected:
// We unravel _WITH_META here just as we did for PType.
enum { MetaClassNum = CLASSREG_PClassClass };
TArray<FTypeAndOffset> SpecialInits;
virtual void Derive(PClass *newclass);
void InitializeSpecials(void *addr) const;
public:
typedef PClassClass MetaClass;
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) {}
static void StaticInit();
static void StaticShutdown();
@ -639,10 +714,10 @@ public:
void InsertIntoHash();
DObject *CreateNew() const;
PClass *CreateDerivedClass(FName name, unsigned int size);
unsigned int Extend(unsigned int extension, unsigned int alignment);
unsigned int Extend(const PType *type) { return Extend(type->Size, type->Align); }
PField *AddField(FName name, PType *type, DWORD flags=0) override;
void InitializeActorInfo();
void BuildFlatPointers();
void DestroySpecials(void *addr) const;
const PClass *NativeClass() const;
// 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.
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 FString &name) { return FindClass(FName(name, true)); }
static PClass *FindClass(ENamedName name) { return FindClass(FName(name)); }
@ -810,4 +888,31 @@ public:
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

View file

@ -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)
{
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)
{
if (m_Storing)
@ -868,7 +899,7 @@ FArchive &FArchive::operator<< (FString &str)
{
if (m_Storing)
{
WriteString (str.GetChars());
WriteString (str);
}
else
{
@ -883,8 +914,7 @@ FArchive &FArchive::operator<< (FString &str)
char *str2 = (char *)alloca(size*sizeof(char));
size--;
Read (str2, size);
str2[size] = 0;
str = str2;
str = FString(str2, size);
}
}
return *this;

View file

@ -166,7 +166,14 @@ public:
virtual void Write (const void *mem, unsigned int len);
virtual void Read (void *mem, unsigned int len);
void WriteString(const FString &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);
DWORD ReadCount ();

View file

@ -82,6 +82,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FirePistol)
return 0;
P_SetPsprite (self->player, ps_flash, weapon->FindState(NAME_Flash));
self->player->psprites[ps_flash].processPending = true;
}
self->player->mo->PlayAttacking2 ();
@ -274,6 +275,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireShotgun)
if (!weapon->DepleteAmmo (weapon->bAltFire, true, 1))
return 0;
P_SetPsprite (player, ps_flash, weapon->FindState(NAME_Flash));
self->player->psprites[ps_flash].processPending = true;
}
player->mo->PlayAttacking2 ();
@ -310,6 +312,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireShotgun2)
if (!weapon->DepleteAmmo (weapon->bAltFire, true, 2))
return 0;
P_SetPsprite (player, ps_flash, weapon->FindState(NAME_Flash));
self->player->psprites[ps_flash].processPending = true;
}
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
P_SetPsprite (player, ps_flash, flashstate + index);
player->psprites[ps_flash].processPending = true;
return;
}
else
{
// oh, no! The state is beyond the end of the state table so use the original flash state.
P_SetPsprite (player, ps_flash, flashstate);
player->psprites[ps_flash].processPending = true;
return;
}
}
@ -404,6 +409,7 @@ void P_SetSafeFlash(AWeapon *weapon, player_t *player, FState *flashstate, int i
index = 0;
}
P_SetPsprite (player, ps_flash, flashstate + index);
player->psprites[ps_flash].processPending = true;
}
//

View file

@ -708,6 +708,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FireGrenade)
return 0;
P_SetPsprite (player, ps_flash, flash);
self->player->psprites[ps_flash].processPending = true;
if (grenadetype != NULL)
{

View file

@ -5144,7 +5144,7 @@ void P_RadiusAttack(AActor *bombspot, AActor *bombsource, int bombdamage, int bo
points *= thing->GetClass()->RDFactor;
// 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
double vz;
double thrust;

View file

@ -94,17 +94,23 @@ public:
{
return &Array[0];
}
const_iterator begin() const
{
return &Array[0];
}
const_iterator cbegin() const
{
return &Array[0];
}
iterator end()
{
return &Array[Count];
}
const_iterator cbegin() const
const_iterator end() const
{
return &Array[0];
return &Array[Count];
}
const_iterator cend() const
{
return &Array[Count];

View file

@ -2745,6 +2745,22 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_LogInt)
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

View file

@ -2995,10 +2995,10 @@ FxExpression *FxArrayElement::Resolve(FCompileContext &ctx)
}
ValueType = arraytype->ElementType;
if (ValueType->GetRegType() != REGT_INT)
if (ValueType->GetRegType() != REGT_INT && ValueType->GetRegType() != REGT_FLOAT)
{
// 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;
return NULL;
}
@ -3015,7 +3015,10 @@ FxExpression *FxArrayElement::Resolve(FCompileContext &ctx)
ExpEmit FxArrayElement::Emit(VMFunctionBuilder *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)
{
ExpEmit tmpstart(build, REGT_POINTER);
@ -3025,19 +3028,30 @@ ExpEmit FxArrayElement::Emit(VMFunctionBuilder *build)
if (index->isConstant())
{
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");
}
indexval <<= 2;
build->Emit(OP_LW, dest.RegNum, start.RegNum, build->GetConstantInt(indexval));
indexval *= arraytype->ElementSize;
build->Emit(arraytype->ElementType->GetLoadOp(), dest.RegNum,
start.RegNum, build->GetConstantInt(indexval));
}
else
{
ExpEmit indexv(index->Emit(build));
build->Emit(OP_SLL_RI, indexv.RegNum, indexv.RegNum, 2);
build->Emit(OP_BOUND, indexv.RegNum, static_cast<PArray*>(Array->ValueType)->ElementCount);
build->Emit(OP_LW_R, dest.RegNum, start.RegNum, indexv.RegNum);
int shiftbits = 0;
while (1u << shiftbits < arraytype->ElementSize)
{
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);
}
start.Free(build);

View file

@ -525,12 +525,17 @@ static void ParseUserVariable (FScanner &sc, PSymbolTable *symt, PClassActor *cl
// Read the type and make sure it's acceptable.
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++;
break;
}
type = sc.TokenType == TK_Int ? (PType *)TypeSInt32 : (PType *)TypeFloat64;
sc.MustGetToken(TK_Identifier);
// 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(';');
PField *sym = new PField(symname, type, 0);
sym->Offset = cls->Extend(type);
if (symt->AddSymbol(sym) == NULL)
PField *sym = cls->AddField(symname, type, 0);
if (cls == NULL)
{
delete sym;
sc.ScriptMessage ("'%s' is already defined in '%s'.",
symname.GetChars(), cls ? cls->TypeName.GetChars() : "Global");
FScriptPosition::ErrorCounter++;

View file

@ -203,6 +203,7 @@ ACTOR Actor native //: Thinker
action native A_PrintBold(string whattoprint, float time = 0, name fontname = "");
action native A_Log(string 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_FadeIn(float reduce = 0.1, int flags = 0);
action native A_FadeOut(float reduce = 0.1, int flags = 1); //bool remove == true